209 lines
4.9 KiB
TypeScript
209 lines
4.9 KiB
TypeScript
import { defineStore } from 'pinia';
|
|
import { serviceService } from '@/services/serviceService';
|
|
import { ServiceModel } from '@/models/service';
|
|
import type { Service } from '@/models/service';
|
|
|
|
export const useServicesStore = defineStore('jmapc_services', {
|
|
state: () => ({
|
|
services: [] as ServiceModel[],
|
|
loading: false,
|
|
error: null as string | null,
|
|
}),
|
|
|
|
getters: {
|
|
/**
|
|
* Get services filtered by capability
|
|
*/
|
|
byCapability: (state) => (capability: string) => {
|
|
return state.services.filter(s => s.capabilities.includes(capability));
|
|
},
|
|
|
|
/**
|
|
* Get mail services
|
|
*/
|
|
mailServices: (state) => {
|
|
return state.services.filter(s => s.hasMail());
|
|
},
|
|
|
|
/**
|
|
* Get contact services
|
|
*/
|
|
contactServices: (state) => {
|
|
return state.services.filter(s => s.hasContacts());
|
|
},
|
|
|
|
/**
|
|
* Get calendar services
|
|
*/
|
|
calendarServices: (state) => {
|
|
return state.services.filter(s => s.hasCalendars());
|
|
},
|
|
|
|
/**
|
|
* Get service by ID
|
|
*/
|
|
getById: (state) => (id: string) => {
|
|
return state.services.find(s => s.id === id);
|
|
},
|
|
},
|
|
|
|
actions: {
|
|
/**
|
|
* Load all services from API
|
|
*/
|
|
async loadServices(capability?: string) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await serviceService.list(capability);
|
|
this.services = response.services.map(s => new ServiceModel(s));
|
|
} catch (error: any) {
|
|
this.error = error.message || 'Failed to load services';
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Load a single service
|
|
*/
|
|
async loadService(id: string) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const service = await serviceService.fetch(id);
|
|
const model = new ServiceModel(service);
|
|
|
|
// Update or add to store
|
|
const index = this.services.findIndex(s => s.id === id);
|
|
if (index >= 0) {
|
|
this.services[index] = model;
|
|
} else {
|
|
this.services.push(model);
|
|
}
|
|
|
|
return model;
|
|
} catch (error: any) {
|
|
this.error = error.message || 'Failed to load service';
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Create a new service
|
|
*/
|
|
async createService(service: Partial<Service>) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const created = await serviceService.create(service);
|
|
const model = new ServiceModel(created);
|
|
this.services.push(model);
|
|
return model;
|
|
} catch (error: any) {
|
|
this.error = error.message || 'Failed to create service';
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Update an existing service
|
|
*/
|
|
async updateService(id: string, service: Partial<Service>) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const updated = await serviceService.update(id, service);
|
|
const model = new ServiceModel(updated);
|
|
|
|
const index = this.services.findIndex(s => s.id === id);
|
|
if (index >= 0) {
|
|
this.services[index] = model;
|
|
}
|
|
|
|
return model;
|
|
} catch (error: any) {
|
|
this.error = error.message || 'Failed to update service';
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Delete a service
|
|
*/
|
|
async deleteService(id: string) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
await serviceService.destroy(id);
|
|
this.services = this.services.filter(s => s.id !== id);
|
|
} catch (error: any) {
|
|
this.error = error.message || 'Failed to delete service';
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Test connection with provided settings
|
|
*/
|
|
async testConnection(config: any) {
|
|
return serviceService.test(config);
|
|
},
|
|
|
|
/**
|
|
* Auto-discover JMAP endpoint
|
|
*/
|
|
async discover(hostname: string, protocol?: string, port?: number, path?: string) {
|
|
return serviceService.discover(hostname, protocol, port, path);
|
|
},
|
|
|
|
/**
|
|
* Fetch collections for a service
|
|
*/
|
|
async fetchCollections(id: string) {
|
|
return serviceService.fetchCollections(id);
|
|
},
|
|
|
|
/**
|
|
* Refresh collections for a service
|
|
*/
|
|
async refreshCollections(id: string) {
|
|
const result = await serviceService.refreshCollections(id);
|
|
|
|
// Update local service with fresh collection data
|
|
const service = this.getById(id);
|
|
if (service && result.success) {
|
|
service.collections = {
|
|
contacts: result.contacts || [],
|
|
calendars: result.calendars || []
|
|
};
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Clear all services
|
|
*/
|
|
reset() {
|
|
this.services = [];
|
|
this.error = null;
|
|
this.loading = false;
|
|
},
|
|
},
|
|
});
|