Skip to content

Commit

Permalink
Feature/wd3691 (#36)
Browse files Browse the repository at this point in the history
* WD-3691 Add material UI, users table

* WD-3691 Rebase development, update changelog

* Fix linting errors.

Co-authored-by: Alex <awintschel@gmail.com>
  • Loading branch information
Baelx and Alex committed Jan 12, 2022
1 parent 2c7f7a4 commit 96f399a
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 55 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Developer Changelog

### January 12, 2022 WD-3691
* add material UI, including theming, icons
* add users table and related components

### January 11, 2022 WD-3815 part 2
* backend
* added secretfile support for openshift database password
Expand Down
8 changes: 7 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
"license": "Apache-2.0",
"dependencies": {
"@bcgov/bc-sans": "^1.0.1",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@mui/icons-material": "^5.2.5",
"@mui/material": "^5.2.8",
"@react-keycloak/web": "^3.4.0",
"axios": "^0.24.0",
"keycloak-js": "^15.0.2",
Expand Down Expand Up @@ -81,6 +85,8 @@
"typescript": "^4.4.4"
},
"jest": {
"snapshotSerializers": ["enzyme-to-json/serializer"]
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import { shallow } from "enzyme";
import { List } from "../pages/Contract";
import Sidebar from "../components/Sidebar";
import Main from "../components/Main";
import { List } from "../../pages/Contract";
import Sidebar from "../../components/Sidebar";
import Main from "../../components/Main";

describe("Contract <List /> component", () => {
const contractList = shallow(<List />);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { shallow } from "enzyme";
import Login from "../pages/Login";
import Login from "../../pages/Login";

// Mock react router.
jest.mock("react-router-dom", () => {
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/__tests__/pages/PageNotFound.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";
import { mountWithTheme } from "../../setupTests";
import { MemoryRouter } from "react-router-dom";
import AppRouter from "../../router/AppRouter";
import PageNotFound from "../../pages/PageNotFound";

describe("<PageNotFound /> routing", () => {
it("redirects to <PageNotFound /> when an invalid URL is passed", () => {
const appWrapper = mountWithTheme(
<MemoryRouter initialEntries={["/invalid-url"]}>
<AppRouter />
</MemoryRouter>
);
expect(appWrapper.find(PageNotFound)).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import { shallow } from "enzyme";
import { List } from "../pages/Project";
import Sidebar from "../components/Sidebar";
import Main from "../components/Main";
import { List } from "../../pages/Project";
import Sidebar from "../../components/Sidebar";
import Main from "../../components/Main";

describe("Project <List /> component", () => {
const projectList = shallow(<List />);
Expand Down
16 changes: 9 additions & 7 deletions frontend/src/__tests__/pages/Users.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import React from "react";
import { shallow } from "enzyme";
import { User } from "../../pages/Admin";
// import { User } from "../../pages/Admin";

jest.mock("react-router-dom", () => ({
useParams: () => ({ userId: null }),
}));

describe("User Api call", () => {
it("renders Users display page when '/admin/user' is hit", () => {
const user = shallow(<User />);
expect(user.find("h2")).toHaveLength(1);
expect(user.find("div pre")).toHaveLength(1);
// it("renders Users display page when '/admin/user' is hit", () => {
// const user = shallow(<User />);
// expect(user.find("h2")).toHaveLength(1);
// expect(user.find("div pre")).toHaveLength(1);
// });

it("is a dummy test", () => {
expect(true).toBe(true);
});
});
19 changes: 19 additions & 0 deletions frontend/src/bcgovTheme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createTheme } from "@mui/material/styles";

/**
* Create a theme that uses BC Gov colours.
*
* @see https://mui.com/customization/theming/
*/
const bcgovTheme = createTheme({
palette: {
primary: {
main: "#036",
},
secondary: {
main: "#38598a",
},
},
});

export default bcgovTheme;
14 changes: 14 additions & 0 deletions frontend/src/components/RowEditDeleteChip/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@import "../../styles/components/variables";

.row-edit-delete-chip {
border-radius: 20px;
border: 1px solid $grey;

.edit-icon {

}

.delete-icon {

}
}
30 changes: 30 additions & 0 deletions frontend/src/components/RowEditDeleteChip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { FC } from "react";
import "./index.scss";
import Box from "@mui/material/Box";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import { visuallyHidden } from "@mui/utils";
// import red from '@mui/material/colors/red';

// Callbacks can have any number of arguments and can have any return type.
interface IProps {
editCallback: (...args: any[]) => any;
deleteCallback: (...args: any[]) => any;
}

const RowEditDeleteChip: FC<IProps> = ({ editCallback, deleteCallback }) => {
return (
<div className="row-edit-delete-chip">
<EditIcon className="edit-icon" sx={{ color: "secondary.main" }} onClick={editCallback} />
<Box component="span" sx={visuallyHidden}>
Edit user
</Box>
<DeleteIcon className="delete-icon" onClick={deleteCallback} />
<Box component="span" sx={visuallyHidden}>
Delete user
</Box>
</div>
);
};

export default RowEditDeleteChip;
6 changes: 5 additions & 1 deletion frontend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { ReactKeycloakProvider } from "@react-keycloak/web";
import keycloak from "./keycloak";
import bcgovTheme from "./bcgovTheme";
import { ThemeProvider } from "@mui/material/styles";

ReactDOM.render(
<ReactKeycloakProvider authClient={keycloak}>
<App />
<ThemeProvider theme={bcgovTheme}>
<App />
</ThemeProvider>
</ReactKeycloakProvider>,
document.getElementById("root")
);
Expand Down
33 changes: 3 additions & 30 deletions frontend/src/pages/Admin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { FC, useState, useEffect } from "react";
import React, { FC } from "react";
import { Outlet, useParams } from "react-router-dom";
import apiAxios from "../../utils/apiAxios";
import Sidebar from "../../components/Sidebar";
import Main from "../../components/Main";
import Debug from "../../components/Debug";
Expand All @@ -11,39 +10,13 @@ export const Admin: FC = () => {
<Sidebar />
<Main>
<Outlet />
<Debug />
</Main>
</>
);
};

export const User: FC = () => {
let { userId } = useParams();
const [userData, setUserData] = useState({});
useEffect(() => {
const axiosResponse = apiAxios();
let uri = "users";
if (userId) {
uri = `${uri}/${userId}`;
}
axiosResponse
.get(uri)
.then((data) => {
setUserData(data);
})
.catch((error) => {
console.log(error);
});
}, [userId]);

return (
<div>
<h2>User {userId}</h2>
<div>
<pre>{JSON.stringify(userData, null, 2)}</pre>
</div>
</div>
);
export const AdminDebug: FC = () => {
return <Debug />;
};

export const Contacts: FC = () => {
Expand Down
91 changes: 91 additions & 0 deletions frontend/src/pages/Users/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
@import '../../styles/components/variables';

.users {
.table-data-filter {
margin-top: 2.5rem;
margin-bottom: 1rem;
display: flex;
justify-content: space-between;

.filter-form {
> * {
margin-right: 1rem;
}

label {
font-size: 1.1rem;
font-weight: bold;
color: $nav-background;
}
}

.user-search-form {
input {
padding: 0.4rem;
}

button {
background-color: $nav-background;
color: $white;
border: none;
padding: 0.5rem 0.75rem;
font-size: 1rem;
border-radius: 20px;
font-weight: bold;
}
}

.user-filter {

}
}

.user-table {
border-radius: 5px;
border: 2px solid $nav-background;

.user-table-head {
background-color: $nav-background;

.head-cell {
&:first-child {
border-right: 1px solid $white;
}

&:last-child {
min-width: 50px;
}

border-right: none;
color: $white;
font-weight: bold;
font-size: 1.2rem;
}
}

.user-table-body {
.table-body-row {
.body-cell {
&:first-child {
border-right: 2px solid $nav-background;
}

border-right: none;
border-bottom: none;
font-size: 1rem;
font-weight: bold;
}
}
}
}

.user-role-totals {
font-weight: bold;
margin-top: 1rem;

span {
margin-right: 1rem;
}
}
}

0 comments on commit 96f399a

Please sign in to comment.