Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export default class BuildConsole extends Component {

openPathsYamlResetConfirm?: () => void;

hubsAvailability: boolean = true;

@requiredAction renewToken!: (binderhubUrl: string) => void;

@requiredAction requestBuild!: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
<div local-class='build_launcher'>
<BsButton
data-test-binderhub-launch
@type='success'
@type={{if this.hubsAvailability 'success' ''}}
disabled={{not this.hubsAvailability}}
local-class='build_launch_button'
@onClick={{action this.safeLaunch}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ import Component from '@ember/component';
import EmberError from '@ember/error';
import { action, computed } from '@ember/object';
import { later } from '@ember/runloop';
import { inject as service } from '@ember/service';
import Intl from 'ember-intl/services/intl';
import { requiredAction } from 'ember-osf-web/decorators/component';
import {
BootstrapPath,
checkJupyterHubAvailability,
getJupyterHubServerURL,
isBinderHubConfigFulfilled,
JupyterServer,
JupyterServerEntry,
ServerState,
validateBinderHubToken,
} from 'ember-osf-web/guid-node/binderhub/controller';
import BinderHubConfigModel, { JupyterHub } from 'ember-osf-web/models/binderhub-config';
import Node from 'ember-osf-web/models/node';
import ServerAnnotationModel from 'ember-osf-web/models/server-annotation';
import { addPathSegment } from 'ember-osf-web/utils/url-parts';
import Toast from 'ember-toastr/services/toast';

/* eslint-disable camelcase */
interface JupyterUser {
Expand All @@ -40,6 +45,10 @@ function validateJupyterHubToken(jupyterhub: JupyterHub) {
}

export default class JupyterServersList extends Component {
@service toast!: Toast;

@service intl!: Intl;

binderHubConfig!: BinderHubConfigModel;

@requiredAction renewToken!: (jupyterhubUrl: string) => void;
Expand Down Expand Up @@ -74,6 +83,8 @@ export default class JupyterServersList extends Component {

serverAnnotationHash: { [key: string]: ServerAnnotationModel } = {};

hubsAvailability: boolean = true;

@requiredAction requestAnnotationCreation!: (
entry: JupyterServerEntry,
binderhubUrl: URL,
Expand All @@ -86,6 +97,10 @@ export default class JupyterServersList extends Component {

@requiredAction requestAnnotationReload!: (peek: boolean) => void;

@requiredAction updateHubsAvailability!: (
state: ServerState,
) => void;

didReceiveAttrs() {
if (!this.initialized && !this.validateToken()) {
return;
Expand Down Expand Up @@ -181,6 +196,14 @@ export default class JupyterServersList extends Component {
return jupyterhub.token.user;
}

async updateJHAvailability(jupyterhubUrl: string): Promise<boolean> {
const state = await checkJupyterHubAvailability(jupyterhubUrl);
if (!state.availability) {
this.updateHubsAvailability(state);
}
return state.availability;
}

/**
* An string array whose `i`th element is the (initial) contents of
* `i`th jupyter server (i.e. this.servers[i]). An element `null`
Expand Down Expand Up @@ -284,15 +307,18 @@ export default class JupyterServersList extends Component {
this.set('serversLink', null);
this.set('namedServerLimit', null);
later(async () => {
const servers = await this.loadServers(jupyterhubUrl);
this.set('serversLink', addPathSegment(jupyterhubUrl, 'hub/home'));
if (servers === null) {
this.set('allServers', null);
this.set('namedServerLimit', null);
return;
const availability = await this.updateJHAvailability(jupyterhubUrl);
if (availability) {
const servers = await this.loadServers(jupyterhubUrl);
this.set('serversLink', addPathSegment(jupyterhubUrl, 'hub/home'));
if (servers === null) {
this.set('allServers', null);
this.set('namedServerLimit', null);
return;
}
this.set('allServers', servers.entries);
this.set('namedServerLimit', servers.namedServerLimit);
}
this.set('allServers', servers.entries);
this.set('namedServerLimit', servers.namedServerLimit);
}, 0);
}

Expand Down Expand Up @@ -411,7 +437,12 @@ export default class JupyterServersList extends Component {
}
const url = new URL(jupyterhub.url);
url.pathname = server.entry.url;
window.open(getJupyterHubServerURL(url.toString(), undefined, path), '_blank');
later(async () => {
const availability = await this.updateJHAvailability(jupyterhub.url);
if (availability) {
window.open(getJupyterHubServerURL(url.toString(), undefined, path), '_blank');
}
}, 0);
}

@action
Expand All @@ -422,7 +453,12 @@ export default class JupyterServersList extends Component {
}
const url = new URL(jupyterhub.url);
url.pathname = server.entry.url;
window.open(url.toString(), '_blank');
later(async () => {
const availability = await this.updateJHAvailability(url.toString());
if (availability) {
window.open(url.toString(), '_blank');
}
}, 0);
}

@action
Expand All @@ -440,19 +476,22 @@ export default class JupyterServersList extends Component {
const server = this.showDeleteConfirmDialogTarget;
this.set('showDeleteConfirmDialogTarget', null);
later(async () => {
const serverpath = server.entry.name.length > 0 ? `servers/${server.entry.name}` : 'server';
await this.jupyterhubAPIAJAX(
server.ownerUrl,
`users/${user}/${serverpath}`,
{
method: 'DELETE',
contentType: 'application/json',
data: JSON.stringify({ remove: true }),
},
);
await this.requestAnnotationDelete(server.entry.url, true);
const servers = await this.loadServers(server.ownerUrl);
this.set('allServers', servers !== null ? servers.entries : null);
const availability = await this.updateJHAvailability(server.ownerUrl);
if (availability) {
const serverpath = server.entry.name.length > 0 ? `servers/${server.entry.name}` : 'server';
await this.jupyterhubAPIAJAX(
server.ownerUrl,
`users/${user}/${serverpath}`,
{
method: 'DELETE',
contentType: 'application/json',
data: JSON.stringify({ remove: true }),
},
);
await this.requestAnnotationDelete(server.entry.url, true);
const servers = await this.loadServers(server.ownerUrl);
this.set('allServers', servers !== null ? servers.entries : null);
}
}, 0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<BsAlert
@type='danger'
@dismissible={{false}}
@visible={{this.notAuthorized}}
@visible={{and this.notAuthorized this.hubsAvailability}}
local-class='BinderHub__connection_alert'
>
{{t 'binderhub.error.jupyterhub_auth_error'}}
Expand All @@ -15,10 +15,12 @@
{{t 'binderhub.error.reconnect_jupyterhub'}}
</button>
</BsAlert>
{{#if this.loading}}
{{# if (not this.hubsAvailability)}}
{{t 'binderhub.jupyter_servers_list.jupyterhub_unavailable'}}
{{else if this.loading}}
{{t 'binderhub.loading'}}
{{else}}
{{#if (not this.apiLoaded)}}
{{#if (and this.hubsAvailability (not this.apiLoaded))}}
<a href={{this.serversLink}} target='_blank' rel='noopener'>
{{t 'binderhub.servers.server_hub_home'}}
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ export default class ProjectEditor extends Component {

deletingCustomBaseImageModel?: CustomBaseImageModel = undefined;

hubsAvailability: boolean = true;

didReceiveAttrs() {
if (!this.configFolder || this.configFolder.path === this.loadingPath) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@
@userHasWritePermission={{this.node.userHasWritePermission}}
@toggleCopyDefaultStorage={{action this.toggleCopyDefaultStorage}}
@openPathsYamlResetConfirm={{action this.openPathsYamlResetConfirm}}
@hubsAvailability={{this.hubsAvailability}}
/>
{{/if}}
</div>
Expand Down
Loading