diff --git a/src/fireedge/src/client/components/Cards/WavesCard.js b/src/fireedge/src/client/components/Cards/WavesCard.js
index f6fdd4f6f6..8813263824 100644
--- a/src/fireedge/src/client/components/Cards/WavesCard.js
+++ b/src/fireedge/src/client/components/Cards/WavesCard.js
@@ -16,93 +16,95 @@
import { memo } from 'react'
import PropTypes from 'prop-types'
-import clsx from 'clsx'
-import { Paper, Typography, lighten, darken } from '@mui/material'
-import makeStyles from '@mui/styles/makeStyles'
+import { styled, keyframes, lighten, darken } from '@mui/material'
+import Paper from '@mui/material/Paper'
+import Typography from '@mui/material/Typography'
-import { addOpacityToColor } from 'client/utils'
import { SCHEMES } from 'client/constants'
-const useStyles = makeStyles((theme) => {
+const Card = styled(Paper)(({ theme, bgcolor, onClick }) => {
const getBackgroundColor =
theme.palette.mode === SCHEMES.DARK ? darken : lighten
- const getContrastBackgroundColor =
- theme.palette.mode === SCHEMES.LIGHT ? darken : lighten
return {
- root: {
- padding: '2em',
- position: 'relative',
- overflow: 'hidden',
- backgroundColor: ({ bgColor }) => getBackgroundColor(bgColor, 0.3),
- [theme.breakpoints.only('xs')]: {
- display: 'flex',
- alignItems: 'baseline',
- gap: '1em',
+ padding: '2em',
+ position: 'relative',
+ overflow: 'hidden',
+ backgroundColor: getBackgroundColor(bgcolor, 0.3),
+ ...(onClick && {
+ '&:hover': {
+ backgroundColor: getBackgroundColor(bgcolor, 0.4),
+ boxShadow: theme.shadows[10],
+ cursor: 'pointer',
},
- },
- icon: {
- position: 'absolute',
- top: 0,
- right: 0,
- width: '100%',
- height: '100%',
- textAlign: 'end',
- '& > svg': {
- color: addOpacityToColor(theme.palette.common.white, 0.2),
- height: '100%',
- width: '30%',
- },
- },
- wave: {
- display: 'block',
- position: 'absolute',
- opacity: 0.4,
- top: '-5%',
- left: '50%',
- width: 220,
- height: 220,
- borderRadius: '43%',
- },
- wave1: {
- backgroundColor: ({ bgColor }) =>
- getContrastBackgroundColor(bgColor, 0.3),
- animation: '$drift 7s infinite linear',
- },
- wave2: {
- backgroundColor: ({ bgColor }) =>
- getContrastBackgroundColor(bgColor, 0.5),
- animation: '$drift 5s infinite linear',
- },
- '@keyframes drift': {
- from: { transform: 'rotate(0deg)' },
- to: { transform: 'rotate(360deg)' },
+ }),
+ [theme.breakpoints.only('xs')]: {
+ display: 'flex',
+ alignItems: 'baseline',
+ gap: '1em',
},
}
})
-const WavesCard = memo(
- ({ text, value, bgColor, icon: Icon }) => {
- const classes = useStyles({ bgColor })
-
- return (
-
-
- {text}
-
-
- {value}
-
-
-
- {Icon && (
-
-
-
- )}
-
- )
+const OverSizeIcon = styled('span')(({ theme }) => ({
+ position: 'absolute',
+ top: 0,
+ right: 0,
+ width: '100%',
+ height: '100%',
+ textAlign: 'end',
+ '& > svg': {
+ color: theme.palette.action.active,
+ height: '100%',
+ width: '30%',
},
+}))
+
+const drift = keyframes`
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+`
+
+const Wave = styled('span')(({ theme, bgcolor, duration = 1 }) => {
+ const getContrastBackgroundColor =
+ theme.palette.mode === SCHEMES.DARK ? lighten : darken
+
+ return {
+ display: 'block',
+ position: 'absolute',
+ opacity: 0.4,
+ top: '-5%',
+ left: '50%',
+ width: 220,
+ height: 220,
+ borderRadius: '43%',
+ backgroundColor: getContrastBackgroundColor(bgcolor, duration / 10),
+ animation: `${drift} ${duration}s infinite linear`,
+ }
+})
+
+const WavesCard = memo(
+ ({ text, value, bgColor, icon: Icon, onClick }) => (
+
+
+ {text}
+
+
+ {value}
+
+
+
+ {Icon && (
+
+
+
+ )}
+
+ ),
(prev, next) => prev.value === next.value
)
@@ -115,6 +117,7 @@ WavesCard.propTypes = {
]),
bgColor: PropTypes.string,
icon: PropTypes.any,
+ onClick: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
}
WavesCard.defaultProps = {
@@ -122,6 +125,7 @@ WavesCard.defaultProps = {
value: undefined,
bgColor: '#ffffff00',
icon: undefined,
+ onClick: undefined,
}
WavesCard.displayName = 'WavesCard'
diff --git a/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js b/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js
index e622c3138f..2e515f5b5c 100644
--- a/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js
+++ b/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
-import { memo, ReactElement } from 'react'
+import { memo, useMemo, ReactElement } from 'react'
import PropTypes from 'prop-types'
-import { Box, CircularProgress, Grid } from '@mui/material'
+import { useHistory } from 'react-router-dom'
+import { Container, Box, CircularProgress, Grid } from '@mui/material'
import {
ModernTv as VmsIcons,
List as TemplatesIcon,
@@ -23,19 +24,30 @@ import {
NetworkAlt as NetworkIcon,
} from 'iconoir-react'
-import { useAuth } from 'client/features/Auth'
+import { useAuth, useViews } from 'client/features/Auth'
import { useGetVmsQuery } from 'client/features/OneApi/vm'
import { useGetTemplatesQuery } from 'client/features/OneApi/vmTemplate'
import { useGetImagesQuery } from 'client/features/OneApi/image'
import { useGetVNetworksQuery } from 'client/features/OneApi/network'
+
import NumberEasing from 'client/components/NumberEasing'
import WavesCard from 'client/components/Cards/WavesCard'
import { stringToBoolean } from 'client/models/Helper'
-import { T } from 'client/constants'
+import { PATH } from 'client/apps/sunstone/routesOne'
+import { T, RESOURCE_NAMES } from 'client/constants'
+
+const { VM, VM_TEMPLATE, IMAGE, VNET } = RESOURCE_NAMES
/** @returns {ReactElement} Sunstone dashboard container */
function SunstoneDashboard() {
const { settings: { DISABLE_ANIMATIONS } = {} } = useAuth()
+ const { view, hasAccessToResource } = useViews()
+ const { push: goTo } = useHistory()
+
+ const vmAccess = useMemo(() => hasAccessToResource(VM), [view])
+ const templateAccess = useMemo(() => hasAccessToResource(VM_TEMPLATE), [view])
+ const imageAccess = useMemo(() => hasAccessToResource(IMAGE), [view])
+ const vnetAccess = useMemo(() => hasAccessToResource(VNET), [view])
return (
-
-
-
-
-
-
-
+
+
+ goTo(PATH.INSTANCE.VMS.LIST))}
+ />
+ goTo(PATH.TEMPLATE.VMS.LIST))}
+ />
+ goTo(PATH.STORAGE.IMAGES.LIST))}
+ />
+ goTo(PATH.NETWORK.VNETS.LIST))}
+ />
+
+
)
}
diff --git a/src/fireedge/src/client/features/Auth/hooks.js b/src/fireedge/src/client/features/Auth/hooks.js
index c7178caceb..9a71b91798 100644
--- a/src/fireedge/src/client/features/Auth/hooks.js
+++ b/src/fireedge/src/client/features/Auth/hooks.js
@@ -125,6 +125,17 @@ export const useViews = () => {
[view]
)
+ /**
+ * Check if user has a view for a resource.
+ *
+ * @param {RESOURCE_NAMES} resourceName - Name of resource
+ * @returns {boolean} Returns true if user has a view for a resource
+ */
+ const hasAccessToResource = useCallback(
+ (resourceName) => !!getResourceView(resourceName),
+ [view]
+ )
+
return useMemo(
() => ({
...Object.values(RESOURCE_NAMES).reduce(
@@ -134,6 +145,7 @@ export const useViews = () => {
}),
{}
),
+ hasAccessToResource,
getResourceView,
views,
view,