aboutsummaryrefslogtreecommitdiffstats
path: root/client/js/app/src/app/libs/router.jsx
blob: 452a0d6379fde6c8b8419727043503c256aaca1e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
import React from 'react';
import { Routes, Route, useParams, Navigate } from 'react-router-dom';
import { Error } from 'app/components';

const mainTitle = 'Vespa App';

function TitledRoute({ element, title, default: isDefault, ...props }) {
  const params = useParams();
  const clone = React.cloneElement(element, Object.assign(props, params));
  if (title != null) {
    const titleStr = typeof title === 'function' ? title(params) : title;
    document.title = titleStr.endsWith(mainTitle)
      ? titleStr
      : `${titleStr} - ${mainTitle}`;
  } else if (isDefault) {
    // Reset the title if title is not set and this is a default router
    document.title = mainTitle;
  }

  return clone;
}

export function Router({ children }) {
  // If there is only one route then this comes as an object.
  if (!Array.isArray(children)) children = [children];
  children = children.filter(({ props }) => props.enabled ?? true);

  if (!children.some((child) => child.props.default))
    children.push(<Error code={404} default />);

  return (
    <Routes>
      {children.map(({ props, ...element }, i) => (
        <Route
          key={`${i}-${props.path}`}
          path={props.default ? '*' : props.path}
          element={
            element.type === Redirect ? (
              Object.assign({ props }, element)
            ) : (
              <TitledRoute element={element} {...props} />
            )
          }
        />
      ))}
    </Routes>
  );
}

export function Redirect({ to, replace }) {
  return <Navigate {...{ to, replace }} />;
}