refactor(project): Renamed all instances of dafa to msfa or mina-sidor-fa. (TV-379)
Squashed commit of the following: commit d3f52ff6876f6e246c7d3c188e56cc2370289341 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 17 14:10:38 2021 +0200 Renamed all dafa instances to msfa
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
// Takes either 6 or 8 characters string (YYYYMMDD) and formats it to ISO standard (YYYY-MM-DD).
|
||||
export function formatToIsoString(date: string): string {
|
||||
if (date.length === 6) {
|
||||
return `${date.substring(0, 4)}-${date.substring(4)}`;
|
||||
} else if (date.length === 8) {
|
||||
return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6)}`;
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
export function formatToDate(date: string): Date {
|
||||
const year = date.substring(0, 4);
|
||||
const month = date.substring(4, 6) || '01';
|
||||
const day = date.substring(6, 8) || '01';
|
||||
|
||||
return new Date(`${year}-${month}-${day}`);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { NAVIGATION } from '@msfa-constants/navigation';
|
||||
|
||||
export function mapPathToPageName(path: string): string {
|
||||
return (NAVIGATION[path] || `${path.charAt(0).toUpperCase()}${path.slice(1)}`) as string;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { NavigationBreadcrumbsItem } from '@af/digi-ng/_navigation/navigation-breadcrumbs';
|
||||
import { mapPathToPageName } from './map-path-to-page-name.util';
|
||||
|
||||
export function mapPathsToBreadcrumbs(
|
||||
paths: string[],
|
||||
startBreadcrumb?: NavigationBreadcrumbsItem
|
||||
): NavigationBreadcrumbsItem[] {
|
||||
const breadcrumbs = [
|
||||
...(startBreadcrumb ? [startBreadcrumb] : []),
|
||||
...paths.map((path, index) => ({
|
||||
text: mapPathToPageName(path),
|
||||
routerLink: `/${paths.slice(0, index + 1).join('/')}`,
|
||||
})),
|
||||
];
|
||||
|
||||
if (isEmployeeCardRoute(paths)) {
|
||||
breadcrumbs[breadcrumbs.length - 1].text = 'Personal information';
|
||||
} else if (isParticipantCardRoute(paths)) {
|
||||
breadcrumbs[breadcrumbs.length - 1].text = 'Deltagarinformation';
|
||||
}
|
||||
|
||||
return breadcrumbs;
|
||||
}
|
||||
|
||||
function isEmployeeCardRoute(paths: string[]): boolean {
|
||||
return paths.length === 3 && paths[1] === 'personal';
|
||||
}
|
||||
|
||||
function isParticipantCardRoute(paths: string[]): boolean {
|
||||
return paths.length === 2 && paths[0] === 'deltagare';
|
||||
}
|
||||
54
apps/mina-sidor-fa/src/app/shared/utils/sort.util.spec.ts
Normal file
54
apps/mina-sidor-fa/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);
|
||||
});
|
||||
});
|
||||
});
|
||||
69
apps/mina-sidor-fa/src/app/shared/utils/sort.util.ts
Normal file
69
apps/mina-sidor-fa/src/app/shared/utils/sort.util.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Sort } from '@msfa-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;
|
||||
return [...data].sort((a, b) => {
|
||||
const first = a[sort.key];
|
||||
const second = b[sort.key];
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||
import { ValidationError } from '@msfa-models/validation-error.model';
|
||||
|
||||
export function EmailValidator(label = 'Fältet'): ValidatorFn {
|
||||
const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/;
|
||||
|
||||
return (control: AbstractControl): ValidationError => {
|
||||
if (control && control.value && !emailRegex.test(control.value)) {
|
||||
return { type: 'invalid', message: `Ogiltig ${label}` };
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||
import { ValidationError } from '@msfa-models/validation-error.model';
|
||||
|
||||
export function RequiredValidator(label = 'Fältet'): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationError => {
|
||||
if (control) {
|
||||
if (!control.value) {
|
||||
return { type: 'required', message: `${label} är obligatoriskt` };
|
||||
}
|
||||
|
||||
if (Array.isArray(control.value) && !control.value.length) {
|
||||
return { type: 'required', message: `Minst ${label} behöver väljas` };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||
import { ValidationError } from '@msfa-models/validation-error.model';
|
||||
|
||||
export function SocialSecurityNumberValidator(): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationError => {
|
||||
if (!control || !control.value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const ssn = control.value as string;
|
||||
|
||||
if (/[^0-9-]/g.test(ssn)) {
|
||||
return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
|
||||
}
|
||||
|
||||
let strippedSsn = ssn.replace(/[^0-9]/g, '');
|
||||
|
||||
// Year format 1991 -> 91
|
||||
if (strippedSsn.length === 12) {
|
||||
strippedSsn = strippedSsn.substr(2);
|
||||
}
|
||||
|
||||
// Check length
|
||||
if (strippedSsn.length !== 10) {
|
||||
return { type: 'ssnNotComplete', message: 'Personnummret är inte fullständigt' };
|
||||
}
|
||||
|
||||
// Check month
|
||||
if (+strippedSsn.substr(2, 2) > 12 || strippedSsn.substr(2, 2) === '00') {
|
||||
return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
|
||||
}
|
||||
|
||||
// Check date (valid date + 60 is also apporved because of co-ordination number)
|
||||
if (
|
||||
(+strippedSsn.substr(4, 2) > 31 || strippedSsn.substr(4, 2) === '00') &&
|
||||
(+strippedSsn.substr(4, 2) > 91 || +strippedSsn.substr(4, 2) <= 60)
|
||||
) {
|
||||
return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
|
||||
}
|
||||
|
||||
return isControlDigitLegit(strippedSsn) ? null : { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
|
||||
};
|
||||
}
|
||||
|
||||
function isControlDigitLegit(ssn: string): boolean {
|
||||
// Run the mod 10 algorithm to produce check digit
|
||||
const enteredControlDigit = +ssn.substr(-1);
|
||||
let inc = 0;
|
||||
let multiplicator = 2;
|
||||
let product: number;
|
||||
|
||||
for (const char of ssn.slice(0, -1)) {
|
||||
product = +char * multiplicator;
|
||||
if (product > 9) {
|
||||
inc += product - 9;
|
||||
} else {
|
||||
inc += product;
|
||||
}
|
||||
multiplicator = multiplicator === 1 ? 2 : 1;
|
||||
}
|
||||
|
||||
let calculatedControlDigit = 10 - (inc - Math.floor(inc / 10) * 10);
|
||||
if (calculatedControlDigit === 10) {
|
||||
calculatedControlDigit = 0;
|
||||
}
|
||||
|
||||
return calculatedControlDigit === enteredControlDigit;
|
||||
}
|
||||
Reference in New Issue
Block a user