concepto-user-controls 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/esm2022/lib/concepto-context-menu/concepto-context-menu.component.mjs +3 -7
  2. package/esm2022/lib/concepto-tree/components/tree-node/tree-node.component.mjs +301 -0
  3. package/esm2022/lib/concepto-tree/components/tree-node-checkbox/tree-node-checkbox.component.mjs +90 -0
  4. package/esm2022/lib/concepto-tree/components/tree-node-content/tree-node-content.component.mjs +65 -0
  5. package/esm2022/lib/concepto-tree/components/tree-node-expander/tree-node-expander.component.mjs +74 -0
  6. package/esm2022/lib/concepto-tree/components/tree-root/tree-root.component.mjs +230 -0
  7. package/esm2022/lib/concepto-tree/components/tree-viewport/tree-viewport.component.mjs +216 -0
  8. package/esm2022/lib/concepto-tree/concepto-tree.component.mjs +220 -0
  9. package/esm2022/lib/concepto-tree/core/models/tree-events.model.mjs +2 -0
  10. package/esm2022/lib/concepto-tree/core/models/tree-node.model.mjs +102 -0
  11. package/esm2022/lib/concepto-tree/core/models/tree-options.model.mjs +24 -0
  12. package/esm2022/lib/concepto-tree/core/models/tree.model.mjs +313 -0
  13. package/esm2022/lib/concepto-tree/core/services/tree-drag-drop.service.mjs +27 -0
  14. package/esm2022/lib/concepto-tree/directives/tree-drag.directive.mjs +69 -0
  15. package/esm2022/lib/concepto-tree/directives/tree-drop.directive.mjs +124 -0
  16. package/esm2022/lib/concepto-tree/directives/tree-node-template.directive.mjs +19 -0
  17. package/esm2022/lib/entity-comparison/components/entity-comparison.component.mjs +218 -0
  18. package/esm2022/lib/entity-comparison/core/services/entity-comparison.service.mjs +111 -0
  19. package/esm2022/public-api.mjs +4 -1
  20. package/fesm2022/concepto-user-controls.mjs +2147 -7
  21. package/fesm2022/concepto-user-controls.mjs.map +1 -1
  22. package/lib/concepto-context-menu/concepto-context-menu.component.d.ts +2 -3
  23. package/lib/concepto-tree/components/tree-node/tree-node.component.d.ts +19 -0
  24. package/lib/concepto-tree/components/tree-node-checkbox/tree-node-checkbox.component.d.ts +17 -0
  25. package/lib/concepto-tree/components/tree-node-content/tree-node-content.component.d.ts +18 -0
  26. package/lib/concepto-tree/components/tree-node-expander/tree-node-expander.component.d.ts +12 -0
  27. package/lib/concepto-tree/components/tree-root/tree-root.component.d.ts +35 -0
  28. package/lib/concepto-tree/components/tree-viewport/tree-viewport.component.d.ts +33 -0
  29. package/lib/concepto-tree/concepto-tree.component.d.ts +36 -0
  30. package/lib/concepto-tree/core/models/tree-events.model.d.ts +13 -0
  31. package/lib/concepto-tree/core/models/tree-node.model.d.ts +39 -0
  32. package/lib/concepto-tree/core/models/tree-options.model.d.ts +28 -0
  33. package/lib/concepto-tree/core/models/tree.model.d.ts +54 -0
  34. package/lib/concepto-tree/core/services/tree-drag-drop.service.d.ts +11 -0
  35. package/lib/concepto-tree/directives/tree-drag.directive.d.ts +16 -0
  36. package/lib/concepto-tree/directives/tree-drop.directive.d.ts +25 -0
  37. package/lib/concepto-tree/directives/tree-node-template.directive.d.ts +8 -0
  38. package/lib/entity-comparison/components/entity-comparison.component.d.ts +49 -0
  39. package/lib/entity-comparison/core/services/entity-comparison.service.d.ts +10 -0
  40. package/package.json +1 -1
  41. package/public-api.d.ts +3 -0
@@ -0,0 +1,218 @@
1
+ import { Component } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { EntityComparisonService } from '../core/services/entity-comparison.service';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../core/services/entity-comparison.service";
6
+ import * as i2 from "@angular/common";
7
+ export class EntityComparisonComponent {
8
+ comparisonService;
9
+ leftFile = '';
10
+ rightFile = '';
11
+ leftEntities = [];
12
+ rightEntities = [];
13
+ selectedLeftEntity = null;
14
+ selectedRightEntity = null;
15
+ comparisonResult = null;
16
+ expandedNodes = new Set();
17
+ isFullScreen = false;
18
+ currentDifferenceIndex = 0;
19
+ differences = [];
20
+ constructor(comparisonService) {
21
+ this.comparisonService = comparisonService;
22
+ }
23
+ onLeftFileSelected(event) {
24
+ const file = event.target.files[0];
25
+ if (!file)
26
+ return;
27
+ this.leftFile = file.name;
28
+ const reader = new FileReader();
29
+ reader.onload = (e) => {
30
+ const xmlContent = e.target.result;
31
+ this.leftEntities = this.comparisonService.parseEntities(xmlContent);
32
+ this.selectedLeftEntity = null;
33
+ this.comparisonResult = null;
34
+ };
35
+ reader.readAsText(file);
36
+ }
37
+ onRightFileSelected(event) {
38
+ const file = event.target.files[0];
39
+ if (!file)
40
+ return;
41
+ this.rightFile = file.name;
42
+ const reader = new FileReader();
43
+ reader.onload = (e) => {
44
+ const xmlContent = e.target.result;
45
+ this.rightEntities = this.comparisonService.parseEntities(xmlContent);
46
+ this.selectedRightEntity = null;
47
+ this.comparisonResult = null;
48
+ };
49
+ reader.readAsText(file);
50
+ }
51
+ selectLeftEntity(entity) {
52
+ this.selectedLeftEntity = entity;
53
+ this.compareIfBothSelected();
54
+ }
55
+ selectRightEntity(entity) {
56
+ this.selectedRightEntity = entity;
57
+ this.compareIfBothSelected();
58
+ }
59
+ compareIfBothSelected() {
60
+ if (this.selectedLeftEntity && this.selectedRightEntity) {
61
+ this.comparisonResult = this.comparisonService.compareStructures(this.selectedLeftEntity.structure, this.selectedRightEntity.structure);
62
+ this.buildDifferencesList();
63
+ this.currentDifferenceIndex = 0;
64
+ }
65
+ }
66
+ buildDifferencesList() {
67
+ if (!this.comparisonResult) {
68
+ this.differences = [];
69
+ return;
70
+ }
71
+ this.differences = [
72
+ ...this.comparisonResult.leftOnly.map(node => ({ node, type: 'removed' })),
73
+ ...this.comparisonResult.rightOnly.map(node => ({ node, type: 'added' })),
74
+ ...this.comparisonResult.modified.map(node => ({ node, type: 'modified' }))
75
+ ];
76
+ }
77
+ navigateToNextDifference() {
78
+ if (this.differences.length === 0)
79
+ return;
80
+ this.currentDifferenceIndex = (this.currentDifferenceIndex + 1) % this.differences.length;
81
+ this.scrollToDifference();
82
+ }
83
+ navigateToPreviousDifference() {
84
+ if (this.differences.length === 0)
85
+ return;
86
+ this.currentDifferenceIndex = this.currentDifferenceIndex === 0
87
+ ? this.differences.length - 1
88
+ : this.currentDifferenceIndex - 1;
89
+ this.scrollToDifference();
90
+ }
91
+ scrollToDifference() {
92
+ if (this.differences.length === 0)
93
+ return;
94
+ const currentDiff = this.differences[this.currentDifferenceIndex];
95
+ const nodeId = `${currentDiff.node.Id}-${currentDiff.node.name}`;
96
+ // Expand parent nodes FIRST to make the difference visible
97
+ this.expandPathToNode(currentDiff.node);
98
+ // Wait for DOM to update after expansion, then scroll
99
+ setTimeout(() => {
100
+ const leftElement = document.querySelector(`[data-node-id="left-${nodeId}"]`);
101
+ const rightElement = document.querySelector(`[data-node-id="right-${nodeId}"]`);
102
+ if (leftElement) {
103
+ leftElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
104
+ }
105
+ if (rightElement) {
106
+ rightElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
107
+ }
108
+ }, 100);
109
+ }
110
+ expandPathToNode(node) {
111
+ // Find and expand all parent nodes in both structures
112
+ this.expandParentsInStructure(this.selectedLeftEntity.structure, node, 'left');
113
+ this.expandParentsInStructure(this.selectedRightEntity.structure, node, 'right');
114
+ }
115
+ expandParentsInStructure(structure, targetNode, side) {
116
+ for (const node of structure) {
117
+ const nodeId = `${side}-${node.Id}-${node.name}`;
118
+ const targetId = `${targetNode.Id}-${targetNode.name}`;
119
+ const currentId = `${node.Id}-${node.name}`;
120
+ // If this is the target node, we found it
121
+ if (currentId === targetId) {
122
+ return true;
123
+ }
124
+ // Check children if they exist
125
+ if (this.hasChildren(node)) {
126
+ const children = this.getChildren(node);
127
+ if (this.expandParentsInStructure(children, targetNode, side)) {
128
+ // If the target is in this branch, expand this node
129
+ this.expandedNodes.add(nodeId);
130
+ return true;
131
+ }
132
+ }
133
+ }
134
+ return false;
135
+ }
136
+ get hasDifferences() {
137
+ return this.differences.length > 0;
138
+ }
139
+ get currentDifferenceNumber() {
140
+ return this.currentDifferenceIndex + 1;
141
+ }
142
+ get totalDifferences() {
143
+ return this.differences.length;
144
+ }
145
+ toggleNode(nodeId) {
146
+ if (this.expandedNodes.has(nodeId)) {
147
+ this.expandedNodes.delete(nodeId);
148
+ }
149
+ else {
150
+ this.expandedNodes.add(nodeId);
151
+ }
152
+ }
153
+ isExpanded(nodeId) {
154
+ return this.expandedNodes.has(nodeId);
155
+ }
156
+ getNodeId(node, prefix) {
157
+ return `${prefix}-${node.Id}-${node.name}`;
158
+ }
159
+ hasChildren(node) {
160
+ return node.Children && JSON.parse(node.Children).length > 0;
161
+ }
162
+ getChildren(node) {
163
+ if (!node.Children)
164
+ return [];
165
+ try {
166
+ return JSON.parse(node.Children);
167
+ }
168
+ catch {
169
+ return [];
170
+ }
171
+ }
172
+ getProperties(node) {
173
+ if (!node.Properties)
174
+ return {};
175
+ try {
176
+ return JSON.parse(node.Properties);
177
+ }
178
+ catch {
179
+ return {};
180
+ }
181
+ }
182
+ getPropertyKeys(node) {
183
+ const props = this.getProperties(node);
184
+ return Object.keys(props);
185
+ }
186
+ getChangeType(node) {
187
+ if (!this.comparisonResult)
188
+ return '';
189
+ const nodeId = `${node.Id}-${node.name}`;
190
+ if (this.comparisonResult.leftOnly.some(n => `${n.Id}-${n.name}` === nodeId)) {
191
+ return 'removed';
192
+ }
193
+ if (this.comparisonResult.rightOnly.some(n => `${n.Id}-${n.name}` === nodeId)) {
194
+ return 'added';
195
+ }
196
+ if (this.comparisonResult.modified.some(n => `${n.Id}-${n.name}` === nodeId)) {
197
+ return 'modified';
198
+ }
199
+ return 'unchanged';
200
+ }
201
+ getModifiedProperties(node) {
202
+ if (!this.comparisonResult)
203
+ return [];
204
+ const nodeId = `${node.Id}-${node.name}`;
205
+ const modified = this.comparisonResult.modified.find(n => `${n.Id}-${n.name}` === nodeId);
206
+ return modified?.modifiedProperties || [];
207
+ }
208
+ toggleFullScreen() {
209
+ this.isFullScreen = !this.isFullScreen;
210
+ }
211
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EntityComparisonComponent, deps: [{ token: i1.EntityComparisonService }], target: i0.ɵɵFactoryTarget.Component });
212
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EntityComparisonComponent, isStandalone: true, selector: "app-entity-comparison", providers: [EntityComparisonService], ngImport: i0, template: "<div class=\"comparison-container\" [class.fullscreen]=\"isFullScreen\">\r\n <header class=\"header\">\r\n <h1>Entity Structure Comparison</h1>\r\n <p class=\"subtitle\">Compare EntityStructureJson between two entity exports</p>\r\n </header>\r\n\r\n <div class=\"file-selection\">\r\n <div class=\"file-input-group\">\r\n <label class=\"file-label left\">\r\n <input type=\"file\" accept=\".xml\" (change)=\"onLeftFileSelected($event)\" hidden>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"17 8 12 3 7 8\" />\r\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\r\n </svg>\r\n Load Left Entity\r\n </label>\r\n <span *ngIf=\"leftFile\" class=\"file-name\">{{ leftFile }}</span>\r\n </div>\r\n\r\n <div class=\"vs-separator\">VS</div>\r\n\r\n <div class=\"file-input-group\">\r\n <label class=\"file-label right\">\r\n <input type=\"file\" accept=\".xml\" (change)=\"onRightFileSelected($event)\" hidden>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"17 8 12 3 7 8\" />\r\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\r\n </svg>\r\n Load Right Entity\r\n </label>\r\n <span *ngIf=\"rightFile\" class=\"file-name\">{{ rightFile }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"entity-selection\" *ngIf=\"leftEntities.length > 0 || rightEntities.length > 0\">\r\n <div class=\"entity-list\">\r\n <h3>Left Entities</h3>\r\n <div class=\"entities\">\r\n <div *ngFor=\"let entity of leftEntities\" class=\"entity-card\"\r\n [class.selected]=\"selectedLeftEntity === entity\" (click)=\"selectLeftEntity(entity)\">\r\n <div class=\"entity-icon\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\">\r\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\r\n </svg>\r\n </div>\r\n <div class=\"entity-info\">\r\n <div class=\"entity-name\">{{ entity.name }}</div>\r\n <div class=\"entity-id\">{{ entity.id }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"entity-list\">\r\n <h3>Right Entities</h3>\r\n <div class=\"entities\">\r\n <div *ngFor=\"let entity of rightEntities\" class=\"entity-card\"\r\n [class.selected]=\"selectedRightEntity === entity\" (click)=\"selectRightEntity(entity)\">\r\n <div class=\"entity-icon\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\">\r\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\r\n </svg>\r\n </div>\r\n <div class=\"entity-info\">\r\n <div class=\"entity-name\">{{ entity.name }}</div>\r\n <div class=\"entity-id\">{{ entity.id }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"summary-section\" *ngIf=\"comparisonResult\">\r\n <div class=\"summary\">\r\n <div class=\"summary-item added\">\r\n <span class=\"count\">{{ comparisonResult.rightOnly.length }}</span>\r\n <span class=\"label\">Added</span>\r\n </div>\r\n <div class=\"summary-item removed\">\r\n <span class=\"count\">{{ comparisonResult.leftOnly.length }}</span>\r\n <span class=\"label\">Removed</span>\r\n </div>\r\n <div class=\"summary-item modified\">\r\n <span class=\"count\">{{ comparisonResult.modified.length }}</span>\r\n <span class=\"label\">Modified</span>\r\n </div>\r\n <div class=\"summary-item unchanged\">\r\n <span class=\"count\">{{ comparisonResult.unchanged.length }}</span>\r\n <span class=\"label\">Unchanged</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"comparison-results\" *ngIf=\"comparisonResult\">\r\n <div class=\"results-header\">\r\n <div class=\"header-title\">\r\n <h2>Comparison Results</h2>\r\n <div class=\"header-actions\">\r\n <div class=\"diff-navigation\" *ngIf=\"hasDifferences\">\r\n <button class=\"nav-btn\" (click)=\"navigateToPreviousDifference()\" title=\"Previous Difference\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <polyline points=\"18 15 12 9 6 15\" />\r\n </svg>\r\n </button>\r\n <span class=\"diff-counter\">{{ currentDifferenceNumber }} / {{ totalDifferences }}</span>\r\n <button class=\"nav-btn\" (click)=\"navigateToNextDifference()\" title=\"Next Difference\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <button class=\"fullscreen-btn\" (click)=\"toggleFullScreen()\" [title]=\"isFullScreen ? 'Exit Full Screen' : 'Enter Full Screen'\">\r\n <svg *ngIf=\"!isFullScreen\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3\" />\r\n </svg>\r\n <svg *ngIf=\"isFullScreen\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"structure-comparison\">\r\n <div class=\"comparison-section\">\r\n <h3>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M9 11l3 3L22 4\" />\r\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\" />\r\n </svg>\r\n {{ selectedLeftEntity.name }}\r\n </h3>\r\n <div class=\"structure-tree\">\r\n <ng-container *ngFor=\"let node of selectedLeftEntity.structure\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nodeTemplate; context: { $implicit: node, side: 'left' }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"comparison-section\">\r\n <h3>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M9 11l3 3L22 4\" />\r\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\" />\r\n </svg>\r\n {{ selectedRightEntity.name }}\r\n </h3>\r\n <div class=\"structure-tree\">\r\n <ng-container *ngFor=\"let node of selectedRightEntity.structure\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nodeTemplate; context: { $implicit: node, side: 'right' }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<ng-template #nodeTemplate let-node let-side=\"side\">\r\n <div class=\"tree-node\" [class]=\"getChangeType(node)\" [attr.data-node-id]=\"getNodeId(node, side)\">\r\n <div class=\"node-header\">\r\n <button *ngIf=\"hasChildren(node)\" class=\"expand-btn\" (click)=\"toggleNode(getNodeId(node, side))\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <polyline *ngIf=\"!isExpanded(getNodeId(node, side))\" points=\"9 18 15 12 9 6\" />\r\n <polyline *ngIf=\"isExpanded(getNodeId(node, side))\" points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n <div *ngIf=\"!hasChildren(node)\" class=\"spacer\"></div>\r\n\r\n <div class=\"node-icon\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path *ngIf=\"node.nodeType === 'Group'\"\r\n d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\r\n <circle *ngIf=\"node.nodeType === 'Attribute'\" cx=\"12\" cy=\"12\" r=\"10\" />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"node-content\">\r\n <span class=\"node-name\">{{ node.name }}</span>\r\n <span class=\"node-type\">{{ node.nodeType }}</span>\r\n <span class=\"change-badge\" *ngIf=\"getChangeType(node) !== 'unchanged'\">\r\n {{ getChangeType(node) }}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"node-properties\" *ngIf=\"getPropertyKeys(node).length > 0\">\r\n <div *ngFor=\"let key of getPropertyKeys(node)\" class=\"property\"\r\n [class.modified]=\"getModifiedProperties(node).includes(key)\">\r\n <span class=\"property-key\">{{ key }}:</span>\r\n <span class=\"property-value\">{{ getProperties(node)[key] }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"node-children\" *ngIf=\"hasChildren(node) && isExpanded(getNodeId(node, side))\">\r\n <ng-container *ngFor=\"let child of getChildren(node)\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nodeTemplate; context: { $implicit: child, side: side }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</ng-template>", styles: [".comparison-container{display:flex;flex-direction:column;height:100%;width:100%;background:#f9fafb}.header{background:#fff;padding:1.5rem;border-bottom:1px solid #e5e7eb;box-shadow:0 1px 3px #0000001a}.header h1{margin:0;font-size:1.5rem;font-weight:700;color:#1f2937}.subtitle{margin:.5rem 0 0;font-size:.875rem;color:#6b7280}.file-selection{display:flex;align-items:center;gap:2rem;padding:1.5rem;background:#fff;border-bottom:1px solid #e5e7eb}.file-input-group{flex:1;display:flex;flex-direction:column;gap:.5rem}.file-label{display:inline-flex;align-items:center;gap:.5rem;padding:.75rem 1.25rem;border:2px solid #2563eb;border-radius:.5rem;cursor:pointer;font-weight:500;transition:all .2s;justify-content:center}.file-label.left{background:#fff;color:#2563eb}.file-label.left:hover{background:#eff6ff}.file-label.right{background:#fff;color:#7c3aed;border-color:#7c3aed}.file-label.right:hover{background:#f5f3ff}.file-name{font-size:.875rem;color:#6b7280;text-align:center}.vs-separator{padding:.75rem 1.5rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;font-weight:700;border-radius:2rem;font-size:1.25rem;box-shadow:0 4px 6px #0000001a}.entity-selection{display:flex;gap:1rem;padding:1rem;background:#fff;border-bottom:1px solid #e5e7eb}.entity-list{flex:1}.entity-list h3{margin:0 0 .75rem;font-size:.875rem;font-weight:600;color:#6b7280;text-transform:uppercase}.entities{display:flex;flex-direction:column;gap:.5rem}.entity-card{display:flex;align-items:center;gap:.75rem;padding:.75rem;border:1px solid #e5e7eb;border-radius:.5rem;cursor:pointer;transition:all .2s}.entity-card:hover{background:#f9fafb;border-color:#d1d5db}.entity-card.selected{background:#eff6ff;border-color:#2563eb}.entity-icon{color:#6b7280}.entity-card.selected .entity-icon{color:#2563eb}.entity-info{flex:1}.entity-name{font-size:.875rem;font-weight:500;color:#1f2937}.entity-id{font-size:.75rem;color:#6b7280}.summary-section{padding:1.5rem 1.5rem 0;background:#f9fafb}.comparison-results{flex:1;overflow:auto;padding:1.5rem}.results-header{margin-bottom:1.5rem;position:sticky;top:0;background:#f9fafb;z-index:100;padding-top:1rem;padding-bottom:1rem;margin-top:-1rem}.header-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem}.results-header h2{margin:0;font-size:1.25rem;font-weight:700;color:#1f2937}.header-actions{display:flex;align-items:center;gap:1rem}.diff-navigation{display:flex;align-items:center;gap:.5rem;background:#fff;border:1px solid #e5e7eb;border-radius:.5rem;padding:.25rem}.nav-btn{background:#fff;border:1px solid #e5e7eb;border-radius:.375rem;padding:.5rem;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;color:#6b7280}.nav-btn:hover{background:#f9fafb;border-color:#2563eb;color:#2563eb}.diff-counter{font-size:.875rem;font-weight:600;color:#1f2937;padding:0 .5rem;white-space:nowrap;min-width:60px;text-align:center}.fullscreen-btn{background:#fff;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;color:#6b7280}.fullscreen-btn:hover{background:#f9fafb;border-color:#2563eb;color:#2563eb}.summary{display:flex;gap:1rem}.summary-item{flex:1;display:flex;flex-direction:column;align-items:center;padding:1rem;border-radius:.5rem;background:#fff;border:2px solid}.summary-item.added{border-color:#10b981;background:#ecfdf5}.summary-item.removed{border-color:#ef4444;background:#fef2f2}.summary-item.modified{border-color:#f59e0b;background:#fffbeb}.summary-item.unchanged{border-color:#6b7280;background:#f9fafb}.summary-item .count{font-size:1.5rem;font-weight:700}.summary-item.added .count{color:#10b981}.summary-item.removed .count{color:#ef4444}.summary-item.modified .count{color:#f59e0b}.summary-item.unchanged .count{color:#6b7280}.summary-item .label{font-size:.75rem;font-weight:600;text-transform:uppercase;margin-top:.25rem}.structure-comparison{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;height:100%}.comparison-section{background:#fff;border-radius:.5rem;padding:1rem;border:1px solid #e5e7eb;min-width:0;width:100%;overflow:auto}.comparison-section h3{display:flex;align-items:center;gap:.5rem;margin:0 0 1rem;font-size:1rem;font-weight:600;color:#1f2937;padding-bottom:.75rem;border-bottom:1px solid #e5e7eb}.structure-tree{display:flex;flex-direction:column;gap:.5rem}.tree-node{border-left:3px solid transparent;padding-left:.5rem;transition:all .2s;max-width:100%;overflow:hidden}.tree-node.added{background:#ecfdf5;border-left-color:#10b981}.tree-node.removed{background:#fef2f2;border-left-color:#ef4444}.tree-node.modified{background:#fffbeb;border-left-color:#f59e0b}.node-header{display:flex;align-items:center;gap:.5rem;padding:.5rem;border-radius:.375rem}.expand-btn{background:none;border:none;cursor:pointer;padding:.25rem;display:flex;align-items:center;justify-content:center;border-radius:.25rem;transition:background .2s}.expand-btn:hover{background:#f3f4f6}.spacer{width:24px}.node-icon{color:#6b7280}.node-content{display:flex;align-items:center;gap:.5rem;flex:1}.node-name{font-size:.875rem;font-weight:500;color:#1f2937}.node-type{font-size:.75rem;color:#6b7280;background:#f3f4f6;padding:.125rem .5rem;border-radius:.25rem}.change-badge{font-size:.625rem;font-weight:600;text-transform:uppercase;padding:.125rem .5rem;border-radius:.25rem;margin-left:auto}.tree-node.added .change-badge{background:#10b981;color:#fff}.tree-node.removed .change-badge{background:#ef4444;color:#fff}.tree-node.modified .change-badge{background:#f59e0b;color:#fff}.node-properties{margin-left:2.5rem;margin-top:.5rem;padding:.5rem;background:#f9fafb;border-radius:.375rem;font-size:.75rem;max-width:100%;overflow:hidden}.property{display:flex;flex-wrap:wrap;gap:.5rem;padding:.25rem 0;max-width:100%;overflow:hidden}.property.modified{background:#fef3c7;padding:.25rem .5rem;border-radius:.25rem;margin:.125rem 0}.property-key{font-weight:600;color:#374151;flex-shrink:0}.property-value{color:#6b7280;word-break:break-word;overflow:auto;overflow-wrap:break-word;flex:1;min-width:0}.node-children{margin-left:1.5rem;margin-top:.5rem;display:flex;flex-direction:column;gap:.5rem}.comparison-container.fullscreen{position:fixed;inset:0;z-index:9999;background:#f9fafb}.comparison-container.fullscreen .header,.comparison-container.fullscreen .file-selection,.comparison-container.fullscreen .entity-selection,.comparison-container.fullscreen .summary-section{display:none}.comparison-container.fullscreen .comparison-results{height:100vh;padding:2rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
213
+ }
214
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EntityComparisonComponent, decorators: [{
215
+ type: Component,
216
+ args: [{ selector: 'app-entity-comparison', standalone: true, imports: [CommonModule], providers: [EntityComparisonService], template: "<div class=\"comparison-container\" [class.fullscreen]=\"isFullScreen\">\r\n <header class=\"header\">\r\n <h1>Entity Structure Comparison</h1>\r\n <p class=\"subtitle\">Compare EntityStructureJson between two entity exports</p>\r\n </header>\r\n\r\n <div class=\"file-selection\">\r\n <div class=\"file-input-group\">\r\n <label class=\"file-label left\">\r\n <input type=\"file\" accept=\".xml\" (change)=\"onLeftFileSelected($event)\" hidden>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"17 8 12 3 7 8\" />\r\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\r\n </svg>\r\n Load Left Entity\r\n </label>\r\n <span *ngIf=\"leftFile\" class=\"file-name\">{{ leftFile }}</span>\r\n </div>\r\n\r\n <div class=\"vs-separator\">VS</div>\r\n\r\n <div class=\"file-input-group\">\r\n <label class=\"file-label right\">\r\n <input type=\"file\" accept=\".xml\" (change)=\"onRightFileSelected($event)\" hidden>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"17 8 12 3 7 8\" />\r\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\r\n </svg>\r\n Load Right Entity\r\n </label>\r\n <span *ngIf=\"rightFile\" class=\"file-name\">{{ rightFile }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"entity-selection\" *ngIf=\"leftEntities.length > 0 || rightEntities.length > 0\">\r\n <div class=\"entity-list\">\r\n <h3>Left Entities</h3>\r\n <div class=\"entities\">\r\n <div *ngFor=\"let entity of leftEntities\" class=\"entity-card\"\r\n [class.selected]=\"selectedLeftEntity === entity\" (click)=\"selectLeftEntity(entity)\">\r\n <div class=\"entity-icon\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\">\r\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\r\n </svg>\r\n </div>\r\n <div class=\"entity-info\">\r\n <div class=\"entity-name\">{{ entity.name }}</div>\r\n <div class=\"entity-id\">{{ entity.id }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"entity-list\">\r\n <h3>Right Entities</h3>\r\n <div class=\"entities\">\r\n <div *ngFor=\"let entity of rightEntities\" class=\"entity-card\"\r\n [class.selected]=\"selectedRightEntity === entity\" (click)=\"selectRightEntity(entity)\">\r\n <div class=\"entity-icon\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\">\r\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\r\n </svg>\r\n </div>\r\n <div class=\"entity-info\">\r\n <div class=\"entity-name\">{{ entity.name }}</div>\r\n <div class=\"entity-id\">{{ entity.id }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"summary-section\" *ngIf=\"comparisonResult\">\r\n <div class=\"summary\">\r\n <div class=\"summary-item added\">\r\n <span class=\"count\">{{ comparisonResult.rightOnly.length }}</span>\r\n <span class=\"label\">Added</span>\r\n </div>\r\n <div class=\"summary-item removed\">\r\n <span class=\"count\">{{ comparisonResult.leftOnly.length }}</span>\r\n <span class=\"label\">Removed</span>\r\n </div>\r\n <div class=\"summary-item modified\">\r\n <span class=\"count\">{{ comparisonResult.modified.length }}</span>\r\n <span class=\"label\">Modified</span>\r\n </div>\r\n <div class=\"summary-item unchanged\">\r\n <span class=\"count\">{{ comparisonResult.unchanged.length }}</span>\r\n <span class=\"label\">Unchanged</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"comparison-results\" *ngIf=\"comparisonResult\">\r\n <div class=\"results-header\">\r\n <div class=\"header-title\">\r\n <h2>Comparison Results</h2>\r\n <div class=\"header-actions\">\r\n <div class=\"diff-navigation\" *ngIf=\"hasDifferences\">\r\n <button class=\"nav-btn\" (click)=\"navigateToPreviousDifference()\" title=\"Previous Difference\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <polyline points=\"18 15 12 9 6 15\" />\r\n </svg>\r\n </button>\r\n <span class=\"diff-counter\">{{ currentDifferenceNumber }} / {{ totalDifferences }}</span>\r\n <button class=\"nav-btn\" (click)=\"navigateToNextDifference()\" title=\"Next Difference\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <button class=\"fullscreen-btn\" (click)=\"toggleFullScreen()\" [title]=\"isFullScreen ? 'Exit Full Screen' : 'Enter Full Screen'\">\r\n <svg *ngIf=\"!isFullScreen\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3\" />\r\n </svg>\r\n <svg *ngIf=\"isFullScreen\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"structure-comparison\">\r\n <div class=\"comparison-section\">\r\n <h3>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M9 11l3 3L22 4\" />\r\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\" />\r\n </svg>\r\n {{ selectedLeftEntity.name }}\r\n </h3>\r\n <div class=\"structure-tree\">\r\n <ng-container *ngFor=\"let node of selectedLeftEntity.structure\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nodeTemplate; context: { $implicit: node, side: 'left' }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"comparison-section\">\r\n <h3>\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M9 11l3 3L22 4\" />\r\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\" />\r\n </svg>\r\n {{ selectedRightEntity.name }}\r\n </h3>\r\n <div class=\"structure-tree\">\r\n <ng-container *ngFor=\"let node of selectedRightEntity.structure\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nodeTemplate; context: { $implicit: node, side: 'right' }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<ng-template #nodeTemplate let-node let-side=\"side\">\r\n <div class=\"tree-node\" [class]=\"getChangeType(node)\" [attr.data-node-id]=\"getNodeId(node, side)\">\r\n <div class=\"node-header\">\r\n <button *ngIf=\"hasChildren(node)\" class=\"expand-btn\" (click)=\"toggleNode(getNodeId(node, side))\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <polyline *ngIf=\"!isExpanded(getNodeId(node, side))\" points=\"9 18 15 12 9 6\" />\r\n <polyline *ngIf=\"isExpanded(getNodeId(node, side))\" points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n <div *ngIf=\"!hasChildren(node)\" class=\"spacer\"></div>\r\n\r\n <div class=\"node-icon\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path *ngIf=\"node.nodeType === 'Group'\"\r\n d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\r\n <circle *ngIf=\"node.nodeType === 'Attribute'\" cx=\"12\" cy=\"12\" r=\"10\" />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"node-content\">\r\n <span class=\"node-name\">{{ node.name }}</span>\r\n <span class=\"node-type\">{{ node.nodeType }}</span>\r\n <span class=\"change-badge\" *ngIf=\"getChangeType(node) !== 'unchanged'\">\r\n {{ getChangeType(node) }}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"node-properties\" *ngIf=\"getPropertyKeys(node).length > 0\">\r\n <div *ngFor=\"let key of getPropertyKeys(node)\" class=\"property\"\r\n [class.modified]=\"getModifiedProperties(node).includes(key)\">\r\n <span class=\"property-key\">{{ key }}:</span>\r\n <span class=\"property-value\">{{ getProperties(node)[key] }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"node-children\" *ngIf=\"hasChildren(node) && isExpanded(getNodeId(node, side))\">\r\n <ng-container *ngFor=\"let child of getChildren(node)\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nodeTemplate; context: { $implicit: child, side: side }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</ng-template>", styles: [".comparison-container{display:flex;flex-direction:column;height:100%;width:100%;background:#f9fafb}.header{background:#fff;padding:1.5rem;border-bottom:1px solid #e5e7eb;box-shadow:0 1px 3px #0000001a}.header h1{margin:0;font-size:1.5rem;font-weight:700;color:#1f2937}.subtitle{margin:.5rem 0 0;font-size:.875rem;color:#6b7280}.file-selection{display:flex;align-items:center;gap:2rem;padding:1.5rem;background:#fff;border-bottom:1px solid #e5e7eb}.file-input-group{flex:1;display:flex;flex-direction:column;gap:.5rem}.file-label{display:inline-flex;align-items:center;gap:.5rem;padding:.75rem 1.25rem;border:2px solid #2563eb;border-radius:.5rem;cursor:pointer;font-weight:500;transition:all .2s;justify-content:center}.file-label.left{background:#fff;color:#2563eb}.file-label.left:hover{background:#eff6ff}.file-label.right{background:#fff;color:#7c3aed;border-color:#7c3aed}.file-label.right:hover{background:#f5f3ff}.file-name{font-size:.875rem;color:#6b7280;text-align:center}.vs-separator{padding:.75rem 1.5rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;font-weight:700;border-radius:2rem;font-size:1.25rem;box-shadow:0 4px 6px #0000001a}.entity-selection{display:flex;gap:1rem;padding:1rem;background:#fff;border-bottom:1px solid #e5e7eb}.entity-list{flex:1}.entity-list h3{margin:0 0 .75rem;font-size:.875rem;font-weight:600;color:#6b7280;text-transform:uppercase}.entities{display:flex;flex-direction:column;gap:.5rem}.entity-card{display:flex;align-items:center;gap:.75rem;padding:.75rem;border:1px solid #e5e7eb;border-radius:.5rem;cursor:pointer;transition:all .2s}.entity-card:hover{background:#f9fafb;border-color:#d1d5db}.entity-card.selected{background:#eff6ff;border-color:#2563eb}.entity-icon{color:#6b7280}.entity-card.selected .entity-icon{color:#2563eb}.entity-info{flex:1}.entity-name{font-size:.875rem;font-weight:500;color:#1f2937}.entity-id{font-size:.75rem;color:#6b7280}.summary-section{padding:1.5rem 1.5rem 0;background:#f9fafb}.comparison-results{flex:1;overflow:auto;padding:1.5rem}.results-header{margin-bottom:1.5rem;position:sticky;top:0;background:#f9fafb;z-index:100;padding-top:1rem;padding-bottom:1rem;margin-top:-1rem}.header-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem}.results-header h2{margin:0;font-size:1.25rem;font-weight:700;color:#1f2937}.header-actions{display:flex;align-items:center;gap:1rem}.diff-navigation{display:flex;align-items:center;gap:.5rem;background:#fff;border:1px solid #e5e7eb;border-radius:.5rem;padding:.25rem}.nav-btn{background:#fff;border:1px solid #e5e7eb;border-radius:.375rem;padding:.5rem;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;color:#6b7280}.nav-btn:hover{background:#f9fafb;border-color:#2563eb;color:#2563eb}.diff-counter{font-size:.875rem;font-weight:600;color:#1f2937;padding:0 .5rem;white-space:nowrap;min-width:60px;text-align:center}.fullscreen-btn{background:#fff;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;color:#6b7280}.fullscreen-btn:hover{background:#f9fafb;border-color:#2563eb;color:#2563eb}.summary{display:flex;gap:1rem}.summary-item{flex:1;display:flex;flex-direction:column;align-items:center;padding:1rem;border-radius:.5rem;background:#fff;border:2px solid}.summary-item.added{border-color:#10b981;background:#ecfdf5}.summary-item.removed{border-color:#ef4444;background:#fef2f2}.summary-item.modified{border-color:#f59e0b;background:#fffbeb}.summary-item.unchanged{border-color:#6b7280;background:#f9fafb}.summary-item .count{font-size:1.5rem;font-weight:700}.summary-item.added .count{color:#10b981}.summary-item.removed .count{color:#ef4444}.summary-item.modified .count{color:#f59e0b}.summary-item.unchanged .count{color:#6b7280}.summary-item .label{font-size:.75rem;font-weight:600;text-transform:uppercase;margin-top:.25rem}.structure-comparison{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;height:100%}.comparison-section{background:#fff;border-radius:.5rem;padding:1rem;border:1px solid #e5e7eb;min-width:0;width:100%;overflow:auto}.comparison-section h3{display:flex;align-items:center;gap:.5rem;margin:0 0 1rem;font-size:1rem;font-weight:600;color:#1f2937;padding-bottom:.75rem;border-bottom:1px solid #e5e7eb}.structure-tree{display:flex;flex-direction:column;gap:.5rem}.tree-node{border-left:3px solid transparent;padding-left:.5rem;transition:all .2s;max-width:100%;overflow:hidden}.tree-node.added{background:#ecfdf5;border-left-color:#10b981}.tree-node.removed{background:#fef2f2;border-left-color:#ef4444}.tree-node.modified{background:#fffbeb;border-left-color:#f59e0b}.node-header{display:flex;align-items:center;gap:.5rem;padding:.5rem;border-radius:.375rem}.expand-btn{background:none;border:none;cursor:pointer;padding:.25rem;display:flex;align-items:center;justify-content:center;border-radius:.25rem;transition:background .2s}.expand-btn:hover{background:#f3f4f6}.spacer{width:24px}.node-icon{color:#6b7280}.node-content{display:flex;align-items:center;gap:.5rem;flex:1}.node-name{font-size:.875rem;font-weight:500;color:#1f2937}.node-type{font-size:.75rem;color:#6b7280;background:#f3f4f6;padding:.125rem .5rem;border-radius:.25rem}.change-badge{font-size:.625rem;font-weight:600;text-transform:uppercase;padding:.125rem .5rem;border-radius:.25rem;margin-left:auto}.tree-node.added .change-badge{background:#10b981;color:#fff}.tree-node.removed .change-badge{background:#ef4444;color:#fff}.tree-node.modified .change-badge{background:#f59e0b;color:#fff}.node-properties{margin-left:2.5rem;margin-top:.5rem;padding:.5rem;background:#f9fafb;border-radius:.375rem;font-size:.75rem;max-width:100%;overflow:hidden}.property{display:flex;flex-wrap:wrap;gap:.5rem;padding:.25rem 0;max-width:100%;overflow:hidden}.property.modified{background:#fef3c7;padding:.25rem .5rem;border-radius:.25rem;margin:.125rem 0}.property-key{font-weight:600;color:#374151;flex-shrink:0}.property-value{color:#6b7280;word-break:break-word;overflow:auto;overflow-wrap:break-word;flex:1;min-width:0}.node-children{margin-left:1.5rem;margin-top:.5rem;display:flex;flex-direction:column;gap:.5rem}.comparison-container.fullscreen{position:fixed;inset:0;z-index:9999;background:#f9fafb}.comparison-container.fullscreen .header,.comparison-container.fullscreen .file-selection,.comparison-container.fullscreen .entity-selection,.comparison-container.fullscreen .summary-section{display:none}.comparison-container.fullscreen .comparison-results{height:100vh;padding:2rem}\n"] }]
217
+ }], ctorParameters: () => [{ type: i1.EntityComparisonService }] });
218
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWNvbXBhcmlzb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29uY2VwdG8tdXNlci1jb250cm9scy9zcmMvbGliL2VudGl0eS1jb21wYXJpc29uL2NvbXBvbmVudHMvZW50aXR5LWNvbXBhcmlzb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29uY2VwdG8tdXNlci1jb250cm9scy9zcmMvbGliL2VudGl0eS1jb21wYXJpc29uL2NvbXBvbmVudHMvZW50aXR5LWNvbXBhcmlzb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNENBQTRDLENBQUM7Ozs7QUFpQnJGLE1BQU0sT0FBTyx5QkFBeUI7SUFhaEI7SUFacEIsUUFBUSxHQUFXLEVBQUUsQ0FBQztJQUN0QixTQUFTLEdBQVcsRUFBRSxDQUFDO0lBQ3ZCLFlBQVksR0FBVSxFQUFFLENBQUM7SUFDekIsYUFBYSxHQUFVLEVBQUUsQ0FBQztJQUMxQixrQkFBa0IsR0FBUSxJQUFJLENBQUM7SUFDL0IsbUJBQW1CLEdBQVEsSUFBSSxDQUFDO0lBQ2hDLGdCQUFnQixHQUE0QixJQUFJLENBQUM7SUFDakQsYUFBYSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDbEMsWUFBWSxHQUFHLEtBQUssQ0FBQztJQUNyQixzQkFBc0IsR0FBRyxDQUFDLENBQUM7SUFDM0IsV0FBVyxHQUFVLEVBQUUsQ0FBQztJQUV4QixZQUFvQixpQkFBMEM7UUFBMUMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUF5QjtJQUFHLENBQUM7SUFFbEUsa0JBQWtCLENBQUMsS0FBVTtRQUMz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QztRQUV0QyxNQUFNLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3pDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxNQUFNLENBQUMsQ0FBQztRQUUxRixPQUFPLFFBQVEsRUFBRSxrQkFBa0IsSUFBSSxFQUFFLENBQUM7SUFDNUMsQ0FBQztJQUVELGdCQUFnQjtRQUNkLElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQ3pDLENBQUM7d0dBNU9VLHlCQUF5Qjs0RkFBekIseUJBQXlCLG9FQUp6QixDQUFDLHVCQUF1QixDQUFDLDBCQ2Z0QyxxNFdBOE1jLGkvTURoTUYsWUFBWTs7NEZBS1gseUJBQXlCO2tCQVJyQyxTQUFTOytCQUNFLHVCQUF1QixjQUNyQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLENBQUMsYUFDWixDQUFDLHVCQUF1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEVudGl0eUNvbXBhcmlzb25TZXJ2aWNlIH0gZnJvbSAnLi4vY29yZS9zZXJ2aWNlcy9lbnRpdHktY29tcGFyaXNvbi5zZXJ2aWNlJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29tcGFyaXNvblJlc3VsdCB7XHJcbiAgbGVmdE9ubHk6IGFueVtdO1xyXG4gIHJpZ2h0T25seTogYW55W107XHJcbiAgbW9kaWZpZWQ6IGFueVtdO1xyXG4gIHVuY2hhbmdlZDogYW55W107XHJcbn1cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXBwLWVudGl0eS1jb21wYXJpc29uJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxyXG4gIHByb3ZpZGVyczogW0VudGl0eUNvbXBhcmlzb25TZXJ2aWNlXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vZW50aXR5LWNvbXBhcmlzb24uY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2VudGl0eS1jb21wYXJpc29uLmNvbXBvbmVudC5jc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRW50aXR5Q29tcGFyaXNvbkNvbXBvbmVudCB7XHJcbiAgbGVmdEZpbGU6IHN0cmluZyA9ICcnO1xyXG4gIHJpZ2h0RmlsZTogc3RyaW5nID0gJyc7XHJcbiAgbGVmdEVudGl0aWVzOiBhbnlbXSA9IFtdO1xyXG4gIHJpZ2h0RW50aXRpZXM6IGFueVtdID0gW107XHJcbiAgc2VsZWN0ZWRMZWZ0RW50aXR5OiBhbnkgPSBudWxsO1xyXG4gIHNlbGVjdGVkUmlnaHRFbnRpdHk6IGFueSA9IG51bGw7XHJcbiAgY29tcGFyaXNvblJlc3VsdDogQ29tcGFyaXNvblJlc3VsdCB8IG51bGwgPSBudWxsO1xyXG4gIGV4cGFuZGVkTm9kZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcclxuICBpc0Z1bGxTY3JlZW4gPSBmYWxzZTtcclxuICBjdXJyZW50RGlmZmVyZW5jZUluZGV4ID0gMDtcclxuICBkaWZmZXJlbmNlczogYW55W10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjb21wYXJpc29uU2VydmljZTogRW50aXR5Q29tcGFyaXNvblNlcnZpY2UpIHt9XHJcblxyXG4gIG9uTGVmdEZpbGVTZWxlY3RlZChldmVudDogYW55KTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWxlOiBGaWxlID0gZXZlbnQudGFyZ2V0LmZpbGVzWzBdO1xyXG4gICAgaWYgKCFmaWxlKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5sZWZ0RmlsZSA9IGZpbGUubmFtZTtcclxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICBcclxuICAgIHJlYWRlci5vbmxvYWQgPSAoZTogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IHhtbENvbnRlbnQgPSBlLnRhcmdldC5yZXN1bHQ7XHJcbiAgICAgIHRoaXMubGVmdEVudGl0aWVzID0gdGhpcy5jb21wYXJpc29uU2VydmljZS5wYXJzZUVudGl0aWVzKHhtbENvbnRlbnQpO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkTGVmdEVudGl0eSA9IG51bGw7XHJcbiAgICAgIHRoaXMuY29tcGFyaXNvblJlc3VsdCA9IG51bGw7XHJcbiAgICB9O1xyXG4gICAgXHJcbiAgICByZWFkZXIucmVhZEFzVGV4dChmaWxlKTtcclxuICB9XHJcblxyXG4gIG9uUmlnaHRGaWxlU2VsZWN0ZWQoZXZlbnQ6IGFueSk6IHZvaWQge1xyXG4gICAgY29uc3QgZmlsZTogRmlsZSA9IGV2ZW50LnRhcmdldC5maWxlc1swXTtcclxuICAgIGlmICghZmlsZSkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMucmlnaHRGaWxlID0gZmlsZS5uYW1lO1xyXG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgIFxyXG4gICAgcmVhZGVyLm9ubG9hZCA9IChlOiBhbnkpID0+IHtcclxuICAgICAgY29uc3QgeG1sQ29udGVudCA9IGUudGFyZ2V0LnJlc3VsdDtcclxuICAgICAgdGhpcy5yaWdodEVudGl0aWVzID0gdGhpcy5jb21wYXJpc29uU2VydmljZS5wYXJzZUVudGl0aWVzKHhtbENvbnRlbnQpO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkUmlnaHRFbnRpdHkgPSBudWxsO1xyXG4gICAgICB0aGlzLmNvbXBhcmlzb25SZXN1bHQgPSBudWxsO1xyXG4gICAgfTtcclxuICAgIFxyXG4gICAgcmVhZGVyLnJlYWRBc1RleHQoZmlsZSk7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RMZWZ0RW50aXR5KGVudGl0eTogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLnNlbGVjdGVkTGVmdEVudGl0eSA9IGVudGl0eTtcclxuICAgIHRoaXMuY29tcGFyZUlmQm90aFNlbGVjdGVkKCk7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RSaWdodEVudGl0eShlbnRpdHk6IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5zZWxlY3RlZFJpZ2h0RW50aXR5ID0gZW50aXR5O1xyXG4gICAgdGhpcy5jb21wYXJlSWZCb3RoU2VsZWN0ZWQoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY29tcGFyZUlmQm90aFNlbGVjdGVkKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRMZWZ0RW50aXR5ICYmIHRoaXMuc2VsZWN0ZWRSaWdodEVudGl0eSkge1xyXG4gICAgICB0aGlzLmNvbXBhcmlzb25SZXN1bHQgPSB0aGlzLmNvbXBhcmlzb25TZXJ2aWNlLmNvbXBhcmVTdHJ1Y3R1cmVzKFxyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRMZWZ0RW50aXR5LnN0cnVjdHVyZSxcclxuICAgICAgICB0aGlzLnNlbGVjdGVkUmlnaHRFbnRpdHkuc3RydWN0dXJlXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuYnVpbGREaWZmZXJlbmNlc0xpc3QoKTtcclxuICAgICAgdGhpcy5jdXJyZW50RGlmZmVyZW5jZUluZGV4ID0gMDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnVpbGREaWZmZXJlbmNlc0xpc3QoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY29tcGFyaXNvblJlc3VsdCkge1xyXG4gICAgICB0aGlzLmRpZmZlcmVuY2VzID0gW107XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmRpZmZlcmVuY2VzID0gW1xyXG4gICAgICAuLi50aGlzLmNvbXBhcmlzb25SZXN1bHQubGVmdE9ubHkubWFwKG5vZGUgPT4gKHsgbm9kZSwgdHlwZTogJ3JlbW92ZWQnIH0pKSxcclxuICAgICAgLi4udGhpcy5jb21wYXJpc29uUmVzdWx0LnJpZ2h0T25seS5tYXAobm9kZSA9PiAoeyBub2RlLCB0eXBlOiAnYWRkZWQnIH0pKSxcclxuICAgICAgLi4udGhpcy5jb21wYXJpc29uUmVzdWx0Lm1vZGlmaWVkLm1hcChub2RlID0+ICh7IG5vZGUsIHR5cGU6ICdtb2RpZmllZCcgfSkpXHJcbiAgICBdO1xyXG4gIH1cclxuXHJcbiAgbmF2aWdhdGVUb05leHREaWZmZXJlbmNlKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZGlmZmVyZW5jZXMubGVuZ3RoID09PSAwKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5jdXJyZW50RGlmZmVyZW5jZUluZGV4ID0gKHRoaXMuY3VycmVudERpZmZlcmVuY2VJbmRleCArIDEpICUgdGhpcy5kaWZmZXJlbmNlcy5sZW5ndGg7XHJcbiAgICB0aGlzLnNjcm9sbFRvRGlmZmVyZW5jZSgpO1xyXG4gIH1cclxuXHJcbiAgbmF2aWdhdGVUb1ByZXZpb3VzRGlmZmVyZW5jZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmRpZmZlcmVuY2VzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMuY3VycmVudERpZmZlcmVuY2VJbmRleCA9IHRoaXMuY3VycmVudERpZmZlcmVuY2VJbmRleCA9PT0gMFxyXG4gICAgICA/IHRoaXMuZGlmZmVyZW5jZXMubGVuZ3RoIC0gMVxyXG4gICAgICA6IHRoaXMuY3VycmVudERpZmZlcmVuY2VJbmRleCAtIDE7XHJcbiAgICB0aGlzLnNjcm9sbFRvRGlmZmVyZW5jZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzY3JvbGxUb0RpZmZlcmVuY2UoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5kaWZmZXJlbmNlcy5sZW5ndGggPT09IDApIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBjdXJyZW50RGlmZiA9IHRoaXMuZGlmZmVyZW5jZXNbdGhpcy5jdXJyZW50RGlmZmVyZW5jZUluZGV4XTtcclxuICAgIGNvbnN0IG5vZGVJZCA9IGAke2N1cnJlbnREaWZmLm5vZGUuSWR9LSR7Y3VycmVudERpZmYubm9kZS5uYW1lfWA7XHJcblxyXG4gICAgLy8gRXhwYW5kIHBhcmVudCBub2RlcyBGSVJTVCB0byBtYWtlIHRoZSBkaWZmZXJlbmNlIHZpc2libGVcclxuICAgIHRoaXMuZXhwYW5kUGF0aFRvTm9kZShjdXJyZW50RGlmZi5ub2RlKTtcclxuXHJcbiAgICAvLyBXYWl0IGZvciBET00gdG8gdXBkYXRlIGFmdGVyIGV4cGFuc2lvbiwgdGhlbiBzY3JvbGxcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICBjb25zdCBsZWZ0RWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYFtkYXRhLW5vZGUtaWQ9XCJsZWZ0LSR7bm9kZUlkfVwiXWApO1xyXG4gICAgICBjb25zdCByaWdodEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBbZGF0YS1ub2RlLWlkPVwicmlnaHQtJHtub2RlSWR9XCJdYCk7XHJcblxyXG4gICAgICBpZiAobGVmdEVsZW1lbnQpIHtcclxuICAgICAgICBsZWZ0RWxlbWVudC5zY3JvbGxJbnRvVmlldyh7IGJlaGF2aW9yOiAnc21vb3RoJywgYmxvY2s6ICdjZW50ZXInIH0pO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChyaWdodEVsZW1lbnQpIHtcclxuICAgICAgICByaWdodEVsZW1lbnQuc2Nyb2xsSW50b1ZpZXcoeyBiZWhhdmlvcjogJ3Ntb290aCcsIGJsb2NrOiAnY2VudGVyJyB9KTtcclxuICAgICAgfVxyXG4gICAgfSwgMTAwKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXhwYW5kUGF0aFRvTm9kZShub2RlOiBhbnkpOiB2b2lkIHtcclxuICAgIC8vIEZpbmQgYW5kIGV4cGFuZCBhbGwgcGFyZW50IG5vZGVzIGluIGJvdGggc3RydWN0dXJlc1xyXG4gICAgdGhpcy5leHBhbmRQYXJlbnRzSW5TdHJ1Y3R1cmUodGhpcy5zZWxlY3RlZExlZnRFbnRpdHkuc3RydWN0dXJlLCBub2RlLCAnbGVmdCcpO1xyXG4gICAgdGhpcy5leHBhbmRQYXJlbnRzSW5TdHJ1Y3R1cmUodGhpcy5zZWxlY3RlZFJpZ2h0RW50aXR5LnN0cnVjdHVyZSwgbm9kZSwgJ3JpZ2h0Jyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGV4cGFuZFBhcmVudHNJblN0cnVjdHVyZShzdHJ1Y3R1cmU6IGFueVtdLCB0YXJnZXROb2RlOiBhbnksIHNpZGU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgZm9yIChjb25zdCBub2RlIG9mIHN0cnVjdHVyZSkge1xyXG4gICAgICBjb25zdCBub2RlSWQgPSBgJHtzaWRlfS0ke25vZGUuSWR9LSR7bm9kZS5uYW1lfWA7XHJcbiAgICAgIGNvbnN0IHRhcmdldElkID0gYCR7dGFyZ2V0Tm9kZS5JZH0tJHt0YXJnZXROb2RlLm5hbWV9YDtcclxuICAgICAgY29uc3QgY3VycmVudElkID0gYCR7bm9kZS5JZH0tJHtub2RlLm5hbWV9YDtcclxuXHJcbiAgICAgIC8vIElmIHRoaXMgaXMgdGhlIHRhcmdldCBub2RlLCB3ZSBmb3VuZCBpdFxyXG4gICAgICBpZiAoY3VycmVudElkID09PSB0YXJnZXRJZCkge1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDaGVjayBjaGlsZHJlbiBpZiB0aGV5IGV4aXN0XHJcbiAgICAgIGlmICh0aGlzLmhhc0NoaWxkcmVuKG5vZGUpKSB7XHJcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLmdldENoaWxkcmVuKG5vZGUpO1xyXG4gICAgICAgIGlmICh0aGlzLmV4cGFuZFBhcmVudHNJblN0cnVjdHVyZShjaGlsZHJlbiwgdGFyZ2V0Tm9kZSwgc2lkZSkpIHtcclxuICAgICAgICAgIC8vIElmIHRoZSB0YXJnZXQgaXMgaW4gdGhpcyBicmFuY2gsIGV4cGFuZCB0aGlzIG5vZGVcclxuICAgICAgICAgIHRoaXMuZXhwYW5kZWROb2Rlcy5hZGQobm9kZUlkKTtcclxuICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIGdldCBoYXNEaWZmZXJlbmNlcygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmRpZmZlcmVuY2VzLmxlbmd0aCA+IDA7XHJcbiAgfVxyXG5cclxuICBnZXQgY3VycmVudERpZmZlcmVuY2VOdW1iZXIoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmN1cnJlbnREaWZmZXJlbmNlSW5kZXggKyAxO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHRvdGFsRGlmZmVyZW5jZXMoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmRpZmZlcmVuY2VzLmxlbmd0aDtcclxuICB9XHJcblxyXG4gIHRvZ2dsZU5vZGUobm9kZUlkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmV4cGFuZGVkTm9kZXMuaGFzKG5vZGVJZCkpIHtcclxuICAgICAgdGhpcy5leHBhbmRlZE5vZGVzLmRlbGV0ZShub2RlSWQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5leHBhbmRlZE5vZGVzLmFkZChub2RlSWQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaXNFeHBhbmRlZChub2RlSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZXhwYW5kZWROb2Rlcy5oYXMobm9kZUlkKTtcclxuICB9XHJcblxyXG4gIGdldE5vZGVJZChub2RlOiBhbnksIHByZWZpeDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBgJHtwcmVmaXh9LSR7bm9kZS5JZH0tJHtub2RlLm5hbWV9YDtcclxuICB9XHJcblxyXG4gIGhhc0NoaWxkcmVuKG5vZGU6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIG5vZGUuQ2hpbGRyZW4gJiYgSlNPTi5wYXJzZShub2RlLkNoaWxkcmVuKS5sZW5ndGggPiAwO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q2hpbGRyZW4obm9kZTogYW55KTogYW55W10ge1xyXG4gICAgaWYgKCFub2RlLkNoaWxkcmVuKSByZXR1cm4gW107XHJcbiAgICB0cnkge1xyXG4gICAgICByZXR1cm4gSlNPTi5wYXJzZShub2RlLkNoaWxkcmVuKTtcclxuICAgIH0gY2F0Y2gge1xyXG4gICAgICByZXR1cm4gW107XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXRQcm9wZXJ0aWVzKG5vZGU6IGFueSk6IGFueSB7XHJcbiAgICBpZiAoIW5vZGUuUHJvcGVydGllcykgcmV0dXJuIHt9O1xyXG4gICAgdHJ5IHtcclxuICAgICAgcmV0dXJuIEpTT04ucGFyc2Uobm9kZS5Qcm9wZXJ0aWVzKTtcclxuICAgIH0gY2F0Y2gge1xyXG4gICAgICByZXR1cm4ge307XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXRQcm9wZXJ0eUtleXMobm9kZTogYW55KTogc3RyaW5nW10ge1xyXG4gICAgY29uc3QgcHJvcHMgPSB0aGlzLmdldFByb3BlcnRpZXMobm9kZSk7XHJcbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvcHMpO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q2hhbmdlVHlwZShub2RlOiBhbnkpOiBzdHJpbmcge1xyXG4gICAgaWYgKCF0aGlzLmNvbXBhcmlzb25SZXN1bHQpIHJldHVybiAnJztcclxuICAgIFxyXG4gICAgY29uc3Qgbm9kZUlkID0gYCR7bm9kZS5JZH0tJHtub2RlLm5hbWV9YDtcclxuICAgIFxyXG4gICAgaWYgKHRoaXMuY29tcGFyaXNvblJlc3VsdC5sZWZ0T25seS5zb21lKG4gPT4gYCR7bi5JZH0tJHtuLm5hbWV9YCA9PT0gbm9kZUlkKSkge1xyXG4gICAgICByZXR1cm4gJ3JlbW92ZWQnO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuY29tcGFyaXNvblJlc3VsdC5yaWdodE9ubHkuc29tZShuID0+IGAke24uSWR9LSR7bi5uYW1lfWAgPT09IG5vZGVJZCkpIHtcclxuICAgICAgcmV0dXJuICdhZGRlZCc7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5jb21wYXJpc29uUmVzdWx0Lm1vZGlmaWVkLnNvbWUobiA9PiBgJHtuLklkfS0ke24ubmFtZX1gID09PSBub2RlSWQpKSB7XHJcbiAgICAgIHJldHVybiAnbW9kaWZpZWQnO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuICd1bmNoYW5nZWQnO1xyXG4gIH1cclxuXHJcbiAgZ2V0TW9kaWZpZWRQcm9wZXJ0aWVzKG5vZGU6IGFueSk6IHN0cmluZ1tdIHtcclxuICAgIGlmICghdGhpcy5jb21wYXJpc29uUmVzdWx0KSByZXR1cm4gW107XHJcblxyXG4gICAgY29uc3Qgbm9kZUlkID0gYCR7bm9kZS5JZH0tJHtub2RlLm5hbWV9YDtcclxuICAgIGNvbnN0IG1vZGlmaWVkID0gdGhpcy5jb21wYXJpc29uUmVzdWx0Lm1vZGlmaWVkLmZpbmQobiA9PiBgJHtuLklkfS0ke24ubmFtZX1gID09PSBub2RlSWQpO1xyXG5cclxuICAgIHJldHVybiBtb2RpZmllZD8ubW9kaWZpZWRQcm9wZXJ0aWVzIHx8IFtdO1xyXG4gIH1cclxuXHJcbiAgdG9nZ2xlRnVsbFNjcmVlbigpOiB2b2lkIHtcclxuICAgIHRoaXMuaXNGdWxsU2NyZWVuID0gIXRoaXMuaXNGdWxsU2NyZWVuO1xyXG4gIH1cclxufSIsIjxkaXYgY2xhc3M9XCJjb21wYXJpc29uLWNvbnRhaW5lclwiIFtjbGFzcy5mdWxsc2NyZWVuXT1cImlzRnVsbFNjcmVlblwiPlxyXG4gICAgPGhlYWRlciBjbGFzcz1cImhlYWRlclwiPlxyXG4gICAgICAgIDxoMT5FbnRpdHkgU3RydWN0dXJlIENvbXBhcmlzb248L2gxPlxyXG4gICAgICAgIDxwIGNsYXNzPVwic3VidGl0bGVcIj5Db21wYXJlIEVudGl0eVN0cnVjdHVyZUpzb24gYmV0d2VlbiB0d28gZW50aXR5IGV4cG9ydHM8L3A+XHJcbiAgICA8L2hlYWRlcj5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwiZmlsZS1zZWxlY3Rpb25cIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmlsZS1pbnB1dC1ncm91cFwiPlxyXG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmaWxlLWxhYmVsIGxlZnRcIj5cclxuICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIGFjY2VwdD1cIi54bWxcIiAoY2hhbmdlKT1cIm9uTGVmdEZpbGVTZWxlY3RlZCgkZXZlbnQpXCIgaGlkZGVuPlxyXG4gICAgICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBzdHJva2Utd2lkdGg9XCIyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0yMSAxNXY0YTIgMiAwIDAgMS0yIDJINWEyIDIgMCAwIDEtMi0ydi00XCIgLz5cclxuICAgICAgICAgICAgICAgICAgICA8cG9seWxpbmUgcG9pbnRzPVwiMTcgOCAxMiAzIDcgOFwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgPGxpbmUgeDE9XCIxMlwiIHkxPVwiM1wiIHgyPVwiMTJcIiB5Mj1cIjE1XCIgLz5cclxuICAgICAgICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgTG9hZCBMZWZ0IEVudGl0eVxyXG4gICAgICAgICAgICA8L2xhYmVsPlxyXG4gICAgICAgICAgICA8c3BhbiAqbmdJZj1cImxlZnRGaWxlXCIgY2xhc3M9XCJmaWxlLW5hbWVcIj57eyBsZWZ0RmlsZSB9fTwvc3Bhbj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInZzLXNlcGFyYXRvclwiPlZTPC9kaXY+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWxlLWlucHV0LWdyb3VwXCI+XHJcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpbGUtbGFiZWwgcmlnaHRcIj5cclxuICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIGFjY2VwdD1cIi54bWxcIiAoY2hhbmdlKT1cIm9uUmlnaHRGaWxlU2VsZWN0ZWQoJGV2ZW50KVwiIGhpZGRlbj5cclxuICAgICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMjEgMTV2NGEyIDIgMCAwIDEtMiAySDVhMiAyIDAgMCAxLTItMnYtNFwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgPHBvbHlsaW5lIHBvaW50cz1cIjE3IDggMTIgMyA3IDhcIiAvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxsaW5lIHgxPVwiMTJcIiB5MT1cIjNcIiB4Mj1cIjEyXCIgeTI9XCIxNVwiIC8+XHJcbiAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgIExvYWQgUmlnaHQgRW50aXR5XHJcbiAgICAgICAgICAgIDwvbGFiZWw+XHJcbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwicmlnaHRGaWxlXCIgY2xhc3M9XCJmaWxlLW5hbWVcIj57eyByaWdodEZpbGUgfX08L3NwYW4+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwiZW50aXR5LXNlbGVjdGlvblwiICpuZ0lmPVwibGVmdEVudGl0aWVzLmxlbmd0aCA+IDAgfHwgcmlnaHRFbnRpdGllcy5sZW5ndGggPiAwXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImVudGl0eS1saXN0XCI+XHJcbiAgICAgICAgICAgIDxoMz5MZWZ0IEVudGl0aWVzPC9oMz5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImVudGl0aWVzXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBlbnRpdHkgb2YgbGVmdEVudGl0aWVzXCIgY2xhc3M9XCJlbnRpdHktY2FyZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2NsYXNzLnNlbGVjdGVkXT1cInNlbGVjdGVkTGVmdEVudGl0eSA9PT0gZW50aXR5XCIgKGNsaWNrKT1cInNlbGVjdExlZnRFbnRpdHkoZW50aXR5KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbnRpdHktaWNvblwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2Utd2lkdGg9XCIyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTIyIDE5YTIgMiAwIDAgMS0yIDJINGEyIDIgMCAwIDEtMi0yVjVhMiAyIDAgMCAxIDItMmg1bDIgM2g5YTIgMiAwIDAgMSAyIDJ6XCIgLz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImVudGl0eS1pbmZvXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbnRpdHktbmFtZVwiPnt7IGVudGl0eS5uYW1lIH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbnRpdHktaWRcIj57eyBlbnRpdHkuaWQgfX08L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImVudGl0eS1saXN0XCI+XHJcbiAgICAgICAgICAgIDxoMz5SaWdodCBFbnRpdGllczwvaDM+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbnRpdGllc1wiPlxyXG4gICAgICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZW50aXR5IG9mIHJpZ2h0RW50aXRpZXNcIiBjbGFzcz1cImVudGl0eS1jYXJkXCJcclxuICAgICAgICAgICAgICAgICAgICBbY2xhc3Muc2VsZWN0ZWRdPVwic2VsZWN0ZWRSaWdodEVudGl0eSA9PT0gZW50aXR5XCIgKGNsaWNrKT1cInNlbGVjdFJpZ2h0RW50aXR5KGVudGl0eSlcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZW50aXR5LWljb25cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjIwXCIgaGVpZ2h0PVwiMjBcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0yMiAxOWEyIDIgMCAwIDEtMiAySDRhMiAyIDAgMCAxLTItMlY1YTIgMiAwIDAgMSAyLTJoNWwyIDNoOWEyIDIgMCAwIDEgMiAyelwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbnRpdHktaW5mb1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZW50aXR5LW5hbWVcIj57eyBlbnRpdHkubmFtZSB9fTwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZW50aXR5LWlkXCI+e3sgZW50aXR5LmlkIH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1zZWN0aW9uXCIgKm5nSWY9XCJjb21wYXJpc29uUmVzdWx0XCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInN1bW1hcnlcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN1bW1hcnktaXRlbSBhZGRlZFwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjb3VudFwiPnt7IGNvbXBhcmlzb25SZXN1bHQucmlnaHRPbmx5Lmxlbmd0aCB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWxcIj5BZGRlZDwvc3Bhbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdW1tYXJ5LWl0ZW0gcmVtb3ZlZFwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjb3VudFwiPnt7IGNvbXBhcmlzb25SZXN1bHQubGVmdE9ubHkubGVuZ3RoIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbFwiPlJlbW92ZWQ8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1pdGVtIG1vZGlmaWVkXCI+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNvdW50XCI+e3sgY29tcGFyaXNvblJlc3VsdC5tb2RpZmllZC5sZW5ndGggfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsXCI+TW9kaWZpZWQ8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1pdGVtIHVuY2hhbmdlZFwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjb3VudFwiPnt7IGNvbXBhcmlzb25SZXN1bHQudW5jaGFuZ2VkLmxlbmd0aCB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWxcIj5VbmNoYW5nZWQ8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cImNvbXBhcmlzb24tcmVzdWx0c1wiICpuZ0lmPVwiY29tcGFyaXNvblJlc3VsdFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJyZXN1bHRzLWhlYWRlclwiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLXRpdGxlXCI+XHJcbiAgICAgICAgICAgICAgICA8aDI+Q29tcGFyaXNvbiBSZXN1bHRzPC9oMj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItYWN0aW9uc1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaWZmLW5hdmlnYXRpb25cIiAqbmdJZj1cImhhc0RpZmZlcmVuY2VzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJuYXYtYnRuXCIgKGNsaWNrKT1cIm5hdmlnYXRlVG9QcmV2aW91c0RpZmZlcmVuY2UoKVwiIHRpdGxlPVwiUHJldmlvdXMgRGlmZmVyZW5jZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjIwXCIgaGVpZ2h0PVwiMjBcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBzdHJva2Utd2lkdGg9XCIyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBvbHlsaW5lIHBvaW50cz1cIjE4IDE1IDEyIDkgNiAxNVwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZGlmZi1jb3VudGVyXCI+e3sgY3VycmVudERpZmZlcmVuY2VOdW1iZXIgfX0gLyB7eyB0b3RhbERpZmZlcmVuY2VzIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwibmF2LWJ0blwiIChjbGljayk9XCJuYXZpZ2F0ZVRvTmV4dERpZmZlcmVuY2UoKVwiIHRpdGxlPVwiTmV4dCBEaWZmZXJlbmNlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cG9seWxpbmUgcG9pbnRzPVwiNiA5IDEyIDE1IDE4IDlcIiAvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJmdWxsc2NyZWVuLWJ0blwiIChjbGljayk9XCJ0b2dnbGVGdWxsU2NyZWVuKClcIiBbdGl0bGVdPVwiaXNGdWxsU2NyZWVuID8gJ0V4aXQgRnVsbCBTY3JlZW4nIDogJ0VudGVyIEZ1bGwgU2NyZWVuJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3ZnICpuZ0lmPVwiIWlzRnVsbFNjcmVlblwiIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNOCAzSDVhMiAyIDAgMCAwLTIgMnYzbTE4IDBWNWEyIDIgMCAwIDAtMi0yaC0zbTAgMThoM2EyIDIgMCAwIDAgMi0ydi0zTTMgMTZ2M2EyIDIgMCAwIDAgMiAyaDNcIiAvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyAqbmdJZj1cImlzRnVsbFNjcmVlblwiIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNOCAzdjNhMiAyIDAgMCAxLTIgMkgzbTE4IDBoLTNhMiAyIDAgMCAxLTItMlYzbTAgMTh2LTNhMiAyIDAgMCAxIDItMmgzTTMgMTZoM2EyIDIgMCAwIDEgMiAydjNcIiAvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInN0cnVjdHVyZS1jb21wYXJpc29uXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb21wYXJpc29uLXNlY3Rpb25cIj5cclxuICAgICAgICAgICAgICAgIDxoMz5cclxuICAgICAgICAgICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk05IDExbDMgM0wyMiA0XCIgLz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0yMSAxMnY3YTIgMiAwIDAgMS0yIDJINWEyIDIgMCAwIDEtMi0yVjVhMiAyIDAgMCAxIDItMmgxMVwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAge3sgc2VsZWN0ZWRMZWZ0RW50aXR5Lm5hbWUgfX1cclxuICAgICAgICAgICAgICAgIDwvaDM+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RydWN0dXJlLXRyZWVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBub2RlIG9mIHNlbGVjdGVkTGVmdEVudGl0eS5zdHJ1Y3R1cmVcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJub2RlVGVtcGxhdGU7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBub2RlLCBzaWRlOiAnbGVmdCcgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbXBhcmlzb24tc2VjdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgPGgzPlxyXG4gICAgICAgICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTkgMTFsMyAzTDIyIDRcIiAvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTIxIDEydjdhMiAyIDAgMCAxLTIgMkg1YTIgMiAwIDAgMS0yLTJWNWEyIDIgMCAwIDEgMi0yaDExXCIgLz5cclxuICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgICAgICB7eyBzZWxlY3RlZFJpZ2h0RW50aXR5Lm5hbWUgfX1cclxuICAgICAgICAgICAgICAgIDwvaDM+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RydWN0dXJlLXRyZWVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBub2RlIG9mIHNlbGVjdGVkUmlnaHRFbnRpdHkuc3RydWN0dXJlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwibm9kZVRlbXBsYXRlOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogbm9kZSwgc2lkZTogJ3JpZ2h0JyB9XCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48bmctdGVtcGxhdGUgI25vZGVUZW1wbGF0ZSBsZXQtbm9kZSBsZXQtc2lkZT1cInNpZGVcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJ0cmVlLW5vZGVcIiBbY2xhc3NdPVwiZ2V0Q2hhbmdlVHlwZShub2RlKVwiIFthdHRyLmRhdGEtbm9kZS1pZF09XCJnZXROb2RlSWQobm9kZSwgc2lkZSlcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibm9kZS1oZWFkZXJcIj5cclxuICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImhhc0NoaWxkcmVuKG5vZGUpXCIgY2xhc3M9XCJleHBhbmQtYnRuXCIgKGNsaWNrKT1cInRvZ2dsZU5vZGUoZ2V0Tm9kZUlkKG5vZGUsIHNpZGUpKVwiPlxyXG4gICAgICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjEyXCIgaGVpZ2h0PVwiMTJcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBzdHJva2Utd2lkdGg9XCIyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHBvbHlsaW5lICpuZ0lmPVwiIWlzRXhwYW5kZWQoZ2V0Tm9kZUlkKG5vZGUsIHNpZGUpKVwiIHBvaW50cz1cIjkgMTggMTUgMTIgOSA2XCIgLz5cclxuICAgICAgICAgICAgICAgICAgICA8cG9seWxpbmUgKm5nSWY9XCJpc0V4cGFuZGVkKGdldE5vZGVJZChub2RlLCBzaWRlKSlcIiBwb2ludHM9XCI2IDkgMTIgMTUgMTggOVwiIC8+XHJcbiAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCIhaGFzQ2hpbGRyZW4obm9kZSlcIiBjbGFzcz1cInNwYWNlclwiPjwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vZGUtaWNvblwiPlxyXG4gICAgICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBzdHJva2Utd2lkdGg9XCIyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHBhdGggKm5nSWY9XCJub2RlLm5vZGVUeXBlID09PSAnR3JvdXAnXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgZD1cIk0yMiAxOWEyIDIgMCAwIDEtMiAySDRhMiAyIDAgMCAxLTItMlY1YTIgMiAwIDAgMSAyLTJoNWwyIDNoOWEyIDIgMCAwIDEgMiAyelwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSAqbmdJZj1cIm5vZGUubm9kZVR5cGUgPT09ICdBdHRyaWJ1dGUnXCIgY3g9XCIxMlwiIGN5PVwiMTJcIiByPVwiMTBcIiAvPlxyXG4gICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vZGUtY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJub2RlLW5hbWVcIj57eyBub2RlLm5hbWUgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5vZGUtdHlwZVwiPnt7IG5vZGUubm9kZVR5cGUgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNoYW5nZS1iYWRnZVwiICpuZ0lmPVwiZ2V0Q2hhbmdlVHlwZShub2RlKSAhPT0gJ3VuY2hhbmdlZCdcIj5cclxuICAgICAgICAgICAgICAgICAgICB7eyBnZXRDaGFuZ2VUeXBlKG5vZGUpIH19XHJcbiAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibm9kZS1wcm9wZXJ0aWVzXCIgKm5nSWY9XCJnZXRQcm9wZXJ0eUtleXMobm9kZSkubGVuZ3RoID4gMFwiPlxyXG4gICAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBrZXkgb2YgZ2V0UHJvcGVydHlLZXlzKG5vZGUpXCIgY2xhc3M9XCJwcm9wZXJ0eVwiXHJcbiAgICAgICAgICAgICAgICBbY2xhc3MubW9kaWZpZWRdPVwiZ2V0TW9kaWZpZWRQcm9wZXJ0aWVzKG5vZGUpLmluY2x1ZGVzKGtleSlcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwicHJvcGVydHkta2V5XCI+e3sga2V5IH19Ojwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwicHJvcGVydHktdmFsdWVcIj57eyBnZXRQcm9wZXJ0aWVzKG5vZGUpW2tleV0gfX08L3NwYW4+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibm9kZS1jaGlsZHJlblwiICpuZ0lmPVwiaGFzQ2hpbGRyZW4obm9kZSkgJiYgaXNFeHBhbmRlZChnZXROb2RlSWQobm9kZSwgc2lkZSkpXCI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGNoaWxkIG9mIGdldENoaWxkcmVuKG5vZGUpXCI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJub2RlVGVtcGxhdGU7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBjaGlsZCwgc2lkZTogc2lkZSB9XCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+Il19
@@ -0,0 +1,111 @@
1
+ import { Injectable } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export class EntityComparisonService {
4
+ parseEntities(xmlString) {
5
+ const parser = new DOMParser();
6
+ const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
7
+ const exportItems = xmlDoc.querySelectorAll('ExportItem[Type="Entity"]');
8
+ const entities = [];
9
+ exportItems.forEach((item) => {
10
+ const entity = item.querySelector('Entity_WithoutRedundancies');
11
+ if (!entity)
12
+ return;
13
+ const structureJson = entity.querySelector('EntityStructureJson')?.textContent;
14
+ if (!structureJson)
15
+ return;
16
+ try {
17
+ const structure = JSON.parse(structureJson);
18
+ entities.push({
19
+ id: entity.querySelector('EntityId')?.textContent || '',
20
+ name: entity.querySelector('EntityName')?.textContent || '',
21
+ structure: structure
22
+ });
23
+ }
24
+ catch (e) {
25
+ console.error('Error parsing EntityStructureJson:', e);
26
+ }
27
+ });
28
+ return entities;
29
+ }
30
+ compareStructures(leftStructure, rightStructure) {
31
+ const leftOnly = [];
32
+ const rightOnly = [];
33
+ const modified = [];
34
+ const unchanged = [];
35
+ // Create maps for quick lookup
36
+ const leftMap = this.createNodeMap(leftStructure);
37
+ const rightMap = this.createNodeMap(rightStructure);
38
+ // Find nodes only in left or modified
39
+ for (const [key, leftNode] of leftMap.entries()) {
40
+ if (!rightMap.has(key)) {
41
+ leftOnly.push(leftNode);
42
+ }
43
+ else {
44
+ const rightNode = rightMap.get(key);
45
+ const diff = this.compareNodes(leftNode, rightNode);
46
+ if (diff.length > 0) {
47
+ modified.push({ ...leftNode, modifiedProperties: diff });
48
+ }
49
+ else {
50
+ unchanged.push(leftNode);
51
+ }
52
+ }
53
+ }
54
+ // Find nodes only in right
55
+ for (const [key, rightNode] of rightMap.entries()) {
56
+ if (!leftMap.has(key)) {
57
+ rightOnly.push(rightNode);
58
+ }
59
+ }
60
+ return { leftOnly, rightOnly, modified, unchanged };
61
+ }
62
+ createNodeMap(structure, parentPath = '') {
63
+ const map = new Map();
64
+ for (const node of structure) {
65
+ const nodePath = parentPath ? `${parentPath}/${node.Id}-${node.name}` : `${node.Id}-${node.name}`;
66
+ map.set(nodePath, node);
67
+ if (node.Children) {
68
+ try {
69
+ const children = JSON.parse(node.Children);
70
+ const childMap = this.createNodeMap(children, nodePath);
71
+ for (const [key, value] of childMap.entries()) {
72
+ map.set(key, value);
73
+ }
74
+ }
75
+ catch (e) {
76
+ // Ignore parsing errors
77
+ }
78
+ }
79
+ }
80
+ return map;
81
+ }
82
+ compareNodes(left, right) {
83
+ const modifiedProps = [];
84
+ try {
85
+ const leftProps = JSON.parse(left.Properties || '{}');
86
+ const rightProps = JSON.parse(right.Properties || '{}');
87
+ const allKeys = new Set([
88
+ ...Object.keys(leftProps),
89
+ ...Object.keys(rightProps)
90
+ ]);
91
+ for (const key of allKeys) {
92
+ if (leftProps[key] !== rightProps[key]) {
93
+ modifiedProps.push(key);
94
+ }
95
+ }
96
+ }
97
+ catch (e) {
98
+ // Ignore parsing errors
99
+ }
100
+ return modifiedProps;
101
+ }
102
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EntityComparisonService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
103
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EntityComparisonService, providedIn: 'root' });
104
+ }
105
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EntityComparisonService, decorators: [{
106
+ type: Injectable,
107
+ args: [{
108
+ providedIn: 'root'
109
+ }]
110
+ }] });
111
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWNvbXBhcmlzb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbmNlcHRvLXVzZXItY29udHJvbHMvc3JjL2xpYi9lbnRpdHktY29tcGFyaXNvbi9jb3JlL3NlcnZpY2VzL2VudGl0eS1jb21wYXJpc29uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFNM0MsTUFBTSxPQUFPLHVCQUF1QjtJQUVsQyxhQUFhLENBQUMsU0FBaUI7UUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUMvQixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUU3RCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUN6RSxNQUFNLFFBQVEsR0FBVSxFQUFFLENBQUM7UUFFM0IsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQzNCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsNEJBQTRCLENBQUMsQ0FBQztZQUNoRSxJQUFJLENBQUMsTUFBTTtnQkFBRSxPQUFPO1lBRXBCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMscUJBQXFCLENBQUMsRUFBRSxXQUFXLENBQUM7WUFDL0UsSUFBSSxDQUFDLGFBQWE7Z0JBQUUsT0FBTztZQUUzQixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDNUMsUUFBUSxDQUFDLElBQUksQ0FBQztvQkFDWixFQUFFLEVBQUUsTUFBTSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsRUFBRSxXQUFXLElBQUksRUFBRTtvQkFDdkQsSUFBSSxFQUFFLE1BQU0sQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLEVBQUUsV0FBVyxJQUFJLEVBQUU7b0JBQzNELFNBQVMsRUFBRSxTQUFTO2lCQUNyQixDQUFDLENBQUM7WUFDTCxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3pELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxhQUFvQixFQUFFLGNBQXFCO1FBQzNELE1BQU0sUUFBUSxHQUFVLEVBQUUsQ0FBQztRQUMzQixNQUFNLFNBQVMsR0FBVSxFQUFFLENBQUM7UUFDNUIsTUFBTSxRQUFRLEdBQVUsRUFBRSxDQUFDO1FBQzNCLE1BQU0sU0FBUyxHQUFVLEVBQUUsQ0FBQztRQUU1QiwrQkFBK0I7UUFDL0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNsRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRXBELHNDQUFzQztRQUN0QyxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDdkIsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMxQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDcEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsU0FBVSxDQUFDLENBQUM7Z0JBQ3JELElBQUksSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDcEIsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQzNELENBQUM7cUJBQU0sQ0FBQztvQkFDTixTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUMzQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCwyQkFBMkI7UUFDM0IsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQ2xELElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDNUIsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUVPLGFBQWEsQ0FBQyxTQUFnQixFQUFFLGFBQXFCLEVBQUU7UUFDN0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQWUsQ0FBQztRQUVuQyxLQUFLLE1BQU0sSUFBSSxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQzdCLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLElBQUksSUFBSSxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFFeEIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2xCLElBQUksQ0FBQztvQkFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDM0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7b0JBQ3hELEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQzt3QkFDOUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQ3RCLENBQUM7Z0JBQ0gsQ0FBQztnQkFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNYLHdCQUF3QjtnQkFDMUIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRU8sWUFBWSxDQUFDLElBQVMsRUFBRSxLQUFVO1FBQ3hDLE1BQU0sYUFBYSxHQUFhLEVBQUUsQ0FBQztRQUVuQyxJQUFJLENBQUM7WUFDSCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLENBQUM7WUFDdEQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxDQUFDO1lBRXhELE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxDQUFDO2dCQUN0QixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUN6QixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO2FBQzNCLENBQUMsQ0FBQztZQUVILEtBQUssTUFBTSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQzFCLElBQUksU0FBUyxDQUFDLEdBQUcsQ0FBQyxLQUFLLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN2QyxhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUMxQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsd0JBQXdCO1FBQzFCLENBQUM7UUFFRCxPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO3dHQS9HVSx1QkFBdUI7NEdBQXZCLHVCQUF1QixjQUZ0QixNQUFNOzs0RkFFUCx1QkFBdUI7a0JBSG5DLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21wYXJpc29uUmVzdWx0IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9lbnRpdHktY29tcGFyaXNvbi5jb21wb25lbnQnO1xyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRW50aXR5Q29tcGFyaXNvblNlcnZpY2Uge1xyXG5cclxuICBwYXJzZUVudGl0aWVzKHhtbFN0cmluZzogc3RyaW5nKTogYW55W10ge1xyXG4gICAgY29uc3QgcGFyc2VyID0gbmV3IERPTVBhcnNlcigpO1xyXG4gICAgY29uc3QgeG1sRG9jID0gcGFyc2VyLnBhcnNlRnJvbVN0cmluZyh4bWxTdHJpbmcsICd0ZXh0L3htbCcpO1xyXG4gICAgXHJcbiAgICBjb25zdCBleHBvcnRJdGVtcyA9IHhtbERvYy5xdWVyeVNlbGVjdG9yQWxsKCdFeHBvcnRJdGVtW1R5cGU9XCJFbnRpdHlcIl0nKTtcclxuICAgIGNvbnN0IGVudGl0aWVzOiBhbnlbXSA9IFtdO1xyXG4gICAgXHJcbiAgICBleHBvcnRJdGVtcy5mb3JFYWNoKChpdGVtKSA9PiB7XHJcbiAgICAgIGNvbnN0IGVudGl0eSA9IGl0ZW0ucXVlcnlTZWxlY3RvcignRW50aXR5X1dpdGhvdXRSZWR1bmRhbmNpZXMnKTtcclxuICAgICAgaWYgKCFlbnRpdHkpIHJldHVybjtcclxuICAgICAgXHJcbiAgICAgIGNvbnN0IHN0cnVjdHVyZUpzb24gPSBlbnRpdHkucXVlcnlTZWxlY3RvcignRW50aXR5U3RydWN0dXJlSnNvbicpPy50ZXh0Q29udGVudDtcclxuICAgICAgaWYgKCFzdHJ1Y3R1cmVKc29uKSByZXR1cm47XHJcbiAgICAgIFxyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGNvbnN0IHN0cnVjdHVyZSA9IEpTT04ucGFyc2Uoc3RydWN0dXJlSnNvbik7XHJcbiAgICAgICAgZW50aXRpZXMucHVzaCh7XHJcbiAgICAgICAgICBpZDogZW50aXR5LnF1ZXJ5U2VsZWN0b3IoJ0VudGl0eUlkJyk/LnRleHRDb250ZW50IHx8ICcnLFxyXG4gICAgICAgICAgbmFtZTogZW50aXR5LnF1ZXJ5U2VsZWN0b3IoJ0VudGl0eU5hbWUnKT8udGV4dENvbnRlbnQgfHwgJycsXHJcbiAgICAgICAgICBzdHJ1Y3R1cmU6IHN0cnVjdHVyZVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgcGFyc2luZyBFbnRpdHlTdHJ1Y3R1cmVKc29uOicsIGUpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIFxyXG4gICAgcmV0dXJuIGVudGl0aWVzO1xyXG4gIH1cclxuXHJcbiAgY29tcGFyZVN0cnVjdHVyZXMobGVmdFN0cnVjdHVyZTogYW55W10sIHJpZ2h0U3RydWN0dXJlOiBhbnlbXSk6IENvbXBhcmlzb25SZXN1bHQge1xyXG4gICAgY29uc3QgbGVmdE9ubHk6IGFueVtdID0gW107XHJcbiAgICBjb25zdCByaWdodE9ubHk6IGFueVtdID0gW107XHJcbiAgICBjb25zdCBtb2RpZmllZDogYW55W10gPSBbXTtcclxuICAgIGNvbnN0IHVuY2hhbmdlZDogYW55W10gPSBbXTtcclxuICAgIFxyXG4gICAgLy8gQ3JlYXRlIG1hcHMgZm9yIHF1aWNrIGxvb2t1cFxyXG4gICAgY29uc3QgbGVmdE1hcCA9IHRoaXMuY3JlYXRlTm9kZU1hcChsZWZ0U3RydWN0dXJlKTtcclxuICAgIGNvbnN0IHJpZ2h0TWFwID0gdGhpcy5jcmVhdGVOb2RlTWFwKHJpZ2h0U3RydWN0dXJlKTtcclxuICAgIFxyXG4gICAgLy8gRmluZCBub2RlcyBvbmx5IGluIGxlZnQgb3IgbW9kaWZpZWRcclxuICAgIGZvciAoY29uc3QgW2tleSwgbGVmdE5vZGVdIG9mIGxlZnRNYXAuZW50cmllcygpKSB7XHJcbiAgICAgIGlmICghcmlnaHRNYXAuaGFzKGtleSkpIHtcclxuICAgICAgICBsZWZ0T25seS5wdXNoKGxlZnROb2RlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCByaWdodE5vZGUgPSByaWdodE1hcC5nZXQoa2V5KTtcclxuICAgICAgICBjb25zdCBkaWZmID0gdGhpcy5jb21wYXJlTm9kZXMobGVmdE5vZGUsIHJpZ2h0Tm9kZSEpO1xyXG4gICAgICAgIGlmIChkaWZmLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIG1vZGlmaWVkLnB1c2goeyAuLi5sZWZ0Tm9kZSwgbW9kaWZpZWRQcm9wZXJ0aWVzOiBkaWZmIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB1bmNoYW5nZWQucHVzaChsZWZ0Tm9kZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIEZpbmQgbm9kZXMgb25seSBpbiByaWdodFxyXG4gICAgZm9yIChjb25zdCBba2V5LCByaWdodE5vZGVdIG9mIHJpZ2h0TWFwLmVudHJpZXMoKSkge1xyXG4gICAgICBpZiAoIWxlZnRNYXAuaGFzKGtleSkpIHtcclxuICAgICAgICByaWdodE9ubHkucHVzaChyaWdodE5vZGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHJldHVybiB7IGxlZnRPbmx5LCByaWdodE9ubHksIG1vZGlmaWVkLCB1bmNoYW5nZWQgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlTm9kZU1hcChzdHJ1Y3R1cmU6IGFueVtdLCBwYXJlbnRQYXRoOiBzdHJpbmcgPSAnJyk6IE1hcDxzdHJpbmcsIGFueT4ge1xyXG4gICAgY29uc3QgbWFwID0gbmV3IE1hcDxzdHJpbmcsIGFueT4oKTtcclxuICAgIFxyXG4gICAgZm9yIChjb25zdCBub2RlIG9mIHN0cnVjdHVyZSkge1xyXG4gICAgICBjb25zdCBub2RlUGF0aCA9IHBhcmVudFBhdGggPyBgJHtwYXJlbnRQYXRofS8ke25vZGUuSWR9LSR7bm9kZS5uYW1lfWAgOiBgJHtub2RlLklkfS0ke25vZGUubmFtZX1gO1xyXG4gICAgICBtYXAuc2V0KG5vZGVQYXRoLCBub2RlKTtcclxuICAgICAgXHJcbiAgICAgIGlmIChub2RlLkNoaWxkcmVuKSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIGNvbnN0IGNoaWxkcmVuID0gSlNPTi5wYXJzZShub2RlLkNoaWxkcmVuKTtcclxuICAgICAgICAgIGNvbnN0IGNoaWxkTWFwID0gdGhpcy5jcmVhdGVOb2RlTWFwKGNoaWxkcmVuLCBub2RlUGF0aCk7XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBjaGlsZE1hcC5lbnRyaWVzKCkpIHtcclxuICAgICAgICAgICAgbWFwLnNldChrZXksIHZhbHVlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAvLyBJZ25vcmUgcGFyc2luZyBlcnJvcnNcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuIG1hcDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY29tcGFyZU5vZGVzKGxlZnQ6IGFueSwgcmlnaHQ6IGFueSk6IHN0cmluZ1tdIHtcclxuICAgIGNvbnN0IG1vZGlmaWVkUHJvcHM6IHN0cmluZ1tdID0gW107XHJcbiAgICBcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IGxlZnRQcm9wcyA9IEpTT04ucGFyc2UobGVmdC5Qcm9wZXJ0aWVzIHx8ICd7fScpO1xyXG4gICAgICBjb25zdCByaWdodFByb3BzID0gSlNPTi5wYXJzZShyaWdodC5Qcm9wZXJ0aWVzIHx8ICd7fScpO1xyXG4gICAgICBcclxuICAgICAgY29uc3QgYWxsS2V5cyA9IG5ldyBTZXQoW1xyXG4gICAgICAgIC4uLk9iamVjdC5rZXlzKGxlZnRQcm9wcyksXHJcbiAgICAgICAgLi4uT2JqZWN0LmtleXMocmlnaHRQcm9wcylcclxuICAgICAgXSk7XHJcbiAgICAgIFxyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBhbGxLZXlzKSB7XHJcbiAgICAgICAgaWYgKGxlZnRQcm9wc1trZXldICE9PSByaWdodFByb3BzW2tleV0pIHtcclxuICAgICAgICAgIG1vZGlmaWVkUHJvcHMucHVzaChrZXkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAvLyBJZ25vcmUgcGFyc2luZyBlcnJvcnNcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuIG1vZGlmaWVkUHJvcHM7XHJcbiAgfVxyXG59Il19
@@ -5,4 +5,7 @@ export * from './lib/concepto-user-controls.service';
5
5
  export * from './lib/concepto-user-controls.component';
6
6
  export * from './lib/concepto-message/concepto-message.component';
7
7
  export * from './lib/concepto-context-menu/concepto-context-menu.component';
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2NvbmNlcHRvLXVzZXItY29udHJvbHMvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLHNDQUFzQyxDQUFDO0FBQ3JELGNBQWMsd0NBQXdDLENBQUM7QUFDdkQsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLDZEQUE2RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIGNvbmNlcHRvLW1lc3NhZ2VcclxuICovXHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb25jZXB0by11c2VyLWNvbnRyb2xzLnNlcnZpY2UnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb25jZXB0by11c2VyLWNvbnRyb2xzLmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbmNlcHRvLW1lc3NhZ2UvY29uY2VwdG8tbWVzc2FnZS5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb25jZXB0by1jb250ZXh0LW1lbnUvY29uY2VwdG8tY29udGV4dC1tZW51LmNvbXBvbmVudCc7Il19
8
+ export * from './lib/concepto-tree/concepto-tree.component';
9
+ export * from './lib/entity-comparison/components/entity-comparison.component';
10
+ export * from './lib/entity-comparison/core/services/entity-comparison.service';
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2NvbmNlcHRvLXVzZXItY29udHJvbHMvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLHNDQUFzQyxDQUFDO0FBQ3JELGNBQWMsd0NBQXdDLENBQUM7QUFDdkQsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLDZEQUE2RCxDQUFDO0FBQzVFLGNBQWMsNkNBQTZDLENBQUM7QUFDNUQsY0FBYyxnRUFBZ0UsQ0FBQztBQUMvRSxjQUFjLGlFQUFpRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIGNvbmNlcHRvLW1lc3NhZ2VcclxuICovXHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb25jZXB0by11c2VyLWNvbnRyb2xzLnNlcnZpY2UnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb25jZXB0by11c2VyLWNvbnRyb2xzLmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbmNlcHRvLW1lc3NhZ2UvY29uY2VwdG8tbWVzc2FnZS5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb25jZXB0by1jb250ZXh0LW1lbnUvY29uY2VwdG8tY29udGV4dC1tZW51LmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbmNlcHRvLXRyZWUvY29uY2VwdG8tdHJlZS5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9lbnRpdHktY29tcGFyaXNvbi9jb21wb25lbnRzL2VudGl0eS1jb21wYXJpc29uLmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2VudGl0eS1jb21wYXJpc29uL2NvcmUvc2VydmljZXMvZW50aXR5LWNvbXBhcmlzb24uc2VydmljZSc7Il19