mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-22 18:50:08 +03:00
M #~: Minor fixes to Fireedge Sunstone (#2224)
(cherry picked from commit 75c5af9c7bf0c6a19444503916cf161da0764b7e)
This commit is contained in:
parent
11dbb1e418
commit
7b9b4711b0
@ -32,10 +32,12 @@ import { Translate } from 'client/components/HOC'
|
||||
import { T, SCHEMES } from 'client/constants'
|
||||
|
||||
const StepperStyled = styled(Stepper)(({ theme }) => ({
|
||||
backdropFilter: 'blur(3px)',
|
||||
position: 'sticky',
|
||||
top: -15,
|
||||
minHeight: 100,
|
||||
zIndex: theme.zIndex.mobileStepper,
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
}))
|
||||
|
||||
const ConnectorStyled = styled(StepConnector)(({ theme }) => ({
|
||||
@ -75,6 +77,16 @@ const StepIconStyled = styled(StepIcon)(({ theme }) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
const ButtonsWrapper = styled(Box)(({ theme }) => ({
|
||||
padding: '1em 0.5em',
|
||||
textAlign: 'end',
|
||||
backdropFilter: 'blur(3px)',
|
||||
position: 'sticky',
|
||||
top: 85,
|
||||
zIndex: theme.zIndex.mobileStepper + 1,
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
}))
|
||||
|
||||
const CustomStepper = ({
|
||||
steps,
|
||||
activeStep,
|
||||
@ -115,7 +127,7 @@ const CustomStepper = ({
|
||||
</Step>
|
||||
))}
|
||||
</StepperStyled>
|
||||
<Box marginY={2} textAlign="end">
|
||||
<ButtonsWrapper>
|
||||
<Button
|
||||
data-cy="stepper-back-button"
|
||||
disabled={disabledBack || isSubmitting}
|
||||
@ -132,7 +144,7 @@ const CustomStepper = ({
|
||||
size="small"
|
||||
label={<Translate word={activeStep === lastStep ? T.Finish : T.Next} />}
|
||||
/>
|
||||
</Box>
|
||||
</ButtonsWrapper>
|
||||
</>
|
||||
)
|
||||
|
||||
|
@ -28,10 +28,10 @@ const ENFORCE = {
|
||||
|
||||
const MEMORY = {
|
||||
name: 'MEMORY',
|
||||
label: T.Memory,
|
||||
label: [T.MemoryWithUnit, '(MB)'],
|
||||
tooltip: T.MemoryConcept,
|
||||
type: INPUT_TYPES.TEXT,
|
||||
htmlType: 'number',
|
||||
tooltip: T.MemoryConcept,
|
||||
validation: number()
|
||||
.required()
|
||||
.positive()
|
||||
@ -40,10 +40,10 @@ const MEMORY = {
|
||||
|
||||
const PHYSICAL_CPU = {
|
||||
name: 'CPU',
|
||||
label: T.PhysicalCpu,
|
||||
label: T.PhysicalCpuWithPercent,
|
||||
tooltip: T.CpuConcept,
|
||||
type: INPUT_TYPES.TEXT,
|
||||
htmlType: 'number',
|
||||
tooltip: T.CpuConcept,
|
||||
validation: number()
|
||||
.required()
|
||||
.positive()
|
||||
@ -52,10 +52,10 @@ const PHYSICAL_CPU = {
|
||||
|
||||
const VIRTUAL_CPU = {
|
||||
name: 'VCPU',
|
||||
label: T.VirtualCpu,
|
||||
label: T.VirtualCpuWithPercent,
|
||||
tooltip: T.VirtualCpuConcept,
|
||||
type: INPUT_TYPES.TEXT,
|
||||
htmlType: 'number',
|
||||
tooltip: T.VirtualCpuConcept,
|
||||
validation: number().default(() => undefined),
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ const commonValidation = number()
|
||||
/** @type {Field} Memory field */
|
||||
export const MEMORY = generateCapacityInput({
|
||||
name: 'MEMORY',
|
||||
label: T.Memory,
|
||||
label: [T.MemoryWithUnit, '(MB)'],
|
||||
tooltip: T.MemoryConcept,
|
||||
validation: commonValidation
|
||||
.integer()
|
||||
@ -70,7 +70,7 @@ export const MEMORY_FIELDS = [MEMORY, ...HR_MEMORY_FIELDS, ...MOD_MEMORY_FIELDS]
|
||||
/** @type {Field} Physical CPU field */
|
||||
export const PHYSICAL_CPU = generateCapacityInput({
|
||||
name: 'CPU',
|
||||
label: T.PhysicalCpu,
|
||||
label: T.PhysicalCpuWithPercent,
|
||||
tooltip: T.CpuConcept,
|
||||
validation: commonValidation.required(),
|
||||
})
|
||||
@ -88,7 +88,7 @@ export const CPU_FIELDS = [PHYSICAL_CPU, ...MOD_CPU_FIELDS]
|
||||
/** @type {Field} Virtual CPU field */
|
||||
export const VIRTUAL_CPU = generateCapacityInput({
|
||||
name: 'VCPU',
|
||||
label: T.VirtualCpu,
|
||||
label: T.VirtualCpuWithPercent,
|
||||
tooltip: T.VirtualCpuConcept,
|
||||
validation: commonValidation,
|
||||
})
|
||||
|
@ -267,6 +267,7 @@ export const generateCapacityInput = ({ validation, ...field }) => ({
|
||||
modificationType === list ? schema.oneOf(options) : schema
|
||||
),
|
||||
grid: { md: 3 },
|
||||
fieldProps: { min: 0 },
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -34,9 +34,17 @@ import {
|
||||
const { number, numberFloat, range, rangeFloat } = USER_INPUT_TYPES
|
||||
|
||||
const TRANSLATES = {
|
||||
MEMORY: { name: 'MEMORY', label: T.Memory, tooltip: T.MemoryConcept },
|
||||
CPU: { name: 'CPU', label: T.PhysicalCpu, tooltip: T.CpuConcept },
|
||||
VCPU: { name: 'VCPU', label: T.VirtualCpu, tooltip: T.VirtualCpuConcept },
|
||||
MEMORY: {
|
||||
name: 'MEMORY',
|
||||
label: [T.MemoryWithUnit, '(MB)'],
|
||||
tooltip: T.MemoryConcept,
|
||||
},
|
||||
CPU: { name: 'CPU', label: T.PhysicalCpuWithPercent, tooltip: T.CpuConcept },
|
||||
VCPU: {
|
||||
name: 'VCPU',
|
||||
label: T.VirtualCpuWithPercent,
|
||||
tooltip: T.VirtualCpuConcept,
|
||||
},
|
||||
}
|
||||
|
||||
const valueLabelFormat = (value) => prettyBytes(value, 'MB')
|
||||
|
@ -20,7 +20,7 @@ import PropTypes from 'prop-types'
|
||||
import clsx from 'clsx'
|
||||
import InfoEmpty from 'iconoir-react/dist/InfoEmpty'
|
||||
import RemoveIcon from 'iconoir-react/dist/RemoveSquare'
|
||||
import { Box } from '@mui/material'
|
||||
import { Box, Chip } from '@mui/material'
|
||||
import {
|
||||
useGlobalFilter,
|
||||
useFilters,
|
||||
@ -184,6 +184,8 @@ const EnhancedTable = ({
|
||||
[disableGlobalLabel]
|
||||
)
|
||||
|
||||
const canResetFilter = state.filters?.length > 0 || state.sortBy?.length > 0
|
||||
|
||||
return (
|
||||
<Box
|
||||
{...getTableProps()}
|
||||
@ -244,18 +246,17 @@ const EnhancedTable = ({
|
||||
</div>
|
||||
|
||||
{/* RESET FILTERS */}
|
||||
<Box
|
||||
visibility={
|
||||
state.filters?.length > 0 || state.sortBy?.length > 0
|
||||
? 'visible'
|
||||
: 'hidden'
|
||||
}
|
||||
>
|
||||
<span className={styles.resetFilters} onClick={handleResetFilters}>
|
||||
<RemoveIcon />
|
||||
<Translate word={T.ResetFilters} />
|
||||
</span>
|
||||
</Box>
|
||||
<Chip
|
||||
label={<Translate word={T.ResetFilters} />}
|
||||
onClick={canResetFilter ? handleResetFilters : undefined}
|
||||
icon={<RemoveIcon />}
|
||||
sx={{
|
||||
visibility: canResetFilter ? 'visible' : 'hidden',
|
||||
width: 'fit-content',
|
||||
padding: '0.75em',
|
||||
marginBottom: '0.5em',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className={clsx(styles.body, classes.body)}>
|
||||
{/* NO DATA MESSAGE */}
|
||||
|
@ -55,16 +55,6 @@ export default makeStyles(({ palette, typography, breakpoints }) => ({
|
||||
justifySelf: 'end',
|
||||
gap: '1em',
|
||||
},
|
||||
resetFilters: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5em',
|
||||
cursor: 'pointer',
|
||||
marginBottom: '1em',
|
||||
'&:hover': {
|
||||
color: palette.secondary.dark,
|
||||
},
|
||||
},
|
||||
body: {
|
||||
overflow: 'auto',
|
||||
display: 'grid',
|
||||
|
@ -16,14 +16,12 @@
|
||||
import { memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {
|
||||
Trash,
|
||||
Edit,
|
||||
UndoAction,
|
||||
SaveActionFloppy,
|
||||
Camera,
|
||||
Expand,
|
||||
} from 'iconoir-react'
|
||||
import Trash from 'iconoir-react/dist/Trash'
|
||||
import Edit from 'iconoir-react/dist/Edit'
|
||||
import UndoAction from 'iconoir-react/dist/UndoAction'
|
||||
import SaveActionFloppy from 'iconoir-react/dist/SaveActionFloppy'
|
||||
import Camera from 'iconoir-react/dist/Camera'
|
||||
import Expand from 'iconoir-react/dist/ExpandLines'
|
||||
|
||||
import {
|
||||
useAttachDiskMutation,
|
||||
|
@ -465,11 +465,14 @@ module.exports = {
|
||||
/* VM schema - capacity */
|
||||
Capacity: 'Capacity',
|
||||
PhysicalCpu: 'Physical CPU',
|
||||
PhysicalCpuWithPercent: 'Physical CPU (%)',
|
||||
VirtualCpu: 'Virtual CPU',
|
||||
VirtualCpuWithPercent: 'Virtual CPU (%)',
|
||||
VirtualCores: 'Virtual Cores',
|
||||
Cores: 'Cores',
|
||||
Sockets: 'Sockets',
|
||||
Memory: 'Memory',
|
||||
MemoryWithUnit: 'Memory %s',
|
||||
Cost: 'Cost',
|
||||
CostEachMonth: '%s / month',
|
||||
CostCpu: 'Cost / CPU',
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetClustersQuery,
|
||||
useUpdateClusterMutation,
|
||||
} from 'client/features/OneApi/cluster'
|
||||
import { ClustersTable } from 'client/components/Tables'
|
||||
import ClusterTabs from 'client/components/Tabs/Cluster'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, Cluster } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Clusters() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<ClustersTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<ClustersTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateClusterMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Clusters() {
|
||||
<InfoTabs
|
||||
cluster={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Clusters() {
|
||||
*
|
||||
* @param {Cluster} cluster - Cluster to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Cluster
|
||||
* @param {Function} [unselect] - Function to unselect a Cluster
|
||||
* @returns {ReactElement} Cluster details
|
||||
*/
|
||||
const InfoTabs = memo(({ cluster, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${cluster.ID} | ${cluster.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ cluster, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetClustersQuery()
|
||||
const id = lazyData?.ID ?? cluster.ID
|
||||
const name = lazyData?.NAME ?? cluster.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<ClusterTabs id={id} />
|
||||
</Stack>
|
||||
<ClusterTabs id={cluster.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
cluster: PropTypes.object.isRequired,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetDatastoreQuery,
|
||||
useUpdateDatastoreMutation,
|
||||
} from 'client/features/OneApi/datastore'
|
||||
import { DatastoresTable } from 'client/components/Tables'
|
||||
import DatastoreTabs from 'client/components/Tabs/Datastore'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, Datastore } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Datastores() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<DatastoresTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<DatastoresTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateDatastoreMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Datastores() {
|
||||
<InfoTabs
|
||||
datastore={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Datastores() {
|
||||
*
|
||||
* @param {Datastore} datastore - Datastore to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Datastore
|
||||
* @param {Function} [unselect] - Function to unselect a Datastore
|
||||
* @returns {ReactElement} Datastore details
|
||||
*/
|
||||
const InfoTabs = memo(({ datastore, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${datastore.ID} | ${datastore.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ datastore, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetDatastoreQuery()
|
||||
const id = lazyData?.ID ?? datastore.ID
|
||||
const name = lazyData?.NAME ?? datastore.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<DatastoreTabs id={id} />
|
||||
</Stack>
|
||||
<DatastoreTabs id={datastore.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
datastore: PropTypes.object.isRequired,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetGroupQuery,
|
||||
useUpdateGroupMutation,
|
||||
} from 'client/features/OneApi/group'
|
||||
import { GroupsTable } from 'client/components/Tables'
|
||||
import GroupTabs from 'client/components/Tabs/Group'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, Group } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Groups() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<GroupsTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<GroupsTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateGroupMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Groups() {
|
||||
<InfoTabs
|
||||
group={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Groups() {
|
||||
*
|
||||
* @param {Group} group - Group to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Group
|
||||
* @param {Function} [unselect] - Function to unselect a Group
|
||||
* @returns {ReactElement} Group details
|
||||
*/
|
||||
const InfoTabs = memo(({ group, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${group.ID} | ${group.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ group, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetGroupQuery()
|
||||
const id = lazyData?.ID ?? group.ID
|
||||
const name = lazyData?.NAME ?? group.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<GroupTabs id={id} />
|
||||
</Stack>
|
||||
<GroupTabs id={group.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
group: PropTypes.object.isRequired,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -91,7 +91,12 @@ const InfoTabs = memo(({ host, gotoPage, unselect }) => {
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
@ -115,9 +120,7 @@ const InfoTabs = memo(({ host, gotoPage, unselect }) => {
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<HostTabs id={id} />
|
||||
</Stack>
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetImageQuery,
|
||||
useUpdateImageMutation,
|
||||
} from 'client/features/OneApi/image'
|
||||
import { ImagesTable } from 'client/components/Tables'
|
||||
import ImageTabs from 'client/components/Tabs/Image'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, Image } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Images() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<ImagesTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<ImagesTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateImageMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Images() {
|
||||
<InfoTabs
|
||||
image={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Images() {
|
||||
*
|
||||
* @param {Image} image - Image to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of an Image
|
||||
* @param {Function} [unselect] - Function to unselect a Image
|
||||
* @returns {ReactElement} Image details
|
||||
*/
|
||||
const InfoTabs = memo(({ image, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${image.ID} | ${image.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ image, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetImageQuery()
|
||||
const id = lazyData?.ID ?? image.ID
|
||||
const name = lazyData?.NAME ?? image.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<ImageTabs id={id} />
|
||||
</Stack>
|
||||
<ImageTabs id={image.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
image: PropTypes.object.isRequired,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -85,7 +85,7 @@ function MarketplaceApps() {
|
||||
* @returns {ReactElement} Marketplace App details
|
||||
*/
|
||||
const InfoTabs = memo(({ app, gotoPage, unselect }) => {
|
||||
const [getApp, queryState] = useLazyGetMarketplaceAppQuery()
|
||||
const [get, queryState] = useLazyGetMarketplaceAppQuery()
|
||||
const { data: lazyData, isFetching } = queryState
|
||||
|
||||
const id = lazyData?.ID ?? app.ID
|
||||
@ -93,13 +93,18 @@ const InfoTabs = memo(({ app, gotoPage, unselect }) => {
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => getApp({ id })}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
@ -117,9 +122,7 @@ const InfoTabs = memo(({ app, gotoPage, unselect }) => {
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<MarketplaceAppsTabs id={id} />
|
||||
</Stack>
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetMarketplaceQuery,
|
||||
useUpdateMarketplaceMutation,
|
||||
} from 'client/features/OneApi/marketplace'
|
||||
import { MarketplacesTable } from 'client/components/Tables'
|
||||
import MarketplaceTabs from 'client/components/Tabs/Marketplace'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, Marketplace } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Marketplaces() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<MarketplacesTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<MarketplacesTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateMarketplaceMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Marketplaces() {
|
||||
<InfoTabs
|
||||
market={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Marketplaces() {
|
||||
*
|
||||
* @param {Marketplace} market - Marketplace to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Marketplace
|
||||
* @param {Function} [unselect] - Function to unselect a Marketplace
|
||||
* @returns {ReactElement} Marketplace details
|
||||
*/
|
||||
const InfoTabs = memo(({ market, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${market.ID} | ${market.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ market, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetMarketplaceQuery()
|
||||
const id = lazyData?.ID ?? market.ID
|
||||
const name = lazyData?.NAME ?? market.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<MarketplaceTabs id={id} />
|
||||
</Stack>
|
||||
<MarketplaceTabs id={market.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
market: PropTypes.object.isRequired,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -15,15 +15,18 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import serviceTemplateApi from 'client/features/OneApi/serviceTemplate'
|
||||
import { useLazyGetServiceTemplateQuery } from 'client/features/OneApi/serviceTemplate'
|
||||
import { ServiceTemplatesTable } from 'client/components/Tables'
|
||||
import ServiceTemplateTabs from 'client/components/Tabs/ServiceTemplate'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T } from 'client/constants'
|
||||
|
||||
@ -54,6 +57,7 @@ function ServiceTemplates() {
|
||||
<InfoTabs
|
||||
id={selectedRows[0]?.original?.ID}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,28 +71,48 @@ function ServiceTemplates() {
|
||||
/**
|
||||
* Displays details of a Service Template.
|
||||
*
|
||||
* @param {string} id - Service Template id to display
|
||||
* @param {object} template - Service Template to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Service Template
|
||||
* @param {Function} [unselect] - Function to unselect a Service Template
|
||||
* @returns {ReactElement} Service Template details
|
||||
*/
|
||||
const InfoTabs = memo(({ id, gotoPage }) => {
|
||||
const template =
|
||||
serviceTemplateApi.endpoints.getServiceTemplates.useQueryState(undefined, {
|
||||
selectFromResult: ({ data = [] }) =>
|
||||
data.find((item) => +item.ID === +id),
|
||||
})
|
||||
const InfoTabs = memo(({ template, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetServiceTemplateQuery()
|
||||
const id = lazyData?.ID ?? template.ID
|
||||
const name = lazyData?.NAME ?? template.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${template.NAME}`}
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<ServiceTemplateTabs id={id} />
|
||||
</Stack>
|
||||
@ -96,8 +120,9 @@ const InfoTabs = memo(({ id, gotoPage }) => {
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
template: PropTypes.object,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -15,15 +15,18 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import serviceApi from 'client/features/OneApi/service'
|
||||
import { useLazyGetServiceQuery } from 'client/features/OneApi/service'
|
||||
import { ServicesTable } from 'client/components/Tables'
|
||||
import ServiceTabs from 'client/components/Tabs/Service'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T } from 'client/constants'
|
||||
|
||||
@ -54,6 +57,7 @@ function Services() {
|
||||
<InfoTabs
|
||||
id={selectedRows[0]?.original?.ID}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,26 +71,48 @@ function Services() {
|
||||
/**
|
||||
* Displays details of a Service.
|
||||
*
|
||||
* @param {string} id - Service id to display
|
||||
* @param {object} service - Service to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Service
|
||||
* @param {Function} [unselect] - Function to unselect a Service
|
||||
* @returns {ReactElement} Service details
|
||||
*/
|
||||
const InfoTabs = memo(({ id, gotoPage }) => {
|
||||
const template = serviceApi.endpoints.getServices.useQueryState(undefined, {
|
||||
selectFromResult: ({ data = [] }) => data.find((item) => +item.ID === +id),
|
||||
})
|
||||
const InfoTabs = memo(({ service, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetServiceQuery()
|
||||
const id = lazyData?.ID ?? service.ID
|
||||
const name = lazyData?.NAME ?? service.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${template.NAME}`}
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<ServiceTabs id={id} />
|
||||
</Stack>
|
||||
@ -94,8 +120,9 @@ const InfoTabs = memo(({ id, gotoPage }) => {
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
service: PropTypes.object,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetUserQuery,
|
||||
useUpdateUserMutation,
|
||||
} from 'client/features/OneApi/user'
|
||||
import { UsersTable } from 'client/components/Tables'
|
||||
import UserTabs from 'client/components/Tabs/User'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, User } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Users() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<UsersTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<UsersTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateUserMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Users() {
|
||||
<InfoTabs
|
||||
user={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Users() {
|
||||
*
|
||||
* @param {User} user - User to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of an User
|
||||
* @param {Function} [unselect] - Function to unselect a User
|
||||
* @returns {ReactElement} User details
|
||||
*/
|
||||
const InfoTabs = memo(({ user, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${user.ID} | ${user.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ user, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetUserQuery()
|
||||
const id = lazyData?.ID ?? user.ID
|
||||
const name = lazyData?.NAME ?? user.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<UserTabs id={id} />
|
||||
</Stack>
|
||||
<UserTabs id={user.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
user: PropTypes.object.isRequired,
|
||||
user: PropTypes.object,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetVNTemplateQuery,
|
||||
useUpdateVNTemplateMutation,
|
||||
} from 'client/features/OneApi/networkTemplate'
|
||||
import { VNetworkTemplatesTable } from 'client/components/Tables'
|
||||
import VNetworkTemplateTabs from 'client/components/Tabs/VNetworkTemplate'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, VNetworkTemplate } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function VNetworkTemplates() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<VNetworkTemplatesTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<VNetworkTemplatesTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateVNTemplateMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function VNetworkTemplates() {
|
||||
<InfoTabs
|
||||
vnTemplate={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function VNetworkTemplates() {
|
||||
*
|
||||
* @param {VNetworkTemplate} vnTemplate - VNet Template to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a VNet Template
|
||||
* @param {Function} [unselect] - Function to unselect
|
||||
* @returns {ReactElement} VNet Template details
|
||||
*/
|
||||
const InfoTabs = memo(({ vnTemplate, gotoPage }) => (
|
||||
<Stack overflow="auto" data-cy="detail">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${vnTemplate.ID} | ${vnTemplate.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ vnTemplate, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetVNTemplateQuery()
|
||||
const id = lazyData?.ID ?? vnTemplate.ID
|
||||
const name = lazyData?.NAME ?? vnTemplate.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<VNetworkTemplateTabs id={id} />
|
||||
</Stack>
|
||||
<VNetworkTemplateTabs id={vnTemplate.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
vnTemplate: PropTypes.object.isRequired,
|
||||
vnTemplate: PropTypes.object,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
@ -91,7 +91,12 @@ const InfoTabs = memo(({ vm, gotoPage, unselect }) => {
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
@ -115,9 +120,7 @@ const InfoTabs = memo(({ vm, gotoPage, unselect }) => {
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<VmTabs id={id} />
|
||||
</Stack>
|
||||
|
@ -91,7 +91,12 @@ const InfoTabs = memo(({ vnet, gotoPage, unselect }) => {
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
@ -115,9 +120,7 @@ const InfoTabs = memo(({ vnet, gotoPage, unselect }) => {
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<VNetworkTabs id={id} />
|
||||
</Stack>
|
||||
|
@ -89,7 +89,12 @@ const InfoTabs = memo(({ template, gotoPage, unselect }) => {
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
@ -113,9 +118,7 @@ const InfoTabs = memo(({ template, gotoPage, unselect }) => {
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<VmTemplateTabs id={id} />
|
||||
</Stack>
|
||||
|
@ -15,14 +15,21 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { ReactElement, useState, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { BookmarkEmpty } from 'iconoir-react'
|
||||
import { Typography, Box, Stack, Chip, IconButton } from '@mui/material'
|
||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||
import Cancel from 'iconoir-react/dist/Cancel'
|
||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
||||
import { Row } from 'react-table'
|
||||
|
||||
import {
|
||||
useLazyGetZoneQuery,
|
||||
useUpdateZoneMutation,
|
||||
} from 'client/features/OneApi/zone'
|
||||
import { ZonesTable } from 'client/components/Tables'
|
||||
import ZoneTabs from 'client/components/Tabs/Zone'
|
||||
import SplitPane from 'client/components/SplitPane'
|
||||
import MultipleTags from 'client/components/MultipleTags'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, Zone } from 'client/constants'
|
||||
|
||||
@ -41,7 +48,10 @@ function Zones() {
|
||||
<SplitPane gridTemplateRows="1fr auto 1fr">
|
||||
{({ getGridProps, GutterComponent }) => (
|
||||
<Box height={1} {...(hasSelectedRows && getGridProps())}>
|
||||
<ZonesTable onSelectedRowsChange={onSelectedRowsChange} />
|
||||
<ZonesTable
|
||||
onSelectedRowsChange={onSelectedRowsChange}
|
||||
useUpdateMutation={useUpdateZoneMutation}
|
||||
/>
|
||||
|
||||
{hasSelectedRows && (
|
||||
<>
|
||||
@ -52,6 +62,7 @@ function Zones() {
|
||||
<InfoTabs
|
||||
zone={selectedRows[0]?.original}
|
||||
gotoPage={selectedRows[0]?.gotoPage}
|
||||
unselect={() => selectedRows[0]?.toggleRowSelected(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@ -67,27 +78,56 @@ function Zones() {
|
||||
*
|
||||
* @param {Zone} zone - Zone to display
|
||||
* @param {Function} [gotoPage] - Function to navigate to a page of a Zone
|
||||
* @param {Function} [unselect] - Function to unselect
|
||||
* @returns {ReactElement} Zone details
|
||||
*/
|
||||
const InfoTabs = memo(({ zone, gotoPage }) => (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap>
|
||||
{`#${zone.ID} | ${zone.NAME}`}
|
||||
</Typography>
|
||||
{gotoPage && (
|
||||
<IconButton title={Tr(T.LocateOnTable)} onClick={gotoPage}>
|
||||
<BookmarkEmpty />
|
||||
</IconButton>
|
||||
)}
|
||||
const InfoTabs = memo(({ zone, gotoPage, unselect }) => {
|
||||
const [get, { data: lazyData, isFetching }] = useLazyGetZoneQuery()
|
||||
const id = lazyData?.ID ?? zone.ID
|
||||
const name = lazyData?.NAME ?? zone.NAME
|
||||
|
||||
return (
|
||||
<Stack overflow="auto">
|
||||
<Stack direction="row" alignItems="center" gap={1} mx={1} mb={1}>
|
||||
<Typography color="text.primary" noWrap flexGrow={1}>
|
||||
{`#${id} | ${name}`}
|
||||
</Typography>
|
||||
|
||||
{/* -- ACTIONS -- */}
|
||||
<SubmitButton
|
||||
data-cy="detail-refresh"
|
||||
icon={<RefreshDouble />}
|
||||
tooltip={Tr(T.Refresh)}
|
||||
isSubmitting={isFetching}
|
||||
onClick={() => get({ id })}
|
||||
/>
|
||||
{typeof gotoPage === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="locate-on-table"
|
||||
icon={<GotoIcon />}
|
||||
tooltip={Tr(T.LocateOnTable)}
|
||||
onClick={() => gotoPage()}
|
||||
/>
|
||||
)}
|
||||
{typeof unselect === 'function' && (
|
||||
<SubmitButton
|
||||
data-cy="unselect"
|
||||
icon={<Cancel />}
|
||||
tooltip={Tr(T.Close)}
|
||||
onClick={() => unselect()}
|
||||
/>
|
||||
)}
|
||||
{/* -- END ACTIONS -- */}
|
||||
</Stack>
|
||||
<ZoneTabs id={id} />
|
||||
</Stack>
|
||||
<ZoneTabs id={zone.ID} />
|
||||
</Stack>
|
||||
))
|
||||
)
|
||||
})
|
||||
|
||||
InfoTabs.propTypes = {
|
||||
zone: PropTypes.object.isRequired,
|
||||
zone: PropTypes.object,
|
||||
gotoPage: PropTypes.func,
|
||||
unselect: PropTypes.func,
|
||||
}
|
||||
|
||||
InfoTabs.displayName = 'InfoTabs'
|
||||
|
Loading…
x
Reference in New Issue
Block a user