Show announcement dates
This commit is contained in:
		
							parent
							
								
									ce84557190
								
							
						
					
					
						commit
						04fbb6d93d
					
				
					 8 changed files with 156 additions and 58 deletions
				
			
		|  | @ -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) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -5,27 +5,42 @@ | |||
|     </div> | ||||
|     <div class="body"> | ||||
|       <rich-content | ||||
|         v-if="!editing" | ||||
|         :html="content" | ||||
|         :emoji="announcement.emojis" | ||||
|         :handle-links="true" | ||||
|       /> | ||||
|       <announcement-editor | ||||
|         v-else | ||||
|         :announcement="newAnnouncement" | ||||
|       /> | ||||
|     </div> | ||||
|     <div class="footer"> | ||||
|       <button | ||||
|         v-if="currentUser" | ||||
|         class="btn button-default" | ||||
|         :class="{ toggled: isRead }" | ||||
|         @click="markAsRead" | ||||
|       > | ||||
|         {{ $t('announcements.mark_as_read_action') }} | ||||
|       </button> | ||||
|       <button | ||||
|         v-if="currentUser && currentUser.role === 'admin'" | ||||
|         class="btn button-default" | ||||
|         @click="deleteAnnouncement" | ||||
|       > | ||||
|         {{ $t('announcements.delete_action') }} | ||||
|       </button> | ||||
|       <div class="times"> | ||||
|         <span v-if="startsAt"> | ||||
|           {{ $t('announcements.start_time_display', { time: startsAt }) }} | ||||
|         </span> | ||||
|         <span v-if="endsAt"> | ||||
|           {{ $t('announcements.end_time_display', { time: endsAt }) }} | ||||
|         </span> | ||||
|       </div> | ||||
|       <div class="actions"> | ||||
|         <button | ||||
|           v-if="currentUser" | ||||
|           class="btn button-default" | ||||
|           :class="{ toggled: isRead }" | ||||
|           @click="markAsRead" | ||||
|         > | ||||
|           {{ $t('announcements.mark_as_read_action') }} | ||||
|         </button> | ||||
|         <button | ||||
|           v-if="currentUser && currentUser.role === 'admin'" | ||||
|           class="btn button-default" | ||||
|           @click="deleteAnnouncement" | ||||
|         > | ||||
|           {{ $t('announcements.delete_action') }} | ||||
|         </button> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										13
									
								
								src/components/announcement_editor/announcement_editor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/components/announcement_editor/announcement_editor.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| import Checkbox from '../checkbox/checkbox.vue' | ||||
| 
 | ||||
| const AnnouncementEditor = { | ||||
|   components: { | ||||
|     Checkbox | ||||
|   }, | ||||
|   props: { | ||||
|     announcement: Object, | ||||
|     disabled: Boolean | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export default AnnouncementEditor | ||||
							
								
								
									
										52
									
								
								src/components/announcement_editor/announcement_editor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/components/announcement_editor/announcement_editor.vue
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | |||
| <template> | ||||
|   <div class="announcement-editor"> | ||||
|     <textarea | ||||
|       ref="textarea" | ||||
|       v-model="announcement.content" | ||||
|       class="post-textarea" | ||||
|       rows="1" | ||||
|       cols="1" | ||||
|       :placeholder="$t('announcements.post_placeholder')" | ||||
|       :disabled="disabled" | ||||
|     /> | ||||
|     <span class="announcement-metadata"> | ||||
|       <label for="announcement-start-time">{{ $t('announcements.start_time_prompt') }}</label> | ||||
|       <input | ||||
|         id="announcement-start-time" | ||||
|         v-model="announcement.startsAt" | ||||
|         :type="announcement.allDay ? 'date' : 'datetime-local'" | ||||
|         :disabled="disabled" | ||||
|       > | ||||
|     </span> | ||||
|     <span class="announcement-metadata"> | ||||
|       <label for="announcement-end-time">{{ $t('announcements.end_time_prompt') }}</label> | ||||
|       <input | ||||
|         id="announcement-end-time" | ||||
|         v-model="announcement.endsAt" | ||||
|         :type="announcement.allDay ? 'date' : 'datetime-local'" | ||||
|         :disabled="disabled" | ||||
|       > | ||||
|     </span> | ||||
|     <span class="announcement-metadata"> | ||||
|       <Checkbox | ||||
|         id="announcement-all-day" | ||||
|         v-model="announcement.allDay" | ||||
|         :disabled="disabled" | ||||
|       /> | ||||
|       <label for="announcement-all-day">{{ $t('announcements.all_day_prompt') }}</label> | ||||
|     </span> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script src="./announcement_editor.js"></script> | ||||
| 
 | ||||
| <style lang="scss"> | ||||
|     .announcement-editor { | ||||
|       display: flex; | ||||
|       align-items: stretch; | ||||
|       flex-direction: column; | ||||
|       .announcement-metadata { | ||||
|         margin-top: 0.5em; | ||||
|       } | ||||
|     } | ||||
| </style> | ||||
|  | @ -1,11 +1,11 @@ | |||
| import { mapState } from 'vuex' | ||||
| import Announcement from '../announcement/announcement.vue' | ||||
| import Checkbox from '../checkbox/checkbox.vue' | ||||
| import AnnouncementEditor from '../announcement_editor/announcement_editor.vue' | ||||
| 
 | ||||
| const AnnouncementsPage = { | ||||
|   components: { | ||||
|     Announcement, | ||||
|     Checkbox | ||||
|     AnnouncementEditor | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|  |  | |||
|  | @ -14,38 +14,10 @@ | |||
|             <h4>{{ $t('announcements.post_form_header') }}</h4> | ||||
|           </div> | ||||
|           <div class="body"> | ||||
|             <textarea | ||||
|               ref="textarea" | ||||
|               v-model="newAnnouncement.content" | ||||
|               class="post-textarea" | ||||
|               rows="1" | ||||
|               cols="1" | ||||
|               :placeholder="$t('announcements.post_placeholder')" | ||||
|             <announcement-editor | ||||
|               :announcement="newAnnouncement" | ||||
|               :disabled="posting" | ||||
|             /> | ||||
|             <span class="announcement-metadata"> | ||||
|               <label for="announcement-start-time">{{ $t('announcements.start_time_prompt') }}</label> | ||||
|               <input | ||||
|                 id="announcement-start-time" | ||||
|                 v-model="newAnnouncement.startsAt" | ||||
|                 :type="newAnnouncement.allDay ? 'date' : 'datetime-local'" | ||||
|               > | ||||
|             </span> | ||||
|             <span class="announcement-metadata"> | ||||
|               <label for="announcement-end-time">{{ $t('announcements.end_time_prompt') }}</label> | ||||
|               <input | ||||
|                 id="announcement-end-time" | ||||
|                 v-model="newAnnouncement.endsAt" | ||||
|                 :type="newAnnouncement.allDay ? 'date' : 'datetime-local'" | ||||
|               > | ||||
|             </span> | ||||
|             <span class="announcement-metadata"> | ||||
|               <Checkbox | ||||
|                 id="announcement-all-day" | ||||
|                 v-model="newAnnouncement.allDay" | ||||
|               /> | ||||
|               <label for="announcement-all-day">{{ $t('announcements.all_day_prompt') }}</label> | ||||
|             </span> | ||||
|           </div> | ||||
|           <div class="footer"> | ||||
|             <button | ||||
|  | @ -99,15 +71,6 @@ | |||
|       margin-bottom: var(--status-margin, $status-margin); | ||||
|     } | ||||
| 
 | ||||
|     .body { | ||||
|       display: flex; | ||||
|       align-items: stretch; | ||||
|       flex-direction: column; | ||||
|       .announcement-metadata { | ||||
|         margin-top: 0.5em; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .post-textarea { | ||||
|       resize: vertical; | ||||
|       height: 10em; | ||||
|  |  | |||
|  | @ -28,7 +28,12 @@ const announcements = { | |||
|   mutations, | ||||
|   actions: { | ||||
|     fetchAnnouncements (store) { | ||||
|       return store.rootState.api.backendInteractor.fetchAnnouncements() | ||||
|       const currentUser = store.rootState.users.currentUser | ||||
|       const isAdmin = currentUser && currentUser.role === 'admin' | ||||
| 
 | ||||
|       return (isAdmin | ||||
|         ? store.rootState.api.backendInteractor.adminFetchAnnouncements() | ||||
|         : store.rootState.api.backendInteractor.fetchAnnouncements()) | ||||
|         .then(announcements => { | ||||
|           store.commit('setAnnouncements', announcements) | ||||
|         }) | ||||
|  |  | |||
|  | @ -102,6 +102,7 @@ const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read` | |||
| const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => `/api/v1/pleroma/chats/${chatId}/messages/${messageId}` | ||||
| const PLEROMA_ADMIN_REPORTS = '/api/pleroma/admin/reports' | ||||
| const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups' | ||||
| const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements' | ||||
| const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements' | ||||
| const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}` | ||||
| 
 | ||||
|  | @ -1365,6 +1366,10 @@ const dismissNotification = ({ credentials, id }) => { | |||
|   }) | ||||
| } | ||||
| 
 | ||||
| const adminFetchAnnouncements = ({ credentials }) => { | ||||
|   return promisedRequest({ url: PLEROMA_ANNOUNCEMENTS_URL, credentials }) | ||||
| } | ||||
| 
 | ||||
| const fetchAnnouncements = ({ credentials }) => { | ||||
|   return promisedRequest({ url: MASTODON_ANNOUNCEMENTS_URL, credentials }) | ||||
| } | ||||
|  | @ -1738,7 +1743,8 @@ const apiService = { | |||
|   fetchAnnouncements, | ||||
|   dismissAnnouncement, | ||||
|   postAnnouncement, | ||||
|   deleteAnnouncement | ||||
|   deleteAnnouncement, | ||||
|   adminFetchAnnouncements | ||||
| } | ||||
| 
 | ||||
| export default apiService | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Tusooa Zhu
						Tusooa Zhu