diff --git a/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 b/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 index 2fbac162ced..0020dae6ec8 100644 --- a/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 @@ -11,6 +11,7 @@ export default Ember.Controller.extend(CanCheckEmails, { editingName: false, editingTitle: false, originalPrimaryGroupId: null, + customGroupIdsBuffer: null, availableGroups: null, userTitleValue: null, @@ -30,6 +31,20 @@ export default Ember.Controller.extend(CanCheckEmails, { "model.can_disable_second_factor" ), + @computed("model.customGroups") + customGroupIds(customGroups) { + return customGroups.mapBy("id"); + }, + + @computed("customGroupIdsBuffer", "customGroupIds") + customGroupsDirty(buffer, original) { + if (buffer === null) return false; + + return buffer.length === original.length + ? buffer.any(id => !original.includes(id)) + : true; + }, + @computed("model.automaticGroups") automaticGroups(automaticGroups) { return automaticGroups @@ -105,6 +120,27 @@ export default Ember.Controller.extend(CanCheckEmails, { } }, + groupAdded(added) { + this.get("model") + .groupAdded(added) + .catch(function() { + bootbox.alert(I18n.t("generic_error")); + }); + }, + + groupRemoved(groupId) { + this.get("model") + .groupRemoved(groupId) + .then(() => { + if (groupId === this.get("originalPrimaryGroupId")) { + this.set("originalPrimaryGroupId", null); + } + }) + .catch(function() { + bootbox.alert(I18n.t("generic_error")); + }); + }, + actions: { impersonate() { return this.get("model").impersonate(); @@ -278,20 +314,22 @@ export default Ember.Controller.extend(CanCheckEmails, { this.get("model").generateApiKey(); }, - groupAdded(added) { - this.get("model") - .groupAdded(added) - .catch(function() { - bootbox.alert(I18n.t("generic_error")); - }); + saveCustomGroups() { + const currentIds = this.get("customGroupIds"); + const bufferedIds = this.get("customGroupIdsBuffer"); + const availableGroups = this.get("availableGroups"); + + bufferedIds.filter(id => !currentIds.includes(id)).forEach(id => { + this.groupAdded(availableGroups.findBy("id", id)); + }); + + currentIds + .filter(id => !bufferedIds.includes(id)) + .forEach(id => this.groupRemoved(id)); }, - groupRemoved(groupId) { - this.get("model") - .groupRemoved(groupId) - .catch(function() { - bootbox.alert(I18n.t("generic_error")); - }); + resetCustomGroups() { + this.set("customGroupIdsBuffer", null); }, savePrimaryGroup() { diff --git a/app/assets/javascripts/admin/templates/user-index.hbs b/app/assets/javascripts/admin/templates/user-index.hbs index 35daa9560d6..a02756d2e64 100644 --- a/app/assets/javascripts/admin/templates/user-index.hbs +++ b/app/assets/javascripts/admin/templates/user-index.hbs @@ -459,19 +459,29 @@
{{i18n 'admin.groups.custom'}}
- {{admin-group-selector selected=model.customGroups available=availableGroups}} -
-
- {{#if model.customGroups}} - {{i18n 'admin.groups.primary'}} - {{combo-box content=model.customGroups value=model.primary_group_id none="admin.groups.no_primary"}} - {{/if}} - {{#if primaryGroupDirty}} - {{d-button icon="check" class="ok" action="savePrimaryGroup"}} - {{d-button icon="times" class="cancel" action="resetPrimaryGroup"}} - {{/if}} + {{admin-group-selector selected=model.customGroups available=availableGroups buffer=customGroupIdsBuffer}}
+ {{#if customGroupsDirty}} +
+ {{d-button icon="check" class="ok" action="saveCustomGroups"}} + {{d-button icon="times" class="cancel" action="resetCustomGroups"}} +
+ {{/if}}
+ {{#if model.customGroups}} +
+
{{i18n 'admin.groups.primary'}}
+
+ {{combo-box content=model.customGroups value=model.primary_group_id none="admin.groups.no_primary"}} +
+ {{#if primaryGroupDirty}} +
+ {{d-button icon="check" class="ok" action="savePrimaryGroup"}} + {{d-button icon="times" class="cancel" action="resetPrimaryGroup"}} +
+ {{/if}} +
+ {{/if}} {{/if}} diff --git a/app/assets/javascripts/select-kit/components/admin-group-selector.js.es6 b/app/assets/javascripts/select-kit/components/admin-group-selector.js.es6 index fa15690c088..0c79d92a4d5 100644 --- a/app/assets/javascripts/select-kit/components/admin-group-selector.js.es6 +++ b/app/assets/javascripts/select-kit/components/admin-group-selector.js.es6 @@ -1,4 +1,5 @@ import MultiSelectComponent from "select-kit/components/multi-select"; +import computed from "ember-addons/ember-computed-decorators"; const { makeArray } = Ember; export default MultiSelectComponent.extend({ @@ -7,11 +8,13 @@ export default MultiSelectComponent.extend({ selected: null, available: null, allowAny: false, + buffer: null, - computeValues() { - return makeArray(this.get("selected")).map(s => - this.valueForContentItem(s) - ); + @computed("buffer") + values(buffer) { + return buffer === null + ? makeArray(this.get("selected")).map(s => this.valueForContentItem(s)) + : buffer; }, computeContent() { @@ -25,33 +28,6 @@ export default MultiSelectComponent.extend({ }, mutateValues(values) { - if (values.length > this.get("selected").length) { - const newValues = values.filter( - v => - !this.get("selected") - .map(s => this.valueForContentItem(s)) - .includes(v) - ); - - newValues.forEach(value => { - const actionContext = this.get("available").findBy( - this.get("valueAttribute"), - parseInt(value, 10) - ); - - this.triggerAction({ action: "groupAdded", actionContext }); - }); - } else if (values.length < this.get("selected").length) { - const selected = this.get("selected").filter( - s => !values.includes(this.valueForContentItem(s)) - ); - - selected.forEach(s => { - this.triggerAction({ - action: "groupRemoved", - actionContext: this.valueForContentItem(s) - }); - }); - } + this.set("buffer", values); } });