Add calendar integrations and collaboration updates
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
import { computed, ref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useAuthStore } from '@/features/auth/stores/authStore.js';
|
||||
import { useWorkspaceStore } from '@/features/workspaces/stores/workspaceStore.js';
|
||||
import { useClient } from '@/plugins/api.js';
|
||||
|
||||
export const useCalendarIntegrationsStore = defineStore('calendar-integrations', () => {
|
||||
const authStore = useAuthStore();
|
||||
const workspaceStore = useWorkspaceStore();
|
||||
const client = useClient();
|
||||
|
||||
const sources = ref([]);
|
||||
const events = ref([]);
|
||||
const catalogEntries = ref([]);
|
||||
const hiddenSourceIds = ref(new Set());
|
||||
const isLoadingSources = ref(false);
|
||||
const isLoadingEvents = ref(false);
|
||||
const isLoadingCatalog = ref(false);
|
||||
const isCreatingSource = ref(false);
|
||||
const error = ref(null);
|
||||
|
||||
const visibleSourceIds = computed(() =>
|
||||
new Set(sources.value
|
||||
.filter(source => source.isEnabled && !hiddenSourceIds.value.has(source.id))
|
||||
.map(source => source.id))
|
||||
);
|
||||
|
||||
const visibleEvents = computed(() =>
|
||||
events.value.filter(event => visibleSourceIds.value.has(event.calendarSourceId))
|
||||
);
|
||||
|
||||
function sourceById(sourceId) {
|
||||
return sources.value.find(source => source.id === sourceId) ?? null;
|
||||
}
|
||||
|
||||
async function fetchSources(workspaceId = workspaceStore.activeWorkspaceId) {
|
||||
if (!authStore.isAuthenticated) {
|
||||
sources.value = [];
|
||||
error.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingSources.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
const response = await client.get('/api/calendar-integrations/sources', {
|
||||
params: {
|
||||
workspaceId: workspaceId ?? undefined,
|
||||
},
|
||||
});
|
||||
sources.value = response.data ?? [];
|
||||
} catch (fetchError) {
|
||||
console.error('Failed to fetch calendar sources:', fetchError);
|
||||
sources.value = [];
|
||||
error.value = 'Failed to load calendar sources.';
|
||||
} finally {
|
||||
isLoadingSources.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchEvents({ workspaceId = workspaceStore.activeWorkspaceId, startDate, endDate } = {}) {
|
||||
if (!authStore.isAuthenticated) {
|
||||
events.value = [];
|
||||
error.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingEvents.value = true;
|
||||
|
||||
try {
|
||||
const response = await client.get('/api/calendar-integrations/events', {
|
||||
params: {
|
||||
workspaceId: workspaceId ?? undefined,
|
||||
startDate,
|
||||
endDate,
|
||||
},
|
||||
});
|
||||
events.value = response.data ?? [];
|
||||
} catch (fetchError) {
|
||||
console.error('Failed to fetch calendar events:', fetchError);
|
||||
events.value = [];
|
||||
error.value = 'Failed to load calendar events.';
|
||||
} finally {
|
||||
isLoadingEvents.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function searchCatalog(filters = {}) {
|
||||
if (!authStore.isAuthenticated) {
|
||||
catalogEntries.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingCatalog.value = true;
|
||||
|
||||
try {
|
||||
const response = await client.get('/api/calendar-integrations/catalog', {
|
||||
params: filters,
|
||||
});
|
||||
catalogEntries.value = response.data ?? [];
|
||||
} catch (fetchError) {
|
||||
console.error('Failed to search calendar catalog:', fetchError);
|
||||
catalogEntries.value = [];
|
||||
error.value = 'Failed to load calendar catalog.';
|
||||
} finally {
|
||||
isLoadingCatalog.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function createSource(payload) {
|
||||
isCreatingSource.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
const response = await client.post('/api/calendar-integrations/sources', payload);
|
||||
if (response.data) {
|
||||
sources.value = [...sources.value, response.data]
|
||||
.sort((left, right) => left.displayTitle.localeCompare(right.displayTitle));
|
||||
}
|
||||
return response.data;
|
||||
} catch (createError) {
|
||||
console.error('Failed to create calendar source:', createError);
|
||||
error.value = 'Failed to add calendar source.';
|
||||
throw createError;
|
||||
} finally {
|
||||
isCreatingSource.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshSource(sourceId) {
|
||||
if (!sourceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.post(`/api/calendar-integrations/sources/${sourceId}/refresh`);
|
||||
const refreshedSource = response.data;
|
||||
if (refreshedSource) {
|
||||
sources.value = sources.value.map(source =>
|
||||
source.id === refreshedSource.id ? refreshedSource : source
|
||||
);
|
||||
}
|
||||
return refreshedSource;
|
||||
} catch (refreshError) {
|
||||
console.error('Failed to refresh calendar source:', refreshError);
|
||||
error.value = 'Failed to refresh calendar source.';
|
||||
throw refreshError;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSourceVisibility(sourceId) {
|
||||
const nextHiddenIds = new Set(hiddenSourceIds.value);
|
||||
if (nextHiddenIds.has(sourceId)) {
|
||||
nextHiddenIds.delete(sourceId);
|
||||
} else {
|
||||
nextHiddenIds.add(sourceId);
|
||||
}
|
||||
hiddenSourceIds.value = nextHiddenIds;
|
||||
}
|
||||
|
||||
return {
|
||||
sources,
|
||||
events,
|
||||
catalogEntries,
|
||||
hiddenSourceIds,
|
||||
visibleSourceIds,
|
||||
visibleEvents,
|
||||
isLoadingSources,
|
||||
isLoadingEvents,
|
||||
isLoadingCatalog,
|
||||
isCreatingSource,
|
||||
error,
|
||||
sourceById,
|
||||
fetchSources,
|
||||
fetchEvents,
|
||||
searchCatalog,
|
||||
createSource,
|
||||
refreshSource,
|
||||
toggleSourceVisibility,
|
||||
};
|
||||
});
|
||||
@@ -13,6 +13,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
const comments = ref([]);
|
||||
const approvals = ref([]);
|
||||
const notifications = ref([]);
|
||||
const activity = ref([]);
|
||||
const isLoading = ref(false);
|
||||
const error = ref(null);
|
||||
const actions = reactive({
|
||||
@@ -35,6 +36,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
comments.value = [];
|
||||
approvals.value = [];
|
||||
notifications.value = [];
|
||||
activity.value = [];
|
||||
error.value = null;
|
||||
}
|
||||
|
||||
@@ -49,19 +51,14 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
assetsResponse,
|
||||
commentsResponse,
|
||||
approvalsResponse,
|
||||
notificationsResponse,
|
||||
activityResponse,
|
||||
] = await Promise.all([
|
||||
client.get(`/api/content-items/${contentItemId}`),
|
||||
client.get(`/api/content-items/${contentItemId}/revisions`),
|
||||
client.get('/api/assets', { params: { contentItemId } }),
|
||||
client.get('/api/comments', { params: { contentItemId } }),
|
||||
client.get('/api/approvals', { params: { contentItemId } }),
|
||||
client.get('/api/notifications', {
|
||||
params: {
|
||||
workspaceId: workspaceStore.activeWorkspaceId ?? undefined,
|
||||
contentItemId,
|
||||
},
|
||||
}),
|
||||
client.get(`/api/content-items/${contentItemId}/activity`),
|
||||
]);
|
||||
|
||||
item.value = itemResponse.data;
|
||||
@@ -69,7 +66,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
assets.value = assetsResponse.data ?? [];
|
||||
comments.value = commentsResponse.data ?? [];
|
||||
approvals.value = approvalsResponse.data ?? [];
|
||||
notifications.value = notificationsResponse.data ?? [];
|
||||
activity.value = activityResponse.data ?? [];
|
||||
} catch (fetchError) {
|
||||
console.error('Failed to load content item detail:', fetchError);
|
||||
reset();
|
||||
@@ -105,7 +102,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
});
|
||||
if (response.data) {
|
||||
assets.value = [...assets.value, response.data];
|
||||
await fetchNotifications(contentItemId);
|
||||
await fetchActivity(contentItemId);
|
||||
}
|
||||
return response.data;
|
||||
} finally {
|
||||
@@ -120,7 +117,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
const response = await client.post(`/api/assets/${assetId}/revisions`, payload);
|
||||
if (response.data) {
|
||||
await fetchAssets(contentItemId);
|
||||
await fetchNotifications(contentItemId);
|
||||
await fetchActivity(contentItemId);
|
||||
}
|
||||
return response.data;
|
||||
} finally {
|
||||
@@ -139,22 +136,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
});
|
||||
if (response.data) {
|
||||
comments.value = [...comments.value, response.data];
|
||||
await fetchNotifications(contentItemId);
|
||||
}
|
||||
return response.data;
|
||||
} finally {
|
||||
actions.comment = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveComment(contentItemId, commentId) {
|
||||
actions.comment = true;
|
||||
|
||||
try {
|
||||
const response = await client.post(`/api/comments/${commentId}/resolve`);
|
||||
if (response.data) {
|
||||
comments.value = comments.value.map(comment => comment.id === commentId ? response.data : comment);
|
||||
await fetchNotifications(contentItemId);
|
||||
await fetchActivity(contentItemId);
|
||||
}
|
||||
return response.data;
|
||||
} finally {
|
||||
@@ -170,7 +152,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
if (response.data) {
|
||||
approvals.value = approvals.value.map(approval => approval.id === approvalId ? response.data : approval);
|
||||
await fetchContentItem(contentItemId);
|
||||
await fetchNotifications(contentItemId);
|
||||
await fetchActivity(contentItemId);
|
||||
}
|
||||
return response.data;
|
||||
} finally {
|
||||
@@ -184,7 +166,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
try {
|
||||
const response = await client.post(`/api/content-items/${contentItemId}/status`, { status });
|
||||
item.value = response.data;
|
||||
await fetchNotifications(contentItemId);
|
||||
await fetchActivity(contentItemId);
|
||||
return response.data;
|
||||
} finally {
|
||||
actions.status = false;
|
||||
@@ -214,6 +196,12 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
return notifications.value;
|
||||
}
|
||||
|
||||
async function fetchActivity(contentItemId) {
|
||||
const response = await client.get(`/api/content-items/${contentItemId}/activity`);
|
||||
activity.value = response.data ?? [];
|
||||
return activity.value;
|
||||
}
|
||||
|
||||
return {
|
||||
item,
|
||||
revisions,
|
||||
@@ -221,6 +209,7 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
comments,
|
||||
approvals,
|
||||
notifications,
|
||||
activity,
|
||||
isLoading,
|
||||
error,
|
||||
actions,
|
||||
@@ -230,8 +219,8 @@ export const useContentItemDetailStore = defineStore('content-item-detail', () =
|
||||
addGoogleDriveAsset,
|
||||
addAssetRevision,
|
||||
addComment,
|
||||
resolveComment,
|
||||
submitDecision,
|
||||
updateStatus,
|
||||
fetchActivity,
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user