oip-common 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/oip-common.mjs +4267 -0
- package/fesm2022/oip-common.mjs.map +1 -0
- package/index.d.ts +1028 -0
- package/package.json +17 -5
- package/ng-package.json +0 -19
- package/src/api/FolderModule.ts +0 -124
- package/src/api/Menu.ts +0 -134
- package/src/api/Module.ts +0 -92
- package/src/api/Security.ts +0 -40
- package/src/api/Service.ts +0 -57
- package/src/api/data-contracts.ts +0 -186
- package/src/api/http-client.ts +0 -276
- package/src/components/app-configurator.component.ts +0 -491
- package/src/components/app-floating-configurator.component.ts +0 -47
- package/src/components/app-modules.component.ts +0 -144
- package/src/components/app.layout.component.ts +0 -130
- package/src/components/auth/access/access.component.ts +0 -42
- package/src/components/auth/error/error.component.ts +0 -42
- package/src/components/auth/login/login.component.ts +0 -120
- package/src/components/auth/unauthorized/unauthorized.component.ts +0 -51
- package/src/components/base-module.component.ts +0 -258
- package/src/components/config.component.ts +0 -131
- package/src/components/db-migration/db-migration.component.ts +0 -164
- package/src/components/db-migration.component.ts +0 -155
- package/src/components/footer.component.ts +0 -17
- package/src/components/logo.component.ts +0 -34
- package/src/components/menu/menu-item-create-dialog.component.ts +0 -119
- package/src/components/menu/menu-item-edit-dialog.component.ts +0 -124
- package/src/components/menu/menu-item.component.ts +0 -295
- package/src/components/menu/menu.component.ts +0 -85
- package/src/components/notfound.component.ts +0 -31
- package/src/components/profile.component.ts +0 -44
- package/src/components/security.component.ts +0 -102
- package/src/components/sidebar.component.ts +0 -12
- package/src/components/top-bar.component.ts +0 -147
- package/src/dtos/context-menu-item.dto.ts +0 -23
- package/src/dtos/edit-module-instance.dto.ts +0 -8
- package/src/dtos/no-settings.dto.ts +0 -4
- package/src/dtos/put-security.dto.ts +0 -6
- package/src/dtos/security.dto.ts +0 -6
- package/src/dtos/top-bar.dto.ts +0 -13
- package/src/events/menu-change.event.ts +0 -23
- package/src/helpers/date.helper.ts +0 -94
- package/src/intercepts/i18n-intercept.service.ts +0 -13
- package/src/modules/http-loader.factory.ts +0 -40
- package/src/modules/secure.pipe.ts +0 -19
- package/src/public-api.ts +0 -42
- package/src/services/app-title.service.ts +0 -22
- package/src/services/app.layout.service.ts +0 -236
- package/src/services/app.menu.service.ts +0 -64
- package/src/services/auth.service.ts +0 -58
- package/src/services/base-data.service.ts +0 -74
- package/src/services/l10n.service.ts +0 -71
- package/src/services/msg.service.ts +0 -76
- package/src/services/security-data.service.ts +0 -19
- package/src/services/security-storage.service.ts +0 -21
- package/src/services/security.service.ts +0 -116
- package/src/services/top-bar.service.ts +0 -44
- package/src/services/user.service.ts +0 -77
- package/src/test.ts +0 -11
- package/src/user-api/UserProfile.ts +0 -85
- package/src/user-api/data-contracts.ts +0 -42
- package/src/user-api/http-client.ts +0 -253
- package/tsconfig.lib.json +0 -12
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -9
- /package/{src/assets → assets}/demo/code.scss +0 -0
- /package/{src/assets → assets}/demo/demo.scss +0 -0
- /package/{src/assets → assets}/demo/flags/flags.scss +0 -0
- /package/{src/assets → assets}/demo/flags/flags_responsive.png +0 -0
- /package/{src/assets → assets}/demo/images/access/asset-access.svg +0 -0
- /package/{src/assets → assets}/demo/images/error/asset-error.svg +0 -0
- /package/{src/assets → assets}/demo/images/flag/flag_placeholder.png +0 -0
- /package/{src/assets → assets}/favicon.svg +0 -0
- /package/{src/assets → assets}/i18n/app-modules.en.json +0 -0
- /package/{src/assets → assets}/i18n/app-modules.ru.json +0 -0
- /package/{src/assets → assets}/i18n/config.en.json +0 -0
- /package/{src/assets → assets}/i18n/config.ru.json +0 -0
- /package/{src/assets → assets}/layout/_core.scss +0 -0
- /package/{src/assets → assets}/layout/_footer.scss +0 -0
- /package/{src/assets → assets}/layout/_logo.scss +0 -0
- /package/{src/assets → assets}/layout/_main.scss +0 -0
- /package/{src/assets → assets}/layout/_menu.scss +0 -0
- /package/{src/assets → assets}/layout/_mixins.scss +0 -0
- /package/{src/assets → assets}/layout/_preloading.scss +0 -0
- /package/{src/assets → assets}/layout/_responsive.scss +0 -0
- /package/{src/assets → assets}/layout/_topbar.scss +0 -0
- /package/{src/assets → assets}/layout/_typography.scss +0 -0
- /package/{src/assets → assets}/layout/_utils.scss +0 -0
- /package/{src/assets → assets}/layout/layout.scss +0 -0
- /package/{src/assets → assets}/layout/variables/_common.scss +0 -0
- /package/{src/assets → assets}/layout/variables/_dark.scss +0 -0
- /package/{src/assets → assets}/layout/variables/_light.scss +0 -0
- /package/{src/assets → assets}/oip-common.scss +0 -0
- /package/{src/assets → assets}/tailwind.css +0 -0
|
@@ -0,0 +1,4267 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, inject, ChangeDetectorRef, signal, effect, Component, Input, computed, PLATFORM_ID, HostBinding, EventEmitter, Output, ViewChild, Renderer2, Pipe } from '@angular/core';
|
|
3
|
+
import * as i2$3 from 'primeng/api';
|
|
4
|
+
import { MessageService, ConfirmationService, PrimeIcons, SharedModule } from 'primeng/api';
|
|
5
|
+
import { HttpErrorResponse, HttpClient as HttpClient$1, HttpHeaders } from '@angular/common/http';
|
|
6
|
+
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
|
7
|
+
import * as i1$3 from '@angular/router';
|
|
8
|
+
import { ActivatedRoute, Router, RouterModule, NavigationEnd, RouterLinkActive, RouterLink } from '@angular/router';
|
|
9
|
+
import { lastValueFrom, BehaviorSubject, Subject, filter as filter$1, combineLatest, of, map as map$1, Observable } from 'rxjs';
|
|
10
|
+
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
11
|
+
import * as i1 from 'primeng/multiselect';
|
|
12
|
+
import { MultiSelectModule } from 'primeng/multiselect';
|
|
13
|
+
import * as i2 from 'primeng/tooltip';
|
|
14
|
+
import { TooltipModule, Tooltip } from 'primeng/tooltip';
|
|
15
|
+
import * as i1$1 from 'primeng/button';
|
|
16
|
+
import { ButtonModule, Button } from 'primeng/button';
|
|
17
|
+
import * as i5 from '@angular/forms';
|
|
18
|
+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
19
|
+
import * as i1$2 from '@angular/common';
|
|
20
|
+
import { isPlatformBrowser, CommonModule, NgIf, NgClass, NgFor } from '@angular/common';
|
|
21
|
+
import * as i4 from 'primeng/styleclass';
|
|
22
|
+
import { StyleClassModule } from 'primeng/styleclass';
|
|
23
|
+
import { updatePreset, updateSurfacePalette, $t } from '@primeng/themes';
|
|
24
|
+
import Aura from '@primeng/themes/aura';
|
|
25
|
+
import Lara from '@primeng/themes/lara';
|
|
26
|
+
import Nora from '@primeng/themes/nora';
|
|
27
|
+
import { PrimeNG } from 'primeng/config';
|
|
28
|
+
import * as i3 from 'primeng/selectbutton';
|
|
29
|
+
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
30
|
+
import { OidcSecurityService, PublicEventsService, EventTypes, StsConfigHttpLoader } from 'angular-auth-oidc-client';
|
|
31
|
+
import { filter, map, switchMap, catchError } from 'rxjs/operators';
|
|
32
|
+
import { Tabs, TabList, Tab } from 'primeng/tabs';
|
|
33
|
+
import * as i5$1 from 'primeng/avatar';
|
|
34
|
+
import { AvatarModule } from 'primeng/avatar';
|
|
35
|
+
import * as i1$4 from 'primeng/contextmenu';
|
|
36
|
+
import { ContextMenuModule, ContextMenu } from 'primeng/contextmenu';
|
|
37
|
+
import * as i2$1 from 'primeng/dialog';
|
|
38
|
+
import { DialogModule } from 'primeng/dialog';
|
|
39
|
+
import * as i3$2 from 'primeng/inputtext';
|
|
40
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
41
|
+
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
42
|
+
import * as i3$1 from 'primeng/ripple';
|
|
43
|
+
import { RippleModule } from 'primeng/ripple';
|
|
44
|
+
import { ConfirmDialog } from 'primeng/confirmdialog';
|
|
45
|
+
import * as i4$1 from 'primeng/select';
|
|
46
|
+
import { SelectModule, Select } from 'primeng/select';
|
|
47
|
+
import * as i1$5 from 'primeng/fileupload';
|
|
48
|
+
import { FileUploadModule } from 'primeng/fileupload';
|
|
49
|
+
import { ImageModule } from 'primeng/image';
|
|
50
|
+
import { Fluid } from 'primeng/fluid';
|
|
51
|
+
import * as i1$6 from 'primeng/table';
|
|
52
|
+
import { TableModule } from 'primeng/table';
|
|
53
|
+
import * as i2$2 from 'primeng/toggleswitch';
|
|
54
|
+
import { ToggleSwitchModule } from 'primeng/toggleswitch';
|
|
55
|
+
import { TagModule, Tag } from 'primeng/tag';
|
|
56
|
+
import { TextareaModule } from 'primeng/textarea';
|
|
57
|
+
import * as i4$2 from 'primeng/toolbar';
|
|
58
|
+
import { ToolbarModule } from 'primeng/toolbar';
|
|
59
|
+
|
|
60
|
+
class TopBarService {
|
|
61
|
+
get availableTopBarItems() {
|
|
62
|
+
return this.topBarItems;
|
|
63
|
+
}
|
|
64
|
+
get activeTopBarItem() {
|
|
65
|
+
if (this._activeId === undefined) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return this.topBarItems.find((topBarItem) => topBarItem.id === this._activeId);
|
|
69
|
+
}
|
|
70
|
+
get activeId() {
|
|
71
|
+
return this._activeId;
|
|
72
|
+
}
|
|
73
|
+
set activeId(value) {
|
|
74
|
+
this._activeId = value;
|
|
75
|
+
if (this.activeTopBarItem?.click)
|
|
76
|
+
this.activeTopBarItem.click();
|
|
77
|
+
}
|
|
78
|
+
constructor() {
|
|
79
|
+
this.topBarItems = [];
|
|
80
|
+
}
|
|
81
|
+
// Set tob bar items
|
|
82
|
+
setTopBarItems(items) {
|
|
83
|
+
this.topBarItems = items;
|
|
84
|
+
}
|
|
85
|
+
checkId(id) {
|
|
86
|
+
if (this.activeTopBarItem === undefined && id === 'content')
|
|
87
|
+
return true;
|
|
88
|
+
if (this.activeTopBarItem === undefined)
|
|
89
|
+
return false;
|
|
90
|
+
return this.activeTopBarItem.id == id;
|
|
91
|
+
}
|
|
92
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: TopBarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
93
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: TopBarService, providedIn: 'root' }); }
|
|
94
|
+
}
|
|
95
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: TopBarService, decorators: [{
|
|
96
|
+
type: Injectable,
|
|
97
|
+
args: [{
|
|
98
|
+
providedIn: 'root'
|
|
99
|
+
}]
|
|
100
|
+
}], ctorParameters: () => [] });
|
|
101
|
+
|
|
102
|
+
class MsgService {
|
|
103
|
+
constructor() {
|
|
104
|
+
this.messageService = inject(MessageService);
|
|
105
|
+
this.translate = inject(TranslateService);
|
|
106
|
+
this.lifetime = 2000;
|
|
107
|
+
}
|
|
108
|
+
add(msg) {
|
|
109
|
+
this.messageService.add(msg);
|
|
110
|
+
}
|
|
111
|
+
success(detail, summary = this.translate.instant('msgService.success'), life = this.lifetime) {
|
|
112
|
+
this.messageService.add({
|
|
113
|
+
severity: 'success',
|
|
114
|
+
summary: summary,
|
|
115
|
+
detail: detail,
|
|
116
|
+
life: life
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
info(detail, summary = this.translate.instant('msgService.info'), life = this.lifetime) {
|
|
120
|
+
this.messageService.add({
|
|
121
|
+
severity: 'info',
|
|
122
|
+
summary: summary,
|
|
123
|
+
detail: detail,
|
|
124
|
+
life: life
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
warn(detail, summary = this.translate.instant('msgService.warn'), life = this.lifetime) {
|
|
128
|
+
this.messageService.add({
|
|
129
|
+
severity: 'warn',
|
|
130
|
+
summary: summary,
|
|
131
|
+
detail: detail,
|
|
132
|
+
life: life
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
error(detail, summary = this.translate.instant('msgService.error'), life = this.lifetime) {
|
|
136
|
+
if (detail instanceof HttpErrorResponse) {
|
|
137
|
+
summary = `Error: ${detail.status} ${detail.statusText}`;
|
|
138
|
+
detail = `${detail.name} \r\n ${detail.message}`;
|
|
139
|
+
}
|
|
140
|
+
this.messageService.add({
|
|
141
|
+
severity: 'error',
|
|
142
|
+
summary: summary,
|
|
143
|
+
detail: detail.toString(),
|
|
144
|
+
life: life
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
contrast(detail, summary = this.translate.instant('msgService.error'), life = this.lifetime) {
|
|
148
|
+
this.messageService.add({
|
|
149
|
+
severity: 'contrast',
|
|
150
|
+
summary: summary,
|
|
151
|
+
detail: detail,
|
|
152
|
+
life: life
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
secondary(detail, summary = this.translate.instant('msgService.secondary'), life = this.lifetime) {
|
|
156
|
+
this.messageService.add({
|
|
157
|
+
severity: 'secondary',
|
|
158
|
+
summary: summary,
|
|
159
|
+
detail: detail,
|
|
160
|
+
life: life
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MsgService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
164
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MsgService, providedIn: 'root' }); }
|
|
165
|
+
}
|
|
166
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MsgService, decorators: [{
|
|
167
|
+
type: Injectable,
|
|
168
|
+
args: [{
|
|
169
|
+
providedIn: 'root'
|
|
170
|
+
}]
|
|
171
|
+
}] });
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* BaseDataService provides a unified interface for sending HTTP requests
|
|
175
|
+
* using Angular's HttpClient. It supports standard HTTP methods and automatic
|
|
176
|
+
* credential handling.
|
|
177
|
+
*/
|
|
178
|
+
class BaseDataService {
|
|
179
|
+
constructor() {
|
|
180
|
+
this.http = inject(HttpClient$1);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Gets the base URL of the application from the HTML <base> tag.
|
|
184
|
+
*/
|
|
185
|
+
get baseUrl() {
|
|
186
|
+
return document.getElementsByTagName('base')[0].href;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Sends an HTTP request with the specified method and data.
|
|
190
|
+
*
|
|
191
|
+
* @template TResponse - Expected response type.
|
|
192
|
+
* @param url - The target URL for the HTTP request.
|
|
193
|
+
* @param method - The HTTP method to use (GET, PUT, POST, DELETE). Default is 'GET'.
|
|
194
|
+
* @param data - An object containing request parameters or payload.
|
|
195
|
+
* @returns A promise that resolves to the response of type TResponse.
|
|
196
|
+
*/
|
|
197
|
+
sendRequest(url, method = 'GET', data = {}) {
|
|
198
|
+
const httpOptions = { withCredentials: true };
|
|
199
|
+
let result;
|
|
200
|
+
switch (method) {
|
|
201
|
+
case 'GET':
|
|
202
|
+
result = this.http.get(url, { params: data });
|
|
203
|
+
break;
|
|
204
|
+
case 'PUT':
|
|
205
|
+
result = this.http.put(url, data, httpOptions);
|
|
206
|
+
break;
|
|
207
|
+
case 'POST':
|
|
208
|
+
result = this.http.post(url, data, httpOptions);
|
|
209
|
+
break;
|
|
210
|
+
case 'DELETE':
|
|
211
|
+
result = this.http.request('DELETE', url, {
|
|
212
|
+
body: data,
|
|
213
|
+
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
|
|
214
|
+
withCredentials: true
|
|
215
|
+
});
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
return lastValueFrom(result);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Sends a GET request and retrieves a response as a Blob.
|
|
222
|
+
*
|
|
223
|
+
* @param url - The target URL for the GET request.
|
|
224
|
+
* @returns A promise that resolves to a Object response.
|
|
225
|
+
*/
|
|
226
|
+
getBlob(url) {
|
|
227
|
+
const httpOptions = {
|
|
228
|
+
responseType: 'blob',
|
|
229
|
+
withCredentials: true
|
|
230
|
+
};
|
|
231
|
+
const result = this.http.get(url, httpOptions);
|
|
232
|
+
return lastValueFrom(result);
|
|
233
|
+
}
|
|
234
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
235
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseDataService }); }
|
|
236
|
+
}
|
|
237
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseDataService, decorators: [{
|
|
238
|
+
type: Injectable
|
|
239
|
+
}] });
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Service to manage the application title.
|
|
243
|
+
*/
|
|
244
|
+
class AppTitleService {
|
|
245
|
+
constructor() {
|
|
246
|
+
this.title = inject(Title);
|
|
247
|
+
this.titleSubject = new BehaviorSubject('');
|
|
248
|
+
this.title$ = this.titleSubject.asObservable();
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Set the title of the current HTML document.
|
|
252
|
+
* @param newTitle
|
|
253
|
+
*/
|
|
254
|
+
setTitle(newTitle) {
|
|
255
|
+
this.title.setTitle(newTitle);
|
|
256
|
+
this.titleSubject.next(newTitle);
|
|
257
|
+
}
|
|
258
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppTitleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
259
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppTitleService, providedIn: 'root' }); }
|
|
260
|
+
}
|
|
261
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppTitleService, decorators: [{
|
|
262
|
+
type: Injectable,
|
|
263
|
+
args: [{ providedIn: 'root' }]
|
|
264
|
+
}] });
|
|
265
|
+
|
|
266
|
+
class BaseModuleComponent {
|
|
267
|
+
/**
|
|
268
|
+
* Updates local settings and persists them to local storage.
|
|
269
|
+
* @return {void}
|
|
270
|
+
*/
|
|
271
|
+
onConfigUpdate() {
|
|
272
|
+
if (Object.keys(this.localSettings()).length > 0) {
|
|
273
|
+
this._localSettings = { ...this.localSettings() };
|
|
274
|
+
this.localSettingsUpdate.next(this._localSettings);
|
|
275
|
+
localStorage.setItem(`Instance_${this.id}`, JSON.stringify(this._localSettings));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
getLocalStorageSettings() {
|
|
279
|
+
try {
|
|
280
|
+
const localStorageSettingsString = localStorage.getItem(`Instance_${this.id}`);
|
|
281
|
+
if (localStorageSettingsString != null) {
|
|
282
|
+
this.localSettings.set(JSON.parse(localStorageSettingsString));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
this.msgService.error(error, 'Error parsing layoutConfig:');
|
|
287
|
+
this.localSettings.set({});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Checks if the content ID is present.
|
|
292
|
+
* @returns {boolean} True if the content ID is present, false otherwise.
|
|
293
|
+
*/
|
|
294
|
+
get isContent() {
|
|
295
|
+
return this.topBarService.checkId('content');
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Checks if the settings ID is present.
|
|
299
|
+
* @returns {boolean} True if the settings ID is present, false otherwise.
|
|
300
|
+
*/
|
|
301
|
+
get isSettings() {
|
|
302
|
+
return this.topBarService.checkId('settings');
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Checks if the security ID is present.
|
|
306
|
+
* @returns {boolean} True if the security ID is present, false otherwise.
|
|
307
|
+
*/
|
|
308
|
+
get isSecurity() {
|
|
309
|
+
return this.topBarService.checkId('security');
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Initializes the component and subscribes to local settings updates.
|
|
313
|
+
*/
|
|
314
|
+
constructor() {
|
|
315
|
+
/**
|
|
316
|
+
* Provides access to topbar related functionality, such as managing visibility and content.
|
|
317
|
+
* @type {TopBarService}
|
|
318
|
+
*/
|
|
319
|
+
this.topBarService = inject(TopBarService);
|
|
320
|
+
/**
|
|
321
|
+
* Provides access to information about the current route.
|
|
322
|
+
* This includes route parameters, data, and the route's path.
|
|
323
|
+
*/
|
|
324
|
+
this.route = inject(ActivatedRoute);
|
|
325
|
+
/**
|
|
326
|
+
* Provides access to messaging services.
|
|
327
|
+
*/
|
|
328
|
+
this.msgService = inject(MsgService);
|
|
329
|
+
/**
|
|
330
|
+
* Provides access to base data service functionality.
|
|
331
|
+
* @deprecated The method should not be used
|
|
332
|
+
*/
|
|
333
|
+
this.baseDataService = inject(BaseDataService);
|
|
334
|
+
/**
|
|
335
|
+
* Provides access to translation functionality.
|
|
336
|
+
*/
|
|
337
|
+
this.translateService = inject(TranslateService);
|
|
338
|
+
/**
|
|
339
|
+
* Provides access to the application's title service.
|
|
340
|
+
*/
|
|
341
|
+
this.appTitleService = inject(AppTitleService);
|
|
342
|
+
/**
|
|
343
|
+
* Reference to the ChangeDetector. Used to trigger change detection manually.
|
|
344
|
+
*/
|
|
345
|
+
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
346
|
+
/**
|
|
347
|
+
* Represents a subscription to an observable.
|
|
348
|
+
* Manages the lifecycle of receiving data from the observable and allows unsubscribing to stop receiving data.
|
|
349
|
+
* @type {Subscription}
|
|
350
|
+
*/
|
|
351
|
+
this.subscriptions = [];
|
|
352
|
+
/**
|
|
353
|
+
* Configuration object for backend storage
|
|
354
|
+
* @type {TBackendStoreSettings}
|
|
355
|
+
*/
|
|
356
|
+
this.settings = {};
|
|
357
|
+
/**
|
|
358
|
+
* Configuration object for local storage.
|
|
359
|
+
* @type {TLocalStoreSettings}
|
|
360
|
+
*/
|
|
361
|
+
this._localSettings = {};
|
|
362
|
+
/**
|
|
363
|
+
* A signal representing the local application settings. Changes to this signal
|
|
364
|
+
* propagate updates to the underlying local store settings.
|
|
365
|
+
* @type {WritableSignal<TLocalStoreSettings>}
|
|
366
|
+
*/
|
|
367
|
+
this.localSettings = signal(this._localSettings, ...(ngDevMode ? [{ debugName: "localSettings" }] : []));
|
|
368
|
+
/**
|
|
369
|
+
* A Subject emitting updates to local store settings. Observables can subscribe to this Subject to react to changes in local settings.
|
|
370
|
+
* @type {Subject<TLocalStoreSettings>}
|
|
371
|
+
*/
|
|
372
|
+
this.localSettingsUpdate = new Subject();
|
|
373
|
+
/**
|
|
374
|
+
* A unique numerical identifier for the module.
|
|
375
|
+
* @type {number}
|
|
376
|
+
*/
|
|
377
|
+
this.id = undefined;
|
|
378
|
+
/**
|
|
379
|
+
* Defines the top bar items.
|
|
380
|
+
*/
|
|
381
|
+
this.topBarItems = [
|
|
382
|
+
{ id: 'content', icon: 'pi-box', caption: '' },
|
|
383
|
+
{ id: 'settings', icon: 'pi-cog', caption: '' },
|
|
384
|
+
{ id: 'security', icon: 'pi-lock', caption: '' }
|
|
385
|
+
];
|
|
386
|
+
effect(() => {
|
|
387
|
+
const config = this.localSettings();
|
|
388
|
+
if (config) {
|
|
389
|
+
this.onConfigUpdate();
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
this.subscriptions.push(this.route.url.subscribe((url) => {
|
|
393
|
+
this.controller = url[0].path;
|
|
394
|
+
}));
|
|
395
|
+
this.subscriptions.push(this.route.paramMap.subscribe((params) => {
|
|
396
|
+
this.id = +params.get('id');
|
|
397
|
+
this.getLocalStorageSettings();
|
|
398
|
+
}));
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Lifecycle hook that is called when a component is destroyed.
|
|
402
|
+
* Unsubscribes from all subscriptions to prevent memory leaks,
|
|
403
|
+
* resets the top bar items to an empty array, and sets the active ID
|
|
404
|
+
* to the ID of the first top bar item (if available).
|
|
405
|
+
*/
|
|
406
|
+
ngOnDestroy() {
|
|
407
|
+
this.topBarService.setTopBarItems([]);
|
|
408
|
+
this.topBarService.activeId = this.topBarItems[0].id;
|
|
409
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Initializes the component. Subscribes to translation service to set captions for top bar items,
|
|
413
|
+
* sets the top bar items via the top bar service, sets the active ID,
|
|
414
|
+
* subscribes to route parameters to get the ID, and retrieves settings.
|
|
415
|
+
* @return {Promise<void>} A promise that resolves when the initialization is complete.
|
|
416
|
+
*/
|
|
417
|
+
async ngOnInit() {
|
|
418
|
+
this.subscriptions.push(this.translateService.get('baseComponent').subscribe((value) => {
|
|
419
|
+
this.topBarItems[0].caption = value.content;
|
|
420
|
+
this.topBarItems[1].caption = value.settings;
|
|
421
|
+
this.topBarItems[2].caption = value.security;
|
|
422
|
+
}));
|
|
423
|
+
this.topBarService.setTopBarItems(this.topBarItems);
|
|
424
|
+
this.topBarService.activeId = this.topBarItems[0].id;
|
|
425
|
+
await this.getSettings();
|
|
426
|
+
this.subscriptions.push(this.appTitleService.title$.subscribe((title) => {
|
|
427
|
+
this.title = title;
|
|
428
|
+
this.changeDetectorRef.detectChanges();
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Retrieves module instance settings.
|
|
433
|
+
* @return {Promise<void>} A promise that resolves when settings are retrieved.
|
|
434
|
+
*/
|
|
435
|
+
async getSettings() {
|
|
436
|
+
try {
|
|
437
|
+
this.settings = await this.baseDataService.sendRequest(`${this.baseDataService.baseUrl}api/${this.controller}/get-module-instance-settings?id=${this.id}`);
|
|
438
|
+
}
|
|
439
|
+
catch (error) {
|
|
440
|
+
this.msgService.error(error);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Saves the provided settings to the backend.
|
|
445
|
+
* @param {TLocalStoreSettings} settings - The settings object to save.
|
|
446
|
+
* @return {Promise<void>} A promise that resolves when the settings are saved. Reject if an error occurs.
|
|
447
|
+
*/
|
|
448
|
+
async saveSettings(settings) {
|
|
449
|
+
await this.baseDataService
|
|
450
|
+
.sendRequest(`api/${this.controller}/put-module-instance-settings`, 'PUT', {
|
|
451
|
+
id: this.id,
|
|
452
|
+
settings: settings
|
|
453
|
+
})
|
|
454
|
+
.then(() => {
|
|
455
|
+
this.msgService.success(this.translateService.instant('baseComponent.success'));
|
|
456
|
+
})
|
|
457
|
+
.catch((error) => {
|
|
458
|
+
this.msgService.error(error);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseModuleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
462
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: BaseModuleComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: '', isInline: true }); }
|
|
463
|
+
}
|
|
464
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseModuleComponent, decorators: [{
|
|
465
|
+
type: Component,
|
|
466
|
+
args: [{ standalone: true, template: '' }]
|
|
467
|
+
}], ctorParameters: () => [] });
|
|
468
|
+
|
|
469
|
+
class SecurityDataService extends BaseDataService {
|
|
470
|
+
getSecurity(controller, id) {
|
|
471
|
+
return this.sendRequest(this.baseUrl + `api/${controller}/get-security?id=${id}`);
|
|
472
|
+
}
|
|
473
|
+
saveSecurity(controller, request) {
|
|
474
|
+
return this.sendRequest(this.baseUrl + `api/${controller}/put-security`, 'PUT', request);
|
|
475
|
+
}
|
|
476
|
+
getRealmRoles() {
|
|
477
|
+
return this.sendRequest(this.baseUrl + `api/security/get-realm-roles`);
|
|
478
|
+
}
|
|
479
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityDataService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
480
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityDataService }); }
|
|
481
|
+
}
|
|
482
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityDataService, decorators: [{
|
|
483
|
+
type: Injectable
|
|
484
|
+
}] });
|
|
485
|
+
|
|
486
|
+
class SecurityComponent {
|
|
487
|
+
constructor() {
|
|
488
|
+
this.msgService = inject(MsgService);
|
|
489
|
+
this.dataService = inject(SecurityDataService);
|
|
490
|
+
this.translateService = inject(TranslateService);
|
|
491
|
+
this.roles = [];
|
|
492
|
+
}
|
|
493
|
+
ngOnDestroy() {
|
|
494
|
+
// on destroy
|
|
495
|
+
}
|
|
496
|
+
ngOnInit() {
|
|
497
|
+
if (!this.id) {
|
|
498
|
+
this.msgService.error('Module id not passed!');
|
|
499
|
+
}
|
|
500
|
+
if (!this.controller) {
|
|
501
|
+
this.msgService.error('Controller not passed!');
|
|
502
|
+
}
|
|
503
|
+
this.dataService.getSecurity(this.controller, this.id).then((result) => {
|
|
504
|
+
this.securityData = result;
|
|
505
|
+
}, (error) => this.msgService.error(error));
|
|
506
|
+
this.dataService.getRealmRoles().then((result) => {
|
|
507
|
+
this.roles = result;
|
|
508
|
+
}, (error) => this.msgService.error(error));
|
|
509
|
+
}
|
|
510
|
+
saveClick() {
|
|
511
|
+
const request = {
|
|
512
|
+
id: this.id,
|
|
513
|
+
securities: this.securityData
|
|
514
|
+
};
|
|
515
|
+
this.dataService.saveSecurity(this.controller, request).then((result) => {
|
|
516
|
+
this.msgService.success(this.translateService.instant('securityComponent.savedSecurity'));
|
|
517
|
+
}, (error) => this.msgService.error(error));
|
|
518
|
+
}
|
|
519
|
+
saveKeyDown($event) {
|
|
520
|
+
if ($event.key === 'Enter' || $event.key === 'Space') {
|
|
521
|
+
this.saveKeyDown(null);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
525
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: SecurityComponent, isStandalone: true, selector: "security", inputs: { id: "id", controller: "controller" }, ngImport: i0, template: `
|
|
526
|
+
<div class="flex flex-col md:flex-row gap-8">
|
|
527
|
+
<div class="md:w-1/2">
|
|
528
|
+
<div class="card flex flex-col gap-4">
|
|
529
|
+
<div class="font-semibold text-xl">
|
|
530
|
+
{{ 'securityComponent.security' | translate }}
|
|
531
|
+
</div>
|
|
532
|
+
@for (item of securityData; track item.name) {
|
|
533
|
+
<div class="flex flex-col gap-2">
|
|
534
|
+
<label htmlFor="oip-security-multiselect-{{ item.name }}">
|
|
535
|
+
{{ item.name }}
|
|
536
|
+
<span class="pi pi-question-circle" pTooltip="{{ item.description }}" tooltipPosition="right"></span>
|
|
537
|
+
</label>
|
|
538
|
+
<p-multiSelect
|
|
539
|
+
id="oip-security-multiselect-{{ item.name }}"
|
|
540
|
+
placeholder="Select roles"
|
|
541
|
+
[maxSelectedLabels]="10"
|
|
542
|
+
[options]="roles"
|
|
543
|
+
[(ngModel)]="item.roles" />
|
|
544
|
+
</div>
|
|
545
|
+
}
|
|
546
|
+
<div class="flex justify-content-end flex-wrap">
|
|
547
|
+
<p-button
|
|
548
|
+
icon="pi pi-save"
|
|
549
|
+
id="oip-security-save-button"
|
|
550
|
+
label="{{ 'securityComponent.save' | translate }}"
|
|
551
|
+
(click)="saveClick()"
|
|
552
|
+
(keydown)="saveKeyDown($event)" />
|
|
553
|
+
</div>
|
|
554
|
+
</div>
|
|
555
|
+
</div>
|
|
556
|
+
</div>
|
|
557
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i1.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
558
|
+
}
|
|
559
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityComponent, decorators: [{
|
|
560
|
+
type: Component,
|
|
561
|
+
args: [{
|
|
562
|
+
selector: 'security',
|
|
563
|
+
template: `
|
|
564
|
+
<div class="flex flex-col md:flex-row gap-8">
|
|
565
|
+
<div class="md:w-1/2">
|
|
566
|
+
<div class="card flex flex-col gap-4">
|
|
567
|
+
<div class="font-semibold text-xl">
|
|
568
|
+
{{ 'securityComponent.security' | translate }}
|
|
569
|
+
</div>
|
|
570
|
+
@for (item of securityData; track item.name) {
|
|
571
|
+
<div class="flex flex-col gap-2">
|
|
572
|
+
<label htmlFor="oip-security-multiselect-{{ item.name }}">
|
|
573
|
+
{{ item.name }}
|
|
574
|
+
<span class="pi pi-question-circle" pTooltip="{{ item.description }}" tooltipPosition="right"></span>
|
|
575
|
+
</label>
|
|
576
|
+
<p-multiSelect
|
|
577
|
+
id="oip-security-multiselect-{{ item.name }}"
|
|
578
|
+
placeholder="Select roles"
|
|
579
|
+
[maxSelectedLabels]="10"
|
|
580
|
+
[options]="roles"
|
|
581
|
+
[(ngModel)]="item.roles" />
|
|
582
|
+
</div>
|
|
583
|
+
}
|
|
584
|
+
<div class="flex justify-content-end flex-wrap">
|
|
585
|
+
<p-button
|
|
586
|
+
icon="pi pi-save"
|
|
587
|
+
id="oip-security-save-button"
|
|
588
|
+
label="{{ 'securityComponent.save' | translate }}"
|
|
589
|
+
(click)="saveClick()"
|
|
590
|
+
(keydown)="saveKeyDown($event)" />
|
|
591
|
+
</div>
|
|
592
|
+
</div>
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
595
|
+
`,
|
|
596
|
+
imports: [MultiSelectModule, TooltipModule, FormsModule, ButtonModule, TranslatePipe],
|
|
597
|
+
standalone: true
|
|
598
|
+
}]
|
|
599
|
+
}], propDecorators: { id: [{
|
|
600
|
+
type: Input
|
|
601
|
+
}], controller: [{
|
|
602
|
+
type: Input
|
|
603
|
+
}] } });
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Convert Date to string in format 2022-02-22
|
|
607
|
+
* @param date
|
|
608
|
+
*/
|
|
609
|
+
function dateToString(date) {
|
|
610
|
+
const year = date.getFullYear();
|
|
611
|
+
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
612
|
+
const day = date.getDate().toString().padStart(2, '0');
|
|
613
|
+
return `${year}-${month}-${day}`;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Convert string in format 2022-02-22 to Date
|
|
617
|
+
* @param date
|
|
618
|
+
*/
|
|
619
|
+
function stringToDate(date) {
|
|
620
|
+
const dateParts = date.split('-');
|
|
621
|
+
const day = parseInt(dateParts[2], 10);
|
|
622
|
+
const month = parseInt(dateParts[1], 10) - 1;
|
|
623
|
+
const year = parseInt(dateParts[0], 10);
|
|
624
|
+
return new Date(year, month, day);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Add days to date
|
|
628
|
+
* @param date
|
|
629
|
+
* @param days
|
|
630
|
+
*/
|
|
631
|
+
function addDays(date, days) {
|
|
632
|
+
const clonedDate = structuredClone(date);
|
|
633
|
+
clonedDate.setDate(clonedDate.getDate() + days);
|
|
634
|
+
return clonedDate;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Get today's date
|
|
638
|
+
* @param date
|
|
639
|
+
*/
|
|
640
|
+
function getTodayDate() {
|
|
641
|
+
const date = new Date();
|
|
642
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
643
|
+
}
|
|
644
|
+
/* Convert dateformat from DatePipe to PrimeNG*/
|
|
645
|
+
function convertToPrimeNgDateFormat(dateformat) {
|
|
646
|
+
switch (dateformat) {
|
|
647
|
+
case 'dd.MM.yyyy':
|
|
648
|
+
return 'dd.mm.yy';
|
|
649
|
+
case 'dd.MM.yy':
|
|
650
|
+
return 'dd.mm.y';
|
|
651
|
+
case 'yyyy-MM-dd':
|
|
652
|
+
return 'yy-mm-dd';
|
|
653
|
+
case 'dd.MMM.yyyy':
|
|
654
|
+
return 'dd.M.yy';
|
|
655
|
+
default:
|
|
656
|
+
console.error(`Failed to convert format: ${dateformat}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Convert all properties of an object with string dates to Date objects
|
|
661
|
+
* @param obj
|
|
662
|
+
*/
|
|
663
|
+
function restoreDates(obj) {
|
|
664
|
+
if (obj === null || typeof obj !== 'object')
|
|
665
|
+
return obj;
|
|
666
|
+
if (Array.isArray(obj)) {
|
|
667
|
+
return obj.map((item) => restoreDates(item));
|
|
668
|
+
}
|
|
669
|
+
const result = {};
|
|
670
|
+
for (const key in obj) {
|
|
671
|
+
const value = obj[key];
|
|
672
|
+
if (typeof value === 'string' && isIsoDate(value)) {
|
|
673
|
+
result[key] = new Date(value);
|
|
674
|
+
}
|
|
675
|
+
else if (typeof value === 'object' && value !== null && !(value instanceof Date)) {
|
|
676
|
+
result[key] = restoreDates(value);
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
result[key] = value;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Check if a string is a date in ISO format
|
|
686
|
+
* @param str
|
|
687
|
+
*/
|
|
688
|
+
function isIsoDate(str) {
|
|
689
|
+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(str);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
class LayoutService {
|
|
693
|
+
constructor() {
|
|
694
|
+
this._config = this.getAppConfigFromStorage();
|
|
695
|
+
this._state = {
|
|
696
|
+
staticMenuDesktopInactive: false,
|
|
697
|
+
overlayMenuActive: false,
|
|
698
|
+
configSidebarVisible: false,
|
|
699
|
+
staticMenuMobileActive: false,
|
|
700
|
+
menuHoverActive: false
|
|
701
|
+
};
|
|
702
|
+
this.layoutConfig = signal(this._config, ...(ngDevMode ? [{ debugName: "layoutConfig" }] : []));
|
|
703
|
+
this.layoutState = signal(this._state, ...(ngDevMode ? [{ debugName: "layoutState" }] : []));
|
|
704
|
+
this.configUpdate = new Subject();
|
|
705
|
+
this.overlayOpen = new Subject();
|
|
706
|
+
this.menuSource = new Subject();
|
|
707
|
+
this.resetSource = new Subject();
|
|
708
|
+
this.menuSource$ = this.menuSource.asObservable();
|
|
709
|
+
this.resetSource$ = this.resetSource.asObservable();
|
|
710
|
+
this.configUpdate$ = this.configUpdate.asObservable();
|
|
711
|
+
this.overlayOpen$ = this.overlayOpen.asObservable();
|
|
712
|
+
this.theme = computed(() => (this.layoutConfig()?.darkTheme ? 'light' : 'dark'), ...(ngDevMode ? [{ debugName: "theme" }] : []));
|
|
713
|
+
this.isSidebarActive = computed(() => this.layoutState().overlayMenuActive || this.layoutState().staticMenuMobileActive, ...(ngDevMode ? [{ debugName: "isSidebarActive" }] : []));
|
|
714
|
+
this.isDarkTheme = computed(() => this.layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
715
|
+
this.getPrimary = computed(() => this.layoutConfig().primary, ...(ngDevMode ? [{ debugName: "getPrimary" }] : []));
|
|
716
|
+
this.getSurface = computed(() => this.layoutConfig().surface, ...(ngDevMode ? [{ debugName: "getSurface" }] : []));
|
|
717
|
+
this.isOverlay = computed(() => this.layoutConfig().menuMode === 'overlay', ...(ngDevMode ? [{ debugName: "isOverlay" }] : []));
|
|
718
|
+
this.language = computed(() => this.layoutConfig().language, ...(ngDevMode ? [{ debugName: "language" }] : []));
|
|
719
|
+
this.dateFormat = computed(() => this.layoutConfig().dateFormat, ...(ngDevMode ? [{ debugName: "dateFormat" }] : []));
|
|
720
|
+
this.primeNgDateFormat = computed(() => convertToPrimeNgDateFormat(this.layoutConfig().dateFormat), ...(ngDevMode ? [{ debugName: "primeNgDateFormat" }] : []));
|
|
721
|
+
this.timeFormat = computed(() => this.layoutConfig().timeFormat, ...(ngDevMode ? [{ debugName: "timeFormat" }] : []));
|
|
722
|
+
this.dateTimeFormat = computed(() => `${this.layoutConfig().dateFormat} ${this.layoutConfig().timeFormat}`, ...(ngDevMode ? [{ debugName: "dateTimeFormat" }] : []));
|
|
723
|
+
this.monthFormat = computed(() => {
|
|
724
|
+
const reDay = /d+/i;
|
|
725
|
+
const reDelimeter = /^[^\w]|[^\w]$|([^\w])\1+/;
|
|
726
|
+
const ngDateFormat = convertToPrimeNgDateFormat(this.layoutConfig().dateFormat);
|
|
727
|
+
const ngDate = ngDateFormat.replace(reDay, '');
|
|
728
|
+
const dateGroups = ngDate.match(reDelimeter);
|
|
729
|
+
if (Array.isArray(dateGroups) && dateGroups.length > 1) {
|
|
730
|
+
return dateGroups[1] !== undefined
|
|
731
|
+
? ngDate.replace(dateGroups[0], '')
|
|
732
|
+
: ngDate.startsWith(dateGroups[0])
|
|
733
|
+
? ngDate.substring(1)
|
|
734
|
+
: ngDate.substring(0, ngDate.length - 1);
|
|
735
|
+
}
|
|
736
|
+
return ngDateFormat;
|
|
737
|
+
}, ...(ngDevMode ? [{ debugName: "monthFormat" }] : []));
|
|
738
|
+
this.timeZone = computed(() => this.layoutConfig().timeZone, ...(ngDevMode ? [{ debugName: "timeZone" }] : []));
|
|
739
|
+
this.transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "transitionComplete" }] : []));
|
|
740
|
+
this.initialized = false;
|
|
741
|
+
effect(() => {
|
|
742
|
+
const config = this.layoutConfig();
|
|
743
|
+
if (config) {
|
|
744
|
+
this.onConfigUpdate();
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
effect(() => {
|
|
748
|
+
const config = this.layoutConfig();
|
|
749
|
+
if (!this.initialized || !config) {
|
|
750
|
+
this.initialized = true;
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
this.handleDarkModeTransition(config);
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Get application settings from browser storage
|
|
758
|
+
* @returns AppConfig
|
|
759
|
+
*/
|
|
760
|
+
getAppConfigFromStorage() {
|
|
761
|
+
const appConfigUiString = localStorage.getItem('layoutConfig');
|
|
762
|
+
if (appConfigUiString != null) {
|
|
763
|
+
const config = JSON.parse(appConfigUiString);
|
|
764
|
+
config.timeZone ??= Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
765
|
+
return config;
|
|
766
|
+
}
|
|
767
|
+
return {
|
|
768
|
+
preset: 'Aura',
|
|
769
|
+
primary: 'emerald',
|
|
770
|
+
surface: null,
|
|
771
|
+
darkTheme: false,
|
|
772
|
+
menuMode: 'static',
|
|
773
|
+
language: 'ru',
|
|
774
|
+
dateFormat: 'yyyy-MM-dd',
|
|
775
|
+
timeFormat: 'HH:mm:ss',
|
|
776
|
+
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',
|
|
777
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
handleDarkModeTransition(config) {
|
|
781
|
+
if (document.startViewTransition) {
|
|
782
|
+
this.startViewTransition(config);
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
this.toggleDarkMode(config);
|
|
786
|
+
this.onTransitionEnd();
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
startViewTransition(config) {
|
|
790
|
+
const transition = document.startViewTransition(() => {
|
|
791
|
+
this.toggleDarkMode(config);
|
|
792
|
+
});
|
|
793
|
+
transition.ready
|
|
794
|
+
.then(() => {
|
|
795
|
+
this.onTransitionEnd();
|
|
796
|
+
})
|
|
797
|
+
.catch(() => { });
|
|
798
|
+
}
|
|
799
|
+
toggleDarkMode(config) {
|
|
800
|
+
const _config = config || this.layoutConfig();
|
|
801
|
+
if (_config.darkTheme) {
|
|
802
|
+
document.documentElement.classList.add('app-dark');
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
document.documentElement.classList.remove('app-dark');
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
onTransitionEnd() {
|
|
809
|
+
this.transitionComplete.set(true);
|
|
810
|
+
setTimeout(() => {
|
|
811
|
+
this.transitionComplete.set(false);
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
onMenuToggle() {
|
|
815
|
+
if (this.isOverlay()) {
|
|
816
|
+
this.layoutState.update((prev) => ({ ...prev, overlayMenuActive: !this.layoutState().overlayMenuActive }));
|
|
817
|
+
if (this.layoutState().overlayMenuActive) {
|
|
818
|
+
this.overlayOpen.next(null);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (this.isDesktop()) {
|
|
822
|
+
this.layoutState.update((prev) => ({
|
|
823
|
+
...prev,
|
|
824
|
+
staticMenuDesktopInactive: !this.layoutState().staticMenuDesktopInactive
|
|
825
|
+
}));
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
this.layoutState.update((prev) => ({
|
|
829
|
+
...prev,
|
|
830
|
+
staticMenuMobileActive: !this.layoutState().staticMenuMobileActive
|
|
831
|
+
}));
|
|
832
|
+
if (this.layoutState().staticMenuMobileActive) {
|
|
833
|
+
this.overlayOpen.next(null);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
isDesktop() {
|
|
838
|
+
return window.innerWidth > 991;
|
|
839
|
+
}
|
|
840
|
+
isMobile() {
|
|
841
|
+
return !this.isDesktop();
|
|
842
|
+
}
|
|
843
|
+
onConfigUpdate() {
|
|
844
|
+
this._config = { ...this.layoutConfig() };
|
|
845
|
+
this.configUpdate.next(this.layoutConfig());
|
|
846
|
+
localStorage.setItem('layoutConfig', JSON.stringify(this.layoutConfig()));
|
|
847
|
+
}
|
|
848
|
+
onMenuStateChange(event) {
|
|
849
|
+
this.menuSource.next(event);
|
|
850
|
+
}
|
|
851
|
+
reset() {
|
|
852
|
+
this.resetSource.next(true);
|
|
853
|
+
}
|
|
854
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
855
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutService, providedIn: 'root' }); }
|
|
856
|
+
}
|
|
857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutService, decorators: [{
|
|
858
|
+
type: Injectable,
|
|
859
|
+
args: [{ providedIn: 'root' }]
|
|
860
|
+
}], ctorParameters: () => [] });
|
|
861
|
+
|
|
862
|
+
const presets = {
|
|
863
|
+
Aura,
|
|
864
|
+
Lara,
|
|
865
|
+
Nora
|
|
866
|
+
};
|
|
867
|
+
class AppConfiguratorComponent {
|
|
868
|
+
constructor() {
|
|
869
|
+
this.router = inject(Router);
|
|
870
|
+
this.config = inject(PrimeNG);
|
|
871
|
+
this.layoutService = inject(LayoutService);
|
|
872
|
+
this.platformId = inject(PLATFORM_ID);
|
|
873
|
+
this.primeng = inject(PrimeNG);
|
|
874
|
+
this.presets = Object.keys(presets);
|
|
875
|
+
this.showMenuModeButton = signal(!this.router.url.includes('auth'), ...(ngDevMode ? [{ debugName: "showMenuModeButton" }] : []));
|
|
876
|
+
this.menuModeOptions = [
|
|
877
|
+
{ label: 'Static', value: 'static' },
|
|
878
|
+
{ label: 'Overlay', value: 'overlay' }
|
|
879
|
+
];
|
|
880
|
+
this.surfaces = [
|
|
881
|
+
{
|
|
882
|
+
name: 'slate',
|
|
883
|
+
palette: {
|
|
884
|
+
0: '#ffffff',
|
|
885
|
+
50: '#f8fafc',
|
|
886
|
+
100: '#f1f5f9',
|
|
887
|
+
200: '#e2e8f0',
|
|
888
|
+
300: '#cbd5e1',
|
|
889
|
+
400: '#94a3b8',
|
|
890
|
+
500: '#64748b',
|
|
891
|
+
600: '#475569',
|
|
892
|
+
700: '#334155',
|
|
893
|
+
800: '#1e293b',
|
|
894
|
+
900: '#0f172a',
|
|
895
|
+
950: '#020617'
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
name: 'gray',
|
|
900
|
+
palette: {
|
|
901
|
+
0: '#ffffff',
|
|
902
|
+
50: '#f9fafb',
|
|
903
|
+
100: '#f3f4f6',
|
|
904
|
+
200: '#e5e7eb',
|
|
905
|
+
300: '#d1d5db',
|
|
906
|
+
400: '#9ca3af',
|
|
907
|
+
500: '#6b7280',
|
|
908
|
+
600: '#4b5563',
|
|
909
|
+
700: '#374151',
|
|
910
|
+
800: '#1f2937',
|
|
911
|
+
900: '#111827',
|
|
912
|
+
950: '#030712'
|
|
913
|
+
}
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
name: 'zinc',
|
|
917
|
+
palette: {
|
|
918
|
+
0: '#ffffff',
|
|
919
|
+
50: '#fafafa',
|
|
920
|
+
100: '#f4f4f5',
|
|
921
|
+
200: '#e4e4e7',
|
|
922
|
+
300: '#d4d4d8',
|
|
923
|
+
400: '#a1a1aa',
|
|
924
|
+
500: '#71717a',
|
|
925
|
+
600: '#52525b',
|
|
926
|
+
700: '#3f3f46',
|
|
927
|
+
800: '#27272a',
|
|
928
|
+
900: '#18181b',
|
|
929
|
+
950: '#09090b'
|
|
930
|
+
}
|
|
931
|
+
},
|
|
932
|
+
{
|
|
933
|
+
name: 'neutral',
|
|
934
|
+
palette: {
|
|
935
|
+
0: '#ffffff',
|
|
936
|
+
50: '#fafafa',
|
|
937
|
+
100: '#f5f5f5',
|
|
938
|
+
200: '#e5e5e5',
|
|
939
|
+
300: '#d4d4d4',
|
|
940
|
+
400: '#a3a3a3',
|
|
941
|
+
500: '#737373',
|
|
942
|
+
600: '#525252',
|
|
943
|
+
700: '#404040',
|
|
944
|
+
800: '#262626',
|
|
945
|
+
900: '#171717',
|
|
946
|
+
950: '#0a0a0a'
|
|
947
|
+
}
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
name: 'stone',
|
|
951
|
+
palette: {
|
|
952
|
+
0: '#ffffff',
|
|
953
|
+
50: '#fafaf9',
|
|
954
|
+
100: '#f5f5f4',
|
|
955
|
+
200: '#e7e5e4',
|
|
956
|
+
300: '#d6d3d1',
|
|
957
|
+
400: '#a8a29e',
|
|
958
|
+
500: '#78716c',
|
|
959
|
+
600: '#57534e',
|
|
960
|
+
700: '#44403c',
|
|
961
|
+
800: '#292524',
|
|
962
|
+
900: '#1c1917',
|
|
963
|
+
950: '#0c0a09'
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
name: 'soho',
|
|
968
|
+
palette: {
|
|
969
|
+
0: '#ffffff',
|
|
970
|
+
50: '#ececec',
|
|
971
|
+
100: '#dedfdf',
|
|
972
|
+
200: '#c4c4c6',
|
|
973
|
+
300: '#adaeb0',
|
|
974
|
+
400: '#97979b',
|
|
975
|
+
500: '#7f8084',
|
|
976
|
+
600: '#6a6b70',
|
|
977
|
+
700: '#55565b',
|
|
978
|
+
800: '#3f4046',
|
|
979
|
+
900: '#2c2c34',
|
|
980
|
+
950: '#16161d'
|
|
981
|
+
}
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
name: 'viva',
|
|
985
|
+
palette: {
|
|
986
|
+
0: '#ffffff',
|
|
987
|
+
50: '#f3f3f3',
|
|
988
|
+
100: '#e7e7e8',
|
|
989
|
+
200: '#cfd0d0',
|
|
990
|
+
300: '#b7b8b9',
|
|
991
|
+
400: '#9fa1a1',
|
|
992
|
+
500: '#87898a',
|
|
993
|
+
600: '#6e7173',
|
|
994
|
+
700: '#565a5b',
|
|
995
|
+
800: '#3e4244',
|
|
996
|
+
900: '#262b2c',
|
|
997
|
+
950: '#0e1315'
|
|
998
|
+
}
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
name: 'ocean',
|
|
1002
|
+
palette: {
|
|
1003
|
+
0: '#ffffff',
|
|
1004
|
+
50: '#fbfcfc',
|
|
1005
|
+
100: '#F7F9F8',
|
|
1006
|
+
200: '#EFF3F2',
|
|
1007
|
+
300: '#DADEDD',
|
|
1008
|
+
400: '#B1B7B6',
|
|
1009
|
+
500: '#828787',
|
|
1010
|
+
600: '#5F7274',
|
|
1011
|
+
700: '#415B61',
|
|
1012
|
+
800: '#29444E',
|
|
1013
|
+
900: '#183240',
|
|
1014
|
+
950: '#0c1920'
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
];
|
|
1018
|
+
this.selectedPrimaryColor = computed(() => {
|
|
1019
|
+
return this.layoutService.layoutConfig().primary;
|
|
1020
|
+
}, ...(ngDevMode ? [{ debugName: "selectedPrimaryColor" }] : []));
|
|
1021
|
+
this.selectedSurfaceColor = computed(() => this.layoutService.layoutConfig().surface, ...(ngDevMode ? [{ debugName: "selectedSurfaceColor" }] : []));
|
|
1022
|
+
this.selectedPreset = computed(() => this.layoutService.layoutConfig().preset, ...(ngDevMode ? [{ debugName: "selectedPreset" }] : []));
|
|
1023
|
+
this.menuMode = computed(() => this.layoutService.layoutConfig().menuMode, ...(ngDevMode ? [{ debugName: "menuMode" }] : []));
|
|
1024
|
+
this.primaryColors = computed(() => {
|
|
1025
|
+
const presetPalette = presets[this.layoutService.layoutConfig().preset].primitive;
|
|
1026
|
+
const colors = [
|
|
1027
|
+
'emerald',
|
|
1028
|
+
'green',
|
|
1029
|
+
'lime',
|
|
1030
|
+
'orange',
|
|
1031
|
+
'amber',
|
|
1032
|
+
'yellow',
|
|
1033
|
+
'teal',
|
|
1034
|
+
'cyan',
|
|
1035
|
+
'sky',
|
|
1036
|
+
'blue',
|
|
1037
|
+
'indigo',
|
|
1038
|
+
'violet',
|
|
1039
|
+
'purple',
|
|
1040
|
+
'fuchsia',
|
|
1041
|
+
'pink',
|
|
1042
|
+
'rose'
|
|
1043
|
+
];
|
|
1044
|
+
const palettes = [{ name: 'noir', palette: {} }];
|
|
1045
|
+
colors.forEach((color) => {
|
|
1046
|
+
palettes.push({
|
|
1047
|
+
name: color,
|
|
1048
|
+
palette: presetPalette?.[color]
|
|
1049
|
+
});
|
|
1050
|
+
});
|
|
1051
|
+
return palettes;
|
|
1052
|
+
}, ...(ngDevMode ? [{ debugName: "primaryColors" }] : []));
|
|
1053
|
+
}
|
|
1054
|
+
ngOnInit() {
|
|
1055
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
1056
|
+
this.onPresetChange(this.layoutService.layoutConfig().preset);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
getPresetExt() {
|
|
1060
|
+
const color = this.primaryColors().find((c) => c.name === this.selectedPrimaryColor()) || {};
|
|
1061
|
+
const preset = this.layoutService.layoutConfig().preset;
|
|
1062
|
+
if (color.name === 'noir') {
|
|
1063
|
+
return {
|
|
1064
|
+
semantic: {
|
|
1065
|
+
primary: {
|
|
1066
|
+
50: '{surface.50}',
|
|
1067
|
+
100: '{surface.100}',
|
|
1068
|
+
200: '{surface.200}',
|
|
1069
|
+
300: '{surface.300}',
|
|
1070
|
+
400: '{surface.400}',
|
|
1071
|
+
500: '{surface.500}',
|
|
1072
|
+
600: '{surface.600}',
|
|
1073
|
+
700: '{surface.700}',
|
|
1074
|
+
800: '{surface.800}',
|
|
1075
|
+
900: '{surface.900}',
|
|
1076
|
+
950: '{surface.950}'
|
|
1077
|
+
},
|
|
1078
|
+
colorScheme: {
|
|
1079
|
+
light: {
|
|
1080
|
+
primary: {
|
|
1081
|
+
color: '{primary.950}',
|
|
1082
|
+
contrastColor: '#ffffff',
|
|
1083
|
+
hoverColor: '{primary.800}',
|
|
1084
|
+
activeColor: '{primary.700}'
|
|
1085
|
+
},
|
|
1086
|
+
highlight: {
|
|
1087
|
+
background: '{primary.950}',
|
|
1088
|
+
focusBackground: '{primary.700}',
|
|
1089
|
+
color: '#ffffff',
|
|
1090
|
+
focusColor: '#ffffff'
|
|
1091
|
+
}
|
|
1092
|
+
},
|
|
1093
|
+
dark: {
|
|
1094
|
+
primary: {
|
|
1095
|
+
color: '{primary.50}',
|
|
1096
|
+
contrastColor: '{primary.950}',
|
|
1097
|
+
hoverColor: '{primary.200}',
|
|
1098
|
+
activeColor: '{primary.300}'
|
|
1099
|
+
},
|
|
1100
|
+
highlight: {
|
|
1101
|
+
background: '{primary.50}',
|
|
1102
|
+
focusBackground: '{primary.300}',
|
|
1103
|
+
color: '{primary.950}',
|
|
1104
|
+
focusColor: '{primary.950}'
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
else if (preset === 'Nora') {
|
|
1112
|
+
return {
|
|
1113
|
+
semantic: {
|
|
1114
|
+
primary: color.palette,
|
|
1115
|
+
colorScheme: {
|
|
1116
|
+
light: {
|
|
1117
|
+
primary: {
|
|
1118
|
+
color: '{primary.600}',
|
|
1119
|
+
contrastColor: '#ffffff',
|
|
1120
|
+
hoverColor: '{primary.700}',
|
|
1121
|
+
activeColor: '{primary.800}'
|
|
1122
|
+
},
|
|
1123
|
+
highlight: {
|
|
1124
|
+
background: '{primary.600}',
|
|
1125
|
+
focusBackground: '{primary.700}',
|
|
1126
|
+
color: '#ffffff',
|
|
1127
|
+
focusColor: '#ffffff'
|
|
1128
|
+
}
|
|
1129
|
+
},
|
|
1130
|
+
dark: {
|
|
1131
|
+
primary: {
|
|
1132
|
+
color: '{primary.500}',
|
|
1133
|
+
contrastColor: '{surface.900}',
|
|
1134
|
+
hoverColor: '{primary.400}',
|
|
1135
|
+
activeColor: '{primary.300}'
|
|
1136
|
+
},
|
|
1137
|
+
highlight: {
|
|
1138
|
+
background: '{primary.500}',
|
|
1139
|
+
focusBackground: '{primary.400}',
|
|
1140
|
+
color: '{surface.900}',
|
|
1141
|
+
focusColor: '{surface.900}'
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
else {
|
|
1149
|
+
return {
|
|
1150
|
+
semantic: {
|
|
1151
|
+
primary: color.palette,
|
|
1152
|
+
colorScheme: {
|
|
1153
|
+
light: {
|
|
1154
|
+
primary: {
|
|
1155
|
+
color: '{primary.500}',
|
|
1156
|
+
contrastColor: '#ffffff',
|
|
1157
|
+
hoverColor: '{primary.600}',
|
|
1158
|
+
activeColor: '{primary.700}'
|
|
1159
|
+
},
|
|
1160
|
+
highlight: {
|
|
1161
|
+
background: '{primary.50}',
|
|
1162
|
+
focusBackground: '{primary.100}',
|
|
1163
|
+
color: '{primary.700}',
|
|
1164
|
+
focusColor: '{primary.800}'
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
dark: {
|
|
1168
|
+
primary: {
|
|
1169
|
+
color: '{primary.400}',
|
|
1170
|
+
contrastColor: '{surface.900}',
|
|
1171
|
+
hoverColor: '{primary.300}',
|
|
1172
|
+
activeColor: '{primary.200}'
|
|
1173
|
+
},
|
|
1174
|
+
highlight: {
|
|
1175
|
+
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
|
|
1176
|
+
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
|
|
1177
|
+
color: 'rgba(255,255,255,.87)',
|
|
1178
|
+
focusColor: 'rgba(255,255,255,.87)'
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
updateColors(event, type, color) {
|
|
1187
|
+
if (type === 'primary') {
|
|
1188
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1189
|
+
...state,
|
|
1190
|
+
primary: color.name
|
|
1191
|
+
}));
|
|
1192
|
+
}
|
|
1193
|
+
else if (type === 'surface') {
|
|
1194
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1195
|
+
...state,
|
|
1196
|
+
surface: color.name
|
|
1197
|
+
}));
|
|
1198
|
+
}
|
|
1199
|
+
this.applyTheme(type, color);
|
|
1200
|
+
event.stopPropagation();
|
|
1201
|
+
}
|
|
1202
|
+
applyTheme(type, color) {
|
|
1203
|
+
if (type === 'primary') {
|
|
1204
|
+
updatePreset(this.getPresetExt());
|
|
1205
|
+
}
|
|
1206
|
+
else if (type === 'surface') {
|
|
1207
|
+
updateSurfacePalette(color.palette);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
onPresetChange(event) {
|
|
1211
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1212
|
+
...state,
|
|
1213
|
+
preset: event
|
|
1214
|
+
}));
|
|
1215
|
+
const preset = presets[event];
|
|
1216
|
+
const surfacePalette = this.surfaces.find((s) => s.name === this.selectedSurfaceColor())?.palette;
|
|
1217
|
+
$t().preset(preset).preset(this.getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
|
|
1218
|
+
}
|
|
1219
|
+
onMenuModeChange(event) {
|
|
1220
|
+
this.layoutService.layoutConfig.update((prev) => ({
|
|
1221
|
+
...prev,
|
|
1222
|
+
menuMode: event
|
|
1223
|
+
}));
|
|
1224
|
+
}
|
|
1225
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1226
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: AppConfiguratorComponent, isStandalone: true, selector: "app-configurator", host: { classAttribute: "hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]" }, ngImport: i0, template: `
|
|
1227
|
+
<div class="flex flex-col gap-4">
|
|
1228
|
+
<div>
|
|
1229
|
+
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
1230
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1231
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
1232
|
+
<button
|
|
1233
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1234
|
+
id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
|
|
1235
|
+
type="button"
|
|
1236
|
+
[ngClass]="{
|
|
1237
|
+
'outline-primary': primaryColor.name === selectedPrimaryColor()
|
|
1238
|
+
}"
|
|
1239
|
+
[style]="{
|
|
1240
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
1241
|
+
}"
|
|
1242
|
+
[title]="primaryColor.name"
|
|
1243
|
+
(click)="updateColors($event, 'primary', primaryColor)"></button>
|
|
1244
|
+
}
|
|
1245
|
+
</div>
|
|
1246
|
+
</div>
|
|
1247
|
+
<div>
|
|
1248
|
+
<span class="text-sm text-muted-color font-semibold">Surface</span>
|
|
1249
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1250
|
+
@for (surface of surfaces; track surface.name) {
|
|
1251
|
+
<button
|
|
1252
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1253
|
+
id="oip-app-configurator-surface-color-{{ surface.name }}"
|
|
1254
|
+
type="button"
|
|
1255
|
+
[ngClass]="{
|
|
1256
|
+
'outline-primary': selectedSurfaceColor()
|
|
1257
|
+
? selectedSurfaceColor() === surface.name
|
|
1258
|
+
: layoutService.layoutConfig().darkTheme
|
|
1259
|
+
? surface.name === 'zinc'
|
|
1260
|
+
: surface.name === 'slate'
|
|
1261
|
+
}"
|
|
1262
|
+
[style]="{
|
|
1263
|
+
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
1264
|
+
}"
|
|
1265
|
+
[title]="surface.name"
|
|
1266
|
+
(click)="updateColors($event, 'surface', surface)"></button>
|
|
1267
|
+
}
|
|
1268
|
+
</div>
|
|
1269
|
+
</div>
|
|
1270
|
+
<div class="flex flex-col gap-2">
|
|
1271
|
+
<span class="text-sm text-muted-color font-semibold">Presets</span>
|
|
1272
|
+
<p-selectButton
|
|
1273
|
+
id="oip-app-configurator-preset-select-button"
|
|
1274
|
+
size="small"
|
|
1275
|
+
[allowEmpty]="false"
|
|
1276
|
+
[ngModel]="selectedPreset()"
|
|
1277
|
+
[options]="presets"
|
|
1278
|
+
(ngModelChange)="onPresetChange($event)" />
|
|
1279
|
+
</div>
|
|
1280
|
+
@if (showMenuModeButton()) {
|
|
1281
|
+
<div class="flex flex-col gap-2">
|
|
1282
|
+
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
|
|
1283
|
+
<p-selectButton
|
|
1284
|
+
id="oip-app-configurator-menu-mode-select-button"
|
|
1285
|
+
size="small"
|
|
1286
|
+
[allowEmpty]="false"
|
|
1287
|
+
[ngModel]="menuMode()"
|
|
1288
|
+
[options]="menuModeOptions"
|
|
1289
|
+
(ngModelChange)="onMenuModeChange($event)" />
|
|
1290
|
+
</div>
|
|
1291
|
+
}
|
|
1292
|
+
</div>
|
|
1293
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.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"] }] }); }
|
|
1294
|
+
}
|
|
1295
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppConfiguratorComponent, decorators: [{
|
|
1296
|
+
type: Component,
|
|
1297
|
+
args: [{
|
|
1298
|
+
selector: 'app-configurator',
|
|
1299
|
+
standalone: true,
|
|
1300
|
+
imports: [CommonModule, FormsModule, SelectButtonModule],
|
|
1301
|
+
template: `
|
|
1302
|
+
<div class="flex flex-col gap-4">
|
|
1303
|
+
<div>
|
|
1304
|
+
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
1305
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1306
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
1307
|
+
<button
|
|
1308
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1309
|
+
id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
|
|
1310
|
+
type="button"
|
|
1311
|
+
[ngClass]="{
|
|
1312
|
+
'outline-primary': primaryColor.name === selectedPrimaryColor()
|
|
1313
|
+
}"
|
|
1314
|
+
[style]="{
|
|
1315
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
1316
|
+
}"
|
|
1317
|
+
[title]="primaryColor.name"
|
|
1318
|
+
(click)="updateColors($event, 'primary', primaryColor)"></button>
|
|
1319
|
+
}
|
|
1320
|
+
</div>
|
|
1321
|
+
</div>
|
|
1322
|
+
<div>
|
|
1323
|
+
<span class="text-sm text-muted-color font-semibold">Surface</span>
|
|
1324
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1325
|
+
@for (surface of surfaces; track surface.name) {
|
|
1326
|
+
<button
|
|
1327
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1328
|
+
id="oip-app-configurator-surface-color-{{ surface.name }}"
|
|
1329
|
+
type="button"
|
|
1330
|
+
[ngClass]="{
|
|
1331
|
+
'outline-primary': selectedSurfaceColor()
|
|
1332
|
+
? selectedSurfaceColor() === surface.name
|
|
1333
|
+
: layoutService.layoutConfig().darkTheme
|
|
1334
|
+
? surface.name === 'zinc'
|
|
1335
|
+
: surface.name === 'slate'
|
|
1336
|
+
}"
|
|
1337
|
+
[style]="{
|
|
1338
|
+
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
1339
|
+
}"
|
|
1340
|
+
[title]="surface.name"
|
|
1341
|
+
(click)="updateColors($event, 'surface', surface)"></button>
|
|
1342
|
+
}
|
|
1343
|
+
</div>
|
|
1344
|
+
</div>
|
|
1345
|
+
<div class="flex flex-col gap-2">
|
|
1346
|
+
<span class="text-sm text-muted-color font-semibold">Presets</span>
|
|
1347
|
+
<p-selectButton
|
|
1348
|
+
id="oip-app-configurator-preset-select-button"
|
|
1349
|
+
size="small"
|
|
1350
|
+
[allowEmpty]="false"
|
|
1351
|
+
[ngModel]="selectedPreset()"
|
|
1352
|
+
[options]="presets"
|
|
1353
|
+
(ngModelChange)="onPresetChange($event)" />
|
|
1354
|
+
</div>
|
|
1355
|
+
@if (showMenuModeButton()) {
|
|
1356
|
+
<div class="flex flex-col gap-2">
|
|
1357
|
+
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
|
|
1358
|
+
<p-selectButton
|
|
1359
|
+
id="oip-app-configurator-menu-mode-select-button"
|
|
1360
|
+
size="small"
|
|
1361
|
+
[allowEmpty]="false"
|
|
1362
|
+
[ngModel]="menuMode()"
|
|
1363
|
+
[options]="menuModeOptions"
|
|
1364
|
+
(ngModelChange)="onMenuModeChange($event)" />
|
|
1365
|
+
</div>
|
|
1366
|
+
}
|
|
1367
|
+
</div>
|
|
1368
|
+
`,
|
|
1369
|
+
host: {
|
|
1370
|
+
class: 'hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]'
|
|
1371
|
+
}
|
|
1372
|
+
}]
|
|
1373
|
+
}] });
|
|
1374
|
+
|
|
1375
|
+
class LogoComponent {
|
|
1376
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LogoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1377
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: LogoComponent, isStandalone: true, selector: "logo", inputs: { width: "width", height: "height" }, ngImport: i0, template: `
|
|
1378
|
+
<svg
|
|
1379
|
+
viewBox="0.8516 1.7159 60.0074 64.7142"
|
|
1380
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1381
|
+
[attr.height]="height + 'px'"
|
|
1382
|
+
[attr.width]="width + 'px'">
|
|
1383
|
+
<path
|
|
1384
|
+
class="primary-logo-color"
|
|
1385
|
+
d="M -130.45 -104.78 C -130.45 -105.9 -130.43 -107.01 -130.45 -108.13 C -130.49 -108.52 -130.28 -108.9 -129.92 -109.07 C -125.87 -111.4 -121.82 -113.74 -117.77 -116.08 C -115.7 -117.26 -113.63 -118.45 -111.58 -119.67 C -111.26 -119.89 -110.83 -119.89 -110.51 -119.67 C -101.66 -114.53 -92.787 -109.41 -83.915 -104.29 C -83.752 -104.2 -83.479 -104.16 -83.475 -103.94 C -83.472 -103.72 -83.766 -103.65 -83.947 -103.54 C -86.326 -102.16 -88.716 -100.79 -91.092 -99.39 C -91.377 -99.18 -91.761 -99.18 -92.046 -99.39 C -98.211 -102.98 -104.38 -106.55 -110.56 -110.12 C -110.85 -110.33 -111.23 -110.33 -111.52 -110.12 C -114.88 -108.16 -118.25 -106.22 -121.63 -104.28 C -122.01 -104.11 -122.24 -103.71 -122.2 -103.3 C -122.18 -101.11 -122.2 -98.922 -122.2 -96.736 C -122.19 -95.98 -122.21 -95.98 -122.84 -96.335 C -125.2 -97.7 -127.57 -99.07 -129.93 -100.42 C -130.27 -100.57 -130.49 -100.92 -130.46 -101.3 C -130.43 -102.46 -130.45 -103.62 -130.45 -104.78 Z"
|
|
1386
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1387
|
+
<path
|
|
1388
|
+
class="primary-logo-color"
|
|
1389
|
+
d="M -70.504 -100.94 L -70.504 -90.438 C -70.447 -89.98 -70.692 -89.537 -71.11 -89.342 C -78.942 -84.839 -86.769 -80.325 -94.592 -75.8 C -95.635 -75.2 -96.684 -74.612 -97.713 -73.988 C -98.17 -73.708 -98.255 -73.846 -98.255 -74.314 L -98.255 -82.785 C -98.268 -83.116 -98.07 -83.419 -97.762 -83.541 C -92.003 -86.86 -86.269 -90.236 -80.468 -93.47 C -79.181 -94.179 -78.667 -94.934 -78.731 -96.441 C -78.869 -99.76 -78.791 -103.09 -78.755 -106.42 C -78.694 -107 -79.02 -107.56 -79.56 -107.8 C -81.436 -108.83 -83.28 -109.93 -85.138 -110.99 C -85.734 -111.34 -85.734 -111.34 -85.113 -111.7 C -82.748 -113.07 -80.379 -114.43 -78.021 -115.82 C -77.707 -116.05 -77.283 -116.06 -76.957 -115.84 C -74.962 -114.66 -72.953 -113.5 -70.929 -112.37 C -70.62 -112.19 -70.456 -111.84 -70.521 -111.49 C -70.514 -107.99 -70.508 -104.48 -70.504 -100.94 Z"
|
|
1390
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1391
|
+
<path
|
|
1392
|
+
class="primary-logo-color"
|
|
1393
|
+
d="M -108.68 -85.743 L -108.68 -75.169 C -108.72 -74.754 -108.5 -74.358 -108.12 -74.179 C -104.77 -72.267 -101.44 -70.339 -98.117 -68.396 C -97.762 -68.141 -97.284 -68.141 -96.929 -68.396 C -95.028 -69.527 -93.096 -70.598 -91.195 -71.725 C -90.667 -72.041 -90.581 -71.892 -90.581 -71.371 C -90.596 -68.591 -90.596 -65.811 -90.581 -63.03 C -90.551 -62.7 -90.729 -62.386 -91.028 -62.243 C -93.083 -61.073 -95.13 -59.891 -97.17 -58.697 C -97.436 -58.537 -97.775 -58.569 -98.007 -58.775 C -102.74 -61.517 -107.47 -64.254 -112.22 -66.984 C -113.63 -67.796 -115.01 -68.615 -116.42 -69.406 C -116.77 -69.561 -116.97 -69.913 -116.94 -70.286 C -116.93 -80.555 -116.93 -90.823 -116.94 -101.09 C -116.94 -101.63 -116.86 -101.75 -116.35 -101.44 C -113.98 -100.05 -111.59 -98.667 -109.19 -97.303 C -108.84 -97.135 -108.62 -96.76 -108.66 -96.367 C -108.68 -92.833 -108.69 -89.291 -108.68 -85.743 Z"
|
|
1394
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1395
|
+
<path
|
|
1396
|
+
class="secondary-logo-color"
|
|
1397
|
+
d="M -122.18 -85.807 L -122.18 -82.129 C -122.18 -81.637 -122.34 -81.615 -122.72 -81.839 C -125.16 -83.257 -127.6 -84.667 -130.05 -86.069 C -130.35 -86.219 -130.53 -86.535 -130.5 -86.867 L -130.5 -94.09 C -130.5 -94.64 -130.34 -94.679 -129.89 -94.417 C -127.49 -92.998 -125.09 -91.607 -122.67 -90.243 C -122.35 -90.103 -122.15 -89.772 -122.18 -89.42 C -122.21 -88.214 -122.18 -87.012 -122.18 -85.807 Z M -82.688 -119.15 C -83.954 -118.41 -85.17 -117.7 -86.365 -117.02 C -87.748 -116.22 -89.138 -115.44 -90.514 -114.63 C -90.761 -114.45 -91.093 -114.45 -91.34 -114.63 C -93.432 -115.86 -95.535 -117.07 -97.649 -118.27 C -98.053 -118.5 -98.191 -118.63 -97.67 -118.93 C -95.216 -120.32 -92.776 -121.74 -90.337 -123.15 C -90.134 -123.33 -89.845 -123.36 -89.61 -123.23 L -82.918 -119.33 C -82.862 -119.28 -82.812 -119.24 -82.688 -119.15 Z M -85.365 -65.616 L -85.365 -72.062 L -85.365 -74.622 C -85.403 -74.928 -85.24 -75.223 -84.961 -75.353 C -82.886 -76.534 -80.83 -77.736 -78.77 -78.931 C -78.174 -79.286 -78.135 -79.257 -78.135 -78.576 L -78.135 -70.303 C -78.135 -69.991 -78.135 -69.711 -78.468 -69.52 C -80.656 -68.275 -82.833 -67.013 -85.014 -65.761 C -85.127 -65.704 -85.245 -65.655 -85.365 -65.616 Z"
|
|
1398
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1399
|
+
</svg>
|
|
1400
|
+
`, isInline: true }); }
|
|
1401
|
+
}
|
|
1402
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LogoComponent, decorators: [{
|
|
1403
|
+
type: Component,
|
|
1404
|
+
args: [{
|
|
1405
|
+
selector: 'logo',
|
|
1406
|
+
standalone: true,
|
|
1407
|
+
template: `
|
|
1408
|
+
<svg
|
|
1409
|
+
viewBox="0.8516 1.7159 60.0074 64.7142"
|
|
1410
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1411
|
+
[attr.height]="height + 'px'"
|
|
1412
|
+
[attr.width]="width + 'px'">
|
|
1413
|
+
<path
|
|
1414
|
+
class="primary-logo-color"
|
|
1415
|
+
d="M -130.45 -104.78 C -130.45 -105.9 -130.43 -107.01 -130.45 -108.13 C -130.49 -108.52 -130.28 -108.9 -129.92 -109.07 C -125.87 -111.4 -121.82 -113.74 -117.77 -116.08 C -115.7 -117.26 -113.63 -118.45 -111.58 -119.67 C -111.26 -119.89 -110.83 -119.89 -110.51 -119.67 C -101.66 -114.53 -92.787 -109.41 -83.915 -104.29 C -83.752 -104.2 -83.479 -104.16 -83.475 -103.94 C -83.472 -103.72 -83.766 -103.65 -83.947 -103.54 C -86.326 -102.16 -88.716 -100.79 -91.092 -99.39 C -91.377 -99.18 -91.761 -99.18 -92.046 -99.39 C -98.211 -102.98 -104.38 -106.55 -110.56 -110.12 C -110.85 -110.33 -111.23 -110.33 -111.52 -110.12 C -114.88 -108.16 -118.25 -106.22 -121.63 -104.28 C -122.01 -104.11 -122.24 -103.71 -122.2 -103.3 C -122.18 -101.11 -122.2 -98.922 -122.2 -96.736 C -122.19 -95.98 -122.21 -95.98 -122.84 -96.335 C -125.2 -97.7 -127.57 -99.07 -129.93 -100.42 C -130.27 -100.57 -130.49 -100.92 -130.46 -101.3 C -130.43 -102.46 -130.45 -103.62 -130.45 -104.78 Z"
|
|
1416
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1417
|
+
<path
|
|
1418
|
+
class="primary-logo-color"
|
|
1419
|
+
d="M -70.504 -100.94 L -70.504 -90.438 C -70.447 -89.98 -70.692 -89.537 -71.11 -89.342 C -78.942 -84.839 -86.769 -80.325 -94.592 -75.8 C -95.635 -75.2 -96.684 -74.612 -97.713 -73.988 C -98.17 -73.708 -98.255 -73.846 -98.255 -74.314 L -98.255 -82.785 C -98.268 -83.116 -98.07 -83.419 -97.762 -83.541 C -92.003 -86.86 -86.269 -90.236 -80.468 -93.47 C -79.181 -94.179 -78.667 -94.934 -78.731 -96.441 C -78.869 -99.76 -78.791 -103.09 -78.755 -106.42 C -78.694 -107 -79.02 -107.56 -79.56 -107.8 C -81.436 -108.83 -83.28 -109.93 -85.138 -110.99 C -85.734 -111.34 -85.734 -111.34 -85.113 -111.7 C -82.748 -113.07 -80.379 -114.43 -78.021 -115.82 C -77.707 -116.05 -77.283 -116.06 -76.957 -115.84 C -74.962 -114.66 -72.953 -113.5 -70.929 -112.37 C -70.62 -112.19 -70.456 -111.84 -70.521 -111.49 C -70.514 -107.99 -70.508 -104.48 -70.504 -100.94 Z"
|
|
1420
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1421
|
+
<path
|
|
1422
|
+
class="primary-logo-color"
|
|
1423
|
+
d="M -108.68 -85.743 L -108.68 -75.169 C -108.72 -74.754 -108.5 -74.358 -108.12 -74.179 C -104.77 -72.267 -101.44 -70.339 -98.117 -68.396 C -97.762 -68.141 -97.284 -68.141 -96.929 -68.396 C -95.028 -69.527 -93.096 -70.598 -91.195 -71.725 C -90.667 -72.041 -90.581 -71.892 -90.581 -71.371 C -90.596 -68.591 -90.596 -65.811 -90.581 -63.03 C -90.551 -62.7 -90.729 -62.386 -91.028 -62.243 C -93.083 -61.073 -95.13 -59.891 -97.17 -58.697 C -97.436 -58.537 -97.775 -58.569 -98.007 -58.775 C -102.74 -61.517 -107.47 -64.254 -112.22 -66.984 C -113.63 -67.796 -115.01 -68.615 -116.42 -69.406 C -116.77 -69.561 -116.97 -69.913 -116.94 -70.286 C -116.93 -80.555 -116.93 -90.823 -116.94 -101.09 C -116.94 -101.63 -116.86 -101.75 -116.35 -101.44 C -113.98 -100.05 -111.59 -98.667 -109.19 -97.303 C -108.84 -97.135 -108.62 -96.76 -108.66 -96.367 C -108.68 -92.833 -108.69 -89.291 -108.68 -85.743 Z"
|
|
1424
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1425
|
+
<path
|
|
1426
|
+
class="secondary-logo-color"
|
|
1427
|
+
d="M -122.18 -85.807 L -122.18 -82.129 C -122.18 -81.637 -122.34 -81.615 -122.72 -81.839 C -125.16 -83.257 -127.6 -84.667 -130.05 -86.069 C -130.35 -86.219 -130.53 -86.535 -130.5 -86.867 L -130.5 -94.09 C -130.5 -94.64 -130.34 -94.679 -129.89 -94.417 C -127.49 -92.998 -125.09 -91.607 -122.67 -90.243 C -122.35 -90.103 -122.15 -89.772 -122.18 -89.42 C -122.21 -88.214 -122.18 -87.012 -122.18 -85.807 Z M -82.688 -119.15 C -83.954 -118.41 -85.17 -117.7 -86.365 -117.02 C -87.748 -116.22 -89.138 -115.44 -90.514 -114.63 C -90.761 -114.45 -91.093 -114.45 -91.34 -114.63 C -93.432 -115.86 -95.535 -117.07 -97.649 -118.27 C -98.053 -118.5 -98.191 -118.63 -97.67 -118.93 C -95.216 -120.32 -92.776 -121.74 -90.337 -123.15 C -90.134 -123.33 -89.845 -123.36 -89.61 -123.23 L -82.918 -119.33 C -82.862 -119.28 -82.812 -119.24 -82.688 -119.15 Z M -85.365 -65.616 L -85.365 -72.062 L -85.365 -74.622 C -85.403 -74.928 -85.24 -75.223 -84.961 -75.353 C -82.886 -76.534 -80.83 -77.736 -78.77 -78.931 C -78.174 -79.286 -78.135 -79.257 -78.135 -78.576 L -78.135 -70.303 C -78.135 -69.991 -78.135 -69.711 -78.468 -69.52 C -80.656 -68.275 -82.833 -67.013 -85.014 -65.761 C -85.127 -65.704 -85.245 -65.655 -85.365 -65.616 Z"
|
|
1428
|
+
transform="matrix(1, 0, 0, 1, 131.35482788085938, 125.0257797241211)" />
|
|
1429
|
+
</svg>
|
|
1430
|
+
`
|
|
1431
|
+
}]
|
|
1432
|
+
}], propDecorators: { width: [{
|
|
1433
|
+
type: Input
|
|
1434
|
+
}], height: [{
|
|
1435
|
+
type: Input
|
|
1436
|
+
}] } });
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* SecurityService extends OidcSecurityService to manage authentication,
|
|
1440
|
+
* token handling, and user role access in an Angular application.
|
|
1441
|
+
*
|
|
1442
|
+
* It provides helper methods for checking authentication, managing tokens,
|
|
1443
|
+
* determining user roles, and performing logout and refresh operations.
|
|
1444
|
+
*/
|
|
1445
|
+
class SecurityService extends OidcSecurityService {
|
|
1446
|
+
/**
|
|
1447
|
+
* Initializes service and subscribes to authentication events.
|
|
1448
|
+
* When a 'NewAuthenticationResult' event is received, the `auth` method is called.
|
|
1449
|
+
*/
|
|
1450
|
+
constructor() {
|
|
1451
|
+
super();
|
|
1452
|
+
/**
|
|
1453
|
+
* Handles angular OIDC events.
|
|
1454
|
+
*/
|
|
1455
|
+
this.publicEventsService = inject(PublicEventsService);
|
|
1456
|
+
/**
|
|
1457
|
+
* Stores the latest login response from checkAuth().
|
|
1458
|
+
*/
|
|
1459
|
+
this.loginResponse = new BehaviorSubject(null);
|
|
1460
|
+
/**
|
|
1461
|
+
* Stores the decoded access token payload.
|
|
1462
|
+
*/
|
|
1463
|
+
this.payload = new BehaviorSubject(null);
|
|
1464
|
+
this.publicEventsService
|
|
1465
|
+
.registerForEvents()
|
|
1466
|
+
.pipe(filter((event) => event.type === EventTypes.NewAuthenticationResult))
|
|
1467
|
+
.subscribe(() => {
|
|
1468
|
+
this.auth();
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Returns the ID token for the sign-in.
|
|
1473
|
+
* @returns A string with the id token.
|
|
1474
|
+
*/
|
|
1475
|
+
getAccessToken() {
|
|
1476
|
+
return this.loginResponse.pipe(map((data) => data?.accessToken));
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Indicates whether the current user has the 'admin' role.
|
|
1480
|
+
*
|
|
1481
|
+
* @returns {boolean} True if the user is an admin, false otherwise.
|
|
1482
|
+
*/
|
|
1483
|
+
get isAdmin() {
|
|
1484
|
+
return this.payload.getValue()?.realm_access?.roles?.includes('admin');
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* Initiates authentication check and updates login response, user data,
|
|
1488
|
+
* and decoded token payload if authenticated.
|
|
1489
|
+
*/
|
|
1490
|
+
auth() {
|
|
1491
|
+
super.checkAuth().subscribe((_response) => {
|
|
1492
|
+
this.loginResponse.next(_response);
|
|
1493
|
+
this.userData = _response.userData;
|
|
1494
|
+
this.getPayloadFromAccessToken().subscribe((_token) => {
|
|
1495
|
+
this.payload.next(_token);
|
|
1496
|
+
});
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Performs logout and clears the local token payload.
|
|
1501
|
+
*
|
|
1502
|
+
* @param {string} [configId] Optional configuration ID for logout.
|
|
1503
|
+
* @param {LogoutAuthOptions} [logoutAuthOptions] Optional logout options.
|
|
1504
|
+
*/
|
|
1505
|
+
logout(configId, logoutAuthOptions) {
|
|
1506
|
+
this.logoff(configId, logoutAuthOptions).subscribe((x) => this.payload.next(x));
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Completes the BehaviorSubjects when the service is destroyed to avoid memory leaks.
|
|
1510
|
+
*/
|
|
1511
|
+
ngOnDestroy() {
|
|
1512
|
+
this.loginResponse.complete();
|
|
1513
|
+
this.payload.complete();
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Checks whether the current access token is expired based on the 'exp' claim.
|
|
1517
|
+
*
|
|
1518
|
+
* @returns {Observable<boolean>} Observable that emits true if the token is expired.
|
|
1519
|
+
*/
|
|
1520
|
+
isTokenExpired() {
|
|
1521
|
+
return this.getPayloadFromAccessToken().pipe(map((payload) => {
|
|
1522
|
+
return payload.exp < Math.floor(Date.now() / 1000);
|
|
1523
|
+
}));
|
|
1524
|
+
}
|
|
1525
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1526
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityService, providedIn: 'root' }); }
|
|
1527
|
+
}
|
|
1528
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityService, decorators: [{
|
|
1529
|
+
type: Injectable,
|
|
1530
|
+
args: [{ providedIn: 'root' }]
|
|
1531
|
+
}], ctorParameters: () => [] });
|
|
1532
|
+
|
|
1533
|
+
/**
|
|
1534
|
+
* UserService is responsible for retrieving and handling user-related data,
|
|
1535
|
+
* including the user's photo and short label for avatar display.
|
|
1536
|
+
*/
|
|
1537
|
+
class UserService {
|
|
1538
|
+
constructor() {
|
|
1539
|
+
this.securityService = inject(SecurityService);
|
|
1540
|
+
this.baseDataService = inject(BaseDataService);
|
|
1541
|
+
/**
|
|
1542
|
+
* Stores the user's photo as a data URL or binary blob, depending on how it's processed.
|
|
1543
|
+
*/
|
|
1544
|
+
this.photo = null;
|
|
1545
|
+
/**
|
|
1546
|
+
* Indicates whether the user photo has finished loading.
|
|
1547
|
+
*/
|
|
1548
|
+
this.photoLoaded = false;
|
|
1549
|
+
this.getUserPhoto();
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Returns a short label composed of the user's initials.
|
|
1553
|
+
* Typically used for avatar display when a photo is unavailable.
|
|
1554
|
+
*/
|
|
1555
|
+
get shortLabel() {
|
|
1556
|
+
const data = this.securityService.userData;
|
|
1557
|
+
return data.given_name[0] + data.family_name[0];
|
|
1558
|
+
}
|
|
1559
|
+
get userName() {
|
|
1560
|
+
const data = this.securityService.userData;
|
|
1561
|
+
return `${data.given_name} ${data.family_name}`;
|
|
1562
|
+
}
|
|
1563
|
+
/**
|
|
1564
|
+
* Initiates an HTTP request to fetch the user's photo based on their email,
|
|
1565
|
+
* and updates the `photo` and `photoLoaded` properties accordingly.
|
|
1566
|
+
*/
|
|
1567
|
+
getUserPhoto() {
|
|
1568
|
+
const url = `${this.baseDataService.baseUrl}api/user-profile/get-user-photo?email=${this.securityService.userData.email}`;
|
|
1569
|
+
this.baseDataService.getBlob(url).then((data) => {
|
|
1570
|
+
this.createImageFromBlob(data);
|
|
1571
|
+
this.photoLoaded = true;
|
|
1572
|
+
}, (error) => {
|
|
1573
|
+
console.log(error);
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Converts a Blob image into a Base64 data URL and stores it in the `photo` property.
|
|
1578
|
+
*
|
|
1579
|
+
* @param image - The image Blob to be converted.
|
|
1580
|
+
*/
|
|
1581
|
+
createImageFromBlob(image) {
|
|
1582
|
+
const reader = new FileReader();
|
|
1583
|
+
reader.addEventListener('load', () => {
|
|
1584
|
+
this.photo = reader.result;
|
|
1585
|
+
}, false);
|
|
1586
|
+
if (image) {
|
|
1587
|
+
reader.readAsDataURL(image);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1591
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: UserService }); }
|
|
1592
|
+
}
|
|
1593
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: UserService, decorators: [{
|
|
1594
|
+
type: Injectable
|
|
1595
|
+
}], ctorParameters: () => [] });
|
|
1596
|
+
|
|
1597
|
+
class AppTopbar {
|
|
1598
|
+
constructor(layoutService) {
|
|
1599
|
+
this.layoutService = layoutService;
|
|
1600
|
+
this.securityService = inject(SecurityService);
|
|
1601
|
+
this.topBarService = inject(TopBarService);
|
|
1602
|
+
this.userService = inject(UserService);
|
|
1603
|
+
}
|
|
1604
|
+
toggleDarkMode() {
|
|
1605
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1606
|
+
...state,
|
|
1607
|
+
darkTheme: !state.darkTheme
|
|
1608
|
+
}));
|
|
1609
|
+
}
|
|
1610
|
+
logoutKeyDown($event) {
|
|
1611
|
+
if ($event.key === 'Enter') {
|
|
1612
|
+
this.securityService.logout();
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppTopbar, deps: [{ token: LayoutService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1616
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: AppTopbar, isStandalone: true, selector: "app-topbar", ngImport: i0, template: ` <div class="layout-topbar">
|
|
1617
|
+
<div class="layout-topbar-logo-container">
|
|
1618
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
1619
|
+
<i class="pi pi-bars"></i>
|
|
1620
|
+
</button>
|
|
1621
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
1622
|
+
<logo [height]="36" [width]="36"></logo>
|
|
1623
|
+
<span>OIP</span>
|
|
1624
|
+
</a>
|
|
1625
|
+
</div>
|
|
1626
|
+
|
|
1627
|
+
@if (securityService.isAdmin && topBarService.topBarItems.length > 0) {
|
|
1628
|
+
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
1629
|
+
<p-tablist>
|
|
1630
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
1631
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
1632
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
1633
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
1634
|
+
</p-tab>
|
|
1635
|
+
}
|
|
1636
|
+
</p-tablist>
|
|
1637
|
+
</p-tabs>
|
|
1638
|
+
}
|
|
1639
|
+
<div class="layout-topbar-actions">
|
|
1640
|
+
<div class="layout-config-menu">
|
|
1641
|
+
<p-button
|
|
1642
|
+
class="layout-topbar-action"
|
|
1643
|
+
id="oip-app-topbar-theme-button"
|
|
1644
|
+
severity="secondary"
|
|
1645
|
+
type="button"
|
|
1646
|
+
[rounded]="true"
|
|
1647
|
+
[text]="true"
|
|
1648
|
+
(click)="toggleDarkMode()">
|
|
1649
|
+
<i
|
|
1650
|
+
class="pi"
|
|
1651
|
+
[ngClass]="{
|
|
1652
|
+
'pi-moon': layoutService.isDarkTheme(),
|
|
1653
|
+
'pi-sun': !layoutService.isDarkTheme()
|
|
1654
|
+
}"></i>
|
|
1655
|
+
</p-button>
|
|
1656
|
+
<div class="relative">
|
|
1657
|
+
<p-button
|
|
1658
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
1659
|
+
enterActiveClass="animate-scalein"
|
|
1660
|
+
enterFromClass="hidden"
|
|
1661
|
+
id="oip-app-topbar-palette-button"
|
|
1662
|
+
leaveActiveClass="animate-fadeout"
|
|
1663
|
+
leaveToClass="hidden"
|
|
1664
|
+
pStyleClass="@next"
|
|
1665
|
+
[hideOnOutsideClick]="true"
|
|
1666
|
+
[rounded]="true">
|
|
1667
|
+
<i class="pi pi-palette"></i>
|
|
1668
|
+
</p-button>
|
|
1669
|
+
<app-configurator />
|
|
1670
|
+
</div>
|
|
1671
|
+
</div>
|
|
1672
|
+
|
|
1673
|
+
<button
|
|
1674
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
1675
|
+
enterActiveClass="animate-scalein"
|
|
1676
|
+
enterFromClass="hidden"
|
|
1677
|
+
id="oip-app-topbar-menu-expand-button"
|
|
1678
|
+
leaveActiveClass="animate-fadeout"
|
|
1679
|
+
leaveToClass="hidden"
|
|
1680
|
+
pStyleClass="@next"
|
|
1681
|
+
[hideOnOutsideClick]="true">
|
|
1682
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
1683
|
+
</button>
|
|
1684
|
+
|
|
1685
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
1686
|
+
<div class="layout-topbar-menu-content">
|
|
1687
|
+
<button
|
|
1688
|
+
class="layout-topbar-action"
|
|
1689
|
+
id="oip-app-topbar-logout-button"
|
|
1690
|
+
type="button"
|
|
1691
|
+
(click)="securityService.logout()"
|
|
1692
|
+
(keydown)="logoutKeyDown($event)">
|
|
1693
|
+
<i class="pi pi-sign-out"></i>
|
|
1694
|
+
<span>Logout</span>
|
|
1695
|
+
</button>
|
|
1696
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
1697
|
+
<p-avatar
|
|
1698
|
+
class="p-link flex align-items-center"
|
|
1699
|
+
id="oip-app-topbar-user-avatar"
|
|
1700
|
+
shape="circle"
|
|
1701
|
+
size="normal"
|
|
1702
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
1703
|
+
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
1704
|
+
</p-avatar>
|
|
1705
|
+
<span class="ml-2">Profile</span>
|
|
1706
|
+
</button>
|
|
1707
|
+
</div>
|
|
1708
|
+
</div>
|
|
1709
|
+
</div>
|
|
1710
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i4.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }, { kind: "component", type: LogoComponent, selector: "logo", inputs: ["width", "height"] }, { kind: "component", type: Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: TabList, selector: "p-tablist" }, { kind: "component", type: Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i5$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }] }); }
|
|
1711
|
+
}
|
|
1712
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppTopbar, decorators: [{
|
|
1713
|
+
type: Component,
|
|
1714
|
+
args: [{
|
|
1715
|
+
selector: 'app-topbar',
|
|
1716
|
+
standalone: true,
|
|
1717
|
+
imports: [
|
|
1718
|
+
RouterModule,
|
|
1719
|
+
CommonModule,
|
|
1720
|
+
StyleClassModule,
|
|
1721
|
+
AppConfiguratorComponent,
|
|
1722
|
+
LogoComponent,
|
|
1723
|
+
Tabs,
|
|
1724
|
+
TabList,
|
|
1725
|
+
Tab,
|
|
1726
|
+
AvatarModule,
|
|
1727
|
+
ButtonModule
|
|
1728
|
+
],
|
|
1729
|
+
template: ` <div class="layout-topbar">
|
|
1730
|
+
<div class="layout-topbar-logo-container">
|
|
1731
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
1732
|
+
<i class="pi pi-bars"></i>
|
|
1733
|
+
</button>
|
|
1734
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
1735
|
+
<logo [height]="36" [width]="36"></logo>
|
|
1736
|
+
<span>OIP</span>
|
|
1737
|
+
</a>
|
|
1738
|
+
</div>
|
|
1739
|
+
|
|
1740
|
+
@if (securityService.isAdmin && topBarService.topBarItems.length > 0) {
|
|
1741
|
+
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
1742
|
+
<p-tablist>
|
|
1743
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
1744
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
1745
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
1746
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
1747
|
+
</p-tab>
|
|
1748
|
+
}
|
|
1749
|
+
</p-tablist>
|
|
1750
|
+
</p-tabs>
|
|
1751
|
+
}
|
|
1752
|
+
<div class="layout-topbar-actions">
|
|
1753
|
+
<div class="layout-config-menu">
|
|
1754
|
+
<p-button
|
|
1755
|
+
class="layout-topbar-action"
|
|
1756
|
+
id="oip-app-topbar-theme-button"
|
|
1757
|
+
severity="secondary"
|
|
1758
|
+
type="button"
|
|
1759
|
+
[rounded]="true"
|
|
1760
|
+
[text]="true"
|
|
1761
|
+
(click)="toggleDarkMode()">
|
|
1762
|
+
<i
|
|
1763
|
+
class="pi"
|
|
1764
|
+
[ngClass]="{
|
|
1765
|
+
'pi-moon': layoutService.isDarkTheme(),
|
|
1766
|
+
'pi-sun': !layoutService.isDarkTheme()
|
|
1767
|
+
}"></i>
|
|
1768
|
+
</p-button>
|
|
1769
|
+
<div class="relative">
|
|
1770
|
+
<p-button
|
|
1771
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
1772
|
+
enterActiveClass="animate-scalein"
|
|
1773
|
+
enterFromClass="hidden"
|
|
1774
|
+
id="oip-app-topbar-palette-button"
|
|
1775
|
+
leaveActiveClass="animate-fadeout"
|
|
1776
|
+
leaveToClass="hidden"
|
|
1777
|
+
pStyleClass="@next"
|
|
1778
|
+
[hideOnOutsideClick]="true"
|
|
1779
|
+
[rounded]="true">
|
|
1780
|
+
<i class="pi pi-palette"></i>
|
|
1781
|
+
</p-button>
|
|
1782
|
+
<app-configurator />
|
|
1783
|
+
</div>
|
|
1784
|
+
</div>
|
|
1785
|
+
|
|
1786
|
+
<button
|
|
1787
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
1788
|
+
enterActiveClass="animate-scalein"
|
|
1789
|
+
enterFromClass="hidden"
|
|
1790
|
+
id="oip-app-topbar-menu-expand-button"
|
|
1791
|
+
leaveActiveClass="animate-fadeout"
|
|
1792
|
+
leaveToClass="hidden"
|
|
1793
|
+
pStyleClass="@next"
|
|
1794
|
+
[hideOnOutsideClick]="true">
|
|
1795
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
1796
|
+
</button>
|
|
1797
|
+
|
|
1798
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
1799
|
+
<div class="layout-topbar-menu-content">
|
|
1800
|
+
<button
|
|
1801
|
+
class="layout-topbar-action"
|
|
1802
|
+
id="oip-app-topbar-logout-button"
|
|
1803
|
+
type="button"
|
|
1804
|
+
(click)="securityService.logout()"
|
|
1805
|
+
(keydown)="logoutKeyDown($event)">
|
|
1806
|
+
<i class="pi pi-sign-out"></i>
|
|
1807
|
+
<span>Logout</span>
|
|
1808
|
+
</button>
|
|
1809
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
1810
|
+
<p-avatar
|
|
1811
|
+
class="p-link flex align-items-center"
|
|
1812
|
+
id="oip-app-topbar-user-avatar"
|
|
1813
|
+
shape="circle"
|
|
1814
|
+
size="normal"
|
|
1815
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
1816
|
+
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
1817
|
+
</p-avatar>
|
|
1818
|
+
<span class="ml-2">Profile</span>
|
|
1819
|
+
</button>
|
|
1820
|
+
</div>
|
|
1821
|
+
</div>
|
|
1822
|
+
</div>
|
|
1823
|
+
</div>`
|
|
1824
|
+
}]
|
|
1825
|
+
}], ctorParameters: () => [{ type: LayoutService }] });
|
|
1826
|
+
|
|
1827
|
+
class FooterComponent {
|
|
1828
|
+
constructor() { }
|
|
1829
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1830
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: FooterComponent, isStandalone: true, selector: "app-footer", ngImport: i0, template: `
|
|
1831
|
+
<div class="layout-footer">
|
|
1832
|
+
<logo class="mr-2" height="18" width="18"></logo>
|
|
1833
|
+
<span class="font-medium">OIP</span>
|
|
1834
|
+
</div>
|
|
1835
|
+
`, isInline: true, dependencies: [{ kind: "component", type: LogoComponent, selector: "logo", inputs: ["width", "height"] }] }); }
|
|
1836
|
+
}
|
|
1837
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FooterComponent, decorators: [{
|
|
1838
|
+
type: Component,
|
|
1839
|
+
args: [{
|
|
1840
|
+
selector: 'app-footer',
|
|
1841
|
+
template: `
|
|
1842
|
+
<div class="layout-footer">
|
|
1843
|
+
<logo class="mr-2" height="18" width="18"></logo>
|
|
1844
|
+
<span class="font-medium">OIP</span>
|
|
1845
|
+
</div>
|
|
1846
|
+
`,
|
|
1847
|
+
standalone: true,
|
|
1848
|
+
imports: [LogoComponent]
|
|
1849
|
+
}]
|
|
1850
|
+
}], ctorParameters: () => [] });
|
|
1851
|
+
|
|
1852
|
+
/* eslint-disable */
|
|
1853
|
+
/* tslint:disable */
|
|
1854
|
+
// @ts-nocheck
|
|
1855
|
+
/*
|
|
1856
|
+
* ---------------------------------------------------------------
|
|
1857
|
+
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
|
1858
|
+
* ## ##
|
|
1859
|
+
* ## AUTHOR: acacode ##
|
|
1860
|
+
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
|
1861
|
+
* ---------------------------------------------------------------
|
|
1862
|
+
*/
|
|
1863
|
+
var ContentType;
|
|
1864
|
+
(function (ContentType) {
|
|
1865
|
+
ContentType["Json"] = "application/json";
|
|
1866
|
+
ContentType["FormData"] = "multipart/form-data";
|
|
1867
|
+
ContentType["UrlEncoded"] = "application/x-www-form-urlencoded";
|
|
1868
|
+
ContentType["Text"] = "text/plain";
|
|
1869
|
+
})(ContentType || (ContentType = {}));
|
|
1870
|
+
class HttpClient {
|
|
1871
|
+
constructor() {
|
|
1872
|
+
this.securityService = inject(SecurityService);
|
|
1873
|
+
this.layoutService = inject(LayoutService);
|
|
1874
|
+
this.baseUrl = "";
|
|
1875
|
+
this.securityData = null;
|
|
1876
|
+
this.securityWorker = (securityData) => ({
|
|
1877
|
+
headers: {
|
|
1878
|
+
"Accept-language": this.layoutService.language()
|
|
1879
|
+
? this.layoutService.language()
|
|
1880
|
+
: "en",
|
|
1881
|
+
"X-Timezone": this.layoutService.timeZone(),
|
|
1882
|
+
Authorization: `Bearer ${securityData}`,
|
|
1883
|
+
},
|
|
1884
|
+
});
|
|
1885
|
+
this.abortControllers = new Map();
|
|
1886
|
+
this.customFetch = (...fetchParams) => fetch(...fetchParams);
|
|
1887
|
+
this.baseApiParams = {
|
|
1888
|
+
credentials: "same-origin",
|
|
1889
|
+
headers: {},
|
|
1890
|
+
redirect: "follow",
|
|
1891
|
+
referrerPolicy: "no-referrer",
|
|
1892
|
+
};
|
|
1893
|
+
this.setSecurityData = (data) => {
|
|
1894
|
+
this.securityData = data;
|
|
1895
|
+
};
|
|
1896
|
+
this.contentFormatters = {
|
|
1897
|
+
[ContentType.Json]: (input) => input !== null && (typeof input === "object" || typeof input === "string")
|
|
1898
|
+
? JSON.stringify(input)
|
|
1899
|
+
: input,
|
|
1900
|
+
[ContentType.Text]: (input) => input !== null && typeof input !== "string"
|
|
1901
|
+
? JSON.stringify(input)
|
|
1902
|
+
: input,
|
|
1903
|
+
[ContentType.FormData]: (input) => Object.keys(input || {}).reduce((formData, key) => {
|
|
1904
|
+
const property = input[key];
|
|
1905
|
+
formData.append(key, property instanceof Blob
|
|
1906
|
+
? property
|
|
1907
|
+
: typeof property === "object" && property !== null
|
|
1908
|
+
? JSON.stringify(property)
|
|
1909
|
+
: `${property}`);
|
|
1910
|
+
return formData;
|
|
1911
|
+
}, new FormData()),
|
|
1912
|
+
[ContentType.UrlEncoded]: (input) => this.toQueryString(input),
|
|
1913
|
+
};
|
|
1914
|
+
this.createAbortSignal = (cancelToken) => {
|
|
1915
|
+
if (this.abortControllers.has(cancelToken)) {
|
|
1916
|
+
const abortController = this.abortControllers.get(cancelToken);
|
|
1917
|
+
if (abortController) {
|
|
1918
|
+
return abortController.signal;
|
|
1919
|
+
}
|
|
1920
|
+
return void 0;
|
|
1921
|
+
}
|
|
1922
|
+
const abortController = new AbortController();
|
|
1923
|
+
this.abortControllers.set(cancelToken, abortController);
|
|
1924
|
+
return abortController.signal;
|
|
1925
|
+
};
|
|
1926
|
+
this.abortRequest = (cancelToken) => {
|
|
1927
|
+
const abortController = this.abortControllers.get(cancelToken);
|
|
1928
|
+
if (abortController) {
|
|
1929
|
+
abortController.abort();
|
|
1930
|
+
this.abortControllers.delete(cancelToken);
|
|
1931
|
+
}
|
|
1932
|
+
};
|
|
1933
|
+
this.request = async ({ body, secure, path, type, query, format, baseUrl, cancelToken, ...params }) => {
|
|
1934
|
+
const secureParams = ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) &&
|
|
1935
|
+
this.securityWorker &&
|
|
1936
|
+
(await this.securityWorker(this.securityData))) ||
|
|
1937
|
+
{};
|
|
1938
|
+
const requestParams = this.mergeRequestParams(params, secureParams);
|
|
1939
|
+
const queryString = query && this.toQueryString(query);
|
|
1940
|
+
const payloadFormatter = this.contentFormatters[type || ContentType.Json];
|
|
1941
|
+
let responseFormat = format || requestParams.format;
|
|
1942
|
+
return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
|
|
1943
|
+
...requestParams,
|
|
1944
|
+
headers: {
|
|
1945
|
+
...(requestParams.headers || {}),
|
|
1946
|
+
...(type && type !== ContentType.FormData
|
|
1947
|
+
? { "Content-Type": type }
|
|
1948
|
+
: {}),
|
|
1949
|
+
},
|
|
1950
|
+
signal: (cancelToken
|
|
1951
|
+
? this.createAbortSignal(cancelToken)
|
|
1952
|
+
: requestParams.signal) || null,
|
|
1953
|
+
body: typeof body === "undefined" || body === null
|
|
1954
|
+
? null
|
|
1955
|
+
: payloadFormatter(body),
|
|
1956
|
+
}).then(async (response) => {
|
|
1957
|
+
const r = response.clone();
|
|
1958
|
+
r.data = null;
|
|
1959
|
+
r.error = null;
|
|
1960
|
+
if (typeof E !== undefined && responseFormat === undefined)
|
|
1961
|
+
responseFormat = "json";
|
|
1962
|
+
const data = !responseFormat
|
|
1963
|
+
? r
|
|
1964
|
+
: await response[responseFormat]()
|
|
1965
|
+
.then((data) => {
|
|
1966
|
+
if (r.ok) {
|
|
1967
|
+
r.data = data;
|
|
1968
|
+
}
|
|
1969
|
+
else {
|
|
1970
|
+
r.error = data;
|
|
1971
|
+
}
|
|
1972
|
+
return r;
|
|
1973
|
+
})
|
|
1974
|
+
.catch((e) => {
|
|
1975
|
+
r.error = e;
|
|
1976
|
+
return r;
|
|
1977
|
+
});
|
|
1978
|
+
if (cancelToken) {
|
|
1979
|
+
this.abortControllers.delete(cancelToken);
|
|
1980
|
+
}
|
|
1981
|
+
if (!response.ok)
|
|
1982
|
+
throw data;
|
|
1983
|
+
return data.data;
|
|
1984
|
+
});
|
|
1985
|
+
};
|
|
1986
|
+
this.securityService.getAccessToken().subscribe((token) => {
|
|
1987
|
+
this.securityData = token;
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
encodeQueryParam(key, value) {
|
|
1991
|
+
const encodedKey = encodeURIComponent(key);
|
|
1992
|
+
return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`;
|
|
1993
|
+
}
|
|
1994
|
+
addQueryParam(query, key) {
|
|
1995
|
+
return this.encodeQueryParam(key, query[key]);
|
|
1996
|
+
}
|
|
1997
|
+
addArrayQueryParam(query, key) {
|
|
1998
|
+
const value = query[key];
|
|
1999
|
+
return value.map((v) => this.encodeQueryParam(key, v)).join("&");
|
|
2000
|
+
}
|
|
2001
|
+
toQueryString(rawQuery) {
|
|
2002
|
+
const query = rawQuery || {};
|
|
2003
|
+
const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
|
|
2004
|
+
return keys
|
|
2005
|
+
.map((key) => Array.isArray(query[key])
|
|
2006
|
+
? this.addArrayQueryParam(query, key)
|
|
2007
|
+
: this.addQueryParam(query, key))
|
|
2008
|
+
.join("&");
|
|
2009
|
+
}
|
|
2010
|
+
addQueryParams(rawQuery) {
|
|
2011
|
+
const queryString = this.toQueryString(rawQuery);
|
|
2012
|
+
return queryString ? `?${queryString}` : "";
|
|
2013
|
+
}
|
|
2014
|
+
mergeRequestParams(params1, params2) {
|
|
2015
|
+
return {
|
|
2016
|
+
...this.baseApiParams,
|
|
2017
|
+
...params1,
|
|
2018
|
+
...(params2 || {}),
|
|
2019
|
+
headers: {
|
|
2020
|
+
...(this.baseApiParams.headers || {}),
|
|
2021
|
+
...(params1.headers || {}),
|
|
2022
|
+
...((params2 && params2.headers) || {}),
|
|
2023
|
+
},
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: HttpClient, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2027
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: HttpClient, providedIn: "root" }); }
|
|
2028
|
+
}
|
|
2029
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: HttpClient, decorators: [{
|
|
2030
|
+
type: Injectable,
|
|
2031
|
+
args: [{ providedIn: "root" }]
|
|
2032
|
+
}], ctorParameters: () => [] });
|
|
2033
|
+
|
|
2034
|
+
/* eslint-disable */
|
|
2035
|
+
/* tslint:disable */
|
|
2036
|
+
// @ts-nocheck
|
|
2037
|
+
/*
|
|
2038
|
+
* ---------------------------------------------------------------
|
|
2039
|
+
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
|
2040
|
+
* ## ##
|
|
2041
|
+
* ## AUTHOR: acacode ##
|
|
2042
|
+
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
|
2043
|
+
* ---------------------------------------------------------------
|
|
2044
|
+
*/
|
|
2045
|
+
class Menu extends HttpClient {
|
|
2046
|
+
constructor() {
|
|
2047
|
+
super(...arguments);
|
|
2048
|
+
/**
|
|
2049
|
+
* @description Retrieves the menu available to the current authenticated user.
|
|
2050
|
+
*
|
|
2051
|
+
* @tags Menu
|
|
2052
|
+
* @name menuGet
|
|
2053
|
+
* @request GET:/api/menu/get
|
|
2054
|
+
* @secure
|
|
2055
|
+
*/
|
|
2056
|
+
this.menuGet = (params = {}) => this.request({
|
|
2057
|
+
path: `/api/menu/get`,
|
|
2058
|
+
method: "GET",
|
|
2059
|
+
secure: true,
|
|
2060
|
+
format: "json",
|
|
2061
|
+
...params,
|
|
2062
|
+
});
|
|
2063
|
+
/**
|
|
2064
|
+
* @description Retrieves the admin-specific menu.
|
|
2065
|
+
*
|
|
2066
|
+
* @tags Menu
|
|
2067
|
+
* @name menuGetAdminMenu
|
|
2068
|
+
* @request GET:/api/menu/get-admin-menu
|
|
2069
|
+
* @secure
|
|
2070
|
+
*/
|
|
2071
|
+
this.menuGetAdminMenu = (params = {}) => this.request({
|
|
2072
|
+
path: `/api/menu/get-admin-menu`,
|
|
2073
|
+
method: "GET",
|
|
2074
|
+
secure: true,
|
|
2075
|
+
format: "json",
|
|
2076
|
+
...params,
|
|
2077
|
+
});
|
|
2078
|
+
/**
|
|
2079
|
+
* @description Retrieves all available modules in the system.
|
|
2080
|
+
*
|
|
2081
|
+
* @tags Menu
|
|
2082
|
+
* @name menuGetModules
|
|
2083
|
+
* @request GET:/api/menu/get-modules
|
|
2084
|
+
* @secure
|
|
2085
|
+
*/
|
|
2086
|
+
this.menuGetModules = (params = {}) => this.request({
|
|
2087
|
+
path: `/api/menu/get-modules`,
|
|
2088
|
+
method: "GET",
|
|
2089
|
+
secure: true,
|
|
2090
|
+
format: "json",
|
|
2091
|
+
...params,
|
|
2092
|
+
});
|
|
2093
|
+
/**
|
|
2094
|
+
* @description Adds a new module instance to the system.
|
|
2095
|
+
*
|
|
2096
|
+
* @tags Menu
|
|
2097
|
+
* @name menuAddModuleInstance
|
|
2098
|
+
* @request POST:/api/menu/add-module-instance
|
|
2099
|
+
* @secure
|
|
2100
|
+
*/
|
|
2101
|
+
this.menuAddModuleInstance = (data, params = {}) => this.request({
|
|
2102
|
+
path: `/api/menu/add-module-instance`,
|
|
2103
|
+
method: "POST",
|
|
2104
|
+
body: data,
|
|
2105
|
+
secure: true,
|
|
2106
|
+
type: ContentType.Json,
|
|
2107
|
+
...params,
|
|
2108
|
+
});
|
|
2109
|
+
/**
|
|
2110
|
+
* @description Edits an existing module instance.
|
|
2111
|
+
*
|
|
2112
|
+
* @tags Menu
|
|
2113
|
+
* @name menuEditModuleInstance
|
|
2114
|
+
* @request POST:/api/menu/edit-module-instance
|
|
2115
|
+
* @secure
|
|
2116
|
+
*/
|
|
2117
|
+
this.menuEditModuleInstance = (data, params = {}) => this.request({
|
|
2118
|
+
path: `/api/menu/edit-module-instance`,
|
|
2119
|
+
method: "POST",
|
|
2120
|
+
body: data,
|
|
2121
|
+
secure: true,
|
|
2122
|
+
type: ContentType.Json,
|
|
2123
|
+
...params,
|
|
2124
|
+
});
|
|
2125
|
+
/**
|
|
2126
|
+
* @description Deletes a module instance by its identifier.
|
|
2127
|
+
*
|
|
2128
|
+
* @tags Menu
|
|
2129
|
+
* @name menuDeleteModuleInstance
|
|
2130
|
+
* @request DELETE:/api/menu/delete-module-instance
|
|
2131
|
+
* @secure
|
|
2132
|
+
*/
|
|
2133
|
+
this.menuDeleteModuleInstance = (query, params = {}) => this.request({
|
|
2134
|
+
path: `/api/menu/delete-module-instance`,
|
|
2135
|
+
method: "DELETE",
|
|
2136
|
+
query: query,
|
|
2137
|
+
secure: true,
|
|
2138
|
+
...params,
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Menu, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2142
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Menu }); }
|
|
2143
|
+
}
|
|
2144
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Menu, decorators: [{
|
|
2145
|
+
type: Injectable
|
|
2146
|
+
}] });
|
|
2147
|
+
|
|
2148
|
+
class MenuService extends BaseDataService {
|
|
2149
|
+
constructor() {
|
|
2150
|
+
super(...arguments);
|
|
2151
|
+
this.menuSource = new Subject();
|
|
2152
|
+
this.resetSource = new Subject();
|
|
2153
|
+
this.titleService = inject(AppTitleService);
|
|
2154
|
+
this.menuDataService = inject(Menu);
|
|
2155
|
+
this.menuSource$ = this.menuSource.asObservable();
|
|
2156
|
+
this.resetSource$ = this.resetSource.asObservable();
|
|
2157
|
+
this.menu = [];
|
|
2158
|
+
this.adminMode = false;
|
|
2159
|
+
}
|
|
2160
|
+
async loadMenu() {
|
|
2161
|
+
this.menu = this.adminMode ? await this.getAdminMenu() : await this.getMenu();
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Handles changes in the menu state.
|
|
2165
|
+
* @param {MenuChangeEvent} event - The event containing information about the menu state change.
|
|
2166
|
+
* @return {void}
|
|
2167
|
+
*/
|
|
2168
|
+
onMenuStateChange(event) {
|
|
2169
|
+
this.menuSource.next(event);
|
|
2170
|
+
this.titleService.setTitle(event.item.label);
|
|
2171
|
+
}
|
|
2172
|
+
reset() {
|
|
2173
|
+
this.resetSource.next(true);
|
|
2174
|
+
}
|
|
2175
|
+
getMenu() {
|
|
2176
|
+
return this.menuDataService.menuGet();
|
|
2177
|
+
}
|
|
2178
|
+
getAdminMenu() {
|
|
2179
|
+
return this.menuDataService.menuGetAdminMenu();
|
|
2180
|
+
}
|
|
2181
|
+
getModules() {
|
|
2182
|
+
return this.menuDataService.menuGetModules();
|
|
2183
|
+
}
|
|
2184
|
+
addModuleInstance(addModuleInstance) {
|
|
2185
|
+
return this.menuDataService.menuAddModuleInstance(addModuleInstance);
|
|
2186
|
+
}
|
|
2187
|
+
deleteItem(moduleInstanceId) {
|
|
2188
|
+
return this.sendRequest(this.baseUrl + 'api/menu/delete-module-instance?id=' + moduleInstanceId, 'DELETE');
|
|
2189
|
+
}
|
|
2190
|
+
editModuleInstance(item) {
|
|
2191
|
+
return this.sendRequest(this.baseUrl + 'api/menu/edit-module-instance', 'POST', item);
|
|
2192
|
+
}
|
|
2193
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2194
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuService }); }
|
|
2195
|
+
}
|
|
2196
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuService, decorators: [{
|
|
2197
|
+
type: Injectable
|
|
2198
|
+
}] });
|
|
2199
|
+
|
|
2200
|
+
class MenuItemComponent {
|
|
2201
|
+
constructor(cd, router, menuService) {
|
|
2202
|
+
this.cd = cd;
|
|
2203
|
+
this.router = router;
|
|
2204
|
+
this.menuService = menuService;
|
|
2205
|
+
this.layoutService = inject(LayoutService);
|
|
2206
|
+
this.translateService = inject(TranslateService);
|
|
2207
|
+
this.confirmationService = inject(ConfirmationService);
|
|
2208
|
+
this.msgService = inject(MsgService);
|
|
2209
|
+
this.menuDataService = inject(Menu);
|
|
2210
|
+
this.active = false;
|
|
2211
|
+
this.subscriptions = [];
|
|
2212
|
+
this.localization = {};
|
|
2213
|
+
this.key = '';
|
|
2214
|
+
this.subscriptions.push(this.menuService.menuSource$.subscribe((value) => {
|
|
2215
|
+
Promise.resolve(null).then(() => {
|
|
2216
|
+
if (value.routeEvent) {
|
|
2217
|
+
this.active = value.key === this.key || value.key.startsWith(this.key + '-');
|
|
2218
|
+
}
|
|
2219
|
+
else if (value.key !== this.key && !value.key.startsWith(this.key + '-')) {
|
|
2220
|
+
this.active = false;
|
|
2221
|
+
}
|
|
2222
|
+
});
|
|
2223
|
+
}));
|
|
2224
|
+
this.subscriptions.push(this.menuService.resetSource$.subscribe(() => {
|
|
2225
|
+
this.active = false;
|
|
2226
|
+
}));
|
|
2227
|
+
this.subscriptions.push(this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((params) => {
|
|
2228
|
+
if (this.item.routerLink) {
|
|
2229
|
+
this.updateActiveStateFromRoute();
|
|
2230
|
+
}
|
|
2231
|
+
}));
|
|
2232
|
+
this.subscriptions.push(this.translateService.get('menuItemComponent').subscribe((value) => {
|
|
2233
|
+
this.localization = value;
|
|
2234
|
+
}));
|
|
2235
|
+
}
|
|
2236
|
+
ngOnInit() {
|
|
2237
|
+
this.key = this.parentKey ? this.parentKey + '-' + this.index : String(this.index);
|
|
2238
|
+
if (this.item.routerLink) {
|
|
2239
|
+
this.updateActiveStateFromRoute();
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
updateActiveStateFromRoute() {
|
|
2243
|
+
const activeRoute = this.router.isActive(this.item.routerLink[0], {
|
|
2244
|
+
paths: 'exact',
|
|
2245
|
+
queryParams: 'ignored',
|
|
2246
|
+
matrixParams: 'ignored',
|
|
2247
|
+
fragment: 'ignored'
|
|
2248
|
+
});
|
|
2249
|
+
if (activeRoute) {
|
|
2250
|
+
this.menuService.onMenuStateChange({
|
|
2251
|
+
key: this.key,
|
|
2252
|
+
item: this.item,
|
|
2253
|
+
routeEvent: true
|
|
2254
|
+
});
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
itemClick(event) {
|
|
2258
|
+
// avoid processing disabled items
|
|
2259
|
+
if (this.item.disabled) {
|
|
2260
|
+
event.preventDefault();
|
|
2261
|
+
return;
|
|
2262
|
+
}
|
|
2263
|
+
// execute command
|
|
2264
|
+
if (this.item.command) {
|
|
2265
|
+
this.item.command({ originalEvent: event, item: this.item });
|
|
2266
|
+
}
|
|
2267
|
+
// toggle active state
|
|
2268
|
+
if (this.item.items) {
|
|
2269
|
+
this.active = !this.active;
|
|
2270
|
+
}
|
|
2271
|
+
this.menuService.onMenuStateChange({ key: this.key, item: this.item });
|
|
2272
|
+
}
|
|
2273
|
+
get submenuAnimation() {
|
|
2274
|
+
return this.root || this.active ? 'expanded' : 'collapsed';
|
|
2275
|
+
}
|
|
2276
|
+
get activeClass() {
|
|
2277
|
+
return this.active && !this.root;
|
|
2278
|
+
}
|
|
2279
|
+
ngOnDestroy() {
|
|
2280
|
+
this.subscriptions.map((s) => s.unsubscribe());
|
|
2281
|
+
}
|
|
2282
|
+
newClick(e) {
|
|
2283
|
+
this.menuItemCreateDialogComponent.showDialog();
|
|
2284
|
+
}
|
|
2285
|
+
onContextMenu($event, item) {
|
|
2286
|
+
this.menuService.contextMenuItem = item;
|
|
2287
|
+
this.contextMenu.model = [
|
|
2288
|
+
{
|
|
2289
|
+
label: this.localization.new,
|
|
2290
|
+
icon: PrimeIcons.PLUS,
|
|
2291
|
+
command: (event) => this.newClick(event)
|
|
2292
|
+
},
|
|
2293
|
+
{
|
|
2294
|
+
label: this.localization.edit,
|
|
2295
|
+
icon: PrimeIcons.FILE_EDIT,
|
|
2296
|
+
command: (event) => this.editClick(event)
|
|
2297
|
+
},
|
|
2298
|
+
{ separator: true },
|
|
2299
|
+
{
|
|
2300
|
+
label: this.localization.delete,
|
|
2301
|
+
icon: PrimeIcons.TRASH,
|
|
2302
|
+
command: (event) => this.deleteItem(event)
|
|
2303
|
+
}
|
|
2304
|
+
];
|
|
2305
|
+
this.contextMenu.show($event);
|
|
2306
|
+
}
|
|
2307
|
+
deleteItem(event) {
|
|
2308
|
+
this.confirmationService.confirm({
|
|
2309
|
+
header: this.localization.deleteItemConfirmHeader,
|
|
2310
|
+
message: this.localization.deleteItemConfirmMessage,
|
|
2311
|
+
icon: PrimeIcons.TRASH,
|
|
2312
|
+
rejectButtonProps: {
|
|
2313
|
+
label: this.localization.deleteItemConfirmRejectButtonPropsLabel,
|
|
2314
|
+
severity: 'secondary',
|
|
2315
|
+
outlined: true
|
|
2316
|
+
},
|
|
2317
|
+
acceptButtonProps: {
|
|
2318
|
+
label: this.localization.deleteItemConfirmAcceptButtonPropsLabel,
|
|
2319
|
+
severity: 'danger'
|
|
2320
|
+
},
|
|
2321
|
+
accept: async () => {
|
|
2322
|
+
await this.menuDataService.menuDeleteModuleInstance({
|
|
2323
|
+
id: this.menuService.contextMenuItem?.moduleInstanceId
|
|
2324
|
+
});
|
|
2325
|
+
this.msgService.success(this.localization.deleteItemSuccessMessage);
|
|
2326
|
+
await this.menuService.loadMenu();
|
|
2327
|
+
}
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
editClick(event) {
|
|
2331
|
+
this.menuItemEditDialogComponent.showDialog();
|
|
2332
|
+
}
|
|
2333
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$3.Router }, { token: MenuService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2334
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: MenuItemComponent, isStandalone: true, selector: "[app-menuitem]", inputs: { item: "item", index: "index", root: "root", parentKey: "parentKey", menuItemCreateDialogComponent: "menuItemCreateDialogComponent", menuItemEditDialogComponent: "menuItemEditDialogComponent", contextMenu: "contextMenu" }, host: { properties: { "class.layout-root-menuitem": "this.root", "class.active-menuitem": "this.activeClass" } }, providers: [ConfirmationService], ngImport: i0, template: `
|
|
2335
|
+
<ng-container>
|
|
2336
|
+
<p-confirm-dialog />
|
|
2337
|
+
<div
|
|
2338
|
+
*ngIf="root && item.visible !== false"
|
|
2339
|
+
class="layout-menuitem-root-text"
|
|
2340
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2341
|
+
{{ item.label }}
|
|
2342
|
+
</div>
|
|
2343
|
+
<a
|
|
2344
|
+
*ngIf="(!item.routerLink || item.items) && item.visible !== false"
|
|
2345
|
+
pRipple
|
|
2346
|
+
tabindex="0"
|
|
2347
|
+
[attr.href]="item.url"
|
|
2348
|
+
[attr.target]="item.target"
|
|
2349
|
+
[ngClass]="item.class"
|
|
2350
|
+
(click)="itemClick($event)">
|
|
2351
|
+
<i class="layout-menuitem-icon" [ngClass]="item.icon"></i>
|
|
2352
|
+
<span class="layout-menuitem-text">{{ item.label }}</span>
|
|
2353
|
+
<i *ngIf="item.items" class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
2354
|
+
</a>
|
|
2355
|
+
<a
|
|
2356
|
+
*ngIf="item.routerLink && !item.items && item.visible !== false"
|
|
2357
|
+
pRipple
|
|
2358
|
+
routerLinkActive="active-route"
|
|
2359
|
+
tabindex="0"
|
|
2360
|
+
[attr.target]="item.target"
|
|
2361
|
+
[fragment]="item.fragment"
|
|
2362
|
+
[ngClass]="item.class"
|
|
2363
|
+
[preserveFragment]="item.preserveFragment"
|
|
2364
|
+
[queryParams]="item.queryParams"
|
|
2365
|
+
[queryParamsHandling]="item.queryParamsHandling"
|
|
2366
|
+
[replaceUrl]="item.replaceUrl"
|
|
2367
|
+
[routerLink]="item.routerLink"
|
|
2368
|
+
[routerLinkActiveOptions]="
|
|
2369
|
+
item.routerLinkActiveOptions || {
|
|
2370
|
+
paths: 'exact',
|
|
2371
|
+
queryParams: 'ignored',
|
|
2372
|
+
matrixParams: 'ignored',
|
|
2373
|
+
fragment: 'ignored'
|
|
2374
|
+
}
|
|
2375
|
+
"
|
|
2376
|
+
[skipLocationChange]="item.skipLocationChange"
|
|
2377
|
+
[state]="item.state"
|
|
2378
|
+
(click)="itemClick($event)"
|
|
2379
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2380
|
+
<i class="layout-menuitem-icon" [ngClass]="item.icon"></i>
|
|
2381
|
+
<span class="layout-menuitem-text">{{ item.label }}</span>
|
|
2382
|
+
<i *ngIf="item.items" class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
2383
|
+
</a>
|
|
2384
|
+
|
|
2385
|
+
<ul
|
|
2386
|
+
*ngIf="item.items && item.visible !== false"
|
|
2387
|
+
[@children]="submenuAnimation"
|
|
2388
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2389
|
+
<ng-template let-child let-i="index" ngFor [ngForOf]="item.items">
|
|
2390
|
+
<li
|
|
2391
|
+
app-menuitem
|
|
2392
|
+
[class]="child.badgeClass"
|
|
2393
|
+
[contextMenu]="contextMenu"
|
|
2394
|
+
[index]="i"
|
|
2395
|
+
[item]="child"
|
|
2396
|
+
[menuItemCreateDialogComponent]="menuItemCreateDialogComponent"
|
|
2397
|
+
[menuItemEditDialogComponent]="menuItemEditDialogComponent"
|
|
2398
|
+
[parentKey]="key"></li>
|
|
2399
|
+
</ng-template>
|
|
2400
|
+
</ul>
|
|
2401
|
+
</ng-container>
|
|
2402
|
+
`, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i3$1.Ripple, selector: "[pRipple]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position", "draggable"], outputs: ["onHide"] }], animations: [
|
|
2403
|
+
trigger('children', [
|
|
2404
|
+
state('collapsed', style({
|
|
2405
|
+
height: '0'
|
|
2406
|
+
})),
|
|
2407
|
+
state('expanded', style({
|
|
2408
|
+
height: '*'
|
|
2409
|
+
})),
|
|
2410
|
+
transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
|
|
2411
|
+
])
|
|
2412
|
+
] }); }
|
|
2413
|
+
}
|
|
2414
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuItemComponent, decorators: [{
|
|
2415
|
+
type: Component,
|
|
2416
|
+
args: [{
|
|
2417
|
+
// eslint-disable-next-line @angular-eslint/component-selector
|
|
2418
|
+
selector: '[app-menuitem]',
|
|
2419
|
+
template: `
|
|
2420
|
+
<ng-container>
|
|
2421
|
+
<p-confirm-dialog />
|
|
2422
|
+
<div
|
|
2423
|
+
*ngIf="root && item.visible !== false"
|
|
2424
|
+
class="layout-menuitem-root-text"
|
|
2425
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2426
|
+
{{ item.label }}
|
|
2427
|
+
</div>
|
|
2428
|
+
<a
|
|
2429
|
+
*ngIf="(!item.routerLink || item.items) && item.visible !== false"
|
|
2430
|
+
pRipple
|
|
2431
|
+
tabindex="0"
|
|
2432
|
+
[attr.href]="item.url"
|
|
2433
|
+
[attr.target]="item.target"
|
|
2434
|
+
[ngClass]="item.class"
|
|
2435
|
+
(click)="itemClick($event)">
|
|
2436
|
+
<i class="layout-menuitem-icon" [ngClass]="item.icon"></i>
|
|
2437
|
+
<span class="layout-menuitem-text">{{ item.label }}</span>
|
|
2438
|
+
<i *ngIf="item.items" class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
2439
|
+
</a>
|
|
2440
|
+
<a
|
|
2441
|
+
*ngIf="item.routerLink && !item.items && item.visible !== false"
|
|
2442
|
+
pRipple
|
|
2443
|
+
routerLinkActive="active-route"
|
|
2444
|
+
tabindex="0"
|
|
2445
|
+
[attr.target]="item.target"
|
|
2446
|
+
[fragment]="item.fragment"
|
|
2447
|
+
[ngClass]="item.class"
|
|
2448
|
+
[preserveFragment]="item.preserveFragment"
|
|
2449
|
+
[queryParams]="item.queryParams"
|
|
2450
|
+
[queryParamsHandling]="item.queryParamsHandling"
|
|
2451
|
+
[replaceUrl]="item.replaceUrl"
|
|
2452
|
+
[routerLink]="item.routerLink"
|
|
2453
|
+
[routerLinkActiveOptions]="
|
|
2454
|
+
item.routerLinkActiveOptions || {
|
|
2455
|
+
paths: 'exact',
|
|
2456
|
+
queryParams: 'ignored',
|
|
2457
|
+
matrixParams: 'ignored',
|
|
2458
|
+
fragment: 'ignored'
|
|
2459
|
+
}
|
|
2460
|
+
"
|
|
2461
|
+
[skipLocationChange]="item.skipLocationChange"
|
|
2462
|
+
[state]="item.state"
|
|
2463
|
+
(click)="itemClick($event)"
|
|
2464
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2465
|
+
<i class="layout-menuitem-icon" [ngClass]="item.icon"></i>
|
|
2466
|
+
<span class="layout-menuitem-text">{{ item.label }}</span>
|
|
2467
|
+
<i *ngIf="item.items" class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
2468
|
+
</a>
|
|
2469
|
+
|
|
2470
|
+
<ul
|
|
2471
|
+
*ngIf="item.items && item.visible !== false"
|
|
2472
|
+
[@children]="submenuAnimation"
|
|
2473
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2474
|
+
<ng-template let-child let-i="index" ngFor [ngForOf]="item.items">
|
|
2475
|
+
<li
|
|
2476
|
+
app-menuitem
|
|
2477
|
+
[class]="child.badgeClass"
|
|
2478
|
+
[contextMenu]="contextMenu"
|
|
2479
|
+
[index]="i"
|
|
2480
|
+
[item]="child"
|
|
2481
|
+
[menuItemCreateDialogComponent]="menuItemCreateDialogComponent"
|
|
2482
|
+
[menuItemEditDialogComponent]="menuItemEditDialogComponent"
|
|
2483
|
+
[parentKey]="key"></li>
|
|
2484
|
+
</ng-template>
|
|
2485
|
+
</ul>
|
|
2486
|
+
</ng-container>
|
|
2487
|
+
`,
|
|
2488
|
+
animations: [
|
|
2489
|
+
trigger('children', [
|
|
2490
|
+
state('collapsed', style({
|
|
2491
|
+
height: '0'
|
|
2492
|
+
})),
|
|
2493
|
+
state('expanded', style({
|
|
2494
|
+
height: '*'
|
|
2495
|
+
})),
|
|
2496
|
+
transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
|
|
2497
|
+
])
|
|
2498
|
+
],
|
|
2499
|
+
imports: [NgIf, RippleModule, NgClass, RouterLinkActive, RouterLink, NgFor, ContextMenuModule, ConfirmDialog],
|
|
2500
|
+
providers: [ConfirmationService]
|
|
2501
|
+
}]
|
|
2502
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$3.Router }, { type: MenuService }], propDecorators: { item: [{
|
|
2503
|
+
type: Input
|
|
2504
|
+
}], index: [{
|
|
2505
|
+
type: Input
|
|
2506
|
+
}], root: [{
|
|
2507
|
+
type: Input
|
|
2508
|
+
}, {
|
|
2509
|
+
type: HostBinding,
|
|
2510
|
+
args: ['class.layout-root-menuitem']
|
|
2511
|
+
}], parentKey: [{
|
|
2512
|
+
type: Input
|
|
2513
|
+
}], menuItemCreateDialogComponent: [{
|
|
2514
|
+
type: Input
|
|
2515
|
+
}], menuItemEditDialogComponent: [{
|
|
2516
|
+
type: Input
|
|
2517
|
+
}], contextMenu: [{
|
|
2518
|
+
type: Input
|
|
2519
|
+
}], activeClass: [{
|
|
2520
|
+
type: HostBinding,
|
|
2521
|
+
args: ['class.active-menuitem']
|
|
2522
|
+
}] } });
|
|
2523
|
+
|
|
2524
|
+
class MenuItemCreateDialogComponent {
|
|
2525
|
+
constructor() {
|
|
2526
|
+
this.menuService = inject(MenuService);
|
|
2527
|
+
this.menu = inject(Menu);
|
|
2528
|
+
this.visibleChange = new EventEmitter();
|
|
2529
|
+
this.modules = [];
|
|
2530
|
+
this.selectIcon = 'pi pi-box';
|
|
2531
|
+
}
|
|
2532
|
+
async ngOnInit() {
|
|
2533
|
+
this.modules = await this.menu.menuGetModules();
|
|
2534
|
+
}
|
|
2535
|
+
changeVisible() {
|
|
2536
|
+
this.visible = !this.visible;
|
|
2537
|
+
this.visibleChange.emit(this.visible);
|
|
2538
|
+
}
|
|
2539
|
+
async save() {
|
|
2540
|
+
const item = {
|
|
2541
|
+
moduleId: this.selectModule,
|
|
2542
|
+
label: this.label,
|
|
2543
|
+
icon: this.selectIcon,
|
|
2544
|
+
parentId: this.menuService.contextMenuItem?.moduleInstanceId
|
|
2545
|
+
};
|
|
2546
|
+
await this.menuService.addModuleInstance(item);
|
|
2547
|
+
await this.menuService.loadMenu();
|
|
2548
|
+
this.hide();
|
|
2549
|
+
}
|
|
2550
|
+
hide() {
|
|
2551
|
+
this.visible = false;
|
|
2552
|
+
this.visibleChange.emit(this.visible);
|
|
2553
|
+
}
|
|
2554
|
+
showDialog() {
|
|
2555
|
+
this.visible = true;
|
|
2556
|
+
this.visibleChange.emit(this.visible);
|
|
2557
|
+
}
|
|
2558
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuItemCreateDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2559
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: MenuItemCreateDialogComponent, isStandalone: true, selector: "menu-item-create-dialog", inputs: { visible: "visible" }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: `
|
|
2560
|
+
<p-dialog
|
|
2561
|
+
header="{{ 'menuItemCreateDialogComponent.header' | translate }}"
|
|
2562
|
+
[modal]="true"
|
|
2563
|
+
[style]="{ width: '40rem' }"
|
|
2564
|
+
[(visible)]="visible">
|
|
2565
|
+
@if (menuService.contextMenuItem) {
|
|
2566
|
+
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
2567
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-parent-input">
|
|
2568
|
+
{{ 'menuItemCreateDialogComponent.parentLabel' | translate }}
|
|
2569
|
+
</label>
|
|
2570
|
+
<input
|
|
2571
|
+
autocomplete="off"
|
|
2572
|
+
class="flex-auto"
|
|
2573
|
+
id="oip-menu-item-create-dialog-parent-input"
|
|
2574
|
+
pInputText
|
|
2575
|
+
readonly
|
|
2576
|
+
[ngModel]="menuService.contextMenuItem?.label"/>
|
|
2577
|
+
</div>
|
|
2578
|
+
}
|
|
2579
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2580
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-label">
|
|
2581
|
+
{{ 'menuItemCreateDialogComponent.label' | translate }}
|
|
2582
|
+
</label>
|
|
2583
|
+
<input autocomplete="off" class="flex-auto" id="oip-menu-item-create-label" pInputText [(ngModel)]="label"/>
|
|
2584
|
+
</div>
|
|
2585
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2586
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-module">
|
|
2587
|
+
{{ 'menuItemCreateDialogComponent.module' | translate }}
|
|
2588
|
+
</label>
|
|
2589
|
+
<p-select
|
|
2590
|
+
appendTo="body"
|
|
2591
|
+
class="flex-auto"
|
|
2592
|
+
id="oip-menu-item-create-module"
|
|
2593
|
+
optionLabel="value"
|
|
2594
|
+
optionValue="key"
|
|
2595
|
+
placeholder="{{ 'menuItemCreateDialogComponent.selectModule' | translate }}"
|
|
2596
|
+
[options]="modules"
|
|
2597
|
+
[(ngModel)]="selectModule"/>
|
|
2598
|
+
</div>
|
|
2599
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2600
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-icon">
|
|
2601
|
+
{{ 'menuItemCreateDialogComponent.icon' | translate }}
|
|
2602
|
+
</label>
|
|
2603
|
+
<i class="{{ selectIcon }}"></i>
|
|
2604
|
+
<input class="flex-auto" id="oip-menu-item-create-dialog-icon" pInputText [(ngModel)]="selectIcon"/>
|
|
2605
|
+
</div>
|
|
2606
|
+
<div class="flex justify-end gap-2">
|
|
2607
|
+
<p-button
|
|
2608
|
+
id="oip-menu-item-create-cancel"
|
|
2609
|
+
label="{{ 'menuItemCreateDialogComponent.cancel' | translate }}"
|
|
2610
|
+
severity="secondary"
|
|
2611
|
+
(click)="changeVisible()"
|
|
2612
|
+
(keydown)="changeVisible()"/>
|
|
2613
|
+
<p-button
|
|
2614
|
+
id="oip-menu-item-create-save"
|
|
2615
|
+
label="{{ 'menuItemCreateDialogComponent.save' | translate }}"
|
|
2616
|
+
(click)="save()"
|
|
2617
|
+
(keydown)="save()"/>
|
|
2618
|
+
</div>
|
|
2619
|
+
</p-dialog>
|
|
2620
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2$1.Dialog, selector: "p-dialog", inputs: ["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", "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: i3$2.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4$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"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
2621
|
+
}
|
|
2622
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuItemCreateDialogComponent, decorators: [{
|
|
2623
|
+
type: Component,
|
|
2624
|
+
args: [{
|
|
2625
|
+
selector: 'menu-item-create-dialog',
|
|
2626
|
+
standalone: true,
|
|
2627
|
+
imports: [ButtonModule, DialogModule, InputTextModule, SelectModule, FormsModule, TranslatePipe],
|
|
2628
|
+
template: `
|
|
2629
|
+
<p-dialog
|
|
2630
|
+
header="{{ 'menuItemCreateDialogComponent.header' | translate }}"
|
|
2631
|
+
[modal]="true"
|
|
2632
|
+
[style]="{ width: '40rem' }"
|
|
2633
|
+
[(visible)]="visible">
|
|
2634
|
+
@if (menuService.contextMenuItem) {
|
|
2635
|
+
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
2636
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-parent-input">
|
|
2637
|
+
{{ 'menuItemCreateDialogComponent.parentLabel' | translate }}
|
|
2638
|
+
</label>
|
|
2639
|
+
<input
|
|
2640
|
+
autocomplete="off"
|
|
2641
|
+
class="flex-auto"
|
|
2642
|
+
id="oip-menu-item-create-dialog-parent-input"
|
|
2643
|
+
pInputText
|
|
2644
|
+
readonly
|
|
2645
|
+
[ngModel]="menuService.contextMenuItem?.label"/>
|
|
2646
|
+
</div>
|
|
2647
|
+
}
|
|
2648
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2649
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-label">
|
|
2650
|
+
{{ 'menuItemCreateDialogComponent.label' | translate }}
|
|
2651
|
+
</label>
|
|
2652
|
+
<input autocomplete="off" class="flex-auto" id="oip-menu-item-create-label" pInputText [(ngModel)]="label"/>
|
|
2653
|
+
</div>
|
|
2654
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2655
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-module">
|
|
2656
|
+
{{ 'menuItemCreateDialogComponent.module' | translate }}
|
|
2657
|
+
</label>
|
|
2658
|
+
<p-select
|
|
2659
|
+
appendTo="body"
|
|
2660
|
+
class="flex-auto"
|
|
2661
|
+
id="oip-menu-item-create-module"
|
|
2662
|
+
optionLabel="value"
|
|
2663
|
+
optionValue="key"
|
|
2664
|
+
placeholder="{{ 'menuItemCreateDialogComponent.selectModule' | translate }}"
|
|
2665
|
+
[options]="modules"
|
|
2666
|
+
[(ngModel)]="selectModule"/>
|
|
2667
|
+
</div>
|
|
2668
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2669
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-icon">
|
|
2670
|
+
{{ 'menuItemCreateDialogComponent.icon' | translate }}
|
|
2671
|
+
</label>
|
|
2672
|
+
<i class="{{ selectIcon }}"></i>
|
|
2673
|
+
<input class="flex-auto" id="oip-menu-item-create-dialog-icon" pInputText [(ngModel)]="selectIcon"/>
|
|
2674
|
+
</div>
|
|
2675
|
+
<div class="flex justify-end gap-2">
|
|
2676
|
+
<p-button
|
|
2677
|
+
id="oip-menu-item-create-cancel"
|
|
2678
|
+
label="{{ 'menuItemCreateDialogComponent.cancel' | translate }}"
|
|
2679
|
+
severity="secondary"
|
|
2680
|
+
(click)="changeVisible()"
|
|
2681
|
+
(keydown)="changeVisible()"/>
|
|
2682
|
+
<p-button
|
|
2683
|
+
id="oip-menu-item-create-save"
|
|
2684
|
+
label="{{ 'menuItemCreateDialogComponent.save' | translate }}"
|
|
2685
|
+
(click)="save()"
|
|
2686
|
+
(keydown)="save()"/>
|
|
2687
|
+
</div>
|
|
2688
|
+
</p-dialog>
|
|
2689
|
+
`
|
|
2690
|
+
}]
|
|
2691
|
+
}], propDecorators: { visible: [{
|
|
2692
|
+
type: Input
|
|
2693
|
+
}], visibleChange: [{
|
|
2694
|
+
type: Output
|
|
2695
|
+
}] } });
|
|
2696
|
+
|
|
2697
|
+
class MenuItemEditDialogComponent {
|
|
2698
|
+
constructor() {
|
|
2699
|
+
this.menuService = inject(MenuService);
|
|
2700
|
+
this.securityDataService = inject(SecurityDataService);
|
|
2701
|
+
this.visibleChange = new EventEmitter();
|
|
2702
|
+
this.modules = [];
|
|
2703
|
+
this.roles = [];
|
|
2704
|
+
this.item = {
|
|
2705
|
+
icon: '',
|
|
2706
|
+
label: '',
|
|
2707
|
+
viewRoles: [''],
|
|
2708
|
+
moduleId: 0,
|
|
2709
|
+
moduleInstanceId: 0,
|
|
2710
|
+
parentId: 0
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2713
|
+
changeVisible() {
|
|
2714
|
+
this.visible = !this.visible;
|
|
2715
|
+
this.visibleChange.emit(this.visible);
|
|
2716
|
+
}
|
|
2717
|
+
async save() {
|
|
2718
|
+
await this.menuService.editModuleInstance(this.item);
|
|
2719
|
+
await this.menuService.loadMenu();
|
|
2720
|
+
this.hide();
|
|
2721
|
+
}
|
|
2722
|
+
hide() {
|
|
2723
|
+
this.visible = false;
|
|
2724
|
+
this.visibleChange.emit(this.visible);
|
|
2725
|
+
}
|
|
2726
|
+
async showDialog() {
|
|
2727
|
+
this.item = {
|
|
2728
|
+
moduleInstanceId: this.menuService.contextMenuItem?.moduleInstanceId,
|
|
2729
|
+
moduleId: this.menuService.contextMenuItem?.moduleId,
|
|
2730
|
+
parentId: this.menuService.contextMenuItem?.parentId,
|
|
2731
|
+
label: this.menuService.contextMenuItem?.label,
|
|
2732
|
+
icon: this.menuService.contextMenuItem?.icon,
|
|
2733
|
+
viewRoles: this.menuService.contextMenuItem?.securities
|
|
2734
|
+
};
|
|
2735
|
+
this.roles = await this.securityDataService.getRealmRoles();
|
|
2736
|
+
this.menuService.getModules().then((data) => {
|
|
2737
|
+
this.modules = data;
|
|
2738
|
+
});
|
|
2739
|
+
this.visible = true;
|
|
2740
|
+
this.visibleChange.emit(this.visible);
|
|
2741
|
+
}
|
|
2742
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuItemEditDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2743
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: MenuItemEditDialogComponent, isStandalone: true, selector: "menu-item-edit-dialog", inputs: { visible: "visible" }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: `
|
|
2744
|
+
<p-dialog
|
|
2745
|
+
header="{{ 'menuItemEditDialogComponent.header' | translate }}"
|
|
2746
|
+
[modal]="true"
|
|
2747
|
+
[style]="{ width: '40rem' }"
|
|
2748
|
+
[(visible)]="visible">
|
|
2749
|
+
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
2750
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-menu-input">
|
|
2751
|
+
{{ 'menuItemEditDialogComponent.label' | translate }}
|
|
2752
|
+
</label>
|
|
2753
|
+
<input
|
|
2754
|
+
autocomplete="off"
|
|
2755
|
+
class="flex-auto"
|
|
2756
|
+
id="oip-menu-item-edit-dialog-menu-input"
|
|
2757
|
+
pInputText
|
|
2758
|
+
[(ngModel)]="item.label"/>
|
|
2759
|
+
</div>
|
|
2760
|
+
|
|
2761
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2762
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-icon">
|
|
2763
|
+
{{ 'menuItemEditDialogComponent.icon' | translate }}
|
|
2764
|
+
</label>
|
|
2765
|
+
<i class="{{ item.icon }}"></i>
|
|
2766
|
+
<input class="flex-auto" id="oip-menu-item-edit-dialog-icon" pInputText [(ngModel)]="item.icon"/>
|
|
2767
|
+
</div>
|
|
2768
|
+
|
|
2769
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2770
|
+
<label class="font-semibold w-1/3" for="security">
|
|
2771
|
+
{{ 'menuItemEditDialogComponent.security' | translate }}
|
|
2772
|
+
</label>
|
|
2773
|
+
<p-multiSelect
|
|
2774
|
+
appendTo="body"
|
|
2775
|
+
class="flex-auto"
|
|
2776
|
+
id="oip-menu-item-edit-dialog-roles-multi-select"
|
|
2777
|
+
placeholder="Select roles"
|
|
2778
|
+
[maxSelectedLabels]="10"
|
|
2779
|
+
[options]="roles"
|
|
2780
|
+
[(ngModel)]="item.viewRoles"/>
|
|
2781
|
+
</div>
|
|
2782
|
+
|
|
2783
|
+
<div class="flex justify-end gap-2">
|
|
2784
|
+
<p-button
|
|
2785
|
+
id="oip-menu-item-edit-dialog-cancel-edit-button"
|
|
2786
|
+
label="{{ 'menuItemEditDialogComponent.cancel' | translate }}"
|
|
2787
|
+
severity="secondary"
|
|
2788
|
+
(click)="changeVisible()"
|
|
2789
|
+
(keydown)="changeVisible()"/>
|
|
2790
|
+
<p-button
|
|
2791
|
+
id="oip-menu-item-edit-dialog-save-edit-button"
|
|
2792
|
+
label="{{ 'menuItemEditDialogComponent.save' | translate }}"
|
|
2793
|
+
(click)="save()"
|
|
2794
|
+
(keydown)="save()"/>
|
|
2795
|
+
</div>
|
|
2796
|
+
</p-dialog>
|
|
2797
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2$1.Dialog, selector: "p-dialog", inputs: ["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", "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: i3$2.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i1.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
2798
|
+
}
|
|
2799
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuItemEditDialogComponent, decorators: [{
|
|
2800
|
+
type: Component,
|
|
2801
|
+
args: [{
|
|
2802
|
+
imports: [ButtonModule, DialogModule, InputTextModule, FormsModule, TranslatePipe, MultiSelectModule],
|
|
2803
|
+
selector: 'menu-item-edit-dialog',
|
|
2804
|
+
standalone: true,
|
|
2805
|
+
template: `
|
|
2806
|
+
<p-dialog
|
|
2807
|
+
header="{{ 'menuItemEditDialogComponent.header' | translate }}"
|
|
2808
|
+
[modal]="true"
|
|
2809
|
+
[style]="{ width: '40rem' }"
|
|
2810
|
+
[(visible)]="visible">
|
|
2811
|
+
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
2812
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-menu-input">
|
|
2813
|
+
{{ 'menuItemEditDialogComponent.label' | translate }}
|
|
2814
|
+
</label>
|
|
2815
|
+
<input
|
|
2816
|
+
autocomplete="off"
|
|
2817
|
+
class="flex-auto"
|
|
2818
|
+
id="oip-menu-item-edit-dialog-menu-input"
|
|
2819
|
+
pInputText
|
|
2820
|
+
[(ngModel)]="item.label"/>
|
|
2821
|
+
</div>
|
|
2822
|
+
|
|
2823
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2824
|
+
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-icon">
|
|
2825
|
+
{{ 'menuItemEditDialogComponent.icon' | translate }}
|
|
2826
|
+
</label>
|
|
2827
|
+
<i class="{{ item.icon }}"></i>
|
|
2828
|
+
<input class="flex-auto" id="oip-menu-item-edit-dialog-icon" pInputText [(ngModel)]="item.icon"/>
|
|
2829
|
+
</div>
|
|
2830
|
+
|
|
2831
|
+
<div class="flex items-center gap-4 mb-4">
|
|
2832
|
+
<label class="font-semibold w-1/3" for="security">
|
|
2833
|
+
{{ 'menuItemEditDialogComponent.security' | translate }}
|
|
2834
|
+
</label>
|
|
2835
|
+
<p-multiSelect
|
|
2836
|
+
appendTo="body"
|
|
2837
|
+
class="flex-auto"
|
|
2838
|
+
id="oip-menu-item-edit-dialog-roles-multi-select"
|
|
2839
|
+
placeholder="Select roles"
|
|
2840
|
+
[maxSelectedLabels]="10"
|
|
2841
|
+
[options]="roles"
|
|
2842
|
+
[(ngModel)]="item.viewRoles"/>
|
|
2843
|
+
</div>
|
|
2844
|
+
|
|
2845
|
+
<div class="flex justify-end gap-2">
|
|
2846
|
+
<p-button
|
|
2847
|
+
id="oip-menu-item-edit-dialog-cancel-edit-button"
|
|
2848
|
+
label="{{ 'menuItemEditDialogComponent.cancel' | translate }}"
|
|
2849
|
+
severity="secondary"
|
|
2850
|
+
(click)="changeVisible()"
|
|
2851
|
+
(keydown)="changeVisible()"/>
|
|
2852
|
+
<p-button
|
|
2853
|
+
id="oip-menu-item-edit-dialog-save-edit-button"
|
|
2854
|
+
label="{{ 'menuItemEditDialogComponent.save' | translate }}"
|
|
2855
|
+
(click)="save()"
|
|
2856
|
+
(keydown)="save()"/>
|
|
2857
|
+
</div>
|
|
2858
|
+
</p-dialog>
|
|
2859
|
+
`
|
|
2860
|
+
}]
|
|
2861
|
+
}], propDecorators: { visible: [{
|
|
2862
|
+
type: Input
|
|
2863
|
+
}], visibleChange: [{
|
|
2864
|
+
type: Output
|
|
2865
|
+
}] } });
|
|
2866
|
+
|
|
2867
|
+
class MenuComponent {
|
|
2868
|
+
constructor() {
|
|
2869
|
+
this.menuService = inject(MenuService);
|
|
2870
|
+
this.securityService = inject(SecurityService);
|
|
2871
|
+
this.translateService = inject(TranslateService);
|
|
2872
|
+
}
|
|
2873
|
+
ngOnInit() {
|
|
2874
|
+
this.menuService.loadMenu().then();
|
|
2875
|
+
}
|
|
2876
|
+
newClick(e) {
|
|
2877
|
+
this.menuItemCreateDialogComponent.showDialog();
|
|
2878
|
+
}
|
|
2879
|
+
onContextMenu($event) {
|
|
2880
|
+
this.menuService.contextMenuItem = null;
|
|
2881
|
+
this.contextMenu.model = [
|
|
2882
|
+
{
|
|
2883
|
+
label: this.translateService.instant('menuComponent.new'),
|
|
2884
|
+
icon: PrimeIcons.PLUS,
|
|
2885
|
+
command: (event) => this.newClick(event)
|
|
2886
|
+
}
|
|
2887
|
+
];
|
|
2888
|
+
}
|
|
2889
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2890
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: MenuComponent, isStandalone: true, selector: "app-menu", providers: [Menu], viewQueries: [{ propertyName: "menuItemCreateDialogComponent", first: true, predicate: MenuItemCreateDialogComponent, descendants: true }, { propertyName: "menuItemEditDialogComponent", first: true, predicate: MenuItemEditDialogComponent, descendants: true }, { propertyName: "contextMenu", first: true, predicate: ContextMenu, descendants: true }], ngImport: i0, template: ` <div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
2891
|
+
<ul class="layout-menu">
|
|
2892
|
+
@for (item of menuService.menu; track item; let i = $index) {
|
|
2893
|
+
<ng-container>
|
|
2894
|
+
@if (item.separator) {
|
|
2895
|
+
<li class="menu-separator"></li>
|
|
2896
|
+
} @else {
|
|
2897
|
+
<li
|
|
2898
|
+
app-menuitem
|
|
2899
|
+
[contextMenu]="contextMenu"
|
|
2900
|
+
[index]="i"
|
|
2901
|
+
[item]="item"
|
|
2902
|
+
[menuItemCreateDialogComponent]="menuItemCreateDialogComponent"
|
|
2903
|
+
[menuItemEditDialogComponent]="menuItemEditDialogComponent"
|
|
2904
|
+
[root]="true"></li>
|
|
2905
|
+
}
|
|
2906
|
+
</ng-container>
|
|
2907
|
+
}
|
|
2908
|
+
</ul>
|
|
2909
|
+
</div>
|
|
2910
|
+
<p-contextMenu [target]="empty" />
|
|
2911
|
+
@if (securityService.isAdmin) {
|
|
2912
|
+
<menu-item-create-dialog />
|
|
2913
|
+
<menu-item-edit-dialog />
|
|
2914
|
+
}`, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i1$4.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "component", type: MenuItemCreateDialogComponent, selector: "menu-item-create-dialog", inputs: ["visible"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: MenuItemEditDialogComponent, selector: "menu-item-edit-dialog", inputs: ["visible"], outputs: ["visibleChange"] }] }); }
|
|
2915
|
+
}
|
|
2916
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MenuComponent, decorators: [{
|
|
2917
|
+
type: Component,
|
|
2918
|
+
args: [{
|
|
2919
|
+
imports: [
|
|
2920
|
+
MenuItemComponent,
|
|
2921
|
+
ButtonModule,
|
|
2922
|
+
ContextMenuModule,
|
|
2923
|
+
DialogModule,
|
|
2924
|
+
InputTextModule,
|
|
2925
|
+
MenuItemCreateDialogComponent,
|
|
2926
|
+
FormsModule,
|
|
2927
|
+
MenuItemEditDialogComponent
|
|
2928
|
+
],
|
|
2929
|
+
providers: [Menu],
|
|
2930
|
+
selector: 'app-menu',
|
|
2931
|
+
standalone: true,
|
|
2932
|
+
template: ` <div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
2933
|
+
<ul class="layout-menu">
|
|
2934
|
+
@for (item of menuService.menu; track item; let i = $index) {
|
|
2935
|
+
<ng-container>
|
|
2936
|
+
@if (item.separator) {
|
|
2937
|
+
<li class="menu-separator"></li>
|
|
2938
|
+
} @else {
|
|
2939
|
+
<li
|
|
2940
|
+
app-menuitem
|
|
2941
|
+
[contextMenu]="contextMenu"
|
|
2942
|
+
[index]="i"
|
|
2943
|
+
[item]="item"
|
|
2944
|
+
[menuItemCreateDialogComponent]="menuItemCreateDialogComponent"
|
|
2945
|
+
[menuItemEditDialogComponent]="menuItemEditDialogComponent"
|
|
2946
|
+
[root]="true"></li>
|
|
2947
|
+
}
|
|
2948
|
+
</ng-container>
|
|
2949
|
+
}
|
|
2950
|
+
</ul>
|
|
2951
|
+
</div>
|
|
2952
|
+
<p-contextMenu [target]="empty" />
|
|
2953
|
+
@if (securityService.isAdmin) {
|
|
2954
|
+
<menu-item-create-dialog />
|
|
2955
|
+
<menu-item-edit-dialog />
|
|
2956
|
+
}`
|
|
2957
|
+
}]
|
|
2958
|
+
}], propDecorators: { menuItemCreateDialogComponent: [{
|
|
2959
|
+
type: ViewChild,
|
|
2960
|
+
args: [MenuItemCreateDialogComponent]
|
|
2961
|
+
}], menuItemEditDialogComponent: [{
|
|
2962
|
+
type: ViewChild,
|
|
2963
|
+
args: [MenuItemEditDialogComponent]
|
|
2964
|
+
}], contextMenu: [{
|
|
2965
|
+
type: ViewChild,
|
|
2966
|
+
args: [ContextMenu]
|
|
2967
|
+
}] } });
|
|
2968
|
+
|
|
2969
|
+
class SidebarComponent {
|
|
2970
|
+
constructor() { }
|
|
2971
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2972
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: SidebarComponent, isStandalone: true, selector: "app-sidebar", ngImport: i0, template: ` <app-menu></app-menu>`, isInline: true, dependencies: [{ kind: "component", type: MenuComponent, selector: "app-menu" }] }); }
|
|
2973
|
+
}
|
|
2974
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
2975
|
+
type: Component,
|
|
2976
|
+
args: [{
|
|
2977
|
+
selector: 'app-sidebar',
|
|
2978
|
+
template: ` <app-menu></app-menu>`,
|
|
2979
|
+
standalone: true,
|
|
2980
|
+
imports: [MenuComponent]
|
|
2981
|
+
}]
|
|
2982
|
+
}], ctorParameters: () => [] });
|
|
2983
|
+
|
|
2984
|
+
class AppLayoutComponent {
|
|
2985
|
+
constructor() {
|
|
2986
|
+
this.layoutService = inject(LayoutService);
|
|
2987
|
+
this.router = inject(Router);
|
|
2988
|
+
this.renderer = inject(Renderer2);
|
|
2989
|
+
this.overlayMenuOpenSubscription = this.layoutService.overlayOpen$.subscribe(() => {
|
|
2990
|
+
if (!this.menuOutsideClickListener) {
|
|
2991
|
+
this.menuOutsideClickListener = this.renderer.listen('document', 'click', (event) => {
|
|
2992
|
+
if (this.isOutsideClicked(event)) {
|
|
2993
|
+
this.hideMenu();
|
|
2994
|
+
}
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
if (this.layoutService.layoutState().staticMenuMobileActive) {
|
|
2998
|
+
this.blockBodyScroll();
|
|
2999
|
+
}
|
|
3000
|
+
});
|
|
3001
|
+
this.router.events.pipe(filter$1((event) => event instanceof NavigationEnd)).subscribe(() => {
|
|
3002
|
+
this.hideMenu();
|
|
3003
|
+
});
|
|
3004
|
+
}
|
|
3005
|
+
isOutsideClicked(event) {
|
|
3006
|
+
const sidebarEl = document.querySelector('.layout-sidebar');
|
|
3007
|
+
const topbarEl = document.querySelector('.layout-menu-button');
|
|
3008
|
+
const eventTarget = event.target;
|
|
3009
|
+
return !(sidebarEl?.isSameNode(eventTarget) ||
|
|
3010
|
+
sidebarEl?.contains(eventTarget) ||
|
|
3011
|
+
topbarEl?.isSameNode(eventTarget) ||
|
|
3012
|
+
topbarEl?.contains(eventTarget));
|
|
3013
|
+
}
|
|
3014
|
+
hideMenu() {
|
|
3015
|
+
this.layoutService.layoutState.update((prev) => ({
|
|
3016
|
+
...prev,
|
|
3017
|
+
overlayMenuActive: false,
|
|
3018
|
+
staticMenuMobileActive: false,
|
|
3019
|
+
menuHoverActive: false
|
|
3020
|
+
}));
|
|
3021
|
+
if (this.menuOutsideClickListener) {
|
|
3022
|
+
this.menuOutsideClickListener();
|
|
3023
|
+
this.menuOutsideClickListener = null;
|
|
3024
|
+
}
|
|
3025
|
+
this.unblockBodyScroll();
|
|
3026
|
+
}
|
|
3027
|
+
blockBodyScroll() {
|
|
3028
|
+
if (document.body.classList) {
|
|
3029
|
+
document.body.classList.add('blocked-scroll');
|
|
3030
|
+
}
|
|
3031
|
+
else {
|
|
3032
|
+
document.body.className += ' blocked-scroll';
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
unblockBodyScroll() {
|
|
3036
|
+
if (document.body.classList) {
|
|
3037
|
+
document.body.classList.remove('blocked-scroll');
|
|
3038
|
+
}
|
|
3039
|
+
else {
|
|
3040
|
+
document.body.className = document.body.className.replace(new RegExp('(^|\\b)' + 'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
get containerClass() {
|
|
3044
|
+
return {
|
|
3045
|
+
'layout-overlay': this.layoutService.layoutConfig().menuMode === 'overlay',
|
|
3046
|
+
'layout-static': this.layoutService.layoutConfig().menuMode === 'static',
|
|
3047
|
+
'layout-static-inactive': this.layoutService.layoutState().staticMenuDesktopInactive &&
|
|
3048
|
+
this.layoutService.layoutConfig().menuMode === 'static',
|
|
3049
|
+
'layout-overlay-active': this.layoutService.layoutState().overlayMenuActive,
|
|
3050
|
+
'layout-mobile-active': this.layoutService.layoutState().staticMenuMobileActive
|
|
3051
|
+
};
|
|
3052
|
+
}
|
|
3053
|
+
ngOnDestroy() {
|
|
3054
|
+
if (this.overlayMenuOpenSubscription) {
|
|
3055
|
+
this.overlayMenuOpenSubscription.unsubscribe();
|
|
3056
|
+
}
|
|
3057
|
+
if (this.menuOutsideClickListener) {
|
|
3058
|
+
this.menuOutsideClickListener();
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3062
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: AppLayoutComponent, isStandalone: true, selector: "app-layout", providers: [MenuService, Menu], viewQueries: [{ propertyName: "appSidebar", first: true, predicate: SidebarComponent, descendants: true }, { propertyName: "appTopBar", first: true, predicate: AppTopbar, descendants: true }], ngImport: i0, template: `
|
|
3063
|
+
<div class="layout-wrapper" [ngClass]="containerClass">
|
|
3064
|
+
<app-topbar></app-topbar>
|
|
3065
|
+
<app-sidebar></app-sidebar>
|
|
3066
|
+
<div class="layout-main-container">
|
|
3067
|
+
<div class="layout-main">
|
|
3068
|
+
<router-outlet></router-outlet>
|
|
3069
|
+
</div>
|
|
3070
|
+
<app-footer></app-footer>
|
|
3071
|
+
</div>
|
|
3072
|
+
<div class="layout-mask animate-fadein"></div>
|
|
3073
|
+
</div>
|
|
3074
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "app-topbar" }, { kind: "component", type: SidebarComponent, selector: "app-sidebar" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: FooterComponent, selector: "app-footer" }] }); }
|
|
3075
|
+
}
|
|
3076
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppLayoutComponent, decorators: [{
|
|
3077
|
+
type: Component,
|
|
3078
|
+
args: [{
|
|
3079
|
+
selector: 'app-layout',
|
|
3080
|
+
standalone: true,
|
|
3081
|
+
imports: [CommonModule, AppTopbar, SidebarComponent, RouterModule, FooterComponent],
|
|
3082
|
+
template: `
|
|
3083
|
+
<div class="layout-wrapper" [ngClass]="containerClass">
|
|
3084
|
+
<app-topbar></app-topbar>
|
|
3085
|
+
<app-sidebar></app-sidebar>
|
|
3086
|
+
<div class="layout-main-container">
|
|
3087
|
+
<div class="layout-main">
|
|
3088
|
+
<router-outlet></router-outlet>
|
|
3089
|
+
</div>
|
|
3090
|
+
<app-footer></app-footer>
|
|
3091
|
+
</div>
|
|
3092
|
+
<div class="layout-mask animate-fadein"></div>
|
|
3093
|
+
</div>
|
|
3094
|
+
`,
|
|
3095
|
+
providers: [MenuService, Menu]
|
|
3096
|
+
}]
|
|
3097
|
+
}], ctorParameters: () => [], propDecorators: { appSidebar: [{
|
|
3098
|
+
type: ViewChild,
|
|
3099
|
+
args: [SidebarComponent]
|
|
3100
|
+
}], appTopBar: [{
|
|
3101
|
+
type: ViewChild,
|
|
3102
|
+
args: [AppTopbar]
|
|
3103
|
+
}] } });
|
|
3104
|
+
|
|
3105
|
+
class AppFloatingConfiguratorComponent {
|
|
3106
|
+
constructor() {
|
|
3107
|
+
this.LayoutService = inject(LayoutService);
|
|
3108
|
+
this.isDarkTheme = computed(() => this.LayoutService.layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
3109
|
+
}
|
|
3110
|
+
toggleDarkMode() {
|
|
3111
|
+
this.LayoutService.layoutConfig.update((state) => ({
|
|
3112
|
+
...state,
|
|
3113
|
+
darkTheme: !state.darkTheme
|
|
3114
|
+
}));
|
|
3115
|
+
}
|
|
3116
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppFloatingConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3117
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: AppFloatingConfiguratorComponent, isStandalone: true, selector: "app-floating-configurator", ngImport: i0, template: `
|
|
3118
|
+
<div class="fixed flex gap-4 top-8 right-8">
|
|
3119
|
+
<p-button
|
|
3120
|
+
id="oip-app-floating-configurator-dark-theme-button"
|
|
3121
|
+
severity="secondary"
|
|
3122
|
+
type="button"
|
|
3123
|
+
[icon]="isDarkTheme() ? 'pi pi-moon' : 'pi pi-sun'"
|
|
3124
|
+
[rounded]="true"
|
|
3125
|
+
(onClick)="toggleDarkMode()" />
|
|
3126
|
+
<div class="relative">
|
|
3127
|
+
<p-button
|
|
3128
|
+
enterActiveClass="animate-scalein"
|
|
3129
|
+
enterFromClass="hidden"
|
|
3130
|
+
icon="pi pi-palette"
|
|
3131
|
+
id="oip-app-floating-configurator-next-button"
|
|
3132
|
+
leaveActiveClass="animate-fadeout"
|
|
3133
|
+
leaveToClass="hidden"
|
|
3134
|
+
pStyleClass="@next"
|
|
3135
|
+
type="button"
|
|
3136
|
+
[hideOnOutsideClick]="true"
|
|
3137
|
+
[rounded]="true" />
|
|
3138
|
+
<app-configurator />
|
|
3139
|
+
</div>
|
|
3140
|
+
</div>
|
|
3141
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i4.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }] }); }
|
|
3142
|
+
}
|
|
3143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppFloatingConfiguratorComponent, decorators: [{
|
|
3144
|
+
type: Component,
|
|
3145
|
+
args: [{
|
|
3146
|
+
selector: 'app-floating-configurator',
|
|
3147
|
+
imports: [ButtonModule, StyleClassModule, AppConfiguratorComponent],
|
|
3148
|
+
template: `
|
|
3149
|
+
<div class="fixed flex gap-4 top-8 right-8">
|
|
3150
|
+
<p-button
|
|
3151
|
+
id="oip-app-floating-configurator-dark-theme-button"
|
|
3152
|
+
severity="secondary"
|
|
3153
|
+
type="button"
|
|
3154
|
+
[icon]="isDarkTheme() ? 'pi pi-moon' : 'pi pi-sun'"
|
|
3155
|
+
[rounded]="true"
|
|
3156
|
+
(onClick)="toggleDarkMode()" />
|
|
3157
|
+
<div class="relative">
|
|
3158
|
+
<p-button
|
|
3159
|
+
enterActiveClass="animate-scalein"
|
|
3160
|
+
enterFromClass="hidden"
|
|
3161
|
+
icon="pi pi-palette"
|
|
3162
|
+
id="oip-app-floating-configurator-next-button"
|
|
3163
|
+
leaveActiveClass="animate-fadeout"
|
|
3164
|
+
leaveToClass="hidden"
|
|
3165
|
+
pStyleClass="@next"
|
|
3166
|
+
type="button"
|
|
3167
|
+
[hideOnOutsideClick]="true"
|
|
3168
|
+
[rounded]="true" />
|
|
3169
|
+
<app-configurator />
|
|
3170
|
+
</div>
|
|
3171
|
+
</div>
|
|
3172
|
+
`
|
|
3173
|
+
}]
|
|
3174
|
+
}] });
|
|
3175
|
+
|
|
3176
|
+
class NotfoundComponent {
|
|
3177
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NotfoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3178
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: NotfoundComponent, isStandalone: true, selector: "app-notfound", ngImport: i0, template: ` <app-floating-configurator />
|
|
3179
|
+
<div class="flex items-center justify-center min-h-screen overflow-hidden">
|
|
3180
|
+
<div class="flex flex-col items-center justify-center">
|
|
3181
|
+
<div
|
|
3182
|
+
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, color-mix(in srgb, var(--primary-color), transparent 60%) 10%, var(--surface-ground) 30%)">
|
|
3183
|
+
<div
|
|
3184
|
+
class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center"
|
|
3185
|
+
style="border-radius: 53px">
|
|
3186
|
+
<div class="flex flex-col items-center justify-center">
|
|
3187
|
+
<logo height="96" width="96"></logo>
|
|
3188
|
+
</div>
|
|
3189
|
+
<span class="text-primary font-bold text-3xl">404</span>
|
|
3190
|
+
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-3xl lg:text-5xl mb-2">Not Found</h1>
|
|
3191
|
+
<div class="text-surface-600 dark:text-surface-200 mb-8">Requested resource is not available.</div>
|
|
3192
|
+
<p-button id="oip-app-notfound-go-to-home-button" label="Go to home" routerLink="/" />
|
|
3193
|
+
</div>
|
|
3194
|
+
</div>
|
|
3195
|
+
</div>
|
|
3196
|
+
</div>`, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: LogoComponent, selector: "logo", inputs: ["width", "height"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: AppFloatingConfiguratorComponent, selector: "app-floating-configurator" }] }); }
|
|
3197
|
+
}
|
|
3198
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NotfoundComponent, decorators: [{
|
|
3199
|
+
type: Component,
|
|
3200
|
+
args: [{
|
|
3201
|
+
selector: 'app-notfound',
|
|
3202
|
+
template: ` <app-floating-configurator />
|
|
3203
|
+
<div class="flex items-center justify-center min-h-screen overflow-hidden">
|
|
3204
|
+
<div class="flex flex-col items-center justify-center">
|
|
3205
|
+
<div
|
|
3206
|
+
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, color-mix(in srgb, var(--primary-color), transparent 60%) 10%, var(--surface-ground) 30%)">
|
|
3207
|
+
<div
|
|
3208
|
+
class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center"
|
|
3209
|
+
style="border-radius: 53px">
|
|
3210
|
+
<div class="flex flex-col items-center justify-center">
|
|
3211
|
+
<logo height="96" width="96"></logo>
|
|
3212
|
+
</div>
|
|
3213
|
+
<span class="text-primary font-bold text-3xl">404</span>
|
|
3214
|
+
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-3xl lg:text-5xl mb-2">Not Found</h1>
|
|
3215
|
+
<div class="text-surface-600 dark:text-surface-200 mb-8">Requested resource is not available.</div>
|
|
3216
|
+
<p-button id="oip-app-notfound-go-to-home-button" label="Go to home" routerLink="/" />
|
|
3217
|
+
</div>
|
|
3218
|
+
</div>
|
|
3219
|
+
</div>
|
|
3220
|
+
</div>`,
|
|
3221
|
+
imports: [RouterLink, LogoComponent, Button, AppFloatingConfiguratorComponent],
|
|
3222
|
+
standalone: true
|
|
3223
|
+
}]
|
|
3224
|
+
}] });
|
|
3225
|
+
|
|
3226
|
+
class UnauthorizedComponent {
|
|
3227
|
+
constructor() {
|
|
3228
|
+
this.securityService = inject(SecurityService);
|
|
3229
|
+
}
|
|
3230
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: UnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3231
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: UnauthorizedComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
|
|
3232
|
+
<app-floating-configurator />
|
|
3233
|
+
<div
|
|
3234
|
+
class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
|
3235
|
+
<div class="flex flex-col items-center justify-center">
|
|
3236
|
+
<div
|
|
3237
|
+
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
|
3238
|
+
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
|
3239
|
+
<div class="flex flex-col items-center justify-center">
|
|
3240
|
+
<logo [height]="96" [width]="96" />
|
|
3241
|
+
</div>
|
|
3242
|
+
<div class="text-center mb-8">
|
|
3243
|
+
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">
|
|
3244
|
+
{{ 'unauthorized.welcomeToOip' | translate }}
|
|
3245
|
+
</div>
|
|
3246
|
+
<span class="text-muted-color font-medium">{{ 'unauthorized.signInToContinue' | translate }}</span>
|
|
3247
|
+
</div>
|
|
3248
|
+
<div>
|
|
3249
|
+
<p-button
|
|
3250
|
+
id="oip-unauthorized-error-sign-in-button"
|
|
3251
|
+
label="{{ 'unauthorized.signIn' | translate }}"
|
|
3252
|
+
styleClass="w-full"
|
|
3253
|
+
(click)="securityService.authorize()"></p-button>
|
|
3254
|
+
</div>
|
|
3255
|
+
</div>
|
|
3256
|
+
</div>
|
|
3257
|
+
</div>
|
|
3258
|
+
</div>
|
|
3259
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RippleModule }, { kind: "component", type: LogoComponent, selector: "logo", inputs: ["width", "height"] }, { kind: "component", type: AppFloatingConfiguratorComponent, selector: "app-floating-configurator" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3260
|
+
}
|
|
3261
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: UnauthorizedComponent, decorators: [{
|
|
3262
|
+
type: Component,
|
|
3263
|
+
args: [{
|
|
3264
|
+
template: `
|
|
3265
|
+
<app-floating-configurator />
|
|
3266
|
+
<div
|
|
3267
|
+
class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
|
3268
|
+
<div class="flex flex-col items-center justify-center">
|
|
3269
|
+
<div
|
|
3270
|
+
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
|
3271
|
+
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
|
3272
|
+
<div class="flex flex-col items-center justify-center">
|
|
3273
|
+
<logo [height]="96" [width]="96" />
|
|
3274
|
+
</div>
|
|
3275
|
+
<div class="text-center mb-8">
|
|
3276
|
+
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">
|
|
3277
|
+
{{ 'unauthorized.welcomeToOip' | translate }}
|
|
3278
|
+
</div>
|
|
3279
|
+
<span class="text-muted-color font-medium">{{ 'unauthorized.signInToContinue' | translate }}</span>
|
|
3280
|
+
</div>
|
|
3281
|
+
<div>
|
|
3282
|
+
<p-button
|
|
3283
|
+
id="oip-unauthorized-error-sign-in-button"
|
|
3284
|
+
label="{{ 'unauthorized.signIn' | translate }}"
|
|
3285
|
+
styleClass="w-full"
|
|
3286
|
+
(click)="securityService.authorize()"></p-button>
|
|
3287
|
+
</div>
|
|
3288
|
+
</div>
|
|
3289
|
+
</div>
|
|
3290
|
+
</div>
|
|
3291
|
+
</div>
|
|
3292
|
+
`,
|
|
3293
|
+
imports: [
|
|
3294
|
+
ButtonModule,
|
|
3295
|
+
RippleModule,
|
|
3296
|
+
LogoComponent,
|
|
3297
|
+
AppFloatingConfiguratorComponent,
|
|
3298
|
+
ReactiveFormsModule,
|
|
3299
|
+
TranslatePipe
|
|
3300
|
+
]
|
|
3301
|
+
}]
|
|
3302
|
+
}] });
|
|
3303
|
+
|
|
3304
|
+
class ErrorComponent {
|
|
3305
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3306
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: ErrorComponent, isStandalone: true, selector: "app-error", ngImport: i0, template: `<div
|
|
3307
|
+
class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
|
3308
|
+
<div class="flex flex-column align-items-center justify-content-center">
|
|
3309
|
+
<img alt="Sakai logo" class="mb-5 w-6rem flex-shrink-0" src="assets/demo/images/error/logo-error.svg" />
|
|
3310
|
+
<div
|
|
3311
|
+
style="border-radius:56px; padding:0.3rem; background: linear-gradient(180deg, rgba(233, 30, 99, 0.4) 10%, rgba(33, 150, 243, 0) 30%);">
|
|
3312
|
+
<div
|
|
3313
|
+
class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center"
|
|
3314
|
+
style="border-radius:53px">
|
|
3315
|
+
<div class="grid flex flex-column align-items-center">
|
|
3316
|
+
<div
|
|
3317
|
+
class="flex justify-content-center align-items-center bg-pink-500 border-circle"
|
|
3318
|
+
style="height:3.2rem; width:3.2rem;">
|
|
3319
|
+
<i class="pi pi-fw pi-exclamation-circle text-2xl text-white"></i>
|
|
3320
|
+
</div>
|
|
3321
|
+
<h1 class="text-900 font-bold text-5xl mb-2">Error Occured</h1>
|
|
3322
|
+
<span class="text-600 mb-5">Requested resource is not available.</span>
|
|
3323
|
+
<img alt="Error" class="mb-5" src="assets/demo/images/error/asset-error.svg" width="80%" />
|
|
3324
|
+
<button
|
|
3325
|
+
class="p-button-text"
|
|
3326
|
+
icon="pi pi-arrow-left"
|
|
3327
|
+
id="oip-app-error-go-to-dashboard-button"
|
|
3328
|
+
label="Go to Dashboard"
|
|
3329
|
+
pButton
|
|
3330
|
+
pRipple
|
|
3331
|
+
[routerLink]="['/']"></button>
|
|
3332
|
+
</div>
|
|
3333
|
+
</div>
|
|
3334
|
+
</div>
|
|
3335
|
+
</div>
|
|
3336
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i3$1.Ripple, selector: "[pRipple]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
|
|
3337
|
+
}
|
|
3338
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ErrorComponent, decorators: [{
|
|
3339
|
+
type: Component,
|
|
3340
|
+
args: [{
|
|
3341
|
+
selector: 'app-error',
|
|
3342
|
+
template: `<div
|
|
3343
|
+
class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
|
3344
|
+
<div class="flex flex-column align-items-center justify-content-center">
|
|
3345
|
+
<img alt="Sakai logo" class="mb-5 w-6rem flex-shrink-0" src="assets/demo/images/error/logo-error.svg" />
|
|
3346
|
+
<div
|
|
3347
|
+
style="border-radius:56px; padding:0.3rem; background: linear-gradient(180deg, rgba(233, 30, 99, 0.4) 10%, rgba(33, 150, 243, 0) 30%);">
|
|
3348
|
+
<div
|
|
3349
|
+
class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center"
|
|
3350
|
+
style="border-radius:53px">
|
|
3351
|
+
<div class="grid flex flex-column align-items-center">
|
|
3352
|
+
<div
|
|
3353
|
+
class="flex justify-content-center align-items-center bg-pink-500 border-circle"
|
|
3354
|
+
style="height:3.2rem; width:3.2rem;">
|
|
3355
|
+
<i class="pi pi-fw pi-exclamation-circle text-2xl text-white"></i>
|
|
3356
|
+
</div>
|
|
3357
|
+
<h1 class="text-900 font-bold text-5xl mb-2">Error Occured</h1>
|
|
3358
|
+
<span class="text-600 mb-5">Requested resource is not available.</span>
|
|
3359
|
+
<img alt="Error" class="mb-5" src="assets/demo/images/error/asset-error.svg" width="80%" />
|
|
3360
|
+
<button
|
|
3361
|
+
class="p-button-text"
|
|
3362
|
+
icon="pi pi-arrow-left"
|
|
3363
|
+
id="oip-app-error-go-to-dashboard-button"
|
|
3364
|
+
label="Go to Dashboard"
|
|
3365
|
+
pButton
|
|
3366
|
+
pRipple
|
|
3367
|
+
[routerLink]="['/']"></button>
|
|
3368
|
+
</div>
|
|
3369
|
+
</div>
|
|
3370
|
+
</div>
|
|
3371
|
+
</div>
|
|
3372
|
+
</div>`,
|
|
3373
|
+
standalone: true,
|
|
3374
|
+
imports: [ButtonModule, RippleModule, RouterLink]
|
|
3375
|
+
}]
|
|
3376
|
+
}] });
|
|
3377
|
+
|
|
3378
|
+
class ProfileComponent {
|
|
3379
|
+
constructor() {
|
|
3380
|
+
this.userService = inject(UserService);
|
|
3381
|
+
this.msgService = inject(MsgService);
|
|
3382
|
+
this.translateService = inject(TranslateService);
|
|
3383
|
+
}
|
|
3384
|
+
onBasicUploadAuto($event) {
|
|
3385
|
+
this.msgService.success(this.translateService.instant('profileComponent.successfullyUploaded'));
|
|
3386
|
+
}
|
|
3387
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ProfileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3388
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: ProfileComponent, isStandalone: true, selector: "user-profile", ngImport: i0, template: `
|
|
3389
|
+
<p-avatar
|
|
3390
|
+
class="mr-2"
|
|
3391
|
+
id="oip-user-profile-photo-avatar"
|
|
3392
|
+
shape="circle"
|
|
3393
|
+
size="xlarge"
|
|
3394
|
+
[image]="userService.photoLoaded ? userService.photo : null"/>
|
|
3395
|
+
<div class="mt-2">
|
|
3396
|
+
<p-fileupload
|
|
3397
|
+
accept="image/*"
|
|
3398
|
+
chooseIcon="pi pi-upload"
|
|
3399
|
+
chooseLabel="{{ 'profileComponent.changePhoto' | translate }}"
|
|
3400
|
+
id="oip-user-profile-file-upload"
|
|
3401
|
+
maxFileSize="1000000"
|
|
3402
|
+
mode="basic"
|
|
3403
|
+
name="files"
|
|
3404
|
+
url="/api/user-profile/post-user-photo"
|
|
3405
|
+
withCredentials="true"
|
|
3406
|
+
[auto]="true"
|
|
3407
|
+
(onUpload)="onBasicUploadAuto($event)"/>
|
|
3408
|
+
</div>
|
|
3409
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i1$5.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: ImageModule }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i5$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3410
|
+
}
|
|
3411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ProfileComponent, decorators: [{
|
|
3412
|
+
type: Component,
|
|
3413
|
+
args: [{
|
|
3414
|
+
selector: 'user-profile',
|
|
3415
|
+
standalone: true,
|
|
3416
|
+
imports: [FileUploadModule, ImageModule, ImageModule, FileUploadModule, ImageModule, AvatarModule, TranslatePipe],
|
|
3417
|
+
template: `
|
|
3418
|
+
<p-avatar
|
|
3419
|
+
class="mr-2"
|
|
3420
|
+
id="oip-user-profile-photo-avatar"
|
|
3421
|
+
shape="circle"
|
|
3422
|
+
size="xlarge"
|
|
3423
|
+
[image]="userService.photoLoaded ? userService.photo : null"/>
|
|
3424
|
+
<div class="mt-2">
|
|
3425
|
+
<p-fileupload
|
|
3426
|
+
accept="image/*"
|
|
3427
|
+
chooseIcon="pi pi-upload"
|
|
3428
|
+
chooseLabel="{{ 'profileComponent.changePhoto' | translate }}"
|
|
3429
|
+
id="oip-user-profile-file-upload"
|
|
3430
|
+
maxFileSize="1000000"
|
|
3431
|
+
mode="basic"
|
|
3432
|
+
name="files"
|
|
3433
|
+
url="/api/user-profile/post-user-photo"
|
|
3434
|
+
withCredentials="true"
|
|
3435
|
+
[auto]="true"
|
|
3436
|
+
(onUpload)="onBasicUploadAuto($event)"/>
|
|
3437
|
+
</div>
|
|
3438
|
+
`
|
|
3439
|
+
}]
|
|
3440
|
+
}] });
|
|
3441
|
+
|
|
3442
|
+
/**
|
|
3443
|
+
* Service for managing translation loading in the application
|
|
3444
|
+
*/
|
|
3445
|
+
class L10nService {
|
|
3446
|
+
constructor() {
|
|
3447
|
+
this.loadedTranslations = new Set();
|
|
3448
|
+
this.httpClient = inject(HttpClient$1);
|
|
3449
|
+
this.translateService = inject(TranslateService);
|
|
3450
|
+
}
|
|
3451
|
+
/**
|
|
3452
|
+
* Loads translations for a specific component
|
|
3453
|
+
* @param component - Name of the component to load translations for
|
|
3454
|
+
*/
|
|
3455
|
+
async loadComponentTranslations(component) {
|
|
3456
|
+
const lang = this.translateService.currentLang;
|
|
3457
|
+
await this.loadTranslations(component, lang);
|
|
3458
|
+
}
|
|
3459
|
+
/**
|
|
3460
|
+
* Gets the translated value of a key (or an array of keys)
|
|
3461
|
+
* @returns the translated key, or an object of translated keys
|
|
3462
|
+
*/
|
|
3463
|
+
async get(key) {
|
|
3464
|
+
await this.loadComponentTranslations(key);
|
|
3465
|
+
return this.translateService.get(key);
|
|
3466
|
+
}
|
|
3467
|
+
/**
|
|
3468
|
+
* Internal method to load translations from JSON files
|
|
3469
|
+
* @param component - Component or translation namespace
|
|
3470
|
+
* @param lang - Language code to load translations for
|
|
3471
|
+
*/
|
|
3472
|
+
async loadTranslations(component, lang) {
|
|
3473
|
+
// Create unique key for this component-language combination
|
|
3474
|
+
const key = `${component}.${lang}`;
|
|
3475
|
+
// Skip if translations are already loaded
|
|
3476
|
+
if (this.loadedTranslations.has(key)) {
|
|
3477
|
+
return;
|
|
3478
|
+
}
|
|
3479
|
+
try {
|
|
3480
|
+
// Load translation file from assets
|
|
3481
|
+
const translations = await lastValueFrom(this.httpClient.get(`./assets/i18n/${component}.${lang}.json`));
|
|
3482
|
+
// Get existing translations for the language
|
|
3483
|
+
const current = this.translateService.translations[lang] || {};
|
|
3484
|
+
// Merge new translations with existing ones
|
|
3485
|
+
this.translateService.setTranslation(lang, { ...current, ...translations }, true);
|
|
3486
|
+
// Mark these translations as loaded
|
|
3487
|
+
this.loadedTranslations.add(key);
|
|
3488
|
+
}
|
|
3489
|
+
catch (e) {
|
|
3490
|
+
console.warn(`No translations found for ${component}.${lang}.json`);
|
|
3491
|
+
console.error(e);
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
/**
|
|
3495
|
+
* Changes the lang currently used
|
|
3496
|
+
*/
|
|
3497
|
+
use(selectedLanguage) {
|
|
3498
|
+
this.translateService.use(selectedLanguage);
|
|
3499
|
+
}
|
|
3500
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: L10nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3501
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: L10nService, providedIn: 'root' }); }
|
|
3502
|
+
}
|
|
3503
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: L10nService, decorators: [{
|
|
3504
|
+
type: Injectable,
|
|
3505
|
+
args: [{ providedIn: 'root' }]
|
|
3506
|
+
}] });
|
|
3507
|
+
|
|
3508
|
+
class ConfigComponent {
|
|
3509
|
+
constructor() {
|
|
3510
|
+
this.layoutService = inject(LayoutService);
|
|
3511
|
+
this.l10nService = inject(L10nService);
|
|
3512
|
+
this.userService = inject(UserService);
|
|
3513
|
+
this.securityService = inject(SecurityService);
|
|
3514
|
+
this.menuService = inject(MenuService);
|
|
3515
|
+
this.l10n = {};
|
|
3516
|
+
this.languages = [
|
|
3517
|
+
{ value: 'en', label: 'English' },
|
|
3518
|
+
{ value: 'ru', label: 'Русский' }
|
|
3519
|
+
];
|
|
3520
|
+
this.selectedLanguage = this.layoutService.language();
|
|
3521
|
+
}
|
|
3522
|
+
async ngOnInit() {
|
|
3523
|
+
(await this.l10nService.get('config')).subscribe((l10n) => {
|
|
3524
|
+
this.l10n = l10n;
|
|
3525
|
+
});
|
|
3526
|
+
}
|
|
3527
|
+
/**
|
|
3528
|
+
* Changes the application's language.
|
|
3529
|
+
* @return {void}
|
|
3530
|
+
*/
|
|
3531
|
+
changeLanguage() {
|
|
3532
|
+
this.layoutService.layoutConfig.update((config) => ({
|
|
3533
|
+
...config,
|
|
3534
|
+
language: this.selectedLanguage
|
|
3535
|
+
}));
|
|
3536
|
+
this.l10nService.use(this.selectedLanguage);
|
|
3537
|
+
}
|
|
3538
|
+
async onSwitchChange() {
|
|
3539
|
+
await this.menuService.loadMenu();
|
|
3540
|
+
}
|
|
3541
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3542
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ConfigComponent, isStandalone: true, selector: "app-config", ngImport: i0, template: `
|
|
3543
|
+
<p-fluid>
|
|
3544
|
+
<div class="flex flex-col md:flex-row gap-4">
|
|
3545
|
+
<div class="md:w-1/2">
|
|
3546
|
+
<div class="card flex flex-col gap-4">
|
|
3547
|
+
<div class="font-semibold text-xl">{{ l10n.profile }}</div>
|
|
3548
|
+
<div class="flex justify-content-end flex-wrap">
|
|
3549
|
+
{{ userService.userName }}
|
|
3550
|
+
</div>
|
|
3551
|
+
<label>
|
|
3552
|
+
{{ l10n.photo }}
|
|
3553
|
+
<span
|
|
3554
|
+
class="pi pi-question-circle"
|
|
3555
|
+
pTooltip="{{ l10n.usePhoto256x256Pixel }}"
|
|
3556
|
+
tooltipPosition="right"></span>
|
|
3557
|
+
</label>
|
|
3558
|
+
<div class="flex justify-content-end flex-wrap">
|
|
3559
|
+
<user-profile></user-profile>
|
|
3560
|
+
</div>
|
|
3561
|
+
</div>
|
|
3562
|
+
</div>
|
|
3563
|
+
<div class="md:w-1/2">
|
|
3564
|
+
<div class="card flex flex-col gap-4">
|
|
3565
|
+
<div class="font-semibold text-xl">{{ l10n.localization }}</div>
|
|
3566
|
+
<label> {{ l10n.selectLanguage }} </label>
|
|
3567
|
+
<div class="flex justify-content-end flex-wrap">
|
|
3568
|
+
<p-select
|
|
3569
|
+
class="w-full md:w-56"
|
|
3570
|
+
id="oip-app-config-language-select"
|
|
3571
|
+
optionLabel="label"
|
|
3572
|
+
optionValue="value"
|
|
3573
|
+
[options]="languages"
|
|
3574
|
+
[(ngModel)]="selectedLanguage"
|
|
3575
|
+
(onChange)="changeLanguage()" />
|
|
3576
|
+
</div>
|
|
3577
|
+
</div>
|
|
3578
|
+
</div>
|
|
3579
|
+
@if (securityService.isAdmin) {
|
|
3580
|
+
<div class="md:w-1/2">
|
|
3581
|
+
<div class="card flex flex-col gap-4">
|
|
3582
|
+
<div class="font-semibold text-xl">{{ l10n.menu }}</div>
|
|
3583
|
+
<div class="flex items-center gap-2">
|
|
3584
|
+
<label for="oip-app-config-admin-mode">{{ l10n.all }}</label>
|
|
3585
|
+
<p-toggle-switch
|
|
3586
|
+
id="oip-app-config-admin-mode"
|
|
3587
|
+
[(ngModel)]="menuService.adminMode"
|
|
3588
|
+
(onChange)="onSwitchChange()"></p-toggle-switch>
|
|
3589
|
+
</div>
|
|
3590
|
+
<div class="flex items-center gap-2">
|
|
3591
|
+
<label for="oip-app-config-admin-mode">{{ l10n.moduleManagement }}</label>
|
|
3592
|
+
<p-button icon="pi pi-cog" label="{{ l10n.goTo }}" routerLink="/modules" />
|
|
3593
|
+
</div>
|
|
3594
|
+
</div>
|
|
3595
|
+
</div>
|
|
3596
|
+
}
|
|
3597
|
+
</div>
|
|
3598
|
+
</p-fluid>
|
|
3599
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ProfileComponent, selector: "user-profile" }, { kind: "component", type: Fluid, selector: "p-fluid" }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: 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"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TableModule }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$2.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }] }); }
|
|
3600
|
+
}
|
|
3601
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ConfigComponent, decorators: [{
|
|
3602
|
+
type: Component,
|
|
3603
|
+
args: [{
|
|
3604
|
+
selector: 'app-config',
|
|
3605
|
+
template: `
|
|
3606
|
+
<p-fluid>
|
|
3607
|
+
<div class="flex flex-col md:flex-row gap-4">
|
|
3608
|
+
<div class="md:w-1/2">
|
|
3609
|
+
<div class="card flex flex-col gap-4">
|
|
3610
|
+
<div class="font-semibold text-xl">{{ l10n.profile }}</div>
|
|
3611
|
+
<div class="flex justify-content-end flex-wrap">
|
|
3612
|
+
{{ userService.userName }}
|
|
3613
|
+
</div>
|
|
3614
|
+
<label>
|
|
3615
|
+
{{ l10n.photo }}
|
|
3616
|
+
<span
|
|
3617
|
+
class="pi pi-question-circle"
|
|
3618
|
+
pTooltip="{{ l10n.usePhoto256x256Pixel }}"
|
|
3619
|
+
tooltipPosition="right"></span>
|
|
3620
|
+
</label>
|
|
3621
|
+
<div class="flex justify-content-end flex-wrap">
|
|
3622
|
+
<user-profile></user-profile>
|
|
3623
|
+
</div>
|
|
3624
|
+
</div>
|
|
3625
|
+
</div>
|
|
3626
|
+
<div class="md:w-1/2">
|
|
3627
|
+
<div class="card flex flex-col gap-4">
|
|
3628
|
+
<div class="font-semibold text-xl">{{ l10n.localization }}</div>
|
|
3629
|
+
<label> {{ l10n.selectLanguage }} </label>
|
|
3630
|
+
<div class="flex justify-content-end flex-wrap">
|
|
3631
|
+
<p-select
|
|
3632
|
+
class="w-full md:w-56"
|
|
3633
|
+
id="oip-app-config-language-select"
|
|
3634
|
+
optionLabel="label"
|
|
3635
|
+
optionValue="value"
|
|
3636
|
+
[options]="languages"
|
|
3637
|
+
[(ngModel)]="selectedLanguage"
|
|
3638
|
+
(onChange)="changeLanguage()" />
|
|
3639
|
+
</div>
|
|
3640
|
+
</div>
|
|
3641
|
+
</div>
|
|
3642
|
+
@if (securityService.isAdmin) {
|
|
3643
|
+
<div class="md:w-1/2">
|
|
3644
|
+
<div class="card flex flex-col gap-4">
|
|
3645
|
+
<div class="font-semibold text-xl">{{ l10n.menu }}</div>
|
|
3646
|
+
<div class="flex items-center gap-2">
|
|
3647
|
+
<label for="oip-app-config-admin-mode">{{ l10n.all }}</label>
|
|
3648
|
+
<p-toggle-switch
|
|
3649
|
+
id="oip-app-config-admin-mode"
|
|
3650
|
+
[(ngModel)]="menuService.adminMode"
|
|
3651
|
+
(onChange)="onSwitchChange()"></p-toggle-switch>
|
|
3652
|
+
</div>
|
|
3653
|
+
<div class="flex items-center gap-2">
|
|
3654
|
+
<label for="oip-app-config-admin-mode">{{ l10n.moduleManagement }}</label>
|
|
3655
|
+
<p-button icon="pi pi-cog" label="{{ l10n.goTo }}" routerLink="/modules" />
|
|
3656
|
+
</div>
|
|
3657
|
+
</div>
|
|
3658
|
+
</div>
|
|
3659
|
+
}
|
|
3660
|
+
</div>
|
|
3661
|
+
</p-fluid>
|
|
3662
|
+
`,
|
|
3663
|
+
imports: [ProfileComponent, Fluid, Tooltip, FormsModule, Select, TableModule, ToggleSwitchModule, RouterLink, Button]
|
|
3664
|
+
}]
|
|
3665
|
+
}], ctorParameters: () => [] });
|
|
3666
|
+
|
|
3667
|
+
class DbMigrationComponent extends BaseModuleComponent {
|
|
3668
|
+
async ngOnInit() {
|
|
3669
|
+
await super.ngOnInit();
|
|
3670
|
+
await this.refreshAction();
|
|
3671
|
+
}
|
|
3672
|
+
async refreshAction() {
|
|
3673
|
+
this.getData()
|
|
3674
|
+
.then((response) => {
|
|
3675
|
+
this.data = response;
|
|
3676
|
+
})
|
|
3677
|
+
.catch((error) => {
|
|
3678
|
+
console.log(error);
|
|
3679
|
+
this.msgService.error('Error refreshing database');
|
|
3680
|
+
});
|
|
3681
|
+
}
|
|
3682
|
+
async getData() {
|
|
3683
|
+
return this.baseDataService.sendRequest(`api/${this.controller}/get-migrations`, 'GET');
|
|
3684
|
+
}
|
|
3685
|
+
async applyMigration(rowData) {
|
|
3686
|
+
const request = { name: rowData.name };
|
|
3687
|
+
return this.baseDataService.sendRequest(`api/${this.controller}/apply-migration`, 'POST', request);
|
|
3688
|
+
}
|
|
3689
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: DbMigrationComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
3690
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: DbMigrationComponent, isStandalone: true, selector: "db-migration", providers: [ConfirmationService], usesInheritance: true, ngImport: i0, template: `
|
|
3691
|
+
<div *ngIf="isContent" class="card" style="height: 100%">
|
|
3692
|
+
<p-confirmDialog/>
|
|
3693
|
+
<div>
|
|
3694
|
+
<h5>Migration manager</h5>
|
|
3695
|
+
<div class="flex flex-row gap-2">
|
|
3696
|
+
<p-button
|
|
3697
|
+
icon="pi pi-refresh"
|
|
3698
|
+
pTooltip="Refresh"
|
|
3699
|
+
severity="secondary"
|
|
3700
|
+
tooltipPosition="bottom"
|
|
3701
|
+
[outlined]="true"
|
|
3702
|
+
(click)="refreshAction()"/>
|
|
3703
|
+
<p-button
|
|
3704
|
+
icon="pi pi-filter-slash"
|
|
3705
|
+
pTooltip="Clean filter"
|
|
3706
|
+
severity="secondary"
|
|
3707
|
+
tooltipPosition="bottom"
|
|
3708
|
+
[outlined]="true"
|
|
3709
|
+
(click)="dt.clear()"/>
|
|
3710
|
+
</div>
|
|
3711
|
+
<div>
|
|
3712
|
+
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
3713
|
+
<ng-template let-columns pTemplate="header">
|
|
3714
|
+
<tr>
|
|
3715
|
+
<th pSortableColumn="name" scope="col">
|
|
3716
|
+
Migration name
|
|
3717
|
+
<p-columnFilter display="menu" field="name" type="text"/>
|
|
3718
|
+
</th>
|
|
3719
|
+
<th scope="col">Applied</th>
|
|
3720
|
+
<th scope="col">Exist</th>
|
|
3721
|
+
<th>Pending</th>
|
|
3722
|
+
<th scope="col"></th>
|
|
3723
|
+
</tr>
|
|
3724
|
+
</ng-template>
|
|
3725
|
+
|
|
3726
|
+
<ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
|
|
3727
|
+
<tr [pEditableRow]="rowData">
|
|
3728
|
+
<td>
|
|
3729
|
+
{{ rowData.name }}
|
|
3730
|
+
</td>
|
|
3731
|
+
<td>
|
|
3732
|
+
<p-button
|
|
3733
|
+
*ngIf="rowData.applied"
|
|
3734
|
+
icon="pi pi-check"
|
|
3735
|
+
severity="success"
|
|
3736
|
+
[rounded]="true"
|
|
3737
|
+
[text]="true">
|
|
3738
|
+
</p-button>
|
|
3739
|
+
</td>
|
|
3740
|
+
<td>
|
|
3741
|
+
@if (rowData.exist) {
|
|
3742
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"/>
|
|
3743
|
+
}
|
|
3744
|
+
</td>
|
|
3745
|
+
<td>
|
|
3746
|
+
@if (rowData.pending) {
|
|
3747
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
3748
|
+
}
|
|
3749
|
+
</td>
|
|
3750
|
+
<td>
|
|
3751
|
+
<p-button
|
|
3752
|
+
icon="pi pi-bolt"
|
|
3753
|
+
pCancelEditableRow
|
|
3754
|
+
pTooltip="Apply migration"
|
|
3755
|
+
severity="secondary"
|
|
3756
|
+
tooltipPosition="left"
|
|
3757
|
+
[rounded]="true"
|
|
3758
|
+
[text]="true"
|
|
3759
|
+
(click)="applyMigration(rowData)">
|
|
3760
|
+
</p-button>
|
|
3761
|
+
</td>
|
|
3762
|
+
</tr>
|
|
3763
|
+
</ng-template>
|
|
3764
|
+
</p-table>
|
|
3765
|
+
</div>
|
|
3766
|
+
</div>
|
|
3767
|
+
</div>
|
|
3768
|
+
@if (isSecurity) {
|
|
3769
|
+
<security [controller]="controller" [id]="id"/>
|
|
3770
|
+
}
|
|
3771
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$6.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: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$6.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1$6.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i1$6.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i1$6.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: TextareaModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: SecurityComponent, selector: "security", inputs: ["id", "controller"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] }); }
|
|
3772
|
+
}
|
|
3773
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: DbMigrationComponent, decorators: [{
|
|
3774
|
+
type: Component,
|
|
3775
|
+
args: [{
|
|
3776
|
+
imports: [
|
|
3777
|
+
TableModule,
|
|
3778
|
+
SharedModule,
|
|
3779
|
+
TagModule,
|
|
3780
|
+
InputTextModule,
|
|
3781
|
+
TextareaModule,
|
|
3782
|
+
ButtonModule,
|
|
3783
|
+
FormsModule,
|
|
3784
|
+
ConfirmDialog,
|
|
3785
|
+
NgIf,
|
|
3786
|
+
SecurityComponent,
|
|
3787
|
+
Tooltip
|
|
3788
|
+
],
|
|
3789
|
+
selector: 'db-migration',
|
|
3790
|
+
template: `
|
|
3791
|
+
<div *ngIf="isContent" class="card" style="height: 100%">
|
|
3792
|
+
<p-confirmDialog/>
|
|
3793
|
+
<div>
|
|
3794
|
+
<h5>Migration manager</h5>
|
|
3795
|
+
<div class="flex flex-row gap-2">
|
|
3796
|
+
<p-button
|
|
3797
|
+
icon="pi pi-refresh"
|
|
3798
|
+
pTooltip="Refresh"
|
|
3799
|
+
severity="secondary"
|
|
3800
|
+
tooltipPosition="bottom"
|
|
3801
|
+
[outlined]="true"
|
|
3802
|
+
(click)="refreshAction()"/>
|
|
3803
|
+
<p-button
|
|
3804
|
+
icon="pi pi-filter-slash"
|
|
3805
|
+
pTooltip="Clean filter"
|
|
3806
|
+
severity="secondary"
|
|
3807
|
+
tooltipPosition="bottom"
|
|
3808
|
+
[outlined]="true"
|
|
3809
|
+
(click)="dt.clear()"/>
|
|
3810
|
+
</div>
|
|
3811
|
+
<div>
|
|
3812
|
+
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
3813
|
+
<ng-template let-columns pTemplate="header">
|
|
3814
|
+
<tr>
|
|
3815
|
+
<th pSortableColumn="name" scope="col">
|
|
3816
|
+
Migration name
|
|
3817
|
+
<p-columnFilter display="menu" field="name" type="text"/>
|
|
3818
|
+
</th>
|
|
3819
|
+
<th scope="col">Applied</th>
|
|
3820
|
+
<th scope="col">Exist</th>
|
|
3821
|
+
<th>Pending</th>
|
|
3822
|
+
<th scope="col"></th>
|
|
3823
|
+
</tr>
|
|
3824
|
+
</ng-template>
|
|
3825
|
+
|
|
3826
|
+
<ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
|
|
3827
|
+
<tr [pEditableRow]="rowData">
|
|
3828
|
+
<td>
|
|
3829
|
+
{{ rowData.name }}
|
|
3830
|
+
</td>
|
|
3831
|
+
<td>
|
|
3832
|
+
<p-button
|
|
3833
|
+
*ngIf="rowData.applied"
|
|
3834
|
+
icon="pi pi-check"
|
|
3835
|
+
severity="success"
|
|
3836
|
+
[rounded]="true"
|
|
3837
|
+
[text]="true">
|
|
3838
|
+
</p-button>
|
|
3839
|
+
</td>
|
|
3840
|
+
<td>
|
|
3841
|
+
@if (rowData.exist) {
|
|
3842
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"/>
|
|
3843
|
+
}
|
|
3844
|
+
</td>
|
|
3845
|
+
<td>
|
|
3846
|
+
@if (rowData.pending) {
|
|
3847
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
3848
|
+
}
|
|
3849
|
+
</td>
|
|
3850
|
+
<td>
|
|
3851
|
+
<p-button
|
|
3852
|
+
icon="pi pi-bolt"
|
|
3853
|
+
pCancelEditableRow
|
|
3854
|
+
pTooltip="Apply migration"
|
|
3855
|
+
severity="secondary"
|
|
3856
|
+
tooltipPosition="left"
|
|
3857
|
+
[rounded]="true"
|
|
3858
|
+
[text]="true"
|
|
3859
|
+
(click)="applyMigration(rowData)">
|
|
3860
|
+
</p-button>
|
|
3861
|
+
</td>
|
|
3862
|
+
</tr>
|
|
3863
|
+
</ng-template>
|
|
3864
|
+
</p-table>
|
|
3865
|
+
</div>
|
|
3866
|
+
</div>
|
|
3867
|
+
</div>
|
|
3868
|
+
@if (isSecurity) {
|
|
3869
|
+
<security [controller]="controller" [id]="id"/>
|
|
3870
|
+
}
|
|
3871
|
+
`,
|
|
3872
|
+
providers: [ConfirmationService]
|
|
3873
|
+
}]
|
|
3874
|
+
}] });
|
|
3875
|
+
|
|
3876
|
+
/* eslint-disable */
|
|
3877
|
+
/* tslint:disable */
|
|
3878
|
+
// @ts-nocheck
|
|
3879
|
+
/*
|
|
3880
|
+
* ---------------------------------------------------------------
|
|
3881
|
+
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
|
3882
|
+
* ## ##
|
|
3883
|
+
* ## AUTHOR: acacode ##
|
|
3884
|
+
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
|
3885
|
+
* ---------------------------------------------------------------
|
|
3886
|
+
*/
|
|
3887
|
+
class Module extends HttpClient {
|
|
3888
|
+
constructor() {
|
|
3889
|
+
super(...arguments);
|
|
3890
|
+
/**
|
|
3891
|
+
* @description Retrieves all modules stored in the system.
|
|
3892
|
+
*
|
|
3893
|
+
* @tags Module
|
|
3894
|
+
* @name moduleGetAll
|
|
3895
|
+
* @request GET:/api/module/get-all
|
|
3896
|
+
* @secure
|
|
3897
|
+
*/
|
|
3898
|
+
this.moduleGetAll = (params = {}) => this.request({
|
|
3899
|
+
path: `/api/module/get-all`,
|
|
3900
|
+
method: "GET",
|
|
3901
|
+
secure: true,
|
|
3902
|
+
format: "json",
|
|
3903
|
+
...params,
|
|
3904
|
+
});
|
|
3905
|
+
/**
|
|
3906
|
+
* @description Inserts a new module into the system.
|
|
3907
|
+
*
|
|
3908
|
+
* @tags Module
|
|
3909
|
+
* @name moduleInsert
|
|
3910
|
+
* @request POST:/api/module/insert
|
|
3911
|
+
* @secure
|
|
3912
|
+
*/
|
|
3913
|
+
this.moduleInsert = (data, params = {}) => this.request({
|
|
3914
|
+
path: `/api/module/insert`,
|
|
3915
|
+
method: "POST",
|
|
3916
|
+
body: data,
|
|
3917
|
+
secure: true,
|
|
3918
|
+
type: ContentType.Json,
|
|
3919
|
+
...params,
|
|
3920
|
+
});
|
|
3921
|
+
/**
|
|
3922
|
+
* @description Deletes a module by its identifier.
|
|
3923
|
+
*
|
|
3924
|
+
* @tags Module
|
|
3925
|
+
* @name moduleDelete
|
|
3926
|
+
* @request DELETE:/api/module/delete
|
|
3927
|
+
* @secure
|
|
3928
|
+
*/
|
|
3929
|
+
this.moduleDelete = (data, params = {}) => this.request({
|
|
3930
|
+
path: `/api/module/delete`,
|
|
3931
|
+
method: "DELETE",
|
|
3932
|
+
body: data,
|
|
3933
|
+
secure: true,
|
|
3934
|
+
type: ContentType.Json,
|
|
3935
|
+
...params,
|
|
3936
|
+
});
|
|
3937
|
+
/**
|
|
3938
|
+
* @description Returns all registered modules and indicates whether each one is currently loaded into the application.
|
|
3939
|
+
*
|
|
3940
|
+
* @tags Module
|
|
3941
|
+
* @name moduleGetModulesWithLoadStatus
|
|
3942
|
+
* @request GET:/api/module/get-modules-with-load-status
|
|
3943
|
+
* @secure
|
|
3944
|
+
*/
|
|
3945
|
+
this.moduleGetModulesWithLoadStatus = (params = {}) => this.request({
|
|
3946
|
+
path: `/api/module/get-modules-with-load-status`,
|
|
3947
|
+
method: "GET",
|
|
3948
|
+
secure: true,
|
|
3949
|
+
format: "json",
|
|
3950
|
+
...params,
|
|
3951
|
+
});
|
|
3952
|
+
}
|
|
3953
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Module, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3954
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Module }); }
|
|
3955
|
+
}
|
|
3956
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Module, decorators: [{
|
|
3957
|
+
type: Injectable
|
|
3958
|
+
}] });
|
|
3959
|
+
|
|
3960
|
+
class AppModulesComponent {
|
|
3961
|
+
constructor() {
|
|
3962
|
+
this.dataService = inject(BaseDataService);
|
|
3963
|
+
this.modules = [];
|
|
3964
|
+
this.msgService = inject(MsgService);
|
|
3965
|
+
this.confirmationService = inject(ConfirmationService);
|
|
3966
|
+
this.l10nService = inject(L10nService);
|
|
3967
|
+
this.l10n = {};
|
|
3968
|
+
this.titleService = inject(AppTitleService);
|
|
3969
|
+
this.moduleService = inject(Module);
|
|
3970
|
+
}
|
|
3971
|
+
async ngOnInit() {
|
|
3972
|
+
(await this.l10nService.get('app-modules')).subscribe((l) => {
|
|
3973
|
+
this.l10n = l;
|
|
3974
|
+
});
|
|
3975
|
+
this.titleService.setTitle(this.l10n.title);
|
|
3976
|
+
await this.refreshAction();
|
|
3977
|
+
}
|
|
3978
|
+
async refreshAction() {
|
|
3979
|
+
this.modules = await this.moduleService.moduleGetModulesWithLoadStatus();
|
|
3980
|
+
}
|
|
3981
|
+
deleteModule(module) {
|
|
3982
|
+
this.confirmationService.confirm({
|
|
3983
|
+
header: this.l10n.confirm.header,
|
|
3984
|
+
message: this.l10n.confirm.message,
|
|
3985
|
+
icon: 'pi pi-trash',
|
|
3986
|
+
rejectButtonProps: {
|
|
3987
|
+
label: this.l10n.confirm.cancel,
|
|
3988
|
+
severity: 'secondary',
|
|
3989
|
+
outlined: true
|
|
3990
|
+
},
|
|
3991
|
+
acceptButtonProps: {
|
|
3992
|
+
label: this.l10n.confirm.delete,
|
|
3993
|
+
severity: 'danger'
|
|
3994
|
+
},
|
|
3995
|
+
accept: async () => {
|
|
3996
|
+
this.dataService
|
|
3997
|
+
.sendRequest(`api/module/delete`, 'DELETE', {
|
|
3998
|
+
moduleId: module.moduleId
|
|
3999
|
+
})
|
|
4000
|
+
.then(() => this.refreshAction())
|
|
4001
|
+
.catch((error) => console.error(error));
|
|
4002
|
+
this.msgService.success(this.l10n.messages.deleteSuccess);
|
|
4003
|
+
}
|
|
4004
|
+
});
|
|
4005
|
+
}
|
|
4006
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppModulesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4007
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: AppModulesComponent, isStandalone: true, selector: "app-modules", providers: [ConfirmationService, Module], ngImport: i0, template: `
|
|
4008
|
+
<p-confirmDialog></p-confirmDialog>
|
|
4009
|
+
<div class="flex flex-col md:flex-row gap-4">
|
|
4010
|
+
<div class="card w-full">
|
|
4011
|
+
<div class="font-semibold text-xl mb-4">
|
|
4012
|
+
{{ l10n.title }}
|
|
4013
|
+
</div>
|
|
4014
|
+
<div class="mb-4">
|
|
4015
|
+
<p-toolbar>
|
|
4016
|
+
<p-button
|
|
4017
|
+
icon="pi pi-refresh"
|
|
4018
|
+
rounded="true"
|
|
4019
|
+
severity="secondary"
|
|
4020
|
+
text="true"
|
|
4021
|
+
tooltipPosition="bottom"
|
|
4022
|
+
[pTooltip]="l10n.refreshTooltip"
|
|
4023
|
+
(onClick)="refreshAction()"></p-button>
|
|
4024
|
+
</p-toolbar>
|
|
4025
|
+
</div>
|
|
4026
|
+
<p-table class="mt-4" [paginator]="true" [rows]="100" [value]="modules">
|
|
4027
|
+
<ng-template pTemplate="header">
|
|
4028
|
+
<tr>
|
|
4029
|
+
<th>{{ l10n.table.moduleId }}</th>
|
|
4030
|
+
<th>{{ l10n.table.name }}</th>
|
|
4031
|
+
<th>{{ l10n.table.currentlyLoaded }}</th>
|
|
4032
|
+
<th style="width: 4rem"></th>
|
|
4033
|
+
</tr>
|
|
4034
|
+
</ng-template>
|
|
4035
|
+
<ng-template let-module pTemplate="body">
|
|
4036
|
+
<tr>
|
|
4037
|
+
<td>{{ module.moduleId }}</td>
|
|
4038
|
+
<td>{{ module.name }}</td>
|
|
4039
|
+
<td>
|
|
4040
|
+
<p-tag
|
|
4041
|
+
[severity]="module.currentlyLoaded ? 'success' : 'danger'"
|
|
4042
|
+
[value]="module.currentlyLoaded ? l10n.table.yes : l10n.table.no"></p-tag>
|
|
4043
|
+
</td>
|
|
4044
|
+
<td>
|
|
4045
|
+
<p-button
|
|
4046
|
+
icon="pi pi-trash"
|
|
4047
|
+
rounded="true"
|
|
4048
|
+
severity="danger"
|
|
4049
|
+
text="true"
|
|
4050
|
+
tooltipPosition="bottom"
|
|
4051
|
+
[pTooltip]="l10n.table.deleteTooltip"
|
|
4052
|
+
(onClick)="deleteModule(module)"></p-button>
|
|
4053
|
+
</td>
|
|
4054
|
+
</tr>
|
|
4055
|
+
</ng-template>
|
|
4056
|
+
</p-table>
|
|
4057
|
+
</div>
|
|
4058
|
+
</div>
|
|
4059
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$6.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: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i4$2.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position", "draggable"], outputs: ["onHide"] }] }); }
|
|
4060
|
+
}
|
|
4061
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AppModulesComponent, decorators: [{
|
|
4062
|
+
type: Component,
|
|
4063
|
+
args: [{
|
|
4064
|
+
imports: [FormsModule, TableModule, Tag, ButtonModule, ToolbarModule, Tooltip, ConfirmDialog],
|
|
4065
|
+
providers: [ConfirmationService, Module],
|
|
4066
|
+
selector: 'app-modules',
|
|
4067
|
+
template: `
|
|
4068
|
+
<p-confirmDialog></p-confirmDialog>
|
|
4069
|
+
<div class="flex flex-col md:flex-row gap-4">
|
|
4070
|
+
<div class="card w-full">
|
|
4071
|
+
<div class="font-semibold text-xl mb-4">
|
|
4072
|
+
{{ l10n.title }}
|
|
4073
|
+
</div>
|
|
4074
|
+
<div class="mb-4">
|
|
4075
|
+
<p-toolbar>
|
|
4076
|
+
<p-button
|
|
4077
|
+
icon="pi pi-refresh"
|
|
4078
|
+
rounded="true"
|
|
4079
|
+
severity="secondary"
|
|
4080
|
+
text="true"
|
|
4081
|
+
tooltipPosition="bottom"
|
|
4082
|
+
[pTooltip]="l10n.refreshTooltip"
|
|
4083
|
+
(onClick)="refreshAction()"></p-button>
|
|
4084
|
+
</p-toolbar>
|
|
4085
|
+
</div>
|
|
4086
|
+
<p-table class="mt-4" [paginator]="true" [rows]="100" [value]="modules">
|
|
4087
|
+
<ng-template pTemplate="header">
|
|
4088
|
+
<tr>
|
|
4089
|
+
<th>{{ l10n.table.moduleId }}</th>
|
|
4090
|
+
<th>{{ l10n.table.name }}</th>
|
|
4091
|
+
<th>{{ l10n.table.currentlyLoaded }}</th>
|
|
4092
|
+
<th style="width: 4rem"></th>
|
|
4093
|
+
</tr>
|
|
4094
|
+
</ng-template>
|
|
4095
|
+
<ng-template let-module pTemplate="body">
|
|
4096
|
+
<tr>
|
|
4097
|
+
<td>{{ module.moduleId }}</td>
|
|
4098
|
+
<td>{{ module.name }}</td>
|
|
4099
|
+
<td>
|
|
4100
|
+
<p-tag
|
|
4101
|
+
[severity]="module.currentlyLoaded ? 'success' : 'danger'"
|
|
4102
|
+
[value]="module.currentlyLoaded ? l10n.table.yes : l10n.table.no"></p-tag>
|
|
4103
|
+
</td>
|
|
4104
|
+
<td>
|
|
4105
|
+
<p-button
|
|
4106
|
+
icon="pi pi-trash"
|
|
4107
|
+
rounded="true"
|
|
4108
|
+
severity="danger"
|
|
4109
|
+
text="true"
|
|
4110
|
+
tooltipPosition="bottom"
|
|
4111
|
+
[pTooltip]="l10n.table.deleteTooltip"
|
|
4112
|
+
(onClick)="deleteModule(module)"></p-button>
|
|
4113
|
+
</td>
|
|
4114
|
+
</tr>
|
|
4115
|
+
</ng-template>
|
|
4116
|
+
</p-table>
|
|
4117
|
+
</div>
|
|
4118
|
+
</div>
|
|
4119
|
+
`
|
|
4120
|
+
}]
|
|
4121
|
+
}] });
|
|
4122
|
+
|
|
4123
|
+
/**
|
|
4124
|
+
* A route guard that ensures the user is authenticated and has a valid access token.
|
|
4125
|
+
* If the access token is expired, it attempts to refresh the session.
|
|
4126
|
+
* If authentication fails or refresh is unsuccessful, redirects to the unauthorized page.
|
|
4127
|
+
*/
|
|
4128
|
+
class AuthGuardService {
|
|
4129
|
+
constructor() {
|
|
4130
|
+
this.oidcSecurityService = inject(SecurityService);
|
|
4131
|
+
this.router = inject(Router);
|
|
4132
|
+
}
|
|
4133
|
+
/**
|
|
4134
|
+
* Checks whether the route can be activated.
|
|
4135
|
+
* - Returns `true` if the user is authenticated and the token is valid.
|
|
4136
|
+
* - Attempts to refresh the token if expired.
|
|
4137
|
+
* - Redirects to `/unauthorized` if not authenticated or refresh fails.
|
|
4138
|
+
*
|
|
4139
|
+
* @returns {Observable<boolean | UrlTree>} A stream resolving to true (allow), or UrlTree (redirect).
|
|
4140
|
+
*/
|
|
4141
|
+
canActivate() {
|
|
4142
|
+
return combineLatest([this.oidcSecurityService.isAuthenticated(), this.oidcSecurityService.isTokenExpired()]).pipe(switchMap(([authenticated, tokenExpired]) => {
|
|
4143
|
+
if (!authenticated) {
|
|
4144
|
+
return of(this.router.parseUrl('/unauthorized'));
|
|
4145
|
+
}
|
|
4146
|
+
if (!tokenExpired) {
|
|
4147
|
+
return of(true);
|
|
4148
|
+
}
|
|
4149
|
+
// Token is expired; attempt to refresh
|
|
4150
|
+
return this.tryRefreshToken();
|
|
4151
|
+
}));
|
|
4152
|
+
}
|
|
4153
|
+
/**
|
|
4154
|
+
* Attempts to refresh the session using the refresh token.
|
|
4155
|
+
* If successful, allows route activation; otherwise, redirects to `/unauthorized`.
|
|
4156
|
+
*
|
|
4157
|
+
* @returns {boolean | UrlTree} A stream resolving to true or redirect UrlTree.
|
|
4158
|
+
*/
|
|
4159
|
+
tryRefreshToken() {
|
|
4160
|
+
return this.oidcSecurityService.forceRefreshSession().pipe(map((refreshSuccess) => {
|
|
4161
|
+
return refreshSuccess ? true : this.router.parseUrl('/unauthorized');
|
|
4162
|
+
}), catchError((err) => {
|
|
4163
|
+
console.warn(err);
|
|
4164
|
+
return of(this.router.parseUrl('/unauthorized'));
|
|
4165
|
+
}));
|
|
4166
|
+
}
|
|
4167
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AuthGuardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4168
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AuthGuardService }); }
|
|
4169
|
+
}
|
|
4170
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AuthGuardService, decorators: [{
|
|
4171
|
+
type: Injectable
|
|
4172
|
+
}] });
|
|
4173
|
+
|
|
4174
|
+
class SecurityStorageService {
|
|
4175
|
+
read(key) {
|
|
4176
|
+
return localStorage.getItem(key);
|
|
4177
|
+
}
|
|
4178
|
+
write(key, value) {
|
|
4179
|
+
localStorage.setItem(key, value);
|
|
4180
|
+
}
|
|
4181
|
+
remove(key) {
|
|
4182
|
+
localStorage.removeItem(key);
|
|
4183
|
+
}
|
|
4184
|
+
clear() {
|
|
4185
|
+
localStorage.clear();
|
|
4186
|
+
}
|
|
4187
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4188
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityStorageService }); }
|
|
4189
|
+
}
|
|
4190
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurityStorageService, decorators: [{
|
|
4191
|
+
type: Injectable
|
|
4192
|
+
}] });
|
|
4193
|
+
|
|
4194
|
+
const langIntercept = (req, next) => {
|
|
4195
|
+
const layoutService = inject(LayoutService);
|
|
4196
|
+
const lang = layoutService.language() ? layoutService.language() : 'en';
|
|
4197
|
+
const httpHeaders = req.headers.set('Accept-language', lang);
|
|
4198
|
+
const authReq = req.clone({
|
|
4199
|
+
headers: httpHeaders
|
|
4200
|
+
});
|
|
4201
|
+
return next(authReq);
|
|
4202
|
+
};
|
|
4203
|
+
|
|
4204
|
+
class SecurePipe {
|
|
4205
|
+
constructor() {
|
|
4206
|
+
this.http = inject(HttpClient$1);
|
|
4207
|
+
this.sanitizer = inject(DomSanitizer);
|
|
4208
|
+
}
|
|
4209
|
+
transform(url) {
|
|
4210
|
+
return this.http
|
|
4211
|
+
.get(url, { responseType: 'blob' })
|
|
4212
|
+
.pipe(map$1((val) => this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(val))));
|
|
4213
|
+
}
|
|
4214
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
4215
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: SecurePipe, isStandalone: true, name: "secure" }); }
|
|
4216
|
+
}
|
|
4217
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SecurePipe, decorators: [{
|
|
4218
|
+
type: Pipe,
|
|
4219
|
+
args: [{
|
|
4220
|
+
standalone: true,
|
|
4221
|
+
name: 'secure'
|
|
4222
|
+
}]
|
|
4223
|
+
}] });
|
|
4224
|
+
|
|
4225
|
+
/**
|
|
4226
|
+
* Load keycloak settings from backend and save to sessionStorage
|
|
4227
|
+
* @param httpClient
|
|
4228
|
+
* @returns StsConfigHttpLoader
|
|
4229
|
+
*/
|
|
4230
|
+
const httpLoaderAuthFactory = (httpClient) => {
|
|
4231
|
+
const KEYCLOAK_SETTINGS_KEY = 'keycloak-client-settings';
|
|
4232
|
+
const settingsStings = sessionStorage.getItem(KEYCLOAK_SETTINGS_KEY);
|
|
4233
|
+
if (settingsStings) {
|
|
4234
|
+
const config$ = new Observable((subscribe) => {
|
|
4235
|
+
subscribe.next(JSON.parse(settingsStings));
|
|
4236
|
+
});
|
|
4237
|
+
return new StsConfigHttpLoader(config$);
|
|
4238
|
+
}
|
|
4239
|
+
else {
|
|
4240
|
+
const config$ = httpClient.get(`api/security/get-keycloak-client-settings`).pipe(map$1((config) => {
|
|
4241
|
+
const authConfig = {
|
|
4242
|
+
authority: config.authority,
|
|
4243
|
+
redirectUrl: window.location.origin,
|
|
4244
|
+
postLogoutRedirectUri: window.location.origin,
|
|
4245
|
+
clientId: config.clientId,
|
|
4246
|
+
scope: config.scope,
|
|
4247
|
+
responseType: config.responseType,
|
|
4248
|
+
useRefreshToken: config.useRefreshToken,
|
|
4249
|
+
silentRenew: config.silentRenew,
|
|
4250
|
+
logLevel: config.logLevel,
|
|
4251
|
+
secureRoutes: config.secureRoutes
|
|
4252
|
+
};
|
|
4253
|
+
sessionStorage.setItem(KEYCLOAK_SETTINGS_KEY, JSON.stringify(authConfig));
|
|
4254
|
+
return authConfig;
|
|
4255
|
+
}));
|
|
4256
|
+
return new StsConfigHttpLoader(config$);
|
|
4257
|
+
}
|
|
4258
|
+
};
|
|
4259
|
+
|
|
4260
|
+
// Components
|
|
4261
|
+
|
|
4262
|
+
/**
|
|
4263
|
+
* Generated bundle index. Do not edit.
|
|
4264
|
+
*/
|
|
4265
|
+
|
|
4266
|
+
export { AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService, BaseDataService, BaseModuleComponent, ConfigComponent, DbMigrationComponent, ErrorComponent, FooterComponent, LayoutService, LogoComponent, MenuComponent, MenuService, MsgService, NotfoundComponent, ProfileComponent, SecurePipe, SecurityComponent, SecurityDataService, SecurityService, SecurityStorageService, SidebarComponent, TopBarService, UnauthorizedComponent, UserService, httpLoaderAuthFactory, langIntercept };
|
|
4267
|
+
//# sourceMappingURL=oip-common.mjs.map
|