提交 a511969a 编写于 作者: P Piotr Bryk

Merge pull request #163 from bryk/move-namespace-select

Move namespace select to deploy from settings
......@@ -33,26 +33,14 @@ limitations under the License.
<div ng-switch="ctrl.selection">
<deploy-from-settings ng-switch-when="Settings"
name="ctrl.name"
namespace="ctrl.namespace"
namespaces="ctrl.namespaces"
detail="ctrl.detail">
</deploy-from-settings>
<deploy-from-file ng-switch-when="File"
name="ctrl.name"
namespace="ctrl.namespace"
detail="ctrl.detail">
</deploy-from-file>
</div>
<md-input-container class="md-block">
<label>Namespace</label>
<md-select ng-model="ctrl.namespace" required>
<md-option ng-repeat="namespace in ctrl.namespaces" ng-value="namespace">
{{namespace}}
</md-option>
<md-option ng-click="ctrl.handleNamespaceDialog($event)">
Create a new namespace...
</md-option>
</md-select>
</md-input-container>
<md-button class="md-raised md-primary" type="submit" ng-disabled="ctrl.isDeployDisabled()">
Deploy
</md-button>
......
......@@ -13,7 +13,6 @@
// limitations under the License.
import {stateName as zerostate} from 'zerostate/zerostate_state';
import showNamespaceDialog from 'deploy/createnamespace_dialog';
/**
* Controller for the deploy view.
......@@ -25,11 +24,10 @@ export default class DeployController {
* @param {!angular.$resource} $resource
* @param {!angular.$log} $log
* @param {!ui.router.$state} $state
* @param {!md.$dialog} $mdDialog
* @param {!backendApi.NamespaceList} namespaces
* @ngInject
*/
constructor($resource, $log, $state, $mdDialog, namespaces) {
constructor($resource, $log, $state, namespaces) {
/** @export {!angular.FormController} Initialized from the template */
this.deployForm;
......@@ -38,15 +36,26 @@ export default class DeployController {
/**
* List of available namespaces.
* TODO(bryk): Move this to deploy from settings directive. E.g., use activate method when
* switching to Angular 1.5.
* @export {!Array<string>}
*/
this.namespaces = namespaces.namespaces;
/**
* Currently chosen namespace.
* @export {(string|undefined)}
* Contains the selected directive's controller which has its own deploy logic
*
* Initialized from the template.
* @export {{deploy:function()}|undefined}
*/
this.detail;
/**
* Child directive selection model. The list of possible values is in template. This value
* represents the default selection.
* @export {string}
*/
this.namespace = this.namespaces.length > 0 ? this.namespaces[0] : undefined;
this.selection = "Settings";
/** @private {!angular.$resource} */
this.resource_ = $resource;
......@@ -57,25 +66,8 @@ export default class DeployController {
/** @private {!ui.router.$state} */
this.state_ = $state;
/** @private {!md.$dialog} */
this.mdDialog_ = $mdDialog;
/** @private {boolean} */
this.isDeployInProgress_ = false;
/**
* Contains the selected directive's controller which has its own deploy logic
*
* @export {{deploy:function()}}
*/
this.detail = {deploy: function() {}};
/**
* Child directive selection model. The list of possible values is in template. This value
* represents the default selection.
* @export {string}
*/
this.selection = "Settings";
}
/**
......@@ -87,37 +79,14 @@ export default class DeployController {
this.detail.deploy().finally(() => { this.isDeployInProgress_ = false; });
}
/**
* Displays new namespace creation dialog.
* @param {!angular.Scope.Event} event
* @export
*/
handleNamespaceDialog(event) {
showNamespaceDialog(this.mdDialog_, event, this.namespaces)
.then(
/**
* Handles namespace dialog result. If namespace was created successfully then it
* will be selected, otherwise first namespace will be selected.
*
* @param {string|undefined} answer
*/
(answer) => {
if (answer) {
this.namespace = answer;
this.namespaces = this.namespaces.concat(answer);
} else {
this.namespace = this.namespaces[0];
}
},
() => { this.namespace = this.namespaces[0]; });
}
/**
* Returns true when the deploy action should be enabled.
* @return {boolean}
* @export
*/
isDeployDisabled() { return this.isDeployInProgress_ || this.deployForm.$invalid; }
isDeployDisabled() {
return this.isDeployInProgress_ || this.deployForm.$invalid || !this.detail;
}
/**
* Cancels the deployment form.
......
......@@ -19,7 +19,6 @@ export default function deployFromFileDirective() {
scope: {},
bindToController: {
'name': '=',
'namespace': '=',
'detail': '=',
},
controller: DeployFromFileController,
......
......@@ -15,47 +15,58 @@ limitations under the License.
-->
<md-input-container class="md-block">
<label>Container image</label>
<input ng-model="ctrl.containerImage" required>
<label>Container image</label>
<input ng-model="ctrl.containerImage" required>
</md-input-container>
<md-input-container class="md-block">
<label>Number of pods</label>
<input ng-model="ctrl.replicas" type="number" required min="1">
<label>Number of pods</label>
<input ng-model="ctrl.replicas" type="number" required min="1">
</md-input-container>
<div layout="row" ng-repeat="portMapping in ctrl.portMappings">
<md-input-container flex>
<label>Port</label>
<input ng-model="portMapping.port" type="number" min="0">
</md-input-container>
<md-input-container flex>
<label>Target port</label>
<input ng-model="portMapping.targetPort" type="number" min="0">
</md-input-container>
<md-input-container flex="none">
<label>Protocol</label>
<md-select ng-model="portMapping.protocol" required>
<md-option ng-repeat="protocol in ctrl.protocols" ng-value="protocol">
{{protocol}}
</md-option>
</md-select>
</md-input-container>
<md-input-container flex>
<label>Port</label>
<input ng-model="portMapping.port" type="number" min="0">
</md-input-container>
<md-input-container flex>
<label>Target port</label>
<input ng-model="portMapping.targetPort" type="number" min="0">
</md-input-container>
<md-input-container flex="none">
<label>Protocol</label>
<md-select ng-model="portMapping.protocol" required>
<md-option ng-repeat="protocol in ctrl.protocols" ng-value="protocol">
{{protocol}}
</md-option>
</md-select>
</md-input-container>
</div>
<md-switch ng-model="ctrl.isExternal" class="md-primary">
Expose service externally
Expose service externally
</md-switch>
<md-input-container>
<label>Description (optional)</label>
<textarea ng-model="ctrl.description"></textarea>
<label>Description (optional)</label>
<textarea ng-model="ctrl.description"></textarea>
</md-input-container>
<div>
<div>Labels (optional)</div>
<div layout="column">
<div layout="row">
<p flex>Key</p>
<p flex>Value</p>
</div>
<div ng-repeat="label in ctrl.labels">
<kd-label layout="row" flex label="label" labels="ctrl.labels"></kd-label>
</div>
<div>Labels (optional)</div>
<div layout="column">
<div layout="row">
<p flex>Key</p>
<p flex>Value</p>
</div>
<div ng-repeat="label in ctrl.labels">
<kd-label layout="row" flex label="label" labels="ctrl.labels"></kd-label>
</div>
</div>
</div>
<md-input-container class="md-block">
<label>Namespace</label>
<md-select ng-model="ctrl.namespace" required>
<md-option ng-repeat="namespace in ctrl.namespaces" ng-value="namespace">
{{namespace}}
</md-option>
<md-option ng-click="ctrl.handleNamespaceDialog($event)">
Create a new namespace...
</md-option>
</md-select>
</md-input-container>
......@@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import showNamespaceDialog from './createnamespace_dialog';
import DeployLabel from './deploylabel';
import {stateName as replicasetliststate} from 'replicasetlist/replicasetlist_state';
// Label keys for predefined labels
export const APP_LABEL_KEY = 'app';
export const VERSION_LABEL_KEY = 'version';
const APP_LABEL_KEY = 'app';
const VERSION_LABEL_KEY = 'version';
/**
* Controller for the deploy from settings directive.
......@@ -30,9 +31,10 @@ export default class DeployFromSettingsController {
* @param {!ui.router.$state} $state
* @param {!angular.$resource} $resource
* @param {!angular.$q} $q
* @param {!md.$dialog} $mdDialog
* @ngInject
*/
constructor($log, $state, $resource, $q) {
constructor($log, $state, $resource, $q, $mdDialog) {
/**
* It initializes the scope output parameter
*
......@@ -40,18 +42,6 @@ export default class DeployFromSettingsController {
*/
this.detail = this;
/** @private {!angular.$q} */
this.q_ = $q;
/** @private {!angular.$resource} */
this.resource_ = $resource;
/** @private {!angular.$log} */
this.log_ = $log;
/** @private {!ui.router.$state} */
this.state_ = $state;
/** @export {string} */
this.containerImage = '';
......@@ -80,13 +70,42 @@ export default class DeployFromSettingsController {
new DeployLabel(VERSION_LABEL_KEY, '', false, this.getContainerImageVersion_.bind(this)),
new DeployLabel(),
];
/**
* List of available namespaces.
*
* Initialized from the scope.
* @export {!Array<string>}
*/
this.namespaces;
/**
* Currently chosen namespace.
* @export {(string|undefined)}
*/
this.namespace = this.namespaces.length > 0 ? this.namespaces[0] : undefined;
/** @private {!angular.$q} */
this.q_ = $q;
/** @private {!angular.$resource} */
this.resource_ = $resource;
/** @private {!angular.$log} */
this.log_ = $log;
/** @private {!ui.router.$state} */
this.state_ = $state;
/** @private {!md.$dialog} */
this.mdDialog_ = $mdDialog;
}
/**
* Deploys the application based on the state of the controller.
*
* @export
* @return {angular.$q.Promise}
* @export
*/
deploy() {
// TODO(bryk): Validate input data before sending to the server.
......@@ -120,6 +139,32 @@ export default class DeployFromSettingsController {
return defer.promise;
}
/**
* Displays new namespace creation dialog.
*
* @param {!angular.Scope.Event} event
* @export
*/
handleNamespaceDialog(event) {
showNamespaceDialog(this.mdDialog_, event, this.namespaces)
.then(
/**
* Handles namespace dialog result. If namespace was created successfully then it
* will be selected, otherwise first namespace will be selected.
*
* @param {string|undefined} answer
*/
(answer) => {
if (answer) {
this.namespace = answer;
this.namespaces = this.namespaces.concat(answer);
} else {
this.namespace = this.namespaces[0];
}
},
() => { this.namespace = this.namespaces[0]; });
}
/**
* Converts array of DeployLabel to array of backend api label
* @param {!Array<!DeployLabel>} labels
......
......@@ -23,7 +23,7 @@ export default function deployFromSettingsDirective() {
scope: {},
bindToController: {
'name': '=',
'namespace': '=',
'namespaces': '=',
'detail': '=',
},
controller: DeployFromSettingsController,
......
......@@ -26,12 +26,13 @@ export default class UploadController {
/**
* Browse file function which is defined by the clients.
*
* @private {Function} */
this.browseFileFunc_ = function() {};
* Initialized from the registerBrowseFileFunction method.
* @private {(function())|undefined} */
this.browseFileFunc_;
}
/**
* @param {Function} func
* @param {function()} func
* @export
*/
registerBrowseFileFunction(func) {
......@@ -47,5 +48,9 @@ export default class UploadController {
*
* @export
*/
browseFile() { this.browseFileFunc_(); }
browseFile() {
if (this.browseFileFunc_) {
this.browseFileFunc_();
}
}
}
......@@ -28,10 +28,10 @@ describe('Deploy controller', () => {
beforeEach(() => {
angular.mock.module(deployModule.name);
angular.mock.inject(($resource, $log, $state, $mdDialog, $q) => {
angular.mock.inject(($controller, $state) => {
state = $state;
ctrl = new DeployController($resource, $log, state, $mdDialog, {namespaces: []});
settingsCtrl = new DeployFromSettingController($log, $state, $resource, $q);
ctrl = $controller(DeployController, {namespaces: []});
settingsCtrl = $controller(DeployFromSettingController, {}, {namespaces: []});
});
// prepare and mock
......
......@@ -22,8 +22,8 @@ describe('DeployFromSettings controller', () => {
beforeEach(() => {
angular.mock.module(deployModule.name);
angular.mock.inject(($log, $state, $resource, $q) => {
ctrl = new DeployFromSettingController($log, $state, $resource, $q);
angular.mock.inject(($controller) => {
ctrl = $controller(DeployFromSettingController, {}, {namespaces: []});
});
});
......
......@@ -15,7 +15,7 @@
import DeployLabelController from 'deploy/deploylabel_controller';
import DeployLabel from 'deploy/deploylabel';
describe('DeployFromSettings controller', () => {
describe('DeployLabel controller', () => {
let ctrl;
let labelForm;
......
......@@ -18,7 +18,7 @@ describe('Zero state view', () => {
let page;
beforeEach(() => {
browser.get('/index.html');
browser.get('/index.html/#zerostate');
page = new PageObject();
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册