From 445f023af2ccd1d6db2a435b2d29eb70b373e817 Mon Sep 17 00:00:00 2001 From: Sidharth Mohanty Date: Tue, 12 Sep 2023 15:14:03 +0530 Subject: [PATCH] add all pages Signed-off-by: Sidharth Mohanty --- system-apps/app-store/pluginDefinition.json | 1 - .../webClient/src/assets/download.svg | 2 +- .../webClient/src/assets/installed.svg | 1 + .../webClient/src/assets/license.svg | 20 +++ .../webClient/src/assets/uninstall.svg | 1 + .../AppStore/LeftPanel/NavigationButtons.tsx | 11 +- .../AppStore/RightPanel/RightPanel.tsx | 1 + .../webClient/src/components/UI/AppCard.tsx | 74 +++++---- .../src/components/UI/AppCarouselList.tsx | 13 +- .../app-store/webClient/src/context/apps.tsx | 58 +++++++ system-apps/app-store/webClient/src/index.tsx | 5 +- .../app-store/webClient/src/pages/AppInfo.tsx | 144 +++++++++++++++--- .../webClient/src/pages/Discover.tsx | 63 ++++---- .../app-store/webClient/src/pages/Help.tsx | 87 +++++++++++ .../webClient/src/pages/InstalledApps.tsx | 43 ++++++ .../webClient/src/pages/OnPremise.tsx | 45 ++++++ .../webClient/src/pages/Settings.tsx | 55 +++++++ .../app-store/webClient/src/pages/Updates.tsx | 8 + .../app-store/webClient/src/routes.tsx | 25 +++ .../webClient/src/styles/globals.css | 58 +++++++ .../app-store/webClient/src/utils/index.js | 2 +- 21 files changed, 629 insertions(+), 88 deletions(-) create mode 100644 system-apps/app-store/webClient/src/assets/installed.svg create mode 100644 system-apps/app-store/webClient/src/assets/license.svg create mode 100644 system-apps/app-store/webClient/src/assets/uninstall.svg create mode 100644 system-apps/app-store/webClient/src/context/apps.tsx create mode 100644 system-apps/app-store/webClient/src/pages/Help.tsx create mode 100644 system-apps/app-store/webClient/src/pages/InstalledApps.tsx create mode 100644 system-apps/app-store/webClient/src/pages/OnPremise.tsx create mode 100644 system-apps/app-store/webClient/src/pages/Settings.tsx create mode 100644 system-apps/app-store/webClient/src/pages/Updates.tsx diff --git a/system-apps/app-store/pluginDefinition.json b/system-apps/app-store/pluginDefinition.json index d439db1f..ebc3b1d3 100644 --- a/system-apps/app-store/pluginDefinition.json +++ b/system-apps/app-store/pluginDefinition.json @@ -3,7 +3,6 @@ "apiVersion": "1.0.0", "pluginVersion": "1.0.0", "pluginType": "application", - "isSystemPlugin":true, "webContent": { "framework": "react", "launchDefinition": { diff --git a/system-apps/app-store/webClient/src/assets/download.svg b/system-apps/app-store/webClient/src/assets/download.svg index c34f2db3..f766ac73 100644 --- a/system-apps/app-store/webClient/src/assets/download.svg +++ b/system-apps/app-store/webClient/src/assets/download.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/system-apps/app-store/webClient/src/assets/installed.svg b/system-apps/app-store/webClient/src/assets/installed.svg new file mode 100644 index 00000000..9778f413 --- /dev/null +++ b/system-apps/app-store/webClient/src/assets/installed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/system-apps/app-store/webClient/src/assets/license.svg b/system-apps/app-store/webClient/src/assets/license.svg new file mode 100644 index 00000000..ebda24ff --- /dev/null +++ b/system-apps/app-store/webClient/src/assets/license.svg @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/system-apps/app-store/webClient/src/assets/uninstall.svg b/system-apps/app-store/webClient/src/assets/uninstall.svg new file mode 100644 index 00000000..7cfe4658 --- /dev/null +++ b/system-apps/app-store/webClient/src/assets/uninstall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/system-apps/app-store/webClient/src/components/AppStore/LeftPanel/NavigationButtons.tsx b/system-apps/app-store/webClient/src/components/AppStore/LeftPanel/NavigationButtons.tsx index 750552dc..8d87c192 100644 --- a/system-apps/app-store/webClient/src/components/AppStore/LeftPanel/NavigationButtons.tsx +++ b/system-apps/app-store/webClient/src/components/AppStore/LeftPanel/NavigationButtons.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Link } from "react-router-dom"; +import { Link, useLocation } from "react-router-dom"; const options = [ { @@ -35,6 +35,7 @@ const options = [ ]; const NavigationButtons = () => { + const location = useLocation(); return (
{ }} > {options.map((opt) => ( - + {opt.name} ))} diff --git a/system-apps/app-store/webClient/src/components/AppStore/RightPanel/RightPanel.tsx b/system-apps/app-store/webClient/src/components/AppStore/RightPanel/RightPanel.tsx index 2389df1d..81313e2b 100644 --- a/system-apps/app-store/webClient/src/components/AppStore/RightPanel/RightPanel.tsx +++ b/system-apps/app-store/webClient/src/components/AppStore/RightPanel/RightPanel.tsx @@ -10,6 +10,7 @@ const RightPanel: React.FC = ({ overflowY: "scroll", paddingBottom: "40px", minHeight: "100vh", + borderLeft: "1px solid #333", }}> {children}
diff --git a/system-apps/app-store/webClient/src/components/UI/AppCard.tsx b/system-apps/app-store/webClient/src/components/UI/AppCard.tsx index ebaf17ed..0a1ebcf9 100644 --- a/system-apps/app-store/webClient/src/components/UI/AppCard.tsx +++ b/system-apps/app-store/webClient/src/components/UI/AppCard.tsx @@ -1,36 +1,52 @@ -import React from 'react'; -import { trunc } from '../../utils'; -import { ASSETS_URL } from '../../constants'; -import { Link } from 'react-router-dom'; +import React from "react"; +import { trunc } from "../../utils"; +import { ASSETS_URL } from "../../constants"; +import { Link } from "react-router-dom"; type AppProps = { - name: string; - icon: string; - description: string; - publisher: string; - id: string; + name: string; + icon: string; + description: string; + publisher: string; + id: string; + installed: boolean; }; -const App: React.FC = ({ name, icon, description, publisher, id }) => { - return ( - - {name} -
-
- - {publisher} - - {name}
- {trunc(description, 36)} - -
- - ); +const App: React.FC = ({ + name, + icon, + description, + publisher, + id, + installed, +}) => { + return ( + + {name} +
+
+ {publisher} + {name} +
+ {trunc(description, 36)} + +
+ + ); }; export default App; diff --git a/system-apps/app-store/webClient/src/components/UI/AppCarouselList.tsx b/system-apps/app-store/webClient/src/components/UI/AppCarouselList.tsx index 5b00f927..c5b6797f 100644 --- a/system-apps/app-store/webClient/src/components/UI/AppCarouselList.tsx +++ b/system-apps/app-store/webClient/src/components/UI/AppCarouselList.tsx @@ -49,12 +49,13 @@ const AppCarouselList: React.FC = ({ apps }) => { {apps.map((app) => ( ))} diff --git a/system-apps/app-store/webClient/src/context/apps.tsx b/system-apps/app-store/webClient/src/context/apps.tsx new file mode 100644 index 00000000..9d167763 --- /dev/null +++ b/system-apps/app-store/webClient/src/context/apps.tsx @@ -0,0 +1,58 @@ +import React, { createContext, useContext, useState, useEffect } from "react"; + +type AppsContextType = { + apps: any[]; +}; + +const AppsContext = createContext(null); + +export const useAppsCtx = () => useContext(AppsContext); + +const AppsProvider: React.FC = ({ children }) => { + const [apps, setApps] = useState([]); + const [installedApps, setInstalledApps] = useState([]); + + // fetch default apps + useEffect(() => { + const fetchApps = async () => { + // TODO: using mock server, need to use nodeserver + const allAppsResponse = await fetch( + "http://localhost:8000/appstore/api/apps" + ); + const data = await allAppsResponse.json(); + const installedAppsResponse = await fetch("/plugins?type=all"); + const { pluginDefinitions } = await installedAppsResponse.json(); + const serializedApps = data.map((app) => { + const installedApp = pluginDefinitions.find( + (installedApp) => installedApp.identifier === app.identifier + ); + if (installedApp) { + return { + ...app, + installed: true, + }; + } + return { + ...app, + installed: false, + }; + }); + setInstalledApps(serializedApps.filter((app) => app.installed)); + setApps(serializedApps); + }; + fetchApps(); + }, []); + + return ( + + {children} + + ); +}; + +export default AppsProvider; diff --git a/system-apps/app-store/webClient/src/index.tsx b/system-apps/app-store/webClient/src/index.tsx index 74da6bc9..c7276988 100644 --- a/system-apps/app-store/webClient/src/index.tsx +++ b/system-apps/app-store/webClient/src/index.tsx @@ -5,6 +5,7 @@ import { MVDResources } from "./context/mvd-resources"; import WindowSizeProvider from "./context/window-size"; import { RouterProvider } from "react-router-dom"; import { router } from "./routes"; +import AppsProvider from "./context/apps"; export function renderPlugin( domElement: HTMLElement, @@ -13,7 +14,9 @@ export function renderPlugin( ReactDOM.render( - + + + , domElement diff --git a/system-apps/app-store/webClient/src/pages/AppInfo.tsx b/system-apps/app-store/webClient/src/pages/AppInfo.tsx index c03e9498..ca3101ff 100644 --- a/system-apps/app-store/webClient/src/pages/AppInfo.tsx +++ b/system-apps/app-store/webClient/src/pages/AppInfo.tsx @@ -1,18 +1,19 @@ import React from "react"; import AppStoreLayout from "../components/AppStore/AppStoreLayout"; import { useParams, Link } from "react-router-dom"; -import { APPS, ASSETS_URL } from "../constants"; -import { CustomPrevArrow } from "../components/UI"; +import { ASSETS_URL } from "../constants"; +import { useAppsCtx } from "../context/apps"; const AppPage = () => { const { id } = useParams(); + const { apps } = useAppsCtx(); if (!id) { // TODO: return a not found page return null; } - const app = APPS.find((app) => app.id === parseInt(id)); + const app = apps?.find((app) => app.identifier === id); return ( @@ -64,7 +65,7 @@ const AppPage = () => { }} > app icon { marginBottom: "2px", }} > - {app?.publisher} + {app?.author || "Zowe"}

{ marginBottom: "10px", }} > - {app?.name} + {app.webContent.launchDefinition.pluginShortNameDefault}

{ marginBottom: "4px", }} > - com.zowe.org + {app.identifier}

{ marginBottom: "4px", }} > - v0.0.1 + v{app.pluginVersion}

- + + {app.installed && ( + + )} + +
+

+ App Description: {app.webContent.descriptionDefault} +

+ {app.license && ( +
+ +

+ License: {app.license} +

+
+ )} + {app.homepage && ( + + + + + + )} +
); }; diff --git a/system-apps/app-store/webClient/src/pages/Discover.tsx b/system-apps/app-store/webClient/src/pages/Discover.tsx index 56767ffc..d9c38caf 100644 --- a/system-apps/app-store/webClient/src/pages/Discover.tsx +++ b/system-apps/app-store/webClient/src/pages/Discover.tsx @@ -1,41 +1,48 @@ import React from "react"; import { Section, AppCarouselList } from "../components/UI"; -import { APPS } from "../constants"; -import AppStoreLayout from '../components/AppStore/AppStoreLayout'; +import AppStoreLayout from "../components/AppStore/AppStoreLayout"; +import { useAppsCtx } from "../context/apps"; -const sections = [ +const Discover = () => { + const { apps } = useAppsCtx(); + + if (!apps) { + // TODO: a nice loading spinner + return

Loading...

; + } + + const sections = [ { - id: 1, - title: "Popular Apps", - apps: APPS + id: 1, + title: "Popular Apps", + apps: apps, }, { - id: 2, - title: "Recently Updated", - apps: APPS + id: 2, + title: "Recently Updated", + apps: apps, }, { - id: 3, - title: "New Releases", - apps: APPS + id: 3, + title: "New Releases", + apps: apps, }, { - id: 4, - title: "Most Downloaded", - apps: APPS - } -] + id: 4, + title: "Most Downloaded", + apps: apps, + }, + ]; -const Discover = () => { - return ( - - {sections.map((section) => ( -
- -
- ))} -
- ) -} + return ( + + {sections.map((section) => ( +
+ +
+ ))} +
+ ); +}; export default Discover; diff --git a/system-apps/app-store/webClient/src/pages/Help.tsx b/system-apps/app-store/webClient/src/pages/Help.tsx new file mode 100644 index 00000000..39a6471e --- /dev/null +++ b/system-apps/app-store/webClient/src/pages/Help.tsx @@ -0,0 +1,87 @@ +import React from "react"; +import AppStoreLayout from "../components/AppStore/AppStoreLayout"; +import { Section } from "../components/UI"; + +const Help = () => { + return ( + +
+
+

+ The App Store uses zwe commands under the hood and requires a zowe + instance to be configured. If you have not configured it yet, please + follow the instructions below. +
+
+ Note: Make changes to zowe.yaml file so that it understands + that you'll be installing plugins from external sources + (registries). Follow{" "} + + this + + . +

+

+ For more help, please join our Slack channel or raise an issue on + GitHub. +

+ +
+
+
+ ); +}; + +export default Help; diff --git a/system-apps/app-store/webClient/src/pages/InstalledApps.tsx b/system-apps/app-store/webClient/src/pages/InstalledApps.tsx new file mode 100644 index 00000000..383bed97 --- /dev/null +++ b/system-apps/app-store/webClient/src/pages/InstalledApps.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import AppStoreLayout from "../components/AppStore/AppStoreLayout"; +import { useAppsCtx } from "../context/apps"; +import { AppCard, Section } from "../components/UI"; +import { useWindowSize } from "../context/window-size"; + +const InstalledApps = () => { + const { installedApps } = useAppsCtx(); + const windowSize = useWindowSize(); + return ( + +
+
+ {installedApps.map((app) => ( + + ))} +
+
+
+ ); +}; + +export default InstalledApps; diff --git a/system-apps/app-store/webClient/src/pages/OnPremise.tsx b/system-apps/app-store/webClient/src/pages/OnPremise.tsx new file mode 100644 index 00000000..5fa3680b --- /dev/null +++ b/system-apps/app-store/webClient/src/pages/OnPremise.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import AppStoreLayout from "../components/AppStore/AppStoreLayout"; +import { Section } from "../components/UI"; + +const OnPremise = () => { + return ( + +
+
+

Enter your registry URL here

+ + +
+
+
+ ); +}; + +export default OnPremise; diff --git a/system-apps/app-store/webClient/src/pages/Settings.tsx b/system-apps/app-store/webClient/src/pages/Settings.tsx new file mode 100644 index 00000000..6110c56a --- /dev/null +++ b/system-apps/app-store/webClient/src/pages/Settings.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import AppStoreLayout from "../components/AppStore/AppStoreLayout"; +import { Section } from "../components/UI"; + +const Settings = () => { + return ( + +
+
+

Enter your zowe config file path

+ + +

Select a handler

+
+ +
+ + +
+
+
+ ); +}; + +export default Settings; diff --git a/system-apps/app-store/webClient/src/pages/Updates.tsx b/system-apps/app-store/webClient/src/pages/Updates.tsx new file mode 100644 index 00000000..d72a4c59 --- /dev/null +++ b/system-apps/app-store/webClient/src/pages/Updates.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import AppStoreLayout from "../components/AppStore/AppStoreLayout"; + +const Updates = () => { + return Updates; +}; + +export default Updates; diff --git a/system-apps/app-store/webClient/src/routes.tsx b/system-apps/app-store/webClient/src/routes.tsx index 8387784c..711fe0c9 100644 --- a/system-apps/app-store/webClient/src/routes.tsx +++ b/system-apps/app-store/webClient/src/routes.tsx @@ -1,6 +1,11 @@ import React from "react"; import { createMemoryRouter } from "react-router-dom"; import Discover from "./pages/Discover"; +import InstalledApps from "./pages/InstalledApps"; +import Help from "./pages/Help"; +import OnPremise from "./pages/OnPremise"; +import Settings from "./pages/Settings"; +import Updates from "./pages/Updates"; const AppInfo = React.lazy(() => import("./pages/AppInfo")); @@ -25,6 +30,26 @@ export const router = createMemoryRouter( ), }, + { + path: "/installed", + element: , + }, + { + path: "/help", + element: , + }, + { + path: "/on-premise", + element: , + }, + { + path: "/settings", + element: , + }, + { + path: "/updates", + element: , + }, ], { initialEntries: ["/"], diff --git a/system-apps/app-store/webClient/src/styles/globals.css b/system-apps/app-store/webClient/src/styles/globals.css index ddb4bde1..8aea0ade 100644 --- a/system-apps/app-store/webClient/src/styles/globals.css +++ b/system-apps/app-store/webClient/src/styles/globals.css @@ -1,3 +1,12 @@ +a { + text-decoration: none; +} + +a:hover { + text-decoration: none; + cursor: pointer; +} + .appStoreContainer { font-family: "Roboto", sans-serif; background-color: #2f2f2f; @@ -92,6 +101,11 @@ justify-content: center; } +.installButton[disabled] { + background: #555; + cursor: not-allowed; +} + .appList { width: 90%; } @@ -115,6 +129,11 @@ font-weight: 500; } +.optionButton.active { + background: #343434; + color: #fff; +} + .optionButton:focus { outline: none; } @@ -124,6 +143,45 @@ color: #fff; } +select { + appearance: none; + outline: 0; + border: 0; + box-shadow: none; + flex: 1; + padding: 0 1em; + color: #fff; + background-color: #333; + background-image: none; + cursor: pointer; +} +select::-ms-expand { + display: none; +} +.select { + position: relative; + display: flex; + width: 20em; + height: 3em; + border-radius: 0.25em; + overflow: hidden; +} +/* Arrow */ +.select::after { + content: "\25BC"; + position: absolute; + top: 0; + right: 0; + padding: 1em; + background-color: #333; + transition: 0.25s all ease; + pointer-events: none; +} +/* Transition */ +.select:hover::after { + color: #f39c12; +} + ::-webkit-scrollbar { width: 6px; } diff --git a/system-apps/app-store/webClient/src/utils/index.js b/system-apps/app-store/webClient/src/utils/index.js index 19143895..2c72d866 100644 --- a/system-apps/app-store/webClient/src/utils/index.js +++ b/system-apps/app-store/webClient/src/utils/index.js @@ -1 +1 @@ -export const trunc = (str, n) => str.length > n ? str.substring(0, n - 1) + '...' : str; +export const trunc = (str, n) => str && str.length > n ? str.substring(0, n - 1) + '...' : str;