diff --git a/app/controllers/api/v1/accounts/articles_controller.rb b/app/controllers/api/v1/accounts/articles_controller.rb
index 8576ec294..ccaa33a42 100644
--- a/app/controllers/api/v1/accounts/articles_controller.rb
+++ b/app/controllers/api/v1/accounts/articles_controller.rb
@@ -5,6 +5,7 @@ class Api::V1::Accounts::ArticlesController < Api::V1::Accounts::BaseController
before_action :set_current_page, only: [:index]
def index
+ @articles_count = @portal.articles.count
@articles = @portal.articles
@articles = @articles.search(list_params) if list_params.present?
end
diff --git a/app/javascript/dashboard/api/helpCenter/portals.js b/app/javascript/dashboard/api/helpCenter/portals.js
index 8b8e8f797..2a15fa7bd 100644
--- a/app/javascript/dashboard/api/helpCenter/portals.js
+++ b/app/javascript/dashboard/api/helpCenter/portals.js
@@ -1,9 +1,16 @@
+/* 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 new PortalsAPI();
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue
index 252215c8c..e88c1eafc 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleItem.vue
@@ -4,7 +4,7 @@
-
+
{{ title }}
@@ -24,16 +24,20 @@
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue
index 6d397c92e..282e292b3 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/ArticleTable.vue
@@ -16,20 +16,22 @@
@@ -47,7 +49,7 @@ export default {
type: Array,
default: () => {},
},
- articleCount: {
+ totalCount: {
type: Number,
default: 0,
},
@@ -55,10 +57,14 @@ export default {
type: Number,
default: 1,
},
+ pageSize: {
+ type: Number,
+ default: 15,
+ },
},
methods: {
- onPageChange() {
- this.$emit('onPageChange');
+ onPageChange(page) {
+ this.$emit('on-page-change', page);
},
},
};
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/HelpCenterLayout.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/HelpCenterLayout.vue
index 3bc51afbe..1ba016edd 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/HelpCenterLayout.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/HelpCenterLayout.vue
@@ -66,6 +66,12 @@ export default {
...mapGetters({
accountId: 'getCurrentAccountId',
}),
+ portalSlug() {
+ return this.$route.params.portalSlug;
+ },
+ locale() {
+ return this.$route.params.locale;
+ },
accessibleMenuItems() {
return [
{
@@ -74,7 +80,7 @@ export default {
key: 'list_all_locale_articles',
count: 199,
toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/articles`
+ `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles`
),
toolTip: 'All Articles',
toStateName: 'list_all_locale_articles',
@@ -85,7 +91,7 @@ export default {
key: 'mine_articles',
count: 112,
toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/articles/mine`
+ `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/mine`
),
toolTip: 'My articles',
toStateName: 'mine_articles',
@@ -96,7 +102,7 @@ export default {
key: 'list_draft_articles',
count: 32,
toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/articles/draft`
+ `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/draft`
),
toolTip: 'Draft',
toStateName: 'list_draft_articles',
@@ -107,7 +113,7 @@ export default {
key: 'list_archived_articles',
count: 10,
toState: frontendURL(
- `accounts/${this.accountId}/portals/:portalSlug/:locale/articles/archived`
+ `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/archived`
),
toolTip: 'Archived',
toStateName: 'list_archived_articles',
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/mixins/portalMixin.js b/app/javascript/dashboard/routes/dashboard/helpcenter/mixins/portalMixin.js
new file mode 100644
index 000000000..9586b8bcd
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/mixins/portalMixin.js
@@ -0,0 +1,20 @@
+import { mapGetters } from 'vuex';
+import { frontendURL } from 'dashboard/helper/URLHelper';
+export default {
+ computed: {
+ ...mapGetters({ accountId: 'getCurrentAccountId' }),
+ portalSlug() {
+ return this.$route.params.portalSlug;
+ },
+ locale() {
+ return this.$route.params.locale;
+ },
+ },
+ methods: {
+ articleUrl(id) {
+ return frontendURL(
+ `accounts/${this.accountId}/portals/${this.portalSlug}/${this.locale}/articles/${id}`
+ );
+ },
+ },
+};
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/mixins/specs/portalMixin.spec.js b/app/javascript/dashboard/routes/dashboard/helpcenter/mixins/specs/portalMixin.spec.js
new file mode 100644
index 000000000..44c1e5b2a
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/mixins/specs/portalMixin.spec.js
@@ -0,0 +1,68 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import portalMixin from '../portalMixin';
+import Vuex from 'vuex';
+import VueRouter from 'vue-router';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+localVue.use(VueRouter);
+import ListAllArticles from '../../pages/portals/ListAllPortals.vue';
+
+const router = new VueRouter({
+ routes: [
+ {
+ path: ':portalSlug/:locale/articles',
+ name: 'list_all_locale_articles',
+ component: ListAllArticles,
+ },
+ ],
+});
+
+describe('portalMixin', () => {
+ let getters;
+ let store;
+ let wrapper;
+
+ beforeEach(() => {
+ getters = {
+ getCurrentAccountId: () => 1,
+ };
+ const Component = {
+ render() {},
+ title: 'TestComponent',
+ mixins: [portalMixin],
+ router,
+ };
+ store = new Vuex.Store({ getters });
+ wrapper = shallowMount(Component, { store, localVue });
+ });
+
+ it('return account id', () => {
+ expect(wrapper.vm.accountId).toBe(1);
+ });
+
+ it('returns portal url', () => {
+ router.push({
+ name: 'list_all_locale_articles',
+ params: { portalSlug: 'fur-rent', locale: 'en' },
+ });
+ expect(wrapper.vm.articleUrl(1)).toBe(
+ '/app/accounts/1/portals/fur-rent/en/articles/1'
+ );
+ });
+
+ it('returns portal locale', () => {
+ router.push({
+ name: 'list_all_locale_articles',
+ params: { portalSlug: 'fur-rent', locale: 'es' },
+ });
+ expect(wrapper.vm.portalSlug).toBe('fur-rent');
+ });
+
+ it('returns portal slug', () => {
+ router.push({
+ name: 'list_all_locale_articles',
+ params: { portalSlug: 'campaign', locale: 'es' },
+ });
+ expect(wrapper.vm.portalSlug).toBe('campaign');
+ });
+});
diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue
index cb3bb02c1..5b87e4d8f 100644
--- a/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue
+++ b/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue
@@ -2,26 +2,30 @@
-
-
-
-
+
{{ $t('HELP_CENTER.TABLE.LOADING_MESSAGE') }}
+
diff --git a/app/javascript/dashboard/store/actions.js b/app/javascript/dashboard/store/actions.js
deleted file mode 100755
index e69de29bb..000000000
diff --git a/app/javascript/dashboard/store/index.js b/app/javascript/dashboard/store/index.js
index 4957a27cc..c4823ec2b 100755
--- a/app/javascript/dashboard/store/index.js
+++ b/app/javascript/dashboard/store/index.js
@@ -35,6 +35,7 @@ import teamMembers from './modules/teamMembers';
import teams from './modules/teams';
import userNotificationSettings from './modules/userNotificationSettings';
import webhooks from './modules/webhooks';
+import articles from './modules/helpCenterArticles';
Vue.use(Vuex);
export default new Vuex.Store({
@@ -73,5 +74,6 @@ export default new Vuex.Store({
teams,
userNotificationSettings,
webhooks,
+ articles,
},
});
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js b/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js
index d484dd40c..87d4a886d 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js
@@ -1,13 +1,22 @@
-import articlesAPI from 'dashboard/api/helpCenter/articles.js';
+import portalAPI from 'dashboard/api/helpCenter/portals';
+import articlesAPI from 'dashboard/api/helpCenter/articles';
import { throwErrorMessage } from 'dashboard/store/utils/api';
import types from '../../mutation-types';
export const actions = {
- index: async ({ commit }) => {
+ index: async ({ commit }, { pageNumber, portalSlug, locale }) => {
try {
commit(types.SET_UI_FLAG, { isFetching: true });
- const { data } = await articlesAPI.get();
- const articleIds = data.map(article => article.id);
- commit(types.ADD_MANY_ARTICLES, data);
+ const {
+ data: { payload, meta },
+ } = await portalAPI.getArticles({
+ pageNumber,
+ portalSlug,
+ locale,
+ });
+ const articleIds = payload.map(article => article.id);
+ commit(types.CLEAR_ARTICLES);
+ commit(types.ADD_MANY_ARTICLES, payload);
+ commit(types.SET_ARTICLES_META, meta);
commit(types.ADD_MANY_ARTICLES_ID, articleIds);
return articleIds;
} catch (error) {
@@ -31,6 +40,22 @@ export const actions = {
commit(types.SET_UI_FLAG, { isCreating: false });
}
},
+
+ show: async ({ commit }, { id, portalSlug }) => {
+ commit(types.SET_UI_FLAG, { isFetching: true });
+ try {
+ const response = await portalAPI.getArticle({ id, portalSlug });
+ const {
+ data: { payload },
+ } = response;
+ const { id: articleId } = payload;
+ commit(types.ADD_ARTICLE, payload);
+ commit(types.ADD_ARTICLE_ID, articleId);
+ commit(types.SET_UI_FLAG, { isFetching: false });
+ } catch (error) {
+ commit(types.SET_UI_FLAG, { isFetching: false });
+ }
+ },
update: async ({ commit }, params) => {
const articleId = params.id;
commit(types.ADD_ARTICLE_FLAG, {
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/getters.js b/app/javascript/dashboard/store/modules/helpCenterArticles/getters.js
index 1cd5d94b0..35e32ee5e 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/getters.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/getters.js
@@ -1,16 +1,14 @@
export const getters = {
- uiFlagsIn: state => helpCenterId => {
+ uiFlags: state => helpCenterId => {
const uiFlags = state.articles.uiFlags.byId[helpCenterId];
if (uiFlags) return uiFlags;
return { isFetching: false, isUpdating: false, isDeleting: false };
},
- isFetchingHelpCenterArticles: state => state.uiFlags.isFetching,
+ isFetching: state => state.uiFlags.isFetching,
articleById: (...getterArguments) => articleId => {
const [state] = getterArguments;
const article = state.articles.byId[articleId];
-
if (!article) return undefined;
-
return article;
},
allArticles: (...getterArguments) => {
@@ -20,4 +18,7 @@ export const getters = {
});
return articles;
},
+ getMeta: state => {
+ return state.meta;
+ },
};
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/index.js b/app/javascript/dashboard/store/modules/helpCenterArticles/index.js
index bbb10f8a2..7648b1ef6 100755
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/index.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/index.js
@@ -8,6 +8,10 @@ export const defaultHelpCenterFlags = {
isDeleting: false,
};
const state = {
+ meta: {
+ count: 0,
+ currentPage: 1,
+ },
articles: {
byId: {},
allIds: [],
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/mutations.js b/app/javascript/dashboard/store/modules/helpCenterArticles/mutations.js
index 3657a1e71..9dd0ac28b 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/mutations.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/mutations.js
@@ -16,19 +16,28 @@ export const mutations = {
...article,
});
},
+ [types.CLEAR_ARTICLES]: $state => {
+ Vue.set($state.articles, 'byId', {});
+ Vue.set($state.articles, 'allIds', []);
+ Vue.set($state.articles, 'uiFlags', {});
+ },
[types.ADD_MANY_ARTICLES]($state, articles) {
const allArticles = { ...$state.articles.byId };
articles.forEach(article => {
allArticles[article.id] = article;
});
- Vue.set($state.articles, 'byId', {
- allArticles,
- });
+ Vue.set($state.articles, 'byId', allArticles);
},
[types.ADD_MANY_ARTICLES_ID]($state, articleIds) {
$state.articles.allIds.push(...articleIds);
},
+ [types.SET_ARTICLES_META]: ($state, data) => {
+ const { articles_count: count, current_page: currentPage } = data;
+ Vue.set($state.meta, 'count', count);
+ Vue.set($state.meta, 'currentPage', currentPage);
+ },
+
[types.ADD_ARTICLE_ID]: ($state, articleId) => {
$state.articles.allIds.push(articleId);
},
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/action.spec.js b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/action.spec.js
index c2ff2c74b..0250031b1 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/action.spec.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/action.spec.js
@@ -15,10 +15,22 @@ jest.mock('axios');
describe('#actions', () => {
describe('#index', () => {
it('sends correct actions if API is success', async () => {
- axios.get.mockResolvedValue({ data: articleList });
- await actions.index({ commit });
+ axios.get.mockResolvedValue({
+ data: {
+ payload: articleList,
+ meta: {
+ current_page: '1',
+ articles_count: 5,
+ },
+ },
+ });
+ await actions.index(
+ { commit },
+ { pageNumber: 1, portalSlug: 'test', locale: 'en' }
+ );
expect(commit.mock.calls).toEqual([
[types.default.SET_UI_FLAG, { isFetching: true }],
+ [types.default.CLEAR_ARTICLES],
[
types.default.ADD_MANY_ARTICLES,
[
@@ -29,13 +41,22 @@ describe('#actions', () => {
},
],
],
+ [
+ types.default.SET_ARTICLES_META,
+ { current_page: '1', articles_count: 5 },
+ ],
[types.default.ADD_MANY_ARTICLES_ID, [1]],
[types.default.SET_UI_FLAG, { isFetching: false }],
]);
});
it('sends correct actions if API is error', async () => {
axios.get.mockRejectedValue({ message: 'Incorrect header' });
- await expect(actions.index({ commit })).rejects.toThrow(Error);
+ await expect(
+ actions.index(
+ { commit },
+ { pageNumber: 1, portalSlug: 'test', locale: 'en' }
+ )
+ ).rejects.toThrow(Error);
expect(commit.mock.calls).toEqual([
[types.default.SET_UI_FLAG, { isFetching: true }],
[types.default.SET_UI_FLAG, { isFetching: false }],
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/fixtures.js b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/fixtures.js
index 326f3c2fb..37de5df56 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/fixtures.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/fixtures.js
@@ -1,4 +1,8 @@
export default {
+ meta: {
+ count: 123,
+ currentPage: 2,
+ },
articles: {
byId: {
1: {
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/getters.spec.js b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/getters.spec.js
index ab271d3a0..73d703641 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/getters.spec.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/getters.spec.js
@@ -5,8 +5,8 @@ describe('#getters', () => {
beforeEach(() => {
state = articles;
});
- it('uiFlagsIn', () => {
- expect(getters.uiFlagsIn(state)(1)).toEqual({
+ it('uiFlags', () => {
+ expect(getters.uiFlags(state)(1)).toEqual({
isFetching: false,
isUpdating: true,
isDeleting: false,
@@ -34,7 +34,7 @@ describe('#getters', () => {
});
});
- it('isFetchingHelpCenters', () => {
- expect(getters.isFetchingHelpCenterArticles(state)).toEqual(true);
+ it('isFetchingArticles', () => {
+ expect(getters.isFetching(state)).toEqual(true);
});
});
diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/mutation.spec.js b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/mutation.spec.js
index ce3b6b33a..077b35aad 100644
--- a/app/javascript/dashboard/store/modules/helpCenterArticles/specs/mutation.spec.js
+++ b/app/javascript/dashboard/store/modules/helpCenterArticles/specs/mutation.spec.js
@@ -46,6 +46,19 @@ describe('#mutations', () => {
});
});
+ describe('#ARTICLES_META', () => {
+ it('add meta to state', () => {
+ mutations[types.SET_ARTICLES_META](state, {
+ articles_count: 3,
+ current_page: 1,
+ });
+ expect(state.meta).toEqual({
+ count: 3,
+ currentPage: 1,
+ });
+ });
+ });
+
describe('#ADD_ARTICLE_ID', () => {
it('add valid article id to state', () => {
mutations[types.ADD_ARTICLE_ID](state, 3);
@@ -87,4 +100,13 @@ describe('#mutations', () => {
expect(state.articles.byId[2]).toEqual(undefined);
});
});
+
+ describe('#CLEAR_ARTICLES', () => {
+ it('clears articles', () => {
+ mutations[types.CLEAR_ARTICLES](state);
+ expect(state.articles.allIds).toEqual([]);
+ expect(state.articles.byId).toEqual({});
+ expect(state.articles.uiFlags).toEqual({});
+ });
+ });
});
diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js
index 034190507..c9073d58a 100755
--- a/app/javascript/dashboard/store/mutation-types.js
+++ b/app/javascript/dashboard/store/mutation-types.js
@@ -226,8 +226,10 @@ export default {
ADD_ARTICLE_ID: 'ADD_ARTICLE_ID',
ADD_MANY_ARTICLES: 'ADD_MANY_ARTICLES',
ADD_MANY_ARTICLES_ID: 'ADD_MANY_ARTICLES_ID',
+ SET_ARTICLES_META: 'SET_ARTICLES_META',
ADD_ARTICLE_FLAG: 'ADD_ARTICLE_FLAG',
UPDATE_ARTICLE: 'UPDATE_ARTICLE',
+ CLEAR_ARTICLES: 'CLEAR_ARTICLES',
REMOVE_ARTICLE: 'REMOVE_ARTICLE',
REMOVE_ARTICLE_ID: 'REMOVE_ARTICLE_ID',
SET_UI_FLAG: 'SET_UI_FLAG',
diff --git a/app/views/api/v1/accounts/articles/_article.json.jbuilder b/app/views/api/v1/accounts/articles/_article.json.jbuilder
index e3b1af52b..93a7bbf84 100644
--- a/app/views/api/v1/accounts/articles/_article.json.jbuilder
+++ b/app/views/api/v1/accounts/articles/_article.json.jbuilder
@@ -5,6 +5,7 @@ json.content article.content
json.description article.description
json.status article.status
json.account_id article.account_id
+json.updated_at article.updated_at.to_i
if article.portal.present?
json.portal do
diff --git a/app/views/api/v1/accounts/articles/index.json.jbuilder b/app/views/api/v1/accounts/articles/index.json.jbuilder
index 89634e32a..fef8dc521 100644
--- a/app/views/api/v1/accounts/articles/index.json.jbuilder
+++ b/app/views/api/v1/accounts/articles/index.json.jbuilder
@@ -4,5 +4,5 @@ end
json.meta do
json.current_page @current_page
- json.articles_count @articles.size
+ json.articles_count @articles_count
end
diff --git a/spec/controllers/api/v1/accounts/articles_controller_spec.rb b/spec/controllers/api/v1/accounts/articles_controller_spec.rb
index 57d4f8feb..1e98af260 100644
--- a/spec/controllers/api/v1/accounts/articles_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/articles_controller_spec.rb
@@ -190,7 +190,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do
expect(response).to have_http_status(:success)
json_response = JSON.parse(response.body)
expect(json_response['payload'].count).to be 1
- expect(json_response['meta']['articles_count']).to be json_response['payload'].size
+ expect(json_response['meta']['articles_count']).to be 2
end
end