From d57bf0f15c858ce3329c8d234d89bd5bafa39ee4 Mon Sep 17 00:00:00 2001 From: David Sword Date: Fri, 21 Sep 2018 08:23:18 -0700 Subject: [PATCH 1/5] Add state & progress indicators to an Entries Delete btn Re: #476 When a user on a slower network/server clicked delete, there was no visual feedback that their action was processing. Adding this state allows ternary checks within the component to change the buttons text & add a 'active' CSS animation class. This gives the user a indicator of their delete action is being preformed. --- src/react/containers/EntryContainer.js | 12 +++++++++--- src/styles/core/app/_buttons.scss | 12 ++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/react/containers/EntryContainer.js b/src/react/containers/EntryContainer.js index f39efd55a..fcfe3ed1e 100644 --- a/src/react/containers/EntryContainer.js +++ b/src/react/containers/EntryContainer.js @@ -12,13 +12,18 @@ class EntryContainer extends Component { constructor(props) { super(props); + this.state = { isDeleting: false }; + this.isEditing = () => { const { user, entry } = this.props; return user.entries[entry.id] && user.entries[entry.id].isEditing; }; this.edit = () => this.props.entryEditOpen(this.props.entry.id); this.close = () => this.props.entryEditClose(this.props.entry.id); - this.delete = () => this.props.deleteEntry(this.props.entry.id); + this.delete = () => { + this.setState({ isDeleting: true }); + this.props.deleteEntry(this.props.entry.id); + }; this.scrollIntoView = () => { this.node.scrollIntoView({ block: 'start', behavior: 'instant' }); this.props.resetScrollOnEntry(`id_${this.props.entry.id}`); @@ -40,6 +45,7 @@ class EntryContainer extends Component { entryActions() { const { config } = this.props; + const { isDeleting } = this.state; if (config.is_liveblog_editable !== '1') return false; return ( @@ -54,10 +60,10 @@ class EntryContainer extends Component { } ); diff --git a/src/styles/core/app/_buttons.scss b/src/styles/core/app/_buttons.scss index 8fcd9ab5e..84ab12aec 100644 --- a/src/styles/core/app/_buttons.scss +++ b/src/styles/core/app/_buttons.scss @@ -64,3 +64,15 @@ background: darken($color-warning, 10%); } +.liveblog-btn-delete--active { + &, &:hover { + animation: liveblog-btn-delete--active-animation 2.5s infinite linear; + background-size: 100px 100%; + background-image: linear-gradient(-45deg,darken($color-warning, 5%) 28%,$color-warning 0,$color-warning 72%,darken($color-warning, 5%) 0); + } +} +@keyframes liveblog-btn-delete--active-animation { + 0% { + background-position: 200px 0; + } +} From cb71159bf59d12bd7ba622237ee25d6451157b56 Mon Sep 17 00:00:00 2001 From: David Sword Date: Fri, 21 Sep 2018 08:25:06 -0700 Subject: [PATCH 2/5] Add isPublishingNew state to reference new submissions progress Re: #476 When a user on a slower network/server clicked Publish New Entry, there was no visual feedback that their action was processing. Adding this state by using pre-existing Redux actions, we can know when the Publishing transaction is occurring, allowing ternary checks within the components, which gives the availability to change the buttons text and classes. --- src/react/reducers/api.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/react/reducers/api.js b/src/react/reducers/api.js index 2259eadc1..3df1914b3 100644 --- a/src/react/reducers/api.js +++ b/src/react/reducers/api.js @@ -60,17 +60,25 @@ export const api = (state = initialState, action) => { : state.newestEntry, }; + case 'CREATE_ENTRY': + return { + ...state, + isPublishingNew: true, + }; + case 'CREATE_ENTRY_SUCCESS': return { ...state, error: false, nonce: action.payload.nonce, + isPublishingNew: false, }; case 'CREATE_ENTRY_FAILED': return { ...state, error: true, + isPublishingNew: false, }; case 'DELETE_ENTRY_SUCCESS': From 29fb034189a825def8febdeb0daf7518cb357aaf Mon Sep 17 00:00:00 2001 From: David Sword Date: Fri, 21 Sep 2018 08:30:45 -0700 Subject: [PATCH 3/5] Add isPublishing state to Entries to reference update progress Re: #476 When a user on a slower network/server clicked Publish Update, there was no visual feedback that their action was processing. Adding this state to the entries by using pre-existing Redux actions, we can know when the Publishing transaction is occurring, allowing conditional checks within the components. This gives the option to change the buttons text and classes, which can indicate progress. --- src/react/reducers/user.js | 41 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/react/reducers/user.js b/src/react/reducers/user.js index 183d9fec9..7ffd35a28 100644 --- a/src/react/reducers/user.js +++ b/src/react/reducers/user.js @@ -7,13 +7,50 @@ export const user = (state = initialState, action) => { case 'ENTRY_EDIT_OPEN': return { ...state, - entries: { ...state.entries, [action.payload]: { isEditing: true } }, + entries: { + ...state.entries, + [action.payload]: { + isEditing: true, + isPublishing: false, + }, + }, }; case 'ENTRY_EDIT_CLOSE': return { ...state, - entries: { ...state.entries, [action.payload]: { isEditing: false } }, + entries: { + ...state.entries, + [action.payload]: + { + isEditing: false, + isPublishing: false, + }, + }, + }; + + case 'UPDATE_ENTRY': + return { + ...state, + entries: { + ...state.entries, + [action.payload.id]: { + isEditing: true, + isPublishing: true, + }, + }, + }; + + case 'UPDATE_ENTRY_SUCCESS': + return { + ...state, + entries: { + ...state.entries, + [action.payload.entries[0].id]: { + isEditing: false, + isPublishing: false, + }, + }, }; default: From e49fbe0622b0ca101531efd8fb5dc521a89050f8 Mon Sep 17 00:00:00 2001 From: David Sword Date: Fri, 21 Sep 2018 08:52:01 -0700 Subject: [PATCH 4/5] Add progress indicators to the publish btn on add/update Entry Re: #476 When a user on a slower network/server clicked Publish Update, there was no visual feedback that their action was processing. By using the isPublishingNew state for the main 'add new entry' form, and using the isPublish state while editing the contents of individual entries, the component can now change the button text and buttons css class to indicate the action is in progress. --- src/react/containers/EditorContainer.js | 23 +++++++++++++++++++---- src/styles/core/editor/_buttons.scss | 13 +++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/react/containers/EditorContainer.js b/src/react/containers/EditorContainer.js index 5f1cf0857..775825dcc 100644 --- a/src/react/containers/EditorContainer.js +++ b/src/react/containers/EditorContainer.js @@ -87,7 +87,7 @@ class EditorContainer extends Component { } publish() { - const { updateEntry, entry, entryEditClose, createEntry, isEditing } = this.props; + const { updateEntry, entry, createEntry, isEditing } = this.props; const { editorState, authors } = this.state; const content = this.getContent(); const authorIds = authors.map(author => author.id); @@ -224,7 +224,20 @@ class EditorContainer extends Component { readOnly, } = this.state; - const { isEditing, config } = this.props; + const { isEditing, config, api, user, entry } = this.props; + + const isPublishingUpdate = ( + entry && user.entries[entry.id] && user.entries[entry.id].isPublishing + ); + const isPublishingNew = (!isEditing && api.isPublishingNew); + const isPublishing = (isPublishingNew || isPublishingUpdate); + + let publishBtnText; + if (isPublishing) { + publishBtnText = 'Publishing...'; + } else { + publishBtnText = isEditing ? 'Publish Update' : 'Publish New Entry'; + } return (
@@ -296,8 +309,8 @@ class EditorContainer extends Component { clearable={false} cache={false} /> -
); @@ -305,12 +318,14 @@ class EditorContainer extends Component { } EditorContainer.propTypes = { + api: PropTypes.object, config: PropTypes.object, updateEntry: PropTypes.func, entry: PropTypes.object, entryEditClose: PropTypes.func, createEntry: PropTypes.func, isEditing: PropTypes.bool, + isPublishing: PropTypes.bool, authors: PropTypes.array, getAuthors: PropTypes.func, }; diff --git a/src/styles/core/editor/_buttons.scss b/src/styles/core/editor/_buttons.scss index beddb6cd5..b8fca358c 100644 --- a/src/styles/core/editor/_buttons.scss +++ b/src/styles/core/editor/_buttons.scss @@ -150,6 +150,19 @@ font-size: .9rem; } +.liveblog-publish-btn--active { + &, &:hover { + animation: liveblog-publish-btn--active-animation 2.5s infinite linear; + background-size: 100px 100%; + background-image: linear-gradient(-45deg,darken($color-primary, 5%) 28%,$color-primary 0,$color-primary 72%,darken($color-primary, 5%) 0); + } +} +@keyframes liveblog-publish-btn--active-animation { + 0% { + background-position: 200px 0; + } +} + .liveblog-cancel-btn { background: $color-grey-light; color: $color-grey-dark; From 0ef80388b0b6bc9e4faa9771c1562ded6ae8edcd Mon Sep 17 00:00:00 2001 From: David Sword Date: Fri, 21 Sep 2018 09:00:41 -0700 Subject: [PATCH 5/5] Remove entryEditClose function from edit entry editor. Re: #476 This function was used to close the editor immediately after clicking 'Publish Update'. When a user on a slower network/server clicked this, the editor disappeared instantly, however it would take several seconds for the entries text to actually update - there was no visual feedback that their action was processing. By not using this function the editor does not instantly get removed. Not being removed right away allows the editor component to check if the `store > user > entries` entry has a true isPublishing state, adding necessary indicators of progress. The editor is already set to close by changing the isEditing state to false, on the UPDATE_ENTRY_SUCCESS Redux action in the user.js reducer. --- src/react/containers/EditorContainer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/react/containers/EditorContainer.js b/src/react/containers/EditorContainer.js index 775825dcc..78007b689 100644 --- a/src/react/containers/EditorContainer.js +++ b/src/react/containers/EditorContainer.js @@ -101,7 +101,6 @@ class EditorContainer extends Component { author, contributors, }); - entryEditClose(entry.id); return; } @@ -322,7 +321,6 @@ EditorContainer.propTypes = { config: PropTypes.object, updateEntry: PropTypes.func, entry: PropTypes.object, - entryEditClose: PropTypes.func, createEntry: PropTypes.func, isEditing: PropTypes.bool, isPublishing: PropTypes.bool,