diff --git a/README.md b/README.md index bddf986..02e48b6 100644 --- a/README.md +++ b/README.md @@ -19,24 +19,50 @@ Built with [WDS Block Starter](https://github.com/WebDevStudios/wds-block-starte When the Initiative Tracker block is active (i.e., selected for editing) in the block editor, characters are divided into Players (PCs) and NPCs and sorted alphabetically in ascending order. Otherwise, both character lists are combined and sorted according to initiative score in descending order. ### How should I use this block? ### -This block is best for Game Masters who have a fairly good plan for the session's combat ahead of time. Prior to the start of the session, create a fresh page or post for the session and add an Initiative Tracker block. Populate the block with the players (PCs), then duplicate the block for as many combats you expect to encounter (this way you don't have to re-enter players for each block). Next, add the different NPCs for each encounter to each block – bonus: pre-roll your NPCs' initiative scores and enter those into the blocks ahead of time. Finally, during gameplay, input the players' initiative scores for the current round of combat, save your page or post, and flip to the frontend to iterate through the active characters. +This block is best for games where there's a fairly good plan for the session's combat ahead of time. Prior to the start of the session, create a fresh page or post for the session, and add an Initiative Tracker block. Populate the block with the players (PCs), then duplicate the block for as many combats you expect to encounter (this way you don't have to re-enter players for each block). Next, add the different NPCs for each encounter to each block – bonus: roll your NPCs' initiative scores and enter those into the blocks ahead of time – and save your post. Finally, during gameplay, input the players' initiative scores for the current round of combat on the frontend by clicking "Edit Initiative", entering player scores, then clicking "Save Initiative." Now you can click "Next Character" to iterate through the active characters. ### How can I report issues or suggest improvements? ### Feel free to create an issue or PR in the [Github repo here](https://github.com/ravewebdev/initiative-tracker). ## Screenshots ## -### Admin Demo 1: Insert Initiative Tracker block ### -![Admin Demo 1: Insert Initiative Tracker block](assets/screenshot-1.gif) +### Admin Demo: Insert Initiative Tracker Block and Add Characters ### +![Admin Demo: Insert Initiative Tracker Block and Add Characters](assets/screenshot-1.gif) -### Admin Demo 2: Add Combat Notes and Characters ### -![Admin Demo 2: Add Combat Notes and Characters](assets/screenshot-2.gif) +### Frontend Demo 1: Edit Character Initiative ### +![Frontend Demo 1: Edit Character Initiative](assets/screenshot-2.gif) -### Frontend Demo: Cycle through active characters ### -![Frontend Demo: Cycle through active characters](assets/screenshot-3.gif) +### Frontend Demo 2: Cycle Active Character ### +![Frontend Demo: Cycle Active Character](assets/screenshot-3.gif) ## Changelog ## +### NEXT ### +* Fixed: Changed character edit `` tags to ` - - - - ); + return ( +
+ { + setState( { + ...state, + name: newName, + nameIsEmpty: ( '' === newName.trim() ), + } ); + } } + className={ null !== name && nameIsEmpty ? errorClass : '' } + onKeyPress={ maybeSubmitForm } + /> + { isPlayer && ( + { + setState( { + ...state, + player: newPlayer, + playerIsEmpty: ( '' === newPlayer.trim() ), + } ); + } } + className={ null !== player && playerIsEmpty ? errorClass : '' } + onKeyPress={ maybeSubmitForm } + /> + ) } + { + setState( { + ...state, + initiative: newInitiative, + } ); + } } + onKeyPress={ maybeSubmitForm } + min="0" + /> +
+ + +
+
+ ); }; export default AddEditCharacterForm; diff --git a/src/block/initiative-tracker/components/Character.js b/src/block/initiative-tracker/components/Character.js index 653b5a9..1786bd4 100644 --- a/src/block/initiative-tracker/components/Character.js +++ b/src/block/initiative-tracker/components/Character.js @@ -3,15 +3,9 @@ */ const { - i18n: { - __, - }, - components: { - TextControl, + element: { + useState, }, - element: { - useState, - }, } = wp; /** @@ -71,7 +65,7 @@ const Character = ( props ) => { /** * Display Initiative inputs if editing on frontend. * - * @author Rebekah Van Epps + * @author R A Van Epps * @since 2.0.0 * * @return {ReactElement} JSX for read-only or editable initiative score. @@ -93,11 +87,11 @@ const Character = ( props ) => { { '' !== player && ( <>   - { `( ${ player } )`} + { `( ${ player } )` } ) } -  —  +  :  { displayInitiative() } diff --git a/src/block/initiative-tracker/components/CharacterList.js b/src/block/initiative-tracker/components/CharacterList.js index 5660bc0..2351aaf 100644 --- a/src/block/initiative-tracker/components/CharacterList.js +++ b/src/block/initiative-tracker/components/CharacterList.js @@ -3,12 +3,11 @@ */ import Character from './Character'; -import AddEditCharacterForm from './AddEditCharacterForm'; const { - element: { - useState, - }, + element: { + useState, + }, } = wp; /** @@ -59,12 +58,12 @@ const CharacterList = ( props ) => { const onFrontend = null !== activeIndex; return ( -
+

{ title }

{ null !== children && children } - { characters.length > 0 && ( + { 0 < characters.length && (
    { characters.map( ( character, index ) => ( { <> @@ -63,26 +63,26 @@ const DeleteCharacterModal = ( props ) => {
    - -
    + isSecondary + onClick={ toggle } + > + { __( 'Cancel', 'initiative-tracker' ) } + + +
) } ); -} +}; export default DeleteCharacterModal; diff --git a/src/block/initiative-tracker/components/FrontendTracker.js b/src/block/initiative-tracker/components/FrontendTracker.js index c211e4d..9f84fc4 100644 --- a/src/block/initiative-tracker/components/FrontendTracker.js +++ b/src/block/initiative-tracker/components/FrontendTracker.js @@ -10,16 +10,16 @@ import { sortCharacters } from '../util'; const { apiFetch, i18n: { - __, - }, - components: { - Dashicon, - TextControl, - }, - element: { - useEffect, - useState, - }, + __, + }, + components: { + Dashicon, + TextControl, + }, + element: { + useEffect, + useState, + }, } = wp; /** @@ -34,7 +34,6 @@ const { const FrontendTracker = ( props ) => { const { dataAttributes, - className, } = props; // Block attributes. @@ -64,215 +63,224 @@ const FrontendTracker = ( props ) => { // Set initial attribute values from props. useEffect( () => { resetAttributes(); + }, [] ); + + // Clear notice after delay if not null. + useEffect( () => { + if ( null === notice ) { + return; + } - // Clear notice after delay. const timer = setTimeout( () => { setNotice( null ); }, 60000 ); return () => clearTimeout( timer ); - }, [] ); + }, [ notice ] ); /** * Reset state attributes to original dataAttributes. * - * @author Rebekah Van Epps + * @author R A Van Epps * @since 2.0.0 */ const resetAttributes = () => { setAttributes( { ...dataAttributes, } ); - } - - /** - * Helper function to update isEditing status and clear notice. - * - * @author Rebekah Van Epps - * @since 2.0.0 - * - * @param {boolean} status New isEditing status. - */ - const onSetIsEditing = ( status ) => { - setIsEditing( status ); - setNotice( null ); - }; + }; + + /** + * Helper function to update isEditing status and clear notice. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @param {boolean} status New isEditing status. + */ + const onSetIsEditing = ( status ) => { + setIsEditing( status ); + setNotice( null ); + }; // Sort characters: alphabetical if editing, by initiative otherwise. const characters = isEditing ? [ ...sortCharacters( players ), ...sortCharacters( npcs ), ] : sortCharacters( [ - ...players, - ...npcs, - ], false ); + ...players, + ...npcs, + ], false ); + + /** + * Edit character attributes on frontend. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @param {Object} newCharacter Modified character object. + * @param {Object} character Original character object. + */ + const editCharacter = ( newCharacter, character ) => { + const type = 0 === character.player.trim().length ? 'npcs' : 'players', + newCharacters = [ ...attributes[ type ] ], + index = newCharacters.indexOf( character ); + + newCharacters[ index ] = newCharacter; + + setAttributes( { + ...attributes, + [ type ]: newCharacters, + } ); + }; /** - * Edit character attributes on frontend. - * - * @author R A Van Epps - * @since 2.0.0 - * - * @param {Object} newCharacter Modified character object. - * @param {Object} character Original character object. - */ - const editCharacter = ( newCharacter, character ) => { - const type = 0 === character.player.trim().length ? 'npcs' : 'players', - newCharacters = [ ...attributes[ type ] ], - index = newCharacters.indexOf( character ); - - newCharacters[ index ] = newCharacter; - - setAttributes( { - ...attributes, - [ type ]: newCharacters, - } ); - } - - /** - * Display input to edit Initiative. - * - * @author Rebekah Van Epps - * @since 2.0.0 - * - * @param {Object} character Character object. - * @return {?ReactElement} Text input JSX. - */ - const displayEditForm = ( character ) => { - if ( ! isEditing ) { - return null; - } - - return ( - + * @since 2.0.0 + * + * @param {Object} character Character object. + * @return {?ReactElement} Text input JSX. + */ + const displayEditForm = ( character ) => { + if ( ! isEditing ) { + return null; + } + + return ( + { - editCharacter( { - ...character, - initiative, - }, character ); - } } - onBlur={ () => { - const initiative = parseInt( character.initiative, 10 ); - - // Reset initiative to 0 if not a number or less than 0. - if ( isNaN( initiative ) || 0 > initiative ) { - editCharacter( { - ...character, - initiative: 0, - }, character ); - } - } } - min="0" - /> + type="number" + value={ character.initiative } + onChange={ ( initiative ) => { + editCharacter( { + ...character, + initiative, + }, character ); + } } + onBlur={ () => { + const initiative = parseInt( character.initiative, 10 ); + + // Reset initiative to 0 if not a number or less than 0. + if ( isNaN( initiative ) || 0 > initiative ) { + editCharacter( { + ...character, + initiative: 0, + }, character ); + } + } } + min="0" + /> + ); + }; + + /** + * Display edit/save Character links. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @return {ReactElement} Character link JSX. + */ + const displayEditLinks = () => { + const path = initTracker.initiative; + + if ( null === path ) { + return; + } + + const linkClass = `char-link ${ isLoading ? 'disabled' : '' }`; + + if ( ! isEditing ) { + return displayEditLink( linkClass, 'edit', __( 'Edit Initiative', 'initiative-tracker' ), () => onSetIsEditing( true ) ); + } + + return ( + <> + { displayEditLink( linkClass, 'no', __( 'Cancel', 'initiative-tracker' ), () => { + resetAttributes(); + onSetIsEditing( false ); + } ) } + { displayEditLink( linkClass, 'yes', __( 'Save Initiative', 'initiative-tracker' ), () => saveCharacterUpdates() ) } + + ); + }; + + /** + * Display edit/save link. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @param {string} linkClass Link class(es). + * @param {string} icon Dashicon icon. + * @param {string} label Link label text. + * @param {function} clickFn Functionality to call on link click. + * @return {ReactElement} Link JSX. + */ + const displayEditLink = ( linkClass, icon, label, clickFn ) => { + return ( + ); - }; - - /** - * Display edit/save Character links. - * - * @author Rebekah Van Epps - * @since 2.0.0 - * - * @return {ReactElement} Character link JSX. - */ - const displayEditLinks = () => { - const path = initTracker.initiative, - nonce = initTracker.nonce; - - if ( null === path || null === nonce ) { - return; - } - - const linkClass = `char-link ${ isLoading ? 'disabled' : '' }`; - - if ( ! isEditing ) { - return displayEditLink( linkClass, 'edit', __( 'Edit Initiative', 'initiative-tracker' ), () => onSetIsEditing( true ) ); - } - - return ( - <> - { displayEditLink( linkClass, 'no', __( 'Cancel', 'initiative-tracker' ), () => { - resetAttributes(); - onSetIsEditing( false ); - } ) } - { displayEditLink( linkClass, 'yes', __( 'Save Initiative', 'initiative-tracker' ), () => saveCharacterUpdates() ) } - - ); - }; - - /** - * Display edit/save link. - * - * @author Rebekah Van Epps - * @since 2.0.0 - * - * @param {string} linkClass Link class(es). - * @param {string} icon Dashicon icon. - * @param {string} label Link label text. - * @param {function} clickFn Functionality to call on link click. - * @return {ReactElement} Link JSX. - */ - const displayEditLink = ( linkClass, icon, label, clickFn ) => { - return ( -
{ - event.preventDefault(); - - // Stop here if currently in loading state. - if ( isLoading ) { - return false; - } - - clickFn(); - } } - > - { label } - - ); - }; - - /** - * Update block attributes. - * - * @author Rebekah Van Epps - * @since 2.0.0 - * - * @return {void} - */ - const saveCharacterUpdates = async () => { - const path = initTracker.initiative, - nonce = initTracker.nonce; - - if ( null === path || null === nonce ) { - return; - } + }; + + /** + * Update block attributes. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @return {void} + */ + const saveCharacterUpdates = async () => { + if ( 'object' !== typeof initTracker || ! initTracker.hasOwnProperty( 'initiative' ) ) { + return; + } + + const path = initTracker.initiative; + + if ( null === path ) { + return; + } setLoading( true ); + setNotice( null ); + + const response = await apiFetch( { + path: `${ path }/${ dataAttributes.post_id }`, + method: 'POST', + data: { + ...attributes, + }, + } ) + .then( ( success ) => { + + // Update dataAttributes to reflect changes. + dataAttributes.players = [ ...players ]; + dataAttributes.npcs = [ ...npcs ]; - const response = await apiFetch( { - path: `${path}/${ dataAttributes.post_id }`, - method: 'POST', - data: { - ...attributes, - }, - } ) - .then( ( success ) => { - // Update dataAttributes to reflect changes. - dataAttributes.players = [ ...players ]; - dataAttributes.npcs = [ ...npcs ]; - - onSetIsEditing( false ); - - return { - type: 'success', - message: success, - }; - } ) + onSetIsEditing( false ); + + return { + type: 'success', + message: success, + }; + } ) .catch( ( error ) => { return { type: 'error', @@ -281,42 +289,40 @@ const FrontendTracker = ( props ) => { } ); setLoading( false ); - setNotice( response ); - }; + setNotice( response ); + }; return ( -
-
- -
- { displayEditLinks() } - { null !== notice && ( - - { notice.message } - - ) } -
-
- - -
-
+
+ +
+ { displayEditLinks() } + { null !== notice && ( + + { notice.message } + + ) } +
+
+ + +
); }; diff --git a/src/block/initiative-tracker/edit.js b/src/block/initiative-tracker/edit.js index f4e018a..fbc5e4e 100644 --- a/src/block/initiative-tracker/edit.js +++ b/src/block/initiative-tracker/edit.js @@ -7,17 +7,19 @@ import CharacterList from './components/CharacterList'; import DeleteCharacterModal from './components/DeleteCharacterModal'; import { sortCharacters } from './util'; +import './editor.scss'; + const { - i18n: { - __, - }, - components: { - Button, - Dashicon, - }, - element: { - useEffect, - }, + i18n: { + __, + }, + components: { + Button, + Dashicon, + }, + element: { + useEffect, + }, } = wp; /** @@ -30,230 +32,231 @@ const { * @return {ReactElement} Block edit JSX. */ const edit = ( props ) => { - const { - attributes: { - id, - players, - npcs, - }, - clientId, - className, - setAttributes, - isSelected, - } = props; + const { + attributes: { + id, + players, + npcs, + }, + clientId, + className, + setAttributes, + isSelected, + } = props; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useEffect( () => { - useEffect( () => { + // If id is not set (initial block creation), set id to clientId value. + if ( 0 === id.length ) { + setAttributes( { + id: clientId, + } ); + } + }, [] ); - // If id is not set (initial block creation), set id to clientId value. - if ( 0 === id.length ) { - setAttributes( { - id: clientId, - } ); - } - }, [] ); + /** + * Add new character, sort alphabetically. + * + * @author R A Van Epps + * @since 1.0.0 + * + * @param {string} type Type of character. + * @param {Object} character New character object. + */ + const addCharacter = ( type, character ) => { + type = `${ type }s`; + character.key = Date.now(); - /** - * Add new character, sort alphabetically. - * - * @author R A Van Epps - * @since 1.0.0 - * - * @param {string} type Type of character. - * @param {Object} character New character object. - */ - const addCharacter = ( type, character ) => { - type = `${type}s`; - character.key = Date.now(); + const characters = [ ...props.attributes[ type ], character ]; - const characters = [ ...props.attributes[ type ], character ]; + setAttributes( { + [ type ]: sortCharacters( characters ), + } ); + }; - setAttributes( { - [ type ]: sortCharacters( characters ) - } ); - }; + /** + * Edit character attributes. + * + * @author R A Van Epps + * @since 1.0.0 + * + * @param {string} type Type of character. + * @param {number} index Character index. + * @param {Object} character Character object. + */ + const editCharacter = ( type, index, character ) => { + type = `${ type }s`; + const characters = [ ...props.attributes[ type ] ]; + characters[ index ] = character; + setAttributes( { + [ type ]: sortCharacters( characters ), + } ); + }; - /** - * Edit character attributes. - * - * @author R A Van Epps - * @since 1.0.0 - * - * @param {string} type Type of character. - * @param {integer} index Character index. - * @param {Object} character Character object. - */ - const editCharacter = ( type, index, character ) => { - type = `${type}s`; - const characters = [ ...props.attributes[ type ] ]; - characters[ index ] = character; - setAttributes( { - [ type ]: sortCharacters( characters ) - } ); - } + /** + * Delete character. + * + * @author R A Van Epps + * @since 1.0.0 + * + * @param {string} type Type of character. + * @param {number} index Character index. + */ + const deleteCharacter = ( type, index ) => { + type = `${ type }s`; + const characters = [ ...props.attributes[ type ] ].filter( function( character, charIndex ) { + return charIndex !== index; + }, index ); + setAttributes( { + [ type ]: characters, + } ); + }; - /** - * Delete character. - * - * @author R A Van Epps - * @since 1.0.0 - * - * @param {string} type Type of character. - * @param {integer} index Character index. - */ - const deleteCharacter = ( type, index ) => { - type = `${type}s`; - const characters = [ ...props.attributes[ type ] ].filter( function( character, charIndex ) { - return charIndex !== index; - }, index ); - setAttributes( { - [ type ]: characters - } ); - }; + /** + * Display AddEditCharacterForm component. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @param {Object} fnProps Props to pass to componenent. + * @param {string} action Version of form to display. + * @return {ReactElement} JSX to display. + */ + const displayAddEditForm = ( fnProps, action = 'add' ) => { + const { + type, + characterFn, + toggleFn, + isActive, + character = null, + index = null, + } = fnProps; - /** - * Display AddEditCharacterForm component. - * - * @author R A Van Epps - * @since 2.0.0 - * - * @param {Object} fnProps Props to pass to componenent. - * @param {string} action Version of form to display. - * @return {ReactElement} JSX to display. - */ - const displayAddEditForm = ( fnProps, action = 'add' ) => { - const { - type, - characterFn, - toggleFn, - isActive, - character = null, - index = null, - } = fnProps; + const formProps = { + type, + characterFn, + toggle: () => toggleFn( type ), + }; - const formProps = { - type, - characterFn, - toggle: () => toggleFn( type ), - }; + if ( 'edit' === action ) { + formProps.character = character; + formProps.index = index; + } - if ( 'edit' === action ) { - formProps.character = character; - formProps.index = index; - } + if ( isActive ) { + return ( + + ); + } - if ( isActive ) { - return ( - - ); - } else { - return ( -
- { 'add' === action ? ( - - ) : ( - <> - - - - ) } -
- ); - } - }; + return ( +
+ { 'add' === action ? ( + + ) : ( + <> + + + + ) } +
+ ); + }; - /** - * Display Add version of AddEditCharacterForm. - * - * @author R A Van Epps - * @since 2.0.0 - * - * @param {string} type Type of Character list being displayed. - * @param {boolean} isAdding Whether currently in editing mode. - * @param {function} toggleFn Toggle function. - * @return {ReactElement} JSX to display. - */ - const displayAddForm = ( type, isAdding, toggleFn ) => ( - displayAddEditForm( { - type, - characterFn: addCharacter, - toggleFn: toggleFn, - isActive: isAdding, - } ) - ); + /** + * Display Add version of AddEditCharacterForm. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @param {string} type Type of Character list being displayed. + * @param {boolean} isAdding Whether currently in editing mode. + * @param {function} toggleFn Toggle function. + * @return {ReactElement} JSX to display. + */ + const displayAddForm = ( type, isAdding, toggleFn ) => ( + displayAddEditForm( { + type, + characterFn: addCharacter, + toggleFn, + isActive: isAdding, + } ) + ); - /** - * Display Edit version of AddEditCharacterForm. - * - * @author R A Van Epps - * @since 2.0.0 - * - * @param {string} type Type of Character list being displayed. - * @param {boolean} isEditing Whether currently in editing mode. - * @param {function} toggleFn Toggle function. - * @param {Object} character Character object. - * @param {integer} index Character index. - * @return {ReactElement} JSX to display. - */ - const displayEditForm = ( type, isEditing, toggleFn, character, index ) => ( - displayAddEditForm( { - type, - characterFn: editCharacter, - toggleFn, - isActive: isEditing, - character, - index, - }, 'edit' ) - ); + /** + * Display Edit version of AddEditCharacterForm. + * + * @author R A Van Epps + * @since 2.0.0 + * + * @param {string} type Type of Character list being displayed. + * @param {boolean} isEditing Whether currently in editing mode. + * @param {function} toggleFn Toggle function. + * @param {Object} character Character object. + * @param {number} index Character index. + * @return {ReactElement} JSX to display. + */ + const displayEditForm = ( type, isEditing, toggleFn, character, index ) => ( + displayAddEditForm( { + type, + characterFn: editCharacter, + toggleFn, + isActive: isEditing, + character, + index, + }, 'edit' ) + ); - return ( -
-
- { isSelected && ( - <> - - - - ) } - { ! isSelected && ( - - ) } -
-
- ); + return ( +
+
+ { isSelected && ( + <> + + + + ) } + { ! isSelected && ( + + ) } +
+
+ ); }; export default edit; diff --git a/src/block/initiative-tracker/frontend.js b/src/block/initiative-tracker/frontend.js index 484148d..bbffd7b 100644 --- a/src/block/initiative-tracker/frontend.js +++ b/src/block/initiative-tracker/frontend.js @@ -5,13 +5,13 @@ import FrontendTracker from './components/FrontendTracker'; const { - element: { + element: { render, }, } = wp; -const trackerClass = 'wp-block-rave-initiative-tracker'; -const trackers = document.querySelectorAll( `.${trackerClass}` ); +const trackerClass = '.wp-block-rave-initiative-tracker', + trackers = document.querySelectorAll( trackerClass ); /** * Retrieve and re-render initiative tracker blocks. @@ -30,10 +30,7 @@ trackers.forEach( ( tracker ) => { }; render( - , - tracker + , + tracker ); } ); diff --git a/src/block/initiative-tracker/index.js b/src/block/initiative-tracker/index.js index 7a566c9..9f30e4e 100644 --- a/src/block/initiative-tracker/index.js +++ b/src/block/initiative-tracker/index.js @@ -7,43 +7,45 @@ import edit from './edit'; import save from './save'; +import './style.scss'; + const { - i18n: { - __, - }, - blocks: { - registerBlockType, - }, + i18n: { + __, + }, + blocks: { + registerBlockType, + }, } = wp; /** * Register Initiative Tracker block. */ registerBlockType( 'rave/initiative-tracker', { - title: __( 'Initiative Tracker', 'initiative-tracker' ), - description: __( 'This block helps track and organize character initiative scores.', 'initiative-tracker' ), - icon: 'list-view', - category: 'widgets', - keywords: [ - __( 'initiative tracker', 'initiative-tracker' ), - ], - supports: { - html: false, - }, - attributes: { - id: { - type: 'string', - default: '', - }, - players: { - type: 'array', - default: [], - }, - npcs: { - type: 'array', - default: [], - }, - }, - edit, - save, + title: __( 'Initiative Tracker', 'initiative-tracker' ), + description: __( 'This block helps track and organize character initiative scores.', 'initiative-tracker' ), + icon: 'list-view', + category: 'widgets', + keywords: [ + __( 'initiative tracker', 'initiative-tracker' ), + ], + supports: { + html: false, + }, + attributes: { + id: { + type: 'string', + default: '', + }, + players: { + type: 'array', + default: [], + }, + npcs: { + type: 'array', + default: [], + }, + }, + edit, + save, } ); diff --git a/src/block/initiative-tracker/save.js b/src/block/initiative-tracker/save.js index 3ff810d..b7d2fd5 100644 --- a/src/block/initiative-tracker/save.js +++ b/src/block/initiative-tracker/save.js @@ -8,11 +8,10 @@ * @author R A Van Epps * @since 1.0.0 * - * @param {Object} props Block props. * @return {?ReactElement} Block save JSX. */ -const save = ( props ) => { - return null; +const save = () => { + return null; }; export default save; diff --git a/src/block/initiative-tracker/style.scss b/src/block/initiative-tracker/style.scss index cfa8a1a..580929e 100644 --- a/src/block/initiative-tracker/style.scss +++ b/src/block/initiative-tracker/style.scss @@ -4,16 +4,16 @@ $color-status: #00a400; .wp-block-rave-initiative-tracker { margin: 1rem 0; - &.is-loading { - opacity: 0.75; - } - h2 { margin-bottom: 0; } .characters { + &.is-loading { + opacity: 0.75; + } + ul { list-style-type: circle; padding-bottom: 0; @@ -61,8 +61,9 @@ $color-status: #00a400; .char-link { display: inline-block; - font-size: smaller; + font-size: small; margin: 1rem 2rem 1rem 0; + padding: 1rem; &.disabled { cursor: not-allowed; @@ -88,4 +89,15 @@ $color-status: #00a400; color: $color-error; } } + + .character-list { + + ul { + width: max-content; + } + + .initiative { + float: right; + } + } } diff --git a/src/block/initiative-tracker/util.js b/src/block/initiative-tracker/util.js index 0176eef..6fb1fb5 100644 --- a/src/block/initiative-tracker/util.js +++ b/src/block/initiative-tracker/util.js @@ -8,16 +8,18 @@ * @author R A Van Epps * @since 1.0.0 * - * @param {array} characters Array of characters. + * @param {Array} characters Array of characters. + * @param {boolean} alpha Whether to sort alphabetically (true) or by inititiative score (false). + * @return {Array} Sorted array of characters. */ const sortCharacters = ( characters, alpha = true ) => { - characters.sort( function( char1, char2 ) { - if ( alpha ) { - return char1.name.localeCompare( char2.name ); - } - return ( parseInt( char1.initiative ) > parseInt( char2.initiative ) ? -1 : 1 ); - } ); - return characters; + characters.sort( function( char1, char2 ) { + if ( alpha ) { + return char1.name.localeCompare( char2.name ); + } + return ( parseInt( char1.initiative, 10 ) > parseInt( char2.initiative, 10 ) ? -1 : 1 ); + } ); + return characters; }; export { diff --git a/webpack.config.js b/webpack.config.js index 6c42fa1..898308e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,59 +8,28 @@ const glob = require( 'glob' ); * External Dependencies. */ const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' ); -const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' ); const IgnoreEmitPlugin = require( 'ignore-emit-webpack-plugin' ); const entry = { - ...defaultConfig.entry, + ...defaultConfig.entry, }; -const styles = glob.sync( './src/**/*/style.{scss,css}' ); -if ( styles.length ) { - entry.style = styles; -} - -const editorStyles = glob.sync( './src/**/*/editor.{scss,css}' ); -if ( editorStyles.length ) { - entry.editor = editorStyles; -} - const frontendScript = glob.sync( './src/frontend.js' ); if ( frontendScript.length ) { - entry.frontend = frontendScript; + entry.frontend = frontendScript; } module.exports = { - ...defaultConfig, - entry, - module: { - ...defaultConfig.module, - rules: [ - ...defaultConfig.module.rules, - { - test: /\.s?css$/, - use: [ - { loader: MiniCssExtractPlugin.loader }, - { loader: 'css-loader', options: { importLoaders: 1 } }, - { loader: 'postcss-loader' }, - { loader: 'sass-loader' }, - ], - }, - ], - }, - plugins: [ - ...defaultConfig.plugins, - new CleanWebpackPlugin(), - new MiniCssExtractPlugin( { - filename: '[name].css', - chunkFilename: '[id].css', - } ), - new IgnoreEmitPlugin( [ - 'editor.asset.php', - 'editor.js', - 'frontend.asset.php', - 'style.asset.php', - 'style.js', - ] ), - ], + ...defaultConfig, + entry, + module: { + ...defaultConfig.module, + }, + plugins: [ + ...defaultConfig.plugins, + new CleanWebpackPlugin(), + new IgnoreEmitPlugin( [ + 'frontend.asset.php', + ] ), + ], };