adding jsdoc

This commit is contained in:
luce 2025-09-09 11:38:25 +02:00
commit 05b4cbe6d6
5 changed files with 250 additions and 80 deletions

View file

@ -5,18 +5,30 @@ const PageList = {
SelectableList
},
props: {
/**
* only make the checkbox clickable to toggle, not the whole area
*/
boxOnly: {
type: Boolean,
default: false
},
/**
* how many entries to fetch at once
*/
pageSize: {
type: Number,
default: 50
},
/**
* the function/callback used to fetch new entries (one page)
*/
fetchPage: {
type: Function,
default: async () => []
},
/**
* wether or not this is a single page list (so it won't allow fetching more pages)
*/
singlePage: {
type: Boolean,
default: false
@ -31,6 +43,9 @@ const PageList = {
}
},
methods: {
/**
* reset and load first page
*/
reset () {
this.canLoadMore = true
this.pageIndex = 1
@ -38,6 +53,9 @@ const PageList = {
this.isLoading = false
this.loadMore() // load one page
},
/**
* load another page
*/
loadMore () {
if (!this.isLoading && this.canLoadMore) {
this.isLoading = true
@ -50,10 +68,17 @@ const PageList = {
})
}
},
/**
* get currently selected elements
* @returns {Array}
*/
getSelected () {
return this.$refs.list.selected
}
},
/**
* auto-load first page when mounted
*/
mounted () {
this.loadMore()
}

View file

@ -6,9 +6,23 @@ import Modal from 'src/components/modal/modal.vue'
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' &&
@ -22,7 +36,8 @@ const AdminCard = {
data () {
return {
progress: false,
topLevelExpanded: false,
detailsExpanded: false,
topLevelExpanded: false, // REMOVE
jsonExpanded: false,
timelineExpanded: false,
justApproved: false,
@ -31,15 +46,28 @@ const AdminCard = {
}
},
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') {
@ -47,6 +75,9 @@ const AdminCard = {
}
return false
},
/**
* @returns {boolean} is user admin
*/
isAdmin () {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof(u) !== 'undefined') {
@ -54,6 +85,9 @@ const AdminCard = {
}
return false
},
/**
* @returns {boolean} is user moderator
*/
isModerator () {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof(u) !== 'undefined') {
@ -61,6 +95,9 @@ const AdminCard = {
}
return false
},
/**
* @returns {boolean} is user active
*/
isActivated () {
const u = this.$store.getters.findUser(this.userDetails.id)
if (typeof(u) !== 'undefined') {
@ -68,10 +105,16 @@ const AdminCard = {
}
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)
}
@ -84,7 +127,10 @@ const AdminCard = {
Modal
},
methods: {
toggleAdmin (v) {
/**
* @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)
@ -92,7 +138,10 @@ const AdminCard = {
this.$store.dispatch('adminRemoveUserFromAdminGroup', u)
}
},
toggleModerator (v) {
/**
* @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)
@ -100,7 +149,10 @@ const AdminCard = {
this.$store.dispatch('adminRemoveUserFromModeratorGroup', u)
}
},
toggleActivation (v) {
/**
* @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)
@ -108,28 +160,47 @@ const AdminCard = {
this.$store.dispatch('adminDeactivateUser', u)
}
},
/**
* confirm this user
*/
confirmUser () {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminConfirmUser', u)
this.just_confirmed = true
},
/**
* try resending the confirmation email
*/
resendConfirmationEmail () {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminResendConfirmationEmail', u)
},
toggleApproval () {
/**
* approve this user
*/
approveUser () {
const u = this.$store.getters.findUser(this.userDetails.id)
this.$store.dispatch('adminApproveUser', u)
},
/**
* update user info from server
*/
forceUpdateUser () {
this.$store.dispatch('fetchUser', this.userDetails.id)
},
/**
* 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)
@ -137,7 +208,12 @@ const AdminCard = {
this.justDeleted = true
}
},
fetchStatuses (store, opts) {
/**
* @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: true, withReblogs: true}})
return res.then(r => r.activities)

View file

@ -5,37 +5,26 @@
</div>
<div v-else>
<BasicUserCard :user="user" />
<div v-if="!topLevelExpanded">
<button
class="button button-default btn"
type="button"
@click="topLevelExpanded = true"
>
{{ $t('admin_dash.users.expand_user') }}
</button>
</div>
<button
class="button button-default btn"
type="button"
@click="detailsExpanded = true"
>
{{ $t('admin_dash.users.details') }}
</button>
<div
v-else
v-if="detailsExpanded"
>
<Modal
@backdrop-clicked="() => { topLevelExpanded = false }"
@backdrop-clicked="() => { detailsExpanded = false }"
>
<ul class="setting-list">
<li>
<button
class="button button-default btn"
type="button"
@click="topLevelExpanded = false"
>
{{ $t('admin_dash.users.collapse_user') }}
</button>
</li>
<li
v-if="isLocal"
>
<Checkbox
:model-value="isAdmin"
@update:model-value="v => toggleAdmin(v)"
@update:model-value="v => setAdmin(v)"
>
{{ $t('admin_dash.users.is_admin') }}
</Checkbox>
@ -45,7 +34,7 @@
>
<Checkbox
:model-value="isModerator"
@update:model-value="v => toggleModerator(v)"
@update:model-value="v => setModerator(v)"
>
{{ $t('admin_dash.users.is_moderator') }}
</Checkbox>
@ -78,7 +67,7 @@
<button
class="button button-default btn"
type="button"
@click="toggleApproval(true)"
@click="approveUser()"
>
{{ $t('admin_dash.users.approve') }}
</button>
@ -86,7 +75,7 @@
<li>
<Checkbox
:model-value="isActivated"
@update:model-value="v => toggleActivation(v)"
@update:model-value="v => setActivation(v)"
>
{{ $t('admin_dash.users.is_active') }}
</Checkbox>
@ -195,7 +184,7 @@
{{ $t('admin_dash.users.expand_raw_info') }}
</button>
</div>
<div
<div
v-else
class="setting-item"
>

View file

@ -4,53 +4,92 @@ import Status from 'src/components/status/status.vue'
import { parseStatus } from 'src/services/entity_normalizer/entity_normalizer.service.js'
const AdminStatusCard = {
props: ['statusDetails'],
data () {
return {
jsonExpanded: false,
statusCache: undefined,
props: {
/**
* minimal status info
* @type {import('vue').PropType<{
* id: string
* }>}
*/
statusDetails: {
type: Object,
required: true,
/**
* @param {any} u
* @returns {u is { id: string }}
*/
validator (u) {
return typeof(u.id) === 'string'
}
},
computed: {
isSensitive () {
return this.statusDetails.sensitive === true
},
visibility () {
return this.statusDetails.visibility
}
},
methods: {
changeSensitivity (v) {
this.$store.dispatch('adminChangeStatusScope', { opts: { id: this.statusDetails.id, sensitive: v }}).then(res => parseStatus(res)).then(s => this.statusCache = s)
},
changeVisibility (v) {
this.$store.dispatch('adminChangeStatusScope', { opts: { id: this.statusDetails.id, visibility: v }}).then(res => parseStatus(res)).then(s => this.statusCache = s)
},
// show popup
confirmSelection(box) {
this.$refs[box].show()
this.$refs.dropdown.hidePopover()
},
// do the thing
selectionConfirmed(action, opts) {
const restricted = []
const s = this.$refs.userList.getSelected()
s.forEach(u => {
if (restricted.includes(action) !== false || u.id !== this.$store.state.users.currentUser.id) {
this.$store.dispatch(action, { id: this.statusDetails.id, ...(opts || {}) })
}
})
this.reset()
}
},
components: {
Checkbox,
Select,
Status,
},
mounted () {
this.$store.dispatch('adminChangeStatusScope', { opts: { id: this.statusDetails.id }}).then(res => parseStatus(res)).then(s => this.statusCache = s)
}
}
},
data () {
return {
jsonExpanded: false,
statusCache: undefined,
}
},
computed: {
/**
* @returns {boolean} is this status sensitive?
*/
isSensitive () {
return this.statusDetails.sensitive === true
},
/**
* @returns {'public' | 'unlisted' | 'private' | 'direct'} status visibility
*/
visibility () {
return this.statusDetails.visibility
}
},
methods: {
/**
* @param {boolean} v set sensitive
*/
changeSensitivity (v) {
this.$store.dispatch('adminChangeStatusScope', { opts: { id: this.statusDetails.id, sensitive: v }}).then(res => parseStatus(res)).then(s => this.statusCache = s)
},
/**
* @param {boolean} v set visible
*/
changeVisibility (v) {
this.$store.dispatch('adminChangeStatusScope', { opts: { id: this.statusDetails.id, visibility: v }}).then(res => parseStatus(res)).then(s => this.statusCache = s)
},
/**
* show the confirmation box for bulk actions.
* @param {string} box ref name specified for the confirm component
*/
confirmSelection(box) {
this.$refs[box].show()
this.$refs.dropdown.hidePopover()
},
/**
* called when a bulk action was confirmed
* @param {string} action
*/
selectionConfirmed(action, opts) {
const restricted = []
const s = this.$refs.userList.getSelected()
s.forEach(u => {
if (restricted.includes(action) !== false || u.id !== this.$store.state.users.currentUser.id) {
this.$store.dispatch(action, { id: this.statusDetails.id, ...(opts || {}) })
}
})
this.reset()
}
},
components: {
Checkbox,
Select,
Status,
},
/**
* fetch and cache status info
*/
mounted () {
this.$store.dispatch('adminChangeStatusScope', { opts: { id: this.statusDetails.id }}).then(res => parseStatus(res)).then(s => this.statusCache = s)
}
}
export default AdminStatusCard

View file

@ -31,21 +31,45 @@ const UsersTab = {
}
},
computed: {
/**
* do we filter for admins?
* @returns {boolean}
*/
filtersIsAdmin () {
return this.filtersPrivileges === 'admin' || this.filtersPrivileges === 'modsnadmins'
},
/**
* do we filter for moderators?
* @returns {boolean}
*/
filtersIsModerator () {
return this.filtersPrivileges === 'moderator' || this.filtersPrivileges === 'modsnadmins'
},
/**
* do we filter for active users?
* @returns {boolean}
*/
filtersActive () {
return this.filtersActivity === 'active'
},
/**
* do we filter for deactivated users?
* @returns {boolean}
*/
filtersDeactivated () {
return this.filtersActivity === 'deactivated'
},
/**
* do we filter for local users?
* @returns {boolean}
*/
filtersLocal () {
return this.filtersOrigin === 'local'
},
/**
* do we filter for external users?
* @return {boolean}
*/
filtersExternal () {
return this.filtersOrigin === 'external'
}
@ -55,13 +79,18 @@ const UsersTab = {
Select,
BasicUserCard,
PageList,
ProgressButton,
ProgressButton,
AdminCard,
TabSwitcher,
Popover,
GenericConfirm
},
methods: {
/**
* fetch a new page of users via admin-api
* @param {object} store
* @param {object} opts
*/
fetchPage (store, opts) {
if(!this.init) return new Promise(() => [])
const filters = {
@ -83,15 +112,24 @@ const UsersTab = {
const users = store.dispatch('fetchAdminUsers', nopts)
return users
},
/**
* reset the userlist explicitly
*/
reset () {
this.$refs.userList.reset()
},
// show popup
/**
* show the confirmation box for bulk actions.
* @param {string} box ref name specified for the confirm component
*/
confirmSelection(box) {
this.$refs[box].show()
this.$refs.dropdown.hidePopover()
},
// do the thing
/**
* called when a bulk action was confirmed
* @param {string} action
*/
selectionConfirmed(action) {
const restricted = []
const s = this.$refs.userList.getSelected()
@ -103,6 +141,9 @@ const UsersTab = {
this.reset()
}
},
/**
* mark as initialized and reset user list
*/
mounted () {
this.init = true
this.reset()