import { defineStore } from 'pinia' const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5 export const useAnnouncementsStore = defineStore('announcements', { state: () => ({ announcements: [], supportsAnnouncements: true, fetchAnnouncementsTimer: undefined, }), getters: { unreadAnnouncementCount() { if (!window.vuex.state.users.currentUser) { return 0 } const unread = this.announcements.filter( (announcement) => !(announcement.inactive || announcement.read), ) return unread.length }, }, actions: { fetchAnnouncements() { if (!this.supportsAnnouncements) { return Promise.resolve() } const currentUser = window.vuex.state.users.currentUser const isAdmin = currentUser && currentUser.privileges.includes('announcements_manage_announcements') const getAnnouncements = async () => { if (!isAdmin) { return window.vuex.state.api.backendInteractor.fetchAnnouncements() } const all = await window.vuex.state.api.backendInteractor.adminFetchAnnouncements() const visible = await window.vuex.state.api.backendInteractor.fetchAnnouncements() const visibleObject = visible.reduce((a, c) => { a[c.id] = c return a }, {}) const getWithinVisible = (announcement) => visibleObject[announcement.id] all.forEach((announcement) => { const visibleAnnouncement = getWithinVisible(announcement) if (!visibleAnnouncement) { announcement.inactive = true } else { announcement.read = visibleAnnouncement.read } }) return all } return getAnnouncements() .then((announcements) => { this.announcements = announcements }) .catch((error) => { // If and only if backend does not support announcements, it would return 404. // In this case, silently ignores it. if (error && error.statusCode === 404) { this.supportsAnnouncements = false } else { throw error } }) }, markAnnouncementAsRead(id) { return window.vuex.state.api.backendInteractor .dismissAnnouncement({ id }) .then(() => { const index = this.announcements.findIndex((a) => a.id === id) if (index < 0) { return } this.announcements[index].read = true }) }, startFetchingAnnouncements() { if (this.fetchAnnouncementsTimer) { return } const interval = setInterval( () => this.fetchAnnouncements(), FETCH_ANNOUNCEMENT_INTERVAL_MS, ) this.fetchAnnouncementsTimer = interval return this.fetchAnnouncements() }, stopFetchingAnnouncements() { const interval = this.fetchAnnouncementsTimer this.fetchAnnouncementsTimer = undefined clearInterval(interval) }, postAnnouncement({ content, startsAt, endsAt, allDay }) { return window.vuex.state.api.backendInteractor .postAnnouncement({ content, startsAt, endsAt, allDay }) .then(() => { return this.fetchAnnouncements() }) }, editAnnouncement({ id, content, startsAt, endsAt, allDay }) { return window.vuex.state.api.backendInteractor .editAnnouncement({ id, content, startsAt, endsAt, allDay }) .then(() => { return this.fetchAnnouncements() }) }, deleteAnnouncement(id) { return window.vuex.state.api.backendInteractor .deleteAnnouncement({ id }) .then(() => { return this.fetchAnnouncements() }) }, }, })