From e067783a30be41644abe1aecca631ef31cf476a8 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 17 Mar 2022 12:59:10 -0400 Subject: Add announcement display with placeholder messages --- src/components/announcement/announcement.vue | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/components/announcement/announcement.vue (limited to 'src/components/announcement/announcement.vue') diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue new file mode 100644 index 00000000..c31328ee --- /dev/null +++ b/src/components/announcement/announcement.vue @@ -0,0 +1,19 @@ + + + + + -- cgit v1.2.3-70-g09d2 From 95750509b14ab5f5a5d8c9a5defafd95ee7efbe3 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 17 Mar 2022 14:01:45 -0400 Subject: Fetch real data from backend --- src/components/announcement/announcement.js | 10 ++++ src/components/announcement/announcement.vue | 24 ++++++++- .../announcements_page/announcements_page.js | 33 ++---------- src/main.js | 4 +- src/modules/announcements.js | 60 ++++++++++++++++++++++ src/services/api/api.service.js | 18 ++++++- 6 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 src/modules/announcements.js (limited to 'src/components/announcement/announcement.vue') diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js index 595f3b4e..9e043e48 100644 --- a/src/components/announcement/announcement.js +++ b/src/components/announcement/announcement.js @@ -6,6 +6,16 @@ const Announcement = { computed: { content () { return this.announcement.content + }, + isRead () { + return this.announcement.read + } + }, + methods: { + markAsRead () { + if (!this.isRead) { + return this.$store.dispatch('markAnnouncementAsRead', this.announcement.id) + } } } } diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue index c31328ee..d8591468 100644 --- a/src/components/announcement/announcement.vue +++ b/src/components/announcement/announcement.vue @@ -1,6 +1,24 @@ @@ -15,5 +33,9 @@ border-bottom-color: var(--border, $fallback--border); border-radius: 0; padding: var(--status-margin, $status-margin); + + .heading, .body { + margin-bottom: var(--status-margin, $status-margin); + } } diff --git a/src/components/announcements_page/announcements_page.js b/src/components/announcements_page/announcements_page.js index 716468e6..a2a218fd 100644 --- a/src/components/announcements_page/announcements_page.js +++ b/src/components/announcements_page/announcements_page.js @@ -4,37 +4,12 @@ const AnnouncementsPage = { components: { Announcement }, + mounted () { + this.$store.dispatch('fetchAnnouncements') + }, computed: { announcements () { - return [{ - "id": "8", - "content": "

Looks like there was an issue processing audio attachments without embedded art since yesterday due to an experimental new feature. That issue has now been fixed, so you may see older posts with audio from other servers pop up in your feeds now as they are being finally properly processed. Sorry!

", - "starts_at": null, - "ends_at": null, - "all_day": false, - "published_at": "2020-07-03T01:27:38.726Z", - "updated_at": "2020-07-03T01:27:38.752Z", - "read": true, - "mentions": [], - "statuses": [], - "tags": [], - "emojis": [], - "reactions": [] - }, { - "id": "8", - "content": "

Looks like there was an issue processing audio attachments without embedded art since yesterday due to an experimental new feature. That issue has now been fixed, so you may see older posts with audio from other servers pop up in your feeds now as they are being finally properly processed. Sorry!

", - "starts_at": null, - "ends_at": null, - "all_day": false, - "published_at": "2020-07-03T01:27:38.726Z", - "updated_at": "2020-07-03T01:27:38.752Z", - "read": true, - "mentions": [], - "statuses": [], - "tags": [], - "emojis": [], - "reactions": [] - }] + return this.$store.state.announcements.announcements } } } diff --git a/src/main.js b/src/main.js index 6aa9cbb7..d3e60a0f 100644 --- a/src/main.js +++ b/src/main.js @@ -24,6 +24,7 @@ import editStatusModule from './modules/editStatus.js' import statusHistoryModule from './modules/statusHistory.js' import chatsModule from './modules/chats.js' +import announcementsModule from './modules/announcements.js' import { createI18n } from 'vue-i18n' @@ -91,7 +92,8 @@ const persistedStateOptions = { postStatus: postStatusModule, editStatus: editStatusModule, statusHistory: statusHistoryModule, - chats: chatsModule + chats: chatsModule, + announcements: announcementsModule }, plugins, strict: false // Socket modifies itself, let's ignore this for now. diff --git a/src/modules/announcements.js b/src/modules/announcements.js new file mode 100644 index 00000000..2ab2600c --- /dev/null +++ b/src/modules/announcements.js @@ -0,0 +1,60 @@ +import { set } from 'vue' + +const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5 + +export const defaultState = { + announcements: [], + fetchAnnouncementsTimer: undefined +} + +export const mutations = { + setAnnouncements (state, announcements) { + set(state, 'announcements', announcements) + }, + setAnnouncementRead (state, { id, read }) { + if (!state.announcements[id]) { + return + } + + set(state.announcements[id], 'read', read) + }, + setFetchAnnouncementsTimer (state, timer) { + set(state, 'fetchAnnouncementsTimer', announcements) + } +} + +const announcements = { + state: defaultState, + mutations, + actions: { + fetchAnnouncements (store) { + return store.rootState.api.backendInteractor.fetchAnnouncements() + .then(announcements => { + store.commit('setAnnouncements', announcements) + }) + }, + 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) + } + } +} + +export default announcements diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 1ec77b37..10d43632 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -90,6 +90,8 @@ const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks' const MASTODON_LISTS_URL = '/api/v1/lists' const MASTODON_STREAMING = '/api/v1/streaming' const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers' +const MASTODON_ANNOUNCEMENTS_URL = '/api/v1/announcements' +const MASTODON_ANNOUNCEMENTS_DISMISS_URL = id => `/api/v1/announcements/${id}/dismiss` const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions` const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` @@ -1361,6 +1363,18 @@ const dismissNotification = ({ credentials, id }) => { }) } +const fetchAnnouncements = ({ credentials }) => { + return promisedRequest({ url: MASTODON_ANNOUNCEMENTS_URL, credentials }) +} + +const dismissAnnouncement = ({ id, credentials }) => { + return promisedRequest({ + url: MASTODON_ANNOUNCEMENTS_DISMISS_URL(id), + credentials, + method: 'POST' + }) +} + export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => { return Object.entries({ ...(credentials @@ -1687,7 +1701,9 @@ const apiService = { readChat, deleteChatMessage, setReportState, - fetchUserInLists + fetchUserInLists, + fetchAnnouncements, + dismissAnnouncement } export default apiService -- cgit v1.2.3-70-g09d2 From e877fedb0e60e795bd5c6aa3e706c64f12746c66 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 17 Mar 2022 15:07:04 -0400 Subject: Implement deleting announcement --- src/components/announcement/announcement.js | 7 +++++++ src/components/announcement/announcement.vue | 18 ++++++++++++++++++ src/modules/announcements.js | 6 ++++++ src/services/api/api.service.js | 12 +++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) (limited to 'src/components/announcement/announcement.vue') diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js index 9e043e48..b1f5ee77 100644 --- a/src/components/announcement/announcement.js +++ b/src/components/announcement/announcement.js @@ -1,9 +1,13 @@ +import { mapState } from 'vuex' const Announcement = { props: { announcement: Object }, computed: { + ...mapState({ + currentUser: state => state.users.currentUser + }), content () { return this.announcement.content }, @@ -16,6 +20,9 @@ const Announcement = { if (!this.isRead) { return this.$store.dispatch('markAnnouncementAsRead', this.announcement.id) } + }, + deleteAnnouncement () { + return this.$store.dispatch('deleteAnnouncement', this.announcement.id) } } } diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue index d8591468..d6f35b9f 100644 --- a/src/components/announcement/announcement.vue +++ b/src/components/announcement/announcement.vue @@ -12,12 +12,20 @@ @@ -37,5 +45,15 @@ .heading, .body { margin-bottom: var(--status-margin, $status-margin); } + + .footer { + display: flex; + flex-direction: row; + justify-content: space-around; + + .btn { + min-width: 10em; + } + } } diff --git a/src/modules/announcements.js b/src/modules/announcements.js index 76cea154..ddc51c33 100644 --- a/src/modules/announcements.js +++ b/src/modules/announcements.js @@ -59,6 +59,12 @@ const announcements = { .then(() => { return store.dispatch('fetchAnnouncements') }) + }, + deleteAnnouncement (store, id) { + return store.rootState.api.backendInteractor.deleteAnnouncement({ id }) + .then(() => { + return store.dispatch('fetchAnnouncements') + }) } } } diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 5206602d..96b8bd70 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -103,6 +103,7 @@ const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => `/api/v1/pleroma/ const PLEROMA_ADMIN_REPORTS = '/api/pleroma/admin/reports' const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups' const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements' +const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}` const oldfetch = window.fetch @@ -1399,6 +1400,14 @@ const postAnnouncement = ({ credentials, content, startsAt, endsAt, allDay }) => }) } +const deleteAnnouncement = ({ id, credentials }) => { + return promisedRequest({ + url: PLEROMA_DELETE_ANNOUNCEMENT_URL(id), + credentials, + method: 'DELETE' + }) +} + export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => { return Object.entries({ ...(credentials @@ -1728,7 +1737,8 @@ const apiService = { fetchUserInLists, fetchAnnouncements, dismissAnnouncement, - postAnnouncement + postAnnouncement, + deleteAnnouncement } export default apiService -- cgit v1.2.3-70-g09d2 From 04fbb6d93d6217812dc1b594b65f237bcee692a7 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 17 Mar 2022 16:51:32 -0400 Subject: Show announcement dates --- src/components/announcement/announcement.js | 35 ++++++++++++++ src/components/announcement/announcement.vue | 54 ++++++++++++++++------ .../announcement_editor/announcement_editor.js | 13 ++++++ .../announcement_editor/announcement_editor.vue | 52 +++++++++++++++++++++ .../announcements_page/announcements_page.js | 4 +- .../announcements_page/announcements_page.vue | 41 +--------------- src/modules/announcements.js | 7 ++- src/services/api/api.service.js | 8 +++- 8 files changed, 156 insertions(+), 58 deletions(-) create mode 100644 src/components/announcement_editor/announcement_editor.js create mode 100644 src/components/announcement_editor/announcement_editor.vue (limited to 'src/components/announcement/announcement.vue') diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js index b1f5ee77..309eecea 100644 --- a/src/components/announcement/announcement.js +++ b/src/components/announcement/announcement.js @@ -1,6 +1,21 @@ import { mapState } from 'vuex' +import AnnouncementEditor from '../announcement_editor/announcement_editor.vue' +import localeService from '../../services/locale/locale.service.js' const Announcement = { + components: { + AnnouncementEditor + }, + data () { + return { + editing: false, + newAnnouncement: { + content: '', + startsAt: undefined, + endsAt: undefined + } + } + }, props: { announcement: Object }, @@ -13,6 +28,22 @@ const Announcement = { }, isRead () { return this.announcement.read + }, + startsAt () { + const time = this.announcement['starts_at'] + if (!time) { + return + } + + return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale)) + }, + endsAt () { + const time = this.announcement['ends_at'] + if (!time) { + return + } + + return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale)) } }, methods: { @@ -23,6 +54,10 @@ const Announcement = { }, deleteAnnouncement () { return this.$store.dispatch('deleteAnnouncement', this.announcement.id) + }, + formatTimeOrDate (time, locale) { + const d = new Date(time) + return this.announcement['all_day'] ? d.toLocaleDateString(locale) : d.toLocaleString(locale) } } } diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue index d6f35b9f..5ddeebf5 100644 --- a/src/components/announcement/announcement.vue +++ b/src/components/announcement/announcement.vue @@ -5,27 +5,42 @@
+
@@ -47,6 +62,15 @@ } .footer { + display: flex; + flex-direction: column; + .times { + display: flex; + flex-direction: column; + } + } + + .footer .actions { display: flex; flex-direction: row; justify-content: space-around; diff --git a/src/components/announcement_editor/announcement_editor.js b/src/components/announcement_editor/announcement_editor.js new file mode 100644 index 00000000..79a03afe --- /dev/null +++ b/src/components/announcement_editor/announcement_editor.js @@ -0,0 +1,13 @@ +import Checkbox from '../checkbox/checkbox.vue' + +const AnnouncementEditor = { + components: { + Checkbox + }, + props: { + announcement: Object, + disabled: Boolean + } +} + +export default AnnouncementEditor diff --git a/src/components/announcement_editor/announcement_editor.vue b/src/components/announcement_editor/announcement_editor.vue new file mode 100644 index 00000000..e2418b8d --- /dev/null +++ b/src/components/announcement_editor/announcement_editor.vue @@ -0,0 +1,52 @@ +