Skip to content

Commit

Permalink
feat(HeaderBar): add user account dropdown on header bar
Browse files Browse the repository at this point in the history
Creates AccountDropdown as the menu list and AccountDropdownTrigger as the
dropdown display. Adds accompanying typescript files.

Closes DCOS-38940
  • Loading branch information
Tommy Nguyen authored and weblancaster committed Jul 18, 2018
1 parent cbaf561 commit 84cd37e
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 4 deletions.
1 change: 1 addition & 0 deletions packages/ui-kit-stage/HeaderBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import * as React from "react";
import { coreColors } from "@dcos/ui-kit/dist/packages/shared/styles/color";

// TODO: DCOS-39074
const headerBarStyles: object = {
backgroundColor: coreColors().purpleDarken4,
height: "32px",
Expand Down
9 changes: 9 additions & 0 deletions src/js/components/AccountDropdown.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from "react";

interface AccountDropdownProps {
userName?: null | string;
menuItems?: object;
willAnchorRight?: boolean;
}

export default class AccountDropdown extends Component<AccountDropdownProps> {}
56 changes: 56 additions & 0 deletions src/js/components/AccountDropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Dropdown } from "reactjs-components";
import React from "react";

import AuthStore from "#SRC/js/stores/AuthStore";
import AccountDropdownTrigger from "./AccountDropdownTrigger";

class AccountDropdown extends React.Component {
constructor() {
super(...arguments);
this.userLabel = AuthStore.getUserLabel();
}

getMenuItems() {
const menuItems = [
{
className: "dropdown-menu-section-header",
html: <label>{this.userLabel}</label>,
id: "header-support",
selectable: false
},
{
html: "Sign Out",
id: "sign-out",
onClick: AuthStore.logout
}
];

return menuItems;
}

getTrigger() {
return <AccountDropdownTrigger content={this.userLabel} />;
}

handleItemSelection(item) {
if (item.onClick) {
item.onClick();
}
}

render() {
return (
<Dropdown
trigger={this.getTrigger()}
dropdownMenuClassName="user-account-dropdown-menu dropdown-menu header-bar-dropdown-menu"
dropdownMenuListClassName="user-account-dropdown-list dropdown-menu-list"
items={this.getMenuItems()}
onItemSelection={this.handleItemSelection}
persistentID="dropdown-trigger"
transition={true}
/>
);
}
}

module.exports = AccountDropdown;
43 changes: 43 additions & 0 deletions src/js/components/AccountDropdownTrigger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import mixin from "reactjs-mixin";
import PropTypes from "prop-types";
import React from "react";
import { StoreMixin } from "mesosphere-shared-reactjs";

class AccountDropdownTrigger extends mixin(StoreMixin) {
constructor() {
super(...arguments);

this.store_listeners = [
{
name: "metadata",
events: ["success"],
listenAlways: false
}
];
}

componentDidUpdate() {
if (this.props.onUpdate) {
this.props.onUpdate();
}
}

render() {
const { content, onTrigger } = this.props;

// TODO: DCOS-38944
return (
<a className="header-bar-dropdown" onClick={onTrigger}>
<span>{content}</span>
</a>
);
}
}

AccountDropdownTrigger.propTypes = {
content: PropTypes.string.isRequired,
onUpdate: PropTypes.func,
onTrigger: PropTypes.func
};

module.exports = AccountDropdownTrigger;
4 changes: 3 additions & 1 deletion src/js/components/HeaderBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as React from "react";

import { HeaderBar as UIHeaderBar } from "ui-kit-stage/HeaderBar";
import ClusterDropdown from "./ClusterDropdown";
import AccountDropdown from "./AccountDropdown";

export default function HeaderBar() {
// remove this to activate component
Expand All @@ -14,7 +16,7 @@ export default function HeaderBar() {
<div className="header-bar-logo-wrapper">
<div className="header-bar-logo" />
</div>
<span>user-menu component here</span>
<AccountDropdown />
<ClusterDropdown />
</UIHeaderBar>
);
Expand Down
13 changes: 13 additions & 0 deletions src/js/stores/AuthStore.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import GetSetBaseStore from "./GetSetBaseStore";

export default class AuthStore extends GetSetBaseStore {
constructor();
static login: () => void;
static logout(): void;
static isLoggedIn: () => boolean;
static getUser: () => null | object;
static getUserLabel: () => null | string;
processLoginSuccess: () => void;
processLogoutSuccess: () => void;
static storeID: () => string;
}
14 changes: 14 additions & 0 deletions src/js/stores/AuthStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ class AuthStore extends GetSetBaseStore {
}
}

getUserLabel() {
const user = this.getUser();

if (!user) {
return null;
}

if (!user.is_remote) {
return user.description;
}

return user.uid;
}

processLoginSuccess() {
Hooks.doAction("userLoginSuccess");
this.emit(AUTH_USER_LOGIN_CHANGED);
Expand Down
6 changes: 6 additions & 0 deletions src/js/stores/BaseStore.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { EventEmitter } from "events";

export default class BaseStore extends EventEmitter {
addChangeListener: (eventName: string, callback: () => void) => void;
removeChangeListener: (eventName: string, callback: () => void) => void;
}
6 changes: 6 additions & 0 deletions src/js/stores/GetSetBaseStore.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import BaseStore from "./BaseStore";

export default class GetSetBaseStore extends BaseStore {
get: (key: string) => null | object;
set: (data: object) => void;
}
39 changes: 36 additions & 3 deletions src/styles/components/header-bar/styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
.header-bar-logo-wrapper {
display: inline-block;
height: 16px;
margin-left: 10px;
margin-top: 10px;
margin-top: 5px;
overflow: hidden;
width: @full-logo-width;

Expand All @@ -19,7 +18,7 @@

& when (@layout-screen-small-enabled) {

@media (max-width: @layout-screen-small-min-width) {
@media (max-width: @layout-screen-small-max-width) {
width: @short-logo-width;
}
}
Expand All @@ -37,4 +36,38 @@
margin-left: 6px;
}
}

.header-bar-dropdown {
color: @purple-lighten-4;
cursor: pointer;
display: inline-flex;
padding-left: 15px;
text-decoration: none;

&:hover {
color: @white;
text-decoration: none;
}

&:after {
.triangle-base();
.triangle-color('down', @purple-lighten-4);
align-self: center;
content: '';
display: inline-block;
margin-left: 6px;

& when not (@header-dropdown-caret-width = null) {
.triangle-size-width('down', @header-dropdown-caret-width);
}

& when not (@header-dropdown-caret-height = null) {
.triangle-size-height('down', @header-dropdown-caret-height);
}
}
}

.header-bar-dropdown-menu.down {
margin-top: 10px;
}
}
3 changes: 3 additions & 0 deletions src/styles/components/header-bar/variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@

@full-logo-width: 166px;
@short-logo-width: 20px;

@header-dropdown-caret-width: 10px;
@header-dropdown-caret-height: 6px;

0 comments on commit 84cd37e

Please sign in to comment.