feat: Portals store integration (#5185)
This commit is contained in:
parent
052422ed03
commit
20f3568583
30 changed files with 982 additions and 413 deletions
|
@ -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'
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
29
app/javascript/dashboard/api/specs/article.spec.js
Normal file
29
app/javascript/dashboard/api/specs/article.spec.js
Normal file
|
@ -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'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
13
app/javascript/dashboard/api/specs/portals.spec.js
Normal file
13
app/javascript/dashboard/api/specs/portals.spec.js
Normal file
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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",
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ category }}</td>
|
||||
<td>{{ category.name }}</td>
|
||||
<td>{{ readCount }}</td>
|
||||
<td>
|
||||
<Label :title="status" :color-scheme="labelColor" />
|
||||
|
@ -48,8 +48,8 @@ export default {
|
|||
default: () => {},
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
default: '',
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
readCount: {
|
||||
type: Number,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<table-footer
|
||||
v-if="articles.length"
|
||||
:on-page-change="onPageChange"
|
||||
:current-page="Number(currentPage)"
|
||||
:total-count="totalCount"
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
@open-key-shortcut-modal="toggleKeyShortcutModal"
|
||||
@close-key-shortcut-modal="closeKeyShortcutModal"
|
||||
/>
|
||||
<div class="margin-right-small">
|
||||
<div v-if="portals.length" class="margin-right-small">
|
||||
<help-center-sidebar
|
||||
header-title="Help Center"
|
||||
sub-title="English"
|
||||
:header-title="headerTitle"
|
||||
:sub-title="localeName(selectedPortalLocale)"
|
||||
:accessible-menu-items="accessibleMenuItems"
|
||||
:additional-secondary-menu-items="additionalSecondaryMenuItems"
|
||||
@open-popover="openPortalPopover"
|
||||
|
@ -30,8 +30,8 @@
|
|||
<portal-popover
|
||||
v-if="showPortalPopover"
|
||||
:portals="portals"
|
||||
:active-portal="selectedPortal"
|
||||
@close-popover="closePortalPopover"
|
||||
@open-portal-page="openPortalPage"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -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;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-for="portal in portals" :key="portal.id" class="portal">
|
||||
<div class="portal">
|
||||
<thumbnail :username="portal.name" variant="square" />
|
||||
<div class="container">
|
||||
<header>
|
||||
|
@ -118,7 +118,6 @@
|
|||
class="theme-color"
|
||||
:style="{ background: portal.color }"
|
||||
/>
|
||||
<span class="text-block-title">{{ portal.page_title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="configuration-item">
|
||||
|
@ -127,7 +126,7 @@
|
|||
'HELP_CENTER.PORTAL.PORTAL_SETTINGS.LIST_ITEM.PORTAL_CONFIG.ITEMS.SUB_TEXT'
|
||||
)
|
||||
}}</label>
|
||||
<span class="text-block-title">{{ portal.page_title }}</span>
|
||||
<span class="text-block-title">{{ portal.header_text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -141,8 +140,8 @@
|
|||
}}
|
||||
</h2>
|
||||
<locale-item-table
|
||||
:portals="portal"
|
||||
:selected-locale-code="selectedLocaleCode"
|
||||
:locales="locales"
|
||||
:selected-locale-code="portal.meta.default_locale"
|
||||
@swap="swapLocale"
|
||||
@delete="deleteLocale"
|
||||
/>
|
||||
|
@ -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: {
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
<td colspan="100%" class="horizontal-line" />
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr v-for="locale in portals.locales" :key="locale.code">
|
||||
<tr v-for="locale in locales" :key="locale.code">
|
||||
<td>
|
||||
<span>{{ locale.name }}</span>
|
||||
<span>{{ localeName(locale.code) }}</span>
|
||||
<Label
|
||||
v-if="locale.code === selectedLocaleCode"
|
||||
:title="
|
||||
|
@ -95,20 +95,23 @@
|
|||
|
||||
<script>
|
||||
import Label from 'dashboard/components/ui/Label';
|
||||
import portalMixin from '../mixins/portalMixin';
|
||||
export default {
|
||||
components: {
|
||||
Label,
|
||||
},
|
||||
mixins: [portalMixin],
|
||||
props: {
|
||||
portals: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
locales: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
selectedLocaleCode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
swapLocale() {
|
||||
this.$emit('swap');
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
color-scheme="secondary"
|
||||
icon="settings"
|
||||
size="small"
|
||||
@click="openPortalPage"
|
||||
>
|
||||
{{ $t('HELP_CENTER.PORTAL.POPOVER.PORTAL_SETTINGS') }}
|
||||
</woot-button>
|
||||
|
@ -24,6 +23,8 @@
|
|||
v-for="portal in portals"
|
||||
:key="portal.id"
|
||||
:portal="portal"
|
||||
:active="portal.id === activePortal.id"
|
||||
@open-portal-page="openPortalPage"
|
||||
/>
|
||||
</div>
|
||||
<footer>
|
||||
|
@ -50,13 +51,26 @@ export default {
|
|||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
activePortal: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closePortalPopover() {
|
||||
this.$emit('close-popover');
|
||||
},
|
||||
openPortalPage() {
|
||||
this.$emit('open-portal-page');
|
||||
openPortalPage({ slug, locale }) {
|
||||
this.$emit('close-popover');
|
||||
const portal = this.portals.find(p => p.slug === slug);
|
||||
this.$store.dispatch('portals/setPortalId', portal.id);
|
||||
this.$router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: {
|
||||
portalSlug: slug,
|
||||
locale: locale,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div>
|
||||
<h2 class="portal-title">{{ portal.name }}</h2>
|
||||
<p class="portal-count">
|
||||
{{ portal.articles_count }}
|
||||
{{ articlesCount }}
|
||||
{{ $t('HELP_CENTER.PORTAL.ARTICLES_LABEL') }}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -19,7 +19,7 @@
|
|||
{{ $t('HELP_CENTER.PORTAL.CHOOSE_LOCALE_LABEL') }}
|
||||
</h2>
|
||||
<ul>
|
||||
<li v-for="locale in portal.locales" :key="locale.code">
|
||||
<li v-for="locale in locales" :key="locale.code">
|
||||
<label :for="`locale-${locale.code}`" class="locale-item">
|
||||
<input
|
||||
:id="`locale-${locale.code}`"
|
||||
|
@ -27,9 +27,10 @@
|
|||
type="radio"
|
||||
name="locale"
|
||||
:value="locale.code"
|
||||
@click="onClick(locale.code, portal)"
|
||||
/>
|
||||
<div>
|
||||
<p>{{ locale.name }}</p>
|
||||
<p>{{ localeName(locale.code) }}</p>
|
||||
<span>
|
||||
{{ locale.articles_count }}
|
||||
{{ $t('HELP_CENTER.PORTAL.ARTICLES_LABEL') }} -
|
||||
|
@ -49,10 +50,12 @@
|
|||
|
||||
<script>
|
||||
import thumbnail from 'dashboard/components/widgets/Thumbnail';
|
||||
import portalMixin from '../mixins/portalMixin';
|
||||
export default {
|
||||
components: {
|
||||
thumbnail,
|
||||
},
|
||||
mixins: [portalMixin],
|
||||
props: {
|
||||
portal: {
|
||||
type: Object,
|
||||
|
@ -65,11 +68,24 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
selectedLocale: '',
|
||||
selectedLocale: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
locales() {
|
||||
return this.portal?.config?.allowed_locales;
|
||||
},
|
||||
articlesCount() {
|
||||
return this.portal?.meta?.all_articles_count;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.selectedLocale = this.portal.locales[0].code;
|
||||
this.selectedLocale = this.locale || this.portal?.meta?.default_locale;
|
||||
},
|
||||
methods: {
|
||||
onClick(code, portal) {
|
||||
this.$emit('open-portal-page', { slug: portal.slug, locale: code });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { mapGetters } from 'vuex';
|
||||
import { frontendURL } from 'dashboard/helper/URLHelper';
|
||||
import allLocales from 'shared/constants/locales.js';
|
||||
export default {
|
||||
computed: {
|
||||
...mapGetters({ accountId: 'getCurrentAccountId' }),
|
||||
|
@ -16,5 +17,8 @@ export default {
|
|||
`accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/${id}`
|
||||
);
|
||||
},
|
||||
localeName(code) {
|
||||
return allLocales[code];
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ describe('portalMixin', () => {
|
|||
expect(wrapper.vm.accountId).toBe(1);
|
||||
});
|
||||
|
||||
it('returns portal url', () => {
|
||||
it('returns article url', () => {
|
||||
router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: { portalSlug: 'fur-rent', locale: 'en' },
|
||||
|
@ -65,4 +65,12 @@ describe('portalMixin', () => {
|
|||
});
|
||||
expect(wrapper.vm.portalSlug).toBe('campaign');
|
||||
});
|
||||
|
||||
it('returns locale name', () => {
|
||||
router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: { portalSlug: 'fur-rent', locale: 'es' },
|
||||
});
|
||||
expect(wrapper.vm.localeName('es')).toBe('Spanish');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
:total-count="meta.count"
|
||||
@on-page-change="onPageChange"
|
||||
/>
|
||||
<div v-if="isFetching" class="articles--loader">
|
||||
<div v-if="shouldShowLoader" class="articles--loader">
|
||||
<spinner />
|
||||
<span>{{ $t('HELP_CENTER.TABLE.LOADING_MESSAGE') }}</span>
|
||||
</div>
|
||||
<empty-state
|
||||
v-else-if="!isFetching && !articles.length"
|
||||
v-else-if="shouldShowEmptyState"
|
||||
:title="$t('HELP_CENTER.TABLE.NO_ARTICLES')"
|
||||
/>
|
||||
</div>
|
||||
|
@ -48,10 +48,13 @@ export default {
|
|||
uiFlags: 'articles/uiFlags',
|
||||
meta: 'articles/getMeta',
|
||||
isFetching: 'articles/isFetching',
|
||||
currentUserId: 'getCurrentUserID',
|
||||
}),
|
||||
|
||||
showEmptyState() {
|
||||
return this.articles.length === 0;
|
||||
shouldShowEmptyState() {
|
||||
return !this.isFetching && !this.articles.length;
|
||||
},
|
||||
shouldShowLoader() {
|
||||
return this.isFetching && !this.articles.length;
|
||||
},
|
||||
articleType() {
|
||||
return this.$route.path.split('/').pop();
|
||||
|
@ -68,19 +71,46 @@ export default {
|
|||
return this.$t('HELP_CENTER.HEADER.TITLES.ALL_ARTICLES');
|
||||
}
|
||||
},
|
||||
status() {
|
||||
switch (this.articleType) {
|
||||
case 'draft':
|
||||
return 0;
|
||||
case 'published':
|
||||
return 1;
|
||||
case 'archived':
|
||||
return 2;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
author() {
|
||||
if (this.articleType === 'mine') {
|
||||
return this.currentUserId;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.pageNumber = 1;
|
||||
this.fetchArticles();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchArticles({ pageNumber: this.pageNumber });
|
||||
this.fetchArticles();
|
||||
},
|
||||
|
||||
methods: {
|
||||
newArticlePage() {
|
||||
this.$router.push({ name: 'new_article' });
|
||||
},
|
||||
fetchArticles({ pageNumber }) {
|
||||
fetchArticles() {
|
||||
this.$store.dispatch('articles/index', {
|
||||
pageNumber,
|
||||
pageNumber: this.pageNumber,
|
||||
portalSlug: this.$route.params.portalSlug,
|
||||
locale: this.$route.params.locale,
|
||||
status: this.status,
|
||||
author_id: this.author,
|
||||
});
|
||||
},
|
||||
onPageChange(page) {
|
||||
|
|
|
@ -8,134 +8,46 @@
|
|||
</div>
|
||||
<div class="portal-container">
|
||||
<portal-list-item
|
||||
:portals="portals"
|
||||
status="published"
|
||||
selected-locale-code="en-US"
|
||||
v-for="portal in portals"
|
||||
:key="portal.id"
|
||||
:portal="portal"
|
||||
:status="portalStatus"
|
||||
/>
|
||||
<div v-if="isFetching" class="portals--loader">
|
||||
<spinner />
|
||||
<span>{{ $t('HELP_CENTER.PORTAL.LOADING_MESSAGE') }}</span>
|
||||
</div>
|
||||
<empty-state
|
||||
v-else-if="shouldShowEmptyState"
|
||||
:title="$t('HELP_CENTER.PORTAL.NO_PORTALS_MESSAGE')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PortalListItem from 'dashboard/routes/dashboard/helpcenter/components/PortalListItem';
|
||||
import { mapGetters } from 'vuex';
|
||||
import PortalListItem from '../../components/PortalListItem';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
import EmptyState from 'dashboard/components/widgets/EmptyState';
|
||||
export default {
|
||||
components: {
|
||||
PortalListItem,
|
||||
EmptyState,
|
||||
Spinner,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Dummy data for testing will remove once the state is implemented.
|
||||
portals: [
|
||||
{
|
||||
name: 'Chatwoot Help Center',
|
||||
id: 1,
|
||||
color: 'red',
|
||||
custom_domain: 'help-center.chatwoot.com',
|
||||
articles_count: 123,
|
||||
header_text: 'Help center',
|
||||
homepage_link: null,
|
||||
page_title: 'English',
|
||||
slug: 'help-center',
|
||||
archived: false,
|
||||
config: {
|
||||
allowed_locales: [
|
||||
{
|
||||
code: 'en-US',
|
||||
name: 'English',
|
||||
articles_count: 123,
|
||||
categories_count: 42,
|
||||
computed: {
|
||||
...mapGetters({
|
||||
portals: 'portals/allPortals',
|
||||
meta: 'portals/getMeta',
|
||||
isFetching: 'portals/isFetchingPortals',
|
||||
}),
|
||||
portalStatus() {
|
||||
return this.archived ? 'Archived' : 'Live';
|
||||
},
|
||||
{
|
||||
code: 'fr-FR',
|
||||
name: 'Français',
|
||||
articles_count: 23,
|
||||
categories_count: 11,
|
||||
shouldShowEmptyState() {
|
||||
return !this.isFetching && !this.portals.length;
|
||||
},
|
||||
{
|
||||
code: 'de-DE',
|
||||
name: 'Deutsch',
|
||||
articles_count: 32,
|
||||
categories_count: 12,
|
||||
},
|
||||
{
|
||||
code: 'es-ES',
|
||||
name: 'Español',
|
||||
articles_count: 12,
|
||||
categories_count: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
locales: [
|
||||
{
|
||||
code: 'en-US',
|
||||
name: 'English',
|
||||
articles_count: 123,
|
||||
categories_count: 42,
|
||||
},
|
||||
{
|
||||
code: 'fr-FR',
|
||||
name: 'Français',
|
||||
articles_count: 23,
|
||||
categories_count: 11,
|
||||
},
|
||||
{
|
||||
code: 'de-DE',
|
||||
name: 'Deutsch',
|
||||
articles_count: 32,
|
||||
categories_count: 12,
|
||||
},
|
||||
{
|
||||
code: 'es-ES',
|
||||
name: 'Español',
|
||||
articles_count: 12,
|
||||
categories_count: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Chatwoot Docs',
|
||||
id: 2,
|
||||
color: 'green',
|
||||
custom_domain: 'doc-chatwoot.com',
|
||||
articles_count: 67,
|
||||
header_text: 'Docs',
|
||||
homepage_link: null,
|
||||
page_title: 'Portal',
|
||||
slug: 'second_portal',
|
||||
archived: false,
|
||||
config: {
|
||||
allowed_locales: [
|
||||
{
|
||||
name: 'English',
|
||||
code: 'en-EN',
|
||||
articles_count: 12,
|
||||
categories_count: 66,
|
||||
},
|
||||
{
|
||||
name: 'Mandarin',
|
||||
code: 'ch-CH',
|
||||
articles_count: 6,
|
||||
categories_count: 23,
|
||||
},
|
||||
],
|
||||
},
|
||||
locales: [
|
||||
{
|
||||
name: 'English',
|
||||
code: 'en-EN',
|
||||
articles_count: 12,
|
||||
categories_count: 66,
|
||||
},
|
||||
{
|
||||
name: 'Mandarin',
|
||||
code: 'ch-CH',
|
||||
articles_count: 6,
|
||||
categories_count: 23,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
createPortal() {
|
||||
|
@ -149,7 +61,13 @@ export default {
|
|||
.container {
|
||||
padding: var(--space-small) var(--space-normal);
|
||||
width: 100%;
|
||||
|
||||
.portals--loader {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-size: var(--font-size-default);
|
||||
justify-content: center;
|
||||
padding: var(--space-big);
|
||||
}
|
||||
.header-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
|
|
@ -36,6 +36,8 @@ import teams from './modules/teams';
|
|||
import userNotificationSettings from './modules/userNotificationSettings';
|
||||
import webhooks from './modules/webhooks';
|
||||
import articles from './modules/helpCenterArticles';
|
||||
import portals from './modules/helpCenterPortals';
|
||||
import categories from './modules/helpCenterCategories';
|
||||
|
||||
Vue.use(Vuex);
|
||||
export default new Vuex.Store({
|
||||
|
@ -75,5 +77,7 @@ export default new Vuex.Store({
|
|||
userNotificationSettings,
|
||||
webhooks,
|
||||
articles,
|
||||
portals,
|
||||
categories,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
import PortalAPI from 'dashboard/api/helpCenter/portals';
|
||||
import articlesAPI from 'dashboard/api/helpCenter/articles';
|
||||
import { throwErrorMessage } from 'dashboard/store/utils/api';
|
||||
const portalAPIs = new PortalAPI();
|
||||
|
||||
import types from '../../mutation-types';
|
||||
export const actions = {
|
||||
index: async ({ commit }, { pageNumber, portalSlug, locale }) => {
|
||||
index: async (
|
||||
{ commit },
|
||||
{ pageNumber, portalSlug, locale, status, author_id }
|
||||
) => {
|
||||
try {
|
||||
commit(types.SET_UI_FLAG, { isFetching: true });
|
||||
const {
|
||||
data: { payload, meta },
|
||||
} = await portalAPIs.getArticles({
|
||||
} = await articlesAPI.getArticles({
|
||||
pageNumber,
|
||||
portalSlug,
|
||||
locale,
|
||||
status,
|
||||
author_id,
|
||||
});
|
||||
const articleIds = payload.map(article => article.id);
|
||||
commit(types.CLEAR_ARTICLES);
|
||||
|
|
|
@ -8,7 +8,7 @@ export const defaultHelpCenterFlags = {
|
|||
isDeleting: false,
|
||||
};
|
||||
const state = {
|
||||
categoriess: {
|
||||
categories: {
|
||||
byId: {},
|
||||
byLocale: {},
|
||||
allIds: [],
|
||||
|
|
|
@ -3,13 +3,22 @@ import { throwErrorMessage } from 'dashboard/store/utils/api';
|
|||
import { types } from './mutations';
|
||||
const portalAPIs = new PortalAPI();
|
||||
export const actions = {
|
||||
index: async ({ commit }) => {
|
||||
index: async ({ commit, state, dispatch }) => {
|
||||
try {
|
||||
commit(types.SET_UI_FLAG, { isFetching: true });
|
||||
const { data } = await portalAPIs.get();
|
||||
const portalIds = data.map(portal => portal.id);
|
||||
commit(types.ADD_MANY_PORTALS_ENTRY, data);
|
||||
const {
|
||||
data: { payload, meta },
|
||||
} = await portalAPIs.get();
|
||||
commit(types.CLEAR_PORTALS);
|
||||
const portalIds = payload.map(portal => portal.id);
|
||||
commit(types.ADD_MANY_PORTALS_ENTRY, payload);
|
||||
commit(types.ADD_MANY_PORTALS_IDS, portalIds);
|
||||
const { selectedPortalId } = state;
|
||||
// Check if selected portal is still in the portals list
|
||||
if (!portalIds.includes(selectedPortalId)) {
|
||||
dispatch('setPortalId', portalIds[0]);
|
||||
}
|
||||
commit(types.SET_PORTALS_META, meta);
|
||||
} catch (error) {
|
||||
throwErrorMessage(error);
|
||||
} finally {
|
||||
|
@ -68,4 +77,8 @@ export const actions = {
|
|||
});
|
||||
}
|
||||
},
|
||||
|
||||
setPortalId: async ({ commit }, portalId) => {
|
||||
commit(types.SET_SELECTED_PORTAL_ID, portalId);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -16,11 +16,18 @@ export const getters = {
|
|||
},
|
||||
allPortals: (...getterArguments) => {
|
||||
const [state, _getters] = getterArguments;
|
||||
|
||||
const portals = state.portals.allIds.map(id => {
|
||||
return _getters.portalById(id);
|
||||
});
|
||||
return portals;
|
||||
},
|
||||
count: state => state.portals.allIds.length || 0,
|
||||
getMeta: state => {
|
||||
return state.meta;
|
||||
},
|
||||
getSelectedPortal: (...getterArguments) => {
|
||||
const [state, _getters] = getterArguments;
|
||||
const { selectedPortalId } = state.portals;
|
||||
return _getters.portalById(selectedPortalId);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -9,6 +9,11 @@ export const defaultPortalFlags = {
|
|||
};
|
||||
|
||||
const state = {
|
||||
meta: {
|
||||
count: 0,
|
||||
currentPage: 1,
|
||||
},
|
||||
|
||||
portals: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
|
@ -20,6 +25,7 @@ const state = {
|
|||
meta: {
|
||||
byId: {},
|
||||
},
|
||||
selectedPortalId: null,
|
||||
},
|
||||
uiFlags: {
|
||||
allFetched: false,
|
||||
|
|
|
@ -4,9 +4,12 @@ import { defaultPortalFlags } from './index';
|
|||
export const types = {
|
||||
SET_UI_FLAG: 'setUIFlag',
|
||||
ADD_PORTAL_ENTRY: 'addPortalEntry',
|
||||
SET_PORTALS_META: 'setPortalsMeta',
|
||||
ADD_MANY_PORTALS_ENTRY: 'addManyPortalsEntry',
|
||||
ADD_PORTAL_ID: 'addPortalId',
|
||||
CLEAR_PORTALS: 'clearPortals',
|
||||
ADD_MANY_PORTALS_IDS: 'addManyPortalsIds',
|
||||
SET_SELECTED_PORTAL_ID: 'setSelectedPortalId',
|
||||
UPDATE_PORTAL_ENTRY: 'updatePortalEntry',
|
||||
REMOVE_PORTAL_ENTRY: 'removePortalEntry',
|
||||
REMOVE_PORTAL_ID: 'removePortalId',
|
||||
|
@ -32,9 +35,23 @@ export const mutations = {
|
|||
portals.forEach(portal => {
|
||||
allPortals[portal.id] = portal;
|
||||
});
|
||||
Vue.set($state.portals, 'byId', {
|
||||
allPortals,
|
||||
});
|
||||
Vue.set($state.portals, 'byId', allPortals);
|
||||
},
|
||||
|
||||
[types.CLEAR_PORTALS]: $state => {
|
||||
Vue.set($state.portals, 'byId', {});
|
||||
Vue.set($state.portals, 'allIds', []);
|
||||
Vue.set($state.portals, 'uiFlags', {});
|
||||
},
|
||||
|
||||
[types.SET_PORTALS_META]: ($state, data) => {
|
||||
const { portals_count: count, current_page: currentPage } = data;
|
||||
Vue.set($state.meta, 'count', count);
|
||||
Vue.set($state.meta, 'currentPage', currentPage);
|
||||
},
|
||||
|
||||
[types.SET_SELECTED_PORTAL_ID]: ($state, portalId) => {
|
||||
Vue.set($state.portals, 'selectedPortalId', portalId);
|
||||
},
|
||||
|
||||
[types.ADD_PORTAL_ID]($state, portalId) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { types } from '../mutations';
|
|||
import { apiResponse } from './fixtures';
|
||||
|
||||
const commit = jest.fn();
|
||||
const dispatch = jest.fn();
|
||||
global.axios = axios;
|
||||
jest.mock('axios');
|
||||
|
||||
|
@ -11,11 +12,20 @@ describe('#actions', () => {
|
|||
describe('#index', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: apiResponse });
|
||||
await actions.index({ commit });
|
||||
await actions.index({
|
||||
commit,
|
||||
dispatch,
|
||||
state: {
|
||||
selectedPortalId: 4,
|
||||
},
|
||||
});
|
||||
expect(dispatch.mock.calls).toMatchObject([['setPortalId', 1]]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_UI_FLAG, { isFetching: true }],
|
||||
[types.ADD_MANY_PORTALS_ENTRY, apiResponse],
|
||||
[types.CLEAR_PORTALS],
|
||||
[types.ADD_MANY_PORTALS_ENTRY, apiResponse.payload],
|
||||
[types.ADD_MANY_PORTALS_IDS, [1, 2]],
|
||||
[types.SET_PORTALS_META, { current_page: 1, portals_count: 1 }],
|
||||
[types.SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
@ -31,7 +41,7 @@ describe('#actions', () => {
|
|||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: apiResponse[1] });
|
||||
axios.post.mockResolvedValue({ data: apiResponse.payload[1] });
|
||||
await actions.create(
|
||||
{ commit },
|
||||
{
|
||||
|
@ -42,7 +52,7 @@ describe('#actions', () => {
|
|||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_UI_FLAG, { isCreating: true }],
|
||||
[types.ADD_PORTAL_ENTRY, apiResponse[1]],
|
||||
[types.ADD_PORTAL_ENTRY, apiResponse.payload[1]],
|
||||
[types.ADD_PORTAL_ID, 2],
|
||||
[types.SET_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
|
@ -59,14 +69,14 @@ describe('#actions', () => {
|
|||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: apiResponse[1] });
|
||||
await actions.update({ commit }, apiResponse[1]);
|
||||
axios.patch.mockResolvedValue({ data: apiResponse.payload[1] });
|
||||
await actions.update({ commit }, apiResponse.payload[1]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_HELP_PORTAL_UI_FLAG,
|
||||
{ uiFlags: { isUpdating: true }, portalId: 2 },
|
||||
],
|
||||
[types.UPDATE_PORTAL_ENTRY, apiResponse[1]],
|
||||
[types.UPDATE_PORTAL_ENTRY, apiResponse.payload[1]],
|
||||
[
|
||||
types.SET_HELP_PORTAL_UI_FLAG,
|
||||
{ uiFlags: { isUpdating: false }, portalId: 2 },
|
||||
|
@ -75,9 +85,9 @@ describe('#actions', () => {
|
|||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.update({ commit }, apiResponse[1])).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
await expect(
|
||||
actions.update({ commit }, apiResponse.payload[1])
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_HELP_PORTAL_UI_FLAG,
|
||||
|
@ -123,4 +133,11 @@ describe('#actions', () => {
|
|||
]);
|
||||
});
|
||||
});
|
||||
describe('#setPortalId', () => {
|
||||
it('sends correct actions', async () => {
|
||||
axios.delete.mockResolvedValue({});
|
||||
await actions.setPortalId({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([[types.SET_SELECTED_PORTAL_ID, 1]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export default {
|
||||
meta: {
|
||||
count: 0,
|
||||
currentPage: 1,
|
||||
},
|
||||
portals: {
|
||||
byId: {
|
||||
1: {
|
||||
|
@ -36,6 +40,7 @@ export default {
|
|||
1: { isFetching: false, isUpdating: true, isDeleting: false },
|
||||
},
|
||||
},
|
||||
selectedPortalId: 1,
|
||||
},
|
||||
uiFlags: {
|
||||
allFetched: false,
|
||||
|
@ -43,7 +48,8 @@ export default {
|
|||
},
|
||||
};
|
||||
|
||||
export const apiResponse = [
|
||||
export const apiResponse = {
|
||||
payload: [
|
||||
{
|
||||
id: 1,
|
||||
color: 'red',
|
||||
|
@ -72,4 +78,9 @@ export const apiResponse = [
|
|||
allowed_locales: ['en'],
|
||||
},
|
||||
},
|
||||
];
|
||||
],
|
||||
meta: {
|
||||
current_page: 1,
|
||||
portals_count: 1,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -42,4 +42,9 @@ describe('#getters', () => {
|
|||
const state = portal;
|
||||
expect(getters.count(state)).toEqual(2);
|
||||
});
|
||||
|
||||
it('getMeta', () => {
|
||||
const state = portal;
|
||||
expect(getters.getMeta(state)).toEqual({ count: 0, currentPage: 1 });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -92,4 +92,33 @@ describe('#mutations', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_PORTALS', () => {
|
||||
it('clears portals', () => {
|
||||
mutations[types.CLEAR_PORTALS](state);
|
||||
expect(state.portals.allIds).toEqual([]);
|
||||
expect(state.portals.byId).toEqual({});
|
||||
expect(state.portals.uiFlags).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_PORTALS_META', () => {
|
||||
it('add meta to state', () => {
|
||||
mutations[types.SET_PORTALS_META](state, {
|
||||
portals_count: 10,
|
||||
current_page: 1,
|
||||
});
|
||||
expect(state.meta).toEqual({
|
||||
count: 10,
|
||||
currentPage: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_SELECTED_PORTAL_ID', () => {
|
||||
it('set selected portal id', () => {
|
||||
mutations[types.SET_SELECTED_PORTAL_ID](state, 4);
|
||||
expect(state.portals.selectedPortalId).toEqual(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
566
app/javascript/shared/constants/locales.js
Normal file
566
app/javascript/shared/constants/locales.js
Normal file
|
@ -0,0 +1,566 @@
|
|||
const locales = {
|
||||
af: 'Afrikaans',
|
||||
af_NA: 'Afrikaans (Namibia)',
|
||||
af_ZA: 'Afrikaans (South Africa)',
|
||||
ak: 'Akan',
|
||||
ak_GH: 'Akan (Ghana)',
|
||||
sq: 'Albanian',
|
||||
sq_AL: 'Albanian (Albania)',
|
||||
sq_XK: 'Albanian (Kosovo)',
|
||||
sq_MK: 'Albanian (Macedonia)',
|
||||
am: 'Amharic',
|
||||
am_ET: 'Amharic (Ethiopia)',
|
||||
ar: 'Arabic',
|
||||
ar_DZ: 'Arabic (Algeria)',
|
||||
ar_BH: 'Arabic (Bahrain)',
|
||||
ar_TD: 'Arabic (Chad)',
|
||||
ar_KM: 'Arabic (Comoros)',
|
||||
ar_DJ: 'Arabic (Djibouti)',
|
||||
ar_EG: 'Arabic (Egypt)',
|
||||
ar_ER: 'Arabic (Eritrea)',
|
||||
ar_IQ: 'Arabic (Iraq)',
|
||||
ar_IL: 'Arabic (Israel)',
|
||||
ar_JO: 'Arabic (Jordan)',
|
||||
ar_KW: 'Arabic (Kuwait)',
|
||||
ar_LB: 'Arabic (Lebanon)',
|
||||
ar_LY: 'Arabic (Libya)',
|
||||
ar_MR: 'Arabic (Mauritania)',
|
||||
ar_MA: 'Arabic (Morocco)',
|
||||
ar_OM: 'Arabic (Oman)',
|
||||
ar_PS: 'Arabic (Palestinian Territories)',
|
||||
ar_QA: 'Arabic (Qatar)',
|
||||
ar_SA: 'Arabic (Saudi Arabia)',
|
||||
ar_SO: 'Arabic (Somalia)',
|
||||
ar_SS: 'Arabic (South Sudan)',
|
||||
ar_SD: 'Arabic (Sudan)',
|
||||
ar_SY: 'Arabic (Syria)',
|
||||
ar_TN: 'Arabic (Tunisia)',
|
||||
ar_AE: 'Arabic (United Arab Emirates)',
|
||||
ar_EH: 'Arabic (Western Sahara)',
|
||||
ar_YE: 'Arabic (Yemen)',
|
||||
hy: 'Armenian',
|
||||
hy_AM: 'Armenian (Armenia)',
|
||||
as: 'Assamese',
|
||||
as_IN: 'Assamese (India)',
|
||||
az: 'Azerbaijani',
|
||||
az_AZ: 'Azerbaijani (Azerbaijan)',
|
||||
az_Cyrl_AZ: 'Azerbaijani (Cyrillic, Azerbaijan)',
|
||||
az_Cyrl: 'Azerbaijani (Cyrillic)',
|
||||
az_Latn_AZ: 'Azerbaijani (Latin, Azerbaijan)',
|
||||
az_Latn: 'Azerbaijani (Latin)',
|
||||
bm: 'Bambara',
|
||||
bm_Latn_ML: 'Bambara (Latin, Mali)',
|
||||
bm_Latn: 'Bambara (Latin)',
|
||||
eu: 'Basque',
|
||||
eu_ES: 'Basque (Spain)',
|
||||
be: 'Belarusian',
|
||||
be_BY: 'Belarusian (Belarus)',
|
||||
bn: 'Bengali',
|
||||
bn_BD: 'Bengali (Bangladesh)',
|
||||
bn_IN: 'Bengali (India)',
|
||||
bs: 'Bosnian',
|
||||
bs_BA: 'Bosnian (Bosnia & Herzegovina)',
|
||||
bs_Cyrl_BA: 'Bosnian (Cyrillic, Bosnia & Herzegovina)',
|
||||
bs_Cyrl: 'Bosnian (Cyrillic)',
|
||||
bs_Latn_BA: 'Bosnian (Latin, Bosnia & Herzegovina)',
|
||||
bs_Latn: 'Bosnian (Latin)',
|
||||
br: 'Breton',
|
||||
br_FR: 'Breton (France)',
|
||||
bg: 'Bulgarian',
|
||||
bg_BG: 'Bulgarian (Bulgaria)',
|
||||
my: 'Burmese',
|
||||
my_MM: 'Burmese (Myanmar (Burma))',
|
||||
ca: 'Catalan',
|
||||
ca_AD: 'Catalan (Andorra)',
|
||||
ca_FR: 'Catalan (France)',
|
||||
ca_IT: 'Catalan (Italy)',
|
||||
ca_ES: 'Catalan (Spain)',
|
||||
zh: 'Chinese',
|
||||
zh_CN: 'Chinese (China)',
|
||||
zh_HK: 'Chinese (Hong Kong SAR China)',
|
||||
zh_MO: 'Chinese (Macau SAR China)',
|
||||
zh_Hans_CN: 'Chinese (Simplified, China)',
|
||||
zh_Hans_HK: 'Chinese (Simplified, Hong Kong SAR China)',
|
||||
zh_Hans_MO: 'Chinese (Simplified, Macau SAR China)',
|
||||
zh_Hans_SG: 'Chinese (Simplified, Singapore)',
|
||||
zh_Hans: 'Chinese (Simplified)',
|
||||
zh_SG: 'Chinese (Singapore)',
|
||||
zh_TW: 'Chinese (Taiwan)',
|
||||
zh_Hant_HK: 'Chinese (Traditional, Hong Kong SAR China)',
|
||||
zh_Hant_MO: 'Chinese (Traditional, Macau SAR China)',
|
||||
zh_Hant_TW: 'Chinese (Traditional, Taiwan)',
|
||||
zh_Hant: 'Chinese (Traditional)',
|
||||
kw: 'Cornish',
|
||||
kw_GB: 'Cornish (United Kingdom)',
|
||||
hr: 'Croatian',
|
||||
hr_BA: 'Croatian (Bosnia & Herzegovina)',
|
||||
hr_HR: 'Croatian (Croatia)',
|
||||
cs: 'Czech',
|
||||
cs_CZ: 'Czech (Czech Republic)',
|
||||
da: 'Danish',
|
||||
da_DK: 'Danish (Denmark)',
|
||||
da_GL: 'Danish (Greenland)',
|
||||
nl: 'Dutch',
|
||||
nl_AW: 'Dutch (Aruba)',
|
||||
nl_BE: 'Dutch (Belgium)',
|
||||
nl_BQ: 'Dutch (Caribbean Netherlands)',
|
||||
nl_CW: 'Dutch (Curaçao)',
|
||||
nl_NL: 'Dutch (Netherlands)',
|
||||
nl_SX: 'Dutch (Sint Maarten)',
|
||||
nl_SR: 'Dutch (Suriname)',
|
||||
dz: 'Dzongkha',
|
||||
dz_BT: 'Dzongkha (Bhutan)',
|
||||
en: 'English',
|
||||
en_AS: 'English (American Samoa)',
|
||||
en_AI: 'English (Anguilla)',
|
||||
en_AG: 'English (Antigua & Barbuda)',
|
||||
en_AU: 'English (Australia)',
|
||||
en_BS: 'English (Bahamas)',
|
||||
en_BB: 'English (Barbados)',
|
||||
en_BE: 'English (Belgium)',
|
||||
en_BZ: 'English (Belize)',
|
||||
en_BM: 'English (Bermuda)',
|
||||
en_BW: 'English (Botswana)',
|
||||
en_IO: 'English (British Indian Ocean Territory)',
|
||||
en_VG: 'English (British Virgin Islands)',
|
||||
en_CM: 'English (Cameroon)',
|
||||
en_CA: 'English (Canada)',
|
||||
en_KY: 'English (Cayman Islands)',
|
||||
en_CX: 'English (Christmas Island)',
|
||||
en_CC: 'English (Cocos (Keeling) Islands)',
|
||||
en_CK: 'English (Cook Islands)',
|
||||
en_DG: 'English (Diego Garcia)',
|
||||
en_DM: 'English (Dominica)',
|
||||
en_ER: 'English (Eritrea)',
|
||||
en_FK: 'English (Falkland Islands)',
|
||||
en_FJ: 'English (Fiji)',
|
||||
en_GM: 'English (Gambia)',
|
||||
en_GH: 'English (Ghana)',
|
||||
en_GI: 'English (Gibraltar)',
|
||||
en_GD: 'English (Grenada)',
|
||||
en_GU: 'English (Guam)',
|
||||
en_GG: 'English (Guernsey)',
|
||||
en_GY: 'English (Guyana)',
|
||||
en_HK: 'English (Hong Kong SAR China)',
|
||||
en_IN: 'English (India)',
|
||||
en_IE: 'English (Ireland)',
|
||||
en_IM: 'English (Isle of Man)',
|
||||
en_JM: 'English (Jamaica)',
|
||||
en_JE: 'English (Jersey)',
|
||||
en_KE: 'English (Kenya)',
|
||||
en_KI: 'English (Kiribati)',
|
||||
en_LS: 'English (Lesotho)',
|
||||
en_LR: 'English (Liberia)',
|
||||
en_MO: 'English (Macau SAR China)',
|
||||
en_MG: 'English (Madagascar)',
|
||||
en_MW: 'English (Malawi)',
|
||||
en_MY: 'English (Malaysia)',
|
||||
en_MT: 'English (Malta)',
|
||||
en_MH: 'English (Marshall Islands)',
|
||||
en_MU: 'English (Mauritius)',
|
||||
en_FM: 'English (Micronesia)',
|
||||
en_MS: 'English (Montserrat)',
|
||||
en_NA: 'English (Namibia)',
|
||||
en_NR: 'English (Nauru)',
|
||||
en_NZ: 'English (New Zealand)',
|
||||
en_NG: 'English (Nigeria)',
|
||||
en_NU: 'English (Niue)',
|
||||
en_NF: 'English (Norfolk Island)',
|
||||
en_MP: 'English (Northern Mariana Islands)',
|
||||
en_PK: 'English (Pakistan)',
|
||||
en_PW: 'English (Palau)',
|
||||
en_PG: 'English (Papua New Guinea)',
|
||||
en_PH: 'English (Philippines)',
|
||||
en_PN: 'English (Pitcairn Islands)',
|
||||
en_PR: 'English (Puerto Rico)',
|
||||
en_RW: 'English (Rwanda)',
|
||||
en_WS: 'English (Samoa)',
|
||||
en_SC: 'English (Seychelles)',
|
||||
en_SL: 'English (Sierra Leone)',
|
||||
en_SG: 'English (Singapore)',
|
||||
en_SX: 'English (Sint Maarten)',
|
||||
en_SB: 'English (Solomon Islands)',
|
||||
en_ZA: 'English (South Africa)',
|
||||
en_SS: 'English (South Sudan)',
|
||||
en_SH: 'English (St. Helena)',
|
||||
en_KN: 'English (St. Kitts & Nevis)',
|
||||
en_LC: 'English (St. Lucia)',
|
||||
en_VC: 'English (St. Vincent & Grenadines)',
|
||||
en_SD: 'English (Sudan)',
|
||||
en_SZ: 'English (Swaziland)',
|
||||
en_TZ: 'English (Tanzania)',
|
||||
en_TK: 'English (Tokelau)',
|
||||
en_TO: 'English (Tonga)',
|
||||
en_TT: 'English (Trinidad & Tobago)',
|
||||
en_TC: 'English (Turks & Caicos Islands)',
|
||||
en_TV: 'English (Tuvalu)',
|
||||
en_UM: 'English (U.S. Outlying Islands)',
|
||||
en_VI: 'English (U.S. Virgin Islands)',
|
||||
en_UG: 'English (Uganda)',
|
||||
en_GB: 'English (United Kingdom)',
|
||||
en_US: 'English (United States)',
|
||||
en_VU: 'English (Vanuatu)',
|
||||
en_ZM: 'English (Zambia)',
|
||||
en_ZW: 'English (Zimbabwe)',
|
||||
eo: 'Esperanto',
|
||||
et: 'Estonian',
|
||||
et_EE: 'Estonian (Estonia)',
|
||||
ee: 'Ewe',
|
||||
ee_GH: 'Ewe (Ghana)',
|
||||
ee_TG: 'Ewe (Togo)',
|
||||
fo: 'Faroese',
|
||||
fo_FO: 'Faroese (Faroe Islands)',
|
||||
fi: 'Finnish',
|
||||
fi_FI: 'Finnish (Finland)',
|
||||
fr: 'French',
|
||||
fr_DZ: 'French (Algeria)',
|
||||
fr_BE: 'French (Belgium)',
|
||||
fr_BJ: 'French (Benin)',
|
||||
fr_BF: 'French (Burkina Faso)',
|
||||
fr_BI: 'French (Burundi)',
|
||||
fr_CM: 'French (Cameroon)',
|
||||
fr_CA: 'French (Canada)',
|
||||
fr_CF: 'French (Central African Republic)',
|
||||
fr_TD: 'French (Chad)',
|
||||
fr_KM: 'French (Comoros)',
|
||||
fr_CG: 'French (Congo - Brazzaville)',
|
||||
fr_CD: 'French (Congo - Kinshasa)',
|
||||
fr_CI: 'French (Côte d’Ivoire)',
|
||||
fr_DJ: 'French (Djibouti)',
|
||||
fr_GQ: 'French (Equatorial Guinea)',
|
||||
fr_FR: 'French (France)',
|
||||
fr_GF: 'French (French Guiana)',
|
||||
fr_PF: 'French (French Polynesia)',
|
||||
fr_GA: 'French (Gabon)',
|
||||
fr_GP: 'French (Guadeloupe)',
|
||||
fr_GN: 'French (Guinea)',
|
||||
fr_HT: 'French (Haiti)',
|
||||
fr_LU: 'French (Luxembourg)',
|
||||
fr_MG: 'French (Madagascar)',
|
||||
fr_ML: 'French (Mali)',
|
||||
fr_MQ: 'French (Martinique)',
|
||||
fr_MR: 'French (Mauritania)',
|
||||
fr_MU: 'French (Mauritius)',
|
||||
fr_YT: 'French (Mayotte)',
|
||||
fr_MC: 'French (Monaco)',
|
||||
fr_MA: 'French (Morocco)',
|
||||
fr_NC: 'French (New Caledonia)',
|
||||
fr_NE: 'French (Niger)',
|
||||
fr_RE: 'French (Réunion)',
|
||||
fr_RW: 'French (Rwanda)',
|
||||
fr_SN: 'French (Senegal)',
|
||||
fr_SC: 'French (Seychelles)',
|
||||
fr_BL: 'French (St. Barthélemy)',
|
||||
fr_MF: 'French (St. Martin)',
|
||||
fr_PM: 'French (St. Pierre & Miquelon)',
|
||||
fr_CH: 'French (Switzerland)',
|
||||
fr_SY: 'French (Syria)',
|
||||
fr_TG: 'French (Togo)',
|
||||
fr_TN: 'French (Tunisia)',
|
||||
fr_VU: 'French (Vanuatu)',
|
||||
fr_WF: 'French (Wallis & Futuna)',
|
||||
ff: 'Fulah',
|
||||
ff_CM: 'Fulah (Cameroon)',
|
||||
ff_GN: 'Fulah (Guinea)',
|
||||
ff_MR: 'Fulah (Mauritania)',
|
||||
ff_SN: 'Fulah (Senegal)',
|
||||
gl: 'Galician',
|
||||
gl_ES: 'Galician (Spain)',
|
||||
lg: 'Ganda',
|
||||
lg_UG: 'Ganda (Uganda)',
|
||||
ka: 'Georgian',
|
||||
ka_GE: 'Georgian (Georgia)',
|
||||
de: 'German',
|
||||
de_AT: 'German (Austria)',
|
||||
de_BE: 'German (Belgium)',
|
||||
de_DE: 'German (Germany)',
|
||||
de_LI: 'German (Liechtenstein)',
|
||||
de_LU: 'German (Luxembourg)',
|
||||
de_CH: 'German (Switzerland)',
|
||||
el: 'Greek',
|
||||
el_CY: 'Greek (Cyprus)',
|
||||
el_GR: 'Greek (Greece)',
|
||||
gu: 'Gujarati',
|
||||
gu_IN: 'Gujarati (India)',
|
||||
ha: 'Hausa',
|
||||
ha_GH: 'Hausa (Ghana)',
|
||||
ha_Latn_GH: 'Hausa (Latin, Ghana)',
|
||||
ha_Latn_NE: 'Hausa (Latin, Niger)',
|
||||
ha_Latn_NG: 'Hausa (Latin, Nigeria)',
|
||||
ha_Latn: 'Hausa (Latin)',
|
||||
ha_NE: 'Hausa (Niger)',
|
||||
ha_NG: 'Hausa (Nigeria)',
|
||||
he: 'Hebrew',
|
||||
he_IL: 'Hebrew (Israel)',
|
||||
hi: 'Hindi',
|
||||
hi_IN: 'Hindi (India)',
|
||||
hu: 'Hungarian',
|
||||
hu_HU: 'Hungarian (Hungary)',
|
||||
is: 'Icelandic',
|
||||
is_IS: 'Icelandic (Iceland)',
|
||||
ig: 'Igbo',
|
||||
ig_NG: 'Igbo (Nigeria)',
|
||||
id: 'Indonesian',
|
||||
id_ID: 'Indonesian (Indonesia)',
|
||||
ga: 'Irish',
|
||||
ga_IE: 'Irish (Ireland)',
|
||||
it: 'Italian',
|
||||
it_IT: 'Italian (Italy)',
|
||||
it_SM: 'Italian (San Marino)',
|
||||
it_CH: 'Italian (Switzerland)',
|
||||
ja: 'Japanese',
|
||||
ja_JP: 'Japanese (Japan)',
|
||||
kl: 'Kalaallisut',
|
||||
kl_GL: 'Kalaallisut (Greenland)',
|
||||
kn: 'Kannada',
|
||||
kn_IN: 'Kannada (India)',
|
||||
ks: 'Kashmiri',
|
||||
ks_Arab_IN: 'Kashmiri (Arabic, India)',
|
||||
ks_Arab: 'Kashmiri (Arabic)',
|
||||
ks_IN: 'Kashmiri (India)',
|
||||
kk: 'Kazakh',
|
||||
kk_Cyrl_KZ: 'Kazakh (Cyrillic, Kazakhstan)',
|
||||
kk_Cyrl: 'Kazakh (Cyrillic)',
|
||||
kk_KZ: 'Kazakh (Kazakhstan)',
|
||||
km: 'Khmer',
|
||||
km_KH: 'Khmer (Cambodia)',
|
||||
ki: 'Kikuyu',
|
||||
ki_KE: 'Kikuyu (Kenya)',
|
||||
rw: 'Kinyarwanda',
|
||||
rw_RW: 'Kinyarwanda (Rwanda)',
|
||||
ko: 'Korean',
|
||||
ko_KP: 'Korean (North Korea)',
|
||||
ko_KR: 'Korean (South Korea)',
|
||||
ky: 'Kyrgyz',
|
||||
ky_Cyrl_KG: 'Kyrgyz (Cyrillic, Kyrgyzstan)',
|
||||
ky_Cyrl: 'Kyrgyz (Cyrillic)',
|
||||
ky_KG: 'Kyrgyz (Kyrgyzstan)',
|
||||
lo: 'Lao',
|
||||
lo_LA: 'Lao (Laos)',
|
||||
lv: 'Latvian',
|
||||
lv_LV: 'Latvian (Latvia)',
|
||||
ln: 'Lingala',
|
||||
ln_AO: 'Lingala (Angola)',
|
||||
ln_CF: 'Lingala (Central African Republic)',
|
||||
ln_CG: 'Lingala (Congo - Brazzaville)',
|
||||
ln_CD: 'Lingala (Congo - Kinshasa)',
|
||||
lt: 'Lithuanian',
|
||||
lt_LT: 'Lithuanian (Lithuania)',
|
||||
lu: 'Luba-Katanga',
|
||||
lu_CD: 'Luba-Katanga (Congo - Kinshasa)',
|
||||
lb: 'Luxembourgish',
|
||||
lb_LU: 'Luxembourgish (Luxembourg)',
|
||||
mk: 'Macedonian',
|
||||
mk_MK: 'Macedonian (Macedonia)',
|
||||
mg: 'Malagasy',
|
||||
mg_MG: 'Malagasy (Madagascar)',
|
||||
ms: 'Malay',
|
||||
ms_BN: 'Malay (Brunei)',
|
||||
ms_Latn_BN: 'Malay (Latin, Brunei)',
|
||||
ms_Latn_MY: 'Malay (Latin, Malaysia)',
|
||||
ms_Latn_SG: 'Malay (Latin, Singapore)',
|
||||
ms_Latn: 'Malay (Latin)',
|
||||
ms_MY: 'Malay (Malaysia)',
|
||||
ms_SG: 'Malay (Singapore)',
|
||||
ml: 'Malayalam',
|
||||
ml_IN: 'Malayalam (India)',
|
||||
mt: 'Maltese',
|
||||
mt_MT: 'Maltese (Malta)',
|
||||
gv: 'Manx',
|
||||
gv_IM: 'Manx (Isle of Man)',
|
||||
mr: 'Marathi',
|
||||
mr_IN: 'Marathi (India)',
|
||||
mn: 'Mongolian',
|
||||
mn_Cyrl_MN: 'Mongolian (Cyrillic, Mongolia)',
|
||||
mn_Cyrl: 'Mongolian (Cyrillic)',
|
||||
mn_MN: 'Mongolian (Mongolia)',
|
||||
ne: 'Nepali',
|
||||
ne_IN: 'Nepali (India)',
|
||||
ne_NP: 'Nepali (Nepal)',
|
||||
nd: 'North Ndebele',
|
||||
nd_ZW: 'North Ndebele (Zimbabwe)',
|
||||
se: 'Northern Sami',
|
||||
se_FI: 'Northern Sami (Finland)',
|
||||
se_NO: 'Northern Sami (Norway)',
|
||||
se_SE: 'Northern Sami (Sweden)',
|
||||
no: 'Norwegian',
|
||||
no_NO: 'Norwegian (Norway)',
|
||||
nb: 'Norwegian Bokmål',
|
||||
nb_NO: 'Norwegian Bokmål (Norway)',
|
||||
nb_SJ: 'Norwegian Bokmål (Svalbard & Jan Mayen)',
|
||||
nn: 'Norwegian Nynorsk',
|
||||
nn_NO: 'Norwegian Nynorsk (Norway)',
|
||||
or: 'Oriya',
|
||||
or_IN: 'Oriya (India)',
|
||||
om: 'Oromo',
|
||||
om_ET: 'Oromo (Ethiopia)',
|
||||
om_KE: 'Oromo (Kenya)',
|
||||
os: 'Ossetic',
|
||||
os_GE: 'Ossetic (Georgia)',
|
||||
os_RU: 'Ossetic (Russia)',
|
||||
ps: 'Pashto',
|
||||
ps_AF: 'Pashto (Afghanistan)',
|
||||
fa: 'Persian',
|
||||
fa_AF: 'Persian (Afghanistan)',
|
||||
fa_IR: 'Persian (Iran)',
|
||||
pl: 'Polish',
|
||||
pl_PL: 'Polish (Poland)',
|
||||
pt: 'Portuguese',
|
||||
pt_AO: 'Portuguese (Angola)',
|
||||
pt_BR: 'Portuguese (Brazil)',
|
||||
pt_CV: 'Portuguese (Cape Verde)',
|
||||
pt_GW: 'Portuguese (Guinea-Bissau)',
|
||||
pt_MO: 'Portuguese (Macau SAR China)',
|
||||
pt_MZ: 'Portuguese (Mozambique)',
|
||||
pt_PT: 'Portuguese (Portugal)',
|
||||
pt_ST: 'Portuguese (São Tomé & Príncipe)',
|
||||
pt_TL: 'Portuguese (Timor-Leste)',
|
||||
pa: 'Punjabi',
|
||||
pa_Arab_PK: 'Punjabi (Arabic, Pakistan)',
|
||||
pa_Arab: 'Punjabi (Arabic)',
|
||||
pa_Guru_IN: 'Punjabi (Gurmukhi, India)',
|
||||
pa_Guru: 'Punjabi (Gurmukhi)',
|
||||
pa_IN: 'Punjabi (India)',
|
||||
pa_PK: 'Punjabi (Pakistan)',
|
||||
qu: 'Quechua',
|
||||
qu_BO: 'Quechua (Bolivia)',
|
||||
qu_EC: 'Quechua (Ecuador)',
|
||||
qu_PE: 'Quechua (Peru)',
|
||||
ro: 'Romanian',
|
||||
ro_MD: 'Romanian (Moldova)',
|
||||
ro_RO: 'Romanian (Romania)',
|
||||
rm: 'Romansh',
|
||||
rm_CH: 'Romansh (Switzerland)',
|
||||
rn: 'Rundi',
|
||||
rn_BI: 'Rundi (Burundi)',
|
||||
ru: 'Russian',
|
||||
ru_BY: 'Russian (Belarus)',
|
||||
ru_KZ: 'Russian (Kazakhstan)',
|
||||
ru_KG: 'Russian (Kyrgyzstan)',
|
||||
ru_MD: 'Russian (Moldova)',
|
||||
ru_RU: 'Russian (Russia)',
|
||||
ru_UA: 'Russian (Ukraine)',
|
||||
sg: 'Sango',
|
||||
sg_CF: 'Sango (Central African Republic)',
|
||||
gd: 'Scottish Gaelic',
|
||||
gd_GB: 'Scottish Gaelic (United Kingdom)',
|
||||
sr: 'Serbian',
|
||||
sr_BA: 'Serbian (Bosnia & Herzegovina)',
|
||||
sr_Cyrl_BA: 'Serbian (Cyrillic, Bosnia & Herzegovina)',
|
||||
sr_Cyrl_XK: 'Serbian (Cyrillic, Kosovo)',
|
||||
sr_Cyrl_ME: 'Serbian (Cyrillic, Montenegro)',
|
||||
sr_Cyrl_RS: 'Serbian (Cyrillic, Serbia)',
|
||||
sr_Cyrl: 'Serbian (Cyrillic)',
|
||||
sr_XK: 'Serbian (Kosovo)',
|
||||
sr_Latn_BA: 'Serbian (Latin, Bosnia & Herzegovina)',
|
||||
sr_Latn_XK: 'Serbian (Latin, Kosovo)',
|
||||
sr_Latn_ME: 'Serbian (Latin, Montenegro)',
|
||||
sr_Latn_RS: 'Serbian (Latin, Serbia)',
|
||||
sr_Latn: 'Serbian (Latin)',
|
||||
sr_ME: 'Serbian (Montenegro)',
|
||||
sr_RS: 'Serbian (Serbia)',
|
||||
sh: 'Serbo-Croatian',
|
||||
sh_BA: 'Serbo-Croatian (Bosnia & Herzegovina)',
|
||||
sn: 'Shona',
|
||||
sn_ZW: 'Shona (Zimbabwe)',
|
||||
ii: 'Sichuan Yi',
|
||||
ii_CN: 'Sichuan Yi (China)',
|
||||
si: 'Sinhala',
|
||||
si_LK: 'Sinhala (Sri Lanka)',
|
||||
sk: 'Slovak',
|
||||
sk_SK: 'Slovak (Slovakia)',
|
||||
sl: 'Slovenian',
|
||||
sl_SI: 'Slovenian (Slovenia)',
|
||||
so: 'Somali',
|
||||
so_DJ: 'Somali (Djibouti)',
|
||||
so_ET: 'Somali (Ethiopia)',
|
||||
so_KE: 'Somali (Kenya)',
|
||||
so_SO: 'Somali (Somalia)',
|
||||
es: 'Spanish',
|
||||
es_AR: 'Spanish (Argentina)',
|
||||
es_BO: 'Spanish (Bolivia)',
|
||||
es_IC: 'Spanish (Canary Islands)',
|
||||
es_EA: 'Spanish (Ceuta & Melilla)',
|
||||
es_CL: 'Spanish (Chile)',
|
||||
es_CO: 'Spanish (Colombia)',
|
||||
es_CR: 'Spanish (Costa Rica)',
|
||||
es_CU: 'Spanish (Cuba)',
|
||||
es_DO: 'Spanish (Dominican Republic)',
|
||||
es_EC: 'Spanish (Ecuador)',
|
||||
es_SV: 'Spanish (El Salvador)',
|
||||
es_GQ: 'Spanish (Equatorial Guinea)',
|
||||
es_GT: 'Spanish (Guatemala)',
|
||||
es_HN: 'Spanish (Honduras)',
|
||||
es_MX: 'Spanish (Mexico)',
|
||||
es_NI: 'Spanish (Nicaragua)',
|
||||
es_PA: 'Spanish (Panama)',
|
||||
es_PY: 'Spanish (Paraguay)',
|
||||
es_PE: 'Spanish (Peru)',
|
||||
es_PH: 'Spanish (Philippines)',
|
||||
es_PR: 'Spanish (Puerto Rico)',
|
||||
es_ES: 'Spanish (Spain)',
|
||||
es_US: 'Spanish (United States)',
|
||||
es_UY: 'Spanish (Uruguay)',
|
||||
es_VE: 'Spanish (Venezuela)',
|
||||
sw: 'Swahili',
|
||||
sw_KE: 'Swahili (Kenya)',
|
||||
sw_TZ: 'Swahili (Tanzania)',
|
||||
sw_UG: 'Swahili (Uganda)',
|
||||
sv: 'Swedish',
|
||||
sv_AX: 'Swedish (Åland Islands)',
|
||||
sv_FI: 'Swedish (Finland)',
|
||||
sv_SE: 'Swedish (Sweden)',
|
||||
tl: 'Tagalog',
|
||||
tl_PH: 'Tagalog (Philippines)',
|
||||
ta: 'Tamil',
|
||||
ta_IN: 'Tamil (India)',
|
||||
ta_MY: 'Tamil (Malaysia)',
|
||||
ta_SG: 'Tamil (Singapore)',
|
||||
ta_LK: 'Tamil (Sri Lanka)',
|
||||
te: 'Telugu',
|
||||
te_IN: 'Telugu (India)',
|
||||
th: 'Thai',
|
||||
th_TH: 'Thai (Thailand)',
|
||||
bo: 'Tibetan',
|
||||
bo_CN: 'Tibetan (China)',
|
||||
bo_IN: 'Tibetan (India)',
|
||||
ti: 'Tigrinya',
|
||||
ti_ER: 'Tigrinya (Eritrea)',
|
||||
ti_ET: 'Tigrinya (Ethiopia)',
|
||||
to: 'Tongan',
|
||||
to_TO: 'Tongan (Tonga)',
|
||||
tr: 'Turkish',
|
||||
tr_CY: 'Turkish (Cyprus)',
|
||||
tr_TR: 'Turkish (Turkey)',
|
||||
uk: 'Ukrainian',
|
||||
uk_UA: 'Ukrainian (Ukraine)',
|
||||
ur: 'Urdu',
|
||||
ur_IN: 'Urdu (India)',
|
||||
ur_PK: 'Urdu (Pakistan)',
|
||||
ug: 'Uyghur',
|
||||
ug_Arab_CN: 'Uyghur (Arabic, China)',
|
||||
ug_Arab: 'Uyghur (Arabic)',
|
||||
ug_CN: 'Uyghur (China)',
|
||||
uz: 'Uzbek',
|
||||
uz_AF: 'Uzbek (Afghanistan)',
|
||||
uz_Arab_AF: 'Uzbek (Arabic, Afghanistan)',
|
||||
uz_Arab: 'Uzbek (Arabic)',
|
||||
uz_Cyrl_UZ: 'Uzbek (Cyrillic, Uzbekistan)',
|
||||
uz_Cyrl: 'Uzbek (Cyrillic)',
|
||||
uz_Latn_UZ: 'Uzbek (Latin, Uzbekistan)',
|
||||
uz_Latn: 'Uzbek (Latin)',
|
||||
uz_UZ: 'Uzbek (Uzbekistan)',
|
||||
vi: 'Vietnamese',
|
||||
vi_VN: 'Vietnamese (Vietnam)',
|
||||
cy: 'Welsh',
|
||||
cy_GB: 'Welsh (United Kingdom)',
|
||||
fy: 'Western Frisian',
|
||||
fy_NL: 'Western Frisian (Netherlands)',
|
||||
yi: 'Yiddish',
|
||||
yo: 'Yoruba',
|
||||
yo_BJ: 'Yoruba (Benin)',
|
||||
yo_NG: 'Yoruba (Nigeria)',
|
||||
zu: 'Zulu',
|
||||
zu_ZA: 'Zulu (South Africa)',
|
||||
};
|
||||
export default locales;
|
|
@ -1,5 +1,4 @@
|
|||
json.id article.id
|
||||
json.category_id article.category_id
|
||||
json.title article.title
|
||||
json.content article.content
|
||||
json.description article.description
|
||||
|
@ -7,6 +6,11 @@ json.status article.status
|
|||
json.account_id article.account_id
|
||||
json.updated_at article.updated_at.to_i
|
||||
|
||||
json.category do
|
||||
json.id article.category_id
|
||||
json.name article.category.name
|
||||
end
|
||||
|
||||
if article.portal.present?
|
||||
json.portal do
|
||||
json.partial! 'api/v1/accounts/portals/portal.json.jbuilder', portal: article.portal
|
||||
|
|
Loading…
Reference in a new issue