Support relative and baseUrl-relative app URLs

Because we constructed a URL object from the appUrl setting, it had to
be an absolute URL. Here we emulate the logic from pywwt to prepend the
JupyterLab baseUrl if the URL starts with `/wwt`, and also to make it an
absolute URL if required. This allows us to successfully work with
user-specific appUrls, such as the local version of the research app
provided by pywwt.
This commit is contained in:
Peter Williams 2021-10-23 12:36:18 -04:00
Родитель ad2858a0cd
Коммит b36c9d590c
2 изменённых файлов: 25 добавлений и 13 удалений

Просмотреть файл

@ -29,7 +29,7 @@ const CATEGORY = 'AAS WorldWide Telescope';
const OPEN_COMMAND = 'wwtelescope:open';
const wwtIcon = new LabIcon({
name: '@wwtelescope/jupyterlab:research:wwt',
name: RESEARCH_PLUGIN_ID + ':wwt',
svgstr: WWT_ICON,
});
@ -66,8 +66,7 @@ class WWTLabExtensionState {
// We'll pass this information to kernels so that they can give the user
// guidance about what features are available.
const baseUrl = PageConfig.getBaseUrl();
const url = baseUrl + 'wwtkdr/_probe';
const url = this.maybeApplyBaseUrl('/wwtkdr/_probe');
fetch(url).then((response: Response) => {
this.commMgr.dataRelayConfirmedAvailable = response.ok;
@ -85,7 +84,7 @@ class WWTLabExtensionState {
const content = new WWTLabViewer(this.commMgr, this.appUrl);
this.widget = new MainAreaWidget({ content });
this.widget.id = '@wwtelescope/jupyterlab:research:wwt';
this.widget.id = RESEARCH_PLUGIN_ID + ':wwt';
this.widget.title.label = 'AAS WorldWide Telescope';
this.widget.title.icon = wwtIcon;
this.widget.title.closable = true;
@ -108,12 +107,28 @@ class WWTLabExtensionState {
private readonly onSettingsUpdate = (
settings: ISettingRegistry.ISettings
): void => {
this.appUrl = settings.get('appUrl').composite as string;
this.appUrl = this.maybeApplyBaseUrl(
settings.get('appUrl').composite as string
);
// If there is an active widget, in principle we could have a way to tell it
// to reload its iframe, but that would be annoying to implement and doesn't
// enable any realistic user wins that I can see -- just close and reopen
// the app pane.
};
private readonly maybeApplyBaseUrl = (url: string): string => {
if (url.slice(0, 4) === '/wwt') {
const baseUrl = PageConfig.getBaseUrl();
if (baseUrl.slice(-1) === '/') {
url = baseUrl.slice(0, -1) + url;
} else {
url = baseUrl + url;
}
}
return url;
};
}
function activate(

Просмотреть файл

@ -11,22 +11,20 @@ import { WWTLabCommManager } from './comms';
export class WWTLabViewer extends Widget {
private readonly comms: WWTLabCommManager;
private appUrl: string;
private appOrigin: string;
private iframe: HTMLIFrameElement;
constructor(comms: WWTLabCommManager, appUrl: string) {
super();
this.appUrl = appUrl;
// Set up to receive messages from the iframe that we're about to create.
// For now we just don't worry about removing the listener :-(
const iframeOrigin = new URL(this.appUrl).origin;
this.appOrigin = new URL(appUrl, location.toString()).origin;
window.addEventListener(
'message',
(event) => {
if (event.origin === iframeOrigin) {
if (event.origin === this.appOrigin) {
this.onIframeMessage(event.data);
}
},
@ -41,8 +39,7 @@ export class WWTLabViewer extends Widget {
// prevention, but so long as the research app can't do anything on behalf
// of the user (which it can't right now because we don't even have
// "users"), that's OK.
this.iframe.src =
this.appUrl + '?origin=' + encodeURIComponent(location.origin);
this.iframe.src = appUrl + '?origin=' + encodeURIComponent(location.origin);
this.iframe.style.setProperty('height', '100%', '');
this.iframe.style.setProperty('width', '100%', '');
@ -73,7 +70,7 @@ export class WWTLabViewer extends Widget {
const window = this.iframe.contentWindow;
if (window) {
classicPywwt.applyBaseUrlIfApplicable(d, location.toString());
window.postMessage(d, this.appUrl);
window.postMessage(d, this.appOrigin);
}
};
}