iss-ctrl 0.0.12 → 0.0.13
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/fesm2022/iss-ctrl-iss-ctrl-BN9rcLt2.mjs +8855 -0
- package/fesm2022/iss-ctrl-iss-ctrl-BN9rcLt2.mjs.map +1 -0
- package/fesm2022/iss-ctrl-iss-ctrl-DOmgkxUv.mjs +8924 -0
- package/fesm2022/iss-ctrl-iss-ctrl-DOmgkxUv.mjs.map +1 -0
- package/fesm2022/iss-ctrl-load-event-AgBohfHa.mjs +60 -0
- package/fesm2022/iss-ctrl-load-event-AgBohfHa.mjs.map +1 -0
- package/fesm2022/iss-ctrl-load-event-D70VZuyD.mjs +60 -0
- package/fesm2022/iss-ctrl-load-event-D70VZuyD.mjs.map +1 -0
- package/fesm2022/iss-ctrl-load-options-event-ClQPHNBO.mjs +50 -0
- package/fesm2022/iss-ctrl-load-options-event-ClQPHNBO.mjs.map +1 -0
- package/fesm2022/iss-ctrl-load-options-event-DHmaMAOb.mjs +50 -0
- package/fesm2022/iss-ctrl-load-options-event-DHmaMAOb.mjs.map +1 -0
- package/fesm2022/iss-ctrl-load-value-event-CDAKsE_O.mjs +52 -0
- package/fesm2022/iss-ctrl-load-value-event-CDAKsE_O.mjs.map +1 -0
- package/fesm2022/iss-ctrl-load-value-event-Cpuy1og1.mjs +52 -0
- package/fesm2022/iss-ctrl-load-value-event-Cpuy1og1.mjs.map +1 -0
- package/fesm2022/iss-ctrl-note.field-C9cVaAz0.mjs +65 -0
- package/fesm2022/iss-ctrl-note.field-C9cVaAz0.mjs.map +1 -0
- package/fesm2022/iss-ctrl-note.field-IM4x1O3b.mjs +65 -0
- package/fesm2022/iss-ctrl-note.field-IM4x1O3b.mjs.map +1 -0
- package/fesm2022/iss-ctrl-replace-api-keys-CLP4wBYu.mjs +57 -0
- package/fesm2022/iss-ctrl-replace-api-keys-CLP4wBYu.mjs.map +1 -0
- package/fesm2022/iss-ctrl-replace-api-keys-CvhCKvNB.mjs +57 -0
- package/fesm2022/iss-ctrl-replace-api-keys-CvhCKvNB.mjs.map +1 -0
- package/fesm2022/iss-ctrl-set-value-event-C7YYwHZV.mjs +61 -0
- package/fesm2022/iss-ctrl-set-value-event-C7YYwHZV.mjs.map +1 -0
- package/fesm2022/iss-ctrl-set-value-event-CrpzRR6X.mjs +61 -0
- package/fesm2022/iss-ctrl-set-value-event-CrpzRR6X.mjs.map +1 -0
- package/fesm2022/iss-ctrl-table.field-BP-HMKO3.mjs +592 -0
- package/fesm2022/iss-ctrl-table.field-BP-HMKO3.mjs.map +1 -0
- package/fesm2022/iss-ctrl-table.field-CDSVakji.mjs +592 -0
- package/fesm2022/iss-ctrl-table.field-CDSVakji.mjs.map +1 -0
- package/fesm2022/iss-ctrl-trigger-based-on-json-value-DS4TR38v.mjs +24 -0
- package/fesm2022/iss-ctrl-trigger-based-on-json-value-DS4TR38v.mjs.map +1 -0
- package/fesm2022/iss-ctrl-trigger-based-on-json-value-Dp0EhVLA.mjs +24 -0
- package/fesm2022/iss-ctrl-trigger-based-on-json-value-Dp0EhVLA.mjs.map +1 -0
- package/fesm2022/iss-ctrl-user-picker.field-8Jb1325c.mjs +225 -0
- package/fesm2022/iss-ctrl-user-picker.field-8Jb1325c.mjs.map +1 -0
- package/fesm2022/iss-ctrl-user-picker.field-PxT_dZ_O.mjs +225 -0
- package/fesm2022/iss-ctrl-user-picker.field-PxT_dZ_O.mjs.map +1 -0
- package/fesm2022/iss-ctrl.mjs +1 -1
- package/package.json +1 -1
- package/types/iss-ctrl.d.ts +3 -5
- package/upgrade.scss +16 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, signal, CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { MatSidenav, MatSidenavContainer } from '@angular/material/sidenav';
|
|
5
|
+
import { Subject, debounceTime, distinctUntilChanged, switchMap, map } from 'rxjs';
|
|
6
|
+
import { F as FieldBase, E as Employee, V as VIEW_PROVIDER, S as SelectControl, a as ValidationMessageComponent } from './iss-ctrl-iss-ctrl-DOmgkxUv.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `<iss-user-picker>` — employee lookup, searched against the directory API.
|
|
10
|
+
*
|
|
11
|
+
* Rendered by the outlet for fields of type `userPicker`. In `edit` mode it renders
|
|
12
|
+
* {@link SelectControl} — always multi-select — over the employees returned by the search;
|
|
13
|
+
* in `view` mode the stored value as plain text. Selecting a user opens a details drawer.
|
|
14
|
+
*
|
|
15
|
+
* ### Supported `config` keys
|
|
16
|
+
* | Key | Type | Description |
|
|
17
|
+
* | --- | --- | --- |
|
|
18
|
+
* | `min` | `number` | Minimum number of users required. |
|
|
19
|
+
* | `max` | `number` | Maximum number of users allowed. |
|
|
20
|
+
* | `readonly` | `boolean` | Shows the value but blocks interaction. |
|
|
21
|
+
*
|
|
22
|
+
* ### Other field members used
|
|
23
|
+
* `label()` · `value` · `ctrlJsonValue()`
|
|
24
|
+
*
|
|
25
|
+
* Every field also honours `visible`, `mode`, `validation`, `asyncValidation` and
|
|
26
|
+
* `events` — see {@link IssField} for the full model and {@link FieldConfig} for all keys.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```json
|
|
30
|
+
* { "name": "approvers", "type": "userPicker", "label": "Approvers", "config": { "max": 3 } }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
class UserPickerField extends FieldBase {
|
|
34
|
+
userImageHost = "https://igateapp.stc.com.sa";
|
|
35
|
+
employeeService = inject(Employee);
|
|
36
|
+
options = signal([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
37
|
+
userData;
|
|
38
|
+
#query = new Subject();
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
41
|
+
this.#query.pipe(debounceTime(300), distinctUntilChanged(),
|
|
42
|
+
// a new query cancels the request still in flight
|
|
43
|
+
switchMap((query) => this.employeeService.search(query)), map((res) => {
|
|
44
|
+
return res.map((user) => {
|
|
45
|
+
user.value = user.email;
|
|
46
|
+
user.label = user.name;
|
|
47
|
+
return user;
|
|
48
|
+
});
|
|
49
|
+
}), takeUntilDestroyed(this.destroyRef)).subscribe((res) => {
|
|
50
|
+
this.options.set(res);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
userImage() {
|
|
54
|
+
const image = this.userData?.profileImage ?? this.userData?.profileImageUrl;
|
|
55
|
+
if (!image) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return image.startsWith("http") ? image : this.userImageHost + image;
|
|
59
|
+
}
|
|
60
|
+
search(event) {
|
|
61
|
+
this.#query.next(event);
|
|
62
|
+
}
|
|
63
|
+
updateField($event) {
|
|
64
|
+
this.options.set([]);
|
|
65
|
+
}
|
|
66
|
+
showUserData(item) {
|
|
67
|
+
this.userData = item;
|
|
68
|
+
}
|
|
69
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserPickerField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
70
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: UserPickerField, isStandalone: true, selector: "iss-user-picker", usesInheritance: true, ngImport: i0, template: `
|
|
71
|
+
@if (field.visible()) {
|
|
72
|
+
@if (field.mode() === "edit") {
|
|
73
|
+
<iss-ctrl-select
|
|
74
|
+
[formControlName]="field.name"
|
|
75
|
+
[min]="field.config.min() ?? null"
|
|
76
|
+
[max]="field.config.max() ?? null"
|
|
77
|
+
[options]="options()"
|
|
78
|
+
[multiple]="true"
|
|
79
|
+
[readonly]="field.config.readonly() ?? false"
|
|
80
|
+
(onQueryChange)="search($event)"
|
|
81
|
+
(onChange)="updateField($event)"
|
|
82
|
+
>
|
|
83
|
+
<label>{{ field.label() }}</label>
|
|
84
|
+
<ng-template let-item #optionTemplate>
|
|
85
|
+
<div class="d-flex align-items-center gap-2">
|
|
86
|
+
<ds-avatar size="x-small" [attr.image]="item.image"></ds-avatar>
|
|
87
|
+
<span class="fs-14 fw-medium fc-black">{{ item.name }}</span>
|
|
88
|
+
</div>
|
|
89
|
+
</ng-template>
|
|
90
|
+
<ng-template let-item #cardViewerTemplate>
|
|
91
|
+
<div (click)="showUserData(item);drawer.open()">
|
|
92
|
+
{{ item.name }}
|
|
93
|
+
</div>
|
|
94
|
+
</ng-template>
|
|
95
|
+
</iss-ctrl-select>
|
|
96
|
+
<iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="!ctrl.untouched"/>
|
|
97
|
+
} @else {
|
|
98
|
+
<p>{{ field.value }}</p>
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
<mat-sidenav-container [hasBackdrop]="true">
|
|
102
|
+
<mat-sidenav #drawer [mode]="'over'" [position]="'start'" [autoFocus]="false">
|
|
103
|
+
<div class="main-sidenav">
|
|
104
|
+
<div class="sidenav-title bc-white">
|
|
105
|
+
<h3> Employee Information </h3>
|
|
106
|
+
<ds-icon icon="close" class="fc-black fs-20 p-3 cursor-pointer" (click)="drawer.close()"></ds-icon>
|
|
107
|
+
</div>
|
|
108
|
+
<div class="sidenav-body p-0">
|
|
109
|
+
<div class="d-flex flex-column align-items-center gap-3 sidenav-user bc-off-white text-center">
|
|
110
|
+
<ds-avatar [attr.image]="userImage()" [attr.label]="userData?.name"></ds-avatar>
|
|
111
|
+
@if (userData?.employeeNumber) {
|
|
112
|
+
<div class="d-flex flex-column gap-1">
|
|
113
|
+
<h4 class="fs-16 fc-black fw-medium mb-0">{{ userData?.name }}</h4>
|
|
114
|
+
@if (!userData?.job?.name) {
|
|
115
|
+
<h6 class="fs-12 fc-dark-gray fw-normal mb-0">{{ userData?.position?.name }}</h6>
|
|
116
|
+
}
|
|
117
|
+
@if (!userData?.position?.name) {
|
|
118
|
+
<h6 class="fs-12 fc-dark-gray fw-normal mb-0">{{ userData?.job?.name }}</h6>
|
|
119
|
+
}
|
|
120
|
+
</div>
|
|
121
|
+
}
|
|
122
|
+
<div class="d-flex flex-wrap gap-2">
|
|
123
|
+
<div class="fs-12 fc-black d-flex align-items-center gap-2 box-shadow bc-white radius-4 p-2 profile-box">
|
|
124
|
+
<ds-icon icon="mail-o" class="fc-coral fs-20"></ds-icon>
|
|
125
|
+
<a [href]="'mailTo:' + userData?.email" class="fc-black">{{ userData?.email }}</a>
|
|
126
|
+
</div>
|
|
127
|
+
@if (userData?.contact?.mobile) {
|
|
128
|
+
<div class="fs-12 fc-black d-flex align-items-center gap-2 box-shadow bc-white radius-4 p-2 profile-box">
|
|
129
|
+
<ds-icon icon="phone" class="fc-coral fs-20"></ds-icon>
|
|
130
|
+
<a [href]="'tel:' + userData?.contact?.mobile" class="fc-black">
|
|
131
|
+
<bdi>{{ userData?.contact?.mobile }}</bdi>
|
|
132
|
+
</a>
|
|
133
|
+
</div>
|
|
134
|
+
}
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</mat-sidenav>
|
|
140
|
+
</mat-sidenav-container>
|
|
141
|
+
`, isInline: true, styles: [".mat-drawer{position:fixed;left:0}\n"], dependencies: [{ kind: "component", type: SelectControl, selector: "iss-ctrl-select", inputs: ["options", "height", "loading"], outputs: ["onQueryChange"] }, { kind: "component", type: ValidationMessageComponent, selector: "iss-validation-message-viewer", inputs: ["errors", "showMessage"] }, { kind: "component", type: MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }], viewProviders: [VIEW_PROVIDER] });
|
|
142
|
+
}
|
|
143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserPickerField, decorators: [{
|
|
144
|
+
type: Component,
|
|
145
|
+
args: [{ selector: "iss-user-picker", viewProviders: [VIEW_PROVIDER], imports: [
|
|
146
|
+
SelectControl,
|
|
147
|
+
ValidationMessageComponent,
|
|
148
|
+
MatSidenav,
|
|
149
|
+
MatSidenavContainer,
|
|
150
|
+
], template: `
|
|
151
|
+
@if (field.visible()) {
|
|
152
|
+
@if (field.mode() === "edit") {
|
|
153
|
+
<iss-ctrl-select
|
|
154
|
+
[formControlName]="field.name"
|
|
155
|
+
[min]="field.config.min() ?? null"
|
|
156
|
+
[max]="field.config.max() ?? null"
|
|
157
|
+
[options]="options()"
|
|
158
|
+
[multiple]="true"
|
|
159
|
+
[readonly]="field.config.readonly() ?? false"
|
|
160
|
+
(onQueryChange)="search($event)"
|
|
161
|
+
(onChange)="updateField($event)"
|
|
162
|
+
>
|
|
163
|
+
<label>{{ field.label() }}</label>
|
|
164
|
+
<ng-template let-item #optionTemplate>
|
|
165
|
+
<div class="d-flex align-items-center gap-2">
|
|
166
|
+
<ds-avatar size="x-small" [attr.image]="item.image"></ds-avatar>
|
|
167
|
+
<span class="fs-14 fw-medium fc-black">{{ item.name }}</span>
|
|
168
|
+
</div>
|
|
169
|
+
</ng-template>
|
|
170
|
+
<ng-template let-item #cardViewerTemplate>
|
|
171
|
+
<div (click)="showUserData(item);drawer.open()">
|
|
172
|
+
{{ item.name }}
|
|
173
|
+
</div>
|
|
174
|
+
</ng-template>
|
|
175
|
+
</iss-ctrl-select>
|
|
176
|
+
<iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="!ctrl.untouched"/>
|
|
177
|
+
} @else {
|
|
178
|
+
<p>{{ field.value }}</p>
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
<mat-sidenav-container [hasBackdrop]="true">
|
|
182
|
+
<mat-sidenav #drawer [mode]="'over'" [position]="'start'" [autoFocus]="false">
|
|
183
|
+
<div class="main-sidenav">
|
|
184
|
+
<div class="sidenav-title bc-white">
|
|
185
|
+
<h3> Employee Information </h3>
|
|
186
|
+
<ds-icon icon="close" class="fc-black fs-20 p-3 cursor-pointer" (click)="drawer.close()"></ds-icon>
|
|
187
|
+
</div>
|
|
188
|
+
<div class="sidenav-body p-0">
|
|
189
|
+
<div class="d-flex flex-column align-items-center gap-3 sidenav-user bc-off-white text-center">
|
|
190
|
+
<ds-avatar [attr.image]="userImage()" [attr.label]="userData?.name"></ds-avatar>
|
|
191
|
+
@if (userData?.employeeNumber) {
|
|
192
|
+
<div class="d-flex flex-column gap-1">
|
|
193
|
+
<h4 class="fs-16 fc-black fw-medium mb-0">{{ userData?.name }}</h4>
|
|
194
|
+
@if (!userData?.job?.name) {
|
|
195
|
+
<h6 class="fs-12 fc-dark-gray fw-normal mb-0">{{ userData?.position?.name }}</h6>
|
|
196
|
+
}
|
|
197
|
+
@if (!userData?.position?.name) {
|
|
198
|
+
<h6 class="fs-12 fc-dark-gray fw-normal mb-0">{{ userData?.job?.name }}</h6>
|
|
199
|
+
}
|
|
200
|
+
</div>
|
|
201
|
+
}
|
|
202
|
+
<div class="d-flex flex-wrap gap-2">
|
|
203
|
+
<div class="fs-12 fc-black d-flex align-items-center gap-2 box-shadow bc-white radius-4 p-2 profile-box">
|
|
204
|
+
<ds-icon icon="mail-o" class="fc-coral fs-20"></ds-icon>
|
|
205
|
+
<a [href]="'mailTo:' + userData?.email" class="fc-black">{{ userData?.email }}</a>
|
|
206
|
+
</div>
|
|
207
|
+
@if (userData?.contact?.mobile) {
|
|
208
|
+
<div class="fs-12 fc-black d-flex align-items-center gap-2 box-shadow bc-white radius-4 p-2 profile-box">
|
|
209
|
+
<ds-icon icon="phone" class="fc-coral fs-20"></ds-icon>
|
|
210
|
+
<a [href]="'tel:' + userData?.contact?.mobile" class="fc-black">
|
|
211
|
+
<bdi>{{ userData?.contact?.mobile }}</bdi>
|
|
212
|
+
</a>
|
|
213
|
+
</div>
|
|
214
|
+
}
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
</mat-sidenav>
|
|
220
|
+
</mat-sidenav-container>
|
|
221
|
+
`, schemas: [CUSTOM_ELEMENTS_SCHEMA], styles: [".mat-drawer{position:fixed;left:0}\n"] }]
|
|
222
|
+
}], ctorParameters: () => [] });
|
|
223
|
+
|
|
224
|
+
export { UserPickerField };
|
|
225
|
+
//# sourceMappingURL=iss-ctrl-user-picker.field-PxT_dZ_O.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iss-ctrl-user-picker.field-PxT_dZ_O.mjs","sources":["../../../projects/iss/src/components/controls/user-picker/user-picker.field.ts"],"sourcesContent":["import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, signal } from \"@angular/core\";\r\nimport { takeUntilDestroyed } from \"@angular/core/rxjs-interop\";\r\nimport { MatSidenav, MatSidenavContainer } from \"@angular/material/sidenav\";\r\nimport { debounceTime, distinctUntilChanged, map, Subject, switchMap } from \"rxjs\";\r\nimport { ValidationMessageComponent } from \"../../shared/validation-message.component\";\r\nimport { FieldBase } from \"../base/field-base\";\r\nimport { SelectControl } from \"../select/select.control\";\r\nimport { Employee } from \"./employee\";\r\nimport { VIEW_PROVIDER } from \"../../../shared/constants/view-provider.const\";\r\n\r\n/**\r\n * `<iss-user-picker>` — employee lookup, searched against the directory API.\r\n *\r\n * Rendered by the outlet for fields of type `userPicker`. In `edit` mode it renders\r\n * {@link SelectControl} — always multi-select — over the employees returned by the search;\r\n * in `view` mode the stored value as plain text. Selecting a user opens a details drawer.\r\n *\r\n * ### Supported `config` keys\r\n * | Key | Type | Description |\r\n * | --- | --- | --- |\r\n * | `min` | `number` | Minimum number of users required. |\r\n * | `max` | `number` | Maximum number of users allowed. |\r\n * | `readonly` | `boolean` | Shows the value but blocks interaction. |\r\n *\r\n * ### Other field members used\r\n * `label()` · `value` · `ctrlJsonValue()`\r\n *\r\n * Every field also honours `visible`, `mode`, `validation`, `asyncValidation` and\r\n * `events` — see {@link IssField} for the full model and {@link FieldConfig} for all keys.\r\n *\r\n * @example\r\n * ```json\r\n * { \"name\": \"approvers\", \"type\": \"userPicker\", \"label\": \"Approvers\", \"config\": { \"max\": 3 } }\r\n * ```\r\n */\r\n@Component({\r\n selector: \"iss-user-picker\",\r\n viewProviders: [VIEW_PROVIDER],\r\n imports: [\r\n SelectControl,\r\n ValidationMessageComponent,\r\n MatSidenav,\r\n MatSidenavContainer,\r\n ],\r\n template: `\r\n @if (field.visible()) {\r\n @if (field.mode() === \"edit\") {\r\n <iss-ctrl-select\r\n [formControlName]=\"field.name\"\r\n [min]=\"field.config.min() ?? null\"\r\n [max]=\"field.config.max() ?? null\"\r\n [options]=\"options()\"\r\n [multiple]=\"true\"\r\n [readonly]=\"field.config.readonly() ?? false\"\r\n (onQueryChange)=\"search($event)\"\r\n (onChange)=\"updateField($event)\"\r\n >\r\n <label>{{ field.label() }}</label>\r\n <ng-template let-item #optionTemplate>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <ds-avatar size=\"x-small\" [attr.image]=\"item.image\"></ds-avatar>\r\n <span class=\"fs-14 fw-medium fc-black\">{{ item.name }}</span>\r\n </div>\r\n </ng-template>\r\n <ng-template let-item #cardViewerTemplate>\r\n <div (click)=\"showUserData(item);drawer.open()\">\r\n {{ item.name }}\r\n </div>\r\n </ng-template>\r\n </iss-ctrl-select>\r\n <iss-validation-message-viewer [errors]=\"ctrl.errors\" [showMessage]=\"!ctrl.untouched\"/>\r\n } @else {\r\n <p>{{ field.value }}</p>\r\n }\r\n }\r\n <mat-sidenav-container [hasBackdrop]=\"true\">\r\n <mat-sidenav #drawer [mode]=\"'over'\" [position]=\"'start'\" [autoFocus]=\"false\">\r\n <div class=\"main-sidenav\">\r\n <div class=\"sidenav-title bc-white\">\r\n <h3> Employee Information </h3>\r\n <ds-icon icon=\"close\" class=\"fc-black fs-20 p-3 cursor-pointer\" (click)=\"drawer.close()\"></ds-icon>\r\n </div>\r\n <div class=\"sidenav-body p-0\">\r\n <div class=\"d-flex flex-column align-items-center gap-3 sidenav-user bc-off-white text-center\">\r\n <ds-avatar [attr.image]=\"userImage()\" [attr.label]=\"userData?.name\"></ds-avatar>\r\n @if (userData?.employeeNumber) {\r\n <div class=\"d-flex flex-column gap-1\">\r\n <h4 class=\"fs-16 fc-black fw-medium mb-0\">{{ userData?.name }}</h4>\r\n @if (!userData?.job?.name) {\r\n <h6 class=\"fs-12 fc-dark-gray fw-normal mb-0\">{{ userData?.position?.name }}</h6>\r\n }\r\n @if (!userData?.position?.name) {\r\n <h6 class=\"fs-12 fc-dark-gray fw-normal mb-0\">{{ userData?.job?.name }}</h6>\r\n }\r\n </div>\r\n }\r\n <div class=\"d-flex flex-wrap gap-2\">\r\n <div class=\"fs-12 fc-black d-flex align-items-center gap-2 box-shadow bc-white radius-4 p-2 profile-box\">\r\n <ds-icon icon=\"mail-o\" class=\"fc-coral fs-20\"></ds-icon>\r\n <a [href]=\"'mailTo:' + userData?.email\" class=\"fc-black\">{{ userData?.email }}</a>\r\n </div>\r\n @if (userData?.contact?.mobile) {\r\n <div class=\"fs-12 fc-black d-flex align-items-center gap-2 box-shadow bc-white radius-4 p-2 profile-box\">\r\n <ds-icon icon=\"phone\" class=\"fc-coral fs-20\"></ds-icon>\r\n <a [href]=\"'tel:' + userData?.contact?.mobile\" class=\"fc-black\">\r\n <bdi>{{ userData?.contact?.mobile }}</bdi>\r\n </a>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-sidenav>\r\n </mat-sidenav-container>\r\n `,\r\n styles: `\r\n .mat-drawer {\r\n position: fixed;\r\n left: 0;\r\n }`,\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA]\r\n})\r\nexport class UserPickerField extends FieldBase {\r\n userImageHost = \"https://igateapp.stc.com.sa\";\r\n employeeService = inject(Employee);\r\n options: any = signal([]);\r\n userData: any;\r\n #query: Subject<string> = new Subject<string>();\r\n\r\n constructor() {\r\n super();\r\n this.#query.pipe(\r\n debounceTime(300),\r\n distinctUntilChanged(),\r\n // a new query cancels the request still in flight\r\n switchMap((query: string) => this.employeeService.search(query)),\r\n map((res: any) => {\r\n return res.map((user: any) => {\r\n user.value = user.email;\r\n user.label = user.name;\r\n return user;\r\n });\r\n }),\r\n takeUntilDestroyed(this.destroyRef)\r\n ).subscribe((res: any) => {\r\n this.options.set(res);\r\n });\r\n }\r\n\r\n userImage(): string | null {\r\n const image: string | undefined = this.userData?.profileImage ?? this.userData?.profileImageUrl;\r\n if (!image) {\r\n return null;\r\n }\r\n return image.startsWith(\"http\") ? image : this.userImageHost + image;\r\n }\r\n\r\n search(event: string) {\r\n this.#query.next(event);\r\n }\r\n\r\n updateField($event: string | FormData) {\r\n this.options.set([]);\r\n }\r\n\r\n showUserData(item: any) {\r\n this.userData = item;\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
package/fesm2022/iss-ctrl.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ai as ATTACHMENT_DOWNLOAD_URL, ah as ATTACHMENT_UPLOAD_RESPONSE_MAPPER, ag as ATTACHMENT_UPLOAD_URL, am as ArabicNumberPipe, a0 as AttachmentViewer, ab as COMPONENTS, a6 as COUNTRIES, d as CheckboxControl, v as CheckboxField, Y as CheckboxViewer, e as ChipsControl, q as ChipsField, Q as ChipsViewer, C as ControlBase, a8 as DATETIME_FORMAT, a7 as DATE_FORMAT_ADAPTER, a5 as DEFAULT_COUNTRY, D as DatePickerControl, B as DatePickerField, a3 as DatePickerTimeViewer, a2 as DatePickerViewer, f as DateRangePickerControl, J as DateRangePickerField, a4 as DateRangePickerViewer, h as DatetimePickerControl, G as DatetimePickerField, al as Droppable, E as Employee, ae as FIELD_DATA, F as FieldBase, an as FieldDataInjector, ar as FileHandler, i as FilePickerControl, z as FilePickerField, aw as FileValidators, c as FormEngine, H as HOST, ak as HintsComponent, j as InputControl, o as InputField, K as InputViewer, av as IssValidators, L as Loader, M as MobileControl, u as MobileField, X as MobileViewer, O as Outlet, P as PLACEHOLDER_REGEX, a9 as PLATE_LETTERS, as as Phone, k as PlateControl, y as PlateField, ao as PlateLetterPipe, $ as PlateViewer, R as RadioControl, s as RadioField, U as RadioViewer, ac as SERVICES, S as SelectControl, t as SelectField, ap as SelectStatusPipe, W as SelectViewer, l as SlideToggleControl, x as SlideToggleField, _ as SlideToggleViewer, T as TextareaControl, p as TextareaField, N as TextareaViewer, m as TimePickerControl, A as TimePickerField, a1 as TimePickerViewer, ax as TimeValidator, n as ToggleButtonControl, w as ToggleButtonField, Z as ToggleButtonViewer, aq as TranslatePipe, af as UI_LANGUAGE, aj as USER_SEARCH_API, aa as VALIDATION_MESSAGES, ad as VALIDATORS, V as VIEW_PROVIDER, a as ValidationMessageComponent, at as arrayFrom, au as formatFileSize, g as getPropertyByPath, r as replacePlaceholders } from './iss-ctrl-iss-ctrl-
|
|
1
|
+
export { ai as ATTACHMENT_DOWNLOAD_URL, ah as ATTACHMENT_UPLOAD_RESPONSE_MAPPER, ag as ATTACHMENT_UPLOAD_URL, am as ArabicNumberPipe, a0 as AttachmentViewer, ab as COMPONENTS, a6 as COUNTRIES, d as CheckboxControl, v as CheckboxField, Y as CheckboxViewer, e as ChipsControl, q as ChipsField, Q as ChipsViewer, C as ControlBase, a8 as DATETIME_FORMAT, a7 as DATE_FORMAT_ADAPTER, a5 as DEFAULT_COUNTRY, D as DatePickerControl, B as DatePickerField, a3 as DatePickerTimeViewer, a2 as DatePickerViewer, f as DateRangePickerControl, J as DateRangePickerField, a4 as DateRangePickerViewer, h as DatetimePickerControl, G as DatetimePickerField, al as Droppable, E as Employee, ae as FIELD_DATA, F as FieldBase, an as FieldDataInjector, ar as FileHandler, i as FilePickerControl, z as FilePickerField, aw as FileValidators, c as FormEngine, H as HOST, ak as HintsComponent, j as InputControl, o as InputField, K as InputViewer, av as IssValidators, L as Loader, M as MobileControl, u as MobileField, X as MobileViewer, O as Outlet, P as PLACEHOLDER_REGEX, a9 as PLATE_LETTERS, as as Phone, k as PlateControl, y as PlateField, ao as PlateLetterPipe, $ as PlateViewer, R as RadioControl, s as RadioField, U as RadioViewer, ac as SERVICES, S as SelectControl, t as SelectField, ap as SelectStatusPipe, W as SelectViewer, l as SlideToggleControl, x as SlideToggleField, _ as SlideToggleViewer, T as TextareaControl, p as TextareaField, N as TextareaViewer, m as TimePickerControl, A as TimePickerField, a1 as TimePickerViewer, ax as TimeValidator, n as ToggleButtonControl, w as ToggleButtonField, Z as ToggleButtonViewer, aq as TranslatePipe, af as UI_LANGUAGE, aj as USER_SEARCH_API, aa as VALIDATION_MESSAGES, ad as VALIDATORS, V as VIEW_PROVIDER, a as ValidationMessageComponent, at as arrayFrom, au as formatFileSize, g as getPropertyByPath, r as replacePlaceholders } from './iss-ctrl-iss-ctrl-BN9rcLt2.mjs';
|
|
2
2
|
//# sourceMappingURL=iss-ctrl.mjs.map
|
package/package.json
CHANGED
package/types/iss-ctrl.d.ts
CHANGED
|
@@ -52,7 +52,9 @@ interface Hint {
|
|
|
52
52
|
*
|
|
53
53
|
* ### Content projection
|
|
54
54
|
* Controls that render a `mat-form-field` project `<label>` into the floating label.
|
|
55
|
-
*
|
|
55
|
+
* An omitted label — or one that interpolates to an empty string — leaves `<mat-label>`
|
|
56
|
+
* empty, and `upgrade.scss` collapses the floating-label space for it. No label markup is
|
|
57
|
+
* removed at runtime, so a label that arrives later simply shows up.
|
|
56
58
|
*
|
|
57
59
|
* @example
|
|
58
60
|
* ```html
|
|
@@ -116,16 +118,12 @@ declare class ControlBase implements ControlValueAccessor, Validator {
|
|
|
116
118
|
*/
|
|
117
119
|
onChange: OutputEmitterRef<any>;
|
|
118
120
|
protected ctrl: FormControl;
|
|
119
|
-
protected hasLabel: WritableSignal<boolean>;
|
|
120
|
-
private hostRef;
|
|
121
|
-
constructor();
|
|
122
121
|
registerOnChange(fn: () => void): void;
|
|
123
122
|
registerOnTouched(fn: () => void): void;
|
|
124
123
|
setDisabledState(isDisabled: boolean): void;
|
|
125
124
|
writeValue(value: string | FormData | Date | null): void;
|
|
126
125
|
markAsTouched(): void;
|
|
127
126
|
validate(control: AbstractControl): ValidationErrors | null;
|
|
128
|
-
private hasProjectedLabel;
|
|
129
127
|
protected onTouch: () => void;
|
|
130
128
|
protected onPropagateValue: (_: any) => void;
|
|
131
129
|
protected emitValue(value?: any): void;
|
package/upgrade.scss
CHANGED
|
@@ -54,6 +54,22 @@ mat-form-field.mat-mdc-form-field:has(mat-label) .mat-mdc-form-field-infix {
|
|
|
54
54
|
padding-top: 10px !important;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// mat-form-field always renders its floating label, so a control whose label is omitted or
|
|
58
|
+
// interpolates to "" would keep the space above the input. Both cases leave an :empty element
|
|
59
|
+
// — <mat-label> itself when nothing is projected, the projected <label> when its text is empty
|
|
60
|
+
// — which is what these selectors collapse. Keep <mat-label> free of whitespace in templates,
|
|
61
|
+
// or it is never :empty.
|
|
62
|
+
mat-form-field.mat-mdc-form-field:has(mat-label:empty),
|
|
63
|
+
mat-form-field.mat-mdc-form-field:has(mat-label > label:empty) {
|
|
64
|
+
.mdc-floating-label {
|
|
65
|
+
display: none !important;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.mat-mdc-form-field-infix {
|
|
69
|
+
padding-top: 0 !important;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
57
73
|
|
|
58
74
|
mat-form-field.mat-mdc-form-field
|
|
59
75
|
.mat-mdc-input-element::placeholder {
|