2023-04-06 16:32:21 -06:00
|
|
|
import { defineStore } from 'pinia'
|
|
|
|
|
|
2026-06-16 17:32:26 +03:00
|
|
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
2026-06-13 03:10:00 +03:00
|
|
|
|
2026-06-17 14:36:45 +03:00
|
|
|
import { getAnnouncements } from 'src/api/public.js'
|
2026-06-13 03:10:00 +03:00
|
|
|
|
2023-04-06 16:32:21 -06:00
|
|
|
const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5
|
|
|
|
|
|
|
|
|
|
export const useAnnouncementsStore = defineStore('announcements', {
|
|
|
|
|
state: () => ({
|
|
|
|
|
announcements: [],
|
|
|
|
|
supportsAnnouncements: true,
|
2026-01-06 16:22:52 +02:00
|
|
|
fetchAnnouncementsTimer: undefined,
|
2026-06-17 18:15:54 +03:00
|
|
|
adminActions: {},
|
2026-06-17 18:19:44 +03:00
|
|
|
userActions: {},
|
2023-04-06 16:32:21 -06:00
|
|
|
}),
|
|
|
|
|
getters: {
|
2026-01-06 16:22:52 +02:00
|
|
|
unreadAnnouncementCount() {
|
2023-04-06 16:32:21 -06:00
|
|
|
if (!window.vuex.state.users.currentUser) {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
const unread = this.announcements.filter(
|
|
|
|
|
(announcement) => !(announcement.inactive || announcement.read),
|
|
|
|
|
)
|
2023-04-06 16:32:21 -06:00
|
|
|
return unread.length
|
2026-01-06 16:22:52 +02:00
|
|
|
},
|
2023-04-06 16:32:21 -06:00
|
|
|
},
|
|
|
|
|
actions: {
|
2026-06-17 18:15:54 +03:00
|
|
|
async fetchAnnouncements() {
|
|
|
|
|
if (!this.supportsAnnouncements) return
|
2023-04-06 16:32:21 -06:00
|
|
|
|
|
|
|
|
const currentUser = window.vuex.state.users.currentUser
|
2026-01-06 16:22:52 +02:00
|
|
|
const isAdmin =
|
|
|
|
|
currentUser &&
|
2026-06-10 01:58:49 +03:00
|
|
|
currentUser.privileges.has('announcements_manage_announcements')
|
2023-04-06 16:32:21 -06:00
|
|
|
|
2026-06-17 18:15:54 +03:00
|
|
|
try {
|
2026-06-17 18:19:44 +03:00
|
|
|
if (currentUser) {
|
|
|
|
|
this.userActions = await import('src/api/user.js')
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-17 18:15:54 +03:00
|
|
|
if (isAdmin) {
|
|
|
|
|
this.adminActions = await import('src/api/admin.js')
|
|
|
|
|
} else {
|
|
|
|
|
const all = await getAnnouncements({
|
2026-06-16 17:32:26 +03:00
|
|
|
credentials: useOAuthStore().token,
|
2026-06-13 03:10:00 +03:00
|
|
|
})
|
2026-06-17 18:15:54 +03:00
|
|
|
return all.data
|
2023-04-06 16:32:21 -06:00
|
|
|
}
|
|
|
|
|
|
2026-06-17 18:15:54 +03:00
|
|
|
const { data: all } = await this.adminActions.getAnnouncements({
|
2026-06-16 17:32:26 +03:00
|
|
|
credentials: useOAuthStore().token,
|
2026-06-13 03:10:00 +03:00
|
|
|
})
|
2026-06-17 18:15:54 +03:00
|
|
|
|
2026-06-17 17:58:14 +03:00
|
|
|
const { data: visible } = await getAnnouncements({
|
2026-06-16 17:32:26 +03:00
|
|
|
credentials: useOAuthStore().token,
|
2026-06-13 03:10:00 +03:00
|
|
|
})
|
2026-06-17 18:15:54 +03:00
|
|
|
|
2023-04-06 16:32:21 -06:00
|
|
|
const visibleObject = visible.reduce((a, c) => {
|
|
|
|
|
a[c.id] = c
|
|
|
|
|
return a
|
|
|
|
|
}, {})
|
2026-06-17 18:15:54 +03:00
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
const getWithinVisible = (announcement) =>
|
|
|
|
|
visibleObject[announcement.id]
|
2023-04-06 16:32:21 -06:00
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
all.forEach((announcement) => {
|
2023-04-06 16:32:21 -06:00
|
|
|
const visibleAnnouncement = getWithinVisible(announcement)
|
|
|
|
|
if (!visibleAnnouncement) {
|
|
|
|
|
announcement.inactive = true
|
|
|
|
|
} else {
|
|
|
|
|
announcement.read = visibleAnnouncement.read
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2026-06-17 18:15:54 +03:00
|
|
|
this.announcements = all
|
|
|
|
|
} 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
|
|
|
|
|
}
|
2023-04-06 16:32:21 -06:00
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
markAnnouncementAsRead(id) {
|
2026-06-17 18:19:44 +03:00
|
|
|
return this.userActions.dismissAnnouncement({
|
2026-06-13 03:10:00 +03:00
|
|
|
id,
|
2026-06-16 17:32:26 +03:00
|
|
|
credentials: useOAuthStore().token,
|
2026-06-13 03:10:00 +03:00
|
|
|
}).then(() => {
|
|
|
|
|
const index = this.announcements.findIndex((a) => a.id === id)
|
2023-04-06 16:32:21 -06:00
|
|
|
|
2026-06-13 03:10:00 +03:00
|
|
|
if (index < 0) {
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-04-06 16:32:21 -06:00
|
|
|
|
2026-06-13 03:10:00 +03:00
|
|
|
this.announcements[index].read = true
|
|
|
|
|
})
|
2023-04-06 16:32:21 -06:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
startFetchingAnnouncements() {
|
2023-04-06 16:32:21 -06:00
|
|
|
if (this.fetchAnnouncementsTimer) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
const interval = setInterval(
|
|
|
|
|
() => this.fetchAnnouncements(),
|
|
|
|
|
FETCH_ANNOUNCEMENT_INTERVAL_MS,
|
|
|
|
|
)
|
2023-04-06 16:32:21 -06:00
|
|
|
this.fetchAnnouncementsTimer = interval
|
|
|
|
|
|
|
|
|
|
return this.fetchAnnouncements()
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
stopFetchingAnnouncements() {
|
2023-04-06 16:32:21 -06:00
|
|
|
const interval = this.fetchAnnouncementsTimer
|
|
|
|
|
this.fetchAnnouncementsTimer = undefined
|
|
|
|
|
clearInterval(interval)
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
postAnnouncement({ content, startsAt, endsAt, allDay }) {
|
2026-06-17 18:15:54 +03:00
|
|
|
return this.adminActions
|
|
|
|
|
.postAnnouncement({
|
|
|
|
|
credentials: useOAuthStore().token,
|
|
|
|
|
content,
|
|
|
|
|
startsAt,
|
|
|
|
|
endsAt,
|
|
|
|
|
allDay,
|
|
|
|
|
})
|
|
|
|
|
.then(() => {
|
|
|
|
|
return this.fetchAnnouncements()
|
|
|
|
|
})
|
2023-04-06 16:32:21 -06:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
editAnnouncement({ id, content, startsAt, endsAt, allDay }) {
|
2026-06-17 18:15:54 +03:00
|
|
|
return this.adminActions
|
|
|
|
|
.editAnnouncement({
|
|
|
|
|
id,
|
|
|
|
|
content,
|
|
|
|
|
startsAt,
|
|
|
|
|
endsAt,
|
|
|
|
|
allDay,
|
|
|
|
|
credentials: useOAuthStore().token,
|
|
|
|
|
})
|
|
|
|
|
.then(() => {
|
|
|
|
|
return this.fetchAnnouncements()
|
|
|
|
|
})
|
2023-04-06 16:32:21 -06:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
deleteAnnouncement(id) {
|
2026-06-17 18:15:54 +03:00
|
|
|
return this.adminActions
|
|
|
|
|
.deleteAnnouncement({
|
|
|
|
|
id,
|
|
|
|
|
credentials: useOAuthStore().token,
|
|
|
|
|
})
|
|
|
|
|
.then(() => {
|
|
|
|
|
return this.fetchAnnouncements()
|
|
|
|
|
})
|
2026-01-06 16:22:52 +02:00
|
|
|
},
|
|
|
|
|
},
|
2023-04-06 16:32:21 -06:00
|
|
|
})
|