This commit is contained in:
Henry Jameson 2026-06-08 20:31:42 +03:00
commit 7d3f46c529
13 changed files with 137 additions and 828 deletions

View file

@ -57,7 +57,7 @@ const List = {
return new Set(this.finalItems.map(this.getKey))
},
filteredSelected() {
return [ ...this.allKeys.values().filter((key) => this.selected.has(key))]
return [...this.allKeys.values().filter((key) => this.selected.has(key))]
},
allSelected() {
return this.selected.size === this.finalItems.length
@ -70,7 +70,7 @@ const List = {
},
finalItems() {
return this.externalItems || this.items
}
},
},
created() {
window.addEventListener('scroll', this.scrollLoad)

View file

@ -1,5 +1,5 @@
<template>
<basic-user-card :user="user">
<BasicUserCard :user="user">
<div class="mute-card-content-container">
<span
v-if="muted && muteExpiryAvailable"
@ -30,7 +30,7 @@
:is-mute="true"
/>
</teleport>
</basic-user-card>
</BasicUserCard>
</template>
<script src="./mute_card.js"></script>

View file

@ -1,291 +1,49 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import GenericConfirm from 'src/components/confirm_modal/generic_confirm.vue'
import TextConfirm from 'src/components/confirm_modal/text_confirm.vue'
import Modal from 'src/components/modal/modal.vue'
import List from 'src/components/list/list.vue'
import Popover from 'src/components/popover/popover.vue'
import Select from 'src/components/select/select.vue'
import AdminStatusCard from 'src/components/settings_modal/admin_tabs/admin_status_card.vue'
import BasicUserCard from '../../basic_user_card/basic_user_card.vue'
import { defineAsyncComponent } from 'vue'
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import { useAdminUsersStore } from 'src/stores/adminUsers.js'
const AdminCard = {
props: {
/**
* minimal user info
* @type {import('vue').PropType<{
* id: string,
* _original: {
* is_approved: boolean;
* is_confirmed: boolean;
* };
* }>}
*/
userDetails: {
type: Object,
required: true,
/**
* @param {any} u
* @returns {u is { id: string; _original: { is_approved; is_confirmed: boolean; } } }
*/
validator(u) {
return (
typeof u.id === 'string' &&
typeof u._original === 'object' &&
typeof u._original.is_approved === 'boolean' &&
typeof u._original.is_confirmed === 'boolean'
)
},
},
},
data() {
return {
progress: false,
detailsExpanded: false,
topLevelExpanded: false, // REMOVE
jsonExpanded: false,
timelineExpanded: false,
justApproved: false,
justConfirmed: false,
justDeleted: false,
showDirect: false,
showReblogs: false,
timelineSorting: 'des',
}
},
computed: {
/**
* checks if the user is defined
* @returns {boolean}
*/
isLoaded() {
return typeof this.user !== 'undefined'
},
/**
* @returns {object} user info
*/
user() {
return this.$store.getters.findUser(this.userDetails.id)
},
/**
* @returns {object} user relationship
*/
relationship() {
return this.$store.getters.relationship(this.userDetails.id)
},
/**
* @returns {boolean} is user local
*/
isLocal() {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof u !== 'undefined') {
return u.is_local === true
}
return false
},
/**
* @returns {boolean} is user admin
*/
isAdmin() {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof u !== 'undefined') {
return u.rights.admin === true
}
return false
},
/**
* @returns {boolean} is user moderator
*/
isModerator() {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof u !== 'undefined') {
return u.rights.moderator === true
}
return false
},
/**
* @returns {boolean} is user active
*/
isActivated() {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof u !== 'undefined') {
return u.deactivated === false
}
return false
},
/**
* @returns {boolean} has this user been confirmed
*/
isConfirmed() {
const u = this.$store.getters.findUser(this.userDetails.id)
return u._original.is_confirmed === true || this.justConfirmed === true
},
/**
* @returns {boolean} has this user been approved
*/
isApproved() {
return (
this.userDetails._original.is_approved === true ||
this.justApproved === true
)
userId: {
type: String
},
},
components: {
BasicUserCard,
Checkbox,
List,
AdminStatusCard,
Modal,
Popover,
GenericConfirm,
Select,
TextConfirm,
ModerationTools: defineAsyncComponent(
() => import('src/components/moderation_tools/moderation_tools.vue'),
),
},
methods: {
/**
* @param {boolean} v set admin status
*/
setAdmin(v) {
const u = this.$store.getters.findUser(this.userDetails.id)
if (v === true) {
this.$store.dispatch('adminAddUserToAdminGroup', u)
} else {
this.$store.dispatch('adminRemoveUserFromAdminGroup', u)
}
computed: {
user() {
return this.$store.getters.findUser(this.userId)
},
/**
* @param {boolean} v set moderator status
*/
setModerator(v) {
const u = this.$store.getters.findUser(this.userDetails.id)
if (v === true) {
this.$store.dispatch('adminAddUserToModeratorGroup', u)
} else {
this.$store.dispatch('adminRemoveUserFromModeratorGroup', u)
}
userAdminData() {
return useAdminUsersStore().getUser(this.userId)
},
/**
* @param {boolean} v set activation status
*/
setActivation(v) {
const u = this.$store.getters.findUser(this.userDetails.id)
if (v === true) {
this.$store.dispatch('adminActivateUser', u)
} else {
this.$store.dispatch('adminDeactivateUser', u)
}
relationship() {
return this.$store.getters.relationship(this.userId)
},
/**
* confirm this user
*/
confirmUser() {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminConfirmUser', u)
this.just_confirmed = true
isLocal() {
return this.user.is_local
},
/**
* try resending the confirmation email
*/
resendConfirmationEmail() {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminResendConfirmationEmail', u)
isAdmin() {
return this.user.rights.admin
},
/**
* approve this user
*/
approveUser() {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminApproveUser', u)
isModerator() {
return this.user.rights.moderator
},
/**
* update user info from server
*/
forceUpdateUser() {
this.$store.dispatch('fetchUser', this.userDetails.id)
isActivated() {
return !this.user.deactivated
},
/**
* delete selected statuses
*/
deleteSelection() {
const l = this.$refs.timelineList
const s = l.getSelected()
s.forEach((p) => this.$store.dispatch('deleteStatus', p))
l.reset()
},
/**
* delete this user. keep in mind that user deletion is not intuitive in pleroma backend.
* it actually deletes all content of a user. the user itself will keep showing up in search results.
*/
deleteUser() {
if (!this.justDeleted) {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminDeleteUser', u)
this.justDeleted = true
}
},
/**
* @param {string} text name of tag to be added to user
*/
addUserTag(text) {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store
.dispatch('adminTagUser', { user: u, tag: text })
.then(() => this.$store.dispatch('fetchUser', this.userDetails.id))
},
/**
* @param {string} text name of tag to be removed from user
*/
removeUserTag(text) {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store
.dispatch('adminUntagUser', { user: u, tag: text })
.then(() => this.$store.dispatch('fetchUser', this.userDetails.id))
},
/**
* @param {object} store
* @param {object} opts
* @returns {Promise<Array<object>>} statuses
*/
async fetchStatuses(store, opts) {
const u = this.$store.getters.findUser(this.userDetails.id)
const res = store.dispatch('adminListStatuses', {
user: u,
opts: {
pageSize: opts.pageSize,
godmode: this.showDirect,
withReblogs: this.showReblogs,
},
})
return res.then((r) => {
const a = r.activities
console.log(this.timelineSorting)
if (this.timelineSorting === 'des') {
return [...a].sort(
(a, b) => new Date(b.created_at) - new Date(a.created_at),
)
} else if (this.timelineSorting === 'asc') {
return [...a].sort(
(a, b) => new Date(a.created_at) - new Date(b.created_at),
)
} else return []
})
},
confirmAction(box) {
this.$refs[box].show()
this.$refs.dropdownuser.hidePopover()
},
userActionConfirmed(action) {
this.$store.dispatch(
action,
this.$store.getters.findUser(this.userDetails.id),
)
},
statusActionConfirmed(action, opts) {
const s = this.$refs.statusList.getSelected()
s.forEach((p) => {
this.$store.dispatch(action, { id: p.id, ...(opts || {}) })
})
this.reset()
isApproved() {
return this.userAdminData.is_approved
},
isConfirmed() {
return this.userAdminData.is_confirmed
}
},
}

View file

@ -1,19 +1,9 @@
.inline-layout {
display: flex;
align-items: center;
.AdminCard {
width: 100%;
gap: 8px;
}
.alert {
text-shadow: none;
}
.user-role {
display: inline-block;
vertical-align: baseline;
}
.modalfix::before {
opacity: 1.0;
.right-side {
align-items: baseline;
justify-content: end;
display: flex;
}
}

View file

@ -1,528 +1,56 @@
<template>
<div v-if="!isLoaded">
<template v-if="!user">
<FAIcon
icon="circle-notch"
spin
size="lg"
/>
</div>
<div v-else>
<div class="inline-layout">
<BasicUserCard :user="user" />
<label
v-if="isAdmin"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.admin') }}
</label>
<label
v-if="isModerator"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.moderator') }}
</label>
<label
v-if="isActivated"
class="alert info 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="isConfirmed"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.confirmed') }}
</label>
<button
class="button button-default btn"
type="button"
@click="detailsExpanded = true"
>
{{ $t('admin_dash.users.details.button') }}
</button>
<Popover
ref="dropdownuser"
trigger="click"
placement="top"
>
<template #trigger>
<button
class="button button-default btn"
>
{{ $t('admin_dash.users.actions.title') }}
</button>
</template>
<template #content>
<div
v-if="!isActivated"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmActivate')"
>
{{ $t('admin_dash.users.activate') }}
</button>
</div>
</div>
<div
v-if="isActivated"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmDeactivate')"
>
{{ $t('admin_dash.users.actions.deactivate') }}
</button>
</div>
</div>
<div class="dropdown-menu">
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmDeleteUser')"
>
{{ $t('admin_dash.users.actions.delete_user') }}
</button>
</div>
</div>
<div
v-if="!isAdmin"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmGrantAdmin')"
>
{{ $t('admin_dash.users.actions.grant_admin') }}
</button>
</div>
</div>
<div
v-if="isAdmin"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmRevokeAdmin')"
>
{{ $t('admin_dash.users.actions.revoke_admin') }}
</button>
</div>
</div>
<div
v-if="!isModerator"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmGrantModerator')"
>
{{ $t('admin_dash.users.actions.grant_moderator') }}
</button>
</div>
</div>
<div
v-if="isModerator"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmRevokeModerator')"
>
{{ $t('admin_dash.users.actions.revoke_moderator') }}
</button>
</div>
</div>
<div
v-if="isApproved"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmApprove')"
>
{{ $t('admin_dash.users.actions.approve') }}
</button>
</div>
</div>
<div
v-if="isConfirmed"
class="dropdown-menu"
>
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmConfirm')"
>
{{ $t('admin_dash.users.actions.confirm') }}
</button>
</div>
</div>
<div class="dropdown-menu">
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmResendConfirmationEmail')"
>
{{ $t('admin_dash.users.actions.resend_confirmation_email') }}
</button>
</div>
</div>
<div class="dropdown-menu">
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmRequirePasswordChange')"
>
{{ $t('admin_dash.users.actions.require_password_change') }}
</button>
</div>
</div>
<div class="dropdown-menu">
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmDisableMFA')"
>
{{ $t('admin_dash.users.actions.disable_mfa') }}
</button>
</div>
</div>
</template>
</Popover>
</div>
<div
v-if="detailsExpanded"
</template>
<template v-else>
<BasicUserCard
class="AdminCard"
:user="user"
>
<Modal
class="settings-modal"
:no-background="false"
@backdrop-clicked="() => { detailsExpanded = false }"
>
<div class="settings-modal-panel panel">
<div class="panel-heading">
<h1 class="title">
{{ $t('admin_dash.users.details.title') }}
</h1>
<button
class="btn button-default"
:title="$t('general.close')"
@click="() => { detailsExpanded = false }"
>
<FAIcon
icon="times"
fixed-width
/>
</button>
</div>
<div
class="panel-body"
style="overflow-y: auto;"
>
<h2 class="title">
{{ $t('admin_dash.users.details.overview') }}
</h2>
<ul
class="setting-list"
style="columns: 2;"
>
<li>
{{ $t('admin_dash.users.details.id') }}
</li>
<li>
{{ $t('admin_dash.users.details.actor_type') }}
</li>
<li>
{{ $t('admin_dash.users.details.roles') }}
</li>
<li>
{{ $t('admin_dash.users.details.account_type') }}
</li>
<li>
{{ $t('admin_dash.users.details.status') }}
</li>
<li>
{{ user.id }}
</li>
<li>
{{ $t('admin_dash.users.details.actor_types.' + user.actor_type.toLowerCase()) }}
</li>
<li>
<span v-if="user.rights.admin === true"> {{ $t('admin_dash.users.details.admin') }} </span>
<span v-if="user.rights.admin === true && user.rights.moderator === true"> ,&nbsp; </span>
<span v-if="user.rights.moderator === true"> {{ $t('admin_dash.users.details.moderator') }} </span>
</li>
<li>
<span v-if="user.is_local"> {{ $t('admin_dash.users.details.local') }} </span>
<span v-else> {{ $t('admin_dash.users.details.remote') }} </span>
</li>
<li>
<span v-if="user.deactivated === false"> {{ $t('admin_dash.users.details.active') }} </span>
<span v-else> {{ $t('admin_dash.users.details.inactive') }} </span>
</li>
</ul>
<h2 class="title">
{{ $t('admin_dash.users.details.tags') }}
</h2>
<ul class="setting-list">
<li
v-for="tag in user.tags"
:key="tag"
>
{{ tag }}
<button
class="button button-default btn"
@click="removeUserTag(tag)"
>
<FAIcon
icon="minus"
size="lg"
/>
</button>
</li>
</ul>
<button
class="button button-default btn"
@click="$refs.addTextBox.show()"
>
{{ $t('admin_dash.users.tags.add_new') }}
<FAIcon
icon="plus"
size="lg"
/>
</button>
<PageList
ref="timelineList"
:refresh="true"
:get-key="i => i"
:box-only="true"
:page-size="20"
:single-page="true"
:fetch-page="(store, opts) => fetchStatuses(store, opts)"
>
<template #header>
<Checkbox
v-model="showDirect"
@update:model-value="() => $refs.timelineList.reset()"
>
{{ $t('admin_dash.users.filters.show_direct') }}
</Checkbox>
<Checkbox
v-model="showReblogs"
@update:model-value="() => $refs.timelineList.reset()"
>
{{ $t('admin_dash.users.filters.show_reblogs') }}
</Checkbox>
<Select
v-model="timelineSorting"
@update:model-value="() => $refs.timelineList.reset()"
>
<option value="asc">
{{ $t('admin_dash.users.filters.ascending') }}
</option>
<option value="des">
{{ $t('admin_dash.users.filters.descending') }}
</option>
</Select>
<Popover
ref="dropdownstatus"
trigger="click"
placement="top"
>
<template #trigger>
<button
class="button button-default btn"
>
{{ $t('admin_dash.users.actions.title') }}
</button>
</template>
<p> wrap </p>
<template #content>
<div class="dropdown-menu">
<div class="menu-item dropdown-item">
<button
class="main-button"
@click="confirmAction('confirmDeleteStatus')"
>
{{ $t('admin_dash.users.delete_status') }}
</button>
</div>
<p> set sensitive </p>
<p> unset sensitive </p>
<p> make public </p>
<p> make unlisted </p>
<p> make private </p>
<p> make direct </p>
</div>
</template>
</Popover>
</template>
<template #item="{item}">
<AdminStatusCard
:status-details="item"
style="width: 100%"
/>
</template>
<template #empty>
<p> {{ $t('admin_dash.users.user_has_no_posts') }} </p>
</template>
<template #load>
<FAIcon
icon="circle-notch"
spin
size="lg"
/>
</template>
</PageList>
</div>
</div>
</Modal>
</div>
</div>
<GenericConfirm
ref="confirmActivate"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.activate')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminActivateUser')"
/>
<GenericConfirm
ref="confirmDeactivate"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.deactivate')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminDeactivateUser')"
/>
<GenericConfirm
ref="confirmDeleteUser"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.delete_user')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminDeleteUser')"
/>
<GenericConfirm
ref="confirmGrantAdmin"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.grant_admin')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminAddUserToAdminGroup')"
/>
<GenericConfirm
ref="confirmRevokeAdmin"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.revoke_admin')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminRemoveUserFromAdminGroup')"
/>
<GenericConfirm
ref="confirmGrantModerator"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.grant_moderator')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminAddUserToModeratorGroup')"
/>
<GenericConfirm
ref="confirmRevokeModerator"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.revoke_moderator')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminRemoveUserFromModeratorGroup')"
/>
<GenericConfirm
ref="confirmApprove"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.approve')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminApproveUser')"
/>
<GenericConfirm
ref="confirmConfirm"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.confirm')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminConfirmUser')"
/>
<GenericConfirm
ref="confirmResendConfirmationEmail"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.resend_confirmation_email')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminResendConfirmationEmail')"
/>
<GenericConfirm
ref="confirmRequirePasswordChange"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.require_password_change')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminRequirePasswordChange')"
/>
<GenericConfirm
ref="confirmDisableMFA"
style="z-index: 10000;"
:title="$t('admin_dash.users.actions.confirm_single.title')"
:message="$t('admin_dash.users.actions.confirm_single.disable_mfa')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="userActionConfirmed('adminDisableMFA')"
/>
<TextConfirm
ref="addTextBox"
style="z-index: 10001;"
:title="$t('admin_dash.users.tags.add_new')"
:message="$t('admin_dash.users.tags.new_title')"
:cancel-text="$t('admin_dash.users.actions.no')"
:confirm-text="$t('admin_dash.users.actions.yes')"
@action="addUserTag"
/>
<div class="right-side">
<label
v-if="isAdmin"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.admin') }}
</label>
<label
v-if="isModerator"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.moderator') }}
</label>
<label
v-if="isActivated"
class="alert info 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="isConfirmed"
class="alert neutral user-role"
>
{{ $t('admin_dash.users.indicator.confirmed') }}
</label>
<ModerationTools
class="moderation-menu"
:user="user"
/>
</div>
</BasicUserCard>
</template>
</template>
<script src="./admin_card.js"></script>
<style lang="scss" src="./admin_card.scss"></style>
<style lang="scss" src="../settings_modal.scss"></style>
<!--<style lang="scss">
.admin-card-content-container {
margin-top: 0.5em;
text-align: right;
button {
width: 10em;
}
}
</style>-->
<style lang="scss" src="./admin_card.scss"></style>

View file

@ -10,6 +10,8 @@ import Select from 'src/components/select/select.vue'
import AdminCard from 'src/components/settings_modal/admin_tabs/admin_card.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import { useAdminUsersStore } from 'src/stores/adminUsers.js'
const UsersTab = {
provide() {
return {
@ -113,9 +115,7 @@ const UsersTab = {
},
methods: {
fetchUsers(page) {
console.log(page)
return this.$store
.dispatch('fetchAdminUsers', {
return useAdminUsersStore().fetchAdminUsers({
...this.fetchOptions,
page,
})
@ -148,10 +148,10 @@ const UsersTab = {
},
},
watch: {
fetchOptions () {
fetchOptions() {
this.$refs.usersList.reset()
}
}
},
},
}
export default UsersTab

View file

@ -242,7 +242,11 @@
</Popover>
</template>
<template #item="{item}">
<AdminCard :user-details="item" />
<AdminCard
:user-id="item.id"
:confirmed="item.is_confirmed"
:suggested="item.is_suggested"
/>
</template>
<template #load>
<span> loading </span>

View file

@ -1,4 +1,4 @@
import { get, map, reject, isEmpty } from 'lodash'
import { get, isEmpty, map, reject } from 'lodash'
import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
import BlockCard from 'src/components/block_card/block_card.vue'

View file

@ -27,7 +27,8 @@
width: 10em;
}
.blocks, .mutes {
.blocks,
.mutes {
display: flex;
flex-direction: column;
min-height: 100%;

View file

@ -103,10 +103,10 @@ const UserProfile = {
this.footerRef = el
},
fetchUsers(group) {
return () => this
.$store
.dispatch('fetch' + group, this.userId)
.then((result) => ({ items: result }))
return () =>
this.$store
.dispatch('fetch' + group, this.userId)
.then((result) => ({ items: result }))
},
load(userNameOrId) {
const startFetchingTimeline = (timeline, userId) => {

View file

@ -151,9 +151,9 @@ const adminSettingsStorage = {
adminApproveUser(store, user) {
return store.rootState.api.backendInteractor.adminApproveUser({ user })
},
adminListStatuses(store, { user, opts }) {
adminListStatuses(store, { userId, opts }) {
return store.rootState.api.backendInteractor.adminListStatuses({
user,
userId,
opts,
})
},

View file

@ -1740,17 +1740,19 @@ const adminApproveUser = ({ user: { screen_name: nickname }, credentials }) => {
}
const adminListStatuses = ({
user: { id },
opts: { pageSize, godmode, withReblogs },
userId,
pageSize = 20,
godmode,
withReblogs,
credentials,
}) => {
const url = PLEROMA_ADMIN_LIST_STATUSES_URL(
id,
userId,
pageSize,
godmode,
withReblogs,
)
return promisedRequest({ url: url, credentials, method: 'GET' })
return promisedRequest({ url, credentials, method: 'GET' })
}
const adminChangeStatusScope = ({

26
src/stores/adminUsers.js Normal file
View file

@ -0,0 +1,26 @@
import { defineStore } from 'pinia'
export const useAdminUsersStore = defineStore('adminUsers', {
state: () => ({
users: new Map()
}),
getters: {
getUser(state) {
return (id) => state.users.get(id)
},
},
actions: {
async fetchAdminUsers(opts) {
const data = await window.vuex.state.api.backendInteractor.adminListUsers({
opts,
})
data.users.forEach((user) => {
window.vuex.dispatch('fetchUserIfMissing', user.id),
this.users.set(user.id, user)
})
return data
},
},
})