From cf28f785299390d5349d71581f73cac18338e0bb Mon Sep 17 00:00:00 2001 From: despiegk Date: Thu, 31 Oct 2024 07:34:19 +0100 Subject: [PATCH] ... --- react-shadcn-starter/src/lib/circle-data.ts | 160 ++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 react-shadcn-starter/src/lib/circle-data.ts diff --git a/react-shadcn-starter/src/lib/circle-data.ts b/react-shadcn-starter/src/lib/circle-data.ts new file mode 100644 index 0000000..4c383b7 --- /dev/null +++ b/react-shadcn-starter/src/lib/circle-data.ts @@ -0,0 +1,160 @@ +import md5 from 'md5'; + +export type WebDAVConfig = { + url: string; + username: string; + password: string; +} + +export type Role = 'admin' | 'stakeholder' | 'member' | 'coordinator' | 'viewer' | 'contributor'; + +export type Member = { + id: string; + name: string; + email: string; + role: Role; + description: string; +} + +export const defaultMembers: Member[] = [ + { + id: "1", + name: "John Smith", + email: "john.smith@example.com", + role: "admin", + description: "Project lead and main administrator" + }, + { + id: "2", + name: "Sarah Johnson", + email: "sarah.j@example.com", + role: "coordinator", + description: "Team coordinator and event organizer" + }, + { + id: "3", + name: "Mike Wilson", + email: "mike.w@example.com", + role: "stakeholder", + description: "Key stakeholder representing finance department" + }, + { + id: "4", + name: "Lisa Chen", + email: "lisa.chen@example.com", + role: "contributor", + description: "Technical contributor and documentation specialist" + } +]; + +export class CircleDataManager { + private static instance: CircleDataManager; + private currentHash: string | null = null; + private webdavConfig: WebDAVConfig | null = null; + private circleFile: string | null = null; + + private constructor() {} + + static getInstance(): CircleDataManager { + if (!CircleDataManager.instance) { + CircleDataManager.instance = new CircleDataManager(); + } + return CircleDataManager.instance; + } + + setConfig(config: WebDAVConfig, circleFile: string) { + this.webdavConfig = config; + this.circleFile = circleFile; + } + + private calculateHash(members: Member[]): string { + // Sort members by ID to ensure consistent hash + const sortedMembers = [...members].sort((a, b) => a.id.localeCompare(b.id)); + return md5(JSON.stringify(sortedMembers)); + } + + hasChanged(members: Member[]): boolean { + const newHash = this.calculateHash(members); + if (newHash === this.currentHash) { + return false; + } + this.currentHash = newHash; + return true; + } + + async fetchMembers(): Promise { + if (!this.webdavConfig || !this.circleFile) { + throw new Error('WebDAV configuration or circle file not set'); + } + + try { + const response = await fetch(`${this.webdavConfig.url}${this.circleFile}`, { + headers: { + 'Authorization': 'Basic ' + btoa(`${this.webdavConfig.username}:${this.webdavConfig.password}`) + } + }); + + if (response.status === 404) { + // If file doesn't exist, save and return default members + await this.saveMembers(defaultMembers); + return defaultMembers; + } + + if (!response.ok) { + throw new Error(`Failed to fetch circle data: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + return data.members; + } catch (error) { + // If there's any error (including 404), save and return default members + await this.saveMembers(defaultMembers); + return defaultMembers; + } + } + + async saveMembers(members: Member[]): Promise { + if (!this.webdavConfig || !this.circleFile) { + throw new Error('WebDAV configuration or circle file not set'); + } + + const response = await fetch(`${this.webdavConfig.url}${this.circleFile}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Basic ' + btoa(`${this.webdavConfig.username}:${this.webdavConfig.password}`) + }, + body: JSON.stringify({ members }, null, 2) + }); + + if (!response.ok) { + throw new Error('Failed to save circle data'); + } + + this.currentHash = this.calculateHash(members); + } + + addMember(members: Member[], newMember: Omit): Member[] { + const id = crypto.randomUUID(); + const member: Member = { ...newMember, id }; + return [...members, member]; + } + + updateMember(members: Member[], id: string, updates: Partial>): Member[] { + return members.map(member => + member.id === id ? { ...member, ...updates } : member + ); + } + + removeMember(members: Member[], id: string): Member[] { + return members.filter(member => member.id !== id); + } + + getMemberById(members: Member[], id: string): Member | undefined { + return members.find(member => member.id === id); + } + + getMembersByRole(members: Member[], role: Role): Member[] { + return members.filter(member => member.role === role); + } +}