Skip to content

Commit

Permalink
Merge pull request #22 from wordpress-mobile/feature/hook-setAttributes
Browse files Browse the repository at this point in the history
Wire up setAttributes
  • Loading branch information
maxme authored Mar 29, 2018
2 parents aafd0c2 + 3f0755b commit b19b73e
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 115 deletions.
20 changes: 12 additions & 8 deletions AppContainer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @format */
import { connect } from 'react-redux';
import {
updateBlockAttributes,
focusBlockAction,
moveBlockUpAction,
moveBlockDownAction,
Expand All @@ -15,17 +16,20 @@ const mapStateToProps = state => ( {
const mapDispatchToProps = ( dispatch, ownProps ) => {
return {
...ownProps,
focusBlockAction: index => {
dispatch( focusBlockAction( index ) );
onChange: ( uid, attributes ) => {
dispatch( updateBlockAttributes( uid, attributes ) );
},
moveBlockUpAction: index => {
dispatch( moveBlockUpAction( index ) );
focusBlockAction: uid => {
dispatch( focusBlockAction( uid ) );
},
moveBlockDownAction: index => {
dispatch( moveBlockDownAction( index ) );
moveBlockUpAction: uid => {
dispatch( moveBlockUpAction( uid ) );
},
deleteBlockAction: index => {
dispatch( deleteBlockAction( index ) );
moveBlockDownAction: uid => {
dispatch( moveBlockDownAction( uid ) );
},
deleteBlockAction: uid => {
dispatch( deleteBlockAction( uid ) );
},
};
};
Expand Down
24 changes: 12 additions & 12 deletions block-management/block-holder.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@ import React from 'react';
import { StyleSheet, View, Text, TouchableWithoutFeedback } from 'react-native';
import Toolbar from './toolbar';

import type { BlockType } from '../store/';

// Gutenberg imports
import { getBlockType } from '@gutenberg/blocks/api';

type PropsType = {
index: number,
blockType: string,
content: string,
focused: boolean,
onToolbarButtonPressed: ( button: number, index: number ) => void,
onBlockHolderPressed: ( rowId: number ) => void,
type PropsType = BlockType & {
onChange: ( uid: string, attributes: mixed ) => void,
onToolbarButtonPressed: ( button: number, uid: string ) => void,
onBlockHolderPressed: ( uid: string ) => void,
};
type StateType = { selected: boolean, focused: boolean };

export default class BlockHolder extends React.Component<PropsType, StateType> {
renderToolbarIfBlockFocused() {
if ( this.props.focused ) {
return (
<Toolbar index={ this.props.index } onButtonPressed={ this.props.onToolbarButtonPressed } />
<Toolbar uid={ this.props.uid } onButtonPressed={ this.props.onToolbarButtonPressed } />
);
} else {
// Return empty view, toolbar won't be rendered
Expand All @@ -39,20 +38,21 @@ export default class BlockHolder extends React.Component<PropsType, StateType> {
// TODO: setAttributes needs to change the state/attributes
return (
<Block
attributes={ { ...this.props } }
setAttributes={ attrs => console.log( { attrs } ) }
attributes={ { ...this.props.attributes } }
// pass a curried version of onChanged with just one argument
setAttributes={ attrs => this.props.onChange( this.props.uid, attrs ) }
/>
);
} else {
// Default block placeholder
return <Text>{ this.props.content }</Text>;
return <Text>{ this.props.attributes.content }</Text>;
}
}

render() {
return (
<TouchableWithoutFeedback
onPress={ this.props.onBlockHolderPressed.bind( this, this.props.index ) }
onPress={ this.props.onBlockHolderPressed.bind( this, this.props.uid ) }
>
<View style={ styles.blockHolder }>
<View style={ styles.blockTitle }>
Expand Down
41 changes: 18 additions & 23 deletions block-management/block-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,36 @@ import { StyleSheet, Text, View, FlatList, TextInput } from 'react-native';
import BlockHolder from './block-holder';
import { ToolbarButton } from './constants';

import type { BlockType } from '../store/';

export type BlockListType = {
focusBlockAction: number => mixed,
moveBlockUpAction: number => mixed,
moveBlockDownAction: number => mixed,
deleteBlockAction: number => mixed,
blocks: Array<{
key: string,
blockType: string,
content: string,
focused: boolean,
}>,
onChange: ( uid: string, attributes: mixed ) => void,
focusBlockAction: string => mixed,
moveBlockUpAction: string => mixed,
moveBlockDownAction: string => mixed,
deleteBlockAction: string => mixed,
blocks: Array<BlockType>,
refresh: boolean,
};

type PropsType = BlockListType;
type StateType = {};

export default class BlockManager extends React.Component<PropsType, StateType> {
onBlockHolderPressed( rowId: number ) {
this.props.focusBlockAction( rowId );
onBlockHolderPressed( uid: string ) {
this.props.focusBlockAction( uid );
}

onToolbarButtonPressed( button: number, index: number ) {
var blocks = this.props.blocks;
onToolbarButtonPressed( button: number, uid: string ) {
switch ( button ) {
case ToolbarButton.UP:
this.props.moveBlockUpAction( index );
this.props.moveBlockUpAction( uid );
break;
case ToolbarButton.DOWN:
this.props.moveBlockDownAction( index );
this.props.moveBlockDownAction( uid );
break;
case ToolbarButton.DELETE:
this.props.deleteBlockAction( index );
blocks.splice( index, 1 );
this.props.deleteBlockAction( uid );
break;
case ToolbarButton.SETTINGS:
// TODO: implement settings
Expand All @@ -57,22 +53,21 @@ export default class BlockManager extends React.Component<PropsType, StateType>
style={ styles.list }
data={ this.props.blocks }
extraData={ this.props.refresh }
keyExtractor={ ( item, index ) => item.uid }
renderItem={ this.renderItem.bind( this ) }
/>
</View>
);
}

renderItem( value: {
item: { key: string, blockType: string, content: string, focused: boolean },
index: number,
} ) {
renderItem( value: { item: BlockType, uid: string } ) {
return (
<BlockHolder
onToolbarButtonPressed={ this.onToolbarButtonPressed.bind( this ) }
onBlockHolderPressed={ this.onBlockHolderPressed.bind( this ) }
onChange={ this.props.onChange.bind( this ) }
focused={ value.item.focused }
index={ value.index }
uid={ value.uid }
{ ...value.item }
/>
);
Expand Down
16 changes: 6 additions & 10 deletions block-management/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { StyleSheet, Text, View, Button } from 'react-native';
import { ToolbarButton } from './constants';

type PropsType = {
index: number,
onButtonPressed: ( button: number, index: number ) => void,
uid: string,
onButtonPressed: ( button: number, uid: string ) => void,
};

export default class Toolbar extends React.Component<PropsType> {
Expand All @@ -15,30 +15,26 @@ export default class Toolbar extends React.Component<PropsType> {
<View style={ styles.toolbar }>
<Button
style={ styles.toolbarButton }
onPress={ this.props.onButtonPressed.bind( this, ToolbarButton.UP, this.props.index ) }
onPress={ this.props.onButtonPressed.bind( this, ToolbarButton.UP, this.props.uid ) }
title="Up"
/>
<Button
style={ styles.toolbarButton }
onPress={ this.props.onButtonPressed.bind( this, ToolbarButton.DOWN, this.props.index ) }
onPress={ this.props.onButtonPressed.bind( this, ToolbarButton.DOWN, this.props.uid ) }
title="Down"
/>
<Button
style={ styles.toolbarButton }
onPress={ this.props.onButtonPressed.bind(
this,
ToolbarButton.SETTINGS,
this.props.index
this.props.uid
) }
title="Settings"
/>
<Button
style={ styles.toolbarButton }
onPress={ this.props.onButtonPressed.bind(
this,
ToolbarButton.DELETE,
this.props.index
) }
onPress={ this.props.onButtonPressed.bind( this, ToolbarButton.DELETE, this.props.uid ) }
title="Delete"
/>
</View>
Expand Down
1 change: 1 addition & 0 deletions store/actions/ActionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

export default {
BLOCK: {
UPDATE_ATTRIBUTES: 'UPDATE_BLOCK_ATTRIBUTES',
FOCUS: 'BLOCK_FOCUS_ACTION',
MOVE_UP: 'BLOCK_MOVE_UP_ACTION',
MOVE_DOWN: 'BLOCK_MOVE_DOWN_ACTION',
Expand Down
28 changes: 18 additions & 10 deletions store/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,35 @@

import ActionTypes from './ActionTypes';

export type BlockActionType = number => {
export type BlockActionType = string => {
type: $Values<typeof ActionTypes.BLOCK>,
rowId: number,
uid: string,
};

export const focusBlockAction: BlockActionType = ( index: number ) => ( {
export function updateBlockAttributes( uid: string, attributes: mixed ) {
return {
type: ActionTypes.BLOCK.UPDATE_ATTRIBUTES,
uid,
attributes,
};
}

export const focusBlockAction: BlockActionType = uid => ( {
type: ActionTypes.BLOCK.FOCUS,
rowId: index,
uid: uid,
} );

export const moveBlockUpAction: BlockActionType = index => ( {
export const moveBlockUpAction: BlockActionType = uid => ( {
type: ActionTypes.BLOCK.MOVE_UP,
rowId: index,
uid: uid,
} );

export const moveBlockDownAction: BlockActionType = index => ( {
export const moveBlockDownAction: BlockActionType = uid => ( {
type: ActionTypes.BLOCK.MOVE_DOWN,
rowId: index,
uid: uid,
} );

export const deleteBlockAction: BlockActionType = index => ( {
export const deleteBlockAction: BlockActionType = uid => ( {
type: ActionTypes.BLOCK.DELETE,
rowId: index,
uid: uid,
} );
16 changes: 8 additions & 8 deletions store/actions/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ import ActionTypes from './ActionTypes';
describe( 'Store', () => {
describe( 'actions', () => {
it( 'should create an action to focus a block', () => {
const action = actions.focusBlockAction( 1 );
const action = actions.focusBlockAction( '1' );
expect( action.type ).toBeDefined();
expect( action.type ).toEqual( ActionTypes.BLOCK.FOCUS );
expect( action.rowId ).toEqual( 1 );
expect( action.uid ).toEqual( '1' );
} );

it( 'should create an action to move block up', () => {
const action = actions.moveBlockUpAction( 1 );
const action = actions.moveBlockUpAction( '1' );
expect( action.type ).toBeDefined();
expect( action.type ).toEqual( ActionTypes.BLOCK.MOVE_UP );
expect( action.rowId ).toEqual( 1 );
expect( action.uid ).toEqual( '1' );
} );

it( 'should create an action to move block down', () => {
const action = actions.moveBlockDownAction( 1 );
const action = actions.moveBlockDownAction( '1' );
expect( action.type ).toBeDefined();
expect( action.type ).toEqual( ActionTypes.BLOCK.MOVE_DOWN );
expect( action.rowId ).toEqual( 1 );
expect( action.uid ).toEqual( '1' );
} );

it( 'should create an action to delete a block', () => {
const action = actions.deleteBlockAction( 1 );
const action = actions.deleteBlockAction( '1' );
expect( action.type ).toBeDefined();
expect( action.type ).toEqual( ActionTypes.BLOCK.DELETE );
expect( action.rowId ).toEqual( 1 );
expect( action.uid ).toEqual( '1' );
} );
} );
} );
40 changes: 25 additions & 15 deletions store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { createStore } from 'redux';
import { reducer } from './reducers';

export type BlockType = {
key: string,
uid: string,
blockType: string,
content: string,
attributes: { content: string },
focused: boolean,
};

Expand All @@ -23,36 +23,46 @@ const initialState: StateType = {
// If not it should be created from a string parsing (commented HTML to json).
blocks: [
{
key: '0',
uid: '0',
blockType: 'title',
content: 'Hello World',
attributes: {
content: 'Hello World',
},
focused: false,
},
{
key: '1',
uid: '1',
blockType: 'paragraph',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer tempor tincidunt sapien, quis dictum orci sollicitudin quis. Proin sed elit id est pulvinar feugiat vitae eget dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
attributes: {
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer tempor tincidunt sapien, quis dictum orci sollicitudin quis. Proin sed elit id est pulvinar feugiat vitae eget dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
},
focused: false,
},
{
key: '2',
uid: '2',
blockType: 'paragraph',
content:
'書籍やウェブページや広告などのデザインのプロトタイプを制作したり顧客にプレゼンテーションしたりする際に、まだ正式な文章の出来上がっていないテキスト部分の書体(フォント)、タイポグラフィ、レイアウトなどといった視覚的なデザインを調整したりわかりやすく見せるために用いられる。',
attributes: {
content:
'書籍やウェブページや広告などのデザインのプロトタイプを制作したり顧客にプレゼンテーションしたりする際に、まだ正式な文章の出来上がっていないテキスト部分の書体(フォント)、タイポグラフィ、レイアウトなどといった視覚的なデザインを調整したりわかりやすく見せるために用いられる。',
},
focused: false,
},
{
key: '3',
uid: '3',
blockType: 'core/code',
content: 'if name == "World":\n return "Hello World"\nelse:\n return "Hello Pony"',
attributes: {
content: 'if name == "World":\n return "Hello World"\nelse:\n return "Hello Pony"',
},
focused: false,
},
{
key: '4',
uid: '4',
blockType: 'paragraph',
content:
'Лорем ипсум долор сит амет, адиписци трацтатос еа еум. Меа аудиам малуиссет те, хас меис либрис елеифенд ин. Нец ех тота деленит сусципит. Яуас порро инструцтиор но нец.',
attributes: {
content:
'Лорем ипсум долор сит амет, адиписци трацтатос еа еум. Меа аудиам малуиссет те, хас меис либрис елеифенд ин. Нец ех тота деленит сусципит. Яуас порро инструцтиор но нец.',
},
focused: false,
},
],
Expand Down
Loading

0 comments on commit b19b73e

Please sign in to comment.