Skip to content

Commit 663bf09

Browse files
vichanssonjloboescalona2MiguelERuizvickmpaaizel1
authored andcommitted
M #-: Design System Beta Fixes (#4323)
Signed-off-by: Victor Hansson <vhansson@opennebula.io> Co-authored-by: Jorge Miguel Lobo Escalona <jlobo@opennebula.io> Co-authored-by: Miguel E. Ruiz <mruiz@opennebula.io> Co-authored-by: Victor Palma <vpalma@opennebula.io> Co-authored-by: Alejandro <aaizel@opennebula.io> Co-authored-by: David <dcarracedo@opennebula.io> (cherry picked from commit c859cfb)
1 parent 99a365a commit 663bf09

299 files changed

Lines changed: 4869 additions & 2553 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/fireedge/etc/sunstone/tab-manifest.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
- title: Create VR Template
7777
path: /vrouter-template/create
7878
Component: CreateVrTemplate
79+
- title: Update VR Template
80+
path: /vrouter-template/update
81+
Component: CreateVrTemplate
7982
- title: VR Template
8083
path: /vrouter-template/:id
8184
Component: VrTemplateDetail

src/fireedge/etc/sunstone/views/cloud/dashboard-tab.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ cards:
1111
order: 10
1212
size: full
1313
to: true
14-
- id: host-cpu-chart
14+
- id: cpu-chart
1515
order: 20
1616
size: half
1717
to: false
18-
- id: host-memory-chart
18+
- id: memory-chart
1919
order: 30
2020
size: half
2121
to: false

src/fireedge/src/client/router/index.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,39 @@ const appendResourceToLastBreadcrumb = (breadcrumbs, state) => {
8282
)
8383
}
8484

85+
const normalizeRoutePath = (path = '') => {
86+
const normalized = `/${String(path).replace(/^\/+|\/+$/g, '')}`
87+
88+
return normalized === '/' ? normalized : normalized.replace(/\/+$/g, '')
89+
}
90+
91+
const getEndpointPaths = (endpoints = []) => {
92+
const paths = []
93+
const collect = (route) => {
94+
if (route.path) paths.push(route.path)
95+
route.routes?.forEach(collect)
96+
}
97+
98+
endpoints.forEach(collect)
99+
100+
return paths
101+
}
102+
103+
const getExactResourceActionRoutePath = (paths = [], pathname = '') => {
104+
const basePath = normalizeRoutePath(pathname)
105+
const getActionPath = (action) =>
106+
`${basePath === '/' ? '' : basePath}/${action}`
107+
const actionPaths = ['create', 'instantiate'].map(getActionPath)
108+
109+
return (
110+
actionPaths
111+
.map((actionPath) =>
112+
paths.find((path) => normalizeRoutePath(path) === actionPath)
113+
)
114+
.find(Boolean) ?? null
115+
)
116+
}
117+
85118
/**
86119
* @param {object} props - Props
87120
* @param {string} props.redirectWhenAuth
@@ -96,6 +129,7 @@ const Router = ({ redirectWhenAuth, endpoints }) => {
96129
() => buildBreadcrumbMap(endpoints),
97130
[endpoints]
98131
)
132+
const endpointPaths = useMemo(() => getEndpointPaths(endpoints), [endpoints])
99133

100134
const { setBreadcrumbs, setResourceCreatePath } = useFunctionalityApi()
101135

@@ -105,10 +139,13 @@ const Router = ({ redirectWhenAuth, endpoints }) => {
105139
state
106140
)
107141
setBreadcrumbs(breadCrumbs)
108-
const createPath = getBreadcrumbs(`${pathname}/create`)?.at(-1) ?? null
142+
const actionPath = getExactResourceActionRoutePath(endpointPaths, pathname)
143+
const createPath = actionPath
144+
? getBreadcrumbs(actionPath)?.at(-1) ?? null
145+
: null
109146
const isSupportPath = pathname === PATH.SUPPORT
110147
setResourceCreatePath(isSupportPath && !supportUser ? null : createPath)
111-
}, [pathname, state, supportUser])
148+
}, [endpointPaths, getBreadcrumbs, pathname, state, supportUser])
112149

113150
return (
114151
<TransitionGroup>

src/fireedge/src/modules/componentsv2/composed/Cards/CardBlock/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const CardBlock = forwardRef(
6262
(
6363
{
6464
actions,
65+
dataCy,
6566
isRemoveCheckbox = false,
6667
isSelectable = true,
6768
isSelected = false,
@@ -79,6 +80,7 @@ export const CardBlock = forwardRef(
7980
isRemoveCheckbox={!isSelectable || isRemoveCheckbox}
8081
isSelected={isSelected}
8182
onClick={isSelectable ? onClick : undefined}
83+
dataCy={dataCy}
8284
sx={[
8385
(theme) =>
8486
getStyles({
@@ -94,6 +96,7 @@ export const CardBlock = forwardRef(
9496
{showActions && (
9597
<Box
9698
className="card-block-actions"
99+
data-cy={dataCy ? `${dataCy}-actions` : undefined}
97100
onClick={(event) => event.stopPropagation()}
98101
>
99102
{renderActions(actions)}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* ------------------------------------------------------------------------- *
2+
* Copyright 2002-2026, OpenNebula Project, OpenNebula Systems *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
5+
* not use this file except in compliance with the License. You may obtain *
6+
* a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
* ------------------------------------------------------------------------- */
16+
17+
import { Component, forwardRef } from 'react'
18+
import PropTypes from 'prop-types'
19+
import { Box } from '@mui/material'
20+
import {
21+
Cpu,
22+
ElectronicsChip,
23+
HardDrive,
24+
Network,
25+
Check,
26+
Copy,
27+
} from 'iconoir-react'
28+
import { T } from '@ConstantsModule'
29+
import { useClipboard } from '@HooksModule'
30+
import { useTranslation } from '@ProvidersModule'
31+
import { TagList } from '@modules/componentsv2/primitives/Tags/List'
32+
import { getStyles } from '@modules/componentsv2/composed/Cards/Default/slots/capacity/styles'
33+
34+
const CAPACITY_ITEMS = [
35+
{ Icon: Cpu, label: T.CPU, valueKey: 'cpu' },
36+
{ Icon: ElectronicsChip, label: T.Memory, valueKey: 'memory' },
37+
{ Icon: HardDrive, label: T.DiskSize, valueKey: 'disk' },
38+
]
39+
40+
/**
41+
* Displays the CPU, memory, disk capacity and IP values of a resource card.
42+
*
43+
* @param {object} props - Component properties
44+
* @param {*} props.cpu - CPU capacity value
45+
* @param {*} props.memory - Memory capacity value
46+
* @param {*} props.disk - Total disk capacity value
47+
* @param {string[]} props.ips - IP addresses to display
48+
* @param {object} ref - Forwarded reference
49+
* @returns {Component} Capacity card slot
50+
*/
51+
export const CapacitySlot = forwardRef(
52+
({ cpu, memory, disk, ips = [] }, ref) => {
53+
const { translate } = useTranslation()
54+
const { copy, isCopied } = useClipboard()
55+
const values = { cpu, memory, disk }
56+
57+
return (
58+
<Box sx={(theme) => getStyles({ theme })} ref={ref}>
59+
{CAPACITY_ITEMS.map(({ Icon, label, valueKey }) => (
60+
<Box key={valueKey} className="capacity-item">
61+
<Icon className="capacity-icon" />
62+
<span className="capacity-label">{`${translate(label)}:`}</span>
63+
<span className="capacity-value">{values[valueKey] ?? '-'}</span>
64+
</Box>
65+
))}
66+
<Box
67+
className="capacity-item"
68+
onClick={(event) => event.stopPropagation()}
69+
>
70+
<Network className="capacity-icon" />
71+
<span className="capacity-label">{`${translate(T.IP)}:`}</span>
72+
{ips.length > 0 ? (
73+
<TagList
74+
max={1}
75+
tags={ips.map((ip) => ({
76+
title: ip,
77+
endIcon: isCopied(ip) ? <Check /> : <Copy />,
78+
onClick: (event) => {
79+
event.stopPropagation()
80+
copy(ip)
81+
},
82+
}))}
83+
/>
84+
) : (
85+
<span className="capacity-value">-</span>
86+
)}
87+
</Box>
88+
</Box>
89+
)
90+
}
91+
)
92+
93+
CapacitySlot.propTypes = {
94+
cpu: PropTypes.node,
95+
memory: PropTypes.node,
96+
disk: PropTypes.node,
97+
ips: PropTypes.arrayOf(PropTypes.string),
98+
}
99+
100+
CapacitySlot.displayName = 'CapacitySlot'
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* ------------------------------------------------------------------------- *
2+
* Copyright 2002-2026, OpenNebula Project, OpenNebula Systems *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
5+
* not use this file except in compliance with the License. You may obtain *
6+
* a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
* ------------------------------------------------------------------------- */
16+
17+
/**
18+
* @param {object} root0 - Parameters
19+
* @param {object} root0.theme - Current theme
20+
* @returns {object} Slot styles
21+
*/
22+
export const getStyles = ({ theme }) => ({
23+
display: 'flex',
24+
flexWrap: 'wrap',
25+
alignItems: 'center',
26+
gap: `${theme.scale[400]}px`,
27+
maxWidth: '100%',
28+
29+
'& .capacity-item': {
30+
display: 'inline-flex',
31+
alignItems: 'center',
32+
gap: `${theme.scale[100]}px`,
33+
minWidth: 0,
34+
whiteSpace: 'nowrap',
35+
},
36+
37+
'& .capacity-icon': {
38+
flexShrink: 0,
39+
width: `${theme.scale[500]}px`,
40+
height: `${theme.scale[500]}px`,
41+
color: 'icon.primary',
42+
},
43+
44+
'& .capacity-label, & .capacity-value': {
45+
fontFamily: 'Inter',
46+
fontStyle: 'normal',
47+
fontSize: {
48+
xs: theme.fontSize.body.caption.mobile,
49+
sm: theme.fontSize.body.caption.tablet,
50+
md: theme.fontSize.body.caption.desktop,
51+
},
52+
lineHeight: {
53+
xs: theme.lineHeight.body.caption.mobile,
54+
sm: theme.lineHeight.body.caption.tablet,
55+
md: theme.lineHeight.body.caption.desktop,
56+
},
57+
},
58+
59+
'& .capacity-label': {
60+
color: 'text.body',
61+
fontWeight: theme.typography.fontWeightMedium,
62+
},
63+
64+
'& .capacity-value': {
65+
color: 'text.headings',
66+
fontWeight: {
67+
xs: theme.fontWeight.heading.h6.mobile,
68+
sm: theme.fontWeight.heading.h6.tablet,
69+
md: theme.fontWeight.heading.h6.desktop,
70+
},
71+
},
72+
})

src/fireedge/src/modules/componentsv2/composed/Cards/Default/slots/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License. *
1515
* ------------------------------------------------------------------------- */
1616

17+
export * from '@modules/componentsv2/composed/Cards/Default/slots/capacity'
1718
export * from '@modules/componentsv2/composed/Cards/Default/slots/label'
1819
export * from '@modules/componentsv2/composed/Cards/Default/slots/metadata'
1920
export * from '@modules/componentsv2/composed/Cards/Default/slots/ownership'

src/fireedge/src/modules/componentsv2/composed/Cards/Default/slots/title/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License. *
1515
* ------------------------------------------------------------------------- */
1616

17-
import { forwardRef, Component } from 'react'
17+
import { forwardRef, Component, ReactNode } from 'react'
1818
import PropTypes from 'prop-types'
1919
import { Box } from '@mui/material'
2020
import { getStyles } from '@modules/componentsv2/composed/Cards/Default/slots/title/styles'
@@ -25,7 +25,7 @@ import { StatusTag } from '@modules/componentsv2/composed/Status'
2525
* TitleSlot component.
2626
*
2727
* @param {object} root0 - Params
28-
* @param {string} root0.title - Title text
28+
* @param {ReactNode} root0.title - Title content
2929
* @param {string} root0.status - Badge status
3030
* @param {string} root0.statusName - Status label
3131
* @returns {Component} - TextField component
@@ -52,7 +52,7 @@ export const TitleSlot = forwardRef(
5252
)
5353

5454
TitleSlot.propTypes = {
55-
title: PropTypes.string,
55+
title: PropTypes.node,
5656
status: PropTypes.string,
5757
statusName: PropTypes.string,
5858
}

src/fireedge/src/modules/componentsv2/composed/Cards/Default/styles.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export const getStyles = ({ theme, isSelected }) => {
7171
display: 'flex',
7272
width: '16px',
7373
height: '16px',
74+
marginTop: `${theme.scale[200]}px`,
7475
padding: 0,
7576
justifyContent: 'center',
7677
alignItems: 'center',

0 commit comments

Comments
 (0)