From 73c5eaf276e36594b1da9a6b2e450d1afdfa11e1 Mon Sep 17 00:00:00 2001 From: Anton Timmermans Date: Thu, 23 Nov 2017 12:00:37 +0100 Subject: [PATCH] Try block annotation, starting with full annotation --- editor/actions.js | 22 +++++++++++++++ editor/components/block-list/block.js | 5 +++- editor/components/block-list/style.scss | 4 +++ .../components/block-settings-menu/index.js | 15 +++++++++-- editor/reducer.js | 14 ++++++++++ editor/selectors.js | 27 +++++++++++++++++++ 6 files changed, 84 insertions(+), 3 deletions(-) diff --git a/editor/actions.js b/editor/actions.js index a35fb7ba337ff..18c016f323de4 100644 --- a/editor/actions.js +++ b/editor/actions.js @@ -576,3 +576,25 @@ export function convertBlockToReusable( uid ) { uid, }; } + +/** + * Returns an action object used to add an annotation to the editor. + * + * @param {string} start The ID of the block to start the annotation. + * @param {string} end The ID of the block to end the annotation. + * @returns {Object} Action object. + */ +export function annotateBlocks( start, end ) { + return { + type: 'ADD_ANNOTATION', + annotation: { + start: { + block: start, + }, + end: { + block: end, + }, + blockAnnotation: true, + }, + }; +} diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index d175136ed9930..f942eeef51277 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -52,6 +52,7 @@ import { isFirstMultiSelectedBlock, isTyping, getBlockMode, + getAnnotationsForBlock, } from '../../selectors'; const { BACKSPACE, ESCAPE, DELETE, ENTER, UP, RIGHT, DOWN, LEFT } = keycodes; @@ -346,7 +347,7 @@ class BlockListBlock extends Component { // (mover, toolbar, wrapper) and the display of the block content. // Generate the wrapper class names handling the different states of the block. - const { isHovered, isSelected, isMultiSelected, isFirstMultiSelected, focus } = this.props; + const { isHovered, isSelected, isMultiSelected, isFirstMultiSelected, focus, annotations } = this.props; const showUI = isSelected && ( ! this.props.isTyping || ( focus && focus.collapsed === false ) ); const { error } = this.state; const wrapperClassName = classnames( 'editor-block-list__block', { @@ -354,6 +355,7 @@ class BlockListBlock extends Component { 'is-selected': showUI, 'is-multi-selected': isMultiSelected, 'is-hovered': isHovered, + 'is-fully-annotated': annotations.filter( annotation => annotation.blockAnnotation ).length !== 0, } ); const { onMouseLeave, onFocus, onReplace } = this.props; @@ -453,6 +455,7 @@ export default connect( order: getBlockIndex( state, ownProps.uid ), meta: getEditedPostAttribute( state, 'meta' ), mode: getBlockMode( state, ownProps.uid ), + annotations: getAnnotationsForBlock( state, ownProps.uid ), }; }, ( dispatch, ownProps ) => ( { diff --git a/editor/components/block-list/style.scss b/editor/components/block-list/style.scss index b896388aad6b6..6684fa9cd6d54 100644 --- a/editor/components/block-list/style.scss +++ b/editor/components/block-list/style.scss @@ -91,6 +91,10 @@ background: $blue-medium-highlight; } + &.is-fully-annotated { + outline: 1px solid red; + } + .iframe-overlay { position: relative; } diff --git a/editor/components/block-settings-menu/index.js b/editor/components/block-settings-menu/index.js index c8d3b5a72c337..097871267b4dd 100644 --- a/editor/components/block-settings-menu/index.js +++ b/editor/components/block-settings-menu/index.js @@ -3,6 +3,7 @@ */ import classnames from 'classnames'; import { connect } from 'react-redux'; +import { flow, noop, head, last } from 'lodash'; /** * WordPress dependencies @@ -18,9 +19,9 @@ import BlockInspectorButton from './block-inspector-button'; import BlockModeToggle from './block-mode-toggle'; import BlockDeleteButton from './block-delete-button'; import UnknownConverter from './unknown-converter'; -import { selectBlock } from '../../actions'; +import { selectBlock, annotateBlocks } from '../../actions'; -function BlockSettingsMenu( { uids, onSelect, focus } ) { +function BlockSettingsMenu( { uids, onSelect, focus, onAnnotate } ) { const count = uids.length; return ( @@ -55,6 +56,13 @@ function BlockSettingsMenu( { uids, onSelect, focus } ) { { count === 1 && } { count === 1 && } + onAnnotate( uids ) } + icon="admin-generic" + > + { __( 'Annotate' ) } + ) } @@ -68,5 +76,8 @@ export default connect( onSelect( uid ) { dispatch( selectBlock( uid ) ); }, + onAnnotate( uids ) { + dispatch( annotateBlocks( head( uids ), last( uids ) ) ); + } } ) )( BlockSettingsMenu ); diff --git a/editor/reducer.js b/editor/reducer.js index 145dbcdc969de..859260d1af66c 100644 --- a/editor/reducer.js +++ b/editor/reducer.js @@ -717,6 +717,19 @@ export const reusableBlocks = combineReducers( { }, } ); +export function annotations( state = [], action ) { + switch ( action.type ) { + case 'ADD_ANNOTATION': + return [ + action.annotation, + ...state + ]; + break; + } + + return state; +} + export default optimist( combineReducers( { editor, currentPost, @@ -731,4 +744,5 @@ export default optimist( combineReducers( { notices, metaBoxes, reusableBlocks, + annotations, } ) ); diff --git a/editor/selectors.js b/editor/selectors.js index a3e231995f062..9eff3570d41ba 100644 --- a/editor/selectors.js +++ b/editor/selectors.js @@ -1072,3 +1072,30 @@ export function isSavingReusableBlock( state, ref ) { export function getReusableBlocks( state ) { return Object.values( state.reusableBlocks.data ); } + +/** + * Returns all the annotations for a specific block. + * + * @param {Object} state Global application state. + * @param {string} uid The block UID to get annotations for. + * @returns {Object[]} The annotations relevant for this block. + */ +export const getAnnotationsForBlock = createSelector( + ( state, uid ) => { + const { blockOrder } = state.editor.present; + const { annotations } = state; + + return annotations.filter( ( annotation ) => { + const startIndex = blockOrder.indexOf( annotation.start.block ); + const endIndex = blockOrder.indexOf( annotation.end.block ); + + const annotatedBlocks = blockOrder.slice( startIndex, endIndex + 1 ); + + return annotatedBlocks.includes( uid ); + } ); + }, + ( state, uid ) => [ + state.annotations, + ], +); +