@tuki-io/tuki-widgets 0.0.177 → 0.0.178

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.
Files changed (54) hide show
  1. package/contact-center/cc-script-editor/cc-script-editor.component.d.ts +53 -0
  2. package/contact-center/cc-script-editor/cc-script-editor.module.d.ts +20 -0
  3. package/contact-center/cc-script-editor/components/dialogs/add-node-dialog/add-node-dialog.component.d.ts +35 -0
  4. package/contact-center/cc-script-editor/components/dialogs/link-node-dialog/link-node-dialog.component.d.ts +38 -0
  5. package/contact-center/cc-script-editor/components/floating-toolbar/floating-toolbar.component.d.ts +34 -0
  6. package/contact-center/cc-script-editor/components/floating-toolbar/floating-toolbar.module.d.ts +9 -0
  7. package/contact-center/cc-script-editor/components/node-action-toolbar/node-action-toolbar.component.d.ts +27 -0
  8. package/contact-center/cc-script-editor/components/node-details-sidebar/node-details-sidebar.component.d.ts +27 -0
  9. package/contact-center/cc-script-editor/components/node-search-panel/node-search-panel.component.d.ts +14 -0
  10. package/contact-center/cc-script-editor/components/wxcc-actions-bar/wxcc-actions-bar.component.d.ts +11 -0
  11. package/contact-center/cc-script-editor/components/wxcc-file-selection-bar/wxcc-file-selection-bar.component.d.ts +24 -0
  12. package/contact-center/cc-script-editor/components/wxcc-flowchart/wxcc-flowchart.component.d.ts +66 -0
  13. package/contact-center/cc-script-editor/constants/cytoscape.config.d.ts +2 -0
  14. package/contact-center/cc-script-editor/constants/wxcc-api.constants.d.ts +15 -0
  15. package/contact-center/cc-script-editor/services/wxcc-activity-creation.service.d.ts +21 -0
  16. package/contact-center/cc-script-editor/services/wxcc-activity-manage.service.d.ts +8 -0
  17. package/contact-center/cc-script-editor/services/wxcc-flow-api.service.d.ts +43 -0
  18. package/contact-center/cc-script-editor/services/wxcc2graph.service.d.ts +42 -0
  19. package/contact-center/cc-script-editor/types/extended-activity.d.ts +47 -0
  20. package/contact-center/cc-script-editor/types/wxcc-activity.d.ts +96 -0
  21. package/contact-center/cc-script-editor/types/wxcc.d.ts +161 -0
  22. package/contact-center/cc-script-editor/utils/node-html-template.d.ts +3 -0
  23. package/contact-center/cc-script-editor/utils/node-mappings.d.ts +54 -0
  24. package/contact-center/public-api.d.ts +2 -0
  25. package/esm2020/contact-center/cc-script-editor/cc-script-editor.component.mjs +193 -0
  26. package/esm2020/contact-center/cc-script-editor/cc-script-editor.module.mjs +83 -0
  27. package/esm2020/contact-center/cc-script-editor/components/dialogs/add-node-dialog/add-node-dialog.component.mjs +60 -0
  28. package/esm2020/contact-center/cc-script-editor/components/dialogs/link-node-dialog/link-node-dialog.component.mjs +83 -0
  29. package/esm2020/contact-center/cc-script-editor/components/floating-toolbar/floating-toolbar.component.mjs +104 -0
  30. package/esm2020/contact-center/cc-script-editor/components/floating-toolbar/floating-toolbar.module.mjs +28 -0
  31. package/esm2020/contact-center/cc-script-editor/components/node-action-toolbar/node-action-toolbar.component.mjs +65 -0
  32. package/esm2020/contact-center/cc-script-editor/components/node-details-sidebar/node-details-sidebar.component.mjs +97 -0
  33. package/esm2020/contact-center/cc-script-editor/components/node-search-panel/node-search-panel.component.mjs +43 -0
  34. package/esm2020/contact-center/cc-script-editor/components/wxcc-actions-bar/wxcc-actions-bar.component.mjs +27 -0
  35. package/esm2020/contact-center/cc-script-editor/components/wxcc-file-selection-bar/wxcc-file-selection-bar.component.mjs +61 -0
  36. package/esm2020/contact-center/cc-script-editor/components/wxcc-flowchart/wxcc-flowchart.component.mjs +434 -0
  37. package/esm2020/contact-center/cc-script-editor/constants/cytoscape.config.mjs +72 -0
  38. package/esm2020/contact-center/cc-script-editor/constants/wxcc-api.constants.mjs +14 -0
  39. package/esm2020/contact-center/cc-script-editor/mock/data/QWC_ir.json +912 -0
  40. package/esm2020/contact-center/cc-script-editor/services/wxcc-activity-creation.service.mjs +82 -0
  41. package/esm2020/contact-center/cc-script-editor/services/wxcc-activity-manage.service.mjs +162 -0
  42. package/esm2020/contact-center/cc-script-editor/services/wxcc-flow-api.service.mjs +79 -0
  43. package/esm2020/contact-center/cc-script-editor/services/wxcc2graph.service.mjs +144 -0
  44. package/esm2020/contact-center/cc-script-editor/types/extended-activity.mjs +4 -0
  45. package/esm2020/contact-center/cc-script-editor/types/wxcc-activity.mjs +2 -0
  46. package/esm2020/contact-center/cc-script-editor/types/wxcc.mjs +6 -0
  47. package/esm2020/contact-center/cc-script-editor/utils/node-html-template.mjs +76 -0
  48. package/esm2020/contact-center/cc-script-editor/utils/node-mappings.mjs +109 -0
  49. package/esm2020/contact-center/public-api.mjs +3 -1
  50. package/fesm2015/tuki-io-tuki-widgets-contact-center.mjs +2948 -3
  51. package/fesm2015/tuki-io-tuki-widgets-contact-center.mjs.map +1 -1
  52. package/fesm2020/tuki-io-tuki-widgets-contact-center.mjs +2974 -3
  53. package/fesm2020/tuki-io-tuki-widgets-contact-center.mjs.map +1 -1
  54. package/package.json +1 -1
@@ -1,21 +1,40 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, Component, Input, NgModule } from '@angular/core';
2
+ import { Injectable, inject, Component, Input, NgModule, ChangeDetectionStrategy, Inject, EventEmitter, Output, ViewChild } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i1 from '@angular/common/http';
6
6
  import { HttpHeaders, HttpClientModule } from '@angular/common/http';
7
- import { map, catchError, of, finalize } from 'rxjs';
7
+ import { map, catchError, of, finalize, Subject, forkJoin, throwError } from 'rxjs';
8
8
  import * as i2 from 'ng-apexcharts';
9
9
  import { NgApexchartsModule } from 'ng-apexcharts';
10
10
  import * as i3 from '@angular/material/select';
11
11
  import { MatSelectModule } from '@angular/material/select';
12
12
  import * as i4 from '@angular/material/core';
13
13
  import { MatOptionModule } from '@angular/material/core';
14
+ import * as i1$4 from '@angular/material/button';
14
15
  import { MatButtonModule } from '@angular/material/button';
15
16
  import { MatCheckboxModule } from '@angular/material/checkbox';
16
17
  import { MatPaginatorModule } from '@angular/material/paginator';
18
+ import * as i4$1 from '@angular/material/progress-spinner';
17
19
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
18
20
  import { MatTableModule } from '@angular/material/table';
21
+ import cytoscape from 'cytoscape';
22
+ import dagre from 'cytoscape-dagre';
23
+ import nodeHtmlLabel from 'cytoscape-node-html-label';
24
+ import * as i1$2 from '@angular/material/dialog';
25
+ import { MAT_DIALOG_DATA } from '@angular/material/dialog';
26
+ import * as uuid from 'uuid';
27
+ import * as i3$1 from '@angular/material/tooltip';
28
+ import { MatTooltipModule } from '@angular/material/tooltip';
29
+ import * as i1$3 from '@angular/platform-browser';
30
+ import * as i2$1 from '@angular/forms';
31
+ import { FormsModule } from '@angular/forms';
32
+ import * as i2$2 from '@angular/material/form-field';
33
+ import { MatFormFieldModule } from '@angular/material/form-field';
34
+ import { mergeMap, takeUntil, finalize as finalize$1, tap } from 'rxjs/operators';
35
+ import { MatProgressBarModule } from '@angular/material/progress-bar';
36
+ import { MatIconModule } from '@angular/material/icon';
37
+ import { MatInputModule } from '@angular/material/input';
19
38
 
20
39
  class APIService {
21
40
  constructor(httpClient) {
@@ -430,9 +449,2961 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
430
449
  }]
431
450
  }] });
432
451
 
452
+ const StyleConfig = [
453
+ {
454
+ selector: 'node',
455
+ style: {
456
+ 'background-color': 'transparent',
457
+ 'background-opacity': 0,
458
+ 'width': 220,
459
+ 'height': 100,
460
+ 'shape': 'roundrectangle',
461
+ 'border-width': 0
462
+ }
463
+ },
464
+ {
465
+ selector: 'node:selected',
466
+ style: {
467
+ 'background-color': 'transparent',
468
+ 'background-opacity': 0
469
+ }
470
+ },
471
+ {
472
+ selector: 'edge',
473
+ style: {
474
+ 'width': 1,
475
+ 'line-color': '#d4d4d4',
476
+ // 'line-color': '#B0BEC5',
477
+ 'target-arrow-color': '#d4d4d4',
478
+ 'target-arrow-shape': 'triangle',
479
+ 'curve-style': 'bezier',
480
+ 'control-point-step-size': 40,
481
+ 'label': 'data(label)',
482
+ 'font-size': '9px',
483
+ 'color': '#546E7A',
484
+ 'text-background-color': '#fff',
485
+ 'text-background-opacity': 1,
486
+ 'text-background-padding': '4px',
487
+ 'text-border-width': 1,
488
+ 'text-border-color': '#E0E0E0',
489
+ 'text-border-opacity': 0.8,
490
+ 'text-margin-y': -10,
491
+ 'z-index': 10
492
+ }
493
+ },
494
+ {
495
+ selector: 'edge[label="default"]',
496
+ style: {
497
+ 'line-color': '#90A4AE',
498
+ 'target-arrow-color': '#90A4AE'
499
+ }
500
+ },
501
+ {
502
+ selector: 'edge[label="queued"]',
503
+ style: {
504
+ 'line-color': '#66BB6A',
505
+ 'target-arrow-color': '#66BB6A'
506
+ }
507
+ },
508
+ {
509
+ selector: 'edge[label="failure"]',
510
+ style: {
511
+ 'line-color': '#EF5350',
512
+ 'target-arrow-color': '#EF5350'
513
+ }
514
+ },
515
+ {
516
+ selector: ':selected',
517
+ style: {
518
+ 'line-color': '#FF6B6B',
519
+ 'target-arrow-color': '#FF6B6B'
520
+ }
521
+ }
522
+ ];
523
+
524
+ const CREATABLE_WXCC_ACTIVITY_TYPES = new Set([
525
+ 'NewPhoneContact',
526
+ 'play-message',
527
+ 'play-music',
528
+ 'ivr-menu',
529
+ 'set-variable',
530
+ 'blind-transfer',
531
+ 'business-hours',
532
+ ]);
533
+ /**
534
+ * Map of node icons based on display type or label
535
+ */
536
+ const ICON_MAP = {
537
+ 'condition-activity': 'assets/wxcc/if.svg',
538
+ 'queue-contact': 'assets/wxcc/route.svg',
539
+ 'ivr-menu': 'assets/wxcc/m1.svg',
540
+ 'blind-transfer': 'assets/wxcc/terminate2.svg',
541
+ 'wait-activity': 'assets/wxcc/delay.svg',
542
+ 'newphonecontact': 'assets/wxcc/p1.svg',
543
+ 'disconnect-contact': 'assets/wxcc/terminate2.svg',
544
+ 'play-message': 'assets/wxcc/s1.svg',
545
+ 'play-music': 'assets/wxcc/delay.svg',
546
+ 'unmapped': 'assets/wxcc/unmapped.svg',
547
+ 'business-hours': 'assets/wxcc/c2.svg',
548
+ 'set-variable': 'assets/wxcc/variable.svg',
549
+ 'end': 'assets/wxcc/close1.svg'
550
+ };
551
+ /**
552
+ * Map of node color classes based on group
553
+ */
554
+ const COLOR_CLASS_MAP = {
555
+ 'start': 'node-start',
556
+ 'end': 'node-end',
557
+ 'terminating-action': 'node-end',
558
+ 'set-variable': 'node-action',
559
+ 'unmapped': 'node-default',
560
+ 'enum-gateway': 'node-gateway',
561
+ 'action': 'node-action'
562
+ };
563
+ /**
564
+ * Map of activity type labels based on group
565
+ */
566
+ const ACTIVITY_TYPE_LABELS = {
567
+ 'start': 'Start',
568
+ 'end': 'End',
569
+ 'terminating-action': 'Terminate',
570
+ 'enum-gateway': 'Menu',
571
+ 'action': 'Action',
572
+ 'unmapped': 'Unmapped'
573
+ };
574
+ /**
575
+ * All available activity display types for node configuration
576
+ * Values match ICON_MAP keys exactly
577
+ */
578
+ const ACTIVITY_DISPLAY_TYPES = [
579
+ { activityName: 'NewPhoneContact', value: 'newphonecontact', label: 'Start', icon: ICON_MAP['newphonecontact'], group: 'start' },
580
+ { activityName: 'end', value: 'end', label: 'End', icon: ICON_MAP['end'], group: 'end' },
581
+ { activityName: 'play-message', value: 'play-message', label: 'Play Message', icon: ICON_MAP['play-message'], group: 'action' },
582
+ { activityName: 'ivr-menu', value: 'ivr-menu', label: 'Menu', icon: ICON_MAP['ivr-menu'], group: 'enum-gateway' },
583
+ { activityName: 'queue-contact', value: 'queue-contact', label: 'Queue Contact', icon: ICON_MAP['queue-contact'], group: 'action' },
584
+ { activityName: 'set-variable', value: 'set-variable', label: 'Set Variable', icon: ICON_MAP['set-variable'], group: 'set-variable' },
585
+ { activityName: 'condition-activity', value: 'condition-activity', label: 'Condition', icon: ICON_MAP['condition-activity'], group: 'enum-gateway' },
586
+ { activityName: 'business-hours', value: 'business-hours', label: 'Business Hours', icon: ICON_MAP['business-hours'], group: 'enum-gateway' },
587
+ { activityName: 'wait-activity', value: 'wait-activity', label: 'Wait', icon: ICON_MAP['wait-activity'], group: 'action' },
588
+ { activityName: 'play-music', value: 'play-music', label: 'Play Music', icon: ICON_MAP['play-music'], group: 'action' },
589
+ { activityName: 'blind-transfer', value: 'blind-transfer', label: 'Blind Transfer', icon: ICON_MAP['blind-transfer'], group: 'action' },
590
+ { activityName: 'disconnect-contact', value: 'disconnect-contact', label: 'Disconnect', icon: ICON_MAP['disconnect-contact'], group: 'terminating-action' },
591
+ { activityName: 'unmapped', value: 'unmapped', label: 'Unmapped', icon: ICON_MAP['unmapped'], group: 'unmapped' }
592
+ ];
593
+ const CREATABLE_ACTIVITY_DISPLAY_TYPES = ACTIVITY_DISPLAY_TYPES
594
+ .filter(type => CREATABLE_WXCC_ACTIVITY_TYPES.has(type.activityName));
595
+ /**
596
+ * Get node icon information based on name or display type
597
+ * @param name - The node name or display type
598
+ * @returns Icon information with src and alt text
599
+ */
600
+ function getNodeIcon(name) {
601
+ const key = name.toLowerCase();
602
+ const iconSrc = ICON_MAP[key] || ICON_MAP['unmapped'];
603
+ return { iconSrc, alt: key };
604
+ }
605
+ /**
606
+ * Get node color class based on group
607
+ * @param group - The node group
608
+ * @returns CSS class name for node coloring
609
+ */
610
+ function getNodeColorClass(group) {
611
+ return COLOR_CLASS_MAP[group] || 'node-default';
612
+ }
613
+ /**
614
+ * Get activity type label based on group
615
+ * @param group - The node group
616
+ * @returns Human-readable activity type label
617
+ */
618
+ function getActivityTypeLabel(group) {
619
+ return ACTIVITY_TYPE_LABELS[group] || 'Activity';
620
+ }
621
+ /**
622
+ * Find activity display type by value
623
+ * @param value - The display type value
624
+ * @returns Display type or unmapped if not found
625
+ */
626
+ function getActivityDisplayTypeByValue(value) {
627
+ return ACTIVITY_DISPLAY_TYPES.find(dt => dt.value === value) || ACTIVITY_DISPLAY_TYPES[ACTIVITY_DISPLAY_TYPES.length - 1];
628
+ }
629
+ function getCreatableActivityDisplayTypeByValue(value) {
630
+ return CREATABLE_ACTIVITY_DISPLAY_TYPES.find(type => type.value === value) || CREATABLE_ACTIVITY_DISPLAY_TYPES[0];
631
+ }
632
+
633
+ function escapeHtml(text) {
634
+ if (!text)
635
+ return '';
636
+ return text
637
+ .replace(/&/g, '&')
638
+ .replace(/</g, '&lt;')
639
+ .replace(/>/g, '&gt;')
640
+ .replace(/"/g, '&quot;')
641
+ .replace(/'/g, '&#039;');
642
+ }
643
+ function getTranformedActivityName(name) {
644
+ return name
645
+ .split('-')
646
+ .map(s => s.charAt(0).toLocaleUpperCase() + s.slice(1))
647
+ .join(' ');
648
+ }
649
+ function getReviewElement(review) {
650
+ if (!review)
651
+ return `No review is available`;
652
+ const reviewColor = review.color;
653
+ const reviewColorLabel = `${reviewColor.charAt(0).toUpperCase()}${reviewColor.slice(1)}`;
654
+ const reviewLevelLabel = review.level.replace('_', ' ');
655
+ return `
656
+ <span class="review-${reviewColor}">
657
+ ${reviewColorLabel} (${reviewLevelLabel})
658
+ </span>
659
+ `;
660
+ }
661
+ function getNodeHtmlTemplate(data) {
662
+ const group = data.wxccGroup || 'unknown';
663
+ const colorClass = getNodeColorClass(group);
664
+ const typeLabel = getActivityTypeLabel(group);
665
+ const name = data.name ? data.name.split('\n')[0] : '';
666
+ const detailsHeading = (data.suggestedProperties && data.suggestedProperties.uccxDescription
667
+ ? data.suggestedProperties.uccxDescription
668
+ : '').trim();
669
+ const activityName = data.wxccActivityName || 'unmapped';
670
+ const iconInfo = data.iconUrl ?
671
+ { iconSrc: data.iconUrl, alt: data.iconUrl } :
672
+ getNodeIcon(typeLabel === 'Unmapped' ? typeLabel : activityName);
673
+ const { iconSrc, alt } = iconInfo;
674
+ const transformedActivityName = getTranformedActivityName(activityName);
675
+ const extraDetails = {
676
+ Review: getReviewElement(data.review)
677
+ };
678
+ // Allow highlight class to be toggled by data.highlighted property
679
+ const highlightClass = data.highlighted ? 'highlighted' : '';
680
+ return `
681
+ <div class="node-content ${colorClass} ${highlightClass}">
682
+ <header>
683
+ <div class="node-icon">
684
+ <img
685
+ src="${iconSrc}"
686
+ alt="${alt}"
687
+ title="${typeLabel}"
688
+ />
689
+ </div>
690
+ <div class="node-info">
691
+ <div class="node-label" title="${escapeHtml(name)}">${name}</div>
692
+ <div class="node-activity-name" title="${escapeHtml(transformedActivityName)}">
693
+ ${transformedActivityName}
694
+ </div>
695
+ </div>
696
+ </header>
697
+ <div class="node-details">
698
+ <div class="node-details-item" title="${escapeHtml(detailsHeading)}">${detailsHeading}</div>
699
+ ${Object.entries(extraDetails).map(([key, value]) => {
700
+ const fullText = `${key}: ${value}`;
701
+ return `<div>${fullText}</div>`;
702
+ })}
703
+ </div>
704
+ </div>
705
+ `;
706
+ }
707
+
708
+ class AddNodeDialogComponent {
709
+ constructor(data, dialogRef) {
710
+ this.data = data;
711
+ this.dialogRef = dialogRef;
712
+ this.activityDisplayTypes = CREATABLE_ACTIVITY_DISPLAY_TYPES;
713
+ this.selectedActivityType = CREATABLE_ACTIVITY_DISPLAY_TYPES[0];
714
+ this.nodeName = '';
715
+ this.selectedParentIds = [];
716
+ this.selectedChildIds = [];
717
+ this.availableNodes = [];
718
+ }
719
+ ngOnInit() {
720
+ this.availableNodes = this.data.availableNodes;
721
+ }
722
+ resetForm() {
723
+ this.selectedActivityType = CREATABLE_ACTIVITY_DISPLAY_TYPES[0];
724
+ this.nodeName = '';
725
+ this.selectedParentIds = [];
726
+ this.selectedChildIds = [];
727
+ }
728
+ onActivityTypeChange(value) {
729
+ this.selectedActivityType = getCreatableActivityDisplayTypeByValue(value);
730
+ }
731
+ onClose() {
732
+ this.dialogRef.close();
733
+ }
734
+ onSubmit() {
735
+ if (!this.nodeName.trim()) {
736
+ return;
737
+ }
738
+ const newNodeData = {
739
+ activityTypeName: this.selectedActivityType.activityName,
740
+ name: this.nodeName.trim(),
741
+ parentNodeIds: this.selectedParentIds,
742
+ childNodeIds: this.selectedChildIds
743
+ };
744
+ this.dialogRef.close(newNodeData);
745
+ }
746
+ trackByValue(index, type) {
747
+ return type.value;
748
+ }
749
+ trackByNodeId(index, node) {
750
+ return node.id;
751
+ }
752
+ }
753
+ AddNodeDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AddNodeDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$2.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component });
754
+ AddNodeDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: AddNodeDialogComponent, selector: "add-node-dialog", ngImport: i0, template: "", styles: [".form-group{margin-bottom:1.25rem}.form-group:last-child{margin-bottom:0}.form-group .form-label{display:block;font-size:.75rem;font-weight:600;color:#24292e;margin-bottom:.5rem;text-transform:uppercase;letter-spacing:.5px}.form-group .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.form-group .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.form-group .form-control::placeholder{color:#959da5}.form-group textarea.form-control{resize:vertical;min-height:80px}.form-group .display-type-preview{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:#f6f8fa;border-radius:6px;margin-bottom:.5rem}.form-group .display-type-preview .type-icon{width:20px;height:20px}.form-group .display-type-preview .type-label{font-size:.875rem;font-weight:500;color:#24292e}.form-group .node-selection-list{max-height:150px;overflow-y:auto;border:1px solid #d1d5da;border-radius:6px;background:#fafbfc}.form-group .node-selection-list .node-selection-item{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background .15s;border-bottom:1px solid #e1e4e8}.form-group .node-selection-list .node-selection-item:last-child{border-bottom:none}.form-group .node-selection-list .node-selection-item:hover{background:#f0f3f6}.form-group .node-selection-list .node-selection-item.selected{background:rgba(3,102,214,.08)}.form-group .node-selection-list .node-selection-item .node-name{font-size:.8125rem;color:#24292e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.form-group .node-selection-list .empty-list{padding:1rem;text-align:center;color:#586069;font-size:.8125rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
755
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AddNodeDialogComponent, decorators: [{
756
+ type: Component,
757
+ args: [{ selector: 'add-node-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "", styles: [".form-group{margin-bottom:1.25rem}.form-group:last-child{margin-bottom:0}.form-group .form-label{display:block;font-size:.75rem;font-weight:600;color:#24292e;margin-bottom:.5rem;text-transform:uppercase;letter-spacing:.5px}.form-group .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.form-group .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.form-group .form-control::placeholder{color:#959da5}.form-group textarea.form-control{resize:vertical;min-height:80px}.form-group .display-type-preview{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:#f6f8fa;border-radius:6px;margin-bottom:.5rem}.form-group .display-type-preview .type-icon{width:20px;height:20px}.form-group .display-type-preview .type-label{font-size:.875rem;font-weight:500;color:#24292e}.form-group .node-selection-list{max-height:150px;overflow-y:auto;border:1px solid #d1d5da;border-radius:6px;background:#fafbfc}.form-group .node-selection-list .node-selection-item{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background .15s;border-bottom:1px solid #e1e4e8}.form-group .node-selection-list .node-selection-item:last-child{border-bottom:none}.form-group .node-selection-list .node-selection-item:hover{background:#f0f3f6}.form-group .node-selection-list .node-selection-item.selected{background:rgba(3,102,214,.08)}.form-group .node-selection-list .node-selection-item .node-name{font-size:.8125rem;color:#24292e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.form-group .node-selection-list .empty-list{padding:1rem;text-align:center;color:#586069;font-size:.8125rem}\n"] }]
758
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
759
+ type: Inject,
760
+ args: [MAT_DIALOG_DATA]
761
+ }] }, { type: i1$2.MatDialogRef }]; } });
762
+
763
+ class LinkNodeDialogComponent {
764
+ constructor(data, dialogRef) {
765
+ this.data = data;
766
+ this.dialogRef = dialogRef;
767
+ // @Input() isOpen = false;
768
+ // @Input() sourceNode: ActivityData | null = null;
769
+ this.availableNodes = [];
770
+ this.close = new EventEmitter();
771
+ this.linkNodes = new EventEmitter();
772
+ this.selectedTargetId = null;
773
+ this.linkLabel = '';
774
+ this.searchQuery = '';
775
+ }
776
+ ngOnInit() {
777
+ this.availableNodes = this.data.availableNodes;
778
+ this.sourceNode = this.data.sourceNode;
779
+ }
780
+ get filteredNodes() {
781
+ if (!this.sourceNode) {
782
+ return [];
783
+ }
784
+ if (!this.searchQuery.trim()) {
785
+ return this.availableNodes.filter(n => n && n.id !== this.sourceNode.id);
786
+ }
787
+ const query = this.searchQuery.toLowerCase();
788
+ return this.availableNodes.filter(n => n && n.id !== this.sourceNode.id &&
789
+ ((n.name && n.name.toLowerCase().includes(query)) ||
790
+ (n.wxccActivityName && n.wxccActivityName.toLowerCase().includes(query))));
791
+ }
792
+ ngOnChanges(changes) {
793
+ // if (changes['isOpen'] && this.isOpen) {
794
+ // this.resetForm();
795
+ // }
796
+ }
797
+ resetForm() {
798
+ this.selectedTargetId = null;
799
+ this.linkLabel = '';
800
+ this.searchQuery = '';
801
+ }
802
+ selectNode(nodeId) {
803
+ this.selectedTargetId = nodeId;
804
+ }
805
+ isSelected(nodeId) {
806
+ return this.selectedTargetId === nodeId;
807
+ }
808
+ onClose() {
809
+ this.dialogRef.close();
810
+ }
811
+ onSubmit() {
812
+ if (!this.sourceNode || !this.selectedTargetId) {
813
+ return;
814
+ }
815
+ const linkData = {
816
+ sourceNodeId: this.sourceNode.id,
817
+ targetNodeId: this.selectedTargetId,
818
+ label: this.linkLabel.trim() || undefined
819
+ };
820
+ this.dialogRef.close(linkData);
821
+ // this.linkNodes.emit(linkData);
822
+ // this.onClose();
823
+ }
824
+ trackByNodeId(index, node) {
825
+ return node.id;
826
+ }
827
+ }
828
+ LinkNodeDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LinkNodeDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$2.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component });
829
+ LinkNodeDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: LinkNodeDialogComponent, selector: "link-node-dialog", outputs: { close: "close", linkNodes: "linkNodes" }, usesOnChanges: true, ngImport: i0, template: "", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";.source-node-info{margin-bottom:1.25rem}.source-node-info .node-preview{display:flex;flex-direction:column;gap:.25rem;padding:.75rem 1rem;background:#f0f3f6;border-radius:6px}.source-node-info .node-preview .node-name{font-size:.875rem;font-weight:600;color:#24292e}.source-node-info .node-preview .node-type{font-size:.75rem;color:#586069}.form-group{margin-bottom:1.25rem}.form-group:last-child{margin-bottom:0}.form-group .form-label{display:block;font-size:.75rem;font-weight:600;color:#24292e;margin-bottom:.5rem;text-transform:uppercase;letter-spacing:.5px}.form-group .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.form-group .form-control:focus{outline:none;border-color:#0985a0;box-shadow:0 0 0 3px #0366d61a}.form-group .form-control::placeholder{color:#959da5}.form-group .search-input{margin-bottom:.75rem}.form-group .node-selection-list{max-height:200px;overflow-y:auto;border:1px solid #d1d5da;border-radius:6px;background:#fafbfc}.form-group .node-selection-list .node-selection-item{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;cursor:pointer;transition:background .15s;border-bottom:1px solid #e1e4e8}.form-group .node-selection-list .node-selection-item:last-child{border-bottom:none}.form-group .node-selection-list .node-selection-item:hover{background:#f0f3f6}.form-group .node-selection-list .node-selection-item.selected{background:rgba(0,155,183,.08)}.form-group .node-selection-list .node-selection-item.selected .node-radio{border-color:#0985a0}.form-group .node-selection-list .node-selection-item.selected .node-radio .radio-inner{background:#0985A0}.form-group .node-selection-list .node-selection-item .node-radio{width:18px;height:18px;border:2px solid #d1d5da;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:border-color .15s}.form-group .node-selection-list .node-selection-item .node-radio .radio-inner{width:10px;height:10px;border-radius:50%}.form-group .node-selection-list .node-selection-item .node-details{display:flex;flex-direction:column;gap:.125rem;min-width:0;flex:1}.form-group .node-selection-list .node-selection-item .node-details .node-name{font-size:.8125rem;font-weight:500;color:#24292e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.form-group .node-selection-list .node-selection-item .node-details .node-type{font-size:.6875rem;color:#586569}.form-group .node-selection-list .empty-list{padding:1.5rem;text-align:center;color:#586569;font-size:.8125rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
830
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LinkNodeDialogComponent, decorators: [{
831
+ type: Component,
832
+ args: [{ selector: 'link-node-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";.source-node-info{margin-bottom:1.25rem}.source-node-info .node-preview{display:flex;flex-direction:column;gap:.25rem;padding:.75rem 1rem;background:#f0f3f6;border-radius:6px}.source-node-info .node-preview .node-name{font-size:.875rem;font-weight:600;color:#24292e}.source-node-info .node-preview .node-type{font-size:.75rem;color:#586069}.form-group{margin-bottom:1.25rem}.form-group:last-child{margin-bottom:0}.form-group .form-label{display:block;font-size:.75rem;font-weight:600;color:#24292e;margin-bottom:.5rem;text-transform:uppercase;letter-spacing:.5px}.form-group .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.form-group .form-control:focus{outline:none;border-color:#0985a0;box-shadow:0 0 0 3px #0366d61a}.form-group .form-control::placeholder{color:#959da5}.form-group .search-input{margin-bottom:.75rem}.form-group .node-selection-list{max-height:200px;overflow-y:auto;border:1px solid #d1d5da;border-radius:6px;background:#fafbfc}.form-group .node-selection-list .node-selection-item{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;cursor:pointer;transition:background .15s;border-bottom:1px solid #e1e4e8}.form-group .node-selection-list .node-selection-item:last-child{border-bottom:none}.form-group .node-selection-list .node-selection-item:hover{background:#f0f3f6}.form-group .node-selection-list .node-selection-item.selected{background:rgba(0,155,183,.08)}.form-group .node-selection-list .node-selection-item.selected .node-radio{border-color:#0985a0}.form-group .node-selection-list .node-selection-item.selected .node-radio .radio-inner{background:#0985A0}.form-group .node-selection-list .node-selection-item .node-radio{width:18px;height:18px;border:2px solid #d1d5da;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:border-color .15s}.form-group .node-selection-list .node-selection-item .node-radio .radio-inner{width:10px;height:10px;border-radius:50%}.form-group .node-selection-list .node-selection-item .node-details{display:flex;flex-direction:column;gap:.125rem;min-width:0;flex:1}.form-group .node-selection-list .node-selection-item .node-details .node-name{font-size:.8125rem;font-weight:500;color:#24292e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.form-group .node-selection-list .node-selection-item .node-details .node-type{font-size:.6875rem;color:#586569}.form-group .node-selection-list .empty-list{padding:1.5rem;text-align:center;color:#586569;font-size:.8125rem}\n"] }]
833
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
834
+ type: Inject,
835
+ args: [MAT_DIALOG_DATA]
836
+ }] }, { type: i1$2.MatDialogRef }]; }, propDecorators: { close: [{
837
+ type: Output
838
+ }], linkNodes: [{
839
+ type: Output
840
+ }] } });
841
+
842
+ class WxCC2GraphService {
843
+ parseWxCC(wxcc, nonIr) {
844
+ this.wxccJSON = wxcc;
845
+ if (nonIr) {
846
+ this.wxccNonIRJSON = nonIr;
847
+ }
848
+ const nodes = [];
849
+ const edges = [];
850
+ wxcc.activities.forEach(activity => nodes.push(this.toWxCCNode(activity)));
851
+ wxcc.links.forEach(link => edges.push(this.toWxCCEdge(link)));
852
+ return {
853
+ flowId: wxcc.generatedAt,
854
+ flowName: wxcc.prefix,
855
+ nodes: nodes,
856
+ edges: edges
857
+ };
858
+ }
859
+ setSourceDocuments(ir, nonIr) {
860
+ this.wxccJSON = ir;
861
+ this.wxccNonIRJSON = nonIr;
862
+ }
863
+ updateActivityData(data) {
864
+ const { iconUrl, ...dataWithoutIcon } = data;
865
+ const wxccActivityData = this.getActivityById(data.id);
866
+ if (!wxccActivityData) {
867
+ console.error(`Activity with id ${data.id} not found`);
868
+ return false;
869
+ }
870
+ const source = dataWithoutIcon;
871
+ const target = wxccActivityData;
872
+ Object.keys(source).forEach(key => {
873
+ if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
874
+ // For nested objects, merge them recursively
875
+ target[key] = { ...target[key], ...source[key] };
876
+ }
877
+ else {
878
+ // For primitives and arrays, assign directly
879
+ target[key] = source[key];
880
+ }
881
+ });
882
+ return true;
883
+ }
884
+ /**
885
+ * Add a new activity to the graph
886
+ */
887
+ addActivity(activity) {
888
+ // Add to internal JSON structure
889
+ this.wxccJSON.activities.push(activity);
890
+ return this.toWxCCNode(activity);
891
+ }
892
+ /**
893
+ * Remove an activity and all its connected links
894
+ */
895
+ removeActivity(activityId) {
896
+ // Remove the activity
897
+ const activityIndex = this.wxccJSON.activities.findIndex(a => a.id === activityId);
898
+ if (activityIndex !== -1) {
899
+ this.wxccJSON.activities.splice(activityIndex, 1);
900
+ }
901
+ // Find and remove all links connected to this activity
902
+ const removedLinkIds = [];
903
+ const linksToRemove = this.wxccJSON.links.filter(link => link.sourceActivityId === activityId || link.targetActivityId === activityId);
904
+ linksToRemove.forEach(link => {
905
+ removedLinkIds.push(link.id);
906
+ const linkIndex = this.wxccJSON.links.findIndex(l => l.id === link.id);
907
+ if (linkIndex !== -1) {
908
+ this.wxccJSON.links.splice(linkIndex, 1);
909
+ }
910
+ });
911
+ return { removedLinkIds };
912
+ }
913
+ /**
914
+ * Add a new link between two activities
915
+ */
916
+ addLink(sourceActivityId, targetActivityId, label) {
917
+ const linkId = this.generateId();
918
+ const link = {
919
+ id: linkId,
920
+ sourceActivityId,
921
+ targetActivityId,
922
+ uccxLabel: label || ''
923
+ };
924
+ this.wxccJSON.links.push(link);
925
+ return this.toWxCCEdge(link);
926
+ }
927
+ /**
928
+ * Remove a link by its id
929
+ */
930
+ removeLink(linkId) {
931
+ const linkIndex = this.wxccJSON.links.findIndex(l => l.id === linkId);
932
+ if (linkIndex !== -1) {
933
+ this.wxccJSON.links.splice(linkIndex, 1);
934
+ return true;
935
+ }
936
+ return false;
937
+ }
938
+ /**
939
+ * Check if a link already exists between two nodes
940
+ */
941
+ linkExists(sourceActivityId, targetActivityId) {
942
+ return this.wxccJSON.links.some(link => link.sourceActivityId === sourceActivityId && link.targetActivityId === targetActivityId);
943
+ }
944
+ /**
945
+ * Get all activities for selection purposes
946
+ */
947
+ getAllActivities() {
948
+ return [...this.wxccJSON.activities];
949
+ }
950
+ getActivityById(id) {
951
+ return this.wxccJSON.activities.find(a => a.id === id);
952
+ }
953
+ generateId() {
954
+ return uuid.v4();
955
+ }
956
+ toWxCCNode(activity) {
957
+ const label = activity.name || activity.wxccActivityName || 'Activity';
958
+ return {
959
+ data: {
960
+ ...activity,
961
+ label: label
962
+ }
963
+ };
964
+ }
965
+ toWxCCEdge(link) {
966
+ const label = link.uccxLabel || link.conditionExpr || '';
967
+ return {
968
+ data: {
969
+ ...link,
970
+ source: link.sourceActivityId,
971
+ target: link.targetActivityId,
972
+ label: label
973
+ }
974
+ };
975
+ }
976
+ }
977
+ WxCC2GraphService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCC2GraphService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
978
+ WxCC2GraphService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCC2GraphService });
979
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCC2GraphService, decorators: [{
980
+ type: Injectable
981
+ }] });
982
+
983
+ class WxCCActivityManageService {
984
+ constructor() {
985
+ this.ACTIVITY_TEMPLATES = {
986
+ NewPhoneContact: {
987
+ id: '',
988
+ type: 'NewPhoneContact',
989
+ group: 'start',
990
+ name: 'NewPhoneContact',
991
+ properties: {
992
+ name: 'NewPhoneContact',
993
+ event: 'NewPhoneContact',
994
+ flowType: {
995
+ eventSourceName: 'WebexContactCenter',
996
+ eventSpecificationName: 'ContactStartWorkflow',
997
+ eventClassificationId: '',
998
+ eventClassificationName: '',
999
+ eventSpecificationId: '',
1000
+ eventSourceId: ''
1001
+ },
1002
+ activityName: 'NewPhoneContact',
1003
+ _renderRequestTimestamp: Date.now(),
1004
+ activityId: 'start'
1005
+ }
1006
+ },
1007
+ "blind-transfer": {
1008
+ id: '',
1009
+ type: 'blind-transfer',
1010
+ group: 'terminating-action',
1011
+ name: 'BlindTransfer',
1012
+ properties: {
1013
+ name: 'BlindTransfer',
1014
+ activityName: 'blind-transfer',
1015
+ _renderRequestTimestamp: Date.now(),
1016
+ transfertodn: '',
1017
+ activityId: '',
1018
+ transfertodn_radioName: 'dn',
1019
+ 'transfertodn:radioName': 'dn',
1020
+ customAttributes: {},
1021
+ flowDecryptAccess: false,
1022
+ }
1023
+ },
1024
+ "ivr-menu": {
1025
+ id: '',
1026
+ type: 'ivr-menu',
1027
+ group: 'enum-gateway',
1028
+ name: 'Menu',
1029
+ properties: {
1030
+ connector_name: null,
1031
+ name: 'Menu',
1032
+ menuLinks: [],
1033
+ toggle: false,
1034
+ activityName: 'ivr-menu',
1035
+ prompts: [],
1036
+ _renderRequestTimestamp: Date.now(),
1037
+ 'connector:name': null,
1038
+ activityId: '',
1039
+ 'menuLinks:input': [],
1040
+ entryTimeout: 3,
1041
+ volumeGainDb: 0,
1042
+ menuLinks_input: [],
1043
+ voiceLanguage_name: null,
1044
+ promptsTts: null,
1045
+ interruptible: false,
1046
+ connector: null,
1047
+ speakingRate: 1,
1048
+ toggleLanguage: null,
1049
+ voiceLanguage: null,
1050
+ flowDecryptAccess: false,
1051
+ 'voiceLanguage:name': null
1052
+ }
1053
+ },
1054
+ "play-message": {
1055
+ id: '',
1056
+ type: 'play-message',
1057
+ group: 'action',
1058
+ name: 'PlayMessage',
1059
+ properties: {
1060
+ connector_name: null,
1061
+ name: 'PlayMessage',
1062
+ toggle: false,
1063
+ activityName: 'play-message',
1064
+ prompts: [],
1065
+ _renderRequestTimestamp: Date.now(),
1066
+ 'connector:name': null,
1067
+ activityId: '',
1068
+ volumeGainDb: 0,
1069
+ voiceLanguage_name: null,
1070
+ promptsTts: null,
1071
+ connector: null,
1072
+ speakingRate: 1,
1073
+ toggleLanguage: null,
1074
+ voiceLanguage: null,
1075
+ flowDecryptAccess: false,
1076
+ 'voiceLanguage:name': null
1077
+ }
1078
+ },
1079
+ "play-music": {
1080
+ id: '',
1081
+ type: 'play-music',
1082
+ group: 'action',
1083
+ name: 'PlayPrompt',
1084
+ properties: {
1085
+ connector_name: null,
1086
+ name: 'PlayPrompt',
1087
+ toggle: false,
1088
+ activityName: 'play-music',
1089
+ prompts: [],
1090
+ _renderRequestTimestamp: Date.now(),
1091
+ 'connector:name': null,
1092
+ activityId: '',
1093
+ volumeGainDb: 0,
1094
+ voiceLanguage_name: null,
1095
+ promptsTts: null,
1096
+ connector: null,
1097
+ speakingRate: 1,
1098
+ toggleLanguage: null,
1099
+ voiceLanguage: null,
1100
+ flowDecryptAccess: false,
1101
+ 'voiceLanguage:name': null
1102
+ }
1103
+ },
1104
+ "set-variable": {
1105
+ id: '',
1106
+ type: 'set-variable',
1107
+ group: 'set-variable',
1108
+ name: 'SetVariable',
1109
+ properties: {
1110
+ setTo: 'set-to-literal',
1111
+ name: 'SetVariable',
1112
+ literal_invalid_error: false,
1113
+ activityName: 'set-variable',
1114
+ _renderRequestTimestamp: Date.now(),
1115
+ activityId: 'set-variable',
1116
+ setVariablesArray: [],
1117
+ flowDecryptAccess: false
1118
+ }
1119
+ },
1120
+ "business-hours": {
1121
+ id: '',
1122
+ type: 'business-hours',
1123
+ name: '',
1124
+ group: '',
1125
+ properties: {
1126
+ activityName: 'business-hours',
1127
+ _renderRequestTimestamp: Date.now(),
1128
+ activityId: ''
1129
+ }
1130
+ }
1131
+ };
1132
+ }
1133
+ create(type) {
1134
+ return JSON.parse(JSON.stringify(this.ACTIVITY_TEMPLATES[type]));
1135
+ }
1136
+ }
1137
+ WxCCActivityManageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActivityManageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1138
+ WxCCActivityManageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActivityManageService });
1139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActivityManageService, decorators: [{
1140
+ type: Injectable
1141
+ }] });
1142
+
1143
+ class WxCCActivityCreationService {
1144
+ constructor(wxcc2graph, wxccActivityTemplateService) {
1145
+ this.wxcc2graph = wxcc2graph;
1146
+ this.wxccActivityTemplateService = wxccActivityTemplateService;
1147
+ }
1148
+ createAndSync(request) {
1149
+ const newActivityId = this.wxcc2graph.generateId();
1150
+ const activityTemplate = this.buildTemplatedActivity(request, newActivityId);
1151
+ this.seedNonIrActivity(activityTemplate, newActivityId);
1152
+ const activityData = this.buildExtendedActivity(request, activityTemplate, newActivityId);
1153
+ const node = this.wxcc2graph.addActivity(activityData);
1154
+ return node;
1155
+ }
1156
+ buildTemplatedActivity(request, newActivityId) {
1157
+ const activityTemplate = this.wxccActivityTemplateService.create(request.activityTypeName);
1158
+ const templateProperties = activityTemplate.properties;
1159
+ const displayType = ACTIVITY_DISPLAY_TYPES.find((type) => type.activityName === request.activityTypeName);
1160
+ activityTemplate.id = newActivityId;
1161
+ activityTemplate.name = request.name;
1162
+ activityTemplate.group = activityTemplate.group || displayType?.group || "unmapped";
1163
+ activityTemplate.properties.activityId = newActivityId;
1164
+ activityTemplate.properties._renderRequestTimestamp = Date.now();
1165
+ // @ts-ignore
1166
+ templateProperties.name = request.name;
1167
+ return activityTemplate;
1168
+ }
1169
+ seedNonIrActivity(activityTemplate, newActivityId) {
1170
+ const nonIrActivities = this.getNonIrActivitiesMap();
1171
+ if (!nonIrActivities) {
1172
+ return;
1173
+ }
1174
+ nonIrActivities[newActivityId] = {
1175
+ id: newActivityId,
1176
+ group: activityTemplate.group,
1177
+ name: activityTemplate.name,
1178
+ properties: {
1179
+ ...activityTemplate.properties,
1180
+ },
1181
+ };
1182
+ }
1183
+ getNonIrActivitiesMap() {
1184
+ const nonIrDoc = this.wxcc2graph.wxccNonIRJSON;
1185
+ if (!nonIrDoc) {
1186
+ return null;
1187
+ }
1188
+ const process = nonIrDoc.process;
1189
+ if (!process) {
1190
+ return null;
1191
+ }
1192
+ const activities = process.activities;
1193
+ if (!activities) {
1194
+ return null;
1195
+ }
1196
+ return activities;
1197
+ }
1198
+ buildExtendedActivity(request, activityTemplate, newActivityId) {
1199
+ const displayType = ACTIVITY_DISPLAY_TYPES.find((type) => type.activityName === request.activityTypeName);
1200
+ return {
1201
+ id: newActivityId,
1202
+ name: request.name,
1203
+ wxccActivityName: activityTemplate.type,
1204
+ wxccGroup: activityTemplate.group,
1205
+ wxccActivityId: activityTemplate.properties.activityId,
1206
+ // @ts-ignore
1207
+ iconUrl: displayType.icon || "assets/wxcc/unmapped.svg",
1208
+ suggestedProperties: {
1209
+ uccxDescription: "",
1210
+ },
1211
+ };
1212
+ }
1213
+ }
1214
+ WxCCActivityCreationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActivityCreationService, deps: [{ token: WxCC2GraphService }, { token: WxCCActivityManageService }], target: i0.ɵɵFactoryTarget.Injectable });
1215
+ WxCCActivityCreationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActivityCreationService });
1216
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActivityCreationService, decorators: [{
1217
+ type: Injectable
1218
+ }], ctorParameters: function () { return [{ type: WxCC2GraphService }, { type: WxCCActivityManageService }]; } });
1219
+
1220
+ const DEFAULT_VISIBILITY = {
1221
+ resetView: true,
1222
+ zoomIn: true,
1223
+ zoomOut: true,
1224
+ export: true
1225
+ };
1226
+ class FloatingToolBarComponent {
1227
+ constructor(sanitizer) {
1228
+ this.sanitizer = sanitizer;
1229
+ this.visibility = DEFAULT_VISIBILITY;
1230
+ this.resetViewChange = new EventEmitter();
1231
+ this.zoomInChange = new EventEmitter();
1232
+ this.zoomOutChange = new EventEmitter();
1233
+ this.exportImageChange = new EventEmitter();
1234
+ }
1235
+ ngOnInit() {
1236
+ const mergedVisibility = { ...DEFAULT_VISIBILITY, ...this.visibility };
1237
+ const allItems = [
1238
+ {
1239
+ id: 'reset-view',
1240
+ visibilityKey: 'resetView',
1241
+ label: 'UCCX.BUTTONS.RESET_VIEW',
1242
+ svg: this.sanitizer.bypassSecurityTrustHtml(`<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1243
+ <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
1244
+ <path d="M21 3v5h-5"></path>
1245
+ <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path>
1246
+ <path d="M3 21v-5h5"></path>
1247
+ </svg>`),
1248
+ action: () => this.resetView()
1249
+ },
1250
+ {
1251
+ id: 'zoom-in',
1252
+ visibilityKey: 'zoomIn',
1253
+ label: 'UCCX.BUTTONS.ZOOM_IN',
1254
+ svg: this.sanitizer.bypassSecurityTrustHtml(`<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1255
+ <circle cx="11" cy="11" r="8"></circle>
1256
+ <path d="m21 21-4.35-4.35"></path>
1257
+ <path d="M11 8v6M8 11h6"></path>
1258
+ </svg>`),
1259
+ action: () => this.zoomIn()
1260
+ },
1261
+ {
1262
+ id: 'zoom-out',
1263
+ visibilityKey: 'zoomOut',
1264
+ label: 'UCCX.BUTTONS.ZOOM_OUT',
1265
+ svg: this.sanitizer.bypassSecurityTrustHtml(`<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1266
+ <circle cx="11" cy="11" r="8"></circle>
1267
+ <path d="m21 21-4.35-4.35"></path>
1268
+ <path d="M8 11h6"></path>
1269
+ </svg>`),
1270
+ action: () => this.zoomOut()
1271
+ },
1272
+ {
1273
+ id: 'export',
1274
+ visibilityKey: 'export',
1275
+ label: 'UCCX.BUTTONS.EXPORT',
1276
+ svg: this.sanitizer.bypassSecurityTrustHtml(`<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1277
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
1278
+ <polyline points="7 10 12 15 17 10"></polyline>
1279
+ <line x1="12" y1="15" x2="12" y2="3"></line>
1280
+ </svg>`),
1281
+ action: () => this.exportImage()
1282
+ }
1283
+ ];
1284
+ this.toolbarConfig = allItems.filter(item => mergedVisibility[item.visibilityKey] !== false);
1285
+ }
1286
+ resetView() {
1287
+ this.resetViewChange.emit();
1288
+ }
1289
+ zoomIn() {
1290
+ this.zoomInChange.emit();
1291
+ }
1292
+ zoomOut() {
1293
+ this.zoomOutChange.emit();
1294
+ }
1295
+ exportImage() {
1296
+ this.exportImageChange.emit();
1297
+ }
1298
+ trackById(index, item) {
1299
+ return item.id;
1300
+ }
1301
+ }
1302
+ FloatingToolBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolBarComponent, deps: [{ token: i1$3.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
1303
+ FloatingToolBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: FloatingToolBarComponent, selector: "graph-floating-toolbar", inputs: { visibility: "visibility" }, outputs: { resetViewChange: "resetViewChange", zoomInChange: "zoomInChange", zoomOutChange: "zoomOutChange", exportImageChange: "exportImageChange" }, ngImport: i0, template: "<div class=\"toolbar-wrapper\" role=\"toolbar\">\r\n <ng-container *ngFor=\"let item of toolbarConfig; trackBy: trackById\">\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"item.label\"\r\n [matTooltip]=\"item.label\"\r\n matTooltipPosition=\"left\"\r\n class=\"toolbar-button\"\r\n (click)=\"item.action()\">\r\n <div [innerHTML]=\"item.svg\"></div>\r\n </button>\r\n </ng-container>\r\n</div>", styles: [".toolbar-wrapper{background-color:#ffffffac;position:absolute;display:flex;flex-direction:column;gap:.5rem;bottom:0;right:0;padding:.5rem;width:-moz-fit-content;width:fit-content;margin:1rem;border-radius:1rem;box-shadow:2px 4px 15px #0000002d;z-index:999}.toolbar-wrapper button{outline:none;border:none;border-radius:.5rem;background-color:#f6f6f6;padding:.5rem;cursor:pointer;font-size:1rem;display:flex;align-items:center;justify-content:center;width:40px;height:40px;transition:all .2s ease}.toolbar-wrapper button:hover{background-color:#eefff8;transform:scale(1.05)}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolBarComponent, decorators: [{
1305
+ type: Component,
1306
+ args: [{ selector: 'graph-floating-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"toolbar-wrapper\" role=\"toolbar\">\r\n <ng-container *ngFor=\"let item of toolbarConfig; trackBy: trackById\">\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"item.label\"\r\n [matTooltip]=\"item.label\"\r\n matTooltipPosition=\"left\"\r\n class=\"toolbar-button\"\r\n (click)=\"item.action()\">\r\n <div [innerHTML]=\"item.svg\"></div>\r\n </button>\r\n </ng-container>\r\n</div>", styles: [".toolbar-wrapper{background-color:#ffffffac;position:absolute;display:flex;flex-direction:column;gap:.5rem;bottom:0;right:0;padding:.5rem;width:-moz-fit-content;width:fit-content;margin:1rem;border-radius:1rem;box-shadow:2px 4px 15px #0000002d;z-index:999}.toolbar-wrapper button{outline:none;border:none;border-radius:.5rem;background-color:#f6f6f6;padding:.5rem;cursor:pointer;font-size:1rem;display:flex;align-items:center;justify-content:center;width:40px;height:40px;transition:all .2s ease}.toolbar-wrapper button:hover{background-color:#eefff8;transform:scale(1.05)}\n"] }]
1307
+ }], ctorParameters: function () { return [{ type: i1$3.DomSanitizer }]; }, propDecorators: { visibility: [{
1308
+ type: Input
1309
+ }], resetViewChange: [{
1310
+ type: Output
1311
+ }], zoomInChange: [{
1312
+ type: Output
1313
+ }], zoomOutChange: [{
1314
+ type: Output
1315
+ }], exportImageChange: [{
1316
+ type: Output
1317
+ }] } });
1318
+
1319
+ class NodeDetailsSidebarComponent {
1320
+ constructor() {
1321
+ this.isOpen = false;
1322
+ this.nodeData = null;
1323
+ this.close = new EventEmitter();
1324
+ this.activityTypeChange = new EventEmitter();
1325
+ this.descriptionChange = new EventEmitter();
1326
+ this.activityDisplayTypes = ACTIVITY_DISPLAY_TYPES;
1327
+ this.selectedActivityType = null;
1328
+ }
1329
+ ngOnChanges(changes) {
1330
+ if (changes['nodeData'] && this.nodeData) {
1331
+ this.initializeActivityType();
1332
+ }
1333
+ }
1334
+ initializeActivityType() {
1335
+ const activityName = this.nodeData && this.nodeData.wxccActivityName;
1336
+ this.selectedActivityType = getActivityDisplayTypeByValue((activityName || 'unmapped').toLocaleLowerCase());
1337
+ this.transformedActivityName = getTranformedActivityName(activityName || 'unmapped');
1338
+ }
1339
+ onDescriptionChange(event) {
1340
+ const target = event.target;
1341
+ if (!target) {
1342
+ return;
1343
+ }
1344
+ const description = target.value.trim();
1345
+ if (!description)
1346
+ return;
1347
+ this.descriptionChange.emit(description);
1348
+ }
1349
+ onActivityTypeChange(type) {
1350
+ this.selectedActivityType = type;
1351
+ this.activityTypeChange.emit(type);
1352
+ }
1353
+ onActivityTypeSelectChange(event) {
1354
+ const target = event.target;
1355
+ if (!target) {
1356
+ return;
1357
+ }
1358
+ const value = target.value;
1359
+ const type = getActivityDisplayTypeByValue(value);
1360
+ this.onActivityTypeChange(type);
1361
+ }
1362
+ onClose() {
1363
+ this.close.emit();
1364
+ }
1365
+ getNodeIcon() {
1366
+ return (this.selectedActivityType && this.selectedActivityType.icon) || ICON_MAP['unmapped'];
1367
+ }
1368
+ getNodeColorClass() {
1369
+ const group = (this.selectedActivityType && this.selectedActivityType.group) || 'unmapped';
1370
+ return getNodeColorClass(group);
1371
+ }
1372
+ getReviewColor() {
1373
+ const color = (this.nodeData && this.nodeData.review && this.nodeData.review.color) ||
1374
+ 'green';
1375
+ const colors = {
1376
+ 'green': '#4CAF50',
1377
+ 'yellow': '#FF9800',
1378
+ 'red': '#F44336'
1379
+ };
1380
+ return colors[color] || colors['green'];
1381
+ }
1382
+ getReviewLabel() {
1383
+ const color = (this.nodeData && this.nodeData.review && this.nodeData.review.color) ||
1384
+ 'green';
1385
+ const level = (this.nodeData && this.nodeData.review && this.nodeData.review.level) ||
1386
+ 'confident';
1387
+ return `${color.charAt(0).toUpperCase() + color.slice(1)} (${level.replace('_', ' ')})`;
1388
+ }
1389
+ trackByValue(index, type) {
1390
+ return type.value;
1391
+ }
1392
+ }
1393
+ NodeDetailsSidebarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeDetailsSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1394
+ NodeDetailsSidebarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NodeDetailsSidebarComponent, selector: "node-details-sidebar", inputs: { isOpen: "isOpen", nodeData: "nodeData" }, outputs: { close: "close", activityTypeChange: "activityTypeChange", descriptionChange: "descriptionChange" }, usesOnChanges: true, ngImport: i0, template: "<!-- <div class=\"sidebar-overlay\" *ngIf=\"isOpen\" (click)=\"onClose()\"></div> -->\r\n\r\n<div class=\"node-details-sidebar\" [class.open]=\"isOpen\">\r\n <div class=\"sidebar-header\">\r\n <h3>Node Details</h3>\r\n <button class=\"close-btn\" (click)=\"onClose()\">\r\n <span>&times;</span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"sidebar-content\" *ngIf=\"nodeData\">\r\n <!-- Node Preview -->\r\n <div class=\"node-preview\">\r\n <div class=\"node-preview-card\" [ngClass]=\"getNodeColorClass()\">\r\n <div class=\"node-icon\">\r\n <img [src]=\"getNodeIcon()\" alt=\"Node Icon\" />\r\n </div>\r\n <div class=\"node-info\">\r\n <div class=\"node-label\">{{ nodeData?.name?.split(\"\\n\")?.[0] }}</div>\r\n <div class=\"node-type\">{{ transformedActivityName }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity Type Selector -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Activity Type</label>\r\n <div class=\"display-type-selector\">\r\n <select\r\n class=\"form-control\"\r\n title=\"Select activity type\"\r\n [value]=\"selectedActivityType?.value\"\r\n (change)=\"onActivityTypeSelectChange($event)\"\r\n >\r\n <option\r\n *ngFor=\"let type of activityDisplayTypes; trackBy: trackByValue\"\r\n [value]=\"type.value\"\r\n >\r\n {{ type.label }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section\">\r\n <label class=\"section-label\">Description</label>\r\n <div class=\"display-type-selector\">\r\n <textarea\r\n class=\"form-control\"\r\n aria-label=\"property-description\"\r\n (input)=\"onDescriptionChange($event)\"\r\n [value]=\"nodeData.suggestedProperties?.uccxDescription\"\r\n rows=\"3\"\r\n ></textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Node Information -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Information</label>\r\n <div class=\"info-grid\">\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">UCCX Type:</span>\r\n <span class=\"info-value\" [title]=\"nodeData.uccxTypeName\">{{\r\n nodeData.uccxTypeName\r\n }}</span>\r\n </div>\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">WxCC Activity Name:</span>\r\n <span class=\"info-value\" [title]=\"transformedActivityName\">{{\r\n transformedActivityName\r\n }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Review Status -->\r\n <div class=\"section\" *ngIf=\"nodeData.review\">\r\n <label class=\"section-label\">Review Status</label>\r\n <div class=\"review-status\">\r\n <div class=\"review-badge\" [style.background-color]=\"getReviewColor()\">\r\n {{ getReviewLabel() }}\r\n </div>\r\n <div\r\n class=\"review-reasons\"\r\n *ngIf=\"nodeData.review.reasons && nodeData.review.reasons.length > 0\"\r\n >\r\n <div class=\"reason\" *ngFor=\"let reason of nodeData.review.reasons\">\r\n <span class=\"reason-icon\">\u26A0</span>\r\n <span>{{ reason }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Suggested Properties -->\r\n <div class=\"section\" *ngIf=\"nodeData.suggestedProperties\">\r\n <label class=\"section-label\">Migration Information</label>\r\n <div class=\"migration-info\">\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.closestWxccActivity\"\r\n >\r\n <div class=\"card-label\">Closest WXCC Activity</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.closestWxccActivity }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.mappingNotes\"\r\n >\r\n <div class=\"card-label\">Mapping Notes</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.mappingNotes }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.migrationInstructions\"\r\n >\r\n <div class=\"card-label\">Migration Instructions</div>\r\n <div class=\"card-value instructions\">\r\n {{ nodeData.suggestedProperties.migrationInstructions }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.node-details-sidebar{position:fixed;top:0;right:-420px;width:420px;height:100%;background:#ffffff;box-shadow:-2px 0 8px #00000026;z-index:1000;transition:right .4s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow:hidden}.node-details-sidebar.open{right:0}.node-details-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1.5rem;border-bottom:1px solid #e1e4e8;background:#f8f9fa}.node-details-sidebar .sidebar-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#24292e}.node-details-sidebar .sidebar-header .close-btn{background:none;border:none;font-size:2rem;line-height:1;cursor:pointer;color:#586069;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s}.node-details-sidebar .sidebar-header .close-btn:hover{background:rgba(0,0,0,.05);color:#24292e}.node-details-sidebar .sidebar-content{flex:1;overflow-y:auto;padding:1.5rem}.node-details-sidebar .sidebar-content .node-preview{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .node-preview .node-preview-card{display:flex;align-items:center;gap:1rem;padding:1rem;border-radius:8px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:8px;flex-shrink:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon img{width:24px;height:24px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info{flex:1;min-width:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-label{font-size:1rem;font-weight:600;margin-bottom:.25rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-type{font-size:.875rem;color:#586069}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start{background-color:#4caf500d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-icon{background-color:#4caf501a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-label{color:#4caf50}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end{background-color:#f443360d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-icon{background-color:#f443361a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-label{color:#f44336}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway{background-color:#ff98000d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-icon{background-color:#ff98001a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-label{color:#ff9800}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action{background-color:#9c27b00d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-icon{background-color:#9c27b01a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-label{color:#9c27b0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default{background-color:#607d8b0d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-icon{background-color:#607d8b1a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-label{color:#607d8b}.node-details-sidebar .sidebar-content .section{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .section .section-label{display:block;font-size:.65rem;font-weight:600;color:#24292e;margin-bottom:.75rem;text-transform:uppercase;letter-spacing:.5px}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s;box-sizing:border-box;resize:vertical}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.node-details-sidebar .sidebar-content .section .info-grid{display:flex;flex-direction:column;gap:.75rem}.node-details-sidebar .sidebar-content .section .info-grid .info-item{display:flex;justify-content:space-between;align-items:flex-start;padding:.75rem;background:#f6f8fa;border-radius:6px}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-label{font-size:.8125rem;color:#586069;font-weight:500}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-value{font-size:.8125rem;color:#24292e;font-weight:600;text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .section .review-status .review-badge{display:inline-block;padding:.5rem 1rem;border-radius:20px;color:#fff;font-size:.8125rem;font-weight:600;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason{display:flex;align-items:flex-start;gap:.5rem;padding:.75rem;background:#fff3cd;border-radius:4px;margin-bottom:.5rem;font-size:.8125rem;color:#856404}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason .reason-icon{flex-shrink:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card{padding:1rem;background:#f6f8fa;border-radius:6px;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card:last-child{margin-bottom:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-label{font-size:.75rem;font-weight:600;color:#586069;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value{font-size:.875rem;color:#24292e;line-height:1.5}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value.instructions{white-space:pre-wrap}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1395
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeDetailsSidebarComponent, decorators: [{
1396
+ type: Component,
1397
+ args: [{ selector: 'node-details-sidebar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- <div class=\"sidebar-overlay\" *ngIf=\"isOpen\" (click)=\"onClose()\"></div> -->\r\n\r\n<div class=\"node-details-sidebar\" [class.open]=\"isOpen\">\r\n <div class=\"sidebar-header\">\r\n <h3>Node Details</h3>\r\n <button class=\"close-btn\" (click)=\"onClose()\">\r\n <span>&times;</span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"sidebar-content\" *ngIf=\"nodeData\">\r\n <!-- Node Preview -->\r\n <div class=\"node-preview\">\r\n <div class=\"node-preview-card\" [ngClass]=\"getNodeColorClass()\">\r\n <div class=\"node-icon\">\r\n <img [src]=\"getNodeIcon()\" alt=\"Node Icon\" />\r\n </div>\r\n <div class=\"node-info\">\r\n <div class=\"node-label\">{{ nodeData?.name?.split(\"\\n\")?.[0] }}</div>\r\n <div class=\"node-type\">{{ transformedActivityName }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity Type Selector -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Activity Type</label>\r\n <div class=\"display-type-selector\">\r\n <select\r\n class=\"form-control\"\r\n title=\"Select activity type\"\r\n [value]=\"selectedActivityType?.value\"\r\n (change)=\"onActivityTypeSelectChange($event)\"\r\n >\r\n <option\r\n *ngFor=\"let type of activityDisplayTypes; trackBy: trackByValue\"\r\n [value]=\"type.value\"\r\n >\r\n {{ type.label }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section\">\r\n <label class=\"section-label\">Description</label>\r\n <div class=\"display-type-selector\">\r\n <textarea\r\n class=\"form-control\"\r\n aria-label=\"property-description\"\r\n (input)=\"onDescriptionChange($event)\"\r\n [value]=\"nodeData.suggestedProperties?.uccxDescription\"\r\n rows=\"3\"\r\n ></textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Node Information -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Information</label>\r\n <div class=\"info-grid\">\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">UCCX Type:</span>\r\n <span class=\"info-value\" [title]=\"nodeData.uccxTypeName\">{{\r\n nodeData.uccxTypeName\r\n }}</span>\r\n </div>\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">WxCC Activity Name:</span>\r\n <span class=\"info-value\" [title]=\"transformedActivityName\">{{\r\n transformedActivityName\r\n }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Review Status -->\r\n <div class=\"section\" *ngIf=\"nodeData.review\">\r\n <label class=\"section-label\">Review Status</label>\r\n <div class=\"review-status\">\r\n <div class=\"review-badge\" [style.background-color]=\"getReviewColor()\">\r\n {{ getReviewLabel() }}\r\n </div>\r\n <div\r\n class=\"review-reasons\"\r\n *ngIf=\"nodeData.review.reasons && nodeData.review.reasons.length > 0\"\r\n >\r\n <div class=\"reason\" *ngFor=\"let reason of nodeData.review.reasons\">\r\n <span class=\"reason-icon\">\u26A0</span>\r\n <span>{{ reason }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Suggested Properties -->\r\n <div class=\"section\" *ngIf=\"nodeData.suggestedProperties\">\r\n <label class=\"section-label\">Migration Information</label>\r\n <div class=\"migration-info\">\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.closestWxccActivity\"\r\n >\r\n <div class=\"card-label\">Closest WXCC Activity</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.closestWxccActivity }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.mappingNotes\"\r\n >\r\n <div class=\"card-label\">Mapping Notes</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.mappingNotes }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.migrationInstructions\"\r\n >\r\n <div class=\"card-label\">Migration Instructions</div>\r\n <div class=\"card-value instructions\">\r\n {{ nodeData.suggestedProperties.migrationInstructions }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.node-details-sidebar{position:fixed;top:0;right:-420px;width:420px;height:100%;background:#ffffff;box-shadow:-2px 0 8px #00000026;z-index:1000;transition:right .4s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow:hidden}.node-details-sidebar.open{right:0}.node-details-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1.5rem;border-bottom:1px solid #e1e4e8;background:#f8f9fa}.node-details-sidebar .sidebar-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#24292e}.node-details-sidebar .sidebar-header .close-btn{background:none;border:none;font-size:2rem;line-height:1;cursor:pointer;color:#586069;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s}.node-details-sidebar .sidebar-header .close-btn:hover{background:rgba(0,0,0,.05);color:#24292e}.node-details-sidebar .sidebar-content{flex:1;overflow-y:auto;padding:1.5rem}.node-details-sidebar .sidebar-content .node-preview{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .node-preview .node-preview-card{display:flex;align-items:center;gap:1rem;padding:1rem;border-radius:8px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:8px;flex-shrink:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon img{width:24px;height:24px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info{flex:1;min-width:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-label{font-size:1rem;font-weight:600;margin-bottom:.25rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-type{font-size:.875rem;color:#586069}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start{background-color:#4caf500d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-icon{background-color:#4caf501a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-label{color:#4caf50}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end{background-color:#f443360d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-icon{background-color:#f443361a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-label{color:#f44336}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway{background-color:#ff98000d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-icon{background-color:#ff98001a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-label{color:#ff9800}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action{background-color:#9c27b00d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-icon{background-color:#9c27b01a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-label{color:#9c27b0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default{background-color:#607d8b0d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-icon{background-color:#607d8b1a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-label{color:#607d8b}.node-details-sidebar .sidebar-content .section{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .section .section-label{display:block;font-size:.65rem;font-weight:600;color:#24292e;margin-bottom:.75rem;text-transform:uppercase;letter-spacing:.5px}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s;box-sizing:border-box;resize:vertical}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.node-details-sidebar .sidebar-content .section .info-grid{display:flex;flex-direction:column;gap:.75rem}.node-details-sidebar .sidebar-content .section .info-grid .info-item{display:flex;justify-content:space-between;align-items:flex-start;padding:.75rem;background:#f6f8fa;border-radius:6px}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-label{font-size:.8125rem;color:#586069;font-weight:500}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-value{font-size:.8125rem;color:#24292e;font-weight:600;text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .section .review-status .review-badge{display:inline-block;padding:.5rem 1rem;border-radius:20px;color:#fff;font-size:.8125rem;font-weight:600;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason{display:flex;align-items:flex-start;gap:.5rem;padding:.75rem;background:#fff3cd;border-radius:4px;margin-bottom:.5rem;font-size:.8125rem;color:#856404}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason .reason-icon{flex-shrink:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card{padding:1rem;background:#f6f8fa;border-radius:6px;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card:last-child{margin-bottom:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-label{font-size:.75rem;font-weight:600;color:#586069;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value{font-size:.875rem;color:#24292e;line-height:1.5}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value.instructions{white-space:pre-wrap}\n"] }]
1398
+ }], propDecorators: { isOpen: [{
1399
+ type: Input
1400
+ }], nodeData: [{
1401
+ type: Input
1402
+ }], close: [{
1403
+ type: Output
1404
+ }], activityTypeChange: [{
1405
+ type: Output
1406
+ }], descriptionChange: [{
1407
+ type: Output
1408
+ }] } });
1409
+
1410
+ class NodeActionToolbarComponent {
1411
+ constructor(sanitizer) {
1412
+ this.sanitizer = sanitizer;
1413
+ this.isVisible = false;
1414
+ this.position = { x: 0, y: 0 };
1415
+ this.deleteNode = new EventEmitter();
1416
+ this.linkNode = new EventEmitter();
1417
+ this.toolbarActions = [
1418
+ {
1419
+ id: 'link',
1420
+ label: 'Link to Node',
1421
+ svg: this.sanitizer.bypassSecurityTrustHtml(`
1422
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1423
+ <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
1424
+ <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
1425
+ </svg>
1426
+ `),
1427
+ action: () => this.onLinkNode()
1428
+ },
1429
+ {
1430
+ id: 'delete',
1431
+ label: 'Delete Node',
1432
+ svg: this.sanitizer.bypassSecurityTrustHtml(`
1433
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1434
+ <path d="M3 6h18"></path>
1435
+ <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
1436
+ <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
1437
+ <line x1="10" y1="11" x2="10" y2="17"></line>
1438
+ <line x1="14" y1="11" x2="14" y2="17"></line>
1439
+ </svg>
1440
+ `),
1441
+ action: () => this.onDeleteNode()
1442
+ }
1443
+ ];
1444
+ }
1445
+ onDeleteNode() {
1446
+ this.deleteNode.emit();
1447
+ }
1448
+ onLinkNode() {
1449
+ this.linkNode.emit();
1450
+ }
1451
+ trackById(index, item) {
1452
+ return item.id;
1453
+ }
1454
+ }
1455
+ NodeActionToolbarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeActionToolbarComponent, deps: [{ token: i1$3.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
1456
+ NodeActionToolbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NodeActionToolbarComponent, selector: "node-action-toolbar", inputs: { isVisible: "isVisible", position: "position" }, outputs: { deleteNode: "deleteNode", linkNode: "linkNode" }, ngImport: i0, template: "<div \r\n class=\"node-action-toolbar\" \r\n [class.visible]=\"isVisible\"\r\n [style.left.px]=\"position.x\"\r\n [style.top.px]=\"position.y\">\r\n <ng-container *ngFor=\"let action of toolbarActions; trackBy: trackById\">\r\n <button\r\n type=\"button\"\r\n class=\"toolbar-action-btn\"\r\n [class.delete-btn]=\"action.id === 'delete'\"\r\n [attr.aria-label]=\"action.label\"\r\n [matTooltip]=\"action.label\"\r\n matTooltipPosition=\"above\"\r\n (click)=\"action.action()\">\r\n <div [innerHTML]=\"action.svg\"></div>\r\n </button>\r\n </ng-container>\r\n</div>\r\n", styles: [".node-action-toolbar{position:absolute;display:flex;flex-direction:row;gap:.25rem;padding:.35rem;background:white;border-radius:6px;box-shadow:0 2px 8px #0000001a;border:1px solid #d8d8d8;z-index:1000;opacity:0;visibility:hidden;transform:translateY(10px);transition:all .2s ease;pointer-events:none}.node-action-toolbar.visible{opacity:1;visibility:visible;transform:translateY(0);pointer-events:auto}.node-action-toolbar .toolbar-action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:4px;background:#f6f8fa;color:#586069;cursor:pointer;transition:all .15s ease}.node-action-toolbar .toolbar-action-btn:hover{background:#e1e4e8;color:#24292e;transform:scale(1.05)}.node-action-toolbar .toolbar-action-btn:active{transform:scale(.95)}.node-action-toolbar .toolbar-action-btn.delete-btn:hover{background:rgba(244,67,54,.1);color:#f44336}.node-action-toolbar .toolbar-action-btn div{display:flex;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeActionToolbarComponent, decorators: [{
1458
+ type: Component,
1459
+ args: [{ selector: 'node-action-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div \r\n class=\"node-action-toolbar\" \r\n [class.visible]=\"isVisible\"\r\n [style.left.px]=\"position.x\"\r\n [style.top.px]=\"position.y\">\r\n <ng-container *ngFor=\"let action of toolbarActions; trackBy: trackById\">\r\n <button\r\n type=\"button\"\r\n class=\"toolbar-action-btn\"\r\n [class.delete-btn]=\"action.id === 'delete'\"\r\n [attr.aria-label]=\"action.label\"\r\n [matTooltip]=\"action.label\"\r\n matTooltipPosition=\"above\"\r\n (click)=\"action.action()\">\r\n <div [innerHTML]=\"action.svg\"></div>\r\n </button>\r\n </ng-container>\r\n</div>\r\n", styles: [".node-action-toolbar{position:absolute;display:flex;flex-direction:row;gap:.25rem;padding:.35rem;background:white;border-radius:6px;box-shadow:0 2px 8px #0000001a;border:1px solid #d8d8d8;z-index:1000;opacity:0;visibility:hidden;transform:translateY(10px);transition:all .2s ease;pointer-events:none}.node-action-toolbar.visible{opacity:1;visibility:visible;transform:translateY(0);pointer-events:auto}.node-action-toolbar .toolbar-action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:4px;background:#f6f8fa;color:#586069;cursor:pointer;transition:all .15s ease}.node-action-toolbar .toolbar-action-btn:hover{background:#e1e4e8;color:#24292e;transform:scale(1.05)}.node-action-toolbar .toolbar-action-btn:active{transform:scale(.95)}.node-action-toolbar .toolbar-action-btn.delete-btn:hover{background:rgba(244,67,54,.1);color:#f44336}.node-action-toolbar .toolbar-action-btn div{display:flex;align-items:center;justify-content:center}\n"] }]
1460
+ }], ctorParameters: function () { return [{ type: i1$3.DomSanitizer }]; }, propDecorators: { isVisible: [{
1461
+ type: Input
1462
+ }], position: [{
1463
+ type: Input
1464
+ }], deleteNode: [{
1465
+ type: Output
1466
+ }], linkNode: [{
1467
+ type: Output
1468
+ }] } });
1469
+
1470
+ class NodeSearchPanelComponent {
1471
+ constructor() {
1472
+ this.searchChange = new EventEmitter();
1473
+ this.selectNodeChange = new EventEmitter();
1474
+ }
1475
+ ngOnInit() {
1476
+ this.filteredNodes = this.nodes;
1477
+ }
1478
+ onSearchChange(event) {
1479
+ const value = event.target.value.trim().toLowerCase();
1480
+ if (!value) {
1481
+ this.filteredNodes = this.nodes.slice();
1482
+ return;
1483
+ }
1484
+ this.filteredNodes = this.nodes
1485
+ .filter(node => node.name?.toLowerCase().includes(value) ||
1486
+ node.wxccActivityName?.toLowerCase().includes(value) ||
1487
+ node.uccxTypeName?.toLowerCase().includes(value) ||
1488
+ node.wxccGroup?.toLowerCase().includes(value) ||
1489
+ node.uccxDisplayType?.toLowerCase().includes(value));
1490
+ }
1491
+ onSelectNodeChange(event) {
1492
+ const target = event.target;
1493
+ const id = target.id;
1494
+ this.selectNodeChange.emit(id);
1495
+ }
1496
+ }
1497
+ NodeSearchPanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeSearchPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1498
+ NodeSearchPanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NodeSearchPanelComponent, selector: "node-search-panel", inputs: { nodes: "nodes" }, outputs: { searchChange: "searchChange", selectNodeChange: "selectNodeChange" }, ngImport: i0, template: "<div class=\"search-panel\">\r\n <div class=\"search-input-wrapper\">\r\n <div class=\"search-icon\">\r\n <img src=\"assets/icons/search.svg\" />\r\n </div>\r\n <input (input)=\"onSearchChange($event)\" type=\"text\" name=\"\" id=\"\" placeholder=\"Search nodes by name, type, variables...\" class=\"search-input\">\r\n </div>\r\n <div class=\"search-results-wrapper\" (click)=\"onSelectNodeChange($event)\">\r\n <div class=\"activity-result-wrapper\" *ngFor=\"let act of filteredNodes\" id=\"{{ act.id }}\">\r\n {{ act.wxccActivityName || act.name }}\r\n </div>\r\n </div>\r\n</div>", styles: [".search-panel{position:absolute;min-width:400px;min-height:400px;max-height:500px;top:1rem;left:1rem;display:flex;flex-direction:column;border-radius:1rem;background-color:#fff}.search-input-wrapper{padding:1rem;position:relative;display:flex;align-items:center;justify-content:center}.search-results-wrapper{padding:1rem;display:flex;flex-direction:column;gap:.25rem;overflow-y:auto}.search-icon{position:absolute;left:1.5rem;display:flex}.search-icon img{width:32px;height:32px}.search-input{border-radius:.5rem;padding:.75rem .75rem .75rem 2.5rem;width:100%}.activity-result-wrapper{padding:1rem;cursor:pointer;background-color:#f1f1f180;border-radius:.5rem}.activity-result-wrapper:hover{background-color:#cbe3ecac}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeSearchPanelComponent, decorators: [{
1500
+ type: Component,
1501
+ args: [{ selector: 'node-search-panel', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"search-panel\">\r\n <div class=\"search-input-wrapper\">\r\n <div class=\"search-icon\">\r\n <img src=\"assets/icons/search.svg\" />\r\n </div>\r\n <input (input)=\"onSearchChange($event)\" type=\"text\" name=\"\" id=\"\" placeholder=\"Search nodes by name, type, variables...\" class=\"search-input\">\r\n </div>\r\n <div class=\"search-results-wrapper\" (click)=\"onSelectNodeChange($event)\">\r\n <div class=\"activity-result-wrapper\" *ngFor=\"let act of filteredNodes\" id=\"{{ act.id }}\">\r\n {{ act.wxccActivityName || act.name }}\r\n </div>\r\n </div>\r\n</div>", styles: [".search-panel{position:absolute;min-width:400px;min-height:400px;max-height:500px;top:1rem;left:1rem;display:flex;flex-direction:column;border-radius:1rem;background-color:#fff}.search-input-wrapper{padding:1rem;position:relative;display:flex;align-items:center;justify-content:center}.search-results-wrapper{padding:1rem;display:flex;flex-direction:column;gap:.25rem;overflow-y:auto}.search-icon{position:absolute;left:1.5rem;display:flex}.search-icon img{width:32px;height:32px}.search-input{border-radius:.5rem;padding:.75rem .75rem .75rem 2.5rem;width:100%}.activity-result-wrapper{padding:1rem;cursor:pointer;background-color:#f1f1f180;border-radius:.5rem}.activity-result-wrapper:hover{background-color:#cbe3ecac}\n"] }]
1502
+ }], propDecorators: { nodes: [{
1503
+ type: Input
1504
+ }], searchChange: [{
1505
+ type: Output
1506
+ }], selectNodeChange: [{
1507
+ type: Output
1508
+ }] } });
1509
+
1510
+ cytoscape.use(dagre);
1511
+ cytoscape.use(nodeHtmlLabel);
1512
+ class WxCCFlowchartComponent {
1513
+ constructor(wxcc2graph,
1514
+ // private readonly cytoscapeViewportService: CytoscapeViewportService,
1515
+ dialog, wxccActivityCreationService, cdr) {
1516
+ this.wxcc2graph = wxcc2graph;
1517
+ this.dialog = dialog;
1518
+ this.wxccActivityCreationService = wxccActivityCreationService;
1519
+ this.cdr = cdr;
1520
+ this.viewReady = false;
1521
+ this.layoutOptions = {
1522
+ name: "dagre",
1523
+ rankDir: "LR",
1524
+ nodeSep: 180,
1525
+ edgeSep: 60,
1526
+ rankSep: 150,
1527
+ animate: true,
1528
+ animationDuration: 500,
1529
+ fit: true
1530
+ };
1531
+ // Sidebar state
1532
+ this.isSidebarOpen = false;
1533
+ this.selectedNodeData = null;
1534
+ // Search panel state
1535
+ this.isSearchPanelVisible = false;
1536
+ this.searchPanelVisible = false;
1537
+ // Node action toolbar state
1538
+ this.isNodeToolbarVisible = false;
1539
+ this.nodeToolbarPosition = { x: 0, y: 0 };
1540
+ // Add node dialog state
1541
+ this.availableNodes = [];
1542
+ // Link node dialog state
1543
+ this.isLinkDialogOpen = false;
1544
+ this.selectedEdgeId = null;
1545
+ this.selectedEdgeDeleteButtonPosition = null;
1546
+ }
1547
+ ngAfterViewInit() {
1548
+ this.viewReady = true;
1549
+ this.tryInit();
1550
+ }
1551
+ ngOnChanges(changes) {
1552
+ if (changes["flowchart"]) {
1553
+ this.tryInit();
1554
+ }
1555
+ }
1556
+ ngOnDestroy() {
1557
+ this.cy?.destroy();
1558
+ this.cy = undefined;
1559
+ }
1560
+ tryInit() {
1561
+ if (!this.viewReady || !this.flowchartContainer || !this.flowchart) {
1562
+ return;
1563
+ }
1564
+ this.init();
1565
+ }
1566
+ init() {
1567
+ const container = this.flowchartContainer.nativeElement;
1568
+ this.cy?.destroy();
1569
+ this.cy = undefined;
1570
+ const elements = [
1571
+ ...this.flowchart.nodes,
1572
+ ...this.flowchart.edges,
1573
+ ];
1574
+ this.cy = cytoscape({
1575
+ container: container,
1576
+ elements: elements,
1577
+ style: this.getStylesheet(),
1578
+ });
1579
+ this.cy.nodeHtmlLabel([
1580
+ {
1581
+ query: "node",
1582
+ halign: "center",
1583
+ valign: "center",
1584
+ halignBox: "center",
1585
+ valignBox: "center",
1586
+ tpl: (data) => getNodeHtmlTemplate(data),
1587
+ },
1588
+ ]);
1589
+ const layout = this.cy?.layout({
1590
+ ...this.layoutOptions,
1591
+ }).run();
1592
+ layout.on("layoutstop", () => {
1593
+ // this.cytoscapeViewportService.resetView(this.cy, this.cy?.elements());
1594
+ });
1595
+ this.setupEventListeners();
1596
+ }
1597
+ get activities() { return this.wxcc2graph.getAllActivities(); }
1598
+ // Toggle search panel visibility
1599
+ toggleSearchPanel() {
1600
+ this.isSearchPanelVisible = !this.isSearchPanelVisible;
1601
+ this.cdr.markForCheck();
1602
+ }
1603
+ setupEventListeners() {
1604
+ // Single tap on node - show only the toolbar (quick actions)
1605
+ this.cy?.on("mouseover", "node", (event) => {
1606
+ const node = event.target;
1607
+ this.selectedNodeData = node.data();
1608
+ // Calculate toolbar position relative to the container
1609
+ this.updateToolbarPosition(node);
1610
+ this.isNodeToolbarVisible = true;
1611
+ this.cdr.detectChanges();
1612
+ });
1613
+ this.cy?.on("tap", "node", (event) => {
1614
+ const node = event.target;
1615
+ this.clearSelectedEdge();
1616
+ this.selectedNodeData = node.data();
1617
+ this.isSidebarOpen = true;
1618
+ // Hide toolbar when sidebar opens
1619
+ this.isNodeToolbarVisible = false;
1620
+ this.cdr.detectChanges();
1621
+ });
1622
+ this.cy?.on("mousemove", "node", (event) => {
1623
+ const node = event.target;
1624
+ this.updateToolbarPosition(node);
1625
+ this.cdr.detectChanges();
1626
+ });
1627
+ // Edge tap - select edge for explicit deletion action
1628
+ this.cy?.on("tap", "edge", (event) => {
1629
+ const edge = event.target;
1630
+ this.isSidebarOpen = false;
1631
+ this.hideNodeToolbar();
1632
+ this.selectedNodeData = null;
1633
+ this.selectedEdgeId = edge.id();
1634
+ edge.select();
1635
+ this.updateSelectedEdgeDeleteButtonPosition();
1636
+ this.cdr.detectChanges();
1637
+ });
1638
+ // Canvas tap - hide toolbar and deselect
1639
+ this.cy?.on("tap", (event) => {
1640
+ if (event.target === this.cy) {
1641
+ this.clearSelectedEdge();
1642
+ this.isSidebarOpen = false;
1643
+ this.hideNodeToolbar();
1644
+ this.selectedNodeData = null;
1645
+ }
1646
+ });
1647
+ // Pan/zoom events - update toolbar position
1648
+ this.cy?.on("pan zoom", () => {
1649
+ if (this.isNodeToolbarVisible && this.selectedNodeData) {
1650
+ const node = this.cy?.getElementById(this.selectedNodeData.id);
1651
+ if (node?.length) {
1652
+ this.updateToolbarPosition(node);
1653
+ }
1654
+ }
1655
+ if (this.selectedEdgeId) {
1656
+ this.updateSelectedEdgeDeleteButtonPosition();
1657
+ }
1658
+ this.cdr.detectChanges();
1659
+ });
1660
+ }
1661
+ updateToolbarPosition(node) {
1662
+ const renderedPosition = node.renderedPosition();
1663
+ const renderedWidth = node.renderedWidth();
1664
+ const renderedHeight = node.renderedHeight();
1665
+ // Position toolbar above the node, centered
1666
+ this.nodeToolbarPosition = {
1667
+ x: renderedPosition.x - 30,
1668
+ y: renderedPosition.y - renderedHeight / 2 - 40, // Above the node
1669
+ };
1670
+ }
1671
+ hideNodeToolbar() {
1672
+ this.isNodeToolbarVisible = false;
1673
+ this.cdr.detectChanges();
1674
+ }
1675
+ getStylesheet() {
1676
+ return StyleConfig;
1677
+ }
1678
+ // ==================== Sidebar Events ====================
1679
+ onCloseSidebar() {
1680
+ this.isSidebarOpen = false;
1681
+ this.hideNodeToolbar();
1682
+ this.selectedNodeData = null;
1683
+ // this.cdr.detectChanges();
1684
+ }
1685
+ onDescriptionChange(description) {
1686
+ if (!this.selectedNodeData || !this.cy)
1687
+ return;
1688
+ const node = this.cy?.getElementById(this.selectedNodeData.id);
1689
+ if (node) {
1690
+ const updatedData = {
1691
+ ...this.selectedNodeData,
1692
+ suggestedProperties: {
1693
+ ...this.selectedNodeData.suggestedProperties,
1694
+ uccxDescription: description,
1695
+ },
1696
+ };
1697
+ this.wxcc2graph.updateActivityData(updatedData);
1698
+ node.data(updatedData);
1699
+ this.selectedNodeData = updatedData;
1700
+ }
1701
+ }
1702
+ onActivityTypeChange(activityType) {
1703
+ if (!this.selectedNodeData || !this.cy)
1704
+ return;
1705
+ const node = this.cy?.getElementById(this.selectedNodeData.id);
1706
+ if (node) {
1707
+ const updatedData = {
1708
+ ...this.selectedNodeData,
1709
+ wxccActivityName: activityType.activityName,
1710
+ wxccGroup: activityType.group,
1711
+ iconUrl: activityType.icon
1712
+ };
1713
+ this.wxcc2graph.updateActivityData(updatedData);
1714
+ node.data(updatedData);
1715
+ this.selectedNodeData = updatedData;
1716
+ }
1717
+ }
1718
+ // ==================== Node Toolbar Events ====================
1719
+ onDeleteNode() {
1720
+ if (!this.selectedNodeData || !this.cy)
1721
+ return;
1722
+ const nodeId = this.selectedNodeData.id;
1723
+ // Remove from service and get affected link IDs
1724
+ const { removedLinkIds } = this.wxcc2graph.removeActivity(nodeId);
1725
+ // Remove edges from cytoscape
1726
+ removedLinkIds.forEach((linkId) => {
1727
+ this.cy?.getElementById(linkId).remove();
1728
+ });
1729
+ // Remove node from cytoscape
1730
+ this.cy?.getElementById(nodeId).remove();
1731
+ // Close sidebar and toolbar
1732
+ this.onCloseSidebar();
1733
+ // Re-run layout
1734
+ this.runLayout();
1735
+ }
1736
+ onDeleteSelectedEdge() {
1737
+ if (!this.selectedEdgeId || !this.cy)
1738
+ return;
1739
+ const edgeId = this.selectedEdgeId;
1740
+ const removed = this.wxcc2graph.removeLink(edgeId);
1741
+ if (!removed)
1742
+ return;
1743
+ this.cy?.getElementById(edgeId).remove();
1744
+ this.selectedEdgeId = null;
1745
+ this.selectedEdgeDeleteButtonPosition = null;
1746
+ this.cdr.detectChanges();
1747
+ }
1748
+ onLinkNodeRequest() {
1749
+ if (!this.selectedNodeData || !this.cy)
1750
+ return;
1751
+ const sourceNode = this.selectedNodeData;
1752
+ if (!this.canCreateOutgoingLink(sourceNode.id)) {
1753
+ return;
1754
+ }
1755
+ // Get the cytoscape node to inspect existing connections
1756
+ const cyNode = this.cy?.getElementById(sourceNode.id);
1757
+ // Collect IDs of nodes already connected as targets from this source
1758
+ const existingTargetIds = new Set(cyNode.outgoers('node').map((n) => n.id()));
1759
+ // Build the filtered list of linkable targets:
1760
+ // - Never allow the start node (NewPhoneContact) as a target
1761
+ // - Exclude the source node itself
1762
+ // - Exclude nodes already linked as targets from this source
1763
+ this.availableNodes = this.wxcc2graph.getAllActivities().filter(act => act.id !== sourceNode.id &&
1764
+ act.wxccActivityName !== 'NewPhoneContact' &&
1765
+ !existingTargetIds.has(act.id));
1766
+ const dialogRef = this.dialog.open(LinkNodeDialogComponent, {
1767
+ panelClass: "no-padding-modal",
1768
+ width: "550px",
1769
+ data: {
1770
+ availableNodes: this.availableNodes,
1771
+ sourceNode: this.selectedNodeData,
1772
+ },
1773
+ });
1774
+ dialogRef.afterClosed().subscribe((result) => {
1775
+ if (result) {
1776
+ this.onLinkNodes(result);
1777
+ }
1778
+ });
1779
+ }
1780
+ // ==================== Link Dialog Events ====================
1781
+ onLinkNodes(linkData) {
1782
+ if (!this.cy)
1783
+ return;
1784
+ if (!this.canCreateOutgoingLink(linkData.sourceNodeId)) {
1785
+ return;
1786
+ }
1787
+ if (this.wxcc2graph.linkExists(linkData.sourceNodeId, linkData.targetNodeId)) {
1788
+ console.warn("Link already exists between these nodes");
1789
+ return;
1790
+ }
1791
+ const edge = this.wxcc2graph.addLink(linkData.sourceNodeId, linkData.targetNodeId, linkData.label);
1792
+ this.cy?.add(edge);
1793
+ this.runLayout();
1794
+ }
1795
+ // ==================== Add Node Dialog Events ====================
1796
+ openAddNodeDialog() {
1797
+ this.availableNodes = this.wxcc2graph.getAllActivities();
1798
+ const dialogRef = this.dialog.open(AddNodeDialogComponent, {
1799
+ panelClass: "no-padding-modal",
1800
+ width: '450px',
1801
+ data: {
1802
+ availableNodes: this.availableNodes,
1803
+ },
1804
+ });
1805
+ dialogRef.afterClosed().subscribe((result) => {
1806
+ if (result) {
1807
+ this.addActivity(result);
1808
+ }
1809
+ });
1810
+ }
1811
+ addActivity(newNodeData) {
1812
+ if (!this.cy)
1813
+ return;
1814
+ const node = this.wxccActivityCreationService.createAndSync({
1815
+ activityTypeName: newNodeData.activityTypeName,
1816
+ name: newNodeData.name
1817
+ });
1818
+ // Add node to cytoscape
1819
+ this.cy?.add({
1820
+ group: "nodes",
1821
+ data: node.data
1822
+ });
1823
+ // Re-run layout to position the new node
1824
+ this.runLayout();
1825
+ }
1826
+ onNodeSelectChange(id) {
1827
+ const node = this.cy?.getElementById(id);
1828
+ if (node) {
1829
+ this.cy?.center(node);
1830
+ // Set highlighted property in node data
1831
+ const originalData = node.data();
1832
+ node.data({ ...originalData, highlighted: true });
1833
+ node.emit('data');
1834
+ // Remove highlight after 1s
1835
+ setTimeout(() => {
1836
+ const currentData = node.data();
1837
+ if (currentData.highlighted) {
1838
+ // Remove the property completely
1839
+ delete currentData.highlighted;
1840
+ node.data(currentData);
1841
+ node.emit('data');
1842
+ }
1843
+ }, 1000);
1844
+ }
1845
+ }
1846
+ zoomIn() {
1847
+ // this.cytoscapeViewportService.zoomIn(this.cy);
1848
+ }
1849
+ zoomOut() {
1850
+ // this.cytoscapeViewportService.zoomOut(this.cy);
1851
+ }
1852
+ resetView() {
1853
+ // this.cytoscapeViewportService.resetView(this.cy, this.cy?.elements());
1854
+ }
1855
+ runLayout() {
1856
+ if (!this.cy)
1857
+ return;
1858
+ const layout = this.cy?.layout({
1859
+ ...this.layoutOptions,
1860
+ }).run();
1861
+ layout.on("layoutstop", () => {
1862
+ // this.cytoscapeViewportService.resetView(this.cy, this.cy?.elements());
1863
+ });
1864
+ }
1865
+ canCreateOutgoingLink(sourceNodeId) {
1866
+ if (!this.cy)
1867
+ return false;
1868
+ const cyNode = this.cy?.getElementById(sourceNodeId);
1869
+ if (!cyNode || cyNode.length === 0)
1870
+ return false;
1871
+ const sourceActivity = cyNode.data().wxccActivityName;
1872
+ const outgoingEdgeCount = cyNode.outgoers('edge').length;
1873
+ // End-type nodes cannot have outgoing links.
1874
+ const END_NODE_TYPES = ['end', 'disconnect-contact', 'blind-transfer'];
1875
+ if (END_NODE_TYPES.includes(sourceActivity))
1876
+ return false;
1877
+ // Start node can only have one output.
1878
+ if (sourceActivity === 'NewPhoneContact' && outgoingEdgeCount >= 1)
1879
+ return false;
1880
+ // Condition node can only have true/false outputs.
1881
+ if (sourceActivity === 'condition-activity' && outgoingEdgeCount >= 2)
1882
+ return false;
1883
+ return true;
1884
+ }
1885
+ clearSelectedEdge() {
1886
+ if (!this.selectedEdgeId || !this.cy)
1887
+ return;
1888
+ const edge = this.cy?.getElementById(this.selectedEdgeId);
1889
+ if (edge && edge.length) {
1890
+ edge.unselect();
1891
+ }
1892
+ this.selectedEdgeId = null;
1893
+ this.selectedEdgeDeleteButtonPosition = null;
1894
+ this.cdr.detectChanges();
1895
+ }
1896
+ updateSelectedEdgeDeleteButtonPosition() {
1897
+ if (!this.cy || !this.selectedEdgeId) {
1898
+ this.selectedEdgeDeleteButtonPosition = null;
1899
+ return;
1900
+ }
1901
+ const edge = this.cy?.getElementById(this.selectedEdgeId);
1902
+ if (!edge || edge.length === 0) {
1903
+ this.selectedEdgeDeleteButtonPosition = null;
1904
+ return;
1905
+ }
1906
+ const midpoint = edge.renderedMidpoint();
1907
+ // Slight offset so the icon does not sit exactly on top of the edge line.
1908
+ this.selectedEdgeDeleteButtonPosition = {
1909
+ x: midpoint.x + 12,
1910
+ y: midpoint.y - 12,
1911
+ };
1912
+ }
1913
+ }
1914
+ WxCCFlowchartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartComponent, deps: [{ token: WxCC2GraphService }, { token: i1$2.MatDialog }, { token: WxCCActivityCreationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1915
+ WxCCFlowchartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFlowchartComponent, selector: "wxcc-flowchart", inputs: { flowchart: "flowchart" }, viewQueries: [{ propertyName: "flowchartContainer", first: true, predicate: ["flowchartContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"wxcc-flowchart-container\">\r\n <div #flowchartContainer class=\"flowchart-canvas\"></div>\r\n\r\n <!-- Floating toolbar for viewport controls -->\r\n <graph-floating-toolbar\r\n [visibility]=\"{ export: false }\"\r\n (resetViewChange)=\"resetView()\"\r\n (zoomInChange)=\"zoomIn()\"\r\n (zoomOutChange)=\"zoomOut()\">\r\n </graph-floating-toolbar>\r\n\r\n <!-- Graph Acts -->\r\n <div class=\"graph-actions-wrapper\">\r\n <button\r\n class=\"add-node-btn\"\r\n matTooltip=\"Search workflow\"\r\n matTooltipPosition=\"above\"\r\n (click)=\"toggleSearchPanel()\"\r\n >\r\n <img src=\"assets/wxcc/search.svg\" width=\"28\" height=\"28\" alt=\"\" />\r\n </button>\r\n <button\r\n class=\"add-node-btn\"\r\n matTooltip=\"Add New Node\"\r\n matTooltipPosition=\"above\"\r\n (click)=\"openAddNodeDialog()\"\r\n >\r\n <svg\r\n width=\"28\"\r\n height=\"28\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n >\r\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\r\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <button\r\n *ngIf=\"selectedEdgeId && selectedEdgeDeleteButtonPosition\"\r\n class=\"edge-delete-btn\"\r\n matTooltip=\"Delete this edge\"\r\n matTooltipPosition=\"above\"\r\n [style.left.px]=\"selectedEdgeDeleteButtonPosition.x\"\r\n [style.top.px]=\"selectedEdgeDeleteButtonPosition.y\"\r\n (click)=\"onDeleteSelectedEdge()\"\r\n type=\"button\"\r\n aria-label=\"Delete selected edge\"\r\n >\r\n \u00D7\r\n </button>\r\n\r\n <node-search-panel\r\n class=\"fade-in-search-panel\"\r\n [class.visible]=\"isSearchPanelVisible\"\r\n [nodes]=\"activities\"\r\n (selectNodeChange)=\"onNodeSelectChange($event)\"\r\n (searchChange)=\"openAddNodeDialog()\"\r\n >\r\n </node-search-panel>\r\n\r\n <!-- Node action toolbar (floating near selected node) -->\r\n <node-action-toolbar\r\n [isVisible]=\"isNodeToolbarVisible\"\r\n [position]=\"nodeToolbarPosition\"\r\n (deleteNode)=\"onDeleteNode()\"\r\n (linkNode)=\"onLinkNodeRequest()\"\r\n >\r\n </node-action-toolbar>\r\n\r\n <!-- Node details sidebar -->\r\n <node-details-sidebar\r\n [isOpen]=\"isSidebarOpen\"\r\n [nodeData]=\"selectedNodeData\"\r\n (close)=\"onCloseSidebar()\"\r\n (descriptionChange)=\"onDescriptionChange($event)\"\r\n (activityTypeChange)=\"onActivityTypeChange($event)\"\r\n >\r\n </node-details-sidebar>\r\n</div>\r\n", styles: [".fade-in-search-panel{position:absolute;top:0;left:0;right:0;margin:0 auto;z-index:1000;opacity:0;pointer-events:none;transform:translateY(-40px);transition:opacity .4s cubic-bezier(.4,0,.2,1),transform .4s cubic-bezier(.4,0,.2,1)}.fade-in-search-panel.visible{opacity:1;pointer-events:auto;transform:translateY(0)}.close-search-panel{position:absolute;top:10px;right:16px;background:transparent;border:none;font-size:2rem;color:#333;cursor:pointer;z-index:1100}:host ::ng-deep .node-content.highlighted{border-radius:10px;z-index:10}:host ::ng-deep .node-content.highlighted{position:relative;z-index:10}:host ::ng-deep .node-content.highlighted:after{content:\"\";position:absolute;inset:-14px;border:4px solid rgba(110,110,110,.4705882353);border-radius:13px;pointer-events:none;opacity:1}:host ::ng-deep .node-content:not(.highlighted):after{opacity:0}:host{display:block;overflow:hidden;width:100%;height:100%}.wxcc-flowchart-container{display:flex;flex-direction:column;position:relative;background-color:#f8f9fa;border-radius:.5rem;border:1px solid #e1e4e8;box-sizing:border-box;height:100%}.wxcc-flowchart-container .flowchart-canvas{height:100%;background:linear-gradient(90deg,rgba(200,200,200,.1) 1px,transparent 1px),linear-gradient(rgba(200,200,200,.1) 1px,transparent 1px);background-size:20px 20px}.wxcc-flowchart-container .add-node-btn{outline:none;border:none;border-radius:.5rem;background-color:#f6f6f6;padding:.5rem;cursor:pointer;font-size:1rem;display:flex;align-items:center;justify-content:center;width:40px;height:40px;transition:all .2s ease}.wxcc-flowchart-container .add-node-btn:hover{background-color:#eefff8;transform:scale(1.05)}.wxcc-flowchart-container .add-node-btn:active{transform:scale(.95)}.edge-delete-btn{position:absolute;z-index:1100;transform:translate(-50%,-50%);width:24px;height:24px;border-radius:50%;border:1px solid #cc3d36;background:#fff;color:#cc3d36;font-size:16px;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px #0000002e}.edge-delete-btn:hover{background:#fff1f0;transform:translate(-50%,-50%) scale(1.08)}.edge-delete-btn:active{transform:translate(-50%,-50%) scale(.95)}:host ::ng-deep .node-content{cursor:pointer;display:flex;justify-content:center;flex-direction:column;gap:.5rem;padding:.5rem;background:white;border-radius:6px;border:1px solid #d8d8d8;border-left:4px solid;min-width:200px;transition:all .2s ease}:host ::ng-deep .node-content header{display:flex;align-items:center;gap:.5rem}:host ::ng-deep .node-content img{width:18px;height:18px}:host ::ng-deep .node-content .node-icon{font-size:24px;display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:.5rem;flex-shrink:0}:host ::ng-deep .node-content .node-info{flex:1;min-width:0}:host ::ng-deep .node-content .node-info .node-label{font-size:16px;letter-spacing:.5px;opacity:.7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}:host ::ng-deep .node-content .node-info .node-activity-name{font-size:12px;color:#99a5b1;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}:host ::ng-deep .node-content .node-details{font-size:12px;color:#000;padding:0 .25rem;display:flex;flex-direction:column;gap:.25rem}:host ::ng-deep .node-content .node-details .node-details-item{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}:host ::ng-deep .node-content .node-details .review-red{background-color:#ffe6e6;border-left-color:#f44336;color:#f44336;padding:.1rem .25rem;border-radius:.25rem;font-size:10px}:host ::ng-deep .node-content .node-details .review-green{background-color:#e6ffe6;border-left-color:#4caf50;color:#4caf50;padding:.1rem .25rem;border-radius:.25rem;font-size:10px}:host ::ng-deep .node-content .node-details .review-yellow{background-color:#fff9e6;border-left-color:#ff9800;color:#ff9800;padding:.1rem .25rem;border-radius:.25rem;font-size:10px}:host ::ng-deep .node-content.node-start{border-left-color:#4caf50}:host ::ng-deep .node-content.node-start .node-icon{background-color:#4caf501a;color:#4caf50}:host ::ng-deep .node-content.node-start .node-label{color:#4caf50}:host ::ng-deep .node-content.node-end{border-left-color:#f44336}:host ::ng-deep .node-content.node-end .node-icon{background-color:#f443361a;color:#f44336}:host ::ng-deep .node-content.node-end .node-label{color:#f44336}:host ::ng-deep .node-content.node-gateway{border-left-color:#ff9800}:host ::ng-deep .node-content.node-gateway .node-icon{background-color:#ff98001a;color:#ff9800}:host ::ng-deep .node-content.node-gateway .node-label{color:#ff9800}:host ::ng-deep .node-content.node-action{border-left-color:#9c27b0}:host ::ng-deep .node-content.node-action .node-icon{background-color:#9c27b01a;color:#9c27b0}:host ::ng-deep .node-content.node-action .node-label{color:#9c27b0}:host ::ng-deep .node-content.node-default{border-left-color:#607d8b}:host ::ng-deep .node-content.node-default .node-icon{background-color:#607d8b1a;color:#607d8b}:host ::ng-deep .node-content.node-default .node-label{color:#607d8b}.graph-actions-wrapper{position:absolute;right:1rem;top:1rem;display:flex;align-items:center;gap:.5rem;box-shadow:2px 4px 15px #0000002d;padding:8px;background-color:#ffffffac;border-radius:1rem;z-index:999}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: FloatingToolBarComponent, selector: "graph-floating-toolbar", inputs: ["visibility"], outputs: ["resetViewChange", "zoomInChange", "zoomOutChange", "exportImageChange"] }, { kind: "component", type: NodeDetailsSidebarComponent, selector: "node-details-sidebar", inputs: ["isOpen", "nodeData"], outputs: ["close", "activityTypeChange", "descriptionChange"] }, { kind: "component", type: NodeActionToolbarComponent, selector: "node-action-toolbar", inputs: ["isVisible", "position"], outputs: ["deleteNode", "linkNode"] }, { kind: "component", type: NodeSearchPanelComponent, selector: "node-search-panel", inputs: ["nodes"], outputs: ["searchChange", "selectNodeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1916
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartComponent, decorators: [{
1917
+ type: Component,
1918
+ args: [{ selector: "wxcc-flowchart", changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"wxcc-flowchart-container\">\r\n <div #flowchartContainer class=\"flowchart-canvas\"></div>\r\n\r\n <!-- Floating toolbar for viewport controls -->\r\n <graph-floating-toolbar\r\n [visibility]=\"{ export: false }\"\r\n (resetViewChange)=\"resetView()\"\r\n (zoomInChange)=\"zoomIn()\"\r\n (zoomOutChange)=\"zoomOut()\">\r\n </graph-floating-toolbar>\r\n\r\n <!-- Graph Acts -->\r\n <div class=\"graph-actions-wrapper\">\r\n <button\r\n class=\"add-node-btn\"\r\n matTooltip=\"Search workflow\"\r\n matTooltipPosition=\"above\"\r\n (click)=\"toggleSearchPanel()\"\r\n >\r\n <img src=\"assets/wxcc/search.svg\" width=\"28\" height=\"28\" alt=\"\" />\r\n </button>\r\n <button\r\n class=\"add-node-btn\"\r\n matTooltip=\"Add New Node\"\r\n matTooltipPosition=\"above\"\r\n (click)=\"openAddNodeDialog()\"\r\n >\r\n <svg\r\n width=\"28\"\r\n height=\"28\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n >\r\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\r\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <button\r\n *ngIf=\"selectedEdgeId && selectedEdgeDeleteButtonPosition\"\r\n class=\"edge-delete-btn\"\r\n matTooltip=\"Delete this edge\"\r\n matTooltipPosition=\"above\"\r\n [style.left.px]=\"selectedEdgeDeleteButtonPosition.x\"\r\n [style.top.px]=\"selectedEdgeDeleteButtonPosition.y\"\r\n (click)=\"onDeleteSelectedEdge()\"\r\n type=\"button\"\r\n aria-label=\"Delete selected edge\"\r\n >\r\n \u00D7\r\n </button>\r\n\r\n <node-search-panel\r\n class=\"fade-in-search-panel\"\r\n [class.visible]=\"isSearchPanelVisible\"\r\n [nodes]=\"activities\"\r\n (selectNodeChange)=\"onNodeSelectChange($event)\"\r\n (searchChange)=\"openAddNodeDialog()\"\r\n >\r\n </node-search-panel>\r\n\r\n <!-- Node action toolbar (floating near selected node) -->\r\n <node-action-toolbar\r\n [isVisible]=\"isNodeToolbarVisible\"\r\n [position]=\"nodeToolbarPosition\"\r\n (deleteNode)=\"onDeleteNode()\"\r\n (linkNode)=\"onLinkNodeRequest()\"\r\n >\r\n </node-action-toolbar>\r\n\r\n <!-- Node details sidebar -->\r\n <node-details-sidebar\r\n [isOpen]=\"isSidebarOpen\"\r\n [nodeData]=\"selectedNodeData\"\r\n (close)=\"onCloseSidebar()\"\r\n (descriptionChange)=\"onDescriptionChange($event)\"\r\n (activityTypeChange)=\"onActivityTypeChange($event)\"\r\n >\r\n </node-details-sidebar>\r\n</div>\r\n", styles: [".fade-in-search-panel{position:absolute;top:0;left:0;right:0;margin:0 auto;z-index:1000;opacity:0;pointer-events:none;transform:translateY(-40px);transition:opacity .4s cubic-bezier(.4,0,.2,1),transform .4s cubic-bezier(.4,0,.2,1)}.fade-in-search-panel.visible{opacity:1;pointer-events:auto;transform:translateY(0)}.close-search-panel{position:absolute;top:10px;right:16px;background:transparent;border:none;font-size:2rem;color:#333;cursor:pointer;z-index:1100}:host ::ng-deep .node-content.highlighted{border-radius:10px;z-index:10}:host ::ng-deep .node-content.highlighted{position:relative;z-index:10}:host ::ng-deep .node-content.highlighted:after{content:\"\";position:absolute;inset:-14px;border:4px solid rgba(110,110,110,.4705882353);border-radius:13px;pointer-events:none;opacity:1}:host ::ng-deep .node-content:not(.highlighted):after{opacity:0}:host{display:block;overflow:hidden;width:100%;height:100%}.wxcc-flowchart-container{display:flex;flex-direction:column;position:relative;background-color:#f8f9fa;border-radius:.5rem;border:1px solid #e1e4e8;box-sizing:border-box;height:100%}.wxcc-flowchart-container .flowchart-canvas{height:100%;background:linear-gradient(90deg,rgba(200,200,200,.1) 1px,transparent 1px),linear-gradient(rgba(200,200,200,.1) 1px,transparent 1px);background-size:20px 20px}.wxcc-flowchart-container .add-node-btn{outline:none;border:none;border-radius:.5rem;background-color:#f6f6f6;padding:.5rem;cursor:pointer;font-size:1rem;display:flex;align-items:center;justify-content:center;width:40px;height:40px;transition:all .2s ease}.wxcc-flowchart-container .add-node-btn:hover{background-color:#eefff8;transform:scale(1.05)}.wxcc-flowchart-container .add-node-btn:active{transform:scale(.95)}.edge-delete-btn{position:absolute;z-index:1100;transform:translate(-50%,-50%);width:24px;height:24px;border-radius:50%;border:1px solid #cc3d36;background:#fff;color:#cc3d36;font-size:16px;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px #0000002e}.edge-delete-btn:hover{background:#fff1f0;transform:translate(-50%,-50%) scale(1.08)}.edge-delete-btn:active{transform:translate(-50%,-50%) scale(.95)}:host ::ng-deep .node-content{cursor:pointer;display:flex;justify-content:center;flex-direction:column;gap:.5rem;padding:.5rem;background:white;border-radius:6px;border:1px solid #d8d8d8;border-left:4px solid;min-width:200px;transition:all .2s ease}:host ::ng-deep .node-content header{display:flex;align-items:center;gap:.5rem}:host ::ng-deep .node-content img{width:18px;height:18px}:host ::ng-deep .node-content .node-icon{font-size:24px;display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:.5rem;flex-shrink:0}:host ::ng-deep .node-content .node-info{flex:1;min-width:0}:host ::ng-deep .node-content .node-info .node-label{font-size:16px;letter-spacing:.5px;opacity:.7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}:host ::ng-deep .node-content .node-info .node-activity-name{font-size:12px;color:#99a5b1;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}:host ::ng-deep .node-content .node-details{font-size:12px;color:#000;padding:0 .25rem;display:flex;flex-direction:column;gap:.25rem}:host ::ng-deep .node-content .node-details .node-details-item{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}:host ::ng-deep .node-content .node-details .review-red{background-color:#ffe6e6;border-left-color:#f44336;color:#f44336;padding:.1rem .25rem;border-radius:.25rem;font-size:10px}:host ::ng-deep .node-content .node-details .review-green{background-color:#e6ffe6;border-left-color:#4caf50;color:#4caf50;padding:.1rem .25rem;border-radius:.25rem;font-size:10px}:host ::ng-deep .node-content .node-details .review-yellow{background-color:#fff9e6;border-left-color:#ff9800;color:#ff9800;padding:.1rem .25rem;border-radius:.25rem;font-size:10px}:host ::ng-deep .node-content.node-start{border-left-color:#4caf50}:host ::ng-deep .node-content.node-start .node-icon{background-color:#4caf501a;color:#4caf50}:host ::ng-deep .node-content.node-start .node-label{color:#4caf50}:host ::ng-deep .node-content.node-end{border-left-color:#f44336}:host ::ng-deep .node-content.node-end .node-icon{background-color:#f443361a;color:#f44336}:host ::ng-deep .node-content.node-end .node-label{color:#f44336}:host ::ng-deep .node-content.node-gateway{border-left-color:#ff9800}:host ::ng-deep .node-content.node-gateway .node-icon{background-color:#ff98001a;color:#ff9800}:host ::ng-deep .node-content.node-gateway .node-label{color:#ff9800}:host ::ng-deep .node-content.node-action{border-left-color:#9c27b0}:host ::ng-deep .node-content.node-action .node-icon{background-color:#9c27b01a;color:#9c27b0}:host ::ng-deep .node-content.node-action .node-label{color:#9c27b0}:host ::ng-deep .node-content.node-default{border-left-color:#607d8b}:host ::ng-deep .node-content.node-default .node-icon{background-color:#607d8b1a;color:#607d8b}:host ::ng-deep .node-content.node-default .node-label{color:#607d8b}.graph-actions-wrapper{position:absolute;right:1rem;top:1rem;display:flex;align-items:center;gap:.5rem;box-shadow:2px 4px 15px #0000002d;padding:8px;background-color:#ffffffac;border-radius:1rem;z-index:999}\n"] }]
1919
+ }], ctorParameters: function () { return [{ type: WxCC2GraphService }, { type: i1$2.MatDialog }, { type: WxCCActivityCreationService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { flowchart: [{
1920
+ type: Input
1921
+ }], flowchartContainer: [{
1922
+ type: ViewChild,
1923
+ args: ["flowchartContainer"]
1924
+ }] } });
1925
+
1926
+ const BASE = '/api/uccx/migration';
1927
+ function buildUrl(customerId, uccxIp, fileName, action, state, format) {
1928
+ return `${BASE}/customer/${customerId}/uccx/${uccxIp}/filename/${fileName}/${action}/type/${state}/wxcc${format ? '/ir' : ''}/json`;
1929
+ }
1930
+ /**
1931
+ * Any WxCC flowchart api endpoint should go here
1932
+ */
1933
+ const WXCC_FLOWCHART_API = {
1934
+ GET_DATA: (params, state = 'ORIG', format) => buildUrl(params.customerId, params.uccxIp, params.fileName, 'get', state, format),
1935
+ SAVE_DRAFT: (params, format) => buildUrl(params.customerId, params.uccxIp, params.fileName, 'save', 'DRAFT', format),
1936
+ RESET_DRAFT: (params, format) => `${BASE}/customer/${params.customerId}/uccx/${params.uccxIp}/filename/${params.fileName}${format ? '' : '/wxcc'}/reset/draft`,
1937
+ COMPLETE_FLOW: (params, format) => buildUrl(params.customerId, params.uccxIp, params.fileName, 'save', 'COMPLETED', format)
1938
+ };
1939
+
1940
+ class WxCCAPIService {
1941
+ constructor(api) {
1942
+ this.api = api;
1943
+ }
1944
+ /**
1945
+ * Fetch original WXCC flow data
1946
+ */
1947
+ fetchWxCCFlowData(params, state = 'ORIG') {
1948
+ const url = WXCC_FLOWCHART_API.GET_DATA(params, state);
1949
+ // @ts-ignore
1950
+ return this.api.fetch(url);
1951
+ }
1952
+ /**
1953
+ * Fetch original WXCC flow data as IR format
1954
+ */
1955
+ fetchWxCCFlowDataIR(params, state = 'ORIG') {
1956
+ const url = WXCC_FLOWCHART_API.GET_DATA(params, state, 'ir');
1957
+ // @ts-ignore
1958
+ return this.api.fetch(url);
1959
+ }
1960
+ /**
1961
+ * Save WXCC flow data as DRAFT
1962
+ */
1963
+ saveWxCCFlowData(params, data) {
1964
+ const url = WXCC_FLOWCHART_API.SAVE_DRAFT(params);
1965
+ // @ts-ignore
1966
+ return this.api.post(url, data);
1967
+ }
1968
+ /**
1969
+ * Save WXCC flow data as DRAFT in IR format
1970
+ */
1971
+ saveWxCCFlowDataIR(params, data) {
1972
+ const url = WXCC_FLOWCHART_API.SAVE_DRAFT(params, 'ir');
1973
+ // @ts-ignore
1974
+ return this.api.post(url, data);
1975
+ }
1976
+ /**
1977
+ * Reset to original WXCC flow data
1978
+ */
1979
+ resetWxCCFlowData(params) {
1980
+ const url = WXCC_FLOWCHART_API.RESET_DRAFT(params);
1981
+ // @ts-ignore
1982
+ return this.api.post(url);
1983
+ }
1984
+ /**
1985
+ * Reset to original WXCC flow data in IR format
1986
+ */
1987
+ resetWxCCFlowDataIR(params) {
1988
+ const url = WXCC_FLOWCHART_API.RESET_DRAFT(params, 'ir');
1989
+ // @ts-ignore
1990
+ return this.api.post(url);
1991
+ }
1992
+ /**
1993
+ * Save WXCC flow data as COMPLETED
1994
+ */
1995
+ completeWxCCFlowData(params, data) {
1996
+ const url = WXCC_FLOWCHART_API.COMPLETE_FLOW(params);
1997
+ // @ts-ignore
1998
+ return this.api.post(url, data);
1999
+ }
2000
+ /**
2001
+ * Save WXCC flow data as COMPLETED in IR format
2002
+ */
2003
+ completeWxCCFlowDataIR(params, data) {
2004
+ const url = WXCC_FLOWCHART_API.COMPLETE_FLOW(params, 'ir');
2005
+ // @ts-ignore
2006
+ return this.api.post(url, data);
2007
+ }
2008
+ }
2009
+ WxCCAPIService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCAPIService, deps: [{ token: APIService }], target: i0.ɵɵFactoryTarget.Injectable });
2010
+ WxCCAPIService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCAPIService });
2011
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCAPIService, decorators: [{
2012
+ type: Injectable
2013
+ }], ctorParameters: function () { return [{ type: APIService }]; } });
2014
+
2015
+ class WxCCFileSelectionBarComponent {
2016
+ constructor() {
2017
+ this.fileNameSelectionChange = new EventEmitter();
2018
+ this.hostFileNames = new Map();
2019
+ }
2020
+ ngOnInit() {
2021
+ this.fileNames.forEach(({ fileName, host }) => {
2022
+ if (!this.hostFileNames.has(host)) {
2023
+ this.hostFileNames.set(host, []);
2024
+ }
2025
+ this.hostFileNames.get(host)?.push(fileName);
2026
+ });
2027
+ }
2028
+ get fileNamesByHost() {
2029
+ return this.hostFileNames.get(this.selectedHost);
2030
+ }
2031
+ get hosts() {
2032
+ if (!this.fileNames.length) {
2033
+ return null;
2034
+ }
2035
+ const hostsSet = new Set(this.fileNames.map((file) => file.host));
2036
+ return Array.from(hostsSet).filter(host => host);
2037
+ }
2038
+ onFileSelectionChange(fileName) {
2039
+ this.fileNameSelectionChange.emit({ fileName: fileName, host: this.selectedHost });
2040
+ }
2041
+ onHostSelectionChange(host) {
2042
+ this.selectedHost = host;
2043
+ this.fileNameSelectionChange.emit({
2044
+ host: host,
2045
+ fileName: this.fileNamesByHost[0]
2046
+ });
2047
+ }
2048
+ trackByFileName(_index, fileName) {
2049
+ return fileName;
2050
+ }
2051
+ trackByHost(_index, host) {
2052
+ return host;
2053
+ }
2054
+ }
2055
+ WxCCFileSelectionBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFileSelectionBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2056
+ WxCCFileSelectionBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFileSelectionBarComponent, selector: "wxcc-file-selection-bar", inputs: { fileNames: "fileNames", selectedFileName: "selectedFileName", selectedHost: "selectedHost" }, outputs: { fileNameSelectionChange: "fileNameSelectionChange" }, ngImport: i0, template: "<div class=\"file-selection-bar\">\r\n <mat-form-field appearance=\"outline\" class=\"host-selection\" *ngIf=\"hosts?.length\">\r\n <!-- <mat-label>Host</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedHost\"\r\n (selectionChange)=\"onHostSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let host of hosts; trackBy: trackByHost\"\r\n title=\"{{ host }}\"\r\n [value]=\"host\">\r\n {{ host }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"file-selection\">\r\n <!-- <mat-label>Script file</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedFileName\"\r\n (selectionChange)=\"onFileSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let name of fileNamesByHost; trackBy: trackByFileName\"\r\n title=\"{{ name }}\"\r\n [value]=\"name\">\r\n {{ name }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-wrapper{margin:0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{padding:.25rem 0 .5rem}:host ::ng-deep .mat-select-trigger{display:block}:host ::ng-deep .mat-select-trigger .mat-select-arrow-wrapper{transform:none}.file-selection-bar{display:flex;gap:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "component", type: i3.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", exportAs: ["matOption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2057
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFileSelectionBarComponent, decorators: [{
2058
+ type: Component,
2059
+ args: [{ selector: 'wxcc-file-selection-bar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"file-selection-bar\">\r\n <mat-form-field appearance=\"outline\" class=\"host-selection\" *ngIf=\"hosts?.length\">\r\n <!-- <mat-label>Host</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedHost\"\r\n (selectionChange)=\"onHostSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let host of hosts; trackBy: trackByHost\"\r\n title=\"{{ host }}\"\r\n [value]=\"host\">\r\n {{ host }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"file-selection\">\r\n <!-- <mat-label>Script file</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedFileName\"\r\n (selectionChange)=\"onFileSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let name of fileNamesByHost; trackBy: trackByFileName\"\r\n title=\"{{ name }}\"\r\n [value]=\"name\">\r\n {{ name }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-wrapper{margin:0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{padding:.25rem 0 .5rem}:host ::ng-deep .mat-select-trigger{display:block}:host ::ng-deep .mat-select-trigger .mat-select-arrow-wrapper{transform:none}.file-selection-bar{display:flex;gap:1rem}\n"] }]
2060
+ }], propDecorators: { fileNames: [{
2061
+ type: Input
2062
+ }], selectedFileName: [{
2063
+ type: Input
2064
+ }], selectedHost: [{
2065
+ type: Input
2066
+ }], fileNameSelectionChange: [{
2067
+ type: Output
2068
+ }] } });
2069
+
2070
+ class WxCCActionsBarComponent {
2071
+ constructor() {
2072
+ this.save = new EventEmitter();
2073
+ this.reset = new EventEmitter();
2074
+ this.complete = new EventEmitter();
2075
+ this.exportNonIr = new EventEmitter();
2076
+ }
2077
+ ngOnInit() { }
2078
+ }
2079
+ WxCCActionsBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActionsBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2080
+ WxCCActionsBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCActionsBarComponent, selector: "wxcc-actions-bar", outputs: { save: "save", reset: "reset", complete: "complete", exportNonIr: "exportNonIr" }, ngImport: i0, template: "<div class=\"actions-wrapper\">\r\n <button\r\n type=\"button\"\r\n mat-button\r\n class=\"outline-button\"\r\n (click)=\"exportNonIr.emit()\">\r\n Export JSON\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-button\r\n class=\"outline-button\"\r\n (click)=\"reset.emit()\">\r\n Reset\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-button\r\n class=\"outline-button\"\r\n (click)=\"save.emit()\">\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-button\r\n color=\"primary\"\r\n (click)=\"complete.emit()\">\r\n Complete\r\n </button>\r\n</div>", styles: [".actions-wrapper{display:flex;align-items:center;gap:.5rem}.actions-wrapper button.outline-button{border:none!important}\n"], dependencies: [{ kind: "component", type: i1$4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2081
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCActionsBarComponent, decorators: [{
2082
+ type: Component,
2083
+ args: [{ selector: 'wxcc-actions-bar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"actions-wrapper\">\r\n <button\r\n type=\"button\"\r\n mat-button\r\n class=\"outline-button\"\r\n (click)=\"exportNonIr.emit()\">\r\n Export JSON\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-button\r\n class=\"outline-button\"\r\n (click)=\"reset.emit()\">\r\n Reset\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-button\r\n class=\"outline-button\"\r\n (click)=\"save.emit()\">\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-button\r\n color=\"primary\"\r\n (click)=\"complete.emit()\">\r\n Complete\r\n </button>\r\n</div>", styles: [".actions-wrapper{display:flex;align-items:center;gap:.5rem}.actions-wrapper button.outline-button{border:none!important}\n"] }]
2084
+ }], propDecorators: { save: [{
2085
+ type: Output
2086
+ }], reset: [{
2087
+ type: Output
2088
+ }], complete: [{
2089
+ type: Output
2090
+ }], exportNonIr: [{
2091
+ type: Output
2092
+ }] } });
2093
+
2094
+ var activities = [
2095
+ {
2096
+ id: "8c89c876-e556-3c8c-a1be-77b8cfbd3800",
2097
+ name: "Start_0\nStart",
2098
+ review: {
2099
+ color: "green",
2100
+ level: "confident",
2101
+ reasons: [
2102
+ ]
2103
+ },
2104
+ suggestedProperties: {
2105
+ uccxDescription: "Start",
2106
+ uccxComment: "Simple Queuing With Calendar Template",
2107
+ closestWxccActivity: "Start Flow",
2108
+ mappingNotes: "In UCCX voice scripts, callers typically hear ringing until an explicit Accept step executes; in WxCC, the Start Flow event fires when the contact arrives at the Entry Point.",
2109
+ migrationInstructions: "The Start Flow activity appears on the Main Flow canvas by default. You cannot delete the Start Flow activity.\n\nNote: There are certain Output Variables associated with the Start Flow activity depend on the selected Flow Trigger Event. These variables store data that is captured at the moment the flow is triggered.",
2110
+ allAudioFilesInFlow: [
2111
+ "ICD\\ICDQueue.wav",
2112
+ "ICD\\ICDWelcome.wav",
2113
+ "ICDQueue.wav",
2114
+ "ICDWelcome.wav"
2115
+ ]
2116
+ },
2117
+ uccxDisplayType: "Start",
2118
+ uccxTypeName: "Start",
2119
+ uccxWfId: 0,
2120
+ unmappedReason: null,
2121
+ wxccActivityId: "start",
2122
+ wxccActivityName: "NewPhoneContact",
2123
+ wxccGroup: "start"
2124
+ },
2125
+ {
2126
+ id: "c535b5fd-5ab9-323f-b1ac-667f4590d801",
2127
+ name: "End_12\nEnd",
2128
+ review: {
2129
+ color: "green",
2130
+ level: "confident",
2131
+ reasons: [
2132
+ ]
2133
+ },
2134
+ suggestedProperties: {
2135
+ uccxDescription: "End",
2136
+ closestWxccActivity: "End Flow",
2137
+ mappingNotes: "UCCX commonly uses Terminate + End; in Flow Designer, Disconnect Contact + End Flow is the typical pattern.",
2138
+ migrationInstructions: "* Drag and drop the \"End Flow\" Activity to the flow canvas\n* Analyze the UCCX call flow, identify and connect the existing Acvities output branch to the End Flow input.\n\nNote: There is no Output Branch for the End Flow Activity and we can add Multiple End Flow Activity to help with readability of the flow when the flow becomes super big",
2139
+ allAudioFilesInFlow: [
2140
+ "ICD\\ICDQueue.wav",
2141
+ "ICD\\ICDWelcome.wav",
2142
+ "ICDQueue.wav",
2143
+ "ICDWelcome.wav"
2144
+ ]
2145
+ },
2146
+ uccxDisplayType: "End",
2147
+ uccxTypeName: "End",
2148
+ uccxWfId: 12,
2149
+ unmappedReason: null,
2150
+ wxccActivityId: "end",
2151
+ wxccActivityName: "end",
2152
+ wxccGroup: "end"
2153
+ },
2154
+ {
2155
+ id: "78c3dea1-172e-3de9-9c99-3ce92fb4b12e",
2156
+ name: "Play Prompt_16\nPlay Prompt (--Triggering Contact--, WelcomePrompt)",
2157
+ review: {
2158
+ color: "green",
2159
+ level: "confident",
2160
+ reasons: [
2161
+ ]
2162
+ },
2163
+ suggestedProperties: {
2164
+ uccxDescription: "Play Prompt (--Triggering Contact--, WelcomePrompt)",
2165
+ prompt: "WelcomePrompt",
2166
+ closestWxccActivity: "Play Message",
2167
+ mappingNotes: "Flow Designer Play Message supports mixing audio files and TTS in a single activity; UCCX often builds composite prompts using Prompt steps.",
2168
+ migrationInstructions: "* Drag and drop the Play Message Activity to the Canvas\n* Click the \"Play Message\" Activity to update its property\n* We shall either use Text-to-Speech or Choose play using an Audio Prompt(.WAV)\n* For TTS, Toggle the \"Enable Text-to-Speech\" to utilize TTS, if not, Select the Audio File from the dropdown menu.\n* Optionally, we can also create Local Variables to store the Audio File name if we do not want to point the WAV file directly\n\nNote: When using TTS, the TTS Message field accepts two types of input: raw text (plaintext) or SSML-formatted data. You can use variables also as part of the message to read the dynamic content\n\nNote: If customer would like to utilize the existing Prompts from the UCCX, we can go with selecting Auio files or if the customer would like to go with TTS, then we can turn on the TTS but the we have to input the Text that should be converted to Speech.\n\nFor supported SSML tags for Cisco Cloud Text-to-Speech, see the link: https://help.webex.com/en-us/article/ntkjqhw/Text-to-Speech-(TTS)-in-Webex-Contact-Center#reference-template_b6eff334-4963-4685-b1dc-17184aaaa308",
2169
+ uccxKeyFields: [
2170
+ "promptDTMFExpr",
2171
+ "bargeIn",
2172
+ "continueOnPromptErrors",
2173
+ "flushInputBufferFlag"
2174
+ ],
2175
+ uccxKeyFieldExamples: {
2176
+ flushInputBufferFlag: "true",
2177
+ promptDTMFExpr: "P[1161.wav]",
2178
+ bargeIn: "true",
2179
+ continueOnPromptErrors: "true"
2180
+ },
2181
+ allAudioFilesInFlow: [
2182
+ "ICD\\ICDQueue.wav",
2183
+ "ICD\\ICDWelcome.wav",
2184
+ "ICDQueue.wav",
2185
+ "ICDWelcome.wav"
2186
+ ]
2187
+ },
2188
+ uccxDisplayType: "Play Prompt",
2189
+ uccxTypeName: "Play Prompt",
2190
+ uccxWfId: 16,
2191
+ unmappedReason: null,
2192
+ wxccActivityId: "5f114466ef5cfc454fbbf131",
2193
+ wxccActivityName: "play-message",
2194
+ wxccGroup: "action"
2195
+ },
2196
+ {
2197
+ id: "94eb01a7-71de-3b5b-96b5-02c38e29f58f",
2198
+ name: "Accept_43\nAccept (--Triggering Contact--)",
2199
+ review: {
2200
+ color: "red",
2201
+ level: "must_review",
2202
+ reasons: [
2203
+ "Mapper mappingQuality=red (missing WxCC activity identification)",
2204
+ "IR marked activity as unmapped: No mapper entry or missing activityName"
2205
+ ]
2206
+ },
2207
+ suggestedProperties: {
2208
+ uccxDescription: "Accept (--Triggering Contact--)",
2209
+ closestWxccActivity: "Start Flow (implicit accept)",
2210
+ mappingNotes: "When migrating, ensure any UCCX logic that occurs *before Accept* is still valid; in WxCC, the IVR flow starts upon entry point invocation.",
2211
+ migrationInstructions: "The Start Flow activity appears on the Main Flow canvas by default. You cannot delete the Start Flow activity.\n\nNote: There are certain Output Variables associated with the Start Flow activity depend on the selected Flow Trigger Event. These variables store data that is captured at the moment the flow is triggered.",
2212
+ allAudioFilesInFlow: [
2213
+ "ICD\\ICDQueue.wav",
2214
+ "ICD\\ICDWelcome.wav",
2215
+ "ICDQueue.wav",
2216
+ "ICDWelcome.wav"
2217
+ ]
2218
+ },
2219
+ uccxDisplayType: "Accept",
2220
+ uccxTypeName: "Accept",
2221
+ uccxWfId: 43,
2222
+ unmappedReason: "No mapper entry or missing activityName",
2223
+ wxccActivityId: null,
2224
+ wxccActivityName: "unmapped",
2225
+ wxccGroup: "unmapped"
2226
+ },
2227
+ {
2228
+ id: "95c0b5ba-20a8-3062-995f-d01036660cdc",
2229
+ name: "Calendar_54\nCalendar (cal)",
2230
+ review: {
2231
+ color: "green",
2232
+ level: "confident",
2233
+ reasons: [
2234
+ ]
2235
+ },
2236
+ suggestedProperties: {
2237
+ uccxDescription: "Calendar (cal)",
2238
+ calendarVarName: "cal",
2239
+ calendarExpr: "cal",
2240
+ closestWxccActivity: "Business Hours",
2241
+ mappingNotes: "We should create the Business Hours first in the WebEx CC Control Hub so that it can be refferenced inside the Business Hours Activity in Flow Designer.\n\nWe need to ensure the \"\"outConnections\"\" of the Calendar Step in UCCX maps correctly in the \"links\" section of the WxCC JSON to connect to the proper Activities.",
2242
+ migrationInstructions: "* Drag and drop the \"Business Hours\" Activity in the Canvas\n* Click the \"Business Hours\" Activity to update its properties\n* Select the configured Busines Hours schedule in the drop down menu under Schedule Details\n* Connect the below output branches to the appropriate Activity in the flow canvas based on the the call flow\n\n • Key UCCX JSON fields to map with WxCC Activites under the \"link\" to ensure the call flow logic follws the UCCX scorrectly\n\n \"Business Hours\" > workingHours\n \"Holidays\", > holidays\n \"The Rest\", > default\n \"Failure\" > error",
2243
+ allAudioFilesInFlow: [
2244
+ "ICD\\ICDQueue.wav",
2245
+ "ICD\\ICDWelcome.wav",
2246
+ "ICDQueue.wav",
2247
+ "ICDWelcome.wav"
2248
+ ]
2249
+ },
2250
+ uccxDisplayType: "Calendar",
2251
+ uccxTypeName: "Calendar",
2252
+ uccxWfId: 54,
2253
+ unmappedReason: null,
2254
+ wxccActivityId: "business-hours",
2255
+ wxccActivityName: "business-hours",
2256
+ wxccGroup: "enum-gateway"
2257
+ },
2258
+ {
2259
+ id: "30eea40d-78b7-32e3-83c6-94738320acab",
2260
+ name: "Play Prompt_87\nPlay Prompt (--Triggering Contact--, FailurePrompt)",
2261
+ review: {
2262
+ color: "green",
2263
+ level: "confident",
2264
+ reasons: [
2265
+ ]
2266
+ },
2267
+ suggestedProperties: {
2268
+ uccxDescription: "Play Prompt (--Triggering Contact--, FailurePrompt)",
2269
+ prompt: "FailurePrompt",
2270
+ closestWxccActivity: "Play Message",
2271
+ mappingNotes: "Flow Designer Play Message supports mixing audio files and TTS in a single activity; UCCX often builds composite prompts using Prompt steps.",
2272
+ migrationInstructions: "* Drag and drop the Play Message Activity to the Canvas\n* Click the \"Play Message\" Activity to update its property\n* We shall either use Text-to-Speech or Choose play using an Audio Prompt(.WAV)\n* For TTS, Toggle the \"Enable Text-to-Speech\" to utilize TTS, if not, Select the Audio File from the dropdown menu.\n* Optionally, we can also create Local Variables to store the Audio File name if we do not want to point the WAV file directly\n\nNote: When using TTS, the TTS Message field accepts two types of input: raw text (plaintext) or SSML-formatted data. You can use variables also as part of the message to read the dynamic content\n\nNote: If customer would like to utilize the existing Prompts from the UCCX, we can go with selecting Auio files or if the customer would like to go with TTS, then we can turn on the TTS but the we have to input the Text that should be converted to Speech.\n\nFor supported SSML tags for Cisco Cloud Text-to-Speech, see the link: https://help.webex.com/en-us/article/ntkjqhw/Text-to-Speech-(TTS)-in-Webex-Contact-Center#reference-template_b6eff334-4963-4685-b1dc-17184aaaa308",
2273
+ uccxKeyFields: [
2274
+ "promptDTMFExpr",
2275
+ "bargeIn",
2276
+ "continueOnPromptErrors",
2277
+ "flushInputBufferFlag"
2278
+ ],
2279
+ uccxKeyFieldExamples: {
2280
+ flushInputBufferFlag: "true",
2281
+ promptDTMFExpr: "P[1161.wav]",
2282
+ bargeIn: "true",
2283
+ continueOnPromptErrors: "true"
2284
+ },
2285
+ allAudioFilesInFlow: [
2286
+ "ICD\\ICDQueue.wav",
2287
+ "ICD\\ICDWelcome.wav",
2288
+ "ICDQueue.wav",
2289
+ "ICDWelcome.wav"
2290
+ ]
2291
+ },
2292
+ uccxDisplayType: "Play Prompt",
2293
+ uccxTypeName: "Play Prompt",
2294
+ uccxWfId: 87,
2295
+ unmappedReason: null,
2296
+ wxccActivityId: "5f114466ef5cfc454fbbf131",
2297
+ wxccActivityName: "play-message",
2298
+ wxccGroup: "action"
2299
+ },
2300
+ {
2301
+ id: "824f0d8a-01d5-3f21-9563-590427002c86",
2302
+ name: "Play Prompt_107\nPlay Prompt (--Triggering Contact--, NonBusinessHourPrompt)",
2303
+ review: {
2304
+ color: "green",
2305
+ level: "confident",
2306
+ reasons: [
2307
+ ]
2308
+ },
2309
+ suggestedProperties: {
2310
+ uccxDescription: "Play Prompt (--Triggering Contact--, NonBusinessHourPrompt)",
2311
+ prompt: "NonBusinessHourPrompt",
2312
+ closestWxccActivity: "Play Message",
2313
+ mappingNotes: "Flow Designer Play Message supports mixing audio files and TTS in a single activity; UCCX often builds composite prompts using Prompt steps.",
2314
+ migrationInstructions: "* Drag and drop the Play Message Activity to the Canvas\n* Click the \"Play Message\" Activity to update its property\n* We shall either use Text-to-Speech or Choose play using an Audio Prompt(.WAV)\n* For TTS, Toggle the \"Enable Text-to-Speech\" to utilize TTS, if not, Select the Audio File from the dropdown menu.\n* Optionally, we can also create Local Variables to store the Audio File name if we do not want to point the WAV file directly\n\nNote: When using TTS, the TTS Message field accepts two types of input: raw text (plaintext) or SSML-formatted data. You can use variables also as part of the message to read the dynamic content\n\nNote: If customer would like to utilize the existing Prompts from the UCCX, we can go with selecting Auio files or if the customer would like to go with TTS, then we can turn on the TTS but the we have to input the Text that should be converted to Speech.\n\nFor supported SSML tags for Cisco Cloud Text-to-Speech, see the link: https://help.webex.com/en-us/article/ntkjqhw/Text-to-Speech-(TTS)-in-Webex-Contact-Center#reference-template_b6eff334-4963-4685-b1dc-17184aaaa308",
2315
+ uccxKeyFields: [
2316
+ "promptDTMFExpr",
2317
+ "bargeIn",
2318
+ "continueOnPromptErrors",
2319
+ "flushInputBufferFlag"
2320
+ ],
2321
+ uccxKeyFieldExamples: {
2322
+ flushInputBufferFlag: "true",
2323
+ promptDTMFExpr: "P[1161.wav]",
2324
+ bargeIn: "true",
2325
+ continueOnPromptErrors: "true"
2326
+ },
2327
+ allAudioFilesInFlow: [
2328
+ "ICD\\ICDQueue.wav",
2329
+ "ICD\\ICDWelcome.wav",
2330
+ "ICDQueue.wav",
2331
+ "ICDWelcome.wav"
2332
+ ]
2333
+ },
2334
+ uccxDisplayType: "Play Prompt",
2335
+ uccxTypeName: "Play Prompt",
2336
+ uccxWfId: 107,
2337
+ unmappedReason: null,
2338
+ wxccActivityId: "5f114466ef5cfc454fbbf131",
2339
+ wxccActivityName: "play-message",
2340
+ wxccGroup: "action"
2341
+ },
2342
+ {
2343
+ id: "eb11f7cf-18d7-31aa-936f-68df91fc9c6f",
2344
+ name: "Select Resource_123\nSelect Resource (--Triggering Contact-- from HolidayCSQ)",
2345
+ review: {
2346
+ color: "green",
2347
+ level: "confident",
2348
+ reasons: [
2349
+ ]
2350
+ },
2351
+ suggestedProperties: {
2352
+ uccxDescription: "Select Resource (--Triggering Contact-- from HolidayCSQ)",
2353
+ queuingExpr: "HolidayCSQ",
2354
+ ringTimeExpr: "12",
2355
+ routingTypeStr: "Contact Service Queue",
2356
+ toQueue: true,
2357
+ toConnect: true,
2358
+ closestWxccActivity: "Queue Contact (agent selection is built-in) or Queue To Agent",
2359
+ mappingNotes: "Avoid reproducing UCCX resource-selection logic step-by-step unless absolutely required; leverage WxCC routing features where possible.",
2360
+ migrationInstructions: "* Drag and drop the \"Queue Contact\" Activity to the canvas\n* Click the added \"Queue Contact\" activity to update its property\n* Select the \"Static Queue\" name if all contacts should go to a single queue or select the \"Variable Queue\" if the queue should change based on the certain parameters or choosen menu options, etc.\n* If we selected the Static Queue whick routes based on Skill then we have to Configure the Skill Requirements or if we choosen Dynamic Queue, we should also choose the reuqired Skill either through static or dynamic.\n\n* We should also select the Fallback Queue. \n\nNote: The Fallback Queue always honors Longest Available Agent routing. If the selected queue uses Skills Based Routing, skills cannot be configured.\n\nNote: Queue should be already created in the WebEx CC Control Hub to be available inside the flow designer to select. Depends on the type of the Queue, we select, there may be additional options to choose from the properties.\n\nNote: UCCX Select Resource does not give any information about the Queue itself like wheather its group or Skill based and manual intervention is required after the flow is created and certain settings shall need to be updated directly on the Flow Designer.",
2361
+ uccxKeyFields: [
2362
+ "queuingExpr",
2363
+ "toQueue",
2364
+ "toConnect",
2365
+ "ringTimeExpr"
2366
+ ],
2367
+ uccxKeyFieldExamples: {
2368
+ ringTimeExpr: "10",
2369
+ toQueue: "true",
2370
+ toConnect: "true",
2371
+ queuingExpr: "\"CSQ_SalesStars\""
2372
+ },
2373
+ allAudioFilesInFlow: [
2374
+ "ICD\\ICDQueue.wav",
2375
+ "ICD\\ICDWelcome.wav",
2376
+ "ICDQueue.wav",
2377
+ "ICDWelcome.wav"
2378
+ ]
2379
+ },
2380
+ uccxDisplayType: "Select Resource",
2381
+ uccxTypeName: "Select Resource",
2382
+ uccxWfId: 123,
2383
+ unmappedReason: null,
2384
+ wxccActivityId: "5f114550ef5cfc454fbbf133",
2385
+ wxccActivityName: "queue-contact",
2386
+ wxccGroup: "action"
2387
+ },
2388
+ {
2389
+ id: "ddb6c20e-1574-3485-8151-f23052f6f6e7",
2390
+ name: "Play Prompt_125\nPlay Prompt (--Triggering Contact--, QueuePrompt)",
2391
+ review: {
2392
+ color: "green",
2393
+ level: "confident",
2394
+ reasons: [
2395
+ ]
2396
+ },
2397
+ suggestedProperties: {
2398
+ uccxDescription: "Play Prompt (--Triggering Contact--, QueuePrompt)",
2399
+ prompt: "QueuePrompt",
2400
+ closestWxccActivity: "Play Message",
2401
+ mappingNotes: "Flow Designer Play Message supports mixing audio files and TTS in a single activity; UCCX often builds composite prompts using Prompt steps.",
2402
+ migrationInstructions: "* Drag and drop the Play Message Activity to the Canvas\n* Click the \"Play Message\" Activity to update its property\n* We shall either use Text-to-Speech or Choose play using an Audio Prompt(.WAV)\n* For TTS, Toggle the \"Enable Text-to-Speech\" to utilize TTS, if not, Select the Audio File from the dropdown menu.\n* Optionally, we can also create Local Variables to store the Audio File name if we do not want to point the WAV file directly\n\nNote: When using TTS, the TTS Message field accepts two types of input: raw text (plaintext) or SSML-formatted data. You can use variables also as part of the message to read the dynamic content\n\nNote: If customer would like to utilize the existing Prompts from the UCCX, we can go with selecting Auio files or if the customer would like to go with TTS, then we can turn on the TTS but the we have to input the Text that should be converted to Speech.\n\nFor supported SSML tags for Cisco Cloud Text-to-Speech, see the link: https://help.webex.com/en-us/article/ntkjqhw/Text-to-Speech-(TTS)-in-Webex-Contact-Center#reference-template_b6eff334-4963-4685-b1dc-17184aaaa308",
2403
+ uccxKeyFields: [
2404
+ "promptDTMFExpr",
2405
+ "bargeIn",
2406
+ "continueOnPromptErrors",
2407
+ "flushInputBufferFlag"
2408
+ ],
2409
+ uccxKeyFieldExamples: {
2410
+ flushInputBufferFlag: "true",
2411
+ promptDTMFExpr: "P[1161.wav]",
2412
+ bargeIn: "true",
2413
+ continueOnPromptErrors: "true"
2414
+ },
2415
+ allAudioFilesInFlow: [
2416
+ "ICD\\ICDQueue.wav",
2417
+ "ICD\\ICDWelcome.wav",
2418
+ "ICDQueue.wav",
2419
+ "ICDWelcome.wav"
2420
+ ]
2421
+ },
2422
+ uccxDisplayType: "Play Prompt",
2423
+ uccxTypeName: "Play Prompt",
2424
+ uccxWfId: 125,
2425
+ unmappedReason: null,
2426
+ wxccActivityId: "5f114466ef5cfc454fbbf131",
2427
+ wxccActivityName: "play-message",
2428
+ wxccGroup: "action"
2429
+ },
2430
+ {
2431
+ id: "9e093dc4-866c-32ca-bebf-624ae3dcfd62",
2432
+ name: "Delay_126\nDelay DelayWhileQueued sec",
2433
+ review: {
2434
+ color: "green",
2435
+ level: "confident",
2436
+ reasons: [
2437
+ ]
2438
+ },
2439
+ suggestedProperties: {
2440
+ uccxDescription: "Delay DelayWhileQueued sec",
2441
+ delayExpression: "DelayWhileQueued",
2442
+ expression: "DelayWhileQueued",
2443
+ interruptible: true,
2444
+ closestWxccActivity: "Wait",
2445
+ mappingNotes: "The practical outcome of these two steps is functionally equivalent: they introduce a time-based pause in the call flow\n\nAlthought the Wait Activity is the equivalent of Delay but we don't recommend usage of the Wait activity when an IVR session is active as it may cause the IVR session to time out. In such cases, contact will experience dead air resulting in call failures. We strongly recommend flow designers to use the Wait activity in the CallbackFailed event and specify the wait period.",
2446
+ migrationInstructions: "* Drag and drop the \"wait\" Activity into the canvas\n* Click the Wait Activity to update its properties\n* Enter duration between 00:00:05 - 72:00:00\n\nNote: No Input or Output Variables are applicable on this activity\n\nTypically, in UCCX, Delay Step uses either Variable or it shall be statically configured through Delay Step property",
2447
+ uccxKeyFields: [
2448
+ "delayExpression",
2449
+ "interruptible"
2450
+ ],
2451
+ uccxKeyFieldExamples: {
2452
+ delayExpression: "DelayWhileQueued",
2453
+ interruptible: "true"
2454
+ },
2455
+ allAudioFilesInFlow: [
2456
+ "ICD\\ICDQueue.wav",
2457
+ "ICD\\ICDWelcome.wav",
2458
+ "ICDQueue.wav",
2459
+ "ICDWelcome.wav"
2460
+ ]
2461
+ },
2462
+ uccxDisplayType: "Delay",
2463
+ uccxTypeName: "Delay",
2464
+ uccxWfId: 126,
2465
+ unmappedReason: null,
2466
+ wxccActivityId: "wait-activity",
2467
+ wxccActivityName: "wait-activity",
2468
+ wxccGroup: "action"
2469
+ },
2470
+ {
2471
+ id: "8dd88674-9b03-39f0-803e-1a06ecc32970",
2472
+ name: "Select Resource_133\nSelect Resource (--Triggering Contact-- from BusinessHourCSQ)",
2473
+ review: {
2474
+ color: "green",
2475
+ level: "confident",
2476
+ reasons: [
2477
+ ]
2478
+ },
2479
+ suggestedProperties: {
2480
+ uccxDescription: "Select Resource (--Triggering Contact-- from BusinessHourCSQ)",
2481
+ queuingExpr: "BusinessHourCSQ",
2482
+ ringTimeExpr: "12",
2483
+ routingTypeStr: "Contact Service Queue",
2484
+ toQueue: true,
2485
+ toConnect: true,
2486
+ closestWxccActivity: "Queue Contact (agent selection is built-in) or Queue To Agent",
2487
+ mappingNotes: "Avoid reproducing UCCX resource-selection logic step-by-step unless absolutely required; leverage WxCC routing features where possible.",
2488
+ migrationInstructions: "* Drag and drop the \"Queue Contact\" Activity to the canvas\n* Click the added \"Queue Contact\" activity to update its property\n* Select the \"Static Queue\" name if all contacts should go to a single queue or select the \"Variable Queue\" if the queue should change based on the certain parameters or choosen menu options, etc.\n* If we selected the Static Queue whick routes based on Skill then we have to Configure the Skill Requirements or if we choosen Dynamic Queue, we should also choose the reuqired Skill either through static or dynamic.\n\n* We should also select the Fallback Queue. \n\nNote: The Fallback Queue always honors Longest Available Agent routing. If the selected queue uses Skills Based Routing, skills cannot be configured.\n\nNote: Queue should be already created in the WebEx CC Control Hub to be available inside the flow designer to select. Depends on the type of the Queue, we select, there may be additional options to choose from the properties.\n\nNote: UCCX Select Resource does not give any information about the Queue itself like wheather its group or Skill based and manual intervention is required after the flow is created and certain settings shall need to be updated directly on the Flow Designer.",
2489
+ uccxKeyFields: [
2490
+ "queuingExpr",
2491
+ "toQueue",
2492
+ "toConnect",
2493
+ "ringTimeExpr"
2494
+ ],
2495
+ uccxKeyFieldExamples: {
2496
+ ringTimeExpr: "10",
2497
+ toQueue: "true",
2498
+ toConnect: "true",
2499
+ queuingExpr: "\"CSQ_SalesStars\""
2500
+ },
2501
+ allAudioFilesInFlow: [
2502
+ "ICD\\ICDQueue.wav",
2503
+ "ICD\\ICDWelcome.wav",
2504
+ "ICDQueue.wav",
2505
+ "ICDWelcome.wav"
2506
+ ]
2507
+ },
2508
+ uccxDisplayType: "Select Resource",
2509
+ uccxTypeName: "Select Resource",
2510
+ uccxWfId: 133,
2511
+ unmappedReason: null,
2512
+ wxccActivityId: "5f114550ef5cfc454fbbf133",
2513
+ wxccActivityName: "queue-contact",
2514
+ wxccGroup: "action"
2515
+ },
2516
+ {
2517
+ id: "7b61caf6-ba3f-3a44-84bb-3dacdbde8b60",
2518
+ name: "Play Prompt_135\nPlay Prompt (--Triggering Contact--, QueuePrompt)",
2519
+ review: {
2520
+ color: "green",
2521
+ level: "confident",
2522
+ reasons: [
2523
+ ]
2524
+ },
2525
+ suggestedProperties: {
2526
+ uccxDescription: "Play Prompt (--Triggering Contact--, QueuePrompt)",
2527
+ prompt: "QueuePrompt",
2528
+ closestWxccActivity: "Play Message",
2529
+ mappingNotes: "Flow Designer Play Message supports mixing audio files and TTS in a single activity; UCCX often builds composite prompts using Prompt steps.",
2530
+ migrationInstructions: "* Drag and drop the Play Message Activity to the Canvas\n* Click the \"Play Message\" Activity to update its property\n* We shall either use Text-to-Speech or Choose play using an Audio Prompt(.WAV)\n* For TTS, Toggle the \"Enable Text-to-Speech\" to utilize TTS, if not, Select the Audio File from the dropdown menu.\n* Optionally, we can also create Local Variables to store the Audio File name if we do not want to point the WAV file directly\n\nNote: When using TTS, the TTS Message field accepts two types of input: raw text (plaintext) or SSML-formatted data. You can use variables also as part of the message to read the dynamic content\n\nNote: If customer would like to utilize the existing Prompts from the UCCX, we can go with selecting Auio files or if the customer would like to go with TTS, then we can turn on the TTS but the we have to input the Text that should be converted to Speech.\n\nFor supported SSML tags for Cisco Cloud Text-to-Speech, see the link: https://help.webex.com/en-us/article/ntkjqhw/Text-to-Speech-(TTS)-in-Webex-Contact-Center#reference-template_b6eff334-4963-4685-b1dc-17184aaaa308",
2531
+ uccxKeyFields: [
2532
+ "promptDTMFExpr",
2533
+ "bargeIn",
2534
+ "continueOnPromptErrors",
2535
+ "flushInputBufferFlag"
2536
+ ],
2537
+ uccxKeyFieldExamples: {
2538
+ flushInputBufferFlag: "true",
2539
+ promptDTMFExpr: "P[1161.wav]",
2540
+ bargeIn: "true",
2541
+ continueOnPromptErrors: "true"
2542
+ },
2543
+ allAudioFilesInFlow: [
2544
+ "ICD\\ICDQueue.wav",
2545
+ "ICD\\ICDWelcome.wav",
2546
+ "ICDQueue.wav",
2547
+ "ICDWelcome.wav"
2548
+ ]
2549
+ },
2550
+ uccxDisplayType: "Play Prompt",
2551
+ uccxTypeName: "Play Prompt",
2552
+ uccxWfId: 135,
2553
+ unmappedReason: null,
2554
+ wxccActivityId: "5f114466ef5cfc454fbbf131",
2555
+ wxccActivityName: "play-message",
2556
+ wxccGroup: "action"
2557
+ },
2558
+ {
2559
+ id: "f64571d2-a862-3c35-9098-abae0f54b985",
2560
+ name: "Delay_136\nDelay DelayWhileQueued sec",
2561
+ review: {
2562
+ color: "green",
2563
+ level: "confident",
2564
+ reasons: [
2565
+ ]
2566
+ },
2567
+ suggestedProperties: {
2568
+ uccxDescription: "Delay DelayWhileQueued sec",
2569
+ delayExpression: "DelayWhileQueued",
2570
+ expression: "DelayWhileQueued",
2571
+ interruptible: true,
2572
+ closestWxccActivity: "Wait",
2573
+ mappingNotes: "The practical outcome of these two steps is functionally equivalent: they introduce a time-based pause in the call flow\n\nAlthought the Wait Activity is the equivalent of Delay but we don't recommend usage of the Wait activity when an IVR session is active as it may cause the IVR session to time out. In such cases, contact will experience dead air resulting in call failures. We strongly recommend flow designers to use the Wait activity in the CallbackFailed event and specify the wait period.",
2574
+ migrationInstructions: "* Drag and drop the \"wait\" Activity into the canvas\n* Click the Wait Activity to update its properties\n* Enter duration between 00:00:05 - 72:00:00\n\nNote: No Input or Output Variables are applicable on this activity\n\nTypically, in UCCX, Delay Step uses either Variable or it shall be statically configured through Delay Step property",
2575
+ uccxKeyFields: [
2576
+ "delayExpression",
2577
+ "interruptible"
2578
+ ],
2579
+ uccxKeyFieldExamples: {
2580
+ delayExpression: "DelayWhileQueued",
2581
+ interruptible: "true"
2582
+ },
2583
+ allAudioFilesInFlow: [
2584
+ "ICD\\ICDQueue.wav",
2585
+ "ICD\\ICDWelcome.wav",
2586
+ "ICDQueue.wav",
2587
+ "ICDWelcome.wav"
2588
+ ]
2589
+ },
2590
+ uccxDisplayType: "Delay",
2591
+ uccxTypeName: "Delay",
2592
+ uccxWfId: 136,
2593
+ unmappedReason: null,
2594
+ wxccActivityId: "wait-activity",
2595
+ wxccActivityName: "wait-activity",
2596
+ wxccGroup: "action"
2597
+ }
2598
+ ];
2599
+ var aefFile = "C:\\Windows\\TEMP\\upload-3096504673883630384.aef";
2600
+ var generatedAt = "2026-05-11T11:31:14.143682200Z";
2601
+ var links = [
2602
+ {
2603
+ conditionExpr: "out",
2604
+ id: "fe58c236-9a37-318c-8d4c-0cf6650fdb9d",
2605
+ review: {
2606
+ color: "green",
2607
+ level: "confident",
2608
+ reasons: [
2609
+ ]
2610
+ },
2611
+ sourceActivityId: "8c89c876-e556-3c8c-a1be-77b8cfbd3800",
2612
+ targetActivityId: "94eb01a7-71de-3b5b-96b5-02c38e29f58f",
2613
+ uccxEdgeIndex: 0,
2614
+ uccxFromWfId: 0,
2615
+ uccxLabel: "",
2616
+ uccxToWfId: 43
2617
+ },
2618
+ {
2619
+ conditionExpr: "default",
2620
+ id: "15d60d2d-a2a7-32b7-9ecd-bc7815f49c24",
2621
+ review: {
2622
+ color: "green",
2623
+ level: "confident",
2624
+ reasons: [
2625
+ ]
2626
+ },
2627
+ sourceActivityId: "78c3dea1-172e-3de9-9c99-3ce92fb4b12e",
2628
+ targetActivityId: "95c0b5ba-20a8-3062-995f-d01036660cdc",
2629
+ uccxEdgeIndex: 0,
2630
+ uccxFromWfId: 16,
2631
+ uccxLabel: "",
2632
+ uccxToWfId: 54
2633
+ },
2634
+ {
2635
+ conditionExpr: "default",
2636
+ id: "d2257d15-c592-303e-8995-532bc5c5cf83",
2637
+ review: {
2638
+ color: "green",
2639
+ level: "confident",
2640
+ reasons: [
2641
+ ]
2642
+ },
2643
+ sourceActivityId: "94eb01a7-71de-3b5b-96b5-02c38e29f58f",
2644
+ targetActivityId: "78c3dea1-172e-3de9-9c99-3ce92fb4b12e",
2645
+ uccxEdgeIndex: 0,
2646
+ uccxFromWfId: 43,
2647
+ uccxLabel: "",
2648
+ uccxToWfId: 16
2649
+ },
2650
+ {
2651
+ conditionExpr: "business_hours",
2652
+ id: "3d56441f-0b08-3559-b3a1-9808180504f3",
2653
+ review: {
2654
+ color: "yellow",
2655
+ level: "low_confidence",
2656
+ reasons: [
2657
+ "Non-standard conditionExpr (likely needs manual port selection in Flow Designer)"
2658
+ ]
2659
+ },
2660
+ sourceActivityId: "95c0b5ba-20a8-3062-995f-d01036660cdc",
2661
+ targetActivityId: "8dd88674-9b03-39f0-803e-1a06ecc32970",
2662
+ uccxEdgeIndex: 0,
2663
+ uccxFromWfId: 54,
2664
+ uccxLabel: "Business Hours",
2665
+ uccxToWfId: 133
2666
+ },
2667
+ {
2668
+ conditionExpr: "holidays",
2669
+ id: "2bb98772-9225-3fdf-9646-a3854f1884fd",
2670
+ review: {
2671
+ color: "yellow",
2672
+ level: "low_confidence",
2673
+ reasons: [
2674
+ "Non-standard conditionExpr (likely needs manual port selection in Flow Designer)"
2675
+ ]
2676
+ },
2677
+ sourceActivityId: "95c0b5ba-20a8-3062-995f-d01036660cdc",
2678
+ targetActivityId: "eb11f7cf-18d7-31aa-936f-68df91fc9c6f",
2679
+ uccxEdgeIndex: 1,
2680
+ uccxFromWfId: 54,
2681
+ uccxLabel: "Holidays",
2682
+ uccxToWfId: 123
2683
+ },
2684
+ {
2685
+ conditionExpr: "the_rest",
2686
+ id: "4bf84735-5161-32e2-b94f-3b848390a1ac",
2687
+ review: {
2688
+ color: "yellow",
2689
+ level: "low_confidence",
2690
+ reasons: [
2691
+ "Non-standard conditionExpr (likely needs manual port selection in Flow Designer)"
2692
+ ]
2693
+ },
2694
+ sourceActivityId: "95c0b5ba-20a8-3062-995f-d01036660cdc",
2695
+ targetActivityId: "824f0d8a-01d5-3f21-9563-590427002c86",
2696
+ uccxEdgeIndex: 2,
2697
+ uccxFromWfId: 54,
2698
+ uccxLabel: "The Rest",
2699
+ uccxToWfId: 107
2700
+ },
2701
+ {
2702
+ conditionExpr: "failure",
2703
+ id: "43c91f09-d081-3524-ad2a-7ddf5d0bd3de",
2704
+ review: {
2705
+ color: "green",
2706
+ level: "confident",
2707
+ reasons: [
2708
+ ]
2709
+ },
2710
+ sourceActivityId: "95c0b5ba-20a8-3062-995f-d01036660cdc",
2711
+ targetActivityId: "30eea40d-78b7-32e3-83c6-94738320acab",
2712
+ uccxEdgeIndex: 3,
2713
+ uccxFromWfId: 54,
2714
+ uccxLabel: "Failure",
2715
+ uccxToWfId: 87
2716
+ },
2717
+ {
2718
+ conditionExpr: "default",
2719
+ id: "3cec80e0-81ac-302c-9ff5-57ff85ecaf2d",
2720
+ review: {
2721
+ color: "green",
2722
+ level: "confident",
2723
+ reasons: [
2724
+ ]
2725
+ },
2726
+ sourceActivityId: "30eea40d-78b7-32e3-83c6-94738320acab",
2727
+ targetActivityId: "c535b5fd-5ab9-323f-b1ac-667f4590d801",
2728
+ uccxEdgeIndex: 0,
2729
+ uccxFromWfId: 87,
2730
+ uccxLabel: "",
2731
+ uccxToWfId: 12
2732
+ },
2733
+ {
2734
+ conditionExpr: "default",
2735
+ id: "d4d3a905-3b1a-32fe-a90d-43ac44ff2e94",
2736
+ review: {
2737
+ color: "green",
2738
+ level: "confident",
2739
+ reasons: [
2740
+ ]
2741
+ },
2742
+ sourceActivityId: "824f0d8a-01d5-3f21-9563-590427002c86",
2743
+ targetActivityId: "c535b5fd-5ab9-323f-b1ac-667f4590d801",
2744
+ uccxEdgeIndex: 0,
2745
+ uccxFromWfId: 107,
2746
+ uccxLabel: "",
2747
+ uccxToWfId: 12
2748
+ },
2749
+ {
2750
+ conditionExpr: "default",
2751
+ id: "e9259722-948e-36f0-b292-1cdcbf2fc63c",
2752
+ review: {
2753
+ color: "green",
2754
+ level: "confident",
2755
+ reasons: [
2756
+ ]
2757
+ },
2758
+ sourceActivityId: "eb11f7cf-18d7-31aa-936f-68df91fc9c6f",
2759
+ targetActivityId: "c535b5fd-5ab9-323f-b1ac-667f4590d801",
2760
+ uccxEdgeIndex: 0,
2761
+ uccxFromWfId: 123,
2762
+ uccxLabel: "Connected",
2763
+ uccxToWfId: 12
2764
+ },
2765
+ {
2766
+ conditionExpr: "queued",
2767
+ id: "1e964ee4-d8d5-3607-9bfb-cae54e07f2cb",
2768
+ review: {
2769
+ color: "yellow",
2770
+ level: "low_confidence",
2771
+ reasons: [
2772
+ "Non-standard conditionExpr (likely needs manual port selection in Flow Designer)"
2773
+ ]
2774
+ },
2775
+ sourceActivityId: "eb11f7cf-18d7-31aa-936f-68df91fc9c6f",
2776
+ targetActivityId: "ddb6c20e-1574-3485-8151-f23052f6f6e7",
2777
+ uccxEdgeIndex: 1,
2778
+ uccxFromWfId: 123,
2779
+ uccxLabel: "Queued",
2780
+ uccxToWfId: 125
2781
+ },
2782
+ {
2783
+ conditionExpr: "default",
2784
+ id: "81f3a025-70c9-3d05-a2a5-de4a981c0715",
2785
+ review: {
2786
+ color: "green",
2787
+ level: "confident",
2788
+ reasons: [
2789
+ ]
2790
+ },
2791
+ sourceActivityId: "ddb6c20e-1574-3485-8151-f23052f6f6e7",
2792
+ targetActivityId: "9e093dc4-866c-32ca-bebf-624ae3dcfd62",
2793
+ uccxEdgeIndex: 0,
2794
+ uccxFromWfId: 125,
2795
+ uccxLabel: "",
2796
+ uccxToWfId: 126
2797
+ },
2798
+ {
2799
+ conditionExpr: "default",
2800
+ id: "36d5e8cf-ce9d-3acd-bf49-04c1c3d9f69d",
2801
+ review: {
2802
+ color: "green",
2803
+ level: "confident",
2804
+ reasons: [
2805
+ ]
2806
+ },
2807
+ sourceActivityId: "9e093dc4-866c-32ca-bebf-624ae3dcfd62",
2808
+ targetActivityId: "ddb6c20e-1574-3485-8151-f23052f6f6e7",
2809
+ uccxEdgeIndex: 0,
2810
+ uccxFromWfId: 126,
2811
+ uccxLabel: "",
2812
+ uccxToWfId: 125
2813
+ },
2814
+ {
2815
+ conditionExpr: "default",
2816
+ id: "74d24ec3-31a8-3aef-9359-1eb79b92077c",
2817
+ review: {
2818
+ color: "green",
2819
+ level: "confident",
2820
+ reasons: [
2821
+ ]
2822
+ },
2823
+ sourceActivityId: "8dd88674-9b03-39f0-803e-1a06ecc32970",
2824
+ targetActivityId: "c535b5fd-5ab9-323f-b1ac-667f4590d801",
2825
+ uccxEdgeIndex: 0,
2826
+ uccxFromWfId: 133,
2827
+ uccxLabel: "Connected",
2828
+ uccxToWfId: 12
2829
+ },
2830
+ {
2831
+ conditionExpr: "queued",
2832
+ id: "d96a9238-fc21-3a9d-a90a-e2af7698d36a",
2833
+ review: {
2834
+ color: "yellow",
2835
+ level: "low_confidence",
2836
+ reasons: [
2837
+ "Non-standard conditionExpr (likely needs manual port selection in Flow Designer)"
2838
+ ]
2839
+ },
2840
+ sourceActivityId: "8dd88674-9b03-39f0-803e-1a06ecc32970",
2841
+ targetActivityId: "7b61caf6-ba3f-3a44-84bb-3dacdbde8b60",
2842
+ uccxEdgeIndex: 1,
2843
+ uccxFromWfId: 133,
2844
+ uccxLabel: "Queued",
2845
+ uccxToWfId: 135
2846
+ },
2847
+ {
2848
+ conditionExpr: "default",
2849
+ id: "4fec8261-a460-3a2b-8a84-934592a62734",
2850
+ review: {
2851
+ color: "green",
2852
+ level: "confident",
2853
+ reasons: [
2854
+ ]
2855
+ },
2856
+ sourceActivityId: "7b61caf6-ba3f-3a44-84bb-3dacdbde8b60",
2857
+ targetActivityId: "f64571d2-a862-3c35-9098-abae0f54b985",
2858
+ uccxEdgeIndex: 0,
2859
+ uccxFromWfId: 135,
2860
+ uccxLabel: "",
2861
+ uccxToWfId: 136
2862
+ },
2863
+ {
2864
+ conditionExpr: "default",
2865
+ id: "27e9f7a7-875f-34f1-97d7-a277d48035ac",
2866
+ review: {
2867
+ color: "green",
2868
+ level: "confident",
2869
+ reasons: [
2870
+ ]
2871
+ },
2872
+ sourceActivityId: "f64571d2-a862-3c35-9098-abae0f54b985",
2873
+ targetActivityId: "7b61caf6-ba3f-3a44-84bb-3dacdbde8b60",
2874
+ uccxEdgeIndex: 0,
2875
+ uccxFromWfId: 136,
2876
+ uccxLabel: "",
2877
+ uccxToWfId: 135
2878
+ }
2879
+ ];
2880
+ var prefix = "QueuingWithCalendar_uccx.aef";
2881
+ var resources = {
2882
+ aefFile: "C:\\Windows\\TEMP\\upload-3096504673883630384.aef",
2883
+ audioFiles: [
2884
+ "ICDQueue.wav",
2885
+ "ICDWelcome.wav",
2886
+ "ICD\\ICDQueue.wav",
2887
+ "ICD\\ICDWelcome.wav"
2888
+ ],
2889
+ audioFilesCount: 4,
2890
+ generatedAt: "2026-05-11T11:31:14.128113200Z",
2891
+ variableCount: 10,
2892
+ variables: [
2893
+ {
2894
+ hints: [
2895
+ "default_from_uccx",
2896
+ "prompt"
2897
+ ],
2898
+ isParameter: false,
2899
+ metaAttributes: null,
2900
+ name: "WelcomePrompt",
2901
+ type: "STRING",
2902
+ usedByWfIds: [
2903
+ 16
2904
+ ],
2905
+ value: "ICDWelcome.wav"
2906
+ },
2907
+ {
2908
+ hints: [
2909
+ "calendar",
2910
+ "calendar_expr"
2911
+ ],
2912
+ isParameter: false,
2913
+ metaAttributes: null,
2914
+ name: "cal",
2915
+ type: "STRING",
2916
+ usedByWfIds: [
2917
+ 54
2918
+ ],
2919
+ value: null
2920
+ },
2921
+ {
2922
+ hints: [
2923
+ "prompt"
2924
+ ],
2925
+ isParameter: false,
2926
+ metaAttributes: null,
2927
+ name: "FailurePrompt",
2928
+ type: "STRING",
2929
+ usedByWfIds: [
2930
+ 87
2931
+ ],
2932
+ value: null
2933
+ },
2934
+ {
2935
+ hints: [
2936
+ "prompt"
2937
+ ],
2938
+ isParameter: false,
2939
+ metaAttributes: null,
2940
+ name: "NonBusinessHourPrompt",
2941
+ type: "STRING",
2942
+ usedByWfIds: [
2943
+ 107
2944
+ ],
2945
+ value: null
2946
+ },
2947
+ {
2948
+ hints: [
2949
+ "csq"
2950
+ ],
2951
+ isParameter: false,
2952
+ metaAttributes: null,
2953
+ name: "HolidayCSQ",
2954
+ type: "STRING",
2955
+ usedByWfIds: [
2956
+ 123
2957
+ ],
2958
+ value: null
2959
+ },
2960
+ {
2961
+ hints: [
2962
+ "default_from_uccx",
2963
+ "prompt"
2964
+ ],
2965
+ isParameter: false,
2966
+ metaAttributes: null,
2967
+ name: "QueuePrompt",
2968
+ type: "STRING",
2969
+ usedByWfIds: [
2970
+ 125,
2971
+ 135
2972
+ ],
2973
+ value: "ICDQueue.wav"
2974
+ },
2975
+ {
2976
+ hints: [
2977
+ "csq"
2978
+ ],
2979
+ isParameter: false,
2980
+ metaAttributes: null,
2981
+ name: "BusinessHourCSQ",
2982
+ type: "STRING",
2983
+ usedByWfIds: [
2984
+ 133
2985
+ ],
2986
+ value: null
2987
+ },
2988
+ {
2989
+ hints: [
2990
+ "default_only"
2991
+ ],
2992
+ isParameter: false,
2993
+ metaAttributes: null,
2994
+ name: "resourceID",
2995
+ type: "STRING",
2996
+ usedByWfIds: [
2997
+ ],
2998
+ value: null
2999
+ },
3000
+ {
3001
+ hints: [
3002
+ "default_from_uccx",
3003
+ "default_only"
3004
+ ],
3005
+ isParameter: false,
3006
+ metaAttributes: null,
3007
+ name: "DelayWhileQueued",
3008
+ type: "STRING",
3009
+ usedByWfIds: [
3010
+ ],
3011
+ value: "30"
3012
+ },
3013
+ {
3014
+ hints: [
3015
+ "default_only"
3016
+ ],
3017
+ isParameter: false,
3018
+ metaAttributes: null,
3019
+ name: "SRS_TempResourceSelectedVar2",
3020
+ type: "STRING",
3021
+ usedByWfIds: [
3022
+ ],
3023
+ value: null
3024
+ }
3025
+ ]
3026
+ };
3027
+ var schema = "uccx2wxcc-ir/v1";
3028
+ var warnings = [
3029
+ "Unmapped step: wfId=43 typeName=Accept displayType=Accept"
3030
+ ];
3031
+ var irData = {
3032
+ activities: activities,
3033
+ aefFile: aefFile,
3034
+ generatedAt: generatedAt,
3035
+ links: links,
3036
+ prefix: prefix,
3037
+ resources: resources,
3038
+ schema: schema,
3039
+ warnings: warnings
3040
+ };
3041
+
3042
+ class WxCCFlowchartPageComponent {
3043
+ constructor(api, wxcc2graph) {
3044
+ this.api = api;
3045
+ this.wxcc2graph = wxcc2graph;
3046
+ this.customerId = 0;
3047
+ this.host = "";
3048
+ this.token = "";
3049
+ this.destroy$ = new Subject();
3050
+ this.state = {
3051
+ loading: true
3052
+ };
3053
+ }
3054
+ ngOnInit() {
3055
+ this.subscribeToCustomerChanges();
3056
+ }
3057
+ ngOnDestroy() {
3058
+ this.destroy$.next();
3059
+ this.destroy$.complete();
3060
+ }
3061
+ init() {
3062
+ this.loadMockFlowchart();
3063
+ }
3064
+ subscribeToCustomerChanges() {
3065
+ // if (!this.customer) {
3066
+ // this.customersService.customer$
3067
+ // .pipe(takeUntil(this.destroy$))
3068
+ // .subscribe((customer) => {
3069
+ // if (customer) {
3070
+ this.init();
3071
+ // }
3072
+ // });
3073
+ // } else {
3074
+ // this.init();
3075
+ // }
3076
+ }
3077
+ loadMockFlowchart() {
3078
+ const irDoc = irData;
3079
+ this.state.irDoc = irDoc;
3080
+ this.state.flowchart = this.wxcc2graph.parseWxCC(irDoc);
3081
+ this.setLoading(false);
3082
+ }
3083
+ loadFileNames() {
3084
+ // forkJoin([
3085
+ // this.uccxWorkflowApi.fetchFileNames(this.customerId)
3086
+ // .pipe(filter(fileNames => fileNames && fileNames.length > 0)),
3087
+ // this.contactCenterService.getCallFlowMigrationStatuses()
3088
+ // ]).pipe(takeUntil(this.destroy$))
3089
+ // .subscribe(([fileNames, statuses]) => {
3090
+ // this.state.fileNames = fileNames;
3091
+ // this.state.uccxIp = fileNames[0].host;
3092
+ // this.state.selectedFileName = fileNames[0].fileName;
3093
+ // this.state.statuses = statuses.filter(status => status.uccxIp === this.state.uccxIp);
3094
+ // this.state.selectedFileStatus = this.getStatus(this.state.selectedFileName, this.state.uccxIp);
3095
+ // this.loadWxCCFlowData();
3096
+ // });
3097
+ }
3098
+ loadWxCCFlowData() {
3099
+ forkJoin([
3100
+ this.api.fetchWxCCFlowData(this.baseParams, this.state.selectedFileStatus),
3101
+ this.api.fetchWxCCFlowDataIR(this.baseParams, this.state.selectedFileStatus),
3102
+ ]).pipe(mergeMap(([nonIrDoc, irDoc]) => irDoc !== null ?
3103
+ of({ nonIrDoc, irDoc }) :
3104
+ throwError(() => new Error('No wxcc flow diagram available for this script'))), takeUntil(this.destroy$), finalize$1(() => this.setLoading(false))).subscribe({
3105
+ next: ({ nonIrDoc, irDoc }) => {
3106
+ this.wxcc2graph.setSourceDocuments(irDoc, nonIrDoc);
3107
+ this.state.irDoc = irDoc;
3108
+ this.state.nonIrDoc = nonIrDoc;
3109
+ this.state.flowchart = this.wxcc2graph.parseWxCC(irDoc, nonIrDoc);
3110
+ },
3111
+ error: (error) => {
3112
+ this.state.flowchart = null;
3113
+ this.setError('No wxcc flow diagram available for this script');
3114
+ }
3115
+ });
3116
+ }
3117
+ onSave() {
3118
+ this.setLoading(true);
3119
+ forkJoin([
3120
+ this.api.saveWxCCFlowData(this.baseParams, this.wxcc2graph.wxccNonIRJSON),
3121
+ this.api.saveWxCCFlowDataIR(this.baseParams, this.wxcc2graph.wxccJSON)
3122
+ ]).pipe(takeUntil(this.destroy$), finalize$1(() => this.setLoading(false)), tap(() => {
3123
+ this.state.flowchart = this.wxcc2graph.parseWxCC(this.wxcc2graph.wxccJSON, this.wxcc2graph.wxccNonIRJSON);
3124
+ })).subscribe({
3125
+ next: ([regularResponse, irResponse]) => console.log('Flow data saved as DRAFT', regularResponse, irResponse),
3126
+ error: (error) => console.error('Error while saving wxcc data: ', error)
3127
+ });
3128
+ }
3129
+ onExportNonIr() {
3130
+ if (!this.wxcc2graph.wxccNonIRJSON) {
3131
+ console.error('Non-IR wxcc document is not loaded');
3132
+ return;
3133
+ }
3134
+ const fileStem = (this.state.selectedFileName || 'wxcc-flow').replace(/\.[^/.]+$/, '');
3135
+ const fileName = fileStem + '-non-ir.json';
3136
+ const jsonContent = JSON.stringify(this.wxcc2graph.wxccNonIRJSON, null, 2);
3137
+ const blob = new Blob([jsonContent], { type: 'application/json' });
3138
+ const url = window.URL.createObjectURL(blob);
3139
+ const anchor = document.createElement('a');
3140
+ anchor.href = url;
3141
+ anchor.download = fileName;
3142
+ document.body.appendChild(anchor);
3143
+ anchor.click();
3144
+ document.body.removeChild(anchor);
3145
+ window.URL.revokeObjectURL(url);
3146
+ }
3147
+ onReset() {
3148
+ this.setLoading(true);
3149
+ forkJoin([
3150
+ this.api.resetWxCCFlowData(this.baseParams),
3151
+ this.api.resetWxCCFlowDataIR(this.baseParams)
3152
+ ]).pipe(takeUntil(this.destroy$), finalize$1(() => this.setLoading(false))).subscribe({
3153
+ next: ([nonIrDoc, irDoc]) => {
3154
+ this.wxcc2graph.setSourceDocuments(irDoc, nonIrDoc);
3155
+ this.state.irDoc = irDoc;
3156
+ this.state.nonIrDoc = nonIrDoc;
3157
+ this.state.flowchart = this.wxcc2graph.parseWxCC(irDoc, nonIrDoc);
3158
+ console.log('Flow data reset to original');
3159
+ },
3160
+ error: (error) => {
3161
+ console.error('Error while resetting wxcc data: ', error);
3162
+ }
3163
+ });
3164
+ }
3165
+ onComplete() {
3166
+ this.setLoading(true);
3167
+ forkJoin([
3168
+ this.api.completeWxCCFlowData(this.baseParams, this.wxcc2graph.wxccNonIRJSON),
3169
+ this.api.completeWxCCFlowDataIR(this.baseParams, this.wxcc2graph.wxccJSON)
3170
+ ]).pipe(takeUntil(this.destroy$), finalize$1(() => this.setLoading(false))).subscribe({
3171
+ next: ([regularResponse, irResponse]) => {
3172
+ console.log('Flow data saved as COMPLETED', regularResponse, irResponse);
3173
+ },
3174
+ error: (error) => {
3175
+ console.error('Error while completing wxcc data: ', error);
3176
+ }
3177
+ });
3178
+ }
3179
+ onFileNameSelectionChange(item) {
3180
+ const { fileName, host } = item;
3181
+ this.state.selectedFileName = fileName;
3182
+ this.state.uccxIp = host;
3183
+ this.state.selectedFileStatus = this.getStatus(fileName, this.state.uccxIp);
3184
+ this.setLoading(true);
3185
+ this.loadWxCCFlowData();
3186
+ }
3187
+ getStatus(fileName, uccxIp) {
3188
+ if (!this.state.statuses) {
3189
+ throw Error('File status array is undefined');
3190
+ }
3191
+ const callFlowMigrationStatus = this.state.statuses.find(status => status.uccxIp === uccxIp && status.scriptName === fileName);
3192
+ // if (callFlowMigrationStatus && callFlowMigrationStatus.status) {
3193
+ // return CALL_FLOW_MIGRATION_STATUSES_TO_SCRIPT_STATUS[callFlowMigrationStatus.status];
3194
+ // }
3195
+ }
3196
+ setLoading(loading) {
3197
+ this.state.loading = loading;
3198
+ }
3199
+ setError(error) {
3200
+ this.state.errorMessage = error;
3201
+ }
3202
+ get baseParams() {
3203
+ return {
3204
+ customerId: this.customerId,
3205
+ uccxIp: this.state.uccxIp || '',
3206
+ fileName: this.state.selectedFileName || ''
3207
+ };
3208
+ }
3209
+ }
3210
+ WxCCFlowchartPageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartPageComponent, deps: [{ token: WxCCAPIService }, { token: WxCC2GraphService }], target: i0.ɵɵFactoryTarget.Component });
3211
+ WxCCFlowchartPageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFlowchartPageComponent, selector: "cc-script-editor", inputs: { customerId: "customerId", host: "host", token: "token" }, ngImport: i0, template: "<div class=\"wxcc-flowchart-wrapper\">\r\n <main class=\"content-box\">\r\n <div class=\"wxcc-flowchart-main\">\r\n <header class=\"wxcc-flowchart-header\">\r\n <wxcc-file-selection-bar\r\n *ngIf=\"state.fileNames && state.fileNames.length\"\r\n [fileNames]=\"state.fileNames\"\r\n [selectedHost]=\"state.uccxIp\"\r\n [selectedFileName]=\"state.selectedFileName\"\r\n (fileNameSelectionChange)=\"onFileNameSelectionChange($event)\">\r\n </wxcc-file-selection-bar>\r\n <wxcc-actions-bar\r\n *ngIf=\"state.flowchart\"\r\n (save)=\"onSave()\"\r\n (reset)=\"onReset()\"\r\n (exportNonIr)=\"onExportNonIr()\"\r\n (complete)=\"onComplete()\">\r\n </wxcc-actions-bar>\r\n </header>\r\n <ng-container *ngIf=\"!state.loading; else loadingTemplate\">\r\n <wxcc-flowchart\r\n *ngIf=\"state.flowchart; else errorTemplate\"\r\n [flowchart]=\"state.flowchart\">\r\n </wxcc-flowchart>\r\n </ng-container>\r\n </div>\r\n </main>\r\n</div>\r\n\r\n<ng-template #loadingTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n <mat-spinner diameter=\"40\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #errorTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n Error loading script\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block;width:100%;height:100%}.wxcc-flowchart-wrapper{width:100%;height:100%;display:flex;flex-direction:column}.wxcc-flowchart-wrapper .content-box{flex:1;display:flex;flex-direction:column;overflow:hidden}.wxcc-flowchart-wrapper .wxcc-flowchart-main{flex:1;display:flex;flex-direction:column;gap:.5rem;overflow:hidden}.wxcc-flowchart-wrapper .wxcc-flowchart-main .wxcc-flowchart-header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.wxcc-flowchart-wrapper .wxcc-flowchart-main .placeholder-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: WxCCFlowchartComponent, selector: "wxcc-flowchart", inputs: ["flowchart"] }, { kind: "component", type: WxCCFileSelectionBarComponent, selector: "wxcc-file-selection-bar", inputs: ["fileNames", "selectedFileName", "selectedHost"], outputs: ["fileNameSelectionChange"] }, { kind: "component", type: WxCCActionsBarComponent, selector: "wxcc-actions-bar", outputs: ["save", "reset", "complete", "exportNonIr"] }] });
3212
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartPageComponent, decorators: [{
3213
+ type: Component,
3214
+ args: [{ selector: 'cc-script-editor', template: "<div class=\"wxcc-flowchart-wrapper\">\r\n <main class=\"content-box\">\r\n <div class=\"wxcc-flowchart-main\">\r\n <header class=\"wxcc-flowchart-header\">\r\n <wxcc-file-selection-bar\r\n *ngIf=\"state.fileNames && state.fileNames.length\"\r\n [fileNames]=\"state.fileNames\"\r\n [selectedHost]=\"state.uccxIp\"\r\n [selectedFileName]=\"state.selectedFileName\"\r\n (fileNameSelectionChange)=\"onFileNameSelectionChange($event)\">\r\n </wxcc-file-selection-bar>\r\n <wxcc-actions-bar\r\n *ngIf=\"state.flowchart\"\r\n (save)=\"onSave()\"\r\n (reset)=\"onReset()\"\r\n (exportNonIr)=\"onExportNonIr()\"\r\n (complete)=\"onComplete()\">\r\n </wxcc-actions-bar>\r\n </header>\r\n <ng-container *ngIf=\"!state.loading; else loadingTemplate\">\r\n <wxcc-flowchart\r\n *ngIf=\"state.flowchart; else errorTemplate\"\r\n [flowchart]=\"state.flowchart\">\r\n </wxcc-flowchart>\r\n </ng-container>\r\n </div>\r\n </main>\r\n</div>\r\n\r\n<ng-template #loadingTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n <mat-spinner diameter=\"40\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #errorTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n Error loading script\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block;width:100%;height:100%}.wxcc-flowchart-wrapper{width:100%;height:100%;display:flex;flex-direction:column}.wxcc-flowchart-wrapper .content-box{flex:1;display:flex;flex-direction:column;overflow:hidden}.wxcc-flowchart-wrapper .wxcc-flowchart-main{flex:1;display:flex;flex-direction:column;gap:.5rem;overflow:hidden}.wxcc-flowchart-wrapper .wxcc-flowchart-main .wxcc-flowchart-header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.wxcc-flowchart-wrapper .wxcc-flowchart-main .placeholder-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"] }]
3215
+ }], ctorParameters: function () { return [{ type: WxCCAPIService }, { type: WxCC2GraphService }]; }, propDecorators: { customerId: [{
3216
+ type: Input
3217
+ }], host: [{
3218
+ type: Input
3219
+ }], token: [{
3220
+ type: Input
3221
+ }] } });
3222
+
3223
+ class MaterialModule {
3224
+ }
3225
+ MaterialModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3226
+ MaterialModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, imports: [MatProgressBarModule,
3227
+ MatTooltipModule,
3228
+ MatTableModule,
3229
+ MatCheckboxModule,
3230
+ MatButtonModule,
3231
+ MatIconModule,
3232
+ MatFormFieldModule,
3233
+ MatInputModule,
3234
+ MatSelectModule], exports: [MatProgressBarModule,
3235
+ MatTooltipModule,
3236
+ MatTableModule,
3237
+ MatCheckboxModule,
3238
+ MatButtonModule,
3239
+ MatIconModule,
3240
+ MatFormFieldModule,
3241
+ MatInputModule,
3242
+ MatSelectModule,
3243
+ MatProgressSpinnerModule] });
3244
+ MaterialModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, imports: [MatProgressBarModule,
3245
+ MatTooltipModule,
3246
+ MatTableModule,
3247
+ MatCheckboxModule,
3248
+ MatButtonModule,
3249
+ MatIconModule,
3250
+ MatFormFieldModule,
3251
+ MatInputModule,
3252
+ MatSelectModule, MatProgressBarModule,
3253
+ MatTooltipModule,
3254
+ MatTableModule,
3255
+ MatCheckboxModule,
3256
+ MatButtonModule,
3257
+ MatIconModule,
3258
+ MatFormFieldModule,
3259
+ MatInputModule,
3260
+ MatSelectModule,
3261
+ MatProgressSpinnerModule] });
3262
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, decorators: [{
3263
+ type: NgModule,
3264
+ args: [{
3265
+ imports: [
3266
+ MatProgressBarModule,
3267
+ MatTooltipModule,
3268
+ MatTableModule,
3269
+ MatCheckboxModule,
3270
+ MatButtonModule,
3271
+ MatIconModule,
3272
+ MatFormFieldModule,
3273
+ MatInputModule,
3274
+ MatSelectModule
3275
+ ],
3276
+ exports: [
3277
+ MatProgressBarModule,
3278
+ MatTooltipModule,
3279
+ MatTableModule,
3280
+ MatCheckboxModule,
3281
+ MatButtonModule,
3282
+ MatIconModule,
3283
+ MatFormFieldModule,
3284
+ MatInputModule,
3285
+ MatSelectModule,
3286
+ MatProgressSpinnerModule
3287
+ ]
3288
+ }]
3289
+ }] });
3290
+
3291
+ class SharedModule {
3292
+ }
3293
+ SharedModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3294
+ SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, imports: [CommonModule,
3295
+ MaterialModule,
3296
+ NgApexchartsModule,
3297
+ HttpClientModule], exports: [MaterialModule] });
3298
+ SharedModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, imports: [CommonModule,
3299
+ MaterialModule,
3300
+ NgApexchartsModule,
3301
+ HttpClientModule, MaterialModule] });
3302
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, decorators: [{
3303
+ type: NgModule,
3304
+ args: [{
3305
+ declarations: [],
3306
+ imports: [
3307
+ CommonModule,
3308
+ MaterialModule,
3309
+ NgApexchartsModule,
3310
+ HttpClientModule
3311
+ ],
3312
+ exports: [
3313
+ MaterialModule
3314
+ ]
3315
+ }]
3316
+ }] });
3317
+
3318
+ class FloatingToolbarModule {
3319
+ }
3320
+ FloatingToolbarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolbarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3321
+ FloatingToolbarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolbarModule, declarations: [FloatingToolBarComponent], imports: [CommonModule,
3322
+ MatTooltipModule], exports: [FloatingToolBarComponent] });
3323
+ FloatingToolbarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolbarModule, imports: [CommonModule,
3324
+ MatTooltipModule] });
3325
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolbarModule, decorators: [{
3326
+ type: NgModule,
3327
+ args: [{
3328
+ declarations: [
3329
+ FloatingToolBarComponent
3330
+ ],
3331
+ imports: [
3332
+ CommonModule,
3333
+ MatTooltipModule
3334
+ ],
3335
+ exports: [
3336
+ FloatingToolBarComponent
3337
+ ]
3338
+ }]
3339
+ }] });
3340
+
3341
+ class WxCCFlowchartModule {
3342
+ }
3343
+ WxCCFlowchartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3344
+ WxCCFlowchartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartModule, declarations: [WxCCFlowchartPageComponent,
3345
+ WxCCFlowchartComponent,
3346
+ NodeDetailsSidebarComponent,
3347
+ NodeActionToolbarComponent,
3348
+ LinkNodeDialogComponent,
3349
+ WxCCFileSelectionBarComponent,
3350
+ AddNodeDialogComponent,
3351
+ WxCCActionsBarComponent,
3352
+ NodeSearchPanelComponent], imports: [CommonModule,
3353
+ FormsModule,
3354
+ SharedModule,
3355
+ MaterialModule,
3356
+ FloatingToolbarModule], exports: [WxCCFlowchartPageComponent] });
3357
+ WxCCFlowchartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartModule, providers: [
3358
+ WxCCAPIService,
3359
+ WxCC2GraphService,
3360
+ WxCCActivityManageService,
3361
+ WxCCActivityCreationService
3362
+ ], imports: [CommonModule,
3363
+ FormsModule,
3364
+ SharedModule,
3365
+ MaterialModule,
3366
+ FloatingToolbarModule] });
3367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartModule, decorators: [{
3368
+ type: NgModule,
3369
+ args: [{
3370
+ declarations: [
3371
+ WxCCFlowchartPageComponent,
3372
+ WxCCFlowchartComponent,
3373
+ NodeDetailsSidebarComponent,
3374
+ NodeActionToolbarComponent,
3375
+ LinkNodeDialogComponent,
3376
+ WxCCFileSelectionBarComponent,
3377
+ AddNodeDialogComponent,
3378
+ WxCCActionsBarComponent,
3379
+ NodeSearchPanelComponent
3380
+ ],
3381
+ imports: [
3382
+ CommonModule,
3383
+ FormsModule,
3384
+ SharedModule,
3385
+ MaterialModule,
3386
+ FloatingToolbarModule
3387
+ ],
3388
+ exports: [
3389
+ WxCCFlowchartPageComponent
3390
+ ],
3391
+ providers: [
3392
+ WxCCAPIService,
3393
+ WxCC2GraphService,
3394
+ WxCCActivityManageService,
3395
+ WxCCActivityCreationService
3396
+ ],
3397
+ entryComponents: [
3398
+ AddNodeDialogComponent,
3399
+ LinkNodeDialogComponent
3400
+ ]
3401
+ }]
3402
+ }] });
3403
+
433
3404
  /**
434
3405
  * Generated bundle index. Do not edit.
435
3406
  */
436
3407
 
437
- export { CcReadinessModule, LicencesRequirementComponent, SummaryGridComponent };
3408
+ export { CcReadinessModule, LicencesRequirementComponent, SummaryGridComponent, WxCCFlowchartModule, WxCCFlowchartPageComponent };
438
3409
  //# sourceMappingURL=tuki-io-tuki-widgets-contact-center.mjs.map