diff --git a/src/react/containers/EditorContainer.js b/src/react/containers/EditorContainer.js index 5f1cf0857..78007b689 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); @@ -101,7 +101,6 @@ class EditorContainer extends Component { author, contributors, }); - entryEditClose(entry.id); return; } @@ -224,7 +223,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 +308,8 @@ class EditorContainer extends Component { clearable={false} cache={false} /> -
); @@ -305,12 +317,13 @@ 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/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/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': 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: 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; + } +} 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;