Skip to content

Commit b580e82

Browse files
authored
Merge pull request #11 from hodesza/UI
UI - Dark Mode Implementation
2 parents 03782ba + 4c74c93 commit b580e82

21 files changed

+1868
-1132
lines changed

.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
declare module '*.png'
1+
declare module '*.png'
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React, {useContext} from 'react';
2+
import { createMount, createShallow } from '@material-ui/core/test-utils';
3+
4+
import DashboardContextProvider, { DashboardContext } from '../../../app/context/DashboardContext';
5+
import Settings from '../../../app/components/Settings';
6+
const { ipcRenderer } = require('electron');
7+
jest.mock('electron', () => ({ ipcRenderer: { sendSync: jest.fn() } }));
8+
9+
describe('<Settings />', () => {
10+
let wrapper: any;
11+
let mount: any;
12+
let shallow: any;
13+
14+
beforeEach(() => {
15+
mount = createMount();
16+
shallow = createShallow();
17+
});
18+
19+
afterEach(() => {
20+
mount.cleanUp();
21+
});
22+
23+
it("should render ", () => {
24+
const wrapper = mount(
25+
<DashboardContextProvider>
26+
<Settings />
27+
</DashboardContextProvider>
28+
);
29+
expect(wrapper.exists).toBeTruthy;
30+
});
31+
32+
it("should have a button with text value of Light", () => {
33+
const wrapper = mount(
34+
<DashboardContextProvider>
35+
<Settings />
36+
</DashboardContextProvider>
37+
);
38+
const button = wrapper.find('#lightMode');
39+
// button.simulate('click');
40+
expect(button.text()).toEqual('Light')
41+
});
42+
43+
it("should emit the changeApp event when click light mode", () => {
44+
const wrapper = mount(
45+
<DashboardContextProvider>
46+
<Settings />
47+
</DashboardContextProvider>
48+
);
49+
const button = wrapper.find('#lightMode');
50+
button.simulate('click');
51+
expect(ipcRenderer.sendSync).toHaveBeenCalledWith('changeMode', 'light mode');
52+
});
53+
54+
it("should emit the changeApp event when click dark mode", () => {
55+
const wrapper = mount(
56+
<DashboardContextProvider>
57+
<Settings />
58+
</DashboardContextProvider>
59+
);
60+
const button = wrapper.find('#darkMode');
61+
button.simulate('click');
62+
expect(ipcRenderer.sendSync).toHaveBeenCalledWith('changeMode', 'dark mode');
63+
});
64+
65+
it("should have a button with text value of Dark", () => {
66+
const wrapper = mount(
67+
<DashboardContextProvider>
68+
<Settings />
69+
</DashboardContextProvider>
70+
);
71+
const button = wrapper.find('#darkMode');
72+
// button.simulate('click');
73+
expect(button.text()).toEqual('Dark')
74+
});
75+
76+
77+
});

__tests__/app/context/DashboardContext.test.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('<DashboardContext />', () => {
2323
};
2424
// Mock component that has access to Dashboard Context
2525
const TestComponent = () => {
26-
const { applications, getApplications, addApp, deleteApp } = useContext(DashboardContext);
26+
const { applications, getApplications, addApp, deleteApp, mode, changeMode } = useContext(DashboardContext);
2727

2828
return (
2929
<>
@@ -37,6 +37,9 @@ describe('<DashboardContext />', () => {
3737
<button id="getApplications" onClick={() => getApplications()}>
3838
Test getApplications
3939
</button>
40+
<button id="changeMode" onClick={() => changeMode('light mode')}>
41+
Test changeMode
42+
</button>
4043
</>
4144
);
4245
};
@@ -74,4 +77,10 @@ describe('<DashboardContext />', () => {
7477
button.simulate('click');
7578
expect(ipcRenderer.sendSync).toHaveBeenCalledWith('getApps');
7679
});
80+
81+
it("should emit the 'changeMode' event when invoking changeMode", () => {
82+
const button = wrapper.find('#changeMode');
83+
button.simulate('click');
84+
expect(ipcRenderer.sendSync).toHaveBeenCalledWith('changeMode', 'light mode');
85+
});
7786
});

app/components/Header.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import React, { useContext } from 'react';
22
import { useHistory, Link } from 'react-router-dom';
33
import ListIcon from '@material-ui/icons/List';
44
import { ApplicationContext } from '../context/ApplicationContext';
5+
import { DashboardContext } from '../context/DashboardContext';
56
import '../stylesheets/Header.scss';
6-
7+
import {lightAndDark} from '../components/Styling';
78
export interface HeaderProps {
89
app: string[];
910
service: string;
@@ -15,9 +16,11 @@ const Header: React.FC<HeaderProps> = React.memo(function Header({ app, service,
1516
const history = useHistory();
1617

1718
const { servicesData } = useContext(ApplicationContext);
19+
const { mode } = useContext(DashboardContext);
1820

21+
let currentMode = (mode === 'light mode')? lightAndDark.lightModeHeader : lightAndDark.darkModeHeader;
1922
return (
20-
<div className="microservice-header">
23+
<div className="microservice-header" style={currentMode}>
2124
<h1 className="microserviceTitle">{app}</h1>
2225
<select name="microservice" value={service} onChange={e => history.replace(e.target.value)}>
2326
{servicesData.map(({ _id, microservice }: any) => (

app/components/Occupied.tsx

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import DashboardIcon from '@material-ui/icons/Dashboard';
2424
import NotificationsIcon from '@material-ui/icons/Notifications';
2525
import PersonIcon from '@material-ui/icons/Person';
2626
import UpdateIcon from '@material-ui/icons/Update';
27-
2827
// MODALS
2928
import AddModal from '../modals/AddModal';
3029
import ServicesModal from '../modals/ServicesModal';
@@ -33,6 +32,7 @@ import ServicesModal from '../modals/ServicesModal';
3332
// import '../stylesheets/Occupied.scss';
3433
import '../stylesheets/Occupied.scss';
3534

35+
3636
// DASHBOARD CONTEXT
3737
import { DashboardContext } from '../context/DashboardContext';
3838

@@ -46,20 +46,21 @@ type ClickEvent = React.MouseEvent<HTMLElement>;
4646

4747
const Occupied = React.memo(() => {
4848
const { setServicesData } = useContext(ApplicationContext);
49-
const { applications, getApplications, deleteApp } = useContext(DashboardContext);
49+
const { applications, getApplications, deleteApp, mode, getMode } = useContext(DashboardContext);
5050
const [open, setOpen] = useState<boolean>(false);
5151
const [addOpen, setAddOpen] = useState<boolean>(false);
5252
const [index, setIndex] = useState<number>(0);
5353
const [app, setApp] = useState<string>('');
5454
const [searchTerm, setSearchTerm] = useState<string>('Search...');
5555
// Dynamic refs
5656
const delRef = useRef<any>([]);
57-
57+
//check context from dashboard
5858
useEffect(() => {
5959
setServicesData([]);
60-
getApplications();
60+
getApplications();
6161
}, []);
62-
62+
console.log(mode);
63+
6364
// Ask user for deletetion confirmation
6465
const confirmDelete = (event: ClickEvent, app: string, i: number) => {
6566
const message = `The application '${app}' will be permanently deleted. Continue?`;
@@ -75,8 +76,61 @@ const Occupied = React.memo(() => {
7576
setOpen(true);
7677
}
7778
};
78-
79-
const useStyles = makeStyles<Theme, StyleProps>(theme => ({
79+
//Conditional Rendering of UI Modals for Light and Dark Mode
80+
const useStylesDark = makeStyles<Theme, StyleProps>(theme => ({
81+
// ALL CARDS
82+
paper: {
83+
display: 'flex',
84+
flexDirection: 'column',
85+
alignContent: 'center',
86+
alignItems: 'center',
87+
position: 'relative',
88+
overflow: 'visible',
89+
height: 280,
90+
width: 280,
91+
textAlign: 'center',
92+
color: '#ffffff', // dark mode
93+
whiteSpace: 'nowrap',
94+
backgroundColor: 'transparent', // dark mode
95+
borderRadius: 3,
96+
border: '0',
97+
boxShadow: '0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)', // dark mode
98+
'&:hover, &.Mui-focusVisible': {
99+
backgroundColor: 'rgba(255, 255, 255, 0.2)', // dark mode
100+
color: '#ffffff',
101+
fontWeight: 600,
102+
},
103+
},
104+
iconbutton: {
105+
boxShadow: 'none',
106+
color: 'none',
107+
visibility: 'hidden',
108+
},
109+
btnStyle: {
110+
position: 'absolute',
111+
top: -10,
112+
left: -72,
113+
margin: '0',
114+
color: '#eeeeee',
115+
borderRadius: '0',
116+
backgroundColor: 'none',
117+
visibility: 'visible',
118+
},
119+
icon: {
120+
width: '75px',
121+
height: '75px',
122+
boxShadow: 'none',
123+
},
124+
// ALL CARDS: CONTENT
125+
fontStyles: {
126+
fontSize: '18px',
127+
fontFamily: 'Roboto',
128+
fontWeight: 300,
129+
// color: '#444d56',
130+
color: '#ffffff', // dark mode
131+
}
132+
}));
133+
const useStylesLight = makeStyles<Theme, StyleProps>(theme => ({
80134
// ALL CARDS
81135
paper: {
82136
display: 'flex',
@@ -130,7 +184,7 @@ const Occupied = React.memo(() => {
130184
}
131185
}));
132186

133-
const classes = useStyles({} as StyleProps);
187+
let classes = (mode === 'light mode')? useStylesLight({} as StyleProps) : useStylesDark({} as StyleProps) ;
134188

135189
return (
136190
<div className="entireArea">

app/components/Settings.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
1-
import React from 'react';
1+
import React, {useContext, useEffect, useState} from 'react';
22
import '../stylesheets/Settings.scss';
3+
4+
// DASHBOARD CONTEXT
5+
import { DashboardContext } from '../context/DashboardContext';
6+
37
// Need to add flag to turn off the splash at start
48
// Need to add flag to turn off getting started page
59
// Need to add flag to turn on/off live data (ideally persist on restart)
610
// Need to add dark mode
11+
12+
//Typescript
13+
type ClickEvent = React.MouseEvent<HTMLElement>;
14+
715
const Settings: React.SFC = React.memo((props) => {
16+
//use context from Dash board regarding currentMode
17+
let { changeMode } = useContext(DashboardContext);
18+
const handleClick = (mode: string) => {
19+
changeMode(mode);
20+
}
821
return (
922
<div className="settings">
10-
<button className="mode" id="lightMode">
23+
<button className="mode" id="lightMode" onClick={() => handleClick("light mode")}>
1124
Light
1225
</button>
1326

14-
<button className="mode" id="darkMode">
27+
<button className="mode" id="darkMode" onClick={() => handleClick("dark mode")}>
1528
Dark
1629
</button>
1730
</div>

app/components/Styling.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export const lightAndDark = {
2+
lightModeMain : {
3+
backgroundColor: "#eeeeee",
4+
flex: "1",
5+
minHeight: "100vh",
6+
flexDirection: "column" as "column",
7+
paddingLeft: "140px",
8+
},
9+
lightModeHeader : {
10+
backgroundColor: "#eeeeee",
11+
color: "#444d56",
12+
},
13+
darkModeHeader : {
14+
// backgroundColor: "#transparent",
15+
backgroundColor: "#181818",
16+
color: "white",
17+
},
18+
darkModeMain : {
19+
// backgroundImage: "url('../assets/mountain_longer.png')",
20+
// backgroundColor: "#transparent",
21+
backgroundColor: "#181818",
22+
backgroundSize: 'contain',
23+
flex: "1",
24+
minHeight: "100vh",
25+
flexDirection: "column" as "column",
26+
paddingLeft: "140px",
27+
}
28+
};

app/containers/DashboardContainer.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, {useEffect, useContext} from 'react';
22
import { BrowserRouter as Router } from 'react-router-dom';
33
import MainContainer from './MainContainer';
44
import SidebarContainer from './SidebarContainer';
@@ -8,8 +8,10 @@ import ApplicationContextProvider from '../context/ApplicationContext';
88
import DashboardContextProvider from '../context/DashboardContext';
99
import DockerContextProvider from '../context/DockerContext';
1010
import '../stylesheets/Dashboard.scss';
11+
import { DashboardContext } from '../context/DashboardContext';
12+
const DashboardContainer = React.memo(() => {
1113

12-
const DashboardContainer = React.memo(() => (
14+
return(
1315
<Router>
1416
<div className="dash">
1517
<ApplicationContextProvider>
@@ -26,6 +28,6 @@ const DashboardContainer = React.memo(() => (
2628
</ApplicationContextProvider>
2729
</div>
2830
</Router>
29-
));
31+
)});
3032

3133
export default DashboardContainer;

app/containers/MainContainer.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, {useContext ,useEffect} from 'react';
22
import { Route, Switch } from 'react-router-dom';
33

44
// import GraphsContainer from './Archived';
@@ -8,17 +8,20 @@ import Contact from '../components/Contact';
88
import Settings from '../components/Settings';
99
import Copyright from '../components/Copyright';
1010
import Occupied from '../components/Occupied';
11+
import {lightAndDark} from '../components/Styling';
1112
// import Occupied from '../components/Occupied_darkmode';
1213
import GraphsContainer from './GraphsContainer';
1314
import '../stylesheets/MainContainer.scss';
1415
// import '../stylesheets/MainContainer_darkmode.scss';
1516

1617
import ApplicationContextProvider from '../context/ApplicationContext';
18+
import { DashboardContext } from '../context/DashboardContext';
1719

1820
const MainContainer = React.memo(() => {
19-
21+
const { mode, getMode } = useContext(DashboardContext);
22+
let currentMode = (mode === 'light mode')? lightAndDark.lightModeMain : lightAndDark.darkModeMain;
2023
return (
21-
<div className="main-container">
24+
<div className="main-container" style ={currentMode}>
2225
<div className="main-routes">
2326
<Switch>
2427
<Route exact path="/" component={Home} />

app/containers/SidebarContainer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, {useContext, useEffect, useState} from 'react';
22
import { Link } from 'react-router-dom';
33

44
import HomeSharpIcon from '@material-ui/icons/HomeSharp';
@@ -9,6 +9,8 @@ import SettingsIcon from '@material-ui/icons/Settings';
99
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
1010
import '../stylesheets/SidebarContainer.scss';
1111

12+
// import { DashboardContext } from '../context/DashboardContext';
13+
1214
const iconStyles = {
1315
WebkitBoxSizing: 'border-box',
1416
boxShadow: 'none',
@@ -19,6 +21,7 @@ const iconStyles = {
1921
}
2022

2123
const SidebarContainer = React.memo(function SidebarContainer(props): JSX.Element {
24+
2225
return (
2326
<div className="sidebar-container" id="mySidebar">
2427
<div className="sidebar">

0 commit comments

Comments
 (0)