FEATURE: Support for a `required` setting on user fields.
This commit is contained in:
parent
9f2be41710
commit
f9a8f6d6ce
|
@ -9,11 +9,23 @@ export default Ember.ObjectController.extend(BufferedContent, {
|
|||
return UserField.fieldTypeById(this.get('field_type')).get('name');
|
||||
}.property('field_type'),
|
||||
|
||||
flags: function() {
|
||||
var ret = [];
|
||||
if (this.get('editable')) {
|
||||
ret.push(I18n.t('admin.user_fields.editable.enabled'));
|
||||
}
|
||||
if (this.get('required')) {
|
||||
ret.push(I18n.t('admin.user_fields.required.enabled'));
|
||||
}
|
||||
|
||||
return ret.join(', ');
|
||||
}.property('editable', 'required'),
|
||||
|
||||
actions: {
|
||||
save: function() {
|
||||
var self = this;
|
||||
|
||||
var attrs = this.get('buffered').getProperties('name', 'description', 'field_type', 'editable');
|
||||
var attrs = this.get('buffered').getProperties('name', 'description', 'field_type', 'editable', 'required');
|
||||
|
||||
this.get('model').save(attrs).then(function(res) {
|
||||
self.set('model.id', res.user_field.id);
|
||||
|
|
|
@ -11,12 +11,10 @@
|
|||
{{input value=f.buffered.name class="user-field-name" placeholder=userFieldsName}}
|
||||
</div>
|
||||
<div class='form-element'>
|
||||
{{combo-box content=fieldTypes valueAttribute="id" value=f.buffered.field_type}}
|
||||
{{input value=f.buffered.description class="user-field-desc" placeholder=userFieldsDescription}}
|
||||
</div>
|
||||
<div class='form-element'>
|
||||
<label>
|
||||
{{input type="checkbox" checked=f.buffered.editable}} {{i18n admin.user_fields.editable.title}}
|
||||
</label>
|
||||
{{combo-box content=fieldTypes valueAttribute="id" value=f.buffered.field_type}}
|
||||
</div>
|
||||
<div class='form-element controls'>
|
||||
<button {{action "save"}}class='btn btn-primary'>{{fa-icon 'check'}} {{i18n admin.user_fields.save}}</button>
|
||||
|
@ -25,29 +23,29 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class='form-element'>
|
||||
{{input value=f.buffered.description class="user-field-desc" placeholder=userFieldsDescription}}
|
||||
<label>
|
||||
{{input type="checkbox" checked=f.buffered.editable}} {{i18n admin.user_fields.editable.title}}
|
||||
</label>
|
||||
</div>
|
||||
<div class='form-element'>
|
||||
<label>
|
||||
{{input type="checkbox" checked=f.buffered.required}} {{i18n admin.user_fields.required.title}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row">
|
||||
<div class='form-display'><strong>{{f.name}}</strong></div>
|
||||
<div class='form-display'>{{f.fieldName}}</div>
|
||||
<div class='form-display'>
|
||||
{{#if f.editable}}
|
||||
{{i18n admin.user_fields.editable.enabled}}
|
||||
{{else}}
|
||||
{{i18n admin.user_fields.editable.disabled}}
|
||||
{{/if}}
|
||||
<div class='form-display'><strong>{{f.name}}</strong></div>
|
||||
<div class='form-display'>{{{f.description}}}</div>
|
||||
<div class='form-display'>{{f.fieldName}}</div>
|
||||
<div class='form-display'>
|
||||
</div>
|
||||
<div class='form-element controls'>
|
||||
<button {{action "edit"}}class='btn btn-default'>{{fa-icon 'pencil'}} {{i18n admin.user_fields.edit}}</button>
|
||||
<button {{action "destroy"}}class='btn btn-danger'>{{fa-icon 'trash-o'}} {{i18n admin.user_fields.delete}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class='form-element controls'>
|
||||
<button {{action "edit"}}class='btn btn-default'>{{fa-icon 'pencil'}} {{i18n admin.user_fields.edit}}</button>
|
||||
<button {{action "destroy"}}class='btn btn-danger'>{{fa-icon 'trash-o'}} {{i18n admin.user_fields.delete}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{f.description}}
|
||||
</div>
|
||||
|
||||
<div class="row">{{f.flags}}</div>
|
||||
{{/if}}
|
||||
<div class='clearfix'></div>
|
||||
{{/each}}
|
||||
|
|
|
@ -51,6 +51,7 @@ export default DiscourseController.extend(ModalFunctionality, {
|
|||
|
||||
// Validate required fields
|
||||
var userFields = this.get('userFields');
|
||||
if (userFields) { userFields = userFields.filterProperty('field.required'); }
|
||||
if (!Ember.empty(userFields)) {
|
||||
var anyEmpty = userFields.any(function(uf) {
|
||||
var val = uf.get('value');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<label>{{{field.name}}}</label>
|
||||
<div class='controls'>
|
||||
{{input value=value}}
|
||||
{{#if field.required}}<span class='required'>*</span>{{/if}}
|
||||
<p>{{{field.description}}}</p>
|
||||
</div>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
}
|
||||
.controls {
|
||||
margin-left: 92px;
|
||||
margin-bottom: 15px;
|
||||
label {
|
||||
width: auto;
|
||||
text-align: left;
|
||||
|
|
|
@ -15,6 +15,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
.user-field {
|
||||
.required {
|
||||
text-align: top;
|
||||
color: $danger;
|
||||
font-weight: bold;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
.end-of-stream {
|
||||
border: 3px solid $primary;
|
||||
width: 100%;
|
||||
|
@ -22,7 +31,7 @@
|
|||
|
||||
.user-navigation {
|
||||
|
||||
.map {
|
||||
.map {
|
||||
height: 50px;
|
||||
}
|
||||
.avatar {
|
||||
|
|
|
@ -63,6 +63,7 @@ a#forgot-password-link {clear: left; float: left; }
|
|||
label {
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
margin-top: 0;
|
||||
width: 184px;
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
class Admin::UserFieldsController < Admin::AdminController
|
||||
|
||||
def self.columns
|
||||
[:name, :field_type, :editable, :description, :required]
|
||||
end
|
||||
|
||||
def create
|
||||
field = UserField.new(params.require(:user_field).permit(:name, :field_type, :editable, :description))
|
||||
field = UserField.new(params.require(:user_field).permit(*Admin::UserFieldsController.columns))
|
||||
json_result(field, serializer: UserFieldSerializer) do
|
||||
field.save
|
||||
end
|
||||
|
@ -15,10 +19,10 @@ class Admin::UserFieldsController < Admin::AdminController
|
|||
field_params = params.require(:user_field)
|
||||
|
||||
field = UserField.where(id: params.require(:id)).first
|
||||
field.name = field_params[:name]
|
||||
field.field_type = field_params[:field_type]
|
||||
field.description = field_params[:description]
|
||||
field.editable = field_params[:editable] == "true"
|
||||
|
||||
Admin::UserFieldsController.columns.each do |col|
|
||||
field.send("#{col}=", field_params[col] || false)
|
||||
end
|
||||
|
||||
json_result(field, serializer: UserFieldSerializer) do
|
||||
field.save
|
||||
|
|
|
@ -49,11 +49,12 @@ class UsersController < ApplicationController
|
|||
|
||||
if params[:user_fields].present?
|
||||
params[:custom_fields] ||= {}
|
||||
UserField.where(editable: true).pluck(:id).each do |fid|
|
||||
val = params[:user_fields][fid.to_s]
|
||||
UserField.where(editable: true).each do |f|
|
||||
val = params[:user_fields][f.id.to_s]
|
||||
val = nil if val === "false"
|
||||
return render_json_error(I18n.t("login.missing_user_field")) if val.blank?
|
||||
params[:custom_fields]["user_field_#{fid}"] = val
|
||||
|
||||
return render_json_error(I18n.t("login.missing_user_field")) if val.blank? && f.required?
|
||||
params[:custom_fields]["user_field_#{f.id}"] = val
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -188,16 +189,19 @@ class UsersController < ApplicationController
|
|||
user = User.new(user_params)
|
||||
|
||||
# Handle custom fields
|
||||
user_field_ids = UserField.pluck(:id)
|
||||
if user_field_ids.present?
|
||||
if params[:user_fields].blank?
|
||||
user_fields = UserField.all
|
||||
if user_fields.present?
|
||||
if params[:user_fields].blank? && UserField.where(required: true).exists?
|
||||
return fail_with("login.missing_user_field")
|
||||
else
|
||||
fields = user.custom_fields
|
||||
user_field_ids.each do |fid|
|
||||
field_val = params[:user_fields][fid.to_s]
|
||||
return fail_with("login.missing_user_field") if field_val.blank?
|
||||
fields["user_field_#{fid}"] = field_val
|
||||
user_fields.each do |f|
|
||||
field_val = params[:user_fields][f.id.to_s]
|
||||
if field_val.blank?
|
||||
return fail_with("login.missing_user_field") if f.required?
|
||||
else
|
||||
fields["user_field_#{f.id}"] = field_val
|
||||
end
|
||||
end
|
||||
user.custom_fields = fields
|
||||
end
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
class UserFieldSerializer < ApplicationSerializer
|
||||
attributes :id, :name, :description, :field_type, :editable
|
||||
attributes :id,
|
||||
:name,
|
||||
:description,
|
||||
:field_type,
|
||||
:editable,
|
||||
:required
|
||||
end
|
||||
|
|
|
@ -2019,6 +2019,10 @@ en:
|
|||
delete: "Delete"
|
||||
cancel: "Cancel"
|
||||
delete_confirm: "Are you sure you want to delete that user field?"
|
||||
required:
|
||||
title: "Required at signup?"
|
||||
enabled: "required"
|
||||
disabled: "not required"
|
||||
editable:
|
||||
title: "Editable after signup?"
|
||||
enabled: "editable"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddRequiredSignupToUserFields < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :user_fields, :required, :boolean, default: true, null: false
|
||||
end
|
||||
end
|
|
@ -32,7 +32,7 @@ describe Admin::UserFieldsController do
|
|||
context '.destroy' do
|
||||
let!(:user_field) { Fabricate(:user_field) }
|
||||
|
||||
it "returns a list of user fields" do
|
||||
it "deletes the user field" do
|
||||
-> {
|
||||
xhr :delete, :destroy, id: user_field.id
|
||||
response.should be_success
|
||||
|
@ -43,7 +43,7 @@ describe Admin::UserFieldsController do
|
|||
context '.update' do
|
||||
let!(:user_field) { Fabricate(:user_field) }
|
||||
|
||||
it "returns a list of user fields" do
|
||||
it "updates the user field" do
|
||||
xhr :put, :update, id: user_field.id, user_field: {name: 'fraggle', field_type: 'confirm', description: 'muppet'}
|
||||
response.should be_success
|
||||
user_field.reload
|
||||
|
|
|
@ -559,6 +559,7 @@ describe UsersController do
|
|||
context "with custom fields" do
|
||||
let!(:user_field) { Fabricate(:user_field) }
|
||||
let!(:another_field) { Fabricate(:user_field) }
|
||||
let!(:optional_field) { Fabricate(:user_field, required: false) }
|
||||
|
||||
context "without a value for the fields" do
|
||||
let(:create_params) { {name: @user.name, password: 'watwatwat', username: @user.username, email: @user.email} }
|
||||
|
@ -577,7 +578,7 @@ describe UsersController do
|
|||
}
|
||||
} }
|
||||
|
||||
it "should succeed" do
|
||||
it "should succeed without the optional field" do
|
||||
xhr :post, :create, create_params
|
||||
response.should be_success
|
||||
inserted = User.where(email: @user.email).first
|
||||
|
@ -585,6 +586,19 @@ describe UsersController do
|
|||
inserted.custom_fields.should be_present
|
||||
inserted.custom_fields["user_field_#{user_field.id}"].should == 'value1'
|
||||
inserted.custom_fields["user_field_#{another_field.id}"].should == 'value2'
|
||||
inserted.custom_fields["user_field_#{optional_field.id}"].should be_blank
|
||||
end
|
||||
|
||||
it "should succeed with the optional field" do
|
||||
create_params[:user_fields][optional_field.id.to_s] = 'value3'
|
||||
xhr :post, :create, create_params.merge(create_params)
|
||||
response.should be_success
|
||||
inserted = User.where(email: @user.email).first
|
||||
inserted.should be_present
|
||||
inserted.custom_fields.should be_present
|
||||
inserted.custom_fields["user_field_#{user_field.id}"].should == 'value1'
|
||||
inserted.custom_fields["user_field_#{another_field.id}"].should == 'value2'
|
||||
inserted.custom_fields["user_field_#{optional_field.id}"].should == 'value3'
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -904,6 +918,7 @@ describe UsersController do
|
|||
context "with user fields" do
|
||||
context "an editable field" do
|
||||
let!(:user_field) { Fabricate(:user_field) }
|
||||
let!(:optional_field) { Fabricate(:user_field, required: false ) }
|
||||
|
||||
it "should update the user field" do
|
||||
put :update, username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => 'happy' }
|
||||
|
|
|
@ -3,4 +3,5 @@ Fabricator(:user_field) do
|
|||
description "user field description"
|
||||
field_type 'text'
|
||||
editable true
|
||||
required true
|
||||
end
|
|
@ -2,8 +2,9 @@ import { integration } from "helpers/qunit-helpers";
|
|||
|
||||
integration("Create Account - User Fields", {
|
||||
site: {
|
||||
user_fields: [{"id":34,"name":"I've read the terms of service","field_type":"confirm"},
|
||||
{"id":35,"name":"What is your pet's name?","field_type":"text"}]
|
||||
user_fields: [{"id":34,"name":"I've read the terms of service","field_type":"confirm","required":true},
|
||||
{"id":35,"name":"What is your pet's name?","field_type":"text","required":true},
|
||||
{"id":36,"name":"What's your dad like?","field_type":"text","required":false}]
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -27,7 +28,7 @@ test("create account with user fields", function() {
|
|||
ok(exists('.modal-footer .btn-primary:disabled'), 'create account is still disabled due to lack of user fields');
|
||||
});
|
||||
|
||||
fillIn(".user-field input[type=text]", "Barky");
|
||||
fillIn(".user-field input[type=text]:first", "Barky");
|
||||
|
||||
andThen(function() {
|
||||
ok(exists('.modal-footer .btn-primary:disabled'), 'create account is disabled because field is not checked');
|
||||
|
@ -35,7 +36,7 @@ test("create account with user fields", function() {
|
|||
|
||||
click(".user-field input[type=checkbox]");
|
||||
andThen(function() {
|
||||
not(exists('.modal-footer .btn-primary:disabled'), 'create account is disabled because field is not checked');
|
||||
not(exists('.modal-footer .btn-primary:disabled'), 'create account is enabled because field is not checked');
|
||||
});
|
||||
|
||||
click(".user-field input[type=checkbox]");
|
||||
|
|
Loading…
Reference in New Issue