Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85826567
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
63 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/list/list.vue b/src/components/list/list.vue
index c3e0412010..c092da339d 100644
--- a/src/components/list/list.vue
+++ b/src/components/list/list.vue
@@ -1,92 +1,92 @@
<template>
<div
class="List"
role="list"
:class="{ '-scrollable': scrollable }"
>
<div
v-if="selectable"
class="header"
>
<div class="checkbox-wrapper">
<Checkbox
:model-value="allSelected"
:indeterminate="someSelected"
@update:model-value="toggleAll"
>
{{ $t('selectable_list.select_all') }}
</Checkbox>
</div>
<div class="actions">
<slot
name="header"
:selected="selectedItems"
/>
</div>
</div>
<div
class="list"
role="list"
>
<div
v-for="item in finalItems"
:key="getKey(item)"
class="list-item"
:class="[getClass(item), nonInteractive ? '-non-interactive' : '']"
role="listitem"
>
<div
v-if="selectable"
class="checkbox-wrapper"
>
<Checkbox
:model-value="isSelected(item)"
@update:model-value="checked => toggle(checked, item)"
@click.stop
/>
</div>
<slot
name="item"
:item="item"
/>
</div>
<div
v-if="finalItems.length === 0 && !!$slots.empty"
class="list-empty-content faint"
>
<slot name="empty" />
<slot name="load" />
</div>
<div class="footer">
<button
v-if="error"
class="button-unstyled -link -fullwidth alert error"
@click="fetchEntries"
>
{{ $t('general.generic_error') }}
{{ error }}
</button>
<FAIcon
v-else-if="loading"
spin
icon="circle-notch"
/>
<a
v-else-if="!bottomedOut"
- @click="fetchEntries"
role="button"
tabindex="0"
+ @click="fetchEntries"
>
{{ $t('general.more') }}
</a>
<span v-else>
{{ $t('general.no_more') }}
</span>
</div>
</div>
</div>
</template>
<script src="./list.js"></script>
<style src="./list.css"></style>
diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue
index 43612c693d..4da0be0ee0 100644
--- a/src/components/moderation_tools/moderation_tools.vue
+++ b/src/components/moderation_tools/moderation_tools.vue
@@ -1,124 +1,133 @@
<template>
<div>
<Popover
trigger="click"
class="moderation-tools-popover"
:disabled="disabled"
placement="bottom"
:offset="{ y: 5 }"
@show="setOpen(true)"
@close="setOpen(false)"
>
<template #content="{close}">
<div class="dropdown-menu">
<template v-for="(entry, index) in entries">
<div
v-if="entry === 'separator'"
:key="index"
role="separator"
class="dropdown-divider"
/>
<div
v-else
:key="entry.label"
class="menu-item dropdown-item"
:class="entry.checkbox ? '-icon' : '-icon-space'"
>
<button
class="main-button"
@click="() => maybeShowConfirm(close, entry)"
>
<span
v-if="entry.checkbox"
class="input menu-checkbox"
:class="entry.checkboxClass"
/>
{{ $t(entry.label) }}
</button>
</div>
</template>
</div>
</template>
<template #trigger>
<button
class="btn button-default btn-block moderation-tools-button"
:class="{ toggled: open, disabled }"
:disabled="disabled"
>
{{ $t('user_card.admin_menu.moderation') }}
- <FAIcon v-if="ready" icon="chevron-down" />
- <span v-else class="loading-spinner">
+ <FAIcon
+ v-if="ready"
+ icon="chevron-down"
+ />
+ <span
+ v-else
+ class="loading-spinner"
+ >
<FAIcon
class="fa-old-padding"
spin
icon="circle-notch"
- />
+ />
</span>
</button>
</template>
</Popover>
<teleport to="#modal">
<ConfirmModal
v-if="confirmDialogShow"
:title="$t(confirmDialogTitle)"
:confirm-text="confirmDialogConfirm"
:confirm-danger="confirmDialogDanger"
:cancel-text="$t('general.cancel')"
@accepted="doConfirmDialogAction"
@cancelled="clearConfirmDialog"
>
<i18n-t
:plural="users.length"
scope="global"
:keypath="confirmDialogContent"
tag="p"
>
<template #user>
<span
v-text="users[0].screen_name_ui"
/>
</template>
<template #count>
{{ users.length }}
</template>
<template #name>
<code>
{{ confirmDialogName }}
</code>
</template>
</i18n-t>
<p v-if="confirmDialogContent2">
{{ $t(confirmDialogContent2) }}
</p>
<ul v-if="users.length > 1">
- <li v-for="user in users">
+ <li
+ v-for="user in users"
+ :key="user.screen_name"
+ >
{{ user.screen_name }}
</li>
</ul>
</ConfirmModal>
</teleport>
</div>
</template>
<script src="./moderation_tools.js"></script>
<style lang="scss">
.moderation-tools-popover {
height: 100%;
.trigger {
/* stylelint-disable-next-line declaration-no-important */
display: flex !important;
height: 100%;
}
}
.moderation-tools-button {
white-space: nowrap;
svg,
i {
font-size: 0.8em;
}
}
</style>
diff --git a/src/components/settings_modal/admin_tabs/admin_user_card.vue b/src/components/settings_modal/admin_tabs/admin_user_card.vue
index cf3062b095..00405dfa15 100644
--- a/src/components/settings_modal/admin_tabs/admin_user_card.vue
+++ b/src/components/settings_modal/admin_tabs/admin_user_card.vue
@@ -1,107 +1,107 @@
<template>
<template v-if="!user">
<FAIcon
icon="circle-notch"
spin
size="lg"
/>
</template>
<template v-else>
<BasicUserCard
class="AdminUserCard"
:user="user"
show-line-labels
>
<div>
<strong>
{{ $t('admin_dash.users.labels.email_colon') }}
</strong>
{{ ' ' }}
<span
- class="faint"
v-if="user.adminData.email == null"
+ class="faint"
>
{{ $t('general.not_available') }}
</span>
<a :href="'mailto:' + user.adminData.email">
{{ user.adminData.email }}
</a>
</div>
<details
v-if="user.adminData.registration_reason != null"
open
>
<summary>
{{ $t('user_card.admin_data.registration_reason') }}
</summary>
<span>
- {{ user.adminData.registration_reason }}
+ {{ user.adminData.registration_reason }}
</span>
</details>
<div class="right-side">
<label
v-if="user.is_local && isAdmin"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.admin') }}
</label>
<label
v-if="user.is_local && isModerator"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.moderator') }}
</label>
<label
v-if="isActivated"
class="alert success user-role"
>
{{ $t('admin_dash.users.indicator.active') }}
</label>
<label
v-if="!isActivated"
class="alert error user-role"
>
{{ $t('admin_dash.users.indicator.deactivated') }}
</label>
<label
v-if="user.is_local && user.adminData.is_confirmed"
class="alert success user-role"
>
{{ $t('admin_dash.users.indicator.confirmed') }}
</label>
<label
v-if="user.is_local && !user.adminData.is_confirmed"
class="alert warning user-role"
>
{{ $t('admin_dash.users.indicator.unconfirmed') }}
</label>
<label
v-if="user.is_local && user.adminData.is_approved"
class="alert success user-role"
>
{{ $t('admin_dash.users.indicator.approved') }}
</label>
<label
v-if="user.is_local && !user.adminData.is_approved"
class="alert warning user-role"
>
{{ $t('admin_dash.users.indicator.unapproved') }}
</label>
<label
v-if="user.adminData.is_suggested"
class="alert info user-role"
>
{{ $t('admin_dash.users.indicator.suggested') }}
</label>
<ModerationTools
class="moderation-menu"
:users="[user]"
/>
</div>
</BasicUserCard>
</template>
</template>
<script src="./admin_user_card.js"></script>
<style lang="scss" src="./admin_user_card.scss"></style>
diff --git a/src/components/settings_modal/admin_tabs/users_tab.vue b/src/components/settings_modal/admin_tabs/users_tab.vue
index a12c76dddc..fcc9e9df16 100644
--- a/src/components/settings_modal/admin_tabs/users_tab.vue
+++ b/src/components/settings_modal/admin_tabs/users_tab.vue
@@ -1,146 +1,146 @@
<template>
<div
class="UsersTab"
:label="$t('admin_dash.users.management')"
>
<h3>
{{ $t('admin_dash.users.title') }}
</h3>
<div class="filters-section">
<label class="filter">
<div class="query-label">
{{ $t('admin_dash.users.labels.query') }}
</div>
<input
v-model="filtersQuery"
class="input string-input filter-input"
>
</label>
<label class="filter">
<div class="query-label">
{{ $t('admin_dash.users.labels.name') }}
</div>
<input
v-model="filtersName"
class="input string-input filter-input"
>
</label>
<label class="filter">
<div class="query-label">
{{ $t('admin_dash.users.labels.email') }}
</div>
<input
v-model="filtersEmail"
class="input string-input filter-input"
>
</label>
<div class="filter">
<div class="query-label">
{{ $t('admin_dash.users.labels.origin') }}
</div>
<Select
v-model="filtersOrigin"
>
<option
value="all"
>
{{ $t('admin_dash.users.options.all') }}
</option>
<option
value="local"
>
{{ $t('admin_dash.users.options.only_local') }}
</option>
<option
value="external"
>
{{ $t('admin_dash.users.options.only_external') }}
</option>
</Select>
</div>
<div class="filter">
<div class="query-label">
{{ $t('admin_dash.users.labels.activity') }}
</div>
<Select
v-model="filtersActivity"
>
<option
value="all"
>
{{ $t('admin_dash.users.options.all') }}
</option>
<option
value="active"
>
{{ $t('admin_dash.users.options.only_active') }}
</option>
<option
value="deactivated"
>
{{ $t('admin_dash.users.options.only_deactivated') }}
</option>
</Select>
</div>
<div class="filter">
<div class="query-label">
{{ $t('admin_dash.users.labels.privileges') }}
</div>
<Select v-model="filtersPrivileges">
<option
value="all"
>
{{ $t('admin_dash.users.options.all') }}
</option>
<option
value="admin"
>
{{ $t('admin_dash.users.options.only_admins') }}
</option>
<option
value="modsnadmins"
>
{{ $t('admin_dash.users.options.only_privileged') }}
</option>
<option
value="moderator"
>
{{ $t('admin_dash.users.options.only_moderators') }}
</option>
</Select>
</div>
<div class="filter">
<Checkbox v-model="filtersNeedApproval">
{{ $t('admin_dash.users.options.only_unapproved') }}
</Checkbox>
</div>
<div class="filter">
<Checkbox v-model="filtersUnconfirmed">
{{ $t('admin_dash.users.options.only_unconfirmed') }}
</Checkbox>
</div>
</div>
<List
ref="usersList"
:fetch-function="fetchUsers"
- @select="onSelect"
selectable
scrollable
+ @select="onSelect"
>
<template #header="{selected}">
<ModerationTools :users="selected" />
</template>
<template #item="{item}">
<AdminUserCard :user-id="item.id" />
</template>
<template #load>
<span> loading </span>
</template>
<template #empty>
<span> no users </span>
</template>
</List>
</div>
</template>
<script src="./users_tab.js"></script>
<style lang="scss" src="./users_tab.scss"></style>
diff --git a/src/components/settings_modal/helpers/vertical_tab_switcher.scss b/src/components/settings_modal/helpers/vertical_tab_switcher.scss
index 4c0e94dff1..8db960914c 100644
--- a/src/components/settings_modal/helpers/vertical_tab_switcher.scss
+++ b/src/components/settings_modal/helpers/vertical_tab_switcher.scss
@@ -1,191 +1,192 @@
.vertical-tab-switcher {
display: flex;
flex-direction: row;
container-type: inline-size;
> .tabs {
flex: 0 0 15em;
flex-direction: column;
overflow: hidden auto;
white-space: nowrap;
text-overflow: ellipsis;
width: 15em;
min-width: 15em;
border-right: 1px solid;
border-right-color: var(--border);
box-sizing: border-box;
> .menu-item {
padding: 0.5em 1em;
.tab-icon {
vertical-align: middle;
margin-right: 0.75em;
}
}
}
> .contents {
.tab-content-label {
box-sizing: border-box;
margin: 0;
border-bottom: 1px solid var(--border);
display: none;
button {
box-sizing: border-box;
padding: 0.5em;
}
}
.tab-slot-wrapper {
flex: 1 1 auto;
position: relative;
height: 100%;
padding: 0 1em;
overflow-y: auto;
display: grid;
grid-template-columns: minmax(1em, 1fr) minmax(min-content, 45em) minmax(1em, 1fr);
grid-template-areas: ". content .";
flex-direction: column;
.tab-content {
grid-area: content;
&.-full-width {
grid-column: 1 / 4;
}
&.-full-height {
height: 100%;
+
> * {
height: 100%;
}
}
&.-full-width.-full-height {
position: absolute;
inset: 0;
}
}
}
.tab-content-wrapper {
flex: 1 1 auto;
height: 100%;
display: flex;
flex-direction: column;
&.-hidden {
display: none;
}
}
}
&.-mobile {
> .contents {
.tab-content-label {
display: block
}
}
&.-nav-contents {
> .contents {
display: block;
flex-grow: 1;
flex-shrink: 1;
}
> .tabs {
display: none;
flex-grow: 0;
flex-shrink: 1;
}
}
&.-nav-tabs {
> .tabs {
display: block;
flex-grow: 1;
}
> .contents {
display: none;
flex-grow: 0;
flex-shrink: 1;
}
}
.tab-slot-wrapper {
grid-template-columns: 0 minmax(min-content, 45em) 0;
}
}
@supports (container-type: inline-size) {
&,
&.-mobile {
&.-nav-contents,
&.-nav-tabs {
/* I THINK it's a false positive and eslint doesn't understand the @-rule */
/* stylelint-disable no-descending-specificity */
> .contents {
display: block;
flex-grow: 1;
}
> .tabs {
display: block;
flex-grow: 0;
}
/* stylelint-enable no-descending-specificity */
}
}
@container (width < 50em) {
> .contents {
.tab-content-label {
display: block
}
}
&.-mobile {
> .contents {
.tab-content-label {
display: block
}
}
}
&,
&.-mobile {
&.-nav-contents {
> .contents {
display: block;
flex-grow: 1;
}
> .tabs {
display: none;
flex-grow: 0;
flex-shrink: 1;
}
}
&.-nav-tabs {
/* stylelint-disable no-descending-specificity */
> .tabs {
display: block;
flex-grow: 1;
}
> .contents {
display: none;
flex-grow: 0;
flex-shrink: 1;
}
/* stylelint-enable no-descending-specificity */
}
}
}
}
}
diff --git a/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue b/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue
index 598fb53f80..5b8066ef75 100644
--- a/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue
+++ b/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue
@@ -1,165 +1,168 @@
<template>
<tab-switcher
class="mutes-and-blocks-tab"
:scrollable-tabs
- >
+ >
<div
class="blocks"
:label="$t('settings.user_blocks')"
>
<div class="usersearch-wrapper">
<Autosuggest
:filter="filterUnblockedUsers"
:query="queryUserIds"
:placeholder="$t('settings.search_user_to_block')"
>
<template #default="row">
<BlockCard
:user-id="row.item"
/>
</template>
</Autosuggest>
</div>
<List
:get-key="i => i"
:external-items="blocks"
:fetch-function="fetchItems('Blocks')"
scrollable
selectable
>
<template #header="{selected}">
<div class="bulk-actions">
<ProgressButton
v-if="selected.length > 0"
class="btn button-default bulk-action-button"
:click="() => blockUsers(selected)"
>
{{ $t('user_card.block') }}
<template #progress>
{{ $t('user_card.block_progress') }}
</template>
</ProgressButton>
<ProgressButton
v-if="selected.length > 0"
class="btn button-default"
:click="() => unblockUsers(selected)"
>
{{ $t('user_card.unblock') }}
<template #progress>
{{ $t('user_card.unblock_progress') }}
</template>
</ProgressButton>
</div>
</template>
<template #item="{item}">
<BlockCard :user-id="item" />
</template>
<template #empty>
{{ $t('settings.no_blocks') }}
</template>
</List>
</div>
- <div class="mutes" :label="$t('settings.user_mutes2')">
+ <div
+ class="mutes"
+ :label="$t('settings.user_mutes2')"
+ >
<div class="usersearch-wrapper">
<Autosuggest
:filter="filterUnMutedUsers"
:query="queryUserIds"
:placeholder="$t('settings.search_user_to_mute')"
>
<template #default="row">
<MuteCard
:user-id="row.item"
/>
</template>
</Autosuggest>
</div>
<List
:get-key="i => i"
:external-items="mutes"
:fetch-function="fetchItems('Mutes')"
scrollable
selectable
>
<template #header="{selected}">
<div class="bulk-actions">
<ProgressButton
v-if="selected.length > 0"
class="btn button-default"
:click="() => muteUsers(selected)"
>
{{ $t('user_card.mute') }}
<template #progress>
{{ $t('user_card.mute_progress') }}
</template>
</ProgressButton>
<ProgressButton
v-if="selected.length > 0"
class="btn button-default"
:click="() => unmuteUsers(selected)"
>
{{ $t('user_card.unmute') }}
<template #progress>
{{ $t('user_card.unmute_progress') }}
</template>
</ProgressButton>
</div>
</template>
<template #item="{item}">
<MuteCard :user-id="item" />
</template>
<template #empty>
{{ $t('settings.no_mutes') }}
</template>
</List>
</div>
<div :label="$t('settings.domain_mutes2')">
<div class="domain-mute-form">
<Autosuggest
:filter="filterUnMutedDomains"
:query="queryKnownDomains"
:placeholder="$t('settings.type_domains_to_mute')"
>
<template #default="row">
<DomainMuteCard
:domain="row.item"
/>
</template>
</Autosuggest>
</div>
<List
:get-key="i => i"
:external-items="domains"
:fetch-function="fetchItems('DomainMutes')"
scrollable
selectable
>
<template #header="{selected}">
<div class="bulk-actions">
<ProgressButton
v-if="selected.length > 0"
class="btn button-default"
:click="() => unmuteDomains(selected)"
>
{{ $t('domain_mute_card.unmute') }}
<template #progress>
{{ $t('domain_mute_card.unmute_progress') }}
</template>
</ProgressButton>
</div>
</template>
<template #item="{item}">
{{ item }}
<DomainMuteCard :domain="item" />
</template>
<template #empty>
{{ $t('settings.no_mutes') }}
</template>
</List>
</div>
</tab-switcher>
</template>
<script src="./mutes_and_blocks_tab.js"></script>
<style lang="scss" src="./mutes_and_blocks_tab.scss"></style>
diff --git a/src/components/status_action_buttons/action_button_container.vue b/src/components/status_action_buttons/action_button_container.vue
index 919207622a..24f9a3c3bf 100644
--- a/src/components/status_action_buttons/action_button_container.vue
+++ b/src/components/status_action_buttons/action_button_container.vue
@@ -1,158 +1,159 @@
<template>
<div>
<Popover
v-if="button.dropdown?.()"
:trigger="$attrs.extra ? 'hover' : 'click'"
:offset="{ y: 5 }"
:placement="$attrs.extra ? 'right' : 'bottom'"
>
<template #trigger>
<ActionButton
:button="button"
:status="status"
v-bind.prop="$attrs"
/>
</template>
<template #content>
<div
v-if="button.name === 'changeScope'"
:id="`popup-menu-scope-${randomSeed}`"
class="dropdown-menu"
role="menu"
>
<div
v-for="visibility in availableScopes"
+ :key="visibility"
class="menu-item dropdown-item extra-action -icon"
>
<button
class="main-button"
@click="() => setScope(visibility)"
>
<FAIcon
:icon="visibilityIcon(visibility)"
fixed-width
/>
- {{ $t('general.scope_in_timeline.' + visibility) }}
+ {{ $t('general.scope_in_timeline.' + visibility) }}
</button>
</div>
<div
v-if="status.nsfw"
class="menu-item dropdown-item extra-action -icon"
>
<button
class="main-button"
@click="() => setSensitive(false)"
>
<FAIcon
icon="eye"
fixed-width
/>
- {{ $t('status.mark_as_non-sensitive') }}
+ {{ $t('status.mark_as_non-sensitive') }}
</button>
</div>
<div
v-else
class="menu-item dropdown-item extra-action -icon"
>
<button
class="main-button"
@click="() => setSensitive(true)"
>
<FAIcon
icon="eye-slash"
fixed-width
/>
- {{ $t('status.mark_as_sensitive') }}
+ {{ $t('status.mark_as_sensitive') }}
</button>
</div>
</div>
<div
v-if="button.name === 'mute'"
:id="`popup-menu-${randomSeed}`"
class="dropdown-menu"
role="menu"
>
<div class="menu-item dropdown-item extra-action -icon">
<button
class="main-button"
@click="toggleUserMute"
>
<FAIcon
icon="user"
fixed-width
/>
<template v-if="userIsMuted">
{{ $t('status.unmute_user') }}
</template>
<template v-else>
{{ $t('status.mute_user') }}
</template>
</button>
</div>
<div class="menu-item dropdown-item extra-action -icon">
<button
class="main-button"
@click="toggleConversationMute"
>
<FAIcon
icon="folder-tree"
fixed-width
/>
<template v-if="conversationIsMuted">
{{ $t('status.unmute_conversation') }}
</template>
<template v-else>
{{ $t('status.mute_conversation') }}
</template>
</button>
</div>
<div class="menu-item dropdown-item extra-action -icon">
<button
class="main-button"
@click="toggleDomainMute"
>
<FAIcon
icon="globe"
fixed-width
/>
<template v-if="domainIsMuted">
{{ $t('status.unmute_domain') }}
</template>
<template v-else>
{{ $t('status.mute_domain') }}
</template>
</button>
</div>
</div>
</template>
</Popover>
<ActionButton
v-else
:button="button"
:status="status"
v-bind="$attrs"
@emoji-picker-shown="e => $emit('emojiPickerShown', e)"
/>
<teleport to="#modal">
<MuteConfirm
ref="confirmConversation"
type="conversation"
:status="status"
:user="user"
/>
<MuteConfirm
ref="confirmDomain"
type="domain"
:status="status"
:user="user"
/>
<UserTimedFilterModal
ref="confirmUser"
:is-mute="true"
:user="user"
/>
</teleport>
</div>
</template>
<script src="./action_button_container.js" />
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index cdea958af7..af779823c2 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -1,860 +1,860 @@
<template>
<div class="user-card">
<div class="user-card-inner">
<div class="user-info">
<div
class="user-identity"
:class="{ '-compact': compact }"
>
<div class="header-overlay">
<div class="banner-image">
<img
:src="bannerImgSrc"
:class="{ 'hide-bio': hideBio }"
>
</div>
<div
class="banner-overlay"
:class="{ 'hide-bio': hideBio }"
/>
</div>
<a
v-if="avatarAction === 'zoom'"
class="user-info-avatar -link"
@click="zoomAvatar"
>
<UserAvatar :user="user" />
<div class="user-info-avatar -link -overlay">
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="search-plus"
/>
</div>
</a>
<button
v-else-if="editable"
class="user-info-avatar button-unstyled -link"
:class="{ '-editable': editable }"
@click="changeAvatar"
>
<UserAvatar
:user="user"
:url="avatarImgSrc"
/>
<div class="user-info-avatar -link -overlay">
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="pencil"
/>
</div>
</button>
<UserAvatar
v-else-if="typeof avatarAction === 'function'"
class="user-info-avatar"
:user="user"
@click="avatarAction"
/>
<router-link
v-else
class="user-info-avatar"
:to="userProfileLink(user)"
>
<UserAvatar :user="user" />
</router-link>
<div class="user-summary">
<div class="top-line">
<div
class="other-actions"
>
<button
v-if="editable"
:disabled="newName && newName.length === 0"
class="btn button-unstyled edit-banner-button"
@click="changeBanner"
>
{{ $t('settings.change_banner') }}
<FAIcon
fixed-width
class="icon"
icon="pencil"
:title="$t('settings.change_banner')"
/>
</button>
<button
v-else-if="!editable && !isOtherUser && user.is_local"
class="button-unstyled edit-profile-button"
@click.stop="openProfileTab"
>
<FAIcon
fixed-width
class="icon"
icon="edit"
:title="$t('user_card.edit_profile')"
/>
</button>
<a
v-if="isOtherUser && !user.is_local"
:href="user.statusnet_profile_url"
target="_blank"
class="button-unstyled external-link-button"
>
<FAIcon
class="icon"
icon="external-link-alt"
/>
</a>
<AccountActions
v-if="isOtherUser && loggedIn && !hideButtons"
:user="user"
:relationship="relationship"
/>
<router-link
v-if="showExpand"
:to="userProfileLink(user)"
class="button-unstyled external-link-button"
@click="$emit('close')"
>
<FAIcon
class="icon"
icon="expand-alt"
/>
</router-link>
<button
v-if="showClose"
class="button-unstyled external-link-button"
@click="$emit('close')"
>
<FAIcon
class="icon"
icon="times"
/>
</button>
</div>
<div class="name-wrapper">
<router-link
v-if="!editable || !editingName"
:to="userProfileLink(user)"
class="user-name"
>
<RichContent
:title="editable ? newName : user.name_unescaped"
:html="editable ? newName : user.name_unescaped"
:emoji="editable ? emoji : user.emoji"
:allow-non-square-emoji="allowNonSquareEmoji"
/>
</router-link>
<EmojiInput
v-else-if="editingName"
v-model="newName"
enable-emoji-picker
:suggest="emojiSuggestor"
>
<template #default="inputProps">
<input
id="username"
v-model="newName"
class="input name-changer"
v-bind="propsToNative(inputProps)"
>
</template>
</EmojiInput>
<button
v-if="editable"
class="button-unstyled edit-button"
:title="$t('settings.toggle_edit')"
@click="editingName = !editingName"
>
<FAIcon
class="icon"
icon="pencil"
/>
</button>
</div>
</div>
<div class="bottom-line">
<UserLink
class="user-screen-name"
:user="user"
/>
<span
v-if="user.locked"
class="lock-icon"
>
<FAIcon
icon="lock"
size="sm"
/>
</span>
<span
v-if="relationship.followed_by && loggedIn && isOtherUser"
class="alert neutral user-role"
>
{{ $t('user_card.follows_you') }}
</span>
<template v-if="!hideBio">
<span
v-if="user.deactivated"
class="alert neutral user-role"
>
{{ $t('user_card.deactivated') }}
</span>
<span
v-if="!!visibleRole"
class="alert neutral user-role"
>
{{ $t(`general.role.${visibleRole}`) }}
</span>
<span
v-if="user.actor_type === 'Service'"
class="alert neutral user-role"
>
{{ $t('user_card.bot') }}
</span>
<span
v-if="user.actor_type === 'Group'"
class="alert neutral user-role"
>
{{ $t('user_card.group') }}
</span>
<span
v-for="tag in user.tags"
:key="tag"
class="alert warning user-role"
>
{{ isKnownTag ? $t('user_card.tags.' + tag) : tag }}
</span>
</template>
</div>
</div>
</div>
<div
v-if="loggedIn && isOtherUser && !hideButtons"
class="user-interactions"
>
<div class="btn-group">
<FollowButton
:relationship="relationship"
:user="user"
/>
<template v-if="relationship.following">
<ProgressButton
v-if="!relationship.notifying"
class="btn button-default"
:click="subscribeUser"
:title="$t('user_card.subscribe')"
>
<FAIcon icon="bell" />
</ProgressButton>
<ProgressButton
v-else
class="btn button-default toggled"
:click="unsubscribeUser"
:title="$t('user_card.unsubscribe')"
>
<FALayers>
<FAIcon
icon="rss"
transform="left-5 shrink-6 up-3 rotate-20"
flip="horizontal"
/>
<FAIcon
icon="rss"
transform="right-5 shrink-6 up-3 rotate-20"
/>
<FAIcon icon="bell" />
</FALayers>
</ProgressButton>
</template>
</div>
<button
v-if="relationship.muting"
class="btn button-default btn-mute toggled"
:disabled="user.deactivated"
@click="unmuteUser"
>
{{ $t('user_card.muted') }}
</button>
<button
v-else
class="btn button-default btn-mute"
:disabled="user.deactivated"
@click="muteUser"
>
{{ $t('user_card.mute') }}
</button>
<button
class="btn button-default btn-mention"
:disabled="user.deactivated"
@click="mentionUser"
>
{{ $t('user_card.mention') }}
</button>
<ModerationTools
v-if="showModerationMenu"
:users="[user]"
/>
</div>
<div
v-if="!loggedIn && user.is_local"
class="user-interactions"
>
<RemoteFollow :user="user" />
</div>
</div>
</div>
<div
v-if="!editable && loggedIn && isOtherUser && (hasNote || !hideBio) && !hideRemarks"
class="personal-marks"
>
<UserNote
v-if="hasNote || (hasNoteEditor && supportsNote)"
:user="user"
:relationship="relationship"
:editable="hasNoteEditor"
/>
<div
v-if="!hideBio"
class="highlighter"
>
<h4>{{ $t('user_card.highlight_header') }}</h4>
<Select
:id="'userHighlightSel'+user.id"
v-model="userHighlightType"
class="userHighlightSel unstyled"
:class="{ '-none': userHighlightType === 'disabled' }"
>
<option value="disabled">
{{ $t('user_card.highlight_new.disabled') }}
</option>
<option value="solid">
{{ $t('user_card.highlight_new.solid') }}
</option>
<option value="striped">
{{ $t('user_card.highlight_new.striped') }}
</option>
<option value="side">
{{ $t('user_card.highlight_new.side') }}
</option>
</Select>
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
<ColorInput
v-if="userHighlightType !== 'disabled'"
v-model="userHighlightColor"
class="highlighter-color"
:show-optional-checkbox="false"
name="'userHighlightColorTx'+user.id"
:unstyled="true"
/>
</div>
</div>
<div
- class="admin-data"
v-if="user.adminData && !hideBio"
+ class="admin-data"
>
<details>
<summary>
{{ $t('user_card.admin_data.data') }}
</summary>
<div class="user-profile-fields">
<dl class="user-profile-field">
<dt class="user-profile-field-name">
{{ $t('admin_dash.users.local_id') }}
</dt>
<dd class="user-profile-field-value">
{{ user.adminData.id }}
</dd>
</dl>
<dl
v-if="user.is_local"
class="user-profile-field"
>
<dt class="user-profile-field-name">
{{ $t('admin_dash.users.labels.email') }}
</dt>
<dd
class="user-profile-field-value"
:class="{ faint: user.adminData.email == null }"
>
{{ user.adminData.email == null ? $t('general.not_available') : user.adminData.email }}
</dd>
</dl>
<dl
v-if="user.is_local"
class="user-profile-field"
>
<dt class="user-profile-field-name">
{{ $t('general.role.admin') }}
</dt>
<dd class="user-profile-field-value">
{{ $t('general.' + (user.adminData.roles.admin ? 'yes' : 'no')) }}
</dd>
</dl>
<dl
v-if="user.is_local"
class="user-profile-field"
>
<dt class="user-profile-field-name">
{{ $t('general.role.moderator') }}
</dt>
<dd class="user-profile-field-value">
{{ $t('general.' + (user.adminData.roles.moderator ? 'yes' : 'no')) }}
</dd>
</dl>
<dl
v-if="user.is_local"
class="user-profile-field"
>
<dt class="user-profile-field-name">
{{ $t('admin_dash.users.indicator.confirmed') }}
</dt>
<dd class="user-profile-field-value">
{{ $t('general.' + (user.adminData.is_confirmed ? 'yes' : 'no')) }}
</dd>
</dl>
<dl
v-if="user.is_local"
class="user-profile-field"
>
<dt class="user-profile-field-name">
{{ $t('admin_dash.users.indicator.approved') }}
</dt>
<dd class="user-profile-field-value">
{{ $t('general.' + (user.adminData.is_approved ? 'yes' : 'no')) }}
</dd>
</dl>
<dl class="user-profile-field">
<dt class="user-profile-field-name">
{{ $t('admin_dash.users.indicator.suggested') }}
</dt>
<dd class="user-profile-field-value">
{{ $t('general.' + (user.adminData.is_suggested ? 'yes' : 'no')) }}
</dd>
</dl>
<details
v-if="user.is_local"
open
>
<summary>
{{ $t('user_card.admin_data.registration_reason') }}
</summary>
<span>
{{ user.adminData.registration_reason == null ? $t('general.not_available') : user.adminData.registration_reason }}
</span>
</details>
<details open>
<summary>
{{ $t('user_card.admin_data.tags') }}
</summary>
<ul>
<li v-if="user.adminData.tags.length === 0">
{{ $t('general.none') }}
</li>
<li
v-for="tag in user.adminData.tags"
:key="tag"
>
<code>
- {{ tag }}
+ {{ tag }}
</code>
{{ ' ' }}
</li>
</ul>
</details>
</div>
</details>
</div>
<h3 v-if="editable">
<span>
{{ $t('settings.bio') }}
</span>
{{ ' ' }}
<button
class="button-default"
@click="editingBio = !editingBio"
>
{{ $t('settings.toggle_edit') }}
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="pencil"
/>
</button>
</h3>
<template v-if="!editable || !editingBio">
<RichContent
v-if="!hideBio"
class="user-card-bio"
:class="{ '-justify-left': mergedConfig.userCardLeftJustify }"
:html="editable ? escapedNewBio : user.description_html"
:emoji="editable ? emoji : user.emoji"
:allow-non-square-emoji="allowNonSquareEmoji"
:handle-links="true"
/>
</template>
<template v-else-if="editingBio">
<EmojiInput
v-model="newBio"
enable-emoji-picker
class="user-card-bio"
:class="{ '-justify-left': mergedConfig.userCardLeftJustify }"
:suggest="emojiUserSuggestor"
>
<template #default="inputProps">
<textarea
v-model="newBio"
class="input bio resize-height"
v-bind="propsToNative(inputProps)"
:rows="newBio.split(/\n/g).length"
/>
</template>
</EmojiInput>
</template>
<h3 v-if="editable">
<span>
{{ $t('settings.profile_fields.label') }}
</span>
{{ ' ' }}
<button
class="button-default"
@click="editingFields = !editingFields"
>
{{ $t('settings.toggle_edit') }}
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="pencil"
/>
</button>
</h3>
<template v-if="!editable || !editingFields">
<div
v-if="!hideBio && user.fields_html && user.fields_html.length > 0"
class="user-profile-fields"
>
<dl
v-for="(field, index) in (editable ? newFields : user.fields_html)"
:key="index"
class="user-profile-field"
>
<dt
:title="field.name"
class="user-profile-field-name"
>
<RichContent
:html="field.name"
:emoji="editable ? emoji : user.emoji"
:allow-non-square-emoji="allowNonSquareEmoji"
/>
</dt>
<dd
:title="field.value"
class="user-profile-field-value"
>
<RichContent
:html="field.value"
:emoji="editable ? emoji : user.emoji"
:allow-non-square-emoji="allowNonSquareEmoji"
/>
</dd>
</dl>
</div>
</template>
<template v-else-if="editingFields">
<div
v-if="maxFields > 0"
class="user-profile-fields"
>
<dl
v-for="(_, i) in newFields"
:key="i"
class="user-profile-field"
>
<dt
class="user-profile-field-name -edit"
>
<EmojiInput
v-model="newFields[i].name"
enable-emoji-picker
:suggest="emojiSuggestor"
>
<template #default="inputProps">
<input
v-model="newFields[i].name"
:placeholder="$t('settings.profile_fields.name')"
v-bind="propsToNative(inputProps)"
class="input"
>
</template>
</EmojiInput>
</dt>
<dd
class="user-profile-field-value -edit"
>
<EmojiInput
v-model="newFields[i].value"
enable-emoji-picker
:suggest="emojiSuggestor"
>
<template #default="inputProps">
<input
v-model="newFields[i].value"
:placeholder="$t('settings.profile_fields.value')"
v-bind="propsToNative(inputProps)"
class="input input"
>
</template>
</EmojiInput>
<button
class="delete-field button-default -hover-highlight"
@click="deleteField(i)"
>
<!-- TODO something is wrong with v-show here -->
<FAIcon
v-if="newFields.length > 1"
icon="times"
/>
</button>
</dd>
</dl>
<button
v-if="newFields.length < maxFields"
class="user-profile-field-add add-field button-default -hover-highlight"
@click="addField"
>
<FAIcon
icon="plus"
class="icon"
/>
<span class="label">
{{ $t("settings.profile_fields.add_field") }}
</span>
</button>
</div>
</template>
<div
v-if="!hideBio"
class="user-extras"
>
<span
v-if="!editable && !hideUserStats"
class="user-stats"
>
<dl
v-if="!hideUserStats && !hideBio"
class="user-count"
>
<dd>{{ user.statuses_count }}</dd>
{{ ' ' }}
<dt>{{ $t('user_card.statuses') }}</dt>
</dl>
<dl class="user-count">
<dd>{{ dailyAvg }}</dd>
{{ ' ' }}
<dt>{{ $t('user_card.statuses_per_day') }}</dt>
</dl>
<dl class="user-count">
<dd>{{ hideFollowsCount ? $t('user_card.hidden') : user.friends_count }}</dd>
{{ ' ' }}
<dt>{{ $t('user_card.followees') }}</dt>
</dl>
<dl class="user-count">
<dd>{{ hideFollowersCount ? $t('user_card.hidden') : user.followers_count }}</dd>
{{ ' ' }}
<dt>{{ $t('user_card.followers') }}</dt>
</dl>
</span>
<span
v-if="!hideUserStats"
class="user-stats"
>
<template v-if="!hideBio">
<dl
v-if="user.birthday && !editable"
class="user-count"
>
<dd>
<FAIcon
class="fa-old-padding"
icon="birthday-cake"
/>
</dd>
{{ ' ' }}
<dt>
{{ $t('user_card.birthday', { birthday: formattedBirthday }) }}
</dt>
</dl>
<div
v-else-if="editable"
class="birthday"
>
<div>
<Checkbox v-model="newShowBirthday">
{{ $t('settings.birthday.show_birthday') }}
</Checkbox>
</div>
<FAIcon
class="fa-old-padding"
icon="birthday-cake"
/>
{{ $t('settings.birthday.label') }}
<input
id="birthday"
v-model="newBirthday"
type="date"
class="input birthday-input"
>
</div>
</template>
<dl
v-if="!editable"
class="user-count"
>
<dd>
{{ $t('user_card.joined') }}
</dd>
{{ ' ' }}
<dt>
{{ formattedJoinDate }}
</dt>
</dl>
</span>
</div>
<template v-if="editable">
<h3>{{ $t('settings.profile_other') }}</h3>
<p
v-if="role === 'admin' || role === 'moderator'"
class="user-card-setting"
>
<Checkbox v-model="newShowRole">
<template v-if="role === 'admin'">
{{ $t('settings.show_admin_badge') }}
</template>
<template v-if="role === 'moderator'">
{{ $t('settings.show_moderator_badge') }}
</template>
</Checkbox>
</p>
<p class="user-card-setting">
<label>
{{ $t('settings.actor_type') }}
<Select v-model="newActorType">
<option
v-for="option in availableActorTypes"
:key="option"
:value="option"
>
{{ $t('settings.actor_type_' + (option === 'Person' ? 'person_proper' : option)) }}
</option>
</Select>
<div v-if="groupActorAvailable">
<small>
{{ $t('settings.actor_type_description') }}
</small>
</div>
</label>
</p>
<div class="bottom-buttons">
<button
v-if="editable"
:disabled="!somethingToSave"
class="btn button-default reset-profile-button"
@click="resetState"
>
{{ $t('settings.reset') }}
<FAIcon
fixed-width
class="icon"
icon="clock-rotate-left"
:title="$t('user_card.edit_profile')"
/>
</button>
<button
v-if="editable"
:disabled="!somethingToSave"
class="btn button-default save-profile-button"
@click="updateProfile"
>
{{ $t('settings.save') }}
<FAIcon
fixed-width
class="icon"
icon="save"
:title="$t('user_card.edit_profile')"
/>
</button>
</div>
</template>
<teleport to="#modal">
<UserTimedFilterModal
v-if="isOtherUser"
ref="timedMuteDialog"
:user="user"
:is-mute="true"
/>
</teleport>
<teleport to="#modal">
<DialogModal
v-if="editImage"
class="edit-image"
>
<template #header>
{{ editImage === 'avatar' ? $t('settings.change_avatar') : $t('settings.change_banner') }}
</template>
<p>
{{ editImage === 'avatar' ? $t('settings.avatar_size_instruction') : $t('settings.banner_size_instruction' ) }}
</p>
<div
class="image-container"
:class="{ '-banner': editImage === 'banner' }"
>
<image-cropper
ref="cropper"
class="cropper"
:aspect-ratio="editImage === 'avatar' ? 1 : 3"
@submit="submitImage"
/>
</div>
<button
id="pick-image"
class="button-default btn"
type="button"
@click="() => $refs.cropper.pickImage()"
>
{{ $t('settings.select_picture') }}
</button>
<template #footer>
<button
class="button-default btn"
type="button"
@click="editImage = false"
>
{{ $t('image_cropper.cancel') }}
</button>
<button
:title="editImage === 'avatar' ? $t('settings.reset_avatar') : $t('settings.reset_banner')"
class="button-default btn reset-button"
@click="resetImage"
>
{{ editImage === 'avatar' ? $t('settings.reset_avatar') : $t('settings.reset_banner' ) }}
</button>
<button
class="button-default btn"
type="button"
@click="$refs.cropper.submit(false)"
>
{{ $t('image_cropper.save_without_cropping') }}
</button>
<button
class="button-default btn"
type="button"
@click="$refs.cropper.submit(true)"
>
{{ $t('image_cropper.save') }}
</button>
</template>
</DialogModal>
</teleport>
</div>
</template>
<script src="./user_card.js"></script>
<style lang="scss" src="./user_card.scss" />
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 3d8db1b254..d2d766a7f3 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -1,211 +1,210 @@
import { get } from 'lodash'
import { mapState } from 'pinia'
import FollowCard from 'src/components/follow_card/follow_card.vue'
import List from 'src/components/list/list.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import Timeline from 'src/components/timeline/timeline.vue'
import UserCard from 'src/components/user_card/user_card.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
library.add(faCircleNotch)
const defaultTabKey = 'statuses'
const UserProfile = {
data() {
return {
error: false,
userId: null,
tab: defaultTabKey,
footerRef: null,
}
},
created() {
const routeParams = this.$route.params
this.load({ name: routeParams.name, id: routeParams.id })
this.tab = get(this.$route, 'query.tab', defaultTabKey)
useInterfaceStore().setForeignProfileBackground(this.user?.background_image)
},
updated() {
useInterfaceStore().setForeignProfileBackground(this.user?.background_image)
},
unmounted() {
this.stopFetching()
useInterfaceStore().setForeignProfileBackground(null)
this.$store.dispatch('clearFollowers', this.userId)
this.$store.dispatch('clearFriends', this.userId)
},
computed: {
timeline() {
return this.$store.state.statuses.timelines.user
},
favorites() {
return this.$store.state.statuses.timelines.favorites
},
media() {
return this.$store.state.statuses.timelines.media
},
isUs() {
return (
this.userId &&
this.$store.state.users.currentUser.id &&
this.userId === this.$store.state.users.currentUser.id
)
},
user() {
return this.$store.getters.findUser(this.userId)
},
isExternal() {
return this.$route.name === 'external-user-profile'
},
followsTabVisible() {
return this.isUs || !this.user.hide_follows
},
followersTabVisible() {
return this.isUs || !this.user.hide_followers
},
favoritesTabVisible() {
return (
this.isUs ||
(useInstanceCapabilitiesStore().pleromaPublicFavouritesAvailable &&
!this.user.hide_favorites)
)
},
compactProfiles() {
return useMergedConfigStore().mergedConfig.compactProfiles
},
friends() {
return get(
this.$store.getters.findUser(this.userId),
'friendIds',
[],
).map((id) => this.$store.getters.findUser(id))
},
followers() {
return get(
this.$store.getters.findUser(this.userId),
'followerIds',
[],
).map((id) => this.$store.getters.findUser(id))
},
},
methods: {
setFooterRef(el) {
this.footerRef = el
},
fetchUsers(group) {
return () =>
this.$store
.dispatch('fetch' + group, this.userId)
.then((result) => ({ items: result }))
},
load(userNameOrId) {
const startFetchingTimeline = (timeline, userId) => {
// Clear timeline only if load another user's profile
if (userId !== this.$store.state.statuses.timelines[timeline].userId) {
this.$store.commit('clearTimeline', { timeline })
}
this.$store.dispatch('startFetchingTimeline', { timeline, userId })
}
const loadById = (userId) => {
this.userId = userId
startFetchingTimeline('user', userId)
startFetchingTimeline('media', userId)
if (this.isUs) {
startFetchingTimeline('favorites')
} else if (!this.user.hide_favorites) {
startFetchingTimeline('favorites', userId)
}
// Fetch all pinned statuses immediately
this.$store.dispatch('fetchPinnedStatuses', userId)
}
// Reset view
this.userId = null
this.error = false
const maybeId = userNameOrId.id
const maybeName = userNameOrId.name
// Check if user data is already loaded in store
const user = maybeId
? this.$store.getters.findUser(maybeId)
: this.$store.getters.findUserByName(maybeName)
if (user) {
loadById(user.id)
} else {
;(maybeId
? this.$store.dispatch('fetchUser', maybeId)
: this.$store.dispatch('fetchUserByName', maybeName)
)
.then(({ id }) => loadById(id))
.catch((reason) => {
const errorMessage = get(reason, 'error.error')
if (errorMessage === 'No user with such user_id') {
// Known error
this.error = this.$t('user_profile.profile_does_not_exist')
} else if (errorMessage) {
this.error = errorMessage
} else {
this.error = this.$t('user_profile.profile_loading_error')
}
})
}
},
stopFetching() {
this.$store.dispatch('stopFetchingTimeline', 'user')
this.$store.dispatch('stopFetchingTimeline', 'favorites')
this.$store.dispatch('stopFetchingTimeline', 'media')
},
switchUser(userNameOrId) {
this.stopFetching()
this.load(userNameOrId)
},
onTabSwitch(tab) {
this.tab = tab
this.$router.replace({ query: { tab } })
},
linkClicked({ target }) {
if (target.tagName === 'SPAN') {
target = target.parentNode
}
if (target.tagName === 'A') {
window.open(target.href, '_blank')
}
},
},
watch: {
'$route.params.id': function (newVal) {
if (newVal) {
this.switchUser({ id: newVal })
}
},
'$route.params.name': function (newVal) {
if (newVal) {
this.switchUser({ name: newVal })
}
},
'$route.query': function (newVal) {
this.tab = newVal.tab || defaultTabKey
},
},
components: {
UserCard,
Timeline,
List,
FollowCard,
TabSwitcher,
- Conversation,
},
}
export default UserProfile
diff --git a/src/components/user_profile/user_profile_admin_view.vue b/src/components/user_profile/user_profile_admin_view.vue
index 992ce3b4b2..47a23dd354 100644
--- a/src/components/user_profile/user_profile_admin_view.vue
+++ b/src/components/user_profile/user_profile_admin_view.vue
@@ -1,32 +1,35 @@
<template>
<div
v-if="user"
class="user-profile -admin-view panel panel-default"
>
<div class="panel-body card-wrapper">
<UserCard
:user-id="userId"
:compact="true"
hide-bio
hide-buttons
/>
- <Checkbox class="godmode" v-model="godmode">
+ <Checkbox
+ v-model="godmode"
+ class="godmode"
+ >
{{ $t('admin_dash.users.godmode') }}
</Checkbox>
</div>
<List
ref="list"
:fetch-function="fetchStatuses"
- @select="onSelect"
scrollable
+ @select="onSelect"
>
<template #item="{item}">
<Status :statusoid="item" />
</template>
</List>
</div>
</template>
<script src="./user_profile_admin_view.js"></script>
<style src="./user_profile.scss" lang="scss"></style>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Oct 30, 8:14 AM (20 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1799860
Default Alt Text
(63 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline