feat: Category store integration (#5218)
* Add more actions * Complete sidebar store integration * Complete portal list store integration * Fixed the specs * Added missing specs * Add comment * Code cleanup * Fixed all the spec issues * Add portal and article API specs * Add category name in article list * Add more locales * Code beautification * Exclude locale from codeclimate ci * feat: Category store integration * chore: Minor fixes * chore: API call fixes * chore: Minor fixes * chore: Minor fixes * chore: Adds the ability for get articles based on categories * chore: minor fixes * chore: Minor fixes * chore: fixes specs and minor improvements * chore: Review fixes * chore: Minor fixes * chore: Review fixes * chore: Review fixes * chore: Spacing fixes * Code cleanup Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -7,10 +7,18 @@ class ArticlesAPI extends PortalsAPI {
|
|||||||
super('articles', { accountScoped: true });
|
super('articles', { accountScoped: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
getArticles({ pageNumber, portalSlug, locale, status, author_id }) {
|
getArticles({
|
||||||
|
pageNumber,
|
||||||
|
portalSlug,
|
||||||
|
locale,
|
||||||
|
status,
|
||||||
|
author_id,
|
||||||
|
category_slug,
|
||||||
|
}) {
|
||||||
let baseUrl = `${this.url}/${portalSlug}/articles?page=${pageNumber}&locale=${locale}`;
|
let baseUrl = `${this.url}/${portalSlug}/articles?page=${pageNumber}&locale=${locale}`;
|
||||||
if (status !== undefined) baseUrl += `&status=${status}`;
|
if (status !== undefined) baseUrl += `&status=${status}`;
|
||||||
if (author_id) baseUrl += `&author_id=${author_id}`;
|
if (author_id) baseUrl += `&author_id=${author_id}`;
|
||||||
|
if (category_slug) baseUrl += `&category_slug=${category_slug}`;
|
||||||
return axios.get(baseUrl);
|
return axios.get(baseUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,12 @@
|
|||||||
{{ $t(`SIDEBAR.${menuItem.label}`) }}
|
{{ $t(`SIDEBAR.${menuItem.label}`) }}
|
||||||
</span>
|
</span>
|
||||||
<div v-if="isHelpCenterSidebar" class="submenu-icons">
|
<div v-if="isHelpCenterSidebar" class="submenu-icons">
|
||||||
<fluent-icon icon="search" class="submenu-icon" size="16" />
|
<div class="submenu-icon">
|
||||||
<fluent-icon icon="add" class="submenu-icon" size="16" />
|
<fluent-icon icon="search" size="16" />
|
||||||
|
</div>
|
||||||
|
<div class="submenu-icon" @click="onClickOpen">
|
||||||
|
<fluent-icon icon="add" size="16" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<router-link
|
<router-link
|
||||||
@@ -71,6 +75,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
<p v-if="isHelpCenterSidebar && isCategoryEmpty" class="empty-text">
|
||||||
|
{{ $t('SIDEBAR.HELP_CENTER.CATEGORY_EMPTY_MESSAGE') }}
|
||||||
|
</p>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
@@ -98,6 +105,10 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
isCategoryEmpty: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({ activeInbox: 'getSelectedInbox' }),
|
...mapGetters({ activeInbox: 'getSelectedInbox' }),
|
||||||
@@ -134,11 +145,8 @@ export default {
|
|||||||
this.menuItem.toStateName === 'settings_applications'
|
this.menuItem.toStateName === 'settings_applications'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
isAllArticles() {
|
isArticlesView() {
|
||||||
return (
|
return this.$store.state.route.name === this.menuItem.toStateName;
|
||||||
this.$store.state.route.name === 'list_all_locale_articles' &&
|
|
||||||
this.menuItem.toStateName === 'all_locale_articles'
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computedClass() {
|
computedClass() {
|
||||||
@@ -158,7 +166,7 @@ export default {
|
|||||||
return ' ';
|
return ' ';
|
||||||
}
|
}
|
||||||
if (this.isHelpCenterSidebar) {
|
if (this.isHelpCenterSidebar) {
|
||||||
if (this.isAllArticles) {
|
if (this.isArticlesView) {
|
||||||
return 'is-active';
|
return 'is-active';
|
||||||
}
|
}
|
||||||
return ' ';
|
return ' ';
|
||||||
@@ -195,6 +203,9 @@ export default {
|
|||||||
showItem(item) {
|
showItem(item) {
|
||||||
return this.isAdmin && item.newLink !== undefined;
|
return this.isAdmin && item.newLink !== undefined;
|
||||||
},
|
},
|
||||||
|
onClickOpen() {
|
||||||
|
this.$emit('open');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -324,4 +335,10 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: var(--s-600);
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
margin: var(--space-smaller) 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -70,4 +70,7 @@ export default {
|
|||||||
color: var(--s-600);
|
color: var(--s-600);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
.message {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -174,6 +174,10 @@
|
|||||||
"BUTTONS": {
|
"BUTTONS": {
|
||||||
"CREATE": "Create category",
|
"CREATE": "Create category",
|
||||||
"CANCEL": "Cancel"
|
"CANCEL": "Cancel"
|
||||||
|
},
|
||||||
|
"API": {
|
||||||
|
"SUCCESS_MESSAGE": "Category created successfully",
|
||||||
|
"ERROR_MESSAGE": "Unable to create category"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,8 @@
|
|||||||
"MY_ARTICLES": "My Articles",
|
"MY_ARTICLES": "My Articles",
|
||||||
"DRAFT": "Draft",
|
"DRAFT": "Draft",
|
||||||
"ARCHIVED": "Archived",
|
"ARCHIVED": "Archived",
|
||||||
"CATEGORY": "Category"
|
"CATEGORY": "Category",
|
||||||
|
"CATEGORY_EMPTY_MESSAGE": "No categories found"
|
||||||
},
|
},
|
||||||
"DOCS": "Read docs"
|
"DOCS": "Read docs"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<modal :show.sync="show" :on-close="onClose">
|
<woot-modal :show.sync="show" :on-close="onClose">
|
||||||
<woot-modal-header
|
<woot-modal-header
|
||||||
:header-title="$t('HELP_CENTER.CATEGORY.ADD.TITLE')"
|
:header-title="$t('HELP_CENTER.CATEGORY.ADD.TITLE')"
|
||||||
:header-content="$t('HELP_CENTER.CATEGORY.ADD.SUB_TITLE')"
|
:header-content="$t('HELP_CENTER.CATEGORY.ADD.SUB_TITLE')"
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
:help-text="$t('HELP_CENTER.CATEGORY.ADD.SLUG.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.ADD.SLUG.HELP_TEXT')"
|
||||||
@input="$v.slug.$touch"
|
@input="$v.slug.$touch"
|
||||||
/>
|
/>
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label>
|
||||||
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.LABEL') }}
|
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="description"
|
v-model="description"
|
||||||
@@ -49,37 +49,30 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.PLACEHOLDER')
|
$t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.description.$touch"
|
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.description.$error" class="message">
|
|
||||||
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.ERROR') }}
|
|
||||||
</span>
|
|
||||||
</label>
|
</label>
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<div class="modal-footer justify-content-end w-full">
|
<div class="modal-footer justify-content-end w-full">
|
||||||
<woot-button class="button clear" @click.prevent="onClose">
|
<woot-button class="button clear" @click.prevent="onClose">
|
||||||
{{ $t('HELP_CENTER.CATEGORY.ADD.BUTTONS.CANCEL') }}
|
{{ $t('HELP_CENTER.CATEGORY.ADD.BUTTONS.CANCEL') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
<woot-button>
|
<woot-button @click="addCategory">
|
||||||
{{ $t('HELP_CENTER.CATEGORY.ADD.BUTTONS.CREATE') }}
|
{{ $t('HELP_CENTER.CATEGORY.ADD.BUTTONS.CREATE') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</modal>
|
</woot-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Modal from 'dashboard/components/Modal';
|
import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from 'vuelidate/lib/validators';
|
||||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
|
||||||
Modal,
|
|
||||||
},
|
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
show: {
|
show: {
|
||||||
@@ -110,11 +103,14 @@ export default {
|
|||||||
slug: {
|
slug: {
|
||||||
required,
|
required,
|
||||||
},
|
},
|
||||||
description: {
|
|
||||||
required,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
selectedPortal: 'portals/getSelectedPortal',
|
||||||
|
}),
|
||||||
|
selectedPortalSlug() {
|
||||||
|
return this.selectedPortal?.slug;
|
||||||
|
},
|
||||||
nameError() {
|
nameError() {
|
||||||
if (this.$v.name.$error) {
|
if (this.$v.name.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR');
|
||||||
@@ -134,17 +130,38 @@ export default {
|
|||||||
},
|
},
|
||||||
onCreate() {
|
onCreate() {
|
||||||
this.$emit('create');
|
this.$emit('create');
|
||||||
this.reset();
|
|
||||||
this.$emit('cancel');
|
|
||||||
},
|
},
|
||||||
onClose() {
|
onClose() {
|
||||||
this.reset();
|
|
||||||
this.$emit('cancel');
|
this.$emit('cancel');
|
||||||
},
|
},
|
||||||
reset() {
|
|
||||||
this.name = '';
|
async addCategory() {
|
||||||
this.slug = '';
|
const { name, slug, description } = this;
|
||||||
this.description = '';
|
const data = {
|
||||||
|
name,
|
||||||
|
slug,
|
||||||
|
description,
|
||||||
|
};
|
||||||
|
this.$v.$touch();
|
||||||
|
if (this.$v.$invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('categories/create', {
|
||||||
|
portalSlug: this.selectedPortalSlug,
|
||||||
|
categoryObj: data,
|
||||||
|
});
|
||||||
|
this.alertMessage = this.$t(
|
||||||
|
'HELP_CENTER.CATEGORY.ADD.API.SUCCESS_MESSAGE'
|
||||||
|
);
|
||||||
|
this.onClose();
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = error?.message;
|
||||||
|
this.alertMessage =
|
||||||
|
errorMessage || this.$t('HELP_CENTER.CATEGORY.ADD.API.ERROR_MESSAGE');
|
||||||
|
} finally {
|
||||||
|
this.showAlert(this.alertMessage);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
:accessible-menu-items="accessibleMenuItems"
|
:accessible-menu-items="accessibleMenuItems"
|
||||||
:additional-secondary-menu-items="additionalSecondaryMenuItems"
|
:additional-secondary-menu-items="additionalSecondaryMenuItems"
|
||||||
@open-popover="openPortalPopover"
|
@open-popover="openPortalPopover"
|
||||||
|
@open-modal="onClickOpenAddCatogoryModal"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<section class="app-content columns">
|
<section class="app-content columns">
|
||||||
@@ -33,6 +34,12 @@
|
|||||||
:active-portal="selectedPortal"
|
:active-portal="selectedPortal"
|
||||||
@close-popover="closePortalPopover"
|
@close-popover="closePortalPopover"
|
||||||
/>
|
/>
|
||||||
|
<add-category
|
||||||
|
v-if="showAddCategoryModal"
|
||||||
|
:portal-name="selectedPortalName"
|
||||||
|
:locale="selectedPortalLocale"
|
||||||
|
@cancel="onClickCloseAddCategoryModal"
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -45,8 +52,10 @@ import PortalPopover from '../components/PortalPopover.vue';
|
|||||||
import HelpCenterSidebar from '../components/Sidebar/Sidebar.vue';
|
import HelpCenterSidebar from '../components/Sidebar/Sidebar.vue';
|
||||||
import CommandBar from 'dashboard/routes/dashboard/commands/commandbar.vue';
|
import CommandBar from 'dashboard/routes/dashboard/commands/commandbar.vue';
|
||||||
import WootKeyShortcutModal from 'dashboard/components/widgets/modal/WootKeyShortcutModal';
|
import WootKeyShortcutModal from 'dashboard/components/widgets/modal/WootKeyShortcutModal';
|
||||||
import NotificationPanel from 'dashboard/routes/dashboard/notifications/components/NotificationPanel.vue';
|
import NotificationPanel from 'dashboard/routes/dashboard/notifications/components/NotificationPanel';
|
||||||
import portalMixin from '../mixins/portalMixin';
|
import portalMixin from '../mixins/portalMixin';
|
||||||
|
import AddCategory from '../components/AddCategory.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
@@ -55,6 +64,7 @@ export default {
|
|||||||
WootKeyShortcutModal,
|
WootKeyShortcutModal,
|
||||||
NotificationPanel,
|
NotificationPanel,
|
||||||
PortalPopover,
|
PortalPopover,
|
||||||
|
AddCategory,
|
||||||
},
|
},
|
||||||
mixins: [portalMixin],
|
mixins: [portalMixin],
|
||||||
data() {
|
data() {
|
||||||
@@ -62,6 +72,7 @@ export default {
|
|||||||
showShortcutModal: false,
|
showShortcutModal: false,
|
||||||
showNotificationPanel: false,
|
showNotificationPanel: false,
|
||||||
showPortalPopover: false,
|
showPortalPopover: false,
|
||||||
|
showAddCategoryModal: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -70,9 +81,13 @@ export default {
|
|||||||
accountId: 'getCurrentAccountId',
|
accountId: 'getCurrentAccountId',
|
||||||
selectedPortal: 'portals/getSelectedPortal',
|
selectedPortal: 'portals/getSelectedPortal',
|
||||||
portals: 'portals/allPortals',
|
portals: 'portals/allPortals',
|
||||||
|
categories: 'categories/allCategories',
|
||||||
meta: 'portals/getMeta',
|
meta: 'portals/getMeta',
|
||||||
isFetching: 'portals/isFetchingPortals',
|
isFetching: 'portals/isFetchingPortals',
|
||||||
}),
|
}),
|
||||||
|
selectedPortalName() {
|
||||||
|
return this.selectedPortal ? this.selectedPortal.name : '';
|
||||||
|
},
|
||||||
selectedPortalSlug() {
|
selectedPortalSlug() {
|
||||||
return this.portalSlug || this.selectedPortal?.slug;
|
return this.portalSlug || this.selectedPortal?.slug;
|
||||||
},
|
},
|
||||||
@@ -98,18 +113,18 @@ export default {
|
|||||||
`accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles`
|
`accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles`
|
||||||
),
|
),
|
||||||
toolTip: 'All Articles',
|
toolTip: 'All Articles',
|
||||||
toStateName: 'list_all_selectedPortalLocale_articles',
|
toStateName: 'list_all_locale_articles',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'pen',
|
icon: 'pen',
|
||||||
label: 'HELP_CENTER.MY_ARTICLES',
|
label: 'HELP_CENTER.MY_ARTICLES',
|
||||||
key: 'mine_articles',
|
key: 'list_mine_articles',
|
||||||
count: mineArticlesCount,
|
count: mineArticlesCount,
|
||||||
toState: frontendURL(
|
toState: frontendURL(
|
||||||
`accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles/mine`
|
`accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles/mine`
|
||||||
),
|
),
|
||||||
toolTip: 'My articles',
|
toolTip: 'My articles',
|
||||||
toStateName: 'mine_articles',
|
toStateName: 'list_mine_articles',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'draft',
|
icon: 'draft',
|
||||||
@@ -142,26 +157,15 @@ export default {
|
|||||||
label: 'HELP_CENTER.CATEGORY',
|
label: 'HELP_CENTER.CATEGORY',
|
||||||
hasSubMenu: true,
|
hasSubMenu: true,
|
||||||
key: 'category',
|
key: 'category',
|
||||||
children: [
|
children: this.categories.map(category => ({
|
||||||
{
|
id: category.id,
|
||||||
id: 1,
|
label: category.name,
|
||||||
label: 'Getting started',
|
count: category.meta.articles_count,
|
||||||
count: 12,
|
truncateLabel: true,
|
||||||
truncateLabel: true,
|
toState: frontendURL(
|
||||||
toState: frontendURL(
|
`accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${category.locale}/categories/${category.slug}`
|
||||||
`accounts/${this.accountId}/portals/:portalSlug/:locale/categories/getting-started`
|
),
|
||||||
),
|
})),
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
label: 'Channel',
|
|
||||||
count: 19,
|
|
||||||
truncateLabel: true,
|
|
||||||
toState: frontendURL(
|
|
||||||
`accounts/${this.accountId}/portals/:portalSlug/:locale/categories/channel`
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
@@ -173,11 +177,15 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.fetchPortals();
|
this.fetchPortalsAndItsCategories();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchPortals() {
|
fetchPortalsAndItsCategories() {
|
||||||
this.$store.dispatch('portals/index');
|
this.$store.dispatch('portals/index').then(() => {
|
||||||
|
this.$store.dispatch('categories/index', {
|
||||||
|
portalSlug: this.selectedPortalSlug,
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
toggleKeyShortcutModal() {
|
toggleKeyShortcutModal() {
|
||||||
this.showShortcutModal = true;
|
this.showShortcutModal = true;
|
||||||
@@ -197,6 +205,18 @@ export default {
|
|||||||
closePortalPopover() {
|
closePortalPopover() {
|
||||||
this.showPortalPopover = false;
|
this.showPortalPopover = false;
|
||||||
},
|
},
|
||||||
|
openPortalPage() {
|
||||||
|
this.$router.push({
|
||||||
|
name: 'list_all_portals',
|
||||||
|
});
|
||||||
|
this.showPortalPopover = false;
|
||||||
|
},
|
||||||
|
onClickOpenAddCatogoryModal() {
|
||||||
|
this.showAddCategoryModal = true;
|
||||||
|
},
|
||||||
|
onClickCloseAddCategoryModal() {
|
||||||
|
this.showAddCategoryModal = false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
:key="menuItem.key"
|
:key="menuItem.key"
|
||||||
:menu-item="menuItem"
|
:menu-item="menuItem"
|
||||||
:is-help-center-sidebar="true"
|
:is-help-center-sidebar="true"
|
||||||
|
:is-category-empty="!hasCategory"
|
||||||
|
@open="onClickOpenAddCatogoryModal"
|
||||||
/>
|
/>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,6 +62,14 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
hasCategory() {
|
||||||
|
return (
|
||||||
|
this.additionalSecondaryMenuItems[0] &&
|
||||||
|
this.additionalSecondaryMenuItems[0].children.length > 0
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onSearch(value) {
|
onSearch(value) {
|
||||||
this.$emit('input', value);
|
this.$emit('input', value);
|
||||||
@@ -67,6 +77,9 @@ export default {
|
|||||||
openPortalPopover() {
|
openPortalPopover() {
|
||||||
this.$emit('open-popover');
|
this.$emit('open-popover');
|
||||||
},
|
},
|
||||||
|
onClickOpenAddCatogoryModal() {
|
||||||
|
this.$emit('open-modal');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import AddCategoryComponent from './AddCategory.vue';
|
import AddCategoryComponent from '../AddCategory.vue';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -9,7 +9,7 @@ const ShowPortal = () => import('./pages/portals/ShowPortal');
|
|||||||
const ListAllCategories = () => import('./pages/categories/ListAllCategories');
|
const ListAllCategories = () => import('./pages/categories/ListAllCategories');
|
||||||
const NewCategory = () => import('./pages/categories/NewCategory');
|
const NewCategory = () => import('./pages/categories/NewCategory');
|
||||||
const EditCategory = () => import('./pages/categories/EditCategory');
|
const EditCategory = () => import('./pages/categories/EditCategory');
|
||||||
const ShowCategory = () => import('./pages/categories/ShowCategory');
|
// const ShowCategory = () => import('./pages/categories/ShowCategory');
|
||||||
const ListCategoryArticles = () =>
|
const ListCategoryArticles = () =>
|
||||||
import('./pages/articles/ListCategoryArticles');
|
import('./pages/articles/ListCategoryArticles');
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ const categoryRoutes = [
|
|||||||
path: getPortalRoute(':portalSlug/:locale/categories/:categorySlug'),
|
path: getPortalRoute(':portalSlug/:locale/categories/:categorySlug'),
|
||||||
name: 'show_category',
|
name: 'show_category',
|
||||||
roles: ['administrator', 'agent'],
|
roles: ['administrator', 'agent'],
|
||||||
component: ShowCategory,
|
component: ListAllArticles,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: getPortalRoute(
|
path: getPortalRoute(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<article-header
|
<article-header
|
||||||
:header-title="headerTitle"
|
:header-title="headerTitle"
|
||||||
:count="meta.count"
|
:count="articleCount"
|
||||||
selected-value="Published"
|
selected-value="Published"
|
||||||
@newArticlePage="newArticlePage"
|
@newArticlePage="newArticlePage"
|
||||||
/>
|
/>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
:articles="articles"
|
:articles="articles"
|
||||||
:article-count="articles.length"
|
:article-count="articles.length"
|
||||||
:current-page="Number(meta.currentPage)"
|
:current-page="Number(meta.currentPage)"
|
||||||
:total-count="meta.count"
|
:total-count="articleCount"
|
||||||
@on-page-change="onPageChange"
|
@on-page-change="onPageChange"
|
||||||
/>
|
/>
|
||||||
<div v-if="shouldShowLoader" class="articles--loader">
|
<div v-if="shouldShowLoader" class="articles--loader">
|
||||||
@@ -45,17 +45,31 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
articles: 'articles/allArticles',
|
articles: 'articles/allArticles',
|
||||||
|
categories: 'categories/allCategories',
|
||||||
|
selectedPortal: 'portals/getSelectedPortal',
|
||||||
uiFlags: 'articles/uiFlags',
|
uiFlags: 'articles/uiFlags',
|
||||||
meta: 'articles/getMeta',
|
meta: 'articles/getMeta',
|
||||||
isFetching: 'articles/isFetching',
|
isFetching: 'articles/isFetching',
|
||||||
currentUserId: 'getCurrentUserID',
|
currentUserId: 'getCurrentUserID',
|
||||||
}),
|
}),
|
||||||
|
selectedCategory() {
|
||||||
|
return this.categories.find(
|
||||||
|
category => category.slug === this.selectedCategorySlug
|
||||||
|
);
|
||||||
|
},
|
||||||
shouldShowEmptyState() {
|
shouldShowEmptyState() {
|
||||||
return !this.isFetching && !this.articles.length;
|
return !this.isFetching && !this.articles.length;
|
||||||
},
|
},
|
||||||
shouldShowLoader() {
|
shouldShowLoader() {
|
||||||
return this.isFetching && !this.articles.length;
|
return this.isFetching && !this.articles.length;
|
||||||
},
|
},
|
||||||
|
selectedPortalSlug() {
|
||||||
|
return this.selectedPortal?.slug;
|
||||||
|
},
|
||||||
|
selectedCategorySlug() {
|
||||||
|
const { categorySlug } = this.$route.params;
|
||||||
|
return categorySlug;
|
||||||
|
},
|
||||||
articleType() {
|
articleType() {
|
||||||
return this.$route.path.split('/').pop();
|
return this.$route.path.split('/').pop();
|
||||||
},
|
},
|
||||||
@@ -68,6 +82,9 @@ export default {
|
|||||||
case 'archived':
|
case 'archived':
|
||||||
return this.$t('HELP_CENTER.HEADER.TITLES.ARCHIVED');
|
return this.$t('HELP_CENTER.HEADER.TITLES.ARCHIVED');
|
||||||
default:
|
default:
|
||||||
|
if (this.$route.name === 'show_category') {
|
||||||
|
return this.headerTitleInCategoryView;
|
||||||
|
}
|
||||||
return this.$t('HELP_CENTER.HEADER.TITLES.ALL_ARTICLES');
|
return this.$t('HELP_CENTER.HEADER.TITLES.ALL_ARTICLES');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -89,6 +106,14 @@ export default {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
articleCount() {
|
||||||
|
return this.articles ? this.articles.length : 0;
|
||||||
|
},
|
||||||
|
headerTitleInCategoryView() {
|
||||||
|
return this.categories && this.categories.length
|
||||||
|
? this.selectedCategory.name
|
||||||
|
: '';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
$route() {
|
$route() {
|
||||||
@@ -111,6 +136,7 @@ export default {
|
|||||||
locale: this.$route.params.locale,
|
locale: this.$route.params.locale,
|
||||||
status: this.status,
|
status: this.status,
|
||||||
author_id: this.author,
|
author_id: this.author,
|
||||||
|
category_slug: this.selectedCategorySlug,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onPageChange(page) {
|
onPageChange(page) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import types from '../../mutation-types';
|
|||||||
export const actions = {
|
export const actions = {
|
||||||
index: async (
|
index: async (
|
||||||
{ commit },
|
{ commit },
|
||||||
{ pageNumber, portalSlug, locale, status, author_id }
|
{ pageNumber, portalSlug, locale, status, author_id, category_slug }
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
commit(types.SET_UI_FLAG, { isFetching: true });
|
commit(types.SET_UI_FLAG, { isFetching: true });
|
||||||
@@ -17,6 +17,7 @@ export const actions = {
|
|||||||
locale,
|
locale,
|
||||||
status,
|
status,
|
||||||
author_id,
|
author_id,
|
||||||
|
category_slug,
|
||||||
});
|
});
|
||||||
const articleIds = payload.map(article => article.id);
|
const articleIds = payload.map(article => article.id);
|
||||||
commit(types.CLEAR_ARTICLES);
|
commit(types.CLEAR_ARTICLES);
|
||||||
|
|||||||
@@ -5,13 +5,16 @@ export const actions = {
|
|||||||
index: async ({ commit }, { portalSlug }) => {
|
index: async ({ commit }, { portalSlug }) => {
|
||||||
try {
|
try {
|
||||||
commit(types.SET_UI_FLAG, { isFetching: true });
|
commit(types.SET_UI_FLAG, { isFetching: true });
|
||||||
const {
|
if (portalSlug) {
|
||||||
data: { payload },
|
const {
|
||||||
} = await categoriesAPI.get({ portalSlug });
|
data: { payload },
|
||||||
const categoryIds = payload.map(category => category.id);
|
} = await categoriesAPI.get({ portalSlug });
|
||||||
commit(types.ADD_MANY_CATEGORIES, payload);
|
const categoryIds = payload.map(category => category.id);
|
||||||
commit(types.ADD_MANY_CATEGORIES_ID, categoryIds);
|
commit(types.ADD_MANY_CATEGORIES, payload);
|
||||||
return categoryIds;
|
commit(types.ADD_MANY_CATEGORIES_ID, categoryIds);
|
||||||
|
return categoryIds;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return throwErrorMessage(error);
|
return throwErrorMessage(error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -19,12 +22,14 @@ export const actions = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
create: async ({ commit }, portalSlug, categoryObj) => {
|
create: async ({ commit }, { portalSlug, categoryObj }) => {
|
||||||
commit(types.SET_UI_FLAG, { isCreating: true });
|
commit(types.SET_UI_FLAG, { isCreating: true });
|
||||||
try {
|
try {
|
||||||
const { data } = await categoriesAPI.create({ portalSlug, categoryObj });
|
const {
|
||||||
const { id: categoryId } = data;
|
data: { payload },
|
||||||
commit(types.ADD_CATEGORY, data);
|
} = await categoriesAPI.create({ portalSlug, categoryObj });
|
||||||
|
const { id: categoryId } = payload;
|
||||||
|
commit(types.ADD_CATEGORY, payload);
|
||||||
commit(types.ADD_CATEGORY_ID, categoryId);
|
commit(types.ADD_CATEGORY_ID, categoryId);
|
||||||
return categoryId;
|
return categoryId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -32,12 +32,13 @@ describe('#actions', () => {
|
|||||||
|
|
||||||
describe('#create', () => {
|
describe('#create', () => {
|
||||||
it('sends correct actions if API is success', async () => {
|
it('sends correct actions if API is success', async () => {
|
||||||
axios.post.mockResolvedValue({ data: categoriesPayload.payload[0] });
|
axios.post.mockResolvedValue({ data: categoriesPayload });
|
||||||
await actions.create({ commit }, categoriesPayload.payload[0]);
|
await actions.create({ commit }, categoriesPayload);
|
||||||
|
const { id: categoryId } = categoriesPayload;
|
||||||
expect(commit.mock.calls).toEqual([
|
expect(commit.mock.calls).toEqual([
|
||||||
[types.default.SET_UI_FLAG, { isCreating: true }],
|
[types.default.SET_UI_FLAG, { isCreating: true }],
|
||||||
[types.default.ADD_CATEGORY, categoriesPayload.payload[0]],
|
[types.default.ADD_CATEGORY, categoriesPayload.payload],
|
||||||
[types.default.ADD_CATEGORY_ID, 1],
|
[types.default.ADD_CATEGORY_ID, categoryId],
|
||||||
[types.default.SET_UI_FLAG, { isCreating: false }],
|
[types.default.SET_UI_FLAG, { isCreating: false }],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user