This commit is contained in:
despiegk 2024-10-31 07:34:19 +01:00
parent 8d9018722e
commit cf28f78529

View File

@ -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<Member[]> {
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<void> {
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, 'id'>): Member[] {
const id = crypto.randomUUID();
const member: Member = { ...newMember, id };
return [...members, member];
}
updateMember(members: Member[], id: string, updates: Partial<Omit<Member, 'id'>>): 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);
}
}