chrv-components 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/chrv-components.mjs +5 -0
- package/esm2020/lib/chr-breadcrumb/chr-breadcrumb.component.mjs +22 -0
- package/esm2020/lib/chr-button/chr-button.component.mjs +51 -0
- package/esm2020/lib/chr-checkbox/chr-checkbox.component.mjs +37 -0
- package/esm2020/lib/chr-components.module.mjs +117 -0
- package/esm2020/lib/chr-delete-modal/chr-delete-modal.component.mjs +22 -0
- package/esm2020/lib/chr-form/chr-form.component.mjs +132 -0
- package/esm2020/lib/chr-form/chr-validators/decimal-validator.mjs +58 -0
- package/esm2020/lib/chr-form/chr-validators/max-date-validator.mjs +54 -0
- package/esm2020/lib/chr-form/chr-validators/type-validator.mjs +52 -0
- package/esm2020/lib/chr-search-select/chr-search-select.component.mjs +136 -0
- package/esm2020/lib/chr-searchbar/chr-searchbar.component.mjs +29 -0
- package/esm2020/lib/chr-separator/chr-separator.component.mjs +11 -0
- package/esm2020/lib/chr-table/chr-table.component.mjs +58 -0
- package/esm2020/lib/chr-table-header-cell/chr-table-header-cell.component.mjs +49 -0
- package/esm2020/lib/services/dialog.service.mjs +29 -0
- package/esm2020/public-api.mjs +19 -0
- package/fesm2015/chrv-components.mjs +803 -0
- package/fesm2015/chrv-components.mjs.map +1 -0
- package/fesm2020/chrv-components.mjs +797 -0
- package/fesm2020/chrv-components.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/chr-breadcrumb/chr-breadcrumb.component.d.ts +15 -0
- package/lib/chr-button/chr-button.component.d.ts +19 -0
- package/lib/chr-checkbox/chr-checkbox.component.d.ts +13 -0
- package/lib/chr-components.module.d.ts +28 -0
- package/lib/chr-delete-modal/chr-delete-modal.component.d.ts +11 -0
- package/lib/chr-form/chr-form.component.d.ts +57 -0
- package/lib/chr-form/chr-validators/decimal-validator.d.ts +10 -0
- package/lib/chr-form/chr-validators/max-date-validator.d.ts +10 -0
- package/lib/chr-form/chr-validators/type-validator.d.ts +10 -0
- package/lib/chr-search-select/chr-search-select.component.d.ts +44 -0
- package/lib/chr-searchbar/chr-searchbar.component.d.ts +14 -0
- package/lib/chr-separator/chr-separator.component.d.ts +5 -0
- package/lib/chr-table/chr-table.component.d.ts +38 -0
- package/lib/chr-table-header-cell/chr-table-header-cell.component.d.ts +16 -0
- package/lib/services/dialog.service.d.ts +10 -0
- package/package.json +22 -3
- package/{src/public-api.ts → public-api.d.ts} +15 -21
- package/chr-theme.scss +0 -97
- package/ng-package.json +0 -7
- package/src/lib/chr-breadcrumb/chr-breadcrumb.component.html +0 -9
- package/src/lib/chr-breadcrumb/chr-breadcrumb.component.scss +0 -0
- package/src/lib/chr-breadcrumb/chr-breadcrumb.component.spec.ts +0 -22
- package/src/lib/chr-breadcrumb/chr-breadcrumb.component.ts +0 -23
- package/src/lib/chr-button/chr-button.component.html +0 -20
- package/src/lib/chr-button/chr-button.component.scss +0 -0
- package/src/lib/chr-button/chr-button.component.spec.ts +0 -23
- package/src/lib/chr-button/chr-button.component.ts +0 -36
- package/src/lib/chr-checkbox/chr-checkbox.component.html +0 -4
- package/src/lib/chr-checkbox/chr-checkbox.component.scss +0 -15
- package/src/lib/chr-checkbox/chr-checkbox.component.spec.ts +0 -23
- package/src/lib/chr-checkbox/chr-checkbox.component.ts +0 -30
- package/src/lib/chr-components.module.ts +0 -69
- package/src/lib/chr-delete-modal/chr-delete-modal.component.html +0 -26
- package/src/lib/chr-delete-modal/chr-delete-modal.component.scss +0 -0
- package/src/lib/chr-delete-modal/chr-delete-modal.component.spec.ts +0 -23
- package/src/lib/chr-delete-modal/chr-delete-modal.component.ts +0 -19
- package/src/lib/chr-form/chr-form.component.html +0 -98
- package/src/lib/chr-form/chr-form.component.scss +0 -37
- package/src/lib/chr-form/chr-form.component.spec.ts +0 -23
- package/src/lib/chr-form/chr-form.component.ts +0 -173
- package/src/lib/chr-form/chr-validators/decimal-validator.ts +0 -54
- package/src/lib/chr-form/chr-validators/max-date-validator.ts +0 -48
- package/src/lib/chr-form/chr-validators/type-validator.ts +0 -47
- package/src/lib/chr-search-select/chr-search-select.component.html +0 -19
- package/src/lib/chr-search-select/chr-search-select.component.scss +0 -3
- package/src/lib/chr-search-select/chr-search-select.component.spec.ts +0 -23
- package/src/lib/chr-search-select/chr-search-select.component.ts +0 -164
- package/src/lib/chr-searchbar/chr-searchbar.component.html +0 -10
- package/src/lib/chr-searchbar/chr-searchbar.component.scss +0 -0
- package/src/lib/chr-searchbar/chr-searchbar.component.spec.ts +0 -23
- package/src/lib/chr-searchbar/chr-searchbar.component.ts +0 -23
- package/src/lib/chr-separator/chr-separator.component.html +0 -3
- package/src/lib/chr-separator/chr-separator.component.scss +0 -24
- package/src/lib/chr-separator/chr-separator.component.spec.ts +0 -23
- package/src/lib/chr-separator/chr-separator.component.ts +0 -10
- package/src/lib/chr-table/chr-table.component.html +0 -88
- package/src/lib/chr-table/chr-table.component.scss +0 -53
- package/src/lib/chr-table/chr-table.component.spec.ts +0 -23
- package/src/lib/chr-table/chr-table.component.ts +0 -72
- package/src/lib/chr-table-header-cell/chr-table-header-cell.component.html +0 -9
- package/src/lib/chr-table-header-cell/chr-table-header-cell.component.scss +0 -31
- package/src/lib/chr-table-header-cell/chr-table-header-cell.component.spec.ts +0 -23
- package/src/lib/chr-table-header-cell/chr-table-header-cell.component.ts +0 -39
- package/src/lib/services/dialog.service.ts +0 -23
- package/styles.scss +0 -93
- package/tailwind.config.js +0 -30
- package/theme.scss +0 -59
- package/tsconfig.lib.json +0 -14
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -14
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { CdkPortal } from '@angular/cdk/portal';
|
|
2
|
-
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
3
|
-
import { type } from './chr-validators/type-validator';
|
|
4
|
-
import { ValidatorFn } from '@angular/forms';
|
|
5
|
-
import {
|
|
6
|
-
FormBuilder,
|
|
7
|
-
FormGroup,
|
|
8
|
-
Validators,
|
|
9
|
-
FormControl,
|
|
10
|
-
} from '@angular/forms';
|
|
11
|
-
import { decimal } from './chr-validators/decimal-validator';
|
|
12
|
-
import { maxDate } from './chr-validators/max-date-validator';
|
|
13
|
-
|
|
14
|
-
export interface ISearchFilter {
|
|
15
|
-
display: string;
|
|
16
|
-
callback?: Function;
|
|
17
|
-
tooltip?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface IControlValidation {
|
|
21
|
-
rule: string;
|
|
22
|
-
value?: any;
|
|
23
|
-
display?: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface IControl {
|
|
27
|
-
label?: string;
|
|
28
|
-
name: string;
|
|
29
|
-
span?: string;
|
|
30
|
-
placeholder?: any;
|
|
31
|
-
width?: 'col' | 'row';
|
|
32
|
-
type:
|
|
33
|
-
| 'text'
|
|
34
|
-
| 'password'
|
|
35
|
-
| 'textArea'
|
|
36
|
-
| 'number'
|
|
37
|
-
| 'date'
|
|
38
|
-
| 'searchSelect'
|
|
39
|
-
| 'select';
|
|
40
|
-
value?: any;
|
|
41
|
-
data?: any[];
|
|
42
|
-
icon?: string;
|
|
43
|
-
iconCallback?: Function;
|
|
44
|
-
iconCallbackDisabled?: boolean;
|
|
45
|
-
iconTooltip?: string;
|
|
46
|
-
fn?: Function;
|
|
47
|
-
filters?: ISearchFilter[];
|
|
48
|
-
validations?: IControlValidation[];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface IFormSection {
|
|
52
|
-
title?: string;
|
|
53
|
-
controls: IControl[];
|
|
54
|
-
}
|
|
55
|
-
@Component({
|
|
56
|
-
selector: 'app-chr-form',
|
|
57
|
-
templateUrl: './chr-form.component.html',
|
|
58
|
-
styleUrls: ['./chr-form.component.scss'],
|
|
59
|
-
})
|
|
60
|
-
export class ChrFormComponent {
|
|
61
|
-
@Input() sections: IFormSection[] = [];
|
|
62
|
-
@Input() valid: boolean = false;
|
|
63
|
-
@Output() validChange: EventEmitter<boolean> = new EventEmitter<boolean>();
|
|
64
|
-
|
|
65
|
-
@Input() model: any;
|
|
66
|
-
@Output() modelChange: EventEmitter<any> = new EventEmitter<any>();
|
|
67
|
-
|
|
68
|
-
@Input() disabled: boolean = false;
|
|
69
|
-
|
|
70
|
-
@Output() valuesChange: EventEmitter<any> = new EventEmitter();
|
|
71
|
-
|
|
72
|
-
public form: FormGroup;
|
|
73
|
-
constructor(private builder: FormBuilder) {
|
|
74
|
-
this.form = builder.group({});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
ngOnInit(): void {
|
|
78
|
-
this._initValidators();
|
|
79
|
-
this.form.valueChanges.subscribe((res) => {
|
|
80
|
-
this.valid = this.form.valid;
|
|
81
|
-
this.validChange.emit(this.form.valid);
|
|
82
|
-
this.valuesChange.emit(res);
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
value = (input?: string) => {
|
|
87
|
-
if (input) return this.form.controls[input]?.value;
|
|
88
|
-
return this.form.value;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
setValue = (input: string, value: any) => {
|
|
92
|
-
if (input) this.form.controls[input]?.setValue(value);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
isValid = (input?: string) => {
|
|
96
|
-
if (input) return this.form.controls[input]?.valid;
|
|
97
|
-
return this.valid;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
isControlRequired = (control: IControl) => {
|
|
101
|
-
return control.validations?.find((v) => v.rule.toLowerCase() == 'required');
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
patchValue = (key: string, value: any) => {
|
|
105
|
-
this.form.patchValue({ [key]: value });
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
reset = () => {
|
|
109
|
-
this.form.reset();
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
private _initValidators() {
|
|
113
|
-
for (const section of this.sections) {
|
|
114
|
-
for (const input of section.controls) {
|
|
115
|
-
if (input.type == 'searchSelect' && !input.fn)
|
|
116
|
-
throw new Error(
|
|
117
|
-
"An input of type 'searchSelect' needs a display function !"
|
|
118
|
-
);
|
|
119
|
-
const control = new FormControl(
|
|
120
|
-
input.value,
|
|
121
|
-
this._getValidators(input.validations)
|
|
122
|
-
);
|
|
123
|
-
this.form.addControl(input.name, control);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private _getValidators = (validations?: IControlValidation[]) => {
|
|
129
|
-
const validators: ValidatorFn[] = [];
|
|
130
|
-
if (!validations) return validators;
|
|
131
|
-
//Switch case breaks the mobile app so we'll do if statements
|
|
132
|
-
for (const validation of validations) {
|
|
133
|
-
const rule = validation.rule.toLocaleLowerCase();
|
|
134
|
-
if (rule == 'min') {
|
|
135
|
-
validation.display = 'Cette valeur est trop petite !';
|
|
136
|
-
validators.push(Validators.min(validation.value));
|
|
137
|
-
}
|
|
138
|
-
if (rule == 'max') {
|
|
139
|
-
validation.display = 'Cette valeur est trop grande !';
|
|
140
|
-
validators.push(Validators.max(validation.value));
|
|
141
|
-
}
|
|
142
|
-
if (rule == 'required') {
|
|
143
|
-
validation.display = 'Ce champs est requis !';
|
|
144
|
-
validators.push(Validators.required);
|
|
145
|
-
}
|
|
146
|
-
if (rule == 'email') {
|
|
147
|
-
validation.display = "Cette adresse email n'est pas valide !";
|
|
148
|
-
validators.push(Validators.email);
|
|
149
|
-
}
|
|
150
|
-
if (rule == 'minlength') {
|
|
151
|
-
validation.display = 'Cette valeur est trop petite !';
|
|
152
|
-
validators.push(Validators.minLength(validation.value));
|
|
153
|
-
}
|
|
154
|
-
if (rule == 'maxlength') {
|
|
155
|
-
validation.display = 'Cette valeur est trop grande !';
|
|
156
|
-
validators.push(Validators.maxLength(validation.value));
|
|
157
|
-
}
|
|
158
|
-
if (rule == 'type') {
|
|
159
|
-
validation.display = "Cette valeur n'est pas valide !";
|
|
160
|
-
validators.push(type(validation.value));
|
|
161
|
-
}
|
|
162
|
-
if (rule == 'decimal') {
|
|
163
|
-
validation.display = `Le nombre de décimal n'est pas valide (max: ${validation.value}) !`;
|
|
164
|
-
validators.push(decimal(validation.value));
|
|
165
|
-
}
|
|
166
|
-
if (rule == 'maxdate') {
|
|
167
|
-
validation.display = `Cette date est trop grande ! (max: ${validation.value}) !`;
|
|
168
|
-
validators.push(maxDate(validation.value));
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return validators;
|
|
172
|
-
};
|
|
173
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Directive, forwardRef, Input, Injectable } from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
AbstractControl,
|
|
4
|
-
NG_VALIDATORS,
|
|
5
|
-
ValidationErrors,
|
|
6
|
-
Validator,
|
|
7
|
-
ValidatorFn,
|
|
8
|
-
} from '@angular/forms';
|
|
9
|
-
|
|
10
|
-
@Injectable({ providedIn: 'root' })
|
|
11
|
-
@Directive({
|
|
12
|
-
selector: '[app-decimal]',
|
|
13
|
-
providers: [
|
|
14
|
-
{
|
|
15
|
-
provide: NG_VALIDATORS,
|
|
16
|
-
useExisting: DecimalValidatorDirective,
|
|
17
|
-
multi: true,
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
})
|
|
21
|
-
export class DecimalValidatorDirective implements Validator {
|
|
22
|
-
@Input() amount: number;
|
|
23
|
-
|
|
24
|
-
validate(control: AbstractControl): ValidationErrors | null {
|
|
25
|
-
return this.amount ? decimal(this.amount)(control) : null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function decimal(amount: number): ValidatorFn {
|
|
30
|
-
return (control: AbstractControl): ValidationErrors | null => {
|
|
31
|
-
const value = control.value;
|
|
32
|
-
|
|
33
|
-
if (!value) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
let isTooLong = false;
|
|
38
|
-
|
|
39
|
-
const str = `${value}`;
|
|
40
|
-
isTooLong =
|
|
41
|
-
str.indexOf(',') != -1
|
|
42
|
-
? (str.split(',')[1] ? str.split(',')[1].length : 0) > amount
|
|
43
|
-
: str.indexOf('.') != -1
|
|
44
|
-
? (str.split('.')[1] ? str.split('.')[1].length : 0) > amount
|
|
45
|
-
: false;
|
|
46
|
-
|
|
47
|
-
return isTooLong
|
|
48
|
-
? ({
|
|
49
|
-
decimal: true,
|
|
50
|
-
max: amount,
|
|
51
|
-
} as ValidationErrors)
|
|
52
|
-
: null;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { Directive, forwardRef, Input, Injectable } from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
AbstractControl,
|
|
4
|
-
NG_VALIDATORS,
|
|
5
|
-
ValidationErrors,
|
|
6
|
-
Validator,
|
|
7
|
-
ValidatorFn,
|
|
8
|
-
} from '@angular/forms';
|
|
9
|
-
import * as moment from 'moment';
|
|
10
|
-
|
|
11
|
-
@Injectable({ providedIn: 'root' })
|
|
12
|
-
@Directive({
|
|
13
|
-
selector: '[app-max-date]',
|
|
14
|
-
providers: [
|
|
15
|
-
{
|
|
16
|
-
provide: NG_VALIDATORS,
|
|
17
|
-
useExisting: MaxDateValidatorDirective,
|
|
18
|
-
multi: true,
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
})
|
|
22
|
-
export class MaxDateValidatorDirective implements Validator {
|
|
23
|
-
@Input() date: Date;
|
|
24
|
-
|
|
25
|
-
validate(control: AbstractControl): ValidationErrors | null {
|
|
26
|
-
return this.date ? maxDate(this.date)(control) : null;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function maxDate(date: Date): ValidatorFn {
|
|
31
|
-
return (control: AbstractControl): ValidationErrors | null => {
|
|
32
|
-
const value = control.value;
|
|
33
|
-
if (!value) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const maxDate = moment(date);
|
|
38
|
-
const inputDate = moment(value);
|
|
39
|
-
|
|
40
|
-
return !(inputDate.isValid() && inputDate.isBefore(maxDate))
|
|
41
|
-
? ({
|
|
42
|
-
maxdate: true,
|
|
43
|
-
max: maxDate.toDate(),
|
|
44
|
-
actual: value,
|
|
45
|
-
} as ValidationErrors)
|
|
46
|
-
: null;
|
|
47
|
-
};
|
|
48
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { Directive, forwardRef, Input, Injectable } from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
AbstractControl,
|
|
4
|
-
NG_VALIDATORS,
|
|
5
|
-
ValidationErrors,
|
|
6
|
-
Validator,
|
|
7
|
-
ValidatorFn,
|
|
8
|
-
} from '@angular/forms';
|
|
9
|
-
|
|
10
|
-
@Injectable({ providedIn: 'root' })
|
|
11
|
-
@Directive({
|
|
12
|
-
selector: '[app-type]',
|
|
13
|
-
providers: [
|
|
14
|
-
{
|
|
15
|
-
provide: NG_VALIDATORS,
|
|
16
|
-
useExisting: TypeValidatorDirective,
|
|
17
|
-
multi: true,
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
})
|
|
21
|
-
export class TypeValidatorDirective implements Validator {
|
|
22
|
-
@Input() type: string;
|
|
23
|
-
|
|
24
|
-
validate(control: AbstractControl): ValidationErrors | null {
|
|
25
|
-
return this.type ? type(this.type)(control) : null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function type(type: string): ValidatorFn {
|
|
30
|
-
return (control: AbstractControl): ValidationErrors | null => {
|
|
31
|
-
const value = control.value;
|
|
32
|
-
|
|
33
|
-
if (!value) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const isType = typeof value == type;
|
|
38
|
-
|
|
39
|
-
return !isType
|
|
40
|
-
? ({
|
|
41
|
-
type: true,
|
|
42
|
-
requiredType: type,
|
|
43
|
-
actualType: typeof value,
|
|
44
|
-
} as ValidationErrors)
|
|
45
|
-
: null;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<div *ngIf="predicate" class="w-full dark:bg-slate-600 rounded-lg relative">
|
|
2
|
-
<div class="w-full relative">
|
|
3
|
-
<input #input type="text" matInput [formControl]="searchSelect" [(ngModel)]="model"
|
|
4
|
-
class="w-full bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
5
|
-
placeholder="{{ placeholder }}" required (keyup)="keyup.emit($event)" [matAutocomplete]="auto" />
|
|
6
|
-
<span *ngIf="filters" [matTooltip]="filters[filterIndex].tooltip || ''" matTooltipPosition="above"
|
|
7
|
-
class="absolute cursor-pointer top-[1px] right-[1.5px] h-[calc(100%_-_2px)] text-gray-900 dark:text-gray-400 px-1 border-l border-gray-300 rounded-r-md text-end opacity-100 bg-gray-50 dark:bg-gray-700 flex justify-center align-middle items-center"
|
|
8
|
-
(click)="filters ? increment() : void">{{ filters[filterIndex].display }}
|
|
9
|
-
</span>
|
|
10
|
-
</div>
|
|
11
|
-
|
|
12
|
-
<mat-autocomplete class="dark:!bg-slate-600 dark:!text-white rounded-lg" #auto="matAutocomplete" id="auto"
|
|
13
|
-
[displayWith]="getModelDisplay.bind(this)" (optionSelected)="emit($event.option.value)">
|
|
14
|
-
<mat-option class="dark:!bg-slate-600 dark:!text-gray-400 rounded-lg"
|
|
15
|
-
*ngFor="let model of filteredModelOptions | async" [value]="model" selected>
|
|
16
|
-
{{ getModelDisplay(model) }}
|
|
17
|
-
</mat-option>
|
|
18
|
-
</mat-autocomplete>
|
|
19
|
-
</div>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { ChrSearchSelectComponent } from './chr-search-select.component';
|
|
4
|
-
|
|
5
|
-
describe('ChrSearchSelectComponent', () => {
|
|
6
|
-
let component: ChrSearchSelectComponent;
|
|
7
|
-
let fixture: ComponentFixture<ChrSearchSelectComponent>;
|
|
8
|
-
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
await TestBed.configureTestingModule({
|
|
11
|
-
declarations: [ ChrSearchSelectComponent ]
|
|
12
|
-
})
|
|
13
|
-
.compileComponents();
|
|
14
|
-
|
|
15
|
-
fixture = TestBed.createComponent(ChrSearchSelectComponent);
|
|
16
|
-
component = fixture.componentInstance;
|
|
17
|
-
fixture.detectChanges();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should create', () => {
|
|
21
|
-
expect(component).toBeTruthy();
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
Input,
|
|
4
|
-
Output,
|
|
5
|
-
EventEmitter,
|
|
6
|
-
forwardRef,
|
|
7
|
-
ViewChild,
|
|
8
|
-
} from '@angular/core';
|
|
9
|
-
import {
|
|
10
|
-
ControlValueAccessor,
|
|
11
|
-
FormControl,
|
|
12
|
-
NG_VALUE_ACCESSOR,
|
|
13
|
-
} from '@angular/forms';
|
|
14
|
-
import {
|
|
15
|
-
MatAutocomplete,
|
|
16
|
-
MatAutocompleteTrigger,
|
|
17
|
-
} from '@angular/material/autocomplete';
|
|
18
|
-
import {
|
|
19
|
-
Observable,
|
|
20
|
-
startWith,
|
|
21
|
-
map,
|
|
22
|
-
of,
|
|
23
|
-
combineLatest,
|
|
24
|
-
combineLatestAll,
|
|
25
|
-
} from 'rxjs';
|
|
26
|
-
|
|
27
|
-
export interface IInputSearchFilter {
|
|
28
|
-
display: string;
|
|
29
|
-
callback?: Function;
|
|
30
|
-
tooltip?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
@Component({
|
|
34
|
-
selector: 'app-chr-search-select',
|
|
35
|
-
templateUrl: './chr-search-select.component.html',
|
|
36
|
-
styleUrls: ['./chr-search-select.component.scss'],
|
|
37
|
-
providers: [
|
|
38
|
-
{
|
|
39
|
-
provide: NG_VALUE_ACCESSOR,
|
|
40
|
-
multi: true,
|
|
41
|
-
useExisting: ChrSearchSelectComponent,
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
})
|
|
45
|
-
export class ChrSearchSelectComponent implements ControlValueAccessor {
|
|
46
|
-
public predicate: boolean = true;
|
|
47
|
-
|
|
48
|
-
public searchSelect: FormControl = new FormControl();
|
|
49
|
-
public filteredModelOptions: Observable<any>;
|
|
50
|
-
|
|
51
|
-
public onTouched: any = () => {};
|
|
52
|
-
|
|
53
|
-
@Input() placeholder: string;
|
|
54
|
-
@Input() data: any[] = [];
|
|
55
|
-
@Input() display: Function;
|
|
56
|
-
@Input() disabled: boolean = false;
|
|
57
|
-
@Input() model: any | null = null;
|
|
58
|
-
@Output() modelChange: EventEmitter<any> = new EventEmitter();
|
|
59
|
-
@Output() keyup: EventEmitter<KeyboardEvent> =
|
|
60
|
-
new EventEmitter<KeyboardEvent>();
|
|
61
|
-
|
|
62
|
-
@Input() filters?: IInputSearchFilter[];
|
|
63
|
-
public filterIndex: number = 0;
|
|
64
|
-
|
|
65
|
-
ngOnInit() {
|
|
66
|
-
this.registerFilters();
|
|
67
|
-
this.registerAutoComplete();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getModelDisplay(model: any) {
|
|
71
|
-
return this.display?.(model);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
emit(event: any) {
|
|
75
|
-
this.modelChange.emit(event);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
writeValue(obj: any): void {
|
|
79
|
-
this.searchSelect.setValue(obj);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
registerOnChange(fn: any): void {
|
|
83
|
-
this.searchSelect.valueChanges.subscribe((value) => {
|
|
84
|
-
this.checkNull(value);
|
|
85
|
-
fn(value);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
checkNull(value: any | null) {
|
|
90
|
-
if (typeof value == 'string')
|
|
91
|
-
if (value == '' || value.trim() == '') this.setNull;
|
|
92
|
-
if (value == null || value == '') {
|
|
93
|
-
this.setNull();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
setNull() {
|
|
98
|
-
this.emit(null);
|
|
99
|
-
this.model = null;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
registerOnTouched(fn: any): void {
|
|
103
|
-
this.searchSelect.markAsTouched = fn;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
registerFilters = () => {
|
|
107
|
-
this.filteredModelOptions = this.searchSelect.valueChanges.pipe(
|
|
108
|
-
startWith(''),
|
|
109
|
-
map((value) => this._filterModel(value! || -1)),
|
|
110
|
-
map((values) => {
|
|
111
|
-
return this.filters && this.filters[this.filterIndex].callback
|
|
112
|
-
? values.filter((r) => this.filters![this.filterIndex].callback!(r))
|
|
113
|
-
: values;
|
|
114
|
-
})
|
|
115
|
-
);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
registerAutoComplete = () => {
|
|
119
|
-
//If there is only one value left,
|
|
120
|
-
this.filteredModelOptions.subscribe((values) => {
|
|
121
|
-
if (values.length == 1) {
|
|
122
|
-
this.emit(values[0]);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
setDisabledState?(isDisabled: boolean): void {
|
|
128
|
-
this.disabled = isDisabled;
|
|
129
|
-
isDisabled ? this.searchSelect.disable() : this.searchSelect.enable();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
increment = () => {
|
|
133
|
-
this.writeValue('');
|
|
134
|
-
const modulo = this.filters ? this.filters.length : 1;
|
|
135
|
-
this.filterIndex = (this.filterIndex + 1) % modulo;
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
getValue = () => {
|
|
139
|
-
return this.searchSelect.value;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
void = () => {};
|
|
143
|
-
|
|
144
|
-
private _filterModel(value: number | string): any[] {
|
|
145
|
-
return typeof value == 'string'
|
|
146
|
-
? this._doFilterModelString(`${value}`)
|
|
147
|
-
: this._doFilterModelInt(value);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
private _doFilterModelInt = (id: number) => {
|
|
151
|
-
const tmp = this.data.find((r) => r.id == id);
|
|
152
|
-
return tmp ? tmp : [];
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
private _doFilterModelString(input: string) {
|
|
156
|
-
return this.data.filter((r) => this._filterValues(r, input));
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
private _filterValues(value: any, input: string) {
|
|
160
|
-
return `${this.getModelDisplay(value)}`
|
|
161
|
-
.toLowerCase()
|
|
162
|
-
.includes(input.toLowerCase());
|
|
163
|
-
}
|
|
164
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<div class="w-full">
|
|
2
|
-
<label>{{ label }}</label>
|
|
3
|
-
<input
|
|
4
|
-
matInput
|
|
5
|
-
[formControl]="searchBy"
|
|
6
|
-
placeholder="{{ placeholder }}"
|
|
7
|
-
type="text"
|
|
8
|
-
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
9
|
-
/>
|
|
10
|
-
</div>
|
|
File without changes
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { ChrSearchbarComponent } from './chr-searchbar.component';
|
|
4
|
-
|
|
5
|
-
describe('ChrSearchbarComponent', () => {
|
|
6
|
-
let component: ChrSearchbarComponent;
|
|
7
|
-
let fixture: ComponentFixture<ChrSearchbarComponent>;
|
|
8
|
-
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
await TestBed.configureTestingModule({
|
|
11
|
-
declarations: [ ChrSearchbarComponent ]
|
|
12
|
-
})
|
|
13
|
-
.compileComponents();
|
|
14
|
-
|
|
15
|
-
fixture = TestBed.createComponent(ChrSearchbarComponent);
|
|
16
|
-
component = fixture.componentInstance;
|
|
17
|
-
fixture.detectChanges();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should create', () => {
|
|
21
|
-
expect(component).toBeTruthy();
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
-
import { FormControl } from '@angular/forms';
|
|
3
|
-
|
|
4
|
-
@Component({
|
|
5
|
-
selector: 'app-chr-searchbar',
|
|
6
|
-
templateUrl: './chr-searchbar.component.html',
|
|
7
|
-
styleUrls: ['./chr-searchbar.component.scss'],
|
|
8
|
-
})
|
|
9
|
-
export class ChrSearchbarComponent {
|
|
10
|
-
@Input() model: string | null;
|
|
11
|
-
@Output() modelChange: EventEmitter<string> = new EventEmitter();
|
|
12
|
-
@Input() placeholder: string | null;
|
|
13
|
-
@Input() label: string | null;
|
|
14
|
-
public searchBy = new FormControl<string>('');
|
|
15
|
-
|
|
16
|
-
constructor() {
|
|
17
|
-
this.searchBy.valueChanges.subscribe((value) => this.emit(value));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
emit(event: any) {
|
|
21
|
-
this.modelChange.emit(event);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
@use 'sass:map';
|
|
2
|
-
@use '@angular/material' as mat;
|
|
3
|
-
@import '../../../styles.scss';
|
|
4
|
-
|
|
5
|
-
$color-config: mat.get-color-config($chr-theme);
|
|
6
|
-
$primary-palette: map.get($color-config, 'primary');
|
|
7
|
-
$accent-palette: map.get($color-config, 'accent');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
table {
|
|
11
|
-
width: 100%;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.mat-column-actions {
|
|
15
|
-
text-align: right;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.mat-mdc-header-row {
|
|
19
|
-
background-color: mat.get-color-from-palette($accent-palette, A200);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
::ng-deep .arrow-color .mat-sort-header-arrow {
|
|
23
|
-
color: black;
|
|
24
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { ChrSeparatorComponent } from './chr-separator.component';
|
|
4
|
-
|
|
5
|
-
describe('ChrSeparatorComponent', () => {
|
|
6
|
-
let component: ChrSeparatorComponent;
|
|
7
|
-
let fixture: ComponentFixture<ChrSeparatorComponent>;
|
|
8
|
-
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
await TestBed.configureTestingModule({
|
|
11
|
-
declarations: [ ChrSeparatorComponent ]
|
|
12
|
-
})
|
|
13
|
-
.compileComponents();
|
|
14
|
-
|
|
15
|
-
fixture = TestBed.createComponent(ChrSeparatorComponent);
|
|
16
|
-
component = fixture.componentInstance;
|
|
17
|
-
fixture.detectChanges();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should create', () => {
|
|
21
|
-
expect(component).toBeTruthy();
|
|
22
|
-
});
|
|
23
|
-
});
|