@corp-products/ui-components 3.2.8 → 3.2.9
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/ng-package.json +7 -0
- package/package.json +22 -36
- package/src/enums/date-formatter.ts +21 -0
- package/src/helper/date-handler.ts +142 -0
- package/src/lib/app-accordion/app-accordion.component.html +15 -0
- package/src/lib/app-accordion/app-accordion.component.scss +0 -0
- package/src/lib/app-accordion/app-accordion.component.spec.ts +21 -0
- package/src/lib/app-accordion/app-accordion.component.ts +21 -0
- package/src/lib/app-accordion/index.ts +2 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.component.html +7 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.component.scss +25 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.component.ts +140 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.interface.ts +15 -0
- package/src/lib/app-button/app-button.component.html +7 -0
- package/src/lib/app-button/app-button.component.scss +0 -0
- package/src/lib/app-button/app-button.component.ts +14 -0
- package/src/lib/app-button/app-button.ts +15 -0
- package/src/lib/app-button/index.ts +2 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.html +22 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.scss +39 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.spec.ts +21 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.ts +43 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.ts +17 -0
- package/src/lib/app-dropdown-menu/index.ts +2 -0
- package/src/lib/app-dropdown-menu/menu-popup.pipe.ts +18 -0
- package/src/lib/app-header/app-header.component.html +26 -0
- package/src/lib/app-header/app-header.component.scss +0 -0
- package/src/lib/app-header/app-header.component.ts +43 -0
- package/src/lib/app-side-menu/app-side-menu.component.html +20 -0
- package/src/lib/app-side-menu/app-side-menu.component.ts +28 -0
- package/src/lib/app-side-menu/routes-names.ts +28 -0
- package/src/lib/app-side-menu/side-menu-items.ts +45 -0
- package/src/lib/app-side-menu/side-menu.ts +12 -0
- package/src/lib/app-tabs/app-tab.interface.ts +27 -0
- package/src/lib/app-tabs/app-tabs.component.html +37 -0
- package/src/lib/app-tabs/app-tabs.component.scss +103 -0
- package/src/lib/app-tabs/app-tabs.component.spec.ts +21 -0
- package/src/lib/app-tabs/app-tabs.component.ts +67 -0
- package/src/lib/app-tabs/index.ts +2 -0
- package/src/lib/bottom-sheet/bottom-sheet.component.html +18 -0
- package/src/lib/bottom-sheet/bottom-sheet.component.scss +31 -0
- package/src/lib/bottom-sheet/bottom-sheet.component.ts +26 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.html +37 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.scss +0 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.spec.ts +22 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.ts +64 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.interface.ts +13 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.service.ts +34 -0
- package/src/lib/dual-calender/date-picker-switcher/date-picker-switcher.component.html +27 -0
- package/src/lib/dual-calender/date-picker-switcher/date-picker-switcher.component.scss +22 -0
- package/src/lib/dual-calender/date-picker-switcher/date-picker-switcher.component.ts +64 -0
- package/src/lib/dual-calender/dual-calendar.component.html +31 -0
- package/src/lib/dual-calender/dual-calendar.component.scss +229 -0
- package/src/lib/dual-calender/dual-calendar.component.ts +107 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.html +10 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.scss +0 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.spec.ts +21 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.ts +59 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.html +10 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.scss +0 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.spec.ts +21 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.ts +59 -0
- package/src/lib/dual-calender/services/gregorian-i18n.service.ts +123 -0
- package/src/lib/dual-calender/services/islamic-i18n.service.ts +119 -0
- package/src/lib/dual-calender/utils/date-i18n.utils.ts +58 -0
- package/src/lib/dynamic-form/dynamic-form.component.html +86 -0
- package/src/lib/dynamic-form/dynamic-form.component.scss +0 -0
- package/src/lib/dynamic-form/dynamic-form.component.spec.ts +21 -0
- package/src/lib/dynamic-form/dynamic-form.component.ts +58 -0
- package/src/lib/dynamic-form/dynamic-form.interface.ts +94 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.component.html +32 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.component.scss +3 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.component.ts +82 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.config.ts +31 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.service.ts +41 -0
- package/src/lib/form-components/@utils/form-utils.ts +12 -0
- package/src/lib/form-components/@utils/validations/error-keys.enum.ts +24 -0
- package/src/lib/form-components/@utils/validations/form-validation.service.ts +68 -0
- package/src/lib/form-components/@utils/validations/index.ts +3 -0
- package/src/lib/form-components/@utils/validations/validation-message.pipe.ts +24 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.html +35 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.scss +7 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.spec.ts +21 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.ts +57 -0
- package/src/lib/form-components/components/base-input.component.ts +35 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.html +41 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.scss +16 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.spec.ts +21 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.ts +54 -0
- package/src/lib/form-components/components/input/input.component.html +63 -0
- package/src/lib/form-components/components/input/input.component.scss +41 -0
- package/src/lib/form-components/components/input/input.component.spec.ts +21 -0
- package/src/lib/form-components/components/input/input.component.ts +45 -0
- package/src/lib/form-components/components/select/select.component.html +111 -0
- package/src/lib/form-components/components/select/select.component.scss +43 -0
- package/src/lib/form-components/components/select/select.component.spec.ts +21 -0
- package/src/lib/form-components/components/select/select.component.ts +56 -0
- package/src/lib/form-components/components/select-button/select-button.component.html +21 -0
- package/src/lib/form-components/components/select-button/select-button.component.scss +0 -0
- package/src/lib/form-components/components/select-button/select-button.component.spec.ts +21 -0
- package/src/lib/form-components/components/select-button/select-button.component.ts +22 -0
- package/src/lib/form-components/components/switcher/switch.component.html +5 -0
- package/src/lib/form-components/components/switcher/switch.component.scss +0 -0
- package/src/lib/form-components/components/switcher/switch.component.spec.ts +21 -0
- package/src/lib/form-components/components/switcher/switch.component.ts +25 -0
- package/src/lib/form-components/index.ts +9 -0
- package/src/lib/form-components/interfaces/index.ts +1 -0
- package/src/lib/form-components/interfaces/label-value.ts +4 -0
- package/src/lib/ico-moon-icon/ico-moon-icon.component.ts +23 -0
- package/src/lib/read-more/read-more.component.html +17 -0
- package/src/lib/read-more/read-more.component.scss +0 -0
- package/src/lib/read-more/read-more.component.spec.ts +21 -0
- package/src/lib/read-more/read-more.component.ts +21 -0
- package/src/lib/side-bar/side-bar.component.html +24 -0
- package/src/lib/side-bar/side-bar.component.scss +22 -0
- package/src/lib/side-bar/side-bar.component.spec.ts +21 -0
- package/src/lib/side-bar/side-bar.component.ts +33 -0
- package/src/lib/side-bar-dynamic/data-injector.pipe.ts +15 -0
- package/src/lib/side-bar-dynamic/dynamic-sidebar.service.ts +116 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.html +42 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.scss +5 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.spec.ts +21 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.ts +37 -0
- package/src/lib/side-bar-dynamic/side-bar-utils.ts +30 -0
- package/src/lib/side-bar-dynamic/sidebar-config.ts +48 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.html +20 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.scss +0 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.spec.ts +21 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.ts +21 -0
- package/src/lib/user-info/user-info.component.html +10 -0
- package/src/lib/user-info/user-info.component.ts +11 -0
- package/src/public-api.ts +26 -0
- package/tsconfig.lib.json +18 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +14 -0
- package/fesm2022/corp-products-ui-components.mjs +0 -1416
- package/fesm2022/corp-products-ui-components.mjs.map +0 -1
- package/index.d.ts +0 -625
package/ng-package.json
ADDED
package/package.json
CHANGED
|
@@ -1,36 +1,22 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@corp-products/ui-components",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"author": "shireen Omar",
|
|
5
|
-
"description": "shared UI components across our apps",
|
|
6
|
-
"peerDependencies": {
|
|
7
|
-
"@angular/common": ">=17.0.0 <21.0.0",
|
|
8
|
-
"@angular/core": ">=17.0.0 <21.0.0",
|
|
9
|
-
"@angular/animations": ">=17.0.0 <21.0.0",
|
|
10
|
-
"primeng": ">=17.0.0 <21.0.0",
|
|
11
|
-
"@ngx-translate/core": ">=15.0.0 <18.0.0"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
"angular",
|
|
15
|
-
"library"
|
|
16
|
-
],
|
|
17
|
-
"publishConfig": {
|
|
18
|
-
"access": "public"
|
|
19
|
-
},
|
|
20
|
-
"license": "MIT",
|
|
21
|
-
"sideEffects": false
|
|
22
|
-
|
|
23
|
-
"typings": "index.d.ts",
|
|
24
|
-
"exports": {
|
|
25
|
-
"./package.json": {
|
|
26
|
-
"default": "./package.json"
|
|
27
|
-
},
|
|
28
|
-
".": {
|
|
29
|
-
"types": "./index.d.ts",
|
|
30
|
-
"default": "./fesm2022/corp-products-ui-components.mjs"
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"tslib": "^2.3.0"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@corp-products/ui-components",
|
|
3
|
+
"version": "3.2.9",
|
|
4
|
+
"author": "shireen Omar",
|
|
5
|
+
"description": "shared UI components across our apps",
|
|
6
|
+
"peerDependencies": {
|
|
7
|
+
"@angular/common": ">=17.0.0 <21.0.0",
|
|
8
|
+
"@angular/core": ">=17.0.0 <21.0.0",
|
|
9
|
+
"@angular/animations": ">=17.0.0 <21.0.0",
|
|
10
|
+
"primeng": ">=17.0.0 <21.0.0",
|
|
11
|
+
"@ngx-translate/core": ">=15.0.0 <18.0.0"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"angular",
|
|
15
|
+
"library"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"sideEffects": false
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export enum DateFormats {
|
|
2
|
+
DATE_UTC = "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
|
3
|
+
DATE_TIME_FULL = "dd MMMM yyyy - hh:mm a",
|
|
4
|
+
DATE_TIME_SEMI = "yyyy/MM/dd - hh:mm a",
|
|
5
|
+
DATE = "dd MMMM yyyy",
|
|
6
|
+
DATE_TWO = "yyyy/MM/dd",
|
|
7
|
+
DAY_ONLY = "cccc",
|
|
8
|
+
TIME_ONLY = "hh:mm",
|
|
9
|
+
AM_PM = "a",
|
|
10
|
+
TIME = 'hh:mm a',
|
|
11
|
+
YEAR = 'yyyy',
|
|
12
|
+
MONTH = "MM",
|
|
13
|
+
DAY = "dd"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export enum TimeFormats {
|
|
17
|
+
HOURS12Format = "hh",
|
|
18
|
+
HOURS24Format = "HH",
|
|
19
|
+
MINUTES = "mm",
|
|
20
|
+
SECONDS = "ss"
|
|
21
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { DateTime, DateTimeMaybeValid, DateTimeOptions, LocaleOptions } from 'luxon';
|
|
2
|
+
import { DateFormats, TimeFormats } from '../enums/date-formatter';
|
|
3
|
+
|
|
4
|
+
export class DateHandler {
|
|
5
|
+
/**
|
|
6
|
+
* @param date `ISO string`
|
|
7
|
+
* @param format `format string`
|
|
8
|
+
* @param localeOptions `opts to override the configuration options on this DateTime` - default is system's locale
|
|
9
|
+
* @param isConvertedToUTC
|
|
10
|
+
* @description Returns a string representation of this DateTime formatted according to the specified format string.
|
|
11
|
+
*/
|
|
12
|
+
static formatDate(
|
|
13
|
+
date: string,
|
|
14
|
+
format: DateFormats = DateFormats.DATE_TIME_FULL,
|
|
15
|
+
localeOptions?: LocaleOptions,
|
|
16
|
+
isConvertedToUTC?: boolean
|
|
17
|
+
): string {
|
|
18
|
+
if (!date) {
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
return this.getDateTimeFromISO(date, isConvertedToUTC ? { zone: 'utc' } : {})
|
|
22
|
+
?.toFormat(format, localeOptions)
|
|
23
|
+
.toLocaleString();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static getDateTimeFromISO(
|
|
27
|
+
date: string,
|
|
28
|
+
dateTimeOptions: DateTimeOptions = {}
|
|
29
|
+
): DateTime<true> | DateTime<false> {
|
|
30
|
+
return DateTime.fromISO(date, dateTimeOptions);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static getJSDateFromISO(date: string): Date {
|
|
34
|
+
const dateTime = this.getDateTimeFromISO(date, { zone: 'utc' }); // Ensure it's in UTC
|
|
35
|
+
if (!dateTime.isValid) {
|
|
36
|
+
throw new Error('Invalid date format');
|
|
37
|
+
}
|
|
38
|
+
return new Date(
|
|
39
|
+
dateTime.year,
|
|
40
|
+
dateTime.month - 1,
|
|
41
|
+
dateTime.day,
|
|
42
|
+
dateTime.hour,
|
|
43
|
+
dateTime.minute,
|
|
44
|
+
dateTime.second,
|
|
45
|
+
dateTime.millisecond
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static getUTCDateTime(date: string): string {
|
|
50
|
+
return this.getDateTimeFromISO(date)?.toUTC()?.toISO() as string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static getUTCDateTimeFromJsDate(date: Date): string {
|
|
54
|
+
return this.getDateFromJsDate(new Date(date))?.toUTC()?.toISO() as string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static getCurrentUTCDateTime(): string {
|
|
58
|
+
return DateTime.utc().toISO();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static getDateFromJsDate(date: Date): DateTimeMaybeValid {
|
|
62
|
+
return DateTime.fromJSDate(date);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static checkIfTwoDatesEqual(startDate: Date, endDate: Date): boolean {
|
|
66
|
+
return DateTime.fromJSDate(startDate).equals(DateTime.fromJSDate(endDate));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static getCurrentDateTime() {
|
|
70
|
+
return DateTime;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static constructDateTime(date: Date, time: Date, isConvertedToUTC?: boolean) {
|
|
74
|
+
const dateYear = this.getPartialDateOrTime(date, DateFormats.YEAR);
|
|
75
|
+
const dateMonth = this.getPartialDateOrTime(date, DateFormats.MONTH);
|
|
76
|
+
const dateDay = this.getPartialDateOrTime(date, DateFormats.DAY);
|
|
77
|
+
|
|
78
|
+
const dateHours = this.getPartialDateOrTime(time, TimeFormats.HOURS24Format, isConvertedToUTC);
|
|
79
|
+
const dateMinutes = this.getPartialDateOrTime(time, TimeFormats.MINUTES, isConvertedToUTC);
|
|
80
|
+
const dateSeconds = this.getPartialDateOrTime(time, TimeFormats.SECONDS, isConvertedToUTC);
|
|
81
|
+
|
|
82
|
+
return DateTime.utc(+dateYear, +dateMonth, +dateDay, +dateHours, +dateMinutes, +dateSeconds)
|
|
83
|
+
.toUTC()
|
|
84
|
+
.toISO();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static getPartialDateOrTime(
|
|
88
|
+
date: Date,
|
|
89
|
+
format: TimeFormats | DateFormats,
|
|
90
|
+
isConvertedToUTC?: boolean
|
|
91
|
+
) {
|
|
92
|
+
return DateTime.fromJSDate(date, isConvertedToUTC ? { zone: 'utc' } : {}).toFormat(format);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static getValueFromJSDate(date: Date, unit: 'year' | 'month' | 'day'): number {
|
|
96
|
+
const dt = DateTime.fromJSDate(date);
|
|
97
|
+
switch (unit) {
|
|
98
|
+
case 'year':
|
|
99
|
+
return dt.year;
|
|
100
|
+
case 'month':
|
|
101
|
+
return dt.month;
|
|
102
|
+
case 'day':
|
|
103
|
+
return dt.day;
|
|
104
|
+
default:
|
|
105
|
+
throw new Error(`Unsupported unit: ${unit}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static getValueFromLocalDateTime(unit: 'hour' | 'minute' | 'second'): number {
|
|
110
|
+
const now = DateTime.local();
|
|
111
|
+
switch (unit) {
|
|
112
|
+
case 'hour':
|
|
113
|
+
return now.hour;
|
|
114
|
+
case 'minute':
|
|
115
|
+
return now.minute;
|
|
116
|
+
case 'second':
|
|
117
|
+
return now.second;
|
|
118
|
+
default:
|
|
119
|
+
throw new Error(`Unsupported unit: ${unit}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static getISODateTime(date: Date): string {
|
|
124
|
+
if (!date) {
|
|
125
|
+
throw new Error('Invalid date: date is null or undefined');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Create a DateTime instance from the JS Date, preserving the date parts
|
|
129
|
+
// but using local time for the time parts
|
|
130
|
+
const dt = DateTime.local().set({
|
|
131
|
+
year: DateTime.fromJSDate(date).year,
|
|
132
|
+
month: DateTime.fromJSDate(date).month,
|
|
133
|
+
day: DateTime.fromJSDate(date).day,
|
|
134
|
+
hour: DateTime.local().hour,
|
|
135
|
+
minute: DateTime.local().minute,
|
|
136
|
+
second: DateTime.local().second,
|
|
137
|
+
millisecond: DateTime.local().millisecond,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return dt.toISO() as string;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<p-accordion value="0">
|
|
2
|
+
<p-accordion-panel value="0" [class.!border-0]="!accordionPanelBorder">
|
|
3
|
+
<p-accordion-header>
|
|
4
|
+
<span class="flex items-center gap-2 w-full">
|
|
5
|
+
<app-ico-moon-card [iconClass]="'text-[24px] text-secondary'" [iconName]="'font-icon-'+iconName" />
|
|
6
|
+
<span class="font-bold whitespace-nowrap">{{title}}</span>
|
|
7
|
+
</span>
|
|
8
|
+
</p-accordion-header>
|
|
9
|
+
<p-accordion-content>
|
|
10
|
+
<div [ngClass]="{'border-t-2 border-gray-light pt-2': contentBorderTop, }">
|
|
11
|
+
<ng-content></ng-content>
|
|
12
|
+
</div>
|
|
13
|
+
</p-accordion-content>
|
|
14
|
+
</p-accordion-panel>
|
|
15
|
+
</p-accordion>
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
|
2
|
+
import { AppAccordionComponent } from "./app-accordion.component";
|
|
3
|
+
|
|
4
|
+
describe("HeaderCardComponent", () => {
|
|
5
|
+
let component: AppAccordionComponent;
|
|
6
|
+
let fixture: ComponentFixture<AppAccordionComponent>;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
await TestBed.configureTestingModule({
|
|
10
|
+
imports: [AppAccordionComponent]
|
|
11
|
+
}).compileComponents();
|
|
12
|
+
|
|
13
|
+
fixture = TestBed.createComponent(AppAccordionComponent);
|
|
14
|
+
component = fixture.componentInstance;
|
|
15
|
+
fixture.detectChanges();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should create", () => {
|
|
19
|
+
expect(component).toBeTruthy();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Component, Input } from "@angular/core";
|
|
2
|
+
import { CommonModule } from "@angular/common";
|
|
3
|
+
import { IcoMoonIconComponent } from '../ico-moon-icon/ico-moon-icon.component';
|
|
4
|
+
import { AccordionModule } from 'primeng/accordion';
|
|
5
|
+
import { DividerModule } from 'primeng/divider';
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: "app-accordion",
|
|
9
|
+
standalone: true,
|
|
10
|
+
imports: [CommonModule, DividerModule, AccordionModule, IcoMoonIconComponent],
|
|
11
|
+
templateUrl: "./app-accordion.component.html",
|
|
12
|
+
styleUrl: "./app-accordion.component.scss"
|
|
13
|
+
})
|
|
14
|
+
export class AppAccordionComponent {
|
|
15
|
+
@Input() iconName!: string;
|
|
16
|
+
@Input() iconClass!: string;
|
|
17
|
+
@Input() iconPathCount = 0;
|
|
18
|
+
@Input({required: true}) title!: string;
|
|
19
|
+
@Input() contentBorderTop: boolean = true;
|
|
20
|
+
@Input() accordionPanelBorder: boolean = true;
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.p-breadcrumb-list {
|
|
2
|
+
li:first-child a {
|
|
3
|
+
@apply text-secondary;
|
|
4
|
+
}
|
|
5
|
+
.p-breadcrumb-separator {
|
|
6
|
+
transform: scale(0.7);
|
|
7
|
+
display: none;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
.p-breadcrumb-item:not(:last-of-type) {
|
|
11
|
+
.p-breadcrumb-item-link {
|
|
12
|
+
padding: 0 4px;
|
|
13
|
+
}
|
|
14
|
+
.p-breadcrumb-item-label {
|
|
15
|
+
@apply text-light_red relative;
|
|
16
|
+
&:hover {
|
|
17
|
+
@apply text-light_red;
|
|
18
|
+
}
|
|
19
|
+
&::before {
|
|
20
|
+
content: '/';
|
|
21
|
+
@apply inline-block absolute text-gray-900;
|
|
22
|
+
inset-inline-end: -9px;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
|
3
|
+
import { ActivatedRoute, NavigationEnd, Router, RouterModule } from '@angular/router';
|
|
4
|
+
import { MenuItem } from 'primeng/api';
|
|
5
|
+
import { Breadcrumb } from 'primeng/breadcrumb';
|
|
6
|
+
import { filter } from 'rxjs';
|
|
7
|
+
import { BreadCrumbExtraData, BreadcrumbItem } from './app-breadcrumb.interface';
|
|
8
|
+
|
|
9
|
+
@Component({
|
|
10
|
+
selector: 'app-breadcrumb',
|
|
11
|
+
templateUrl: './app-breadcrumb.component.html',
|
|
12
|
+
styleUrl: './app-breadcrumb.component.scss',
|
|
13
|
+
standalone: true,
|
|
14
|
+
imports: [CommonModule, Breadcrumb, RouterModule],
|
|
15
|
+
encapsulation: ViewEncapsulation.None,
|
|
16
|
+
})
|
|
17
|
+
export class AppBreadcrumbComponent implements OnInit {
|
|
18
|
+
@Input() items: BreadcrumbItem[] | undefined;
|
|
19
|
+
isShown: boolean;
|
|
20
|
+
|
|
21
|
+
constructor(private activatedRoute: ActivatedRoute, private router: Router) {}
|
|
22
|
+
|
|
23
|
+
ngOnInit(): void {
|
|
24
|
+
if (this.items) {
|
|
25
|
+
this.isShown = true;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((e) => {
|
|
29
|
+
// remove duplicates
|
|
30
|
+
this.items = (this._createBreadcrumbs(this.activatedRoute.root) as BreadcrumbItem[]).filter(
|
|
31
|
+
(item, index, self) =>
|
|
32
|
+
index ===
|
|
33
|
+
self.findIndex((t) => t.label === item.label && t.routerLink === item.routerLink)
|
|
34
|
+
);
|
|
35
|
+
this._checkHiddenBreadcrumb();
|
|
36
|
+
this._checkEmpty();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private _checkHiddenBreadcrumb() {
|
|
41
|
+
const activeBreadcrumb = this.items?.find((item) => {
|
|
42
|
+
return item.routerLink === this.router.url;
|
|
43
|
+
});
|
|
44
|
+
this.isShown = !!activeBreadcrumb?.isShown;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private _createBreadcrumbs(
|
|
48
|
+
activatedRoute: ActivatedRoute,
|
|
49
|
+
routerLink = '',
|
|
50
|
+
breadcrumbs: MenuItem[] = []
|
|
51
|
+
): any {
|
|
52
|
+
const children: ActivatedRoute[] = activatedRoute.children;
|
|
53
|
+
|
|
54
|
+
if (children.length === 0) {
|
|
55
|
+
return breadcrumbs;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const child of children) {
|
|
59
|
+
const routeURL: string = child.snapshot.url.map((segment) => segment.path).join('/');
|
|
60
|
+
if (routeURL !== '') {
|
|
61
|
+
routerLink += `/${routeURL}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let label = child.snapshot.data['breadcrumb'];
|
|
65
|
+
const notClickableBreadcrumb = !!child.snapshot.data['notClickableBreadcrumb'];
|
|
66
|
+
const isShown = !!child.snapshot.data['isShown'];
|
|
67
|
+
const extraBreadcrumbs: BreadCrumbExtraData[] = child.snapshot.data['extraBreadcrumbs'] || [];
|
|
68
|
+
if (!(typeof label === 'undefined' || label === null)) {
|
|
69
|
+
const data = activatedRoute.snapshot.firstChild?.data || {};
|
|
70
|
+
// Resolve dynamic breadcrumb label
|
|
71
|
+
if (label && label.startsWith('[') && label.endsWith(']')) {
|
|
72
|
+
label = this._getRecursiveKey(data, label.slice(1, -1).split('.'));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Resolve dynamic URL parts
|
|
76
|
+
const resolveDynamicUrl = (route: string): string => {
|
|
77
|
+
return route.replace(
|
|
78
|
+
/\[([^\]]+)]/g,
|
|
79
|
+
(_, key) => this._getRecursiveKey(data, key.split('.')) || ''
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const mainBreadcrumb: MenuItem = {
|
|
84
|
+
label,
|
|
85
|
+
routerLink,
|
|
86
|
+
data,
|
|
87
|
+
notClickableBreadcrumb,
|
|
88
|
+
isShown,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Process extra breadcrumbs
|
|
92
|
+
const beforeBreadcrumbs: MenuItem[] = [];
|
|
93
|
+
const afterBreadcrumbs: MenuItem[] = [];
|
|
94
|
+
|
|
95
|
+
extraBreadcrumbs.forEach((extra) => {
|
|
96
|
+
let extraLabel = extra.label || '';
|
|
97
|
+
if (extraLabel.startsWith('[') && extraLabel.endsWith(']')) {
|
|
98
|
+
extraLabel = this._getRecursiveKey(data, extraLabel.slice(1, -1).split('.'));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const extraUrl = resolveDynamicUrl(extra.routerLink || '');
|
|
102
|
+
|
|
103
|
+
const extraBreadcrumb: MenuItem = { ...extra, label: extraLabel, routerLink: extraUrl };
|
|
104
|
+
|
|
105
|
+
if (extra.position === 'before') {
|
|
106
|
+
beforeBreadcrumbs.push(extraBreadcrumb);
|
|
107
|
+
} else {
|
|
108
|
+
afterBreadcrumbs.push(extraBreadcrumb);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Merge breadcrumbs
|
|
113
|
+
breadcrumbs.push(...beforeBreadcrumbs, mainBreadcrumb, ...afterBreadcrumbs);
|
|
114
|
+
}
|
|
115
|
+
return this._createBreadcrumbs(child, routerLink, breadcrumbs);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private _checkEmpty() {
|
|
120
|
+
if (!this.items) return;
|
|
121
|
+
const lastBreadcrumbVisibility = this.items[this.items.length - 1].isShown;
|
|
122
|
+
this.items = this.items.filter((b) => b.label !== '');
|
|
123
|
+
this.items[this.items.length - 1].isShown = lastBreadcrumbVisibility;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private _getRecursiveKey(obj: Record<string, any>, keys: string[]): any | undefined {
|
|
127
|
+
if (keys.length === 0) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const [currentKey, ...remainingKeys] = keys;
|
|
132
|
+
if (currentKey in obj) {
|
|
133
|
+
if (remainingKeys.length > 0) {
|
|
134
|
+
return this._getRecursiveKey(obj[currentKey], remainingKeys);
|
|
135
|
+
}
|
|
136
|
+
return obj[currentKey];
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MenuItem } from 'primeng/api';
|
|
2
|
+
|
|
3
|
+
export interface BreadcrumbItem {
|
|
4
|
+
notClickable: boolean;
|
|
5
|
+
label: string;
|
|
6
|
+
routerLink: string;
|
|
7
|
+
isShown: boolean;
|
|
8
|
+
extraBreadcrumbs?: BreadCrumbExtraData[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface BreadCrumbPosition {
|
|
12
|
+
position: 'before' | 'after';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type BreadCrumbExtraData = MenuItem & BreadCrumbPosition;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<p-button (onFocus)="onFocus.emit()" (onBlur)="onBlur.emit()" (onClick)="onClick.emit()" [size]="size"
|
|
2
|
+
[loadingIcon]="loadingIcon" [disabled]="disabled" [iconPos]="iconPos" [icon]="icon" [label]="label"
|
|
3
|
+
[rounded]="rounded" [severity]="severity" [styleClass]="styleClass" [text]="text" [variant]="variant"
|
|
4
|
+
[loading]="loading" [autofocus]="autofocus" [link]="link" [plain]="plain" [raised]="raised"
|
|
5
|
+
[loadingIcon]="loadingIcon" [style]="style" [outlined]="outlined">
|
|
6
|
+
<ng-content></ng-content>
|
|
7
|
+
</p-button>
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { Button, ButtonModule, ButtonStyle } from 'primeng/button';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
imports: [ButtonModule],
|
|
6
|
+
selector: 'app-button',
|
|
7
|
+
standalone: true,
|
|
8
|
+
encapsulation: ViewEncapsulation.None,
|
|
9
|
+
styleUrl: './app-button.component.scss',
|
|
10
|
+
templateUrl: './app-button.component.html',
|
|
11
|
+
providers: [ButtonStyle],
|
|
12
|
+
})
|
|
13
|
+
export class AppButtonComponent extends Button {
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type AppButtonSeverity =
|
|
2
|
+
| 'success'
|
|
3
|
+
| 'info'
|
|
4
|
+
| 'warn'
|
|
5
|
+
| 'danger'
|
|
6
|
+
| 'help'
|
|
7
|
+
| 'primary'
|
|
8
|
+
| 'secondary'
|
|
9
|
+
| 'contrast';
|
|
10
|
+
|
|
11
|
+
export type AppButtonSize = 'large' | 'small';
|
|
12
|
+
|
|
13
|
+
export type AppButtonIconPos = 'left' | 'right' | 'top' | 'bottom';
|
|
14
|
+
|
|
15
|
+
export type AppButtonVariant = 'outlined' | 'text' | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@if (showMenu) {
|
|
2
|
+
<app-button (click)="op.toggle($event)" [class]="buttonClass" [iconPos]="buttonIconPosition" [icon]="buttonIcon"
|
|
3
|
+
[title]="buttonTitle" [styleClass]="buttonStyle" />
|
|
4
|
+
}
|
|
5
|
+
<p-popover #op [styleClass]="popupMenuStyle === 'white' ? 'white-menu' : 'purple-menu'">
|
|
6
|
+
<div class="flex flex-col gap-4 text-sm md:text-xs">
|
|
7
|
+
<ul>
|
|
8
|
+
@for (item of menuItems; track $index) {
|
|
9
|
+
@if (item.show) {
|
|
10
|
+
<li [ngClass]="{'flex-row-reverse': item.iconPosition === 'right'}"
|
|
11
|
+
[class]="'flex justify-between min-w-[130px] gap-3 items-center cursor-pointer text-sm ' + (item.textColor | popupTextColorClass)"
|
|
12
|
+
(click)="onMenuItemClick(item)">
|
|
13
|
+
{{ item.title | translate }}
|
|
14
|
+
@if (item.icon) {
|
|
15
|
+
<i [class]="item.icon"></i>
|
|
16
|
+
}
|
|
17
|
+
</li>
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
</ul>
|
|
21
|
+
</div>
|
|
22
|
+
</p-popover>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.p-popover.p-component {
|
|
2
|
+
box-shadow: none;
|
|
3
|
+
&:is(.purple-menu) {
|
|
4
|
+
@apply bg-primary text-white text-sm mt-2;
|
|
5
|
+
li:not(:last-child) {
|
|
6
|
+
@apply border-b-2 border-purple-700;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
&:is(.white-menu) {
|
|
10
|
+
li:not(:last-child) {
|
|
11
|
+
@apply border-b;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
border-radius: 3px;
|
|
15
|
+
margin-top: 13px;
|
|
16
|
+
&::before, &::after {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
19
|
+
.p-popover-content {
|
|
20
|
+
width: auto;
|
|
21
|
+
min-width: unset;
|
|
22
|
+
|
|
23
|
+
ul {
|
|
24
|
+
li {
|
|
25
|
+
@apply py-3;
|
|
26
|
+
&:hover {
|
|
27
|
+
opacity: 0.7;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
li:first-child {
|
|
31
|
+
@apply pt-0
|
|
32
|
+
}
|
|
33
|
+
li:last-child {
|
|
34
|
+
@apply pb-0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { AppDropdownMenuComponent } from './app-dropdown-menu.component';
|
|
3
|
+
|
|
4
|
+
describe('AppDropdownMenuComponent', () => {
|
|
5
|
+
let component: AppDropdownMenuComponent;
|
|
6
|
+
let fixture: ComponentFixture<AppDropdownMenuComponent>;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
await TestBed.configureTestingModule({
|
|
10
|
+
imports: [AppDropdownMenuComponent],
|
|
11
|
+
}).compileComponents();
|
|
12
|
+
|
|
13
|
+
fixture = TestBed.createComponent(AppDropdownMenuComponent);
|
|
14
|
+
component = fixture.componentInstance;
|
|
15
|
+
fixture.detectChanges();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should create', () => {
|
|
19
|
+
expect(component).toBeTruthy();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {Component, inject, Input, OnInit, ViewEncapsulation} from '@angular/core';
|
|
2
|
+
import { AppButtonComponent } from '../app-button';
|
|
3
|
+
import { Popover } from 'primeng/popover';
|
|
4
|
+
import { DropdownMenuItem } from './app-dropdown-menu';
|
|
5
|
+
import {Router} from '@angular/router';
|
|
6
|
+
import {AppButtonIconPos, AppButtonSeverity} from '../app-button';
|
|
7
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
8
|
+
import {NgClass} from "@angular/common";
|
|
9
|
+
import {MenuPopupTextColorPipe} from "./menu-popup.pipe";
|
|
10
|
+
|
|
11
|
+
@Component({
|
|
12
|
+
selector: "app-dropdown-menu",
|
|
13
|
+
standalone: true,
|
|
14
|
+
imports: [AppButtonComponent, Popover, TranslateModule, NgClass, MenuPopupTextColorPipe],
|
|
15
|
+
templateUrl: "./app-dropdown-menu.component.html",
|
|
16
|
+
styleUrl: "./app-dropdown-menu.component.scss",
|
|
17
|
+
encapsulation: ViewEncapsulation.None
|
|
18
|
+
})
|
|
19
|
+
export class AppDropdownMenuComponent implements OnInit {
|
|
20
|
+
@Input({ required: true }) buttonTitle: string;
|
|
21
|
+
@Input({ required: true }) menuItems: DropdownMenuItem[] = [];
|
|
22
|
+
@Input() popupMenuStyle: "white" | "purple" = "purple";
|
|
23
|
+
@Input() buttonIcon = "font-icon-plus";
|
|
24
|
+
@Input() buttonClass: string;
|
|
25
|
+
@Input() buttonStyle: AppButtonSeverity;
|
|
26
|
+
@Input() buttonIconPosition: AppButtonIconPos = "left";
|
|
27
|
+
router = inject(Router);
|
|
28
|
+
|
|
29
|
+
showMenu: boolean;
|
|
30
|
+
|
|
31
|
+
ngOnInit() {
|
|
32
|
+
this.showMenu = this.menuItems.some((item) => {
|
|
33
|
+
return item.show;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
onMenuItemClick(item: DropdownMenuItem): void {
|
|
37
|
+
if (item.callback) {
|
|
38
|
+
item.callback();
|
|
39
|
+
} else if (item.routerLink) {
|
|
40
|
+
this.router.navigate(Array.isArray(item.routerLink) ? item.routerLink : [item.routerLink], { queryParams: item.queryParams || {} });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|