diff --git a/app/assets/javascripts/discourse/components/group-form.js.es6 b/app/assets/javascripts/discourse/components/group-form.js.es6 deleted file mode 100644 index 6a34e31b1d9..00000000000 --- a/app/assets/javascripts/discourse/components/group-form.js.es6 +++ /dev/null @@ -1,119 +0,0 @@ -import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; -import User from "discourse/models/user"; -import InputValidation from 'discourse/models/input-validation'; -import debounce from 'discourse/lib/debounce'; - -export default Ember.Component.extend({ - disableSave: null, - nameInput: '', - - aliasLevelOptions: [ - { name: I18n.t("groups.alias_levels.nobody"), value: 0 }, - { name: I18n.t("groups.alias_levels.mods_and_admins"), value: 2 }, - { name: I18n.t("groups.alias_levels.members_mods_and_admins"), value: 3 }, - { name: I18n.t("groups.alias_levels.everyone"), value: 99 } - ], - - visibilityLevelOptions: [ - { name: I18n.t("groups.visibility_levels.public"), value: 0 }, - { name: I18n.t("groups.visibility_levels.members"), value: 1 }, - { name: I18n.t("groups.visibility_levels.staff"), value: 2 }, - { name: I18n.t("groups.visibility_levels.owners"), value: 3 } - ], - - trustLevelOptions: [ - { name: I18n.t("groups.trust_levels.none"), value: 0 }, - { name: 1, value: 1 }, { name: 2, value: 2 }, { name: 3, value: 3 }, { name: 4, value: 4 } - ], - - init() { - this._super(); - this.set('nameInput', this.get('model.name')); - }, - - @computed('model.visibility_level', 'model.public_admission') - disableMembershipRequestSetting(visibility_level, publicAdmission) { - visibility_level = parseInt(visibility_level); - return (visibility_level !== 0) || publicAdmission; - }, - - @computed('model.visibility_level', 'model.allow_membership_requests') - disablePublicSetting(visibility_level, allowMembershipRequests) { - visibility_level = parseInt(visibility_level); - return (visibility_level !== 0) || allowMembershipRequests; - }, - - @computed('basicNameValidation', 'uniqueNameValidation') - nameValidation(basicNameValidation, uniqueNameValidation) { - return uniqueNameValidation ? uniqueNameValidation : basicNameValidation; - }, - - @observes("nameInput") - _validateName() { - name = this.get('nameInput'); - - if (name === undefined) { - return this._failedInputValidation(); - }; - - if (name === "") { - this.set('uniqueNameValidation', null); - return this._failedInputValidation(I18n.t('groups.new.name.blank')); - } - - if (name.length < this.siteSettings.min_username_length) { - return this._failedInputValidation(I18n.t('groups.new.name.too_short')); - } - - if (name.length > this.siteSettings.max_username_length) { - return this._failedInputValidation(I18n.t('groups.new.name.too_long')); - } - - this.checkGroupName(); - - return this._failedInputValidation(I18n.t('groups.new.name.checking')); - }, - - checkGroupName: debounce(function() { - name = this.get('nameInput'); - if (Ember.isEmpty(name)) return; - - User.checkUsername(name).then(response => { - const validationName = 'uniqueNameValidation'; - - if (response.available) { - this.set(validationName, InputValidation.create({ - ok: true, - reason: I18n.t('groups.new.name.available') - })); - - this.set('disableSave', false); - this.set('model.name', this.get('nameInput')); - } else { - let reason; - - if (response.errors) { - reason = response.errors.join(' '); - } else { - reason = I18n.t('groups.new.name.not_available'); - } - - this.set(validationName, this._failedInputValidation(reason)); - } - }); - }, 500), - - _failedInputValidation(reason) { - this.set('disableSave', true); - - const options = { failed: true }; - if (reason) options.reason = reason; - this.set('basicNameValidation', InputValidation.create(options)); - }, - - actions: { - save() { - this.sendAction("save"); - }, - } -}); diff --git a/app/assets/javascripts/discourse/components/group-manage-save-button.js.es6 b/app/assets/javascripts/discourse/components/group-manage-save-button.js.es6 new file mode 100644 index 00000000000..a5163d92a6b --- /dev/null +++ b/app/assets/javascripts/discourse/components/group-manage-save-button.js.es6 @@ -0,0 +1,23 @@ +import { popupAjaxError } from 'discourse/lib/ajax-error'; +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + saving: null, + + @computed('saving') + savingText(saving) { + if (saving !== undefined) { + return saving ? I18n.t('saving') : I18n.t('saved'); + } + }, + + actions: { + save() { + this.set('saving', true); + + return this.get('model').save() + .catch(popupAjaxError) + .finally(() => this.set('saving', false)); + } + }, +}); diff --git a/app/assets/javascripts/discourse/components/groups-form-interaction-fields.js.es6 b/app/assets/javascripts/discourse/components/groups-form-interaction-fields.js.es6 new file mode 100644 index 00000000000..1595f652956 --- /dev/null +++ b/app/assets/javascripts/discourse/components/groups-form-interaction-fields.js.es6 @@ -0,0 +1,23 @@ +import { default as computed } from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + visibilityLevelOptions: [ + { name: I18n.t("admin.groups.manage.interaction.visibility_levels.public"), value: 0 }, + { name: I18n.t("admin.groups.manage.interaction.visibility_levels.members"), value: 1 }, + { name: I18n.t("admin.groups.manage.interaction.visibility_levels.staff"), value: 2 }, + { name: I18n.t("admin.groups.manage.interaction.visibility_levels.owners"), value: 3 } + ], + + aliasLevelOptions: [ + { name: I18n.t("groups.alias_levels.nobody"), value: 0 }, + { name: I18n.t("groups.alias_levels.mods_and_admins"), value: 2 }, + { name: I18n.t("groups.alias_levels.members_mods_and_admins"), value: 3 }, + { name: I18n.t("groups.alias_levels.everyone"), value: 99 } + ], + + + @computed('siteSettings.email_in', 'model.automatic', 'currentUser.admin') + showEmailSettings(emailIn, automatic, isAdmin) { + return emailIn && isAdmin && !automatic; + } +}); diff --git a/app/assets/javascripts/discourse/components/groups-form-membership-fields.js.es6 b/app/assets/javascripts/discourse/components/groups-form-membership-fields.js.es6 new file mode 100644 index 00000000000..e9c7e8a37e3 --- /dev/null +++ b/app/assets/javascripts/discourse/components/groups-form-membership-fields.js.es6 @@ -0,0 +1,20 @@ +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + trustLevelOptions: [ + { name: I18n.t("admin.groups.manage.membership.trust_levels_none"), value: 0 }, + { name: 1, value: 1 }, { name: 2, value: 2 }, { name: 3, value: 3 }, { name: 4, value: 4 } + ], + + @computed('model.visibility_level', 'model.public_admission') + disableMembershipRequestSetting(visibility_level, publicAdmission) { + visibility_level = parseInt(visibility_level); + return (visibility_level !== 0) || publicAdmission; + }, + + @computed('model.visibility_level', 'model.allow_membership_requests') + disablePublicSetting(visibility_level, allowMembershipRequests) { + visibility_level = parseInt(visibility_level); + return (visibility_level !== 0) || allowMembershipRequests; + } +}); diff --git a/app/assets/javascripts/discourse/components/groups-form-profile-fields.js.es6 b/app/assets/javascripts/discourse/components/groups-form-profile-fields.js.es6 new file mode 100644 index 00000000000..0c268b265e9 --- /dev/null +++ b/app/assets/javascripts/discourse/components/groups-form-profile-fields.js.es6 @@ -0,0 +1,84 @@ +import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; +import User from "discourse/models/user"; +import InputValidation from 'discourse/models/input-validation'; +import debounce from 'discourse/lib/debounce'; + +export default Ember.Component.extend({ + saving: null, + nameInput: null, + + didInsertElement() { + this._super(); + const name = this.get('model.name'); + if (name) this.set("nameInput", name); + }, + + @computed('basicNameValidation', 'uniqueNameValidation') + nameValidation(basicNameValidation, uniqueNameValidation) { + return uniqueNameValidation ? uniqueNameValidation : basicNameValidation; + }, + + @observes("nameInput") + _validateName() { + name = this.get('nameInput'); + if (name === this.get('model.name')) return; + + if (name === undefined) { + return this._failedInputValidation(); + }; + + if (name === "") { + this.set('uniqueNameValidation', null); + return this._failedInputValidation(I18n.t('admin.groups.new.name.blank')); + } + + if (name.length < this.siteSettings.min_username_length) { + return this._failedInputValidation(I18n.t('admin.groups.new.name.too_short')); + } + + if (name.length > this.siteSettings.max_username_length) { + return this._failedInputValidation(I18n.t('admin.groups.new.name.too_long')); + } + + this.checkGroupName(); + + return this._failedInputValidation(I18n.t('admin.groups.new.name.checking')); + }, + + checkGroupName: debounce(function() { + name = this.get('nameInput'); + if (Ember.isEmpty(name)) return; + + User.checkUsername(name).then(response => { + const validationName = 'uniqueNameValidation'; + + if (response.available) { + this.set(validationName, InputValidation.create({ + ok: true, + reason: I18n.t('admin.groups.new.name.available') + })); + + this.set('saving', false); + this.set('model.name', this.get('nameInput')); + } else { + let reason; + + if (response.errors) { + reason = response.errors.join(' '); + } else { + reason = I18n.t('admin.groups.new.name.not_available'); + } + + this.set(validationName, this._failedInputValidation(reason)); + } + }); + }, 500), + + _failedInputValidation(reason) { + this.set('saving', true); + + const options = { failed: true }; + if (reason) options.reason = reason; + this.set('basicNameValidation', InputValidation.create(options)); + }, +}); diff --git a/app/assets/javascripts/discourse/controllers/group-manage-members.js.es6 b/app/assets/javascripts/discourse/controllers/group-add-members.js.es6 similarity index 77% rename from app/assets/javascripts/discourse/controllers/group-manage-members.js.es6 rename to app/assets/javascripts/discourse/controllers/group-add-members.js.es6 index 71ee3f8a8f0..ac65416c5ca 100644 --- a/app/assets/javascripts/discourse/controllers/group-manage-members.js.es6 +++ b/app/assets/javascripts/discourse/controllers/group-add-members.js.es6 @@ -1,7 +1,8 @@ import computed from 'ember-addons/ember-computed-decorators'; -import { popupAjaxError } from 'discourse/lib/ajax-error'; +import { extractError } from 'discourse/lib/ajax-error'; +import ModalFunctionality from 'discourse/mixins/modal-functionality'; -export default Ember.Controller.extend({ +export default Ember.Controller.extend(ModalFunctionality, { loading: false, setAsOwner: false, @@ -31,10 +32,13 @@ export default Ember.Controller.extend({ this.get('model.name'), { queryParams: { filter: usernames } } ); + model.set("usernames", null); this.send('closeModal'); }) - .catch(popupAjaxError) + .catch(error => { + this.flash(extractError(error), 'error'); + }) .finally(() => this.set('loading', false)); }, }, diff --git a/app/assets/javascripts/discourse/controllers/group-manage-profile.js.es6 b/app/assets/javascripts/discourse/controllers/group-manage-profile.js.es6 index d3afbd6d141..17df28ceb03 100644 --- a/app/assets/javascripts/discourse/controllers/group-manage-profile.js.es6 +++ b/app/assets/javascripts/discourse/controllers/group-manage-profile.js.es6 @@ -1,23 +1,3 @@ -import { popupAjaxError } from 'discourse/lib/ajax-error'; -import computed from 'ember-addons/ember-computed-decorators'; - export default Ember.Controller.extend({ - @computed('saving') - savingText(saving) { - if (saving !== undefined) { - return saving ? I18n.t('saving') : I18n.t('saved'); - } - }, - - actions: { - save() { - this.set('saving', true); - - return this.get('model').save() - .catch(popupAjaxError) - .finally(() => { - this.set('saving', false); - }); - } - } + saving: null, }); diff --git a/app/assets/javascripts/discourse/controllers/group-manage.js.es6 b/app/assets/javascripts/discourse/controllers/group-manage.js.es6 index 2c8ade4cefb..9d100f63e68 100644 --- a/app/assets/javascripts/discourse/controllers/group-manage.js.es6 +++ b/app/assets/javascripts/discourse/controllers/group-manage.js.es6 @@ -6,13 +6,17 @@ export default Ember.Controller.extend({ @computed("model.automatic") tabs(automatic) { const defaultTabs = [ - { route: 'group.manage.profile', title: 'groups.manage.profile.title' }, + { route: 'group.manage.interaction', title: 'groups.manage.interaction.title' }, { route: 'group.manage.logs', title: 'groups.manage.logs.title' }, ]; if (!automatic) { + defaultTabs.splice(0, 0, + { route: 'group.manage.profile', title: 'groups.manage.profile.title' } + ); + defaultTabs.splice(1, 0, - { route: 'group.manage.members', title: 'groups.manage.members.title' } + { route: 'group.manage.membership', title: 'groups.manage.membership.title' } ); } diff --git a/app/assets/javascripts/discourse/routes/app-route-map.js.es6 b/app/assets/javascripts/discourse/routes/app-route-map.js.es6 index eece80d8260..f489faf4bbf 100644 --- a/app/assets/javascripts/discourse/routes/app-route-map.js.es6 +++ b/app/assets/javascripts/discourse/routes/app-route-map.js.es6 @@ -64,6 +64,8 @@ export default function() { this.route('manage', function() { this.route('profile'); + this.route('membership'); + this.route('interaction'); this.route('members'); this.route('logs'); }); diff --git a/app/assets/javascripts/discourse/routes/group-index.js.es6 b/app/assets/javascripts/discourse/routes/group-index.js.es6 index 815308f20a3..10bc4a23d35 100644 --- a/app/assets/javascripts/discourse/routes/group-index.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-index.js.es6 @@ -1,3 +1,5 @@ +import showModal from 'discourse/lib/show-modal'; + export default Discourse.Route.extend({ titleToken() { return I18n.t('groups.members.title'); @@ -20,6 +22,10 @@ export default Discourse.Route.extend({ }, actions: { + showAddMembersModal() { + showModal('group-add-members', { model: this.modelFor('group') }); + }, + didTransition() { this.controllerFor("group-index").set("filterInput", this._params.filter); return true; diff --git a/app/assets/javascripts/discourse/routes/group-manage-members.js.es6 b/app/assets/javascripts/discourse/routes/group-manage-members.js.es6 deleted file mode 100644 index 16bec11a463..00000000000 --- a/app/assets/javascripts/discourse/routes/group-manage-members.js.es6 +++ /dev/null @@ -1,9 +0,0 @@ -export default Discourse.Route.extend({ - titleToken() { - return I18n.t('groups.manage.members.title'); - }, - - model() { - return this.modelFor('group'); - }, -}); diff --git a/app/assets/javascripts/discourse/routes/group-manage.js.es6 b/app/assets/javascripts/discourse/routes/group-manage.js.es6 index 43830174aab..e80cab10893 100644 --- a/app/assets/javascripts/discourse/routes/group-manage.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-manage.js.es6 @@ -19,5 +19,5 @@ export default Discourse.Route.extend({ setupController(controller, model) { this.controllerFor('group-manage').setProperties({ model }); this.controllerFor("group").set("showing", 'manage'); - } + }, }); diff --git a/app/assets/javascripts/discourse/routes/groups-new.js.es6 b/app/assets/javascripts/discourse/routes/groups-new.js.es6 index e7489737cbc..24d0e968582 100644 --- a/app/assets/javascripts/discourse/routes/groups-new.js.es6 +++ b/app/assets/javascripts/discourse/routes/groups-new.js.es6 @@ -2,7 +2,7 @@ import Group from 'discourse/models/group'; export default Discourse.Route.extend({ titleToken() { - return I18n.t('groups.new.title'); + return I18n.t('admin.groups.new.title'); }, model() { diff --git a/app/assets/javascripts/discourse/templates/components/group-flair-inputs.hbs b/app/assets/javascripts/discourse/templates/components/group-flair-inputs.hbs index 5693422c4d5..ad0530ba8e7 100644 --- a/app/assets/javascripts/discourse/templates/components/group-flair-inputs.hbs +++ b/app/assets/javascripts/discourse/templates/components/group-flair-inputs.hbs @@ -1,36 +1,35 @@ -