Skip to content

Commit

Permalink
CHE-2514 add import stack popup
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksii Orel <oorel@codenvy.com>
  • Loading branch information
Oleksii Orel committed Dec 27, 2016
1 parent 9a0c537 commit a6f8443
Show file tree
Hide file tree
Showing 14 changed files with 657 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2015-2016 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*/
'use strict';
import {CheEnvironmentRegistry} from '../../../../components/api/environment/che-environment-registry.factory';
import {ImportStackService} from '../../stack-details/import-stack.service';
import {CheStack} from '../../../../components/api/che-stack.factory';
import {StackValidationService} from '../../stack-details/stack-validation.service';


/**
* @ngdoc controller
* @name stacks.list-stacks.import-stack.controller:ImportStackController
* @description This class is handling the controller for a dialog box with different types of recipe for target stack.
* @author Oleksii Orel
*/
export class ImportStackController {
private $mdDialog: ng.material.IDialogService;
private $location: ng.ILocationService;
private cheStack: CheStack;
private importStackService: ImportStackService;
private stackValidationService: StackValidationService;
private cheEnvironmentRegistry: CheEnvironmentRegistry;
private recipeScript: string;
private recipeFormat: string;
private COMPOSE: string = 'compose';
private DOCKERFILE: string = 'dockerfile';
private environmentValidation: che.IValidation;
private editorOptions: che.IEditorOptions = {
lineNumbers: true,
lineWrapping: true,
matchBrackets: true,
mode: 'text/x-dockerfile'
};

/**
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
constructor($mdDialog: ng.material.IDialogService, $location: ng.ILocationService, stackValidationService: StackValidationService, cheStack: CheStack, importStackService: ImportStackService, cheEnvironmentRegistry: CheEnvironmentRegistry) {
this.$mdDialog = $mdDialog;
this.$location = $location;
this.cheStack = cheStack;
this.importStackService = importStackService;
this.stackValidationService = stackValidationService;
this.cheEnvironmentRegistry = cheEnvironmentRegistry;

// set default values
this.environmentValidation = {isValid: false, errors: []};
this.recipeFormat = this.DOCKERFILE;
this.updateType();
}

/**
* It will hide the dialog box.
*/
cancel(): void {
this.importStackService.setStack({});
this.$mdDialog.cancel();
}

/**
* It will hide the dialog box and redirect to '/stack/import'.
*/
onImport(): void {
this.$mdDialog.hide();
this.$location.path('/stack/import');
}

/**
* Update editor options for needed recipe type.
*/
updateType(): void {
if (this.DOCKERFILE === this.recipeFormat) {
this.editorOptions.mode = 'text/x-dockerfile';
} else if (this.COMPOSE === this.recipeFormat) {
this.editorOptions.mode = 'text/x-yaml';
}
this.recipeScript = '';
this.updateImportedStack();
}

/**
* Update imported stack if it is valid.
*/
updateImportedStack(): void {
let stack = angular.copy(this.cheStack.getStackTemplate());
let environments: che.IWorkspaceEnvironments = stack.workspaceConfig.environments;
let defaultEnv: che.IWorkspaceEnvironment = angular.copy(environments[stack.workspaceConfig.defaultEnv]);
let recipe: che.IRecipe = {content: this.recipeScript, type: this.recipeFormat};

if (this.COMPOSE === this.recipeFormat) {
recipe.contentType = 'application/x-yaml';
}
defaultEnv.recipe = recipe;
let environmentManager = this.cheEnvironmentRegistry.getEnvironmentManager(defaultEnv.recipe.type);
// add ws-agent to default dev-machine for dockerfile recipe format
defaultEnv.machines = this.DOCKERFILE === this.recipeFormat ? {
'dev-machine': {
'agents': [],
'attributes': {
'memoryLimitBytes': 2147483648
}
}
} : {};
let machines = environmentManager.getMachines(defaultEnv);
// add ws-agent to a machine if it one
if (machines.length === 1) {
environmentManager.setDev(machines[0], true);
}
let environment = environmentManager.getEnvironment(defaultEnv, machines);
// check environment correctness
this.environmentValidation = this.stackValidationService.getEnvironmentValidation(environment);
if (!this.environmentValidation.isValid) {
return;
}
environments[stack.workspaceConfig.defaultEnv] = environment;
this.importStackService.setStack(stack);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!--
Copyright (c) 2015 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<che-popup title="Import stack" on-close="importStackController.cancel()">
<div class="import-stack">
<span class="header-label">Select type of stack's recipe and match them:</span>
<div class="toggle-button-area">
<che-toggle ng-model="importStackController.recipeFormat" ng-change="importStackController.updateType()"
md-theme="default">
<che-toggle-button che-title="Dockerfile" che-value="{{importStackController.DOCKERFILE}}"></che-toggle-button>
<che-toggle-button che-title="Composefile"
che-value="{{importStackController.COMPOSE}}"></che-toggle-button>
</che-toggle>
</div>
<ui-codemirror ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 1000, 'blur': 0 } }"
ui-codemirror="importStackController.editorOptions"
ng-model="importStackController.recipeScript"
ng-change="importStackController.updateImportedStack()"></ui-codemirror>
<div class="errors-container">
<span ng-repeat="error in importStackController.environmentValidation.errors | orderBy:'':'reverse'">
{{error}}
</span>
</div>
<che-button-notice che-button-title="Cancel"
ng-click="importStackController.cancel()">
</che-button-notice>
<che-button-primary che-button-title="Ok"
ng-disabled="!importStackController.environmentValidation.isValid"
ng-click="importStackController.onImport()">
</che-button-primary>
</div>
</che-popup>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.import-stack
min-width 800px
user-select none

ui-codemirror
display block
float none
width 800px
max-width 800px
margin-top 15px
margin-bottom 2px

.CodeMirror
max-height 200px
width inherit

.CodeMirror-sizer
margin-left 26px

.CodeMirror-gutter-wrapper
left 0 !important

.CodeMirror-gutter-elt,
.CodeMirror-linenumber
margin-left -55px

.CodeMirror-scroll
margin-left -20px

div.CodeMirror
border 1px solid $list-separator-color
height 250px !important
min-height 250px !important

.errors-container
color $error-color
min-height 20px
margin-right 2px

span
margin-right 2px

.header-label
line-height 30px

.toggle-button-area
position relative
margin-left 0

button
margin-left 0
margin-bottom 0

md-switch
height 100%
margin auto
overflow visible

.footer-label
display inline-block
line-height 30px
margin-top 10px
float right

.import-stack che-button-primary,
.import-stack che-button-notice
float right

button
margin-right 0
margin-bottom 0
44 changes: 31 additions & 13 deletions dashboard/src/app/stacks/list-stacks/list-stacks.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Codenvy, S.A. - initial API and implementation
*/
'use strict';
import {CheStack} from "../../../components/api/che-stack.factory";
import {CheNotification} from "../../../components/notification/che-notification.factory";
import {CheProfile} from "../../../components/api/che-profile.factory";
import {CheStack} from '../../../components/api/che-stack.factory';
import {CheNotification} from '../../../components/notification/che-notification.factory';
import {CheProfile} from '../../../components/api/che-profile.factory';

/**
* @ngdoc controller
Expand Down Expand Up @@ -86,7 +86,7 @@ export class ListStacksController {
this.loading = false;
this.stacks = this.cheStack.getStacks();
},
(error) => {
(error: any) => {
if (error.status === 304) {
this.stacks = this.cheStack.getStacks();
}
Expand All @@ -95,6 +95,24 @@ export class ListStacksController {
});
}

/**
* Show dialog for imported stack.
* @param $event {MouseEvent}
*/
showSelectStackRecipeDialog($event: MouseEvent): void {
this.$mdDialog.show({
targetEvent: $event,
controller: 'ImportStackController',
controllerAs: 'importStackController',
bindToController: true,
clickOutsideToClose: true,
locals: {
callbackController: this
},
templateUrl: 'app/stacks/list-stacks/import-stack/import-stack.html'
});
}

/**
* Performs confirmation and deletion of pointed stack.
*
Expand All @@ -108,9 +126,9 @@ export class ListStacksController {
delete this.stackSelectionState[stack.id];
this.cheNotification.showInfo('Stack ' + stack.name + ' has been successfully removed.');
this.getStacks();
}, (error) => {
}, (error: any) => {
this.loading = false;
let message = 'Failed to delete ' + stack.name + 'stack.' + (error && error.message) ? error.message : "";
let message = 'Failed to delete ' + stack.name + 'stack.' + (error && error.message) ? error.message : '';
this.cheNotification.showError(message);
});
});
Expand All @@ -131,9 +149,9 @@ export class ListStacksController {
this.loading = true;
this.cheStack.createStack(newStack).then(() => {
this.getStacks();
}, (error) => {
}, (error: any) => {
this.loading = false;
let message = 'Failed to create ' + newStack.name + 'stack.' + (error && error.message) ? error.message : "";
let message = 'Failed to create ' + newStack.name + 'stack.' + (error && error.message) ? error.message : '';
this.cheNotification.showError(message);
});
}
Expand Down Expand Up @@ -185,7 +203,7 @@ export class ListStacksController {
*/
selectAllStacks(): void {
this.stackSelectionState = {};
this.stacks.forEach((stack) => {
this.stacks.forEach((stack: che.IStack) => {
if (stack.creator === this.userId) {
this.stackSelectionState[stack.id] = true;
}
Expand All @@ -196,7 +214,7 @@ export class ListStacksController {
* Make all stacks deselected.
*/
deselectAllStacks(): void {
this.stacks.forEach((stack) => {
this.stacks.forEach((stack: che.IStack) => {
if (this.stackSelectionState[stack.id]) {
this.stackSelectionState[stack.id] = false;
}
Expand All @@ -222,7 +240,7 @@ export class ListStacksController {
this.isNoSelected = true;
let keys: Array<string> = Object.keys(this.stackSelectionState);
this.isAllSelected = keys.length > 0;
keys.forEach((key) => {
keys.forEach((key: string) => {
if (this.stackSelectionState[key]) {
this.isNoSelected = false;
} else {
Expand All @@ -238,7 +256,7 @@ export class ListStacksController {
let selectedStackIds: Array<any> = [];


Object.keys(this.stackSelectionState).forEach((key) => {
Object.keys(this.stackSelectionState).forEach((key: string) => {
if (this.stackSelectionState[key]) {
selectedStackIds.push(key);
}
Expand All @@ -253,7 +271,7 @@ export class ListStacksController {
confirmationPromise.then(() => {
let deleteStackPromises = [];

selectedStackIds.forEach((stackId) => {
selectedStackIds.forEach((stackId: string) => {
this.stackSelectionState[stackId] = false;
deleteStackPromises.push(this.cheStack.deleteStack(stackId));
});
Expand Down
2 changes: 2 additions & 0 deletions dashboard/src/app/stacks/list-stacks/list-stacks.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
che-hide-search="listStacksController.stacks.length === 0"
che-add-button-title="Add Stack"
che-add-button-href="#stack/create"
che-import-button-title="Import"
che-on-import="listStacksController.showSelectStackRecipeDialog($event)"
che-delete-button-title="Delete"
che-on-delete="listStacksController.deleteSelectedStacks()"
che-hide-delete="listStacksController.isNoSelected"
Expand Down
Loading

0 comments on commit a6f8443

Please sign in to comment.