mesauth-angular 1.7.0 → 1.7.1
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.
|
@@ -2027,6 +2027,7 @@ class MaArvContainerComponent {
|
|
|
2027
2027
|
description;
|
|
2028
2028
|
referenceId = '';
|
|
2029
2029
|
templateId;
|
|
2030
|
+
templateIds;
|
|
2030
2031
|
callbackUrl;
|
|
2031
2032
|
deadlineHours;
|
|
2032
2033
|
approvalSubmitted = new EventEmitter();
|
|
@@ -2078,6 +2079,8 @@ class MaArvContainerComponent {
|
|
|
2078
2079
|
loadTemplates() {
|
|
2079
2080
|
this.approvalSvc.getTemplates().pipe(takeUntil(this.destroy$)).subscribe({
|
|
2080
2081
|
next: (t) => {
|
|
2082
|
+
if (this.templateIds && this.templateIds.length > 0)
|
|
2083
|
+
t = t.filter(temp => this.templateIds.includes(temp.id));
|
|
2081
2084
|
this.templates = t;
|
|
2082
2085
|
if (this.templateId != null && this.selectedTemplateId == null) {
|
|
2083
2086
|
this.selectedTemplateId = this.templateId;
|
|
@@ -2485,329 +2488,429 @@ ${clone.outerHTML}
|
|
|
2485
2488
|
];
|
|
2486
2489
|
}
|
|
2487
2490
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: MaArvContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2488
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2489
|
-
|
|
2491
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.7", type: MaArvContainerComponent, isStandalone: true, selector: "ma-arv-container", inputs: { title: "title", description: "description", referenceId: "referenceId", templateId: "templateId", templateIds: "templateIds", callbackUrl: "callbackUrl", deadlineHours: "deadlineHours" }, outputs: { approvalSubmitted: "approvalSubmitted", approvalSubmitting: "approvalSubmitting", cancelled: "cancelled" }, host: { properties: { "class": "this.themeClass" } }, viewQueries: [{ propertyName: "contentBody", first: true, predicate: ["contentBody"], descendants: true, static: true }], ngImport: i0, template: `
|
|
2492
|
+
<div class="arv-container">
|
|
2490
2493
|
<!-- Content Area -->
|
|
2491
2494
|
<div class="arv-content-body" #contentBody>
|
|
2492
2495
|
<ng-content></ng-content>
|
|
2493
2496
|
</div>
|
|
2494
2497
|
|
|
2495
2498
|
<!-- Approval Footer -->
|
|
2496
|
-
<div class="arv-footer"
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
<div class="arv-routing
|
|
2502
|
-
<
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
<
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
<div *ngIf="templateId && routingMode === 'template'" class="arv-template-select">
|
|
2516
|
-
<div *ngIf="loadingTemplate" class="arv-template-loading">Loading template...</div>
|
|
2517
|
-
<div *ngIf="selectedTemplate && !loadingTemplate" class="arv-locked-template">
|
|
2518
|
-
<span class="arv-locked-label">Template</span>
|
|
2519
|
-
<span class="arv-locked-name">{{ selectedTemplate.name }}</span>
|
|
2499
|
+
<div class="arv-footer">
|
|
2500
|
+
@if (!isSubmitted) {
|
|
2501
|
+
<div class="arv-footer-inner">
|
|
2502
|
+
|
|
2503
|
+
<!-- Routing mode -->
|
|
2504
|
+
<div class="arv-routing">
|
|
2505
|
+
<div class="arv-routing-header">
|
|
2506
|
+
<h4 class="arv-section-title">Approval Routing</h4>
|
|
2507
|
+
<!-- Show routing toggle only when templateId is NOT locked to a single template -->
|
|
2508
|
+
@if (!templateId || (templateIds && templateIds.length > 0)) {
|
|
2509
|
+
<div class="arv-routing-mode">
|
|
2510
|
+
<label class="arv-radio">
|
|
2511
|
+
<input type="radio" name="routingMode" value="template" [checked]="routingMode === 'template'" (change)="routingMode = 'template'"> Use Template
|
|
2512
|
+
</label>
|
|
2513
|
+
<label class="arv-radio">
|
|
2514
|
+
<input type="radio" name="routingMode" value="adhoc" [checked]="routingMode === 'adhoc'" (change)="routingMode = 'adhoc'"> Custom Steps
|
|
2515
|
+
</label>
|
|
2516
|
+
</div>
|
|
2517
|
+
}
|
|
2520
2518
|
</div>
|
|
2521
|
-
</div>
|
|
2522
2519
|
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
<div class="arv-step-card" *ngFor="let s of selectedTemplate.steps; let i = index">
|
|
2536
|
-
<div class="arv-step-card-header">
|
|
2537
|
-
<span class="arv-step-preview-num">Step {{ s.stepOrder }}</span>
|
|
2538
|
-
<span class="arv-step-preview-name">{{ s.stepName }}</span>
|
|
2539
|
-
<span *ngIf="s.roles && s.roles.length > 0" class="arv-step-role-badge">
|
|
2540
|
-
{{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}
|
|
2541
|
-
</span>
|
|
2542
|
-
</div>
|
|
2543
|
-
<!-- Selectable step (role-based or multi-assignee): show approver picker -->
|
|
2544
|
-
<div *ngIf="stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]" class="arv-step-picker">
|
|
2545
|
-
<div *ngIf="stepLoadingCandidates[i]" class="arv-template-loading">Loading candidates...</div>
|
|
2546
|
-
<select *ngIf="!stepLoadingCandidates[i]" class="arv-select arv-select-sm"
|
|
2547
|
-
(change)="onStepUserChange(i, $event)">
|
|
2548
|
-
<option value="">-- Select approver --</option>
|
|
2549
|
-
<option *ngFor="let u of stepCandidates[i]" [value]="u.userId"
|
|
2550
|
-
[selected]="u.userId === stepSelectedUsers[i]">
|
|
2551
|
-
{{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}
|
|
2552
|
-
</option>
|
|
2553
|
-
</select>
|
|
2554
|
-
</div>
|
|
2555
|
-
<!-- Single fixed-user step: show who is assigned -->
|
|
2556
|
-
<div *ngIf="!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1" class="arv-step-fixed">
|
|
2557
|
-
{{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}
|
|
2558
|
-
</div>
|
|
2520
|
+
<!-- Locked template: only when templateId set and no multi-choice -->
|
|
2521
|
+
@if (templateId && (!templateIds || templateIds.length <= 1) && routingMode === 'template') {
|
|
2522
|
+
<div class="arv-template-select">
|
|
2523
|
+
@if (loadingTemplate) {
|
|
2524
|
+
<div class="arv-template-loading">Loading template...</div>
|
|
2525
|
+
}
|
|
2526
|
+
@if (selectedTemplate && !loadingTemplate) {
|
|
2527
|
+
<div class="arv-locked-template">
|
|
2528
|
+
<span class="arv-locked-label">Template</span>
|
|
2529
|
+
<span class="arv-locked-name">{{ selectedTemplate.name }}</span>
|
|
2530
|
+
</div>
|
|
2531
|
+
}
|
|
2559
2532
|
</div>
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
<!-- Template selector: shown when no templateId, OR when templateIds has multiple choices -->
|
|
2536
|
+
@if ((!templateId || (templateIds && templateIds.length > 1)) && routingMode === 'template') {
|
|
2537
|
+
<div class="arv-template-select">
|
|
2538
|
+
<label class="arv-label">Select Template</label>
|
|
2539
|
+
<select class="arv-select" (change)="onTemplateChange($event)">
|
|
2540
|
+
<option value="">-- Select a template --</option>
|
|
2541
|
+
@for (t of templates; track t.id) {
|
|
2542
|
+
<option [value]="t.id" [selected]="t.id === selectedTemplateId">{{ t.name }}</option>
|
|
2543
|
+
}
|
|
2544
|
+
</select>
|
|
2563
2545
|
</div>
|
|
2564
|
-
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
<!-- Step pickers (shared for both locked and free template) -->
|
|
2549
|
+
@if (routingMode === 'template') {
|
|
2550
|
+
<div class="arv-template-select">
|
|
2551
|
+
@if (!loadingTemplate && selectedTemplate) {
|
|
2552
|
+
<div class="arv-template-steps">
|
|
2553
|
+
@for (s of selectedTemplate.steps; track s.stepOrder; let i = $index) {
|
|
2554
|
+
<div class="arv-step-card">
|
|
2555
|
+
<div class="arv-step-card-header">
|
|
2556
|
+
<span class="arv-step-preview-num">Step {{ s.stepOrder }}</span>
|
|
2557
|
+
<span class="arv-step-preview-name">{{ s.stepName }}</span>
|
|
2558
|
+
@if (s.roles && s.roles.length > 0) {
|
|
2559
|
+
<span class="arv-step-role-badge">
|
|
2560
|
+
{{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}
|
|
2561
|
+
</span>
|
|
2562
|
+
}
|
|
2563
|
+
</div>
|
|
2564
|
+
<!-- Selectable step: show approver picker -->
|
|
2565
|
+
@if (stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]) {
|
|
2566
|
+
<div class="arv-step-picker">
|
|
2567
|
+
@if (stepLoadingCandidates[i]) {
|
|
2568
|
+
<div class="arv-template-loading">Loading candidates...</div>
|
|
2569
|
+
}
|
|
2570
|
+
@if (!stepLoadingCandidates[i]) {
|
|
2571
|
+
<select class="arv-select arv-select-sm" (change)="onStepUserChange(i, $event)">
|
|
2572
|
+
<option value="">-- Select approver --</option>
|
|
2573
|
+
@for (u of stepCandidates[i]; track u.userId) {
|
|
2574
|
+
<option [value]="u.userId" [selected]="u.userId === stepSelectedUsers[i]">
|
|
2575
|
+
{{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}
|
|
2576
|
+
</option>
|
|
2577
|
+
}
|
|
2578
|
+
</select>
|
|
2579
|
+
}
|
|
2580
|
+
</div>
|
|
2581
|
+
}
|
|
2582
|
+
<!-- Single fixed-user step: show who is assigned -->
|
|
2583
|
+
@if (!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1) {
|
|
2584
|
+
<div class="arv-step-fixed">
|
|
2585
|
+
{{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}
|
|
2586
|
+
</div>
|
|
2587
|
+
}
|
|
2588
|
+
</div>
|
|
2589
|
+
}
|
|
2590
|
+
@if (selectedTemplate.referenceUserIds.length > 0) {
|
|
2591
|
+
<div class="arv-step-preview arv-step-preview-cc">
|
|
2592
|
+
<span class="arv-step-preview-num">CC</span>
|
|
2593
|
+
<span class="arv-step-preview-name">{{ selectedTemplate.referenceUserIds.length }} reference user(s) from template</span>
|
|
2594
|
+
</div>
|
|
2595
|
+
}
|
|
2596
|
+
</div>
|
|
2597
|
+
}
|
|
2598
|
+
</div>
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
<!-- Ad-hoc steps -->
|
|
2602
|
+
@if (routingMode === 'adhoc') {
|
|
2603
|
+
<div class="arv-steps">
|
|
2604
|
+
@for (step of adHocSteps; track step.stepOrder; let i = $index) {
|
|
2605
|
+
<div class="arv-step">
|
|
2606
|
+
<div class="arv-step-header">
|
|
2607
|
+
<span class="arv-step-num">Step {{ i + 1 }}</span>
|
|
2608
|
+
<input class="arv-input" [value]="step.stepName" (input)="step.stepName = $any($event.target).value" placeholder="Step name" />
|
|
2609
|
+
<button class="arv-btn-icon arv-btn-danger" (click)="removeStep(i)" title="Remove step">
|
|
2610
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
2611
|
+
</button>
|
|
2612
|
+
</div>
|
|
2613
|
+
<div class="arv-approvers">
|
|
2614
|
+
<div class="arv-approver-tags">
|
|
2615
|
+
@for (uid of step.approverUserIds; track uid; let j = $index) {
|
|
2616
|
+
<span class="arv-tag">
|
|
2617
|
+
{{ userLabelMap[uid] || uid }}
|
|
2618
|
+
<button class="arv-tag-remove" (click)="removeApprover(i, j)">x</button>
|
|
2619
|
+
</span>
|
|
2620
|
+
}
|
|
2621
|
+
</div>
|
|
2622
|
+
<div class="arv-user-search">
|
|
2623
|
+
<input class="arv-input arv-input-sm" [value]="userSearchQuery[i] || ''"
|
|
2624
|
+
(input)="onUserSearchInput(i, $any($event.target).value)"
|
|
2625
|
+
placeholder="Search approver..." />
|
|
2626
|
+
@if (userSearchResults[i]?.length) {
|
|
2627
|
+
<div class="arv-search-results">
|
|
2628
|
+
@for (u of userSearchResults[i]; track u.id) {
|
|
2629
|
+
<div class="arv-search-item" (click)="addApprover(i, u.id)">
|
|
2630
|
+
{{ u.fullName || u.userName }}
|
|
2631
|
+
</div>
|
|
2632
|
+
}
|
|
2633
|
+
</div>
|
|
2634
|
+
}
|
|
2635
|
+
</div>
|
|
2636
|
+
</div>
|
|
2637
|
+
</div>
|
|
2638
|
+
}
|
|
2639
|
+
<button class="arv-btn arv-btn-outline" (click)="addStep()">+ Add Step</button>
|
|
2640
|
+
</div>
|
|
2641
|
+
}
|
|
2565
2642
|
</div>
|
|
2566
2643
|
|
|
2567
|
-
<!--
|
|
2568
|
-
<div
|
|
2569
|
-
<
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
<
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
<div class="arv-
|
|
2585
|
-
|
|
2586
|
-
(
|
|
2587
|
-
placeholder="Search approver..." />
|
|
2588
|
-
<div class="arv-search-results" *ngIf="userSearchResults[i]?.length">
|
|
2589
|
-
<div class="arv-search-item"
|
|
2590
|
-
*ngFor="let u of userSearchResults[i]"
|
|
2591
|
-
(click)="addApprover(i, u.id)">
|
|
2644
|
+
<!-- Reference / CC users -->
|
|
2645
|
+
<div class="arv-references">
|
|
2646
|
+
<h4 class="arv-section-title">CC / Reference</h4>
|
|
2647
|
+
<p class="arv-hint">These users will be notified when the approval completes, but won't be asked to approve.</p>
|
|
2648
|
+
<div class="arv-approver-tags">
|
|
2649
|
+
@for (uid of referenceUserIds; track uid; let j = $index) {
|
|
2650
|
+
<span class="arv-tag">
|
|
2651
|
+
{{ userLabelMap[uid] || uid }}
|
|
2652
|
+
<button class="arv-tag-remove" (click)="removeReference(j)">x</button>
|
|
2653
|
+
</span>
|
|
2654
|
+
}
|
|
2655
|
+
</div>
|
|
2656
|
+
<div class="arv-user-search">
|
|
2657
|
+
<input class="arv-input arv-input-sm" [value]="refSearchQuery"
|
|
2658
|
+
(input)="onRefSearchInput($any($event.target).value)"
|
|
2659
|
+
placeholder="Search CC user..." />
|
|
2660
|
+
@if (refSearchResults?.length) {
|
|
2661
|
+
<div class="arv-search-results">
|
|
2662
|
+
@for (u of refSearchResults; track u.id) {
|
|
2663
|
+
<div class="arv-search-item" (click)="addReference(u.id)">
|
|
2592
2664
|
{{ u.fullName || u.userName }}
|
|
2593
2665
|
</div>
|
|
2594
|
-
|
|
2666
|
+
}
|
|
2595
2667
|
</div>
|
|
2596
|
-
|
|
2668
|
+
}
|
|
2597
2669
|
</div>
|
|
2598
|
-
<button class="arv-btn arv-btn-outline" (click)="addStep()">+ Add Step</button>
|
|
2599
2670
|
</div>
|
|
2600
|
-
</div>
|
|
2601
2671
|
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
</
|
|
2611
|
-
</div>
|
|
2612
|
-
<div class="arv-user-search">
|
|
2613
|
-
<input class="arv-input arv-input-sm" [value]="refSearchQuery"
|
|
2614
|
-
(input)="onRefSearchInput($any($event.target).value)"
|
|
2615
|
-
placeholder="Search CC user..." />
|
|
2616
|
-
<div class="arv-search-results" *ngIf="refSearchResults?.length">
|
|
2617
|
-
<div class="arv-search-item"
|
|
2618
|
-
*ngFor="let u of refSearchResults"
|
|
2619
|
-
(click)="addReference(u.id)">
|
|
2620
|
-
{{ u.fullName || u.userName }}
|
|
2621
|
-
</div>
|
|
2622
|
-
</div>
|
|
2672
|
+
<!-- Actions -->
|
|
2673
|
+
<div class="arv-actions">
|
|
2674
|
+
<button class="arv-btn arv-btn-secondary" (click)="onCancel()">Cancel</button>
|
|
2675
|
+
<button class="arv-btn arv-btn-primary" [disabled]="submitting" (click)="submit()">
|
|
2676
|
+
@if (submitting) {
|
|
2677
|
+
<span class="arv-spinner"></span>
|
|
2678
|
+
}
|
|
2679
|
+
{{ submitting ? 'Submitting...' : 'Submit for Approval' }}
|
|
2680
|
+
</button>
|
|
2623
2681
|
</div>
|
|
2624
|
-
</div>
|
|
2625
2682
|
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
<button class="arv-btn arv-btn-primary" [disabled]="submitting" (click)="submit()">
|
|
2630
|
-
<span *ngIf="submitting" class="arv-spinner"></span>
|
|
2631
|
-
{{ submitting ? 'Submitting...' : 'Submit for Approval' }}
|
|
2632
|
-
</button>
|
|
2683
|
+
@if (errorMessage) {
|
|
2684
|
+
<div class="arv-error">{{ errorMessage }}</div>
|
|
2685
|
+
}
|
|
2633
2686
|
</div>
|
|
2634
|
-
|
|
2635
|
-
<div class="arv-error" *ngIf="errorMessage">{{ errorMessage }}</div>
|
|
2636
|
-
</div>
|
|
2687
|
+
}
|
|
2637
2688
|
</div>
|
|
2638
2689
|
|
|
2639
2690
|
<!-- Success state -->
|
|
2640
|
-
|
|
2641
|
-
<
|
|
2642
|
-
<
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2691
|
+
@if (isSubmitted) {
|
|
2692
|
+
<div class="arv-success">
|
|
2693
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#66bb6a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2694
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
|
2695
|
+
<polyline points="22 4 12 14.01 9 11.01"/>
|
|
2696
|
+
</svg>
|
|
2697
|
+
<p>Submitted for approval successfully.</p>
|
|
2698
|
+
</div>
|
|
2699
|
+
}
|
|
2647
2700
|
</div>
|
|
2648
|
-
`, isInline: true, styles: [":host{display:block;--arv-primary: #90caf9;--arv-primary-hover: #64b5f6;--arv-success: #66bb6a;--arv-danger: #ef5350;--arv-text: #e0e0e0;--arv-text-muted: #9e9e9e;--arv-bg: #1e1e2e;--arv-bg2: #27273a;--arv-border: #383850;--arv-radius: 8px}:host(.theme-light){--arv-primary: #1565c0;--arv-primary-hover: #0d47a1;--arv-success: #2e7d32;--arv-danger: #c62828;--arv-text: #212121;--arv-text-muted: #616161;--arv-bg: #ffffff;--arv-bg2: #f5f5f5;--arv-border: #e0e0e0}.arv-container{display:flex;flex-direction:column;height:100%}.arv-content-body{flex:1;overflow:auto}.arv-footer{border-top:1px solid var(--arv-border);background:var(--arv-bg2)}.arv-footer-inner{padding:16px;display:flex;flex-direction:column;gap:14px}.arv-section-title{margin:0 0 8px;font-size:13px;font-weight:700;color:var(--arv-primary);text-transform:uppercase;letter-spacing:.5px}.arv-routing-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.arv-routing-mode{display:flex;gap:12px}.arv-radio{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--arv-text);cursor:pointer}.arv-label{font-size:12px;color:var(--arv-text-muted);display:block;margin-bottom:4px}.arv-select{width:100%;padding:8px 10px;border:1px solid var(--arv-border);border-radius:var(--arv-radius);background:var(--arv-bg);color:var(--arv-text);font-size:13px}.arv-input{padding:7px 10px;border:1px solid var(--arv-border);border-radius:var(--arv-radius);background:var(--arv-bg);color:var(--arv-text);font-size:13px}.arv-input-sm{width:100%;margin-top:4px}.arv-steps{display:flex;flex-direction:column;gap:10px}.arv-step{background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);padding:10px}.arv-step-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.arv-step-num{font-size:12px;font-weight:700;color:var(--arv-primary);min-width:44px}.arv-approver-tags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}.arv-tag{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;background:#90caf91f;border:1px solid rgba(144,202,249,.3);border-radius:12px;font-size:12px;color:var(--arv-primary)}.arv-tag-remove{background:none;border:none;cursor:pointer;color:var(--arv-text-muted);font-size:11px;padding:0 2px;line-height:1}.arv-tag-remove:hover{color:var(--arv-danger)}.arv-user-search{position:relative}.arv-search-results{position:absolute;left:0;right:0;z-index:100;background:var(--arv-bg2);border:1px solid var(--arv-border);border-radius:var(--arv-radius);max-height:150px;overflow-y:auto}.arv-search-item{padding:8px 12px;cursor:pointer;font-size:13px;color:var(--arv-text)}.arv-search-item:hover{background:var(--arv-bg)}.arv-hint{font-size:12px;color:var(--arv-text-muted);margin:0 0 8px}.arv-btn-icon{background:none;border:none;cursor:pointer;padding:2px;border-radius:4px;display:inline-flex;align-items:center;justify-content:center}.arv-btn-danger{color:var(--arv-danger)}.arv-btn-danger:hover{background:#ef53501a}.arv-actions{display:flex;justify-content:flex-end;gap:10px}.arv-btn{padding:9px 18px;border-radius:var(--arv-radius);font-size:13px;font-weight:600;cursor:pointer;border:none;transition:background .15s}.arv-btn-primary{background:var(--arv-primary);color:#fff}.arv-btn-primary:hover:not(:disabled){background:var(--arv-primary-hover)}.arv-btn-primary:disabled{opacity:.6;cursor:not-allowed}.arv-btn-secondary{background:transparent;border:1px solid var(--arv-border);color:var(--arv-text-muted)}.arv-btn-secondary:hover{color:var(--arv-text);border-color:var(--arv-text-muted)}.arv-btn-outline{background:transparent;border:1px dashed var(--arv-border);color:var(--arv-text-muted);font-size:12px;padding:6px 12px}.arv-btn-outline:hover{border-color:var(--arv-primary);color:var(--arv-primary)}.arv-spinner{display:inline-block;width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:arv-spin .6s linear infinite;margin-right:6px}@keyframes arv-spin{to{transform:rotate(360deg)}}.arv-error{padding:8px 12px;background:#ef53501a;border:1px solid rgba(239,83,80,.3);border-radius:var(--arv-radius);font-size:13px;color:var(--arv-danger)}.arv-success{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px;gap:12px;text-align:center}.arv-success p{color:var(--arv-success);font-size:15px;font-weight:600;margin:0}.arv-references{border-top:1px solid var(--arv-border);padding-top:12px}.arv-template-loading{font-size:12px;color:var(--arv-text-muted);margin-top:8px;padding:4px 0}.arv-template-steps{margin-top:8px;display:flex;flex-direction:column;gap:6px}.arv-step-card{background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);overflow:hidden}.arv-step-card-header{display:flex;align-items:center;gap:8px;padding:7px 10px;background:#00000008;border-bottom:1px solid var(--arv-border);flex-wrap:wrap}.arv-step-preview{display:flex;align-items:center;gap:8px;padding:5px 8px;background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:4px;font-size:12px}.arv-step-preview-num{font-weight:700;color:var(--arv-primary);min-width:44px;flex-shrink:0;font-size:12px}.arv-step-preview-name{flex:1;color:var(--arv-text);font-size:12px;font-weight:600}.arv-step-role-badge{font-size:11px;color:var(--arv-text-muted);background:#90caf91a;border:1px solid rgba(144,202,249,.25);border-radius:10px;padding:1px 7px}.arv-step-preview-cc .arv-step-preview-num{color:var(--arv-text-muted)}.arv-locked-template{display:flex;align-items:center;gap:8px;padding:7px 10px;background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);margin-top:6px}.arv-locked-label{font-size:11px;color:var(--arv-text-muted);text-transform:uppercase;letter-spacing:.5px;flex-shrink:0}.arv-locked-name{font-size:13px;font-weight:600;color:var(--arv-text)}.arv-step-picker{padding:8px 10px}.arv-select-sm{font-size:12px;padding:6px 8px}.arv-step-fixed{padding:6px 10px;font-size:12px;color:var(--arv-text-muted)}\n"]
|
|
2701
|
+
`, isInline: true, styles: [":host{display:block;--arv-primary: #90caf9;--arv-primary-hover: #64b5f6;--arv-success: #66bb6a;--arv-danger: #ef5350;--arv-text: #e0e0e0;--arv-text-muted: #9e9e9e;--arv-bg: #1e1e2e;--arv-bg2: #27273a;--arv-border: #383850;--arv-radius: 8px}:host(.theme-light){--arv-primary: #1565c0;--arv-primary-hover: #0d47a1;--arv-success: #2e7d32;--arv-danger: #c62828;--arv-text: #212121;--arv-text-muted: #616161;--arv-bg: #ffffff;--arv-bg2: #f5f5f5;--arv-border: #e0e0e0}.arv-container{display:flex;flex-direction:column;height:100%}.arv-content-body{flex:1;overflow:auto}.arv-footer{border-top:1px solid var(--arv-border);background:var(--arv-bg2)}.arv-footer-inner{padding:16px;display:flex;flex-direction:column;gap:14px}.arv-section-title{margin:0 0 8px;font-size:13px;font-weight:700;color:var(--arv-primary);text-transform:uppercase;letter-spacing:.5px}.arv-routing-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.arv-routing-mode{display:flex;gap:12px}.arv-radio{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--arv-text);cursor:pointer}.arv-label{font-size:12px;color:var(--arv-text-muted);display:block;margin-bottom:4px}.arv-select{width:100%;padding:8px 10px;border:1px solid var(--arv-border);border-radius:var(--arv-radius);background:var(--arv-bg);color:var(--arv-text);font-size:13px}.arv-input{padding:7px 10px;border:1px solid var(--arv-border);border-radius:var(--arv-radius);background:var(--arv-bg);color:var(--arv-text);font-size:13px}.arv-input-sm{width:100%;margin-top:4px}.arv-steps{display:flex;flex-direction:column;gap:10px}.arv-step{background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);padding:10px}.arv-step-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.arv-step-num{font-size:12px;font-weight:700;color:var(--arv-primary);min-width:44px}.arv-approver-tags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}.arv-tag{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;background:#90caf91f;border:1px solid rgba(144,202,249,.3);border-radius:12px;font-size:12px;color:var(--arv-primary)}.arv-tag-remove{background:none;border:none;cursor:pointer;color:var(--arv-text-muted);font-size:11px;padding:0 2px;line-height:1}.arv-tag-remove:hover{color:var(--arv-danger)}.arv-user-search{position:relative}.arv-search-results{position:absolute;left:0;right:0;z-index:100;background:var(--arv-bg2);border:1px solid var(--arv-border);border-radius:var(--arv-radius);max-height:150px;overflow-y:auto}.arv-search-item{padding:8px 12px;cursor:pointer;font-size:13px;color:var(--arv-text)}.arv-search-item:hover{background:var(--arv-bg)}.arv-hint{font-size:12px;color:var(--arv-text-muted);margin:0 0 8px}.arv-btn-icon{background:none;border:none;cursor:pointer;padding:2px;border-radius:4px;display:inline-flex;align-items:center;justify-content:center}.arv-btn-danger{color:var(--arv-danger)}.arv-btn-danger:hover{background:#ef53501a}.arv-actions{display:flex;justify-content:flex-end;gap:10px}.arv-btn{padding:9px 18px;border-radius:var(--arv-radius);font-size:13px;font-weight:600;cursor:pointer;border:none;transition:background .15s}.arv-btn-primary{background:var(--arv-primary);color:#fff}.arv-btn-primary:hover:not(:disabled){background:var(--arv-primary-hover)}.arv-btn-primary:disabled{opacity:.6;cursor:not-allowed}.arv-btn-secondary{background:transparent;border:1px solid var(--arv-border);color:var(--arv-text-muted)}.arv-btn-secondary:hover{color:var(--arv-text);border-color:var(--arv-text-muted)}.arv-btn-outline{background:transparent;border:1px dashed var(--arv-border);color:var(--arv-text-muted);font-size:12px;padding:6px 12px}.arv-btn-outline:hover{border-color:var(--arv-primary);color:var(--arv-primary)}.arv-spinner{display:inline-block;width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:arv-spin .6s linear infinite;margin-right:6px}@keyframes arv-spin{to{transform:rotate(360deg)}}.arv-error{padding:8px 12px;background:#ef53501a;border:1px solid rgba(239,83,80,.3);border-radius:var(--arv-radius);font-size:13px;color:var(--arv-danger)}.arv-success{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px;gap:12px;text-align:center}.arv-success p{color:var(--arv-success);font-size:15px;font-weight:600;margin:0}.arv-references{border-top:1px solid var(--arv-border);padding-top:12px}.arv-template-loading{font-size:12px;color:var(--arv-text-muted);margin-top:8px;padding:4px 0}.arv-template-steps{margin-top:8px;display:flex;flex-direction:column;gap:6px}.arv-step-card{background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);overflow:hidden}.arv-step-card-header{display:flex;align-items:center;gap:8px;padding:7px 10px;background:#00000008;border-bottom:1px solid var(--arv-border);flex-wrap:wrap}.arv-step-preview{display:flex;align-items:center;gap:8px;padding:5px 8px;background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:4px;font-size:12px}.arv-step-preview-num{font-weight:700;color:var(--arv-primary);min-width:44px;flex-shrink:0;font-size:12px}.arv-step-preview-name{flex:1;color:var(--arv-text);font-size:12px;font-weight:600}.arv-step-role-badge{font-size:11px;color:var(--arv-text-muted);background:#90caf91a;border:1px solid rgba(144,202,249,.25);border-radius:10px;padding:1px 7px}.arv-step-preview-cc .arv-step-preview-num{color:var(--arv-text-muted)}.arv-locked-template{display:flex;align-items:center;gap:8px;padding:7px 10px;background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);margin-top:6px}.arv-locked-label{font-size:11px;color:var(--arv-text-muted);text-transform:uppercase;letter-spacing:.5px;flex-shrink:0}.arv-locked-name{font-size:13px;font-weight:600;color:var(--arv-text)}.arv-step-picker{padding:8px 10px}.arv-select-sm{font-size:12px;padding:6px 8px}.arv-step-fixed{padding:6px 10px;font-size:12px;color:var(--arv-text-muted)}\n"] });
|
|
2649
2702
|
}
|
|
2650
2703
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: MaArvContainerComponent, decorators: [{
|
|
2651
2704
|
type: Component,
|
|
2652
|
-
args: [{ selector: 'ma-arv-container', standalone: true,
|
|
2653
|
-
|
|
2705
|
+
args: [{ selector: 'ma-arv-container', standalone: true, template: `
|
|
2706
|
+
<div class="arv-container">
|
|
2654
2707
|
<!-- Content Area -->
|
|
2655
2708
|
<div class="arv-content-body" #contentBody>
|
|
2656
2709
|
<ng-content></ng-content>
|
|
2657
2710
|
</div>
|
|
2658
2711
|
|
|
2659
2712
|
<!-- Approval Footer -->
|
|
2660
|
-
<div class="arv-footer"
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
<div class="arv-routing
|
|
2666
|
-
<
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
<
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
<div *ngIf="templateId && routingMode === 'template'" class="arv-template-select">
|
|
2680
|
-
<div *ngIf="loadingTemplate" class="arv-template-loading">Loading template...</div>
|
|
2681
|
-
<div *ngIf="selectedTemplate && !loadingTemplate" class="arv-locked-template">
|
|
2682
|
-
<span class="arv-locked-label">Template</span>
|
|
2683
|
-
<span class="arv-locked-name">{{ selectedTemplate.name }}</span>
|
|
2713
|
+
<div class="arv-footer">
|
|
2714
|
+
@if (!isSubmitted) {
|
|
2715
|
+
<div class="arv-footer-inner">
|
|
2716
|
+
|
|
2717
|
+
<!-- Routing mode -->
|
|
2718
|
+
<div class="arv-routing">
|
|
2719
|
+
<div class="arv-routing-header">
|
|
2720
|
+
<h4 class="arv-section-title">Approval Routing</h4>
|
|
2721
|
+
<!-- Show routing toggle only when templateId is NOT locked to a single template -->
|
|
2722
|
+
@if (!templateId || (templateIds && templateIds.length > 0)) {
|
|
2723
|
+
<div class="arv-routing-mode">
|
|
2724
|
+
<label class="arv-radio">
|
|
2725
|
+
<input type="radio" name="routingMode" value="template" [checked]="routingMode === 'template'" (change)="routingMode = 'template'"> Use Template
|
|
2726
|
+
</label>
|
|
2727
|
+
<label class="arv-radio">
|
|
2728
|
+
<input type="radio" name="routingMode" value="adhoc" [checked]="routingMode === 'adhoc'" (change)="routingMode = 'adhoc'"> Custom Steps
|
|
2729
|
+
</label>
|
|
2730
|
+
</div>
|
|
2731
|
+
}
|
|
2684
2732
|
</div>
|
|
2685
|
-
</div>
|
|
2686
2733
|
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
<div class="arv-step-card" *ngFor="let s of selectedTemplate.steps; let i = index">
|
|
2700
|
-
<div class="arv-step-card-header">
|
|
2701
|
-
<span class="arv-step-preview-num">Step {{ s.stepOrder }}</span>
|
|
2702
|
-
<span class="arv-step-preview-name">{{ s.stepName }}</span>
|
|
2703
|
-
<span *ngIf="s.roles && s.roles.length > 0" class="arv-step-role-badge">
|
|
2704
|
-
{{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}
|
|
2705
|
-
</span>
|
|
2706
|
-
</div>
|
|
2707
|
-
<!-- Selectable step (role-based or multi-assignee): show approver picker -->
|
|
2708
|
-
<div *ngIf="stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]" class="arv-step-picker">
|
|
2709
|
-
<div *ngIf="stepLoadingCandidates[i]" class="arv-template-loading">Loading candidates...</div>
|
|
2710
|
-
<select *ngIf="!stepLoadingCandidates[i]" class="arv-select arv-select-sm"
|
|
2711
|
-
(change)="onStepUserChange(i, $event)">
|
|
2712
|
-
<option value="">-- Select approver --</option>
|
|
2713
|
-
<option *ngFor="let u of stepCandidates[i]" [value]="u.userId"
|
|
2714
|
-
[selected]="u.userId === stepSelectedUsers[i]">
|
|
2715
|
-
{{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}
|
|
2716
|
-
</option>
|
|
2717
|
-
</select>
|
|
2718
|
-
</div>
|
|
2719
|
-
<!-- Single fixed-user step: show who is assigned -->
|
|
2720
|
-
<div *ngIf="!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1" class="arv-step-fixed">
|
|
2721
|
-
{{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}
|
|
2722
|
-
</div>
|
|
2734
|
+
<!-- Locked template: only when templateId set and no multi-choice -->
|
|
2735
|
+
@if (templateId && (!templateIds || templateIds.length <= 1) && routingMode === 'template') {
|
|
2736
|
+
<div class="arv-template-select">
|
|
2737
|
+
@if (loadingTemplate) {
|
|
2738
|
+
<div class="arv-template-loading">Loading template...</div>
|
|
2739
|
+
}
|
|
2740
|
+
@if (selectedTemplate && !loadingTemplate) {
|
|
2741
|
+
<div class="arv-locked-template">
|
|
2742
|
+
<span class="arv-locked-label">Template</span>
|
|
2743
|
+
<span class="arv-locked-name">{{ selectedTemplate.name }}</span>
|
|
2744
|
+
</div>
|
|
2745
|
+
}
|
|
2723
2746
|
</div>
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
<!-- Template selector: shown when no templateId, OR when templateIds has multiple choices -->
|
|
2750
|
+
@if ((!templateId || (templateIds && templateIds.length > 1)) && routingMode === 'template') {
|
|
2751
|
+
<div class="arv-template-select">
|
|
2752
|
+
<label class="arv-label">Select Template</label>
|
|
2753
|
+
<select class="arv-select" (change)="onTemplateChange($event)">
|
|
2754
|
+
<option value="">-- Select a template --</option>
|
|
2755
|
+
@for (t of templates; track t.id) {
|
|
2756
|
+
<option [value]="t.id" [selected]="t.id === selectedTemplateId">{{ t.name }}</option>
|
|
2757
|
+
}
|
|
2758
|
+
</select>
|
|
2727
2759
|
</div>
|
|
2728
|
-
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
<!-- Step pickers (shared for both locked and free template) -->
|
|
2763
|
+
@if (routingMode === 'template') {
|
|
2764
|
+
<div class="arv-template-select">
|
|
2765
|
+
@if (!loadingTemplate && selectedTemplate) {
|
|
2766
|
+
<div class="arv-template-steps">
|
|
2767
|
+
@for (s of selectedTemplate.steps; track s.stepOrder; let i = $index) {
|
|
2768
|
+
<div class="arv-step-card">
|
|
2769
|
+
<div class="arv-step-card-header">
|
|
2770
|
+
<span class="arv-step-preview-num">Step {{ s.stepOrder }}</span>
|
|
2771
|
+
<span class="arv-step-preview-name">{{ s.stepName }}</span>
|
|
2772
|
+
@if (s.roles && s.roles.length > 0) {
|
|
2773
|
+
<span class="arv-step-role-badge">
|
|
2774
|
+
{{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}
|
|
2775
|
+
</span>
|
|
2776
|
+
}
|
|
2777
|
+
</div>
|
|
2778
|
+
<!-- Selectable step: show approver picker -->
|
|
2779
|
+
@if (stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]) {
|
|
2780
|
+
<div class="arv-step-picker">
|
|
2781
|
+
@if (stepLoadingCandidates[i]) {
|
|
2782
|
+
<div class="arv-template-loading">Loading candidates...</div>
|
|
2783
|
+
}
|
|
2784
|
+
@if (!stepLoadingCandidates[i]) {
|
|
2785
|
+
<select class="arv-select arv-select-sm" (change)="onStepUserChange(i, $event)">
|
|
2786
|
+
<option value="">-- Select approver --</option>
|
|
2787
|
+
@for (u of stepCandidates[i]; track u.userId) {
|
|
2788
|
+
<option [value]="u.userId" [selected]="u.userId === stepSelectedUsers[i]">
|
|
2789
|
+
{{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}
|
|
2790
|
+
</option>
|
|
2791
|
+
}
|
|
2792
|
+
</select>
|
|
2793
|
+
}
|
|
2794
|
+
</div>
|
|
2795
|
+
}
|
|
2796
|
+
<!-- Single fixed-user step: show who is assigned -->
|
|
2797
|
+
@if (!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1) {
|
|
2798
|
+
<div class="arv-step-fixed">
|
|
2799
|
+
{{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}
|
|
2800
|
+
</div>
|
|
2801
|
+
}
|
|
2802
|
+
</div>
|
|
2803
|
+
}
|
|
2804
|
+
@if (selectedTemplate.referenceUserIds.length > 0) {
|
|
2805
|
+
<div class="arv-step-preview arv-step-preview-cc">
|
|
2806
|
+
<span class="arv-step-preview-num">CC</span>
|
|
2807
|
+
<span class="arv-step-preview-name">{{ selectedTemplate.referenceUserIds.length }} reference user(s) from template</span>
|
|
2808
|
+
</div>
|
|
2809
|
+
}
|
|
2810
|
+
</div>
|
|
2811
|
+
}
|
|
2812
|
+
</div>
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
<!-- Ad-hoc steps -->
|
|
2816
|
+
@if (routingMode === 'adhoc') {
|
|
2817
|
+
<div class="arv-steps">
|
|
2818
|
+
@for (step of adHocSteps; track step.stepOrder; let i = $index) {
|
|
2819
|
+
<div class="arv-step">
|
|
2820
|
+
<div class="arv-step-header">
|
|
2821
|
+
<span class="arv-step-num">Step {{ i + 1 }}</span>
|
|
2822
|
+
<input class="arv-input" [value]="step.stepName" (input)="step.stepName = $any($event.target).value" placeholder="Step name" />
|
|
2823
|
+
<button class="arv-btn-icon arv-btn-danger" (click)="removeStep(i)" title="Remove step">
|
|
2824
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
2825
|
+
</button>
|
|
2826
|
+
</div>
|
|
2827
|
+
<div class="arv-approvers">
|
|
2828
|
+
<div class="arv-approver-tags">
|
|
2829
|
+
@for (uid of step.approverUserIds; track uid; let j = $index) {
|
|
2830
|
+
<span class="arv-tag">
|
|
2831
|
+
{{ userLabelMap[uid] || uid }}
|
|
2832
|
+
<button class="arv-tag-remove" (click)="removeApprover(i, j)">x</button>
|
|
2833
|
+
</span>
|
|
2834
|
+
}
|
|
2835
|
+
</div>
|
|
2836
|
+
<div class="arv-user-search">
|
|
2837
|
+
<input class="arv-input arv-input-sm" [value]="userSearchQuery[i] || ''"
|
|
2838
|
+
(input)="onUserSearchInput(i, $any($event.target).value)"
|
|
2839
|
+
placeholder="Search approver..." />
|
|
2840
|
+
@if (userSearchResults[i]?.length) {
|
|
2841
|
+
<div class="arv-search-results">
|
|
2842
|
+
@for (u of userSearchResults[i]; track u.id) {
|
|
2843
|
+
<div class="arv-search-item" (click)="addApprover(i, u.id)">
|
|
2844
|
+
{{ u.fullName || u.userName }}
|
|
2845
|
+
</div>
|
|
2846
|
+
}
|
|
2847
|
+
</div>
|
|
2848
|
+
}
|
|
2849
|
+
</div>
|
|
2850
|
+
</div>
|
|
2851
|
+
</div>
|
|
2852
|
+
}
|
|
2853
|
+
<button class="arv-btn arv-btn-outline" (click)="addStep()">+ Add Step</button>
|
|
2854
|
+
</div>
|
|
2855
|
+
}
|
|
2729
2856
|
</div>
|
|
2730
2857
|
|
|
2731
|
-
<!--
|
|
2732
|
-
<div
|
|
2733
|
-
<
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
<
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
<div class="arv-
|
|
2749
|
-
|
|
2750
|
-
(
|
|
2751
|
-
placeholder="Search approver..." />
|
|
2752
|
-
<div class="arv-search-results" *ngIf="userSearchResults[i]?.length">
|
|
2753
|
-
<div class="arv-search-item"
|
|
2754
|
-
*ngFor="let u of userSearchResults[i]"
|
|
2755
|
-
(click)="addApprover(i, u.id)">
|
|
2858
|
+
<!-- Reference / CC users -->
|
|
2859
|
+
<div class="arv-references">
|
|
2860
|
+
<h4 class="arv-section-title">CC / Reference</h4>
|
|
2861
|
+
<p class="arv-hint">These users will be notified when the approval completes, but won't be asked to approve.</p>
|
|
2862
|
+
<div class="arv-approver-tags">
|
|
2863
|
+
@for (uid of referenceUserIds; track uid; let j = $index) {
|
|
2864
|
+
<span class="arv-tag">
|
|
2865
|
+
{{ userLabelMap[uid] || uid }}
|
|
2866
|
+
<button class="arv-tag-remove" (click)="removeReference(j)">x</button>
|
|
2867
|
+
</span>
|
|
2868
|
+
}
|
|
2869
|
+
</div>
|
|
2870
|
+
<div class="arv-user-search">
|
|
2871
|
+
<input class="arv-input arv-input-sm" [value]="refSearchQuery"
|
|
2872
|
+
(input)="onRefSearchInput($any($event.target).value)"
|
|
2873
|
+
placeholder="Search CC user..." />
|
|
2874
|
+
@if (refSearchResults?.length) {
|
|
2875
|
+
<div class="arv-search-results">
|
|
2876
|
+
@for (u of refSearchResults; track u.id) {
|
|
2877
|
+
<div class="arv-search-item" (click)="addReference(u.id)">
|
|
2756
2878
|
{{ u.fullName || u.userName }}
|
|
2757
2879
|
</div>
|
|
2758
|
-
|
|
2880
|
+
}
|
|
2759
2881
|
</div>
|
|
2760
|
-
|
|
2882
|
+
}
|
|
2761
2883
|
</div>
|
|
2762
|
-
<button class="arv-btn arv-btn-outline" (click)="addStep()">+ Add Step</button>
|
|
2763
2884
|
</div>
|
|
2764
|
-
</div>
|
|
2765
2885
|
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
</
|
|
2775
|
-
</div>
|
|
2776
|
-
<div class="arv-user-search">
|
|
2777
|
-
<input class="arv-input arv-input-sm" [value]="refSearchQuery"
|
|
2778
|
-
(input)="onRefSearchInput($any($event.target).value)"
|
|
2779
|
-
placeholder="Search CC user..." />
|
|
2780
|
-
<div class="arv-search-results" *ngIf="refSearchResults?.length">
|
|
2781
|
-
<div class="arv-search-item"
|
|
2782
|
-
*ngFor="let u of refSearchResults"
|
|
2783
|
-
(click)="addReference(u.id)">
|
|
2784
|
-
{{ u.fullName || u.userName }}
|
|
2785
|
-
</div>
|
|
2786
|
-
</div>
|
|
2886
|
+
<!-- Actions -->
|
|
2887
|
+
<div class="arv-actions">
|
|
2888
|
+
<button class="arv-btn arv-btn-secondary" (click)="onCancel()">Cancel</button>
|
|
2889
|
+
<button class="arv-btn arv-btn-primary" [disabled]="submitting" (click)="submit()">
|
|
2890
|
+
@if (submitting) {
|
|
2891
|
+
<span class="arv-spinner"></span>
|
|
2892
|
+
}
|
|
2893
|
+
{{ submitting ? 'Submitting...' : 'Submit for Approval' }}
|
|
2894
|
+
</button>
|
|
2787
2895
|
</div>
|
|
2788
|
-
</div>
|
|
2789
2896
|
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
<button class="arv-btn arv-btn-primary" [disabled]="submitting" (click)="submit()">
|
|
2794
|
-
<span *ngIf="submitting" class="arv-spinner"></span>
|
|
2795
|
-
{{ submitting ? 'Submitting...' : 'Submit for Approval' }}
|
|
2796
|
-
</button>
|
|
2897
|
+
@if (errorMessage) {
|
|
2898
|
+
<div class="arv-error">{{ errorMessage }}</div>
|
|
2899
|
+
}
|
|
2797
2900
|
</div>
|
|
2798
|
-
|
|
2799
|
-
<div class="arv-error" *ngIf="errorMessage">{{ errorMessage }}</div>
|
|
2800
|
-
</div>
|
|
2901
|
+
}
|
|
2801
2902
|
</div>
|
|
2802
2903
|
|
|
2803
2904
|
<!-- Success state -->
|
|
2804
|
-
|
|
2805
|
-
<
|
|
2806
|
-
<
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2905
|
+
@if (isSubmitted) {
|
|
2906
|
+
<div class="arv-success">
|
|
2907
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#66bb6a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2908
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
|
2909
|
+
<polyline points="22 4 12 14.01 9 11.01"/>
|
|
2910
|
+
</svg>
|
|
2911
|
+
<p>Submitted for approval successfully.</p>
|
|
2912
|
+
</div>
|
|
2913
|
+
}
|
|
2811
2914
|
</div>
|
|
2812
2915
|
`, styles: [":host{display:block;--arv-primary: #90caf9;--arv-primary-hover: #64b5f6;--arv-success: #66bb6a;--arv-danger: #ef5350;--arv-text: #e0e0e0;--arv-text-muted: #9e9e9e;--arv-bg: #1e1e2e;--arv-bg2: #27273a;--arv-border: #383850;--arv-radius: 8px}:host(.theme-light){--arv-primary: #1565c0;--arv-primary-hover: #0d47a1;--arv-success: #2e7d32;--arv-danger: #c62828;--arv-text: #212121;--arv-text-muted: #616161;--arv-bg: #ffffff;--arv-bg2: #f5f5f5;--arv-border: #e0e0e0}.arv-container{display:flex;flex-direction:column;height:100%}.arv-content-body{flex:1;overflow:auto}.arv-footer{border-top:1px solid var(--arv-border);background:var(--arv-bg2)}.arv-footer-inner{padding:16px;display:flex;flex-direction:column;gap:14px}.arv-section-title{margin:0 0 8px;font-size:13px;font-weight:700;color:var(--arv-primary);text-transform:uppercase;letter-spacing:.5px}.arv-routing-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.arv-routing-mode{display:flex;gap:12px}.arv-radio{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--arv-text);cursor:pointer}.arv-label{font-size:12px;color:var(--arv-text-muted);display:block;margin-bottom:4px}.arv-select{width:100%;padding:8px 10px;border:1px solid var(--arv-border);border-radius:var(--arv-radius);background:var(--arv-bg);color:var(--arv-text);font-size:13px}.arv-input{padding:7px 10px;border:1px solid var(--arv-border);border-radius:var(--arv-radius);background:var(--arv-bg);color:var(--arv-text);font-size:13px}.arv-input-sm{width:100%;margin-top:4px}.arv-steps{display:flex;flex-direction:column;gap:10px}.arv-step{background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);padding:10px}.arv-step-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.arv-step-num{font-size:12px;font-weight:700;color:var(--arv-primary);min-width:44px}.arv-approver-tags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}.arv-tag{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;background:#90caf91f;border:1px solid rgba(144,202,249,.3);border-radius:12px;font-size:12px;color:var(--arv-primary)}.arv-tag-remove{background:none;border:none;cursor:pointer;color:var(--arv-text-muted);font-size:11px;padding:0 2px;line-height:1}.arv-tag-remove:hover{color:var(--arv-danger)}.arv-user-search{position:relative}.arv-search-results{position:absolute;left:0;right:0;z-index:100;background:var(--arv-bg2);border:1px solid var(--arv-border);border-radius:var(--arv-radius);max-height:150px;overflow-y:auto}.arv-search-item{padding:8px 12px;cursor:pointer;font-size:13px;color:var(--arv-text)}.arv-search-item:hover{background:var(--arv-bg)}.arv-hint{font-size:12px;color:var(--arv-text-muted);margin:0 0 8px}.arv-btn-icon{background:none;border:none;cursor:pointer;padding:2px;border-radius:4px;display:inline-flex;align-items:center;justify-content:center}.arv-btn-danger{color:var(--arv-danger)}.arv-btn-danger:hover{background:#ef53501a}.arv-actions{display:flex;justify-content:flex-end;gap:10px}.arv-btn{padding:9px 18px;border-radius:var(--arv-radius);font-size:13px;font-weight:600;cursor:pointer;border:none;transition:background .15s}.arv-btn-primary{background:var(--arv-primary);color:#fff}.arv-btn-primary:hover:not(:disabled){background:var(--arv-primary-hover)}.arv-btn-primary:disabled{opacity:.6;cursor:not-allowed}.arv-btn-secondary{background:transparent;border:1px solid var(--arv-border);color:var(--arv-text-muted)}.arv-btn-secondary:hover{color:var(--arv-text);border-color:var(--arv-text-muted)}.arv-btn-outline{background:transparent;border:1px dashed var(--arv-border);color:var(--arv-text-muted);font-size:12px;padding:6px 12px}.arv-btn-outline:hover{border-color:var(--arv-primary);color:var(--arv-primary)}.arv-spinner{display:inline-block;width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:arv-spin .6s linear infinite;margin-right:6px}@keyframes arv-spin{to{transform:rotate(360deg)}}.arv-error{padding:8px 12px;background:#ef53501a;border:1px solid rgba(239,83,80,.3);border-radius:var(--arv-radius);font-size:13px;color:var(--arv-danger)}.arv-success{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px;gap:12px;text-align:center}.arv-success p{color:var(--arv-success);font-size:15px;font-weight:600;margin:0}.arv-references{border-top:1px solid var(--arv-border);padding-top:12px}.arv-template-loading{font-size:12px;color:var(--arv-text-muted);margin-top:8px;padding:4px 0}.arv-template-steps{margin-top:8px;display:flex;flex-direction:column;gap:6px}.arv-step-card{background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);overflow:hidden}.arv-step-card-header{display:flex;align-items:center;gap:8px;padding:7px 10px;background:#00000008;border-bottom:1px solid var(--arv-border);flex-wrap:wrap}.arv-step-preview{display:flex;align-items:center;gap:8px;padding:5px 8px;background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:4px;font-size:12px}.arv-step-preview-num{font-weight:700;color:var(--arv-primary);min-width:44px;flex-shrink:0;font-size:12px}.arv-step-preview-name{flex:1;color:var(--arv-text);font-size:12px;font-weight:600}.arv-step-role-badge{font-size:11px;color:var(--arv-text-muted);background:#90caf91a;border:1px solid rgba(144,202,249,.25);border-radius:10px;padding:1px 7px}.arv-step-preview-cc .arv-step-preview-num{color:var(--arv-text-muted)}.arv-locked-template{display:flex;align-items:center;gap:8px;padding:7px 10px;background:var(--arv-bg);border:1px solid var(--arv-border);border-radius:var(--arv-radius);margin-top:6px}.arv-locked-label{font-size:11px;color:var(--arv-text-muted);text-transform:uppercase;letter-spacing:.5px;flex-shrink:0}.arv-locked-name{font-size:13px;font-weight:600;color:var(--arv-text)}.arv-step-picker{padding:8px 10px}.arv-select-sm{font-size:12px;padding:6px 8px}.arv-step-fixed{padding:6px 10px;font-size:12px;color:var(--arv-text-muted)}\n"] }]
|
|
2813
2916
|
}], propDecorators: { title: [{
|
|
@@ -2818,6 +2921,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImpor
|
|
|
2818
2921
|
type: Input
|
|
2819
2922
|
}], templateId: [{
|
|
2820
2923
|
type: Input
|
|
2924
|
+
}], templateIds: [{
|
|
2925
|
+
type: Input
|
|
2821
2926
|
}], callbackUrl: [{
|
|
2822
2927
|
type: Input
|
|
2823
2928
|
}], deadlineHours: [{
|