Skip to content

Commit

Permalink
Merge pull request #147 from kaleido-io/identities
Browse files Browse the repository at this point in the history
[identities] identities page
  • Loading branch information
dechdev authored Mar 28, 2022
2 parents 369fe1b + f366d75 commit 2d97f86
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 9 deletions.
5 changes: 4 additions & 1 deletion src/components/Buttons/TxButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export const TxButton: React.FC<Props> = ({ ns, txID, small = false }) => {
<IconButton
size={small ? 'small' : undefined}
sx={{ backgroundColor: FFColors.Purple }}
onClick={() => navigate(FF_NAV_PATHS.activityTxDetailPath(ns, txID))}
onClick={(e) => {
e.stopPropagation();
navigate(FF_NAV_PATHS.activityTxDetailPath(ns, txID));
}}
>
<LaunchIcon />
</IconButton>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Navigation/ActivityNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const ActivityNav = () => {
{
name: t('transactions'),
action: () => navigate(txPath),
itemIsActive: pathname === txPath,
itemIsActive: pathname.startsWith(txPath),
},
{
name: t('operations'),
Expand Down
6 changes: 6 additions & 0 deletions src/components/Navigation/NetworkNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const NetworkNav = () => {
const networkPath = FF_NAV_PATHS.networkPath(selectedNamespace);
const orgPath = FF_NAV_PATHS.networkOrgsPath(selectedNamespace);
const nodePath = FF_NAV_PATHS.networkNodesPath(selectedNamespace);
const identitiesPath = FF_NAV_PATHS.networkIdentitiesPath(selectedNamespace);

const navItems: INavItem[] = [
{
Expand All @@ -48,6 +49,11 @@ export const NetworkNav = () => {
action: () => navigate(nodePath),
itemIsActive: pathname === nodePath,
},
{
name: t('identities'),
action: () => navigate(identitiesPath),
itemIsActive: pathname === identitiesPath,
},
];

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/Navigation/TokensNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const TokensNav = () => {
{
name: t('pools'),
action: () => navigate(poolsPath),
itemIsActive: pathname === poolsPath,
itemIsActive: pathname.startsWith(poolsPath),
},
];

Expand Down
23 changes: 23 additions & 0 deletions src/interfaces/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,22 @@ export interface IGenericPagedResponse {
total: number;
}

export interface IIdentity {
id: string;
did: string;
type: string;
parent?: string;
namespace: string;
name: string;
messages: {
claim: string;
verification: string | null;
update: string | null;
};
created: string;
updated: string;
}

export interface IMessage {
header: {
id: string;
Expand Down Expand Up @@ -291,6 +307,13 @@ export interface IPagedFireFlyApiResponse {
total: number;
}

export interface IPagedIdentityResponse {
pageParam: number;
count: number;
items: IIdentity[];
total: number;
}

export interface IPagedMessageResponse {
pageParam: number;
count: number;
Expand Down
3 changes: 3 additions & 0 deletions src/interfaces/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ export const FF_Paths = {
// Groups
groups: '/groups',
groupsById: (groupId: string) => `/groups/${groupId}`,
// Identities
identities: '/identities',
identitiesById: (identityID: string) => `/identities/${identityID}`,
// Messages
messages: '/messages',
messagesBroadcast: '/messages/broadcast',
Expand Down
3 changes: 3 additions & 0 deletions src/interfaces/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const DOCS_PATH = 'https://hyperledger.github.io/firefly/';
export const EVENTS_PATH = 'events';
export const FILE_EXPLORER_PATH = 'fileExplorer';
export const HOME_PATH = 'home';
export const IDENTITIES_PATH = 'identities';
export const INTERFACES_PATH = 'interfaces';
export const LISTENERS_PATH = 'listeners';
export const MESSAGES_PATH = 'messages';
Expand Down Expand Up @@ -116,6 +117,8 @@ export const FF_NAV_PATHS = {
`/${NAMESPACES_PATH}/${ns}/${NETWORK_PATH}/${ORGANIZATIONS_PATH}`,
networkNodesPath: (ns: string) =>
`/${NAMESPACES_PATH}/${ns}/${NETWORK_PATH}/${NODES_PATH}`,
networkIdentitiesPath: (ns: string) =>
`/${NAMESPACES_PATH}/${ns}/${NETWORK_PATH}/${IDENTITIES_PATH}`,
// My Node
myNodePath: (ns: string) => `/${NAMESPACES_PATH}/${ns}/${MY_NODES_PATH}`,
// Docs
Expand Down
5 changes: 0 additions & 5 deletions src/pages/Activity/views/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ export const ActivityTransactions: () => JSX.Element = () => {
const txColumnHeaders = [
t('type'),
t('id'),
// t('details'),
t('blockchainIds'),
t('created'),
t(''),
Expand All @@ -183,10 +182,6 @@ export const ActivityTransactions: () => JSX.Element = () => {
{
value: <HashPopover shortHash={true} address={tx.id}></HashPopover>,
},
// TODO: Enrich content
// {
// value: <FFTableText color="primary" text={'TODO'} />,
// },
{
value: (
<>
Expand Down
5 changes: 5 additions & 0 deletions src/pages/Network/Routes.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RouteObject } from 'react-router-dom';
import { NAMESPACES_PATH } from '../../interfaces';
import { NetworkMapDashboard } from './views/Dashboard';
import { NetworkIdentities } from './views/Identities';
import { NetworkNodes } from './views/Nodes';
import { NetworkOrganizations } from './views/Organizations';

Expand All @@ -20,5 +21,9 @@ export const NetworkRoutes: RouteObject = {
path: 'nodes',
element: <NetworkNodes />,
},
{
path: 'identities',
element: <NetworkIdentities />,
},
],
};
193 changes: 193 additions & 0 deletions src/pages/Network/views/Identities.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Copyright © 2022 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import PermIdentityIcon from '@mui/icons-material/PermIdentity';
import { Grid } from '@mui/material';
import React, { useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FilterButton } from '../../../components/Filters/FilterButton';
import { FilterModal } from '../../../components/Filters/FilterModal';
import { Header } from '../../../components/Header';
import { ChartTableHeader } from '../../../components/Headers/ChartTableHeader';
import { HashPopover } from '../../../components/Popovers/HashPopover';
import { FFTableText } from '../../../components/Tables/FFTableText';
import { DataTable } from '../../../components/Tables/Table';
import { ApplicationContext } from '../../../contexts/ApplicationContext';
import { DateFilterContext } from '../../../contexts/DateFilterContext';
import { FilterContext } from '../../../contexts/FilterContext';
import { SnackbarContext } from '../../../contexts/SnackbarContext';
import {
FF_Paths,
IDataTableRecord,
IdentityFilters,
IIdentity,
IPagedIdentityResponse,
} from '../../../interfaces';
import { DEFAULT_PADDING, DEFAULT_PAGE_LIMITS } from '../../../theme';
import { fetchCatcher, getFFTime } from '../../../utils';
import { hasIdentityEvent } from '../../../utils/wsEvents';

export const NetworkIdentities: () => JSX.Element = () => {
const { newEvents, lastRefreshTime, clearNewEvents, selectedNamespace } =
useContext(ApplicationContext);
const { dateFilter } = useContext(DateFilterContext);
const { filterAnchor, setFilterAnchor, filterString } =
useContext(FilterContext);
const { reportFetchError } = useContext(SnackbarContext);
const { t } = useTranslation();
const [isMounted, setIsMounted] = useState(false);

const [identities, setIdentities] = useState<IIdentity[]>();
const [identitiesTotal, setIdentitiesTotal] = useState(0);
const [currentPage, setCurrentPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(DEFAULT_PAGE_LIMITS[1]);

useEffect(() => {
setIsMounted(true);
return () => {
setIsMounted(false);
};
}, []);

// Identities
useEffect(() => {
isMounted &&
dateFilter &&
fetchCatcher(
`${FF_Paths.nsPrefix}/${selectedNamespace}${
FF_Paths.identities
}?limit=${rowsPerPage}&count&skip=${rowsPerPage * currentPage}${
filterString ?? ''
}&sort=created`
)
.then((identityRes: IPagedIdentityResponse) => {
if (isMounted) {
setIdentities(identityRes.items);
setIdentitiesTotal(identityRes.total);
}
})
.catch((err) => {
reportFetchError(err);
});
}, [
rowsPerPage,
currentPage,
selectedNamespace,
dateFilter,
filterString,
lastRefreshTime,
isMounted,
]);

const idColHeaders = [
t('name'),
t('id'),
t('did'),
t('type'),
t('parent'),
t('updated'),
];
const idRecords: IDataTableRecord[] | undefined = identities?.map((id) => {
return {
key: id.id,
columns: [
{
value: (
<FFTableText
color="primary"
text={id.name}
icon={<PermIdentityIcon />}
/>
),
},
{
value: <HashPopover shortHash={true} address={id.id} />,
},
{
value: <HashPopover address={id.did} />,
},
{
value: <FFTableText color="primary" text={id.type} />,
},
{
value: id.parent ? (
<HashPopover address={id.parent} />
) : (
<FFTableText color="secondary" text={t('noParentForIdentity')} />
),
},
{
value: (
<FFTableText color="secondary" text={getFFTime(id.updated, true)} />
),
},
],
};
});

return (
<>
<Header
title={t('identities')}
subtitle={t('network')}
noDateFilter
showRefreshBtn={hasIdentityEvent(newEvents)}
onRefresh={clearNewEvents}
></Header>
<Grid container px={DEFAULT_PADDING}>
<Grid container item wrap="nowrap" direction="column">
<ChartTableHeader
title={t('allIdentities')}
filter={
<FilterButton
onSetFilterAnchor={(e: React.MouseEvent<HTMLButtonElement>) =>
setFilterAnchor(e.currentTarget)
}
/>
}
/>
<DataTable
onHandleCurrPageChange={(currentPage: number) =>
setCurrentPage(currentPage)
}
onHandleRowsPerPage={(rowsPerPage: number) =>
setRowsPerPage(rowsPerPage)
}
stickyHeader={true}
minHeight="300px"
maxHeight="calc(100vh - 340px)"
records={idRecords}
columnHeaders={idColHeaders}
paginate={true}
emptyStateText={t('noIdentitiesToDisplay')}
dataTotal={identitiesTotal}
currentPage={currentPage}
rowsPerPage={rowsPerPage}
/>
</Grid>
</Grid>
{filterAnchor && (
<FilterModal
anchor={filterAnchor}
onClose={() => {
setFilterAnchor(null);
}}
fields={IdentityFilters}
/>
)}
</>
);
};
6 changes: 6 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"allData": "All Data",
"allDatatypes": "All Datatypes",
"allEvents": "All Events",
"allIdentities": "All Identities",
"allInterfaces": "All Interfaces",
"allListeners": "All Listeners",
"allMessages": "All Messages",
Expand Down Expand Up @@ -78,6 +79,7 @@
"definition": "Definition",
"description": "Description",
"details": "Details",
"did": "DID",
"docs": "Docs",
"download": "Download",
"dxEndpoint": "DX Endpoint",
Expand All @@ -102,6 +104,7 @@
"groupInit": "Group Init",
"hash": "Hash",
"id": "ID",
"identities": "Identities",
"identity": "Identity",
"identityConfirmed": "Identity Confirmed",
"identityUpdated": "Identity Updated",
Expand Down Expand Up @@ -164,6 +167,7 @@
"noEvents": "No Events",
"noEventsToDisplay": "No Events to Display",
"noFromAccount": "No From Account",
"noIdentitiesToDisplay": "No Identities to Display",
"noInterfacesToDisplay": "No Interfaces to Display",
"noListenersToDisplay": "No Listeners to Display",
"noMessageInTransfer": "No Message In Transfer",
Expand All @@ -175,6 +179,7 @@
"noOperations": "No Operations",
"noOperationsToDisplay": "No Operations to Display",
"noOrganizationsToDisplay": "No Organizations to Display",
"noParentForIdentity": "No Parent for Identity",
"noRecentBlobs": "No Recent Blobs",
"noRecentData": "No Recent Data",
"noRecentNetworkEvents": "No Recent Network Events",
Expand Down Expand Up @@ -207,6 +212,7 @@
"orgOwner": "Org Owner",
"out": "Out",
"output": "Output",
"parent": "Parent",
"peer": "Peer",
"plugin": "Plugin",
"pool": "Pool",
Expand Down
Loading

0 comments on commit 2d97f86

Please sign in to comment.