feat(deltagare): Added functionality to sort work experiences and educations on from/to dates. (TV-270)
Squashed commit of the following: commit 44f2896a04aca23cf7f6aea0ab84ab041d52535c Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 4 12:46:01 2021 +0200 Adjusted sorting functionality to accept Javascript Date objects and added testing commit 735627f65b40f339cef782cbad1ecdd4f75dc71e Merge: 61be4035d1e357Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 4 08:30:20 2021 +0200 Merge branch 'develop' into feature/TV-270-sorting-experiences commit 61be4038cb9616d3d9d6b28ed517bd8602a79cfe Merge: adc7ae53709987Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 4 08:01:53 2021 +0200 Merge branch 'develop' into feature/TV-270-sorting-experiences commit adc7ae53411a426a1686c7234a49bd537f317184 Merge: dbdfde77ab8320Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 4 07:46:12 2021 +0200 Merge branch 'develop' into feature/TV-270-sorting-experiences commit dbdfde7b7d32f08f83af2ac93d942f8ba9c55142 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 3 15:34:01 2021 +0200 Added sorting of educations and workexperiences to deltagare service
This commit is contained in:
@@ -17,6 +17,7 @@ import { DriversLicense, mapResponseToDriversLicense } from '@dafa-models/driver
|
||||
import { Education, mapResponseToEducation } from '@dafa-models/education.model';
|
||||
import { HighestEducation, mapResponseToHighestEducation } from '@dafa-models/highest-education.model';
|
||||
import { mapResponseToWorkExperience, WorkExperience } from '@dafa-models/work-experience.model';
|
||||
import { sortFromToDates } from '@dafa-utils/sort.util';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@@ -64,11 +65,15 @@ export class DeltagareService {
|
||||
return this.httpClient
|
||||
.get<{ data: EducationsResponse }>(`${this._apiBaseUrl}/education/${id}`, { ...API_HEADERS })
|
||||
.pipe(
|
||||
map(response =>
|
||||
response.data.utbildningar
|
||||
? response.data.utbildningar.map(utbildning => mapResponseToEducation(utbildning))
|
||||
: []
|
||||
)
|
||||
map(response => {
|
||||
if (response.data.utbildningar) {
|
||||
return response.data.utbildningar.sort((a, b) =>
|
||||
sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
|
||||
);
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
map(educations => educations.map(utbildning => mapResponseToEducation(utbildning)))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,11 +117,15 @@ export class DeltagareService {
|
||||
return this.httpClient
|
||||
.get<{ data: WorkExperiencesResponse }>(`${this._apiBaseUrl}/work/experience/${id}`, { ...API_HEADERS })
|
||||
.pipe(
|
||||
map(response =>
|
||||
response.data.arbetslivserfarenheter
|
||||
? response.data.arbetslivserfarenheter.map(erfarenhet => mapResponseToWorkExperience(erfarenhet))
|
||||
: []
|
||||
)
|
||||
map(response => {
|
||||
if (response.data.arbetslivserfarenheter) {
|
||||
return response.data.arbetslivserfarenheter.sort((a, b) =>
|
||||
sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
|
||||
);
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet)))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
54
apps/dafa-web/src/app/shared/utils/sort.util.spec.ts
Normal file
54
apps/dafa-web/src/app/shared/utils/sort.util.spec.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { sortFromToDates } from './sort.util';
|
||||
|
||||
const A_LATEST = {
|
||||
a: { from: '20210101', to: '20210801' },
|
||||
b: { from: '20200101', to: '20200801' },
|
||||
};
|
||||
const A_LATEST_DAY_MISSING = {
|
||||
a: { from: '202101', to: '202108' },
|
||||
b: { from: '202001', to: '202008' },
|
||||
};
|
||||
const A_LATEST_DATE = {
|
||||
a: { from: new Date('2021-01-01'), to: new Date('2021-08-01') },
|
||||
b: { from: new Date('2020-01-01'), to: new Date('2020-08-01') },
|
||||
};
|
||||
const B_LATEST = {
|
||||
a: { from: '20200101', to: '20200801' },
|
||||
b: { from: '20210101', to: '20210801' },
|
||||
};
|
||||
const A_B_EQUAL = {
|
||||
a: { from: '20210101', to: '20210801' },
|
||||
b: { from: '20210101', to: '20210801' },
|
||||
};
|
||||
const MISSING_FROM_DATE = {
|
||||
a: { from: undefined, to: '20210801' },
|
||||
b: { from: '20200101', to: '20200801' },
|
||||
};
|
||||
|
||||
describe('SortUtil', () => {
|
||||
describe('Sort complete from/to date-strings from latest to oldest', () => {
|
||||
it('should sort A dates before B dates when A dates are later', () => {
|
||||
expect(sortFromToDates(A_LATEST.a, A_LATEST.b)).toBe(-1);
|
||||
});
|
||||
|
||||
it('should sort A dates before B dates when DAY is missing and A dates are later', () => {
|
||||
expect(sortFromToDates(A_LATEST_DAY_MISSING.a, A_LATEST_DAY_MISSING.b)).toBe(-1);
|
||||
});
|
||||
|
||||
it('should sort A dates before B dates when provided JS Date and A dates are later', () => {
|
||||
expect(sortFromToDates(A_LATEST_DATE.a, A_LATEST_DATE.b)).toBe(-1);
|
||||
});
|
||||
|
||||
it('should sort B from dates before A dates when B dates are later', () => {
|
||||
expect(sortFromToDates(B_LATEST.a, B_LATEST.b)).toBe(1);
|
||||
});
|
||||
|
||||
it('should sort A dates before B dates when dates are equal', () => {
|
||||
expect(sortFromToDates(A_B_EQUAL.a, A_B_EQUAL.b)).toBe(0);
|
||||
});
|
||||
|
||||
it('should sort A dates before B dates when some from-date is missing', () => {
|
||||
expect(sortFromToDates(MISSING_FROM_DATE.a, MISSING_FROM_DATE.b)).toBe(-1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,10 @@
|
||||
import { Sort } from '@dafa-models/sort.model';
|
||||
const CURRENT_YEAR = new Date().getFullYear();
|
||||
|
||||
interface FromToDates {
|
||||
from: string | Date;
|
||||
to: string | Date;
|
||||
}
|
||||
|
||||
export function sort<T>(data: T[], sort: Sort<keyof T>): T[] {
|
||||
const reverse = sort.order === 'desc' ? -1 : 1;
|
||||
@@ -9,3 +15,55 @@ export function sort<T>(data: T[], sort: Sort<keyof T>): T[] {
|
||||
return reverse * (+(first > second) - +(second > first));
|
||||
});
|
||||
}
|
||||
|
||||
export function sortFromToDates(a: FromToDates, b: FromToDates): number {
|
||||
if (!a.from || !b.from) {
|
||||
console.error('Some date is not set: ', { a, b });
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a.from instanceof Date) {
|
||||
a.from = a.from.toISOString();
|
||||
}
|
||||
if (a.to instanceof Date) {
|
||||
a.to = a.to.toISOString();
|
||||
}
|
||||
if (b.from instanceof Date) {
|
||||
b.from = b.from.toISOString();
|
||||
}
|
||||
if (b.to instanceof Date) {
|
||||
b.to = b.to.toISOString();
|
||||
}
|
||||
|
||||
// Remove optional time and '-' characters whenever the ISO date string is given.
|
||||
a.from = a.from.substring(0, 10).replaceAll('-', '');
|
||||
b.from = b.from.substring(0, 10).replaceAll('-', '');
|
||||
a.to = a.to.substring(0, 10).replaceAll('-', '');
|
||||
b.to = b.to.substring(0, 10).replaceAll('-', '');
|
||||
|
||||
// If no complete dates are available we will add as high numbers as possible to make them sort on top.
|
||||
// If no tillValue is available it means it is still ongoing and should sort on top
|
||||
const aFrom = +a.from.padEnd(8, '9');
|
||||
const bFrom = +b.from.padEnd(8, '9');
|
||||
const aTo = !a.to ? +`${CURRENT_YEAR + 1}9999` : +a.to.padEnd(8, '9');
|
||||
const bTo = !b.to ? +`${CURRENT_YEAR + 1}9999` : +b.to.padEnd(8, '9');
|
||||
|
||||
if (isNaN(aTo)) {
|
||||
return 1;
|
||||
}
|
||||
if (isNaN(bTo)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (aTo === bTo) {
|
||||
if (isNaN(aFrom)) {
|
||||
return 1;
|
||||
}
|
||||
if (isNaN(bFrom)) {
|
||||
return -1;
|
||||
}
|
||||
return aFrom === bFrom ? 0 : bFrom < aFrom ? -1 : 1;
|
||||
}
|
||||
|
||||
return bTo < aTo ? -1 : 1;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "esnext",
|
||||
"lib": ["es2017", "dom"],
|
||||
"lib": ["esnext", "dom"],
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
Reference in New Issue
Block a user