diff --git a/src/components/AppContent/CircleContent.vue b/src/components/AppContent/CircleContent.vue index 67540d2952..d3e1ac8d41 100644 --- a/src/components/AppContent/CircleContent.vue +++ b/src/components/AppContent/CircleContent.vue @@ -58,12 +58,6 @@ export default { }, }, - data() { - return { - loadingList: false, - } - }, - computed: { // store variables circles() { @@ -82,25 +76,10 @@ export default { return Object.values(this.circle?.members || []) }, - /** - * Is the current circle empty - * - * @return {boolean} - */ - isEmptyCircle() { - return this.members.length === 0 - }, - ...mapStores(useUserGroupStore), }, watch: { - circle(newCircle) { - if (newCircle?.id) { - this.fetchCircleMembers(newCircle.id) - } - }, - userGroup(newUserGroup) { if (newUserGroup?.id) { this.fetchUserGroupMembers(newUserGroup.id) @@ -109,40 +88,18 @@ export default { }, beforeMount() { - if (this.circle?.id) { - this.fetchCircleMembers(this.circle.id) - } - if (this.userGroup?.id) { this.fetchUserGroupMembers(this.userGroup.id) } }, methods: { - async fetchCircleMembers(circleId) { - this.loadingList = true - this.logger.debug('Fetching members for', { circleId }) - - try { - await this.$store.dispatch('getCircleMembers', circleId) - } catch (error) { - console.error(error) - showError(t('contacts', 'There was an error fetching the member list')) - } finally { - this.loadingList = false - } - }, - async fetchUserGroupMembers(userGroupId) { - this.loadingList = true - try { await this.userGroupStore.getUserGroupMembers(userGroupId) } catch (error) { console.error(error) showError(t('contacts', 'There was an error fetching the member list')) - } finally { - this.loadingList = false } }, }, diff --git a/src/components/MemberList/MemberList.vue b/src/components/MemberList/MemberList.vue index 3002877d6f..be91e94e4b 100644 --- a/src/components/MemberList/MemberList.vue +++ b/src/components/MemberList/MemberList.vue @@ -7,7 +7,7 @@
@@ -29,17 +29,35 @@ - - - + { + searchQuery.value = '' + } + const searchQueryDebounced = refDebounced(searchQuery, 500) + + const searchRole = ref(null) + const roles = Object.entries(CIRCLES_MEMBER_LEVELS).map(([id, label]) => ({ + id: Number(id), + label, + })) + roles.unshift({ + id: Number(MemberLevels.NONE), + label: t('contacts', 'Pending'), + }) + + return { + searchQuery, + searchQueryDebounced, + clearSearchField, + searchRole, + roles, + } + }, + data() { return { + loadingList: false, pickerLoading: false, showPicker: false, showPickerIntro: true, @@ -118,12 +175,30 @@ export default defineComponent({ /** * Return the current circle * - * @return {object} + * @return {Circle} */ circle() { return this.$store.getters.getCircle(this.selectedCircle) }, + members() { + return Object.values(this.$store.getters.getCircle(this.circle.id)?.members || []) + }, + + membershipTooLargeMessage() { + if (this.searchQueryDebounced || this.searchRole?.id) { + const searchQuery = this.searchQueryDebounced || '-' + const searchRole = this.searchRole?.label || 'any' + return `Search results (query: ${searchQuery}, role: ${searchRole}) contains too many entries.` + } + + return 'Users list too large' + }, + + isMembersLisTooLarge() { + return this.flatList.length > MAX_MEMBERS_TO_RENDER + }, + // Decode HTML entities in the circle display name so apostrophes (') and other // HTML-encoded chars (e.g. ') are shown correctly in the picker labels. decodedTeamName(): string { @@ -168,6 +243,24 @@ export default defineComponent({ }, }, + watch: { + searchQueryDebounced(value) { + this.fetchCircleMembers() + }, + + searchRole(value) { + this.fetchCircleMembers() + }, + + 'circle.id': { + handler() { + this.fetchCircleMembers() + }, + + immediate: true, + }, + }, + mounted() { subscribe('contacts:circles:append', this.onShowPicker) subscribe('guests:user:created', this.onGuestCreated) @@ -179,6 +272,8 @@ export default defineComponent({ }, methods: { + t, + /** * Measure the circle details header height from the DOM * and keep it updated via ResizeObserver. @@ -296,6 +391,26 @@ export default defineComponent({ const results = await getSuggestions(guest.username, this.circle) this.$refs.entityPicker.onClick(results[0]) }, + + async fetchCircleMembers() { + if (!this.circle?.canManageMembers) { + return + } + + this.loadingList = true + const payload = { circleId: this.circle.id, search: this.searchQuery || null, role: this.searchRole?.id } + this.logger.debug('Fetching members for', payload) + + try { + await this.$store.dispatch('getCircleMembers', payload) + console.log('debug: getCircleMembers', this.list) + } catch (error) { + console.error(error) + showError(t('contacts', 'There was an error fetching the member list')) + } finally { + this.loadingList = false + } + }, }, }) diff --git a/src/components/MemberList/MemberListGroup.vue b/src/components/MemberList/MemberListGroup.vue index d8c0a18204..bd93f07c33 100644 --- a/src/components/MemberList/MemberListGroup.vue +++ b/src/components/MemberList/MemberListGroup.vue @@ -6,6 +6,9 @@