Skip to content

Commit

Permalink
Updates workbench and adds redux dependency (#46)
Browse files Browse the repository at this point in the history
  - Updates the signin page to require username input. The
    user can't get into the site without a username.
  - Uses  redux state management to keep track of 
    logged in username and highlight the active menu option.
    This username is used to construct the workbench links.
  - Updates codeclimate.yml to increase duplication threshold.

---------

Co-authored-by: Asger <[email protected]>
Co-authored-by: Burnfarm <[email protected]>
Co-authored-by: Omar <[email protected]>
  • Loading branch information
3 people authored Apr 30, 2023
1 parent 4aac6f7 commit af17f91
Show file tree
Hide file tree
Showing 31 changed files with 643 additions and 384 deletions.
10 changes: 6 additions & 4 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ plugins:
enabled: true
config:
languages:
- typescript:
- javascript:
- python:
- php:
typescript:
mass_threshold: 55
javascript:
python:
php:
eslint:
enabled: true
channel: "eslint-8"
Expand All @@ -29,3 +30,4 @@ exclude_patterns:
- "**/build/"
- "**/public/"
- "**/coverage"
- "client/config/"
1 change: 1 addition & 0 deletions .github/workflows/client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
cd client/
yarn install
yarn build
yarn configapp dev
- name: Run client unit and integration tests
run: |
cd client/
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ typings/
.env.test

# front end environment variables
env.js
client/public/env.js

# parcel-bundler cache (https://parceljs.org/)
.cache
Expand Down
6 changes: 6 additions & 0 deletions client/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
"project": ["./tsconfig.json"]
},
"plugins": ["@typescript-eslint"]
},
{
"files": ["src/**/*.slice.ts"],
"rules": {
"no-param-reassign": ["error", { "props": false }]
}
}
]
}
4 changes: 2 additions & 2 deletions client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ yarn build #build the react app into build/ directory
yarn develop #start the development server without building. Great for live edits.


#specify the environment; specify only one
yarn configapp #prod | dev
#Required: Specify the environment; specify only one
yarn configapp #prod | dev #If not specified, the app wont run.

yarn start #start the application
yarn test #UI testing of the application
Expand Down
5 changes: 5 additions & 0 deletions client/config/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ window.env = {
REACT_APP_URL_LIB: 'https://ingenioer.au.dk/',
REACT_APP_URL_DT: 'https://jupyterlite.github.io/demo/repl/index.html',
REACT_APP_URL_WORKBENCH: 'https://ece.au.dk/',
REACT_APP_WORKBENCHLINK_TERMINAL: '/terminals/main',
REACT_APP_WORKBENCHLINK_VNCDESKTOP: '/tools/vnc/?password=vncpassword',
REACT_APP_WORKBENCHLINK_VSCODE: '/tools/vscode/',
REACT_APP_WORKBENCHLINK_JUPYTERLAB: '/lab',
REACT_APP_WORKBENCHLINK_JUPYTERNOTEBOOK: '',
};
5 changes: 5 additions & 0 deletions client/config/prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ window.env = {
REACT_APP_URL_LIB: 'https://ingenioer.au.dk/',
REACT_APP_URL_DT: 'https://au.dk/',
REACT_APP_URL_WORKBENCH: 'https://ece.au.dk/',
REACT_APP_WORKBENCHLINK_TERMINAL: '/terminals/main',
REACT_APP_WORKBENCHLINK_VNCDESKTOP: '/tools/vnc/?password=vncpassword',
REACT_APP_WORKBENCHLINK_VSCODE: '/tools/vscode/',
REACT_APP_WORKBENCHLINK_JUPYTERLAB: '/lab',
REACT_APP_WORKBENCHLINK_JUPYTERNOTEBOOK: '',
};
2 changes: 1 addition & 1 deletion client/jest.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"transformIgnorePatterns": ["/node_modules/(?![d3-shape|recharts]).+\\.js$"],
"collectCoverage": true,
"coverageReporters": ["text", "cobertura", "clover", "lcov", "json"],
"collectCoverageFrom": ["src/**/*.tsx"],
"collectCoverageFrom": ["src/**/*.{ts,tsx}"],
"coveragePathIgnorePatterns": ["node_modules", "build"],
"modulePathIgnorePatterns": ["test/e2e", "mocks", "config"],
"coverageDirectory": "<rootDir>/coverage/",
Expand Down
10 changes: 6 additions & 4 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@
"singleQuote": true
},
"dependencies": {
"@emotion/react": "^11.10.0",
"@emotion/styled": "^11.10.0",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@fontsource/roboto": "^4.5.8",
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.10.0",
"@mui/material": "^5.12.1",
"@reduxjs/toolkit": "^1.9.5",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-is": "^18.2.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.3.0",
"react-tabs": "^6.0.0",
"recharts": "^2.1.13",
"redux": "^4.2.1",
"resize-observer-polyfill": "^1.5.1",
"serve": "^14.0.1",
"styled-components": "^5.3.9",
Expand Down
6 changes: 0 additions & 6 deletions client/public/env.js

This file was deleted.

1 change: 1 addition & 0 deletions client/script/test.bash
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
set -eux
printf "\n\n################ Testing in progress ################"
printf "\n################ Running Jest ################\n"
PATH="$(yarn bin):$PATH"
Expand Down
12 changes: 8 additions & 4 deletions client/src/AppProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { CssBaseline } from '@mui/material';
import { ThemeProvider, createTheme, Theme } from '@mui/material/styles';
import * as React from 'react';
import { Provider } from 'react-redux';
import store from 'store/store';

const mdTheme: Theme = createTheme({
palette: {
Expand All @@ -10,10 +12,12 @@ const mdTheme: Theme = createTheme({

export function AppProvider({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider theme={mdTheme}>
<CssBaseline />
{children}
</ThemeProvider>
<Provider store={store}>
<ThemeProvider theme={mdTheme}>
<CssBaseline />
{children}
</ThemeProvider>
</Provider>
);
}

Expand Down
78 changes: 78 additions & 0 deletions client/src/components/LinkButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import * as React from 'react';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import styled from '@emotion/styled';
import { KeyLinkPair } from 'util/envUtil';
import { Typography } from '@mui/material';
import LinkIcons from './LinkIconsLib';

const IconLabel = styled('div')({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
fontSize: '14px',
});

const ButtonRow = styled('div')({
display: 'flex',
justifyContent: 'center',
flexWrap: 'wrap',
gap: '50px',
});

interface IconButtonData {
link: string;
icon: React.ReactElement;
name: string;
}
const getIconButtons = (buttons: KeyLinkPair[]): IconButtonData[] =>
buttons.map((button) => {
const iconData = LinkIcons[button.key.toUpperCase()] || LinkIcons.NO_ICON;
return {
link: button.link,
icon: iconData.icon,
name: iconData.name || button.key,
};
});

interface LinkButtonProps {
buttons: KeyLinkPair[];
size?: number;
}

/**
* @description Renders a row of buttons with icons and labels. The buttons open a new tab with the link.
* @param buttons: KeyLinkPair[] (required) - an array of objects with a key and link
* @param size: number (optional) - the size of the icons
* @returns React.ReactElement - a row of buttons with icons and labels
* @example
* const linkValues = getWorkbenchLinkValues();
* <LinkButtons buttons={linkValues} size={6} />
*/ const LinkButtons = ({ buttons, size }: LinkButtonProps) => {
const iconButtons = getIconButtons(buttons);
return (
<ButtonRow>
{iconButtons.map((button, index) => (
<Tooltip key={index} title={button.link}>
<IconLabel>
<IconButton
onClick={() => {
window.open(button.link, '_blank');
}}
role="link"
title={`${button.name}-btn`}
>
{React.cloneElement(button.icon, {
style: { fontSize: `${size?.toString() ?? 4}rem` },
})}
</IconButton>
<Typography variant="h6">{button.name}</Typography>
</IconLabel>
</Tooltip>
))}
</ButtonRow>
);
};

export default LinkButtons;
export { default as LinkIcons } from './LinkIconsLib';
41 changes: 41 additions & 0 deletions client/src/components/LinkIconsLib.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as React from 'react';
import TerminalOutlinedIcon from '@mui/icons-material/TerminalOutlined';
import DesktopWindowsOutlinedIcon from '@mui/icons-material/DesktopWindowsOutlined';
import CodeOutlinedIcon from '@mui/icons-material/CodeOutlined';
import ScienceOutlinedIcon from '@mui/icons-material/ScienceOutlined';
import NoteAltOutlinedIcon from '@mui/icons-material/NoteAltOutlined';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';

type LinkIconsType = {
[key: string]: { icon: React.ReactElement; name: string | undefined };
};

const LinkIcons: LinkIconsType = {
TERMINAL: {
icon: <TerminalOutlinedIcon />,
name: 'Terminal',
},
VNCDESKTOP: {
icon: <DesktopWindowsOutlinedIcon />,
name: 'Desktop',
},
VSCODE: {
icon: <CodeOutlinedIcon />,
name: 'VSCode',
},
JUPYTERLAB: {
icon: <ScienceOutlinedIcon />,
name: 'JupyterLab',
},
JUPYTERNOTEBOOK: {
icon: <NoteAltOutlinedIcon />,
name: 'Jupyter Notebook',
},
NO_ICON: {
icon: <OpenInNewIcon />,
name: undefined,
},
};

export default LinkIcons;
export { LinkIcons };
21 changes: 14 additions & 7 deletions client/src/page/Menu.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
import * as React from 'react';
import { useTheme } from '@mui/material/styles';
import Box from '@mui/material/Box';
import { useDispatch, useSelector } from 'react-redux';
import { closeMenu, openMenu } from 'store/menu.slice';
import { RootState } from 'store/store';
import MenuToolbar from './MenuToolbar';
import DrawerComponent from './DrawerComponent';

const drawerWidth = 240;

function MiniDrawer() {
const hooks = () => {
const theme = useTheme();
const [open, setOpen] = React.useState<boolean>(false);
const menuState = useSelector((state: RootState) => state.menu);
const dispatch = useDispatch();
const [anchorElUser, setAnchorElUser] =
React.useState<HTMLButtonElement | null>(null);
return { theme, menuState, dispatch, anchorElUser, setAnchorElUser };
};

function MiniDrawer() {
const { theme, menuState, dispatch, anchorElUser, setAnchorElUser } = hooks();
const handleCloseUserMenu = () => setAnchorElUser(null);
const handleOpenUserMenu = (event: React.MouseEvent<HTMLButtonElement>) =>
setAnchorElUser(event.currentTarget);
const handleDrawerOpen = () => setOpen(true);
const handleDrawerClose = () => setOpen(false);

const handleDrawerOpen = () => dispatch(openMenu());
const handleDrawerClose = () => dispatch(closeMenu());
return (
<Box sx={{ display: 'flex' }}>
<MenuToolbar
open={open}
open={menuState.isOpen}
drawerWidth={drawerWidth}
handleCloseUserMenu={handleCloseUserMenu}
handleDrawerOpen={handleDrawerOpen}
handleOpenUserMenu={handleOpenUserMenu}
anchorElUser={anchorElUser}
/>
<DrawerComponent
open={open}
open={menuState.isOpen}
theme={theme}
handleDrawerClose={handleDrawerClose}
/>
Expand Down
8 changes: 7 additions & 1 deletion client/src/page/MenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ function MenuItems() {
<>
{menuItems.map((item) => (
<Link to={item.link} style={tolinkStyle} key={item.index}>
<ListItemButton>
<ListItemButton
style={
window.location.pathname === item.link
? { backgroundColor: 'lightgray' }
: undefined
}
>
<ListItemIcon>{item.icon}</ListItemIcon>
{item.name}
</ListItemButton>
Expand Down
Loading

0 comments on commit af17f91

Please sign in to comment.