@ruc-lib/org-chart 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/esm2020/index.mjs +4 -0
- package/esm2020/interfaces/org-chart.mjs +2 -0
- package/esm2020/lib/org-chart/org-chart.component.mjs +216 -0
- package/esm2020/lib/ruclib-org-chart.module.mjs +26 -0
- package/esm2020/ruc-lib-org-chart.mjs +5 -0
- package/esm2020/utils/chart-download.util.mjs +182 -0
- package/fesm2015/ruc-lib-org-chart.mjs +416 -0
- package/fesm2015/ruc-lib-org-chart.mjs.map +1 -0
- package/fesm2020/ruc-lib-org-chart.mjs +428 -0
- package/fesm2020/ruc-lib-org-chart.mjs.map +1 -0
- package/index.d.ts +2 -106
- package/interfaces/org-chart.d.ts +41 -0
- package/lib/org-chart/org-chart.component.d.ts +64 -0
- package/lib/ruclib-org-chart.module.d.ts +16 -0
- package/package.json +26 -11
- package/utils/chart-download.util.d.ts +8 -0
- package/fesm2022/ruc-lib-org-chart.mjs +0 -403
- package/fesm2022/ruc-lib-org-chart.mjs.map +0 -1
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
import * as i6 from '@angular/material/menu';
|
|
2
|
-
import { MatMenuModule } from '@angular/material/menu';
|
|
3
|
-
import * as i5 from '@angular/material/input';
|
|
4
|
-
import { MatInputModule } from '@angular/material/input';
|
|
5
|
-
import * as i4 from '@angular/material/form-field';
|
|
6
|
-
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
7
|
-
import * as i3 from '@angular/material/button';
|
|
8
|
-
import { MatButtonModule } from '@angular/material/button';
|
|
9
|
-
import * as i2 from '@angular/material/icon';
|
|
10
|
-
import { MatIconModule } from '@angular/material/icon';
|
|
11
|
-
import * as i0 from '@angular/core';
|
|
12
|
-
import { ViewChild, Input, Component } from '@angular/core';
|
|
13
|
-
import { jsPDF } from 'jspdf';
|
|
14
|
-
import html2canvas from 'html2canvas';
|
|
15
|
-
import * as i7 from 'primeng/organizationchart';
|
|
16
|
-
import { OrganizationChartModule } from 'primeng/organizationchart';
|
|
17
|
-
import * as i1 from '@angular/common';
|
|
18
|
-
import { CommonModule } from '@angular/common';
|
|
19
|
-
import * as i9 from '@angular/forms';
|
|
20
|
-
import { FormsModule } from '@angular/forms';
|
|
21
|
-
import * as i8 from 'primeng/api';
|
|
22
|
-
|
|
23
|
-
const downloadChart = (chartContainer, format) => {
|
|
24
|
-
if (!chartContainer) {
|
|
25
|
-
console.error('Chart container not found!');
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
// Capture the chart container as an image (either PNG or JPEG)
|
|
29
|
-
if (format === 'pdf') {
|
|
30
|
-
createPDF(chartContainer);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
captureElementAsImage(chartContainer, format)
|
|
34
|
-
.then((imgData) => {
|
|
35
|
-
downloadImage(imgData, format); // Download as PNG or JPEG
|
|
36
|
-
})
|
|
37
|
-
.catch(handleCanvasError);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
// Capture the element as an image and return a promise
|
|
41
|
-
const captureElementAsImage = (element, format) => {
|
|
42
|
-
return new Promise((resolve, reject) => {
|
|
43
|
-
html2canvas(element, {
|
|
44
|
-
useCORS: true,
|
|
45
|
-
scrollX: 0,
|
|
46
|
-
scrollY: -window.scrollY,
|
|
47
|
-
logging: false,
|
|
48
|
-
backgroundColor: null,
|
|
49
|
-
})
|
|
50
|
-
.then((canvas) => {
|
|
51
|
-
const imgData = canvas.toDataURL(`image/${format}`);
|
|
52
|
-
resolve(imgData);
|
|
53
|
-
})
|
|
54
|
-
.catch((error) => reject(error));
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
// Downloads the org chart as a PDF document.
|
|
58
|
-
const createPDF = (element) => {
|
|
59
|
-
html2canvas(element, {
|
|
60
|
-
useCORS: true,
|
|
61
|
-
scale: 4,
|
|
62
|
-
scrollX: 0,
|
|
63
|
-
scrollY: -window.scrollY,
|
|
64
|
-
logging: false,
|
|
65
|
-
backgroundColor: null,
|
|
66
|
-
})
|
|
67
|
-
.then((canvas) => {
|
|
68
|
-
const imgData = canvas.toDataURL('image/png'); // Capture as PNG (or you can use JPEG)
|
|
69
|
-
const pdf = new jsPDF('p', 'mm', 'a4'); // Standard A4 page size
|
|
70
|
-
// Get the dimensions of the PDF page
|
|
71
|
-
const pdfWidth = pdf.internal.pageSize.width;
|
|
72
|
-
const pdfHeight = pdf.internal.pageSize.height;
|
|
73
|
-
const canvasWidth = canvas.width;
|
|
74
|
-
const canvasHeight = canvas.height;
|
|
75
|
-
const aspectRatio = canvasWidth / canvasHeight;
|
|
76
|
-
let imgWidth = pdfWidth;
|
|
77
|
-
let imgHeight = pdfWidth / aspectRatio;
|
|
78
|
-
// If the image height exceeds the PDF page height, adjust it
|
|
79
|
-
if (imgHeight > pdfHeight) {
|
|
80
|
-
imgHeight = pdfHeight;
|
|
81
|
-
imgWidth = pdfHeight * aspectRatio;
|
|
82
|
-
}
|
|
83
|
-
// Add the image to the PDF
|
|
84
|
-
pdf.addImage(imgData, 'PNG', 0, 20, imgWidth, imgHeight); // Fit image on PDF page
|
|
85
|
-
pdf.save('organization-chart.pdf'); // Download the PDF
|
|
86
|
-
})
|
|
87
|
-
.catch(handleCanvasError);
|
|
88
|
-
};
|
|
89
|
-
// Download the captured image in the required format (PNG/JPEG)
|
|
90
|
-
const downloadImage = (imgData, format) => {
|
|
91
|
-
const link = document.createElement('a');
|
|
92
|
-
link.href = imgData;
|
|
93
|
-
link.download = `organization-chart.${format}`;
|
|
94
|
-
link.click();
|
|
95
|
-
};
|
|
96
|
-
// Error handler for any issues during canvas generation or file creation
|
|
97
|
-
const handleCanvasError = (error) => {
|
|
98
|
-
console.error('Error generating file:', error);
|
|
99
|
-
};
|
|
100
|
-
const checkPropsType = (props) => {
|
|
101
|
-
if (props.isDisplayHambergerMenu !== undefined && typeof props.isDisplayHambergerMenu !== 'boolean') {
|
|
102
|
-
console.error('Error: isDisplayHambergerMenu should be a boolean.');
|
|
103
|
-
}
|
|
104
|
-
if (props.isDisplaySearchBar !== undefined && typeof props.isDisplaySearchBar !== 'boolean') {
|
|
105
|
-
console.error('Error: isDisplaySearchBar should be a boolean.');
|
|
106
|
-
}
|
|
107
|
-
if (!['portrait', 'triangle', 'landscape'].includes(props.nodeTemplate)) {
|
|
108
|
-
console.error('Error: nodeTemplate should be "portrait", "triangle", or "landscape".');
|
|
109
|
-
}
|
|
110
|
-
if (!Array.isArray(props.hambergerMenuList)) {
|
|
111
|
-
console.error('Error: hambergerMenuList should be an array.');
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
props.hambergerMenuList.forEach(item => {
|
|
115
|
-
if (typeof item.label !== 'string') {
|
|
116
|
-
console.error('Error: hambergerMenuList label should be a string.');
|
|
117
|
-
}
|
|
118
|
-
if (typeof item.id !== 'number') {
|
|
119
|
-
console.error('Error: hambergerMenuList id should be a number.');
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
// Check if greyNodeStyle is of type CustomNodeStyle
|
|
124
|
-
const greyNodeStyle = props.greyNodeStyle;
|
|
125
|
-
if (greyNodeStyle) {
|
|
126
|
-
if (greyNodeStyle.backgroundColor && typeof greyNodeStyle.backgroundColor !== 'string') {
|
|
127
|
-
console.error('Error: greyNodeStyle.backgroundColor should be a string.');
|
|
128
|
-
}
|
|
129
|
-
if (greyNodeStyle.color && typeof greyNodeStyle.color !== 'string') {
|
|
130
|
-
console.error('Error: greyNodeStyle.color should be a string.');
|
|
131
|
-
}
|
|
132
|
-
if (greyNodeStyle.padding && typeof greyNodeStyle.padding !== 'string') {
|
|
133
|
-
console.error('Error: greyNodeStyle.padding should be a string.');
|
|
134
|
-
}
|
|
135
|
-
if (greyNodeStyle.borderRadius && typeof greyNodeStyle.borderRadius !== 'string') {
|
|
136
|
-
console.error('Error: greyNodeStyle.borderRadius should be a string.');
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// Check if orgData is an array of OrgDataItem objects
|
|
140
|
-
if (!Array.isArray(props.orgData)) {
|
|
141
|
-
console.error('Error: orgData should be an array.');
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
props.orgData.forEach(item => checkOrgDataItem(item));
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
const checkOrgDataItem = (item) => {
|
|
148
|
-
if (item.label !== undefined && typeof item.label !== 'string') {
|
|
149
|
-
console.error('Error: OrgDataItem label should be a string.');
|
|
150
|
-
}
|
|
151
|
-
if (item.expanded !== undefined && typeof item.expanded !== 'boolean') {
|
|
152
|
-
console.error('Error: OrgDataItem expanded should be a boolean.');
|
|
153
|
-
}
|
|
154
|
-
if (item.description !== undefined && typeof item.description !== 'string') {
|
|
155
|
-
console.error('Error: OrgDataItem description should be a string.');
|
|
156
|
-
}
|
|
157
|
-
if (item.customNodeStyle !== undefined) {
|
|
158
|
-
const customNodeStyle = item.customNodeStyle;
|
|
159
|
-
if (customNodeStyle.backgroundColor && typeof customNodeStyle.backgroundColor !== 'string') {
|
|
160
|
-
console.error('Error: customNodeStyle.backgroundColor should be a string.');
|
|
161
|
-
}
|
|
162
|
-
if (customNodeStyle.color && typeof customNodeStyle.color !== 'string') {
|
|
163
|
-
console.error('Error: customNodeStyle.color should be a string.');
|
|
164
|
-
}
|
|
165
|
-
if (customNodeStyle.padding && typeof customNodeStyle.padding !== 'string') {
|
|
166
|
-
console.error('Error: customNodeStyle.padding should be a string.');
|
|
167
|
-
}
|
|
168
|
-
if (customNodeStyle.borderRadius && typeof customNodeStyle.borderRadius !== 'string') {
|
|
169
|
-
console.error('Error: customNodeStyle.borderRadius should be a string.');
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
if (!item.data || typeof item.data.title !== 'string') {
|
|
173
|
-
console.error('Error: OrgDataItem data.title should be a string.');
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
if (item.data.image !== undefined && typeof item.data.image !== 'string') {
|
|
177
|
-
console.error('Error: OrgDataItem data.image should be a string.');
|
|
178
|
-
}
|
|
179
|
-
if (item.data.name !== undefined && typeof item.data.name !== 'string') {
|
|
180
|
-
console.error('Error: OrgDataItem data.name should be a string.');
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
if (item.children && Array.isArray(item.children)) {
|
|
184
|
-
item.children.forEach(child => checkOrgDataItem(child)); // Recursive call for children
|
|
185
|
-
}
|
|
186
|
-
if (item.originalStyle) {
|
|
187
|
-
const originalStyle = item.originalStyle;
|
|
188
|
-
if (originalStyle.backgroundColor && typeof originalStyle.backgroundColor !== 'string') {
|
|
189
|
-
console.error('Error: originalStyle.backgroundColor should be a string.');
|
|
190
|
-
}
|
|
191
|
-
if (originalStyle.color && typeof originalStyle.color !== 'string') {
|
|
192
|
-
console.error('Error: originalStyle.color should be a string.');
|
|
193
|
-
}
|
|
194
|
-
if (originalStyle.padding && typeof originalStyle.padding !== 'string') {
|
|
195
|
-
console.error('Error: originalStyle.padding should be a string.');
|
|
196
|
-
}
|
|
197
|
-
if (originalStyle.borderRadius && typeof originalStyle.borderRadius !== 'string') {
|
|
198
|
-
console.error('Error: originalStyle.borderRadius should be a string.');
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
class RuclibOrgChartComponent {
|
|
204
|
-
constructor() {
|
|
205
|
-
this.searchText = '';
|
|
206
|
-
this.hoveredNode = null;
|
|
207
|
-
}
|
|
208
|
-
/** Initializes the component */
|
|
209
|
-
ngOnInit() {
|
|
210
|
-
const updatedJson = this.addDefaultKeysIfNotAvailable(this.rucInputData);
|
|
211
|
-
this.rucInputData.orgData = this.updateRucInputData(updatedJson.orgData);
|
|
212
|
-
checkPropsType(this.rucInputData); // To check rucInputData is in correct format or not
|
|
213
|
-
this.expandAllNodes();
|
|
214
|
-
}
|
|
215
|
-
/** add default property for grey nodes if user does not provided */
|
|
216
|
-
addDefaultKeysIfNotAvailable(orgData) {
|
|
217
|
-
if (!orgData.hasOwnProperty('greyNodeStyle')) {
|
|
218
|
-
orgData.greyNodeStyle = {
|
|
219
|
-
backgroundColor: '#d3d3d3',
|
|
220
|
-
color: '#808080',
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
return orgData;
|
|
224
|
-
}
|
|
225
|
-
/** manipulate input json as If customNodeStyle exists, create originalStyle for node and its children */
|
|
226
|
-
updateRucInputData(data) {
|
|
227
|
-
return data.map((node) => {
|
|
228
|
-
node['type'] = 'person';
|
|
229
|
-
if (node.customNodeStyle) {
|
|
230
|
-
node.originalStyle = { ...node.customNodeStyle };
|
|
231
|
-
}
|
|
232
|
-
if (node.children && node.children.length > 0) {
|
|
233
|
-
node['type'] = 'person';
|
|
234
|
-
node.children = this.updateRucInputData(node.children); // Recursive call
|
|
235
|
-
}
|
|
236
|
-
return node;
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
/** Expands all nodes in the org chart */
|
|
240
|
-
expandAllNodes() {
|
|
241
|
-
this.rucInputData.orgData = this.expandNodes(this.rucInputData.orgData);
|
|
242
|
-
}
|
|
243
|
-
/** Recursively expands all nodes in the given array
|
|
244
|
-
* @param nodes Nodes to expand @returns Expanded nodes */
|
|
245
|
-
expandNodes(nodes) {
|
|
246
|
-
return nodes.map((node) => ({
|
|
247
|
-
...node,
|
|
248
|
-
expanded: true,
|
|
249
|
-
children: node.children ? this.expandNodes(node.children) : [],
|
|
250
|
-
}));
|
|
251
|
-
}
|
|
252
|
-
/** Collapses all nodes in the org chart */
|
|
253
|
-
collapseAllNodes() {
|
|
254
|
-
this.rucInputData.orgData = this.collapseNodes(this.rucInputData.orgData);
|
|
255
|
-
}
|
|
256
|
-
/** Recursively collapses all nodes in the given array
|
|
257
|
-
* @param nodes Nodes to collapse @returns Collapsed nodes */
|
|
258
|
-
collapseNodes(nodes) {
|
|
259
|
-
return nodes.map((node) => ({
|
|
260
|
-
...node,
|
|
261
|
-
expanded: false,
|
|
262
|
-
children: node.children ? this.collapseNodes(node.children) : [],
|
|
263
|
-
}));
|
|
264
|
-
}
|
|
265
|
-
/** Gets the background color of a node based on search text
|
|
266
|
-
@param node Node to check @returns Whether the node matches the search text */
|
|
267
|
-
getBackgroungColorOfNode(node) {
|
|
268
|
-
return (!this.searchText ||
|
|
269
|
-
node.data.title.toLowerCase().includes(this.searchText.toLowerCase()) ||
|
|
270
|
-
node.data.name.toLowerCase().includes(this.searchText.toLowerCase()) ||
|
|
271
|
-
node.label?.toLowerCase().includes(this.searchText.toLowerCase()));
|
|
272
|
-
}
|
|
273
|
-
/** Handles node hover event @param node Hovered node */
|
|
274
|
-
onNodeHover(node) {
|
|
275
|
-
if (this.searchText)
|
|
276
|
-
return;
|
|
277
|
-
this.hoveredNode = node;
|
|
278
|
-
this.updateNodeStyles();
|
|
279
|
-
}
|
|
280
|
-
/** Handles node leave event */
|
|
281
|
-
onNodeLeave() {
|
|
282
|
-
this.hoveredNode = null;
|
|
283
|
-
this.resetNodeStyles();
|
|
284
|
-
}
|
|
285
|
-
/** Updates node styles based on the hovered node */
|
|
286
|
-
updateNodeStyles() {
|
|
287
|
-
this.applyStyles(this.rucInputData.orgData, true);
|
|
288
|
-
}
|
|
289
|
-
/** Resets node styles to their original state */
|
|
290
|
-
resetNodeStyles() {
|
|
291
|
-
this.applyStyles(this.rucInputData.orgData, false);
|
|
292
|
-
}
|
|
293
|
-
/** Applies grey node style to non-matching nodes @param nodes Nodes to apply styles to */
|
|
294
|
-
applyGreyNodes(nodes) {
|
|
295
|
-
nodes.forEach((node) => {
|
|
296
|
-
const isMatching = this.searchText
|
|
297
|
-
? node.data?.title.includes(this.searchText)
|
|
298
|
-
: false;
|
|
299
|
-
node.customNodeStyle = isMatching
|
|
300
|
-
? node.customNodeStyle || node.originalStyle
|
|
301
|
-
: {
|
|
302
|
-
...node.originalStyle,
|
|
303
|
-
backgroundColor: this.rucInputData.greyNodeStyle.backgroundColor,
|
|
304
|
-
color: this.rucInputData.greyNodeStyle.color,
|
|
305
|
-
};
|
|
306
|
-
if (node.children) {
|
|
307
|
-
this.applyGreyNodes(node.children);
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
/** Applies styles to nodes based on the hovered node
|
|
312
|
-
* @param nodes Nodes to apply styles @param isHovered Whether the node is hovered */
|
|
313
|
-
applyStyles(nodes, isHovered) {
|
|
314
|
-
nodes.forEach((node) => {
|
|
315
|
-
if (isHovered) {
|
|
316
|
-
node.customNodeStyle =
|
|
317
|
-
node === this.hoveredNode ||
|
|
318
|
-
this.isParent(node, this.hoveredNode) ||
|
|
319
|
-
this.isChild(node, this.hoveredNode)
|
|
320
|
-
? node.customNodeStyle || node.originalStyle
|
|
321
|
-
: {
|
|
322
|
-
...node.originalStyle,
|
|
323
|
-
backgroundColor: this.rucInputData.greyNodeStyle.backgroundColor,
|
|
324
|
-
color: this.rucInputData.greyNodeStyle.color,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
node.customNodeStyle = node.originalStyle;
|
|
329
|
-
}
|
|
330
|
-
if (node.children) {
|
|
331
|
-
this.applyStyles(node.children, isHovered);
|
|
332
|
-
}
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
/** Use the downloadChart utility method */
|
|
336
|
-
downloadChart(format) {
|
|
337
|
-
const chartContainer = this.orgChart.el.nativeElement;
|
|
338
|
-
downloadChart(chartContainer, format); // Calls the utility function
|
|
339
|
-
}
|
|
340
|
-
/** Handles menu click event @param id Menu item ID */
|
|
341
|
-
onMenuClick(id, event) {
|
|
342
|
-
event.preventDefault();
|
|
343
|
-
event.stopPropagation();
|
|
344
|
-
switch (id) {
|
|
345
|
-
case 1:
|
|
346
|
-
this.downloadChart('pdf');
|
|
347
|
-
break;
|
|
348
|
-
case 2:
|
|
349
|
-
this.downloadChart('png');
|
|
350
|
-
break;
|
|
351
|
-
case 3:
|
|
352
|
-
this.downloadChart('jpeg');
|
|
353
|
-
break;
|
|
354
|
-
case 4:
|
|
355
|
-
this.expandAllNodes();
|
|
356
|
-
break;
|
|
357
|
-
case 5:
|
|
358
|
-
this.collapseAllNodes();
|
|
359
|
-
break;
|
|
360
|
-
default:
|
|
361
|
-
console.warn(`Unknown menu item ID: ${id}. Please enter valid id.`);
|
|
362
|
-
break;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
/** Gets tooltip data for a node @param node Node to get tooltip data */
|
|
366
|
-
getTooltipData(node) {
|
|
367
|
-
return node.description || '';
|
|
368
|
-
}
|
|
369
|
-
/** Checks if a node is a parent of another node.
|
|
370
|
-
* @param currentNode The current node to check.
|
|
371
|
-
* @param hoveredNode The node to check for parentage.
|
|
372
|
-
* @returns Whether the current node is a parent of the hovered node. */
|
|
373
|
-
isParent(currentNode, hoveredNode) {
|
|
374
|
-
return hoveredNode && currentNode.children?.includes(hoveredNode);
|
|
375
|
-
}
|
|
376
|
-
/** Checks if a node is a child of another node.
|
|
377
|
-
* @param node The node to check for child status
|
|
378
|
-
* @param target The node to check for parentage.
|
|
379
|
-
* @returns Whether the node is a child of the target node.*/
|
|
380
|
-
isChild(node, target) {
|
|
381
|
-
return target && target.children?.includes(node);
|
|
382
|
-
}
|
|
383
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RuclibOrgChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
384
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: RuclibOrgChartComponent, isStandalone: true, selector: "uxp-ruclib-org-chart", inputs: { rucInputData: "rucInputData", customTheme: "customTheme" }, viewQueries: [{ propertyName: "orgChart", first: true, predicate: ["orgChart"], descendants: true }], ngImport: i0, template: "<div class={{customTheme}}>\r\n <div class=\"container\">\r\n <!-- Hamburger Menu -->\r\n @if (rucInputData.isDisplayHambergerMenu === true) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\"\r\n class=\"left hamburger-button\">\r\n <mat-icon>menu</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- Menu -->\r\n <mat-menu #menu=\"matMenu\">\r\n @for (menu of rucInputData.hambergerMenuList; track menu) {\r\n <button mat-menu-item (click)=\"onMenuClick(menu.id, $event);\"\r\n [id]=\"'menu-item-' + menu.id\">\r\n {{ menu.label }}\r\n </button>\r\n }\r\n </mat-menu>\r\n\r\n <!-- Search Bar -->\r\n @if (rucInputData.isDisplaySearchBar === true) {\r\n <mat-form-field class=\"search-box right\"\r\n >\r\n <mat-label>Search</mat-label>\r\n <input matInput placeholder=\"Type to search...\" [(ngModel)]=\"searchText\" />\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n\r\n <div class=\"org-chart-container \" id=\"org-chart-data\">\r\n <p-organizationChart #orgChart class=\"org-chart\" [value]=\"this.rucInputData.orgData\" selectionMode=\"multiple\"\r\n [(selection)]=\"selectedNodes\">\r\n <ng-template let-node pTemplate=\"person\">\r\n @if (this.rucInputData.nodeTemplate === 'portrait') {\r\n <div class=\"flex flex-col nodeContent\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\" (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"flex flex-col items-center\" >\r\n <span>@if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"portraitImageDimension\" />\r\n }</span>\r\n <div class=\"font-bold mb-2\">{{ node.data.name }}</div>\r\n <div>{{ node.data.title }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (this.rucInputData.nodeTemplate === 'triangle') {\r\n <div class=\"flex trianlge-up flex-col nodeContent\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\" (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"flex flex-col items-center\" >\r\n @if (!node.data.image) {\r\n <div class=\"triangleImageDimension\">\r\n </div>\r\n }\r\n @if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"triangleImageDimension\" />\r\n }\r\n <div class=\"font-bold mb-2\">{{ node.data.name }}</div>\r\n <div>{{ node.data.title }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n @if (this.rucInputData.nodeTemplate === 'landscape') {\r\n <div>\r\n <div class=\"card borderSolidGrey\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\"\r\n (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"body\" >\r\n <div class=\"icon\">\r\n @if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"landscapeImageDimension\" />\r\n }\r\n </div>\r\n <div class=\"content\">\r\n <div>{{node.data.name}}</div>\r\n <div>{{node.data.title}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </p-organizationChart>\r\n </div>\r\n\r\n</div>\r\n", styles: [".org-chart-container{overflow-x:auto}.nodeContent{border:none;padding:1.5em;border-radius:\"8px\";background-color:none;color:#000}.card{display:flex;width:250px;height:100px;padding:24px;align-self:stretch;align-items:flex-start}.card .body{width:100%;display:flex}.card .body .icon{width:64px;height:64px}.trianlge-up{width:220px;background-color:#980104;clip-path:polygon(50% 0%,0% 100%,100% 100%)}mat-form-field{margin:10px}::ng-deep .p-organizationchart .p-organizationchart-node-content{border:none;background:none;color:#495057;padding:0!important}::ng-deep .p-organizationchart .p-organizationchart-node-content .p-node-toggler{background-color:#dee2e6;cursor:pointer}::ng-deep .p-organizationchart .p-organizationchart-node-content .p-node-toggler .p-node-toggler-icon{top:.2rem}.container{display:flex;justify-content:space-between;width:100%}.container .left{margin-right:auto}.container .right{margin-left:auto}mat-icon-button{margin-right:10px}.mat-form-field{margin-left:10px}.borderSolidGrey{border:1px solid lightgray}.landscapeImageDimension{width:3em;height:3em}.portraitImageDimension,.triangleImageDimension{margin-bottom:4px;width:3em;height:3em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: OrganizationChartModule }, { kind: "component", type: i7.OrganizationChart, selector: "p-organizationChart", inputs: ["value", "style", "styleClass", "selectionMode", "collapsible", "preserveSpace", "selection"], outputs: ["selectionChange", "onNodeSelect", "onNodeUnselect", "onNodeExpand", "onNodeCollapse"] }, { kind: "directive", type: i8.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i9.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i9.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i9.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
|
|
385
|
-
}
|
|
386
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RuclibOrgChartComponent, decorators: [{
|
|
387
|
-
type: Component,
|
|
388
|
-
args: [{ selector: 'uxp-ruclib-org-chart', imports: [CommonModule, MatIconModule, MatButtonModule, MatFormFieldModule, MatInputModule, MatMenuModule, OrganizationChartModule, FormsModule], template: "<div class={{customTheme}}>\r\n <div class=\"container\">\r\n <!-- Hamburger Menu -->\r\n @if (rucInputData.isDisplayHambergerMenu === true) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\"\r\n class=\"left hamburger-button\">\r\n <mat-icon>menu</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- Menu -->\r\n <mat-menu #menu=\"matMenu\">\r\n @for (menu of rucInputData.hambergerMenuList; track menu) {\r\n <button mat-menu-item (click)=\"onMenuClick(menu.id, $event);\"\r\n [id]=\"'menu-item-' + menu.id\">\r\n {{ menu.label }}\r\n </button>\r\n }\r\n </mat-menu>\r\n\r\n <!-- Search Bar -->\r\n @if (rucInputData.isDisplaySearchBar === true) {\r\n <mat-form-field class=\"search-box right\"\r\n >\r\n <mat-label>Search</mat-label>\r\n <input matInput placeholder=\"Type to search...\" [(ngModel)]=\"searchText\" />\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n\r\n <div class=\"org-chart-container \" id=\"org-chart-data\">\r\n <p-organizationChart #orgChart class=\"org-chart\" [value]=\"this.rucInputData.orgData\" selectionMode=\"multiple\"\r\n [(selection)]=\"selectedNodes\">\r\n <ng-template let-node pTemplate=\"person\">\r\n @if (this.rucInputData.nodeTemplate === 'portrait') {\r\n <div class=\"flex flex-col nodeContent\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\" (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"flex flex-col items-center\" >\r\n <span>@if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"portraitImageDimension\" />\r\n }</span>\r\n <div class=\"font-bold mb-2\">{{ node.data.name }}</div>\r\n <div>{{ node.data.title }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (this.rucInputData.nodeTemplate === 'triangle') {\r\n <div class=\"flex trianlge-up flex-col nodeContent\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\" (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"flex flex-col items-center\" >\r\n @if (!node.data.image) {\r\n <div class=\"triangleImageDimension\">\r\n </div>\r\n }\r\n @if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"triangleImageDimension\" />\r\n }\r\n <div class=\"font-bold mb-2\">{{ node.data.name }}</div>\r\n <div>{{ node.data.title }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n @if (this.rucInputData.nodeTemplate === 'landscape') {\r\n <div>\r\n <div class=\"card borderSolidGrey\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\"\r\n (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"body\" >\r\n <div class=\"icon\">\r\n @if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"landscapeImageDimension\" />\r\n }\r\n </div>\r\n <div class=\"content\">\r\n <div>{{node.data.name}}</div>\r\n <div>{{node.data.title}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </p-organizationChart>\r\n </div>\r\n\r\n</div>\r\n", styles: [".org-chart-container{overflow-x:auto}.nodeContent{border:none;padding:1.5em;border-radius:\"8px\";background-color:none;color:#000}.card{display:flex;width:250px;height:100px;padding:24px;align-self:stretch;align-items:flex-start}.card .body{width:100%;display:flex}.card .body .icon{width:64px;height:64px}.trianlge-up{width:220px;background-color:#980104;clip-path:polygon(50% 0%,0% 100%,100% 100%)}mat-form-field{margin:10px}::ng-deep .p-organizationchart .p-organizationchart-node-content{border:none;background:none;color:#495057;padding:0!important}::ng-deep .p-organizationchart .p-organizationchart-node-content .p-node-toggler{background-color:#dee2e6;cursor:pointer}::ng-deep .p-organizationchart .p-organizationchart-node-content .p-node-toggler .p-node-toggler-icon{top:.2rem}.container{display:flex;justify-content:space-between;width:100%}.container .left{margin-right:auto}.container .right{margin-left:auto}mat-icon-button{margin-right:10px}.mat-form-field{margin-left:10px}.borderSolidGrey{border:1px solid lightgray}.landscapeImageDimension{width:3em;height:3em}.portraitImageDimension,.triangleImageDimension{margin-bottom:4px;width:3em;height:3em}\n"] }]
|
|
389
|
-
}], propDecorators: { rucInputData: [{
|
|
390
|
-
type: Input
|
|
391
|
-
}], customTheme: [{
|
|
392
|
-
type: Input
|
|
393
|
-
}], orgChart: [{
|
|
394
|
-
type: ViewChild,
|
|
395
|
-
args: ['orgChart', { static: false }]
|
|
396
|
-
}] } });
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Generated bundle index. Do not edit.
|
|
400
|
-
*/
|
|
401
|
-
|
|
402
|
-
export { RuclibOrgChartComponent };
|
|
403
|
-
//# sourceMappingURL=ruc-lib-org-chart.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ruc-lib-org-chart.mjs","sources":["../../src/utils/chart-download.util.ts","../../src/lib/ruclib-org-chart/ruclib-org-chart.component.ts","../../src/lib/ruclib-org-chart/ruclib-org-chart.component.html","../../src/ruc-lib-org-chart.ts"],"sourcesContent":["import { jsPDF } from 'jspdf';\r\nimport html2canvas from 'html2canvas';\r\nimport { OrgData, OrgDataItem } from '../interfaces/org-chart';\r\n\r\n\r\nexport const downloadChart = (chartContainer: HTMLElement, format: 'png' | 'jpeg' | 'pdf'): void => {\r\n if (!chartContainer) {\r\n console.error('Chart container not found!');\r\n return;\r\n }\r\n\r\n // Capture the chart container as an image (either PNG or JPEG)\r\n if (format === 'pdf') {\r\n createPDF(chartContainer);\r\n } else {\r\n captureElementAsImage(chartContainer, format)\r\n .then((imgData) => {\r\n downloadImage(imgData, format); // Download as PNG or JPEG\r\n })\r\n .catch(handleCanvasError);\r\n }\r\n}\r\n\r\n// Capture the element as an image and return a promise\r\nexport const captureElementAsImage = (element: HTMLElement, format: 'png' | 'jpeg'): Promise<string> => {\r\n return new Promise((resolve, reject) => {\r\n html2canvas(element, {\r\n useCORS: true,\r\n scrollX: 0,\r\n scrollY: -window.scrollY,\r\n logging: false,\r\n backgroundColor: null,\r\n })\r\n .then((canvas) => {\r\n const imgData = canvas.toDataURL(`image/${format}`);\r\n resolve(imgData);\r\n })\r\n .catch((error) => reject(error));\r\n });\r\n}\r\n\r\n// Downloads the org chart as a PDF document.\r\nexport const createPDF = (element: HTMLElement): void => {\r\n html2canvas(element, {\r\n useCORS: true,\r\n scale: 4, \r\n scrollX: 0,\r\n scrollY: -window.scrollY,\r\n logging: false,\r\n backgroundColor: null,\r\n })\r\n .then((canvas) => {\r\n const imgData = canvas.toDataURL('image/png'); // Capture as PNG (or you can use JPEG)\r\n const pdf = new jsPDF('p', 'mm', 'a4'); // Standard A4 page size\r\n\r\n // Get the dimensions of the PDF page\r\n const pdfWidth = pdf.internal.pageSize.width;\r\n const pdfHeight = pdf.internal.pageSize.height;\r\n\r\n const canvasWidth = canvas.width;\r\n const canvasHeight = canvas.height;\r\n\r\n const aspectRatio = canvasWidth / canvasHeight;\r\n\r\n let imgWidth = pdfWidth;\r\n let imgHeight = pdfWidth / aspectRatio;\r\n\r\n // If the image height exceeds the PDF page height, adjust it\r\n if (imgHeight > pdfHeight) {\r\n imgHeight = pdfHeight;\r\n imgWidth = pdfHeight * aspectRatio;\r\n }\r\n\r\n // Add the image to the PDF\r\n pdf.addImage(imgData, 'PNG', 0, 20, imgWidth, imgHeight); // Fit image on PDF page\r\n pdf.save('organization-chart.pdf'); // Download the PDF\r\n })\r\n .catch(handleCanvasError);\r\n}\r\n\r\n// Download the captured image in the required format (PNG/JPEG)\r\nexport const downloadImage = (imgData: string, format: 'png' | 'jpeg'): void => {\r\n const link = document.createElement('a');\r\n link.href = imgData;\r\n link.download = `organization-chart.${format}`;\r\n link.click();\r\n}\r\n\r\n// Error handler for any issues during canvas generation or file creation\r\nexport const handleCanvasError = (error: any): void => {\r\n console.error('Error generating file:', error);\r\n}\r\n\r\n \r\nexport const checkPropsType = (props: OrgData): void => {\r\n if (props.isDisplayHambergerMenu !== undefined && typeof props.isDisplayHambergerMenu !== 'boolean') {\r\n console.error('Error: isDisplayHambergerMenu should be a boolean.');\r\n }\r\n \r\n if (props.isDisplaySearchBar !== undefined && typeof props.isDisplaySearchBar !== 'boolean') {\r\n console.error('Error: isDisplaySearchBar should be a boolean.');\r\n }\r\n \r\n if (!['portrait', 'triangle', 'landscape'].includes(props.nodeTemplate)) {\r\n console.error('Error: nodeTemplate should be \"portrait\", \"triangle\", or \"landscape\".');\r\n }\r\n \r\n if (!Array.isArray(props.hambergerMenuList)) {\r\n console.error('Error: hambergerMenuList should be an array.');\r\n } else {\r\n props.hambergerMenuList.forEach(item => {\r\n if (typeof item.label !== 'string') {\r\n console.error('Error: hambergerMenuList label should be a string.');\r\n }\r\n if (typeof item.id !== 'number') {\r\n console.error('Error: hambergerMenuList id should be a number.');\r\n }\r\n });\r\n }\r\n \r\n // Check if greyNodeStyle is of type CustomNodeStyle\r\n const greyNodeStyle = props.greyNodeStyle;\r\n if (greyNodeStyle) {\r\n if (greyNodeStyle.backgroundColor && typeof greyNodeStyle.backgroundColor !== 'string') {\r\n console.error('Error: greyNodeStyle.backgroundColor should be a string.');\r\n }\r\n if (greyNodeStyle.color && typeof greyNodeStyle.color !== 'string') {\r\n console.error('Error: greyNodeStyle.color should be a string.');\r\n }\r\n if (greyNodeStyle.padding && typeof greyNodeStyle.padding !== 'string') {\r\n console.error('Error: greyNodeStyle.padding should be a string.');\r\n }\r\n if (greyNodeStyle.borderRadius && typeof greyNodeStyle.borderRadius !== 'string') {\r\n console.error('Error: greyNodeStyle.borderRadius should be a string.');\r\n }\r\n }\r\n \r\n // Check if orgData is an array of OrgDataItem objects\r\n if (!Array.isArray(props.orgData)) {\r\n console.error('Error: orgData should be an array.');\r\n } else {\r\n props.orgData.forEach(item => checkOrgDataItem(item));\r\n }\r\n }\r\n\r\n export const checkOrgDataItem = (item: OrgDataItem): void => {\r\n if (item.label !== undefined && typeof item.label !== 'string') {\r\n console.error('Error: OrgDataItem label should be a string.');\r\n }\r\n \r\n if (item.expanded !== undefined && typeof item.expanded !== 'boolean') {\r\n console.error('Error: OrgDataItem expanded should be a boolean.');\r\n }\r\n \r\n if (item.description !== undefined && typeof item.description !== 'string') {\r\n console.error('Error: OrgDataItem description should be a string.');\r\n }\r\n \r\n if (item.customNodeStyle !== undefined) {\r\n const customNodeStyle = item.customNodeStyle;\r\n if (customNodeStyle.backgroundColor && typeof customNodeStyle.backgroundColor !== 'string') {\r\n console.error('Error: customNodeStyle.backgroundColor should be a string.');\r\n }\r\n if (customNodeStyle.color && typeof customNodeStyle.color !== 'string') {\r\n console.error('Error: customNodeStyle.color should be a string.');\r\n }\r\n if (customNodeStyle.padding && typeof customNodeStyle.padding !== 'string') {\r\n console.error('Error: customNodeStyle.padding should be a string.');\r\n }\r\n if (customNodeStyle.borderRadius && typeof customNodeStyle.borderRadius !== 'string') {\r\n console.error('Error: customNodeStyle.borderRadius should be a string.');\r\n }\r\n }\r\n \r\n if (!item.data || typeof item.data.title !== 'string') {\r\n console.error('Error: OrgDataItem data.title should be a string.');\r\n } else {\r\n if (item.data.image !== undefined && typeof item.data.image !== 'string') {\r\n console.error('Error: OrgDataItem data.image should be a string.');\r\n }\r\n if (item.data.name !== undefined && typeof item.data.name !== 'string') {\r\n console.error('Error: OrgDataItem data.name should be a string.');\r\n }\r\n }\r\n\r\n \r\n if (item.children && Array.isArray(item.children)) {\r\n item.children.forEach(child => checkOrgDataItem(child)); // Recursive call for children\r\n }\r\n \r\n if (item.originalStyle) {\r\n const originalStyle = item.originalStyle;\r\n if (originalStyle.backgroundColor && typeof originalStyle.backgroundColor !== 'string') {\r\n console.error('Error: originalStyle.backgroundColor should be a string.');\r\n }\r\n if (originalStyle.color && typeof originalStyle.color !== 'string') {\r\n console.error('Error: originalStyle.color should be a string.');\r\n }\r\n if (originalStyle.padding && typeof originalStyle.padding !== 'string') {\r\n console.error('Error: originalStyle.padding should be a string.');\r\n }\r\n if (originalStyle.borderRadius && typeof originalStyle.borderRadius !== 'string') {\r\n console.error('Error: originalStyle.borderRadius should be a string.');\r\n }\r\n }\r\n }\r\n","import { MatMenuModule } from '@angular/material/menu';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatIconModule } from '@angular/material/icon';\r\n/* eslint-disable no-prototype-builtins */\r\nimport { Component, OnInit, ViewChild, Input } from '@angular/core';\r\nimport { CustomTreeNode, OrgData, OrgDataItem } from '../../interfaces/org-chart';\r\nimport { TreeNode } from 'primeng/api';\r\nimport { checkPropsType, downloadChart } from '../../utils/chart-download.util';\r\nimport { OrganizationChart, OrganizationChartModule } from 'primeng/organizationchart';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'uxp-ruclib-org-chart',\r\n imports: [CommonModule, MatIconModule, MatButtonModule, MatFormFieldModule, MatInputModule, MatMenuModule, OrganizationChartModule, FormsModule],\r\n templateUrl: './ruclib-org-chart.component.html',\r\n styleUrl: './ruclib-org-chart.component.scss'\r\n})\r\nexport class RuclibOrgChartComponent implements OnInit {\r\n @Input() rucInputData!: OrgData;\r\n @Input() customTheme: string | undefined;\r\n selectedNodes!: CustomTreeNode[];\r\n searchText = '';\r\n hoveredNode: CustomTreeNode | null = null;\r\n\r\n @ViewChild('orgChart', { static: false }) orgChart!: OrganizationChart;\r\n\r\n /** Initializes the component */\r\n ngOnInit(): void {\r\n const updatedJson = this.addDefaultKeysIfNotAvailable(this.rucInputData);\r\n this.rucInputData.orgData = this.updateRucInputData(updatedJson.orgData);\r\n checkPropsType(this.rucInputData); // To check rucInputData is in correct format or not\r\n this.expandAllNodes();\r\n }\r\n\r\n /** add default property for grey nodes if user does not provided */\r\n addDefaultKeysIfNotAvailable(orgData: OrgData) {\r\n if (!orgData.hasOwnProperty('greyNodeStyle')) {\r\n orgData.greyNodeStyle = {\r\n backgroundColor: '#d3d3d3',\r\n color: '#808080',\r\n };\r\n }\r\n return orgData;\r\n }\r\n\r\n /** manipulate input json as If customNodeStyle exists, create originalStyle for node and its children */\r\n updateRucInputData(data: OrgDataItem[]): OrgDataItem[] {\r\n return data.map((node: OrgDataItem) => {\r\n node['type'] = 'person';\r\n if (node.customNodeStyle) {\r\n node.originalStyle = { ...node.customNodeStyle };\r\n }\r\n if (node.children && node.children.length > 0) {\r\n node['type'] = 'person';\r\n node.children = this.updateRucInputData(node.children); // Recursive call\r\n }\r\n return node;\r\n });\r\n }\r\n\r\n /** Expands all nodes in the org chart */\r\n expandAllNodes(): void {\r\n this.rucInputData.orgData = this.expandNodes(this.rucInputData.orgData);\r\n }\r\n\r\n /** Recursively expands all nodes in the given array\r\n * @param nodes Nodes to expand @returns Expanded nodes */\r\n expandNodes(nodes: OrgDataItem[]): OrgDataItem[] {\r\n return nodes.map((node) => ({\r\n ...node,\r\n expanded: true,\r\n children: node.children ? this.expandNodes(node.children) : [],\r\n }));\r\n }\r\n\r\n /** Collapses all nodes in the org chart */\r\n collapseAllNodes(): void {\r\n this.rucInputData.orgData = this.collapseNodes(this.rucInputData.orgData);\r\n }\r\n\r\n /** Recursively collapses all nodes in the given array\r\n * @param nodes Nodes to collapse @returns Collapsed nodes */\r\n collapseNodes(nodes: OrgDataItem[]): OrgDataItem[] {\r\n return nodes.map((node) => ({\r\n ...node,\r\n expanded: false,\r\n children: node.children ? this.collapseNodes(node.children) : [],\r\n }));\r\n }\r\n\r\n /** Gets the background color of a node based on search text\r\n @param node Node to check @returns Whether the node matches the search text */\r\n getBackgroungColorOfNode(node: CustomTreeNode): boolean {\r\n return (\r\n !this.searchText ||\r\n node.data.title.toLowerCase().includes(this.searchText.toLowerCase()) ||\r\n node.data.name.toLowerCase().includes(this.searchText.toLowerCase()) ||\r\n node.label?.toLowerCase().includes(this.searchText.toLowerCase())\r\n );\r\n }\r\n\r\n /** Handles node hover event @param node Hovered node */\r\n onNodeHover(node: CustomTreeNode): void {\r\n if (this.searchText) return;\r\n this.hoveredNode = node;\r\n this.updateNodeStyles();\r\n }\r\n\r\n /** Handles node leave event */\r\n onNodeLeave(): void {\r\n this.hoveredNode = null;\r\n this.resetNodeStyles();\r\n }\r\n\r\n /** Updates node styles based on the hovered node */\r\n updateNodeStyles(): void {\r\n this.applyStyles(this.rucInputData.orgData, true);\r\n }\r\n\r\n /** Resets node styles to their original state */\r\n resetNodeStyles(): void {\r\n this.applyStyles(this.rucInputData.orgData, false);\r\n }\r\n\r\n /** Applies grey node style to non-matching nodes @param nodes Nodes to apply styles to */\r\n applyGreyNodes(nodes:OrgDataItem[]): void {\r\n nodes.forEach((node: OrgDataItem) => {\r\n const isMatching = this.searchText\r\n ? node.data?.title.includes(this.searchText)\r\n : false;\r\n node.customNodeStyle = isMatching\r\n ? node.customNodeStyle || node.originalStyle\r\n : {\r\n ...node.originalStyle,\r\n backgroundColor: this.rucInputData.greyNodeStyle.backgroundColor,\r\n color: this.rucInputData.greyNodeStyle.color,\r\n };\r\n\r\n if (node.children) {\r\n this.applyGreyNodes(node.children);\r\n }\r\n });\r\n }\r\n\r\n /** Applies styles to nodes based on the hovered node\r\n * @param nodes Nodes to apply styles @param isHovered Whether the node is hovered */\r\n applyStyles(nodes: OrgDataItem[], isHovered: boolean): void {\r\n nodes.forEach((node) => {\r\n if (isHovered) {\r\n node.customNodeStyle =\r\n node === this.hoveredNode ||\r\n this.isParent(node, this.hoveredNode) ||\r\n this.isChild(node, this.hoveredNode)\r\n ? node.customNodeStyle || node.originalStyle\r\n : {\r\n ...node.originalStyle,\r\n backgroundColor:\r\n this.rucInputData.greyNodeStyle.backgroundColor,\r\n color: this.rucInputData.greyNodeStyle.color,\r\n };\r\n } else {\r\n node.customNodeStyle = node.originalStyle;\r\n }\r\n\r\n if (node.children) {\r\n this.applyStyles(node.children, isHovered);\r\n }\r\n });\r\n }\r\n\r\n /** Use the downloadChart utility method */\r\n downloadChart(format: 'png' | 'jpeg' | 'pdf'): void {\r\n const chartContainer = this.orgChart.el.nativeElement;\r\n downloadChart(chartContainer, format); // Calls the utility function\r\n }\r\n\r\n /** Handles menu click event @param id Menu item ID */\r\n onMenuClick(id: number,event: MouseEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n switch (id) {\r\n case 1:\r\n this.downloadChart('pdf');\r\n break;\r\n case 2:\r\n this.downloadChart('png');\r\n break;\r\n case 3:\r\n this.downloadChart('jpeg');\r\n break;\r\n case 4:\r\n this.expandAllNodes();\r\n break;\r\n case 5:\r\n this.collapseAllNodes();\r\n break;\r\n default:\r\n console.warn(`Unknown menu item ID: ${id}. Please enter valid id.`);\r\n break;\r\n }\r\n }\r\n\r\n /** Gets tooltip data for a node @param node Node to get tooltip data */\r\n getTooltipData(node: CustomTreeNode): string | undefined {\r\n return node.description || '';\r\n }\r\n\r\n /** Checks if a node is a parent of another node.\r\n * @param currentNode The current node to check.\r\n * @param hoveredNode The node to check for parentage.\r\n * @returns Whether the current node is a parent of the hovered node. */\r\n isParent(\r\n currentNode: TreeNode,\r\n hoveredNode: TreeNode | null\r\n ): boolean | null | undefined {\r\n return hoveredNode && currentNode.children?.includes(hoveredNode);\r\n }\r\n\r\n /** Checks if a node is a child of another node.\r\n * @param node The node to check for child status\r\n * @param target The node to check for parentage.\r\n * @returns Whether the node is a child of the target node.*/\r\n isChild(node: TreeNode, target: TreeNode | null): boolean | null | undefined {\r\n return target && target.children?.includes(node);\r\n }\r\n}\r\n\r\n","<div class={{customTheme}}>\r\n <div class=\"container\">\r\n <!-- Hamburger Menu -->\r\n @if (rucInputData.isDisplayHambergerMenu === true) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\"\r\n class=\"left hamburger-button\">\r\n <mat-icon>menu</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- Menu -->\r\n <mat-menu #menu=\"matMenu\">\r\n @for (menu of rucInputData.hambergerMenuList; track menu) {\r\n <button mat-menu-item (click)=\"onMenuClick(menu.id, $event);\"\r\n [id]=\"'menu-item-' + menu.id\">\r\n {{ menu.label }}\r\n </button>\r\n }\r\n </mat-menu>\r\n\r\n <!-- Search Bar -->\r\n @if (rucInputData.isDisplaySearchBar === true) {\r\n <mat-form-field class=\"search-box right\"\r\n >\r\n <mat-label>Search</mat-label>\r\n <input matInput placeholder=\"Type to search...\" [(ngModel)]=\"searchText\" />\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n\r\n <div class=\"org-chart-container \" id=\"org-chart-data\">\r\n <p-organizationChart #orgChart class=\"org-chart\" [value]=\"this.rucInputData.orgData\" selectionMode=\"multiple\"\r\n [(selection)]=\"selectedNodes\">\r\n <ng-template let-node pTemplate=\"person\">\r\n @if (this.rucInputData.nodeTemplate === 'portrait') {\r\n <div class=\"flex flex-col nodeContent\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\" (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"flex flex-col items-center\" >\r\n <span>@if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"portraitImageDimension\" />\r\n }</span>\r\n <div class=\"font-bold mb-2\">{{ node.data.name }}</div>\r\n <div>{{ node.data.title }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (this.rucInputData.nodeTemplate === 'triangle') {\r\n <div class=\"flex trianlge-up flex-col nodeContent\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\" (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"flex flex-col items-center\" >\r\n @if (!node.data.image) {\r\n <div class=\"triangleImageDimension\">\r\n </div>\r\n }\r\n @if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"triangleImageDimension\" />\r\n }\r\n <div class=\"font-bold mb-2\">{{ node.data.name }}</div>\r\n <div>{{ node.data.title }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n @if (this.rucInputData.nodeTemplate === 'landscape') {\r\n <div>\r\n <div class=\"card borderSolidGrey\" [ngStyle]=\"getBackgroungColorOfNode(node) ? node.customNodeStyle : rucInputData.greyNodeStyle\"\r\n (mouseenter)=\"onNodeHover(node)\"\r\n [title]=\"getTooltipData(node)\" (mouseleave)=\"onNodeLeave()\">\r\n <div class=\"body\" >\r\n <div class=\"icon\">\r\n @if (node.data.image) {\r\n <img [src]=\"node.data.image\" class=\"landscapeImageDimension\" />\r\n }\r\n </div>\r\n <div class=\"content\">\r\n <div>{{node.data.name}}</div>\r\n <div>{{node.data.title}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </p-organizationChart>\r\n </div>\r\n\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|