@unopsitg/ux 21.0.5 → 21.0.20
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/README.md +15 -0
- package/assets/_card.scss +89 -2
- package/assets/_config.scss +3 -3
- package/assets/_content.scss +39 -5
- package/assets/_footer.scss +59 -3
- package/assets/_main.scss +6 -8
- package/assets/_responsive.scss +15 -3
- package/assets/_sass_variables.scss +8 -2
- package/assets/_search.scss +3 -3
- package/assets/_tabs.scss +44 -0
- package/assets/_tags.scss +1 -1
- package/assets/_topbar.scss +45 -17
- package/assets/_utils.scss +0 -12
- package/assets/layout.scss +1 -0
- package/assets/sidebar/_sidebar_compact.scss +1 -6
- package/assets/sidebar/_sidebar_horizontal.scss +97 -76
- package/assets/sidebar/_sidebar_slim.scss +1 -6
- package/assets/sidebar/_sidebar_theme_core.scss +19 -19
- package/assets/sidebar/themes/_dark.scss +5 -5
- package/assets/sidebar/themes/_light.scss +2 -2
- package/assets/sidebar/themes/_primary.scss +8 -8
- package/assets/tailwind.css +47 -18
- package/assets/variables/_common.scss +1 -0
- package/assets/variables/_light.scss +2 -2
- package/fesm2022/unopsitg-ux.mjs +1532 -574
- package/fesm2022/unopsitg-ux.mjs.map +1 -1
- package/package.json +1 -1
- package/types/unopsitg-ux.d.ts +211 -203
- package/assets/opp/AppLogo/AppLogo-onDark_V.svg +0 -55
- package/assets/opp/AppLogo/AppLogo-onLight_V.svg +0 -55
- package/assets/opp/AppLogo-dark-vertical.svg +0 -55
- package/assets/opp/drive-download-20260421T141232Z-3-001.zip +0 -0
- package/assets/opp/favicon/favicon.svg +0 -17
- package/assets/opp/logo-dark-horizontal.svg +0 -55
- package/assets/opp/logo-light-horizontal.svg +0 -55
package/fesm2022/unopsitg-ux.mjs
CHANGED
|
@@ -3,23 +3,23 @@ import SoftBase from '@primeuix/themes/aura';
|
|
|
3
3
|
import CrispBase from '@primeuix/themes/lara';
|
|
4
4
|
import ContrastBase from '@primeuix/themes/nora';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
|
-
import { InjectionToken, signal, inject, computed, effect, Injectable, Component, PLATFORM_ID, model, booleanAttribute, Input, input, HostListener, ViewChild, ElementRef,
|
|
6
|
+
import { InjectionToken, signal, inject, computed, effect, Injectable, Component, PLATFORM_ID, model, booleanAttribute, Input, input, ChangeDetectionStrategy, HostListener, ViewChild, ElementRef, output, DestroyRef, Directive, ContentChildren } from '@angular/core';
|
|
7
7
|
import * as i1 from '@angular/router';
|
|
8
8
|
import { Router, NavigationEnd, RouterModule } from '@angular/router';
|
|
9
9
|
import * as i1$1 from '@angular/common';
|
|
10
|
-
import { CommonModule, isPlatformBrowser, NgClass } from '@angular/common';
|
|
10
|
+
import { CommonModule, isPlatformBrowser, NgTemplateOutlet, NgClass } from '@angular/common';
|
|
11
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
11
12
|
import { BehaviorSubject, filter, Subject, takeUntil } from 'rxjs';
|
|
12
|
-
import * as
|
|
13
|
+
import * as i1$2 from '@angular/forms';
|
|
13
14
|
import { FormsModule } from '@angular/forms';
|
|
14
15
|
import { PrimeNG } from 'primeng/config';
|
|
15
16
|
import * as i4 from 'primeng/drawer';
|
|
16
17
|
import { DrawerModule } from 'primeng/drawer';
|
|
17
|
-
import * as i5
|
|
18
|
+
import * as i5 from 'primeng/radiobutton';
|
|
18
19
|
import { RadioButtonModule } from 'primeng/radiobutton';
|
|
19
20
|
import * as i3 from 'primeng/selectbutton';
|
|
20
21
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
21
|
-
import
|
|
22
|
-
import * as i6 from 'primeng/button';
|
|
22
|
+
import * as i2$1 from 'primeng/button';
|
|
23
23
|
import { ButtonModule } from 'primeng/button';
|
|
24
24
|
import * as i2 from 'primeng/divider';
|
|
25
25
|
import { DividerModule } from 'primeng/divider';
|
|
@@ -29,28 +29,42 @@ import * as i3$1 from 'primeng/select';
|
|
|
29
29
|
import { SelectModule } from 'primeng/select';
|
|
30
30
|
import * as i3$2 from 'primeng/autofocus';
|
|
31
31
|
import { AutoFocusModule } from 'primeng/autofocus';
|
|
32
|
-
import * as i1$
|
|
32
|
+
import * as i1$3 from 'primeng/dialog';
|
|
33
33
|
import { DialogModule } from 'primeng/dialog';
|
|
34
34
|
import * as i4$2 from 'primeng/ripple';
|
|
35
35
|
import { RippleModule } from 'primeng/ripple';
|
|
36
36
|
import * as i3$3 from 'primeng/tooltip';
|
|
37
37
|
import { TooltipModule } from 'primeng/tooltip';
|
|
38
|
-
import * as
|
|
38
|
+
import * as i9 from 'primeng/avatar';
|
|
39
39
|
import { AvatarModule } from 'primeng/avatar';
|
|
40
|
-
import * as
|
|
40
|
+
import * as i7 from 'primeng/badge';
|
|
41
41
|
import { BadgeModule } from 'primeng/badge';
|
|
42
|
-
import * as
|
|
42
|
+
import * as i4$3 from 'primeng/iconfield';
|
|
43
43
|
import { IconFieldModule } from 'primeng/iconfield';
|
|
44
|
-
import * as
|
|
44
|
+
import * as i5$1 from 'primeng/inputicon';
|
|
45
45
|
import { InputIconModule } from 'primeng/inputicon';
|
|
46
|
-
import * as
|
|
46
|
+
import * as i8 from 'primeng/overlaybadge';
|
|
47
47
|
import { OverlayBadgeModule } from 'primeng/overlaybadge';
|
|
48
|
-
import * as
|
|
49
|
-
import { StyleClassModule } from 'primeng/styleclass';
|
|
50
|
-
import * as i2$1 from 'primeng/paginator';
|
|
48
|
+
import * as i2$2 from 'primeng/paginator';
|
|
51
49
|
import { PaginatorModule } from 'primeng/paginator';
|
|
52
|
-
import * as
|
|
50
|
+
import * as i4$4 from 'primeng/tabs';
|
|
53
51
|
import { TabsModule } from 'primeng/tabs';
|
|
52
|
+
import * as i3$4 from 'primeng/fileupload';
|
|
53
|
+
import { FileUploadModule } from 'primeng/fileupload';
|
|
54
|
+
import * as i7$1 from 'primeng/menu';
|
|
55
|
+
import { MenuModule } from 'primeng/menu';
|
|
56
|
+
import * as i10 from 'primeng/panel';
|
|
57
|
+
import { PanelModule } from 'primeng/panel';
|
|
58
|
+
import * as i8$1 from 'primeng/table';
|
|
59
|
+
import { TableModule } from 'primeng/table';
|
|
60
|
+
import * as i9$1 from 'primeng/tag';
|
|
61
|
+
import { TagModule } from 'primeng/tag';
|
|
62
|
+
import * as i8$2 from 'primeng/autocomplete';
|
|
63
|
+
import { AutoCompleteModule } from 'primeng/autocomplete';
|
|
64
|
+
import * as i7$2 from 'primeng/datepicker';
|
|
65
|
+
import { DatePickerModule } from 'primeng/datepicker';
|
|
66
|
+
import * as i5$2 from 'primeng/textarea';
|
|
67
|
+
import { TextareaModule } from 'primeng/textarea';
|
|
54
68
|
|
|
55
69
|
/**
|
|
56
70
|
* Brand theme presets built on top of PrimeUIX base presets.
|
|
@@ -61,8 +75,8 @@ import { TabsModule } from 'primeng/tabs';
|
|
|
61
75
|
* Contrast <- @primeuix/themes/nora
|
|
62
76
|
*/
|
|
63
77
|
const brandPrimitives = {
|
|
64
|
-
deepsea: { 50: '#
|
|
65
|
-
gray: { 50: '#
|
|
78
|
+
deepsea: { 50: '#c3c7cb', 100: '#9ea5ac', 200: '#7a838d', 300: '#56626d', 400: '#31404e', 500: '#0d1e2f', 600: '#0b1a28', 700: '#091521', 800: '#07111a', 900: '#050c13', 950: '#03080c' },
|
|
79
|
+
gray: { 50: '#f8fafc', 100: '#f1f5f9', 200: '#e2e8f0', 300: '#cbd5e1', 400: '#94a3b8', 500: '#64748b', 600: '#475569', 700: '#334155', 800: '#1e293b', 900: '#0f172a', 950: '#020617' },
|
|
66
80
|
red: { 50: '#f6cac6', 100: '#f0a9a4', 200: '#eb8982', 300: '#e56960', 400: '#e0493e', 500: '#da291c', 600: '#b92318', 700: '#991d14', 800: '#78170f', 900: '#57100b', 950: '#370a07' },
|
|
67
81
|
orange: { 50: '#f9d6c3', 100: '#f6be9f', 200: '#f2a57a', 300: '#ef8d56', 400: '#eb7432', 500: '#e85c0e', 600: '#c54e0c', 700: '#a2400a', 800: '#803308', 900: '#5d2506', 950: '#3a1704' },
|
|
68
82
|
yellow: { 50: '#fff0c5', 100: '#ffe7a1', 200: '#ffdd7e', 300: '#ffd45b', 400: '#ffcb38', 500: '#ffc215', 600: '#d9a512', 700: '#b3880f', 800: '#8c6b0c', 900: '#664e08', 950: '#403105' },
|
|
@@ -76,7 +90,8 @@ const brandPrimitives = {
|
|
|
76
90
|
blue: { 50: '#DEEFFF', 100: '#C9E8FF', 150: '#99D3ED', 200: '#73c3e6', 300: '#4db3df', 400: '#26a2d8', 500: '#0092d1', 600: '#007cb2', 700: '#006692', 800: '#005073', 900: '#003a54', 950: '#002534' },
|
|
77
91
|
darkblue: { 50: '#D0EEFF', 100: '#B7E2F9', 200: '#73abc7', 300: '#4d94b8', 400: '#267da9', 500: '#00669a', 600: '#005783', 700: '#00476c', 800: '#003855', 900: '#00293e', 950: '#001a27' },
|
|
78
92
|
midnight: { 50: '#bfd2dd', 100: '#99b6c8', 200: '#739bb4', 300: '#4d809f', 400: '#26648b', 500: '#004976', 600: '#003e64', 700: '#003353', 800: '#002841', 850: '#001E31', 900: '#001d2f', 950: '#00121e' },
|
|
79
|
-
cherry: { 50: '#e6c7d9', 100: '#d6a5c2', 200: '#c783ab', 300: '#b86294', 400: '#a8407d', 500: '#991e66', 600: '#821a57', 700: '#6b1547', 800: '#541138', 900: '#3d0c29', 950: '#26081a' }
|
|
93
|
+
cherry: { 50: '#e6c7d9', 100: '#d6a5c2', 200: '#c783ab', 300: '#b86294', 400: '#a8407d', 500: '#991e66', 600: '#821a57', 700: '#6b1547', 800: '#541138', 900: '#3d0c29', 950: '#26081a' },
|
|
94
|
+
ai: { 50: '#f0edff', 100: '#e4deff', 200: '#cdc2ff', 300: '#b0a0ff', 400: '#9378ff', 500: '#7c5cfc', 600: '#6a44f0', 700: '#5835d4', 800: '#482dac', 900: '#3b278a', 950: '#24185e' }
|
|
80
95
|
};
|
|
81
96
|
const brandOverrides = {
|
|
82
97
|
primitive: {
|
|
@@ -115,17 +130,17 @@ const brandOverrides = {
|
|
|
115
130
|
light: {
|
|
116
131
|
surface: {
|
|
117
132
|
0: '#ffffff',
|
|
118
|
-
50: '{
|
|
119
|
-
100: '{
|
|
120
|
-
200: '{
|
|
121
|
-
300: '{
|
|
122
|
-
400: '{
|
|
123
|
-
500: '{
|
|
124
|
-
600: '{
|
|
125
|
-
700: '{
|
|
126
|
-
800: '{
|
|
127
|
-
900: '{
|
|
128
|
-
950: '{
|
|
133
|
+
50: '{gray.50}',
|
|
134
|
+
100: '{gray.100}',
|
|
135
|
+
200: '{gray.200}',
|
|
136
|
+
300: '{gray.300}',
|
|
137
|
+
400: '{gray.400}',
|
|
138
|
+
500: '{gray.500}',
|
|
139
|
+
600: '{gray.600}',
|
|
140
|
+
700: '{gray.700}',
|
|
141
|
+
800: '{gray.800}',
|
|
142
|
+
900: '{gray.900}',
|
|
143
|
+
950: '{gray.950}'
|
|
129
144
|
}
|
|
130
145
|
},
|
|
131
146
|
dark: {
|
|
@@ -135,8 +150,8 @@ const brandOverrides = {
|
|
|
135
150
|
100: '{darkblue.100}',
|
|
136
151
|
200: '{darkblue.200}',
|
|
137
152
|
300: '{darkblue.300}',
|
|
138
|
-
400: '{
|
|
139
|
-
500: '{
|
|
153
|
+
400: '{blue.400}',
|
|
154
|
+
500: '{blue.500}',
|
|
140
155
|
600: '{darkblue.600}',
|
|
141
156
|
700: '{darkblue.700}',
|
|
142
157
|
800: '{darkblue.800}',
|
|
@@ -147,6 +162,12 @@ const brandOverrides = {
|
|
|
147
162
|
}
|
|
148
163
|
},
|
|
149
164
|
components: {
|
|
165
|
+
accordion: {
|
|
166
|
+
root: { transitionDuration: '{transition.duration}' },
|
|
167
|
+
panel: { borderWidth: '0' },
|
|
168
|
+
header: { background: 'transparent', padding: '0 0 0 0' },
|
|
169
|
+
content: { background: 'transparent' }
|
|
170
|
+
},
|
|
150
171
|
button: {
|
|
151
172
|
colorScheme: {
|
|
152
173
|
light: {
|
|
@@ -175,34 +196,36 @@ const brandOverrides = {
|
|
|
175
196
|
}
|
|
176
197
|
}
|
|
177
198
|
},
|
|
199
|
+
// Tab active/hover backgrounds are set in _tabs.scss via sidebar
|
|
200
|
+
// `--d-menuitem-*` tokens (not expressible in the preset). Only structural
|
|
201
|
+
// properties that _tabs.scss does NOT override belong here.
|
|
178
202
|
tabs: {
|
|
179
203
|
tablist: {
|
|
180
|
-
background: 'transparent'
|
|
204
|
+
background: 'transparent',
|
|
205
|
+
borderWidth: '0 0 1px 0'
|
|
181
206
|
},
|
|
182
207
|
tab: {
|
|
183
208
|
background: 'transparent',
|
|
184
|
-
hoverBackground: '{primary.50}',
|
|
185
|
-
hoverColor: '{primary.700}',
|
|
186
|
-
activeBackground: '{primary.100}',
|
|
187
|
-
activeColor: '{primary.900}',
|
|
188
209
|
borderColor: 'transparent',
|
|
189
|
-
activeBorderColor: '
|
|
190
|
-
|
|
210
|
+
activeBorderColor: 'transparent',
|
|
211
|
+
borderWidth: '0',
|
|
212
|
+
padding: '0.5rem 1rem',
|
|
213
|
+
margin: '0 0 0.5rem 0'
|
|
191
214
|
},
|
|
192
215
|
tabpanel: {
|
|
193
216
|
background: 'transparent',
|
|
194
217
|
padding: '0'
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
dataview: {
|
|
221
|
+
header: {
|
|
222
|
+
background: 'transparent',
|
|
223
|
+
borderWidth: '0',
|
|
224
|
+
padding: '0'
|
|
195
225
|
},
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
hoverBackground: '{primary.900}',
|
|
200
|
-
hoverColor: '{primary.200}',
|
|
201
|
-
activeBackground: '{surface.800}',
|
|
202
|
-
activeColor: '{primary.200}',
|
|
203
|
-
activeBorderColor: '{primary.400}'
|
|
204
|
-
}
|
|
205
|
-
}
|
|
226
|
+
content: {
|
|
227
|
+
background: 'transparent',
|
|
228
|
+
padding: '0'
|
|
206
229
|
}
|
|
207
230
|
},
|
|
208
231
|
paginator: {
|
|
@@ -215,6 +238,64 @@ const brandOverrides = {
|
|
|
215
238
|
background: 'transparent'
|
|
216
239
|
}
|
|
217
240
|
},
|
|
241
|
+
panel: {
|
|
242
|
+
root: {
|
|
243
|
+
background: 'transparent',
|
|
244
|
+
borderColor: 'transparent',
|
|
245
|
+
borderRadius: '0'
|
|
246
|
+
},
|
|
247
|
+
header: {
|
|
248
|
+
background: 'transparent',
|
|
249
|
+
padding: '0',
|
|
250
|
+
borderWidth: '0'
|
|
251
|
+
},
|
|
252
|
+
toggleableHeader: {
|
|
253
|
+
padding: '0'
|
|
254
|
+
},
|
|
255
|
+
title: {
|
|
256
|
+
fontWeight: '700'
|
|
257
|
+
},
|
|
258
|
+
content: {
|
|
259
|
+
padding: '0'
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
card: {
|
|
263
|
+
root: {
|
|
264
|
+
shadow: 'none',
|
|
265
|
+
borderRadius: '{border.radius.xl}'
|
|
266
|
+
},
|
|
267
|
+
body: {
|
|
268
|
+
padding: '1.25rem',
|
|
269
|
+
gap: '1rem'
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
avatar: {
|
|
273
|
+
root: {
|
|
274
|
+
borderRadius: '9999px',
|
|
275
|
+
fontSize: '0.875rem'
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
drawer: {
|
|
279
|
+
content: { padding: '1.25rem' }
|
|
280
|
+
},
|
|
281
|
+
inputtext: {
|
|
282
|
+
root: {
|
|
283
|
+
borderRadius: '{border.radius.xl}',
|
|
284
|
+
paddingY: '0.5rem'
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
divider: {
|
|
288
|
+
horizontal: {
|
|
289
|
+
margin: '0',
|
|
290
|
+
padding: '0',
|
|
291
|
+
content: { padding: '0 0.5rem' }
|
|
292
|
+
},
|
|
293
|
+
vertical: {
|
|
294
|
+
margin: '0',
|
|
295
|
+
padding: '0',
|
|
296
|
+
content: { padding: '0.5rem 0' }
|
|
297
|
+
}
|
|
298
|
+
},
|
|
218
299
|
tag: {
|
|
219
300
|
root: {
|
|
220
301
|
padding: '0.25rem 0.5rem',
|
|
@@ -224,22 +305,47 @@ const brandOverrides = {
|
|
|
224
305
|
light: {
|
|
225
306
|
secondary: { color: '{surface.800}' },
|
|
226
307
|
success: { color: '{green.800}' },
|
|
227
|
-
active: { color: '{green.800}' },
|
|
228
|
-
inactive: { color: '{gray.800}' },
|
|
229
308
|
info: { color: '{blue.800}' },
|
|
230
309
|
warn: { color: '{orange.800}' },
|
|
231
|
-
|
|
310
|
+
danger: { color: '{red.800}' }
|
|
232
311
|
},
|
|
233
312
|
dark: {
|
|
234
313
|
secondary: { color: '{surface.100}' },
|
|
235
314
|
success: { color: '{green.100}' },
|
|
236
|
-
active: { color: '{green.100}' },
|
|
237
315
|
info: { color: '{blue.100}' },
|
|
238
|
-
inactive: { color: '{gray.100}' },
|
|
239
316
|
warn: { color: '{orange.100}' },
|
|
240
|
-
|
|
317
|
+
danger: { color: '{red.100}' }
|
|
241
318
|
}
|
|
242
319
|
}
|
|
320
|
+
},
|
|
321
|
+
toolbar: {
|
|
322
|
+
root: {
|
|
323
|
+
background: 'transparent',
|
|
324
|
+
borderColor: 'transparent',
|
|
325
|
+
borderRadius: '0',
|
|
326
|
+
padding: '0',
|
|
327
|
+
gap: '0.5rem'
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
progressbar: {
|
|
331
|
+
root: {
|
|
332
|
+
borderRadius: '{border.radius.lg}',
|
|
333
|
+
height: '0.75rem'
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
message: {
|
|
337
|
+
root: {
|
|
338
|
+
borderRadius: '{border.radius.lg}',
|
|
339
|
+
borderWidth: '0 0 0 4px'
|
|
340
|
+
},
|
|
341
|
+
content: {
|
|
342
|
+
padding: '0.75rem 1rem',
|
|
343
|
+
gap: '0.5rem'
|
|
344
|
+
},
|
|
345
|
+
text: {
|
|
346
|
+
fontSize: '0.875rem',
|
|
347
|
+
fontWeight: '500'
|
|
348
|
+
}
|
|
243
349
|
}
|
|
244
350
|
}
|
|
245
351
|
};
|
|
@@ -429,6 +535,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
429
535
|
}]
|
|
430
536
|
}], ctorParameters: () => [] });
|
|
431
537
|
|
|
538
|
+
class FooterService {
|
|
539
|
+
content = signal(null, ...(ngDevMode ? [{ debugName: "content" }] : []));
|
|
540
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: FooterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
541
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: FooterService, providedIn: 'root' });
|
|
542
|
+
}
|
|
543
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: FooterService, decorators: [{
|
|
544
|
+
type: Injectable,
|
|
545
|
+
args: [{ providedIn: 'root' }]
|
|
546
|
+
}] });
|
|
547
|
+
|
|
432
548
|
class AppBreadcrumb {
|
|
433
549
|
router;
|
|
434
550
|
_breadcrumbs$ = new BehaviorSubject([]);
|
|
@@ -501,11 +617,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
501
617
|
class AppConfigurator {
|
|
502
618
|
simple = false;
|
|
503
619
|
location = 'app';
|
|
504
|
-
router = inject(Router);
|
|
505
620
|
config = inject(PrimeNG);
|
|
506
621
|
layoutService = inject(LayoutService);
|
|
507
622
|
platformId = inject(PLATFORM_ID);
|
|
508
|
-
primeng = inject(PrimeNG);
|
|
509
623
|
presetKeys = Object.keys(brandPresets);
|
|
510
624
|
themeOptions = [
|
|
511
625
|
{ name: 'Light', value: false },
|
|
@@ -533,42 +647,10 @@ class AppConfigurator {
|
|
|
533
647
|
];
|
|
534
648
|
}
|
|
535
649
|
}
|
|
536
|
-
surfaces = [
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
0: '#ffffff',
|
|
541
|
-
50: '#e5e6e6',
|
|
542
|
-
100: '#d5d6d7',
|
|
543
|
-
200: '#c6c7c8',
|
|
544
|
-
300: '#b6b8b9',
|
|
545
|
-
400: '#a7a8aa',
|
|
546
|
-
500: '#97999b',
|
|
547
|
-
600: '#808284',
|
|
548
|
-
700: '#6a6b6d',
|
|
549
|
-
800: '#535455',
|
|
550
|
-
900: '#3c3d3e',
|
|
551
|
-
950: '#262627'
|
|
552
|
-
}
|
|
553
|
-
},
|
|
554
|
-
{
|
|
555
|
-
name: 'darkblue',
|
|
556
|
-
palette: {
|
|
557
|
-
0: '#ffffff',
|
|
558
|
-
50: '#D0EEFF',
|
|
559
|
-
100: '#B7E2F9',
|
|
560
|
-
200: '#73abc7',
|
|
561
|
-
300: '#73abc7',
|
|
562
|
-
400: '#4d94b8',
|
|
563
|
-
500: '#267da9',
|
|
564
|
-
600: '#00669a',
|
|
565
|
-
700: '#005783',
|
|
566
|
-
800: '#00476c',
|
|
567
|
-
900: '#00293e',
|
|
568
|
-
950: '#001a27'
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
];
|
|
650
|
+
surfaces = ['gray', 'darkblue'].map(name => ({
|
|
651
|
+
name,
|
|
652
|
+
palette: { 0: '#ffffff', ...brandPrimitives[name] }
|
|
653
|
+
}));
|
|
572
654
|
selectedPrimaryColor = computed(() => {
|
|
573
655
|
return this.layoutService.layoutConfig().primary;
|
|
574
656
|
}, ...(ngDevMode ? [{ debugName: "selectedPrimaryColor" }] : []));
|
|
@@ -834,12 +916,12 @@ class AppConfigurator {
|
|
|
834
916
|
</div>
|
|
835
917
|
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
836
918
|
<span class="text-lg text-muted-color font-semibold">Card Style</span>
|
|
837
|
-
<p-selectbutton [ngModel]="cardStyle()" (ngModelChange)="onCardStyleChange($event)" [options]="cardStyleOptions" optionLabel="name" optionValue="value" [allowEmpty]="false"
|
|
919
|
+
<p-selectbutton [ngModel]="cardStyle()" (ngModelChange)="onCardStyleChange($event)" [options]="cardStyleOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" />
|
|
838
920
|
</div>
|
|
839
921
|
|
|
840
922
|
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
841
923
|
<span class="text-lg text-muted-color font-semibold">Menu Theme</span>
|
|
842
|
-
<p-selectbutton [ngModel]="menuTheme()" (ngModelChange)="onMenuThemeChange($event)" [options]="menuThemeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false"
|
|
924
|
+
<p-selectbutton [ngModel]="menuTheme()" (ngModelChange)="onMenuThemeChange($event)" [options]="menuThemeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" />
|
|
843
925
|
</div>
|
|
844
926
|
|
|
845
927
|
<div *ngIf="!simple && location === 'app'">
|
|
@@ -857,30 +939,16 @@ class AppConfigurator {
|
|
|
857
939
|
</div>
|
|
858
940
|
</div>
|
|
859
941
|
<div class="flex">
|
|
860
|
-
<div class="flex items-center gap-2 w-6/12">
|
|
861
|
-
<p-radiobutton name="menuMode" value="overlay" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('overlay')" inputId="overlay"></p-radiobutton>
|
|
862
|
-
<label for="overlay">Overlay</label>
|
|
863
|
-
</div>
|
|
864
942
|
<div class="flex items-center gap-2 w-6/12">
|
|
865
943
|
<p-radiobutton name="menuMode" value="slim" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('slim')" inputId="slim"></p-radiobutton>
|
|
866
944
|
<label for="slim">Slim</label>
|
|
867
945
|
</div>
|
|
868
|
-
</div>
|
|
869
|
-
<div class="flex">
|
|
870
946
|
<div class="flex items-center gap-2 w-6/12">
|
|
871
947
|
<p-radiobutton name="menuMode" value="compact" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('compact')" inputId="compact"></p-radiobutton>
|
|
872
948
|
<label for="compact">Compact</label>
|
|
873
949
|
</div>
|
|
874
|
-
<div class="flex items-center gap-2 w-6/12">
|
|
875
|
-
<p-radiobutton name="menuMode" value="reveal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('reveal')" inputId="reveal"></p-radiobutton>
|
|
876
|
-
<label for="reveal">Reveal</label>
|
|
877
|
-
</div>
|
|
878
950
|
</div>
|
|
879
951
|
<div class="flex">
|
|
880
|
-
<div class="flex items-center gap-2 w-6/12">
|
|
881
|
-
<p-radiobutton name="menuMode" value="drawer" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('drawer')" inputId="drawer"></p-radiobutton>
|
|
882
|
-
<label for="drawer">Drawer</label>
|
|
883
|
-
</div>
|
|
884
952
|
<div class="flex items-center gap-2 w-6/12">
|
|
885
953
|
<p-radiobutton name="menuMode" value="horizontal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('horizontal')" inputId="horizontal"></p-radiobutton>
|
|
886
954
|
<label for="horizontal">Horizontal</label>
|
|
@@ -891,13 +959,13 @@ class AppConfigurator {
|
|
|
891
959
|
</div>
|
|
892
960
|
</div>
|
|
893
961
|
</p-drawer>
|
|
894
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type:
|
|
962
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i4.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: i5.RadioButton, selector: "p-radioButton, p-radiobutton, p-radio-button", inputs: ["value", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "styleClass", "autofocus", "binary", "variant", "size"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
895
963
|
}
|
|
896
964
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppConfigurator, decorators: [{
|
|
897
965
|
type: Component,
|
|
898
966
|
args: [{
|
|
899
967
|
selector: 'app-configurator',
|
|
900
|
-
imports: [CommonModule, FormsModule, SelectButtonModule, DrawerModule,
|
|
968
|
+
imports: [CommonModule, FormsModule, SelectButtonModule, DrawerModule, RadioButtonModule],
|
|
901
969
|
template: `
|
|
902
970
|
<p-drawer [(visible)]="configSidebarVisible" position="right" [transitionOptions]="'.3s cubic-bezier(0, 0, 0.2, 1)'" styleClass="layout-config-sidebar w-80" header="Settings" appendTo="body">
|
|
903
971
|
<div class="flex flex-col gap-6">
|
|
@@ -952,12 +1020,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
952
1020
|
</div>
|
|
953
1021
|
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
954
1022
|
<span class="text-lg text-muted-color font-semibold">Card Style</span>
|
|
955
|
-
<p-selectbutton [ngModel]="cardStyle()" (ngModelChange)="onCardStyleChange($event)" [options]="cardStyleOptions" optionLabel="name" optionValue="value" [allowEmpty]="false"
|
|
1023
|
+
<p-selectbutton [ngModel]="cardStyle()" (ngModelChange)="onCardStyleChange($event)" [options]="cardStyleOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" />
|
|
956
1024
|
</div>
|
|
957
1025
|
|
|
958
1026
|
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
959
1027
|
<span class="text-lg text-muted-color font-semibold">Menu Theme</span>
|
|
960
|
-
<p-selectbutton [ngModel]="menuTheme()" (ngModelChange)="onMenuThemeChange($event)" [options]="menuThemeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false"
|
|
1028
|
+
<p-selectbutton [ngModel]="menuTheme()" (ngModelChange)="onMenuThemeChange($event)" [options]="menuThemeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" />
|
|
961
1029
|
</div>
|
|
962
1030
|
|
|
963
1031
|
<div *ngIf="!simple && location === 'app'">
|
|
@@ -975,30 +1043,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
975
1043
|
</div>
|
|
976
1044
|
</div>
|
|
977
1045
|
<div class="flex">
|
|
978
|
-
<div class="flex items-center gap-2 w-6/12">
|
|
979
|
-
<p-radiobutton name="menuMode" value="overlay" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('overlay')" inputId="overlay"></p-radiobutton>
|
|
980
|
-
<label for="overlay">Overlay</label>
|
|
981
|
-
</div>
|
|
982
1046
|
<div class="flex items-center gap-2 w-6/12">
|
|
983
1047
|
<p-radiobutton name="menuMode" value="slim" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('slim')" inputId="slim"></p-radiobutton>
|
|
984
1048
|
<label for="slim">Slim</label>
|
|
985
1049
|
</div>
|
|
986
|
-
</div>
|
|
987
|
-
<div class="flex">
|
|
988
1050
|
<div class="flex items-center gap-2 w-6/12">
|
|
989
1051
|
<p-radiobutton name="menuMode" value="compact" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('compact')" inputId="compact"></p-radiobutton>
|
|
990
1052
|
<label for="compact">Compact</label>
|
|
991
1053
|
</div>
|
|
992
|
-
<div class="flex items-center gap-2 w-6/12">
|
|
993
|
-
<p-radiobutton name="menuMode" value="reveal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('reveal')" inputId="reveal"></p-radiobutton>
|
|
994
|
-
<label for="reveal">Reveal</label>
|
|
995
|
-
</div>
|
|
996
1054
|
</div>
|
|
997
1055
|
<div class="flex">
|
|
998
|
-
<div class="flex items-center gap-2 w-6/12">
|
|
999
|
-
<p-radiobutton name="menuMode" value="drawer" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('drawer')" inputId="drawer"></p-radiobutton>
|
|
1000
|
-
<label for="drawer">Drawer</label>
|
|
1001
|
-
</div>
|
|
1002
1056
|
<div class="flex items-center gap-2 w-6/12">
|
|
1003
1057
|
<p-radiobutton name="menuMode" value="horizontal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('horizontal')" inputId="horizontal"></p-radiobutton>
|
|
1004
1058
|
<label for="horizontal">Horizontal</label>
|
|
@@ -1018,26 +1072,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1018
1072
|
type: Input
|
|
1019
1073
|
}], cardStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardStyle", required: false }] }, { type: i0.Output, args: ["cardStyleChange"] }] } });
|
|
1020
1074
|
|
|
1021
|
-
class AppFooter {
|
|
1022
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1023
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppFooter, isStandalone: true, selector: "[app-footer]", ngImport: i0, template: `
|
|
1024
|
-
<footer class="layout-footer">
|
|
1025
|
-
<span class="footer-copyright">© UNOPS 2026</span>
|
|
1026
|
-
</footer>
|
|
1027
|
-
`, isInline: true });
|
|
1028
|
-
}
|
|
1029
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppFooter, decorators: [{
|
|
1030
|
-
type: Component,
|
|
1031
|
-
args: [{
|
|
1032
|
-
selector: '[app-footer]',
|
|
1033
|
-
template: `
|
|
1034
|
-
<footer class="layout-footer">
|
|
1035
|
-
<span class="footer-copyright">© UNOPS 2026</span>
|
|
1036
|
-
</footer>
|
|
1037
|
-
`
|
|
1038
|
-
}]
|
|
1039
|
-
}] });
|
|
1040
|
-
|
|
1041
1075
|
class AppRightMenu {
|
|
1042
1076
|
layoutService = inject(LayoutService);
|
|
1043
1077
|
cards = [
|
|
@@ -1059,7 +1093,7 @@ class AppRightMenu {
|
|
|
1059
1093
|
<div class="flex flex-col mt-7">
|
|
1060
1094
|
<div class="flex gap-6">
|
|
1061
1095
|
<div class="flex flex-col items-center">
|
|
1062
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1096
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1063
1097
|
<i class="pi pi-dollar text-blue-600 text-2xl!"></i>
|
|
1064
1098
|
</span>
|
|
1065
1099
|
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
@@ -1071,7 +1105,7 @@ class AppRightMenu {
|
|
|
1071
1105
|
</div>
|
|
1072
1106
|
<div class="flex gap-6">
|
|
1073
1107
|
<div class="flex flex-col items-center">
|
|
1074
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1108
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1075
1109
|
<i class="pi pi-download text-orange-600 text-2xl!"></i>
|
|
1076
1110
|
</span>
|
|
1077
1111
|
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
@@ -1083,7 +1117,7 @@ class AppRightMenu {
|
|
|
1083
1117
|
</div>
|
|
1084
1118
|
<div class="flex gap-6">
|
|
1085
1119
|
<div class="flex flex-col items-center">
|
|
1086
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1120
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1087
1121
|
<i class="pi pi-question-circle text-violet-600 text-2xl!"></i>
|
|
1088
1122
|
</span>
|
|
1089
1123
|
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
@@ -1095,7 +1129,7 @@ class AppRightMenu {
|
|
|
1095
1129
|
</div>
|
|
1096
1130
|
<div class="flex gap-6">
|
|
1097
1131
|
<div class="flex flex-col items-center">
|
|
1098
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1132
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1099
1133
|
<i class="pi pi-comment text-blue-600 text-2xl!"></i>
|
|
1100
1134
|
</span>
|
|
1101
1135
|
</div>
|
|
@@ -1121,7 +1155,7 @@ class AppRightMenu {
|
|
|
1121
1155
|
<p class="body-small mt-1 text-left">Track your ongoing shipments to customers.</p>
|
|
1122
1156
|
<img class="w-full h-full max-h-60 object-cover border border-surface rounded-2xl mt-4" src="layout/images/sidebar-right/staticmap.png" alt="unops-ng_ux" />
|
|
1123
1157
|
</div>
|
|
1124
|
-
</p-drawer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i4.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type:
|
|
1158
|
+
</p-drawer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i4.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$1.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }] });
|
|
1125
1159
|
}
|
|
1126
1160
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppRightMenu, decorators: [{
|
|
1127
1161
|
type: Component,
|
|
@@ -1134,7 +1168,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1134
1168
|
<div class="flex flex-col mt-7">
|
|
1135
1169
|
<div class="flex gap-6">
|
|
1136
1170
|
<div class="flex flex-col items-center">
|
|
1137
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1171
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1138
1172
|
<i class="pi pi-dollar text-blue-600 text-2xl!"></i>
|
|
1139
1173
|
</span>
|
|
1140
1174
|
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
@@ -1146,7 +1180,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1146
1180
|
</div>
|
|
1147
1181
|
<div class="flex gap-6">
|
|
1148
1182
|
<div class="flex flex-col items-center">
|
|
1149
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1183
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1150
1184
|
<i class="pi pi-download text-orange-600 text-2xl!"></i>
|
|
1151
1185
|
</span>
|
|
1152
1186
|
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
@@ -1158,7 +1192,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1158
1192
|
</div>
|
|
1159
1193
|
<div class="flex gap-6">
|
|
1160
1194
|
<div class="flex flex-col items-center">
|
|
1161
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1195
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1162
1196
|
<i class="pi pi-question-circle text-violet-600 text-2xl!"></i>
|
|
1163
1197
|
</span>
|
|
1164
1198
|
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
@@ -1170,7 +1204,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1170
1204
|
</div>
|
|
1171
1205
|
<div class="flex gap-6">
|
|
1172
1206
|
<div class="flex flex-col items-center">
|
|
1173
|
-
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-
|
|
1207
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-subtle">
|
|
1174
1208
|
<i class="pi pi-comment text-blue-600 text-2xl!"></i>
|
|
1175
1209
|
</span>
|
|
1176
1210
|
</div>
|
|
@@ -1212,21 +1246,21 @@ class AppSearch {
|
|
|
1212
1246
|
this.layoutService.layoutState.update((prev) => ({ ...prev, searchBarActive: _val }));
|
|
1213
1247
|
}
|
|
1214
1248
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSearch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1215
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppSearch, isStandalone: true, selector: "[app-search]", ngImport: i0, template: ` <p-dialog [(visible)]="searchBarActive" [breakpoints]="{ '
|
|
1249
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppSearch, isStandalone: true, selector: "[app-search]", ngImport: i0, template: ` <p-dialog [(visible)]="searchBarActive" [breakpoints]="{ '1024px': '75vw', '780px': '90vw' }" modal dismissableMask styleClass="w-1/2 search-container">
|
|
1216
1250
|
<ng-template #headless>
|
|
1217
1251
|
<div class="w-full">
|
|
1218
1252
|
<i class="pi pi-search"></i>
|
|
1219
1253
|
<input pInputText type="text" [pAutoFocus]="true" class="p-inputtext search-input" placeholder="Search" (keydown.enter)="toggleSearchBar()" />
|
|
1220
1254
|
</div>
|
|
1221
1255
|
</ng-template>
|
|
1222
|
-
</p-dialog>`, isInline: true, dependencies: [{ kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$
|
|
1256
|
+
</p-dialog>`, isInline: true, dependencies: [{ kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$3.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: AutoFocusModule }, { kind: "directive", type: i3$2.AutoFocus, selector: "[pAutoFocus]", inputs: ["pAutoFocus"] }] });
|
|
1223
1257
|
}
|
|
1224
1258
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSearch, decorators: [{
|
|
1225
1259
|
type: Component,
|
|
1226
1260
|
args: [{
|
|
1227
1261
|
selector: '[app-search]',
|
|
1228
1262
|
imports: [DialogModule, InputTextModule, AutoFocusModule],
|
|
1229
|
-
template: ` <p-dialog [(visible)]="searchBarActive" [breakpoints]="{ '
|
|
1263
|
+
template: ` <p-dialog [(visible)]="searchBarActive" [breakpoints]="{ '1024px': '75vw', '780px': '90vw' }" modal dismissableMask styleClass="w-1/2 search-container">
|
|
1230
1264
|
<ng-template #headless>
|
|
1231
1265
|
<div class="w-full">
|
|
1232
1266
|
<i class="pi pi-search"></i>
|
|
@@ -1237,6 +1271,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1237
1271
|
}]
|
|
1238
1272
|
}] });
|
|
1239
1273
|
|
|
1274
|
+
class FooterMainComponent {
|
|
1275
|
+
/** When true, always shows the default copyright — ignores FooterService content. */
|
|
1276
|
+
copyrightOnly = input(false, ...(ngDevMode ? [{ debugName: "copyrightOnly" }] : []));
|
|
1277
|
+
footerService = inject(FooterService);
|
|
1278
|
+
copyrightYear = new Date().getFullYear();
|
|
1279
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: FooterMainComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1280
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: FooterMainComponent, isStandalone: true, selector: "ux-footer-main", inputs: { copyrightOnly: { classPropertyName: "copyrightOnly", publicName: "copyrightOnly", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ux-footer-main" }, ngImport: i0, template: `
|
|
1281
|
+
<div class="footer-inner">
|
|
1282
|
+
@if (copyrightOnly()) {
|
|
1283
|
+
<span>© UNOPS {{ copyrightYear }}</span>
|
|
1284
|
+
} @else if (footerService.content(); as tpl) {
|
|
1285
|
+
<ng-container [ngTemplateOutlet]="tpl" />
|
|
1286
|
+
}
|
|
1287
|
+
</div>
|
|
1288
|
+
`, isInline: true, styles: [":host{flex-shrink:0;display:flex;align-items:center;height:3rem;background:var(--p-primary-50);font-size:var(--font-size-xs, .75rem);line-height:1.2;color:var(--p-text-color)}:host-context(:root[class*=\"app-dark\"]){background:var(--p-primary-950);color:var(--p-surface-100)}:host(.footer-sticky){position:sticky;bottom:0;z-index:10}.footer-inner{width:100%;max-width:1540px;margin-inline:auto;padding:1rem}@media screen and (min-width:780px){.footer-inner{padding:1rem 3rem}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1289
|
+
}
|
|
1290
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: FooterMainComponent, decorators: [{
|
|
1291
|
+
type: Component,
|
|
1292
|
+
args: [{ selector: 'ux-footer-main', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet], host: { class: 'ux-footer-main' }, template: `
|
|
1293
|
+
<div class="footer-inner">
|
|
1294
|
+
@if (copyrightOnly()) {
|
|
1295
|
+
<span>© UNOPS {{ copyrightYear }}</span>
|
|
1296
|
+
} @else if (footerService.content(); as tpl) {
|
|
1297
|
+
<ng-container [ngTemplateOutlet]="tpl" />
|
|
1298
|
+
}
|
|
1299
|
+
</div>
|
|
1300
|
+
`, styles: [":host{flex-shrink:0;display:flex;align-items:center;height:3rem;background:var(--p-primary-50);font-size:var(--font-size-xs, .75rem);line-height:1.2;color:var(--p-text-color)}:host-context(:root[class*=\"app-dark\"]){background:var(--p-primary-950);color:var(--p-surface-100)}:host(.footer-sticky){position:sticky;bottom:0;z-index:10}.footer-inner{width:100%;max-width:1540px;margin-inline:auto;padding:1rem}@media screen and (min-width:780px){.footer-inner{padding:1rem 3rem}}\n"] }]
|
|
1301
|
+
}], propDecorators: { copyrightOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyrightOnly", required: false }] }] } });
|
|
1302
|
+
|
|
1240
1303
|
class AppMenuitem {
|
|
1241
1304
|
layoutService = inject(LayoutService);
|
|
1242
1305
|
router = inject(Router);
|
|
@@ -1565,12 +1628,13 @@ class AppTopbar {
|
|
|
1565
1628
|
isDarkTheme = computed(() => this.layoutService.isDarkTheme(), ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
1566
1629
|
isSidebarPinned = computed(() => this.layoutService.isSidebarPinned(), ...(ngDevMode ? [{ debugName: "isSidebarPinned" }] : []));
|
|
1567
1630
|
searchActive = signal(false, ...(ngDevMode ? [{ debugName: "searchActive" }] : []));
|
|
1568
|
-
|
|
1631
|
+
activeDropdown = signal(null, ...(ngDevMode ? [{ debugName: "activeDropdown" }] : []));
|
|
1569
1632
|
shouldFocusSearch = false;
|
|
1570
1633
|
menuButton;
|
|
1571
1634
|
searchInput;
|
|
1635
|
+
notificationsItem;
|
|
1636
|
+
languageItem;
|
|
1572
1637
|
profileItem;
|
|
1573
|
-
profilePanel;
|
|
1574
1638
|
notificationsBars = signal([
|
|
1575
1639
|
{
|
|
1576
1640
|
id: 'inbox',
|
|
@@ -1591,21 +1655,21 @@ class AppTopbar {
|
|
|
1591
1655
|
id: 'inbox',
|
|
1592
1656
|
data: [
|
|
1593
1657
|
{
|
|
1594
|
-
|
|
1658
|
+
initials: 'ML',
|
|
1595
1659
|
name: 'Michael Lee',
|
|
1596
1660
|
description: 'You have a new message from the support team regarding your recent inquiry.',
|
|
1597
1661
|
time: '1 hour ago',
|
|
1598
1662
|
new: true
|
|
1599
1663
|
},
|
|
1600
1664
|
{
|
|
1601
|
-
|
|
1665
|
+
initials: 'AJ',
|
|
1602
1666
|
name: 'Alice Johnson',
|
|
1603
1667
|
description: 'Your report has been successfully submitted and is under review.',
|
|
1604
1668
|
time: '10 minutes ago',
|
|
1605
1669
|
new: true
|
|
1606
1670
|
},
|
|
1607
1671
|
{
|
|
1608
|
-
|
|
1672
|
+
initials: 'ED',
|
|
1609
1673
|
name: 'Emily Davis',
|
|
1610
1674
|
description: 'The project deadline has been updated to September 30th. Please check the details.',
|
|
1611
1675
|
time: 'Yesterday at 4:35 PM',
|
|
@@ -1617,14 +1681,14 @@ class AppTopbar {
|
|
|
1617
1681
|
id: 'general',
|
|
1618
1682
|
data: [
|
|
1619
1683
|
{
|
|
1620
|
-
|
|
1684
|
+
initials: 'AJ',
|
|
1621
1685
|
name: 'Alice Johnson',
|
|
1622
1686
|
description: 'Reminder: Your subscription is about to expire in 3 days. Renew now to avoid interruption.',
|
|
1623
1687
|
time: '30 minutes ago',
|
|
1624
1688
|
new: true
|
|
1625
1689
|
},
|
|
1626
1690
|
{
|
|
1627
|
-
|
|
1691
|
+
initials: 'ML',
|
|
1628
1692
|
name: 'Michael Lee',
|
|
1629
1693
|
description: 'The server maintenance has been completed successfully. No further downtime is expected.',
|
|
1630
1694
|
time: 'Yesterday at 2:15 PM',
|
|
@@ -1636,14 +1700,14 @@ class AppTopbar {
|
|
|
1636
1700
|
id: 'archived',
|
|
1637
1701
|
data: [
|
|
1638
1702
|
{
|
|
1639
|
-
|
|
1703
|
+
initials: 'LB',
|
|
1640
1704
|
name: 'Lucas Brown',
|
|
1641
1705
|
description: 'Your appointment with Dr. Anderson has been confirmed for October 12th at 10:00 AM.',
|
|
1642
1706
|
time: '1 week ago',
|
|
1643
1707
|
new: true
|
|
1644
1708
|
},
|
|
1645
1709
|
{
|
|
1646
|
-
|
|
1710
|
+
initials: 'ED',
|
|
1647
1711
|
name: 'Emily Davis',
|
|
1648
1712
|
description: 'The document you uploaded has been successfully archived for future reference.',
|
|
1649
1713
|
time: '2 weeks ago',
|
|
@@ -1653,9 +1717,9 @@ class AppTopbar {
|
|
|
1653
1717
|
}
|
|
1654
1718
|
], ...(ngDevMode ? [{ debugName: "notifications" }] : []));
|
|
1655
1719
|
languages = signal([
|
|
1656
|
-
{ code: 'en', label: 'English', flag: '
|
|
1657
|
-
{ code: 'fr', label: 'French', flag: '
|
|
1658
|
-
{ code: 'es', label: 'Spanish', flag: '
|
|
1720
|
+
{ code: 'en', label: 'English', flag: '\u{1F1EC}\u{1F1E7}' },
|
|
1721
|
+
{ code: 'fr', label: 'French', flag: '\u{1F1EB}\u{1F1F7}' },
|
|
1722
|
+
{ code: 'es', label: 'Spanish', flag: '\u{1F1EA}\u{1F1F8}' }
|
|
1659
1723
|
], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
1660
1724
|
selectedLanguage = signal('en', ...(ngDevMode ? [{ debugName: "selectedLanguage" }] : []));
|
|
1661
1725
|
selectedNotificationBar = model(this.notificationsBars()[0].id ?? 'inbox', ...(ngDevMode ? [{ debugName: "selectedNotificationBar" }] : []));
|
|
@@ -1680,18 +1744,27 @@ class AppTopbar {
|
|
|
1680
1744
|
}
|
|
1681
1745
|
selectLanguage(code) {
|
|
1682
1746
|
this.selectedLanguage.set(code);
|
|
1747
|
+
this.closeDropdown();
|
|
1683
1748
|
}
|
|
1684
|
-
|
|
1749
|
+
toggleDropdown(id, event) {
|
|
1685
1750
|
event.stopPropagation();
|
|
1686
|
-
this.
|
|
1751
|
+
this.activeDropdown.update((current) => (current === id ? null : id));
|
|
1752
|
+
}
|
|
1753
|
+
closeDropdown() {
|
|
1754
|
+
this.activeDropdown.set(null);
|
|
1687
1755
|
}
|
|
1688
1756
|
onDocumentClick(event) {
|
|
1689
|
-
if (!this.
|
|
1757
|
+
if (!this.activeDropdown())
|
|
1690
1758
|
return;
|
|
1691
1759
|
const target = event.target;
|
|
1692
|
-
const
|
|
1693
|
-
|
|
1694
|
-
this.
|
|
1760
|
+
const containers = [
|
|
1761
|
+
this.notificationsItem?.nativeElement,
|
|
1762
|
+
this.languageItem?.nativeElement,
|
|
1763
|
+
this.profileItem?.nativeElement
|
|
1764
|
+
];
|
|
1765
|
+
const insideAny = containers.some((el) => el?.contains(target));
|
|
1766
|
+
if (!insideAny) {
|
|
1767
|
+
this.closeDropdown();
|
|
1695
1768
|
}
|
|
1696
1769
|
}
|
|
1697
1770
|
openSearch() {
|
|
@@ -1711,24 +1784,29 @@ class AppTopbar {
|
|
|
1711
1784
|
this.layoutService.toggleSearchBar();
|
|
1712
1785
|
}
|
|
1713
1786
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppTopbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1714
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppTopbar, isStandalone: true, selector: "[app-topbar]", inputs: { selectedNotificationBar: { classPropertyName: "selectedNotificationBar", publicName: "selectedNotificationBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedNotificationBar: "selectedNotificationBarChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "menuButton", first: true, predicate: ["menubutton"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "
|
|
1787
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppTopbar, isStandalone: true, selector: "[app-topbar]", inputs: { selectedNotificationBar: { classPropertyName: "selectedNotificationBar", publicName: "selectedNotificationBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedNotificationBar: "selectedNotificationBarChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "menuButton", first: true, predicate: ["menubutton"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "notificationsItem", first: true, predicate: ["notificationsItem"], descendants: true }, { propertyName: "languageItem", first: true, predicate: ["languageItem"], descendants: true }, { propertyName: "profileItem", first: true, predicate: ["profileItem"], descendants: true }], ngImport: i0, template: `<div class="layout-topbar">
|
|
1715
1788
|
<button type="button" class="mobile-menu-button" aria-label="Toggle navigation menu" (click)="onMenuButtonClick()">
|
|
1716
1789
|
<i class="pi pi-bars"></i>
|
|
1717
1790
|
</button>
|
|
1718
1791
|
<div class="topbar-left">
|
|
1719
|
-
<
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
<
|
|
1730
|
-
|
|
1731
|
-
|
|
1792
|
+
<div class="topbar-sidebar-section">
|
|
1793
|
+
<button
|
|
1794
|
+
type="button"
|
|
1795
|
+
class="topbar-menu-toggle"
|
|
1796
|
+
[class.active]="isSidebarPinned()"
|
|
1797
|
+
[attr.aria-label]="isSidebarPinned() ? 'Collapse sidebar' : 'Expand sidebar'"
|
|
1798
|
+
(click)="toggleSidebarPin()"
|
|
1799
|
+
>
|
|
1800
|
+
<i class="pi pi-bars"></i>
|
|
1801
|
+
</button>
|
|
1802
|
+
<a class="topbar-logo" [routerLink]="['/']">
|
|
1803
|
+
<img [src]="desktopLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1804
|
+
</a>
|
|
1805
|
+
<span class="topbar-logo-separator"></span>
|
|
1806
|
+
</div>
|
|
1807
|
+
</div>
|
|
1808
|
+
|
|
1809
|
+
<div class="topbar-main">
|
|
1732
1810
|
<div app-breadcrumb></div>
|
|
1733
1811
|
@if (searchActive()) {
|
|
1734
1812
|
<div class="flex items-center gap-2 ml-auto">
|
|
@@ -1741,14 +1819,8 @@ class AppTopbar {
|
|
|
1741
1819
|
</button>
|
|
1742
1820
|
</div>
|
|
1743
1821
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
<a class="mobile-logo" [routerLink]="['/landing']">
|
|
1747
|
-
<img [src]="mobileLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1748
|
-
</a>
|
|
1749
|
-
|
|
1750
|
-
<div class="topbar-right">
|
|
1751
|
-
<ul class="topbar-menu">
|
|
1822
|
+
<div class="topbar-right">
|
|
1823
|
+
<ul class="topbar-menu">
|
|
1752
1824
|
<li class="right-sidebar-item" [class.hidden]="searchActive()">
|
|
1753
1825
|
<a class="right-sidebar-button" aria-label="Open search" (click)="openSearch()">
|
|
1754
1826
|
<i class="pi pi-search"></i>
|
|
@@ -1763,56 +1835,56 @@ class AppTopbar {
|
|
|
1763
1835
|
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
1764
1836
|
</a>
|
|
1765
1837
|
</li>
|
|
1766
|
-
<li class="right-sidebar-item static sm:relative z-50">
|
|
1767
|
-
<a class="right-sidebar-button" aria-label="Notifications"
|
|
1838
|
+
<li class="right-sidebar-item static sm:relative z-50" #notificationsItem>
|
|
1839
|
+
<a class="right-sidebar-button" aria-label="Notifications" (click)="toggleDropdown('notifications', $event)">
|
|
1768
1840
|
<span class="w-2 h-2 rounded-full bg-red-500 absolute top-2 right-2.5"></span>
|
|
1769
1841
|
<i class="pi pi-bell"></i>
|
|
1770
1842
|
</a>
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
<
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
<
|
|
1794
|
-
<
|
|
1795
|
-
<p-
|
|
1796
|
-
<
|
|
1797
|
-
</p-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1843
|
+
@if (activeDropdown() === 'notifications') {
|
|
1844
|
+
<div
|
|
1845
|
+
class="list-none m-0 rounded-2xl border border-surface fixed sm:absolute bg-surface-0 dark:bg-surface-900 overflow-hidden origin-top w-[calc(100vw-2rem)] sm:w-88 mt-2 z-50 top-auto left-4 sm:left-auto sm:right-0 shadow-flyout animate-scalein"
|
|
1846
|
+
>
|
|
1847
|
+
<div class="p-4 flex items-center justify-between border-b border-surface">
|
|
1848
|
+
<span class="label-small text-surface-950 dark:text-surface-0">Notifications</span>
|
|
1849
|
+
<button pRipple class="py-1 px-2 text-surface-950 dark:text-surface-0 label-x-small hover:bg-emphasis border border-surface rounded-lg shadow-subtle transition-all">Mark all as read</button>
|
|
1850
|
+
</div>
|
|
1851
|
+
<div class="flex items-center border-b border-surface">
|
|
1852
|
+
@for (item of notificationsBars(); track item.id; let i = $index) {
|
|
1853
|
+
<button
|
|
1854
|
+
[ngClass]="{ 'border-surface-950 dark:border-surface-0': selectedNotificationBar() === item.id, 'border-transparent': selectedNotificationBar() !== item.id }"
|
|
1855
|
+
class="px-3.5 py-2 inline-flex items-center border-b gap-2"
|
|
1856
|
+
(click)="selectedNotificationBar.set(item.id)"
|
|
1857
|
+
>
|
|
1858
|
+
<span [ngClass]="{ 'text-surface-950 dark:text-surface-0': selectedNotificationBar() === item.id }" class="label-small">{{ item.label }}</span>
|
|
1859
|
+
<p-badge *ngIf="item?.badge" [value]="item.badge" severity="success" size="small" class="rounded-md!" />
|
|
1860
|
+
</button>
|
|
1861
|
+
}
|
|
1862
|
+
</div>
|
|
1863
|
+
<ul class="flex flex-col divide-y divide-(--surface-border) max-h-80 overflow-auto">
|
|
1864
|
+
@for (item of selectedNotificationsBarData(); track item.name; let i = $index) {
|
|
1865
|
+
<li>
|
|
1866
|
+
<div class="flex items-center gap-3 px-4 sm:px-6 py-3.5 cursor-pointer hover:bg-emphasis transition-all">
|
|
1867
|
+
<p-overlay-badge value="" severity="danger" class="inline-flex">
|
|
1868
|
+
<p-avatar [label]="item.initials" size="large" styleClass="rounded-lg" />
|
|
1869
|
+
</p-overlay-badge>
|
|
1870
|
+
<div class="flex items-center gap-3">
|
|
1871
|
+
<div class="flex flex-col">
|
|
1872
|
+
<span class="label-small text-left text-surface-950 dark:text-surface-0">{{ item.name }}</span>
|
|
1873
|
+
<span class="label-xsmall text-left line-clamp-1">{{ item.description }}</span>
|
|
1874
|
+
<span class="label-xsmall text-left">{{ item.time }}</span>
|
|
1875
|
+
</div>
|
|
1876
|
+
<p-badge *ngIf="item.new" value="" severity="success" />
|
|
1804
1877
|
</div>
|
|
1805
|
-
<p-badge *ngIf="item.new" value="" severity="success" />
|
|
1806
1878
|
</div>
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
</
|
|
1812
|
-
|
|
1879
|
+
<span *ngIf="i !== notifications().length - 1"></span>
|
|
1880
|
+
</li>
|
|
1881
|
+
}
|
|
1882
|
+
</ul>
|
|
1883
|
+
</div>
|
|
1884
|
+
}
|
|
1813
1885
|
</li>
|
|
1814
|
-
<li class="right-sidebar-item static sm:relative">
|
|
1815
|
-
<a class="right-sidebar-button relative z-50" aria-label="Change language"
|
|
1886
|
+
<li class="right-sidebar-item static sm:relative" #languageItem>
|
|
1887
|
+
<a class="right-sidebar-button relative z-50" aria-label="Change language" (click)="toggleDropdown('language', $event)">
|
|
1816
1888
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
1817
1889
|
<path d="m5 8 6 6"/>
|
|
1818
1890
|
<path d="m4 14 6-6 2-3"/>
|
|
@@ -1822,137 +1894,149 @@ class AppTopbar {
|
|
|
1822
1894
|
<path d="M14 18h6"/>
|
|
1823
1895
|
</svg>
|
|
1824
1896
|
</a>
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
<
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1897
|
+
@if (activeDropdown() === 'language') {
|
|
1898
|
+
<div
|
|
1899
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 origin-top w-44 mt-2 right-4 sm:right-0 z-999 top-auto shadow-flyout animate-scalein"
|
|
1900
|
+
>
|
|
1901
|
+
<ul class="flex flex-col gap-1">
|
|
1902
|
+
@for (lang of languages(); track lang.code) {
|
|
1903
|
+
<li>
|
|
1904
|
+
<a
|
|
1905
|
+
class="label-small dark:text-surface-400 flex gap-2.5 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
1906
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
1907
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
1908
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
1909
|
+
(click)="selectLanguage(lang.code)"
|
|
1910
|
+
>
|
|
1911
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
1912
|
+
<span>{{ lang.label }}</span>
|
|
1913
|
+
</a>
|
|
1914
|
+
</li>
|
|
1915
|
+
}
|
|
1916
|
+
</ul>
|
|
1917
|
+
</div>
|
|
1918
|
+
}
|
|
1845
1919
|
</li>
|
|
1846
1920
|
<li class="profile-item static sm:relative" #profileItem>
|
|
1847
|
-
<a class="right-sidebar-button relative z-50" aria-label="User profile menu" (click)="
|
|
1921
|
+
<a class="right-sidebar-button relative z-50" aria-label="User profile menu" (click)="toggleDropdown('profile', $event)">
|
|
1848
1922
|
<p-avatar icon="pi pi-user" styleClass="w-10! h-10!" />
|
|
1849
1923
|
</a>
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1924
|
+
@if (activeDropdown() === 'profile') {
|
|
1925
|
+
<div
|
|
1926
|
+
#profilePanel
|
|
1927
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 origin-top w-52 mt-2 right-4 sm:right-0 z-999 top-auto shadow-flyout animate-scalein"
|
|
1928
|
+
>
|
|
1929
|
+
<ul class="flex flex-col gap-1">
|
|
1930
|
+
<div class="mobile-profile-actions">
|
|
1931
|
+
<li>
|
|
1932
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown(); openSearch()">
|
|
1933
|
+
<i class="pi pi-search"></i>
|
|
1934
|
+
<span>Search</span>
|
|
1935
|
+
</a>
|
|
1936
|
+
</li>
|
|
1937
|
+
<li>
|
|
1938
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown(); toggleDarkMode()">
|
|
1939
|
+
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
1940
|
+
<span>{{ isDarkTheme() ? 'Light Mode' : 'Dark Mode' }}</span>
|
|
1941
|
+
</a>
|
|
1942
|
+
</li>
|
|
1943
|
+
<li>
|
|
1944
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer relative" (click)="closeDropdown()">
|
|
1945
|
+
<i class="pi pi-bell"></i>
|
|
1946
|
+
<span>Notifications</span>
|
|
1947
|
+
<span class="w-2 h-2 rounded-full bg-red-500 ml-auto"></span>
|
|
1948
|
+
</a>
|
|
1949
|
+
</li>
|
|
1950
|
+
<li class="border-b border-surface pb-1 mb-1">
|
|
1951
|
+
<span class="label-xsmall px-2.5 py-1 text-surface-400">Language</span>
|
|
1952
|
+
@for (lang of languages(); track lang.code) {
|
|
1953
|
+
<a
|
|
1954
|
+
class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
1955
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
1956
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
1957
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
1958
|
+
(click)="closeDropdown(); selectLanguage(lang.code)"
|
|
1959
|
+
>
|
|
1960
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
1961
|
+
<span>{{ lang.label }}</span>
|
|
1962
|
+
@if (selectedLanguage() === lang.code) {
|
|
1963
|
+
<i class="pi pi-check ml-auto text-xs"></i>
|
|
1964
|
+
}
|
|
1965
|
+
</a>
|
|
1966
|
+
}
|
|
1967
|
+
</li>
|
|
1968
|
+
</div>
|
|
1858
1969
|
<li>
|
|
1859
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="
|
|
1860
|
-
<i class="pi pi-
|
|
1861
|
-
<span>
|
|
1970
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
1971
|
+
<i class="pi pi-user"></i>
|
|
1972
|
+
<span>Profile</span>
|
|
1862
1973
|
</a>
|
|
1863
1974
|
</li>
|
|
1864
1975
|
<li>
|
|
1865
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="
|
|
1866
|
-
<i
|
|
1867
|
-
<span>
|
|
1976
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown(); onConfigButtonClick()">
|
|
1977
|
+
<i class="pi pi-cog"></i>
|
|
1978
|
+
<span>Settings</span>
|
|
1868
1979
|
</a>
|
|
1869
1980
|
</li>
|
|
1870
1981
|
<li>
|
|
1871
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer
|
|
1872
|
-
<i class="pi pi-
|
|
1873
|
-
<span>
|
|
1874
|
-
<span class="w-2 h-2 rounded-full bg-red-500 ml-auto"></span>
|
|
1982
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
1983
|
+
<i class="pi pi-calendar"></i>
|
|
1984
|
+
<span>Calendar</span>
|
|
1875
1985
|
</a>
|
|
1876
1986
|
</li>
|
|
1877
|
-
<li
|
|
1878
|
-
<
|
|
1879
|
-
|
|
1880
|
-
<
|
|
1881
|
-
|
|
1882
|
-
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
1883
|
-
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
1884
|
-
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
1885
|
-
(click)="profileMenuOpen.set(false); selectLanguage(lang.code)"
|
|
1886
|
-
>
|
|
1887
|
-
<span class="text-lg">{{ lang.flag }}</span>
|
|
1888
|
-
<span>{{ lang.label }}</span>
|
|
1889
|
-
@if (selectedLanguage() === lang.code) {
|
|
1890
|
-
<i class="pi pi-check ml-auto text-xs"></i>
|
|
1891
|
-
}
|
|
1892
|
-
</a>
|
|
1893
|
-
}
|
|
1987
|
+
<li>
|
|
1988
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
1989
|
+
<i class="pi pi-inbox"></i>
|
|
1990
|
+
<span>Inbox</span>
|
|
1991
|
+
</a>
|
|
1894
1992
|
</li>
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
</
|
|
1901
|
-
</
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
<i class="pi pi-cog"></i>
|
|
1905
|
-
<span>Settings</span>
|
|
1906
|
-
</a>
|
|
1907
|
-
</li>
|
|
1908
|
-
<li>
|
|
1909
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1910
|
-
<i class="pi pi-calendar"></i>
|
|
1911
|
-
<span>Calendar</span>
|
|
1912
|
-
</a>
|
|
1913
|
-
</li>
|
|
1914
|
-
<li>
|
|
1915
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1916
|
-
<i class="pi pi-inbox"></i>
|
|
1917
|
-
<span>Inbox</span>
|
|
1918
|
-
</a>
|
|
1919
|
-
</li>
|
|
1920
|
-
<li class="border-t border-surface mt-1 pt-1">
|
|
1921
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1922
|
-
<i class="pi pi-power-off"></i>
|
|
1923
|
-
<span>Log out</span>
|
|
1924
|
-
</a>
|
|
1925
|
-
</li>
|
|
1926
|
-
</ul>
|
|
1927
|
-
</div>
|
|
1993
|
+
<li class="border-t border-surface mt-1 pt-1">
|
|
1994
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
1995
|
+
<i class="pi pi-power-off"></i>
|
|
1996
|
+
<span>Log out</span>
|
|
1997
|
+
</a>
|
|
1998
|
+
</li>
|
|
1999
|
+
</ul>
|
|
2000
|
+
</div>
|
|
2001
|
+
}
|
|
1928
2002
|
</li>
|
|
1929
|
-
|
|
2003
|
+
</ul>
|
|
2004
|
+
</div>
|
|
1930
2005
|
</div>
|
|
1931
|
-
|
|
2006
|
+
|
|
2007
|
+
<a class="mobile-logo" [routerLink]="['/']">
|
|
2008
|
+
<img [src]="mobileLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
2009
|
+
</a>
|
|
2010
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AppBreadcrumb, selector: "[app-breadcrumb]" }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i4$3.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i5$1.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i4$2.Ripple, selector: "[pRipple]" }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i7.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: OverlayBadgeModule }, { kind: "component", type: i8.OverlayBadge, selector: "p-overlayBadge, p-overlay-badge, p-overlaybadge", inputs: ["styleClass", "style", "badgeSize", "severity", "value", "badgeDisabled", "size"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i9.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }] });
|
|
1932
2011
|
}
|
|
1933
2012
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppTopbar, decorators: [{
|
|
1934
2013
|
type: Component,
|
|
1935
2014
|
args: [{
|
|
1936
2015
|
selector: '[app-topbar]',
|
|
1937
|
-
imports: [RouterModule, CommonModule,
|
|
2016
|
+
imports: [RouterModule, CommonModule, AppBreadcrumb, InputTextModule, ButtonModule, IconFieldModule, InputIconModule, RippleModule, BadgeModule, OverlayBadgeModule, AvatarModule],
|
|
1938
2017
|
template: `<div class="layout-topbar">
|
|
1939
2018
|
<button type="button" class="mobile-menu-button" aria-label="Toggle navigation menu" (click)="onMenuButtonClick()">
|
|
1940
2019
|
<i class="pi pi-bars"></i>
|
|
1941
2020
|
</button>
|
|
1942
2021
|
<div class="topbar-left">
|
|
1943
|
-
<
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
<
|
|
1954
|
-
|
|
1955
|
-
|
|
2022
|
+
<div class="topbar-sidebar-section">
|
|
2023
|
+
<button
|
|
2024
|
+
type="button"
|
|
2025
|
+
class="topbar-menu-toggle"
|
|
2026
|
+
[class.active]="isSidebarPinned()"
|
|
2027
|
+
[attr.aria-label]="isSidebarPinned() ? 'Collapse sidebar' : 'Expand sidebar'"
|
|
2028
|
+
(click)="toggleSidebarPin()"
|
|
2029
|
+
>
|
|
2030
|
+
<i class="pi pi-bars"></i>
|
|
2031
|
+
</button>
|
|
2032
|
+
<a class="topbar-logo" [routerLink]="['/']">
|
|
2033
|
+
<img [src]="desktopLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
2034
|
+
</a>
|
|
2035
|
+
<span class="topbar-logo-separator"></span>
|
|
2036
|
+
</div>
|
|
2037
|
+
</div>
|
|
2038
|
+
|
|
2039
|
+
<div class="topbar-main">
|
|
1956
2040
|
<div app-breadcrumb></div>
|
|
1957
2041
|
@if (searchActive()) {
|
|
1958
2042
|
<div class="flex items-center gap-2 ml-auto">
|
|
@@ -1965,14 +2049,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1965
2049
|
</button>
|
|
1966
2050
|
</div>
|
|
1967
2051
|
}
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
<a class="mobile-logo" [routerLink]="['/landing']">
|
|
1971
|
-
<img [src]="mobileLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1972
|
-
</a>
|
|
1973
|
-
|
|
1974
|
-
<div class="topbar-right">
|
|
1975
|
-
<ul class="topbar-menu">
|
|
2052
|
+
<div class="topbar-right">
|
|
2053
|
+
<ul class="topbar-menu">
|
|
1976
2054
|
<li class="right-sidebar-item" [class.hidden]="searchActive()">
|
|
1977
2055
|
<a class="right-sidebar-button" aria-label="Open search" (click)="openSearch()">
|
|
1978
2056
|
<i class="pi pi-search"></i>
|
|
@@ -1987,56 +2065,56 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1987
2065
|
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
1988
2066
|
</a>
|
|
1989
2067
|
</li>
|
|
1990
|
-
<li class="right-sidebar-item static sm:relative z-50">
|
|
1991
|
-
<a class="right-sidebar-button" aria-label="Notifications"
|
|
2068
|
+
<li class="right-sidebar-item static sm:relative z-50" #notificationsItem>
|
|
2069
|
+
<a class="right-sidebar-button" aria-label="Notifications" (click)="toggleDropdown('notifications', $event)">
|
|
1992
2070
|
<span class="w-2 h-2 rounded-full bg-red-500 absolute top-2 right-2.5"></span>
|
|
1993
2071
|
<i class="pi pi-bell"></i>
|
|
1994
2072
|
</a>
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
<
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
<
|
|
2018
|
-
<
|
|
2019
|
-
<p-
|
|
2020
|
-
<
|
|
2021
|
-
</p-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2073
|
+
@if (activeDropdown() === 'notifications') {
|
|
2074
|
+
<div
|
|
2075
|
+
class="list-none m-0 rounded-2xl border border-surface fixed sm:absolute bg-surface-0 dark:bg-surface-900 overflow-hidden origin-top w-[calc(100vw-2rem)] sm:w-88 mt-2 z-50 top-auto left-4 sm:left-auto sm:right-0 shadow-flyout animate-scalein"
|
|
2076
|
+
>
|
|
2077
|
+
<div class="p-4 flex items-center justify-between border-b border-surface">
|
|
2078
|
+
<span class="label-small text-surface-950 dark:text-surface-0">Notifications</span>
|
|
2079
|
+
<button pRipple class="py-1 px-2 text-surface-950 dark:text-surface-0 label-x-small hover:bg-emphasis border border-surface rounded-lg shadow-subtle transition-all">Mark all as read</button>
|
|
2080
|
+
</div>
|
|
2081
|
+
<div class="flex items-center border-b border-surface">
|
|
2082
|
+
@for (item of notificationsBars(); track item.id; let i = $index) {
|
|
2083
|
+
<button
|
|
2084
|
+
[ngClass]="{ 'border-surface-950 dark:border-surface-0': selectedNotificationBar() === item.id, 'border-transparent': selectedNotificationBar() !== item.id }"
|
|
2085
|
+
class="px-3.5 py-2 inline-flex items-center border-b gap-2"
|
|
2086
|
+
(click)="selectedNotificationBar.set(item.id)"
|
|
2087
|
+
>
|
|
2088
|
+
<span [ngClass]="{ 'text-surface-950 dark:text-surface-0': selectedNotificationBar() === item.id }" class="label-small">{{ item.label }}</span>
|
|
2089
|
+
<p-badge *ngIf="item?.badge" [value]="item.badge" severity="success" size="small" class="rounded-md!" />
|
|
2090
|
+
</button>
|
|
2091
|
+
}
|
|
2092
|
+
</div>
|
|
2093
|
+
<ul class="flex flex-col divide-y divide-(--surface-border) max-h-80 overflow-auto">
|
|
2094
|
+
@for (item of selectedNotificationsBarData(); track item.name; let i = $index) {
|
|
2095
|
+
<li>
|
|
2096
|
+
<div class="flex items-center gap-3 px-4 sm:px-6 py-3.5 cursor-pointer hover:bg-emphasis transition-all">
|
|
2097
|
+
<p-overlay-badge value="" severity="danger" class="inline-flex">
|
|
2098
|
+
<p-avatar [label]="item.initials" size="large" styleClass="rounded-lg" />
|
|
2099
|
+
</p-overlay-badge>
|
|
2100
|
+
<div class="flex items-center gap-3">
|
|
2101
|
+
<div class="flex flex-col">
|
|
2102
|
+
<span class="label-small text-left text-surface-950 dark:text-surface-0">{{ item.name }}</span>
|
|
2103
|
+
<span class="label-xsmall text-left line-clamp-1">{{ item.description }}</span>
|
|
2104
|
+
<span class="label-xsmall text-left">{{ item.time }}</span>
|
|
2105
|
+
</div>
|
|
2106
|
+
<p-badge *ngIf="item.new" value="" severity="success" />
|
|
2028
2107
|
</div>
|
|
2029
|
-
<p-badge *ngIf="item.new" value="" severity="success" />
|
|
2030
2108
|
</div>
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
</
|
|
2036
|
-
|
|
2109
|
+
<span *ngIf="i !== notifications().length - 1"></span>
|
|
2110
|
+
</li>
|
|
2111
|
+
}
|
|
2112
|
+
</ul>
|
|
2113
|
+
</div>
|
|
2114
|
+
}
|
|
2037
2115
|
</li>
|
|
2038
|
-
<li class="right-sidebar-item static sm:relative">
|
|
2039
|
-
<a class="right-sidebar-button relative z-50" aria-label="Change language"
|
|
2116
|
+
<li class="right-sidebar-item static sm:relative" #languageItem>
|
|
2117
|
+
<a class="right-sidebar-button relative z-50" aria-label="Change language" (click)="toggleDropdown('language', $event)">
|
|
2040
2118
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
2041
2119
|
<path d="m5 8 6 6"/>
|
|
2042
2120
|
<path d="m4 14 6-6 2-3"/>
|
|
@@ -2046,112 +2124,119 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2046
2124
|
<path d="M14 18h6"/>
|
|
2047
2125
|
</svg>
|
|
2048
2126
|
</a>
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
<
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2127
|
+
@if (activeDropdown() === 'language') {
|
|
2128
|
+
<div
|
|
2129
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 origin-top w-44 mt-2 right-4 sm:right-0 z-999 top-auto shadow-flyout animate-scalein"
|
|
2130
|
+
>
|
|
2131
|
+
<ul class="flex flex-col gap-1">
|
|
2132
|
+
@for (lang of languages(); track lang.code) {
|
|
2133
|
+
<li>
|
|
2134
|
+
<a
|
|
2135
|
+
class="label-small dark:text-surface-400 flex gap-2.5 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
2136
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
2137
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
2138
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
2139
|
+
(click)="selectLanguage(lang.code)"
|
|
2140
|
+
>
|
|
2141
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
2142
|
+
<span>{{ lang.label }}</span>
|
|
2143
|
+
</a>
|
|
2144
|
+
</li>
|
|
2145
|
+
}
|
|
2146
|
+
</ul>
|
|
2147
|
+
</div>
|
|
2148
|
+
}
|
|
2069
2149
|
</li>
|
|
2070
2150
|
<li class="profile-item static sm:relative" #profileItem>
|
|
2071
|
-
<a class="right-sidebar-button relative z-50" aria-label="User profile menu" (click)="
|
|
2151
|
+
<a class="right-sidebar-button relative z-50" aria-label="User profile menu" (click)="toggleDropdown('profile', $event)">
|
|
2072
2152
|
<p-avatar icon="pi pi-user" styleClass="w-10! h-10!" />
|
|
2073
2153
|
</a>
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2154
|
+
@if (activeDropdown() === 'profile') {
|
|
2155
|
+
<div
|
|
2156
|
+
#profilePanel
|
|
2157
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 origin-top w-52 mt-2 right-4 sm:right-0 z-999 top-auto shadow-flyout animate-scalein"
|
|
2158
|
+
>
|
|
2159
|
+
<ul class="flex flex-col gap-1">
|
|
2160
|
+
<div class="mobile-profile-actions">
|
|
2161
|
+
<li>
|
|
2162
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown(); openSearch()">
|
|
2163
|
+
<i class="pi pi-search"></i>
|
|
2164
|
+
<span>Search</span>
|
|
2165
|
+
</a>
|
|
2166
|
+
</li>
|
|
2167
|
+
<li>
|
|
2168
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown(); toggleDarkMode()">
|
|
2169
|
+
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
2170
|
+
<span>{{ isDarkTheme() ? 'Light Mode' : 'Dark Mode' }}</span>
|
|
2171
|
+
</a>
|
|
2172
|
+
</li>
|
|
2173
|
+
<li>
|
|
2174
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer relative" (click)="closeDropdown()">
|
|
2175
|
+
<i class="pi pi-bell"></i>
|
|
2176
|
+
<span>Notifications</span>
|
|
2177
|
+
<span class="w-2 h-2 rounded-full bg-red-500 ml-auto"></span>
|
|
2178
|
+
</a>
|
|
2179
|
+
</li>
|
|
2180
|
+
<li class="border-b border-surface pb-1 mb-1">
|
|
2181
|
+
<span class="label-xsmall px-2.5 py-1 text-surface-400">Language</span>
|
|
2182
|
+
@for (lang of languages(); track lang.code) {
|
|
2183
|
+
<a
|
|
2184
|
+
class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
2185
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
2186
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
2187
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
2188
|
+
(click)="closeDropdown(); selectLanguage(lang.code)"
|
|
2189
|
+
>
|
|
2190
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
2191
|
+
<span>{{ lang.label }}</span>
|
|
2192
|
+
@if (selectedLanguage() === lang.code) {
|
|
2193
|
+
<i class="pi pi-check ml-auto text-xs"></i>
|
|
2194
|
+
}
|
|
2195
|
+
</a>
|
|
2196
|
+
}
|
|
2197
|
+
</li>
|
|
2198
|
+
</div>
|
|
2082
2199
|
<li>
|
|
2083
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="
|
|
2084
|
-
<i class="pi pi-
|
|
2085
|
-
<span>
|
|
2200
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
2201
|
+
<i class="pi pi-user"></i>
|
|
2202
|
+
<span>Profile</span>
|
|
2086
2203
|
</a>
|
|
2087
2204
|
</li>
|
|
2088
2205
|
<li>
|
|
2089
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="
|
|
2090
|
-
<i
|
|
2091
|
-
<span>
|
|
2206
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown(); onConfigButtonClick()">
|
|
2207
|
+
<i class="pi pi-cog"></i>
|
|
2208
|
+
<span>Settings</span>
|
|
2092
2209
|
</a>
|
|
2093
2210
|
</li>
|
|
2094
2211
|
<li>
|
|
2095
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer
|
|
2096
|
-
<i class="pi pi-
|
|
2097
|
-
<span>
|
|
2098
|
-
<span class="w-2 h-2 rounded-full bg-red-500 ml-auto"></span>
|
|
2212
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
2213
|
+
<i class="pi pi-calendar"></i>
|
|
2214
|
+
<span>Calendar</span>
|
|
2099
2215
|
</a>
|
|
2100
2216
|
</li>
|
|
2101
|
-
<li
|
|
2102
|
-
<
|
|
2103
|
-
|
|
2104
|
-
<
|
|
2105
|
-
|
|
2106
|
-
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
2107
|
-
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
2108
|
-
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
2109
|
-
(click)="profileMenuOpen.set(false); selectLanguage(lang.code)"
|
|
2110
|
-
>
|
|
2111
|
-
<span class="text-lg">{{ lang.flag }}</span>
|
|
2112
|
-
<span>{{ lang.label }}</span>
|
|
2113
|
-
@if (selectedLanguage() === lang.code) {
|
|
2114
|
-
<i class="pi pi-check ml-auto text-xs"></i>
|
|
2115
|
-
}
|
|
2116
|
-
</a>
|
|
2117
|
-
}
|
|
2217
|
+
<li>
|
|
2218
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
2219
|
+
<i class="pi pi-inbox"></i>
|
|
2220
|
+
<span>Inbox</span>
|
|
2221
|
+
</a>
|
|
2118
2222
|
</li>
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
</
|
|
2125
|
-
</
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
<i class="pi pi-cog"></i>
|
|
2129
|
-
<span>Settings</span>
|
|
2130
|
-
</a>
|
|
2131
|
-
</li>
|
|
2132
|
-
<li>
|
|
2133
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2134
|
-
<i class="pi pi-calendar"></i>
|
|
2135
|
-
<span>Calendar</span>
|
|
2136
|
-
</a>
|
|
2137
|
-
</li>
|
|
2138
|
-
<li>
|
|
2139
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2140
|
-
<i class="pi pi-inbox"></i>
|
|
2141
|
-
<span>Inbox</span>
|
|
2142
|
-
</a>
|
|
2143
|
-
</li>
|
|
2144
|
-
<li class="border-t border-surface mt-1 pt-1">
|
|
2145
|
-
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2146
|
-
<i class="pi pi-power-off"></i>
|
|
2147
|
-
<span>Log out</span>
|
|
2148
|
-
</a>
|
|
2149
|
-
</li>
|
|
2150
|
-
</ul>
|
|
2151
|
-
</div>
|
|
2223
|
+
<li class="border-t border-surface mt-1 pt-1">
|
|
2224
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="closeDropdown()">
|
|
2225
|
+
<i class="pi pi-power-off"></i>
|
|
2226
|
+
<span>Log out</span>
|
|
2227
|
+
</a>
|
|
2228
|
+
</li>
|
|
2229
|
+
</ul>
|
|
2230
|
+
</div>
|
|
2231
|
+
}
|
|
2152
2232
|
</li>
|
|
2153
|
-
|
|
2233
|
+
</ul>
|
|
2234
|
+
</div>
|
|
2154
2235
|
</div>
|
|
2236
|
+
|
|
2237
|
+
<a class="mobile-logo" [routerLink]="['/']">
|
|
2238
|
+
<img [src]="mobileLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
2239
|
+
</a>
|
|
2155
2240
|
</div>`
|
|
2156
2241
|
}]
|
|
2157
2242
|
}], propDecorators: { menuButton: [{
|
|
@@ -2160,18 +2245,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2160
2245
|
}], searchInput: [{
|
|
2161
2246
|
type: ViewChild,
|
|
2162
2247
|
args: ['searchInput']
|
|
2248
|
+
}], notificationsItem: [{
|
|
2249
|
+
type: ViewChild,
|
|
2250
|
+
args: ['notificationsItem']
|
|
2251
|
+
}], languageItem: [{
|
|
2252
|
+
type: ViewChild,
|
|
2253
|
+
args: ['languageItem']
|
|
2163
2254
|
}], profileItem: [{
|
|
2164
2255
|
type: ViewChild,
|
|
2165
2256
|
args: ['profileItem']
|
|
2166
|
-
}], profilePanel: [{
|
|
2167
|
-
type: ViewChild,
|
|
2168
|
-
args: ['profilePanel']
|
|
2169
2257
|
}], selectedNotificationBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedNotificationBar", required: false }] }, { type: i0.Output, args: ["selectedNotificationBarChange"] }], onDocumentClick: [{
|
|
2170
2258
|
type: HostListener,
|
|
2171
2259
|
args: ['document:click', ['$event']]
|
|
2172
2260
|
}] } });
|
|
2173
2261
|
|
|
2174
|
-
const BREAKPOINT =
|
|
2262
|
+
const BREAKPOINT = 1024;
|
|
2175
2263
|
class AppSidebar {
|
|
2176
2264
|
layoutService = inject(LayoutService);
|
|
2177
2265
|
router = inject(Router);
|
|
@@ -2378,22 +2466,28 @@ class AppSidebar {
|
|
|
2378
2466
|
}
|
|
2379
2467
|
}
|
|
2380
2468
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2381
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2382
|
-
<div #menuContainer class="layout-menu-container" (scroll)="onMenuScroll()">
|
|
2469
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppSidebar, isStandalone: true, selector: "[app-sidebar]", viewQueries: [{ propertyName: "menuContainer", first: true, predicate: ["menuContainer"], descendants: true }, { propertyName: "sidebarRef", first: true, predicate: ["sidebarRef"], descendants: true }], ngImport: i0, template: `<nav class="layout-sidebar" aria-label="Main navigation" (mouseleave)="onMouseLeave()">
|
|
2470
|
+
<div #menuContainer class="layout-menu-container min-h-0 grow" (scroll)="onMenuScroll()">
|
|
2383
2471
|
<div app-menu></div>
|
|
2384
2472
|
</div>
|
|
2473
|
+
@if (!isHorizontal()) {
|
|
2474
|
+
<ux-footer-main [copyrightOnly]="true" role="contentinfo" />
|
|
2475
|
+
}
|
|
2385
2476
|
<div app-topbar *ngIf="isHorizontal()"></div>
|
|
2386
|
-
</nav>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AppMenu, selector: "[app-menu]" }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: AppTopbar, selector: "[app-topbar]", inputs: ["selectedNotificationBar"], outputs: ["selectedNotificationBarChange"] }] });
|
|
2477
|
+
</nav>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AppMenu, selector: "[app-menu]" }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: AppTopbar, selector: "[app-topbar]", inputs: ["selectedNotificationBar"], outputs: ["selectedNotificationBarChange"] }, { kind: "component", type: FooterMainComponent, selector: "ux-footer-main", inputs: ["copyrightOnly"] }] });
|
|
2387
2478
|
}
|
|
2388
2479
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSidebar, decorators: [{
|
|
2389
2480
|
type: Component,
|
|
2390
2481
|
args: [{
|
|
2391
2482
|
selector: '[app-sidebar]',
|
|
2392
|
-
imports: [CommonModule, AppMenu, RouterModule, AppTopbar],
|
|
2483
|
+
imports: [CommonModule, AppMenu, RouterModule, AppTopbar, FooterMainComponent],
|
|
2393
2484
|
template: `<nav class="layout-sidebar" aria-label="Main navigation" (mouseleave)="onMouseLeave()">
|
|
2394
|
-
<div #menuContainer class="layout-menu-container" (scroll)="onMenuScroll()">
|
|
2485
|
+
<div #menuContainer class="layout-menu-container min-h-0 grow" (scroll)="onMenuScroll()">
|
|
2395
2486
|
<div app-menu></div>
|
|
2396
2487
|
</div>
|
|
2488
|
+
@if (!isHorizontal()) {
|
|
2489
|
+
<ux-footer-main [copyrightOnly]="true" role="contentinfo" />
|
|
2490
|
+
}
|
|
2397
2491
|
<div app-topbar *ngIf="isHorizontal()"></div>
|
|
2398
2492
|
</nav>`
|
|
2399
2493
|
}]
|
|
@@ -2407,6 +2501,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2407
2501
|
|
|
2408
2502
|
class AppLayout {
|
|
2409
2503
|
layoutService = inject(LayoutService);
|
|
2504
|
+
elRef = inject(ElementRef);
|
|
2410
2505
|
constructor() {
|
|
2411
2506
|
effect(() => {
|
|
2412
2507
|
const state = this.layoutService.layoutState();
|
|
@@ -2417,6 +2512,11 @@ class AppLayout {
|
|
|
2417
2512
|
document.body.classList.remove('blocked-scroll');
|
|
2418
2513
|
}
|
|
2419
2514
|
});
|
|
2515
|
+
inject(Router).events.pipe(filter((e) => e instanceof NavigationEnd), takeUntilDestroyed()).subscribe(() => {
|
|
2516
|
+
const wrapper = this.elRef.nativeElement.querySelector('.layout-content-wrapper');
|
|
2517
|
+
if (wrapper)
|
|
2518
|
+
wrapper.scrollTop = 0;
|
|
2519
|
+
});
|
|
2420
2520
|
}
|
|
2421
2521
|
containerClass = computed(() => {
|
|
2422
2522
|
const layoutConfig = this.layoutService.layoutConfig();
|
|
@@ -2449,21 +2549,21 @@ class AppLayout {
|
|
|
2449
2549
|
<div app-breadcrumb></div>
|
|
2450
2550
|
<router-outlet></router-outlet>
|
|
2451
2551
|
</main>
|
|
2452
|
-
<div app-footer></div>
|
|
2453
2552
|
</div>
|
|
2553
|
+
<ux-footer-main class="footer-sticky" />
|
|
2454
2554
|
</div>
|
|
2455
2555
|
</div>
|
|
2456
2556
|
<app-configurator />
|
|
2457
2557
|
<div app-search></div>
|
|
2458
2558
|
<div app-rightmenu></div>
|
|
2459
2559
|
<div class="layout-mask"></div>
|
|
2460
|
-
</div> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "[app-topbar]", inputs: ["selectedNotificationBar"], outputs: ["selectedNotificationBarChange"] }, { kind: "component", type: AppSidebar, selector: "[app-sidebar]" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator", inputs: ["simple", "location", "cardStyle"], outputs: ["cardStyleChange"] }, { kind: "component", type: AppBreadcrumb, selector: "[app-breadcrumb]" }, { kind: "component", type:
|
|
2560
|
+
</div> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "[app-topbar]", inputs: ["selectedNotificationBar"], outputs: ["selectedNotificationBarChange"] }, { kind: "component", type: AppSidebar, selector: "[app-sidebar]" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator", inputs: ["simple", "location", "cardStyle"], outputs: ["cardStyleChange"] }, { kind: "component", type: AppBreadcrumb, selector: "[app-breadcrumb]" }, { kind: "component", type: FooterMainComponent, selector: "ux-footer-main", inputs: ["copyrightOnly"] }, { kind: "component", type: AppSearch, selector: "[app-search]" }, { kind: "component", type: AppRightMenu, selector: "[app-rightmenu]" }] });
|
|
2461
2561
|
}
|
|
2462
2562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppLayout, decorators: [{
|
|
2463
2563
|
type: Component,
|
|
2464
2564
|
args: [{
|
|
2465
2565
|
selector: 'app-layout',
|
|
2466
|
-
imports: [CommonModule, AppTopbar, AppSidebar, RouterModule, AppConfigurator, AppBreadcrumb,
|
|
2566
|
+
imports: [CommonModule, AppTopbar, AppSidebar, RouterModule, AppConfigurator, AppBreadcrumb, FooterMainComponent, AppSearch, AppRightMenu],
|
|
2467
2567
|
template: `<div class="layout-wrapper" [ngClass]="containerClass()">
|
|
2468
2568
|
<div app-topbar></div>
|
|
2469
2569
|
<div class="layout-body">
|
|
@@ -2474,8 +2574,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2474
2574
|
<div app-breadcrumb></div>
|
|
2475
2575
|
<router-outlet></router-outlet>
|
|
2476
2576
|
</main>
|
|
2477
|
-
<div app-footer></div>
|
|
2478
2577
|
</div>
|
|
2578
|
+
<ux-footer-main class="footer-sticky" />
|
|
2479
2579
|
</div>
|
|
2480
2580
|
</div>
|
|
2481
2581
|
<app-configurator />
|
|
@@ -2486,6 +2586,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2486
2586
|
}]
|
|
2487
2587
|
}], ctorParameters: () => [] });
|
|
2488
2588
|
|
|
2589
|
+
class AppFooter {
|
|
2590
|
+
layoutService = inject(LayoutService);
|
|
2591
|
+
copyrightYear = new Date().getFullYear();
|
|
2592
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2593
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppFooter, isStandalone: true, selector: "[app-footer]", ngImport: i0, template: `
|
|
2594
|
+
@if (layoutService.isHorizontal()) {
|
|
2595
|
+
<footer class="layout-footer">
|
|
2596
|
+
<span class="footer-copyright">© UNOPS {{ copyrightYear }}</span>
|
|
2597
|
+
</footer>
|
|
2598
|
+
}
|
|
2599
|
+
`, isInline: true });
|
|
2600
|
+
}
|
|
2601
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppFooter, decorators: [{
|
|
2602
|
+
type: Component,
|
|
2603
|
+
args: [{
|
|
2604
|
+
selector: '[app-footer]',
|
|
2605
|
+
template: `
|
|
2606
|
+
@if (layoutService.isHorizontal()) {
|
|
2607
|
+
<footer class="layout-footer">
|
|
2608
|
+
<span class="footer-copyright">© UNOPS {{ copyrightYear }}</span>
|
|
2609
|
+
</footer>
|
|
2610
|
+
}
|
|
2611
|
+
`
|
|
2612
|
+
}]
|
|
2613
|
+
}] });
|
|
2614
|
+
|
|
2489
2615
|
class AuthLayout {
|
|
2490
2616
|
layoutService = inject(LayoutService);
|
|
2491
2617
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AuthLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -2571,7 +2697,7 @@ class AiCardBgComponent {
|
|
|
2571
2697
|
/>
|
|
2572
2698
|
</svg>
|
|
2573
2699
|
<ng-content />
|
|
2574
|
-
`, isInline: true, styles: [":host{--ux-ai-bg-from:
|
|
2700
|
+
`, isInline: true, styles: [":host{--ux-ai-bg-from: var(--color-ai-50);--ux-ai-bg-to: var(--color-cherry-50);--ux-ai-fg-from: var(--color-ai-200);--ux-ai-fg-to: var(--color-cherry-100);position:relative;overflow:hidden;isolation:isolate;contain:paint;animation:ux-ai-bg-move 5s ease-in-out infinite;will-change:background-color}:host-context([class*=\"app-dark\"]){--ux-ai-bg-from: var(--color-ai-950);--ux-ai-bg-to: var(--color-cherry-950);--ux-ai-fg-from: var(--color-ai-900);--ux-ai-fg-to: var(--color-cherry-900)}:host>:not(svg){position:relative;z-index:1}:host svg.ux-ai-card-bg__svg{position:absolute;inset:0;z-index:0;height:100%;width:100%;max-height:100%;overflow:hidden;pointer-events:none}.ux-ai-fg{will-change:fill;animation:ux-ai-fg-move 6s ease-in-out infinite}.ux-ai-fg--1{animation-delay:0s}.ux-ai-fg--2{animation-delay:2s}.ux-ai-fg--3{animation-delay:4s}@keyframes ux-ai-bg-move{0%,to{background-color:var(--ux-ai-bg-from)}50%{background-color:var(--ux-ai-bg-to)}}@keyframes ux-ai-fg-move{0%,to{fill:var(--ux-ai-fg-from)}50%{fill:var(--ux-ai-fg-to)}}@media(prefers-reduced-motion:reduce){:host{animation:none;background-color:var(--ux-ai-bg-from)}.ux-ai-fg{animation:none;fill:var(--ux-ai-fg-from)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2575
2701
|
}
|
|
2576
2702
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AiCardBgComponent, decorators: [{
|
|
2577
2703
|
type: Component,
|
|
@@ -2620,7 +2746,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2620
2746
|
/>
|
|
2621
2747
|
</svg>
|
|
2622
2748
|
<ng-content />
|
|
2623
|
-
`, styles: [":host{--ux-ai-bg-from:
|
|
2749
|
+
`, styles: [":host{--ux-ai-bg-from: var(--color-ai-50);--ux-ai-bg-to: var(--color-cherry-50);--ux-ai-fg-from: var(--color-ai-200);--ux-ai-fg-to: var(--color-cherry-100);position:relative;overflow:hidden;isolation:isolate;contain:paint;animation:ux-ai-bg-move 5s ease-in-out infinite;will-change:background-color}:host-context([class*=\"app-dark\"]){--ux-ai-bg-from: var(--color-ai-950);--ux-ai-bg-to: var(--color-cherry-950);--ux-ai-fg-from: var(--color-ai-900);--ux-ai-fg-to: var(--color-cherry-900)}:host>:not(svg){position:relative;z-index:1}:host svg.ux-ai-card-bg__svg{position:absolute;inset:0;z-index:0;height:100%;width:100%;max-height:100%;overflow:hidden;pointer-events:none}.ux-ai-fg{will-change:fill;animation:ux-ai-fg-move 6s ease-in-out infinite}.ux-ai-fg--1{animation-delay:0s}.ux-ai-fg--2{animation-delay:2s}.ux-ai-fg--3{animation-delay:4s}@keyframes ux-ai-bg-move{0%,to{background-color:var(--ux-ai-bg-from)}50%{background-color:var(--ux-ai-bg-to)}}@keyframes ux-ai-fg-move{0%,to{fill:var(--ux-ai-fg-from)}50%{fill:var(--ux-ai-fg-to)}}@media(prefers-reduced-motion:reduce){:host{animation:none;background-color:var(--ux-ai-bg-from)}.ux-ai-fg{animation:none;fill:var(--ux-ai-fg-from)}}\n"] }]
|
|
2624
2750
|
}] });
|
|
2625
2751
|
|
|
2626
2752
|
class AiInsightsCardComponent {
|
|
@@ -2658,27 +2784,25 @@ class AiInsightsCardComponent {
|
|
|
2658
2784
|
return Math.max(1, Math.floor(available / insightCardHeight));
|
|
2659
2785
|
}
|
|
2660
2786
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AiInsightsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2661
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AiInsightsCardComponent, isStandalone: true, selector: "ux-ai-insights-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, insights: { classPropertyName: "insights", publicName: "insights", isSignal: true, isRequired: true, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, host: { properties: { "class.
|
|
2662
|
-
<ux-ai-card-bg class="flex flex-col flex-1
|
|
2663
|
-
<div class="motion-safe:animate-enter-liquid [animation-delay:80ms] flex flex-col flex-1
|
|
2664
|
-
<div class="flex items-center justify-between cursor-pointer shrink-0" (click)="expanded.set(!expanded())">
|
|
2787
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AiInsightsCardComponent, isStandalone: true, selector: "ux-ai-insights-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, insights: { classPropertyName: "insights", publicName: "insights", isSignal: true, isRequired: true, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, host: { properties: { "class.ux-ai-expanded": "expanded()" }, classAttribute: "ux-ai-insights-card block border border-blue-100 dark:border-midnight-400 rounded-2xl shadow-sm overflow-hidden transition-all duration-300 flex flex-col" }, ngImport: i0, template: `
|
|
2788
|
+
<ux-ai-card-bg class="flex flex-col flex-1 p-4">
|
|
2789
|
+
<div class="motion-safe:animate-enter-liquid [animation-delay:80ms] flex flex-col flex-1">
|
|
2790
|
+
<div class="flex items-center justify-between cursor-pointer shrink-0 pr-2" (click)="expanded.set(!expanded())">
|
|
2665
2791
|
<div class="flex items-center gap-3">
|
|
2666
2792
|
<div class="w-[34px] h-[34px] rounded-[10px] flex items-center justify-center shrink-0">
|
|
2667
|
-
<i class="pi pi-sparkles text-
|
|
2793
|
+
<i class="pi pi-sparkles text-ai-600 dark:text-ai-300"></i>
|
|
2668
2794
|
</div>
|
|
2669
2795
|
<div class="flex flex-col">
|
|
2670
2796
|
<h4 class="title-h4 text-left text-deepsea-500 dark:text-surface-0">{{ title() }}</h4>
|
|
2671
2797
|
<span class="text-midnight-700 dark:text-surface-100 text-sm font-medium leading-tight">{{ insights().length }} insights available for your review</span>
|
|
2672
2798
|
</div>
|
|
2673
2799
|
</div>
|
|
2674
|
-
<
|
|
2675
|
-
<i class="pi text-xs text-darkblue-500 dark:text-surface-0" [ngClass]="expanded() ? 'pi-chevron-up' : 'pi-chevron-down'"></i>
|
|
2676
|
-
</button>
|
|
2800
|
+
<i class="pi text-sm text-darkblue-500 dark:text-surface-0" [ngClass]="expanded() ? 'pi-chevron-up' : 'pi-chevron-down'"></i>
|
|
2677
2801
|
</div>
|
|
2678
2802
|
|
|
2679
2803
|
<div class="expand-body" [class.expand-body--open]="expanded()">
|
|
2680
2804
|
<div class="expand-body__inner">
|
|
2681
|
-
<div class="flex flex-col gap-4 mt-4
|
|
2805
|
+
<div class="flex flex-col gap-4 mt-4">
|
|
2682
2806
|
<div class="bg-white/60 dark:bg-surface-800/60 border border-white dark:border-surface-700 rounded-[14px] shadow-sm flex items-center gap-4 px-4 py-2.5 shrink-0">
|
|
2683
2807
|
<i class="pi pi-search text-surface-500 dark:text-surface-300 text-sm"></i>
|
|
2684
2808
|
<input
|
|
@@ -2690,14 +2814,14 @@ class AiInsightsCardComponent {
|
|
|
2690
2814
|
/>
|
|
2691
2815
|
</div>
|
|
2692
2816
|
|
|
2693
|
-
<div class="flex flex-col gap-3
|
|
2817
|
+
<div class="flex flex-col gap-3">
|
|
2694
2818
|
@for (insight of paginatedInsights(); track insight.id) {
|
|
2695
2819
|
<div class="bg-white/70 dark:bg-surface-800/70 border border-white/50 dark:border-surface-700/50 rounded-[14px] shadow-sm p-4 flex gap-3 items-start shrink-0">
|
|
2696
2820
|
<i class="pi mt-0.5" [ngClass]="[insight.icon, insight.iconColor]"></i>
|
|
2697
2821
|
<div class="flex flex-col gap-2 flex-1 min-w-0">
|
|
2698
2822
|
<div class="flex flex-col gap-1">
|
|
2699
2823
|
<span class="text-midnight-500 dark:text-surface-0 text-sm font-bold leading-[21px]">{{ insight.title }}</span>
|
|
2700
|
-
<p class="text-
|
|
2824
|
+
<p class="text-midnight-400 dark:text-surface-300 text-sm leading-normal">{{ insight.description }}</p>
|
|
2701
2825
|
</div>
|
|
2702
2826
|
<button
|
|
2703
2827
|
class="flex items-center gap-1.5 text-darkblue-500 dark:text-primary-400 text-sm font-semibold cursor-pointer hover:underline bg-transparent border-none p-0 w-fit"
|
|
@@ -2718,8 +2842,8 @@ class AiInsightsCardComponent {
|
|
|
2718
2842
|
[first]="first()"
|
|
2719
2843
|
(onPageChange)="page.set($event.page ?? 0)"
|
|
2720
2844
|
[pageLinkSize]="3"
|
|
2721
|
-
styleClass="w-full
|
|
2722
|
-
[pt]="{ root: { class: '
|
|
2845
|
+
styleClass="w-full"
|
|
2846
|
+
[pt]="{ root: { class: 'justify-center' } }"
|
|
2723
2847
|
/>
|
|
2724
2848
|
</div>
|
|
2725
2849
|
</div>
|
|
@@ -2727,34 +2851,32 @@ class AiInsightsCardComponent {
|
|
|
2727
2851
|
</div>
|
|
2728
2852
|
</div>
|
|
2729
2853
|
</ux-ai-card-bg>
|
|
2730
|
-
`, isInline: true, styles: [":host{display:flex}\n"], dependencies: [{ kind: "component", type: AiCardBgComponent, selector: "ux-ai-card-bg" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type:
|
|
2854
|
+
`, isInline: true, styles: [":host{display:flex}\n"], dependencies: [{ kind: "component", type: AiCardBgComponent, selector: "ux-ai-card-bg" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i2$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2731
2855
|
}
|
|
2732
2856
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AiInsightsCardComponent, decorators: [{
|
|
2733
2857
|
type: Component,
|
|
2734
2858
|
args: [{ selector: 'ux-ai-insights-card', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AiCardBgComponent, FormsModule, NgClass, PaginatorModule], host: {
|
|
2735
|
-
class: 'ux-ai-insights-card block border border-
|
|
2736
|
-
'[class.
|
|
2859
|
+
class: 'ux-ai-insights-card block border border-blue-100 dark:border-midnight-400 rounded-2xl shadow-sm overflow-hidden transition-all duration-300 flex flex-col',
|
|
2860
|
+
'[class.ux-ai-expanded]': 'expanded()'
|
|
2737
2861
|
}, template: `
|
|
2738
|
-
<ux-ai-card-bg class="flex flex-col flex-1
|
|
2739
|
-
<div class="motion-safe:animate-enter-liquid [animation-delay:80ms] flex flex-col flex-1
|
|
2740
|
-
<div class="flex items-center justify-between cursor-pointer shrink-0" (click)="expanded.set(!expanded())">
|
|
2862
|
+
<ux-ai-card-bg class="flex flex-col flex-1 p-4">
|
|
2863
|
+
<div class="motion-safe:animate-enter-liquid [animation-delay:80ms] flex flex-col flex-1">
|
|
2864
|
+
<div class="flex items-center justify-between cursor-pointer shrink-0 pr-2" (click)="expanded.set(!expanded())">
|
|
2741
2865
|
<div class="flex items-center gap-3">
|
|
2742
2866
|
<div class="w-[34px] h-[34px] rounded-[10px] flex items-center justify-center shrink-0">
|
|
2743
|
-
<i class="pi pi-sparkles text-
|
|
2867
|
+
<i class="pi pi-sparkles text-ai-600 dark:text-ai-300"></i>
|
|
2744
2868
|
</div>
|
|
2745
2869
|
<div class="flex flex-col">
|
|
2746
2870
|
<h4 class="title-h4 text-left text-deepsea-500 dark:text-surface-0">{{ title() }}</h4>
|
|
2747
2871
|
<span class="text-midnight-700 dark:text-surface-100 text-sm font-medium leading-tight">{{ insights().length }} insights available for your review</span>
|
|
2748
2872
|
</div>
|
|
2749
2873
|
</div>
|
|
2750
|
-
<
|
|
2751
|
-
<i class="pi text-xs text-darkblue-500 dark:text-surface-0" [ngClass]="expanded() ? 'pi-chevron-up' : 'pi-chevron-down'"></i>
|
|
2752
|
-
</button>
|
|
2874
|
+
<i class="pi text-sm text-darkblue-500 dark:text-surface-0" [ngClass]="expanded() ? 'pi-chevron-up' : 'pi-chevron-down'"></i>
|
|
2753
2875
|
</div>
|
|
2754
2876
|
|
|
2755
2877
|
<div class="expand-body" [class.expand-body--open]="expanded()">
|
|
2756
2878
|
<div class="expand-body__inner">
|
|
2757
|
-
<div class="flex flex-col gap-4 mt-4
|
|
2879
|
+
<div class="flex flex-col gap-4 mt-4">
|
|
2758
2880
|
<div class="bg-white/60 dark:bg-surface-800/60 border border-white dark:border-surface-700 rounded-[14px] shadow-sm flex items-center gap-4 px-4 py-2.5 shrink-0">
|
|
2759
2881
|
<i class="pi pi-search text-surface-500 dark:text-surface-300 text-sm"></i>
|
|
2760
2882
|
<input
|
|
@@ -2766,14 +2888,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2766
2888
|
/>
|
|
2767
2889
|
</div>
|
|
2768
2890
|
|
|
2769
|
-
<div class="flex flex-col gap-3
|
|
2891
|
+
<div class="flex flex-col gap-3">
|
|
2770
2892
|
@for (insight of paginatedInsights(); track insight.id) {
|
|
2771
2893
|
<div class="bg-white/70 dark:bg-surface-800/70 border border-white/50 dark:border-surface-700/50 rounded-[14px] shadow-sm p-4 flex gap-3 items-start shrink-0">
|
|
2772
2894
|
<i class="pi mt-0.5" [ngClass]="[insight.icon, insight.iconColor]"></i>
|
|
2773
2895
|
<div class="flex flex-col gap-2 flex-1 min-w-0">
|
|
2774
2896
|
<div class="flex flex-col gap-1">
|
|
2775
2897
|
<span class="text-midnight-500 dark:text-surface-0 text-sm font-bold leading-[21px]">{{ insight.title }}</span>
|
|
2776
|
-
<p class="text-
|
|
2898
|
+
<p class="text-midnight-400 dark:text-surface-300 text-sm leading-normal">{{ insight.description }}</p>
|
|
2777
2899
|
</div>
|
|
2778
2900
|
<button
|
|
2779
2901
|
class="flex items-center gap-1.5 text-darkblue-500 dark:text-primary-400 text-sm font-semibold cursor-pointer hover:underline bg-transparent border-none p-0 w-fit"
|
|
@@ -2794,8 +2916,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2794
2916
|
[first]="first()"
|
|
2795
2917
|
(onPageChange)="page.set($event.page ?? 0)"
|
|
2796
2918
|
[pageLinkSize]="3"
|
|
2797
|
-
styleClass="w-full
|
|
2798
|
-
[pt]="{ root: { class: '
|
|
2919
|
+
styleClass="w-full"
|
|
2920
|
+
[pt]="{ root: { class: 'justify-center' } }"
|
|
2799
2921
|
/>
|
|
2800
2922
|
</div>
|
|
2801
2923
|
</div>
|
|
@@ -2806,6 +2928,153 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2806
2928
|
`, styles: [":host{display:flex}\n"] }]
|
|
2807
2929
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], insights: [{ type: i0.Input, args: [{ isSignal: true, alias: "insights", required: true }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
2808
2930
|
|
|
2931
|
+
class CompletionStepsComponent {
|
|
2932
|
+
title = input('Completion Steps', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
2933
|
+
steps = input([], ...(ngDevMode ? [{ debugName: "steps" }] : []));
|
|
2934
|
+
mandatory = input({ filled: 0, total: 0 }, ...(ngDevMode ? [{ debugName: "mandatory" }] : []));
|
|
2935
|
+
optional = input({ filled: 0, total: 0 }, ...(ngDevMode ? [{ debugName: "optional" }] : []));
|
|
2936
|
+
totalRecords = input(0, ...(ngDevMode ? [{ debugName: "totalRecords" }] : []));
|
|
2937
|
+
interactive = input(false, ...(ngDevMode ? [{ debugName: "interactive" }] : []));
|
|
2938
|
+
emptyTitle = input('No progress tracked yet', ...(ngDevMode ? [{ debugName: "emptyTitle" }] : []));
|
|
2939
|
+
emptyDescription = input('Progress is calculated automatically as you fill in the opportunity sections. Each dot represents a required or optional field — mandatory fields (bordered red) must be completed before submission.', ...(ngDevMode ? [{ debugName: "emptyDescription" }] : []));
|
|
2940
|
+
stepClick = output();
|
|
2941
|
+
dotStyles = {
|
|
2942
|
+
mandatoryFilled: { bg: 'bg-green-200 dark:bg-green-700', text: 'text-green-800 dark:text-green-50', icon: 'pi', iconClass: 'pi-check' },
|
|
2943
|
+
optionalFilled: { bg: 'bg-blue-200 dark:bg-blue-700', text: 'text-blue-800 dark:text-blue-50', icon: 'material', iconClass: 'info_i' },
|
|
2944
|
+
mandatoryMissing: { bg: 'bg-transparent border-2 border-red-400 dark:border-red-500', text: 'text-red-500 dark:text-red-400', icon: 'pi', iconClass: 'pi-plus' },
|
|
2945
|
+
optionalMissing: { bg: 'bg-transparent border-2 border-surface-300 dark:border-surface-600', text: 'text-surface-500 dark:text-surface-400', icon: 'material', iconClass: 'info_i' }
|
|
2946
|
+
};
|
|
2947
|
+
filledTotal = computed(() => this.mandatory().filled + this.optional().filled, ...(ngDevMode ? [{ debugName: "filledTotal" }] : []));
|
|
2948
|
+
empty = computed(() => this.filledTotal() === 0, ...(ngDevMode ? [{ debugName: "empty" }] : []));
|
|
2949
|
+
legendMandatoryBg = computed(() => this.mandatory().filled > 0 ? this.dotStyles.mandatoryFilled.bg : this.dotStyles.mandatoryMissing.bg, ...(ngDevMode ? [{ debugName: "legendMandatoryBg" }] : []));
|
|
2950
|
+
legendOptionalBg = computed(() => this.optional().filled > 0 ? this.dotStyles.optionalFilled.bg : this.dotStyles.optionalMissing.bg, ...(ngDevMode ? [{ debugName: "legendOptionalBg" }] : []));
|
|
2951
|
+
getDotStyle(step) {
|
|
2952
|
+
if (step.filled)
|
|
2953
|
+
return step.type === 'mandatory' ? this.dotStyles.mandatoryFilled : this.dotStyles.optionalFilled;
|
|
2954
|
+
return step.type === 'mandatory' ? this.dotStyles.mandatoryMissing : this.dotStyles.optionalMissing;
|
|
2955
|
+
}
|
|
2956
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: CompletionStepsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2957
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: CompletionStepsComponent, isStandalone: true, selector: "ux-completion-steps", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, mandatory: { classPropertyName: "mandatory", publicName: "mandatory", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, totalRecords: { classPropertyName: "totalRecords", publicName: "totalRecords", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, emptyTitle: { classPropertyName: "emptyTitle", publicName: "emptyTitle", isSignal: true, isRequired: false, transformFunction: null }, emptyDescription: { classPropertyName: "emptyDescription", publicName: "emptyDescription", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stepClick: "stepClick" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
2958
|
+
<div class="card flex flex-col gap-4">
|
|
2959
|
+
<div class="flex items-center justify-between">
|
|
2960
|
+
<div class="flex items-center gap-3">
|
|
2961
|
+
<div class="flex flex-col">
|
|
2962
|
+
<span class="text-xs font-semibold text-surface-600 dark:text-surface-300 uppercase tracking-wide">{{ title() }}</span>
|
|
2963
|
+
</div>
|
|
2964
|
+
</div>
|
|
2965
|
+
<span class="text-2xl font-bold" [class]="filledTotal() > 0 ? 'text-surface-900 dark:text-surface-0' : 'text-surface-500 dark:text-surface-400'">{{ filledTotal() }}/{{ totalRecords() }}</span>
|
|
2966
|
+
</div>
|
|
2967
|
+
|
|
2968
|
+
<div class="flex items-center gap-1 flex-wrap">
|
|
2969
|
+
@for (step of steps(); track $index) {
|
|
2970
|
+
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full"
|
|
2971
|
+
[class.cursor-pointer]="interactive()"
|
|
2972
|
+
[class]="getDotStyle(step).bg"
|
|
2973
|
+
[pTooltip]="step.name + (step.filled ? '' : ' (missing)')" tooltipPosition="top"
|
|
2974
|
+
(click)="interactive() && stepClick.emit($index)">
|
|
2975
|
+
@if (getDotStyle(step).icon === 'pi') {
|
|
2976
|
+
<i class="pi text-[3px]" [class]="getDotStyle(step).iconClass + ' ' + getDotStyle(step).text"></i>
|
|
2977
|
+
} @else if (getDotStyle(step).icon === 'material') {
|
|
2978
|
+
<span class="material-symbols-outlined leading-none" style="font-size:20px;transform:scale(0.9)" [class]="getDotStyle(step).text">{{ getDotStyle(step).iconClass }}</span>
|
|
2979
|
+
} @else {
|
|
2980
|
+
<span class="text-sm font-black leading-none" [class]="getDotStyle(step).text">!</span>
|
|
2981
|
+
}
|
|
2982
|
+
</span>
|
|
2983
|
+
}
|
|
2984
|
+
</div>
|
|
2985
|
+
|
|
2986
|
+
<div class="flex flex-wrap items-center gap-x-6 gap-y-2 mt-1">
|
|
2987
|
+
<div class="flex items-center gap-2">
|
|
2988
|
+
<span class="inline-block w-4 h-4 rounded-full shrink-0" [class]="legendMandatoryBg()"></span>
|
|
2989
|
+
<span class="text-sm text-surface-600 dark:text-surface-300">Mandatory:</span>
|
|
2990
|
+
<span class="text-sm font-semibold text-surface-900 dark:text-surface-0">{{ mandatory().filled }}/{{ mandatory().total }}</span>
|
|
2991
|
+
</div>
|
|
2992
|
+
<div class="flex items-center gap-2">
|
|
2993
|
+
<span class="inline-block w-4 h-4 rounded-full shrink-0" [class]="legendOptionalBg()"></span>
|
|
2994
|
+
<span class="text-sm text-surface-600 dark:text-surface-300">Optional:</span>
|
|
2995
|
+
<span class="text-sm font-semibold text-surface-900 dark:text-surface-0">{{ optional().filled }}/{{ optional().total }}</span>
|
|
2996
|
+
</div>
|
|
2997
|
+
<div class="flex items-center gap-2">
|
|
2998
|
+
<span class="text-sm text-surface-600 dark:text-surface-300">Total:</span>
|
|
2999
|
+
<span class="text-sm font-semibold text-surface-900 dark:text-surface-0">{{ totalRecords() }}</span>
|
|
3000
|
+
</div>
|
|
3001
|
+
</div>
|
|
3002
|
+
|
|
3003
|
+
@if (empty()) {
|
|
3004
|
+
<div class="empty-state">
|
|
3005
|
+
<i class="pi pi-chart-bar text-3xl text-surface-500 dark:text-surface-400"></i>
|
|
3006
|
+
<span class="empty-state-title">{{ emptyTitle() }}</span>
|
|
3007
|
+
<span class="empty-state-desc">{{ emptyDescription() }}</span>
|
|
3008
|
+
</div>
|
|
3009
|
+
}
|
|
3010
|
+
</div>
|
|
3011
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3012
|
+
}
|
|
3013
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: CompletionStepsComponent, decorators: [{
|
|
3014
|
+
type: Component,
|
|
3015
|
+
args: [{
|
|
3016
|
+
selector: 'ux-completion-steps',
|
|
3017
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3018
|
+
imports: [TooltipModule],
|
|
3019
|
+
host: { class: 'block' },
|
|
3020
|
+
template: `
|
|
3021
|
+
<div class="card flex flex-col gap-4">
|
|
3022
|
+
<div class="flex items-center justify-between">
|
|
3023
|
+
<div class="flex items-center gap-3">
|
|
3024
|
+
<div class="flex flex-col">
|
|
3025
|
+
<span class="text-xs font-semibold text-surface-600 dark:text-surface-300 uppercase tracking-wide">{{ title() }}</span>
|
|
3026
|
+
</div>
|
|
3027
|
+
</div>
|
|
3028
|
+
<span class="text-2xl font-bold" [class]="filledTotal() > 0 ? 'text-surface-900 dark:text-surface-0' : 'text-surface-500 dark:text-surface-400'">{{ filledTotal() }}/{{ totalRecords() }}</span>
|
|
3029
|
+
</div>
|
|
3030
|
+
|
|
3031
|
+
<div class="flex items-center gap-1 flex-wrap">
|
|
3032
|
+
@for (step of steps(); track $index) {
|
|
3033
|
+
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full"
|
|
3034
|
+
[class.cursor-pointer]="interactive()"
|
|
3035
|
+
[class]="getDotStyle(step).bg"
|
|
3036
|
+
[pTooltip]="step.name + (step.filled ? '' : ' (missing)')" tooltipPosition="top"
|
|
3037
|
+
(click)="interactive() && stepClick.emit($index)">
|
|
3038
|
+
@if (getDotStyle(step).icon === 'pi') {
|
|
3039
|
+
<i class="pi text-[3px]" [class]="getDotStyle(step).iconClass + ' ' + getDotStyle(step).text"></i>
|
|
3040
|
+
} @else if (getDotStyle(step).icon === 'material') {
|
|
3041
|
+
<span class="material-symbols-outlined leading-none" style="font-size:20px;transform:scale(0.9)" [class]="getDotStyle(step).text">{{ getDotStyle(step).iconClass }}</span>
|
|
3042
|
+
} @else {
|
|
3043
|
+
<span class="text-sm font-black leading-none" [class]="getDotStyle(step).text">!</span>
|
|
3044
|
+
}
|
|
3045
|
+
</span>
|
|
3046
|
+
}
|
|
3047
|
+
</div>
|
|
3048
|
+
|
|
3049
|
+
<div class="flex flex-wrap items-center gap-x-6 gap-y-2 mt-1">
|
|
3050
|
+
<div class="flex items-center gap-2">
|
|
3051
|
+
<span class="inline-block w-4 h-4 rounded-full shrink-0" [class]="legendMandatoryBg()"></span>
|
|
3052
|
+
<span class="text-sm text-surface-600 dark:text-surface-300">Mandatory:</span>
|
|
3053
|
+
<span class="text-sm font-semibold text-surface-900 dark:text-surface-0">{{ mandatory().filled }}/{{ mandatory().total }}</span>
|
|
3054
|
+
</div>
|
|
3055
|
+
<div class="flex items-center gap-2">
|
|
3056
|
+
<span class="inline-block w-4 h-4 rounded-full shrink-0" [class]="legendOptionalBg()"></span>
|
|
3057
|
+
<span class="text-sm text-surface-600 dark:text-surface-300">Optional:</span>
|
|
3058
|
+
<span class="text-sm font-semibold text-surface-900 dark:text-surface-0">{{ optional().filled }}/{{ optional().total }}</span>
|
|
3059
|
+
</div>
|
|
3060
|
+
<div class="flex items-center gap-2">
|
|
3061
|
+
<span class="text-sm text-surface-600 dark:text-surface-300">Total:</span>
|
|
3062
|
+
<span class="text-sm font-semibold text-surface-900 dark:text-surface-0">{{ totalRecords() }}</span>
|
|
3063
|
+
</div>
|
|
3064
|
+
</div>
|
|
3065
|
+
|
|
3066
|
+
@if (empty()) {
|
|
3067
|
+
<div class="empty-state">
|
|
3068
|
+
<i class="pi pi-chart-bar text-3xl text-surface-500 dark:text-surface-400"></i>
|
|
3069
|
+
<span class="empty-state-title">{{ emptyTitle() }}</span>
|
|
3070
|
+
<span class="empty-state-desc">{{ emptyDescription() }}</span>
|
|
3071
|
+
</div>
|
|
3072
|
+
}
|
|
3073
|
+
</div>
|
|
3074
|
+
`
|
|
3075
|
+
}]
|
|
3076
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: false }] }], mandatory: [{ type: i0.Input, args: [{ isSignal: true, alias: "mandatory", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], emptyTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTitle", required: false }] }], emptyDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyDescription", required: false }] }], stepClick: [{ type: i0.Output, args: ["stepClick"] }] } });
|
|
3077
|
+
|
|
2809
3078
|
/**
|
|
2810
3079
|
* Structural directive that marks a template as content for a specific tab
|
|
2811
3080
|
* inside `<ux-detail-layout>`.
|
|
@@ -2843,12 +3112,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2843
3112
|
* <ng-template uxDetailTab="scope">...tab 2...</ng-template>
|
|
2844
3113
|
*
|
|
2845
3114
|
* <ng-container ux-detail-sidebar>
|
|
3115
|
+
* <!-- Use ng-container so children become direct children of the
|
|
3116
|
+
* library's flex container and inherit the gap spacing. -->
|
|
2846
3117
|
* ...right sidebar (AI card, documents, etc.)...
|
|
2847
3118
|
* </ng-container>
|
|
2848
3119
|
*
|
|
2849
|
-
* <ng-container ux-detail-footer>
|
|
2850
|
-
* ...audit metadata row...
|
|
2851
|
-
* </ng-container>
|
|
2852
3120
|
* </ux-detail-layout>
|
|
2853
3121
|
* ```
|
|
2854
3122
|
*/
|
|
@@ -2857,8 +3125,23 @@ class DetailLayoutComponent {
|
|
|
2857
3125
|
tabs = input.required(...(ngDevMode ? [{ debugName: "tabs" }] : []));
|
|
2858
3126
|
/** Currently active tab value (two-way bindable). */
|
|
2859
3127
|
activeTab = model('', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
3128
|
+
/** Options for the mobile tab dropdown. */
|
|
3129
|
+
tabOptions = computed(() => this.tabs().map(t => ({ label: t.label, value: t.value })), ...(ngDevMode ? [{ debugName: "tabOptions" }] : []));
|
|
3130
|
+
/** True when there is only a single tab, making the tab bar redundant. */
|
|
3131
|
+
singleTab = computed(() => this.tabs().length <= 1, ...(ngDevMode ? [{ debugName: "singleTab" }] : []));
|
|
3132
|
+
/** True when viewport is below the lg breakpoint (1024px). */
|
|
3133
|
+
isMobile = signal(false, ...(ngDevMode ? [{ debugName: "isMobile" }] : []));
|
|
2860
3134
|
/** True once the scrollable body has been scrolled past the threshold. */
|
|
2861
3135
|
scrolled = signal(false, ...(ngDevMode ? [{ debugName: "scrolled" }] : []));
|
|
3136
|
+
constructor() {
|
|
3137
|
+
if (isPlatformBrowser(inject(PLATFORM_ID))) {
|
|
3138
|
+
const mql = window.matchMedia('(max-width: 1023px)');
|
|
3139
|
+
this.isMobile.set(mql.matches);
|
|
3140
|
+
const handler = (e) => this.isMobile.set(e.matches);
|
|
3141
|
+
mql.addEventListener('change', handler);
|
|
3142
|
+
inject(DestroyRef).onDestroy(() => mql.removeEventListener('change', handler));
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
2862
3145
|
/** Tab content templates provided by the consumer. */
|
|
2863
3146
|
tabTemplates;
|
|
2864
3147
|
getTabTemplate(value) {
|
|
@@ -2870,8 +3153,8 @@ class DetailLayoutComponent {
|
|
|
2870
3153
|
this.scrolled.set(el.scrollTop > 10);
|
|
2871
3154
|
}
|
|
2872
3155
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: DetailLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2873
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: DetailLayoutComponent, isStandalone: true, selector: "ux-detail-layout", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: true, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeTab: "activeTabChange" }, host: { classAttribute: "ux-detail-layout
|
|
2874
|
-
<div class="flex flex-col
|
|
3156
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: DetailLayoutComponent, isStandalone: true, selector: "ux-detail-layout", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: true, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeTab: "activeTabChange" }, host: { classAttribute: "ux-detail-layout" }, queries: [{ propertyName: "tabTemplates", predicate: DetailTabDirective }], ngImport: i0, template: `
|
|
3157
|
+
<div class="flex flex-col flex-1 min-h-0">
|
|
2875
3158
|
|
|
2876
3159
|
<!-- Sticky header (projected) -->
|
|
2877
3160
|
<div class="ux-dl__header flex-shrink-0 z-10">
|
|
@@ -2883,13 +3166,30 @@ class DetailLayoutComponent {
|
|
|
2883
3166
|
</div>
|
|
2884
3167
|
</div>
|
|
2885
3168
|
|
|
2886
|
-
<!--
|
|
2887
|
-
<
|
|
2888
|
-
(scroll)="onScroll($event)">
|
|
3169
|
+
<!-- p-tabs wraps tablist + scrollable panels for state binding -->
|
|
3170
|
+
<p-tabs class="flex flex-col flex-1 min-h-0" [value]="activeTab()" (valueChange)="activeTab.set($event + '')">
|
|
2889
3171
|
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
3172
|
+
@if (!singleTab()) {
|
|
3173
|
+
<!-- Mobile: dropdown selector -->
|
|
3174
|
+
@if (isMobile()) {
|
|
3175
|
+
<div class="ux-dl__mobile-tabs">
|
|
3176
|
+
<p-select
|
|
3177
|
+
[options]="tabOptions()"
|
|
3178
|
+
[ngModel]="activeTab()"
|
|
3179
|
+
(ngModelChange)="activeTab.set($event)"
|
|
3180
|
+
optionLabel="label"
|
|
3181
|
+
optionValue="value"
|
|
3182
|
+
styleClass="w-full ux-dl__mobile-select"
|
|
3183
|
+
/>
|
|
3184
|
+
</div>
|
|
3185
|
+
}
|
|
3186
|
+
|
|
3187
|
+
<!-- Desktop: horizontal tab bar (outside scroll → stays fixed below header) -->
|
|
3188
|
+
<p-tablist
|
|
3189
|
+
class="flex-shrink-0 ux-dl__tablist"
|
|
3190
|
+
[style.display]="isMobile() ? 'none' : null"
|
|
3191
|
+
[pt]="{ tabList: { class: 'p-0' } }"
|
|
3192
|
+
>
|
|
2893
3193
|
@for (tab of tabs(); track tab.value) {
|
|
2894
3194
|
<p-tab [value]="tab.value">
|
|
2895
3195
|
@if (tab.icon) {
|
|
@@ -2899,12 +3199,17 @@ class DetailLayoutComponent {
|
|
|
2899
3199
|
</p-tab>
|
|
2900
3200
|
}
|
|
2901
3201
|
</p-tablist>
|
|
3202
|
+
}
|
|
2902
3203
|
|
|
2903
|
-
|
|
2904
|
-
|
|
3204
|
+
<!-- Scrollable body (only content scrolls, tabs stay above) -->
|
|
3205
|
+
<div class="flex flex-col flex-1 min-h-0 overflow-y-auto overflow-x-hidden ux-dl__scroll"
|
|
3206
|
+
(scroll)="onScroll($event)">
|
|
3207
|
+
|
|
3208
|
+
<!-- Content + Sidebar row -->
|
|
3209
|
+
<div class="flex flex-col lg:flex-row items-start gap-6 w-full py-4 lg:py-6">
|
|
2905
3210
|
|
|
2906
3211
|
<!-- Main column: tab panels -->
|
|
2907
|
-
<div class="flex-1 min-w-0 flex flex-col gap-6">
|
|
3212
|
+
<div class="w-full flex-1 min-w-0 flex flex-col gap-6">
|
|
2908
3213
|
<p-tabpanels>
|
|
2909
3214
|
@for (tab of tabs(); track tab.value) {
|
|
2910
3215
|
<p-tabpanel [value]="tab.value">
|
|
@@ -2916,27 +3221,27 @@ class DetailLayoutComponent {
|
|
|
2916
3221
|
</p-tabpanel>
|
|
2917
3222
|
}
|
|
2918
3223
|
</p-tabpanels>
|
|
2919
|
-
|
|
2920
|
-
<!-- Footer below tab content -->
|
|
2921
|
-
<ng-content select="[ux-detail-footer]" />
|
|
2922
3224
|
</div>
|
|
2923
3225
|
|
|
2924
3226
|
<!-- Sidebar -->
|
|
2925
|
-
<aside class="w-full lg:w-[380px] shrink-0 flex flex-col lg:sticky lg:top-4 lg:self-start pb-8">
|
|
3227
|
+
<aside class="w-full lg:w-[380px] shrink-0 flex flex-col lg:sticky lg:top-4 lg:self-start lg:pb-8">
|
|
2926
3228
|
<div class="ux-dl__sidebar-inner w-full">
|
|
2927
3229
|
<ng-content select="[ux-detail-sidebar]" />
|
|
2928
3230
|
</div>
|
|
2929
3231
|
</aside>
|
|
2930
3232
|
</div>
|
|
2931
|
-
|
|
2932
|
-
|
|
3233
|
+
|
|
3234
|
+
</div>
|
|
3235
|
+
|
|
3236
|
+
</p-tabs>
|
|
3237
|
+
|
|
2933
3238
|
</div>
|
|
2934
|
-
`, isInline: true, styles: [":host{display:
|
|
3239
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0;font-family:var(--p-font-family, \"Noto Sans\", sans-serif);background:transparent;color:var(--p-text-color)}.ux-dl__header{background:transparent}.ux-dl__scroll{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--p-primary-color) 25%,transparent) color-mix(in srgb,var(--p-surface-500) 8%,transparent)}.ux-dl__scroll::-webkit-scrollbar{width:10px;height:10px}.ux-dl__scroll::-webkit-scrollbar-track{background:color-mix(in srgb,var(--p-surface-500) 8%,transparent);border-radius:var(--p-content-border-radius, .375rem)}.ux-dl__scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--p-primary-color) 25%,transparent);border-radius:var(--p-content-border-radius, .375rem)}.ux-dl__scroll::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--p-primary-color) 45%,transparent)}.ux-dl__sidebar-inner{display:flex;flex-direction:column;gap:1.5rem}.ux-dl__header-meta{overflow:hidden;max-height:80px;opacity:1;transition:max-height .25s ease-out,opacity .2s ease-out}.ux-dl__header-meta--hidden{max-height:0;opacity:0}.ux-dl__tablist{display:flex;overflow:hidden}.ux-dl__mobile-tabs{position:sticky;top:0;z-index:5}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i4$4.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i4$4.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i4$4.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i4$4.TabList, selector: "p-tablist" }, { kind: "component", type: i4$4.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2935
3240
|
}
|
|
2936
3241
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: DetailLayoutComponent, decorators: [{
|
|
2937
3242
|
type: Component,
|
|
2938
|
-
args: [{ selector: 'ux-detail-layout', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, TabsModule], host: { class: 'ux-detail-layout
|
|
2939
|
-
<div class="flex flex-col
|
|
3243
|
+
args: [{ selector: 'ux-detail-layout', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, SelectModule, TabsModule], host: { class: 'ux-detail-layout' }, template: `
|
|
3244
|
+
<div class="flex flex-col flex-1 min-h-0">
|
|
2940
3245
|
|
|
2941
3246
|
<!-- Sticky header (projected) -->
|
|
2942
3247
|
<div class="ux-dl__header flex-shrink-0 z-10">
|
|
@@ -2948,13 +3253,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2948
3253
|
</div>
|
|
2949
3254
|
</div>
|
|
2950
3255
|
|
|
2951
|
-
<!--
|
|
2952
|
-
<
|
|
2953
|
-
(scroll)="onScroll($event)">
|
|
3256
|
+
<!-- p-tabs wraps tablist + scrollable panels for state binding -->
|
|
3257
|
+
<p-tabs class="flex flex-col flex-1 min-h-0" [value]="activeTab()" (valueChange)="activeTab.set($event + '')">
|
|
2954
3258
|
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
3259
|
+
@if (!singleTab()) {
|
|
3260
|
+
<!-- Mobile: dropdown selector -->
|
|
3261
|
+
@if (isMobile()) {
|
|
3262
|
+
<div class="ux-dl__mobile-tabs">
|
|
3263
|
+
<p-select
|
|
3264
|
+
[options]="tabOptions()"
|
|
3265
|
+
[ngModel]="activeTab()"
|
|
3266
|
+
(ngModelChange)="activeTab.set($event)"
|
|
3267
|
+
optionLabel="label"
|
|
3268
|
+
optionValue="value"
|
|
3269
|
+
styleClass="w-full ux-dl__mobile-select"
|
|
3270
|
+
/>
|
|
3271
|
+
</div>
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
<!-- Desktop: horizontal tab bar (outside scroll → stays fixed below header) -->
|
|
3275
|
+
<p-tablist
|
|
3276
|
+
class="flex-shrink-0 ux-dl__tablist"
|
|
3277
|
+
[style.display]="isMobile() ? 'none' : null"
|
|
3278
|
+
[pt]="{ tabList: { class: 'p-0' } }"
|
|
3279
|
+
>
|
|
2958
3280
|
@for (tab of tabs(); track tab.value) {
|
|
2959
3281
|
<p-tab [value]="tab.value">
|
|
2960
3282
|
@if (tab.icon) {
|
|
@@ -2964,12 +3286,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2964
3286
|
</p-tab>
|
|
2965
3287
|
}
|
|
2966
3288
|
</p-tablist>
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
<!-- Scrollable body (only content scrolls, tabs stay above) -->
|
|
3292
|
+
<div class="flex flex-col flex-1 min-h-0 overflow-y-auto overflow-x-hidden ux-dl__scroll"
|
|
3293
|
+
(scroll)="onScroll($event)">
|
|
2967
3294
|
|
|
2968
|
-
<!-- Content + Sidebar row
|
|
2969
|
-
<div class="flex flex-col lg:flex-row items-start gap-6 w-full py-4
|
|
3295
|
+
<!-- Content + Sidebar row -->
|
|
3296
|
+
<div class="flex flex-col lg:flex-row items-start gap-6 w-full py-4 lg:py-6">
|
|
2970
3297
|
|
|
2971
3298
|
<!-- Main column: tab panels -->
|
|
2972
|
-
<div class="flex-1 min-w-0 flex flex-col gap-6">
|
|
3299
|
+
<div class="w-full flex-1 min-w-0 flex flex-col gap-6">
|
|
2973
3300
|
<p-tabpanels>
|
|
2974
3301
|
@for (tab of tabs(); track tab.value) {
|
|
2975
3302
|
<p-tabpanel [value]="tab.value">
|
|
@@ -2981,27 +3308,658 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
2981
3308
|
</p-tabpanel>
|
|
2982
3309
|
}
|
|
2983
3310
|
</p-tabpanels>
|
|
2984
|
-
|
|
2985
|
-
<!-- Footer below tab content -->
|
|
2986
|
-
<ng-content select="[ux-detail-footer]" />
|
|
2987
3311
|
</div>
|
|
2988
3312
|
|
|
2989
3313
|
<!-- Sidebar -->
|
|
2990
|
-
<aside class="w-full lg:w-[380px] shrink-0 flex flex-col lg:sticky lg:top-4 lg:self-start pb-8">
|
|
3314
|
+
<aside class="w-full lg:w-[380px] shrink-0 flex flex-col lg:sticky lg:top-4 lg:self-start lg:pb-8">
|
|
2991
3315
|
<div class="ux-dl__sidebar-inner w-full">
|
|
2992
3316
|
<ng-content select="[ux-detail-sidebar]" />
|
|
2993
3317
|
</div>
|
|
2994
3318
|
</aside>
|
|
2995
3319
|
</div>
|
|
2996
|
-
|
|
2997
|
-
|
|
3320
|
+
|
|
3321
|
+
</div>
|
|
3322
|
+
|
|
3323
|
+
</p-tabs>
|
|
3324
|
+
|
|
2998
3325
|
</div>
|
|
2999
|
-
`, styles: [":host{display:
|
|
3000
|
-
}], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: true }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], tabTemplates: [{
|
|
3326
|
+
`, styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0;font-family:var(--p-font-family, \"Noto Sans\", sans-serif);background:transparent;color:var(--p-text-color)}.ux-dl__header{background:transparent}.ux-dl__scroll{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--p-primary-color) 25%,transparent) color-mix(in srgb,var(--p-surface-500) 8%,transparent)}.ux-dl__scroll::-webkit-scrollbar{width:10px;height:10px}.ux-dl__scroll::-webkit-scrollbar-track{background:color-mix(in srgb,var(--p-surface-500) 8%,transparent);border-radius:var(--p-content-border-radius, .375rem)}.ux-dl__scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--p-primary-color) 25%,transparent);border-radius:var(--p-content-border-radius, .375rem)}.ux-dl__scroll::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--p-primary-color) 45%,transparent)}.ux-dl__sidebar-inner{display:flex;flex-direction:column;gap:1.5rem}.ux-dl__header-meta{overflow:hidden;max-height:80px;opacity:1;transition:max-height .25s ease-out,opacity .2s ease-out}.ux-dl__header-meta--hidden{max-height:0;opacity:0}.ux-dl__tablist{display:flex;overflow:hidden}.ux-dl__mobile-tabs{position:sticky;top:0;z-index:5}\n"] }]
|
|
3327
|
+
}], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: true }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], tabTemplates: [{
|
|
3001
3328
|
type: ContentChildren,
|
|
3002
3329
|
args: [DetailTabDirective]
|
|
3003
3330
|
}] } });
|
|
3004
3331
|
|
|
3332
|
+
/**
|
|
3333
|
+
* Horizontal row of pill-shaped sub-tab buttons. Styling aligns with sidebar menu item
|
|
3334
|
+
* hover/active tokens (`--d-menuitem-*`).
|
|
3335
|
+
*/
|
|
3336
|
+
class PillTabsComponent {
|
|
3337
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
3338
|
+
activeValue = model('', ...(ngDevMode ? [{ debugName: "activeValue" }] : []));
|
|
3339
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: PillTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3340
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: PillTabsComponent, isStandalone: true, selector: "ux-pill-tabs", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, activeValue: { classPropertyName: "activeValue", publicName: "activeValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeValue: "activeValueChange" }, host: { classAttribute: "ux-pill-tabs block" }, ngImport: i0, template: `
|
|
3341
|
+
<div class="ux-pill-tabs__row" role="tablist">
|
|
3342
|
+
@for (item of items(); track item.value) {
|
|
3343
|
+
<button
|
|
3344
|
+
type="button"
|
|
3345
|
+
class="ux-pill-tabs__btn"
|
|
3346
|
+
role="tab"
|
|
3347
|
+
[attr.aria-selected]="activeValue() === item.value"
|
|
3348
|
+
[class.ux-pill-tabs__btn--active]="activeValue() === item.value"
|
|
3349
|
+
(click)="activeValue.set(item.value)"
|
|
3350
|
+
>
|
|
3351
|
+
{{ item.label }}
|
|
3352
|
+
</button>
|
|
3353
|
+
}
|
|
3354
|
+
</div>
|
|
3355
|
+
`, isInline: true, styles: [".ux-pill-tabs__row{display:flex;flex-wrap:wrap;gap:.5rem}.ux-pill-tabs__btn{border-radius:9999px;padding:.375rem .875rem;font-size:var(--p-font-size, .875rem);font-weight:600;font-family:inherit;cursor:pointer;transition:all .15s ease;border:1px solid var(--p-primary-800);background:transparent;color:var(--p-text-muted-color)}:host-context(.app-dark) .ux-pill-tabs__btn:not(.ux-pill-tabs__btn--active){border-color:var(--p-surface-700)}.ux-pill-tabs__btn:hover:not(.ux-pill-tabs__btn--active){background:var(--d-menuitem-hover-bg);color:var(--p-primary-950)}:host-context(.app-dark) .ux-pill-tabs__btn:hover:not(.ux-pill-tabs__btn--active){color:var(--p-primary-200)}.ux-pill-tabs__btn--active{background:var(--p-primary-200);border-color:transparent;color:var(--p-primary-950)}:host-context(.app-dark) .ux-pill-tabs__btn--active{color:var(--p-primary-950)}.ux-pill-tabs__btn:focus{outline:none;box-shadow:none}.ux-pill-tabs__btn:focus-visible{outline:none;box-shadow:var(--d-menuitem-focus-shadow)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3356
|
+
}
|
|
3357
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: PillTabsComponent, decorators: [{
|
|
3358
|
+
type: Component,
|
|
3359
|
+
args: [{ selector: 'ux-pill-tabs', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'ux-pill-tabs block' }, template: `
|
|
3360
|
+
<div class="ux-pill-tabs__row" role="tablist">
|
|
3361
|
+
@for (item of items(); track item.value) {
|
|
3362
|
+
<button
|
|
3363
|
+
type="button"
|
|
3364
|
+
class="ux-pill-tabs__btn"
|
|
3365
|
+
role="tab"
|
|
3366
|
+
[attr.aria-selected]="activeValue() === item.value"
|
|
3367
|
+
[class.ux-pill-tabs__btn--active]="activeValue() === item.value"
|
|
3368
|
+
(click)="activeValue.set(item.value)"
|
|
3369
|
+
>
|
|
3370
|
+
{{ item.label }}
|
|
3371
|
+
</button>
|
|
3372
|
+
}
|
|
3373
|
+
</div>
|
|
3374
|
+
`, styles: [".ux-pill-tabs__row{display:flex;flex-wrap:wrap;gap:.5rem}.ux-pill-tabs__btn{border-radius:9999px;padding:.375rem .875rem;font-size:var(--p-font-size, .875rem);font-weight:600;font-family:inherit;cursor:pointer;transition:all .15s ease;border:1px solid var(--p-primary-800);background:transparent;color:var(--p-text-muted-color)}:host-context(.app-dark) .ux-pill-tabs__btn:not(.ux-pill-tabs__btn--active){border-color:var(--p-surface-700)}.ux-pill-tabs__btn:hover:not(.ux-pill-tabs__btn--active){background:var(--d-menuitem-hover-bg);color:var(--p-primary-950)}:host-context(.app-dark) .ux-pill-tabs__btn:hover:not(.ux-pill-tabs__btn--active){color:var(--p-primary-200)}.ux-pill-tabs__btn--active{background:var(--p-primary-200);border-color:transparent;color:var(--p-primary-950)}:host-context(.app-dark) .ux-pill-tabs__btn--active{color:var(--p-primary-950)}.ux-pill-tabs__btn:focus{outline:none;box-shadow:none}.ux-pill-tabs__btn:focus-visible{outline:none;box-shadow:var(--d-menuitem-focus-shadow)}\n"] }]
|
|
3375
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], activeValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeValue", required: false }] }, { type: i0.Output, args: ["activeValueChange"] }] } });
|
|
3376
|
+
|
|
3377
|
+
class DocumentsCardComponent {
|
|
3378
|
+
documents = input([], ...(ngDevMode ? [{ debugName: "documents" }] : []));
|
|
3379
|
+
rows = input(5, ...(ngDevMode ? [{ debugName: "rows" }] : []));
|
|
3380
|
+
expanded = signal(false, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
|
|
3381
|
+
activeFilter = signal('All Files', ...(ngDevMode ? [{ debugName: "activeFilter" }] : []));
|
|
3382
|
+
searchQuery = model('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
|
|
3383
|
+
fileTypes = computed(() => {
|
|
3384
|
+
const types = [...new Set(this.documents().map(d => d.type))];
|
|
3385
|
+
types.sort();
|
|
3386
|
+
return types;
|
|
3387
|
+
}, ...(ngDevMode ? [{ debugName: "fileTypes" }] : []));
|
|
3388
|
+
filterOptions = computed(() => ['All Files', ...this.fileTypes(), 'Other'], ...(ngDevMode ? [{ debugName: "filterOptions" }] : []));
|
|
3389
|
+
pillTabItems = computed(() => this.filterOptions().map(f => ({ value: f, label: f })), ...(ngDevMode ? [{ debugName: "pillTabItems" }] : []));
|
|
3390
|
+
summary = computed(() => {
|
|
3391
|
+
const docs = this.documents();
|
|
3392
|
+
const count = docs.length;
|
|
3393
|
+
if (count === 0)
|
|
3394
|
+
return 'No files attached';
|
|
3395
|
+
const types = this.fileTypes();
|
|
3396
|
+
const fileWord = count === 1 ? 'file' : 'files';
|
|
3397
|
+
if (types.length === 0)
|
|
3398
|
+
return `${count} ${fileWord} attached`;
|
|
3399
|
+
return `${count} ${fileWord} · ${types.join(', ')}`;
|
|
3400
|
+
}, ...(ngDevMode ? [{ debugName: "summary" }] : []));
|
|
3401
|
+
filtered = computed(() => {
|
|
3402
|
+
let docs = this.documents();
|
|
3403
|
+
const query = this.searchQuery().trim().toLowerCase();
|
|
3404
|
+
if (query) {
|
|
3405
|
+
docs = docs.filter(d => d.fileName.toLowerCase().includes(query) || d.owner.toLowerCase().includes(query));
|
|
3406
|
+
}
|
|
3407
|
+
const filter = this.activeFilter();
|
|
3408
|
+
if (filter === 'All Files')
|
|
3409
|
+
return docs;
|
|
3410
|
+
if (filter === 'Other') {
|
|
3411
|
+
const knownTypes = this.fileTypes();
|
|
3412
|
+
return docs.filter(d => !knownTypes.includes(d.type));
|
|
3413
|
+
}
|
|
3414
|
+
return docs.filter(d => d.type === filter);
|
|
3415
|
+
}, ...(ngDevMode ? [{ debugName: "filtered" }] : []));
|
|
3416
|
+
menuItems = [];
|
|
3417
|
+
onMenuToggle(event, _doc, menu) {
|
|
3418
|
+
this.menuItems = [
|
|
3419
|
+
{ label: 'Preview', icon: 'pi pi-eye' },
|
|
3420
|
+
{ label: 'Share', icon: 'pi pi-share-alt' },
|
|
3421
|
+
{ separator: true },
|
|
3422
|
+
{ label: 'Delete', icon: 'pi pi-trash', styleClass: 'text-red-500' }
|
|
3423
|
+
];
|
|
3424
|
+
menu.toggle(event);
|
|
3425
|
+
}
|
|
3426
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: DocumentsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3427
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: DocumentsCardComponent, isStandalone: true, selector: "ux-documents-card", inputs: { documents: { classPropertyName: "documents", publicName: "documents", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, searchQuery: { classPropertyName: "searchQuery", publicName: "searchQuery", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchQuery: "searchQueryChange" }, host: { classAttribute: "ux-documents-card block" }, ngImport: i0, template: `
|
|
3428
|
+
<div class="card flex flex-col overflow-hidden">
|
|
3429
|
+
<p-panel [toggleable]="true" [collapsed]="!expanded()" (collapsedChange)="expanded.set(!$event)" toggler="header">
|
|
3430
|
+
<ng-template #headericons let-collapsed>
|
|
3431
|
+
<i class="pi text-sm text-darkblue-500 dark:text-surface-0" [ngClass]="collapsed ? 'pi-chevron-down' : 'pi-chevron-up'"></i>
|
|
3432
|
+
</ng-template>
|
|
3433
|
+
<ng-template #header>
|
|
3434
|
+
<div class="flex items-center gap-3 flex-1">
|
|
3435
|
+
<div class="w-[34px] h-[34px] rounded-[10px] flex items-center justify-center shrink-0">
|
|
3436
|
+
<i class="pi pi-folder text-deepsea-500 dark:text-surface-0"></i>
|
|
3437
|
+
</div>
|
|
3438
|
+
<div class="flex flex-col">
|
|
3439
|
+
<h4 class="title-h4 text-left text-deepsea-500 dark:text-surface-0">Documents</h4>
|
|
3440
|
+
<span class="text-surface-500 dark:text-surface-300 text-sm font-medium leading-tight">{{ summary() }}</span>
|
|
3441
|
+
</div>
|
|
3442
|
+
</div>
|
|
3443
|
+
</ng-template>
|
|
3444
|
+
<div class="flex flex-col gap-4 pt-4">
|
|
3445
|
+
<ux-pill-tabs [items]="pillTabItems()" [(activeValue)]="activeFilter" />
|
|
3446
|
+
|
|
3447
|
+
<p-iconfield>
|
|
3448
|
+
<p-inputicon class="pi pi-search" />
|
|
3449
|
+
<input pInputText [(ngModel)]="searchQuery" placeholder="Search documents" class="w-full" />
|
|
3450
|
+
</p-iconfield>
|
|
3451
|
+
|
|
3452
|
+
@if (filtered().length > 0) {
|
|
3453
|
+
<p-table
|
|
3454
|
+
[value]="filtered()"
|
|
3455
|
+
[paginator]="true"
|
|
3456
|
+
[rows]="rows()"
|
|
3457
|
+
sortMode="multiple"
|
|
3458
|
+
styleClass="flex flex-col rounded-2xl overflow-hidden [&>[data-pc-section=paginatorcontainer]]:border-0! [&>[data-pc-section=paginatorcontainer]]:mt-auto [&_[data-pc-name=pcpaginator]]:rounded-none!"
|
|
3459
|
+
tableStyleClass="w-full table-fixed"
|
|
3460
|
+
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink"
|
|
3461
|
+
>
|
|
3462
|
+
<ng-template #header>
|
|
3463
|
+
<tr>
|
|
3464
|
+
<th pSortableColumn="fileName" class="w-1/2">File Name <p-sortIcon field="fileName" /></th>
|
|
3465
|
+
<th pSortableColumn="type" class="w-1/4">Type <p-sortIcon field="type" /></th>
|
|
3466
|
+
<th class="w-1/4">Actions</th>
|
|
3467
|
+
</tr>
|
|
3468
|
+
</ng-template>
|
|
3469
|
+
<ng-template #body let-doc>
|
|
3470
|
+
<tr>
|
|
3471
|
+
<td>
|
|
3472
|
+
<div class="flex items-center gap-3 py-1 min-w-0">
|
|
3473
|
+
<i class="pi text-xl text-surface-600 dark:text-surface-300 shrink-0" [ngClass]="doc.icon"></i>
|
|
3474
|
+
<span class="text-surface-700 dark:text-surface-100 text-sm truncate">{{ doc.fileName }}</span>
|
|
3475
|
+
</div>
|
|
3476
|
+
</td>
|
|
3477
|
+
<td>
|
|
3478
|
+
<p-tag [value]="doc.type" styleClass="px-2 py-1" />
|
|
3479
|
+
</td>
|
|
3480
|
+
<td>
|
|
3481
|
+
<div class="flex items-center gap-1">
|
|
3482
|
+
<p-button icon="pi pi-download" [rounded]="true" [text]="true" size="small" severity="secondary" styleClass="cursor-pointer" ariaLabel="Download" />
|
|
3483
|
+
<p-button icon="pi pi-ellipsis-h" [rounded]="true" [text]="true" size="small" severity="secondary" styleClass="cursor-pointer" ariaLabel="More options" (onClick)="onMenuToggle($event, doc, docMenu)" />
|
|
3484
|
+
<p-menu #docMenu [model]="menuItems" [popup]="true" styleClass="w-48" appendTo="body" />
|
|
3485
|
+
</div>
|
|
3486
|
+
</td>
|
|
3487
|
+
</tr>
|
|
3488
|
+
</ng-template>
|
|
3489
|
+
</p-table>
|
|
3490
|
+
} @else {
|
|
3491
|
+
<div class="flex flex-col items-center gap-3 py-8 text-center">
|
|
3492
|
+
<i class="pi pi-folder-open text-3xl text-surface-300 dark:text-surface-500"></i>
|
|
3493
|
+
<span class="text-surface-600 dark:text-surface-300 text-sm">No documents to show</span>
|
|
3494
|
+
</div>
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
<p-fileupload
|
|
3498
|
+
name="documents[]"
|
|
3499
|
+
[multiple]="true"
|
|
3500
|
+
maxFileSize="10000000"
|
|
3501
|
+
mode="advanced"
|
|
3502
|
+
[auto]="false"
|
|
3503
|
+
chooseLabel="Upload File"
|
|
3504
|
+
chooseIcon="pi pi-upload"
|
|
3505
|
+
[showUploadButton]="false"
|
|
3506
|
+
[showCancelButton]="false"
|
|
3507
|
+
[pt]="{ root: { class: 'bg-transparent' }, header: { class: 'bg-transparent' }, content: { class: 'bg-transparent' } }"
|
|
3508
|
+
>
|
|
3509
|
+
<ng-template #header let-chooseCallback="chooseCallback">
|
|
3510
|
+
<div class="flex items-center gap-2 w-full">
|
|
3511
|
+
<p-button icon="pi pi-upload" label="Upload File" (onClick)="chooseCallback()" />
|
|
3512
|
+
<p-button icon="pi pi-link" label="Share Link" [outlined]="true" styleClass="!text-primary-600 !border-primary-600" />
|
|
3513
|
+
</div>
|
|
3514
|
+
</ng-template>
|
|
3515
|
+
<ng-template #empty>
|
|
3516
|
+
<div class="flex flex-col items-center gap-2 py-4">
|
|
3517
|
+
<i class="pi pi-cloud-upload text-2xl text-surface-400 dark:text-surface-300"></i>
|
|
3518
|
+
<span class="text-surface-500 dark:text-surface-100 text-sm">Drag and drop files here</span>
|
|
3519
|
+
</div>
|
|
3520
|
+
</ng-template>
|
|
3521
|
+
</p-fileupload>
|
|
3522
|
+
</div>
|
|
3523
|
+
</p-panel>
|
|
3524
|
+
</div>
|
|
3525
|
+
`, isInline: true, styles: [""], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2$1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i3$4.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i4$3.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i5$1.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i7$1.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo", "motionOptions"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i8$1.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i8$1.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i8$1.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i9$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: PillTabsComponent, selector: "ux-pill-tabs", inputs: ["items", "activeValue"], outputs: ["activeValueChange"] }, { kind: "ngmodule", type: PanelModule }, { kind: "component", type: i10.Panel, selector: "p-panel", inputs: ["id", "toggleable", "header", "collapsed", "styleClass", "iconPos", "showHeader", "toggler", "transitionOptions", "toggleButtonProps", "motionOptions"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3526
|
+
}
|
|
3527
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: DocumentsCardComponent, decorators: [{
|
|
3528
|
+
type: Component,
|
|
3529
|
+
args: [{ selector: 'ux-documents-card', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass, FormsModule, ButtonModule, FileUploadModule, IconFieldModule, InputIconModule, InputTextModule, MenuModule, TableModule, TagModule, PillTabsComponent, PanelModule], host: { class: 'ux-documents-card block' }, template: `
|
|
3530
|
+
<div class="card flex flex-col overflow-hidden">
|
|
3531
|
+
<p-panel [toggleable]="true" [collapsed]="!expanded()" (collapsedChange)="expanded.set(!$event)" toggler="header">
|
|
3532
|
+
<ng-template #headericons let-collapsed>
|
|
3533
|
+
<i class="pi text-sm text-darkblue-500 dark:text-surface-0" [ngClass]="collapsed ? 'pi-chevron-down' : 'pi-chevron-up'"></i>
|
|
3534
|
+
</ng-template>
|
|
3535
|
+
<ng-template #header>
|
|
3536
|
+
<div class="flex items-center gap-3 flex-1">
|
|
3537
|
+
<div class="w-[34px] h-[34px] rounded-[10px] flex items-center justify-center shrink-0">
|
|
3538
|
+
<i class="pi pi-folder text-deepsea-500 dark:text-surface-0"></i>
|
|
3539
|
+
</div>
|
|
3540
|
+
<div class="flex flex-col">
|
|
3541
|
+
<h4 class="title-h4 text-left text-deepsea-500 dark:text-surface-0">Documents</h4>
|
|
3542
|
+
<span class="text-surface-500 dark:text-surface-300 text-sm font-medium leading-tight">{{ summary() }}</span>
|
|
3543
|
+
</div>
|
|
3544
|
+
</div>
|
|
3545
|
+
</ng-template>
|
|
3546
|
+
<div class="flex flex-col gap-4 pt-4">
|
|
3547
|
+
<ux-pill-tabs [items]="pillTabItems()" [(activeValue)]="activeFilter" />
|
|
3548
|
+
|
|
3549
|
+
<p-iconfield>
|
|
3550
|
+
<p-inputicon class="pi pi-search" />
|
|
3551
|
+
<input pInputText [(ngModel)]="searchQuery" placeholder="Search documents" class="w-full" />
|
|
3552
|
+
</p-iconfield>
|
|
3553
|
+
|
|
3554
|
+
@if (filtered().length > 0) {
|
|
3555
|
+
<p-table
|
|
3556
|
+
[value]="filtered()"
|
|
3557
|
+
[paginator]="true"
|
|
3558
|
+
[rows]="rows()"
|
|
3559
|
+
sortMode="multiple"
|
|
3560
|
+
styleClass="flex flex-col rounded-2xl overflow-hidden [&>[data-pc-section=paginatorcontainer]]:border-0! [&>[data-pc-section=paginatorcontainer]]:mt-auto [&_[data-pc-name=pcpaginator]]:rounded-none!"
|
|
3561
|
+
tableStyleClass="w-full table-fixed"
|
|
3562
|
+
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink"
|
|
3563
|
+
>
|
|
3564
|
+
<ng-template #header>
|
|
3565
|
+
<tr>
|
|
3566
|
+
<th pSortableColumn="fileName" class="w-1/2">File Name <p-sortIcon field="fileName" /></th>
|
|
3567
|
+
<th pSortableColumn="type" class="w-1/4">Type <p-sortIcon field="type" /></th>
|
|
3568
|
+
<th class="w-1/4">Actions</th>
|
|
3569
|
+
</tr>
|
|
3570
|
+
</ng-template>
|
|
3571
|
+
<ng-template #body let-doc>
|
|
3572
|
+
<tr>
|
|
3573
|
+
<td>
|
|
3574
|
+
<div class="flex items-center gap-3 py-1 min-w-0">
|
|
3575
|
+
<i class="pi text-xl text-surface-600 dark:text-surface-300 shrink-0" [ngClass]="doc.icon"></i>
|
|
3576
|
+
<span class="text-surface-700 dark:text-surface-100 text-sm truncate">{{ doc.fileName }}</span>
|
|
3577
|
+
</div>
|
|
3578
|
+
</td>
|
|
3579
|
+
<td>
|
|
3580
|
+
<p-tag [value]="doc.type" styleClass="px-2 py-1" />
|
|
3581
|
+
</td>
|
|
3582
|
+
<td>
|
|
3583
|
+
<div class="flex items-center gap-1">
|
|
3584
|
+
<p-button icon="pi pi-download" [rounded]="true" [text]="true" size="small" severity="secondary" styleClass="cursor-pointer" ariaLabel="Download" />
|
|
3585
|
+
<p-button icon="pi pi-ellipsis-h" [rounded]="true" [text]="true" size="small" severity="secondary" styleClass="cursor-pointer" ariaLabel="More options" (onClick)="onMenuToggle($event, doc, docMenu)" />
|
|
3586
|
+
<p-menu #docMenu [model]="menuItems" [popup]="true" styleClass="w-48" appendTo="body" />
|
|
3587
|
+
</div>
|
|
3588
|
+
</td>
|
|
3589
|
+
</tr>
|
|
3590
|
+
</ng-template>
|
|
3591
|
+
</p-table>
|
|
3592
|
+
} @else {
|
|
3593
|
+
<div class="flex flex-col items-center gap-3 py-8 text-center">
|
|
3594
|
+
<i class="pi pi-folder-open text-3xl text-surface-300 dark:text-surface-500"></i>
|
|
3595
|
+
<span class="text-surface-600 dark:text-surface-300 text-sm">No documents to show</span>
|
|
3596
|
+
</div>
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3599
|
+
<p-fileupload
|
|
3600
|
+
name="documents[]"
|
|
3601
|
+
[multiple]="true"
|
|
3602
|
+
maxFileSize="10000000"
|
|
3603
|
+
mode="advanced"
|
|
3604
|
+
[auto]="false"
|
|
3605
|
+
chooseLabel="Upload File"
|
|
3606
|
+
chooseIcon="pi pi-upload"
|
|
3607
|
+
[showUploadButton]="false"
|
|
3608
|
+
[showCancelButton]="false"
|
|
3609
|
+
[pt]="{ root: { class: 'bg-transparent' }, header: { class: 'bg-transparent' }, content: { class: 'bg-transparent' } }"
|
|
3610
|
+
>
|
|
3611
|
+
<ng-template #header let-chooseCallback="chooseCallback">
|
|
3612
|
+
<div class="flex items-center gap-2 w-full">
|
|
3613
|
+
<p-button icon="pi pi-upload" label="Upload File" (onClick)="chooseCallback()" />
|
|
3614
|
+
<p-button icon="pi pi-link" label="Share Link" [outlined]="true" styleClass="!text-primary-600 !border-primary-600" />
|
|
3615
|
+
</div>
|
|
3616
|
+
</ng-template>
|
|
3617
|
+
<ng-template #empty>
|
|
3618
|
+
<div class="flex flex-col items-center gap-2 py-4">
|
|
3619
|
+
<i class="pi pi-cloud-upload text-2xl text-surface-400 dark:text-surface-300"></i>
|
|
3620
|
+
<span class="text-surface-500 dark:text-surface-100 text-sm">Drag and drop files here</span>
|
|
3621
|
+
</div>
|
|
3622
|
+
</ng-template>
|
|
3623
|
+
</p-fileupload>
|
|
3624
|
+
</div>
|
|
3625
|
+
</p-panel>
|
|
3626
|
+
</div>
|
|
3627
|
+
` }]
|
|
3628
|
+
}], propDecorators: { documents: [{ type: i0.Input, args: [{ isSignal: true, alias: "documents", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], searchQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchQuery", required: false }] }, { type: i0.Output, args: ["searchQueryChange"] }] } });
|
|
3629
|
+
|
|
3630
|
+
class UxSelectComponent {
|
|
3631
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
3632
|
+
optionLabel = input('label', ...(ngDevMode ? [{ debugName: "optionLabel" }] : []));
|
|
3633
|
+
optionValue = input('value', ...(ngDevMode ? [{ debugName: "optionValue" }] : []));
|
|
3634
|
+
optionGroupLabel = input('label', ...(ngDevMode ? [{ debugName: "optionGroupLabel" }] : []));
|
|
3635
|
+
optionGroupChildren = input('items', ...(ngDevMode ? [{ debugName: "optionGroupChildren" }] : []));
|
|
3636
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
3637
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
3638
|
+
filter = input(false, ...(ngDevMode ? [{ debugName: "filter" }] : []));
|
|
3639
|
+
showClear = input(false, ...(ngDevMode ? [{ debugName: "showClear" }] : []));
|
|
3640
|
+
emptyMessage = input('No results found', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
|
|
3641
|
+
group = input(false, ...(ngDevMode ? [{ debugName: "group" }] : []));
|
|
3642
|
+
styleClass = input('', ...(ngDevMode ? [{ debugName: "styleClass" }] : []));
|
|
3643
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
3644
|
+
onChange = output();
|
|
3645
|
+
onFilter = output();
|
|
3646
|
+
resolvedStyleClass = computed(() => {
|
|
3647
|
+
const base = 'ux-select__inner';
|
|
3648
|
+
const extra = this.styleClass();
|
|
3649
|
+
return extra ? `${base} ${extra}` : base;
|
|
3650
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedStyleClass" }] : []));
|
|
3651
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: UxSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3652
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.8", type: UxSelectComponent, isStandalone: true, selector: "ux-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionGroupLabel: { classPropertyName: "optionGroupLabel", publicName: "optionGroupLabel", isSignal: true, isRequired: false, transformFunction: null }, optionGroupChildren: { classPropertyName: "optionGroupChildren", publicName: "optionGroupChildren", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onChange: "onChange", onFilter: "onFilter" }, host: { classAttribute: "ux-select" }, ngImport: i0, template: `
|
|
3653
|
+
<p-select
|
|
3654
|
+
[options]="options()"
|
|
3655
|
+
[optionLabel]="optionLabel()"
|
|
3656
|
+
[optionValue]="optionValue()"
|
|
3657
|
+
[optionGroupLabel]="optionGroupLabel()"
|
|
3658
|
+
[optionGroupChildren]="optionGroupChildren()"
|
|
3659
|
+
[placeholder]="placeholder()"
|
|
3660
|
+
[disabled]="disabled()"
|
|
3661
|
+
[filter]="filter()"
|
|
3662
|
+
[showClear]="showClear()"
|
|
3663
|
+
[emptyMessage]="emptyMessage()"
|
|
3664
|
+
[group]="group()"
|
|
3665
|
+
[ngModel]="value()"
|
|
3666
|
+
(ngModelChange)="value.set($event)"
|
|
3667
|
+
(onChange)="onChange.emit($event)"
|
|
3668
|
+
(onFilter)="onFilter.emit($event)"
|
|
3669
|
+
[styleClass]="resolvedStyleClass()"
|
|
3670
|
+
/>
|
|
3671
|
+
`, isInline: true, styles: [":host :deep .p-select{border-radius:var(--p-content-border-radius, .375rem);font-family:var(--p-font-family, \"Noto Sans\", sans-serif);font-size:var(--font-size-sm, .875rem);transition:border-color .15s ease,box-shadow .15s ease;padding:.5rem 1.5rem}:host :deep .p-select:not(.p-disabled):hover{border-color:var(--p-primary-400)}:host :deep .p-select:not(.p-disabled).p-focus{border-color:var(--p-primary-500);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-500) 20%,transparent)}:host :deep .p-select-label{font-size:var(--font-size-sm, .875rem);color:var(--p-text-color)}:host :deep .p-select-label.p-placeholder{color:var(--p-text-muted-color)}:host :deep .p-select-dropdown{color:var(--p-text-muted-color)}:host-context(:root[class*=\"app-dark\"]) :deep .p-select:not(.p-disabled):hover{border-color:var(--p-primary-300)}:host-context(:root[class*=\"app-dark\"]) :deep .p-select:not(.p-disabled).p-focus{border-color:var(--p-primary-400);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-400) 25%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3672
|
+
}
|
|
3673
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: UxSelectComponent, decorators: [{
|
|
3674
|
+
type: Component,
|
|
3675
|
+
args: [{ selector: 'ux-select', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, SelectModule], host: { class: 'ux-select' }, template: `
|
|
3676
|
+
<p-select
|
|
3677
|
+
[options]="options()"
|
|
3678
|
+
[optionLabel]="optionLabel()"
|
|
3679
|
+
[optionValue]="optionValue()"
|
|
3680
|
+
[optionGroupLabel]="optionGroupLabel()"
|
|
3681
|
+
[optionGroupChildren]="optionGroupChildren()"
|
|
3682
|
+
[placeholder]="placeholder()"
|
|
3683
|
+
[disabled]="disabled()"
|
|
3684
|
+
[filter]="filter()"
|
|
3685
|
+
[showClear]="showClear()"
|
|
3686
|
+
[emptyMessage]="emptyMessage()"
|
|
3687
|
+
[group]="group()"
|
|
3688
|
+
[ngModel]="value()"
|
|
3689
|
+
(ngModelChange)="value.set($event)"
|
|
3690
|
+
(onChange)="onChange.emit($event)"
|
|
3691
|
+
(onFilter)="onFilter.emit($event)"
|
|
3692
|
+
[styleClass]="resolvedStyleClass()"
|
|
3693
|
+
/>
|
|
3694
|
+
`, styles: [":host :deep .p-select{border-radius:var(--p-content-border-radius, .375rem);font-family:var(--p-font-family, \"Noto Sans\", sans-serif);font-size:var(--font-size-sm, .875rem);transition:border-color .15s ease,box-shadow .15s ease;padding:.5rem 1.5rem}:host :deep .p-select:not(.p-disabled):hover{border-color:var(--p-primary-400)}:host :deep .p-select:not(.p-disabled).p-focus{border-color:var(--p-primary-500);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-500) 20%,transparent)}:host :deep .p-select-label{font-size:var(--font-size-sm, .875rem);color:var(--p-text-color)}:host :deep .p-select-label.p-placeholder{color:var(--p-text-muted-color)}:host :deep .p-select-dropdown{color:var(--p-text-muted-color)}:host-context(:root[class*=\"app-dark\"]) :deep .p-select:not(.p-disabled):hover{border-color:var(--p-primary-300)}:host-context(:root[class*=\"app-dark\"]) :deep .p-select:not(.p-disabled).p-focus{border-color:var(--p-primary-400);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-400) 25%,transparent)}\n"] }]
|
|
3695
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onFilter: [{ type: i0.Output, args: ["onFilter"] }] } });
|
|
3696
|
+
|
|
3697
|
+
class TaskDrawerComponent {
|
|
3698
|
+
visible = model(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
3699
|
+
task = input(null, ...(ngDevMode ? [{ debugName: "task" }] : []));
|
|
3700
|
+
mode = input('create', ...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
3701
|
+
availableMembers = input([
|
|
3702
|
+
{ name: 'Amy Elsner', image: 'amyelsner.png' },
|
|
3703
|
+
{ name: 'Anna Fali', image: 'annafali.png' },
|
|
3704
|
+
{ name: 'Asiya Javayant', image: 'asiyajavayant.png' },
|
|
3705
|
+
{ name: 'Bernardo Dominic', image: 'bernardodominic.png' }
|
|
3706
|
+
], ...(ngDevMode ? [{ debugName: "availableMembers" }] : []));
|
|
3707
|
+
save = output();
|
|
3708
|
+
cancel = output();
|
|
3709
|
+
drawerTitle = computed(() => this.mode() === 'create' ? 'Create New Task' : 'Edit Task', ...(ngDevMode ? [{ debugName: "drawerTitle" }] : []));
|
|
3710
|
+
formData = {
|
|
3711
|
+
id: null,
|
|
3712
|
+
title: '',
|
|
3713
|
+
description: '',
|
|
3714
|
+
status: 'pending',
|
|
3715
|
+
completed: false,
|
|
3716
|
+
startDate: null,
|
|
3717
|
+
endDate: null,
|
|
3718
|
+
members: []
|
|
3719
|
+
};
|
|
3720
|
+
statusOptions = [
|
|
3721
|
+
{ label: 'Pending', value: 'pending' },
|
|
3722
|
+
{ label: 'In Progress', value: 'in-progress' },
|
|
3723
|
+
{ label: 'Completed', value: 'completed' }
|
|
3724
|
+
];
|
|
3725
|
+
filteredMembers = [];
|
|
3726
|
+
ngOnChanges(changes) {
|
|
3727
|
+
if (changes['task']) {
|
|
3728
|
+
const newTask = changes['task'].currentValue;
|
|
3729
|
+
if (newTask) {
|
|
3730
|
+
this.formData = {
|
|
3731
|
+
id: newTask.id,
|
|
3732
|
+
title: newTask.title || '',
|
|
3733
|
+
description: newTask.description || '',
|
|
3734
|
+
status: newTask.status || 'pending',
|
|
3735
|
+
completed: newTask.completed || false,
|
|
3736
|
+
startDate: newTask.startDate ? this.parseDate(newTask.startDate) : null,
|
|
3737
|
+
endDate: newTask.endDate ? this.parseDate(newTask.endDate) : null,
|
|
3738
|
+
members: newTask.members || []
|
|
3739
|
+
};
|
|
3740
|
+
}
|
|
3741
|
+
else {
|
|
3742
|
+
this.resetForm();
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
parseDate(dateStr) {
|
|
3747
|
+
if (!dateStr)
|
|
3748
|
+
return null;
|
|
3749
|
+
const parts = dateStr.split('.');
|
|
3750
|
+
if (parts.length === 3) {
|
|
3751
|
+
return new Date(parseInt(parts[2]), parseInt(parts[1]) - 1, parseInt(parts[0]));
|
|
3752
|
+
}
|
|
3753
|
+
return null;
|
|
3754
|
+
}
|
|
3755
|
+
resetForm() {
|
|
3756
|
+
this.formData = {
|
|
3757
|
+
id: null,
|
|
3758
|
+
title: '',
|
|
3759
|
+
description: '',
|
|
3760
|
+
status: 'pending',
|
|
3761
|
+
completed: false,
|
|
3762
|
+
startDate: null,
|
|
3763
|
+
endDate: null,
|
|
3764
|
+
members: []
|
|
3765
|
+
};
|
|
3766
|
+
}
|
|
3767
|
+
filterMembers(event) {
|
|
3768
|
+
const members = this.availableMembers();
|
|
3769
|
+
if (!event.query) {
|
|
3770
|
+
this.filteredMembers = members;
|
|
3771
|
+
return;
|
|
3772
|
+
}
|
|
3773
|
+
this.filteredMembers = members.filter(member => member.name?.toLowerCase().includes(event.query.toLowerCase()));
|
|
3774
|
+
}
|
|
3775
|
+
formatDateForSave(date) {
|
|
3776
|
+
if (!date)
|
|
3777
|
+
return null;
|
|
3778
|
+
const d = new Date(date);
|
|
3779
|
+
return `${String(d.getDate()).padStart(2, '0')}.${String(d.getMonth() + 1).padStart(2, '0')}.${d.getFullYear()}`;
|
|
3780
|
+
}
|
|
3781
|
+
handleSave() {
|
|
3782
|
+
const taskData = {
|
|
3783
|
+
id: this.formData.id,
|
|
3784
|
+
title: this.formData.title,
|
|
3785
|
+
description: this.formData.description || null,
|
|
3786
|
+
status: this.formData.status,
|
|
3787
|
+
completed: this.formData.status === 'completed',
|
|
3788
|
+
startDate: this.formatDateForSave(this.formData.startDate),
|
|
3789
|
+
endDate: this.formatDateForSave(this.formData.endDate),
|
|
3790
|
+
members: this.formData.members
|
|
3791
|
+
};
|
|
3792
|
+
this.save.emit(taskData);
|
|
3793
|
+
this.handleCancel();
|
|
3794
|
+
}
|
|
3795
|
+
handleCancel() {
|
|
3796
|
+
this.resetForm();
|
|
3797
|
+
this.cancel.emit();
|
|
3798
|
+
this.visible.set(false);
|
|
3799
|
+
}
|
|
3800
|
+
onHide() {
|
|
3801
|
+
this.handleCancel();
|
|
3802
|
+
}
|
|
3803
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: TaskDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3804
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.8", type: TaskDrawerComponent, isStandalone: true, selector: "ux-task-drawer", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, task: { classPropertyName: "task", publicName: "task", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, availableMembers: { classPropertyName: "availableMembers", publicName: "availableMembers", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", save: "save", cancel: "cancel" }, host: { classAttribute: "ux-task-drawer" }, usesOnChanges: true, ngImport: i0, template: `
|
|
3805
|
+
<p-drawer [visible]="visible()" position="right" styleClass="w-full! md:w-[420px]!" (onHide)="onHide()" (visibleChange)="visible.set($event)" appendTo="body">
|
|
3806
|
+
<ng-template #header>
|
|
3807
|
+
<div class="flex items-center gap-3">
|
|
3808
|
+
<i class="pi pi-list-check text-xl text-primary-500"></i>
|
|
3809
|
+
<span class="text-surface-900 dark:text-surface-0 font-semibold text-lg">{{ drawerTitle() }}</span>
|
|
3810
|
+
</div>
|
|
3811
|
+
</ng-template>
|
|
3812
|
+
|
|
3813
|
+
<div class="flex flex-col gap-6 p-1">
|
|
3814
|
+
<div class="flex flex-col gap-2">
|
|
3815
|
+
<label for="task-title" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Task Title</label>
|
|
3816
|
+
<input pInputText id="task-title" [(ngModel)]="formData.title" placeholder="Enter task title..." class="w-full" />
|
|
3817
|
+
</div>
|
|
3818
|
+
|
|
3819
|
+
<div class="flex flex-col gap-2">
|
|
3820
|
+
<label for="task-description" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Description</label>
|
|
3821
|
+
<textarea pTextarea id="task-description" [(ngModel)]="formData.description" placeholder="Enter task description..." [rows]="4" class="w-full"></textarea>
|
|
3822
|
+
</div>
|
|
3823
|
+
|
|
3824
|
+
<div class="flex flex-col gap-2">
|
|
3825
|
+
<label for="task-status" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Status</label>
|
|
3826
|
+
<p-select id="task-status" [(ngModel)]="formData.status" [options]="statusOptions" optionLabel="label" optionValue="value" placeholder="Select status" styleClass="w-full" />
|
|
3827
|
+
</div>
|
|
3828
|
+
|
|
3829
|
+
<p-divider styleClass="my-2" />
|
|
3830
|
+
|
|
3831
|
+
<div class="flex flex-col gap-2">
|
|
3832
|
+
<label for="start-date" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Start Date</label>
|
|
3833
|
+
<p-datepicker id="start-date" [(ngModel)]="formData.startDate" dateFormat="dd.mm.yy" placeholder="Select start date" inputStyleClass="w-full" />
|
|
3834
|
+
</div>
|
|
3835
|
+
|
|
3836
|
+
<div class="flex flex-col gap-2">
|
|
3837
|
+
<label for="end-date" class="text-surface-900 dark:text-surface-0 font-medium text-sm">End Date</label>
|
|
3838
|
+
<p-datepicker id="end-date" [(ngModel)]="formData.endDate" dateFormat="dd.mm.yy" placeholder="Select end date" inputStyleClass="w-full" />
|
|
3839
|
+
</div>
|
|
3840
|
+
|
|
3841
|
+
<p-divider styleClass="my-2" />
|
|
3842
|
+
|
|
3843
|
+
<div class="flex flex-col gap-2">
|
|
3844
|
+
<label for="team-members" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Team Members</label>
|
|
3845
|
+
<p-autocomplete
|
|
3846
|
+
id="team-members"
|
|
3847
|
+
[(ngModel)]="formData.members"
|
|
3848
|
+
[suggestions]="filteredMembers"
|
|
3849
|
+
optionLabel="name"
|
|
3850
|
+
[multiple]="true"
|
|
3851
|
+
placeholder="Search team members..."
|
|
3852
|
+
(completeMethod)="filterMembers($event)"
|
|
3853
|
+
styleClass="w-full"
|
|
3854
|
+
>
|
|
3855
|
+
<ng-template #selecteditem let-value>
|
|
3856
|
+
<div class="flex items-center gap-2 bg-surface-50 dark:bg-surface-900 px-2 py-1 rounded">
|
|
3857
|
+
<p-avatar [image]="'demo/images/avatar/' + value.image" shape="circle" styleClass="w-5 h-5 border border-surface-200 dark:border-surface-700" />
|
|
3858
|
+
</div>
|
|
3859
|
+
</ng-template>
|
|
3860
|
+
<ng-template #item let-option>
|
|
3861
|
+
<div class="flex items-center gap-3">
|
|
3862
|
+
<p-avatar [image]="'demo/images/avatar/' + option.image" shape="circle" styleClass="w-8 h-8 border border-surface-200 dark:border-surface-700" />
|
|
3863
|
+
<span class="text-surface-900 dark:text-surface-0 font-medium">{{ option.name }}</span>
|
|
3864
|
+
</div>
|
|
3865
|
+
</ng-template>
|
|
3866
|
+
</p-autocomplete>
|
|
3867
|
+
</div>
|
|
3868
|
+
</div>
|
|
3869
|
+
|
|
3870
|
+
<ng-template #footer>
|
|
3871
|
+
<div class="flex justify-end gap-3 pt-4 border-t border-surface-200 dark:border-surface-700">
|
|
3872
|
+
<p-button label="Cancel" icon="pi pi-times" [outlined]="true" severity="secondary" (onClick)="handleCancel()" styleClass="flex-1" />
|
|
3873
|
+
<p-button [label]="mode() === 'create' ? 'Create Task' : 'Update Task'" [icon]="mode() === 'create' ? 'pi pi-plus' : 'pi pi-check'" (onClick)="handleSave()" styleClass="flex-1" />
|
|
3874
|
+
</div>
|
|
3875
|
+
</ng-template>
|
|
3876
|
+
</p-drawer>
|
|
3877
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2$1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i4.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i5$2.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i7$2.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: AutoCompleteModule }, { kind: "component", type: i8$2.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "minQueryLength", "delay", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "addOnTab", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "addOnBlur", "separator", "appendTo", "motionOptions"], outputs: ["completeMethod", "onSelect", "onUnselect", "onAdd", "onFocus", "onBlur", "onDropdownClick", "onClear", "onInputKeydown", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i9.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3878
|
+
}
|
|
3879
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: TaskDrawerComponent, decorators: [{
|
|
3880
|
+
type: Component,
|
|
3881
|
+
args: [{
|
|
3882
|
+
selector: 'ux-task-drawer',
|
|
3883
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3884
|
+
imports: [FormsModule, ButtonModule, DrawerModule, InputTextModule, TextareaModule, SelectModule, DatePickerModule, AutoCompleteModule, DividerModule, AvatarModule],
|
|
3885
|
+
host: { class: 'ux-task-drawer' },
|
|
3886
|
+
template: `
|
|
3887
|
+
<p-drawer [visible]="visible()" position="right" styleClass="w-full! md:w-[420px]!" (onHide)="onHide()" (visibleChange)="visible.set($event)" appendTo="body">
|
|
3888
|
+
<ng-template #header>
|
|
3889
|
+
<div class="flex items-center gap-3">
|
|
3890
|
+
<i class="pi pi-list-check text-xl text-primary-500"></i>
|
|
3891
|
+
<span class="text-surface-900 dark:text-surface-0 font-semibold text-lg">{{ drawerTitle() }}</span>
|
|
3892
|
+
</div>
|
|
3893
|
+
</ng-template>
|
|
3894
|
+
|
|
3895
|
+
<div class="flex flex-col gap-6 p-1">
|
|
3896
|
+
<div class="flex flex-col gap-2">
|
|
3897
|
+
<label for="task-title" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Task Title</label>
|
|
3898
|
+
<input pInputText id="task-title" [(ngModel)]="formData.title" placeholder="Enter task title..." class="w-full" />
|
|
3899
|
+
</div>
|
|
3900
|
+
|
|
3901
|
+
<div class="flex flex-col gap-2">
|
|
3902
|
+
<label for="task-description" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Description</label>
|
|
3903
|
+
<textarea pTextarea id="task-description" [(ngModel)]="formData.description" placeholder="Enter task description..." [rows]="4" class="w-full"></textarea>
|
|
3904
|
+
</div>
|
|
3905
|
+
|
|
3906
|
+
<div class="flex flex-col gap-2">
|
|
3907
|
+
<label for="task-status" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Status</label>
|
|
3908
|
+
<p-select id="task-status" [(ngModel)]="formData.status" [options]="statusOptions" optionLabel="label" optionValue="value" placeholder="Select status" styleClass="w-full" />
|
|
3909
|
+
</div>
|
|
3910
|
+
|
|
3911
|
+
<p-divider styleClass="my-2" />
|
|
3912
|
+
|
|
3913
|
+
<div class="flex flex-col gap-2">
|
|
3914
|
+
<label for="start-date" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Start Date</label>
|
|
3915
|
+
<p-datepicker id="start-date" [(ngModel)]="formData.startDate" dateFormat="dd.mm.yy" placeholder="Select start date" inputStyleClass="w-full" />
|
|
3916
|
+
</div>
|
|
3917
|
+
|
|
3918
|
+
<div class="flex flex-col gap-2">
|
|
3919
|
+
<label for="end-date" class="text-surface-900 dark:text-surface-0 font-medium text-sm">End Date</label>
|
|
3920
|
+
<p-datepicker id="end-date" [(ngModel)]="formData.endDate" dateFormat="dd.mm.yy" placeholder="Select end date" inputStyleClass="w-full" />
|
|
3921
|
+
</div>
|
|
3922
|
+
|
|
3923
|
+
<p-divider styleClass="my-2" />
|
|
3924
|
+
|
|
3925
|
+
<div class="flex flex-col gap-2">
|
|
3926
|
+
<label for="team-members" class="text-surface-900 dark:text-surface-0 font-medium text-sm">Team Members</label>
|
|
3927
|
+
<p-autocomplete
|
|
3928
|
+
id="team-members"
|
|
3929
|
+
[(ngModel)]="formData.members"
|
|
3930
|
+
[suggestions]="filteredMembers"
|
|
3931
|
+
optionLabel="name"
|
|
3932
|
+
[multiple]="true"
|
|
3933
|
+
placeholder="Search team members..."
|
|
3934
|
+
(completeMethod)="filterMembers($event)"
|
|
3935
|
+
styleClass="w-full"
|
|
3936
|
+
>
|
|
3937
|
+
<ng-template #selecteditem let-value>
|
|
3938
|
+
<div class="flex items-center gap-2 bg-surface-50 dark:bg-surface-900 px-2 py-1 rounded">
|
|
3939
|
+
<p-avatar [image]="'demo/images/avatar/' + value.image" shape="circle" styleClass="w-5 h-5 border border-surface-200 dark:border-surface-700" />
|
|
3940
|
+
</div>
|
|
3941
|
+
</ng-template>
|
|
3942
|
+
<ng-template #item let-option>
|
|
3943
|
+
<div class="flex items-center gap-3">
|
|
3944
|
+
<p-avatar [image]="'demo/images/avatar/' + option.image" shape="circle" styleClass="w-8 h-8 border border-surface-200 dark:border-surface-700" />
|
|
3945
|
+
<span class="text-surface-900 dark:text-surface-0 font-medium">{{ option.name }}</span>
|
|
3946
|
+
</div>
|
|
3947
|
+
</ng-template>
|
|
3948
|
+
</p-autocomplete>
|
|
3949
|
+
</div>
|
|
3950
|
+
</div>
|
|
3951
|
+
|
|
3952
|
+
<ng-template #footer>
|
|
3953
|
+
<div class="flex justify-end gap-3 pt-4 border-t border-surface-200 dark:border-surface-700">
|
|
3954
|
+
<p-button label="Cancel" icon="pi pi-times" [outlined]="true" severity="secondary" (onClick)="handleCancel()" styleClass="flex-1" />
|
|
3955
|
+
<p-button [label]="mode() === 'create' ? 'Create Task' : 'Update Task'" [icon]="mode() === 'create' ? 'pi pi-plus' : 'pi pi-check'" (onClick)="handleSave()" styleClass="flex-1" />
|
|
3956
|
+
</div>
|
|
3957
|
+
</ng-template>
|
|
3958
|
+
</p-drawer>
|
|
3959
|
+
`
|
|
3960
|
+
}]
|
|
3961
|
+
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }, { type: i0.Output, args: ["visibleChange"] }], task: [{ type: i0.Input, args: [{ isSignal: true, alias: "task", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], availableMembers: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableMembers", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], cancel: [{ type: i0.Output, args: ["cancel"] }] } });
|
|
3962
|
+
|
|
3005
3963
|
/*
|
|
3006
3964
|
* Public API Surface of @unopsitg/ux
|
|
3007
3965
|
*/
|
|
@@ -3010,5 +3968,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
3010
3968
|
* Generated bundle index. Do not edit.
|
|
3011
3969
|
*/
|
|
3012
3970
|
|
|
3013
|
-
export { AiCardBgComponent, AiInsightsCardComponent, AppBreadcrumb, AppConfigurator, AppFooter, AppLayout, AppMenu, AppMenuitem, AppRightMenu, AppSearch, AppSidebar, AppTopbar, AuthLayout, BrandContrast, BrandCrisp, BrandSoft, DetailLayoutComponent, DetailTabDirective, LayoutService, MENU_MODEL, SIDEBAR_LOGO, TOPBAR_MOBILE_LOGO, brandPresets, brandPrimitives };
|
|
3971
|
+
export { AiCardBgComponent, AiInsightsCardComponent, AppBreadcrumb, AppConfigurator, AppFooter, AppLayout, AppMenu, AppMenuitem, AppRightMenu, AppSearch, AppSidebar, AppTopbar, AuthLayout, BrandContrast, BrandCrisp, BrandSoft, CompletionStepsComponent, DetailLayoutComponent, DetailTabDirective, DocumentsCardComponent, FooterMainComponent, FooterService, LayoutService, MENU_MODEL, PillTabsComponent, SIDEBAR_LOGO, TOPBAR_MOBILE_LOGO, TaskDrawerComponent, UxSelectComponent, brandPresets, brandPrimitives };
|
|
3014
3972
|
//# sourceMappingURL=unopsitg-ux.mjs.map
|