mirror of
https://github.com/sasjs/server.git
synced 2025-12-11 19:44:35 +00:00
fix: improve responsiveness for mobile view
This commit is contained in:
@@ -2,16 +2,18 @@ import React, { useState, useEffect, useContext } from 'react'
|
|||||||
import { Link, useNavigate, useLocation } from 'react-router-dom'
|
import { Link, useNavigate, useLocation } from 'react-router-dom'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
Box,
|
||||||
AppBar,
|
AppBar,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Tabs,
|
Tabs,
|
||||||
Tab,
|
Tab,
|
||||||
Button,
|
Button,
|
||||||
Menu,
|
Menu,
|
||||||
MenuItem
|
MenuItem,
|
||||||
|
IconButton,
|
||||||
|
Typography
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
|
import { OpenInNew, Settings, Menu as MenuIcon } from '@mui/icons-material'
|
||||||
import SettingsIcon from '@mui/icons-material/Settings'
|
|
||||||
|
|
||||||
import Username from './username'
|
import Username from './username'
|
||||||
import { AppContext } from '../context/appContext'
|
import { AppContext } from '../context/appContext'
|
||||||
@@ -30,31 +32,38 @@ const Header = (props: any) => {
|
|||||||
const [tabValue, setTabValue] = useState(
|
const [tabValue, setTabValue] = useState(
|
||||||
validTabs.includes(pathname) ? pathname : '/'
|
validTabs.includes(pathname) ? pathname : '/'
|
||||||
)
|
)
|
||||||
const [anchorEl, setAnchorEl] = useState<
|
|
||||||
(EventTarget & HTMLButtonElement) | null
|
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null)
|
||||||
>(null)
|
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setAnchorElNav(event.currentTarget)
|
||||||
|
}
|
||||||
|
const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setAnchorElUser(event.currentTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseNavMenu = () => {
|
||||||
|
setAnchorElNav(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseUserMenu = () => {
|
||||||
|
setAnchorElUser(null)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTabValue(validTabs.includes(pathname) ? pathname : '/')
|
setTabValue(validTabs.includes(pathname) ? pathname : '/')
|
||||||
}, [pathname])
|
}, [pathname])
|
||||||
|
|
||||||
const handleMenu = (
|
|
||||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
|
||||||
) => {
|
|
||||||
setAnchorEl(event.currentTarget)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setAnchorEl(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleTabChange = (event: React.SyntheticEvent, value: string) => {
|
const handleTabChange = (event: React.SyntheticEvent, value: string) => {
|
||||||
setTabValue(value)
|
setTabValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
if (appContext.logout) {
|
if (appContext.logout) {
|
||||||
handleClose()
|
handleCloseUserMenu()
|
||||||
appContext.logout()
|
appContext.logout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,11 +73,14 @@ const Header = (props: any) => {
|
|||||||
sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
||||||
>
|
>
|
||||||
<Toolbar variant="dense">
|
<Toolbar variant="dense">
|
||||||
|
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
|
||||||
<img
|
<img
|
||||||
src="logo.png"
|
src="logo.png"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
style={{
|
style={{
|
||||||
width: '35px',
|
width: '35px',
|
||||||
|
height: '35px',
|
||||||
|
marginTop: '9px',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
marginRight: '25px'
|
marginRight: '25px'
|
||||||
}}
|
}}
|
||||||
@@ -97,10 +109,93 @@ const Header = (props: any) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="large"
|
size="large"
|
||||||
endIcon={<OpenInNewIcon />}
|
endIcon={<OpenInNew />}
|
||||||
>
|
>
|
||||||
Apps
|
Apps
|
||||||
</Button>
|
</Button>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
|
||||||
|
<IconButton size="large" onClick={handleOpenNavMenu} color="inherit">
|
||||||
|
<MenuIcon />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<Menu
|
||||||
|
id="menu-appbar"
|
||||||
|
anchorEl={anchorElNav}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'left'
|
||||||
|
}}
|
||||||
|
keepMounted
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'left'
|
||||||
|
}}
|
||||||
|
open={!!anchorElNav}
|
||||||
|
onClose={handleCloseNavMenu}
|
||||||
|
sx={{
|
||||||
|
display: { xs: 'block', md: 'none' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MenuItem sx={{ justifyContent: 'center' }}>
|
||||||
|
<Button
|
||||||
|
component={Link}
|
||||||
|
to="/"
|
||||||
|
onClick={handleCloseNavMenu}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Home
|
||||||
|
</Button>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem sx={{ justifyContent: 'center' }}>
|
||||||
|
<Button
|
||||||
|
component={Link}
|
||||||
|
to="/SASjsStudio"
|
||||||
|
onClick={handleCloseNavMenu}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Studio
|
||||||
|
</Button>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem sx={{ justifyContent: 'center' }}>
|
||||||
|
<Button
|
||||||
|
href={`${baseUrl}/AppStream`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
onClick={handleCloseNavMenu}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
endIcon={<OpenInNew />}
|
||||||
|
>
|
||||||
|
Apps
|
||||||
|
</Button>
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ display: { xs: 'flex', md: 'none' } }}>
|
||||||
|
<img
|
||||||
|
src="logo.png"
|
||||||
|
alt="logo"
|
||||||
|
style={{
|
||||||
|
width: '35px',
|
||||||
|
height: '35px',
|
||||||
|
marginTop: '2px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
marginRight: '25px'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setTabValue('/')
|
||||||
|
navigate('/')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -110,11 +205,11 @@ const Header = (props: any) => {
|
|||||||
>
|
>
|
||||||
<Username
|
<Username
|
||||||
username={appContext.displayName || appContext.username}
|
username={appContext.displayName || appContext.username}
|
||||||
onClickHandler={handleMenu}
|
onClickHandler={handleOpenUserMenu}
|
||||||
/>
|
/>
|
||||||
<Menu
|
<Menu
|
||||||
id="menu-appbar"
|
id="menu-appbar"
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorElUser}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: 'bottom',
|
vertical: 'bottom',
|
||||||
horizontal: 'center'
|
horizontal: 'center'
|
||||||
@@ -124,17 +219,30 @@ const Header = (props: any) => {
|
|||||||
vertical: 'top',
|
vertical: 'top',
|
||||||
horizontal: 'center'
|
horizontal: 'center'
|
||||||
}}
|
}}
|
||||||
open={!!anchorEl}
|
open={!!anchorElUser}
|
||||||
onClose={handleClose}
|
onClose={handleCloseUserMenu}
|
||||||
>
|
>
|
||||||
|
{appContext.loggedIn && (
|
||||||
|
<MenuItem
|
||||||
|
sx={{ justifyContent: 'center', display: { md: 'none' } }}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
sx={{ border: '1px solid black', padding: '5px' }}
|
||||||
|
>
|
||||||
|
{appContext.displayName || appContext.username}
|
||||||
|
</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
|
||||||
<MenuItem sx={{ justifyContent: 'center' }}>
|
<MenuItem sx={{ justifyContent: 'center' }}>
|
||||||
<Button
|
<Button
|
||||||
component={Link}
|
component={Link}
|
||||||
to="/SASjsSettings"
|
to="/SASjsSettings"
|
||||||
onClick={handleClose}
|
onClick={handleCloseUserMenu}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
startIcon={<SettingsIcon />}
|
startIcon={<Settings />}
|
||||||
>
|
>
|
||||||
Settings
|
Settings
|
||||||
</Button>
|
</Button>
|
||||||
@@ -147,7 +255,7 @@ const Header = (props: any) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
size="large"
|
size="large"
|
||||||
color="primary"
|
color="primary"
|
||||||
endIcon={<OpenInNewIcon />}
|
endIcon={<OpenInNew />}
|
||||||
>
|
>
|
||||||
Docs
|
Docs
|
||||||
</Button>
|
</Button>
|
||||||
@@ -160,7 +268,7 @@ const Header = (props: any) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="large"
|
size="large"
|
||||||
endIcon={<OpenInNewIcon />}
|
endIcon={<OpenInNew />}
|
||||||
>
|
>
|
||||||
API
|
API
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -20,7 +20,14 @@ const Username = (props: any) => {
|
|||||||
) : (
|
) : (
|
||||||
<AccountCircle></AccountCircle>
|
<AccountCircle></AccountCircle>
|
||||||
)}
|
)}
|
||||||
<Typography variant="h6" sx={{ color: 'white', padding: '0 8px' }}>
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
sx={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0 8px',
|
||||||
|
display: { xs: 'none', md: 'flex' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
{props.username}
|
{props.username}
|
||||||
</Typography>
|
</Typography>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -31,11 +31,20 @@ const Settings = () => {
|
|||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
flexDirection: { xs: 'column', md: 'row' },
|
||||||
marginTop: '65px'
|
marginTop: '65px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TabContext value={value}>
|
<TabContext value={value}>
|
||||||
<Box component={Paper} sx={{ margin: '0 5px', height: '92vh' }}>
|
<Box
|
||||||
|
component={Paper}
|
||||||
|
sx={{
|
||||||
|
margin: '0 5px',
|
||||||
|
height: { md: '92vh' },
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
<TabList
|
<TabList
|
||||||
TabIndicatorProps={{
|
TabIndicatorProps={{
|
||||||
style: {
|
style: {
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ const BootstrapTableCell = styled(TableCell)({
|
|||||||
textAlign: 'left'
|
textAlign: 'left'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const BootstrapGridItem = styled(Grid)({
|
||||||
|
'&.MuiGrid-item': {
|
||||||
|
maxWidth: '100%'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export enum PrincipalType {
|
export enum PrincipalType {
|
||||||
User = 'User',
|
User = 'User',
|
||||||
Group = 'Group'
|
Group = 'Group'
|
||||||
@@ -350,11 +356,11 @@ const Permission = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Box className="permissions-page">
|
<Box className="permissions-page">
|
||||||
<Grid container direction="column" spacing={1}>
|
<Grid container direction="column" spacing={1}>
|
||||||
<Grid item xs={12}>
|
<BootstrapGridItem item xs={12}>
|
||||||
<Paper elevation={3} sx={{ display: 'flex' }}>
|
<Paper elevation={3} sx={{ display: 'flex' }}>
|
||||||
<Tooltip title="Filter Permissions">
|
<Tooltip title="Filter Permissions">
|
||||||
<IconButton>
|
<IconButton onClick={() => setFilterModalOpen(true)}>
|
||||||
<FilterListIcon onClick={() => setFilterModalOpen(true)} />
|
<FilterListIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{appContext.isAdmin && (
|
{appContext.isAdmin && (
|
||||||
@@ -369,14 +375,14 @@ const Permission = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</BootstrapGridItem>
|
||||||
<Grid item xs={12}>
|
<BootstrapGridItem item xs={12}>
|
||||||
<PermissionTable
|
<PermissionTable
|
||||||
permissions={filterApplied ? filteredPermissions : permissions}
|
permissions={filterApplied ? filteredPermissions : permissions}
|
||||||
handleUpdatePermissionClick={handleUpdatePermissionClick}
|
handleUpdatePermissionClick={handleUpdatePermissionClick}
|
||||||
handleDeletePermissionClick={handleDeletePermissionClick}
|
handleDeletePermissionClick={handleDeletePermissionClick}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</BootstrapGridItem>
|
||||||
</Grid>
|
</Grid>
|
||||||
<BootstrapSnackbar
|
<BootstrapSnackbar
|
||||||
open={openSnackbar}
|
open={openSnackbar}
|
||||||
@@ -553,8 +559,8 @@ const DisplayGroup = ({ group }: DisplayGroupProps) => {
|
|||||||
<Typography sx={{ p: 1 }} variant="h6" component="div">
|
<Typography sx={{ p: 1 }} variant="h6" component="div">
|
||||||
Group Members
|
Group Members
|
||||||
</Typography>
|
</Typography>
|
||||||
{group.users.map((user) => (
|
{group.users.map((user, index) => (
|
||||||
<Typography sx={{ p: 1 }} component="li">
|
<Typography key={index} sx={{ p: 1 }} component="li">
|
||||||
{user.username}
|
{user.username}
|
||||||
</Typography>
|
</Typography>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user