architwin 1.15.1 → 1.15.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.
- package/lib/architwin.d.ts +2 -1
- package/lib/architwin.js +1 -1
- package/lib/atwinui/components/toolbar/i18n.js +9 -2
- package/lib/atwinui/components/toolbar/index.d.ts +2 -1
- package/lib/atwinui/components/toolbar/index.js +3 -1
- package/lib/atwinui/components/toolbar/previewModal.d.ts +6 -0
- package/lib/atwinui/components/toolbar/previewModal.js +104 -0
- package/lib/atwinui/components/toolbar/spacePartition/roomFormPane.js +48 -42
- package/lib/atwinui/components/toolbar/spacePartition/roomTreePane.d.ts +6 -1
- package/lib/atwinui/components/toolbar/spacePartition/roomTreePane.js +54 -31
- package/lib/atwinui/components/toolbar/tagIotFormPane.js +3 -2
- package/lib/atwinui/components/toolbar/tagListPane.js +2 -2
- package/lib/atwinui/events.js +25 -6
- package/lib/loaders/polydrawerLoader.js +24 -5
- package/package.json +1 -1
- package/static/atwinui.css +338 -4
- package/static/utility.css +4 -1
|
@@ -191,6 +191,8 @@ i18n
|
|
|
191
191
|
"Chemical": "Chemical",
|
|
192
192
|
"Submeter": "Submeter",
|
|
193
193
|
"Frequency": "Frequency",
|
|
194
|
+
"Camera": "Camera",
|
|
195
|
+
"Others": "Others",
|
|
194
196
|
"DeleteDevice": "Delete Device",
|
|
195
197
|
"ConfirmDeleteDevice": "Are you sure you want to delete this device? This action cannot be reversed",
|
|
196
198
|
"SuccessDeleteDevice": "Successfully deleted device",
|
|
@@ -272,7 +274,8 @@ i18n
|
|
|
272
274
|
"MoveTagCancelled": "Move Tag Cancelled",
|
|
273
275
|
"Window": "Window",
|
|
274
276
|
"CannotBackDrawingMode": "Cannot go back while drawing mode is active.",
|
|
275
|
-
"PleaseOffDrawingMode": "Action cannot be done, please turn off drawing mode."
|
|
277
|
+
"PleaseOffDrawingMode": "Action cannot be done, please turn off drawing mode.",
|
|
278
|
+
"IotCategoryRequired": "IoT Category is required"
|
|
276
279
|
}
|
|
277
280
|
},
|
|
278
281
|
ja: {
|
|
@@ -464,6 +467,8 @@ i18n
|
|
|
464
467
|
"Chemical": "化学物質",
|
|
465
468
|
"Submeter": "サブメーター",
|
|
466
469
|
"Frequency": "周波数",
|
|
470
|
+
"Camera": "カメラ",
|
|
471
|
+
"Others": "その他",
|
|
467
472
|
"DeleteDevice": "デバイス削除",
|
|
468
473
|
"ConfirmDeleteDevice": "この操作は元に戻せません。このデバイスを削除しますか?",
|
|
469
474
|
"SuccessDeleteDevice": "デバイスを削除しました",
|
|
@@ -538,7 +543,9 @@ i18n
|
|
|
538
543
|
"PressEscCancelRelocation": "再配置をキャンセルするには、Esc キーを押します。",
|
|
539
544
|
"Window": "建具",
|
|
540
545
|
"CannotBackDrawingMode": "描画モードがアクティブな間は戻ることができません。",
|
|
541
|
-
"PleaseOffDrawingMode": "操作を行う前に、描画モードをオフにしてください。"
|
|
546
|
+
"PleaseOffDrawingMode": "操作を行う前に、描画モードをオフにしてください。",
|
|
547
|
+
"Successfully Deleted Tag": "タグを削除しました",
|
|
548
|
+
"IotCategoryRequired": "IoTカテゴリは必須です"
|
|
542
549
|
}
|
|
543
550
|
}
|
|
544
551
|
},
|
|
@@ -3,6 +3,7 @@ import { setActiveMenu, clearActiveMenu, getObjectListStatus } from "./menuBar";
|
|
|
3
3
|
import { renderObjectCards, removeObjectCard } from "./objectListPane";
|
|
4
4
|
import { getTagFormData, setTagCategoriesOption, tagFormMode, selectedTag, renderCategoryDropdownOptions, toggleDropdown } from "./tagFormPane";
|
|
5
5
|
import { renderTags, renderTagRow, addClickEventToTagRow, setTagLink, getTagLink, selectedCategoryFilterId, selectedSubCategoryFilterId, filterTagList } from "./tagListPane";
|
|
6
|
+
import { renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal } from "./previewModal";
|
|
6
7
|
import { setActiveActionBtn, clearActiveActionBtn, toggleActionBarButtons } from "./actionBar";
|
|
7
8
|
import { renderLibraryCards } from "./libraryPane";
|
|
8
9
|
import { setActiveThemeCard } from "./themePane";
|
|
@@ -21,4 +22,4 @@ declare let actionBar: HTMLElement;
|
|
|
21
22
|
*/
|
|
22
23
|
declare function setPreferredLanguage(): void;
|
|
23
24
|
declare function renderToolbarUI(payload: IToolbarData): void;
|
|
24
|
-
export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage };
|
|
25
|
+
export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage, renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal };
|
|
@@ -7,6 +7,7 @@ import { renderViewingRemoteSpace } from "./viewingRemoteSpace";
|
|
|
7
7
|
import { renderAddObjectPane } from "./addObjectPane";
|
|
8
8
|
import { renderTagFormPane, getTagFormData, setTagCategoriesOption, tagFormMode, selectedTag, renderCategoryDropdownOptions, toggleDropdown } from "./tagFormPane";
|
|
9
9
|
import { renderTagListPane, renderTags, renderTagRow, addClickEventToTagRow, setTagLink, getTagLink, selectedCategoryFilterId, selectedSubCategoryFilterId, filterTagList } from "./tagListPane";
|
|
10
|
+
import { renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal } from "./previewModal";
|
|
10
11
|
import { renderAddMediascreenFormPane } from "./addMediascreenFormPane";
|
|
11
12
|
import { renderActionBar, setActiveActionBtn, clearActiveActionBtn, toggleActionBarButtons } from "./actionBar";
|
|
12
13
|
import { renderLibraryPane, renderLibraryCards } from "./libraryPane";
|
|
@@ -108,6 +109,7 @@ function renderToolbarUI(payload) {
|
|
|
108
109
|
pipeListPane = pipeList.renderPane();
|
|
109
110
|
pipeFormPane = pipeForm.renderPane();
|
|
110
111
|
renderModal();
|
|
112
|
+
renderPreviewModal();
|
|
111
113
|
sidebarContainer.appendChild(modelControlPane);
|
|
112
114
|
sidebarContainer.appendChild(basepointCalibratePane);
|
|
113
115
|
sidebarContainer.appendChild(actionBar);
|
|
@@ -165,4 +167,4 @@ function renderToolbarUI(payload) {
|
|
|
165
167
|
themeManager(config);
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
|
-
export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage };
|
|
170
|
+
export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage, renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ModalContent } from '../../../types';
|
|
2
|
+
export declare let activePreviewModal: boolean;
|
|
3
|
+
export declare function renderPreviewModal(): void;
|
|
4
|
+
export declare function togglePreviewModal(visible?: boolean): void;
|
|
5
|
+
export declare function closePreviewModal(): void;
|
|
6
|
+
export declare function setPreviewModalAction(content: ModalContent, iframeSrc?: string): Promise<void>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export let activePreviewModal = false;
|
|
11
|
+
export function renderPreviewModal() {
|
|
12
|
+
const element = document.createElement('div');
|
|
13
|
+
element.setAttribute('id', 'at-preview-modal-overlay');
|
|
14
|
+
element.setAttribute('data-cy', 'at-preview-modal-overlay');
|
|
15
|
+
element.innerHTML = `
|
|
16
|
+
<div class="at_preview_modal">
|
|
17
|
+
<div class="at_preview_modal-header">
|
|
18
|
+
<h2 class="at_preview_modal-title" id="at-preview-modal-content-heading" data-cy="at-preview-modal-content-heading"></h2>
|
|
19
|
+
<button class="at_preview_modal-close-btn" data-cy="at-preview-modal-close-btn">×</button>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="at_preview_modal-body">
|
|
22
|
+
<div class="at_preview_modal-content" id="at-preview-modal-content-subheading" data-cy="at-preview-modal-content-subheading">
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
`;
|
|
27
|
+
document.body.appendChild(element);
|
|
28
|
+
const modalOverlay = document.getElementById('at-preview-modal-overlay');
|
|
29
|
+
const modalCloseBtn = document.querySelector('.at_preview_modal-close-btn');
|
|
30
|
+
if (modalCloseBtn) {
|
|
31
|
+
modalCloseBtn.addEventListener('click', () => {
|
|
32
|
+
modalOverlay.classList.remove('show');
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (modalOverlay) {
|
|
36
|
+
modalOverlay.addEventListener('click', (event) => {
|
|
37
|
+
if (event.target === modalOverlay) {
|
|
38
|
+
modalOverlay.classList.remove('show');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const handleEscape = (event) => {
|
|
43
|
+
if (event.key === 'Escape') {
|
|
44
|
+
modalOverlay.classList.remove('show');
|
|
45
|
+
document.removeEventListener('keydown', handleEscape);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
document.addEventListener('keydown', handleEscape);
|
|
49
|
+
}
|
|
50
|
+
export function togglePreviewModal(visible = true) {
|
|
51
|
+
const modalOverlay = document.getElementById('at-preview-modal-overlay');
|
|
52
|
+
if (!modalOverlay) {
|
|
53
|
+
console.error("Preview modal overlay is undefined");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (visible) {
|
|
57
|
+
modalOverlay.classList.add('show');
|
|
58
|
+
activePreviewModal = true;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
modalOverlay.classList.remove('show');
|
|
62
|
+
activePreviewModal = false;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
export function closePreviewModal() {
|
|
66
|
+
const modalOverlay = document.getElementById('at-preview-modal-overlay');
|
|
67
|
+
if (modalOverlay) {
|
|
68
|
+
modalOverlay.classList.remove('show');
|
|
69
|
+
activePreviewModal = false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function setPreviewModalAction(content, iframeSrc) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
const modalAcceptBtn = document.querySelector('.at_modal-accept-button');
|
|
75
|
+
const modalTitle = document.getElementById('at-preview-modal-content-heading');
|
|
76
|
+
const modelDesc = document.getElementById('at-preview-modal-content-subheading');
|
|
77
|
+
if (content) {
|
|
78
|
+
if (modalTitle && content.title) {
|
|
79
|
+
modalTitle.textContent = content.title;
|
|
80
|
+
}
|
|
81
|
+
if (modelDesc) {
|
|
82
|
+
if (iframeSrc) {
|
|
83
|
+
// If iframeSrc is provided, create iframe instead of text
|
|
84
|
+
modelDesc.innerHTML = `<iframe src="${iframeSrc}" class="at_preview_modal-iframe"></iframe>`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
modelDesc.innerHTML = `<div class="at_preview_modal-content">${content.description}</div>`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// if (modalAcceptBtn) {
|
|
92
|
+
// if (content && content.buttonLabel) {
|
|
93
|
+
// modalAcceptBtn.textContent = content.buttonLabel
|
|
94
|
+
// }
|
|
95
|
+
// if (callback) {
|
|
96
|
+
// modalAcceptBtn.onclick = async () => {
|
|
97
|
+
// await callback()
|
|
98
|
+
// }
|
|
99
|
+
// }else{
|
|
100
|
+
// modalAcceptBtn.onclick = closePreviewModal
|
|
101
|
+
// }
|
|
102
|
+
// }
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import i18n from '../i18n';
|
|
11
11
|
import { SPACE_EVENTS } from "../../../../types";
|
|
12
12
|
import { batchAddEventListenerByClassName } from "../../../events";
|
|
13
|
-
import { startDraw, cancelDraw, disposeModel, _3DXObjects, getCurrentPolygon, dispatchSpaceEvent, enableVerticeControls, setCurrentPolygon, setMeshChildrenMaterialProperty, get3DXObjects, getChildrenOfModel, clearSelectedObject, renderPolygon, addUndoDrawActions, setWallBaseHeight, clearWallBaseHeight, setDrawingConfig, resetDrawingConfig, goToPosition } from '../../../../architwin';
|
|
13
|
+
import { startDraw, cancelDraw, disposeModel, _3DXObjects, getCurrentPolygon, dispatchSpaceEvent, enableVerticeControls, setCurrentPolygon, setMeshChildrenMaterialProperty, get3DXObjects, getChildrenOfModel, clearSelectedObject, renderPolygon, addUndoDrawActions, setWallBaseHeight, clearWallBaseHeight, setDrawingConfig, resetDrawingConfig, goToPosition, clearFloorBaseHeight } from '../../../../architwin';
|
|
14
14
|
import { generateUUID, extractUUID } from '../../../../utils';
|
|
15
15
|
import { getCurrentEditRoomData } from './roomTreePane';
|
|
16
16
|
import { toggleModal, setModalAction } from "../modal";
|
|
@@ -249,6 +249,7 @@ export function toggleDrawWindowButton() {
|
|
|
249
249
|
`;
|
|
250
250
|
const objectIndex = _3DXObjects.findIndex(obj => obj.object.id == currentObject.object.id);
|
|
251
251
|
log.info("objectIndex", objectIndex);
|
|
252
|
+
clearFloorBaseHeight();
|
|
252
253
|
drawingConfig = {
|
|
253
254
|
lineTypeComponentConfig: {
|
|
254
255
|
renderPolygonOnAdd: false,
|
|
@@ -1023,48 +1024,53 @@ function setupDeleteWindow(element, window) {
|
|
|
1023
1024
|
if (!deleteBtn)
|
|
1024
1025
|
return;
|
|
1025
1026
|
deleteBtn.addEventListener("click", () => {
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
windowLists
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
_3DXObjects[objectIndex].children
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1027
|
+
if (!isDrawing) {
|
|
1028
|
+
toggleModal();
|
|
1029
|
+
setModalAction({
|
|
1030
|
+
title: i18n.t("DeleteWindow"),
|
|
1031
|
+
description: i18n.t("ConfirmDeleteWindow"),
|
|
1032
|
+
buttonLabel: i18n.t("YesDelete"),
|
|
1033
|
+
}, () => __awaiter(this, void 0, void 0, function* () {
|
|
1034
|
+
element.remove();
|
|
1035
|
+
log.info("Deleted window:", window.index);
|
|
1036
|
+
toggleModal(false);
|
|
1037
|
+
// Update wall windows
|
|
1038
|
+
currentPolygonData.walls = currentPolygonData.walls.map(wall => {
|
|
1039
|
+
if (wall.uuid !== currentWall.uuid)
|
|
1040
|
+
return wall;
|
|
1041
|
+
if (wall.windows.length === 1) {
|
|
1042
|
+
const windowLists = document.getElementById(`at-window-list-${wall.uuid}`);
|
|
1043
|
+
if (windowLists)
|
|
1044
|
+
windowLists.style.display = "none";
|
|
1045
|
+
}
|
|
1046
|
+
currentWall = Object.assign(Object.assign({}, wall), { windows: wall.windows.filter((w) => w.index !== window.index) });
|
|
1047
|
+
return currentWall;
|
|
1048
|
+
});
|
|
1049
|
+
const objectIndex = _3DXObjects.findIndex(obj => obj.object.object_id == currentObject.object.object_id);
|
|
1050
|
+
if (objectIndex != null) {
|
|
1051
|
+
log.info("objectIndex", objectIndex);
|
|
1052
|
+
if (_3DXObjects[objectIndex].children) {
|
|
1053
|
+
_3DXObjects[objectIndex].children.map((win) => __awaiter(this, void 0, void 0, function* () {
|
|
1054
|
+
log.info("WIND", win);
|
|
1055
|
+
if (win.index == window.index && win.wallUUID == currentWall.uuid) {
|
|
1056
|
+
yield disposeModel(win);
|
|
1057
|
+
}
|
|
1058
|
+
}));
|
|
1059
|
+
}
|
|
1057
1060
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
}
|
|
1061
|
+
// Save + rerender window
|
|
1062
|
+
currentObject.object.object_data.json_data = currentPolygonData;
|
|
1063
|
+
saveWallChanges();
|
|
1064
|
+
notify.success(`${i18n.t('SuccessWindowDelete')}`);
|
|
1065
|
+
log.info("currentPartition polygonJson", JSON.parse(currentPartitionData.polygon_json));
|
|
1066
|
+
log.info("currentObject", currentObject);
|
|
1067
|
+
log.info("currentWall", currentWall);
|
|
1068
|
+
log.info("currentPolygonData", currentPolygonData);
|
|
1069
|
+
}));
|
|
1070
|
+
}
|
|
1071
|
+
else {
|
|
1072
|
+
notify.error(i18n.t("PleaseOffDrawingMode"));
|
|
1073
|
+
}
|
|
1068
1074
|
});
|
|
1069
1075
|
}
|
|
1070
1076
|
/**
|
|
@@ -81,7 +81,7 @@ export declare function highlightSelectedPartitionChild(partitionId: string, nam
|
|
|
81
81
|
* @param name - The specific name/identifier of the child element whose container to toggle
|
|
82
82
|
* @param expand - Optional boolean to explicitly set expansion state (true = show, false = hide). If undefined, toggles current state
|
|
83
83
|
*/
|
|
84
|
-
export declare function
|
|
84
|
+
export declare function toggleExpandPartitionWallChild(partitionId: string, name: string, expand?: boolean): void;
|
|
85
85
|
/**
|
|
86
86
|
* Highlights the selected window element by toggling CSS classes and ensures its parent partition is expanded.
|
|
87
87
|
* @param wallUuid - The unique identifier of the wall containing the window elements
|
|
@@ -92,6 +92,11 @@ export declare function highlightSelectedWindow(wallUuid: string, index: number
|
|
|
92
92
|
* Removes the highlight from all selected window items by removing the 'selected' CSS class.
|
|
93
93
|
*/
|
|
94
94
|
export declare function toggleHighlightedWindowItem(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Toggles the highlighted state of partition items by adding 'selected' class to the matching partition and removing it from others.
|
|
97
|
+
* @param partitionId - The partition ID to highlight (only the prefix before the first hyphen is used for matching)
|
|
98
|
+
*/
|
|
99
|
+
export declare function toggleHighlightedPartitionItem(partitionId: string): void;
|
|
95
100
|
/**
|
|
96
101
|
* Calculates the midpoint (centroid) of multiple 3D coordinates by averaging their x, y, and z values.
|
|
97
102
|
* @param coords - An array of objects containing start Vector3 coordinates
|
|
@@ -120,7 +120,7 @@ export function displayRoomPartition(partition, objectData) {
|
|
|
120
120
|
element.innerHTML = `
|
|
121
121
|
<li class="at_room_tree_parent">
|
|
122
122
|
<div id="at-div-room-${partition.uuid}" class="at_flex at_space_between at_toggle">
|
|
123
|
-
<span class="toggle selectable" id="at-room-${partition.uuid}">▶ ${partition.name}</span>
|
|
123
|
+
<span class="at_room_name_text toggle selectable" id="at-room-${partition.uuid}">▶ ${partition.name}</span>
|
|
124
124
|
<div>
|
|
125
125
|
<span id="at-room-edit-${partition.uuid}-btn" class="mdi mdi-pencil at_room_edit_btn" target-pane="at-room-form-pane"></span>
|
|
126
126
|
<span id="at-room-visibility-btn-${partition.uuid}" class="mdi ${isVisible ? 'mdi-eye ' : 'mdi-eye-off'} at_room_visible_btn"></span>
|
|
@@ -182,8 +182,8 @@ export function displayChildPartitions(partitions, parentPartitionId, objectData
|
|
|
182
182
|
return `
|
|
183
183
|
|
|
184
184
|
<li class="at_room_tree_child">
|
|
185
|
-
<div id="at-child-partition-${partition.uuid.split('-')[0]}" class="at_flex at_space_between at_toggle">
|
|
186
|
-
<span class="toggle selectable" id="at-partition-${partition.uuid}" object-id="${objectId}" parentId="at-partition-${parentPartitionId}">▶ ${i18n.t(`${partition.name}`)}</span>
|
|
185
|
+
<div id="at-child-partition-${partition.uuid.split('-')[0]}" class="at_partion_row_item at_flex at_space_between at_toggle">
|
|
186
|
+
<span class="at_partition_name_text toggle selectable" id="at-partition-${partition.uuid}" object-id="${objectId}" parentId="at-partition-${parentPartitionId}">▶ ${i18n.t(`${partition.name}`)}</span>
|
|
187
187
|
<div>
|
|
188
188
|
<span id="at-partition-visibility-btn-${objectId}" parent-id="${parentPartitionId}"
|
|
189
189
|
class="mdi ${isVisible ? 'mdi-eye ' : 'mdi-eye-off'} at_room_visible_btn"></span>
|
|
@@ -363,7 +363,7 @@ function toggleSelectedPartition() {
|
|
|
363
363
|
yield new Promise(resolve => setTimeout(resolve, 0));
|
|
364
364
|
yield new Promise(resolve => requestAnimationFrame(resolve));
|
|
365
365
|
const wallId = target.getAttribute('polygon-item-id');
|
|
366
|
-
const windowItems = document.querySelectorAll(`li.
|
|
366
|
+
const windowItems = document.querySelectorAll(`li.at_window_row_item[wall-id="${wallId}"]`);
|
|
367
367
|
if (windowItems && windowItems.length > 0) {
|
|
368
368
|
windowItems.forEach((windowLi) => {
|
|
369
369
|
const visibilityBtn = windowLi.querySelector('.at_child_visible_btn');
|
|
@@ -387,6 +387,7 @@ function toggleSelectedPartition() {
|
|
|
387
387
|
yield goToPosition(wallBottomMidPoint);
|
|
388
388
|
highlightSelectedPartitionChild(partitionId, objectName);
|
|
389
389
|
toggleHighlightedWindowItem();
|
|
390
|
+
toggleHighlightedPartitionItem(partitionId);
|
|
390
391
|
}
|
|
391
392
|
catch (e) {
|
|
392
393
|
log.info('goToPosition failed: ', e);
|
|
@@ -404,6 +405,7 @@ function toggleSelectedPartition() {
|
|
|
404
405
|
const floorMidPoint = calculateMidPoint(floorCoords);
|
|
405
406
|
yield goToPosition(floorMidPoint);
|
|
406
407
|
highlightSelectedPartitionChild(partitionId, objectName);
|
|
408
|
+
toggleHighlightedPartitionItem(partitionId);
|
|
407
409
|
}
|
|
408
410
|
catch (e) {
|
|
409
411
|
log.info('goToPosition failed: ', e);
|
|
@@ -441,18 +443,21 @@ function toggleSelectedPartition() {
|
|
|
441
443
|
log.info('goToPosition failed: ', e);
|
|
442
444
|
}
|
|
443
445
|
}));
|
|
444
|
-
batchAddEventListenerByClassName('
|
|
446
|
+
batchAddEventListenerByClassName('at_window_row_item', (event) => __awaiter(this, void 0, void 0, function* () {
|
|
445
447
|
event.stopPropagation();
|
|
446
448
|
const targetElement = event.currentTarget;
|
|
447
449
|
const wallUuid = targetElement.getAttribute('wall-id');
|
|
448
450
|
const windowIndex = targetElement.getAttribute('window-index');
|
|
451
|
+
const partitionId = targetElement.getAttribute('partition-id');
|
|
449
452
|
const windowCoordsEncoded = targetElement.getAttribute('window-coords');
|
|
450
453
|
const windowCoordsJSON = atob(windowCoordsEncoded);
|
|
451
454
|
const windowCoords = JSON.parse(windowCoordsJSON);
|
|
452
455
|
try {
|
|
453
456
|
const windowBottomMidPoint = calculateMidPoint(windowCoords);
|
|
454
457
|
yield goToPosition(windowBottomMidPoint);
|
|
458
|
+
toggleHighlightedWindowItem();
|
|
455
459
|
highlightSelectedWindow(wallUuid, windowIndex);
|
|
460
|
+
toggleHighlightedPartitionItem(partitionId);
|
|
456
461
|
}
|
|
457
462
|
catch (e) {
|
|
458
463
|
log.info('goToPosition failed: ', e);
|
|
@@ -720,21 +725,15 @@ export function highlightSelectedPartitionChild(partitionId, name) {
|
|
|
720
725
|
partitionChildren.forEach((partitionChild) => {
|
|
721
726
|
const isSelected = partitionChild.id === targetId;
|
|
722
727
|
const header = partitionChild.querySelector('.at_partition_child_header');
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
arrow.textContent = arrow.textContent.replace('▼', '▶');
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
}
|
|
728
|
+
const listContainer = partitionChild.querySelector('.at_wall_children_container');
|
|
729
|
+
const arrow = header === null || header === void 0 ? void 0 : header.querySelector('.at_partition_child_expand_icon');
|
|
730
|
+
header === null || header === void 0 ? void 0 : header.classList.toggle('selected', isSelected);
|
|
731
|
+
if (!header || !(arrow === null || arrow === void 0 ? void 0 : arrow.textContent) || !listContainer)
|
|
732
|
+
return;
|
|
733
|
+
// for selected: toggle expand/collapse, for non-selected: always collapse
|
|
734
|
+
const shouldExpand = isSelected && arrow.textContent.includes('▶');
|
|
735
|
+
arrow.textContent = arrow.textContent.replace(shouldExpand ? '▶' : '▼', shouldExpand ? '▼' : '▶');
|
|
736
|
+
listContainer.classList.toggle('at_hidden', !shouldExpand);
|
|
738
737
|
});
|
|
739
738
|
}
|
|
740
739
|
/**
|
|
@@ -743,20 +742,27 @@ export function highlightSelectedPartitionChild(partitionId, name) {
|
|
|
743
742
|
* @param name - The specific name/identifier of the child element whose container to toggle
|
|
744
743
|
* @param expand - Optional boolean to explicitly set expansion state (true = show, false = hide). If undefined, toggles current state
|
|
745
744
|
*/
|
|
746
|
-
export function
|
|
745
|
+
export function toggleExpandPartitionWallChild(partitionId, name, expand) {
|
|
747
746
|
const partitionChildren = document.querySelectorAll(`li[partition-li-id="${partitionId}"]`);
|
|
748
747
|
const targetId = `partition-child-${name}`;
|
|
749
748
|
partitionChildren.forEach((partitionChild) => {
|
|
750
749
|
const isSelected = partitionChild.id === targetId;
|
|
750
|
+
const header = partitionChild.querySelector('.at_partition_child_header');
|
|
751
751
|
const listContainer = partitionChild.querySelector('.at_wall_children_container');
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
752
|
+
const arrow = header === null || header === void 0 ? void 0 : header.querySelector('.at_partition_child_expand_icon');
|
|
753
|
+
if (!header || !(arrow === null || arrow === void 0 ? void 0 : arrow.textContent) || !listContainer)
|
|
754
|
+
return;
|
|
755
|
+
// Determine if should be expanded
|
|
756
|
+
let shouldExpand;
|
|
757
|
+
if (isSelected) {
|
|
758
|
+
shouldExpand = expand !== undefined ? expand : !arrow.textContent.includes('▶');
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
shouldExpand = false;
|
|
759
762
|
}
|
|
763
|
+
// Update arrow and container based on shouldExpand
|
|
764
|
+
arrow.textContent = arrow.textContent.replace(shouldExpand ? '▶' : '▼', shouldExpand ? '▼' : '▶');
|
|
765
|
+
listContainer.classList.toggle('at_hidden', !shouldExpand);
|
|
760
766
|
});
|
|
761
767
|
}
|
|
762
768
|
function displayWindows(wall, partitionId, parentId) {
|
|
@@ -768,7 +774,7 @@ function displayWindows(wall, partitionId, parentId) {
|
|
|
768
774
|
const windowCoords = JSON.stringify(window.edges);
|
|
769
775
|
const windowCoordsEncoded = btoa(windowCoords);
|
|
770
776
|
itemsHTML += `
|
|
771
|
-
<li window-coords="${windowCoordsEncoded}" id="window-${wall.uuid}-${window.index}" wall-id="${wall.uuid}" window-name="${window.name}" window-index="${window.index}" class="
|
|
777
|
+
<li window-coords="${windowCoordsEncoded}" partition-id="${partitionId}" id="window-${wall.uuid}-${window.index}" wall-id="${wall.uuid}" window-name="${window.name}" window-index="${window.index}" class="at_window_row_item">
|
|
772
778
|
<div>${window.name}</div>
|
|
773
779
|
<div>
|
|
774
780
|
<span window-coords="${windowCoordsEncoded}" partition-id="${partitionId}" partition-parent-uuid="${parentId}" polygon-item-id="${wall.uuid}" index="${window.index}" class="mdi mdi-pencil at_window_edit_btn"></span>
|
|
@@ -844,7 +850,7 @@ export function highlightSelectedWindow(wallUuid, index) {
|
|
|
844
850
|
const parentWallItem = windowElement.closest('li.at_partition_wall_row_item');
|
|
845
851
|
const partitionId = parentWallItem.getAttribute('partition-li-id');
|
|
846
852
|
const objectName = parentWallItem.getAttribute('object-name');
|
|
847
|
-
|
|
853
|
+
toggleExpandPartitionWallChild(partitionId, objectName, true);
|
|
848
854
|
}
|
|
849
855
|
windowElement.classList.toggle('selected', windowElement.id === targetId);
|
|
850
856
|
});
|
|
@@ -853,11 +859,28 @@ export function highlightSelectedWindow(wallUuid, index) {
|
|
|
853
859
|
* Removes the highlight from all selected window items by removing the 'selected' CSS class.
|
|
854
860
|
*/
|
|
855
861
|
export function toggleHighlightedWindowItem() {
|
|
856
|
-
const windowItems = document.querySelectorAll('li.
|
|
862
|
+
const windowItems = document.querySelectorAll('li.at_window_row_item.selected');
|
|
857
863
|
windowItems.forEach(el => {
|
|
858
864
|
el.classList.remove('selected');
|
|
859
865
|
});
|
|
860
866
|
}
|
|
867
|
+
/**
|
|
868
|
+
* Toggles the highlighted state of partition items by adding 'selected' class to the matching partition and removing it from others.
|
|
869
|
+
* @param partitionId - The partition ID to highlight (only the prefix before the first hyphen is used for matching)
|
|
870
|
+
*/
|
|
871
|
+
export function toggleHighlightedPartitionItem(partitionId) {
|
|
872
|
+
const partitions = document.querySelectorAll('div.at_partion_row_item');
|
|
873
|
+
partitions === null || partitions === void 0 ? void 0 : partitions.forEach(partition => {
|
|
874
|
+
if (partition.getAttribute('id') === `at-child-partition-${partitionId.split('-')[0]}`) {
|
|
875
|
+
partition.classList.add('selected');
|
|
876
|
+
partition.querySelector('.at_partition_name_text').classList.add('selected'); // Added dot
|
|
877
|
+
}
|
|
878
|
+
else {
|
|
879
|
+
partition.classList.remove('selected');
|
|
880
|
+
partition.querySelector('.at_partition_name_text').classList.remove('selected'); // Added dot
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
}
|
|
861
884
|
/**
|
|
862
885
|
* Calculates the midpoint (centroid) of multiple 3D coordinates by averaging their x, y, and z values.
|
|
863
886
|
* @param coords - An array of objects containing start Vector3 coordinates
|
|
@@ -23,7 +23,7 @@ export let selectedIotTag = undefined;
|
|
|
23
23
|
let tagIotName, iotModelName, iotSerialNumber, iotMfrName, iotSystemLink;
|
|
24
24
|
let selectedIoTCat;
|
|
25
25
|
let linkedDevicesArray = [];
|
|
26
|
-
let iotCategoryIconList = ['mdi-power', 'mdi-thermometer', 'mdi-water-percent', 'mdi-gauge', 'mdi-leak', 'mdi-water', 'mdi-lightbulb-on', 'mdi-gas-cylinder', 'mdi-flask', 'mdi-meter-electric', 'mdi-information-symbol', 'mdi-sine-wave'];
|
|
26
|
+
let iotCategoryIconList = ['mdi-power', 'mdi-thermometer', 'mdi-water-percent', 'mdi-gauge', 'mdi-leak', 'mdi-water', 'mdi-lightbulb-on', 'mdi-gas-cylinder', 'mdi-flask', 'mdi-meter-electric', 'mdi-information-symbol', 'mdi-sine-wave', 'mdi-camera', 'mdi-dots-horizontal'];
|
|
27
27
|
let notify = new Notyf({ position: { x: 'left', y: 'bottom' } });
|
|
28
28
|
export function renderTagIOTFormPane() {
|
|
29
29
|
const element = document.createElement('div');
|
|
@@ -544,7 +544,7 @@ export function getIotTagFormData() {
|
|
|
544
544
|
serialNumber: iotSerialNumber.value,
|
|
545
545
|
tagMf: iotMfrName.value,
|
|
546
546
|
// tagCategoryId: selectedIoTCat.uuid,
|
|
547
|
-
tagCategoryId: selectedIoTCat.name,
|
|
547
|
+
tagCategoryId: selectedIoTCat ? selectedIoTCat.name : undefined,
|
|
548
548
|
systemLink: iotSystemLink.value,
|
|
549
549
|
linkedDevices: linkedDevicesArray,
|
|
550
550
|
iotSystem: selectedIoTSystem,
|
|
@@ -678,6 +678,7 @@ export function clearIotFields() {
|
|
|
678
678
|
iotSystemLink.innerText = '';
|
|
679
679
|
linkedDevicesArray = [];
|
|
680
680
|
selectedIoTSystem = '';
|
|
681
|
+
selectedIoTCat = undefined;
|
|
681
682
|
setSelectedIoTSystemRadio(IOT_LINKED_SYSTEMS.BEMAC);
|
|
682
683
|
deviceContainer.innerHTML = '';
|
|
683
684
|
iotTagFormMode = "ADD" /* FORM_MODE.ADD */;
|
|
@@ -245,7 +245,7 @@ export function renderTags(tags, showOwnTagsOnly = false) {
|
|
|
245
245
|
const payload = { tag: targetTag };
|
|
246
246
|
dispatchSpaceEvent(SPACE_EVENTS.TAG_DISPOSED, payload);
|
|
247
247
|
toggleModal(false);
|
|
248
|
-
notify.success(
|
|
248
|
+
notify.success(i18n.t('Successfully deleted tag'));
|
|
249
249
|
}
|
|
250
250
|
else {
|
|
251
251
|
toggleModal(false);
|
|
@@ -414,7 +414,7 @@ export function addClickEventToTagRow(tag) {
|
|
|
414
414
|
yield disposeTag({ tagId: tagId });
|
|
415
415
|
const tagRow = document.getElementById(`at-tag-row-${tagId}`);
|
|
416
416
|
tagRow.remove();
|
|
417
|
-
notify.success(
|
|
417
|
+
notify.success(i18n.t('Successfully deleted tag'));
|
|
418
418
|
}
|
|
419
419
|
else {
|
|
420
420
|
notify.error("Tag id not found!");
|
package/lib/atwinui/events.js
CHANGED
|
@@ -28,7 +28,7 @@ import { toggleDrawPartitionButton, displayPartitionFormMode, setPartitionFormMo
|
|
|
28
28
|
import { actionSettingsSelectOption, getTempCoordinateSystem, getTempMeasurementUnit, getTempRotationUnit, setCoordinateSystem, setMeasurementUnit, setRotationUnit, initSettingsValues, setTempCoordinateSystem, setTempMeasurementUnit, setTempRotationUnit, toggleActionSettingsDropdown, toggleCalibrateBasepoint, setScaleFactor, getTempScaleFactor, setTempScaleFactor, setBasepoint, getTempBasepoint, setTempBasepoint, getBasepoint, toggleActionSettings, getBasepointObjectPayload, displayConvertedCoordinates, getCoordinateSystem, getScaleFactor, getMeasurementUnit, getRotationUnit, setBasepointObjectPayload } from "./components/toolbar/actionSettingsPane";
|
|
29
29
|
import { getBasepointCalibrateBpCoordinateValues, getBasepointCalibrateMpCoordinateValues, initBsepointCalibratePane, toggleBasepointCalibratePane } from "./components/toolbar/basepointCalibratePane";
|
|
30
30
|
import { toggleGeneralMapOptions, initGeneralSelectedMap, getSelectedMapOption } from './components/toolbar/generalSettingsMenuPane';
|
|
31
|
-
import { searchTagList, setSearchTagTerm, searchClearfield, getSearchTagTerm, sortTags, updateSelectedTagSortOption, resetSelectedTagSortOption, filterIotTagList, setTagPaneActive, isTagPaneActive, setCurrentTagPaneMode, currentTagPaneMode } from './components/toolbar/tagListPane';
|
|
31
|
+
import { searchTagList, setSearchTagTerm, searchClearfield, getSearchTagTerm, sortTags, updateSelectedTagSortOption, resetSelectedTagSortOption, filterIotTagList, setTagPaneActive, isTagPaneActive, setCurrentTagPaneMode, currentTagPaneMode, selectedTagSortOption } from './components/toolbar/tagListPane';
|
|
32
32
|
import { renderUserRows } from "./components/toolbar/spaceUserListPane";
|
|
33
33
|
import { handleRemoteViewResponsiveChanges, renderRemoteSpaceViewing } from "./components/toolbar/viewingRemoteSpace";
|
|
34
34
|
import { PipeList } from "./components/toolbar/pipeListPane";
|
|
@@ -343,19 +343,25 @@ function renderTagPaneContent() {
|
|
|
343
343
|
log.info("1 content", tags);
|
|
344
344
|
setTagPaneActive(true);
|
|
345
345
|
setCurrentTagPaneMode(TAG_TYPE.MP);
|
|
346
|
-
|
|
346
|
+
resetSelectedTagSortOption();
|
|
347
|
+
const sortedTagsToDisplay = sortTags(tags, selectedTagSortOption);
|
|
348
|
+
renderTags(filterTagList(sortedTagsToDisplay));
|
|
347
349
|
}
|
|
348
350
|
else if (tags.length > 0 && isTagPaneActive) {
|
|
349
351
|
log.info("2 content", tags);
|
|
350
352
|
setTagPaneActive(true);
|
|
351
353
|
setCurrentTagPaneMode(TAG_TYPE.MP);
|
|
352
|
-
|
|
354
|
+
resetSelectedTagSortOption();
|
|
355
|
+
const sortedTagsToDisplay = sortTags(tags, selectedTagSortOption);
|
|
356
|
+
renderTags(sortedTagsToDisplay, true);
|
|
353
357
|
}
|
|
354
358
|
else if (!isTagPaneActive) {
|
|
355
359
|
log.info("3 content", tags);
|
|
356
360
|
setTagPaneActive(false);
|
|
357
361
|
setCurrentTagPaneMode(TAG_TYPE.IOT);
|
|
358
|
-
|
|
362
|
+
resetSelectedTagSortOption();
|
|
363
|
+
const sortedTagsToDisplay = sortTags(tags, selectedTagSortOption);
|
|
364
|
+
renderTags(filterIotTagList(sortedTagsToDisplay));
|
|
359
365
|
dispatchSpaceEvent(SPACE_EVENTS.GET_IOT_TAG_ICON, { payload: 'hello from library' });
|
|
360
366
|
}
|
|
361
367
|
if ((_tagCategories === null || _tagCategories === void 0 ? void 0 : _tagCategories.length) > 0) {
|
|
@@ -3476,7 +3482,12 @@ function handlePlaceIotTag() {
|
|
|
3476
3482
|
}
|
|
3477
3483
|
}
|
|
3478
3484
|
else {
|
|
3479
|
-
|
|
3485
|
+
if (!payload.tagCategoryId) {
|
|
3486
|
+
notyf.error(`${i18n.t('IotCategoryRequired')}`);
|
|
3487
|
+
}
|
|
3488
|
+
else {
|
|
3489
|
+
notyf.error(`${i18n.t('RequiredFieldsEmpty')}`);
|
|
3490
|
+
}
|
|
3480
3491
|
isPlacingTag = false;
|
|
3481
3492
|
}
|
|
3482
3493
|
}
|
|
@@ -3776,7 +3787,15 @@ function handleClickEventInTagSortOption() {
|
|
|
3776
3787
|
if (closestOption) {
|
|
3777
3788
|
const sortOption = closestOption.dataset.sort;
|
|
3778
3789
|
updateSelectedTagSortOption(sortOption);
|
|
3779
|
-
|
|
3790
|
+
log.info("_@ _tags: ", _tags);
|
|
3791
|
+
let tags;
|
|
3792
|
+
if (currentTagPaneMode == TAG_TYPE.MP) {
|
|
3793
|
+
tags = getMpTags().filter(tag => (tag.tag_type === TAG_TYPE.MP || tag.tag_type === undefined));
|
|
3794
|
+
}
|
|
3795
|
+
else {
|
|
3796
|
+
tags = getMpTags().filter(tag => tag.tag_type === TAG_TYPE.IOT);
|
|
3797
|
+
}
|
|
3798
|
+
// const tags = getMpTags()
|
|
3780
3799
|
const filteredTags = filterTagList(tags);
|
|
3781
3800
|
const sortConfig = sortTagOptions[sortOption] || { by: 'label', order: 'asc' };
|
|
3782
3801
|
if (selectedCategoryFilterId || selectedSubCategoryFilterId) {
|