Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add on dashboard possibility to stop workspace while it is being started. #4246

Merged
merged 4 commits into from
Mar 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions dashboard/src/app/ide/ide.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,6 @@ class IdeSvc {
this.listeningChannels.push(statusChannel);
// for now, display log of status channel in case of errors
bus.subscribe(statusChannel, (message: any) => {
if (message.eventType === 'DESTROYED' && message.workspaceId === data.id && !(this.$rootScope as any).showIDE) {
// need to show the error
this.$mdDialog.show(
this.$mdDialog.alert()
.title('Unable to start the workspace runtime')
.content('Your workspace runtime is no longer available. It was either destroyed or ran out of memory.')
.ariaLabel('Workspace start')
.ok('OK')
);
}
if (message.eventType === 'ERROR' && message.workspaceId === data.id) {
let errorMessage = 'Error when trying to start the workspace';
if (message.error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright (c) 2015-2017 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 {CheWorkspace} from '../../../components/api/che-workspace.factory';
import {CheAPIBuilder} from '../../../components/api/builder/che-api-builder.factory';
import {CheHttpBackend} from '../../../components/api/test/che-http-backend';
import IdeSvc from '../../ide/ide.service';


/**
* Test of the NavbarRecentWorkspacesController
*/
describe('NavbarRecentWorkspacesController', () => {
/**
* NavbarRecentWorkspacesController
*/
let navbarRecentWorkspacesController;

/**
* API builder
*/
let apiBuilder: CheAPIBuilder;

/**
* Backend for handling http operations
*/
let httpBackend: ng.IHttpBackendService;

/**
* Che backend
*/
let cheBackend: CheHttpBackend;


let workspaces: Array<che.IWorkspace>;

/**
* setup module
*/
beforeEach(angular.mock.module('userDashboard'));

/**
* Inject factory and http backend
*/
beforeEach(inject(($rootScope: ng.IRootScopeService, cheWorkspace: CheWorkspace, cheAPIBuilder: CheAPIBuilder, cheHttpBackend: CheHttpBackend, $controller: any, ideSvc: IdeSvc, $window: ng.IWindowService, $log: ng.ILogService) => {
apiBuilder = cheAPIBuilder;
cheBackend = cheHttpBackend;
httpBackend = cheHttpBackend.getHttpBackend();

let scope = $rootScope.$new();
navbarRecentWorkspacesController = $controller('NavbarRecentWorkspacesController', {
ideSvc: IdeSvc, cheWorkspace: cheWorkspace, $window: $window, $log: $log, $scope: scope, $rootScope: $rootScope
});

workspaces = [];
for (let i = 0; i < 20; ++i) {
let wrkspId = 'workspaceId' + i;
let wrkspName = 'testName' + i;
let wrkspCreateDate = new Date(2001, 1, 1, i, 1).toString();
let wrkspUpdateDate = new Date(2001, 1, 1, i, 2).toString();
let wrkspAttr = {'created': Date.parse(wrkspCreateDate), 'updated': Date.parse(wrkspUpdateDate)};
let workspace = apiBuilder.getWorkspaceBuilder().withId(wrkspId).withAttributes(wrkspAttr).withName(wrkspName).build();
workspaces.push(workspace);
}
// shuffle the workspaces
workspaces.sort(() => {
return 0.5 - Math.random();
});
// providing request
// add workspaces on Http backend
cheBackend.addWorkspaces(workspaces);

// setup backend
cheBackend.setup();

// fetch workspaces
cheWorkspace.fetchWorkspaces();

// flush command
httpBackend.flush();
}));

/**
* Check assertion after the test
*/
afterEach(() => {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});

/**
* Check sorting rule for recent workspaces
*/
it('Check very recent workspaces', inject(() => {
// get recentWorkspaces
let recentWorkspaces = navbarRecentWorkspacesController.getRecentWorkspaces();

// check max length
expect(recentWorkspaces.length).toEqual(navbarRecentWorkspacesController.maxItemsNumber);

// prepare test objects
let testWorkspaces: Array<che.IWorkspace> = angular.copy(workspaces);
testWorkspaces.sort((workspace1: che.IWorkspace, workspace2: che.IWorkspace) => {
return workspace2.attributes.updated - workspace1.attributes.updated;
});
let veryRecentWorkspaceId = testWorkspaces[testWorkspaces.length - 1].id;

// check default sorting
let lastPosition = recentWorkspaces.length - 1;
for (let i = 0; i < lastPosition; i++) {
expect(recentWorkspaces[i].id).toEqual(testWorkspaces[i].id);
}
// check the last one workspace is equal to the last test workspace and not equal to the very recent workspace,
// because we are going to update very recent workspace in controller and sorting rule should be changed
expect(recentWorkspaces[lastPosition].id).toEqual(testWorkspaces[lastPosition].id);
expect(recentWorkspaces[lastPosition].id).not.toEqual(veryRecentWorkspaceId);

// update very recent workspace
navbarRecentWorkspacesController.updateRecentWorkspace(veryRecentWorkspaceId);
recentWorkspaces = navbarRecentWorkspacesController.getRecentWorkspaces();

// check sorting with veryRecentWorkspace
for (let i = 0; i < lastPosition; i++) {
expect(recentWorkspaces[i].id).toEqual(testWorkspaces[i].id);
}
// check the last one workspace is equal to the very recent workspace and not equal to the last test workspace
expect(recentWorkspaces[lastPosition].id).not.toEqual(testWorkspaces[lastPosition].id);
expect(recentWorkspaces[lastPosition].id).toEqual(veryRecentWorkspaceId);
})
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ export class NavbarRecentWorkspacesController {
this.fetchWorkspaceSettings();
}

/**
* Returns the MAX_RECENT_WORKSPACES_ITEMS constant
* @returns {number}
*/
get maxItemsNumber(): number {
return MAX_RECENT_WORKSPACES_ITEMS;
}

/**
* Retrieves workspace settings.
*/
Expand All @@ -84,10 +92,6 @@ export class NavbarRecentWorkspacesController {
} else {
this.cheWorkspace.fetchWorkspaceSettings().then(() => {
this.prepareDropdownItemsTemplate();
}, (error: any) => {
if (error.status === 304) {
this.prepareDropdownItemsTemplate();
}
});
}
}
Expand Down Expand Up @@ -171,13 +175,10 @@ export class NavbarRecentWorkspacesController {
if (recentWorkspaces.length > MAX_RECENT_WORKSPACES_ITEMS) {
let pos: number = veryRecentWorkspace ? recentWorkspaces.indexOf(veryRecentWorkspace) : -1;
if (veryRecentWorkspace && pos >= MAX_RECENT_WORKSPACES_ITEMS) {
recentWorkspaces.splice(MAX_RECENT_WORKSPACES_ITEMS - 1, recentWorkspaces.length , veryRecentWorkspace);
} else {
recentWorkspaces.splice(0, MAX_RECENT_WORKSPACES_ITEMS);
recentWorkspaces[MAX_RECENT_WORKSPACES_ITEMS - 1] = veryRecentWorkspace;
}
}

this.recentWorkspaces = recentWorkspaces;
this.recentWorkspaces = recentWorkspaces.slice(0, MAX_RECENT_WORKSPACES_ITEMS);
}

/**
Expand Down Expand Up @@ -272,6 +273,7 @@ export class NavbarRecentWorkspacesController {
*/
stopRecentWorkspace(workspaceId: string, createSnapshot: boolean): void {
this.cheWorkspace.stopWorkspace(workspaceId, createSnapshot).then(() => {
angular.noop();
}, (error: any) => {
this.$log.error(error);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</md-button>
</md-list-item>
<md-list-item flex class="navbar-subsection-item"
ng-repeat="workspace in navbarRecentWorkspacesController.getRecentWorkspaces()"
ng-repeat="workspace in navbarRecentWorkspacesController.getRecentWorkspaces() | limitTo: navbarRecentWorkspacesController.maxItemsNumber"
ng-class="{'recent-workspaces-last-opened': navbarRecentWorkspacesController.isOpen(workspace.id)}">
<navbar-dropdown-menu flex
navbar-dropdown-items="navbarRecentWorkspacesController.getDropdownItems(workspace.id)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export class WorkspaceEnvironmentsController {

/**
* Show dialog to add a new machine to config
* @param $event
* @param $event {MouseEvent}
*/
showAddMachineDialog($event: MouseEvent): void {
this.$mdDialog.show({
Expand All @@ -301,6 +301,19 @@ export class WorkspaceEnvironmentsController {
});
}

/**
* Gets location URL
*
* @returns {string}
*/
getLocationUrl(): string {
let url: string = '';
if (this.environment && this.environment.recipe.location && /^https?:\/\//i.test(this.environment.recipe.location)) {
url = this.environment.recipe.location;
}
return url;
}

/**
* Sets environments
* @param environments: {[envName: string]: any}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,10 @@
</che-show-area>
</che-label-container>
<!-- OR Location -->
<che-label-container che-label-name="Recipe Location"
ng-if="workspaceEnvironmentsController.recipeType !== 'dockerimage' && workspaceEnvironmentsController.environment.recipe.location">
<che-label-container che-label-name="Recipe Location" ng-if="workspaceEnvironmentsController.environment.recipe.location">
<che-text-info che-text="workspaceEnvironmentsController.environment.recipe.location"
che-href="workspaceEnvironmentsController.environment.recipe.location"
che-copy-clipboard="true"
che-href="workspaceEnvironmentsController.getLocationUrl()"
che-copy-clipboard="workspaceEnvironmentsController.getLocationUrl().length > 0"
class="recipe-location"></che-text-info>
</che-label-container>
<che-button-default class="add-machine-button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,18 @@
border 1px solid $list-separator-color
font-size 12px

.recipe-location a
word-break break-all
.recipe-location
.che-text-info-desktop span
border none
padding-bottom 0
a
word-break break-all

.copy-clipboard
font-size 15px

div
height: inherit;

.add-machine-button
float left
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</che-label-container>

<che-label-container>
<div layout="row">
<div layout="row" flex layout-align="end end">
<che-button-primary che-button-title="{{editVariableDialogController.toEdit ? 'Update' : 'Add'}}"
ng-disabled="envVariableForm.$invalid"
ng-click="editVariableDialogController.saveVariable()"></che-button-primary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
.edit-variable-dialog-content

div.che-label-container
border-bottom none

div.che-label-container-label
min-width 100px
width 100px

div.che-input-desktop-value-column
min-width 100%

input, textarea
width inherit

.che-label-container:last-child
padding-bottom 0

button
margin 0 0 0 10px

.che-label-container
padding 15px 0

.edit-variable-dialog-input
margin -6px 0

.edit-variable-dialog-textarea
margin -8px 0

button
margin 0 30px 0 0

input, textarea
width 300px
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,16 @@ export class WorkspaceDetailsController {
}

stopWorkspace(): void {
let promise = this.cheWorkspace.stopWorkspace(this.workspaceId, this.getAutoSnapshot());
let createSnapshot: boolean;
if (this.getWorkspaceStatus() === 'STARTING') {
createSnapshot = false;
} else {
createSnapshot = this.getAutoSnapshot();
}
let promise = this.cheWorkspace.stopWorkspace(this.workspaceId, createSnapshot);

promise.then(() => {}, (error: any) => {
promise.then(() => {
}, (error: any) => {
this.cheNotification.showError(error.data.message !== null ? error.data.message : 'Stop workspace failed.');
this.$log.error(error);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,16 @@
</div>
<div layout="row" class="workspace-details-action-buttons">
<div>
<che-button-default ng-disabled="(workspaceDetailsController.isCreationFlow || workspaceDetailsController.getWorkspaceStatus() === 'STARTING')"
ng-show="(workspaceDetailsController.getWorkspaceStatus() !== 'RUNNING' && workspaceDetailsController.getWorkspaceStatus() !== 'STOPPING' && workspaceDetailsController.getWorkspaceStatus() !== 'SNAPSHOTTING')"
<che-button-default ng-disabled="(workspaceDetailsController.isCreationFlow)"
ng-show="(workspaceDetailsController.getWorkspaceStatus() !== 'RUNNING' && workspaceDetailsController.getWorkspaceStatus() !== 'STOPPING' && workspaceDetailsController.getWorkspaceStatus() !== 'SNAPSHOTTING') && workspaceDetailsController.getWorkspaceStatus() !== 'STARTING'"
che-button-title="Run" name="runButton"
ng-click="workspaceDetailsController.runWorkspace()"></che-button-default>
<che-button-default ng-disabled="(workspaceDetailsController.isCreationFlow || workspaceDetailsController.getWorkspaceStatus() === 'STOPPING' || workspaceDetailsController.getWorkspaceStatus() === 'SNAPSHOTTING')"
ng-show="(workspaceDetailsController.getWorkspaceStatus() === 'RUNNING' || workspaceDetailsController.getWorkspaceStatus() === 'STOPPING' || workspaceDetailsController.getWorkspaceStatus() === 'SNAPSHOTTING')"
che-button-title="{{workspaceDetailsController.getAutoSnapshot() ? 'Stop' : 'Stop without snapshot'}}" name="stopButton"
ng-click="workspaceDetailsController.stopWorkspace()"></che-button-default>
<che-button-default
ng-disabled="(workspaceDetailsController.isCreationFlow || workspaceDetailsController.getWorkspaceStatus() === 'STOPPING' || workspaceDetailsController.getWorkspaceStatus() === 'SNAPSHOTTING')"
ng-show="(workspaceDetailsController.getWorkspaceStatus() === 'RUNNING' || workspaceDetailsController.getWorkspaceStatus() === 'STOPPING' || workspaceDetailsController.getWorkspaceStatus() === 'SNAPSHOTTING') || workspaceDetailsController.getWorkspaceStatus() === 'STARTING'"
che-button-title="{{workspaceDetailsController.getAutoSnapshot() || workspaceDetailsController.getWorkspaceStatus() === 'STARTING' ? 'Stop' : 'Stop without snapshot'}}"
name="stopButton"
ng-click="workspaceDetailsController.stopWorkspace()"></che-button-default>
</div>
</div>
</div>
Expand Down
Loading