feat: Add the ability to delete/archive articles (#5319)

This commit is contained in:
Muhsin Keloth 2022-09-01 10:55:59 +05:30 committed by GitHub
parent c8d01a84ce
commit 6e945dd61e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 14 deletions

View file

@ -42,6 +42,10 @@ class ArticlesAPI extends PortalsAPI {
category_id, category_id,
}); });
} }
deleteArticle({ articleId, portalSlug }) {
return axios.delete(`${this.url}/${portalSlug}/articles/${articleId}`);
}
} }
export default new ArticlesAPI(); export default new ArticlesAPI();

View file

@ -52,4 +52,15 @@ describe('#PortalAPI', () => {
); );
}); });
}); });
describeWithAPIMock('API calls', context => {
it('#deleteArticle', () => {
articlesAPI.deleteArticle({
articleId: 1,
portalSlug: 'room-rental',
});
expect(context.axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/portals/room-rental/articles/1'
);
});
});
}); });

View file

@ -224,6 +224,26 @@
"ERROR": "Error while saving article" "ERROR": "Error while saving article"
} }
}, },
"ARCHIVE_ARTICLE": {
"API": {
"ERROR": "Error while archiving article",
"SUCCESS": "Article archived successfully"
}
},
"DELETE_ARTICLE": {
"MODAL": {
"CONFIRM": {
"TITLE": "Confirm Deletion",
"MESSAGE": "Are you sure to delete the article?",
"YES": "Yes, Delete",
"NO": "No, Keep it"
}
},
"API": {
"SUCCESS_MESSAGE": "Article deleted successfully",
"ERROR_MESSAGE": "Error while deleting article"
}
},
"CREATE_ARTICLE": { "CREATE_ARTICLE": {
"ERROR_MESSAGE": "Please add the article heading and content then only you can update the settings" "ERROR_MESSAGE": "Please add the article heading and content then only you can update the settings"
}, },

View file

@ -10,7 +10,7 @@
color-scheme="secondary" color-scheme="secondary"
icon="settings" icon="settings"
size="small" size="small"
@click="openPortalPage" @click="openPortalArticles"
> >
{{ $t('HELP_CENTER.PORTAL.POPOVER.PORTAL_SETTINGS') }} {{ $t('HELP_CENTER.PORTAL.POPOVER.PORTAL_SETTINGS') }}
</woot-button> </woot-button>
@ -62,10 +62,16 @@ export default {
closePortalPopover() { closePortalPopover() {
this.$emit('close-popover'); this.$emit('close-popover');
}, },
openPortalPage() { openPortalArticles({ slug, locale }) {
this.$emit('close-popover'); this.$emit('close-popover');
const portal = this.portals.find(p => p.slug === slug);
this.$store.dispatch('portals/setPortalId', portal.id);
this.$router.push({ this.$router.push({
name: 'list_all_portals', name: 'list_all_locale_articles',
params: {
portalSlug: slug,
locale: locale,
},
}); });
}, },
}, },

View file

@ -127,7 +127,7 @@ export default {
props: { props: {
article: { article: {
type: Object, type: Object,
required: true, default: () => ({}),
}, },
}, },
data() { data() {

View file

@ -27,6 +27,17 @@
v-if="showArticleSettings" v-if="showArticleSettings"
:article="article" :article="article"
@save-article="saveArticle" @save-article="saveArticle"
@delete-article="openDeletePopup"
@archive-article="archiveArticle"
/>
<woot-delete-modal
:show.sync="showDeleteConfirmationPopup"
:on-close="closeDeletePopup"
:on-confirm="confirmDeletion"
:title="$t('HELP_CENTER.DELETE_ARTICLE.MODAL.CONFIRM.TITLE')"
:message="$t('HELP_CENTER.DELETE_ARTICLE.MODAL.CONFIRM.MESSAGE')"
:confirm-text="$t('HELP_CENTER.DELETE_ARTICLE.MODAL.CONFIRM.YES')"
:reject-text="$t('HELP_CENTER.DELETE_ARTICLE.MODAL.CONFIRM.NO')"
/> />
</div> </div>
</template> </template>
@ -52,6 +63,7 @@ export default {
isSaved: false, isSaved: false,
showArticleSettings: false, showArticleSettings: false,
alertMessage: '', alertMessage: '',
showDeleteConfirmationPopup: false,
}; };
}, },
computed: { computed: {
@ -82,6 +94,16 @@ export default {
portalSlug: this.selectedPortalSlug, portalSlug: this.selectedPortalSlug,
}); });
}, },
openDeletePopup() {
this.showDeleteConfirmationPopup = true;
},
closeDeletePopup() {
this.showDeleteConfirmationPopup = false;
},
confirmDeletion() {
this.closeDeletePopup();
this.deleteArticle();
},
async saveArticle({ ...values }) { async saveArticle({ ...values }) {
this.isUpdating = true; this.isUpdating = true;
try { try {
@ -92,8 +114,7 @@ export default {
}); });
} catch (error) { } catch (error) {
this.alertMessage = this.alertMessage =
error?.message || error?.message || this.$t('HELP_CENTER.EDIT_ARTICLE.API.ERROR');
this.$t('HELP_CENTER.EDIT_ARTICLE.API.ERROR_MESSAGE');
this.showAlert(this.alertMessage); this.showAlert(this.alertMessage);
} finally { } finally {
setTimeout(() => { setTimeout(() => {
@ -102,6 +123,45 @@ export default {
}, 1500); }, 1500);
} }
}, },
async deleteArticle() {
try {
await this.$store.dispatch('articles/delete', {
portalSlug: this.selectedPortalSlug,
articleId: this.articleId,
});
this.alertMessage = this.$t(
'HELP_CENTER.DELETE_ARTICLE.API.SUCCESS_MESSAGE'
);
this.$router.push({
name: 'list_all_locale_articles',
params: {
portalSlug: this.selectedPortalSlug,
locale: this.locale,
},
});
} catch (error) {
this.alertMessage =
error?.message ||
this.$t('HELP_CENTER.DELETE_ARTICLE.API.ERROR_MESSAGE');
} finally {
this.showAlert(this.alertMessage);
}
},
async archiveArticle() {
try {
await this.$store.dispatch('articles/update', {
portalSlug: this.selectedPortalSlug,
articleId: this.articleId,
status: 2,
});
this.alertMessage = this.$t('HELP_CENTER.ARCHIVE_ARTICLE.API.SUCCESS');
} catch (error) {
this.alertMessage =
error?.message || this.$t('HELP_CENTER.ARCHIVE_ARTICLE.API.ERROR');
} finally {
this.showAlert(this.alertMessage);
}
},
openArticleSettings() { openArticleSettings() {
this.showArticleSettings = true; this.showArticleSettings = true;
}, },

View file

@ -100,7 +100,7 @@ export const actions = {
}); });
} }
}, },
delete: async ({ commit }, articleId) => { delete: async ({ commit }, { portalSlug, articleId }) => {
commit(types.UPDATE_ARTICLE_FLAG, { commit(types.UPDATE_ARTICLE_FLAG, {
uiFlags: { uiFlags: {
isDeleting: true, isDeleting: true,
@ -108,8 +108,7 @@ export const actions = {
articleId, articleId,
}); });
try { try {
await articlesAPI.delete(articleId); await articlesAPI.deleteArticle({ portalSlug, articleId });
commit(types.REMOVE_ARTICLE, articleId); commit(types.REMOVE_ARTICLE, articleId);
commit(types.REMOVE_ARTICLE_ID, articleId); commit(types.REMOVE_ARTICLE_ID, articleId);
return articleId; return articleId;

View file

@ -13,9 +13,11 @@ export const getters = {
}, },
allArticles: (...getterArguments) => { allArticles: (...getterArguments) => {
const [state, _getters] = getterArguments; const [state, _getters] = getterArguments;
const articles = state.articles.allIds.map(id => { const articles = state.articles.allIds
return _getters.articleById(id); .map(id => {
}); return _getters.articleById(id);
})
.filter(article => article !== undefined);
return articles; return articles;
}, },
getMeta: state => { getMeta: state => {

View file

@ -142,7 +142,11 @@ describe('#actions', () => {
describe('#delete', () => { describe('#delete', () => {
it('sends correct actions if API is success', async () => { it('sends correct actions if API is success', async () => {
axios.delete.mockResolvedValue({ data: articleList[0] }); axios.delete.mockResolvedValue({ data: articleList[0] });
await actions.delete({ commit }, articleList[0].id); await actions.delete(
{ commit },
{ portalSlug: 'test', articleId: articleList[0].id }
);
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[ [
types.default.UPDATE_ARTICLE_FLAG, types.default.UPDATE_ARTICLE_FLAG,
@ -159,7 +163,10 @@ describe('#actions', () => {
it('sends correct actions if API is error', async () => { it('sends correct actions if API is error', async () => {
axios.delete.mockRejectedValue({ message: 'Incorrect header' }); axios.delete.mockRejectedValue({ message: 'Incorrect header' });
await expect( await expect(
actions.delete({ commit }, articleList[0].id) actions.delete(
{ commit },
{ portalSlug: 'test', articleId: articleList[0].id }
)
).rejects.toThrow(Error); ).rejects.toThrow(Error);
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[ [