Skip to content

Commit

Permalink
feat(ledger-browser): refactor home page
Browse files Browse the repository at this point in the history
- Remove status apps, its functionality has been moved to the home page.
- Add status components for persistence apps.
- Add home page that contains cards for each configured app. Clicking on it
  naviagtes to specific app, clicking on Status button shows status component.
- Remove app drawer, replace it with a button that navigates to root path
  (i.e. the home app, navigation between apps is handled here).
- Remove all the remaining dead and legacy code, apply small structure upgrades.
- Since this PR removes all old code, and all the current code was written by
  me and Tomasz, I've also removed previous inactive package contributors.

Depends on hyperledger-cacti#3320

Signed-off-by: Michal Bajer <michal.bajer@fujitsu.com>
  • Loading branch information
outSH committed Aug 6, 2024
1 parent fdce6b3 commit 9c99b92
Show file tree
Hide file tree
Showing 36 changed files with 414 additions and 1,024 deletions.
10 changes: 0 additions & 10 deletions packages/cacti-ledger-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@
"name": "Tomasz Awramski",
"email": "tomasz.awramski@fujitsu.com",
"url": "https://www.fujitsu.com/global/"
},
{
"name": "Eryk Baranowski",
"email": "eryk.baranowski@fujitsu.com",
"url": "https://www.fujitsu.com/global/"
},
{
"name": "Barnaba Pawelczak",
"email": "barnaba.pawelczak@fujitsu.com",
"url": "https://www.fujitsu.com/global/"
}
],
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { themeOptions } from "./theme";
import ContentLayout from "./components/Layout/ContentLayout";
import HeaderBar from "./components/Layout/HeaderBar";
import WelcomePage from "./components/WelcomePage";
import HomePage from "./pages/home/HomePage";
import { AppConfig, AppListEntry } from "./common/types/app";
import { patchAppRoutePath } from "./common/utils";
import { NotificationProvider } from "./common/context/NotificationContext";
Expand All @@ -22,8 +22,8 @@ type AppConfigProps = {
function getAppList(appConfig: AppConfig[]) {
const appList: AppListEntry[] = appConfig.map((app) => {
return {
path: app.path,
name: app.name,
path: app.options.path,
name: app.appName,
};
});

Expand All @@ -43,12 +43,12 @@ function getHeaderBarRoutes(appConfig: AppConfig[]) {

const headerRoutesConfig = appConfig.map((app) => {
return {
key: app.path,
path: `${app.path}/*`,
key: app.options.path,
path: `${app.options.path}/*`,
element: (
<HeaderBar
appList={appList}
path={app.path}
path={app.options.path}
menuEntries={app.menuEntries}
/>
),
Expand All @@ -68,12 +68,12 @@ function getHeaderBarRoutes(appConfig: AppConfig[]) {
function getContentRoutes(appConfig: AppConfig[]) {
const appRoutes: RouteObject[] = appConfig.map((app) => {
return {
key: app.path,
path: app.path,
key: app.options.path,
path: app.options.path,
children: app.routes.map((route) => {
return {
key: route.path,
path: patchAppRoutePath(app.path, route.path),
path: patchAppRoutePath(app.options.path, route.path),
element: route.element,
children: route.children,
};
Expand All @@ -84,7 +84,7 @@ function getContentRoutes(appConfig: AppConfig[]) {
// Include landing / welcome page
appRoutes.push({
index: true,
element: <WelcomePage />,
element: <HomePage />,
});

return useRoutes([
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { AppConfig } from "../../common/types/app";
import Dashboard from "./pages/Dashboard/Dashboard";
import Blocks from "./pages/Blocks/Blocks";
import Transactions from "./pages/Transactions/Transactions";
import Accounts from "./pages/Accounts/Accounts";
import { AppConfig } from "../../common/types/app";
import { usePersistenceAppStatus } from "../../common/hook/use-persistence-app-status";
import PersistencePluginStatus from "../../components/PersistencePluginStatus/PersistencePluginStatus";

const ethConfig: AppConfig = {
name: "Ethereum",
path: "/eth",
appName: "Ethereum Browser",
options: {
instanceName: "Ethereum",
description:
"Applicaion for browsing Ethereum ledger blocks, transactions and tokens. Requires Ethereum persistence plugin to work correctly.",
path: "/eth",
},
menuEntries: [
{
title: "Dashboard",
Expand Down Expand Up @@ -34,6 +41,10 @@ const ethConfig: AppConfig = {
element: <Accounts />,
},
],
useAppStatus: () => usePersistenceAppStatus("PluginPersistenceEthereum"),
StatusComponent: (
<PersistencePluginStatus pluginName="PluginPersistenceEthereum" />
),
};

export default ethConfig;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import TextField from "@mui/material/TextField";
import { styled } from "@mui/material/styles";

import { FabricCertificate } from "../../fabric-supabase-types";
import StackedRowItems from "../ui/StackedRowItems";
import StackedRowItems from "../../../../components/ui/StackedRowItems";

const ListHeaderTypography = styled(Typography)(({ theme }) => ({
color: theme.palette.secondary.main,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { AppConfig } from "../../common/types/app";
import Dashboard from "./pages/Dashboard/Dashboard";
import Blocks from "./pages/Blocks/Blocks";
import Transactions from "./pages/Transactions/Transactions";
import { Outlet } from "react-router-dom";
import TransactionDetails from "./pages/TransactionDetails/TransactionDetails";
import { AppConfig } from "../../common/types/app";
import { usePersistenceAppStatus } from "../../common/hook/use-persistence-app-status";
import PersistencePluginStatus from "../../components/PersistencePluginStatus/PersistencePluginStatus";

const fabricConfig: AppConfig = {
name: "Fabric",
path: "/fabric",
appName: "Hyperledger Fabric Browser",
options: {
instanceName: "Fabric",
description:
"Applicaion for browsing Hyperledger Fabric ledger blocks and transactions. Requires Fabric persistence plugin to work correctly.",
path: "/fabric",
},
menuEntries: [
{
title: "Dashboard",
Expand Down Expand Up @@ -41,6 +48,10 @@ const fabricConfig: AppConfig = {
],
},
],
useAppStatus: () => usePersistenceAppStatus("PluginPersistenceFabric"),
StatusComponent: (
<PersistencePluginStatus pluginName="PluginPersistenceFabric" />
),
};

export default fabricConfig;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Skeleton from "@mui/material/Skeleton";

import { FabricTransaction } from "../../fabric-supabase-types";
import ShortenedTypography from "../../../../components/ui/ShortenedTypography";
import StackedRowItems from "../../components/ui/StackedRowItems";
import StackedRowItems from "../../../../components/ui/StackedRowItems";

const ListHeaderTypography = styled(Typography)(({ theme }) => ({
color: theme.palette.secondary.main,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import cactiGuiConfig from "../apps/cacti/index";
import ethereumGuiConfig from "../apps/eth";
import fabricAppConfig from "../apps/fabric";
import { AppConfig } from "./types/app";

export const appConfig: AppConfig[] = [
cactiGuiConfig,
ethereumGuiConfig,
fabricAppConfig,
];
export const appConfig: AppConfig[] = [ethereumGuiConfig, fabricAppConfig];
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import { useQuery } from "@tanstack/react-query";
import { GetStatusResponse } from "../types/app";
import { useNotification } from "../context/NotificationContext";
import { persistencePluginStatus } from "../queries";

/**
* Return status of given persistence plugin from the database.
*
* @param pluginName name of the plugin (as set by the persistence plugin itself)
*/
export function usePersistenceAppStatus(pluginName: string): GetStatusResponse {
const { isError, isPending, data, error } = useQuery(
persistencePluginStatus(pluginName),
);
const { showNotification } = useNotification();

React.useEffect(() => {
isError &&
showNotification(`Could get ${pluginName} status: ${error}`, "error");
}, [isError]);

return {
isPending,
isInitialized: data?.is_schema_initialized ?? false,
status: {
severity: "info",
message: "Unknown",
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { createClient } from "@supabase/supabase-js";
import { queryOptions } from "@tanstack/react-query";
import { PluginStatus } from "./supabase-types";

const supabaseQueryKey = "supabase";
const supabaseUrl = "http://localhost:8000";
const supabaseKey =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE";

export const supabase = createClient(supabaseUrl, supabaseKey);

/**
* Get persistence plugin status from the database using it's name.
*/
export function persistencePluginStatus(name: string) {
const tableName = "plugin_status";

return queryOptions({
queryKey: [supabaseQueryKey, tableName, name],
queryFn: async () => {
const { data, error } = await supabase
.from(tableName)
.select()
.match({ name });

if (error) {
throw new Error(
`Could not get persistence plugin status with name ${name}: ${error.message}`,
);
}

if (data.length !== 1) {
throw new Error(
`Invalid response when persistence plugin status with name ${name}: ${data}`,
);
}

return data.pop() as PluginStatus;
},
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,11 @@ export interface TokenERC20 {
total_supply: number;
token_address: string;
}

export interface PluginStatus {
name: string;
last_instance_id: string;
is_schema_initialized: boolean;
created_at: string;
last_connected_at: string;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import { RouteObject } from "react-router-dom";

export interface AppListEntry {
Expand All @@ -10,9 +11,28 @@ export interface AppConfigMenuEntry {
url: string;
}

export interface AppConfig {
name: string;
export interface AppStatus {
severity: "success" | "info" | "warning" | "error";
message: string;
}

export interface GetStatusResponse {
isPending: boolean;
isInitialized: boolean;
status: AppStatus;
}

export interface AppConfigOptions {
instanceName: string;
description: string | undefined;
path: string;
}

export interface AppConfig {
appName: string;
options: AppConfigOptions;
menuEntries: AppConfigMenuEntry[];
routes: RouteObject[];
useAppStatus: () => GetStatusResponse;
StatusComponent: React.ReactElement;
}
Loading

0 comments on commit 9c99b92

Please sign in to comment.