diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/announcement/announcement.js | 3 | ||||
| -rw-r--r-- | src/components/announcement/announcement.vue | 4 | ||||
| -rw-r--r-- | src/components/announcements_page/announcements_page.js | 3 | ||||
| -rw-r--r-- | src/components/announcements_page/announcements_page.vue | 2 | ||||
| -rw-r--r-- | src/components/emoji_picker/emoji_picker.js | 6 | ||||
| -rw-r--r-- | src/components/lists_edit/lists_edit.js | 4 | ||||
| -rw-r--r-- | src/components/rich_content/rich_content.scss | 6 | ||||
| -rw-r--r-- | src/components/settings_modal/tabs/data_import_export_tab.vue | 10 | ||||
| -rw-r--r-- | src/i18n/en.json | 3 | ||||
| -rw-r--r-- | src/i18n/uk.json | 32 | ||||
| -rw-r--r-- | src/modules/announcements.js | 2 | ||||
| -rw-r--r-- | src/modules/instance.js | 36 |
12 files changed, 95 insertions, 16 deletions
diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js index c10c7d90..30254926 100644 --- a/src/components/announcement/announcement.js +++ b/src/components/announcement/announcement.js @@ -27,6 +27,9 @@ const Announcement = { ...mapState({ currentUser: state => state.users.currentUser }), + canEditAnnouncement () { + return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements') + }, content () { return this.announcement.content }, diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue index 5f64232a..c1b35981 100644 --- a/src/components/announcement/announcement.vue +++ b/src/components/announcement/announcement.vue @@ -45,14 +45,14 @@ {{ $t('announcements.mark_as_read_action') }} </button> <button - v-if="currentUser && currentUser.role === 'admin'" + v-if="canEditAnnouncement" class="btn button-default" @click="enterEditMode" > {{ $t('announcements.edit_action') }} </button> <button - v-if="currentUser && currentUser.role === 'admin'" + v-if="canEditAnnouncement" class="btn button-default" @click="deleteAnnouncement" > diff --git a/src/components/announcements_page/announcements_page.js b/src/components/announcements_page/announcements_page.js index 0bb4892e..8d1204d4 100644 --- a/src/components/announcements_page/announcements_page.js +++ b/src/components/announcements_page/announcements_page.js @@ -28,6 +28,9 @@ const AnnouncementsPage = { }), announcements () { return this.$store.state.announcements.announcements + }, + canPostAnnouncement () { + return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements') } }, methods: { diff --git a/src/components/announcements_page/announcements_page.vue b/src/components/announcements_page/announcements_page.vue index b1489dec..59ed283d 100644 --- a/src/components/announcements_page/announcements_page.vue +++ b/src/components/announcements_page/announcements_page.vue @@ -7,7 +7,7 @@ </div> <div class="panel-body"> <section - v-if="currentUser && currentUser.role === 'admin'" + v-if="canPostAnnouncement" > <div class="post-form"> <div class="heading"> diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index dd5e5217..2838e102 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -287,7 +287,11 @@ const EmojiPicker = { return 0 }, allCustomGroups () { - return this.$store.getters.groupedCustomEmojis + const emojis = this.$store.getters.groupedCustomEmojis + if (emojis.unpacked) { + emojis.unpacked.text = this.$t('emoji.unpacked') + } + return emojis }, defaultGroup () { return Object.keys(this.allCustomGroups)[0] diff --git a/src/components/lists_edit/lists_edit.js b/src/components/lists_edit/lists_edit.js index c22d1323..c33659df 100644 --- a/src/components/lists_edit/lists_edit.js +++ b/src/components/lists_edit/lists_edit.js @@ -95,10 +95,10 @@ const ListsNew = { return this.addedUserIds.has(user.id) }, addUser (user) { - this.$store.dispatch('addListAccount', { accountId: this.user.id, listId: this.id }) + this.$store.dispatch('addListAccount', { accountId: user.id, listId: this.id }) }, removeUser (userId) { - this.$store.dispatch('removeListAccount', { accountId: this.user.id, listId: this.id }) + this.$store.dispatch('removeListAccount', { accountId: userId, listId: this.id }) }, onSearchLoading (results) { this.searchLoading = true diff --git a/src/components/rich_content/rich_content.scss b/src/components/rich_content/rich_content.scss index db08ef1e..52042314 100644 --- a/src/components/rich_content/rich_content.scss +++ b/src/components/rich_content/rich_content.scss @@ -1,7 +1,11 @@ +@import '../../variables'; + .RichContent { blockquote { - margin: 0.2em 0 0.2em 2em; + margin: 0.2em 0 0.2em 0.2em; font-style: italic; + border-left: 0.2em solid var(--faint, $fallback--faint); + padding-left: 1em; } pre { diff --git a/src/components/settings_modal/tabs/data_import_export_tab.vue b/src/components/settings_modal/tabs/data_import_export_tab.vue index e3b7f407..48356c9b 100644 --- a/src/components/settings_modal/tabs/data_import_export_tab.vue +++ b/src/components/settings_modal/tabs/data_import_export_tab.vue @@ -78,6 +78,16 @@ {{ $t('settings.download_backup') }} </a> <span + v-else-if="backup.state === 'running'" + > + {{ $tc('settings.backup_running', backup.processed_number, { number: backup.processed_number }) }} + </span> + <span + v-else-if="backup.state === 'failed'" + > + {{ $t('settings.backup_failed') }} + </span> + <span v-else > {{ $t('settings.backup_not_ready') }} diff --git a/src/i18n/en.json b/src/i18n/en.json index 59ee1c17..1ee1147a 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -225,6 +225,7 @@ "search_emoji": "Search for an emoji", "add_emoji": "Insert emoji", "custom": "Custom emoji", + "unpacked": "Unpacked emoji", "unicode": "Unicode emoji", "unicode_groups": { "activities": "Activities", @@ -390,6 +391,8 @@ "account_backup_table_head": "Backup", "download_backup": "Download", "backup_not_ready": "This backup is not ready yet.", + "backup_running": "This backup is in progress, processed {number} record. | This backup is in progress, processed {number} records.", + "backup_failed": "This backup has failed.", "remove_backup": "Remove", "list_backups_error": "Error fetching backup list: {error}", "add_backup": "Create a new backup", diff --git a/src/i18n/uk.json b/src/i18n/uk.json index 99b49868..c781b1f6 100644 --- a/src/i18n/uk.json +++ b/src/i18n/uk.json @@ -188,7 +188,8 @@ "mobile_sidebar": "Ввімкнути бокову панель", "mobile_notifications": "Відкрити сповіщення (є непрочитані)", "mobile_notifications_close": "Закрити сповіщення", - "edit_nav_mobile": "Редагувати панель навігації" + "edit_nav_mobile": "Редагувати панель навігації", + "announcements": "Анонси" }, "media_modal": { "next": "Наступна", @@ -735,7 +736,10 @@ "hide_favorites_description": "Не показувати список моїх вподобань (люди все одно отримують сповіщення)", "third_column_mode": "Коли достатньо місця, показувати третю колонку, що містить", "user_popover_avatar_action_open": "Відкрити профіль", - "wordfilter": "Фільтр слів" + "wordfilter": "Фільтр слів", + "mention_links": "Посилання для згадування", + "user_profiles": "Профілі користувачів", + "notification_visibility_polls": "Закінчення опитувань, в яких ви проголосували" }, "selectable_list": { "select_all": "Вибрати все" @@ -956,7 +960,8 @@ "show_all_conversation_with_icon": "{icon} {text}", "plus_more": "+{number} більше", "thread_show_full_with_icon": "{icon} {text}", - "show_only_conversation_under_this": "Показати всі відповіді на цей допис" + "show_only_conversation_under_this": "Показати всі відповіді на цей допис", + "status_history": "Історія змін" }, "timeline": { "no_more_statuses": "Більше немає дописів", @@ -996,5 +1001,26 @@ "reported_statuses": "Дописи, на які подано скаргу:", "reporter": "Позивач:", "reported_user": "Відповідач:" + }, + "announcements": { + "delete_action": "Видалити", + "page_header": "Анонси", + "title": "Анонси", + "mark_as_read_action": "Позначити як прочитане", + "post_form_header": "Розмістити оголошення", + "post_placeholder": "Введіть текст вашого оголошення тут...", + "post_action": "Пост", + "post_error": "Помилка: {error}", + "close_error": "Закрити", + "start_time_prompt": "Початок: ", + "end_time_prompt": "Кінець: ", + "all_day_prompt": "Це захід на цілий день", + "published_time_display": "Опубліковано в {time}", + "start_time_display": "Початок о {time}", + "end_time_display": "Кінець о {time}", + "edit_action": "Редагувати", + "submit_edit_action": "Надіслати", + "cancel_edit_action": "Скасувати", + "inactive_message": "Це оголошення неактивне" } } diff --git a/src/modules/announcements.js b/src/modules/announcements.js index e4d2d2b0..4504263b 100644 --- a/src/modules/announcements.js +++ b/src/modules/announcements.js @@ -49,7 +49,7 @@ const announcements = { } const currentUser = store.rootState.users.currentUser - const isAdmin = currentUser && currentUser.role === 'admin' + const isAdmin = currentUser && currentUser.privileges.includes('announcements_manage_announcements') const getAnnouncements = async () => { if (!isAdmin) { diff --git a/src/modules/instance.js b/src/modules/instance.js index 3b15e62e..8e8d13d3 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -181,15 +181,28 @@ const instance = { }, groupedCustomEmojis (state) { const packsOf = emoji => { - return emoji.tags + const packs = emoji.tags .filter(k => k.startsWith('pack:')) - .map(k => k.slice(5)) // remove 'pack:' prefix + .map(k => { + const packName = k.slice(5) // remove 'pack:' prefix + return { + id: `custom-${packName}`, + text: packName + } + }) + + if (!packs.length) { + return [{ + id: 'unpacked' + }] + } else { + return packs + } } return state.customEmoji .reduce((res, emoji) => { - packsOf(emoji).forEach(packName => { - const packId = `custom-${packName}` + packsOf(emoji).forEach(({ id: packId, text: packName }) => { if (!res[packId]) { res[packId] = ({ id: packId, @@ -290,9 +303,22 @@ const instance = { const lb = b.toLowerCase() return la > lb ? 1 : (la < lb ? -1 : 0) } + const noPackLast = (a, b) => { + const aNull = a === '' + const bNull = b === '' + if (aNull === bNull) { + return 0 + } else if (aNull && !bNull) { + return 1 + } else { + return -1 + } + } const byPackThenByName = (a, b) => { const packOf = emoji => (emoji.tags.filter(k => k.startsWith('pack:'))[0] || '').slice(5) - return caseInsensitiveStrCmp(packOf(a), packOf(b)) || caseInsensitiveStrCmp(a.displayText, b.displayText) + const packOfA = packOf(a) + const packOfB = packOf(b) + return noPackLast(packOfA, packOfB) || caseInsensitiveStrCmp(packOfA, packOfB) || caseInsensitiveStrCmp(a.displayText, b.displayText) } const emoji = Object.entries(values).map(([key, value]) => { |
