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

Use dashboard to restart the workspace #15180

Merged
merged 2 commits into from
Nov 14, 2019
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
128 changes: 104 additions & 24 deletions dashboard/src/app/ide/ide-iframe/ide-iframe.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
* Red Hat, Inc. - initial API and implementation
*/
'use strict';
import {CheUIElementsInjectorService} from '../../../components/service/injector/che-ui-elements-injector.service';

import { CheWorkspace } from '../../../components/api/workspace/che-workspace.factory';
import IdeSvc from '../ide.service';

/*global $:false */

Expand All @@ -26,53 +28,131 @@ interface IIdeIFrameRootScope extends ng.IRootScopeService {
* @author Florent Benoit
*/
class IdeIFrameSvc {
static $inject = ['$window', '$location', '$rootScope', '$mdSidenav'];

static $inject = ['$window', '$location', '$rootScope', '$mdSidenav', 'cheWorkspace', 'ideSvc'];

private $location: ng.ILocationService;
private $rootScope: IIdeIFrameRootScope;
private $mdSidenav: ng.material.ISidenavService;
private cheWorkspace: CheWorkspace;
private ideSvc: IdeSvc;

/**
* Default constructor that is using resource
*/
constructor($window: ng.IWindowService,
$location: ng.ILocationService,
$rootScope: IIdeIFrameRootScope,
$mdSidenav: ng.material.ISidenavService) {
$mdSidenav: ng.material.ISidenavService,
cheWorkspace: CheWorkspace,
ideSvc: IdeSvc) {
this.$location = $location;
this.$rootScope = $rootScope;
this.$mdSidenav = $mdSidenav;
this.cheWorkspace = cheWorkspace;
this.ideSvc = ideSvc;

$window.addEventListener('message', (event: any) => {
if ('show-ide' === event.data) {
if (this.isWaitingIDE()) {
$rootScope.$apply(() => {
$rootScope.showIDE = true;
$rootScope.hideLoader = true;
});
}
} else if ('show-workspaces' === event.data) {
$rootScope.$apply(() => {
$location.path('/workspaces');
});

} else if ('show-navbar' === event.data) {
$rootScope.hideNavbar = false;
$mdSidenav('left').open();

} else if ('hide-navbar' === event.data) {
if (this.isWaitingIDE()) {
$rootScope.hideNavbar = true;
$mdSidenav('left').close();
}
if (!event || typeof event.data !== "string") {
return;
}

const msg: string = event.data;

if ('show-ide' === msg) {
this.showIDE();
return;
}

if ('show-workspaces' === msg) {
this.showWorkspaces();
return;
}

if ('show-navbar' === msg) {
this.showNavBar();
return;
}

if ('hide-navbar' === msg) {
this.hideNavBar();
return;
}

if (msg.startsWith('restart-workspace:')) {
this.restartWorkspace(msg);
return;
}

}, false);
}

private showIDE(): void {
if (this.isWaitingIDE()) {
this.$rootScope.$apply(() => {
this.$rootScope.showIDE = true;
this.$rootScope.hideLoader = true;
});
}
}

private showWorkspaces(): void {
this.$rootScope.$apply(() => {
this.$location.path('/workspaces');
});
}

private showNavBar(): void {
this.$rootScope.hideNavbar = false;
this.$mdSidenav('left').open();
}

private hideNavBar(): void {
if (this.isWaitingIDE()) {
this.$rootScope.hideNavbar = true;
this.$mdSidenav('left').close();
}
}

/**
* Restarts the workspace
*
* @param message message from Editor in format
* restart-workspace:${workspaceId}:${token}
* Where
* 'restart-workspace' - action name
* ${workspaceId} - workpsace ID
* ${token} - Che machine token to validate
*/
private restartWorkspace(message: string): void {
// cut action name
message = message.substring(message.indexOf(':') + 1);

// get workpsace ID
const workspaceId = message.substring(0, message.indexOf(':'));

// get Che machine token
const token = message.substring(message.indexOf(':') + 1);

this.cheWorkspace.validateMachineToken(workspaceId, token).then(() => {
this.cheWorkspace.stopWorkspace(workspaceId).then(() => {
this.ideSvc.reloadIdeFrame();
}).catch((error) => {
console.error('Unable to stop workspace. ', error);
});
}).catch(() => {
console.error('Unable to stop workspace: token is not valid.');
});
}

/**
* Returns true if the user is waiting for IDE.
* @returns {boolean}
*/
private isWaitingIDE(): boolean {
return /\/ide\//.test(this.$location.path());
}

}

export default IdeIFrameSvc;
11 changes: 11 additions & 0 deletions dashboard/src/app/ide/ide.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,17 @@ class IdeSvc {
});
}

/**
* Reloads frame with IDE
*/
reloadIdeFrame(): void {
let iframe = angular.element('#ide-application-iframe');
if (iframe) {
const src = iframe.attr('src');
iframe.attr('src', src);
}
}

/**
* Emit event to move workspace immediately
* to top of the recent workspaces list
Expand Down
28 changes: 28 additions & 0 deletions dashboard/src/components/api/workspace/che-workspace.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,34 @@ export class CheWorkspace {
return defer.promise;
}

/**
* Validates machine token for the workspace
*
* @param workspaceId workspace ID
* @param token Che machine token
*/
validateMachineToken(workspaceId: string, token: string): ng.IPromise<any> {
const defer = this.$q.defer();

const promise: ng.IHttpPromise<any> = this.$http.get(`/api/workspace/${workspaceId}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});

promise.then((response: ng.IHttpPromiseCallbackArg<che.IWorkspace>) => {
defer.resolve();
}, (error: any) => {
if (error && error.status === 304) {
defer.resolve();
return;
Copy link
Contributor

@AndrienkoAleksandr AndrienkoAleksandr Nov 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return return defer.promise;?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we only need there to resolve or reject that deferred object promise. And return it at the end of the method.

}
defer.reject(error);
});

return defer.promise;
}

/**
* Adds a project on the workspace
* @param workspaceId {string} the workspace ID required to add a project
Expand Down