mirror of
https://github.com/nextcloud/server.git
synced 2026-06-11 01:30:50 -04:00
perf(settings): Cancel request on new search
Signed-off-by: Christopher Ng <chrng8@gmail.com>
This commit is contained in:
parent
a1a4988c27
commit
8a3a38815f
4 changed files with 70 additions and 35 deletions
|
|
@ -42,7 +42,7 @@
|
|||
<NcAppNavigationList class="account-management__group-list"
|
||||
aria-describedby="group-list-desc"
|
||||
data-cy-users-settings-navigation-groups="custom">
|
||||
<GroupListItem v-for="group in filteredGroups"
|
||||
<GroupListItem v-for="group in userGroups"
|
||||
:id="group.id"
|
||||
ref="groupListItems"
|
||||
:key="group.id"
|
||||
|
|
@ -57,6 +57,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Group } from '../utils/groups.ts'
|
||||
|
||||
import { computed, ref, watch, onBeforeMount } from 'vue'
|
||||
import { Fragment } from 'vue-frag'
|
||||
import { useRoute, useRouter } from 'vue-router/composables'
|
||||
|
|
@ -76,17 +78,9 @@ import GroupListItem from './GroupListItem.vue'
|
|||
|
||||
import { useFormatGroups } from '../composables/useGroupsNavigation.ts'
|
||||
import { useStore } from '../store'
|
||||
import { searchGroups } from '../service/groups.ts'
|
||||
import logger from '../logger.ts'
|
||||
|
||||
interface Group {
|
||||
id: string
|
||||
displayname: string
|
||||
usercount: number
|
||||
disabled: number
|
||||
canAdd: boolean
|
||||
canRemove: boolean
|
||||
}
|
||||
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
|
@ -123,10 +117,6 @@ const loadingGroups = ref(false)
|
|||
const offset = ref(0)
|
||||
/** Search query for groups */
|
||||
const groupsSearchQuery = ref('')
|
||||
/** Filtered groups */
|
||||
const filteredGroups = computed(() => userGroups.value.filter((group) => {
|
||||
return group.title.toLocaleLowerCase().includes(groupsSearchQuery.value.toLocaleLowerCase())
|
||||
}))
|
||||
|
||||
const groupListItems = ref([])
|
||||
const lastGroupListItem = computed(() => {
|
||||
|
|
@ -148,18 +138,24 @@ watch(groupsSearchQuery, async () => {
|
|||
await loadGroups()
|
||||
})
|
||||
|
||||
/** Cancelable promise for search groups request */
|
||||
const promise = ref(null)
|
||||
|
||||
/**
|
||||
* Load groups
|
||||
*/
|
||||
async function loadGroups() {
|
||||
if (promise.value) {
|
||||
promise.value.cancel()
|
||||
}
|
||||
loadingGroups.value = true
|
||||
try {
|
||||
const { data } = await store.dispatch('searchGroups', {
|
||||
promise.value = searchGroups({
|
||||
search: groupsSearchQuery.value,
|
||||
offset: offset.value,
|
||||
limit: 25,
|
||||
})
|
||||
const groups: Group[] = data.ocs?.data?.groups ?? []
|
||||
const groups: Group[] = (await promise.value).data.ocs?.data?.groups ?? []
|
||||
if (groups.length > 0) {
|
||||
offset.value += 25
|
||||
}
|
||||
|
|
@ -176,6 +172,7 @@ async function loadGroups() {
|
|||
} catch (error) {
|
||||
logger.error(t('settings', 'Failed to load groups'), { error })
|
||||
}
|
||||
promise.value = null
|
||||
loadingGroups.value = false
|
||||
}
|
||||
|
||||
|
|
|
|||
35
apps/settings/src/service/groups.ts
Normal file
35
apps/settings/src/service/groups.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { AxiosResponse } from '@nextcloud/axios'
|
||||
|
||||
import axios from '@nextcloud/axios'
|
||||
import { generateOcsUrl } from '@nextcloud/router'
|
||||
import { CancelablePromise } from 'cancelable-promise'
|
||||
|
||||
/**
|
||||
* Search groups
|
||||
*
|
||||
* @param {object} options Options
|
||||
* @param {string} options.search Search query
|
||||
* @param {number} options.offset Offset
|
||||
* @param {number} options.limit Limit
|
||||
*/
|
||||
export const searchGroups = ({ search, offset, limit }): CancelablePromise<AxiosResponse> => {
|
||||
const controller = new AbortController()
|
||||
return new CancelablePromise(async (resolve, reject, onCancel) => {
|
||||
onCancel(() => controller.abort())
|
||||
try {
|
||||
const response = await axios.get(
|
||||
generateOcsUrl('/cloud/groups/details?search={search}&offset={offset}&limit={limit}', { search, offset, limit }), {
|
||||
signal: controller.signal,
|
||||
},
|
||||
)
|
||||
resolve(response)
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -323,25 +323,6 @@ const actions = {
|
|||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* search groups
|
||||
*
|
||||
* @param {object} context Store context
|
||||
* @param {object} options Options
|
||||
* @param {string} options.search Search query
|
||||
* @param {number} options.offset List offset
|
||||
* @param {number} options.limit List limit
|
||||
* @return {Promise}
|
||||
*/
|
||||
searchGroups(context, { search, offset, limit }) {
|
||||
return api.get(generateOcsUrl('cloud/groups/details?search={search}&offset={offset}&limit={limit}', { search, offset, limit }))
|
||||
.catch((error) => {
|
||||
if (!axios.isCancel(error)) {
|
||||
context.commit('API_FAILURE', error)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Get user details
|
||||
*
|
||||
|
|
|
|||
22
apps/settings/src/utils/groups.ts
Normal file
22
apps/settings/src/utils/groups.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
export interface Group {
|
||||
id: string
|
||||
displayname: string
|
||||
usercount: number
|
||||
disabled: number
|
||||
canAdd: boolean
|
||||
canRemove: boolean
|
||||
}
|
||||
|
||||
export const formatGroup = (group: Group) => ({
|
||||
id: group.id,
|
||||
name: group.displayname,
|
||||
usercount: group.usercount,
|
||||
disabled: group.disabled,
|
||||
canAdd: group.canAdd,
|
||||
canRemove: group.canRemove,
|
||||
})
|
||||
Loading…
Reference in a new issue