@underpostnet/underpost 2.98.0 → 2.98.3

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.
@@ -1,1245 +0,0 @@
1
- import { CoreService } from '../../services/core/core.service.js';
2
- import { BtnIcon } from './BtnIcon.js';
3
- import { borderChar, dynamicCol } from './Css.js';
4
- import { DropDown } from './DropDown.js';
5
- import { EventsUI } from './EventsUI.js';
6
- import { Translate } from './Translate.js';
7
- import { s, append, hexToRgbA } from './VanillaJs.js';
8
- import { getProxyPath, getQueryParams, setPath, setQueryParams, RouterEvents } from './Router.js';
9
- import { s4 } from './CommonJs.js';
10
- import { Input } from './Input.js';
11
- import { ToggleSwitch } from './ToggleSwitch.js';
12
- import { ObjectLayerService } from '../../services/object-layer/object-layer.service.js';
13
- import { NotificationManager } from './NotificationManager.js';
14
- import { AgGrid } from './AgGrid.js';
15
- import { Modal } from './Modal.js';
16
- import { loggerFactory } from './Logger.js';
17
- import { LoadingAnimation } from './LoadingAnimation.js';
18
- import { DefaultManagement } from '../../services/default/default.management.js';
19
-
20
- const logger = loggerFactory(import.meta, { trace: true });
21
-
22
- const ObjectLayerEngineModal = {
23
- templates: [
24
- {
25
- label: 'empty',
26
- id: 'empty',
27
- data: [],
28
- },
29
- ],
30
- statDescriptions: {
31
- effect: {
32
- title: 'Effect',
33
- icon: 'fa-solid fa-burst',
34
- description: 'Amount of life removed when an entity collides or deals an impact.',
35
- detail: 'Measured in life points.',
36
- },
37
- resistance: {
38
- title: 'Resistance',
39
- icon: 'fa-solid fa-shield',
40
- description: "Adds to the owner's maximum life (survivability cap).",
41
- detail:
42
- "This value is summed with the entity's base max life. It also increases the amount of life restored when a regeneration event occurs (adds directly to current life).",
43
- },
44
- agility: {
45
- title: 'Agility',
46
- icon: 'fa-solid fa-person-running',
47
- description: 'Increases the movement speed of entities.',
48
- detail: 'Higher values result in faster movement.',
49
- },
50
- range: {
51
- title: 'Range',
52
- icon: 'fa-solid fa-bullseye',
53
- description: 'Increases the lifetime of a cast/summoned entity.',
54
- detail: 'Measured in milliseconds.',
55
- },
56
- intelligence: {
57
- title: 'Intelligence',
58
- icon: 'fa-solid fa-brain',
59
- description: 'Probability-based stat that increases the chance to spawn/trigger a summoned entity.',
60
- detail: 'Higher values increase summoning success rate.',
61
- },
62
- utility: {
63
- title: 'Utility',
64
- icon: 'fa-solid fa-wrench',
65
- description: 'Reduces the cooldown time between actions, allowing for more frequent actions.',
66
- detail: 'It also increases the chance to trigger life-regeneration events.',
67
- },
68
- },
69
-
70
- RenderTemplate: (colorTemplate) => {
71
- const ole = s('object-layer-engine');
72
- if (!ole) {
73
- return;
74
- }
75
-
76
- if (colorTemplate.length === 0) {
77
- ole.clear();
78
- return;
79
- }
80
-
81
- const matrix = colorTemplate.map((row) => row.map((hex) => [...hexToRgbA(hex), 255]));
82
- ole.loadMatrix(matrix);
83
- },
84
- ObjectLayerData: {},
85
- clearData: function () {
86
- // Clear all cached object layer data to prevent contamination between sessions
87
- this.ObjectLayerData = {};
88
-
89
- // Clear the canvas if it exists
90
- const ole = s('object-layer-engine');
91
- if (ole && typeof ole.clear === 'function') {
92
- ole.clear();
93
- }
94
-
95
- // Clear all frame previews from DOM for all direction codes
96
- const directionCodes = ['08', '18', '02', '12', '04', '14', '06', '16'];
97
- for (const directionCode of directionCodes) {
98
- const framesContainer = s(`.frames-${directionCode}`);
99
- if (framesContainer) {
100
- framesContainer.innerHTML = '';
101
- }
102
- }
103
-
104
- // Clear form inputs with correct IDs
105
- const itemIdInput = s('#ol-input-item-id');
106
- if (itemIdInput) itemIdInput.value = '';
107
-
108
- const itemDescInput = s('#ol-input-item-description');
109
- if (itemDescInput) itemDescInput.value = '';
110
-
111
- const frameDurationInput = s('#ol-input-render-frame-duration');
112
- if (frameDurationInput) frameDurationInput.value = '100';
113
-
114
- // Reset toggle switches with correct IDs
115
- const activableCheckbox = s('#ol-toggle-item-activable');
116
- if (activableCheckbox) activableCheckbox.checked = false;
117
-
118
- const statelessCheckbox = s('#ol-toggle-render-is-stateless');
119
- if (statelessCheckbox) statelessCheckbox.checked = false;
120
-
121
- // Clear stat inputs with correct IDs
122
- const statTypes = Object.keys(ObjectLayerEngineModal.statDescriptions);
123
- for (const stat of statTypes) {
124
- const statInput = s(`#ol-input-item-stats-${stat}`);
125
- if (statInput) statInput.value = '0';
126
- }
127
- },
128
- loadFromDatabase: async (objectLayerId) => {
129
- try {
130
- // Load metadata first (lightweight)
131
- const { status: metaStatus, data: metadata } = await ObjectLayerService.getMetadata({ id: objectLayerId });
132
-
133
- if (metaStatus !== 'success' || !metadata) {
134
- NotificationManager.Push({
135
- html: `Failed to load object layer metadata`,
136
- status: 'error',
137
- });
138
- return null;
139
- }
140
-
141
- // Load render data separately (heavy)
142
- const { status: renderStatus, data: renderData } = await ObjectLayerService.getRender({ id: objectLayerId });
143
-
144
- if (renderStatus !== 'success' || !renderData) {
145
- NotificationManager.Push({
146
- html: `Failed to load object layer render data`,
147
- status: 'error',
148
- });
149
- return null;
150
- }
151
-
152
- return { metadata, renderData };
153
- } catch (error) {
154
- console.error('Error loading object layer from database:', error);
155
- NotificationManager.Push({
156
- html: `Error loading object layer: ${error.message}`,
157
- status: 'error',
158
- });
159
- return null;
160
- }
161
- },
162
- Render: async (options = { idModal: '', Elements: {} }) => {
163
- // Clear all cached data at the start of each render to prevent contamination
164
- ObjectLayerEngineModal.clearData();
165
-
166
- const { Elements } = options;
167
- await import(`${getProxyPath()}components/core/ObjectLayerEngine.js`);
168
- // await import(`${getProxyPath()}components/core/WebComponent.js`);
169
- const directionCodes = ['08', '18', '02', '12', '04', '14', '06', '16'];
170
- const itemTypes = ['skin', 'weapon', 'armor', 'artifact', 'floor'];
171
- const statTypes = ['effect', 'resistance', 'agility', 'range', 'intelligence', 'utility'];
172
- let selectItemType = itemTypes[0];
173
- let itemActivable = false;
174
- let renderIsStateless = false;
175
- let renderFrameDuration = 100;
176
-
177
- // Check if we have a 'cid' query parameter to load existing object layer
178
- const queryParams = getQueryParams();
179
- let loadedData = null;
180
- let existingObjectLayerId = null; // Track the _id for updates
181
- let originalDirectionCodes = []; // Track original direction codes for update mode
182
-
183
- // Track frame editing state
184
- let editingFrameId = null;
185
- let editingDirectionCode = null;
186
-
187
- // Helper function to update UI when entering edit mode
188
- const enterEditMode = (frameId, directionCode) => {
189
- editingFrameId = frameId;
190
- editingDirectionCode = directionCode;
191
-
192
- // Hide/disable all "Add Frame" buttons except the one for the editing direction
193
- directionCodes.forEach((code) => {
194
- const addButton = s(`.direction-code-bar-frames-btn-${code}`);
195
- const addButtonParent = addButton?.parentElement;
196
- if (addButton && addButtonParent) {
197
- if (code === directionCode) {
198
- // Keep the button for the editing direction visible and highlighted with animation
199
- addButton.style.opacity = '1';
200
- addButton.style.pointerEvents = 'auto';
201
- addButton.style.border = '2px solid #4CAF50';
202
- addButton.style.boxShadow = '0 0 15px rgba(76, 175, 80, 0.6)';
203
- addButtonParent.classList.add('edit-mode-active');
204
- } else {
205
- // Hide/disable buttons for other directions
206
- addButton.style.opacity = '0.3';
207
- addButton.style.pointerEvents = 'none';
208
- addButton.style.filter = 'grayscale(100%)';
209
- addButton.style.cursor = 'not-allowed';
210
- }
211
- }
212
- });
213
-
214
- // Change the edit button to close button for the frame being edited
215
- const editBtn = s(`.direction-code-bar-edit-btn-${frameId}`);
216
- if (editBtn) {
217
- editBtn.innerHTML = '<i class="fa-solid fa-times"></i>';
218
- editBtn.classList.add('edit-mode-active');
219
- editBtn.title = 'Cancel editing (Esc)';
220
- }
221
-
222
- // Highlight the frame being edited
223
- document.querySelectorAll('.direction-code-bar-frames-img').forEach((img) => {
224
- img.style.border = '';
225
- img.style.boxShadow = '';
226
- });
227
- const frameImg = s(`.direction-code-bar-frames-img-${frameId}`);
228
- if (frameImg) {
229
- frameImg.style.border = '3px solid #4CAF50';
230
- frameImg.style.boxShadow = '0 0 10px rgba(76, 175, 80, 0.5)';
231
- }
232
-
233
- // Show notification with better instructions
234
- NotificationManager.Push({
235
- html: `<strong>Edit Mode Active</strong><br/>Click the glowing <i class="fa-solid fa-edit"></i> button for direction <strong>${directionCode}</strong> to save, or click <i class="fa-solid fa-times"></i> to cancel.`,
236
- status: 'info',
237
- });
238
- s(`.direction-code-bar-frames-btn-icon-add-${directionCode}`).classList.add('hide');
239
- s(`.direction-code-bar-frames-btn-icon-edit-${directionCode}`).classList.remove('hide');
240
- };
241
-
242
- // Helper function to exit edit mode and restore UI
243
- const exitEditMode = () => {
244
- const previousEditingFrameId = editingFrameId;
245
-
246
- s(`.direction-code-bar-frames-btn-icon-add-${editingDirectionCode}`).classList.remove('hide');
247
- s(`.direction-code-bar-frames-btn-icon-edit-${editingDirectionCode}`).classList.add('hide');
248
-
249
- editingFrameId = null;
250
- editingDirectionCode = null;
251
-
252
- // Restore all "Add Frame" buttons
253
- directionCodes.forEach((code) => {
254
- const addButton = s(`.direction-code-bar-frames-btn-${code}`);
255
- const addButtonParent = addButton?.parentElement;
256
- if (addButton) {
257
- addButton.style.opacity = '1';
258
- addButton.style.pointerEvents = 'auto';
259
- addButton.style.border = '';
260
- addButton.style.filter = 'none';
261
- addButton.style.cursor = 'pointer';
262
- addButton.style.boxShadow = '';
263
- if (addButtonParent) {
264
- addButtonParent.classList.remove('edit-mode-active');
265
- }
266
- }
267
- });
268
-
269
- // Restore edit button icon if it exists
270
- if (previousEditingFrameId) {
271
- const editBtn = s(`.direction-code-bar-edit-btn-${previousEditingFrameId}`);
272
- if (editBtn) {
273
- editBtn.innerHTML = '<i class="fa-solid fa-edit"></i>';
274
- editBtn.classList.remove('edit-mode-active');
275
- editBtn.title = 'Edit frame';
276
- }
277
- }
278
-
279
- // Remove all frame borders and shadows
280
- document.querySelectorAll('.direction-code-bar-frames-img').forEach((img) => {
281
- img.style.border = '';
282
- img.style.boxShadow = '';
283
- });
284
- };
285
-
286
- if (queryParams.cid) {
287
- existingObjectLayerId = queryParams.cid;
288
- loadedData = await ObjectLayerEngineModal.loadFromDatabase(queryParams.cid);
289
-
290
- if (loadedData) {
291
- const { metadata, renderData } = loadedData;
292
-
293
- // Set form values from metadata
294
- if (metadata.data) {
295
- if (metadata.data.item) {
296
- selectItemType = metadata.data.item.type || itemTypes[0];
297
- itemActivable = metadata.data.item.activable || false;
298
-
299
- // Add loaded item type to itemTypes array if it doesn't exist
300
- if (selectItemType && !itemTypes.includes(selectItemType)) {
301
- itemTypes.push(selectItemType);
302
- }
303
- }
304
- if (metadata.data.render) {
305
- renderIsStateless = metadata.data.render.is_stateless || false;
306
- renderFrameDuration = metadata.data.render.frame_duration || 100;
307
- }
308
- }
309
- }
310
- }
311
-
312
- for (const url of [
313
- `${getProxyPath()}assets/templates/item-skin-08.json`,
314
- `${getProxyPath()}assets/templates/item-skin-06.json`,
315
- ]) {
316
- const id = url.split('/').pop().replace('.json', '');
317
- ObjectLayerEngineModal.templates.push({
318
- label: id,
319
- id,
320
- data: JSON.parse(await CoreService.getRaw({ url })).color,
321
- });
322
- }
323
-
324
- const cells = 26;
325
- const pixelSize = parseInt(320 / cells);
326
- const idSectionA = 'template-section-a';
327
- const idSectionB = 'template-section-b';
328
-
329
- let directionsCodeBarRender = '';
330
-
331
- // Helper function to add a frame to the direction bar
332
- const addFrameToBar = async (directionCode, id, image, json) => {
333
- // Capture directionCode in a local variable to ensure proper closure
334
- const capturedDirectionCode = directionCode;
335
-
336
- append(
337
- `.frames-${capturedDirectionCode}`,
338
- html`
339
- <div class="in fll ${id}">
340
- <img
341
- class="in fll direction-code-bar-frames-img direction-code-bar-frames-img-${id}"
342
- src="${URL.createObjectURL(image)}"
343
- data-direction-code="${capturedDirectionCode}"
344
- />
345
- ${await BtnIcon.Render({
346
- label: html`<i class="fa-solid fa-edit"></i>`,
347
- class: `abs direction-code-bar-edit-btn direction-code-bar-edit-btn-${id}`,
348
- })}
349
- ${await BtnIcon.Render({
350
- label: html`<i class="fa-solid fa-trash"></i>`,
351
- class: `abs direction-code-bar-trash-btn direction-code-bar-trash-btn-${id}`,
352
- })}
353
- </div>
354
- `,
355
- );
356
-
357
- EventsUI.onClick(`.direction-code-bar-frames-img-${id}`, async (e) => {
358
- // Get direction code from data attribute to ensure we're using the correct one
359
- const clickedDirectionCode = e.target.getAttribute('data-direction-code') || capturedDirectionCode;
360
- console.log(`Clicked frame ${id} from direction code: ${clickedDirectionCode}`);
361
- const frameData = ObjectLayerEngineModal.ObjectLayerData[clickedDirectionCode]?.find(
362
- (frame) => frame.id === id,
363
- );
364
- if (frameData && frameData.json) {
365
- // console.log(`Loading frame data for direction code ${clickedDirectionCode}:`, frameData.json);
366
- s('object-layer-engine').importMatrixJSON(frameData.json);
367
- } else {
368
- console.error(`Frame data not found for id ${id} in direction code ${clickedDirectionCode}`);
369
- }
370
- });
371
-
372
- EventsUI.onClick(`.direction-code-bar-trash-btn-${id}`, async () => {
373
- s(`.${id}`).remove();
374
- ObjectLayerEngineModal.ObjectLayerData[capturedDirectionCode] = ObjectLayerEngineModal.ObjectLayerData[
375
- capturedDirectionCode
376
- ].filter((frame) => frame.id !== id);
377
-
378
- // Clear edit mode if deleting the frame being edited
379
- if (editingFrameId === id && editingDirectionCode === capturedDirectionCode) {
380
- exitEditMode();
381
- }
382
- });
383
-
384
- EventsUI.onClick(`.direction-code-bar-edit-btn-${id}`, async () => {
385
- // Check if this is the frame being edited (close button behavior)
386
- if (editingFrameId === id && editingDirectionCode === capturedDirectionCode) {
387
- console.log(`Canceling edit mode for frame ${id}`);
388
- exitEditMode();
389
- // Clear the editor
390
- s('object-layer-engine').clear();
391
- NotificationManager.Push({
392
- html: `<i class="fa-solid fa-times-circle"></i> Edit canceled`,
393
- status: 'info',
394
- });
395
- return;
396
- }
397
-
398
- s(`.direction-code-bar-frames-btn-icon-add-${capturedDirectionCode}`).classList.add('hide');
399
- s(`.direction-code-bar-frames-btn-icon-edit-${capturedDirectionCode}`).classList.remove('hide');
400
-
401
- console.log(`Edit button clicked for frame ${id} in direction code ${capturedDirectionCode}`);
402
-
403
- // If another frame is being edited, exit that edit mode first
404
- if (editingFrameId && editingFrameId !== id) {
405
- exitEditMode();
406
- }
407
-
408
- // Find the frame data
409
- const frameData = ObjectLayerEngineModal.ObjectLayerData[capturedDirectionCode]?.find(
410
- (frame) => frame.id === id,
411
- );
412
-
413
- if (frameData && frameData.json) {
414
- // Load the frame into the editor
415
- s('object-layer-engine').importMatrixJSON(frameData.json);
416
-
417
- // Enter edit mode with UI updates
418
- enterEditMode(id, capturedDirectionCode);
419
-
420
- console.log(`Entering edit mode for frame ${id} in direction ${capturedDirectionCode}`);
421
- } else {
422
- console.error(`Frame data not found for id ${id} in direction code ${capturedDirectionCode}`);
423
- NotificationManager.Push({
424
- html: `<i class="fa-solid fa-exclamation-triangle"></i> Error: Frame data not found`,
425
- status: 'error',
426
- });
427
- }
428
- });
429
- };
430
-
431
- // Helper function to show loading animation
432
- const showFrameLoading = () => {
433
- if (!s(`.frame-editor-container`) || s(`.frame-editor-container`).classList.contains('hide')) return;
434
- LoadingAnimation.spinner.play(`.frame-editor-container-loading`, 'dual-ring-mini', {
435
- prepend: html`<span class="inl loading-text">Loading </span><br /><br /> ` + '<div style="color: gray;">',
436
- append: '</div>',
437
- });
438
- s(`.frame-editor-container`).classList.add('hide');
439
- s(`.frame-editor-container-loading`).classList.remove('hide');
440
- };
441
-
442
- // Helper function to hide loading animation
443
- const hideFrameLoading = () => {
444
- if (!s(`.frame-editor-container-loading`) || s(`.frame-editor-container-loading`).classList.contains('hide'))
445
- return;
446
- LoadingAnimation.spinner.stop(`.frame-editor-container-loading`);
447
- s(`.frame-editor-container-loading`).classList.add('hide');
448
- s(`.frame-editor-container`).classList.remove('hide');
449
- };
450
-
451
- // Helper function to process and add frame from PNG URL using ObjectLayerPngLoader
452
- const processAndAddFrameFromPngUrl = async (directionCode, pngUrl) => {
453
- // Wait for components to be available with retry logic
454
- let ole = s('object-layer-engine');
455
- let loader = s('object-layer-png-loader');
456
-
457
- if (!ole || !loader) {
458
- console.error('object-layer-engine or object-layer-png-loader component not found after retries');
459
- return;
460
- }
461
-
462
- try {
463
- // Load PNG using the loader component - it will automatically load into the editor
464
- await loader.loadPngUrl(pngUrl);
465
-
466
- // Export as blob and JSON from component after loading
467
- const image = await ole.toBlob();
468
- const json = ole.exportMatrixJSON();
469
- const id = `frame-loaded-${s4()}-${s4()}`;
470
-
471
- // Add to ObjectLayerData
472
- if (!ObjectLayerEngineModal.ObjectLayerData[directionCode]) {
473
- ObjectLayerEngineModal.ObjectLayerData[directionCode] = [];
474
- }
475
- ObjectLayerEngineModal.ObjectLayerData[directionCode].push({ id, image, json });
476
- console.log(
477
- `Stored frame ${id} in direction code ${directionCode}. Total frames:`,
478
- ObjectLayerEngineModal.ObjectLayerData[directionCode].length,
479
- );
480
-
481
- // Add to UI
482
- await addFrameToBar(directionCode, id, image, json);
483
- } catch (error) {
484
- console.error('Error loading frame from PNG URL:', error);
485
- }
486
- };
487
-
488
- for (const directionCode of directionCodes) {
489
- directionsCodeBarRender += html`
490
- <div class="in section-mp-border">
491
- <div class="fl">
492
- <div class="in fll">
493
- <div class="in direction-code-bar-frames-title">${directionCode}</div>
494
- <div class="in direction-code-bar-frames-btn">
495
- ${await BtnIcon.Render({
496
- label: html`
497
- <i class="fa-solid fa-plus direction-code-bar-frames-btn-icon-add-${directionCode}"></i>
498
- <i class="fa-solid fa-edit direction-code-bar-frames-btn-icon-edit-${directionCode} hide"></i>
499
- `,
500
- class: `direction-code-bar-frames-btn-add direction-code-bar-frames-btn-${directionCode}`,
501
- })}
502
- </div>
503
- </div>
504
- <div class="frames-${directionCode}"></div>
505
- </div>
506
- </div>
507
- `;
508
- }
509
-
510
- let statsInputsRender = '';
511
- for (const statType of statTypes) {
512
- const statInfo = ObjectLayerEngineModal.statDescriptions[statType];
513
- const statValue = loadedData?.metadata?.data?.stats?.[statType] || 0;
514
- statsInputsRender += html`
515
- <div class="inl" style="margin-bottom: 10px; position: relative;">
516
- ${await Input.Render({
517
- id: `ol-input-item-stats-${statType}`,
518
- label: html`<div
519
- title="${statInfo.description} ${statInfo.detail}"
520
- class="inl stat-label-container stat-info-icon"
521
- style="width: 120px; font-size: 16px; overflow: visible; position: relative;"
522
- >
523
- <i class="${statInfo.icon}" style="margin-right: 5px;"></i> ${statInfo.title}
524
- </div>`,
525
- containerClass: 'inl',
526
- type: 'number',
527
- min: 0,
528
- max: 10,
529
- placeholder: true,
530
- value: statValue,
531
- })}
532
- <div class="in stat-description">
533
- ${statInfo.description}<br />
534
- <span style="color: #888; font-style: italic;">${statInfo.detail}</span>
535
- </div>
536
- </div>
537
- `;
538
- }
539
-
540
- setTimeout(async () => {
541
- const loadFrames = async () => {
542
- showFrameLoading();
543
-
544
- // Clear all frames and data at the start to prevent duplication from multiple calls
545
- // This must happen BEFORE any async operations to avoid race conditions
546
- for (const directionCode of directionCodes) {
547
- // Clear DOM frames for this direction code
548
- const framesContainer = s(`.frames-${directionCode}`);
549
- if (framesContainer) {
550
- framesContainer.innerHTML = '';
551
- }
552
- // Clear data for this direction code
553
- ObjectLayerEngineModal.ObjectLayerData[directionCode] = [];
554
- }
555
-
556
- for (const directionCode of directionCodes) {
557
- // Use IIFE to properly capture directionCode and handle async operations
558
- await (async (currentDirectionCode) => {
559
- // Register frame add button handler after DOM is ready
560
- // Wait longer to ensure all direction bars are rendered
561
-
562
- if (loadedData && loadedData.metadata && loadedData.metadata.data && currentDirectionCode) {
563
- // Show loading animation only once on first direction that has frames
564
-
565
- const { type, id } = loadedData.metadata.data.item;
566
- const directions = ObjectLayerEngineModal.getDirectionsFromDirectionCode(currentDirectionCode);
567
-
568
- console.log(`Loading frames for direction code: ${currentDirectionCode}, directions:`, directions);
569
-
570
- // Check if frames exist for any direction mapped to this direction code
571
- const { frames } = loadedData.renderData.data.render;
572
- for (const direction of directions) {
573
- if (frames[direction] && frames[direction].length > 0) {
574
- // Track this direction code as having original data
575
- if (!originalDirectionCodes.includes(currentDirectionCode)) {
576
- originalDirectionCodes.push(currentDirectionCode);
577
- }
578
- // Load frames from static PNG URLs sequentially to avoid race conditions
579
- const frameCount = frames[direction].length;
580
- console.log(`Found ${frameCount} frames for direction: ${direction} (code: ${currentDirectionCode})`);
581
- for (let frameIndex = 0; frameIndex < frameCount; frameIndex++) {
582
- const pngUrl = `${getProxyPath()}assets/${type}/${id}/${currentDirectionCode}/${frameIndex}.png`;
583
- console.log(
584
- `Loading frame ${frameIndex} for direction code ${currentDirectionCode} from: ${pngUrl}`,
585
- );
586
- await processAndAddFrameFromPngUrl(currentDirectionCode, pngUrl);
587
- }
588
- console.log(`Completed loading ${frameCount} frames for direction code: ${currentDirectionCode}`);
589
- // Once we found frames for this direction code, we can break to avoid duplicates
590
- break;
591
- }
592
- }
593
- }
594
-
595
- const buttonSelector = `.direction-code-bar-frames-btn-${currentDirectionCode}`;
596
- console.log(`Registering click handler for: ${buttonSelector}`);
597
-
598
- EventsUI.onClick(buttonSelector, async () => {
599
- console.log(`Add frame button clicked for direction: ${currentDirectionCode}`);
600
- const ole = s('object-layer-engine');
601
- if (!ole) {
602
- console.error('object-layer-engine not found');
603
- return;
604
- }
605
- const image = await ole.toBlob();
606
- const json = ole.exportMatrixJSON();
607
-
608
- // Check if we're in edit mode
609
- if (editingFrameId && editingDirectionCode) {
610
- // Ensure we're clicking the add button for the same direction being edited
611
- if (currentDirectionCode !== editingDirectionCode) {
612
- NotificationManager.Push({
613
- html: `<i class="fa-solid fa-exclamation-circle"></i> Please click the glowing <i class="fa-solid fa-edit"></i> button for direction <strong>${editingDirectionCode}</strong> to save changes, or click <i class="fa-solid fa-times"></i> to cancel.`,
614
- status: 'warning',
615
- });
616
- return; // Don't add a new frame
617
- }
618
-
619
- // UPDATE existing frame
620
- console.log(`Updating frame ${editingFrameId} in direction ${editingDirectionCode}`);
621
-
622
- // Find the frame in the data array
623
- const frameArray = ObjectLayerEngineModal.ObjectLayerData[editingDirectionCode];
624
- const frameIndex = frameArray?.findIndex((frame) => frame.id === editingFrameId);
625
-
626
- if (frameIndex !== undefined && frameIndex >= 0) {
627
- // Update the frame data while preserving the ID and index
628
- frameArray[frameIndex] = {
629
- id: editingFrameId,
630
- image,
631
- json,
632
- };
633
-
634
- // Update the visual representation
635
- const imgElement = s(`.direction-code-bar-frames-img-${editingFrameId}`);
636
- if (imgElement) {
637
- imgElement.src = URL.createObjectURL(image);
638
- }
639
-
640
- console.log(`Frame ${editingFrameId} updated successfully at index ${frameIndex}`);
641
- NotificationManager.Push({
642
- html: `<i class="fa-solid fa-check-circle"></i> Frame updated successfully at position ${frameIndex + 1}!`,
643
- status: 'success',
644
- });
645
- } else {
646
- console.error(`Could not find frame ${editingFrameId} in direction ${editingDirectionCode}`);
647
- NotificationManager.Push({
648
- html: `<i class="fa-solid fa-exclamation-triangle"></i> Error: Could not find frame to update`,
649
- status: 'error',
650
- });
651
- }
652
-
653
- // Exit edit mode and restore UI
654
- exitEditMode();
655
- } else {
656
- // ADD new frame (existing behavior)
657
- const id = `frame-capture-${s4()}-${s4()}`;
658
- console.log(`Creating new frame ${id} for direction ${currentDirectionCode}`);
659
-
660
- if (!ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode])
661
- ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode] = [];
662
- ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode].push({ id, image, json });
663
- console.log(
664
- `Stored frame ${id} in direction code ${currentDirectionCode}. Total frames:`,
665
- ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode].length,
666
- );
667
-
668
- await addFrameToBar(currentDirectionCode, id, image, json);
669
- }
670
- });
671
- })(directionCode);
672
- }
673
- hideFrameLoading();
674
- };
675
- RouterEvents[`router-${options.idModal}`] = loadFrames;
676
-
677
- await loadFrames();
678
- s('object-layer-engine').clear();
679
-
680
- EventsUI.onClick(`.ol-btn-save`, async () => {
681
- // Validate minimum frame_duration 100ms
682
- const frameDuration = parseInt(s(`.ol-input-render-frame-duration`).value);
683
- if (!frameDuration || frameDuration < 100) {
684
- NotificationManager.Push({
685
- html: 'Frame duration must be at least 100ms',
686
- status: 'error',
687
- });
688
- return;
689
- }
690
-
691
- // Validate that item.id is not empty
692
- const itemId = s(`.ol-input-item-id`).value;
693
- if (!itemId || itemId.trim() === '') {
694
- NotificationManager.Push({
695
- html: 'Item ID is required',
696
- status: 'error',
697
- });
698
- return;
699
- }
700
-
701
- const objectLayer = {
702
- data: {
703
- render: {
704
- frames: {},
705
- color: [],
706
- frame_duration: 0,
707
- is_stateless: false,
708
- },
709
- stats: {},
710
- item: {},
711
- },
712
- };
713
- for (const directionCode of directionCodes) {
714
- const directions = ObjectLayerEngineModal.getDirectionsFromDirectionCode(directionCode);
715
- for (const direction of directions) {
716
- if (!objectLayer.data.render.frames[direction]) objectLayer.data.render.frames[direction] = [];
717
-
718
- if (!(directionCode in ObjectLayerEngineModal.ObjectLayerData)) {
719
- console.warn('No set directionCodeBarFrameData for directionCode', directionCode);
720
- continue;
721
- }
722
-
723
- for (const frameData of ObjectLayerEngineModal.ObjectLayerData[directionCode]) {
724
- const { matrix } = JSON.parse(frameData.json);
725
- const frameIndexColorMatrix = [];
726
- let indexRow = -1;
727
- for (const row of matrix) {
728
- indexRow++;
729
- frameIndexColorMatrix[indexRow] = [];
730
- let indexCol = -1;
731
- for (const value of row) {
732
- indexCol++;
733
- let colorIndex = objectLayer.data.render.color.findIndex(
734
- (color) =>
735
- color[0] === value[0] && color[1] === value[1] && color[2] === value[2] && color[3] === value[3],
736
- );
737
- if (colorIndex === -1) {
738
- objectLayer.data.render.color.push(value);
739
- colorIndex = objectLayer.data.render.color.length - 1;
740
- }
741
- frameIndexColorMatrix[indexRow][indexCol] = colorIndex;
742
- }
743
- }
744
- objectLayer.data.render.frames[direction].push(frameIndexColorMatrix);
745
- }
746
- }
747
- }
748
- objectLayer.data.render.frame_duration = parseInt(s(`.ol-input-render-frame-duration`).value);
749
- objectLayer.data.render.is_stateless = renderIsStateless;
750
- objectLayer.data.stats = {
751
- effect: parseInt(s(`.ol-input-item-stats-effect`).value),
752
- resistance: parseInt(s(`.ol-input-item-stats-resistance`).value),
753
- agility: parseInt(s(`.ol-input-item-stats-agility`).value),
754
- range: parseInt(s(`.ol-input-item-stats-range`).value),
755
- intelligence: parseInt(s(`.ol-input-item-stats-intelligence`).value),
756
- utility: parseInt(s(`.ol-input-item-stats-utility`).value),
757
- };
758
- objectLayer.data.item = {
759
- type: selectItemType,
760
- activable: itemActivable,
761
- id: s(`.ol-input-item-id`).value,
762
- description: s(`.ol-input-item-description`).value,
763
- };
764
-
765
- // Add _id if we're updating an existing object layer
766
- if (existingObjectLayerId) {
767
- objectLayer._id = existingObjectLayerId;
768
- }
769
-
770
- console.warn('objectLayer', objectLayer, existingObjectLayerId ? '(UPDATE MODE)' : '(CREATE MODE)');
771
-
772
- if (Elements.Data.user.main.model.user.role === 'guest') {
773
- NotificationManager.Push({
774
- html: 'Guests cannot save object layers. Please log in.',
775
- status: 'warning',
776
- });
777
- return;
778
- }
779
-
780
- // Upload images
781
- {
782
- // Get all direction codes that currently have frames
783
- const directionCodesToUpload = Object.keys(ObjectLayerEngineModal.ObjectLayerData);
784
-
785
- // In UPDATE mode, also include original direction codes that may have been cleared
786
- const allDirectionCodes = existingObjectLayerId
787
- ? [...new Set([...directionCodesToUpload, ...originalDirectionCodes])]
788
- : directionCodesToUpload;
789
-
790
- console.warn(
791
- `Uploading frames for ${allDirectionCodes.length} directions:`,
792
- allDirectionCodes,
793
- existingObjectLayerId ? '(UPDATE MODE)' : '(CREATE MODE)',
794
- );
795
-
796
- for (const directionCode of allDirectionCodes) {
797
- const frames = ObjectLayerEngineModal.ObjectLayerData[directionCode] || [];
798
- console.warn(`Direction ${directionCode}: ${frames.length} frames`);
799
-
800
- // Create FormData with ALL frames for this direction
801
- const form = new FormData();
802
- let frameIndex = -1;
803
- for (const frame of frames) {
804
- frameIndex++;
805
- const pngBlob = frame.image;
806
-
807
- if (!pngBlob) {
808
- console.error(`Frame ${frameIndex} in direction ${directionCode} has no image blob!`);
809
- continue;
810
- }
811
-
812
- // Append all frames to the same FormData
813
- form.append(directionCode, pngBlob, `${frameIndex}.png`);
814
- }
815
-
816
- // Send all frames for this direction in one request (even if empty, to remove frames)
817
- try {
818
- if (existingObjectLayerId) {
819
- // UPDATE: use PUT endpoint with object layer ID
820
- const { status, data } = await ObjectLayerService.put({
821
- id: `${existingObjectLayerId}/frame-image/${objectLayer.data.item.type}/${objectLayer.data.item.id}/${directionCode}`,
822
- body: form,
823
- headerId: 'file',
824
- });
825
- console.warn(`Updated ${frames.length} frames for direction ${directionCode}`);
826
- } else {
827
- // CREATE: use POST endpoint (only if frames exist)
828
- if (frames.length > 0) {
829
- const { status, data } = await ObjectLayerService.post({
830
- id: `frame-image/${objectLayer.data.item.type}/${objectLayer.data.item.id}/${directionCode}`,
831
- body: form,
832
- headerId: 'file',
833
- });
834
- console.warn(`Created ${frames.length} frames for direction ${directionCode}`);
835
- }
836
- }
837
- } catch (error) {
838
- console.error(`Error uploading frames for direction ${directionCode}:`, error);
839
- NotificationManager.Push({
840
- html: `Error uploading frames for direction ${directionCode}: ${error.message}`,
841
- status: 'error',
842
- });
843
- return;
844
- }
845
- }
846
-
847
- console.warn('All frames uploaded successfully');
848
- }
849
-
850
- // Upload metadata
851
- {
852
- delete objectLayer.data.render.frames;
853
- delete objectLayer.data.render.color;
854
-
855
- let response;
856
- if (existingObjectLayerId) {
857
- // UPDATE existing object layer
858
- console.warn(
859
- 'PUT path:',
860
- `${existingObjectLayerId}/metadata/${objectLayer.data.item.type}/${objectLayer.data.item.id}`,
861
- );
862
- response = await ObjectLayerService.put({
863
- id: `${existingObjectLayerId}/metadata/${objectLayer.data.item.type}/${objectLayer.data.item.id}`,
864
- body: objectLayer,
865
- });
866
- } else {
867
- // CREATE new object layer
868
- response = await ObjectLayerService.post({
869
- id: `metadata/${objectLayer.data.item.type}/${objectLayer.data.item.id}`,
870
- body: objectLayer,
871
- });
872
- }
873
-
874
- const { status, data, message } = response;
875
-
876
- if (status === 'success') {
877
- NotificationManager.Push({
878
- html: `Object layer "${objectLayer.data.item.id}" ${existingObjectLayerId ? 'updated' : 'created'} successfully!`,
879
- status: 'success',
880
- });
881
- ObjectLayerEngineModal.toManagement();
882
- } else {
883
- NotificationManager.Push({
884
- html: `Error ${existingObjectLayerId ? 'updating' : 'creating'} object layer: ${message}`,
885
- status: 'error',
886
- });
887
- }
888
- }
889
- });
890
-
891
- // Add reset button event listener
892
- EventsUI.onClick(`.ol-btn-reset`, async () => {
893
- const confirmResult = await Modal.RenderConfirm({
894
- html: async () => {
895
- return html`
896
- <div class="in section-mp" style="text-align: center">
897
- Are you sure you want to reset the form? All unsaved data will be lost.
898
- </div>
899
- `;
900
- },
901
- id: `reset-ol-modal-confirm`,
902
- });
903
-
904
- if (confirmResult.status === 'confirm') {
905
- NotificationManager.Push({
906
- html: 'Resetting form to create new object layer...',
907
- status: 'info',
908
- });
909
-
910
- // Clear all data
911
- ObjectLayerEngineModal.clearData();
912
-
913
- setPath(`${getProxyPath()}object-layer-engine`);
914
-
915
- // Reload the modal
916
- await ObjectLayerEngineModal.Reload();
917
-
918
- NotificationManager.Push({
919
- html: 'Form reset! Ready to create new object layer.',
920
- status: 'success',
921
- });
922
- }
923
- });
924
- });
925
-
926
- return html`
927
- <style>
928
- .direction-code-bar-frames-title {
929
- font-weight: bold;
930
- font-size: 1.2rem;
931
- padding: 0.5rem;
932
- }
933
- .direction-code-bar-frames-img {
934
- width: 100px;
935
- height: auto;
936
- margin: 3px;
937
- cursor: pointer;
938
- }
939
- .direction-code-bar-trash-btn {
940
- top: 3px;
941
- left: 30px;
942
- color: white;
943
- border: none !important;
944
- }
945
- .direction-code-bar-edit-btn {
946
- top: 3px;
947
- left: 3px;
948
- color: white;
949
- border: none !important;
950
- }
951
- .direction-code-bar-frames-btn-add {
952
- color: white;
953
- border: none !important;
954
- }
955
- .direction-code-bar-trash-btn:hover {
956
- background: none !important;
957
- color: red;
958
- }
959
- .direction-code-bar-edit-btn:hover {
960
- background: none !important;
961
- color: yellow;
962
- }
963
- .direction-code-bar-frames-btn-add:hover {
964
- background: none !important;
965
- color: #c7ff58;
966
- }
967
- .ol-btn-save {
968
- width: 120px;
969
- padding: 0.5rem;
970
- font-size: 20px;
971
- min-height: 50px;
972
- }
973
- .ol-btn-reset {
974
- width: 120px;
975
- padding: 0.5rem;
976
- font-size: 20px;
977
- min-height: 50px;
978
- }
979
- .ol-number-label {
980
- width: 120px;
981
- font-size: 16px;
982
- overflow: hidden;
983
- font-family: 'retro-font';
984
- }
985
- .sub-title-modal {
986
- color: #ffcc00;
987
- }
988
- .stat-label-container {
989
- display: flex;
990
- align-items: center;
991
- }
992
- .stat-info-icon {
993
- cursor: default;
994
- }
995
- .stat-description {
996
- padding: 2px 5px;
997
- border-left: 2px solid #444;
998
- margin-bottom: 5px;
999
- max-width: 200px;
1000
- }
1001
- .frame-editor-container-loading {
1002
- width: 100%;
1003
- height: 150px;
1004
- color: #ffcc00;
1005
- }
1006
- .loading-text {
1007
- font-family: 'retro-font';
1008
- font-size: 26px;
1009
- }
1010
- </style>
1011
- ${borderChar(2, 'black', [
1012
- '.sub-title-modal',
1013
- '.frame-editor-container-loading',
1014
- '.direction-code-bar-edit-btn',
1015
- '.direction-code-bar-trash-btn',
1016
- '.direction-code-bar-frames-btn-add',
1017
- ])}
1018
- <div class="in frame-editor-container-loading">
1019
- <div class="abs center frame-editor-container-loading-center"></div>
1020
- </div>
1021
- <div class="in section-mp section-mp-border frame-editor-container">
1022
- <div class="in sub-title-modal"><i class="fa-solid fa-table-cells-large"></i> Frame editor</div>
1023
-
1024
- <object-layer-engine id="ole" width="${cells}" height="${cells}" pixel-size="${pixelSize}">
1025
- </object-layer-engine>
1026
- <object-layer-png-loader id="loader" editor-selector="#ole"></object-layer-png-loader>
1027
- </div>
1028
-
1029
- <div class="in section-mp section-mp-border">
1030
- <div class="in sub-title-modal"><i class="fa-solid fa-database"></i> Render data</div>
1031
- ${dynamicCol({ containerSelector: options.idModal, id: idSectionA })}
1032
-
1033
- <div class="fl">
1034
- <div class="in fll ${idSectionA}-col-a">
1035
- <div class="in section-mp">
1036
- ${await DropDown.Render({
1037
- value: ObjectLayerEngineModal.templates[0].id,
1038
- label: html`${Translate.Render('select-template')}`,
1039
- data: ObjectLayerEngineModal.templates.map((template) => {
1040
- return {
1041
- value: template.id,
1042
- display: html`<i class="fa-solid fa-paint-roller"></i> ${template.label}`,
1043
- onClick: async () => {
1044
- ObjectLayerEngineModal.RenderTemplate(template.data);
1045
- },
1046
- };
1047
- }),
1048
- })}
1049
- </div>
1050
- </div>
1051
- <div class="in fll ${idSectionA}-col-b">
1052
- <div class="in section-mp-border" style="width: 135px;">
1053
- ${await Input.Render({
1054
- id: `ol-input-render-frame-duration`,
1055
- label: html`<div class="inl ol-number-label">
1056
- <i class="fa-solid fa-chart-simple"></i> Frame duration
1057
- </div>`,
1058
- containerClass: 'inl',
1059
- type: 'number',
1060
- min: 100,
1061
- max: 1000,
1062
- placeholder: true,
1063
- value: renderFrameDuration,
1064
- })}
1065
- </div>
1066
- <div class="in section-mp">
1067
- ${await ToggleSwitch.Render({
1068
- id: 'ol-toggle-render-is-stateless',
1069
- wrapper: true,
1070
- wrapperLabel: html`${Translate.Render('is-stateless')}`,
1071
- disabledOnClick: true,
1072
- checked: renderIsStateless,
1073
- on: {
1074
- unchecked: () => {
1075
- renderIsStateless = false;
1076
- console.warn('renderIsStateless', renderIsStateless);
1077
- },
1078
- checked: () => {
1079
- renderIsStateless = true;
1080
- console.warn('renderIsStateless', renderIsStateless);
1081
- },
1082
- },
1083
- })}
1084
- </div>
1085
- </div>
1086
- </div>
1087
- ${directionsCodeBarRender}
1088
- </div>
1089
- ${dynamicCol({ containerSelector: options.idModal, id: idSectionB, type: 'a-50-b-50' })}
1090
-
1091
- <div class="fl">
1092
- <div class="in fll ${idSectionB}-col-a">
1093
- <div class="in section-mp section-mp-border">
1094
- <div class="in sub-title-modal"><i class="fa-solid fa-database"></i> Item data</div>
1095
- ${await Input.Render({
1096
- id: `ol-input-item-id`,
1097
- label: html`<i class="fa-solid fa-pen-to-square"></i> ${Translate.Render('item-id')}`,
1098
- containerClass: '',
1099
- placeholder: true,
1100
- value: loadedData?.metadata?.data?.item?.id || '',
1101
- })}
1102
- ${await Input.Render({
1103
- id: `ol-input-item-description`,
1104
- label: html`<i class="fa-solid fa-pen-to-square"></i> ${Translate.Render('item-description')}`,
1105
- containerClass: '',
1106
- placeholder: true,
1107
- value: loadedData?.metadata?.data?.item?.description || '',
1108
- })}
1109
- <div class="in section-mp">
1110
- ${await DropDown.Render({
1111
- value: selectItemType,
1112
- label: html`${Translate.Render('select-item-type')}`,
1113
- data: itemTypes.map((itemType) => {
1114
- return {
1115
- value: itemType,
1116
- display: html`${itemType}`,
1117
- onClick: async () => {
1118
- console.warn('itemType click', itemType);
1119
- selectItemType = itemType;
1120
- },
1121
- };
1122
- }),
1123
- })}
1124
- </div>
1125
- <div class="in section-mp">
1126
- ${await ToggleSwitch.Render({
1127
- id: 'ol-toggle-item-activable',
1128
- wrapper: true,
1129
- wrapperLabel: html`${Translate.Render('item-activable')}`,
1130
- disabledOnClick: true,
1131
- checked: itemActivable,
1132
- on: {
1133
- unchecked: () => {
1134
- itemActivable = false;
1135
- console.warn('itemActivable', itemActivable);
1136
- },
1137
- checked: () => {
1138
- itemActivable = true;
1139
- console.warn('itemActivable', itemActivable);
1140
- },
1141
- },
1142
- })}
1143
- </div>
1144
- </div>
1145
- </div>
1146
- <div class="in fll ${idSectionB}-col-b">
1147
- <div class="in section-mp section-mp-border">
1148
- <div class="in sub-title-modal"><i class="fa-solid fa-database"></i> Stats data</div>
1149
- ${statsInputsRender}
1150
- </div>
1151
- </div>
1152
- </div>
1153
-
1154
- <div class="fl section-mp">
1155
- ${await BtnIcon.Render({
1156
- label: html`<i class="submit-btn-icon fa-solid fa-folder-open"></i> ${Translate.Render('save')}`,
1157
- class: `in flr ol-btn-save`,
1158
- })}
1159
- ${await BtnIcon.Render({
1160
- label: html`<i class="submit-btn-icon fa-solid fa-broom"></i> ${Translate.Render('reset')}`,
1161
- class: `in flr ol-btn-reset`,
1162
- })}
1163
- </div>
1164
- <div class="in section-mp"></div>
1165
- `;
1166
- },
1167
- getDirectionsFromDirectionCode(directionCode = '08') {
1168
- let objectLayerFrameDirections = [];
1169
-
1170
- switch (directionCode) {
1171
- case '08':
1172
- objectLayerFrameDirections = ['down_idle', 'none_idle', 'default_idle'];
1173
- break;
1174
- case '18':
1175
- objectLayerFrameDirections = ['down_walking'];
1176
- break;
1177
- case '02':
1178
- objectLayerFrameDirections = ['up_idle'];
1179
- break;
1180
- case '12':
1181
- objectLayerFrameDirections = ['up_walking'];
1182
- break;
1183
- case '04':
1184
- objectLayerFrameDirections = ['left_idle', 'up_left_idle', 'down_left_idle'];
1185
- break;
1186
- case '14':
1187
- objectLayerFrameDirections = ['left_walking', 'up_left_walking', 'down_left_walking'];
1188
- break;
1189
- case '06':
1190
- objectLayerFrameDirections = ['right_idle', 'up_right_idle', 'down_right_idle'];
1191
- break;
1192
- case '16':
1193
- objectLayerFrameDirections = ['right_walking', 'up_right_walking', 'down_right_walking'];
1194
- break;
1195
- }
1196
-
1197
- return objectLayerFrameDirections;
1198
- },
1199
- toManagement: async () => {
1200
- await ObjectLayerEngineModal.clearData();
1201
- const subModalId = 'viewer' || 'management';
1202
- const modalId = `modal-object-layer-engine-${subModalId}`;
1203
- const queryParams = getQueryParams();
1204
- queryParams.cid = '';
1205
- queryParams.page = 1;
1206
- setQueryParams(queryParams);
1207
- const managerComponent = DefaultManagement.Tokens[modalId];
1208
- if (managerComponent) {
1209
- managerComponent.page = 1;
1210
- if (!managerComponent.readyRowDataEvent) managerComponent.readyRowDataEvent = {};
1211
- let readyLoad = false;
1212
- const gridId = `object-layer-engine-management-grid-${modalId}`;
1213
- managerComponent.readyRowDataEvent[`object-layer-engine-${subModalId}`] = async () => {
1214
- if (readyLoad) {
1215
- AgGrid.grids[gridId].setGridOption('getRowClass', null);
1216
- return delete managerComponent.readyRowDataEvent[`object-layer-engine-${subModalId}`];
1217
- }
1218
-
1219
- AgGrid.grids[gridId].setGridOption('getRowClass', (params) => {
1220
- if (params.node.rowIndex === 0) {
1221
- return 'row-new-highlight';
1222
- }
1223
- });
1224
- readyLoad = true;
1225
- };
1226
- }
1227
-
1228
- const _s = s(` .management-table-btn-reload-${modalId}`);
1229
- if (_s) _s.click();
1230
-
1231
- s(`.main-btn-object-layer-engine-${subModalId}`).click();
1232
- },
1233
- Reload: async function () {
1234
- // Clear data before reload to prevent contamination
1235
- ObjectLayerEngineModal.clearData();
1236
- const idModal = 'modal-object-layer-engine';
1237
- if (s(`.modal-object-layer-engine`))
1238
- Modal.writeHTML({
1239
- idModal,
1240
- html: await Modal.Data[idModal].options.html(),
1241
- });
1242
- },
1243
- };
1244
-
1245
- export { ObjectLayerEngineModal };