aboutsummaryrefslogtreecommitdiff
path: root/src/modules/announcements.js
blob: e4d2d2b01567e6709cede73f2189c60e1ca44355 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5

export const defaultState = {
  announcements: [],
  supportsAnnouncements: true,
  fetchAnnouncementsTimer: undefined
}

export const mutations = {
  setAnnouncements (state, announcements) {
    state.announcements = announcements
  },
  setAnnouncementRead (state, { id, read }) {
    const index = state.announcements.findIndex(a => a.id === id)

    if (index < 0) {
      return
    }

    state.announcements[index].read = read
  },
  setFetchAnnouncementsTimer (state, timer) {
    state.fetchAnnouncementsTimer = timer
  },
  setSupportsAnnouncements (state, supportsAnnouncements) {
    state.supportsAnnouncements = supportsAnnouncements
  }
}

export const getters = {
  unreadAnnouncementCount (state, _getters, rootState) {
    if (!rootState.users.currentUser) {
      return 0
    }

    const unread = state.announcements.filter(announcement => !(announcement.inactive || announcement.read))
    return unread.length
  }
}

const announcements = {
  state: defaultState,
  mutations,
  getters,
  actions: {
    fetchAnnouncements (store) {
      if (!store.state.supportsAnnouncements) {
        return Promise.resolve()
      }

      const currentUser = store.rootState.users.currentUser
      const isAdmin = currentUser && currentUser.role === 'admin'

      const getAnnouncements = async () => {
        if (!isAdmin) {
          return store.rootState.api.backendInteractor.fetchAnnouncements()
        }

        const all = await store.rootState.api.backendInteractor.adminFetchAnnouncements()
        const visible = await store.rootState.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 => {
          store.commit('setAnnouncements', 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) {
            store.commit('setSupportsAnnouncements', false)
          } else {
            throw error
          }
        })
    },
    markAnnouncementAsRead (store, id) {
      return store.rootState.api.backendInteractor.dismissAnnouncement({ id })
        .then(() => {
          store.commit('setAnnouncementRead', { id, read: true })
        })
    },
    startFetchingAnnouncements (store) {
      if (store.state.fetchAnnouncementsTimer) {
        return
      }

      const interval = setInterval(() => store.dispatch('fetchAnnouncements'), FETCH_ANNOUNCEMENT_INTERVAL_MS)
      store.commit('setFetchAnnouncementsTimer', interval)

      return store.dispatch('fetchAnnouncements')
    },
    stopFetchingAnnouncements (store) {
      const interval = store.state.fetchAnnouncementsTimer
      store.commit('setFetchAnnouncementsTimer', undefined)
      clearInterval(interval)
    },
    postAnnouncement (store, { content, startsAt, endsAt, allDay }) {
      return store.rootState.api.backendInteractor.postAnnouncement({ content, startsAt, endsAt, allDay })
        .then(() => {
          return store.dispatch('fetchAnnouncements')
        })
    },
    editAnnouncement (store, { id, content, startsAt, endsAt, allDay }) {
      return store.rootState.api.backendInteractor.editAnnouncement({ id, content, startsAt, endsAt, allDay })
        .then(() => {
          return store.dispatch('fetchAnnouncements')
        })
    },
    deleteAnnouncement (store, id) {
      return store.rootState.api.backendInteractor.deleteAnnouncement({ id })
        .then(() => {
          return store.dispatch('fetchAnnouncements')
        })
    }
  }
}

export default announcements