REFACTOR: Extract group form into a component.

This commit is contained in:
Guo Xiang Tan 2018-03-27 18:59:21 +08:00
parent f81af74ad8
commit f6b6ddd73c
7 changed files with 313 additions and 351 deletions

View File

@ -0,0 +1,102 @@
import computed 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,
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 }
],
@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;
},
@computed('model.name')
basicNameValidation(name) {
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() {
User.checkUsername(this.get('model.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);
} 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;
return InputValidation.create(options);
},
actions: {
save() {
this.sendAction("save");
},
}
});

View File

@ -1,94 +1,6 @@
import { popupAjaxError } from 'discourse/lib/ajax-error';
import computed 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.Controller.extend({
disableSave: null,
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 }
],
@computed('model.visibility_level', 'model.public_admission')
disableMembershipRequestSetting(visibility_level, publicAdmission) {
visibility_level = parseInt(visibility_level);
return (visibility_level !== 0) || publicAdmission;
},
@computed('basicNameValidation', 'uniqueNameValidation')
nameValidation(basicNameValidation, uniqueNameValidation) {
return uniqueNameValidation ? uniqueNameValidation : basicNameValidation;
},
@computed('model.name')
basicNameValidation(name) {
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() {
User.checkUsername(this.get('model.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);
} 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;
return InputValidation.create(options);
},
actions: {
save() {
this.set('disableSave', true);

View File

@ -0,0 +1,191 @@
<form class="groups-new-form form-horizontal">
{{#if this.currentUser.admin}}
<div class="control-group">
<label for="name">{{i18n 'groups.name'}}</label>
{{text-field name="name"
class="input-xxlarge group-form-name"
value=model.name
placeholderKey="groups.name_placeholder"}}
{{input-tip validation=nameValidation}}
</div>
{{/if}}
<div class="control-group">
<label for='full_name'>{{i18n 'groups.manage.full_name'}}</label>
{{text-field name='full_name'
class="input-xxlarge group-form-full-name"
value=model.full_name}}
</div>
{{#if this.currentUser.admin}}
<div class="control-group">
<label for="title">
{{i18n 'admin.groups.default_title'}}
</label>
{{input value=model.title name="title" class="input-xxlarge"}}
</div>
{{/if}}
<div class="control-group">
<label for="bio">{{i18n 'groups.bio'}}</label>
{{d-editor value=model.bio_raw class="group-form-bio"}}
</div>
{{#if manageMembership}}
<div class="control-group">
<label for="owner-selector">{{i18n 'admin.groups.add_owners'}}</label>
{{user-selector usernames=model.ownerUsernames
placeholderKey="groups.selector_placeholder"
id="owner-selector"}}
</div>
<div class="control-group">
<label for="member-selector">{{i18n 'groups.members.title'}}</label>
{{user-selector usernames=model.usernames
placeholderKey="groups.selector_placeholder"
id="member-selector"}}
</div>
<div class="control-group">
<label for="visiblity">{{i18n 'groups.visibility_levels.title'}}</label>
{{combo-box name="alias"
valueAttribute="value"
value=model.visibility_level
content=visibilityLevelOptions
castInteger=true}}
</div>
{{/if}}
<div class="control-group">
{{#if currentUser.admin}}
<label>
{{input type="checkbox" checked=model.primary_group}}
{{i18n 'admin.groups.primary_group'}}
</label>
{{/if}}
<label>
{{input type="checkbox"
class="group-form-public-admission"
checked=model.public_admission
disabled=disablePublicSetting}}
{{i18n 'groups.public_admission'}}
</label>
<label>
{{input type='checkbox'
class='group-form-public-exit'
checked=model.public_exit}}
{{i18n 'groups.public_exit'}}
</label>
<label>
{{input type="checkbox"
class="group-form-allow-membership-requests"
checked=model.allow_membership_requests
disabled=disableMembershipRequestSetting}}
{{i18n 'groups.allow_membership_requests'}}
</label>
{{#if model.allow_membership_requests}}
<div>
<label for="membership-request-template">
{{i18n 'groups.membership_request_template'}}
</label>
{{expanding-text-area name="membership-request-template"
class='group-form-membership-request-template'
value=model.membership_request_template}}
</div>
{{/if}}
</div>
{{#if currentUser.admin}}
<div class="control-group">
<label for="alias">{{i18n 'groups.alias_levels.mentionable'}}</label>
{{combo-box name="alias"
valueAttribute="value"
value=model.mentionable_level
content=aliasLevelOptions}}
</div>
<div class="control-group">
<label for="alias">{{i18n 'groups.alias_levels.messageable'}}</label>
{{combo-box name="alias"
valueAttribute="value"
value=model.messageable_level
content=aliasLevelOptions}}
</div>
<div class="control-group">
<label>{{i18n 'groups.notification_level'}}</label>
{{notifications-button i18nPrefix='groups.notifications'
value=model.default_notification_level}}
</div>
<div class="control-group">
<label for="automatic_membership">
{{i18n 'admin.groups.automatic_membership_email_domains'}}
</label>
{{list-setting name="automatic_membership" settingValue=model.emailDomains}}
<label>
{{input type="checkbox" checked=model.automatic_membership_retroactive}}
{{i18n 'admin.groups.automatic_membership_retroactive'}}
</label>
</div>
<div class="control-group">
<label for="grant_trust_level">{{i18n 'groups.trust_levels.title'}}</label>
{{combo-box name="grant_trust_level"
valueAttribute="value"
value=model.grant_trust_level
content=trustLevelOptions}}
</div>
{{#if siteSettings.email_in}}
<div class="control-group">
<label for="incoming_email">{{i18n 'admin.groups.incoming_email'}}</label>
{{text-field name="incoming_email"
class="input-xxlarge"
value=model.incoming_email
placeholderKey="admin.groups.incoming_email_placeholder"}}
{{plugin-outlet name="group-email-in" args=(hash model=model)}}
</div>
{{/if}}
{{/if}}
<div class="control-group">
{{group-flair-inputs model=model}}
</div>
{{plugin-outlet name="group-edit" args=(hash group=model)}}
<div class='control-group buttons'>
{{d-button action="save"
disabled=disableSave
class='btn btn-primary'
label='groups.new.create'}}
{{#link-to "groups"}}
{{i18n 'cancel'}}
{{/link-to}}
</div>
</form>

View File

@ -1,71 +1,3 @@
<form class="form-horizontal">
{{#if this.currentUser.admin}}
<div class="control-group">
<label for='name'>{{i18n 'groups.manage.name'}}</label>
{{input type='text' name='name' value=model.name class='group-manage-name'}}
</div>
{{/if}}
<div class="control-group">
<label for='full_name'>{{i18n 'groups.manage.full_name'}}</label>
{{input type='text' name='full_name' value=model.full_name class='group-manage-full-name'}}
</div>
<div class="control-group">
<label for='bio'>{{i18n 'groups.bio'}}</label>
{{d-editor value=model.bio_raw class="group-manage-bio"}}
</div>
<div class="control-group">
{{group-flair-inputs model=model}}
</div>
<div class="control-group">
<label>
{{input type='checkbox'
checked=model.public_admission
class="group-manage-public-admission"
disabled=model.allow_membership_requests}}
{{i18n 'groups.public_admission'}}
</label>
</div>
<div class="control-group">
<label>
{{input type='checkbox'
checked=model.public_exit
class="group-manage-public-exit"}}
{{i18n 'groups.public_exit'}}
</label>
</div>
<div class="control-group">
<label>
{{input type='checkbox'
checked=model.allow_membership_requests
class="group-manage-allow-membership-requests"
disabled=model.public_admission}}
{{i18n 'groups.allow_membership_requests'}}
</label>
</div>
{{#if model.allow_membership_requests}}
<div>
<label for="membership-request-template">
{{i18n 'groups.membership_request_template'}}
</label>
{{expanding-text-area name="membership-request-template"
value=model.membership_request_template
class="group-manage-membership-request-template"}}
</div>
{{/if}}
{{plugin-outlet name="group-manage" args=(hash group=model)}}
{{d-button action="save" class="btn-primary" disabled=saving label="save"}}
{{savingText}}
</form>
{{group-form model=model
save="save"
manageMembership=false}}

View File

@ -1,183 +1,5 @@
{{#d-section pageClass="groups-new"}}
<h1>{{i18n "groups.new.title"}}</h1>
<form class="groups-new-form form-horizontal">
<div class="control-group">
<label for="name">{{i18n 'groups.name'}}</label>
{{text-field name="name"
class="input-xxlarge"
value=model.name
placeholderKey="groups.name_placeholder"}}
{{input-tip validation=nameValidation}}
</div>
<div class="control-group">
<label for='full_name'>{{i18n 'groups.manage.full_name'}}</label>
{{text-field name='full_name'
class="input-xxlarge group-manage-full-name"
value=model.full_name}}
</div>
<div class="control-group">
<label for="title">
{{i18n 'admin.groups.default_title'}}
</label>
{{input value=model.title name="title" class="input-xxlarge"}}
</div>
<div class="control-group">
<label for="bio">{{i18n 'groups.bio'}}</label>
{{d-editor value=model.bio_raw}}
</div>
<div class="control-group">
<label for="owner-selector">{{i18n 'admin.groups.add_owners'}}</label>
{{user-selector usernames=model.ownerUsernames
placeholderKey="groups.selector_placeholder"
id="owner-selector"}}
</div>
<div class="control-group">
<label for="member-selector">{{i18n 'groups.members.title'}}</label>
{{user-selector usernames=model.usernames
placeholderKey="groups.selector_placeholder"
id="member-selector"}}
</div>
<div class="control-group">
<label for="visiblity">{{i18n 'groups.visibility_levels.title'}}</label>
{{combo-box name="alias"
valueAttribute="value"
value=model.visibility_level
content=visibilityLevelOptions
castInteger=true}}
</div>
<div class="control-group">
<label>
{{input type="checkbox" checked=model.primary_group}}
{{i18n 'admin.groups.primary_group'}}
</label>
<label>
{{input type="checkbox"
class="groups-new-public-admission"
checked=model.public_admission
disabled=disablePublicSetting}}
{{i18n 'groups.public_admission'}}
</label>
<label>
{{input type='checkbox'
checked=model.public_exit}}
{{i18n 'groups.public_exit'}}
</label>
<label>
{{input type="checkbox"
class="groups-new-allow-membership-requests"
checked=model.allow_membership_requests
disabled=disableMembershipRequestSetting}}
{{i18n 'groups.allow_membership_requests'}}
</label>
{{#if model.allow_membership_requests}}
<div>
<label for="membership-request-template">
{{i18n 'groups.membership_request_template'}}
</label>
{{expanding-text-area name="membership-request-template"
value=model.membership_request_template}}
</div>
{{/if}}
</div>
<div class="control-group">
<label for="alias">{{i18n 'groups.alias_levels.mentionable'}}</label>
{{combo-box name="alias"
valueAttribute="value"
value=model.mentionable_level
content=aliasLevelOptions}}
</div>
<div class="control-group">
<label for="alias">{{i18n 'groups.alias_levels.messageable'}}</label>
{{combo-box name="alias"
valueAttribute="value"
value=model.messageable_level
content=aliasLevelOptions}}
</div>
<div class="control-group">
<label>{{i18n 'groups.notification_level'}}</label>
{{notifications-button i18nPrefix='groups.notifications'
value=model.default_notification_level}}
</div>
<div class="control-group">
<label for="automatic_membership">
{{i18n 'admin.groups.automatic_membership_email_domains'}}
</label>
{{list-setting name="automatic_membership" settingValue=model.emailDomains}}
<label>
{{input type="checkbox" checked=model.automatic_membership_retroactive}}
{{i18n 'admin.groups.automatic_membership_retroactive'}}
</label>
</div>
<div class="control-group">
<label for="grant_trust_level">{{i18n 'groups.trust_levels.title'}}</label>
{{combo-box name="grant_trust_level"
valueAttribute="value"
value=model.grant_trust_level
content=trustLevelOptions}}
</div>
{{#if siteSettings.email_in}}
<div class="control-group">
<label for="incoming_email">{{i18n 'admin.groups.incoming_email'}}</label>
{{text-field name="incoming_email"
class="input-xxlarge"
value=model.incoming_email
placeholderKey="admin.groups.incoming_email_placeholder"}}
{{plugin-outlet name="group-email-in" args=(hash model=model)}}
</div>
{{/if}}
<div class="control-group">
{{group-flair-inputs model=model}}
</div>
{{plugin-outlet name="group-edit" args=(hash group=model)}}
<div class='control-group buttons'>
{{d-button action="save"
disabled=disableSave
class='btn btn-primary'
label='groups.new.create'}}
{{#link-to "groups"}}
{{i18n 'cancel'}}
{{/link-to}}
</div>
</form>
{{group-form model=model save="save"}}
{{/d-section}}

View File

@ -10,44 +10,47 @@ QUnit.test("Editing group", assert => {
andThen(() => {
assert.ok(find('.group-flair-inputs').length === 1, 'it should display avatar flair inputs');
assert.ok(find('.group-manage-bio').length === 1, 'it should display group bio input');
assert.ok(find('.group-manage-name').length === 1, 'it should display group name input');
assert.ok(find('.group-manage-full-name').length === 1, 'it should display group full name input');
assert.ok(find('.group-form-bio').length === 1, 'it should display group bio input');
assert.ok(find('.group-form-name').length === 1, 'it should display group name input');
assert.ok(find('.group-form-full-name').length === 1, 'it should display group full name input');
assert.ok(
find('.group-manage-public-admission').length === 1,
find('.group-form-public-admission').length === 1,
'it should display group public admission input'
);
assert.ok(
find('.group-manage-public-exit').length === 1,
find('.group-form-public-exit').length === 1,
'it should display group public exit input'
);
assert.ok(find('.group-manage-allow-membership-requests').length === 1, 'it should display group allow_membership_requets input');
assert.ok(
find('.group-form-allow-membership-requests').length === 1,
'it should display group allow_membership_request input'
);
assert.ok(
find('.group-manage-allow-membership-requests[disabled]').length === 1,
find('.group-form-allow-membership-requests[disabled]').length === 1,
'it should disable group allow_membership_request input'
);
});
click('.group-manage-public-admission');
click('.group-manage-allow-membership-requests');
click('.group-form-public-admission');
click('.group-form-allow-membership-requests');
andThen(() => {
assert.ok(
find('.group-manage-public-admission[disabled]').length === 1,
find('.group-form-public-admission[disabled]').length === 1,
'it should disable group public admission input'
);
assert.ok(
find('.group-manage-public-exit[disabled]').length === 0,
find('.group-form-public-exit[disabled]').length === 0,
'it should not disable group public exit input'
);
assert.equal(
find('.group-manage-membership-request-template').length, 1,
find('.group-form-membership-request-template').length, 1,
'it should display the membership request template field'
);
});

View File

@ -61,7 +61,7 @@ QUnit.test("Creating a new group", assert => {
);
});
click(".groups-new-public-admission");
click(".group-form-public-admission");
andThen(() => {
assert.equal(