Improve categories tooltip.
- Manage categories with comment enabled.
- Rename mark type to "category".
- Simplify code, use only one mark type.
--- a/client/src/App.scss Thu Jun 08 17:57:57 2017 +0200
+++ b/client/src/App.scss Thu Jun 08 18:54:36 2017 +0200
@@ -40,7 +40,7 @@
z-index: 1;
top: -10000px;
left: -10000px;
- margin-top: -64px;
+ margin-top: -20px;
opacity: 0;
transition: opacity .75s;
}
--- a/client/src/HtmlSerializer.js Thu Jun 08 17:57:57 2017 +0200
+++ b/client/src/HtmlSerializer.js Thu Jun 08 18:54:36 2017 +0200
@@ -10,7 +10,7 @@
em: 'italic',
strong: 'bold',
u: 'underline',
- annotation: 'span'
+ category: 'span'
}
const rules = [
@@ -51,7 +51,7 @@
case 'bold': return <strong>{children}</strong>
case 'italic': return <em>{children}</em>
case 'underline': return <u>{children}</u>
- case 'annotation': return <span style={{ backgroundColor: object.data.get('color') }}>{children}</span>
+ case 'category': return <span style={{ backgroundColor: object.data.get('color') }}>{children}</span>
default: return;
}
}
--- a/client/src/components/CategoriesTooltip.js Thu Jun 08 17:57:57 2017 +0200
+++ b/client/src/components/CategoriesTooltip.js Thu Jun 08 18:54:36 2017 +0200
@@ -3,24 +3,65 @@
class CategoriesTooltip extends Component {
+ state = {
+ activeCategory: null,
+ showCommentControl: false
+ }
+
+ componentDidUpdate = () => {
+ if (this.state.showCommentControl) {
+ this.commentControl.focus();
+ }
+ }
+
+ isCategoryActive = (category) => {
+ return this.state.activeCategory && this.state.activeCategory.key === category.key
+ }
+
onButtonClick = (category) => {
- if (typeof this.props.onCategoryClick === 'function') {
- this.props.onCategoryClick(category)
+ if (category.hasOwnProperty('hasComment') && category.hasComment === true) {
+ this.setState({
+ activeCategory: this.state.activeCategory ? null : category,
+ showCommentControl: !this.state.showCommentControl
+ })
+ } else {
+ if (typeof this.props.onCategoryClick === 'function') {
+ this.props.onCategoryClick(category)
+ }
+ }
+ }
+
+ onSubmit = (e) => {
+ e.preventDefault();
+ if (this.state.showCommentControl) {
+ const comment = this.commentControl.value;
+ const { activeCategory } = this.state;
+ Object.assign(activeCategory, { comment: comment });
+ if (typeof this.props.onCategoryClick === 'function') {
+ this.props.onCategoryClick(activeCategory)
+ }
}
}
render() {
return (
<div className="categories-tooltip">
- <FormGroup className="buttons">
- {this.props.categories.map((category) =>
- <Button key={ category.name } bsStyle="primary" style={{ backgroundColor: category.color }}
- onClick={this.onButtonClick.bind(this, category)}>{ category.name }</Button>
- )}
- </FormGroup>
- <FormGroup>
- <FormControl />
- </FormGroup>
+ <form onSubmit={ this.onSubmit }>
+ <FormGroup className="buttons">
+ {this.props.categories.map((category) =>
+ <Button
+ key={ category.name }
+ bsStyle="primary"
+ style={{ backgroundColor: category.color }}
+ active={ this.isCategoryActive(category) }
+ onClick={ this.onButtonClick.bind(this, category) }>{ category.name }</Button>
+ )}
+ </FormGroup>
+ {this.state.showCommentControl &&
+ <FormGroup>
+ <FormControl inputRef={(ref) => { this.commentControl = ref; }} />
+ </FormGroup>}
+ </form>
</div>
);
}
--- a/client/src/components/SlateEditor.js Thu Jun 08 17:57:57 2017 +0200
+++ b/client/src/components/SlateEditor.js Thu Jun 08 18:54:36 2017 +0200
@@ -31,14 +31,7 @@
bold: {
fontWeight: 'bold'
},
- // This is a "temporary" mark added when the hovering menu is open
- highlight: {
- textDecoration: 'underline',
- textDecorationStyle: 'dotted',
- backgroundColor: '#ccc',
- },
- // This is the mark actually used for annotations
- annotation: props => {
+ category: props => {
const data = props.mark.data;
return <span style={{ backgroundColor: data.get('color') }}>{props.children}</span>
},
@@ -54,7 +47,7 @@
const annotationCategories = [
{ key: 'important', name: 'Important', color: '#F1C40F' },
{ key: 'keyword', name: 'Mot-clé', color: '#2ECC71' },
- { key: 'comment', name: 'Commentaire', color: '#3498DB' }
+ { key: 'comment', name: 'Commentaire', color: '#3498DB', hasComment: true }
];
/**
@@ -227,25 +220,25 @@
onClickMark = (e, type) => {
e.preventDefault()
- let { state, hoveringMenu } = this.state
+ const { state } = this.state
+ const transform = state.transform()
- let toggleMarkOptions;
let isPortalOpen = false;
- if (type === 'highlight') {
- toggleMarkOptions = { type: type, data: { text: this.state.currentSelectionText } }
- isPortalOpen = !this.state.isPortalOpen;
+ if (type === 'category') {
+ // Can't use toggleMark here, because it expects the same object
+ // @see https://github.com/ianstormtaylor/slate/issues/873
+ if (this.hasMark('category')) {
+ state.marks.forEach(mark => transform.removeMark(mark));
+ } else {
+ isPortalOpen = !this.state.isPortalOpen;
+ }
} else {
- toggleMarkOptions = type;
+ transform.toggleMark(type)
}
- state = state
- .transform()
- .toggleMark(toggleMarkOptions)
- .apply()
-
this.setState({
- state: state,
+ state: transform.apply(),
isPortalOpen: isPortalOpen
})
}
@@ -314,16 +307,9 @@
}
onPortalClose = (portal) => {
-
let { state } = this.state
const transform = state.transform();
- state.marks.forEach(mark => {
- if (mark.type === 'highlight') {
- transform.removeMark(mark)
- }
- });
-
this.setState({
state: transform.apply(),
isPortalOpen: false
@@ -336,9 +322,8 @@
const transform = state.transform();
state.marks.forEach(mark => transform.removeMark(mark));
-
transform.addMark({
- type: 'annotation',
+ type: 'category',
data: {
text: this.state.currentSelectionText,
color: category.color,
@@ -350,7 +335,6 @@
state: transform.apply(),
isPortalOpen: false
});
-
}
/**
@@ -380,7 +364,7 @@
{this.renderMarkButton('bold', 'format_bold')}
{this.renderMarkButton('italic', 'format_italic')}
{this.renderMarkButton('underlined', 'format_underlined')}
- {this.renderMarkButton('highlight', 'label')}
+ {this.renderMarkButton('category', 'label')}
{this.renderBlockButton('numbered-list', 'format_list_numbered')}
{this.renderBlockButton('bulleted-list', 'format_list_bulleted')}