mesauth-angular 1.6.0 → 1.6.2
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/mesauth-angular.mjs +100 -61
- package/fesm2022/mesauth-angular.mjs.map +1 -1
- package/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -875,7 +875,6 @@ class NotificationPanelComponent {
|
|
|
875
875
|
}
|
|
876
876
|
selectedNotification = null;
|
|
877
877
|
selectedNotificationHtml = null;
|
|
878
|
-
selectedNotificationUrl = null;
|
|
879
878
|
selectedNotificationDate = '';
|
|
880
879
|
// Returns plain text message for list display
|
|
881
880
|
getNotificationMessage(notification) {
|
|
@@ -956,9 +955,6 @@ class NotificationPanelComponent {
|
|
|
956
955
|
// Cache computed values to avoid re-rendering on every change detection cycle
|
|
957
956
|
const html = notification.messageHtml || notification.message || '';
|
|
958
957
|
this.selectedNotificationHtml = this.sanitizer.bypassSecurityTrustHtml(html);
|
|
959
|
-
this.selectedNotificationUrl = notification.url?.trim()
|
|
960
|
-
? this.sanitizer.bypassSecurityTrustResourceUrl(notification.url.trim())
|
|
961
|
-
: null;
|
|
962
958
|
this.selectedNotificationDate = this.formatDate(notification.createdAt);
|
|
963
959
|
// Mark as read when opening details (if not already read)
|
|
964
960
|
if (!notification.isRead) {
|
|
@@ -975,9 +971,14 @@ class NotificationPanelComponent {
|
|
|
975
971
|
closeDetails() {
|
|
976
972
|
this.selectedNotification = null;
|
|
977
973
|
this.selectedNotificationHtml = null;
|
|
978
|
-
this.selectedNotificationUrl = null;
|
|
979
974
|
this.selectedNotificationDate = '';
|
|
980
975
|
}
|
|
976
|
+
openUrl() {
|
|
977
|
+
const url = this.selectedNotification?.url?.trim();
|
|
978
|
+
if (url) {
|
|
979
|
+
window.open(url, '_blank');
|
|
980
|
+
}
|
|
981
|
+
}
|
|
981
982
|
markAsRead(notificationId, event) {
|
|
982
983
|
if (event) {
|
|
983
984
|
event.stopPropagation();
|
|
@@ -1124,11 +1125,11 @@ class NotificationPanelComponent {
|
|
|
1124
1125
|
<div class="tabs">
|
|
1125
1126
|
<button class="tab-btn" [class.active]="activeTab === 'unread'" (click)="switchTab('unread')">
|
|
1126
1127
|
Unread
|
|
1127
|
-
<span class="tab-
|
|
1128
|
+
<span class="tab-badge" *ngIf="unreadNotifications.length > 0">{{ unreadNotifications.length }}</span>
|
|
1128
1129
|
</button>
|
|
1129
1130
|
<button class="tab-btn" [class.active]="activeTab === 'read'" (click)="switchTab('read')">
|
|
1130
1131
|
Read
|
|
1131
|
-
<span class="tab-
|
|
1132
|
+
<span class="tab-badge read-badge" *ngIf="readNotifications.length > 0">{{ readNotifications.length }}</span>
|
|
1132
1133
|
</button>
|
|
1133
1134
|
</div>
|
|
1134
1135
|
|
|
@@ -1251,16 +1252,14 @@ class NotificationPanelComponent {
|
|
|
1251
1252
|
<span class="app-name">{{ selectedNotification.sourceAppName }}</span>
|
|
1252
1253
|
<span class="time">{{ selectedNotificationDate }}</span>
|
|
1253
1254
|
</div>
|
|
1254
|
-
<div class="modal-body"
|
|
1255
|
-
<div class="modal-body modal-body-iframe" *ngIf="selectedNotificationUrl">
|
|
1256
|
-
<iframe [src]="selectedNotificationUrl" sandbox="allow-same-origin allow-scripts" class="notification-iframe"></iframe>
|
|
1257
|
-
</div>
|
|
1255
|
+
<div class="modal-body" [innerHTML]="selectedNotificationHtml"></div>
|
|
1258
1256
|
<div class="modal-footer">
|
|
1257
|
+
<button class="action-btn see-details-btn" *ngIf="selectedNotification.url?.trim()" (click)="openUrl()">See Details</button>
|
|
1259
1258
|
<button class="action-btn" (click)="closeDetails()">Close</button>
|
|
1260
1259
|
</div>
|
|
1261
1260
|
</div>
|
|
1262
1261
|
</div>
|
|
1263
|
-
`, isInline: true, styles: [":
|
|
1262
|
+
`, isInline: true, styles: [".panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px 18px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.panel-header-left{display:flex;align-items:center;gap:9px;color:var(--primary)}.panel-header h3{margin:0;font-size:16px;font-weight:700;color:var(--text-primary)}.close-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}.close-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.tabs{display:flex;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.tab-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:11px 8px;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;font-size:13px;font-weight:500;transition:color .15s,border-color .15s}.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary)}.tab-btn:hover:not(.active){color:var(--text-secondary)}.tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;background:var(--primary);color:#fff;font-size:11px;font-weight:700;border-radius:9px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;gap:12px;color:var(--text-muted)}.empty-state p{margin:0;font-size:13px}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;gap:12px;color:var(--text-muted);font-size:13px}.spinner{width:24px;height:24px;border:2px solid var(--border-color);border-top-color:var(--primary);border-radius:50%;animation:spin .7s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n", ":host{display:block;position:relative;--primary: #1976d2;--primary-hover: #1565c0;--success: #43a047;--error: #f44336;--error-hover: #d32f2f;--info-color: #2196f3;--info-bg: rgba(33, 150, 243, .1);--success-bg: rgba(67, 160, 71, .1);--warning-color: #f57c00;--warning-bg: rgba(245, 124, 0, .1);--error-bg: rgba(244, 67, 54, .1);--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f8f9fa;--bg-hover: #f0f4ff;--bg-unread: rgba(25, 118, 210, .06);--border-color: #e0e0e0;--border-light: #eeeeee;--shadow: rgba(0, 0, 0, .15)}:host(.theme-dark){--primary: #90caf9;--primary-hover: #64b5f6;--success: #66bb6a;--error: #ef5350;--error-hover: #c62828;--info-color: #64b5f6;--info-bg: rgba(100, 181, 246, .12);--success-bg: rgba(102, 187, 106, .12);--warning-color: #ffb74d;--warning-bg: rgba(255, 183, 77, .12);--error-bg: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--bg-unread: rgba(144, 202, 249, .08);--border-color: #383850;--border-light: #2e2e42;--shadow: rgba(0, 0, 0, .4)}.tab-btn:not(.active) .tab-badge{background:var(--error)}.read-badge{background:var(--text-muted)}.notification-panel{position:fixed;top:0;right:-360px;width:360px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 24px var(--shadow);display:flex;flex-direction:column;z-index:1030;transition:right .3s cubic-bezier(.16,1,.3,1)}.notification-panel.open{right:0}.notifications-list{flex:1;overflow-y:auto}.notification-item{display:flex;align-items:flex-start;gap:0;border-bottom:1px solid var(--border-light);cursor:pointer;background:var(--bg-primary);transition:background-color .15s;position:relative}.notification-item:hover{background:var(--bg-hover)}.notification-item.unread{background:var(--bg-unread)}.notif-accent{width:3px;align-self:stretch;flex-shrink:0;background:transparent;border-radius:0 2px 2px 0;opacity:.3}.notification-item.unread .notif-accent{opacity:1}.notif-accent.type-info{background:var(--info-color)}.notif-accent.type-success{background:var(--success)}.notif-accent.type-warning{background:var(--warning-color)}.notif-accent.type-error{background:var(--error)}.notif-type-icon{flex-shrink:0;width:26px;height:26px;border-radius:7px;display:flex;align-items:center;justify-content:center;align-self:center;margin-left:10px}.notif-type-icon.type-info{color:var(--info-color);background:var(--info-bg)}.notif-type-icon.type-success{color:var(--success);background:var(--success-bg)}.notif-type-icon.type-warning{color:var(--warning-color);background:var(--warning-bg)}.notif-type-icon.type-error{color:var(--error);background:var(--error-bg)}.notification-content{flex:1;min-width:0;padding:12px 8px 12px 12px}.notification-title{font-weight:600;color:var(--text-primary);font-size:13.5px;margin-bottom:3px;line-height:1.35}.notification-message{color:var(--text-secondary);font-size:12px;line-height:1.45;margin-bottom:7px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-meta{display:flex;justify-content:space-between;font-size:11px;color:var(--text-muted)}.app-name{font-weight:600;color:var(--primary)}.icon-btn{background:none;border:none;cursor:pointer;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center;margin-right:8px;transition:color .15s,background-color .15s;color:var(--text-muted)}.read-btn:hover{color:var(--success);background:#43a0471a}.delete-btn:hover{color:var(--error);background:#f443361a}.panel-footer{padding:10px 14px;border-top:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.footer-actions{display:flex;gap:8px}.footer-actions .action-btn{flex:1}.action-btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:8px 12px;background:var(--primary);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:600;transition:background-color .18s,transform .12s}.action-btn:hover{background:var(--primary-hover);transform:translateY(-1px)}.delete-all-btn{background:var(--error)}.delete-all-btn:hover{background:var(--error-hover)}.modal-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1060;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.modal-container{background:var(--bg-primary);border-radius:14px;width:90%;max-width:580px;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 16px 48px #00000040;animation:modal-in .2s cubic-bezier(.16,1,.3,1)}@keyframes modal-in{0%{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:scale(1) translateY(0)}}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);border-radius:14px 14px 0 0;border-top:3px solid transparent}.modal-header.modal-type-info{border-top-color:var(--info-color)}.modal-header.modal-type-success{border-top-color:var(--success)}.modal-header.modal-type-warning{border-top-color:var(--warning-color)}.modal-header.modal-type-error{border-top-color:var(--error)}.modal-header-left{display:flex;align-items:center;gap:10px;min-width:0}.modal-type-icon{flex-shrink:0;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center}.modal-type-info .modal-type-icon{color:var(--info-color);background:var(--info-bg)}.modal-type-success .modal-type-icon{color:var(--success);background:var(--success-bg)}.modal-type-warning .modal-type-icon{color:var(--warning-color);background:var(--warning-bg)}.modal-type-error .modal-type-icon{color:var(--error);background:var(--error-bg)}.modal-header h3{margin:0;font-size:15px;font-weight:700;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.modal-meta{display:flex;justify-content:space-between;padding:8px 20px;font-size:11.5px;color:var(--text-muted);border-bottom:1px solid var(--border-light)}.modal-body{padding:20px;overflow-y:auto;flex:1;color:var(--text-primary);font-size:14px;line-height:1.65}.modal-footer{padding:12px 20px;border-top:1px solid var(--border-color);background:var(--bg-secondary);border-radius:0 0 14px 14px;display:flex;justify-content:flex-end;gap:8px}.modal-footer .action-btn{width:auto;padding:8px 24px}.modal-footer .see-details-btn{background:var(--info-bg);color:var(--info-color);border:1px solid var(--info-color)}.modal-footer .see-details-btn:hover{opacity:.85}@media(max-width:600px){.notification-panel{width:100%;right:-100%}.modal-container{width:95%;max-height:90vh}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
1264
1263
|
}
|
|
1265
1264
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NotificationPanelComponent, decorators: [{
|
|
1266
1265
|
type: Component,
|
|
@@ -1286,11 +1285,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1286
1285
|
<div class="tabs">
|
|
1287
1286
|
<button class="tab-btn" [class.active]="activeTab === 'unread'" (click)="switchTab('unread')">
|
|
1288
1287
|
Unread
|
|
1289
|
-
<span class="tab-
|
|
1288
|
+
<span class="tab-badge" *ngIf="unreadNotifications.length > 0">{{ unreadNotifications.length }}</span>
|
|
1290
1289
|
</button>
|
|
1291
1290
|
<button class="tab-btn" [class.active]="activeTab === 'read'" (click)="switchTab('read')">
|
|
1292
1291
|
Read
|
|
1293
|
-
<span class="tab-
|
|
1292
|
+
<span class="tab-badge read-badge" *ngIf="readNotifications.length > 0">{{ readNotifications.length }}</span>
|
|
1294
1293
|
</button>
|
|
1295
1294
|
</div>
|
|
1296
1295
|
|
|
@@ -1413,16 +1412,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1413
1412
|
<span class="app-name">{{ selectedNotification.sourceAppName }}</span>
|
|
1414
1413
|
<span class="time">{{ selectedNotificationDate }}</span>
|
|
1415
1414
|
</div>
|
|
1416
|
-
<div class="modal-body"
|
|
1417
|
-
<div class="modal-body modal-body-iframe" *ngIf="selectedNotificationUrl">
|
|
1418
|
-
<iframe [src]="selectedNotificationUrl" sandbox="allow-same-origin allow-scripts" class="notification-iframe"></iframe>
|
|
1419
|
-
</div>
|
|
1415
|
+
<div class="modal-body" [innerHTML]="selectedNotificationHtml"></div>
|
|
1420
1416
|
<div class="modal-footer">
|
|
1417
|
+
<button class="action-btn see-details-btn" *ngIf="selectedNotification.url?.trim()" (click)="openUrl()">See Details</button>
|
|
1421
1418
|
<button class="action-btn" (click)="closeDetails()">Close</button>
|
|
1422
1419
|
</div>
|
|
1423
1420
|
</div>
|
|
1424
1421
|
</div>
|
|
1425
|
-
`, styles: [":
|
|
1422
|
+
`, styles: [".panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px 18px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.panel-header-left{display:flex;align-items:center;gap:9px;color:var(--primary)}.panel-header h3{margin:0;font-size:16px;font-weight:700;color:var(--text-primary)}.close-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}.close-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.tabs{display:flex;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.tab-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:11px 8px;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;font-size:13px;font-weight:500;transition:color .15s,border-color .15s}.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary)}.tab-btn:hover:not(.active){color:var(--text-secondary)}.tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;background:var(--primary);color:#fff;font-size:11px;font-weight:700;border-radius:9px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;gap:12px;color:var(--text-muted)}.empty-state p{margin:0;font-size:13px}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;gap:12px;color:var(--text-muted);font-size:13px}.spinner{width:24px;height:24px;border:2px solid var(--border-color);border-top-color:var(--primary);border-radius:50%;animation:spin .7s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n", ":host{display:block;position:relative;--primary: #1976d2;--primary-hover: #1565c0;--success: #43a047;--error: #f44336;--error-hover: #d32f2f;--info-color: #2196f3;--info-bg: rgba(33, 150, 243, .1);--success-bg: rgba(67, 160, 71, .1);--warning-color: #f57c00;--warning-bg: rgba(245, 124, 0, .1);--error-bg: rgba(244, 67, 54, .1);--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f8f9fa;--bg-hover: #f0f4ff;--bg-unread: rgba(25, 118, 210, .06);--border-color: #e0e0e0;--border-light: #eeeeee;--shadow: rgba(0, 0, 0, .15)}:host(.theme-dark){--primary: #90caf9;--primary-hover: #64b5f6;--success: #66bb6a;--error: #ef5350;--error-hover: #c62828;--info-color: #64b5f6;--info-bg: rgba(100, 181, 246, .12);--success-bg: rgba(102, 187, 106, .12);--warning-color: #ffb74d;--warning-bg: rgba(255, 183, 77, .12);--error-bg: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--bg-unread: rgba(144, 202, 249, .08);--border-color: #383850;--border-light: #2e2e42;--shadow: rgba(0, 0, 0, .4)}.tab-btn:not(.active) .tab-badge{background:var(--error)}.read-badge{background:var(--text-muted)}.notification-panel{position:fixed;top:0;right:-360px;width:360px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 24px var(--shadow);display:flex;flex-direction:column;z-index:1030;transition:right .3s cubic-bezier(.16,1,.3,1)}.notification-panel.open{right:0}.notifications-list{flex:1;overflow-y:auto}.notification-item{display:flex;align-items:flex-start;gap:0;border-bottom:1px solid var(--border-light);cursor:pointer;background:var(--bg-primary);transition:background-color .15s;position:relative}.notification-item:hover{background:var(--bg-hover)}.notification-item.unread{background:var(--bg-unread)}.notif-accent{width:3px;align-self:stretch;flex-shrink:0;background:transparent;border-radius:0 2px 2px 0;opacity:.3}.notification-item.unread .notif-accent{opacity:1}.notif-accent.type-info{background:var(--info-color)}.notif-accent.type-success{background:var(--success)}.notif-accent.type-warning{background:var(--warning-color)}.notif-accent.type-error{background:var(--error)}.notif-type-icon{flex-shrink:0;width:26px;height:26px;border-radius:7px;display:flex;align-items:center;justify-content:center;align-self:center;margin-left:10px}.notif-type-icon.type-info{color:var(--info-color);background:var(--info-bg)}.notif-type-icon.type-success{color:var(--success);background:var(--success-bg)}.notif-type-icon.type-warning{color:var(--warning-color);background:var(--warning-bg)}.notif-type-icon.type-error{color:var(--error);background:var(--error-bg)}.notification-content{flex:1;min-width:0;padding:12px 8px 12px 12px}.notification-title{font-weight:600;color:var(--text-primary);font-size:13.5px;margin-bottom:3px;line-height:1.35}.notification-message{color:var(--text-secondary);font-size:12px;line-height:1.45;margin-bottom:7px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-meta{display:flex;justify-content:space-between;font-size:11px;color:var(--text-muted)}.app-name{font-weight:600;color:var(--primary)}.icon-btn{background:none;border:none;cursor:pointer;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center;margin-right:8px;transition:color .15s,background-color .15s;color:var(--text-muted)}.read-btn:hover{color:var(--success);background:#43a0471a}.delete-btn:hover{color:var(--error);background:#f443361a}.panel-footer{padding:10px 14px;border-top:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.footer-actions{display:flex;gap:8px}.footer-actions .action-btn{flex:1}.action-btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:8px 12px;background:var(--primary);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:600;transition:background-color .18s,transform .12s}.action-btn:hover{background:var(--primary-hover);transform:translateY(-1px)}.delete-all-btn{background:var(--error)}.delete-all-btn:hover{background:var(--error-hover)}.modal-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1060;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.modal-container{background:var(--bg-primary);border-radius:14px;width:90%;max-width:580px;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 16px 48px #00000040;animation:modal-in .2s cubic-bezier(.16,1,.3,1)}@keyframes modal-in{0%{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:scale(1) translateY(0)}}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);border-radius:14px 14px 0 0;border-top:3px solid transparent}.modal-header.modal-type-info{border-top-color:var(--info-color)}.modal-header.modal-type-success{border-top-color:var(--success)}.modal-header.modal-type-warning{border-top-color:var(--warning-color)}.modal-header.modal-type-error{border-top-color:var(--error)}.modal-header-left{display:flex;align-items:center;gap:10px;min-width:0}.modal-type-icon{flex-shrink:0;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center}.modal-type-info .modal-type-icon{color:var(--info-color);background:var(--info-bg)}.modal-type-success .modal-type-icon{color:var(--success);background:var(--success-bg)}.modal-type-warning .modal-type-icon{color:var(--warning-color);background:var(--warning-bg)}.modal-type-error .modal-type-icon{color:var(--error);background:var(--error-bg)}.modal-header h3{margin:0;font-size:15px;font-weight:700;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.modal-meta{display:flex;justify-content:space-between;padding:8px 20px;font-size:11.5px;color:var(--text-muted);border-bottom:1px solid var(--border-light)}.modal-body{padding:20px;overflow-y:auto;flex:1;color:var(--text-primary);font-size:14px;line-height:1.65}.modal-footer{padding:12px 20px;border-top:1px solid var(--border-color);background:var(--bg-secondary);border-radius:0 0 14px 14px;display:flex;justify-content:flex-end;gap:8px}.modal-footer .action-btn{width:auto;padding:8px 24px}.modal-footer .see-details-btn{background:var(--info-bg);color:var(--info-color);border:1px solid var(--info-color)}.modal-footer .see-details-btn:hover{opacity:.85}@media(max-width:600px){.notification-panel{width:100%;right:-100%}.modal-container{width:95%;max-height:90vh}}\n"] }]
|
|
1426
1423
|
}], ctorParameters: () => [{ type: MesAuthService }, { type: ToastService }, { type: ThemeService }], propDecorators: { notificationRead: [{
|
|
1427
1424
|
type: Output
|
|
1428
1425
|
}], themeClass: [{
|
|
@@ -1763,7 +1760,7 @@ class MaApprovalPanelComponent {
|
|
|
1763
1760
|
</ng-container>
|
|
1764
1761
|
</div>
|
|
1765
1762
|
</div>
|
|
1766
|
-
`, isInline: true, styles: ["
|
|
1763
|
+
`, isInline: true, styles: [".panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px 18px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.panel-header-left{display:flex;align-items:center;gap:9px;color:var(--primary)}.panel-header h3{margin:0;font-size:16px;font-weight:700;color:var(--text-primary)}.close-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}.close-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.tabs{display:flex;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.tab-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:11px 8px;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;font-size:13px;font-weight:500;transition:color .15s,border-color .15s}.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary)}.tab-btn:hover:not(.active){color:var(--text-secondary)}.tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;background:var(--primary);color:#fff;font-size:11px;font-weight:700;border-radius:9px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;gap:12px;color:var(--text-muted)}.empty-state p{margin:0;font-size:13px}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;gap:12px;color:var(--text-muted);font-size:13px}.spinner{width:24px;height:24px;border:2px solid var(--border-color);border-top-color:var(--primary);border-radius:50%;animation:spin .7s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n", ":host{--primary: #90caf9;--success: #66bb6a;--error: #ef5350;--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--border-color: #383850;--shadow: rgba(0,0,0,.4)}:host(.theme-light){--primary: #1565c0;--success: #2e7d32;--error: #c62828;--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f5f5f5;--bg-hover: #e8eaf6;--border-color: #e0e0e0;--shadow: rgba(0,0,0,.15)}.approval-backdrop{display:none;position:fixed;inset:0;background:#0006;z-index:1029}.approval-backdrop.open{display:block}.approval-panel{position:fixed;top:0;right:-380px;width:380px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 24px var(--shadow);display:flex;flex-direction:column;z-index:1030;transition:right .3s cubic-bezier(.16,1,.3,1)}.approval-panel.open{right:0}.panel-content{flex:1;overflow-y:auto;padding:8px 0}.approval-item{padding:14px 18px;border-bottom:1px solid var(--border-color);cursor:pointer;transition:background .15s}.approval-item:hover{background:var(--bg-hover)}.approval-item:last-child{border-bottom:none}.item-title{font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-meta{font-size:12px;color:var(--text-muted);margin-bottom:8px;display:flex;gap:4px;flex-wrap:wrap}.item-footer{display:flex;align-items:center;gap:8px}.item-time{font-size:11px;color:var(--text-muted);margin-right:auto}.item-link{font-size:12px;color:var(--primary);font-weight:500}.status-badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;letter-spacing:.3px}.approved-badge{background:#66bb6a26;color:var(--success)}.rejected-badge{background:#ef53501f;color:var(--error)}.show-more{text-align:center;padding:14px;font-size:13px;color:var(--primary);cursor:pointer;font-weight:500}.show-more:hover{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: DatePipe, name: "date" }] });
|
|
1767
1764
|
}
|
|
1768
1765
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: MaApprovalPanelComponent, decorators: [{
|
|
1769
1766
|
type: Component,
|
|
@@ -1871,7 +1868,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1871
1868
|
</ng-container>
|
|
1872
1869
|
</div>
|
|
1873
1870
|
</div>
|
|
1874
|
-
`, styles: ["
|
|
1871
|
+
`, styles: [".panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px 18px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.panel-header-left{display:flex;align-items:center;gap:9px;color:var(--primary)}.panel-header h3{margin:0;font-size:16px;font-weight:700;color:var(--text-primary)}.close-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}.close-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.tabs{display:flex;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.tab-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:11px 8px;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;font-size:13px;font-weight:500;transition:color .15s,border-color .15s}.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary)}.tab-btn:hover:not(.active){color:var(--text-secondary)}.tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;background:var(--primary);color:#fff;font-size:11px;font-weight:700;border-radius:9px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;gap:12px;color:var(--text-muted)}.empty-state p{margin:0;font-size:13px}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;gap:12px;color:var(--text-muted);font-size:13px}.spinner{width:24px;height:24px;border:2px solid var(--border-color);border-top-color:var(--primary);border-radius:50%;animation:spin .7s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n", ":host{--primary: #90caf9;--success: #66bb6a;--error: #ef5350;--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--border-color: #383850;--shadow: rgba(0,0,0,.4)}:host(.theme-light){--primary: #1565c0;--success: #2e7d32;--error: #c62828;--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f5f5f5;--bg-hover: #e8eaf6;--border-color: #e0e0e0;--shadow: rgba(0,0,0,.15)}.approval-backdrop{display:none;position:fixed;inset:0;background:#0006;z-index:1029}.approval-backdrop.open{display:block}.approval-panel{position:fixed;top:0;right:-380px;width:380px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 24px var(--shadow);display:flex;flex-direction:column;z-index:1030;transition:right .3s cubic-bezier(.16,1,.3,1)}.approval-panel.open{right:0}.panel-content{flex:1;overflow-y:auto;padding:8px 0}.approval-item{padding:14px 18px;border-bottom:1px solid var(--border-color);cursor:pointer;transition:background .15s}.approval-item:hover{background:var(--bg-hover)}.approval-item:last-child{border-bottom:none}.item-title{font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-meta{font-size:12px;color:var(--text-muted);margin-bottom:8px;display:flex;gap:4px;flex-wrap:wrap}.item-footer{display:flex;align-items:center;gap:8px}.item-time{font-size:11px;color:var(--text-muted);margin-right:auto}.item-link{font-size:12px;color:var(--primary);font-weight:500}.status-badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;letter-spacing:.3px}.approved-badge{background:#66bb6a26;color:var(--success)}.rejected-badge{background:#ef53501f;color:var(--error)}.show-more{text-align:center;padding:14px;font-size:13px;color:var(--primary);cursor:pointer;font-weight:500}.show-more:hover{text-decoration:underline}\n"] }]
|
|
1875
1872
|
}], propDecorators: { approvalActioned: [{
|
|
1876
1873
|
type: Output
|
|
1877
1874
|
}] } });
|
|
@@ -2095,22 +2092,49 @@ class MaArvContainerComponent {
|
|
|
2095
2092
|
this.stepCandidates = steps.map(() => []);
|
|
2096
2093
|
this.stepLoadingCandidates = steps.map(() => false);
|
|
2097
2094
|
this.stepSelectedUsers = steps.map(() => '');
|
|
2095
|
+
const config = this.mesAuth.getConfig();
|
|
2098
2096
|
steps.forEach((step, i) => {
|
|
2099
|
-
if (
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2097
|
+
if (step.roles && step.roles.length > 0) {
|
|
2098
|
+
// Role-based: fetch candidates via role preview
|
|
2099
|
+
this.stepLoadingCandidates[i] = true;
|
|
2100
|
+
const calls = step.roles.map(r => this.approvalSvc.previewRole(r.orgCode, r.positionLevel));
|
|
2101
|
+
forkJoin(calls.length > 0 ? calls : [of([])])
|
|
2102
|
+
.pipe(takeUntil(this.destroy$))
|
|
2103
|
+
.subscribe({
|
|
2104
|
+
next: results => {
|
|
2105
|
+
const merged = new Map();
|
|
2106
|
+
results.forEach(list => list.forEach(u => merged.set(u.userId, u)));
|
|
2107
|
+
this.stepCandidates[i] = Array.from(merged.values());
|
|
2108
|
+
this.stepLoadingCandidates[i] = false;
|
|
2109
|
+
},
|
|
2110
|
+
error: () => { this.stepLoadingCandidates[i] = false; }
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
else if (step.assigneeUserIds && step.assigneeUserIds.length > 0 && config) {
|
|
2114
|
+
// Search-selected employees: resolve IDs to display names
|
|
2115
|
+
this.stepLoadingCandidates[i] = true;
|
|
2116
|
+
const base = config.apiBaseUrl.replace(/\/$/, '');
|
|
2117
|
+
const opts = { withCredentials: config.withCredentials ?? true };
|
|
2118
|
+
const calls = step.assigneeUserIds.map(uid => this.http.get(`${base}/urs/users/${encodeURIComponent(uid)}`, opts));
|
|
2119
|
+
forkJoin(calls)
|
|
2120
|
+
.pipe(takeUntil(this.destroy$))
|
|
2121
|
+
.subscribe({
|
|
2122
|
+
next: results => {
|
|
2123
|
+
this.stepCandidates[i] = results.map((u) => ({
|
|
2124
|
+
userId: u.id || u.Id,
|
|
2125
|
+
fullName: u.fullName || u.FullName || u.userName || u.UserName,
|
|
2126
|
+
department: u.department || u.Department,
|
|
2127
|
+
position: u.position || u.Position
|
|
2128
|
+
}));
|
|
2129
|
+
// Single assignee — pre-select automatically
|
|
2130
|
+
if (this.stepCandidates[i].length === 1) {
|
|
2131
|
+
this.stepSelectedUsers[i] = this.stepCandidates[i][0].userId;
|
|
2132
|
+
}
|
|
2133
|
+
this.stepLoadingCandidates[i] = false;
|
|
2134
|
+
},
|
|
2135
|
+
error: () => { this.stepLoadingCandidates[i] = false; }
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2114
2138
|
});
|
|
2115
2139
|
}
|
|
2116
2140
|
onStepUserChange(stepIndex, event) {
|
|
@@ -2226,11 +2250,12 @@ class MaArvContainerComponent {
|
|
|
2226
2250
|
this.errorMessage = 'Please add at least one approval step.';
|
|
2227
2251
|
return;
|
|
2228
2252
|
}
|
|
2229
|
-
// Validate role-based
|
|
2253
|
+
// Validate selectable steps (role-based or multi-assignee) have a selected approver
|
|
2230
2254
|
if (this.routingMode === 'template' && this.selectedTemplate) {
|
|
2231
2255
|
for (let i = 0; i < this.selectedTemplate.steps.length; i++) {
|
|
2232
2256
|
const step = this.selectedTemplate.steps[i];
|
|
2233
|
-
|
|
2257
|
+
const isSelectable = (this.stepCandidates[i]?.length ?? 0) > 1;
|
|
2258
|
+
if (isSelectable && !this.stepSelectedUsers[i]) {
|
|
2234
2259
|
this.errorMessage = `Please select an approver for step "${step.stepName}".`;
|
|
2235
2260
|
return;
|
|
2236
2261
|
}
|
|
@@ -2258,14 +2283,14 @@ class MaArvContainerComponent {
|
|
|
2258
2283
|
request.templateId = this.selectedTemplateId ?? this.templateId;
|
|
2259
2284
|
// If template has role-based steps with selected approvers, pass explicit steps
|
|
2260
2285
|
if (this.selectedTemplate) {
|
|
2261
|
-
const
|
|
2262
|
-
if (
|
|
2286
|
+
const hasSelectableSteps = this.selectedTemplate.steps.some((s, i) => (this.stepCandidates[i]?.length ?? 0) > 0);
|
|
2287
|
+
if (hasSelectableSteps) {
|
|
2263
2288
|
request.steps = this.selectedTemplate.steps.map((s, i) => ({
|
|
2264
2289
|
stepOrder: s.stepOrder,
|
|
2265
2290
|
stepName: s.stepName,
|
|
2266
2291
|
mode: s.mode,
|
|
2267
|
-
approverUserIds:
|
|
2268
|
-
?
|
|
2292
|
+
approverUserIds: this.stepSelectedUsers[i]
|
|
2293
|
+
? [this.stepSelectedUsers[i]]
|
|
2269
2294
|
: s.assigneeUserIds
|
|
2270
2295
|
}));
|
|
2271
2296
|
}
|
|
@@ -2323,7 +2348,27 @@ class MaArvContainerComponent {
|
|
|
2323
2348
|
if (img)
|
|
2324
2349
|
cloneCanvas.replaceWith(img.cloneNode(true));
|
|
2325
2350
|
});
|
|
2326
|
-
// Step 4: Inline
|
|
2351
|
+
// Step 4: Inline all <img> sources as base64 data URIs for content integrity
|
|
2352
|
+
const imgElements = Array.from(clone.querySelectorAll('img'));
|
|
2353
|
+
await Promise.all(imgElements.map(async (img) => {
|
|
2354
|
+
const src = img.getAttribute('src');
|
|
2355
|
+
if (!src || src.startsWith('data:'))
|
|
2356
|
+
return;
|
|
2357
|
+
try {
|
|
2358
|
+
const resp = await fetch(src, { mode: 'cors', credentials: 'same-origin' });
|
|
2359
|
+
if (!resp.ok)
|
|
2360
|
+
return;
|
|
2361
|
+
const blob = await resp.blob();
|
|
2362
|
+
const dataUri = await new Promise((resolve) => {
|
|
2363
|
+
const reader = new FileReader();
|
|
2364
|
+
reader.onloadend = () => resolve(reader.result);
|
|
2365
|
+
reader.readAsDataURL(blob);
|
|
2366
|
+
});
|
|
2367
|
+
img.setAttribute('src', dataUri);
|
|
2368
|
+
}
|
|
2369
|
+
catch { /* keep original src if fetch fails */ }
|
|
2370
|
+
}));
|
|
2371
|
+
// Step 5: Inline only essential layout styles (skip colors, widths, cursors)
|
|
2327
2372
|
const liveElements = Array.from(host.querySelectorAll('*'));
|
|
2328
2373
|
const cloneElements = Array.from(clone.querySelectorAll('*'));
|
|
2329
2374
|
const styleProps = this.getStyleProperties();
|
|
@@ -2345,7 +2390,7 @@ class MaArvContainerComponent {
|
|
|
2345
2390
|
}
|
|
2346
2391
|
catch { }
|
|
2347
2392
|
});
|
|
2348
|
-
// Step
|
|
2393
|
+
// Step 6: Strip scripts, Angular attributes, style/link tags, and form elements
|
|
2349
2394
|
clone.querySelectorAll('script, link, style').forEach(el => el.remove());
|
|
2350
2395
|
clone.querySelectorAll('*').forEach(el => {
|
|
2351
2396
|
// Remove Angular-specific attributes
|
|
@@ -2363,7 +2408,7 @@ class MaArvContainerComponent {
|
|
|
2363
2408
|
// Remove class attribute (framework-specific classes add no value)
|
|
2364
2409
|
el.removeAttribute('class');
|
|
2365
2410
|
});
|
|
2366
|
-
// Step
|
|
2411
|
+
// Step 7: Wrap in a clean, print-friendly HTML document
|
|
2367
2412
|
return `<!DOCTYPE html>
|
|
2368
2413
|
<html>
|
|
2369
2414
|
<head>
|
|
@@ -2475,8 +2520,8 @@ ${clone.outerHTML}
|
|
|
2475
2520
|
{{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}
|
|
2476
2521
|
</span>
|
|
2477
2522
|
</div>
|
|
2478
|
-
<!--
|
|
2479
|
-
<div *ngIf="
|
|
2523
|
+
<!-- Selectable step (role-based or multi-assignee): show approver picker -->
|
|
2524
|
+
<div *ngIf="stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]" class="arv-step-picker">
|
|
2480
2525
|
<div *ngIf="stepLoadingCandidates[i]" class="arv-template-loading">Loading candidates...</div>
|
|
2481
2526
|
<select *ngIf="!stepLoadingCandidates[i]" class="arv-select arv-select-sm"
|
|
2482
2527
|
(change)="onStepUserChange(i, $event)">
|
|
@@ -2486,13 +2531,10 @@ ${clone.outerHTML}
|
|
|
2486
2531
|
{{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}
|
|
2487
2532
|
</option>
|
|
2488
2533
|
</select>
|
|
2489
|
-
<div *ngIf="!stepLoadingCandidates[i] && stepCandidates[i]?.length === 0" class="arv-template-loading">
|
|
2490
|
-
No candidates found for this role.
|
|
2491
|
-
</div>
|
|
2492
2534
|
</div>
|
|
2493
|
-
<!--
|
|
2494
|
-
<div *ngIf="!
|
|
2495
|
-
{{
|
|
2535
|
+
<!-- Single fixed-user step: show who is assigned -->
|
|
2536
|
+
<div *ngIf="!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1" class="arv-step-fixed">
|
|
2537
|
+
{{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}
|
|
2496
2538
|
</div>
|
|
2497
2539
|
</div>
|
|
2498
2540
|
<div *ngIf="selectedTemplate.referenceUserIds.length > 0" class="arv-step-preview arv-step-preview-cc">
|
|
@@ -2642,8 +2684,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2642
2684
|
{{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}
|
|
2643
2685
|
</span>
|
|
2644
2686
|
</div>
|
|
2645
|
-
<!--
|
|
2646
|
-
<div *ngIf="
|
|
2687
|
+
<!-- Selectable step (role-based or multi-assignee): show approver picker -->
|
|
2688
|
+
<div *ngIf="stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]" class="arv-step-picker">
|
|
2647
2689
|
<div *ngIf="stepLoadingCandidates[i]" class="arv-template-loading">Loading candidates...</div>
|
|
2648
2690
|
<select *ngIf="!stepLoadingCandidates[i]" class="arv-select arv-select-sm"
|
|
2649
2691
|
(change)="onStepUserChange(i, $event)">
|
|
@@ -2653,13 +2695,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2653
2695
|
{{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}
|
|
2654
2696
|
</option>
|
|
2655
2697
|
</select>
|
|
2656
|
-
<div *ngIf="!stepLoadingCandidates[i] && stepCandidates[i]?.length === 0" class="arv-template-loading">
|
|
2657
|
-
No candidates found for this role.
|
|
2658
|
-
</div>
|
|
2659
2698
|
</div>
|
|
2660
|
-
<!--
|
|
2661
|
-
<div *ngIf="!
|
|
2662
|
-
{{
|
|
2699
|
+
<!-- Single fixed-user step: show who is assigned -->
|
|
2700
|
+
<div *ngIf="!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1" class="arv-step-fixed">
|
|
2701
|
+
{{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}
|
|
2663
2702
|
</div>
|
|
2664
2703
|
</div>
|
|
2665
2704
|
<div *ngIf="selectedTemplate.referenceUserIds.length > 0" class="arv-step-preview arv-step-preview-cc">
|