ソースを参照

Adding plugin navigation without reload

bodicsek 3 年 前
コミット
2bebe6fb87
4 ファイル変更34 行追加21 行削除
  1. 1 1
      package.json
  2. 16 2
      src/components/app.tsx
  3. 11 15
      src/components/content/index.tsx
  4. 6 3
      src/components/header.tsx

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "occ-fw-ui",
-  "version": "1.0.13",
+  "version": "1.0.14",
   "description": "An Oracle JavaScript Extension Toolkit(JET) web app",
   "config": {
     "host": "customercentral-poc.oracle.com",

+ 16 - 2
src/components/app.tsx

@@ -1,11 +1,12 @@
 import { registerCustomElement } from "ojs/ojvcomponent";
 import { FunctionComponent } from "preact";
-import { useEffect } from "preact/hooks";
+import { useEffect, useState } from "preact/hooks";
 import { Footer } from "./footer";
 import { Header } from "./header";
 import { Content } from "./content/index";
 import { useLogin } from "../hooks/useLogin";
 import { useQuery, Plugin, NavigationItem } from "../hooks/useQuery";
+import { BrowserRouter, NavigateFunction, Route, Routes } from "react-router-dom";
 
 import Context = require("ojs/ojcontext");
 
@@ -16,9 +17,15 @@ type Props = Readonly<{
 
 const AppComponent: FunctionComponent<Props> = ({ appName = "OCC" }) => {
   const { userLogin, login, logout, accessToken } = useLogin();
+
   const { result: plugins } = useQuery<Plugin[]>("/plugins", accessToken);
   const { result: navigations } = useQuery<NavigationItem[]>("/navigations", accessToken);
 
+  const [navigate, setNavigate] = useState<NavigateFunction>();
+  const getNavigateRef = (navigate: NavigateFunction) => {
+    setNavigate(_ => navigate);
+  }
+
   useEffect(() => {
     Context.getPageContext().getBusyContext().applicationBootstrapComplete();
   }, []);
@@ -30,10 +37,17 @@ const AppComponent: FunctionComponent<Props> = ({ appName = "OCC" }) => {
         userLogin={userLogin}
         login={login}
         logout={logout}
+        navigate={navigate}
         navigations={navigations}
         plugins={plugins}
       />
-      <Content userLogin={userLogin} plugins={plugins} />
+      <BrowserRouter>
+        <Routes>
+          {(plugins ?? [undefined]).map(p => {
+            return (<Route path={p?.path ?? "/"} element={<Content plugin={p} navigateRef={getNavigateRef}/>} />);
+          })}
+        </Routes>
+      </BrowserRouter>
       <Footer />
     </div>
   );

+ 11 - 15
src/components/content/index.tsx

@@ -1,26 +1,22 @@
 import { FunctionComponent } from "preact";
-import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
+import { useEffect } from "preact/hooks";
+import { NavigateFunction, useNavigate } from "react-router-dom";
 import { Plugin } from "src/hooks/useQuery";
 
 type Props = Readonly<{
-  userLogin: string;
-  plugins: Plugin[] | undefined;
+  plugin: Plugin | undefined;
+  navigateRef: (navigate: NavigateFunction) => void;
 }>;
 
-export const Content: FunctionComponent<Props> = ({ userLogin, plugins }) => {
-
+export const Content: FunctionComponent<Props> = ({ plugin, navigateRef }) => {
+  const navigate = useNavigate();
+  useEffect(() => {
+    navigateRef(navigate);
+  }, [navigate]);
   return (
     <div class="oj-web-applayout-max-width oj-flex-item oj-flex">
-      {userLogin && plugins &&
-        <Router>
-          <Routes>
-            {plugins.map(p => {
-              return (<Route path={p.path} element={<iframe src={p.url} className="oj-flex-item"></iframe>}/>);
-            })}
-          </Routes>
-        </Router>
-      }
-      {!userLogin && <h1>Landing Page</h1>}
+      {plugin && <iframe src={plugin.url} className="oj-flex-item"></iframe>}
+      {!plugin && <h1>Landing Page</h1>}
     </div>
   );
 };

+ 6 - 3
src/components/header.tsx

@@ -7,17 +7,19 @@ import { ojButton } from "ojs/ojbutton";
 import { FunctionComponent } from "preact";
 import { useRef, useState, useEffect } from "preact/hooks";
 import { isLinkItem, isPluginItem, NavigationItem, Plugin } from "../hooks/useQuery";
+import { NavigateFunction } from "react-router-dom";
 
 type Props = Readonly<{
   appName: string,
   userLogin: string,
   login: () => void,
   logout: () => void,
+  navigate: NavigateFunction;
   navigations: NavigationItem[] | undefined,
   plugins: Plugin[] | undefined
 }>;
 
-export const Header: FunctionComponent<Props> = ({ appName, userLogin, login, logout, navigations, plugins }) => {
+export const Header: FunctionComponent<Props> = ({ appName, userLogin, login, logout, navigate, navigations, plugins }) => {
   const mediaQueryRef = useRef<MediaQueryList>(window.matchMedia(ResponsiveUtils.getFrameworkQuery("sm-only")));
   const [isSmallWidth, setIsSmallWidth] = useState(mediaQueryRef.current.matches);
 
@@ -55,9 +57,10 @@ export const Header: FunctionComponent<Props> = ({ appName, userLogin, login, lo
     if (isLinkItem(navItem)) {
       window.open(navItem.path, navItem.openInNewTab ? "_blank" : "_self");
     } else if (isPluginItem(navItem)) {
-      window.location.pathname = plugins.find(p => p.name === navItem.pluginName)?.path;
+      // window.location.pathname = plugins.find(p => p.name === navItem.pluginName)?.path;
+      navigate(plugins.find(p => p.name === navItem.pluginName)?.path);
     }
-  }
+  };
 
   return (
     <header role="banner" class="oj-web-applayout-header">