Skip to content
This repository has been archived by the owner on Jun 21, 2022. It is now read-only.

Commit

Permalink
MF-56: Add logout to primary nav bar
Browse files Browse the repository at this point in the history
  • Loading branch information
fatmali committed Sep 11, 2019
1 parent 069cb4d commit 128d09c
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 28 deletions.
9 changes: 9 additions & 0 deletions __mocks__/openmrs-esm-api.mock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { of } from "rxjs";

export function openmrsFetch() {
return new Promise(() => {});
}

export function getCurrentUser() {
return of({ authenticated: false });
}
1 change: 1 addition & 0 deletions jest.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"^.+\\.tsx?$": "babel-jest"
},
"moduleNameMapper": {
"@openmrs/esm-api": "<rootDir>/__mocks__/openmrs-esm-api.mock.tsx",
"\\.(css)$": "identity-obj-proxy"
}
}
116 changes: 107 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
"kremling": "^2.0.1",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-router-dom": "^5.0.1",
"rxjs": "^6.5.3",
"single-spa-react": "^2.10.2"
}
}
16 changes: 16 additions & 0 deletions src/auth.resource.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { getCurrentUser, openmrsFetch } from "@openmrs/esm-api";

export default {
getLoggedInUser,
logoutUser
};

function getLoggedInUser() {
return getCurrentUser();
}

function logoutUser() {
return openmrsFetch("/ws/rest/v1/session", {
method: "DELETE"
});
}
1 change: 1 addition & 0 deletions src/openmrs-esm-primary-navigation.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

declare module "@openmrs/esm-api" {
export function openmrsFetch(url: string, fetchInit: any): any;
export function getCurrentUser(opts?: any): any;
}

declare module "*.css";
87 changes: 71 additions & 16 deletions src/root.component.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import React from "react";
import openmrsRootDecorator from "@openmrs/react-root-decorator";
import styles from "./root.styles.css";
import authResource from "./auth.resource";
import { toggle } from "kremling";
import { BrowserRouter, Redirect } from "react-router-dom";

function Root() {
function Root(props: NavProps) {
const [sidenavOpen, setSidenavOpen] = React.useState(false);
const [isUserMenuOpen, setIsUserMenuOpen] = React.useState(false);
const [userNames, setUserNames] = React.useState(null);
const [userInitials, setUserInitials] = React.useState(null);
const [isLoggedIn, setIsLoggedIn] = React.useState(true);

React.useEffect(() => {
authResource.getLoggedInUser().subscribe(({ person }) => {
const { display } = person;
setUserNames(display);
setUserInitials(
`${display.split(/\s/)[0][0]}${display.split(/\s/)[1][0]}`
);
});
}, []);

React.useEffect(() => {
const operation = sidenavOpen ? "add" : "remove";
Expand All @@ -14,29 +31,67 @@ function Root() {
};
}, [sidenavOpen]);

function logout() {
authResource
.logoutUser()
.then(() => setIsLoggedIn(false))
.catch(err => {
throw err;
});
}

if (!isLoggedIn) {
// @ts-ignore
return <Redirect to={`${window.getOpenmrsSpaBase()}login`} />;
}
return (
<nav className={styles.topNav}>
<button
className="omrs-unstyled omrs-padding-left-4 omrs-padding-right-4"
onClick={toggleSidenav}
>
<svg className={`omrs-icon ${styles.menuIcon}`}>
<use xlinkHref="#omrs-icon-menu" />
</svg>
</button>
<div className="omrs-type-title-4">
{/* We'll figure out whether to use document.title or not later */}
Home
</div>
<div className={styles.avatar}>AB</div>
</nav>
<BrowserRouter>
<React.Fragment>
<nav className={styles.topNav}>
<button
className="omrs-unstyled omrs-padding-left-4 omrs-padding-right-4"
onClick={toggleSidenav}
>
<svg className={`omrs-icon ${styles.menuIcon}`}>
<use xlinkHref="#omrs-icon-menu" />
</svg>
</button>
<div className="omrs-type-title-4">
{/* We'll figure out whether to use document.title or not later */}
Home
</div>
<div>
<button
onClick={() => setIsUserMenuOpen(!isUserMenuOpen)}
className={`omrs-unstyled ${styles.avatar}`}
>
{userInitials}
</button>
</div>
</nav>
<div className={toggle(styles.userMenu, styles.hidden, isUserMenuOpen)}>
<div className={`${styles.userMenuCard} omrs-padding-16`}>
<div className="omrs-type-body-large omrs-margin-12">
{userNames}
</div>
<button onClick={logout} className="omrs-btn omrs-outlined-neutral">
Logout
</button>
</div>
</div>
</React.Fragment>
</BrowserRouter>
);

function toggleSidenav() {
setSidenavOpen(!sidenavOpen);
}
}

type NavProps = {
history?: any;
};

export default openmrsRootDecorator({ featureName: "primary navigation" })(
Root
);
28 changes: 25 additions & 3 deletions src/root.styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,33 @@
}

.avatar {
border: 1px solid var(--omrs-color-bg-lowest-contrast);
border-radius: 50%;
padding: 0.5rem;
border: 1px solid var(--omrs-color-bg-lowest-contrast) !important;
border-radius: 50% !important;
padding: 0.5rem !important;
}

.menuIcon {
fill: var(--omrs-color-interaction);
}

.userMenu {
display: flex;
position: absolute;
justify-content: flex-end;
width: 100%;
right: 0;
}

.userMenuCard {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid var(--omrs-color-ink-lowest-contrast);
border-radius: 0 0 0.25rem 0.25rem;
background: var(--omrs-color-bg-high-contrast);
border-top: none;
}

.hidden {
display: none;
}

0 comments on commit 128d09c

Please sign in to comment.