From be784017fe4b562bee4c99c6696f1b2e37e1a61c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20T=C3=B6pfer?= Date: Wed, 26 Jun 2024 16:10:37 +0200 Subject: [PATCH] Add example of builtin template, fix SubRoute --- client/src/lib/page-common.js | 24 +++++++------ client/src/lib/page.js | 10 ++++-- client/src/root-trusted.js | 36 +++++++++---------- client/src/templates/HelloWorld.js | 18 ++++++++++ .../src/templates/builtin-templates-root.js | 17 +++++++++ 5 files changed, 71 insertions(+), 34 deletions(-) create mode 100644 client/src/templates/HelloWorld.js create mode 100644 client/src/templates/builtin-templates-root.js diff --git a/client/src/lib/page-common.js b/client/src/lib/page-common.js index 14830aa7..57360c58 100644 --- a/client/src/lib/page-common.js +++ b/client/src/lib/page-common.js @@ -2,7 +2,7 @@ import React, {Component} from "react"; import PropTypes from "prop-types"; -import {Navigate, Route, Routes, useLocation, useNavigate, useParams} from "react-router-dom"; +import {Link, Navigate, Route, Routes, useLocation, useNavigate, useParams} from "react-router-dom"; import {withAsyncErrorHandler, withErrorHandling} from "./error-handling"; import axios from "../lib/axios"; import {getUrl} from "./urls"; @@ -192,7 +192,7 @@ export function getRoutes(structure, parentRoute) { const route = { path: (pathWithParams === '' ? '/' : pathWithParams), - exact: true,//!entry.structure && entry.exact !== false, + exact: !entry.structure && entry.exact !== false, structure: entry.structure, panelComponent: entry.panelComponent, panelRender: entry.panelRender, @@ -395,15 +395,12 @@ class SubRoute extends Component { // TODO: update the following code for the new react router (v6), see also root-trusted.js (`getStructure`) const subStructure = route.structure(resolved, permissions, params); const routes = getRoutes(subStructure, route); - const childRoute = routes[0]; + // in ReactRouter v6, absolute paths don't work in nested Routes (https://github.com/remix-run/react-router/discussions/9841), so we need to use relative paths here + routes.forEach(r => { + r.path = r.path.replace(route.path, ''); // remove the parent route path + }); return ( - - - /* + {routes.map(childRoute => ( ))} - */ + } /> + ); } else { return this.props.loadingMessageFn(); @@ -473,3 +471,7 @@ export const withPageHelpers = createComponentMixin({ return {}; } }); + +export function NoMatch() { + return
Page not found. Back to Home
; +} diff --git a/client/src/lib/page.js b/client/src/lib/page.js index 3b0536d4..c83c7402 100644 --- a/client/src/lib/page.js +++ b/client/src/lib/page.js @@ -13,10 +13,11 @@ import interoperableErrors from "../../../shared/interoperable-errors"; import {ActionLink, Button, DismissibleAlert, DropdownActionLink, Icon} from "./bootstrap-components"; import ivisConfig from "ivisConfig"; import styles from "./styles.scss"; -import {getRoutes, RenderRoute, Resolver, SectionContentContext, withPageHelpers} from "./page-common"; +import {getRoutes, RenderRoute, Resolver, SectionContentContext, withPageHelpers, NoMatch} from "./page-common"; import {getBaseDir} from "./urls"; import {createComponentMixin, withComponentMixins} from "./decorator-helpers"; import {getLang} from "../../../shared/langs"; +import _ from "lodash"; export { withPageHelpers } @@ -280,7 +281,8 @@ class PanelRoute extends Component { resolved, permissions, setPanelInFullScreen: this.setPanelInFullScreen, - panelInFullScreen: this.state.panelInFullScreen + panelInFullScreen: this.state.panelInFullScreen, + params: _.omit(params, "*"), // the trailing space in ':panelId/*' is matched incorrectly, so we remove it here }; let panel; @@ -504,7 +506,9 @@ class SectionContentBase extends Component { {routes.map(x => { return this.renderRoute(x); }) - } + } + } /> + ); } diff --git a/client/src/root-trusted.js b/client/src/root-trusted.js index 175bb919..ed1ee8b6 100644 --- a/client/src/root-trusted.js +++ b/client/src/root-trusted.js @@ -83,34 +83,32 @@ import ivisConfig from "ivisConfig"; import {TranslationRoot} from "./lib/i18n"; import {SignalSetKind} from "../../shared/signal-sets"; -import {TaskSource, isBuiltinSource} from "../../shared/tasks"; -import {LegendPosition, StaticPieChart} from "./ivis/PieChart"; +import {isBuiltinSource} from "../../shared/tasks"; + +import "./templates/builtin-templates-root" emCommonDefaults.setDefaults(em); const getStructure = t => { - let panelStructureSpec = { + let panelStructureSpec = (isFullscreen) => ({ title: resolved => resolved.panel.name, link: params => `/workspaces/${params.workspaceId}/${params.panelId}`, resolve: { panel: params => `rest/panels/${params.panelId}` }, - panelRender: props => + panelRender: props => , - /* TODO: update the following code for the new react router (v6), see also page-common.js (`SubRoute`) - structure: (resolved, params) => { + structure: (resolved, permissions, params) => { if (resolved.panel.template) { - console.log("resolved.panel.template ok") return { panelRender: props => } } else { - console.log("failed to resolved.panel.template") const panelStructure = em.get('client.builtinTemplates.routes.' + resolved.panel.builtin_template); - return panelStructure(resolved.panel, t, `/workspaces/${params.workspaceId}/${params.panelId}`); + return panelStructure(resolved.panel, t, `/workspaces/${params.workspaceId}/${params.panelId}`, isFullscreen); } - }*/ - }; + } + }); function getSignalChildren() { return{ @@ -223,15 +221,13 @@ const getStructure = t => { link: params => `/workspaces/${params.workspaceId}`, panelRender: props => , children: { - ':panelId': { - ...panelStructureSpec, - children: { - 'fullscreen': { - ...panelStructureSpec, - panelInFullScreen: true, - link: params => `/workspaces/${params.workspaceId}/${params.panelId}/fullscreen`, - } - } + ':panelId/fullscreen/*': { + ...panelStructureSpec(true), + panelInFullScreen: true, + link: params => `/workspaces/${params.workspaceId}/${params.panelId}/fullscreen`, + }, + ':panelId/*': { + ...panelStructureSpec(false), }, } }, diff --git a/client/src/templates/HelloWorld.js b/client/src/templates/HelloWorld.js new file mode 100644 index 00000000..6e8f5e1a --- /dev/null +++ b/client/src/templates/HelloWorld.js @@ -0,0 +1,18 @@ +'use strict'; + +import React, {Component} from "react"; +import {withComponentMixins} from "../lib/decorator-helpers"; +import {withErrorHandling} from "../lib/error-handling"; +import {withPageHelpers} from "../lib/page"; + +@withComponentMixins([ + withErrorHandling, + withPageHelpers, +]) +export default class HelloWorld extends Component { + render() { + return ( +
{this.props.message}
+ ); + } +} diff --git a/client/src/templates/builtin-templates-root.js b/client/src/templates/builtin-templates-root.js new file mode 100644 index 00000000..746287f9 --- /dev/null +++ b/client/src/templates/builtin-templates-root.js @@ -0,0 +1,17 @@ +'use strict'; + +import em from '../lib/extension-manager'; +import React from "react"; +import HelloWorld from "./HelloWorld"; + +em.set('client.builtinTemplates.routes.hello', (panel, t, panelUrl, isFullscreen) => ({ + // resolve: { ... }, + panelRender: props => , // message from panel configuration + children: { + ':message': { + link: params => `${panelUrl}/${params.message}`, + panelRender: props => , // message from url parameter + panelInFullScreen: isFullscreen, + } + } +}));