From f03ef61352f7305dc313cd995b7172a6424c61fd Mon Sep 17 00:00:00 2001 From: Sergio Betanzos Date: Thu, 24 Jun 2021 16:39:34 +0200 Subject: [PATCH] F OpenNebula/one#5422: Add sortby to tables --- .../src/client/components/Header/Popover.js | 4 + .../components/Tables/Clusters/columns.js | 24 +++- .../client/components/Tables/Clusters/row.js | 12 +- .../components/Tables/Datastores/columns.js | 20 +++- .../components/Tables/Datastores/row.js | 15 +-- .../Tables/Enhanced/Utils/GlobalFilter.js | 106 ++++++++++++++++++ .../Tables/Enhanced/Utils/GlobalSort.js | 105 +++++++++++++++++ .../components/Tables/Enhanced/index.js | 62 ++++++---- .../components/Tables/Enhanced/toolbar.js | 87 ++++++++++++++ .../client/components/Tables/Hosts/columns.js | 83 ++------------ .../src/client/components/Tables/Hosts/row.js | 8 +- .../components/Tables/Images/columns.js | 17 ++- .../client/components/Tables/Images/row.js | 8 +- .../Tables/MarketplaceApps/columns.js | 20 ++-- .../components/Tables/MarketplaceApps/row.js | 6 +- .../components/Tables/Marketplaces/columns.js | 20 ++-- .../components/Tables/Marketplaces/row.js | 10 +- .../components/Tables/Virtualized/toolbar.js | 13 ++- .../client/components/Tables/Vms/columns.js | 26 ++++- .../src/client/components/Tables/Vms/row.js | 8 +- .../src/client/constants/translates.js | 2 + 21 files changed, 483 insertions(+), 173 deletions(-) create mode 100644 src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalFilter.js create mode 100644 src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalSort.js create mode 100644 src/fireedge/src/client/components/Tables/Enhanced/toolbar.js diff --git a/src/fireedge/src/client/components/Header/Popover.js b/src/fireedge/src/client/components/Header/Popover.js index 5458b18bc0..651f16855e 100644 --- a/src/fireedge/src/client/components/Header/Popover.js +++ b/src/fireedge/src/client/components/Header/Popover.js @@ -22,6 +22,7 @@ const HeaderPopover = ({ buttonProps, headerTitle, disablePadding, + popoverProps, children }) => { const classes = headerStyles() @@ -70,6 +71,7 @@ const HeaderPopover = ({ vertical: 'top', horizontal: 'right' }} + {...popoverProps} > {(headerTitle || isMobile) && ( @@ -98,6 +100,7 @@ HeaderPopover.propTypes = { buttonProps: PropTypes.objectOf(PropTypes.any), headerTitle: PropTypes.string, disablePadding: PropTypes.bool, + popoverProps: PropTypes.objectOf(PropTypes.any), children: PropTypes.func } @@ -108,6 +111,7 @@ HeaderPopover.defaultProps = { buttonProps: {}, headerTitle: null, disablePadding: false, + popoverProps: {}, children: () => undefined } diff --git a/src/fireedge/src/client/components/Tables/Clusters/columns.js b/src/fireedge/src/client/components/Tables/Clusters/columns.js index 4e432ce0f6..63e8983013 100644 --- a/src/fireedge/src/client/components/Tables/Clusters/columns.js +++ b/src/fireedge/src/client/components/Tables/Clusters/columns.js @@ -1,7 +1,21 @@ +const getNumberOfResources = resources => [resources?.ID ?? []].flat().length || 0 + export default [ - { Header: '', accessor: 'ID' }, - { Header: '', accessor: 'NAME' }, - { Header: '', accessor: 'HOSTS' }, - { Header: '', accessor: 'DATASTORES' }, - { Header: '', accessor: 'VNETS' } + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', accessor: 'NAME' }, + { + Header: 'Number of Hosts', + id: 'HOSTS', + accessor: row => getNumberOfResources(row?.HOSTS) + }, + { + Header: 'Number of Datastores', + id: 'DATASTORES', + accessor: row => getNumberOfResources(row?.DATASTORES) + }, + { + Header: 'Number of VNets', + id: 'VNETS', + accessor: row => getNumberOfResources(row?.VNETS) + } ] diff --git a/src/fireedge/src/client/components/Tables/Clusters/row.js b/src/fireedge/src/client/components/Tables/Clusters/row.js index 8d30ab1fc7..e797a81a0d 100644 --- a/src/fireedge/src/client/components/Tables/Clusters/row.js +++ b/src/fireedge/src/client/components/Tables/Clusters/row.js @@ -14,6 +14,8 @@ const Row = ({ value, ...props }) => { const datastores = [DATASTORES?.ID ?? []].flat().length || 0 const virtualNetworks = [VNETS?.ID ?? []].flat().length || 0 + const providerName = TEMPLATE?.PROVISION?.PROVIDER_NAME + return (
@@ -22,21 +24,21 @@ const Row = ({ value, ...props }) => {
{`#${ID}`} - + {` ${hosts}`} - + {` ${datastores}`} - + {` ${virtualNetworks}`} - {TEMPLATE?.PROVISION && + {TEMPLATE?.PROVISION && - {` ${TEMPLATE?.PROVISION?.PROVIDER_NAME}`} + {` ${providerName}`} }
diff --git a/src/fireedge/src/client/components/Tables/Datastores/columns.js b/src/fireedge/src/client/components/Tables/Datastores/columns.js index fea5f9c6f5..5e311caaa7 100644 --- a/src/fireedge/src/client/components/Tables/Datastores/columns.js +++ b/src/fireedge/src/client/components/Tables/Datastores/columns.js @@ -1,8 +1,16 @@ +const getNumberOfResources = resources => [resources?.ID ?? []].flat().length || 0 + export default [ - { Header: '', accessor: 'ID' }, - { Header: '', accessor: 'NAME' }, - { Header: '', accessor: 'STATE' }, - { Header: '', accessor: 'TYPE' }, - { Header: '', accessor: 'CLUSTERS' }, - { Header: '', accessor: 'ALLOCATED_CPU' } + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', accessor: 'NAME' }, + { Header: 'Owner', accessor: 'UNAME' }, + { Header: 'Group', accessor: 'GNAME' }, + { Header: 'State', accessor: 'STATE' }, + { Header: 'Type', accessor: 'TYPE' }, + { + Header: 'Number of Clusters', + id: 'CLUSTERS', + accessor: row => getNumberOfResources(row?.CLUSTERS) + }, + { Header: 'Allocated CPU', accessor: 'ALLOCATED_CPU' } ] diff --git a/src/fireedge/src/client/components/Tables/Datastores/row.js b/src/fireedge/src/client/components/Tables/Datastores/row.js index 11378f355a..d8a225b32a 100644 --- a/src/fireedge/src/client/components/Tables/Datastores/row.js +++ b/src/fireedge/src/client/components/Tables/Datastores/row.js @@ -17,8 +17,9 @@ const Row = ({ value, ...props }) => { const state = DatastoreModel.getState(value) const type = DatastoreModel.getType(value) - const clusters = [CLUSTERS?.ID ?? []].flat() + const clusters = [CLUSTERS?.ID ?? []].flat().join(',') const { percentOfUsed, percentLabel } = DatastoreModel.getCapacityInfo(value) + const provisionId = PROVISION?.ID return (
@@ -35,21 +36,21 @@ const Row = ({ value, ...props }) => {
{`#${ID}`} - + {` ${UNAME}`} - + {` ${GNAME}`} - {PROVISION?.ID && + {provisionId && - {` ${PROVISION.ID}`} + {` ${provisionId}`} } - + - {` ${clusters.join(',')}`} + {` ${clusters}`}
diff --git a/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalFilter.js b/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalFilter.js new file mode 100644 index 0000000000..0e1736b603 --- /dev/null +++ b/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalFilter.js @@ -0,0 +1,106 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { makeStyles, fade, debounce, InputBase } from '@material-ui/core' +import { Search as SearchIcon } from 'iconoir-react' + +const useStyles = makeStyles(({ spacing, palette, shape, breakpoints }) => ({ + search: { + position: 'relative', + borderRadius: shape.borderRadius, + backgroundColor: fade(palette.divider, 0.15), + '&:hover': { + backgroundColor: fade(palette.divider, 0.25) + }, + width: '100%', + [breakpoints.up('sm')]: { + marginLeft: spacing(1), + width: 'auto' + } + }, + searchIcon: { + padding: spacing(0, 2), + height: '100%', + position: 'absolute', + pointerEvents: 'none', + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + }, + inputRoot: { + color: 'inherit' + }, + inputInput: { + padding: spacing(1, 1, 1, 0), + // vertical padding + font size from searchIcon + paddingLeft: `calc(1em + ${spacing(4)}px)`, + width: '100%' + } +})) + +const GlobalFilter = props => { + /** + * @type {import('react-table').UseGlobalFiltersInstanceProps & + * import('react-table').UseGlobalFiltersState} + */ + const { preGlobalFilteredRows, globalFilter, setGlobalFilter } = props + + const classes = useStyles() + const count = preGlobalFilteredRows.length + + const [value, setValue] = React.useState(globalFilter) + + const handleChange = React.useCallback( + // Set undefined to remove the filter entirely + debounce(value => { setGlobalFilter(value || undefined) }, 200) + ) + + // Global filter only works with pagination from the first page. + // This may not be a problem for server side pagination when + // only the current page is downloaded. + + /* + + + + + */ + + return ( +
+
+ +
+ { + setValue(event.target.value) + handleChange(event.target.value) + }} + placeholder={'Search...'} + classes={{ + root: classes.inputRoot, + input: classes.inputInput + }} + inputProps={{ 'aria-label': 'search' }} + /> +
+ ) +} + +GlobalFilter.propTypes = { + preGlobalFilteredRows: PropTypes.array.isRequired, + globalFilter: PropTypes.string, + setGlobalFilter: PropTypes.func.isRequired +} + +export default GlobalFilter diff --git a/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalSort.js b/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalSort.js new file mode 100644 index 0000000000..a1d9ab7913 --- /dev/null +++ b/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalSort.js @@ -0,0 +1,105 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { makeStyles, MenuItem, MenuList, Chip } from '@material-ui/core' +import { SortDown, ArrowDown, ArrowUp } from 'iconoir-react' + +import HeaderPopover from 'client/components/Header/Popover' +import { T } from 'client/constants' + +const useStyles = makeStyles(theme => ({ + root: { + display: 'flex', + flexWrap: 'wrap', + gap: 6, + alignItems: 'center' + }, +})) + +const GlobalSort = props => { + const classes = useStyles() + + /** + * @type {import('react-table').TableInstance & + * import('react-table').UseSortByInstanceProps & + * import('react-table').UseSortByState} + */ + const { headers, sortBy, setSortBy } = props + + const sortAvailable = React.useMemo(() => { + const flatSorters = sortBy.map(({ id }) => id) + + return headers.filter(({ id }) => !flatSorters.includes(id)) + }, [sortBy.length]) + + const handleClick = (id, name) => { + setSortBy([{ id, desc: false, name }, ...sortBy]) + } + + const handleDelete = removeId => { + setSortBy(sortBy.filter(({id}) => id !== removeId)) + } + + const handleToggle = (id, desc) => { + setSortBy(sortBy.map(sort => sort.id === id ? ({ ...sort, desc }) : sort)) + } + + return ( +
+ {React.useMemo(() => ( + } + buttonLabel={T.SortBy} + buttonProps={{ + 'data-cy': 'sort-by-button', + disabled: sortAvailable.length === 0, + variant: 'outlined' + }} + popoverProps= {{ + anchorOrigin: { + vertical: 'bottom', + horizontal: 'left' + }, + transformOrigin: { + vertical: 'top', + horizontal: 'left' + } + }} + > + {() => ( + + {sortAvailable.length + ? sortAvailable?.map(({ id, Header: name }) => ( + { handleClick(id, name) }}> + {name} + + )) + : {T.Empty} + } + + )} + + ), [sortAvailable.length])} + + {React.useMemo(() => sortBy?.map(({ name, id, desc }) => ( + : } + label={name ?? id} + onClick={() => handleToggle(id, !desc)} + onDelete={() => handleDelete(id)} + /> + )), [sortBy.length, handleToggle])} +
+ ) +} + +GlobalSort.propTypes = { + headers: PropTypes.array.isRequired, + preSortedRows: PropTypes.array.isRequired, + sortBy: PropTypes.array.isRequired, + setSortBy: PropTypes.func.isRequired +} + +export default GlobalSort diff --git a/src/fireedge/src/client/components/Tables/Enhanced/index.js b/src/fireedge/src/client/components/Tables/Enhanced/index.js index 5b7370aa03..572b2ad9b4 100644 --- a/src/fireedge/src/client/components/Tables/Enhanced/index.js +++ b/src/fireedge/src/client/components/Tables/Enhanced/index.js @@ -1,21 +1,22 @@ -/* eslint-disable react/prop-types */ import * as React from 'react' +import PropTypes from 'prop-types' import { makeStyles, Box, LinearProgress } from '@material-ui/core' import { useGlobalFilter, usePagination, useRowSelect, + useSortBy, useTable } from 'react-table' import SplitPane from 'client/components/SplitPane' -import Toolbar from 'client/components/Tables/Virtualized/toolbar' +import Toolbar from 'client/components/Tables/Enhanced/toolbar' import Pagination from 'client/components/Tables/Enhanced/pagination' import { addOpacityToColor } from 'client/utils' -const useStyles = makeStyles(({ palette, typography }) => ({ +const useStyles = makeStyles(({ palette, typography, breakpoints }) => ({ root: { height: '100%', display: 'flex', @@ -47,37 +48,38 @@ const useStyles = makeStyles(({ palette, typography }) => ({ }, toolbar: { ...typography.body1, - color: palette.text.hint, marginBottom: 16, display: 'flex', - flexWrap: 'wrap', - alignItems: 'center', - justifyContent: 'space-between', gap: '1em', + alignItems: 'start', + justifyContent: 'space-between', '& > div:first-child': { flexGrow: 1 + }, + [breakpoints.down('sm')]: { + flexWrap: 'wrap' } }, pagination: { + flexShrink: 0, display: 'flex', alignItems: 'center', - gap: '1em', - transition: '200ms' + gap: '1em' } })) const EnhancedTable = ({ - data, + canFetchMore, columns, - pageSize = 10, - isLoading, - showPageCount, - getRowId, - RowComponent, - renderDetail, - renderAllSelected = true, + data, fetchMore, - canFetchMore + getRowId, + isLoading, + pageSize = 10, + renderAllSelected = true, + renderDetail, + RowComponent, + showPageCount }) => { const classes = useStyles() @@ -92,20 +94,21 @@ const EnhancedTable = ({ defaultColumn, getRowId, // When table has update, disable all of the auto resetting + autoResetExpanded: false, + autoResetFilters: false, + autoResetGroupBy: false, autoResetPage: false, autoResetRowState: false, autoResetSelectedRow: false, - autoResetExpanded: false, - autoResetGroupBy: false, autoResetSelectedRows: false, autoResetSortBy: false, - autoResetFilters: false, // ------------------------------------- initialState: { pageSize } }, useGlobalFilter, + useSortBy, usePagination, useRowSelect ) @@ -187,4 +190,21 @@ const EnhancedTable = ({ ) } +EnhancedTable.propTypes = { + canFetchMore: PropTypes.bool, + columns: PropTypes.array, + data: PropTypes.array, + fetchMore: PropTypes.func, + getRowId: PropTypes.func, + isLoading: PropTypes.bool, + pageSize: PropTypes.number, + renderAllSelected: PropTypes.bool, + renderDetail: PropTypes.func, + RowComponent: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]), + showPageCount: PropTypes.bool +} + export default EnhancedTable diff --git a/src/fireedge/src/client/components/Tables/Enhanced/toolbar.js b/src/fireedge/src/client/components/Tables/Enhanced/toolbar.js new file mode 100644 index 0000000000..6d18efb1cf --- /dev/null +++ b/src/fireedge/src/client/components/Tables/Enhanced/toolbar.js @@ -0,0 +1,87 @@ +import * as React from 'react' +import PropTypes from 'prop-types' + +import { makeStyles, Button } from '@material-ui/core' +import { Filter as FilterIcon } from 'iconoir-react' + +import GlobalFilter from 'client/components/Tables/Enhanced/Utils/GlobalFilter' +import GlobalSort from 'client/components/Tables/Enhanced/Utils/GlobalSort' + +import { Tr } from 'client/components/HOC' +import { T } from 'client/constants' + +const useToolbarStyles = makeStyles(() => ({ + root: { + display: 'flex', + flexDirection: 'column', + alignItems: 'start', + gap: '1em' + }, + filterWrapper: { + flexGrow: 1, + display: 'flex', + gap: '1em' + }, + filterButton: { + minWidth: 123, + textAlign: 'left' + } +})) + +const Toolbar = ({ useTableProps }) => { + const classes = useToolbarStyles() + + /** + * @type {import('react-table').UseGlobalFiltersInstanceProps & + * import('react-table').UseSortByInstanceProps & + * import('react-table').TableInstance & + * { state: import('react-table').UseGlobalFiltersState & + * import('react-table').TableState + * import('react-table').UseSortByState }} + */ + const { + headers, + preGlobalFilteredRows, + setGlobalFilter, + preSortedRows, + setSortBy, + state: { globalFilter, sortBy } + } = useTableProps + + // const numSelected = Object.keys(selectedRowIds).length + + return ( +
+
+ + +
+ +
+ ) +} + +Toolbar.propTypes = { + useTableProps: PropTypes.object +} + +Toolbar.defaultProps = { + useTableProps: {} +} + +export default Toolbar diff --git a/src/fireedge/src/client/components/Tables/Hosts/columns.js b/src/fireedge/src/client/components/Tables/Hosts/columns.js index 0205d5adde..b63b05f772 100644 --- a/src/fireedge/src/client/components/Tables/Hosts/columns.js +++ b/src/fireedge/src/client/components/Tables/Hosts/columns.js @@ -1,76 +1,13 @@ -import * as React from 'react' - -import { LinearProgressWithLabel, StatusBadge } from 'client/components/Status' -import * as HostModel from 'client/models/Host' - export default [ - /* { - id: 'selection', - // The header can use the table's getToggleAllRowsSelectedProps method - // to render a checkbox. - // Pagination is a problem since this will select all rows even though - // not all rows are on the current page. - // The solution should be server side pagination. - // For one, the clients should not download all rows in most cases. - // The client should only download data for the current page. - // In that case, getToggleAllRowsSelectedProps works fine. - Header: ({ getToggleAllRowsSelectedProps }) => ( - - ), - // The cell can use the individual row's getToggleRowSelectedProps method - // to the render a checkbox - Cell: ({ row }) => ( - - ) - }, */ - { - Header: '', - id: 'STATE', - width: 50, - accessor: row => { - const state = HostModel.getState(row) - - return ( - - ) - } - }, - { Header: '#', accessor: 'ID', width: 45 }, - { Header: 'Name', accessor: 'NAME' }, - { - Header: 'IM/VM', - width: 100, - accessor: ({ IM_MAD, VM_MAD }) => - IM_MAD === VM_MAD ? IM_MAD : `${IM_MAD}/${VM_MAD}` - }, + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', id: 'NAME', accessor: row => row?.TEMPLATE?.NAME ?? row.NAME }, + { Header: 'State', accessor: 'STATE' }, { Header: 'Cluster', accessor: 'CLUSTER' }, - { Header: 'RVMs', accessor: 'HOST_SHARE.RUNNING_VMS', width: 100 }, - { - Header: 'Allocated CPU', - accessor: row => { - const { percentCpuUsed, percentCpuLabel } = HostModel.getAllocatedInfo(row) - - return ( -
- -
- ) - } - }, - { - Header: 'Allocated MEM', - accessor: row => { - const { percentMemUsed, percentMemLabel } = HostModel.getAllocatedInfo(row) - - return ( -
- -
- ) - } - } + { Header: 'IM MAD', accessor: 'IM_MAD' }, + { Header: 'VM MAD', accessor: 'VM_MAD' }, + { Header: 'Running VMs', accessor: 'HOST_SHARE.RUNNING_VMS' }, + { Header: 'CPU Usage', accessor: 'CPU_USAGE' }, + { Header: 'CPU Total', accessor: 'TOTAL_CPU' }, + { Header: 'MEM Usage', accessor: 'MEM_USAGE' }, + { Header: 'MEM Total', accessor: 'TOTAL_MEM' } ] diff --git a/src/fireedge/src/client/components/Tables/Hosts/row.js b/src/fireedge/src/client/components/Tables/Hosts/row.js index b3764e1a90..b8180abd32 100644 --- a/src/fireedge/src/client/components/Tables/Hosts/row.js +++ b/src/fireedge/src/client/components/Tables/Hosts/row.js @@ -11,7 +11,7 @@ import * as HostModel from 'client/models/Host' const Row = ({ value, ...props }) => { const classes = rowStyles() - const { ID, NAME, IM_MAD, VM_MAD, VMS, CLUSTER } = value + const { ID, NAME, IM_MAD, VM_MAD, VMS, CLUSTER, TEMPLATE } = value const { percentCpuUsed, @@ -32,7 +32,7 @@ const Row = ({ value, ...props }) => {
- {NAME} + {TEMPLATE?.NAME ?? NAME} {labels.map(label => ( @@ -41,11 +41,11 @@ const Row = ({ value, ...props }) => {
{`#${ID}`} - + {` ${CLUSTER}`} - + {` ${runningVms}`} diff --git a/src/fireedge/src/client/components/Tables/Images/columns.js b/src/fireedge/src/client/components/Tables/Images/columns.js index 42d3a31988..ae2e7b6cd2 100644 --- a/src/fireedge/src/client/components/Tables/Images/columns.js +++ b/src/fireedge/src/client/components/Tables/Images/columns.js @@ -1,11 +1,10 @@ export default [ - { Header: '', accessor: 'ID' }, - { Header: '', accessor: 'NAME' }, - { Header: '', accessor: 'UNAME' }, - { Header: '', accessor: 'GNAME' }, - { Header: '', accessor: 'STATE' }, - { Header: '', accessor: 'TYPE' }, - { Header: '', accessor: 'DISK_TYPE' }, - { Header: '', accessor: 'DATASTORE_ID' }, - { Header: '', accessor: 'DATASTORE' } + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', accessor: 'NAME' }, + { Header: 'Owner', accessor: 'UNAME' }, + { Header: 'Group', accessor: 'GNAME' }, + { Header: 'State', accessor: 'STATE' }, + { Header: 'Type', accessor: 'TYPE' }, + { Header: 'Disk Type', accessor: 'DISK_TYPE' }, + { Header: 'Datastore', accessor: 'DATASTORE' } ] diff --git a/src/fireedge/src/client/components/Tables/Images/row.js b/src/fireedge/src/client/components/Tables/Images/row.js index c36a6154f0..e0e563a8d6 100644 --- a/src/fireedge/src/client/components/Tables/Images/row.js +++ b/src/fireedge/src/client/components/Tables/Images/row.js @@ -45,19 +45,19 @@ const Row = ({ value, ...props }) => { {`#${ID} ${timeAgo}`} - + {` ${UNAME}`} - + {` ${GNAME}`} - + {` ${DATASTORE}`} - + {` ${RUNNING_VMS} / ${usedByVms}`} diff --git a/src/fireedge/src/client/components/Tables/MarketplaceApps/columns.js b/src/fireedge/src/client/components/Tables/MarketplaceApps/columns.js index 2778e21299..1e31800304 100644 --- a/src/fireedge/src/client/components/Tables/MarketplaceApps/columns.js +++ b/src/fireedge/src/client/components/Tables/MarketplaceApps/columns.js @@ -1,12 +1,12 @@ export default [ - { Header: '', accessor: 'ID' }, - { Header: '', accessor: 'NAME' }, - { Header: '', accessor: 'UNAME' }, - { Header: '', accessor: 'GNAME' }, - { Header: '', accessor: 'REGTIME' }, - { Header: '', accessor: 'MARKETPLACE' }, - { Header: '', accessor: 'STATE' }, - { Header: '', accessor: 'TYPE' }, - { Header: '', accessor: 'ZONE_ID' }, - { Header: '', accessor: 'SIZE' } + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', accessor: 'NAME' }, + { Header: 'Owner', accessor: 'UNAME' }, + { Header: 'Group', accessor: 'GNAME' }, + { Header: 'State', accessor: 'STATE' }, + { Header: 'Type', accessor: 'TYPE' }, + { Header: 'Registration Time', accessor: 'REGTIME' }, + { Header: 'Marketplace', accessor: 'MARKETPLACE' }, + { Header: 'Zone ID', accessor: 'ZONE_ID' }, + { Header: 'Size', accessor: 'SIZE' } ] diff --git a/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js b/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js index f53e7ded64..50da07f12b 100644 --- a/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js +++ b/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js @@ -38,15 +38,15 @@ const Row = ({ value, ...props }) => { {`#${ID} ${timeAgo}`} - + {` ${UNAME}`} - + {` ${GNAME}`} - + {` ${MARKETPLACE}`} diff --git a/src/fireedge/src/client/components/Tables/Marketplaces/columns.js b/src/fireedge/src/client/components/Tables/Marketplaces/columns.js index 7a66cf99a4..e8a10a20d9 100644 --- a/src/fireedge/src/client/components/Tables/Marketplaces/columns.js +++ b/src/fireedge/src/client/components/Tables/Marketplaces/columns.js @@ -1,9 +1,15 @@ +const getNumberOfResources = resources => [resources?.ID ?? []].flat().length || 0 + export default [ - { Header: '', accessor: 'ID' }, - { Header: '', accessor: 'NAME' }, - { Header: '', accessor: 'UNAME' }, - { Header: '', accessor: 'GNAME' }, - { Header: '', accessor: 'MARKET_MAD' }, - { Header: '', accessor: 'ZONE_ID' }, - { Header: '', accessor: 'MARKETPLACEAPPS' } + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', accessor: 'NAME' }, + { Header: 'Owner', accessor: 'UNAME' }, + { Header: 'Group', accessor: 'GNAME' }, + { Header: 'Market', accessor: 'MARKET_MAD' }, + { Header: 'Zone ID', accessor: 'ZONE_ID' }, + { + Header: 'Number of Apps', + id: 'MARKETPLACEAPPS', + accessor: row => getNumberOfResources(row?.MARKETPLACEAPPS) + } ] diff --git a/src/fireedge/src/client/components/Tables/Marketplaces/row.js b/src/fireedge/src/client/components/Tables/Marketplaces/row.js index 139b9452b8..35d16b5360 100644 --- a/src/fireedge/src/client/components/Tables/Marketplaces/row.js +++ b/src/fireedge/src/client/components/Tables/Marketplaces/row.js @@ -1,7 +1,7 @@ import * as React from 'react' import PropTypes from 'prop-types' -import { User, Group } from 'iconoir-react' +import { User, Group, CloudDownload } from 'iconoir-react' import { Typography } from '@material-ui/core' import { StatusCircle, LinearProgressWithLabel, StatusChip } from 'client/components/Status' @@ -32,16 +32,16 @@ const Row = ({ value, ...props }) => {
{`#${ID}`} - + {` ${UNAME}`} - + {` ${GNAME}`} - - + + {` ${apps}`}
diff --git a/src/fireedge/src/client/components/Tables/Virtualized/toolbar.js b/src/fireedge/src/client/components/Tables/Virtualized/toolbar.js index 688393434c..bf5879c8cf 100644 --- a/src/fireedge/src/client/components/Tables/Virtualized/toolbar.js +++ b/src/fireedge/src/client/components/Tables/Virtualized/toolbar.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import { makeStyles, Button } from '@material-ui/core' import { Filter as FilterIcon } from 'iconoir-react' -// import GlobalFilter from 'client/components/Table/Filters/GlobalFilter' +import GlobalFilter from 'client/components/Table/Filters/GlobalFilter' const useToolbarStyles = makeStyles(theme => ({ filterWrapper: { @@ -24,9 +24,9 @@ const Toolbar = ({ useTableProps }) => { const classes = useToolbarStyles() /** @type {import('react-table').UseGlobalFiltersInstanceProps} */ - // const { preGlobalFilteredRows, setGlobalFilter, state } = useTableProps + const { preGlobalFilteredRows, setGlobalFilter, state } = useTableProps - // const { selectedRowIds, globalFilter } = state + const { globalFilter } = state // const numSelected = Object.keys(selectedRowIds).length return ( @@ -38,7 +38,12 @@ const Toolbar = ({ useTableProps }) => { > Filters - No filters selected + + {/* No filters selected */}
) diff --git a/src/fireedge/src/client/components/Tables/Vms/columns.js b/src/fireedge/src/client/components/Tables/Vms/columns.js index 4528662152..24eaf69b3b 100644 --- a/src/fireedge/src/client/components/Tables/Vms/columns.js +++ b/src/fireedge/src/client/components/Tables/Vms/columns.js @@ -1,8 +1,22 @@ +import * as VirtualMachineModel from 'client/models/VirtualMachine' + export default [ - { Header: '', accessor: 'ID' }, - { Header: '', accessor: 'NAME' }, - { Header: '', accessor: 'STATE' }, - { Header: '', accessor: 'LCM_STATE' }, - { Header: '', accessor: 'UID' }, - { Header: '', accessor: 'GID' } + { Header: 'ID', accessor: 'ID' }, + { Header: 'Name', accessor: 'NAME' }, + { Header: 'State', accessor: 'STATE' }, + { Header: 'LCM State', accessor: 'LCM_STATE' }, + { Header: 'Owner', accessor: 'UNAME' }, + { Header: 'Group', accessor: 'GNAME' }, + { Header: 'Start Time', accessor: 'STIME' }, + { Header: 'End Time', accessor: 'ETIME' }, + { + Header: 'Ips', + id: 'IPS', + accessor: row => VirtualMachineModel.getIps(row).join(',') + }, + { + Header: 'Hostname', + id: 'HOSTNAME', + accessor: row => VirtualMachineModel.getLastHistory(row)?.HOSTNAME + } ] diff --git a/src/fireedge/src/client/components/Tables/Vms/row.js b/src/fireedge/src/client/components/Tables/Vms/row.js index fe14da171f..57945c74c7 100644 --- a/src/fireedge/src/client/components/Tables/Vms/row.js +++ b/src/fireedge/src/client/components/Tables/Vms/row.js @@ -36,22 +36,22 @@ const Row = ({ value, ...props }) => { {`#${ID} ${timeAgo}`} - + {` ${UNAME}`} - + {` ${GNAME}`} - + {` ${HOSTNAME}`}
- +
) diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index 8b17c8b98c..16775a9af1 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -3,6 +3,8 @@ module.exports = { Back: 'Back', Previous: 'Previous', Next: 'Next', + SortBy: 'Sort by', + Filter: 'Filter', /* actions */ Accept: 'Accept',