Initial Version
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import type {
|
||||
IntegrationPointType,
|
||||
IntegrationPoint,
|
||||
IntegrationEntry,
|
||||
IntegrationItem,
|
||||
IntegrationGroup
|
||||
} from '@KTXC/types/integrationTypes';
|
||||
|
||||
export const useIntegrationStore = defineStore('integrationStore', {
|
||||
state: () => ({
|
||||
points: new Map<IntegrationPointType, IntegrationPoint>(),
|
||||
}),
|
||||
|
||||
actions: {
|
||||
// Ensure an integration point exists
|
||||
ensurePoint(pointType: IntegrationPointType): void {
|
||||
if (!this.points.has(pointType)) {
|
||||
this.points.set(pointType, { items: new Map() });
|
||||
}
|
||||
},
|
||||
|
||||
// Register a single item to an integration point
|
||||
registerItem(pointType: IntegrationPointType, item: IntegrationItem): void {
|
||||
this.ensurePoint(pointType);
|
||||
const point = this.points.get(pointType)!;
|
||||
point.items.set(item.id, item);
|
||||
},
|
||||
|
||||
// Register a group to an integration point
|
||||
registerGroup(pointType: IntegrationPointType, group: IntegrationGroup): void {
|
||||
this.ensurePoint(pointType);
|
||||
const point = this.points.get(pointType)!;
|
||||
point.items.set(group.id, group);
|
||||
},
|
||||
|
||||
// Bulk register from module integrations
|
||||
registerModuleIntegrations(
|
||||
moduleHandle: string,
|
||||
integrations: Record<string, any[]>
|
||||
): void {
|
||||
for (const [pointType, entries] of Object.entries(integrations)) {
|
||||
if (!entries || !Array.isArray(entries)) continue;
|
||||
|
||||
entries.forEach((entry: any) => {
|
||||
const prefixedEntry = this.prefixEntry(moduleHandle, entry);
|
||||
|
||||
if (entry.type === 'group' || ('items' in entry && Array.isArray(entry.items))) {
|
||||
this.registerGroup(pointType as IntegrationPointType, prefixedEntry as IntegrationGroup);
|
||||
} else {
|
||||
this.registerItem(pointType as IntegrationPointType, prefixedEntry as IntegrationItem);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Prefix IDs and paths with module handle
|
||||
prefixEntry(moduleHandle: string, entry: any): IntegrationEntry {
|
||||
const prefixed: any = {
|
||||
...entry,
|
||||
id: entry.id ? `${moduleHandle}.${entry.id}` : `${moduleHandle}.${this.randomID()}`,
|
||||
moduleHandle,
|
||||
};
|
||||
|
||||
// Remove 'type' field as it's only used for module-side disambiguation
|
||||
delete prefixed.type;
|
||||
|
||||
// Prefix internal paths
|
||||
if (entry.path) {
|
||||
prefixed.to = `/m/${moduleHandle}${entry.path}`;
|
||||
delete prefixed.path;
|
||||
} else if (entry.to && entry.toType !== 'external') {
|
||||
prefixed.to = `/m/${moduleHandle}${entry.to}`;
|
||||
}
|
||||
|
||||
// Recursively prefix items in groups
|
||||
if (entry.items && Array.isArray(entry.items)) {
|
||||
prefixed.items = entry.items.map((item: any) => this.prefixEntry(moduleHandle, item));
|
||||
}
|
||||
|
||||
return prefixed;
|
||||
},
|
||||
|
||||
// Update a specific item (useful for badges, visibility, etc.)
|
||||
updateItem(
|
||||
pointType: IntegrationPointType,
|
||||
itemId: string,
|
||||
updates: Partial<IntegrationItem>
|
||||
): void {
|
||||
const point = this.points.get(pointType);
|
||||
if (!point) return;
|
||||
|
||||
const item = point.items.get(itemId);
|
||||
if (item && !('items' in item)) {
|
||||
point.items.set(itemId, { ...item, ...updates });
|
||||
}
|
||||
},
|
||||
|
||||
// Update badge for notification icons
|
||||
updateBadge(
|
||||
pointType: IntegrationPointType,
|
||||
itemId: string,
|
||||
badge: string | number | null,
|
||||
badgeColor?: string
|
||||
): void {
|
||||
this.updateItem(pointType, itemId, { badge, badgeColor });
|
||||
},
|
||||
|
||||
// Toggle visibility
|
||||
setVisibility(
|
||||
pointType: IntegrationPointType,
|
||||
itemId: string,
|
||||
visible: boolean
|
||||
): void {
|
||||
this.updateItem(pointType, itemId, { visible });
|
||||
},
|
||||
|
||||
// Remove an item
|
||||
unregisterItem(pointType: IntegrationPointType, itemId: string): void {
|
||||
const point = this.points.get(pointType);
|
||||
if (point) {
|
||||
point.items.delete(itemId);
|
||||
}
|
||||
},
|
||||
|
||||
// Remove all items from a module
|
||||
unregisterModule(moduleHandle: string): void {
|
||||
this.points.forEach((point) => {
|
||||
point.items.forEach((entry, id) => {
|
||||
if (entry.moduleHandle === moduleHandle) {
|
||||
point.items.delete(id);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
reset(): void {
|
||||
this.points.clear();
|
||||
},
|
||||
|
||||
randomID(length = 8): string {
|
||||
return Math.random().toString(36).substring(2, 2 + length);
|
||||
},
|
||||
},
|
||||
|
||||
getters: {
|
||||
// Get all entries for an integration point, sorted by priority
|
||||
getPoint: (state) => (pointType: IntegrationPointType): IntegrationEntry[] => {
|
||||
const point = state.points.get(pointType);
|
||||
if (!point) return [];
|
||||
|
||||
return Array.from(point.items.values())
|
||||
.filter(entry => entry.visible !== false)
|
||||
.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
||||
},
|
||||
|
||||
// Get items only (no groups)
|
||||
getItems: (state) => (pointType: IntegrationPointType): IntegrationItem[] => {
|
||||
const point = state.points.get(pointType);
|
||||
if (!point) return [];
|
||||
|
||||
return Array.from(point.items.values())
|
||||
.filter((entry): entry is IntegrationItem => !('items' in entry) && entry.visible !== false)
|
||||
.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
||||
},
|
||||
|
||||
// Get groups only
|
||||
getGroups: (state) => (pointType: IntegrationPointType): IntegrationGroup[] => {
|
||||
const point = state.points.get(pointType);
|
||||
if (!point) return [];
|
||||
|
||||
return Array.from(point.items.values())
|
||||
.filter((entry): entry is IntegrationGroup => 'items' in entry && entry.visible !== false)
|
||||
.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
||||
},
|
||||
|
||||
// Get a specific item by ID
|
||||
getItemById: (state) => (pointType: IntegrationPointType, itemId: string): IntegrationEntry | undefined => {
|
||||
const point = state.points.get(pointType);
|
||||
return point?.items.get(itemId);
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user