Notifications.vue 8.72 KB
Newer Older
1
<template>
Agate's avatar
Agate committed
2
  <main class="main pusher page-notifications" v-title="labels.title">
3
    <section class="ui vertical aligned stripe segment">
4
      <div class="ui container">
5
6
7
8
9
        <div class="ui container" v-if="additionalNotifications">
          <h1 class="ui header"><translate translate-context="Content/Notifications/Title">Your messages</translate></h1>
          <div class="ui two column stackable grid">
            <div class="column" v-if="showInstanceSupportMessage">
              <div class="ui attached info message">
10
                <h4 class="header">
11
                  <translate translate-context="Content/Notifications/Header">Support this Funkwhale pod</translate>
12
                </h4>
13
14
15
16
17
                <div v-html="markdown.makeHtml($store.state.instance.settings.instance.support_message.value)"></div>
              </div>
              <div class="ui bottom attached segment">
                <form @submit.prevent="setDisplayDate('instance_support_message_display_date', instanceSupportMessageDelay)" class="ui inline form">
                  <div class="inline field">
18
                    <label for="instance-reminder-delay">
19
20
                      <translate translate-context="Content/Notifications/Label">Remind me in:</translate>
                    </label>
21
                    <select id="instance-reminder-delay" v-model="instanceSupportMessageDelay">
22
23
24
25
26
27
28
29
30
31
32
33
34
35
                      <option :value="30"><translate translate-context="*/*/*">30 days</translate></option>
                      <option :value="60"><translate translate-context="*/*/*">60 days</translate></option>
                      <option :value="90"><translate translate-context="*/*/*">90 days</translate></option>
                      <option :value="null"><translate translate-context="*/*/*">Never</translate></option>
                    </select>
                    <button type="submit" class="ui right floated basic button">
                      <translate translate-context="Content/Notifications/Button.Label">Got it!</translate>
                    </button>
                  </div>
                </form>
              </div>
            </div>
            <div class="column" v-if="showFunkwhaleSupportMessage">
              <div class="ui info attached message">
36
                <h4 class="header">
37
                  <translate translate-context="Content/Notifications/Header">Do you like Funkwhale?</translate>
38
                </h4>
39
40
41
                <p>
                  <translate translate-context="Content/Notifications/Paragraph">We noticed you've been here for a while. If Funkwhale is useful to you, we could use your help to make it even better!</translate>
                </p>
heyarne's avatar
heyarne committed
42
                <a href="https://funkwhale.audio/support-us" target="_blank" rel="noopener" class="ui primary inverted button">
43
44
                  <translate translate-context="Content/Notifications/Button.Label/Verb">Donate</translate>
                </a>
heyarne's avatar
heyarne committed
45
                <a href="https://contribute.funkwhale.audio" target="_blank" rel="noopener" class="ui secondary inverted button">
46
47
48
49
50
51
                  <translate translate-context="Content/Notifications/Button.Label/Verb">Discover other ways to help</translate>
                </a>
              </div>
              <div class="ui bottom attached segment">
                <form @submit.prevent="setDisplayDate('funkwhale_support_message_display_date', funkwhaleSupportMessageDelay)" class="ui inline form">
                  <div class="inline field">
52
                    <label for="funkwhale-reminder-delay">
53
54
                      <translate translate-context="Content/Notifications/Label">Remind me in:</translate>
                    </label>
55
                    <select id="funkwhale-reminder-delay" v-model="funkwhaleSupportMessageDelay">
56
57
58
59
60
61
62
63
64
65
66
67
68
69
                      <option :value="30"><translate translate-context="*/*/*">30 days</translate></option>
                      <option :value="60"><translate translate-context="*/*/*">60 days</translate></option>
                      <option :value="90"><translate translate-context="*/*/*">90 days</translate></option>
                      <option :value="null"><translate translate-context="*/*/*">Never</translate></option>
                    </select>
                    <button type="submit" class="ui right floated basic button">
                      <translate translate-context="Content/Notifications/Button.Label">Got it!</translate>
                    </button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
70
        <h1 class="ui header"><translate translate-context="Content/Notifications/Title">Your notifications</translate></h1>
71
        <div class="ui toggle checkbox">
72
73
          <input id="show-read-notifications" v-model="filters.is_read" type="checkbox">
          <label for="show-read-notifications"><translate translate-context="Content/Notifications/Form.Label/Verb">Show read notifications</translate></label>
74
        </div>
Agate's avatar
Agate committed
75
        <button
76
          v-if="filters.is_read === false && notifications.count > 0"
Agate's avatar
Agate committed
77
          @click.prevent="markAllAsRead"
78
79
          class="ui basic labeled icon right floated button">
          <i class="ui check icon" />
80
          <translate translate-context="Content/Notifications/Button.Label/Verb">Mark all as read</translate>
Agate's avatar
Agate committed
81
        </button>
82
        <div class="ui hidden divider" />
83
84

        <div v-if="isLoading" :class="['ui', {'active': isLoading}, 'inverted', 'dimmer']">
85
          <div class="ui text loader"><translate translate-context="Content/Notifications/Paragraph">Loading notifications…</translate></div>
86
87
88
        </div>

        <table v-else-if="notifications.count > 0" class="ui table">
89
90
91
92
          <tbody>
            <notification-row :item="item" v-for="item in notifications.results" :key="item.id" />
          </tbody>
        </table>
93
        <p v-else-if="additionalNotifications === 0">
94
          <translate translate-context="Content/Notifications/Paragraph">No notification to show.</translate>
95
96
        </p>
      </div>
97
98
    </section>
  </main>
99
100
101
</template>

<script>
102
import { mapState, mapGetters } from "vuex"
103
104
import axios from "axios"
import logger from "@/logging"
105
106
import showdown from 'showdown'
import moment from 'moment'
107

108
import NotificationRow from "@/components/notifications/NotificationRow"
109
110

export default {
111
  data() {
112
113
    return {
      isLoading: false,
114
      markdown: new showdown.Converter(),
115
      notifications: {count: 0, results: []},
116
117
      instanceSupportMessageDelay: 60,
      funkwhaleSupportMessageDelay: 60,
118
119
120
121
122
123
124
125
      filters: {
        is_read: false
      }
    }
  },
  components: {
    NotificationRow
  },
126
  created() {
127
    this.fetch(this.filters)
128
129
130
    this.$store.commit("ui/addWebsocketEventHandler", {
      eventName: "inbox.item_added",
      id: "notificationPage",
131
132
133
      handler: this.handleNewNotification
    })
  },
134
135
136
137
  destroyed() {
    this.$store.commit("ui/removeWebsocketEventHandler", {
      eventName: "inbox.item_added",
      id: "notificationPage"
138
139
140
141
142
143
    })
  },
  computed: {
    ...mapState({
      events: state => state.instance.events
    }),
144
145
146
147
148
    ...mapGetters({
      additionalNotifications: 'ui/additionalNotifications',
      showInstanceSupportMessage: 'ui/showInstanceSupportMessage',
      showFunkwhaleSupportMessage: 'ui/showFunkwhaleSupportMessage',
    }),
149
    labels() {
150
      return {
jovuit's avatar
jovuit committed
151
        title: this.$pgettext('*/Notifications/*', "Notifications")
152
153
154
155
      }
    }
  },
  methods: {
156
157
    handleNewNotification (event) {
      this.notifications.count += 1
158
159
      this.notifications.results.unshift(event.item)
    },
160
161
162
163
164
165
166
167
168
169
    setDisplayDate (field, days) {
      let payload = {}
      let newDisplayDate
      if (days) {
        newDisplayDate = moment().add({days})
      } else {
        newDisplayDate = null
      }
      payload[field] = newDisplayDate
      let self = this
170
      axios.patch(`users/${this.$store.state.auth.username}/`, payload).then((response) => {
171
172
173
        self.$store.commit('auth/profilePartialUpdate', response.data)
      })
    },
174
    fetch(params) {
175
176
      this.isLoading = true
      let self = this
177
      axios.get("federation/inbox/", { params: params }).then(response => {
178
179
180
181
        self.isLoading = false
        self.notifications = response.data
      })
    },
182
    markAllAsRead() {
183
184
185
      let self = this
      let before = this.notifications.results[0].id
      let payload = {
186
187
        action: "read",
        objects: "all",
188
189
190
191
192
        filters: {
          is_read: false,
          before
        }
      }
193
194
      axios.post("federation/inbox/action/", payload).then(response => {
        self.$store.commit("ui/notifications", { type: "inbox", count: 0 })
195
196
197
198
        self.notifications.results.forEach(n => {
          n.is_read = true
        })
      })
199
    }
200
201
  },
  watch: {
202
    "filters.is_read"() {
203
204
205
206
207
      this.fetch(this.filters)
    }
  }
}
</script>