...
This commit is contained in:
parent
8d9018722e
commit
cf28f78529
160
react-shadcn-starter/src/lib/circle-data.ts
Normal file
160
react-shadcn-starter/src/lib/circle-data.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user