Initial Version

This commit is contained in:
root
2025-12-21 10:09:54 -05:00
commit 4ae6befc7b
422 changed files with 47225 additions and 0 deletions
+183
View File
@@ -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);
},
},
});