feat: Articles store integration (#5133)

This commit is contained in:
Muhsin Keloth
2022-08-02 17:14:10 +05:30
committed by GitHub
parent 82207c0d3e
commit 5735a8e377
22 changed files with 272 additions and 82 deletions

View File

@@ -4,7 +4,7 @@
<div class="row--article-block">
<div class="article-block">
<h6 class="sub-block-title text-truncate">
<router-link class="article-name" :to="articlePath">
<router-link class="article-name" :to="articleUrl(id)">
{{ title }}
</router-link>
</h6>
@@ -24,16 +24,20 @@
</tr>
</template>
<script>
import { frontendURL } from 'dashboard/helper/URLHelper';
import Label from 'dashboard/components/ui/Label';
import timeMixin from 'dashboard/mixins/time';
import portalMixin from '../mixins/portalMixin';
export default {
components: {
Label,
},
mixins: [timeMixin],
mixins: [timeMixin, portalMixin],
props: {
id: {
type: Number,
required: true,
},
title: {
type: String,
default: '',
@@ -79,9 +83,6 @@ export default {
return 'success';
}
},
articlePath() {
return frontendURL(`accounts/${this.accountId}/hc/articles/${this.id}`);
},
},
};
</script>

View File

@@ -16,20 +16,22 @@
<tbody>
<ArticleItem
v-for="article in articles"
:id="article.id"
:key="article.id"
:title="article.title"
:author="article.author"
:category="article.category"
:read-count="article.readCount"
:status="article.status"
:updated-at="article.updatedAt"
:updated-at="article.updated_at"
/>
</tbody>
</table>
<table-footer
:on-page-change="onPageChange"
:current-page="Number(currentPage)"
:total-count="articleCount"
:total-count="totalCount"
:page-size="pageSize"
/>
</div>
</template>
@@ -47,7 +49,7 @@ export default {
type: Array,
default: () => {},
},
articleCount: {
totalCount: {
type: Number,
default: 0,
},
@@ -55,10 +57,14 @@ export default {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 15,
},
},
methods: {
onPageChange() {
this.$emit('onPageChange');
onPageChange(page) {
this.$emit('on-page-change', page);
},
},
};

View File

@@ -66,6 +66,12 @@ export default {
...mapGetters({
accountId: 'getCurrentAccountId',
}),
portalSlug() {
return this.$route.params.portalSlug;
},
locale() {
return this.$route.params.locale;
},
accessibleMenuItems() {
return [
{
@@ -74,7 +80,7 @@ export default {
key: 'list_all_locale_articles',
count: 199,
toState: frontendURL(
`accounts/${this.accountId}/portals/:portalSlug/:locale/articles`
`accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles`
),
toolTip: 'All Articles',
toStateName: 'list_all_locale_articles',
@@ -85,7 +91,7 @@ export default {
key: 'mine_articles',
count: 112,
toState: frontendURL(
`accounts/${this.accountId}/portals/:portalSlug/:locale/articles/mine`
`accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/mine`
),
toolTip: 'My articles',
toStateName: 'mine_articles',
@@ -96,7 +102,7 @@ export default {
key: 'list_draft_articles',
count: 32,
toState: frontendURL(
`accounts/${this.accountId}/portals/:portalSlug/:locale/articles/draft`
`accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/draft`
),
toolTip: 'Draft',
toStateName: 'list_draft_articles',
@@ -107,7 +113,7 @@ export default {
key: 'list_archived_articles',
count: 10,
toState: frontendURL(
`accounts/${this.accountId}/portals/:portalSlug/:locale/articles/archived`
`accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/archived`
),
toolTip: 'Archived',
toStateName: 'list_archived_articles',

View File

@@ -0,0 +1,20 @@
import { mapGetters } from 'vuex';
import { frontendURL } from 'dashboard/helper/URLHelper';
export default {
computed: {
...mapGetters({ accountId: 'getCurrentAccountId' }),
portalSlug() {
return this.$route.params.portalSlug;
},
locale() {
return this.$route.params.locale;
},
},
methods: {
articleUrl(id) {
return frontendURL(
`accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/${id}`
);
},
},
};

View File

@@ -0,0 +1,68 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import portalMixin from '../portalMixin';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(VueRouter);
import ListAllArticles from '../../pages/portals/ListAllPortals.vue';
const router = new VueRouter({
routes: [
{
path: ':portalSlug/:locale/articles',
name: 'list_all_locale_articles',
component: ListAllArticles,
},
],
});
describe('portalMixin', () => {
let getters;
let store;
let wrapper;
beforeEach(() => {
getters = {
getCurrentAccountId: () => 1,
};
const Component = {
render() {},
title: 'TestComponent',
mixins: [portalMixin],
router,
};
store = new Vuex.Store({ getters });
wrapper = shallowMount(Component, { store, localVue });
});
it('return account id', () => {
expect(wrapper.vm.accountId).toBe(1);
});
it('returns portal url', () => {
router.push({
name: 'list_all_locale_articles',
params: { portalSlug: 'fur-rent', locale: 'en' },
});
expect(wrapper.vm.articleUrl(1)).toBe(
'/app/accounts/1/portals/fur-rent/en/articles/1'
);
});
it('returns portal locale', () => {
router.push({
name: 'list_all_locale_articles',
params: { portalSlug: 'fur-rent', locale: 'es' },
});
expect(wrapper.vm.portalSlug).toBe('fur-rent');
});
it('returns portal slug', () => {
router.push({
name: 'list_all_locale_articles',
params: { portalSlug: 'campaign', locale: 'es' },
});
expect(wrapper.vm.portalSlug).toBe('campaign');
});
});

View File

@@ -2,26 +2,30 @@
<div class="container">
<article-header
:header-title="headerTitle"
:count="articleCount"
:count="meta.count"
selected-value="Published"
@newArticlePage="newArticlePage"
/>
<article-table :articles="articles" :article-count="articles.length" />
<empty-state
v-if="showSearchEmptyState"
:title="$t('HELP_CENTER.TABLE.404')"
<article-table
:articles="articles"
:article-count="articles.length"
:current-page="Number(meta.currentPage)"
:total-count="meta.count"
@on-page-change="onPageChange"
/>
<empty-state
v-else-if="!isLoading && !articles.length"
:title="$t('CONTACTS_PAGE.LIST.NO_CONTACTS')"
/>
<div v-if="isLoading" class="articles--loader">
<div v-if="isFetching" class="articles--loader">
<spinner />
<span>{{ $t('HELP_CENTER.TABLE.LOADING_MESSAGE') }}</span>
</div>
<empty-state
v-else-if="!isFetching && !articles.length"
:title="$t('HELP_CENTER.TABLE.NO_ARTICLES')"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import Spinner from 'shared/components/Spinner.vue';
import ArticleHeader from 'dashboard/routes/dashboard/helpcenter/components/Header/ArticleHeader';
import EmptyState from 'dashboard/components/widgets/EmptyState';
@@ -35,45 +39,18 @@ export default {
},
data() {
return {
// Dummy data will remove once the state is implemented.
articles: [
{
title: 'Setup your account',
author: {
name: 'John Doe',
},
readCount: 13,
category: 'Getting started',
status: 'published',
updatedAt: 1657255863,
},
{
title: 'Docker Configuration',
author: {
name: 'Sam Manuel',
},
readCount: 13,
category: 'Engineering',
status: 'draft',
updatedAt: 1656658046,
},
{
title: 'Campaigns',
author: {
name: 'Sam Manuel',
},
readCount: 28,
category: 'Engineering',
status: 'archived',
updatedAt: 1657590446,
},
],
articleCount: 12,
isLoading: false,
pageNumber: 1,
};
},
computed: {
showSearchEmptyState() {
...mapGetters({
articles: 'articles/allArticles',
uiFlags: 'articles/uiFlags',
meta: 'articles/getMeta',
isFetching: 'articles/isFetching',
}),
showEmptyState() {
return this.articles.length === 0;
},
articleType() {
@@ -92,10 +69,23 @@ export default {
}
},
},
mounted() {
this.fetchArticles({ pageNumber: this.pageNumber });
},
methods: {
newArticlePage() {
this.$router.push({ name: 'new_article' });
},
fetchArticles({ pageNumber }) {
this.$store.dispatch('articles/index', {
pageNumber,
portalSlug: this.$route.params.portalSlug,
locale: this.$route.params.locale,
});
},
onPageChange(page) {
this.fetchArticles({ pageNumber: page });
},
},
};
</script>