Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop

This commit is contained in:
sadposter 2021-02-20 15:29:27 +00:00
commit 7ed1fe70d1
40 changed files with 1516 additions and 444 deletions

View file

@ -5,6 +5,8 @@
</template>
<script>
import localeService from 'src/services/locale/locale.service.js'
export default {
name: 'Timeago',
props: ['date'],
@ -16,7 +18,7 @@ export default {
if (this.date.getTime() === today.getTime()) {
return this.$t('display_date.today')
} else {
return this.date.toLocaleDateString('en', { day: 'numeric', month: 'long' })
return this.date.toLocaleDateString(localeService.internalToBrowserLocale(this.$i18n.locale), { day: 'numeric', month: 'long' })
}
}
}

View file

@ -10,6 +10,7 @@
v-if="!hideEmojiButton"
class="button-unstyled emoji-picker-icon"
@click.prevent="togglePicker"
type="button"
>
<FAIcon :icon="['far', 'smile-beam']" />
</button>

View file

@ -139,6 +139,11 @@
@import '../../_variables.scss';
.ExtraButtons {
/* override of popover internal stuff */
.popover-trigger-button {
width: auto;
}
.popover-trigger {
position: static;
padding: 10px;

View file

@ -26,6 +26,7 @@
<button
class="button-unstyled -link"
@click.prevent="requireTOTP"
type="button"
>
{{ $t('login.enter_two_factor_code') }}
</button>
@ -33,6 +34,7 @@
<button
class="button-unstyled -link"
@click.prevent="abortMFA"
type="button"
>
{{ $t('general.cancel') }}
</button>

View file

@ -28,6 +28,7 @@
<button
class="button-unstyled -link"
@click.prevent="requireRecovery"
type="button"
>
{{ $t('login.enter_recovery_code') }}
</button>
@ -35,6 +36,7 @@
<button
class="button-unstyled -link"
@click.prevent="abortMFA"
type="button"
>
{{ $t('general.cancel') }}
</button>

View file

@ -58,7 +58,12 @@
{{ $t('polls.vote') }}
</button>
<div class="total">
{{ totalVotesCount }} {{ $t("polls.votes") }}&nbsp;·&nbsp;
<template v-if="typeof poll.voters_count === 'number'">
{{ $tc("polls.people_voted_count", poll.voters_count, { count: poll.voters_count }) }}&nbsp;·&nbsp;
</template>
<template v-else>
{{ $tc("polls.votes_count", poll.votes_count, { count: poll.votes_count }) }}&nbsp;·&nbsp;
</template>
</div>
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
<Timeago

View file

@ -7,6 +7,7 @@
ref="trigger"
class="button-unstyled -fullwidth popover-trigger-button"
@click="onClick"
type="button"
>
<slot name="trigger" />
</button>

View file

@ -1,6 +1,7 @@
<template>
<Popover
trigger="click"
class="ReactButton"
placement="top"
:offset="{ y: 5 }"
:bound-to="{ x: 'container' }"
@ -42,7 +43,7 @@
</div>
<span
slot="trigger"
class="ReactButton"
class="popover-trigger"
:title="$t('tool_tip.add_reaction')"
>
<FAIcon
@ -58,63 +59,72 @@
<style lang="scss">
@import '../../_variables.scss';
.reaction-picker-filter {
padding: 0.5em;
display: flex;
input {
flex: 1;
.ReactButton {
.reaction-picker-filter {
padding: 0.5em;
display: flex;
input {
flex: 1;
}
}
}
.reaction-picker-divider {
height: 1px;
width: 100%;
margin: 0.5em;
background-color: var(--border, $fallback--border);
}
.reaction-picker-divider {
height: 1px;
width: 100%;
margin: 0.5em;
background-color: var(--border, $fallback--border);
}
.reaction-picker {
width: 10em;
height: 9em;
font-size: 1.5em;
overflow-y: scroll;
display: flex;
flex-wrap: wrap;
padding: 0.5em;
text-align: center;
align-content: flex-start;
user-select: none;
.reaction-picker {
width: 10em;
height: 9em;
font-size: 1.5em;
overflow-y: scroll;
display: flex;
flex-wrap: wrap;
padding: 0.5em;
text-align: center;
align-content: flex-start;
user-select: none;
mask: linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
linear-gradient(to top, white, white);
transition: mask-size 150ms;
mask-size: 100% 20px, 100% 20px, auto;
// Autoprefixed seem to ignore this one, and also syntax is different
-webkit-mask-composite: xor;
mask-composite: exclude;
mask: linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
linear-gradient(to top, white, white);
transition: mask-size 150ms;
mask-size: 100% 20px, 100% 20px, auto;
.emoji-button {
cursor: pointer;
/* Autoprefixed seem to ignore this one, and also syntax is different */
-webkit-mask-composite: xor;
mask-composite: exclude;
flex-basis: 20%;
line-height: 1.5em;
align-content: center;
.emoji-button {
cursor: pointer;
&:hover {
transform: scale(1.25);
flex-basis: 20%;
line-height: 1.5em;
align-content: center;
&:hover {
transform: scale(1.25);
}
}
}
/* override of popover internal stuff */
.popover-trigger-button {
width: auto;
}
.popover-trigger {
padding: 10px;
margin: -10px;
&:hover .svg-inline--fa {
color: $fallback--text;
color: var(--text, $fallback--text);
}
}
}
.ReactButton {
padding: 10px;
margin: -10px;
&:hover .svg-inline--fa {
color: $fallback--text;
color: var(--text, $fallback--text);
}
}
</style>

View file

@ -9,6 +9,7 @@
:class="css.direct"
:title="$t('post_status.scope.direct')"
@click="changeVis('direct')"
type="button"
>
<FAIcon
icon="envelope"
@ -21,6 +22,7 @@
:class="css.private"
:title="$t('post_status.scope.private')"
@click="changeVis('private')"
type="button"
>
<FAIcon
icon="lock"
@ -33,6 +35,7 @@
:class="css.unlisted"
:title="$t('post_status.scope.unlisted')"
@click="changeVis('unlisted')"
type="button"
>
<FAIcon
icon="lock-open"
@ -45,6 +48,7 @@
:class="css.public"
:title="$t('post_status.scope.public')"
@click="changeVis('public')"
type="button"
>
<FAIcon
icon="globe"

View file

@ -16,6 +16,7 @@
<button
class="btn button-default search-button"
@click="newQuery(searchTerm)"
type="submit"
>
<FAIcon icon="search" />
</button>

View file

@ -8,6 +8,7 @@
class="button-unstyled nav-icon"
:title="$t('nav.search')"
@click.prevent.stop="toggleHidden"
type="button"
>
<FAIcon
fixed-width
@ -28,6 +29,7 @@
<button
class="button-default search-button"
@click="find(searchTerm)"
type="submit"
>
<FAIcon
fixed-width
@ -37,6 +39,7 @@
<button
class="button-unstyled cancel-search"
@click.prevent.stop="toggleHidden"
type="button"
>
<FAIcon
fixed-width

View file

@ -0,0 +1,57 @@
<template>
<label
class="BooleanSetting"
>
<Checkbox
:checked="state"
@change="update"
:disabled="disabled"
>
<span
v-if="!!$slots.default"
class="label"
>
<slot />
</span>
<ModifiedIndicator :changed="isChanged" />
</Checkbox>
</label>
</template>
<script>
import { get, set } from 'lodash'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ModifiedIndicator from './modified_indicator.vue'
export default {
props: [
'path',
'disabled'
],
components: {
Checkbox,
ModifiedIndicator
},
computed: {
pathDefault () {
const [firstSegment, ...rest] = this.path.split('.')
return [firstSegment + 'DefaultValue', ...rest].join('.')
},
state () {
return get(this.$parent, this.path)
},
isChanged () {
return get(this.$parent, this.path) !== get(this.$parent, this.pathDefault)
}
},
methods: {
update (e) {
set(this.$parent, this.path, e)
}
}
}
</script>
<style lang="scss">
.BooleanSetting {
}
</style>

View file

@ -0,0 +1,51 @@
<template>
<span
v-if="changed"
class="ModifiedIndicator"
>
<Popover
trigger="hover"
>
<span slot="trigger">
&nbsp;
<FAIcon
icon="wrench"
/>
</span>
<div
class="modified-tooltip"
slot="content"
>
{{ $t('settings.setting_changed') }}
</div>
</Popover>
</span>
</template>
<script>
import Popover from 'src/components/popover/popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faWrench } from '@fortawesome/free-solid-svg-icons'
library.add(
faWrench
)
export default {
props: ['changed'],
components: { Popover }
}
</script>
<style lang="scss">
.ModifiedIndicator {
display: inline-block;
position: relative;
.modified-tooltip {
margin: 0.5em 1em;
min-width: 10em;
text-align: center;
}
}
</style>

View file

@ -1,29 +1,15 @@
import {
instanceDefaultProperties,
multiChoiceProperties,
defaultState as configDefaultState
} from 'src/modules/config.js'
import { defaultState as configDefaultState } from 'src/modules/config.js'
const SharedComputedObject = () => ({
user () {
return this.$store.state.users.currentUser
},
// Getting localized values for instance-default properties
...instanceDefaultProperties
.filter(key => multiChoiceProperties.includes(key))
// Getting values for default properties
...Object.keys(configDefaultState)
.map(key => [
key + 'DefaultValue',
function () {
return this.$store.getters.instanceDefaultConfig[key]
}
])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
...instanceDefaultProperties
.filter(key => !multiChoiceProperties.includes(key))
.map(key => [
key + 'LocalizedValue',
function () {
return this.$t('settings.values.' + this.$store.getters.instanceDefaultConfig[key])
return this.$store.getters.defaultConfig[key]
}
])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),

View file

@ -1,5 +1,5 @@
import { filter, trim } from 'lodash'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
import { library } from '@fortawesome/fontawesome-svg-core'
@ -18,7 +18,7 @@ const FilteringTab = {
}
},
components: {
Checkbox
BooleanSetting
},
computed: {
...SharedComputedObject(),

View file

@ -5,34 +5,34 @@
<span class="label">{{ $t('settings.notification_visibility') }}</span>
<ul class="option-list">
<li>
<Checkbox v-model="notificationVisibility.likes">
<BooleanSetting path="notificationVisibility.likes">
{{ $t('settings.notification_visibility_likes') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="notificationVisibility.repeats">
<BooleanSetting path="notificationVisibility.repeats">
{{ $t('settings.notification_visibility_repeats') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="notificationVisibility.follows">
<BooleanSetting path="notificationVisibility.follows">
{{ $t('settings.notification_visibility_follows') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="notificationVisibility.mentions">
<BooleanSetting path="notificationVisibility.mentions">
{{ $t('settings.notification_visibility_mentions') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="notificationVisibility.moves">
<BooleanSetting path="notificationVisibility.moves">
{{ $t('settings.notification_visibility_moves') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="notificationVisibility.emojiReactions">
<BooleanSetting path="notificationVisibility.emojiReactions">
{{ $t('settings.notification_visibility_emoji_reactions') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</div>
@ -60,14 +60,14 @@
</label>
</div>
<div>
<Checkbox v-model="hidePostStats">
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="hidePostStats">
{{ $t('settings.hide_post_stats') }}
</BooleanSetting>
</div>
<div>
<Checkbox v-model="hideUserStats">
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="hideUserStats">
{{ $t('settings.hide_user_stats') }}
</BooleanSetting>
</div>
</div>
<div class="setting-item">
@ -80,9 +80,9 @@
/>
</div>
<div>
<Checkbox v-model="hideFilteredStatuses">
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="hideFilteredStatuses">
{{ $t('settings.hide_filtered_statuses') }}
</BooleanSetting>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
@ -26,7 +26,7 @@ const GeneralTab = {
}
},
components: {
Checkbox,
BooleanSetting,
InterfaceLanguageSwitcher
},
computed: {

View file

@ -7,14 +7,14 @@
<interface-language-switcher />
</li>
<li v-if="instanceSpecificPanelPresent">
<Checkbox v-model="hideISP">
<BooleanSetting path="hideISP">
{{ $t('settings.hide_isp') }}
</Checkbox>
</BooleanSetting>
</li>
<li v-if="instanceWallpaperUsed">
<Checkbox v-model="hideInstanceWallpaper">
<BooleanSetting path="hideInstanceWallpaper">
{{ $t('settings.hide_wallpaper') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</div>
@ -22,51 +22,51 @@
<h2>{{ $t('nav.timeline') }}</h2>
<ul class="setting-list">
<li>
<Checkbox v-model="hideMutedPosts">
{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="hideMutedPosts">
{{ $t('settings.hide_muted_posts') }}
</BooleanSetting>
</li>
<li>
<Checkbox v-model="collapseMessageWithSubject">
{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="collapseMessageWithSubject">
{{ $t('settings.collapse_subject') }}
</BooleanSetting>
</li>
<li>
<Checkbox v-model="streaming">
<BooleanSetting path="streaming">
{{ $t('settings.streaming') }}
</Checkbox>
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !streaming}]"
>
<li>
<Checkbox
v-model="pauseOnUnfocused"
<BooleanSetting
path="pauseOnUnfocused"
:disabled="!streaming"
>
{{ $t('settings.pause_on_unfocused') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</li>
<li>
<Checkbox v-model="useStreamingApi">
<BooleanSetting path="useStreamingApi">
{{ $t('settings.useStreamingApi') }}
<br>
<small>
{{ $t('settings.useStreamingApiWarning') }}
</small>
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="emojiReactionsOnTimeline">
<BooleanSetting path="emojiReactionsOnTimeline">
{{ $t('settings.emoji_reactions_on_timeline') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="virtualScrolling">
<BooleanSetting path="virtualScrolling">
{{ $t('settings.virtual_scrolling') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</div>
@ -75,14 +75,14 @@
<h2>{{ $t('settings.composing') }}</h2>
<ul class="setting-list">
<li>
<Checkbox v-model="scopeCopy">
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="scopeCopy">
{{ $t('settings.scope_copy') }}
</BooleanSetting>
</li>
<li>
<Checkbox v-model="alwaysShowSubjectInput">
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="alwaysShowSubjectInput">
{{ $t('settings.subject_input_always_show') }}
</BooleanSetting>
</li>
<li>
<div>
@ -143,19 +143,19 @@
</div>
</li>
<li>
<Checkbox v-model="minimalScopesMode">
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="minimalScopesMode">
{{ $t('settings.minimal_scopes_mode') }} {{ minimalScopesModeDefaultValue }}
</BooleanSetting>
</li>
<li>
<Checkbox v-model="autohideFloatingPostButton">
<BooleanSetting path="autohideFloatingPostButton">
{{ $t('settings.autohide_floating_post_button') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="padEmoji">
<BooleanSetting path="padEmoji">
{{ $t('settings.pad_emoji') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</div>
@ -164,14 +164,14 @@
<h2>{{ $t('settings.attachments') }}</h2>
<ul class="setting-list">
<li>
<Checkbox v-model="hideAttachments">
<BooleanSetting path="hideAttachments">
{{ $t('settings.hide_attachments_in_tl') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="hideAttachmentsInConv">
<BooleanSetting path="hideAttachmentsInConv">
{{ $t('settings.hide_attachments_in_convo') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<label for="maxThumbnails">
@ -179,7 +179,7 @@
</label>
<input
id="maxThumbnails"
v-model.number="maxThumbnails"
path.number="maxThumbnails"
class="number-input"
type="number"
min="0"
@ -187,48 +187,48 @@
>
</li>
<li>
<Checkbox v-model="hideNsfw">
<BooleanSetting path="hideNsfw">
{{ $t('settings.nsfw_clickthrough') }}
</Checkbox>
</BooleanSetting>
</li>
<ul class="setting-list suboptions">
<li>
<Checkbox
v-model="preloadImage"
<BooleanSetting
path="preloadImage"
:disabled="!hideNsfw"
>
{{ $t('settings.preload_images') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox
v-model="useOneClickNsfw"
<BooleanSetting
path="useOneClickNsfw"
:disabled="!hideNsfw"
>
{{ $t('settings.use_one_click_nsfw') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
<li>
<Checkbox v-model="stopGifs">
<BooleanSetting path="stopGifs">
{{ $t('settings.stop_gifs') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="loopVideo">
<BooleanSetting path="loopVideo">
{{ $t('settings.loop_video') }}
</Checkbox>
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !streaming}]"
>
<li>
<Checkbox
v-model="loopVideoSilentOnly"
<BooleanSetting
path="loopVideoSilentOnly"
:disabled="!loopVideo || !loopSilentAvailable"
>
{{ $t('settings.loop_video_silent_only') }}
</Checkbox>
</BooleanSetting>
<div
v-if="!loopSilentAvailable"
class="unavailable"
@ -239,14 +239,14 @@
</ul>
</li>
<li>
<Checkbox v-model="playVideosInModal">
<BooleanSetting path="playVideosInModal">
{{ $t('settings.play_videos_in_modal') }}
</Checkbox>
</BooleanSetting>
</li>
<li>
<Checkbox v-model="useContainFit">
<BooleanSetting path="useContainFit">
{{ $t('settings.use_contain_fit') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</div>
@ -255,9 +255,9 @@
<h2>{{ $t('settings.notifications') }}</h2>
<ul class="setting-list">
<li>
<Checkbox v-model="webPushNotifications">
<BooleanSetting path="webPushNotifications">
{{ $t('settings.enable_web_push_notifications') }}
</Checkbox>
</BooleanSetting>
</li>
</ul>
</div>
@ -266,9 +266,9 @@
<h2>{{ $t('settings.fun') }}</h2>
<ul class="setting-list">
<li>
<Checkbox v-model="greentext">
{{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
</Checkbox>
<BooleanSetting path="greentext">
{{ $t('settings.greentext') }}
</BooleanSetting>
</li>
</ul>
</div>

View file

@ -1,6 +1,7 @@
import ProgressButton from 'src/components/progress_button/progress_button.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Mfa from './mfa.vue'
import localeService from 'src/services/locale/locale.service.js'
const SecurityTab = {
data () {
@ -37,7 +38,7 @@ const SecurityTab = {
return {
id: oauthToken.id,
appName: oauthToken.app_name,
validUntil: new Date(oauthToken.valid_until).toLocaleDateString()
validUntil: new Date(oauthToken.valid_until).toLocaleDateString(localeService.internalToBrowserLocale(this.$i18n.locale))
}
})
}

View file

@ -109,7 +109,7 @@
v-if="chat"
@click="toggleDrawer"
>
<router-link :to="{ name: 'chat' }">
<router-link :to="{ name: 'chat-panel' }">
<FAIcon
fixed-width
class="fa-scale-110 fa-old-padding"

View file

@ -1,4 +1,6 @@
import map from 'lodash/map'
import groupBy from 'lodash/groupBy'
import { mapGetters, mapState } from 'vuex'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const StaffPanel = {
@ -10,9 +12,21 @@ const StaffPanel = {
BasicUserCard
},
computed: {
staffAccounts () {
return map(this.$store.state.instance.staffAccounts, nickname => this.$store.getters.findUser(nickname)).filter(_ => _)
}
groupedStaffAccounts () {
const staffAccounts = map(this.staffAccounts, this.findUser).filter(_ => _)
const groupedStaffAccounts = groupBy(staffAccounts, 'role')
return [
{ role: 'admin', users: groupedStaffAccounts['admin'] },
{ role: 'moderator', users: groupedStaffAccounts['moderator'] }
].filter(group => group.users)
},
...mapGetters([
'findUser'
]),
...mapState({
staffAccounts: state => state.instance.staffAccounts
})
}
}

View file

@ -7,11 +7,18 @@
</div>
</div>
<div class="panel-body">
<basic-user-card
v-for="user in staffAccounts"
:key="user.screen_name"
:user="user"
/>
<div
v-for="group in groupedStaffAccounts"
:key="group.role"
class="staff-group"
>
<h4>{{ $t('general.role.' + group.role) }}</h4>
<basic-user-card
v-for="user in group.users"
:key="user.screen_name"
:user="user"
/>
</div>
</div>
</div>
</div>
@ -20,4 +27,14 @@
<script src="./staff_panel.js" ></script>
<style lang="scss">
.staff-group {
padding-left: 1em;
padding-top: 1em;
.basic-user-card {
padding-left: 0;
}
}
</style>

View file

@ -93,7 +93,9 @@ export default Vue.component('tab-switcher', {
<button
disabled={slot.data.attrs.disabled}
onClick={this.clickTab(index)}
class={classesTab.join(' ')}>
class={classesTab.join(' ')}
type="button"
>
<img src={slot.data.attrs.image} title={slot.data.attrs['image-tooltip']}/>
{slot.data.attrs.label ? '' : slot.data.attrs.label}
</button>

View file

@ -9,6 +9,7 @@
<script>
import * as DateUtils from 'src/services/date_utils/date_utils.js'
import localeService from 'src/services/locale/locale.service.js'
export default {
name: 'Timeago',
@ -21,9 +22,10 @@ export default {
},
computed: {
localeDateString () {
const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
return typeof this.time === 'string'
? new Date(Date.parse(this.time)).toLocaleString()
: this.time.toLocaleString()
? new Date(Date.parse(this.time)).toLocaleString(browserLocale)
: this.time.toLocaleString(browserLocale)
}
},
created () {

View file

@ -83,13 +83,13 @@
v-if="!!visibleRole"
class="alert user-role"
>
{{ $t(`user_card.roles.${visibleRole}`) }}
{{ $t(`general.role.${visibleRole}`) }}
</span>
<span
v-if="user.bot"
class="alert user-role"
>
bot
{{ $t('user_card.bot') }}
</span>
</template>
<span v-if="user.locked">