You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ak...@apache.org on 2014/05/21 19:13:59 UTC
git commit: AMBARI-5844. Provide 'Create App' Wizard Step1
functionallity. (akovalenko)
Repository: ambari
Updated Branches:
refs/heads/trunk d4f502272 -> d4afecaf0
AMBARI-5844. Provide 'Create App' Wizard Step1 functionallity. (akovalenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d4afecaf
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d4afecaf
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d4afecaf
Branch: refs/heads/trunk
Commit: d4afecaf06e642c96ecf7d55eb228e845fbbfd29
Parents: d4f5022
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Wed May 21 20:12:05 2014 +0300
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Wed May 21 20:12:05 2014 +0300
----------------------------------------------------------------------
.../ui/app/controllers/createAppWizard/step1.js | 142 +++++++++++++++++++
.../main/resources/ui/app/models/slider_app.js | 11 +-
.../ui/app/models/slider_app_component.js | 2 +-
.../resources/ui/app/models/slider_app_type.js | 2 +-
.../ui/app/templates/createAppWizard/step1.hbs | 19 ++-
.../src/main/resources/ui/app/translations.js | 9 +-
.../ui/app/views/createAppWizard/step1.js | 43 ++++++
7 files changed, 214 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/controllers/createAppWizard/step1.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/controllers/createAppWizard/step1.js b/contrib/views/slider/src/main/resources/ui/app/controllers/createAppWizard/step1.js
new file mode 100644
index 0000000..d162db5
--- /dev/null
+++ b/contrib/views/slider/src/main/resources/ui/app/controllers/createAppWizard/step1.js
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.CreateAppWizardStep1Controller = Ember.Controller.extend({
+
+ needs: "createAppWizard",
+
+ appWizardController: Ember.computed.alias("controllers.createAppWizard"),
+
+ /**
+ * New App object
+ * @type {App.SliderApp}
+ */
+ newApp: null,
+
+ /**
+ * Name for new App
+ * @type {String}
+ */
+ newAppName: '',
+
+ /**
+ * List of available types for App
+ * @type {Array}
+ */
+ availableTypes: [],
+
+ /**
+ * Selected type for new App
+ * @type {App.SliderAppType}
+ */
+ selectedType: null,
+
+ /**
+ * Define if <code>newAppName</code> pass validation
+ * @type {Boolean}
+ */
+ isNameError: false,
+
+ /**
+ * Error message describing App name validation error
+ * @type {String}
+ */
+ nameErrorMessage: '',
+
+ /**
+ * Load all required data for step
+ */
+ loadStep: function () {
+ this.initializeNewApp();
+ this.loadAvailableTypes();
+ },
+
+ /**
+ * Initialize new App and set it to <code>newApp</code>
+ */
+ initializeNewApp: function () {
+ // find early initialized app
+ var newApp = this.store.all('sliderApp').findBy('status', App.SliderApp.Status.initialized);
+ // if there is no one, than create new one
+ if (!newApp) {
+ newApp = this.store.push('sliderApp', {status: App.SliderApp.Status.initialized, id: 'app' + (new Date).getTime()});
+ }
+ this.set('newApp', newApp);
+ },
+
+ /**
+ * Load all available types for App
+ */
+ loadAvailableTypes: function () {
+ this.set('availableTypes', this.store.all('sliderAppType'));
+ },
+
+ /**
+ * Validate <code>newAppName</code>
+ * It should consist only of letters, numbers, '-', '_' and first character should be a letter
+ * @return {Boolean}
+ */
+ nameValidator: function () {
+ var newAppName = this.get('newAppName');
+ if (newAppName) {
+ // new App name should consist only of letters, numbers, '-', '_' and first character should be a letter
+ if (!/^[A-Za-z][A-Za-z0-9_\-]*$/.test(newAppName)) {
+ this.set('isNameError', true);
+ this.set('nameErrorMessage', Em.I18n.t('wizard.step1.nameFormatError'));
+ return false;
+ }
+ // new App name should be unique
+ if (this.store.all('sliderApp').mapProperty('name').contains(newAppName)) {
+ this.set('isNameError', true);
+ this.set('nameErrorMessage', Em.I18n.t('wizard.step1.nameRepeatError'));
+ return false;
+ }
+ }
+ this.set('isNameError', false);
+ return true;
+ }.observes('newAppName'),
+
+ /**
+ * Define description depending on selected App type
+ */
+ typeDescription: function () {
+ var selectedType = this.get('selectedType');
+ return selectedType ? Em.I18n.t('wizard.step1.typeDescription').format(selectedType.get('displayName')) : '';
+ }.property('selectedType'),
+
+ /**
+ * Define if submit button is disabled
+ * <code>newAppName</code> should pass validation and be not empty
+ */
+ isSubmitDisabled: function () {
+ return !this.get('newAppName') || this.get('isNameError');
+ }.property('newAppName', 'isNameError'),
+
+ saveApp: function () {
+ var newApp = this.get('newApp');
+ newApp.set('appType', this.get('selectedType'));
+ newApp.set('name', this.get('newAppName'));
+ },
+
+ actions: {
+ submit: function () {
+ this.saveApp();
+ this.get('appWizardController').nextStep();
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/models/slider_app.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/models/slider_app.js b/contrib/views/slider/src/main/resources/ui/app/models/slider_app.js
index 022b35f..72e51ae 100644
--- a/contrib/views/slider/src/main/resources/ui/app/models/slider_app.js
+++ b/contrib/views/slider/src/main/resources/ui/app/models/slider_app.js
@@ -56,7 +56,7 @@ App.SliderApp = DS.Model.extend({
/**
* @type {App.SliderAppType}
*/
- appType: DS.belongsTo('SliderAppType'),
+ appType: DS.belongsTo('sliderAppType'),
/**
* @type {string}
@@ -66,17 +66,17 @@ App.SliderApp = DS.Model.extend({
/**
* @type {App.SliderAppComponent[]}
*/
- components: DS.hasMany('SliderAppComponent'),
+ components: DS.hasMany('sliderAppComponent'),
/**
* @type {App.QuickLink[]}
*/
- quickLinks: DS.hasMany('QuickLink'),
+ quickLinks: DS.hasMany('quickLink'),
/**
* @type {App.TypedProperty[]}
*/
- runtimeProperties: DS.hasMany('TypedProperty')
+ runtimeProperties: DS.hasMany('typedProperty')
});
App.SliderApp.FIXTURES = [
@@ -160,5 +160,6 @@ App.SliderApp.FIXTURES = [
App.SliderApp.Status = {
running: "Running",
frozen: "Frozen",
- destroyed: "Destroyed"
+ destroyed: "Destroyed",
+ initialized: "Initialized"
};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/models/slider_app_component.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/models/slider_app_component.js b/contrib/views/slider/src/main/resources/ui/app/models/slider_app_component.js
index e6602a6..2d70a13 100644
--- a/contrib/views/slider/src/main/resources/ui/app/models/slider_app_component.js
+++ b/contrib/views/slider/src/main/resources/ui/app/models/slider_app_component.js
@@ -31,7 +31,7 @@ App.SliderAppComponent = DS.Model.extend({
/**
* @type {App.Host}
*/
- host: DS.belongsTo('Host')
+ host: DS.belongsTo('host')
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/models/slider_app_type.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/models/slider_app_type.js b/contrib/views/slider/src/main/resources/ui/app/models/slider_app_type.js
index 9b7f991..2888407 100644
--- a/contrib/views/slider/src/main/resources/ui/app/models/slider_app_type.js
+++ b/contrib/views/slider/src/main/resources/ui/app/models/slider_app_type.js
@@ -31,7 +31,7 @@ App.SliderAppType = DS.Model.extend({
/**
* @type {App.SliderAppTypeComponent[]}
*/
- components: DS.hasMany('SliderAppTypeComponent'),
+ components: DS.hasMany('sliderAppTypeComponent'),
/**
* @type {object}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step1.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step1.hbs b/contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step1.hbs
index 5031603..6acf985 100644
--- a/contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step1.hbs
+++ b/contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step1.hbs
@@ -15,17 +15,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
}}
-<h4>Available Types</h4>
+<h4>{{t wizard.step1.header}}</h4>
<div class="row-fluid">
<div class="span6">
- {{view Ember.Select contentBinding="controller.types" multiple="true" class="type-select"}}
+ {{view view.availableTypesSelect contentBinding="controller.availableTypes" optionLabelPath="content.displayName" multiple="true" class="type-select"}}
</div>
<div class="span6">
- <label>Name: {{input id="app-name-input"}}</label>
- <h5>Description:</h5>
+ <div {{bind-attr class=":control-group controller.isNameError:error"}}>
+ <label>{{t common.name}}: {{input id="app-name-input" valueBinding="controller.newAppName"}}</label>
+ </div>
+ {{#if controller.isNameError}}
+ <div class="alert alert-error">
+ {{controller.nameErrorMessage}}
+ </div>
+ {{/if}}
+ <h5>{{t wizard.step1.description}}:</h5>
<p>
- Deploys HBase cluster on YARN.
+ {{controller.typeDescription}}
</p>
</div>
</div>
-<button class="btn btn-success pull-right next-btn" {{action nextStep target="controller"}}>Next</button>
+<button class="btn btn-success pull-right next-btn" {{bind-attr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} →</button>
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/translations.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/translations.js b/contrib/views/slider/src/main/resources/ui/app/translations.js
index f4a7401..933f083 100644
--- a/contrib/views/slider/src/main/resources/ui/app/translations.js
+++ b/contrib/views/slider/src/main/resources/ui/app/translations.js
@@ -20,7 +20,9 @@
Em.I18n.translations = {
'common' : {
- 'show': "Show"
+ 'show': "Show",
+ 'name': "Name",
+ 'next': "Next"
},
'tableView.filters.all': 'All',
'tableView.filters.filtered': 'Filtered',
@@ -37,6 +39,11 @@ Em.I18n.translations = {
'wizard.name': 'Create Slider App',
'wizard.step1.name': 'Select Type',
+ 'wizard.step1.header': 'Available Types',
+ 'wizard.step1.description': 'Description',
+ 'wizard.step1.typeDescription': 'Deploys {0} cluster on YARN.',
+ 'wizard.step1.nameFormatError': 'App Name should consist only of letters, numbers, \'-\', \'_\' and first character should be a letter.',
+ 'wizard.step1.nameRepeatError': 'App with entered Name already exists.',
'wizard.step2.name': 'Allocate Resources',
'wizard.step3.name': 'Configuration',
'wizard.step4.name': 'Deploy'
http://git-wip-us.apache.org/repos/asf/ambari/blob/d4afecaf/contrib/views/slider/src/main/resources/ui/app/views/createAppWizard/step1.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/views/createAppWizard/step1.js b/contrib/views/slider/src/main/resources/ui/app/views/createAppWizard/step1.js
new file mode 100644
index 0000000..18312c9
--- /dev/null
+++ b/contrib/views/slider/src/main/resources/ui/app/views/createAppWizard/step1.js
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.CreateAppWizardStep1View = Ember.View.extend({
+
+ didInsertElement: function () {
+ this.get('controller').loadStep();
+ },
+
+ availableTypesSelect: Ember.Select.extend({
+
+ /**
+ * Forbid user to select more than one App type
+ * Set selected type to <code>controller.selectedType</code>
+ */
+ setSelection: function () {
+ var content = this.get('content');
+ var selection = this.get('selection');
+ if (content.get('length') && !selection.length) {
+ this.set('selection', content.objectAt(0));
+ }
+ if (selection.length > 1) {
+ this.set('selection', [selection[0]])
+ }
+ this.set('controller.selectedType', this.get('selection')[0])
+ }.observes('content.length', 'selection.length', 'selection.@each')
+ })
+});