forked from AkkomaGang/akkoma-fe
parent
2977edc04d
commit
fab72940c4
58 changed files with 1514 additions and 175 deletions
14
package.json
14
package.json
|
@ -21,10 +21,10 @@
|
||||||
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||||
"@fortawesome/vue-fontawesome": "3.0.0-5",
|
"@fortawesome/vue-fontawesome": "3.0.1",
|
||||||
"@kazvmoe-infra/pinch-zoom-element": "1.2.0",
|
"@kazvmoe-infra/pinch-zoom-element": "1.2.0",
|
||||||
"@vuelidate/core": "2.0.0-alpha.41",
|
"@vuelidate/core": "2.0.0-alpha.42",
|
||||||
"@vuelidate/validators": "2.0.0-alpha.27",
|
"@vuelidate/validators": "2.0.0-alpha.30",
|
||||||
"body-scroll-lock": "2.7.1",
|
"body-scroll-lock": "2.7.1",
|
||||||
"chromatism": "3.0.0",
|
"chromatism": "3.0.0",
|
||||||
"click-outside-vue3": "4.0.1",
|
"click-outside-vue3": "4.0.1",
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
"html-webpack-plugin": "3.2.0",
|
"html-webpack-plugin": "3.2.0",
|
||||||
"http-proxy-middleware": "0.21.0",
|
"http-proxy-middleware": "0.21.0",
|
||||||
"inject-loader": "2.0.1",
|
"inject-loader": "2.0.1",
|
||||||
"iso-639-1": "2.1.13",
|
"iso-639-1": "2.1.15",
|
||||||
"isparta-loader": "2.0.0",
|
"isparta-loader": "2.0.0",
|
||||||
"json-loader": "0.5.7",
|
"json-loader": "0.5.7",
|
||||||
"karma": "6.3.17",
|
"karma": "6.3.17",
|
||||||
|
@ -107,8 +107,8 @@
|
||||||
"ora": "0.4.1",
|
"ora": "0.4.1",
|
||||||
"postcss-loader": "3.0.0",
|
"postcss-loader": "3.0.0",
|
||||||
"raw-loader": "0.5.1",
|
"raw-loader": "0.5.1",
|
||||||
"sass": "1.20.1",
|
"sass": "1.53.0",
|
||||||
"sass-loader": "7.2.0",
|
"sass-loader": "7.3.1",
|
||||||
"selenium-server": "2.53.1",
|
"selenium-server": "2.53.1",
|
||||||
"semver": "5.7.1",
|
"semver": "5.7.1",
|
||||||
"serviceworker-webpack-plugin": "1.0.1",
|
"serviceworker-webpack-plugin": "1.0.1",
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
"vue-style-loader": "4.1.2",
|
"vue-style-loader": "4.1.2",
|
||||||
"webpack": "4.46.0",
|
"webpack": "4.46.0",
|
||||||
"webpack-dev-middleware": "3.7.3",
|
"webpack-dev-middleware": "3.7.3",
|
||||||
"webpack-hot-middleware": "2.24.3",
|
"webpack-hot-middleware": "2.25.1",
|
||||||
"webpack-merge": "0.20.0"
|
"webpack-merge": "0.20.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -310,7 +310,6 @@ nav {
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.underlay,
|
|
||||||
#sidebar,
|
#sidebar,
|
||||||
#notifs-column {
|
#notifs-column {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -370,6 +370,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
|
|
||||||
// Start fetching things that don't need to block the UI
|
// Start fetching things that don't need to block the UI
|
||||||
store.dispatch('fetchMutes')
|
store.dispatch('fetchMutes')
|
||||||
|
store.dispatch('startFetchingAnnouncements')
|
||||||
getTOS({ store })
|
getTOS({ store })
|
||||||
getStickers({ store })
|
getStickers({ store })
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import RemoteUserResolver from 'components/remote_user_resolver/remote_user_reso
|
||||||
import Lists from 'components/lists/lists.vue'
|
import Lists from 'components/lists/lists.vue'
|
||||||
import ListTimeline from 'components/list_timeline/list_timeline.vue'
|
import ListTimeline from 'components/list_timeline/list_timeline.vue'
|
||||||
import ListEdit from 'components/list_edit/list_edit.vue'
|
import ListEdit from 'components/list_edit/list_edit.vue'
|
||||||
|
import AnnouncementsPage from 'components/announcements_page/announcements_page.vue'
|
||||||
|
|
||||||
export default (store) => {
|
export default (store) => {
|
||||||
const validateAuthenticatedRoute = (to, from, next) => {
|
const validateAuthenticatedRoute = (to, from, next) => {
|
||||||
|
@ -72,10 +73,11 @@ export default (store) => {
|
||||||
{ name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) },
|
{ name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) },
|
||||||
{ name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute },
|
{ name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute },
|
||||||
{ name: 'about', path: '/about', component: About },
|
{ name: 'about', path: '/about', component: About },
|
||||||
{ name: 'user-profile', path: '/:_(users)?/:name', component: UserProfile },
|
|
||||||
{ name: 'lists', path: '/lists', component: Lists },
|
{ name: 'lists', path: '/lists', component: Lists },
|
||||||
{ name: 'list-timeline', path: '/lists/:id', component: ListTimeline },
|
{ name: 'list-timeline', path: '/lists/:id', component: ListTimeline },
|
||||||
{ name: 'list-edit', path: '/lists/:id/edit', component: ListEdit }
|
{ name: 'list-edit', path: '/lists/:id/edit', component: ListEdit },
|
||||||
|
{ name: 'announcements', path: '/announcements', component: AnnouncementsPage },
|
||||||
|
{ name: 'user-profile', path: '/:_(users)?/:name', component: UserProfile }
|
||||||
]
|
]
|
||||||
|
|
||||||
if (store.state.instance.pleromaChatMessagesAvailable) {
|
if (store.state.instance.pleromaChatMessagesAvailable) {
|
||||||
|
|
105
src/components/announcement/announcement.js
Normal file
105
src/components/announcement/announcement.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
|
||||||
|
import RichContent from '../rich_content/rich_content.jsx'
|
||||||
|
import localeService from '../../services/locale/locale.service.js'
|
||||||
|
|
||||||
|
const Announcement = {
|
||||||
|
components: {
|
||||||
|
AnnouncementEditor,
|
||||||
|
RichContent
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
editing: false,
|
||||||
|
editedAnnouncement: {
|
||||||
|
content: '',
|
||||||
|
startsAt: undefined,
|
||||||
|
endsAt: undefined,
|
||||||
|
allDay: undefined
|
||||||
|
},
|
||||||
|
editError: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
announcement: Object
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
currentUser: state => state.users.currentUser
|
||||||
|
}),
|
||||||
|
content () {
|
||||||
|
return this.announcement.content
|
||||||
|
},
|
||||||
|
isRead () {
|
||||||
|
return this.announcement.read
|
||||||
|
},
|
||||||
|
publishedAt () {
|
||||||
|
const time = this.announcement['published_at']
|
||||||
|
if (!time) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale))
|
||||||
|
},
|
||||||
|
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))
|
||||||
|
},
|
||||||
|
inactive () {
|
||||||
|
return this.announcement.inactive
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
markAsRead () {
|
||||||
|
if (!this.isRead) {
|
||||||
|
return this.$store.dispatch('markAnnouncementAsRead', this.announcement.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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)
|
||||||
|
},
|
||||||
|
enterEditMode () {
|
||||||
|
this.editedAnnouncement.content = this.announcement.pleroma['raw_content']
|
||||||
|
this.editedAnnouncement.startsAt = this.announcement['starts_at']
|
||||||
|
this.editedAnnouncement.endsAt = this.announcement['ends_at']
|
||||||
|
this.editedAnnouncement.allDay = this.announcement['all_day']
|
||||||
|
this.editing = true
|
||||||
|
},
|
||||||
|
submitEdit () {
|
||||||
|
this.$store.dispatch('editAnnouncement', {
|
||||||
|
id: this.announcement.id,
|
||||||
|
...this.editedAnnouncement
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.editing = false
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.editError = error.error
|
||||||
|
})
|
||||||
|
},
|
||||||
|
cancelEdit () {
|
||||||
|
this.editing = false
|
||||||
|
},
|
||||||
|
clearError () {
|
||||||
|
this.editError = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Announcement
|
136
src/components/announcement/announcement.vue
Normal file
136
src/components/announcement/announcement.vue
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<template>
|
||||||
|
<div class="announcement">
|
||||||
|
<div class="heading">
|
||||||
|
<h4>{{ $t('announcements.title') }}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<rich-content
|
||||||
|
v-if="!editing"
|
||||||
|
:html="content"
|
||||||
|
:emoji="announcement.emojis"
|
||||||
|
:handle-links="true"
|
||||||
|
/>
|
||||||
|
<announcement-editor
|
||||||
|
v-else
|
||||||
|
:announcement="editedAnnouncement"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<div
|
||||||
|
v-if="!editing"
|
||||||
|
class="times"
|
||||||
|
>
|
||||||
|
<span v-if="publishedAt">
|
||||||
|
{{ $t('announcements.published_time_display', { time: publishedAt }) }}
|
||||||
|
</span>
|
||||||
|
<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
|
||||||
|
v-if="!editing"
|
||||||
|
class="actions"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
v-if="currentUser"
|
||||||
|
class="btn button-default"
|
||||||
|
:class="{ toggled: isRead }"
|
||||||
|
:disabled="inactive"
|
||||||
|
:title="inactive ? $t('announcements.inactive_message') : ''"
|
||||||
|
@click="markAsRead"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.mark_as_read_action') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="currentUser && currentUser.role === 'admin'"
|
||||||
|
class="btn button-default"
|
||||||
|
@click="enterEditMode"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.edit_action') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="currentUser && currentUser.role === 'admin'"
|
||||||
|
class="btn button-default"
|
||||||
|
@click="deleteAnnouncement"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.delete_action') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="actions"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="submitEdit"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.submit_edit_action') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="cancelEdit"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.cancel_edit_action') }}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="editing && editError"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.edit_error', { error }) }}
|
||||||
|
<button
|
||||||
|
class="button-unstyled"
|
||||||
|
@click="clearError"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="times"
|
||||||
|
:title="$t('announcements.close_error')"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./announcement.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../variables";
|
||||||
|
|
||||||
|
.announcement {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.times {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
margin: 1em;
|
||||||
|
max-width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
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
|
60
src/components/announcement_editor/announcement_editor.vue
Normal file
60
src/components/announcement_editor/announcement_editor.vue
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-textarea {
|
||||||
|
resize: vertical;
|
||||||
|
height: 10em;
|
||||||
|
overflow: none;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
55
src/components/announcements_page/announcements_page.js
Normal file
55
src/components/announcements_page/announcements_page.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
import Announcement from '../announcement/announcement.vue'
|
||||||
|
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
|
||||||
|
|
||||||
|
const AnnouncementsPage = {
|
||||||
|
components: {
|
||||||
|
Announcement,
|
||||||
|
AnnouncementEditor
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
newAnnouncement: {
|
||||||
|
content: '',
|
||||||
|
startsAt: undefined,
|
||||||
|
endsAt: undefined,
|
||||||
|
allDay: false
|
||||||
|
},
|
||||||
|
posting: false,
|
||||||
|
error: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$store.dispatch('fetchAnnouncements')
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
currentUser: state => state.users.currentUser
|
||||||
|
}),
|
||||||
|
announcements () {
|
||||||
|
return this.$store.state.announcements.announcements
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
postAnnouncement () {
|
||||||
|
this.posting = true
|
||||||
|
this.$store.dispatch('postAnnouncement', this.newAnnouncement)
|
||||||
|
.then(() => {
|
||||||
|
this.newAnnouncement.content = ''
|
||||||
|
this.startsAt = undefined
|
||||||
|
this.endsAt = undefined
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.error = error.error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.posting = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
clearError () {
|
||||||
|
this.error = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnnouncementsPage
|
79
src/components/announcements_page/announcements_page.vue
Normal file
79
src/components/announcements_page/announcements_page.vue
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<template>
|
||||||
|
<div class="panel panel-default announcements-page">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span>
|
||||||
|
{{ $t('announcements.page_header') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<section
|
||||||
|
v-if="currentUser && currentUser.role === 'admin'"
|
||||||
|
>
|
||||||
|
<div class="post-form">
|
||||||
|
<div class="heading">
|
||||||
|
<h4>{{ $t('announcements.post_form_header') }}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<announcement-editor
|
||||||
|
:announcement="newAnnouncement"
|
||||||
|
:disabled="posting"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<button
|
||||||
|
class="btn button-default post-button"
|
||||||
|
:disabled="posting"
|
||||||
|
@click.prevent="postAnnouncement"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.post_action') }}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ $t('announcements.post_error', { error }) }}
|
||||||
|
<button
|
||||||
|
class="button-unstyled"
|
||||||
|
@click="clearError"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="times"
|
||||||
|
:title="$t('announcements.close_error')"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section
|
||||||
|
v-for="announcement in announcements"
|
||||||
|
:key="announcement.id"
|
||||||
|
>
|
||||||
|
<announcement
|
||||||
|
:announcement="announcement"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./announcements_page.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../variables";
|
||||||
|
|
||||||
|
.announcements-page {
|
||||||
|
.post-form {
|
||||||
|
padding: var(--status-margin, $status-margin);
|
||||||
|
|
||||||
|
.heading, .body {
|
||||||
|
margin-bottom: var(--status-margin, $status-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-button {
|
||||||
|
min-width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -3,6 +3,10 @@
|
||||||
.DesktopNav {
|
.DesktopNav {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
input {
|
||||||
|
color: var(--inputTopbarText, var(--inputText));
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--topBarLink, $fallback--link);
|
color: var(--topBarLink, $fallback--link);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
faStickyNote,
|
faStickyNote,
|
||||||
faSmileBeam
|
faSmileBeam
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { trim } from 'lodash'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faBoxOpen,
|
faBoxOpen,
|
||||||
|
@ -176,7 +177,7 @@ const EmojiPicker = {
|
||||||
filteredEmoji () {
|
filteredEmoji () {
|
||||||
return filterByKeyword(
|
return filterByKeyword(
|
||||||
this.$store.state.instance.customEmoji || [],
|
this.$store.state.instance.customEmoji || [],
|
||||||
this.keyword
|
trim(this.keyword)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
customEmojiBuffer () {
|
customEmojiBuffer () {
|
||||||
|
@ -197,7 +198,7 @@ const EmojiPicker = {
|
||||||
id: 'standard',
|
id: 'standard',
|
||||||
text: this.$t('emoji.unicode'),
|
text: this.$t('emoji.unicode'),
|
||||||
icon: 'box-open',
|
icon: 'box-open',
|
||||||
emojis: filterByKeyword(standardEmojis, this.keyword)
|
emojis: filterByKeyword(standardEmojis, trim(this.keyword))
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
type="text"
|
type="text"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
:placeholder="$t('emoji.search_emoji')"
|
:placeholder="$t('emoji.search_emoji')"
|
||||||
|
@input="$event.target.composing = false"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -47,7 +47,7 @@ const MobileNav = {
|
||||||
isChat () {
|
isChat () {
|
||||||
return this.$route.name === 'chat'
|
return this.$route.name === 'chat'
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount'])
|
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleMobileSidebar () {
|
toggleMobileSidebar () {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
icon="bars"
|
icon="bars"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="unreadChatCount"
|
v-if="unreadChatCount || unreadAnnouncementCount"
|
||||||
class="alert-dot"
|
class="alert-dot"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -13,7 +13,8 @@ import {
|
||||||
faBell,
|
faBell,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faStream,
|
faStream,
|
||||||
faList
|
faList,
|
||||||
|
faBullhorn
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
|
@ -27,7 +28,8 @@ library.add(
|
||||||
faBell,
|
faBell,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faStream,
|
faStream,
|
||||||
faList
|
faList,
|
||||||
|
faBullhorn
|
||||||
)
|
)
|
||||||
|
|
||||||
const NavPanel = {
|
const NavPanel = {
|
||||||
|
@ -57,7 +59,7 @@ const NavPanel = {
|
||||||
federating: state => state.instance.federating,
|
federating: state => state.instance.federating,
|
||||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
||||||
}),
|
}),
|
||||||
...mapGetters(['unreadChatCount'])
|
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,24 @@
|
||||||
/>{{ $t("nav.about") }}
|
/>{{ $t("nav.about") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
<li v-if="currentUser">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'announcements' }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110"
|
||||||
|
icon="bullhorn"
|
||||||
|
/>{{ $t('nav.announcements') }}
|
||||||
|
<span
|
||||||
|
v-if="unreadAnnouncementCount > 0"
|
||||||
|
class="badge badge-notification"
|
||||||
|
>
|
||||||
|
{{ unreadAnnouncementCount }}
|
||||||
|
</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -60,7 +60,7 @@ const Notifications = {
|
||||||
return this.unseenNotifications.length
|
return this.unseenNotifications.length
|
||||||
},
|
},
|
||||||
unseenCountTitle () {
|
unseenCountTitle () {
|
||||||
return this.unseenCount + (this.unreadChatCount)
|
return this.unseenCount + (this.unreadChatCount) + this.unreadAnnouncementCount
|
||||||
},
|
},
|
||||||
loading () {
|
loading () {
|
||||||
return this.$store.state.statuses.notifications.loading
|
return this.$store.state.statuses.notifications.loading
|
||||||
|
@ -80,7 +80,7 @@ const Notifications = {
|
||||||
notificationsToDisplay () {
|
notificationsToDisplay () {
|
||||||
return this.filteredNotifications.slice(0, this.unseenCount + this.seenToDisplayCount)
|
return this.filteredNotifications.slice(0, this.unseenCount + this.seenToDisplayCount)
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount'])
|
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
unseenCountTitle (count) {
|
unseenCountTitle (count) {
|
||||||
|
|
|
@ -7,11 +7,16 @@ const DataImportExportTab = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
activeTab: 'profile',
|
activeTab: 'profile',
|
||||||
newDomainToMute: ''
|
newDomainToMute: '',
|
||||||
|
listBackupsError: false,
|
||||||
|
addBackupError: false,
|
||||||
|
addedBackup: false,
|
||||||
|
backups: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.$store.dispatch('fetchTokens')
|
this.$store.dispatch('fetchTokens')
|
||||||
|
this.fetchBackups()
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Importer,
|
Importer,
|
||||||
|
@ -72,6 +77,28 @@ const DataImportExportTab = {
|
||||||
}
|
}
|
||||||
return user.screen_name
|
return user.screen_name
|
||||||
}).join('\n')
|
}).join('\n')
|
||||||
|
},
|
||||||
|
addBackup () {
|
||||||
|
this.$store.state.api.backendInteractor.addBackup()
|
||||||
|
.then((res) => {
|
||||||
|
this.addedBackup = true
|
||||||
|
this.addBackupError = false
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.addedBackup = false
|
||||||
|
this.addBackupError = error
|
||||||
|
})
|
||||||
|
.then(() => this.fetchBackups())
|
||||||
|
},
|
||||||
|
fetchBackups () {
|
||||||
|
this.$store.state.api.backendInteractor.listBackups()
|
||||||
|
.then((res) => {
|
||||||
|
this.backups = res
|
||||||
|
this.listBackupsError = false
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.listBackupsError = error.error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,67 @@
|
||||||
:export-button-label="$t('settings.mute_export_button')"
|
:export-button-label="$t('settings.mute_export_button')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.account_backup') }}</h2>
|
||||||
|
<p>{{ $t('settings.account_backup_description') }}</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ $t('settings.account_backup_table_head') }}</th>
|
||||||
|
<th />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="backup in backups"
|
||||||
|
:key="backup.id"
|
||||||
|
>
|
||||||
|
<td>{{ backup.inserted_at }}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<a
|
||||||
|
v-if="backup.processed"
|
||||||
|
target="_blank"
|
||||||
|
:href="backup.url"
|
||||||
|
>
|
||||||
|
{{ $t('settings.download_backup') }}
|
||||||
|
</a>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
{{ $t('settings.backup_not_ready') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div
|
||||||
|
v-if="listBackupsError"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ $t('settings.list_backups_error', { error }) }}
|
||||||
|
<button
|
||||||
|
:title="$t('settings.hide_list_backups_error_action')"
|
||||||
|
@click="listBackupsError = false"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="times"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="addBackup"
|
||||||
|
>
|
||||||
|
{{ $t('settings.add_backup') }}
|
||||||
|
</button>
|
||||||
|
<p v-if="addedBackup">
|
||||||
|
{{ $t('settings.added_backup') }}
|
||||||
|
</p>
|
||||||
|
<template v-if="addBackupError !== false">
|
||||||
|
<p>{{ $t('settings.add_backup_error', { error: addBackupError }) }}</p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ const SideDrawer = {
|
||||||
...mapState({
|
...mapState({
|
||||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
||||||
}),
|
}),
|
||||||
...mapGetters(['unreadChatCount'])
|
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleDrawer () {
|
toggleDrawer () {
|
||||||
|
|
|
@ -191,6 +191,26 @@
|
||||||
/> {{ $t("nav.administration") }}
|
/> {{ $t("nav.administration") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="currentUser"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'announcements' }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="bullhorn"
|
||||||
|
/> {{ $t("nav.announcements") }}
|
||||||
|
<span
|
||||||
|
v-if="unreadAnnouncementCount"
|
||||||
|
class="badge badge-notification"
|
||||||
|
>
|
||||||
|
{{ unreadAnnouncementCount }}
|
||||||
|
</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
v-if="currentUser"
|
v-if="currentUser"
|
||||||
@click="toggleDrawer"
|
@click="toggleDrawer"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
:datetime="time"
|
:datetime="time"
|
||||||
:title="localeDateString"
|
:title="localeDateString"
|
||||||
>
|
>
|
||||||
{{ $t(relativeTime.key, [relativeTime.num]) }}
|
{{ $tc(relativeTime.key, relativeTime.num, [relativeTime.num]) }}
|
||||||
</time>
|
</time>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -621,7 +621,6 @@
|
||||||
"disable_any_subscription": "Deshabilita completament seguir algú",
|
"disable_any_subscription": "Deshabilita completament seguir algú",
|
||||||
"quarantine": "Deshabilita la federació a les entrades de les usuàries",
|
"quarantine": "Deshabilita la federació a les entrades de les usuàries",
|
||||||
"moderation": "Moderació",
|
"moderation": "Moderació",
|
||||||
"delete_user_confirmation": "Estàs completament segur/a? Aquesta acció no es pot desfer.",
|
|
||||||
"revoke_admin": "Revoca l'Admin",
|
"revoke_admin": "Revoca l'Admin",
|
||||||
"activate_account": "Activa el compte",
|
"activate_account": "Activa el compte",
|
||||||
"deactivate_account": "Desactiva el compte",
|
"deactivate_account": "Desactiva el compte",
|
||||||
|
|
|
@ -582,7 +582,6 @@
|
||||||
"statuses": "Beiträge",
|
"statuses": "Beiträge",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"sandbox": "Erzwinge Beiträge nur für Follower sichtbar zu sein",
|
"sandbox": "Erzwinge Beiträge nur für Follower sichtbar zu sein",
|
||||||
"delete_user_confirmation": "Achtung! Diese Entscheidung kann nicht rückgängig gemacht werden! Trotzdem durchführen?",
|
|
||||||
"grant_admin": "Administratorprivilegien gewähren",
|
"grant_admin": "Administratorprivilegien gewähren",
|
||||||
"delete_user": "Nutzer löschen",
|
"delete_user": "Nutzer löschen",
|
||||||
"strip_media": "Medien von Beiträgen entfernen",
|
"strip_media": "Medien von Beiträgen entfernen",
|
||||||
|
|
|
@ -32,6 +32,27 @@
|
||||||
},
|
},
|
||||||
"staff": "Staff"
|
"staff": "Staff"
|
||||||
},
|
},
|
||||||
|
"announcements": {
|
||||||
|
"page_header": "Announcements",
|
||||||
|
"title": "Announcement",
|
||||||
|
"mark_as_read_action": "Mark as read",
|
||||||
|
"post_form_header": "Post announcement",
|
||||||
|
"post_placeholder": "Type your announcement content here...",
|
||||||
|
"post_action": "Post",
|
||||||
|
"post_error": "Error: {error}",
|
||||||
|
"close_error": "Close",
|
||||||
|
"delete_action": "Delete",
|
||||||
|
"start_time_prompt": "Start time: ",
|
||||||
|
"end_time_prompt": "End time: ",
|
||||||
|
"all_day_prompt": "This is an all-day event",
|
||||||
|
"published_time_display": "Published at {time}",
|
||||||
|
"start_time_display": "Starts at {time}",
|
||||||
|
"end_time_display": "Ends at {time}",
|
||||||
|
"edit_action": "Edit",
|
||||||
|
"submit_edit_action": "Submit",
|
||||||
|
"cancel_edit_action": "Cancel",
|
||||||
|
"inactive_message": "This announcement is inactive"
|
||||||
|
},
|
||||||
"shoutbox": {
|
"shoutbox": {
|
||||||
"title": "Shoutbox"
|
"title": "Shoutbox"
|
||||||
},
|
},
|
||||||
|
@ -147,7 +168,8 @@
|
||||||
"preferences": "Preferences",
|
"preferences": "Preferences",
|
||||||
"timelines": "Timelines",
|
"timelines": "Timelines",
|
||||||
"chats": "Chats",
|
"chats": "Chats",
|
||||||
"lists": "Lists"
|
"lists": "Lists",
|
||||||
|
"announcements": "Announcements"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "Unknown status, searching for it…",
|
"broken_favorite": "Unknown status, searching for it…",
|
||||||
|
@ -322,6 +344,16 @@
|
||||||
"mute_import_error": "Error importing mutes",
|
"mute_import_error": "Error importing mutes",
|
||||||
"mutes_imported": "Mutes imported! Processing them will take a while.",
|
"mutes_imported": "Mutes imported! Processing them will take a while.",
|
||||||
"import_mutes_from_a_csv_file": "Import mutes from a csv file",
|
"import_mutes_from_a_csv_file": "Import mutes from a csv file",
|
||||||
|
"account_backup": "Account backup",
|
||||||
|
"account_backup_description": "This allows you to download an archive of your account information and your posts, but they cannot yet be imported into a Pleroma account.",
|
||||||
|
"account_backup_table_head": "Backup",
|
||||||
|
"download_backup": "Download",
|
||||||
|
"backup_not_ready": "This backup is not ready yet.",
|
||||||
|
"remove_backup": "Remove",
|
||||||
|
"list_backups_error": "Error fetching backup list: {error}",
|
||||||
|
"add_backup": "Create a new backup",
|
||||||
|
"added_backup": "Added a new backup.",
|
||||||
|
"add_backup_error": "Error adding a new backup: {error}",
|
||||||
"blocks_tab": "Blocks",
|
"blocks_tab": "Blocks",
|
||||||
"bot": "This is a bot account",
|
"bot": "This is a bot account",
|
||||||
"btnRadius": "Buttons",
|
"btnRadius": "Buttons",
|
||||||
|
@ -718,38 +750,26 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"day": "{0} day",
|
"unit": {
|
||||||
"days": "{0} days",
|
"days": "{0} day | {0} days",
|
||||||
"day_short": "{0}d",
|
|
||||||
"days_short": "{0}d",
|
"days_short": "{0}d",
|
||||||
"hour": "{0} hour",
|
"hours": "{0} hour | {0} hours",
|
||||||
"hours": "{0} hours",
|
|
||||||
"hour_short": "{0}h",
|
|
||||||
"hours_short": "{0}h",
|
"hours_short": "{0}h",
|
||||||
|
"minutes": "{0} minute | {0} minutes",
|
||||||
|
"minutes_short": "{0}min",
|
||||||
|
"months": "{0} month | {0} months",
|
||||||
|
"months_short": "{0}mo",
|
||||||
|
"seconds": "{0} second | {0} seconds",
|
||||||
|
"seconds_short": "{0}s",
|
||||||
|
"weeks": "{0} week | {0} weeks",
|
||||||
|
"weeks_short": "{0}w",
|
||||||
|
"years": "{0} year | {0} years",
|
||||||
|
"years_short": "{0}y"
|
||||||
|
},
|
||||||
"in_future": "in {0}",
|
"in_future": "in {0}",
|
||||||
"in_past": "{0} ago",
|
"in_past": "{0} ago",
|
||||||
"minute": "{0} minute",
|
|
||||||
"minutes": "{0} minutes",
|
|
||||||
"minute_short": "{0}min",
|
|
||||||
"minutes_short": "{0}min",
|
|
||||||
"month": "{0} month",
|
|
||||||
"months": "{0} months",
|
|
||||||
"month_short": "{0}mo",
|
|
||||||
"months_short": "{0}mo",
|
|
||||||
"now": "just now",
|
"now": "just now",
|
||||||
"now_short": "now",
|
"now_short": "now"
|
||||||
"second": "{0} second",
|
|
||||||
"seconds": "{0} seconds",
|
|
||||||
"second_short": "{0}s",
|
|
||||||
"seconds_short": "{0}s",
|
|
||||||
"week": "{0} week",
|
|
||||||
"weeks": "{0} weeks",
|
|
||||||
"week_short": "{0}w",
|
|
||||||
"weeks_short": "{0}w",
|
|
||||||
"year": "{0} year",
|
|
||||||
"years": "{0} years",
|
|
||||||
"year_short": "{0}y",
|
|
||||||
"years_short": "{0}y"
|
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"collapse": "Collapse",
|
"collapse": "Collapse",
|
||||||
|
@ -878,7 +898,7 @@
|
||||||
"disable_any_subscription": "Disallow following user at all",
|
"disable_any_subscription": "Disallow following user at all",
|
||||||
"quarantine": "Disallow user posts from federating",
|
"quarantine": "Disallow user posts from federating",
|
||||||
"delete_user": "Delete user",
|
"delete_user": "Delete user",
|
||||||
"delete_user_confirmation": "Are you absolutely sure? This action cannot be undone."
|
"delete_user_data_and_deactivate_confirmation": "This will permanently delete the data from this account and deactivate it. Are you absolutely sure?"
|
||||||
},
|
},
|
||||||
"highlight": {
|
"highlight": {
|
||||||
"disabled": "No highlight",
|
"disabled": "No highlight",
|
||||||
|
|
|
@ -606,7 +606,6 @@
|
||||||
"mention": "Mencio",
|
"mention": "Mencio",
|
||||||
"hidden": "Kaŝita",
|
"hidden": "Kaŝita",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"delete_user_confirmation": "Ĉu vi tute certas? Ĉi tiu ago ne estas malfarebla.",
|
|
||||||
"delete_user": "Forigi uzanton",
|
"delete_user": "Forigi uzanton",
|
||||||
"quarantine": "Malpermesi federadon de afiŝoj de uzanto",
|
"quarantine": "Malpermesi federadon de afiŝoj de uzanto",
|
||||||
"disable_any_subscription": "Malpermesi ĉian abonadon al uzanto",
|
"disable_any_subscription": "Malpermesi ĉian abonadon al uzanto",
|
||||||
|
|
|
@ -731,8 +731,7 @@
|
||||||
"disable_remote_subscription": "No permitir que usuarios de instancias remotas te siga",
|
"disable_remote_subscription": "No permitir que usuarios de instancias remotas te siga",
|
||||||
"disable_any_subscription": "No permitir que ningún usuario te siga",
|
"disable_any_subscription": "No permitir que ningún usuario te siga",
|
||||||
"quarantine": "No permitir publicaciones de usuarios de instancias remotas",
|
"quarantine": "No permitir publicaciones de usuarios de instancias remotas",
|
||||||
"delete_user": "Eliminar usuario",
|
"delete_user": "Eliminar usuario"
|
||||||
"delete_user_confirmation": "¿Estás completamente seguro? Esta acción no se puede deshacer."
|
|
||||||
},
|
},
|
||||||
"show_repeats": "Mostrar repetidos",
|
"show_repeats": "Mostrar repetidos",
|
||||||
"hide_repeats": "Ocultar repetidos",
|
"hide_repeats": "Ocultar repetidos",
|
||||||
|
|
|
@ -609,8 +609,7 @@
|
||||||
"disable_remote_subscription": "Ez utzi istantzia kanpoko erabiltzaileak zuri jarraitzea",
|
"disable_remote_subscription": "Ez utzi istantzia kanpoko erabiltzaileak zuri jarraitzea",
|
||||||
"disable_any_subscription": "Ez utzi beste erabiltzaileak zuri jarraitzea",
|
"disable_any_subscription": "Ez utzi beste erabiltzaileak zuri jarraitzea",
|
||||||
"quarantine": "Ez onartu mezuak beste instantzietatik",
|
"quarantine": "Ez onartu mezuak beste instantzietatik",
|
||||||
"delete_user": "Erabiltzailea ezabatu",
|
"delete_user": "Erabiltzailea ezabatu"
|
||||||
"delete_user_confirmation": "Erabat ziur zaude? Ekintza hau ezin da desegin."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
|
|
|
@ -620,8 +620,7 @@
|
||||||
"sandbox": "Pakota viestit vain seuraajille",
|
"sandbox": "Pakota viestit vain seuraajille",
|
||||||
"disable_remote_subscription": "Estä seuraaminen ulkopuolisilta sivuilta",
|
"disable_remote_subscription": "Estä seuraaminen ulkopuolisilta sivuilta",
|
||||||
"quarantine": "Estä käyttäjän viestin federoituminen",
|
"quarantine": "Estä käyttäjän viestin federoituminen",
|
||||||
"delete_user": "Poista käyttäjä",
|
"delete_user": "Poista käyttäjä"
|
||||||
"delete_user_confirmation": "Oletko aivan varma? Tätä ei voi kumota."
|
|
||||||
},
|
},
|
||||||
"favorites": "Tykkäykset",
|
"favorites": "Tykkäykset",
|
||||||
"mention": "Mainitse",
|
"mention": "Mainitse",
|
||||||
|
|
|
@ -659,8 +659,7 @@
|
||||||
"disable_remote_subscription": "Interdir de s'abonner a l'utilisateur depuis l'instance distante",
|
"disable_remote_subscription": "Interdir de s'abonner a l'utilisateur depuis l'instance distante",
|
||||||
"disable_any_subscription": "Interdir de s'abonner à l'utilisateur tout court",
|
"disable_any_subscription": "Interdir de s'abonner à l'utilisateur tout court",
|
||||||
"quarantine": "Interdir les statuts de l'utilisateur à fédérer",
|
"quarantine": "Interdir les statuts de l'utilisateur à fédérer",
|
||||||
"delete_user": "Supprimer l'utilisateur",
|
"delete_user": "Supprimer l'utilisateur"
|
||||||
"delete_user_confirmation": "Êtes-vous absolument-sûr⋅e ? Cette action ne peut être annulée."
|
|
||||||
},
|
},
|
||||||
"mention": "Mention",
|
"mention": "Mention",
|
||||||
"hidden": "Caché",
|
"hidden": "Caché",
|
||||||
|
|
|
@ -347,8 +347,7 @@
|
||||||
"disable_remote_subscription": "אל תאפשר עקיבה של המשתמש מאינסטנס אחר",
|
"disable_remote_subscription": "אל תאפשר עקיבה של המשתמש מאינסטנס אחר",
|
||||||
"disable_any_subscription": "אל תאפשר עקיבה של המשתמש בכלל",
|
"disable_any_subscription": "אל תאפשר עקיבה של המשתמש בכלל",
|
||||||
"quarantine": "אל תאפשר פדרציה של ההודעות של המשתמש",
|
"quarantine": "אל תאפשר פדרציה של ההודעות של המשתמש",
|
||||||
"delete_user": "מחק משתמש",
|
"delete_user": "מחק משתמש"
|
||||||
"delete_user_confirmation": "בטוח? פעולה זו הינה בלתי הפיכה."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
|
|
|
@ -327,8 +327,7 @@
|
||||||
"delete_account": "Hapus akun",
|
"delete_account": "Hapus akun",
|
||||||
"force_nsfw": "Tandai semua postingan sebagai NSFW",
|
"force_nsfw": "Tandai semua postingan sebagai NSFW",
|
||||||
"strip_media": "Hapus media dari postingan-postingan",
|
"strip_media": "Hapus media dari postingan-postingan",
|
||||||
"delete_user": "Hapus pengguna",
|
"delete_user": "Hapus pengguna"
|
||||||
"delete_user_confirmation": "Apakah Anda benar-benar yakin? Tindakan ini tidak dapat dibatalkan."
|
|
||||||
},
|
},
|
||||||
"follow_unfollow": "Berhenti mengikuti",
|
"follow_unfollow": "Berhenti mengikuti",
|
||||||
"followees": "Mengikuti",
|
"followees": "Mengikuti",
|
||||||
|
|
|
@ -485,7 +485,6 @@
|
||||||
"deny": "Nega",
|
"deny": "Nega",
|
||||||
"remote_follow": "Segui da remoto",
|
"remote_follow": "Segui da remoto",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"delete_user_confirmation": "Ne sei completamente sicuro? Non potrai tornare indietro.",
|
|
||||||
"delete_user": "Elimina utente",
|
"delete_user": "Elimina utente",
|
||||||
"quarantine": "I messaggi non arriveranno alle altre stanze",
|
"quarantine": "I messaggi non arriveranno alle altre stanze",
|
||||||
"disable_any_subscription": "Rendi utente non seguibile",
|
"disable_any_subscription": "Rendi utente non seguibile",
|
||||||
|
|
|
@ -608,8 +608,7 @@
|
||||||
"disable_remote_subscription": "ほかのインスタンスからフォローされないようにする",
|
"disable_remote_subscription": "ほかのインスタンスからフォローされないようにする",
|
||||||
"disable_any_subscription": "フォローされないようにする",
|
"disable_any_subscription": "フォローされないようにする",
|
||||||
"quarantine": "ほかのインスタンスのユーザーのとうこうをとめる",
|
"quarantine": "ほかのインスタンスのユーザーのとうこうをとめる",
|
||||||
"delete_user": "ユーザーをけす",
|
"delete_user": "ユーザーをけす"
|
||||||
"delete_user_confirmation": "あなたは、ほんとうに、きはたしかですか? これは、とりけすことが、できません。"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
|
|
|
@ -731,8 +731,7 @@
|
||||||
"disable_remote_subscription": "他のインスタンスからフォローされないようにする",
|
"disable_remote_subscription": "他のインスタンスからフォローされないようにする",
|
||||||
"disable_any_subscription": "フォローされないようにする",
|
"disable_any_subscription": "フォローされないようにする",
|
||||||
"quarantine": "他のインスタンスからの投稿を止める",
|
"quarantine": "他のインスタンスからの投稿を止める",
|
||||||
"delete_user": "ユーザーを削除",
|
"delete_user": "ユーザーを削除"
|
||||||
"delete_user_confirmation": "あなたの精神状態に何か問題はございませんか? この操作を取り消すことはできません。"
|
|
||||||
},
|
},
|
||||||
"roles": {
|
"roles": {
|
||||||
"moderator": "モデレーター",
|
"moderator": "モデレーター",
|
||||||
|
|
|
@ -32,6 +32,7 @@ const loaders = {
|
||||||
pt: () => import('./pt.json'),
|
pt: () => import('./pt.json'),
|
||||||
ro: () => import('./ro.json'),
|
ro: () => import('./ro.json'),
|
||||||
ru: () => import('./ru.json'),
|
ru: () => import('./ru.json'),
|
||||||
|
sk: () => import('./sk.json'),
|
||||||
te: () => import('./te.json'),
|
te: () => import('./te.json'),
|
||||||
uk: () => import('./uk.json'),
|
uk: () => import('./uk.json'),
|
||||||
zh: () => import('./zh.json'),
|
zh: () => import('./zh.json'),
|
||||||
|
|
|
@ -553,8 +553,7 @@
|
||||||
"disable_remote_subscription": "Fjern mulighet til å følge brukeren fra andre instanser",
|
"disable_remote_subscription": "Fjern mulighet til å følge brukeren fra andre instanser",
|
||||||
"disable_any_subscription": "Fjern mulighet til å følge brukeren",
|
"disable_any_subscription": "Fjern mulighet til å følge brukeren",
|
||||||
"quarantine": "Gjør at statuser fra brukeren ikke kan sendes til andre instanser",
|
"quarantine": "Gjør at statuser fra brukeren ikke kan sendes til andre instanser",
|
||||||
"delete_user": "Slett bruker",
|
"delete_user": "Slett bruker"
|
||||||
"delete_user_confirmation": "Er du helt sikker? Denne handlingen kan ikke omgjøres."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
|
|
|
@ -580,7 +580,6 @@
|
||||||
"remote_follow": "Volg vanop afstand",
|
"remote_follow": "Volg vanop afstand",
|
||||||
"statuses": "Statussen",
|
"statuses": "Statussen",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"delete_user_confirmation": "Weet je het heel zeker? Deze uitvoering kan niet ongedaan worden gemaakt.",
|
|
||||||
"delete_user": "Gebruiker verwijderen",
|
"delete_user": "Gebruiker verwijderen",
|
||||||
"quarantine": "Federeren van gebruikers berichten verbieden",
|
"quarantine": "Federeren van gebruikers berichten verbieden",
|
||||||
"disable_any_subscription": "Volgen van gebruiker in zijn geheel verbieden",
|
"disable_any_subscription": "Volgen van gebruiker in zijn geheel verbieden",
|
||||||
|
|
|
@ -501,8 +501,7 @@
|
||||||
"disable_remote_subscription": "Desactivar lo seguiment d’utilizaire d’instàncias alonhadas",
|
"disable_remote_subscription": "Desactivar lo seguiment d’utilizaire d’instàncias alonhadas",
|
||||||
"disable_any_subscription": "Desactivar tot seguiment",
|
"disable_any_subscription": "Desactivar tot seguiment",
|
||||||
"quarantine": "Defendre la federacion de las publicacions de l’utilizaire",
|
"quarantine": "Defendre la federacion de las publicacions de l’utilizaire",
|
||||||
"delete_user": "Suprimir l’utilizaire",
|
"delete_user": "Suprimir l’utilizaire"
|
||||||
"delete_user_confirmation": "Volètz vertadièrament far aquò ? Aquesta accion se pòt pas anullar."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
|
|
|
@ -762,8 +762,7 @@
|
||||||
"disable_remote_subscription": "Zakaż obserwowania użytkownika ze zdalnych instancji",
|
"disable_remote_subscription": "Zakaż obserwowania użytkownika ze zdalnych instancji",
|
||||||
"disable_any_subscription": "Zakaż całkowicie obserwowania użytkownika",
|
"disable_any_subscription": "Zakaż całkowicie obserwowania użytkownika",
|
||||||
"quarantine": "Zakaż federowania postów od tego użytkownika",
|
"quarantine": "Zakaż federowania postów od tego użytkownika",
|
||||||
"delete_user": "Usuń użytkownika",
|
"delete_user": "Usuń użytkownika"
|
||||||
"delete_user_confirmation": "Czy jesteś absolutnie pewny(-a)? Ta operacja nie może być cofnięta."
|
|
||||||
},
|
},
|
||||||
"message": "Napisz",
|
"message": "Napisz",
|
||||||
"edit_profile": "Edytuj profil",
|
"edit_profile": "Edytuj profil",
|
||||||
|
|
|
@ -594,7 +594,6 @@
|
||||||
"unmute_progress": "A retirar silêncio…",
|
"unmute_progress": "A retirar silêncio…",
|
||||||
"mute_progress": "A silenciar…",
|
"mute_progress": "A silenciar…",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"delete_user_confirmation": "Tens a certeza? Esta ação não pode ser revertida.",
|
|
||||||
"delete_user": "Eliminar utilizador",
|
"delete_user": "Eliminar utilizador",
|
||||||
"quarantine": "Não permitir publicações de utilizadores de instâncias remotas",
|
"quarantine": "Não permitir publicações de utilizadores de instâncias remotas",
|
||||||
"disable_any_subscription": "Não permitir que nenhum utilizador te siga",
|
"disable_any_subscription": "Não permitir que nenhum utilizador te siga",
|
||||||
|
|
|
@ -576,8 +576,7 @@
|
||||||
"disable_remote_subscription": "Запретить читать с других узлов",
|
"disable_remote_subscription": "Запретить читать с других узлов",
|
||||||
"disable_any_subscription": "Запретить читать пользователя",
|
"disable_any_subscription": "Запретить читать пользователя",
|
||||||
"quarantine": "Не федерировать статусы пользователя",
|
"quarantine": "Не федерировать статусы пользователя",
|
||||||
"delete_user": "Удалить пользователя",
|
"delete_user": "Удалить пользователя"
|
||||||
"delete_user_confirmation": "Вы уверены? Это действие нельзя отменить."
|
|
||||||
},
|
},
|
||||||
"media": "С вложениями",
|
"media": "С вложениями",
|
||||||
"mention": "Упомянуть",
|
"mention": "Упомянуть",
|
||||||
|
|
|
@ -27,6 +27,7 @@ const messages = {
|
||||||
pt: require('../lib/notification-i18n-loader.js!./pt.json'),
|
pt: require('../lib/notification-i18n-loader.js!./pt.json'),
|
||||||
ro: require('../lib/notification-i18n-loader.js!./ro.json'),
|
ro: require('../lib/notification-i18n-loader.js!./ro.json'),
|
||||||
ru: require('../lib/notification-i18n-loader.js!./ru.json'),
|
ru: require('../lib/notification-i18n-loader.js!./ru.json'),
|
||||||
|
sk: require('../lib/notification-i18n-loader.js!./sk.json'),
|
||||||
te: require('../lib/notification-i18n-loader.js!./te.json'),
|
te: require('../lib/notification-i18n-loader.js!./te.json'),
|
||||||
zh: require('../lib/notification-i18n-loader.js!./zh.json'),
|
zh: require('../lib/notification-i18n-loader.js!./zh.json'),
|
||||||
en: require('../lib/notification-i18n-loader.js!./en.json')
|
en: require('../lib/notification-i18n-loader.js!./en.json')
|
||||||
|
|
512
src/i18n/sk.json
Normal file
512
src/i18n/sk.json
Normal file
|
@ -0,0 +1,512 @@
|
||||||
|
{
|
||||||
|
"about": {
|
||||||
|
"mrf": {
|
||||||
|
"federation": "Federácia",
|
||||||
|
"keyword": {
|
||||||
|
"keyword_policies": "Pravidlá pre kľúčové slová",
|
||||||
|
"ftl_removal": "Odstránenie z časovej osy \"Celej známej siete\"",
|
||||||
|
"reject": "Odmietni",
|
||||||
|
"replace": "Nahraď",
|
||||||
|
"is_replaced_by": "→"
|
||||||
|
},
|
||||||
|
"mrf_policies": "Povoliť MRF pravidlá",
|
||||||
|
"mrf_policies_desc": "MRF pravidlá upravujú správanie servera v rámci federácie s inými. Nasledovné pravidlá sú aktívne:",
|
||||||
|
"simple": {
|
||||||
|
"simple_policies": "Pravidlá špecifické pre tento server",
|
||||||
|
"instance": "Server",
|
||||||
|
"reason": "Dôvod",
|
||||||
|
"not_applicable": "N/A",
|
||||||
|
"accept": "Prijať",
|
||||||
|
"accept_desc": "Tento server preberá správy len z nasledovných serverov:",
|
||||||
|
"reject": "Odmietnuť",
|
||||||
|
"reject_desc": "Tento server preberá správy spravy z nasledovných serverov:",
|
||||||
|
"quarantine": "Karanténa",
|
||||||
|
"quarantine_desc": "Tento server posiela verejné oznamy len na nasledovné servre:",
|
||||||
|
"ftl_removal": "Odstránenie časovej osy \"Známa sieť\"",
|
||||||
|
"ftl_removal_desc": "Tento server odstraňuje nasledovné serverov zo svojej časovej osy \"Známa sieť\":",
|
||||||
|
"media_removal": "Odstránenie médií",
|
||||||
|
"media_removal_desc": "Tento server odstraňuje médiá zo správ nasledovných serverov:",
|
||||||
|
"media_nsfw": "Označenie médií ako citlivých",
|
||||||
|
"media_nsfw_desc": "Tento server označuje média ako citlivé v správach z nasledovných serverov:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"staff": "Personál"
|
||||||
|
},
|
||||||
|
"shoutbox": {
|
||||||
|
"title": "Verejné fórum"
|
||||||
|
},
|
||||||
|
"domain_mute_card": {
|
||||||
|
"mute": "Utíš",
|
||||||
|
"mute_progress": "Utišujem…",
|
||||||
|
"unmute": "Povoľ oznamy",
|
||||||
|
"unmute_progress": "Povoľujem oznamy…"
|
||||||
|
},
|
||||||
|
"exporter": {
|
||||||
|
"export": "Export",
|
||||||
|
"processing": "Spracováva sa, čoskoro sa ti ponúknu na stiahnutie súbory s dátami exportu"
|
||||||
|
},
|
||||||
|
"features_panel": {
|
||||||
|
"shout": "Verejné fórum",
|
||||||
|
"pleroma_chat_messages": "Pleroma Chat",
|
||||||
|
"gopher": "Gopher",
|
||||||
|
"media_proxy": "Proxy pre médiá",
|
||||||
|
"scope_options": "Nastavenia rámca",
|
||||||
|
"text_limit": "Limit počtu znakov",
|
||||||
|
"title": "Vlastnosti",
|
||||||
|
"who_to_follow": "Koho nasledovať",
|
||||||
|
"upload_limit": "Limit nahrávania"
|
||||||
|
},
|
||||||
|
"finder": {
|
||||||
|
"error_fetching_user": "Chyba načítavania užívateľa",
|
||||||
|
"find_user": "Nájsť užívateľa"
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"apply": "Použiť",
|
||||||
|
"submit": "Odoslať",
|
||||||
|
"more": "Viac",
|
||||||
|
"loading": "Nahrávam…",
|
||||||
|
"generic_error": "Nastala chyba",
|
||||||
|
"error_retry": "Zopakuj znova, prosím",
|
||||||
|
"retry": "Zopakuj znova",
|
||||||
|
"optional": "nepovinné",
|
||||||
|
"show_more": "Zobraz viac",
|
||||||
|
"show_less": "Zobraz menej",
|
||||||
|
"dismiss": "Zahoď",
|
||||||
|
"cancel": "Zruš",
|
||||||
|
"disable": "Vypni",
|
||||||
|
"enable": "Zapni",
|
||||||
|
"confirm": "Potvrdiť",
|
||||||
|
"verify": "Overiť",
|
||||||
|
"close": "Zatvoriť",
|
||||||
|
"peek": "Vybrať",
|
||||||
|
"role": {
|
||||||
|
"admin": "Správca",
|
||||||
|
"moderator": "Moderátor"
|
||||||
|
},
|
||||||
|
"flash_content": "Klikni pre zobrazenie Flash obsahu prostredníctvom Ruffle (experimentálne, nemusí fungovať).",
|
||||||
|
"flash_security": "Flash obsah je potencionálne nebezpečný, keďže je to produkt s uzatvoreným kódom.",
|
||||||
|
"flash_fail": "Nepodarilo sa nahrať Flash obsah, pre detaily pozri konzolu prehliadača.",
|
||||||
|
"scope_in_timeline": {
|
||||||
|
"direct": "Priame",
|
||||||
|
"private": "Len pre nasledovníkov",
|
||||||
|
"public": "Verejné",
|
||||||
|
"unlisted": "Nezaradené"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image_cropper": {
|
||||||
|
"crop_picture": "Orezať obrázok",
|
||||||
|
"save": "Uložiť",
|
||||||
|
"save_without_cropping": "Ulož bez orezania",
|
||||||
|
"cancel": "Zrušiť"
|
||||||
|
},
|
||||||
|
"importer": {
|
||||||
|
"submit": "Odoslať",
|
||||||
|
"success": "Úspečne naimportované.",
|
||||||
|
"error": "Pri importe súboru nastala chyba."
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"login": "Prihlásiť sa",
|
||||||
|
"description": "Prihlásiť pomocou OAuth",
|
||||||
|
"logout": "Odhlásiť sa",
|
||||||
|
"password": "Heslo",
|
||||||
|
"placeholder": "napr. peter",
|
||||||
|
"register": "Registrácia",
|
||||||
|
"username": "Meno užívateľa",
|
||||||
|
"hint": "Prihlás sa, aby si sa mohol zúčastniť konverzácie",
|
||||||
|
"authentication_code": "Autentifikačný kód",
|
||||||
|
"enter_recovery_code": "Zadaj kód obnovenia",
|
||||||
|
"enter_two_factor_code": "Zadaj 2-fázový validačný kód",
|
||||||
|
"recovery_code": "Kód obnovenia",
|
||||||
|
"heading": {
|
||||||
|
"totp": "2-fázové overenie",
|
||||||
|
"recovery": "2-fázové obnova"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"media_modal": {
|
||||||
|
"previous": "Predchádzajúce",
|
||||||
|
"next": "Nasledujúce",
|
||||||
|
"counter": "{current} / {total}",
|
||||||
|
"hide": "Zatvoriť prehliadač médií"
|
||||||
|
},
|
||||||
|
"nav": {
|
||||||
|
"about": "O stránke",
|
||||||
|
"administration": "Administrácia",
|
||||||
|
"back": "Späť",
|
||||||
|
"friend_requests": "Žiadosti o priateľstvo",
|
||||||
|
"mentions": "Zmienky",
|
||||||
|
"interactions": "Interakcie",
|
||||||
|
"dms": "Priame správy",
|
||||||
|
"public_tl": "Verejná časová os",
|
||||||
|
"timeline": "Časová os",
|
||||||
|
"home_timeline": "Domáca časová os",
|
||||||
|
"twkn": "Známa sieť",
|
||||||
|
"bookmarks": "Záložky",
|
||||||
|
"user_search": "Hľadanie užívateľa",
|
||||||
|
"search": "Hladať",
|
||||||
|
"who_to_follow": "Koho nasledovať",
|
||||||
|
"preferences": "Nastavenia",
|
||||||
|
"timelines": "Časové osy",
|
||||||
|
"chats": "Chaty"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"broken_favorite": "Neznáma správa, dohľadávam ju…",
|
||||||
|
"error": "Chyba získavania upozornení: {0}",
|
||||||
|
"favorited_you": "si obľúbil tvoju správu",
|
||||||
|
"followed_you": "ťa nasleduje",
|
||||||
|
"follow_request": "ťa chce nasledovať",
|
||||||
|
"load_older": "Nahrať staršie upozornenia",
|
||||||
|
"notifications": "Upozornenia",
|
||||||
|
"read": "Prečítané!",
|
||||||
|
"repeated_you": "zopakoval tvoju správu",
|
||||||
|
"no_more_notifications": "Žiadne ďalšie upozornenia",
|
||||||
|
"migrated_to": "sa presťahoval na",
|
||||||
|
"reacted_with": "reagoval nasledovne {0}"
|
||||||
|
},
|
||||||
|
"polls": {
|
||||||
|
"add_poll": "Pridať anketu",
|
||||||
|
"add_option": "Pridať možnosť",
|
||||||
|
"option": "Možnosť",
|
||||||
|
"votes": "hlasy",
|
||||||
|
"people_voted_count": "{count} volič | {count} voličov",
|
||||||
|
"votes_count": "{count} hlas | {count} hlasov",
|
||||||
|
"vote": "Hlas",
|
||||||
|
"type": "Typ ankety",
|
||||||
|
"single_choice": "Výber jednej možnosti",
|
||||||
|
"multiple_choices": "Výber viacerých možností",
|
||||||
|
"expiry": "Vek ankety",
|
||||||
|
"expires_in": "Anketa končí za {0}",
|
||||||
|
"expired": "Anketa skončila pre {0}",
|
||||||
|
"not_enough_options": "Príliš málo jedinečných možností v ankete"
|
||||||
|
},
|
||||||
|
"emoji": {
|
||||||
|
"stickers": "Nálepka",
|
||||||
|
"emoji": "Emotikon",
|
||||||
|
"keep_open": "Ponechaj okno výberu otvorené",
|
||||||
|
"search_emoji": "Vyhladať emotikon",
|
||||||
|
"add_emoji": "Vložiť emotikon",
|
||||||
|
"custom": "Vlastný emotikon",
|
||||||
|
"unicode": "Unicode emotikon",
|
||||||
|
"load_all_hint": "Nahralo sa prvých {saneAmount} emotikonov, nahranie všetkých by mohlo spôsobiť zníženie výkonu.",
|
||||||
|
"load_all": "Nahrať všetkých {emojiAmount} emotikonov"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"storage_unavailable": "Pleroma nemôže používať úložisko prehliadača. Tvoje prihlasovacie meno a lokálne nastavenia nebudú uchované a môžu sa vyskytnúť neočakávané chyby. Skús povoliť cookie."
|
||||||
|
},
|
||||||
|
"interactions": {
|
||||||
|
"favs_repeats": "Zopakovania a obľúbené",
|
||||||
|
"follows": "Nový nasledovatelia",
|
||||||
|
"moves": "Užívateľ sa sťahuje",
|
||||||
|
"load_older": "Nahrať staršiu komunikáciu"
|
||||||
|
},
|
||||||
|
"post_status": {
|
||||||
|
"new_status": "Poslať novú správu",
|
||||||
|
"account_not_locked_warning": "Tvoj účen nie je {0}. Ktokoľvek ťa môže začať nasledovať a tak vidieť správy určené len pre nasledovateľov.",
|
||||||
|
"account_not_locked_warning_link": "uzamknuté",
|
||||||
|
"attachments_sensitive": "Označiť prílohy ako citlivé",
|
||||||
|
"media_description": "Popis média",
|
||||||
|
"content_type": {
|
||||||
|
"text/plain": "Obyčajný text",
|
||||||
|
"text/html": "HTML",
|
||||||
|
"text/markdown": "Markdown",
|
||||||
|
"text/bbcode": "BBCode"
|
||||||
|
},
|
||||||
|
"content_warning": "Nadpis (nepovinné)",
|
||||||
|
"default": "Práve som ...",
|
||||||
|
"direct_warning_to_all": "Túto správu bude vidieť každý užívateľ, ktorého v nej spomenieš.",
|
||||||
|
"direct_warning_to_first_only": "Táto správa bude viditeľná len pre užívateľov, ktorých vymenuješ na začiatku správy.",
|
||||||
|
"posting": "Posielanie",
|
||||||
|
"post": "Poslať",
|
||||||
|
"preview": "Náhľad",
|
||||||
|
"preview_empty": "Prázdne",
|
||||||
|
"empty_status_error": "Nie je možné odoslať prázdnu správu bez priložených súborov",
|
||||||
|
"media_description_error": "Nepodarilo sa aktualizovať média, skús znova",
|
||||||
|
"scope_notice": {
|
||||||
|
"public": "Túto správu bude vidieť každý",
|
||||||
|
"private": "Túto správu budú vidieť len tvoji nasledovníci",
|
||||||
|
"unlisted": "Táto správa nebude viditeľná na verejnej časovej osi a v celej známej sieti"
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"direct": "Priama správa - zobrazí sa len užívateľom spomenutým v správe",
|
||||||
|
"private": "Pre nasledovníkov - zobrazí sa len tvojim nasledovníkom",
|
||||||
|
"public": "Verejné - zobrazí sa vo všetkých časových osiach",
|
||||||
|
"unlisted": "Nezaradené - nezobrazí sa v žiadnej časovej osy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"registration": {
|
||||||
|
"bio": "Životopis",
|
||||||
|
"email": "Email",
|
||||||
|
"fullname": "Zobrazované meno",
|
||||||
|
"password_confirm": "Potvrdenie hesla",
|
||||||
|
"registration": "Registrácia",
|
||||||
|
"token": "Pozývací kód",
|
||||||
|
"captcha": "CAPTCHA",
|
||||||
|
"new_captcha": "Klikni na obrázok a vnikne nová captcha",
|
||||||
|
"username_placeholder": "napr. peter",
|
||||||
|
"fullname_placeholder": "napr. Peter Kukurica",
|
||||||
|
"bio_placeholder": "e.g.\nHi, I'm Lain.\nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
|
||||||
|
"reason": "Dôvod registrácie",
|
||||||
|
"reason_placeholder": "Tento server schvaľuje registrácie manuálne.\nZanechaj správcom dôvod, prečo máš záujem vytvoriť si tu účet.",
|
||||||
|
"register": "Registrácia",
|
||||||
|
"validations": {
|
||||||
|
"username_required": "nemôže byť prázdne",
|
||||||
|
"fullname_required": "nemôže byť prázdne",
|
||||||
|
"email_required": "nemôže byť prázdne",
|
||||||
|
"password_required": "nemôže byť prázdne",
|
||||||
|
"password_confirmation_required": "nemôže byť prázdne",
|
||||||
|
"password_confirmation_match": "musí byť rovnaké ako heslo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remote_user_resolver": {
|
||||||
|
"remote_user_resolver": "Vzdialené overenie užívateľa",
|
||||||
|
"searching_for": "Hľadám...",
|
||||||
|
"error": "Nenájdené."
|
||||||
|
},
|
||||||
|
"selectable_list": {
|
||||||
|
"select_all": "Vybrať všetko"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"day": "{0} deň",
|
||||||
|
"days": "{0} dní",
|
||||||
|
"day_short": "{0}d",
|
||||||
|
"days_short": "{0}d",
|
||||||
|
"hour": "{0} hodina",
|
||||||
|
"hours": "{0} hodín",
|
||||||
|
"hour_short": "{0}h",
|
||||||
|
"hours_short": "{0}h",
|
||||||
|
"in_future": "za {0}",
|
||||||
|
"in_past": "pred {0}",
|
||||||
|
"minute": "{0} minúta",
|
||||||
|
"minutes": "{0} minút",
|
||||||
|
"minute_short": "{0}min",
|
||||||
|
"minutes_short": "{0}min",
|
||||||
|
"month": "{0} mesiac",
|
||||||
|
"months": "{0} mesiacov",
|
||||||
|
"month_short": "{0}mes",
|
||||||
|
"months_short": "{0}mes",
|
||||||
|
"now": "práve teraz",
|
||||||
|
"now_short": "teraz",
|
||||||
|
"second": "{0} sekunda",
|
||||||
|
"seconds": "{0} sekúnd",
|
||||||
|
"second_short": "{0}s",
|
||||||
|
"seconds_short": "{0}s",
|
||||||
|
"week": "{0} týždeň",
|
||||||
|
"weeks": "{0} týždňov",
|
||||||
|
"week_short": "{0}t",
|
||||||
|
"weeks_short": "{0}t",
|
||||||
|
"year": "{0} rok",
|
||||||
|
"years": "{0} rokov",
|
||||||
|
"year_short": "{0}r",
|
||||||
|
"years_short": "{0}r"
|
||||||
|
},
|
||||||
|
"timeline": {
|
||||||
|
"collapse": "Zbaliť",
|
||||||
|
"conversation": "Konverzácia",
|
||||||
|
"error": "Chyba pri nahrávaní časovej správy: {0}",
|
||||||
|
"load_older": "Nahrať staršie správy",
|
||||||
|
"no_retweet_hint": "Správa je označená ako len-pre-nasledovateľov alebo ako priama a nemôže byť zopakovaná na tvojej časovej osy.",
|
||||||
|
"repeated": "zopakované",
|
||||||
|
"show_new": "Zobraziť nové",
|
||||||
|
"reload": "Znovu nahrať",
|
||||||
|
"up_to_date": "Aktuálne",
|
||||||
|
"no_more_statuses": "Žiadne ďalšie správy",
|
||||||
|
"no_statuses": "Žiadne správy",
|
||||||
|
"socket_reconnected": "Prepojenie v reálnom čase bolo úspešne vytvorené",
|
||||||
|
"socket_broke": "Strata prepojenia v reálnom čase: chyba CloseEvent kód {0}"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"favorites": "Obľúbené",
|
||||||
|
"repeats": "Opakovania",
|
||||||
|
"delete": "Zmazať správu",
|
||||||
|
"pin": "Pripnúť na stránku užívateľa",
|
||||||
|
"unpin": "Odopnúť zo stránky užívateľa",
|
||||||
|
"pinned": "Pripnuté",
|
||||||
|
"bookmark": "Vytvoriť záložku",
|
||||||
|
"unbookmark": "Zmazať záložku",
|
||||||
|
"delete_confirm": "Skutočne chceš zmazať túto správu?",
|
||||||
|
"reply_to": "Odpovedať komu",
|
||||||
|
"mentions": "Spomenutia",
|
||||||
|
"replies_list": "Odpovede:",
|
||||||
|
"replies_list_with_others": "Odpoveď (+{numReplies} iný): | Odpoveď (+{numReplies} iných):",
|
||||||
|
"mute_conversation": "Stíšiť konverzáciu",
|
||||||
|
"unmute_conversation": "Oznamovať konverzáciu",
|
||||||
|
"status_unavailable": "Neznámy status",
|
||||||
|
"copy_link": "Skopírovať odkaz do správy",
|
||||||
|
"external_source": "Vzdialený zdroj",
|
||||||
|
"thread_muted": "Konverzácia stíšená",
|
||||||
|
"thread_muted_and_words": ", má slová:",
|
||||||
|
"show_full_subject": "Zobraziť celý nadpis",
|
||||||
|
"hide_full_subject": "Skry celý nadpis",
|
||||||
|
"show_content": "Zobraziť obsah",
|
||||||
|
"hide_content": "Skryť obsah",
|
||||||
|
"status_deleted": "Táto správa bola zmazaná",
|
||||||
|
"nsfw": "NSFW",
|
||||||
|
"expand": "Rozbaliť správu",
|
||||||
|
"you": "(ty)",
|
||||||
|
"plus_more": "+{number} ďalších",
|
||||||
|
"many_attachments": "Správa má {number} príloh",
|
||||||
|
"collapse_attachments": "Zabaliť médiá",
|
||||||
|
"show_all_attachments": "Zobraz všetky prílohy",
|
||||||
|
"show_attachment_in_modal": "Zobraz médiá modálne",
|
||||||
|
"show_attachment_description": "Náhľad popisku (otvor prílohu pre zobrazenie celého popisku)",
|
||||||
|
"hide_attachment": "Skryť prílohy",
|
||||||
|
"remove_attachment": "Odstrániť prílohy",
|
||||||
|
"attachment_stop_flash": "Zastaviť prehrávač Flashu",
|
||||||
|
"move_up": "Presuň prílohu doľava",
|
||||||
|
"move_down": "Presuň prílohu doprava",
|
||||||
|
"open_gallery": "Otvoriť galériu",
|
||||||
|
"thread_hide": "Skry túto konverzáciu",
|
||||||
|
"thread_show": "Zobraz túto konverzáciu",
|
||||||
|
"thread_show_full": "Zobraz všetko pod touto konverzáciou (celkovo {numStatus} správa, max hĺbka {depth}) | Zobraz všetko pod touto konverzáciou (celkovo {numStatus} správ, max hĺbka {depth})",
|
||||||
|
"thread_show_full_with_icon": "{icon} {text}",
|
||||||
|
"thread_follow": "Zobraz zvyšnú časť tejto konverzácie (celkovo {numStatus} správa) | Zobraz zvyšnú časť tejto konverzácie (celkovo {numStatus} správ)",
|
||||||
|
"thread_follow_with_icon": "{icon} {text}",
|
||||||
|
"ancestor_follow": "Pozri {numReplies} ďalšiu odpoveď pod touto správou | Pozri {numReplies} ďalších odpovedí pod touto správou",
|
||||||
|
"ancestor_follow_with_icon": "{icon} {text}",
|
||||||
|
"show_all_conversation_with_icon": "{icon} {text}",
|
||||||
|
"show_all_conversation": "Zobraz celú konverzáciu ({numStatus} iná správa) | Zobraz celú konverzáciu ({numStatus} iných správ)",
|
||||||
|
"show_only_conversation_under_this": "Zobraz len správy súvisiace s touto správou"
|
||||||
|
},
|
||||||
|
"user_card": {
|
||||||
|
"approve": "Schváliť",
|
||||||
|
"block": "Zablokovať",
|
||||||
|
"blocked": "Blokované!",
|
||||||
|
"deactivated": "Neaktívne",
|
||||||
|
"deny": "Zakázané",
|
||||||
|
"edit_profile": "Uraviť profil",
|
||||||
|
"favorites": "Obľúbené",
|
||||||
|
"follow": "Nasledovať",
|
||||||
|
"follow_cancel": "Požiadavka zrušená",
|
||||||
|
"follow_sent": "Požiadavka zaslaná!",
|
||||||
|
"follow_progress": "Žiadam o povolenie…",
|
||||||
|
"follow_unfollow": "Prestať sledovať",
|
||||||
|
"followees": "Nasleduje",
|
||||||
|
"followers": "Nasledovatelia",
|
||||||
|
"following": "Nasleduješ!",
|
||||||
|
"follows_you": "Nasleduje teba!",
|
||||||
|
"hidden": "Skryté",
|
||||||
|
"its_you": "To si ty!",
|
||||||
|
"media": "Média",
|
||||||
|
"mention": "Spomenul",
|
||||||
|
"message": "Správa",
|
||||||
|
"mute": "Stíšiť",
|
||||||
|
"muted": "Stíšené",
|
||||||
|
"per_day": "za deň",
|
||||||
|
"remote_follow": "Nasledovanie z ďaleka",
|
||||||
|
"report": "Nahlásiť",
|
||||||
|
"statuses": "Vytvorených správ",
|
||||||
|
"subscribe": "Prihlásiť k odberu",
|
||||||
|
"unsubscribe": "Odhlásiť z odberu",
|
||||||
|
"unblock": "Odblokovať",
|
||||||
|
"unblock_progress": "Oblokováva sa…",
|
||||||
|
"block_progress": "Blokujem…",
|
||||||
|
"unmute": "Povoliť oznamy",
|
||||||
|
"unmute_progress": "Povoľujem oznamy…",
|
||||||
|
"mute_progress": "Stišujem…",
|
||||||
|
"hide_repeats": "Skry zopakovania",
|
||||||
|
"show_repeats": "Zobraz zopakovania",
|
||||||
|
"bot": "Robot",
|
||||||
|
"admin_menu": {
|
||||||
|
"moderation": "Moderovanie",
|
||||||
|
"grant_admin": "Povoliť spravovanie",
|
||||||
|
"revoke_admin": "Zakázať spravovanie",
|
||||||
|
"grant_moderator": "Povoliť moderovanie",
|
||||||
|
"revoke_moderator": "Zakázať moderovanie",
|
||||||
|
"activate_account": "Aktivovať účet",
|
||||||
|
"deactivate_account": "Deaktivovať účet",
|
||||||
|
"delete_account": "Zmazať účet",
|
||||||
|
"force_nsfw": "Označ všetky správy ako NSFW",
|
||||||
|
"strip_media": "Odstrániť média zo správy",
|
||||||
|
"force_unlisted": "Vynúť, aby správy neboli zobrazované",
|
||||||
|
"sandbox": "Vynúť, aby správy boli len pre nasledovateľov",
|
||||||
|
"disable_remote_subscription": "Odstrániť prístup k serveru nasledovnému vzdialenému užívateľovi",
|
||||||
|
"disable_any_subscription": "Zakázať nasledovanie užívateľov",
|
||||||
|
"quarantine": "Zakázať federáciu správ užívateľa",
|
||||||
|
"delete_user": "Zmazať užívateľa",
|
||||||
|
"delete_user_confirmation": "Si si úplne istý? Táto akcia sa nedá zobrať späť."
|
||||||
|
},
|
||||||
|
"highlight": {
|
||||||
|
"disabled": "Bez zvýraznenia",
|
||||||
|
"solid": "Jednoliate pozadie",
|
||||||
|
"striped": "Šrafované pozadie",
|
||||||
|
"side": "Pásik na boku"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user_profile": {
|
||||||
|
"timeline_title": "Časová os užívateľa",
|
||||||
|
"profile_does_not_exist": "Prepáč, tento profil neexistuje.",
|
||||||
|
"profile_loading_error": "Prepáč, nastala chyba pri nahrávaní profilu."
|
||||||
|
},
|
||||||
|
"user_reporting": {
|
||||||
|
"title": "Nahlásení {0}",
|
||||||
|
"add_comment_description": "Hlásnenie bude zaslané moderátorom servera. Nižšie môžeš napísať dôvod prečo tento účet nahlasuješ:",
|
||||||
|
"additional_comments": "Ďalšie poznámky",
|
||||||
|
"forward_description": "Účet je z iného servera. Poslať kópiu tohto hlásenia aj tam?",
|
||||||
|
"forward_to": "Preposlať komu {0}",
|
||||||
|
"submit": "Odoslať",
|
||||||
|
"generic_error": "Nastala chyba pri vykonaní tvojej požiadavky."
|
||||||
|
},
|
||||||
|
"who_to_follow": {
|
||||||
|
"more": "Viac",
|
||||||
|
"who_to_follow": "Koho nasledovať"
|
||||||
|
},
|
||||||
|
"tool_tip": {
|
||||||
|
"media_upload": "Nahrať médium",
|
||||||
|
"repeat": "Zopakovať",
|
||||||
|
"reply": "Odpovedať",
|
||||||
|
"favorite": "Obľúbené",
|
||||||
|
"add_reaction": "Reagovať",
|
||||||
|
"user_settings": "Nastavenia užívateľa",
|
||||||
|
"accept_follow_request": "Prijať požiadavku nasledovníka",
|
||||||
|
"reject_follow_request": "Odmietnuť požiadavku nasledovníka",
|
||||||
|
"bookmark": "Záložka"
|
||||||
|
},
|
||||||
|
"upload": {
|
||||||
|
"error": {
|
||||||
|
"base": "Nahrávanie bolo neúspešné.",
|
||||||
|
"message": "Nahrávanie bolo neúspešné: {0}",
|
||||||
|
"file_too_big": "Súbor je príliš veľký [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]",
|
||||||
|
"default": "Vyskúšaj opäť neskôr"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"people": "Ľudia",
|
||||||
|
"hashtags": "Haštagy",
|
||||||
|
"person_talking": "{count} človek hovorí",
|
||||||
|
"people_talking": "{count} ľudí hovorí",
|
||||||
|
"no_results": "Žiadne výsledky"
|
||||||
|
},
|
||||||
|
"password_reset": {
|
||||||
|
"forgot_password": "Zabudol si heslo?",
|
||||||
|
"password_reset": "Obnovenie hesla",
|
||||||
|
"instruction": "Zadaj svoju emailovú adresu alebo užívateľské meno. Pošleme ti odkaz pomocou, ktorého môžeš obnoviť svoje heslo.",
|
||||||
|
"placeholder": "Tvoj email alebo užívateľské meno",
|
||||||
|
"check_email": "V novom emaile ti bol doručený odkaz na spôsob, ako obnovíš svoje heslo.",
|
||||||
|
"return_home": "Návrat na domácu stránku",
|
||||||
|
"too_many_requests": "Prekročil si limit pokusov, skús znova neskôr.",
|
||||||
|
"password_reset_disabled": "Obnova hesla je vypnutá. Kontaktuj, prosím, správcu tohto servera.",
|
||||||
|
"password_reset_required": "Musíš najskôr obnoviť heslo, ak sa chceš prihlásiť.",
|
||||||
|
"password_reset_required_but_mailer_is_disabled": "Musíš obnoviť svoje heslo, ale obnova hesla je na serveri vypnutá. Kontaktuj, prosím, správcu tohto servera."
|
||||||
|
},
|
||||||
|
"chats": {
|
||||||
|
"you": "Ty:",
|
||||||
|
"message_user": "Správa {nickname}",
|
||||||
|
"delete": "Zmazať",
|
||||||
|
"chats": "Rozhovor",
|
||||||
|
"new": "Nový rozhovor",
|
||||||
|
"empty_message_error": "Nie je možné odoslať prázdnu správu",
|
||||||
|
"more": "Viac",
|
||||||
|
"delete_confirm": "Skutočne chceš zmazať túto správu?",
|
||||||
|
"error_loading_chat": "Nastala chyba pri nahrávaní rozhovoru.",
|
||||||
|
"error_sending_message": "Nastala chyba pri odosielaní správ.",
|
||||||
|
"empty_chat_list_placeholder": "Nemáš za sebou žiadne rozhovory. Začni nový rozhovor!"
|
||||||
|
},
|
||||||
|
"file_type": {
|
||||||
|
"audio": "Audio",
|
||||||
|
"video": "Video",
|
||||||
|
"image": "Obrázok",
|
||||||
|
"file": "Súbor"
|
||||||
|
},
|
||||||
|
"display_date": {
|
||||||
|
"today": "Dnes"
|
||||||
|
}
|
||||||
|
}
|
|
@ -755,7 +755,6 @@
|
||||||
"deactivate_account": "Деактивувати обліковий запис",
|
"deactivate_account": "Деактивувати обліковий запис",
|
||||||
"delete_account": "Видалити обліковий запис",
|
"delete_account": "Видалити обліковий запис",
|
||||||
"moderation": "Модерація",
|
"moderation": "Модерація",
|
||||||
"delete_user_confirmation": "Ви абсолютно впевнені? Цю дію неможливо буде скасовувати.",
|
|
||||||
"delete_user": "Видалити обліковий запис",
|
"delete_user": "Видалити обліковий запис",
|
||||||
"strip_media": "Вилучити медіа з дописів користувача",
|
"strip_media": "Вилучити медіа з дописів користувача",
|
||||||
"force_nsfw": "Позначити всі дописи як NSFW",
|
"force_nsfw": "Позначити всі дописи як NSFW",
|
||||||
|
|
|
@ -772,8 +772,7 @@
|
||||||
"quarantine": "Không cho phép tút liên hợp",
|
"quarantine": "Không cho phép tút liên hợp",
|
||||||
"delete_user": "Xóa người dùng",
|
"delete_user": "Xóa người dùng",
|
||||||
"revoke_moderator": "Gỡ bỏ Quản trị viên",
|
"revoke_moderator": "Gỡ bỏ Quản trị viên",
|
||||||
"force_unlisted": "Đánh dấu tất cả tút là hạn chế",
|
"force_unlisted": "Đánh dấu tất cả tút là hạn chế"
|
||||||
"delete_user_confirmation": "Bạn chắc chắn chưa? Hành động này không thể phục hồi."
|
|
||||||
},
|
},
|
||||||
"highlight": {
|
"highlight": {
|
||||||
"disabled": "Không nổi bật",
|
"disabled": "Không nổi bật",
|
||||||
|
|
|
@ -714,8 +714,7 @@
|
||||||
"disable_remote_subscription": "禁止从远程实例关注用户",
|
"disable_remote_subscription": "禁止从远程实例关注用户",
|
||||||
"disable_any_subscription": "完全禁止关注用户",
|
"disable_any_subscription": "完全禁止关注用户",
|
||||||
"quarantine": "从联合实例中禁止用户帖子",
|
"quarantine": "从联合实例中禁止用户帖子",
|
||||||
"delete_user": "删除用户",
|
"delete_user": "删除用户"
|
||||||
"delete_user_confirmation": "你确定吗?此操作无法撤销。"
|
|
||||||
},
|
},
|
||||||
"hidden": "已隐藏",
|
"hidden": "已隐藏",
|
||||||
"show_repeats": "显示转发",
|
"show_repeats": "显示转发",
|
||||||
|
|
|
@ -747,7 +747,6 @@
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"delete_account": "刪除賬號",
|
"delete_account": "刪除賬號",
|
||||||
"delete_user": "刪除用戶",
|
"delete_user": "刪除用戶",
|
||||||
"delete_user_confirmation": "你確認嗎?此操作無法撤銷。",
|
|
||||||
"moderation": "調停",
|
"moderation": "調停",
|
||||||
"grant_admin": "賦予管理權限",
|
"grant_admin": "賦予管理權限",
|
||||||
"revoke_admin": "撤銷管理權限",
|
"revoke_admin": "撤銷管理權限",
|
||||||
|
|
|
@ -20,6 +20,7 @@ import reportsModule from './modules/reports.js'
|
||||||
import pollsModule from './modules/polls.js'
|
import pollsModule from './modules/polls.js'
|
||||||
import postStatusModule from './modules/postStatus.js'
|
import postStatusModule from './modules/postStatus.js'
|
||||||
import chatsModule from './modules/chats.js'
|
import chatsModule from './modules/chats.js'
|
||||||
|
import announcementsModule from './modules/announcements.js'
|
||||||
|
|
||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
@ -83,7 +84,8 @@ const persistedStateOptions = {
|
||||||
reports: reportsModule,
|
reports: reportsModule,
|
||||||
polls: pollsModule,
|
polls: pollsModule,
|
||||||
postStatus: postStatusModule,
|
postStatus: postStatusModule,
|
||||||
chats: chatsModule
|
chats: chatsModule,
|
||||||
|
announcements: announcementsModule
|
||||||
},
|
},
|
||||||
plugins,
|
plugins,
|
||||||
strict: false // Socket modifies itself, let's ignore this for now.
|
strict: false // Socket modifies itself, let's ignore this for now.
|
||||||
|
|
118
src/modules/announcements.js
Normal file
118
src/modules/announcements.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
announcements: [],
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
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
|
|
@ -163,6 +163,7 @@ const api = {
|
||||||
dispatch('startFetchingTimeline', { timeline: 'friends' })
|
dispatch('startFetchingTimeline', { timeline: 'friends' })
|
||||||
dispatch('startFetchingNotifications')
|
dispatch('startFetchingNotifications')
|
||||||
dispatch('startFetchingChats')
|
dispatch('startFetchingChats')
|
||||||
|
dispatch('startFetchingAnnouncements')
|
||||||
dispatch('pushGlobalNotice', {
|
dispatch('pushGlobalNotice', {
|
||||||
level: 'error',
|
level: 'error',
|
||||||
messageKey: 'timeline.socket_broke',
|
messageKey: 'timeline.socket_broke',
|
||||||
|
@ -261,6 +262,18 @@ const api = {
|
||||||
store.commit('removeFetcher', { fetcherName: 'lists', fetcher })
|
store.commit('removeFetcher', { fetcherName: 'lists', fetcher })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Lists
|
||||||
|
startFetchingAnnouncements (store) {
|
||||||
|
if (store.state.fetchers['announcements']) return
|
||||||
|
const fetcher = store.state.backendInteractor.startFetchingAnnouncements({ store })
|
||||||
|
store.commit('addFetcher', { fetcherName: 'announcements', fetcher })
|
||||||
|
},
|
||||||
|
stopFetchingAnnouncements (store) {
|
||||||
|
const fetcher = store.state.fetchers.announcements
|
||||||
|
if (!fetcher) return
|
||||||
|
store.commit('removeFetcher', { fetcherName: 'announcements', fetcher })
|
||||||
|
},
|
||||||
|
|
||||||
// Pleroma websocket
|
// Pleroma websocket
|
||||||
setWsToken (store, token) {
|
setWsToken (store, token) {
|
||||||
store.commit('setWsToken', token)
|
store.commit('setWsToken', token)
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import apiService from '../api/api.service.js'
|
||||||
|
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
||||||
|
|
||||||
|
const fetchAndUpdate = ({ store, credentials }) => {
|
||||||
|
return apiService.fetchAnnouncements({ credentials })
|
||||||
|
.then(announcements => {
|
||||||
|
store.commit('setAnnouncements', announcements)
|
||||||
|
}, () => {})
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
const startFetching = ({ credentials, store }) => {
|
||||||
|
const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
|
||||||
|
boundFetchAndUpdate()
|
||||||
|
return promiseInterval(boundFetchAndUpdate, 60000)
|
||||||
|
}
|
||||||
|
|
||||||
|
const announcementsFetcher = {
|
||||||
|
startFetching
|
||||||
|
}
|
||||||
|
|
||||||
|
export default announcementsFetcher
|
|
@ -87,6 +87,8 @@ const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
||||||
const MASTODON_LISTS_URL = '/api/v1/lists'
|
const MASTODON_LISTS_URL = '/api/v1/lists'
|
||||||
const MASTODON_STREAMING = '/api/v1/streaming'
|
const MASTODON_STREAMING = '/api/v1/streaming'
|
||||||
const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
|
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_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_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}`
|
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
|
@ -95,6 +97,11 @@ const PLEROMA_CHAT_URL = id => `/api/v1/pleroma/chats/by-account-id/${id}`
|
||||||
const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
|
const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
|
||||||
const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
|
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_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => `/api/v1/pleroma/chats/${chatId}/messages/${messageId}`
|
||||||
|
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_EDIT_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
|
||||||
|
const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
|
||||||
|
|
||||||
const oldfetch = window.fetch
|
const oldfetch = window.fetch
|
||||||
|
|
||||||
|
@ -1054,6 +1061,25 @@ const fetchBlocks = ({ credentials }) => {
|
||||||
.then((users) => users.map(parseUser))
|
.then((users) => users.map(parseUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addBackup = ({ credentials }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: PLEROMA_BACKUP_URL,
|
||||||
|
method: 'POST',
|
||||||
|
credentials
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const listBackups = ({ credentials }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: PLEROMA_BACKUP_URL,
|
||||||
|
method: 'GET',
|
||||||
|
credentials,
|
||||||
|
params: {
|
||||||
|
_cacheBooster: (new Date()).getTime()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const fetchOAuthTokens = ({ credentials }) => {
|
const fetchOAuthTokens = ({ credentials }) => {
|
||||||
const url = '/api/oauth_tokens.json'
|
const url = '/api/oauth_tokens.json'
|
||||||
|
|
||||||
|
@ -1271,6 +1297,66 @@ const dismissNotification = ({ credentials, id }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const adminFetchAnnouncements = ({ credentials }) => {
|
||||||
|
return promisedRequest({ url: PLEROMA_ANNOUNCEMENTS_URL, credentials })
|
||||||
|
}
|
||||||
|
|
||||||
|
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'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const announcementToPayload = ({ content, startsAt, endsAt, allDay }) => {
|
||||||
|
const payload = { content }
|
||||||
|
|
||||||
|
if (typeof startsAt !== 'undefined') {
|
||||||
|
payload['starts_at'] = startsAt ? new Date(startsAt).toISOString() : null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof endsAt !== 'undefined') {
|
||||||
|
payload['ends_at'] = endsAt ? new Date(endsAt).toISOString() : null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof allDay !== 'undefined') {
|
||||||
|
payload['all_day'] = allDay
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
|
||||||
|
const postAnnouncement = ({ credentials, content, startsAt, endsAt, allDay }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: PLEROMA_POST_ANNOUNCEMENT_URL,
|
||||||
|
credentials,
|
||||||
|
method: 'POST',
|
||||||
|
payload: announcementToPayload({ content, startsAt, endsAt, allDay })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const editAnnouncement = ({ id, credentials, content, startsAt, endsAt, allDay }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: PLEROMA_EDIT_ANNOUNCEMENT_URL(id),
|
||||||
|
credentials,
|
||||||
|
method: 'PATCH',
|
||||||
|
payload: announcementToPayload({ 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 = {} }) => {
|
export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => {
|
||||||
return Object.entries({
|
return Object.entries({
|
||||||
...(credentials
|
...(credentials
|
||||||
|
@ -1520,6 +1606,8 @@ const apiService = {
|
||||||
generateMfaBackupCodes,
|
generateMfaBackupCodes,
|
||||||
mfaSetupOTP,
|
mfaSetupOTP,
|
||||||
mfaConfirmOTP,
|
mfaConfirmOTP,
|
||||||
|
addBackup,
|
||||||
|
listBackups,
|
||||||
fetchFollowRequests,
|
fetchFollowRequests,
|
||||||
fetchLists,
|
fetchLists,
|
||||||
createList,
|
createList,
|
||||||
|
@ -1556,7 +1644,13 @@ const apiService = {
|
||||||
chatMessages,
|
chatMessages,
|
||||||
sendChatMessage,
|
sendChatMessage,
|
||||||
readChat,
|
readChat,
|
||||||
deleteChatMessage
|
deleteChatMessage,
|
||||||
|
fetchAnnouncements,
|
||||||
|
dismissAnnouncement,
|
||||||
|
postAnnouncement,
|
||||||
|
editAnnouncement,
|
||||||
|
deleteAnnouncement,
|
||||||
|
adminFetchAnnouncements
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apiService
|
export default apiService
|
||||||
|
|
|
@ -3,6 +3,7 @@ import timelineFetcher from '../timeline_fetcher/timeline_fetcher.service.js'
|
||||||
import notificationsFetcher from '../notifications_fetcher/notifications_fetcher.service.js'
|
import notificationsFetcher from '../notifications_fetcher/notifications_fetcher.service.js'
|
||||||
import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
|
import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
|
||||||
import listsFetcher from '../../services/lists_fetcher/lists_fetcher.service.js'
|
import listsFetcher from '../../services/lists_fetcher/lists_fetcher.service.js'
|
||||||
|
import announcementsFetcher from '../../services/announcements_fetcher/announcements_fetcher.service.js'
|
||||||
|
|
||||||
const backendInteractorService = credentials => ({
|
const backendInteractorService = credentials => ({
|
||||||
startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) {
|
startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) {
|
||||||
|
@ -29,6 +30,10 @@ const backendInteractorService = credentials => ({
|
||||||
return listsFetcher.startFetching({ store, credentials })
|
return listsFetcher.startFetching({ store, credentials })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
startFetchingAnnouncements ({ store }) {
|
||||||
|
return announcementsFetcher.startFetching({ store, credentials })
|
||||||
|
},
|
||||||
|
|
||||||
startUserSocket ({ store }) {
|
startUserSocket ({ store }) {
|
||||||
const serv = store.rootState.instance.server.replace('http', 'ws')
|
const serv = store.rootState.instance.server.replace('http', 'ws')
|
||||||
const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
|
const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
|
||||||
|
|
|
@ -10,31 +10,29 @@ export const relativeTime = (date, nowThreshold = 1) => {
|
||||||
if (typeof date === 'string') date = Date.parse(date)
|
if (typeof date === 'string') date = Date.parse(date)
|
||||||
const round = Date.now() > date ? Math.floor : Math.ceil
|
const round = Date.now() > date ? Math.floor : Math.ceil
|
||||||
const d = Math.abs(Date.now() - date)
|
const d = Math.abs(Date.now() - date)
|
||||||
let r = { num: round(d / YEAR), key: 'time.years' }
|
let r = { num: round(d / YEAR), key: 'time.unit.years' }
|
||||||
if (d < nowThreshold * SECOND) {
|
if (d < nowThreshold * SECOND) {
|
||||||
r.num = 0
|
r.num = 0
|
||||||
r.key = 'time.now'
|
r.key = 'time.now'
|
||||||
} else if (d < MINUTE) {
|
} else if (d < MINUTE) {
|
||||||
r.num = round(d / SECOND)
|
r.num = round(d / SECOND)
|
||||||
r.key = 'time.seconds'
|
r.key = 'time.unit.seconds'
|
||||||
} else if (d < HOUR) {
|
} else if (d < HOUR) {
|
||||||
r.num = round(d / MINUTE)
|
r.num = round(d / MINUTE)
|
||||||
r.key = 'time.minutes'
|
r.key = 'time.unit.minutes'
|
||||||
} else if (d < DAY) {
|
} else if (d < DAY) {
|
||||||
r.num = round(d / HOUR)
|
r.num = round(d / HOUR)
|
||||||
r.key = 'time.hours'
|
r.key = 'time.unit.hours'
|
||||||
} else if (d < WEEK) {
|
} else if (d < WEEK) {
|
||||||
r.num = round(d / DAY)
|
r.num = round(d / DAY)
|
||||||
r.key = 'time.days'
|
r.key = 'time.unit.days'
|
||||||
} else if (d < MONTH) {
|
} else if (d < MONTH) {
|
||||||
r.num = round(d / WEEK)
|
r.num = round(d / WEEK)
|
||||||
r.key = 'time.weeks'
|
r.key = 'time.unit.weeks'
|
||||||
} else if (d < YEAR) {
|
} else if (d < YEAR) {
|
||||||
r.num = round(d / MONTH)
|
r.num = round(d / MONTH)
|
||||||
r.key = 'time.months'
|
r.key = 'time.unit.months'
|
||||||
}
|
}
|
||||||
// Remove plural form when singular
|
|
||||||
if (r.num === 1) r.key = r.key.slice(0, -1)
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,30 +11,30 @@ describe('DateUtils', () => {
|
||||||
|
|
||||||
it('rounds down for past', () => {
|
it('rounds down for past', () => {
|
||||||
const time = Date.now() - 1.8 * DateUtils.HOUR
|
const time = Date.now() - 1.8 * DateUtils.HOUR
|
||||||
expect(DateUtils.relativeTime(time)).to.eql({ num: 1, key: 'time.hour' })
|
expect(DateUtils.relativeTime(time)).to.eql({ num: 1, key: 'time.unit.hours' })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rounds up for future', () => {
|
it('rounds up for future', () => {
|
||||||
const time = Date.now() + 1.8 * DateUtils.HOUR
|
const time = Date.now() + 1.8 * DateUtils.HOUR
|
||||||
expect(DateUtils.relativeTime(time)).to.eql({ num: 2, key: 'time.hours' })
|
expect(DateUtils.relativeTime(time)).to.eql({ num: 2, key: 'time.unit.hours' })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('uses plural when necessary', () => {
|
it('uses plural when necessary', () => {
|
||||||
const time = Date.now() - 3.8 * DateUtils.WEEK
|
const time = Date.now() - 3.8 * DateUtils.WEEK
|
||||||
expect(DateUtils.relativeTime(time)).to.eql({ num: 3, key: 'time.weeks' })
|
expect(DateUtils.relativeTime(time)).to.eql({ num: 3, key: 'time.unit.weeks' })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('works with date string', () => {
|
it('works with date string', () => {
|
||||||
const time = Date.now() - 4 * DateUtils.MONTH
|
const time = Date.now() - 4 * DateUtils.MONTH
|
||||||
const dateString = new Date(time).toISOString()
|
const dateString = new Date(time).toISOString()
|
||||||
expect(DateUtils.relativeTime(dateString)).to.eql({ num: 4, key: 'time.months' })
|
expect(DateUtils.relativeTime(dateString)).to.eql({ num: 4, key: 'time.unit.months' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('relativeTimeShort', () => {
|
describe('relativeTimeShort', () => {
|
||||||
it('returns the short version of the same relative time', () => {
|
it('returns the short version of the same relative time', () => {
|
||||||
const time = Date.now() + 2 * DateUtils.YEAR
|
const time = Date.now() + 2 * DateUtils.YEAR
|
||||||
expect(DateUtils.relativeTimeShort(time)).to.eql({ num: 2, key: 'time.years_short' })
|
expect(DateUtils.relativeTimeShort(time)).to.eql({ num: 2, key: 'time.unit.years_short' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
131
yarn.lock
131
yarn.lock
|
@ -1132,10 +1132,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@fortawesome/fontawesome-common-types" "^0.2.36"
|
"@fortawesome/fontawesome-common-types" "^0.2.36"
|
||||||
|
|
||||||
"@fortawesome/vue-fontawesome@3.0.0-5":
|
"@fortawesome/vue-fontawesome@3.0.1":
|
||||||
version "3.0.0-5"
|
version "3.0.1"
|
||||||
resolved "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.0-5.tgz"
|
resolved "https://registry.yarnpkg.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.1.tgz#ced35cefc52b364f7db973f2fe9f50c3dd160715"
|
||||||
integrity sha512-aNmBT4bOecrFsZTog1l6AJDQHPP3ocXV+WQ3Ogy8WZCqstB/ahfhH4CPu5i4N9Hw0MBKXqE+LX+NbUxcj8cVTw==
|
integrity sha512-CdXZJoCS+aEPec26ZP7hWWU3SaJlQPZSCGdgpQ2qGl2HUmtUUNrI3zC4XWdn1JUmh3t5OuDeRG1qB4eGRNSD4A==
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.9.2":
|
"@humanwhocodes/config-array@^0.9.2":
|
||||||
version "0.9.5"
|
version "0.9.5"
|
||||||
|
@ -1903,17 +1903,17 @@
|
||||||
resolved "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.0.0-rc.17.tgz"
|
resolved "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.0.0-rc.17.tgz"
|
||||||
integrity sha512-7LHZKsFRV/HqDoMVY+cJamFzgHgsrmQFalROHC5FMWrzPzd+utG5e11krj1tVsnxYufGA2ABShX4nlcHXED+zQ==
|
integrity sha512-7LHZKsFRV/HqDoMVY+cJamFzgHgsrmQFalROHC5FMWrzPzd+utG5e11krj1tVsnxYufGA2ABShX4nlcHXED+zQ==
|
||||||
|
|
||||||
"@vuelidate/core@2.0.0-alpha.41":
|
"@vuelidate/core@2.0.0-alpha.42":
|
||||||
version "2.0.0-alpha.41"
|
version "2.0.0-alpha.42"
|
||||||
resolved "https://registry.npmjs.org/@vuelidate/core/-/core-2.0.0-alpha.41.tgz"
|
resolved "https://registry.yarnpkg.com/@vuelidate/core/-/core-2.0.0-alpha.42.tgz#f8b4b7c112af374d3f37e38bff34f8bc2da21c5e"
|
||||||
integrity sha512-fST7s5wiLW8ZNTexe8+7fDdBZYT7HjbuA43/XDtKTlHs1BMRDDaBoFLZbHSqmHisQvGXa7zLG9bvG8X5cHZaxg==
|
integrity sha512-yLp5/5IkwNZP8214TqEuexlFLGoEZybEad2OZu/heOYPnERm6tgiWHZltc0USCuQ1JVZ2EJuPRHmqMl/G/N7tw==
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi "^0.12.0"
|
vue-demi "^0.12.0"
|
||||||
|
|
||||||
"@vuelidate/validators@2.0.0-alpha.27":
|
"@vuelidate/validators@2.0.0-alpha.30":
|
||||||
version "2.0.0-alpha.27"
|
version "2.0.0-alpha.30"
|
||||||
resolved "https://registry.npmjs.org/@vuelidate/validators/-/validators-2.0.0-alpha.27.tgz"
|
resolved "https://registry.yarnpkg.com/@vuelidate/validators/-/validators-2.0.0-alpha.30.tgz#978e676b5b5dc160e6a83fdf8c1bf26052f46e88"
|
||||||
integrity sha512-omCUVP+gr2kKBMQwdKsOYPWYk/Fu92K93LRnl8Vk856UudNlb89wCreh0/Q8DpVEOisLljI3T7026QCo9eSq4Q==
|
integrity sha512-XH0oIU1+6bTZ1Kd1RNf7AMDsAahj1hUjLhbFUIrDhKIUKMFvG4658pqYATePNqhAegENFA+RDAPhsDXV/MB2wQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi "^0.12.0"
|
vue-demi "^0.12.0"
|
||||||
|
|
||||||
|
@ -2181,9 +2181,10 @@ ansi-escapes@^4.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.21.3"
|
type-fest "^0.21.3"
|
||||||
|
|
||||||
ansi-html@0.0.7:
|
ansi-html-community@0.0.8:
|
||||||
version "0.0.7"
|
version "0.0.8"
|
||||||
resolved "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz"
|
resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
|
||||||
|
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
|
||||||
|
|
||||||
ansi-regex@^2.0.0:
|
ansi-regex@^2.0.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
|
@ -3143,23 +3144,20 @@ chardet@^0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz"
|
resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz"
|
||||||
|
|
||||||
chokidar@^2.0.0:
|
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1:
|
||||||
version "2.1.6"
|
version "3.5.3"
|
||||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||||
|
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||||
dependencies:
|
dependencies:
|
||||||
anymatch "^2.0.0"
|
anymatch "~3.1.2"
|
||||||
async-each "^1.0.1"
|
braces "~3.0.2"
|
||||||
braces "^2.3.2"
|
glob-parent "~5.1.2"
|
||||||
glob-parent "^3.1.0"
|
is-binary-path "~2.1.0"
|
||||||
inherits "^2.0.3"
|
is-glob "~4.0.1"
|
||||||
is-binary-path "^1.0.0"
|
normalize-path "~3.0.0"
|
||||||
is-glob "^4.0.0"
|
readdirp "~3.6.0"
|
||||||
normalize-path "^3.0.0"
|
|
||||||
path-is-absolute "^1.0.0"
|
|
||||||
readdirp "^2.2.1"
|
|
||||||
upath "^1.1.1"
|
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "^1.2.7"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
chokidar@^2.1.8:
|
chokidar@^2.1.8:
|
||||||
version "2.1.8"
|
version "2.1.8"
|
||||||
|
@ -3195,21 +3193,6 @@ chokidar@^3.4.1:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.1"
|
fsevents "~2.3.1"
|
||||||
|
|
||||||
chokidar@^3.5.1:
|
|
||||||
version "3.5.3"
|
|
||||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
|
|
||||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
|
||||||
dependencies:
|
|
||||||
anymatch "~3.1.2"
|
|
||||||
braces "~3.0.2"
|
|
||||||
glob-parent "~5.1.2"
|
|
||||||
is-binary-path "~2.1.0"
|
|
||||||
is-glob "~4.0.1"
|
|
||||||
normalize-path "~3.0.0"
|
|
||||||
readdirp "~3.6.0"
|
|
||||||
optionalDependencies:
|
|
||||||
fsevents "~2.3.2"
|
|
||||||
|
|
||||||
chownr@^1.1.1:
|
chownr@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz"
|
resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz"
|
||||||
|
@ -5510,9 +5493,10 @@ html-comment-regex@^1.1.0:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz"
|
resolved "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz"
|
||||||
|
|
||||||
html-entities@^1.2.0:
|
html-entities@^2.1.0:
|
||||||
version "1.2.1"
|
version "2.3.3"
|
||||||
resolved "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz"
|
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
|
||||||
|
integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
|
||||||
|
|
||||||
html-escaper@^2.0.0:
|
html-escaper@^2.0.0:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
|
@ -5691,6 +5675,11 @@ immediate@~3.0.5:
|
||||||
version "3.0.6"
|
version "3.0.6"
|
||||||
resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz"
|
resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz"
|
||||||
|
|
||||||
|
immutable@^4.0.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||||
|
integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==
|
||||||
|
|
||||||
import-cwd@^2.0.0:
|
import-cwd@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz"
|
resolved "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz"
|
||||||
|
@ -6221,10 +6210,10 @@ isexe@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
|
||||||
|
|
||||||
iso-639-1@2.1.13:
|
iso-639-1@2.1.15:
|
||||||
version "2.1.13"
|
version "2.1.15"
|
||||||
resolved "https://registry.npmjs.org/iso-639-1/-/iso-639-1-2.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/iso-639-1/-/iso-639-1-2.1.15.tgz#20cf78a4f691aeb802c16f17a6bad7d99271e85d"
|
||||||
integrity sha512-stYt3u6OnVDNcK4IWARGXmTOOY5Wa5g4bUmBsttZp/55ZiEjDUibR3C59ZnorKoSS0tfJmFuGMST3ksnY1zu7Q==
|
integrity sha512-7c7mBznZu2ktfvyT582E2msM+Udc1EjOyhVRE/0ZsjD9LBtWSm23h3PtiRh2a35XoUsTQQjJXaJzuLjXsOdFDg==
|
||||||
|
|
||||||
isobject@^2.0.0:
|
isobject@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
|
@ -9648,23 +9637,25 @@ samsam@1.x, samsam@^1.1.3:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz"
|
resolved "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz"
|
||||||
|
|
||||||
sass-loader@7.2.0:
|
sass-loader@7.3.1:
|
||||||
version "7.2.0"
|
version "7.3.1"
|
||||||
resolved "https://registry.npmjs.org/sass-loader/-/sass-loader-7.2.0.tgz"
|
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.3.1.tgz#a5bf68a04bcea1c13ff842d747150f7ab7d0d23f"
|
||||||
integrity sha512-h8yUWaWtsbuIiOCgR9fd9c2lRXZ2uG+h8Dzg/AGNj+Hg/3TO8+BBAW9mEP+mh8ei+qBKqSJ0F1FLlYjNBc61OA==
|
integrity sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA==
|
||||||
dependencies:
|
dependencies:
|
||||||
clone-deep "^4.0.1"
|
clone-deep "^4.0.1"
|
||||||
loader-utils "^1.0.1"
|
loader-utils "^1.0.1"
|
||||||
neo-async "^2.5.0"
|
neo-async "^2.5.0"
|
||||||
pify "^4.0.1"
|
pify "^4.0.1"
|
||||||
semver "^5.5.0"
|
semver "^6.3.0"
|
||||||
|
|
||||||
sass@1.20.1:
|
sass@1.53.0:
|
||||||
version "1.20.1"
|
version "1.53.0"
|
||||||
resolved "https://registry.npmjs.org/sass/-/sass-1.20.1.tgz"
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.53.0.tgz#eab73a7baac045cc57ddc1d1ff501ad2659952eb"
|
||||||
integrity sha512-BnCawee/L5kVG3B/5Jg6BFwASqUwFVE6fj2lnkVuSXDgQ7gMAhY9a2yPeqsKhJMCN+Wgx0r2mAW7XF/aTF5qtA==
|
integrity sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar "^2.0.0"
|
chokidar ">=3.0.0 <4.0.0"
|
||||||
|
immutable "^4.0.0"
|
||||||
|
source-map-js ">=0.6.2 <2.0.0"
|
||||||
|
|
||||||
sax@~1.2.1:
|
sax@~1.2.1:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
|
@ -10001,7 +9992,7 @@ source-list-map@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz"
|
resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz"
|
||||||
|
|
||||||
source-map-js@^1.0.2:
|
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
|
||||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||||
|
@ -11229,15 +11220,15 @@ webpack-dev-middleware@3.7.3, webpack-dev-middleware@^3.7.0:
|
||||||
range-parser "^1.2.1"
|
range-parser "^1.2.1"
|
||||||
webpack-log "^2.0.0"
|
webpack-log "^2.0.0"
|
||||||
|
|
||||||
webpack-hot-middleware@2.24.3:
|
webpack-hot-middleware@2.25.1:
|
||||||
version "2.24.3"
|
version "2.25.1"
|
||||||
resolved "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.24.3.tgz"
|
resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz#581f59edf0781743f4ca4c200fd32c9266c6cf7c"
|
||||||
integrity sha512-pPlmcdoR2Fn6UhYjAhp1g/IJy1Yc9hD+T6O9mjRcWV2pFbBjIFoJXhP0CoD0xPOhWJuWXuZXGBga9ybbOdzXpg==
|
integrity sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-html "0.0.7"
|
ansi-html-community "0.0.8"
|
||||||
html-entities "^1.2.0"
|
html-entities "^2.1.0"
|
||||||
querystring "^0.2.0"
|
querystring "^0.2.0"
|
||||||
strip-ansi "^3.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
webpack-log@^2.0.0:
|
webpack-log@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
|
Loading…
Reference in a new issue