Skip to content

Commit

Permalink
feat: Add Bulk Operation for Group Binding in Spaces Admin UI - MEED-…
Browse files Browse the repository at this point in the history
…7767 - Meeds-io/MIPs#160 (#4184)

This change will allow to add group(s) as bound to a set of spaces by a
single user selection.
  • Loading branch information
boubaker committed Nov 14, 2024
1 parent 0370781 commit cc332f6
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,4 @@ social.spaces.administration.manageSpaces.processingSpacesBulkOperationCancelCon
social.spaces.administration.manageSpaces.processingSpacesBulkOperation=Processing bulk actions
social.spaces.administration.manageSpaces.successSpacesBulkOperation=Operation finished successfully on space
social.spaces.administration.manageSpaces.errorSpacesBulkOperation=Error while processing the operation
social.spaces.administration.manageSpaces.groupsBoundOnSpaces=Spaces group binding added successfully
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!--

This file is part of the Meeds project (https://meeds.io/).

Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

-->
<template>
<v-btn
:disabled="$root.isBulkProcessing"
color="primary"
elevation="0"
outlined
@click="$root.$emit('space-administration-sync-members-drawer-open', $root.selectedSpaces, $root.allSpacesSelected ? $root.spacesSize : $root.selectedSpaces.length, syncMembers)">
<v-icon size="16" class="me-2">fa-users</v-icon>
{{ $t('social.spaces.administration.manageSpaces.syncMembers') }}
</v-btn>
</template>
<script>
export default {
data: () => ({
successMessage: null,
}),
methods: {
syncMembers(groups) {
// Workaround for context change, compute success message on processing start
this.successMessage = this.$t('social.spaces.administration.manageSpaces.groupsBoundOnSpaces');
this.$root.applyOperationInBulk(
async space => {
let spaceBoundGroups = await this.$spaceBindingService.getGroupSpaceBindings(space.id);
if (!spaceBoundGroups?.length) {
spaceBoundGroups = groups;
} else {
spaceBoundGroups.push(...groups.filter(g => !spaceBoundGroups.find(g)));
}
await this.$spaceBindingService.saveGroupsSpaceBindings(space.id, spaceBoundGroups);
},
null,
() => {
this.$root.$emit('alert-message', this.successMessage, 'success');
this.$root.$emit('spaces-administration-list-refresh');
});
},
},
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@
-->
<template>
<div class="d-flex justify-center">
<v-progress-circular :value="progress" color="primary" class="me-4 my-auto" />
<v-progress-circular
:value="progress"
color="primary"
class="me-4 my-auto" />
<div class="d-flex flex-column me-2">
<span>{{ $t('social.spaces.administration.manageSpaces.processingSpacesBulkOperation1') }}</span>
<span>{{ $t('social.spaces.administration.manageSpaces.processingSpacesBulkOperation2') }}</span>
<span v-sanitized-html="$t('social.spaces.administration.manageSpaces.processingSpacesBulkOperation3', {
0: `<span class='text-subtitle'>`,
1: '</span>',
})"></span>
<span
v-sanitized-html="$t('social.spaces.administration.manageSpaces.processingSpacesBulkOperation3', {
0: `<span class='text-subtitle'>`,
1: '</span>',
})"></span>
</div>
<strong class="ms-4 my-auto">{{ processedSpaces }} / {{ selectedSpacesCount }}</strong>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ export default {
spaceTemplateId: null,
spacePermissions: null,
accessRules: false,
applyOnEmptyTemplate: false,
editorialMode: false,
layoutPermissions: false,
publicSitePermissions: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,28 @@
<v-icon>fa-external-link-alt</v-icon>
</v-btn>
</template>
<template v-if="drawer && space" #content>
<template v-if="drawer && (space || spaces)" #content>
<div class="pa-4">
<div class="mb-4">
{{ $t('social.spaces.administration.manageSpaces.syncMembersDescription') }}
</div>
<div class="text-header mb-1">
<div class="text-header mb-2">
{{ $t('social.spaces.administration.manageSpaces.space') }}
</div>
<space-avatar
v-if="space"
:space="space"
class="mb-4" />
<v-chip
v-else-if="spaces"
class="mb-4 light-grey-color"
height="40">
<span>
{{ $t('social.spaces.administration.manageSpaces.selectedSpacesCount', {
0: selectionCount,
}) }}
</span>
</v-chip>
<div class="text-header mb-1">
{{ $t('social.spaces.administration.manageSpaces.groupSyncedToYourSpace') }}
</div>
Expand Down Expand Up @@ -88,10 +99,14 @@ export default {
groups: null,
originalGroups: null,
bindings: null,
spaces: null,
selectionCount: null,
callback: null,
}),
computed: {
modified() {
return JSON.stringify(this.groups) !== JSON.stringify(this.originalGroups);
return (this.spaces?.length && this.groups.length)
|| (!this.spaces?.length && JSON.stringify(this.groups) !== JSON.stringify(this.originalGroups));
},
},
created() {
Expand All @@ -101,10 +116,21 @@ export default {
this.$root.$off('space-administration-sync-members-drawer-open', this.open);
},
methods: {
async open(space) {
this.space = space;
async open(obj, selectionCount, callback) {
if (obj?.id) {
this.space = obj;
this.spaces = null;
this.selectionCount = 0;
} else {
this.space = null;
this.spaces = obj;
this.selectionCount = selectionCount;
this.callback = callback;
this.spaceTemplateId = null;
this.spacePermissions = null;
}
this.$refs.drawer.open();
if (this.space.hasBindings) {
if (this.space?.hasBindings) {
this.groups = null;
this.bindings = null;
this.originalGroups = null;
Expand All @@ -121,15 +147,21 @@ export default {
async apply() {
this.saving = true;
try {
await this.$spaceBindingService.saveGroupsSpaceBindings(this.space.id, this.groups);
this.$root.$emit('spaces-administration-list-refresh');
this.$root.$emit('alert-message', this.$t('social.spaces.administration.manageSpaces.spaceBindingUpdateSuccess'), 'success');
const bindingsToDelete = this.bindings.filter(b => !this.groups.find(g => g === b.group));
if (bindingsToDelete.length) {
await Promise.all(bindingsToDelete.map(b => this.$spaceBindingService.removeBinding(b.id)));
if (this.callback) {
this.callback(this.groups);
} else {
await this.$spaceBindingService.saveGroupsSpaceBindings(this.space.id, this.groups);
this.$root.$emit('spaces-administration-list-refresh');
this.$root.$emit('alert-message', this.$t('social.spaces.administration.manageSpaces.spaceBindingUpdateSuccess'), 'success');
const bindingsToDelete = this.bindings.filter(b => !this.groups.find(g => g === b.group));
if (bindingsToDelete.length) {
await Promise.all(bindingsToDelete.map(b => this.$spaceBindingService.removeBinding(b.id)));
}
}
this.close();
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
this.$root.$emit('alert-message', this.$t('social.spaces.administration.manageSpaces.spaceBindingUpdateError', {0: this.space.displayName}), 'error');
} finally {
this.saving = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
<component
v-for="extension in $root.bulkExtensions"
:key="extension.name"
:is="extension.componentName" />
:is="extension.componentName"
class="me-4" />
</div>
<v-btn
v-else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ extensionRegistry.registerExtension('spaces-administration', 'menu-action', {
componentName: 'spaces-administration-delete-menu-item',
});

extensionRegistry.registerExtension('spaces-administration', 'bulk-action', {
rank: 10,
name: 'sync-members',
componentName: 'spaces-administration-bulk-sync-members',
});

extensionRegistry.registerExtension('spaces-administration', 'bulk-action', {
rank: 20,
name: 'apply-template',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import SpacesAdministrationSaveAsTemplateMenuItem from './components/menu-action

import SpacesAdministrationProcessingAlert from './components/bulk-action/SpacesAdministrationProcessingAlert.vue';
import SpacesAdministrationBulkApplyTemplate from './components/bulk-action/SpacesAdministrationBulkApplyTemplate.vue';
import SpacesAdministrationBulkSyncMembers from './components/bulk-action/SpacesAdministrationBulkSyncMembers.vue';

import SpacesAdministrationBindingReportItem from './components/binding-report/SpacesAdministrationBindingReportItem.vue';
import SpacesAdministrationBindingReportList from './components/binding-report/SpacesAdministrationBindingReportList.vue';
Expand Down Expand Up @@ -71,6 +72,7 @@ const components = {

'spaces-administration-processing-alert': SpacesAdministrationProcessingAlert,
'spaces-administration-bulk-apply-template': SpacesAdministrationBulkApplyTemplate,
'spaces-administration-bulk-sync-members': SpacesAdministrationBulkSyncMembers,

'spaces-administration-managers-drawer': SpacesAdministrationManagersDrawer,
'spaces-administration-sync-members-drawer': SpacesAdministrationSyncMembersDrawer,
Expand Down

0 comments on commit cc332f6

Please sign in to comment.