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 {
}
- Delete
+ { isDeleting ? 'Deleting...' : 'Delete' }
);
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;