Removed “AppHeader” and “FindBar” from UI

This commit is contained in:
Cássio Zen
2016-09-19 15:52:20 -03:00
parent af1c188a86
commit d7363f276e
7 changed files with 4 additions and 6 deletions

View File

@ -1,17 +0,0 @@
:root {
--foregroundColor: #fff;
--backgroundColor: #272e30;
--textFieldBorderColor: #e7e7e7;
--highlightFGColor: #fff;
--highlightBGColor: #3ab7a5;
}
.appBar {
background-color: var(--backgroundColor);
}
.createBtn {
position: fixed;
right: 2rem;
top: 3.5rem;
}

View File

@ -1,90 +0,0 @@
import React from 'react';
import pluralize from 'pluralize';
import { IndexLink } from 'react-router';
import { Menu, MenuItem, Button, IconButton } from 'react-toolbox';
import AppBar from 'react-toolbox/lib/app_bar';
import FindBar from '../FindBar/FindBar';
import styles from './AppHeader.css';
export default class AppHeader extends React.Component {
state = {
createMenuActive: false
}
handleCreatePostClick = collectionName => {
const { onCreateEntryClick } = this.props;
if (onCreateEntryClick) {
onCreateEntryClick(collectionName);
}
}
handleCreateButtonClick = () => {
this.setState({
createMenuActive: true
});
}
handleCreateMenuHide = () => {
this.setState({
createMenuActive: false
});
}
render() {
const {
collections,
commands,
defaultCommands,
runCommand,
toggleNavDrawer
} = this.props;
const { createMenuActive } = this.state;
return (
<AppBar
fixed
theme={styles}
>
<IconButton
icon="menu"
inverse
onClick={toggleNavDrawer}
/>
<IndexLink to="/">
Dashboard
</IndexLink>
<FindBar
commands={commands}
defaultCommands={defaultCommands}
runCommand={runCommand}
/>
<Button
className={styles.createBtn}
icon='add'
floating
accent
onClick={this.handleCreateButtonClick}
>
<Menu
active={createMenuActive}
position="topRight"
onHide={this.handleCreateMenuHide}
>
{
collections.valueSeq().map(collection =>
<MenuItem
key={collection.get('name')}
value={collection.get('name')}
onClick={this.handleCreatePostClick.bind(this, collection.get('name'))}
caption={pluralize(collection.get('label'), 1)}
/>
)
}
</Menu>
</Button>
</AppBar>
);
}
}

View File

@ -1,98 +0,0 @@
:root {
--foregroundColor: #fff;
--backgroundColor: #272e30;
--textFieldBorderColor: #e7e7e7;
--highlightFGColor: #fff;
--highlightBGColor: #3ab7a5;
}
.root {
flex: 1;
position: relative;
background-color: var(--backgroundColor);
padding: 5px;
}
.inputArea {
display: table;
width: 100%;
color: var(--foregroundColor);
background-color: #fff;
border: 1px solid var(--textFieldBorderColor);
}
.inputScope {
display: table-cell;
width: 1%;
padding: 0 6px 0 8px;
color: #767676;
font-size: 16px;
white-space: nowrap;
vertical-align: middle;
border-right: 1px solid var(--textFieldBorderColor);
margin:0;
}
.inputField {
display: table-cell;
width: 99%;
padding: 6px;
font-size: 16px;
background: none transparent;
border: 0 none;
box-shadow: none;
outline: none;
font-size: inherit;
}
.menu {
position: absolute;
top: 44px;
left: 0;
z-index: 9999;
display: table;
width: 100%;
background: var(--backgroundColor);
font-size: 13px;
font-weight: 400;
padding: 5px;
height: 100%;
}
.suggestions {
display: table-cell;
width: 50%;
padding-right: 10px;
}
.history {
display: table-cell;
width: 50%;
padding-left: 10px;
}
.command {
padding: 6px;
cursor: default;
color: var(--foregroundColor);
}
.command strong, .highlightedCommand strong {
color: #000;
}
.command .faded {
font-weight: 300;
color: #888;
}
.highlightedCommand {
color: var(--highlightFGColor);
background: var(--highlightBGColor);
padding: 6px;
cursor: default;
}
.highlightedCommand .faded {
font-weight: 300;
color: #282c34;
}

View File

@ -1,379 +0,0 @@
import React, { Component, PropTypes } from 'react';
import fuzzy from 'fuzzy';
import _ from 'lodash';
import { Icon } from '../index';
import styles from './FindBar.css';
export const SEARCH = 'SEARCH';
const PLACEHOLDER = 'Search or enter a command';
class FindBar extends Component {
constructor(props) {
super(props);
this._compiledCommands = [];
this._searchCommand = {
search: true,
regexp: `(?:${SEARCH})?(.*)`,
param: { name: 'searchTerm', display: '' },
token: SEARCH
};
this.state = {
value: '',
placeholder: PLACEHOLDER,
activeScope: null,
isOpen: false,
highlightedIndex: 0,
};
this._getSuggestions = _.memoize(this._getSuggestions, (value, activeScope) => value + activeScope);
this.compileCommand = this.compileCommand.bind(this);
this.matchCommand = this.matchCommand.bind(this);
this.maybeRemoveActiveScope = this.maybeRemoveActiveScope.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleInputBlur = this.handleInputBlur.bind(this);
this.handleInputFocus = this.handleInputFocus.bind(this);
this.handleInputClick = this.handleInputClick.bind(this);
this.getSuggestions = this.getSuggestions.bind(this);
this.highlightCommandFromMouse = this.highlightCommandFromMouse.bind(this);
this.selectCommandFromMouse = this.selectCommandFromMouse.bind(this);
this.setIgnoreBlur = this.setIgnoreBlur.bind(this);
}
componentWillMount() {
this._ignoreBlur = false;
}
componentDidMount() {
this._compiledCommands = this.props.commands.map(this.compileCommand);
}
_escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
_camelCaseToSpace(string) {
const result = string.replace(/([A-Z])/g, ' $1');
return result.charAt(0).toUpperCase() + result.slice(1);
}
// Generates a regexp and splits a token and param details for a command
compileCommand(command) {
let regexp = '';
let param = null;
const matcher = /\(:([a-zA-Z_$][a-zA-Z0-9_$]*)(?:(?: as )(.*))?\)/g;
const match = matcher.exec(command.pattern);
const matchIndex = match ? match.index : command.pattern.length;
const token = command.pattern.slice(0, matchIndex) || command.token;
regexp += this._escapeRegExp(command.pattern.slice(0, matchIndex));
if (match && match[1]) {
regexp += '(.*)';
param = { name: match[1], display: match[2] || this._camelCaseToSpace(match[1]) };
}
return Object.assign({}, command, {
regexp,
token,
param
});
}
// Check if the entered string matches any command.
// adds a scope (so user can type param value) and dispatches action for fully matched commands
matchCommand() {
const string = this.state.activeScope ? this.state.activeScope + this.state.value : this.state.value;
let match;
let command = this._compiledCommands.find(command => {
match = string.match(RegExp(`^${command.regexp}`, 'i'));
return match;
});
// If no command was found, trigger a search command
if (!command) {
command = this._searchCommand;
match = string.match(RegExp(`^${this._searchCommand.regexp}`, 'i'));
}
const paramName = command && command.param ? command.param.name : null;
const enteredParamValue = command && command.param && match[1] ? match[1].trim() : null;
console.log(this.props.runCommand);
if (command.search) {
this.setState({
activeScope: SEARCH,
placeholder: ''
});
enteredParamValue && this.props.runCommand(SEARCH, { searchTerm: enteredParamValue });
} else if (command.param && !enteredParamValue) {
// Partial Match
// Command was partially matched: It requires a param, but param wasn't entered
// Set a scope so user can fill the param
this.setState({
value: '',
activeScope: command.token,
placeholder: command.param.display
});
} else {
// Match
// Command was matched and either it doesn't require a param or it's required param was entered
// Dispatch action
this.setState({
value: '',
placeholder: PLACEHOLDER,
activeScope: null
}, () => {
this._input.blur();
});
const payload = command.payload || {};
if (paramName) {
payload[paramName] = enteredParamValue;
}
this.props.runCommand(command.type, payload);
}
}
maybeRemoveActiveScope() {
if (this.state.value.length === 0 && this.state.activeScope) {
this.setState({
activeScope: null,
placeholder: PLACEHOLDER
});
}
}
getSuggestions() {
return this._getSuggestions(this.state.value, this.state.activeScope, this._compiledCommands, this.props.defaultCommands);
}
// Memoized version
_getSuggestions(value, scope, commands, defaultCommands) {
if (scope) return []; // No autocomplete for scoped input
if (value.length === 0 && defaultCommands) {
return commands
.filter(command => defaultCommands.indexOf(command.id) !== -1)
.map(result => (
Object.assign({}, result, { string: result.token }
)));
}
const results = fuzzy.filter(value, commands, {
pre: '<strong>',
post: '</strong>',
extract: el => el.token
});
const returnResults = results.slice(0, 4).map(result => (
Object.assign({}, result.original, { string: result.string }
)));
returnResults.push(this._searchCommand);
return returnResults;
}
handleKeyDown(event) {
let highlightedIndex, index;
switch (event.key) {
case 'ArrowDown':
event.preventDefault();
highlightedIndex = this.state.highlightedIndex;
index = (
highlightedIndex === this.getSuggestions().length - 1 ||
this.state.isOpen === false
) ? 0 : highlightedIndex + 1;
this.setState({
highlightedIndex: index,
isOpen: true,
});
break;
case 'ArrowUp':
event.preventDefault();
highlightedIndex = this.state.highlightedIndex;
index = (
highlightedIndex === 0
) ? this.getSuggestions().length - 1 : highlightedIndex - 1;
this.setState({
highlightedIndex: index,
isOpen: true,
});
break;
case 'Enter':
if (this.state.isOpen) {
const command = this.getSuggestions()[this.state.highlightedIndex];
const newState = {
isOpen: false,
highlightedIndex: 0
};
if (command && !command.search) {
newState.value = command.token;
}
this.setState(newState, () => {
this._input.focus();
this._input.setSelectionRange(
this.state.value.length,
this.state.value.length
);
this.matchCommand();
});
}
break;
case 'Escape':
this.setState({
value: '',
highlightedIndex: 0,
isOpen: false,
activeScope: null,
placeholder: PLACEHOLDER
});
break;
case 'Backspace':
this.setState({
highlightedIndex: 0,
isOpen: true
}, this.maybeRemoveActiveScope);
break;
default:
this.setState({
highlightedIndex: 0,
isOpen: true
});
}
}
handleChange(event) {
this.setState({
value: event.target.value,
});
}
handleInputBlur() {
if (this._ignoreBlur) return;
this.setState({
isOpen: false,
highlightedIndex: 0
});
}
handleInputFocus() {
if (this._ignoreBlur) return;
this.setState({ isOpen: true });
}
handleInputClick() {
if (this.state.isOpen === false)
this.setState({ isOpen: true });
}
highlightCommandFromMouse(index) {
this.setState({ highlightedIndex: index });
}
selectCommandFromMouse(command) {
const newState = {
isOpen: false,
highlightedIndex: 0
};
if (command && !command.search) {
newState.value = command.token;
}
this.setState(newState, () => {
this.matchCommand();
this._input.focus();
this.setIgnoreBlur(false);
});
}
setIgnoreBlur(ignore) {
this._ignoreBlur = ignore;
}
renderMenu() {
const commands = this.getSuggestions().map((command, index) => {
let children;
if (!command.search) {
children = (
<span><span dangerouslySetInnerHTML={{ __html: command.string }}/></span>
);
} else {
children = (
<span>
{this.state.value.length === 0 ?
<span><Icon type="search"/>Search... </span> :
<span className={styles.faded}><Icon type="search"/>Search for: </span>
}
<strong>{this.state.value}</strong>
</span>
);
}
return (
<div
className={this.state.highlightedIndex === index ? styles.highlightedCommand : styles.command}
key={command.token.trim().replace(/[^a-z0-9]+/gi, '-')}
onMouseDown={() => this.setIgnoreBlur(true)}
onMouseEnter={() => this.highlightCommandFromMouse(index)}
onClick={() => this.selectCommandFromMouse(command)}
>
{children}
</div>
);
});
return commands.length === 0 ? null : (
<div className={styles.menu}>
<div className={styles.suggestions}>
{commands}
</div>
<div className={styles.history}>
Your past searches and commands
</div>
</div>
);
}
renderActiveScope() {
if (this.state.activeScope === SEARCH) {
return <div className={styles.inputScope}><Icon type="search"/></div>;
} else {
return <div className={styles.inputScope}>{this.state.activeScope}</div>;
}
}
render() {
const menu = this.state.isOpen && this.renderMenu();
const scope = this.state.activeScope && this.renderActiveScope();
return (
<div className={styles.root}>
<label className={styles.inputArea}>
{scope}
<input
className={styles.inputField}
ref={(c) => this._input = c}
onFocus={this.handleInputFocus}
onBlur={this.handleInputBlur}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onClick={this.handleInputClick}
placeholder={this.state.placeholder}
value={this.state.value}
/>
</label>
{menu}
</div>
);
}
}
FindBar.propTypes = {
commands: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
pattern: PropTypes.string.isRequired
})).isRequired,
defaultCommands: PropTypes.arrayOf(PropTypes.string),
runCommand: PropTypes.func.isRequired,
};
export default FindBar;

View File

@ -2,4 +2,3 @@ export { default as Card } from './card/Card';
export { default as Loader } from './loader/Loader';
export { default as Icon } from './icon/Icon';
export { default as Toast } from './toast/Toast';
export { default as AppHeader } from './AppHeader/AppHeader';