Skip to content

Commit

Permalink
feat: Relative links (#1204)
Browse files Browse the repository at this point in the history
- Notebooks work
- Links between notebooks work
- Deeplinking notebooks works in dev mode with proxy
- Does not work in production - would need server to correctly proxy
URLs and write the correct document base
- Embed-grid works
- Embed-chart works
- Plugins work
- Fixes #1070 
- Unit tests and e2e tests pass
- Tested in both a dev build, and production build
- Tested following steps in #1070 
- Tested in DnD, ensured the correct paths were being loaded
  • Loading branch information
mofojed authored May 3, 2023
1 parent 769d753 commit f440eb9
Show file tree
Hide file tree
Showing 35 changed files with 190 additions and 115 deletions.
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/app-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@deephaven/jsapi-utils": "file:../jsapi-utils",
"@deephaven/log": "file:../log",
"@deephaven/react-hooks": "file:../react-hooks",
"@deephaven/utils": "file:../utils",
"@paciolan/remote-component": "2.13.0",
"@paciolan/remote-module-loader": "^3.0.2",
"fira": "mozilla/fira#4.202"
Expand Down
6 changes: 3 additions & 3 deletions packages/app-utils/src/components/AppBootstrap.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function renderComponent(client: CoreClient) {
});
return render(
<ApiContext.Provider value={api}>
<AppBootstrap apiUrl={API_URL} pluginsUrl={PLUGINS_URL}>
<AppBootstrap serverUrl={API_URL} pluginsUrl={PLUGINS_URL}>
{mockChild}
</AppBootstrap>
</ApiContext.Provider>
Expand All @@ -59,7 +59,7 @@ beforeEach(() => {
it('should throw if api has not been bootstrapped', () => {
expect(() =>
render(
<AppBootstrap apiUrl={API_URL} pluginsUrl={PLUGINS_URL}>
<AppBootstrap serverUrl={API_URL} pluginsUrl={PLUGINS_URL}>
{mockChild}
</AppBootstrap>
)
Expand Down Expand Up @@ -91,7 +91,7 @@ it('should display an error if no login plugin matches the provided auth handler
expect(mockLogin).not.toHaveBeenCalled();
expect(
screen.queryByText(
'Error: No login plugins found, please register a login plugin for auth handlers: MockAuthHandler'
'No login plugins found, please register a login plugin for auth handlers: MockAuthHandler'
)
).not.toBeNull();
});
Expand Down
9 changes: 4 additions & 5 deletions packages/app-utils/src/components/AppBootstrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import FontBootstrap from './FontBootstrap';
import PluginsBootstrap from './PluginsBootstrap';
import AuthBootstrap from './AuthBootstrap';
import ConnectionBootstrap from './ConnectionBootstrap';
import { getBaseUrl, getConnectOptions } from '../utils';
import { getConnectOptions } from '../utils';
import FontsLoaded from './FontsLoaded';

export type AppBootstrapProps = {
/** URL of the API to load. */
apiUrl: string;
/** URL of the server. */
serverUrl: string;

/** URL of the plugins to load. */
pluginsUrl: string;
Expand All @@ -33,12 +33,11 @@ export type AppBootstrapProps = {
* Will display the children when everything is loaded and authenticated.
*/
export function AppBootstrap({
apiUrl,
fontClassNames,
pluginsUrl,
serverUrl,
children,
}: AppBootstrapProps) {
const serverUrl = getBaseUrl(apiUrl).origin;
const clientOptions = useMemo(() => getConnectOptions(), []);

// On logout, we reset the client and have user login again
Expand Down
5 changes: 3 additions & 2 deletions packages/app-utils/src/components/AuthBootstrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@deephaven/auth-plugins';
import { LoadingOverlay } from '@deephaven/components';
import { useClient } from '@deephaven/jsapi-bootstrap';
import { getErrorMessage } from '@deephaven/utils';
import { PluginsContext } from './PluginsBootstrap';
import { getAuthPluginComponent } from '../plugins';
import LoginNotifier from './LoginNotifier';
Expand Down Expand Up @@ -76,8 +77,8 @@ export function AuthBootstrap({ children }: AuthBootstrapProps) {
if (isLoading || error != null) {
return (
<LoadingOverlay
isLoading={isLoading}
errorMessage={error != null ? `${error}` : undefined}
isLoading={isLoading && error == null}
errorMessage={getErrorMessage(error)}
/>
);
}
Expand Down
3 changes: 2 additions & 1 deletion packages/app-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{ "path": "../jsapi-types" },
{ "path": "../jsapi-utils" },
{ "path": "../log" },
{ "path": "../react-hooks" }
{ "path": "../react-hooks" },
{ "path": "../utils" }
]
}
2 changes: 1 addition & 1 deletion packages/auth-plugins/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
"@deephaven/jsapi-types": "file:../jsapi-types",
"@deephaven/jsapi-utils": "file:../jsapi-utils",
"@deephaven/log": "file:../log",
"@deephaven/utils": "file:../utils",
"@deephaven/redux": "file:../redux",
"@deephaven/utils": "file:../utils",
"classnames": "^2.3.1",
"react-transition-group": "^4.4.2",
"js-cookie": "^3.0.5"
Expand Down
4 changes: 2 additions & 2 deletions packages/auth-plugins/src/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ interface LoginProps {
/** What to show in the login input part of the login form. */
children: React.ReactNode;

/** Path to the logo. Defaults to `/logo.png` */
/** Path to the custom logo, relative to document base */
logoPath?: string;
}

export function Login({ children, logoPath = '/logo.png' }: LoginProps) {
export function Login({ children, logoPath = './logo.png' }: LoginProps) {
return (
<div className="login-container">
<RandomAreaPlotAnimation />
Expand Down
14 changes: 11 additions & 3 deletions packages/babel-preset/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,21 @@ module.exports = api => ({
plugins: [
api.env('test')
? [
// This is needed to replace import.meta w/ process in Jest
// This is needed to replace import.meta.env w/ process in Jest
// Jest does not play nicely w/ ESM and Vite uses import.meta
// import.meta is only avaialable in ESM
path.resolve(__dirname, 'importMetaEnvPlugin'),
]
: // The add-import-extension plugin causes Jest to error, but is needed for proper ESM builds
['babel-plugin-add-import-extension'],
: false,
api.env('test')
? [
// Also need to handle import.meta.url
'babel-plugin-transform-import-meta',
]
: false,
api.env('test')
? false // The add-import-extension plugin causes Jest to error, but is needed for proper ESM builds
: ['babel-plugin-add-import-extension'],
[
'transform-rename-import',
{
Expand Down
1 change: 1 addition & 0 deletions packages/babel-preset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@babel/preset-react": "^7.18.0",
"@babel/preset-typescript": "^7.18.0",
"babel-plugin-add-import-extension": "^1.6.0",
"babel-plugin-transform-import-meta": "^2.2.0",
"babel-plugin-transform-rename-import": "^2.3.0"
},
"publishConfig": {
Expand Down
44 changes: 27 additions & 17 deletions packages/code-studio/.env
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
# Location of the iris script and API server
# Set this value to __mocks__ to use mock server instead
BASE_URL=/ide/
VITE_CORE_API_URL=/jsapi
# Path at which the app is served
# https://vitejs.dev/guide/build.html#public-base-path
BASE_URL=./

# Location of the core JS API and API server
# We assume that the jsapi is served up as a sibling of the code studio
# I.e. Web UI served at http://www.example.com/ide/, then JS API served at http://www.example.com/jsapi/
# This path is relative to the base URL, so we need to go up one level
VITE_CORE_API_URL=../jsapi
VITE_CORE_API_NAME=dh-core.js
VITE_PLUGIN_URL=/ide/plugins/

# Path to plugins that load a module
# See https://github.com/deephaven/deephaven-js-plugin-template/
# Like the CORE_API_URL, we assume this is served up as a sibling of the code studio
VITE_MODULE_PLUGINS_URL=../js-plugins

# Path for notebooks and layouts storage on the gRPCStorageService
# Note these are not URLs, these are file system paths on the server in the gRPCStorageService
VITE_STORAGE_PATH_NOTEBOOKS=/notebooks
VITE_STORAGE_PATH_LAYOUTS=/layouts

# Any routes we define here
VITE_ROUTE_NOTEBOOKS=notebooks/

# Proxy used by Vite
VITE_PROXY_URL=http://localhost:10000
VITE_NOTEBOOKS_URL=/notebooks
VITE_LAYOUTS_URL=/layouts
VITE_ENABLE_LOG_PROXY=true
VITE_SUPPORT_LINK=https://github.com/deephaven/web-client-ui/
VITE_DOCS_LINK=https://deephaven.io/core/docs/
VITE_FAVICON=/favicon-cc-app.svg
VITE_BUILD_PATH=./build
VITE_LOG_LEVEL=2

# Plugin URLs
## Path to plugins that load/render as a component (e.g. Table plugins)
## See https://github.com/deephaven/js-plugin-template/ for templates
VITE_COMPONENT_PLUGINS_URL=/ide/plugins/

## Path to plugins that load a module
## See https://github.com/deephaven/deephaven-js-plugin-template/
VITE_MODULE_PLUGINS_URL=/js-plugins
# Proxy the log service to store logs to export easily for support
VITE_ENABLE_LOG_PROXY=true
VITE_LOG_LEVEL=2
4 changes: 2 additions & 2 deletions packages/code-studio/.env.development
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BASE_URL=/ide/
VITE_LOG_LEVEL=4
VITE_ENABLE_LOG_PROXY=false
VITE_FAVICON=/favicon-cc-app-dev.svg

BASE_URL=/
PORT=4000
VITE_LOG_LEVEL=4
2 changes: 0 additions & 2 deletions packages/code-studio/.env.test

This file was deleted.

8 changes: 0 additions & 8 deletions packages/code-studio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ One common setup is to override the API server URL to point to another server. F
VITE_CORE_API_URL=https://www.myserver.com/jsapi
```

### VITE_NOTEBOOKS_URL

One common setup is to override the API server URL to point to another server. For example, add the following block to `.env.development.local` to have `npm start` point to a remote server for the API:

```shell
VITE_CORE_API_URL=https://www.myserver.com/notebooks
```

### VITE_LOG_LEVEL

Printing detailed logs when debugging can be handy. The highest level of logging is already set in your `.env.development` file. You can change it in `.env.development.local` if desired.
Expand Down
1 change: 1 addition & 0 deletions packages/code-studio/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base href="#BASE_URL#" />
<meta name="ui-version" content="v#npm_package_version#" />
<meta charset="utf-8" />
<meta
Expand Down
22 changes: 12 additions & 10 deletions packages/code-studio/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ const AppBootstrap = React.lazy(async () => {
return { default: module.AppBootstrap };
});

const apiURL = new URL(
`${import.meta.env.VITE_CORE_API_URL}/${import.meta.env.VITE_CORE_API_NAME}`,
document.baseURI
);

const pluginsURL = new URL(
import.meta.env.VITE_MODULE_PLUGINS_URL,
document.baseURI
);

ReactDOM.render(
<ApiBootstrap
apiUrl={`${import.meta.env.VITE_CORE_API_URL}/${
import.meta.env.VITE_CORE_API_NAME
}`}
setGlobally
>
<ApiBootstrap apiUrl={apiURL.href} setGlobally>
<Suspense fallback={<LoadingOverlay />}>
<AppBootstrap
apiUrl={import.meta.env.VITE_CORE_API_URL}
pluginsUrl={import.meta.env.VITE_MODULE_PLUGINS_URL}
>
<AppBootstrap serverUrl={apiURL.origin} pluginsUrl={pluginsURL.href}>
<AppRoot />
</AppBootstrap>
</Suspense>
Expand Down
4 changes: 2 additions & 2 deletions packages/code-studio/src/main/AppInit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@ function AppInit(props: AppInitProps) {
const storageService = client.getStorageService();
const layoutStorage = new GrpcLayoutStorage(
storageService,
import.meta.env.VITE_LAYOUTS_URL ?? ''
import.meta.env.VITE_STORAGE_PATH_LAYOUTS ?? ''
);
const fileStorage = new GrpcFileStorage(
storageService,
import.meta.env.VITE_NOTEBOOKS_URL ?? ''
import.meta.env.VITE_STORAGE_PATH_NOTEBOOKS ?? ''
);

const workspaceStorage = new LocalWorkspaceStorage(layoutStorage);
Expand Down
14 changes: 10 additions & 4 deletions packages/code-studio/src/main/AppMainContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ import dh, {
} from '@deephaven/jsapi-shim';
import { SessionConfig } from '@deephaven/jsapi-utils';
import Log from '@deephaven/log';
import { getBaseUrl, loadComponentPlugin } from '@deephaven/app-utils';
import {
getActiveTool,
getWorkspace,
Expand Down Expand Up @@ -653,8 +652,12 @@ export class AppMainContainer extends Component<
TablePlugin: ForwardRefExoticComponent<React.RefAttributes<unknown>>;
}).TablePlugin;
}
const baseURL = getBaseUrl(import.meta.env.VITE_COMPONENT_PLUGINS_URL);
return loadComponentPlugin(baseURL, pluginName);

const errorMessage = `Unable to find table plugin ${pluginName}.`;
log.error(errorMessage);
return ((
<div className="error-message">{`${errorMessage}`}</div>
) as unknown) as ForwardRefExoticComponent<React.RefAttributes<unknown>>;
}

startListeningForDisconnect() {
Expand Down Expand Up @@ -912,7 +915,10 @@ export class AppMainContainer extends Component<
<ConsolePlugin
hydrateConsole={AppMainContainer.hydrateConsole}
notebooksUrl={
getBaseUrl(`${import.meta.env.VITE_NOTEBOOKS_URL}/`).href
new URL(
`${import.meta.env.VITE_ROUTE_NOTEBOOKS}`,
document.baseURI
).href
}
/>
<FilterPlugin />
Expand Down
Loading

0 comments on commit f440eb9

Please sign in to comment.