mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Wizard: Server Side Validation + Finished Step
This commit is contained in:
@@ -64,10 +64,11 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
const $elem = this.$();
|
||||
const minimumResultsForSearch = this.capabilities.isIOS ? -1 : 5;
|
||||
const caps = this.capabilities;
|
||||
const minimumResultsForSearch = (caps && caps.isIOS) ? -1 : 5;
|
||||
$elem.select2({
|
||||
formatResult: this.comboTemplate, minimumResultsForSearch,
|
||||
width: 'resolve',
|
||||
width: this.get('width') || 'resolve',
|
||||
allowClear: true
|
||||
});
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import { htmlHelper } from 'discourse-common/lib/helpers';
|
||||
|
||||
export default htmlHelper((key, params) => I18n.t(key, params.hash));
|
||||
@@ -1,4 +1,4 @@
|
||||
import ComboboxView from 'discourse/components/combo-box';
|
||||
import ComboboxView from 'discourse-common/components/combo-box';
|
||||
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { observes, on } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { iconHTML } from 'discourse-common/helpers/fa-icon';
|
||||
import Combobox from 'discourse/components/combo-box';
|
||||
import Combobox from 'discourse-common/components/combo-box';
|
||||
import { on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Combobox.extend({
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//= require env
|
||||
//= require jquery_include
|
||||
//= require ember_include
|
||||
//= require loader
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
//= require ./discourse/views/container
|
||||
//= require ./discourse/views/modal-body
|
||||
//= require ./discourse/views/flag
|
||||
//= require ./discourse/components/combo-box
|
||||
//= require ./discourse/components/edit-category-panel
|
||||
//= require ./discourse/views/button
|
||||
//= require ./discourse/components/dropdown-button
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//= require logster
|
||||
//= require ./env
|
||||
//= require ./discourse-objects
|
||||
//= require probes.js
|
||||
|
||||
@@ -38,4 +37,3 @@
|
||||
//= require virtual-dom
|
||||
//= require virtual-dom-amd
|
||||
//= require highlight.js
|
||||
//= require_tree ./discourse/ember
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
//= require env
|
||||
//= require template_include.js
|
||||
//= require select2.js
|
||||
|
||||
@@ -4,5 +4,8 @@ export default Ember.Component.extend({
|
||||
classNameBindings: [':wizard-field', ':text-field', 'field.invalid'],
|
||||
|
||||
@computed('field.id')
|
||||
inputClassName: id => `field-${Ember.String.dasherize(id)}`
|
||||
inputClassName: id => `field-${Ember.String.dasherize(id)}`,
|
||||
|
||||
@computed('field.type')
|
||||
inputComponentName: type => `wizard-field-${type}`
|
||||
});
|
||||
|
||||
@@ -12,6 +12,9 @@ export default Ember.Component.extend({
|
||||
@computed('step.displayIndex', 'wizard.totalSteps')
|
||||
showNextButton: (current, total) => current < total,
|
||||
|
||||
@computed('step.displayIndex', 'wizard.totalSteps')
|
||||
showDoneButton: (current, total) => current === total,
|
||||
|
||||
@computed('step.index')
|
||||
showBackButton: index => index > 0,
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ export const States = {
|
||||
|
||||
export default {
|
||||
_validState: null,
|
||||
errorDescription: null,
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
@@ -23,8 +24,14 @@ export default {
|
||||
@computed('_validState')
|
||||
unchecked: state => state === States.UNCHECKED,
|
||||
|
||||
setValid(valid) {
|
||||
setValid(valid, description) {
|
||||
this.set('_validState', valid ? States.VALID : States.INVALID);
|
||||
|
||||
if (!valid && description && description.length) {
|
||||
this.set('errorDescription', description);
|
||||
} else {
|
||||
this.set('errorDescription', null);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export default Ember.Route.extend({
|
||||
model(params) {
|
||||
const allSteps = this.modelFor('application').steps;
|
||||
return allSteps.findProperty('id', params.step_id);
|
||||
const step = allSteps.findProperty('id', params.step_id);
|
||||
return step ? step : allSteps[0];
|
||||
},
|
||||
|
||||
setupController(controller, step) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{{combo-box value=field.value content=field.options nameProperty="label" width="400px"}}
|
||||
@@ -0,0 +1 @@
|
||||
{{input value=field.value class=inputClassName placeholder=field.placeholder}}
|
||||
@@ -2,6 +2,14 @@
|
||||
<span class='label-value'>{{field.label}}</span>
|
||||
|
||||
<div class='input-area'>
|
||||
{{input value=field.value class=inputClassName placeholder=field.placeholder}}
|
||||
{{component inputComponentName field=field inputClassName=inputClassName}}
|
||||
</div>
|
||||
|
||||
{{#if field.errorDescription}}
|
||||
<div class='field-error-description'>{{field.errorDescription}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if field.description}}
|
||||
<div class='field-description'>{{field.description}}</div>
|
||||
{{/if}}
|
||||
</label>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if step.description}}
|
||||
<p class='wizard-step-description'>{{step.description}}</p>
|
||||
<p class='wizard-step-description'>{{{step.description}}}</p>
|
||||
{{/if}}
|
||||
|
||||
{{#wizard-step-form step=step}}
|
||||
@@ -14,24 +14,33 @@
|
||||
|
||||
<div class='wizard-step-footer'>
|
||||
<div class='wizard-progress'>
|
||||
<div class='text'>{{i18n "wizard.step" current=step.displayIndex total=wizard.totalSteps}}</div>
|
||||
<div class='text'>{{bound-i18n "wizard.step" current=step.displayIndex total=wizard.totalSteps}}</div>
|
||||
<div class='bar-container'>
|
||||
<div class='bar-contents' style={{barStyle}}></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if showBackButton}}
|
||||
<button class='wizard-btn back' {{action "backStep"}} disabled={{saving}}>
|
||||
{{fa-icon "chevron-left"}}
|
||||
{{i18n "wizard.back"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
<div class='wizard-buttons'>
|
||||
{{#if showBackButton}}
|
||||
<button class='wizard-btn back' {{action "backStep"}} disabled={{saving}}>
|
||||
{{fa-icon "chevron-left"}}
|
||||
{{i18n "wizard.back"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if showNextButton}}
|
||||
<button class='wizard-btn next' {{action "nextStep"}} disabled={{saving}}>
|
||||
{{i18n "wizard.next"}}
|
||||
{{fa-icon "chevron-right"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
{{#if showNextButton}}
|
||||
<button class='wizard-btn next' {{action "nextStep"}} disabled={{saving}}>
|
||||
{{i18n "wizard.next"}}
|
||||
{{fa-icon "chevron-right"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if showDoneButton}}
|
||||
<button class='wizard-btn done' {{action "finished"}} disabled={{saving}}>
|
||||
{{fa-icon "check"}}
|
||||
{{i18n "wizard.done"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,9 @@ test("Forum Name Step", assert => {
|
||||
assert.ok(exists('.wizard-step-title'));
|
||||
assert.ok(exists('.wizard-step-description'));
|
||||
assert.ok(!exists('.invalid .field-full-name'), "don't show it as invalid until the user does something");
|
||||
assert.ok(exists('.wizard-field .field-description'));
|
||||
assert.ok(!exists('.wizard-btn.back'));
|
||||
assert.ok(!exists('.wizard-field .field-error-description'));
|
||||
});
|
||||
|
||||
// invalid data
|
||||
@@ -32,16 +34,19 @@ test("Forum Name Step", assert => {
|
||||
click('.wizard-btn.next');
|
||||
andThen(() => {
|
||||
assert.ok(exists('.invalid .field-full-name'));
|
||||
assert.ok(exists('.wizard-field .field-error-description'));
|
||||
});
|
||||
|
||||
// server validation ok
|
||||
fillIn('input.field-full-name', "Evil Trout");
|
||||
click('.wizard-btn.next');
|
||||
andThen(() => {
|
||||
assert.ok(!exists('.wizard-field .field-error-description'));
|
||||
assert.ok(!exists('.wizard-step-title'));
|
||||
assert.ok(!exists('.wizard-step-description'));
|
||||
assert.ok(exists('input.field-email'), "went to the next step");
|
||||
assert.ok(!exists('.wizard-btn.next'));
|
||||
assert.ok(exists('.wizard-btn.done'), 'last step shows a done button');
|
||||
assert.ok(exists('.wizard-btn.back'), 'shows the back button');
|
||||
});
|
||||
|
||||
|
||||
@@ -40,7 +40,10 @@ export default function() {
|
||||
title: 'hello there',
|
||||
index: 0,
|
||||
description: 'hello!',
|
||||
fields: [{ id: 'full_name', type: 'text', required: true }],
|
||||
fields: [{ id: 'full_name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
description: "Your name" }],
|
||||
next: 'second-step'
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user