diff --git a/.codeclimate.yml b/.codeclimate.yml
index 916b98510..974681a09 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -53,3 +53,4 @@ exclude_patterns:
- 'app/javascript/dashboard/i18n/index.js'
- 'app/javascript/widget/i18n/index.js'
- 'app/javascript/survey/i18n/index.js'
+ - 'app/javascript/shared/constants/locales.js'
diff --git a/app/javascript/dashboard/api/helpCenter/articles.js b/app/javascript/dashboard/api/helpCenter/articles.js
index c252ce4c2..3f3ab3a49 100644
--- a/app/javascript/dashboard/api/helpCenter/articles.js
+++ b/app/javascript/dashboard/api/helpCenter/articles.js
@@ -1,9 +1,18 @@
-import ApiClient from '../ApiClient';
+/* global axios */
-class ArticlesAPI extends ApiClient {
+import PortalsAPI from './portals';
+
+class ArticlesAPI extends PortalsAPI {
constructor() {
super('articles', { accountScoped: true });
}
+
+ getArticles({ pageNumber, portalSlug, locale, status, author_id }) {
+ let baseUrl = `${this.url}/${portalSlug}/articles?page=${pageNumber}&locale=${locale}`;
+ if (status !== undefined) baseUrl += `&status=${status}`;
+ if (author_id) baseUrl += `&author_id=${author_id}`;
+ return axios.get(baseUrl);
+ }
}
export default new ArticlesAPI();
diff --git a/app/javascript/dashboard/api/helpCenter/portals.js b/app/javascript/dashboard/api/helpCenter/portals.js
index 1df4d2554..594050cdf 100644
--- a/app/javascript/dashboard/api/helpCenter/portals.js
+++ b/app/javascript/dashboard/api/helpCenter/portals.js
@@ -1,16 +1,9 @@
-/* global axios */
import ApiClient from '../ApiClient';
class PortalsAPI extends ApiClient {
constructor() {
super('portals', { accountScoped: true });
}
-
- getArticles({ pageNumber, portalSlug, locale }) {
- return axios.get(
- `${this.url}/${portalSlug}/articles?page=${pageNumber}&locale=${locale}`
- );
- }
}
export default PortalsAPI;
diff --git a/app/javascript/dashboard/api/specs/article.spec.js b/app/javascript/dashboard/api/specs/article.spec.js
new file mode 100644
index 000000000..a60a784c0
--- /dev/null
+++ b/app/javascript/dashboard/api/specs/article.spec.js
@@ -0,0 +1,29 @@
+import articlesAPI from '../helpCenter/articles';
+import ApiClient from 'dashboard/api/helpCenter/portals';
+import describeWithAPIMock from './apiSpecHelper';
+
+describe('#PortalAPI', () => {
+ it('creates correct instance', () => {
+ expect(articlesAPI).toBeInstanceOf(ApiClient);
+ expect(articlesAPI).toHaveProperty('get');
+ expect(articlesAPI).toHaveProperty('show');
+ expect(articlesAPI).toHaveProperty('create');
+ expect(articlesAPI).toHaveProperty('update');
+ expect(articlesAPI).toHaveProperty('delete');
+ expect(articlesAPI).toHaveProperty('getArticles');
+ });
+ describeWithAPIMock('API calls', context => {
+ it('#getArticles', () => {
+ articlesAPI.getArticles({
+ pageNumber: 1,
+ portalSlug: 'room-rental',
+ locale: 'en-US',
+ status: 'published',
+ author_id: '1',
+ });
+ expect(context.axiosMock.get).toHaveBeenCalledWith(
+ '/api/v1/portals/room-rental/articles?page=1&locale=en-US&status=published&author_id=1'
+ );
+ });
+ });
+});
diff --git a/app/javascript/dashboard/api/specs/portals.spec.js b/app/javascript/dashboard/api/specs/portals.spec.js
new file mode 100644
index 000000000..8d6968cb7
--- /dev/null
+++ b/app/javascript/dashboard/api/specs/portals.spec.js
@@ -0,0 +1,13 @@
+import PortalsAPI from '../helpCenter/portals';
+import ApiClient from '../ApiClient';
+const portalAPI = new PortalsAPI();
+describe('#PortalAPI', () => {
+ it('creates correct instance', () => {
+ expect(portalAPI).toBeInstanceOf(ApiClient);
+ expect(portalAPI).toHaveProperty('get');
+ expect(portalAPI).toHaveProperty('show');
+ expect(portalAPI).toHaveProperty('create');
+ expect(portalAPI).toHaveProperty('update');
+ expect(portalAPI).toHaveProperty('delete');
+ });
+});
diff --git a/app/javascript/dashboard/i18n/locale/en/helpCenter.json b/app/javascript/dashboard/i18n/locale/en/helpCenter.json
index 6004f4e29..15792bc97 100644
--- a/app/javascript/dashboard/i18n/locale/en/helpCenter.json
+++ b/app/javascript/dashboard/i18n/locale/en/helpCenter.json
@@ -31,7 +31,9 @@
"NEW_BUTTON": "New Portal",
"ACTIVE_BADGE": "active",
"CHOOSE_LOCALE_LABEL": "Choose a locale",
+ "LOADING_MESSAGE": "Loading portals...",
"ARTICLES_LABEL": "articles",
+ "NO_PORTALS_MESSAGE": "There are no available portals",
"ADD_NEW_LOCALE": "Add a new locale",
"POPOVER": {
"TITLE": "Portals",
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue
index e88c1eafc..3c1f9cdf9 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue
@@ -15,7 +15,7 @@
-
{{ category }} |
+ {{ category.name }} |
{{ readCount }} |
@@ -48,8 +48,8 @@ export default {
default: () => {},
},
category: {
- type: String,
- default: '',
+ type: Object,
+ default: () => {},
},
readCount: {
type: Number,
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue
index 282e292b3..101bc72d7 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue
@@ -28,6 +28,7 @@
-
+
@@ -41,12 +41,12 @@ import { mapGetters } from 'vuex';
import { frontendURL } from '../../../../helper/URLHelper';
import Sidebar from 'dashboard/components/layout/Sidebar';
-import PortalPopover from 'dashboard/routes/dashboard/helpcenter/components/PortalPopover';
-import HelpCenterSidebar from 'dashboard/routes/dashboard/helpcenter/components/Sidebar/Sidebar';
+import PortalPopover from '../components/PortalPopover.vue';
+import HelpCenterSidebar from '../components/Sidebar/Sidebar.vue';
import CommandBar from 'dashboard/routes/dashboard/commands/commandbar.vue';
import WootKeyShortcutModal from 'dashboard/components/widgets/modal/WootKeyShortcutModal';
import NotificationPanel from 'dashboard/routes/dashboard/notifications/components/NotificationPanel.vue';
-
+import portalMixin from '../mixins/portalMixin';
export default {
components: {
Sidebar,
@@ -56,6 +56,7 @@ export default {
NotificationPanel,
PortalPopover,
},
+ mixins: [portalMixin],
data() {
return {
showShortcutModal: false,
@@ -63,36 +64,49 @@ export default {
showPortalPopover: false,
};
},
+
computed: {
...mapGetters({
accountId: 'getCurrentAccountId',
+ selectedPortal: 'portals/getSelectedPortal',
+ portals: 'portals/allPortals',
+ meta: 'portals/getMeta',
+ isFetching: 'portals/isFetchingPortals',
}),
- portalSlug() {
- return this.$route.params.portalSlug;
+ selectedPortalSlug() {
+ return this.portalSlug || this.selectedPortal?.slug;
},
- locale() {
- return this.$route.params.locale;
+ selectedPortalLocale() {
+ return this.locale || this.selectedPortal?.meta?.default_locale;
},
accessibleMenuItems() {
+ const {
+ meta: {
+ all_articles_count: allArticlesCount,
+ mine_articles_count: mineArticlesCount,
+ draft_articles_count: draftArticlesCount,
+ archived_articles_count: archivedArticlesCount,
+ } = {},
+ } = this.selectedPortal;
return [
{
icon: 'book',
label: 'HELP_CENTER.ALL_ARTICLES',
key: 'list_all_locale_articles',
- count: 199,
+ count: allArticlesCount,
toState: frontendURL(
- `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles`
+ `accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles`
),
toolTip: 'All Articles',
- toStateName: 'list_all_locale_articles',
+ toStateName: 'list_all_selectedPortalLocale_articles',
},
{
icon: 'pen',
label: 'HELP_CENTER.MY_ARTICLES',
key: 'mine_articles',
- count: 112,
+ count: mineArticlesCount,
toState: frontendURL(
- `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/mine`
+ `accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles/mine`
),
toolTip: 'My articles',
toStateName: 'mine_articles',
@@ -101,9 +115,9 @@ export default {
icon: 'draft',
label: 'HELP_CENTER.DRAFT',
key: 'list_draft_articles',
- count: 32,
+ count: draftArticlesCount,
toState: frontendURL(
- `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/draft`
+ `accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles/draft`
),
toolTip: 'Draft',
toStateName: 'list_draft_articles',
@@ -112,9 +126,9 @@ export default {
icon: 'archive',
label: 'HELP_CENTER.ARCHIVED',
key: 'list_archived_articles',
- count: 10,
+ count: archivedArticlesCount,
toState: frontendURL(
- `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/archived`
+ `accounts/${this.accountId}/portals/${this.selectedPortalSlug}/${this.selectedPortalLocale}/articles/archived`
),
toolTip: 'Archived',
toStateName: 'list_archived_articles',
@@ -147,172 +161,6 @@ export default {
`accounts/${this.accountId}/portals/:portalSlug/:locale/categories/channel`
),
},
- {
- id: 3,
- label: 'Feature',
- count: 24,
- truncateLabel: true,
- toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/categories/feature`
- ),
- },
- {
- id: 4,
- label: 'Advanced',
- count: 8,
- truncateLabel: true,
- toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/categories/advanced`
- ),
- },
- {
- id: 5,
- label: 'Mobile app',
- count: 3,
- truncateLabel: true,
- toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/categories/mobile-app`
- ),
- },
- {
- id: 6,
- label: 'Others',
- count: 39,
- truncateLabel: true,
- toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/categories/others`
- ),
- },
- ],
- },
- ];
- },
- portals() {
- return [
- {
- name: 'Chatwoot Help Center',
- id: 1,
- color: null,
- custom_domain: 'doc',
- articles_count: 123,
- header_text: null,
- homepage_link: null,
- page_title: null,
- slug: 'first_portal',
- archived: false,
- config: {
- allowed_locales: [
- {
- code: 'en',
- name: 'English',
- articles_count: 123,
- },
- {
- code: 'fr',
- name: 'Français',
- articles_count: 123,
- },
- {
- code: 'de',
- name: 'Deutsch',
- articles_count: 32,
- },
- {
- code: 'es',
- name: 'Español',
- articles_count: 12,
- },
- {
- code: 'it',
- name: 'Italiano',
- articles_count: 8,
- },
- ],
- },
- locales: [
- {
- name: 'English',
- code: 'en',
- articles_count: 12,
- },
- {
- name: 'Español',
- code: 'es',
- articles_count: 42,
- },
- {
- name: 'French',
- code: 'fr',
- articles_count: 29,
- },
- {
- name: 'Italian',
- code: 'it',
- articles_count: 4,
- },
- {
- name: 'German',
- code: 'de',
- articles_count: 66,
- },
- ],
- },
- {
- name: 'Chatwoot Docs',
- id: 2,
- color: null,
- custom_domain: 'doc',
- articles_count: 124,
- header_text: null,
- homepage_link: null,
- page_title: null,
- slug: 'second_portal',
- archived: false,
- config: {
- allowed_locales: [
- {
- code: 'en',
- name: 'English',
- articles_count: 123,
- },
- {
- code: 'fr',
- name: 'Français',
- articles_count: 123,
- },
- {
- code: 'de',
- name: 'Deutsch',
- articles_count: 32,
- },
- {
- code: 'es',
- name: 'Español',
- articles_count: 12,
- },
- {
- code: 'it',
- name: 'Italiano',
- articles_count: 8,
- },
- ],
- },
- locales: [
- {
- name: 'English',
- code: 'en',
- articles_count: 12,
- },
- {
- name: 'Japanese',
- code: 'jp',
- articles_count: 4,
- },
- {
- name: 'Mandarin',
- code: 'CH',
- articles_count: 6,
- },
],
},
];
@@ -320,8 +168,17 @@ export default {
currentRoute() {
return ' ';
},
+ headerTitle() {
+ return this.selectedPortal.name;
+ },
+ },
+ mounted() {
+ this.fetchPortals();
},
methods: {
+ fetchPortals() {
+ this.$store.dispatch('portals/index');
+ },
toggleKeyShortcutModal() {
this.showShortcutModal = true;
},
@@ -340,12 +197,6 @@ export default {
closePortalPopover() {
this.showPortalPopover = false;
},
- openPortalPage() {
- this.$router.push({
- name: 'list_all_portals',
- });
- this.showPortalPopover = false;
- },
},
};
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItem.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItem.vue
index 11de14069..55b38231d 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItem.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItem.vue
@@ -1,6 +1,6 @@
-
+
@@ -118,7 +118,6 @@
class="theme-color"
:style="{ background: portal.color }"
/>
- {{ portal.page_title }}
@@ -127,7 +126,7 @@
'HELP_CENTER.PORTAL.PORTAL_SETTINGS.LIST_ITEM.PORTAL_CONFIG.ITEMS.SUB_TEXT'
)
}}
- {{ portal.page_title }}
+ {{ portal.header_text }}
@@ -141,8 +140,8 @@
}}
@@ -163,33 +162,28 @@ export default {
LocaleItemTable,
},
props: {
- portals: {
- type: Array,
- default: () => [],
+ portal: {
+ type: Object,
+ default: () => {},
},
status: {
type: String,
default: '',
values: ['archived', 'draft', 'published'],
},
- selectedLocaleCode: {
- type: String,
- default: '',
- },
},
computed: {
labelColor() {
switch (this.status) {
- case 'archived':
- return 'secondary';
- case 'draft':
+ case 'Archived':
return 'warning';
default:
return 'success';
}
},
- defaultLocale(code) {
- return code === this.selectedLocaleCode;
+
+ locales() {
+ return this.portal ? this.portal.config.allowed_locales : [];
},
},
methods: {
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue
index d1f44faa7..08e1ee719 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue
@@ -37,9 +37,9 @@
|
-
+
|
- {{ locale.name }}
+ {{ localeName(locale.code) }}
| |