From 4a00d8949422f7e7dbd8f5ccb680e3b38a9804e7 Mon Sep 17 00:00:00 2001 From: luce Date: Sat, 19 Jul 2025 14:11:12 +0200 Subject: [PATCH] page list instead of hoc withloadmore --- src/components/page_list/page_list.js | 50 ++++++++++ src/components/page_list/page_list.vue | 58 +++++++++++ .../settings_modal/admin_tabs/admin_card.js | 3 + .../settings_modal/admin_tabs/admin_card.vue | 9 ++ .../settings_modal/admin_tabs/users_tab.js | 95 +++++++----------- .../settings_modal/admin_tabs/users_tab.vue | 97 ++++++++++++++++++- src/i18n/en.json | 8 +- src/modules/adminSettings.js | 8 +- src/services/api/api.service.js | 71 +++++++++++++- 9 files changed, 327 insertions(+), 72 deletions(-) create mode 100644 src/components/page_list/page_list.js create mode 100644 src/components/page_list/page_list.vue diff --git a/src/components/page_list/page_list.js b/src/components/page_list/page_list.js new file mode 100644 index 000000000..fb99dc2f2 --- /dev/null +++ b/src/components/page_list/page_list.js @@ -0,0 +1,50 @@ +//import Checkbox from 'src/components/checkbox/checkbox.vue' +import SelectableList from 'src/components/selectable_list/selectable_list.vue' + +const PageList = { + components: { + SelectableList + }, + props: { + boxOnly: { + type: Boolean, + default: false + }, + pageSize: { + type: Number, + default: 50 + }, + fetchPage: { + type: Function, + default: async () => [] + } + }, + data () { + return { + pageIndex: 1, + items: [], + selected: [], + canLoadMore: true + } + }, + methods: { + reset () { + this.canLoadMore = true + this.pageIndex = 1 + this.items = [] + this.loadMore() // load one page + }, + loadMore () { + this.fetchPage(this.$store, { + page: this.pageIndex++, + pageSize: this.pageSize + }).then((items) => this.items = [...this.items, ...items]) + // fetch page, add to items + //this.$forceUpdate() + } + }, + mounted () { + this.reset() + } +} +export default PageList diff --git a/src/components/page_list/page_list.vue b/src/components/page_list/page_list.vue new file mode 100644 index 000000000..3de52579c --- /dev/null +++ b/src/components/page_list/page_list.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/settings_modal/admin_tabs/admin_card.js b/src/components/settings_modal/admin_tabs/admin_card.js index 7339e420e..c9bf8147e 100644 --- a/src/components/settings_modal/admin_tabs/admin_card.js +++ b/src/components/settings_modal/admin_tabs/admin_card.js @@ -8,6 +8,9 @@ const AdminCard = { } }, computed: { + isLoaded () { + return typeof(this.user) !== 'undefined' + }, user () { return this.$store.getters.findUser(this.userId) }, diff --git a/src/components/settings_modal/admin_tabs/admin_card.vue b/src/components/settings_modal/admin_tabs/admin_card.vue index cc7b7b4f5..c54cdcf1f 100644 --- a/src/components/settings_modal/admin_tabs/admin_card.vue +++ b/src/components/settings_modal/admin_tabs/admin_card.vue @@ -1,4 +1,12 @@ diff --git a/src/components/settings_modal/admin_tabs/users_tab.js b/src/components/settings_modal/admin_tabs/users_tab.js index 4b875cc93..03274533d 100644 --- a/src/components/settings_modal/admin_tabs/users_tab.js +++ b/src/components/settings_modal/admin_tabs/users_tab.js @@ -2,34 +2,11 @@ import Checkbox from 'src/components/checkbox/checkbox.vue' import Select from 'src/components/select/select.vue' import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue' -import withLoadMore from 'src/components/../hocs/with_load_more/with_load_more' -import SelectableList from 'src/components/selectable_list/selectable_list.vue' import ProgressButton from 'src/components/progress_button/progress_button.vue' import AdminCard from 'src/components/settings_modal/admin_tabs/admin_card.vue' -//import { ref } from 'vue' +import PageList from 'src/components/page_list/page_list.vue' -const UserList = withLoadMore({ - fetch: (props, $store) => { - console.log('fetch', props) - return $store.dispatch('fetchAdminUsers') - }, - select: (props, $store) => { - console.log('select', props) - const filterMethod = typeof props.filterMethod === 'function' ? props.filterMethod : () => true - const users = $store.state.users.users.filter(user => user.id !== $store.state.users.currentUser.id && filterMethod(user)) - console.log('users', users) - return users - }, - destroy: () => {}, - childPropName: 'items' -})(SelectableList) -const UserSortStrategy = Object.freeze({ - NONE: 0, - NICKNAME: 1, - DISPLAYNAME: 2, - JOINED: 3 -}) const UsersTab = { provide () { @@ -40,13 +17,17 @@ const UsersTab = { }, data() { return { - filterTerms: [], - users: [], - sortStrategy: UserSortStrategy.NONE, - sortAscending: true, + filters: { + local: false, + external: false, + active: false, + need_approval: false, + unconfirmed: false, + deactivated: false, + is_admin: false, + is_moderator: false + }, expandedUser: null, - filterActive: 'active_only', - filterLocal: 'local_only', loading: false } }, @@ -54,47 +35,39 @@ const UsersTab = { Checkbox, Select, BasicUserCard, - UserList, + PageList, ProgressButton, AdminCard, }, computed: { - knownDomains () { - return this.$store.state.instance.knownDomains - }, - user () { - return this.$store.state.users.currentUser - } }, methods: { + delete_selection () { + console.log('delete selection') + }, + delete_user () {}, + fetch_page (store, opts) { + opts.query = "" + console.log('current filters:', this.filters) + opts.filters = this.filters + opts.name = "" + opts.email = "" + const users = store.dispatch('fetchAdminUsers', opts) + console.log('users', users) + return users + }, + reset () { + this.$refs.userList.reset() + }, + toggleLocal () { + console.log('toggle local') + this.filters.local = !this.filters.local + this.reset() + } }, mounted() { console.log("mounted") - /*const store = this.$store; - const moduleTree = buildModuleTree(store._modules.root); - console.log(JSON.stringify(moduleTree, null, 2));*/ } } -/*function buildModuleTree(module, path = []) { - const fullPath = path.join('/') || 'root'; - const moduleInfo = { - path: fullPath, - namespaced: module.namespaced, - state: Object.keys(module.state), - actions: module._rawModule.actions ? Object.keys(module._rawModule.actions) : [], - mutations: module._rawModule.mutations ? Object.keys(module._rawModule.mutations) : [], - getters: module._rawModule.getters ? Object.keys(module._rawModule.getters) : [], - modules: [] - }; - - if (module._children) { - for (const key in module._children) { - const child = module._children[key]; - moduleInfo.modules.push(buildModuleTree(child, path.concat(key))); - } - } - - return moduleInfo; -}*/ export default UsersTab diff --git a/src/components/settings_modal/admin_tabs/users_tab.vue b/src/components/settings_modal/admin_tabs/users_tab.vue index 0f9d681bf..d60cd99a3 100644 --- a/src/components/settings_modal/admin_tabs/users_tab.vue +++ b/src/components/settings_modal/admin_tabs/users_tab.vue @@ -1,14 +1,101 @@ diff --git a/src/i18n/en.json b/src/i18n/en.json index 05aa63c5b..e8bdd53c3 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -376,6 +376,9 @@ "selectable_list": { "select_all": "Select all" }, + "page_list": { + "load_more": "Load more" + }, "settings": { "add_language": "Add fallback language", "remove_language": "Remove", @@ -1138,7 +1141,10 @@ "local_only": "local only", "external_only": "external only" }, - "loading": "Loading..." + "loading": "Loading...", + "deactivate": "deactivate", + "activate": "activate", + "delete": "delete" }, "limits": { "arbitrary_limits": "Arbitrary limits", diff --git a/src/modules/adminSettings.js b/src/modules/adminSettings.js index 260b2d8b6..a55a48951 100644 --- a/src/modules/adminSettings.js +++ b/src/modules/adminSettings.js @@ -60,8 +60,12 @@ const adminSettingsStorage = { } }, actions: { - fetchAdminUsers (store) { - store.rootState.api.backendInteractor.adminListUsers().then((users) => users.forEach(user => store.dispatch('fetchUserIfMissing', user.id))) + async fetchAdminUsers (store, opts) { + const users = await store.rootState.api.backendInteractor.adminListUsers({opts}) + //await Promise.all( + users.map(user => store.dispatch('fetchUserIfMissing', user.id)) + //) + return users }, loadFrontendsStuff ({ rootState, commit }) { rootState.api.backendInteractor.fetchAvailableFrontends() diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index f88c3a6e5..acb014a53 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -115,7 +115,30 @@ const PLEROMA_ADMIN_CONFIG_URL = '/api/pleroma/admin/config' const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/pleroma/admin/config/descriptions' const PLEROMA_ADMIN_FRONTENDS_URL = '/api/pleroma/admin/frontends' const PLEROMA_ADMIN_FRONTENDS_INSTALL_URL = '/api/pleroma/admin/frontends/install' -const PLEROMA_ADMIN_USERS_URL = '/api/v1/pleroma/admin/users' +const PLEROMA_ADMIN_USERS_URL = ({page, pageSize, filters = {}, query = '', name = '', email = ''}) => { + const { + local = false, + external = false, + active = false, + need_approval = false, + unconfirmed = false, + deactivated = false, + is_admin = true, + is_moderator = true, + } = filters + const filters_str = (local ? 'local,' : '') + + (external ? 'external,' : '') + + (active ? 'active,' : '') + + (need_approval ? 'need_approval,' : '') + + (unconfirmed ? 'unconfirmed,' : '') + + (deactivated ? 'deactivated,' : '') + + (is_admin ? 'is_admin,' : '') + + (is_moderator ? 'is_moderator,' : '') + return `/api/v1/pleroma/admin/users?page=${page}&page_size=${pageSize}&filters=${filters_str}&query=${query}&name=${name}&email=${email}` +} +const PLEROMA_ADMIN_DELETE_USERS_URL = '/api/v1/pleroma/admin/users' +const PLEROMA_ADMIN_ACTIVATE_USER_URL = '/api/v1/pleroma/admin/users/activate' +const PLEROMA_ADMIN_DEACTIVATE_USER_URL = '/api/v1/pleroma/admin/users/deactivate' const PLEROMA_EMOJI_RELOAD_URL = '/api/pleroma/admin/reload_emoji' const PLEROMA_EMOJI_IMPORT_FS_URL = '/api/pleroma/emoji/packs/import' @@ -1441,10 +1464,49 @@ const dismissAnnouncement = ({ id, credentials }) => { }) } -const adminListUsers = ({ credentials }) => { +const adminListUsers = ({ opts, credentials }) => { // the reported list is hardly useful because standards are for dating i guess, // so make sure to fetchIfMissing right afterward using this call - return promisedRequest({ url: PLEROMA_ADMIN_USERS_URL, credentials }).then((data) => data.users.map(parseUser)) + const url = PLEROMA_ADMIN_USERS_URL(opts) + console.log('admin api: ', url) + return promisedRequest({ url: url, + credentials, + method: 'GET' + }).then((data) => data.users.map(parseUser)) +} + +const adminDeleteUser = ({ nicknames, credentials }) => { + return promisedRequest({ + url: PLEROMA_ADMIN_DELETE_USERS_URL, + credentials, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({'nicknames': nicknames}) + }) +} + +const adminActivateUser = ({ nicknames, credentials }) => { + return promisedRequest({ url: PLEROMA_ADMIN_ACTIVATE_USER_URL, + credentials, + method: 'PATCH', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({'nicknames': nicknames}) + }) +} + +const adminDeactivateUser = ({ nicknames, credentials }) => { + return promisedRequest({ url: PLEROMA_ADMIN_DEACTIVATE_USER_URL, + credentials, + method: 'PATCH', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({'nicknames': nicknames}) + }) } const announcementToPayload = ({ content, startsAt, endsAt, allDay }) => { @@ -2120,6 +2182,9 @@ const apiService = { updateBookmarkFolder, deleteBookmarkFolder, adminListUsers, + adminDeleteUser, + adminActivateUser, + adminDeactivateUser, } export default apiService