2025-10-06 10:41:40 +05:30
|
|
|
|
import { create } from "zustand";
|
|
|
|
|
|
import { immer } from "zustand/middleware/immer";
|
|
|
|
|
|
|
|
|
|
|
|
interface AssetGroupStore {
|
|
|
|
|
|
assetGroups: AssetGroup[];
|
|
|
|
|
|
selectedGroups: string[]; // Array of groupUuids
|
|
|
|
|
|
groupHierarchy: AssetGroupHierarchy;
|
|
|
|
|
|
|
|
|
|
|
|
// Group CRUD operations
|
|
|
|
|
|
addGroup: (group: AssetGroup) => { createdGroups: AssetGroup[]; updatedGroups: AssetGroup[] };
|
|
|
|
|
|
removeGroup: (groupUuid: string) => void;
|
|
|
|
|
|
clearGroups: () => void;
|
|
|
|
|
|
setGroups: (groups: AssetGroup[]) => void;
|
|
|
|
|
|
|
|
|
|
|
|
// Group selection
|
|
|
|
|
|
setSelectedGroups: (groupUuids: string[]) => void;
|
|
|
|
|
|
addSelectedGroup: (groupUuid: string) => void;
|
|
|
|
|
|
removeSelectedGroup: (groupUuid: string) => void;
|
|
|
|
|
|
toggleSelectedGroup: (groupUuid: string) => void;
|
|
|
|
|
|
clearSelectedGroups: () => void;
|
|
|
|
|
|
hasSelectedGroup: (groupUuid: string) => boolean;
|
|
|
|
|
|
|
|
|
|
|
|
// Group children management
|
|
|
|
|
|
addChildToGroup: (groupUuid: string, child: { type: "Asset" | "Group"; childrenUuid: string }) => { updatedGroups: AssetGroup[] };
|
|
|
|
|
|
removeChildFromGroup: (groupUuid: string, childUuid: string) => void;
|
|
|
|
|
|
getGroupChildren: (groupUuid: string) => { type: "Asset" | "Group"; childrenUuid: string }[];
|
|
|
|
|
|
|
|
|
|
|
|
// Group properties
|
|
|
|
|
|
setGroupName: (groupUuid: string, newName: string) => void;
|
|
|
|
|
|
setGroupVisibility: (groupUuid: string, isVisible: boolean) => void;
|
|
|
|
|
|
setGroupLock: (groupUuid: string, isLocked: boolean) => void;
|
|
|
|
|
|
toggleGroupVisibility: (groupUuid: string) => void;
|
|
|
|
|
|
setGroupExpanded: (groupUuid: string, isExpanded: boolean) => void;
|
|
|
|
|
|
|
|
|
|
|
|
// Hierarchy operations
|
|
|
|
|
|
buildHierarchy: (assets: Assets, groups: AssetGroup[]) => AssetGroupHierarchy;
|
|
|
|
|
|
flattenHierarchy: (hierarchy: AssetGroupHierarchy) => { assets: Asset[]; groups: AssetGroup[] };
|
|
|
|
|
|
getGroupHierarchy: (groupUuid: string) => AssetGroupHierarchyNode | null;
|
|
|
|
|
|
getFlatGroupAssets: (groupUuid: string, assets: Assets) => Asset[];
|
|
|
|
|
|
getFlatGroupChildren: (groupUuid: string) => string[]; // Returns all child uuids (both assets and groups)
|
|
|
|
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
|
|
getGroupById: (groupUuid: string) => AssetGroup | undefined;
|
|
|
|
|
|
getGroupsContainingAsset: (assetUuid: string) => AssetGroup[];
|
|
|
|
|
|
getGroupsContainingGroup: (childGroupUuid: string) => AssetGroup[];
|
2025-10-09 14:58:53 +05:30
|
|
|
|
getParentGroup: (item: AssetGroupChild) => string | null;
|
2025-10-06 10:41:40 +05:30
|
|
|
|
hasGroup: (groupUuid: string) => boolean;
|
|
|
|
|
|
isGroup: (item: AssetGroupChild) => item is AssetGroupHierarchyNode;
|
|
|
|
|
|
isEmptyGroup: (groupUuid: string) => boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const createAssetGroupStore = () => {
|
|
|
|
|
|
return create<AssetGroupStore>()(
|
|
|
|
|
|
immer((set, get) => ({
|
|
|
|
|
|
assetGroups: [],
|
|
|
|
|
|
selectedGroups: [],
|
|
|
|
|
|
groupHierarchy: [],
|
|
|
|
|
|
|
|
|
|
|
|
// Group CRUD operations
|
|
|
|
|
|
addGroup: (group) => {
|
|
|
|
|
|
const result: { createdGroups: AssetGroup[]; updatedGroups: AssetGroup[] } = {
|
|
|
|
|
|
createdGroups: [],
|
|
|
|
|
|
updatedGroups: [],
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
// Check if group already exists
|
|
|
|
|
|
if (state.assetGroups.some((g) => g.groupUuid === group.groupUuid)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Find all asset children in the new group
|
2025-10-09 14:58:53 +05:30
|
|
|
|
const assetChildren = group.children.filter((child) => child.type === "Asset");
|
2025-10-06 10:41:40 +05:30
|
|
|
|
const assetUuids = new Set(assetChildren.map((child) => child.childrenUuid));
|
|
|
|
|
|
|
|
|
|
|
|
// Remove these assets from existing groups and track updated groups
|
|
|
|
|
|
const updatedGroups: AssetGroup[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
state.assetGroups.forEach((existingGroup) => {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
const originalLength = existingGroup.children.length;
|
|
|
|
|
|
existingGroup.children = existingGroup.children.filter((child) => !(child.type === "Asset" && assetUuids.has(child.childrenUuid)));
|
2025-10-06 10:41:40 +05:30
|
|
|
|
|
|
|
|
|
|
// If group was modified, add to updated groups
|
2025-10-09 14:58:53 +05:30
|
|
|
|
if (existingGroup.children.length !== originalLength) {
|
2025-10-06 10:41:40 +05:30
|
|
|
|
updatedGroups.push({ ...existingGroup });
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Add the new group
|
|
|
|
|
|
state.assetGroups.push(group);
|
|
|
|
|
|
result.createdGroups.push({ ...group });
|
|
|
|
|
|
result.updatedGroups = updatedGroups;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
removeGroup: (groupUuid) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
// First remove this group from any parent groups
|
|
|
|
|
|
state.assetGroups.forEach((group) => {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
group.children = group.children.filter((child) => !(child.type === "Group" && child.childrenUuid === groupUuid));
|
2025-10-06 10:41:40 +05:30
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Then remove the group itself
|
|
|
|
|
|
state.assetGroups = state.assetGroups.filter((g) => g.groupUuid !== groupUuid);
|
|
|
|
|
|
|
|
|
|
|
|
// Remove from selected groups
|
|
|
|
|
|
state.selectedGroups = state.selectedGroups.filter((uuid) => uuid !== groupUuid);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
clearGroups: () => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
state.assetGroups = [];
|
|
|
|
|
|
state.selectedGroups = [];
|
|
|
|
|
|
state.groupHierarchy = [];
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
setGroups: (groups) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
state.assetGroups = groups;
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Group selection
|
|
|
|
|
|
setSelectedGroups: (groupUuids) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
state.selectedGroups = groupUuids;
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
addSelectedGroup: (groupUuid) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
if (!state.selectedGroups.includes(groupUuid)) {
|
|
|
|
|
|
state.selectedGroups.push(groupUuid);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
removeSelectedGroup: (groupUuid) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
state.selectedGroups = state.selectedGroups.filter((uuid) => uuid !== groupUuid);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
toggleSelectedGroup: (groupUuid) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const exists = state.selectedGroups.includes(groupUuid);
|
|
|
|
|
|
if (exists) {
|
|
|
|
|
|
state.selectedGroups = state.selectedGroups.filter((uuid) => uuid !== groupUuid);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
state.selectedGroups.push(groupUuid);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
clearSelectedGroups: () => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
state.selectedGroups = [];
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
hasSelectedGroup: (groupUuid: string) => {
|
|
|
|
|
|
return get().selectedGroups.includes(groupUuid);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Group children management
|
|
|
|
|
|
addChildToGroup: (groupUuid, child) => {
|
|
|
|
|
|
const result: { updatedGroups: AssetGroup[] } = { updatedGroups: [] };
|
|
|
|
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const targetGroup = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (!targetGroup) return;
|
|
|
|
|
|
|
|
|
|
|
|
const updatedGroups: AssetGroup[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 1️⃣ Remove the child from any other groups (to maintain single-parent rule)
|
|
|
|
|
|
state.assetGroups.forEach((group) => {
|
|
|
|
|
|
if (group.groupUuid === groupUuid) return; // skip target group
|
|
|
|
|
|
|
2025-10-09 14:58:53 +05:30
|
|
|
|
const originalLength = group.children.length;
|
|
|
|
|
|
group.children = group.children.filter((c) => c.childrenUuid !== child.childrenUuid);
|
2025-10-06 10:41:40 +05:30
|
|
|
|
|
2025-10-09 14:58:53 +05:30
|
|
|
|
if (group.children.length !== originalLength) {
|
2025-10-06 10:41:40 +05:30
|
|
|
|
updatedGroups.push({ ...group });
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 2️⃣ Add the child to the target group (if not already present)
|
2025-10-09 14:58:53 +05:30
|
|
|
|
if (!targetGroup.children.some((c) => c.childrenUuid === child.childrenUuid)) {
|
|
|
|
|
|
targetGroup.children.push(child);
|
2025-10-06 10:41:40 +05:30
|
|
|
|
updatedGroups.push({ ...targetGroup });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3️⃣ Rebuild hierarchy after modification
|
|
|
|
|
|
state.groupHierarchy = get().buildHierarchy([], state.assetGroups);
|
|
|
|
|
|
|
|
|
|
|
|
result.updatedGroups = updatedGroups;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
removeChildFromGroup: (groupUuid, childUuid) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (group) {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
group.children = group.children.filter((child) => child.childrenUuid !== childUuid);
|
2025-10-06 10:41:40 +05:30
|
|
|
|
state.groupHierarchy = get().buildHierarchy([], state.assetGroups);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getGroupChildren: (groupUuid) => {
|
|
|
|
|
|
const group = get().assetGroups.find((g) => g.groupUuid === groupUuid);
|
2025-10-09 14:58:53 +05:30
|
|
|
|
return group?.children || [];
|
2025-10-06 10:41:40 +05:30
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Group properties
|
|
|
|
|
|
setGroupName: (groupUuid, newName) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (group) {
|
|
|
|
|
|
group.groupName = newName;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
setGroupVisibility: (groupUuid, isVisible) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (group) {
|
|
|
|
|
|
group.isVisible = isVisible;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
setGroupLock: (groupUuid, isLocked) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (group) {
|
|
|
|
|
|
group.isLocked = isLocked;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
toggleGroupVisibility: (groupUuid) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (group) {
|
|
|
|
|
|
group.isVisible = !group.isVisible;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
setGroupExpanded: (groupUuid, isExpanded) => {
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (group) {
|
|
|
|
|
|
group.isExpanded = isExpanded;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Hierarchy operations
|
|
|
|
|
|
buildHierarchy: (assets: Assets, groups: AssetGroup[]): AssetGroupHierarchy => {
|
|
|
|
|
|
const assetMap = new Map(assets.map((asset) => [asset.modelUuid, asset]));
|
|
|
|
|
|
const groupMap = new Map(groups.map((group) => [group.groupUuid, group]));
|
|
|
|
|
|
|
|
|
|
|
|
const buildNode = (group: AssetGroup): AssetGroupHierarchyNode => {
|
|
|
|
|
|
const children: AssetGroupChild[] = [];
|
|
|
|
|
|
|
2025-10-09 14:58:53 +05:30
|
|
|
|
group.children.forEach((child) => {
|
2025-10-06 10:41:40 +05:30
|
|
|
|
if (child.type === "Asset") {
|
|
|
|
|
|
const asset = assetMap.get(child.childrenUuid);
|
|
|
|
|
|
if (asset) {
|
|
|
|
|
|
children.push(asset);
|
|
|
|
|
|
// Remove from assetMap so we know it's been processed
|
|
|
|
|
|
assetMap.delete(child.childrenUuid);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (child.type === "Group") {
|
|
|
|
|
|
const childGroup = groupMap.get(child.childrenUuid);
|
|
|
|
|
|
if (childGroup) {
|
|
|
|
|
|
children.push(buildNode(childGroup));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
groupUuid: group.groupUuid,
|
|
|
|
|
|
groupName: group.groupName,
|
|
|
|
|
|
isVisible: group.isVisible,
|
|
|
|
|
|
isLocked: group.isLocked,
|
|
|
|
|
|
isExpanded: group.isExpanded,
|
|
|
|
|
|
children,
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Find root groups (groups that are not children of any other group)
|
|
|
|
|
|
const childGroupUuids = new Set();
|
|
|
|
|
|
groups.forEach((group) => {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
group.children.forEach((child) => {
|
2025-10-06 10:41:40 +05:30
|
|
|
|
if (child.type === "Group") {
|
|
|
|
|
|
childGroupUuids.add(child.childrenUuid);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const rootGroups = groups.filter((group) => !childGroupUuids.has(group.groupUuid));
|
|
|
|
|
|
|
|
|
|
|
|
// Build hierarchy starting from root groups
|
|
|
|
|
|
const hierarchy: AssetGroupHierarchy = rootGroups.map(buildNode);
|
|
|
|
|
|
|
|
|
|
|
|
// Add remaining assets that are not in any group
|
|
|
|
|
|
const ungroupedAssets: Asset[] = [];
|
|
|
|
|
|
assetMap.forEach((asset) => {
|
|
|
|
|
|
ungroupedAssets.push(asset);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const finalHierarchy = [...hierarchy, ...ungroupedAssets];
|
|
|
|
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
|
|
state.groupHierarchy = finalHierarchy;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return finalHierarchy;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
flattenHierarchy: (hierarchy: AssetGroupHierarchy) => {
|
|
|
|
|
|
const assets: Asset[] = [];
|
|
|
|
|
|
const groups: AssetGroup[] = [];
|
|
|
|
|
|
const processedGroups = new Set<string>();
|
|
|
|
|
|
|
|
|
|
|
|
const processNode = (node: AssetGroupChild) => {
|
|
|
|
|
|
if ("modelUuid" in node) {
|
|
|
|
|
|
// It's an Asset
|
|
|
|
|
|
assets.push(node);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// It's an AssetGroupHierarchyNode
|
|
|
|
|
|
if (!processedGroups.has(node.groupUuid)) {
|
|
|
|
|
|
groups.push({
|
|
|
|
|
|
groupUuid: node.groupUuid,
|
|
|
|
|
|
groupName: node.groupName,
|
|
|
|
|
|
isVisible: node.isVisible,
|
|
|
|
|
|
isLocked: node.isLocked,
|
|
|
|
|
|
isExpanded: node.isExpanded,
|
2025-10-09 14:58:53 +05:30
|
|
|
|
children: node.children.map((child) =>
|
2025-10-06 10:41:40 +05:30
|
|
|
|
"modelUuid" in child ? { type: "Asset" as const, childrenUuid: child.modelUuid } : { type: "Group" as const, childrenUuid: child.groupUuid }
|
|
|
|
|
|
),
|
|
|
|
|
|
});
|
|
|
|
|
|
processedGroups.add(node.groupUuid);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
node.children.forEach(processNode);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
hierarchy.forEach(processNode);
|
|
|
|
|
|
return { assets, groups };
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getGroupHierarchy: (groupUuid) => {
|
|
|
|
|
|
const hierarchy = get().groupHierarchy;
|
|
|
|
|
|
|
|
|
|
|
|
const findGroup = (nodes: AssetGroupHierarchy): AssetGroupHierarchyNode | null => {
|
|
|
|
|
|
for (const node of nodes) {
|
|
|
|
|
|
if ("groupUuid" in node && node.groupUuid === groupUuid) {
|
|
|
|
|
|
return node;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ("children" in node) {
|
|
|
|
|
|
const found = findGroup(node.children);
|
|
|
|
|
|
if (found) return found;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return findGroup(hierarchy);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getFlatGroupAssets: (groupUuid, assets) => {
|
|
|
|
|
|
const groupHierarchy = get().getGroupHierarchy(groupUuid);
|
|
|
|
|
|
if (!groupHierarchy) return [];
|
|
|
|
|
|
|
|
|
|
|
|
const flatAssets: Asset[] = [];
|
|
|
|
|
|
const assetMap = new Map(assets.map((asset) => [asset.modelUuid, asset]));
|
|
|
|
|
|
|
|
|
|
|
|
const collectAssets = (nodes: AssetGroupChild[]) => {
|
|
|
|
|
|
nodes.forEach((node) => {
|
|
|
|
|
|
if ("modelUuid" in node) {
|
|
|
|
|
|
const asset = assetMap.get(node.modelUuid);
|
|
|
|
|
|
if (asset) flatAssets.push(asset);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
collectAssets(node.children);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
collectAssets(groupHierarchy.children);
|
|
|
|
|
|
return flatAssets;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getFlatGroupChildren: (groupUuid) => {
|
|
|
|
|
|
const group = get().assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
if (!group) return [];
|
|
|
|
|
|
|
|
|
|
|
|
const allChildren: string[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
const collectChildren = (children: { type: "Asset" | "Group"; childrenUuid: string }[]) => {
|
|
|
|
|
|
children.forEach((child) => {
|
|
|
|
|
|
allChildren.push(child.childrenUuid);
|
|
|
|
|
|
if (child.type === "Group") {
|
|
|
|
|
|
const childGroup = get().assetGroups.find((g) => g.groupUuid === child.childrenUuid);
|
|
|
|
|
|
if (childGroup) {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
collectChildren(childGroup.children);
|
2025-10-06 10:41:40 +05:30
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-09 14:58:53 +05:30
|
|
|
|
collectChildren(group.children);
|
2025-10-06 10:41:40 +05:30
|
|
|
|
return allChildren;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
|
|
getGroupById: (groupUuid) => {
|
|
|
|
|
|
return get().assetGroups.find((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getGroupsContainingAsset: (assetUuid) => {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
return get().assetGroups.filter((group) => group.children.some((child) => child.type === "Asset" && child.childrenUuid === assetUuid));
|
2025-10-06 10:41:40 +05:30
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getGroupsContainingGroup: (childGroupUuid) => {
|
2025-10-09 14:58:53 +05:30
|
|
|
|
return get().assetGroups.filter((group) => group.children.some((child) => child.type === "Group" && child.childrenUuid === childGroupUuid));
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getParentGroup: (item) => {
|
|
|
|
|
|
if (get().isGroup(item)) {
|
|
|
|
|
|
const parents = get().getGroupsContainingGroup(item.groupUuid);
|
|
|
|
|
|
return parents.length > 0 ? parents[0].groupUuid : null;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const parents = get().getGroupsContainingAsset(item.modelUuid);
|
|
|
|
|
|
return parents.length > 0 ? parents[0].groupUuid : null;
|
|
|
|
|
|
}
|
2025-10-06 10:41:40 +05:30
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
hasGroup: (groupUuid) => {
|
|
|
|
|
|
return get().assetGroups.some((g) => g.groupUuid === groupUuid);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
isGroup: (item): item is AssetGroupHierarchyNode => {
|
|
|
|
|
|
return "children" in item;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
isEmptyGroup: (groupUuid) => {
|
|
|
|
|
|
const group = get().assetGroups.find((g) => g.groupUuid === groupUuid);
|
2025-10-09 14:58:53 +05:30
|
|
|
|
return !group || group.children.length === 0;
|
2025-10-06 10:41:40 +05:30
|
|
|
|
},
|
|
|
|
|
|
}))
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export type AssetGroupStoreType = ReturnType<typeof createAssetGroupStore>;
|