From 2184c982fb95b66750ec774bd0183347ac1e0303 Mon Sep 17 00:00:00 2001 From: Pierre Gonzalez Date: Thu, 9 Apr 2020 17:32:15 +0200 Subject: [PATCH] add isUniqueValuesLoading to dataset header column --- src/lib/dataset/index.ts | 1 + src/store/backend-plugin.ts | 44 ++++++++++++++++++------- src/store/getters.ts | 6 ++++ src/store/mutations.ts | 12 +++++++ tests/unit/plugins.spec.ts | 64 +++++++++++++++++++++++++++++++++++-- 5 files changed, 113 insertions(+), 14 deletions(-) diff --git a/src/lib/dataset/index.ts b/src/lib/dataset/index.ts index 93cb39d589..f50aa53eb2 100644 --- a/src/lib/dataset/index.ts +++ b/src/lib/dataset/index.ts @@ -12,6 +12,7 @@ export type ColumnTypeMapping = { export type DataSetColumn = { name: string; type?: DataSetColumnType; + isUniqueValueLoading?: boolean; //It will be updated by backendify function }; /** diff --git a/src/store/backend-plugin.ts b/src/store/backend-plugin.ts index 78c4de0773..d122a1ffb0 100644 --- a/src/store/backend-plugin.ts +++ b/src/store/backend-plugin.ts @@ -9,7 +9,7 @@ */ import { Store } from 'vuex'; -import { BackendResponse } from '@/lib/backend-response'; +import { BackendError, BackendResponse } from '@/lib/backend-response'; import { DataSet } from '@/lib/dataset'; import { pageOffset } from '@/lib/dataset/pagination'; import { Pipeline } from '@/lib/steps'; @@ -114,32 +114,54 @@ function _preparePipeline(pipeline: Pipeline, store: Store) { * - logs the error in the store if any, * - sets the `loading: false` property on the store at the end. */ -export function backendify(target: Function) { +export function backendify( + target: Function, + callFront?: Function, + callBack?: Function, + reject?: Function, +) { return async function(this: BackendService | void, store: Store, ...args: any[]) { try { - store.commit(VQBnamespace('setLoading'), { isLoading: true }); + if (callFront) { + callFront(); + } const response = await target.bind(this)(store, ...args); if (response.error) { - store.commit(VQBnamespace('logBackendError'), { - backendError: response.error, - }); + if (reject) { + reject(response.error); + } } return response; } catch (error) { const response = { error: { type: 'error', message: error.toString() } }; - store.commit(VQBnamespace('logBackendError'), { - backendError: response.error, - }); + if (reject) { + reject(response.error); + } return response; } finally { - store.commit(VQBnamespace('setLoading'), { isLoading: false }); + if (callBack) { + callBack(); + } } }; } async function _updateDataset(store: Store, service: BackendService, pipeline: Pipeline) { pipeline = _preparePipeline(pipeline, store); - const response = await backendify(service.executePipeline).bind(service)( + const response = await backendify( + service.executePipeline, + () => { + store.commit(VQBnamespace('setLoading'), { isLoading: true }); + }, + () => { + store.commit(VQBnamespace('setLoading'), { isLoading: false }); + }, + (error: BackendError) => { + store.commit(VQBnamespace('logBackendError'), { + backendError: error, + }); + }, + ).bind(service)( store, pipeline, store.state[VQB_MODULE_NAME].pagesize, diff --git a/src/store/getters.ts b/src/store/getters.ts index 9c4fc2b5bc..3085a496ba 100644 --- a/src/store/getters.ts +++ b/src/store/getters.ts @@ -82,6 +82,12 @@ const getters: GetterTree = { */ pageno: (state: VQBState) => state.dataset.paginationContext ? state.dataset.paginationContext.pageno : 1, + /** + * helper that is True if unique values are loading + */ + isUniqueValuesLoading: (state: VQBState) => (column: string) => + state.dataset.headers[state.dataset.headers.map(col => col.name).indexOf(column)] + .isUniqueValueLoading, /** * Return current edited pipeline */ diff --git a/src/store/mutations.ts b/src/store/mutations.ts index f1b320cbc2..a64e2d1bde 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -284,6 +284,18 @@ class Mutations { state.isLoading = isLoading; } + /** + * Set unique values loading + */ + setUniqueValuesLoading( + state: VQBState, + { isLoading, column }: { isLoading: boolean; column: string }, + ) { + state.dataset.headers[ + state.dataset.headers.map(col => col.name).indexOf(column) + ].isUniqueValueLoading = isLoading; + } + /** * Update translator. */ diff --git a/tests/unit/plugins.spec.ts b/tests/unit/plugins.spec.ts index af1daa99f1..08966ee63b 100644 --- a/tests/unit/plugins.spec.ts +++ b/tests/unit/plugins.spec.ts @@ -4,6 +4,7 @@ import _ from 'lodash'; import Vuex, { Store } from 'vuex'; import PipelineComponent from '@/components/Pipeline.vue'; +import { BackendError } from '@/lib/backend-response'; import { Pipeline } from '@/lib/steps'; import { ScopeContext } from '@/lib/templating'; import { VQB_MODULE_NAME, VQBnamespace } from '@/store'; @@ -57,10 +58,29 @@ describe('backendify tests', () => { it('should return the expected valid response', async () => { const backendResponse = { data: 'foo' }; // no-error backend response const mockOperation = jest.fn((_store, ..._args) => Promise.resolve(backendResponse)); - const result = await backendify(mockOperation)(store, 'foo', 'bar', 'baz'); + const callFront = jest.fn(() => { + store.commit(VQBnamespace('setLoading'), { isLoading: true }); + }); + const callBack = jest.fn(() => { + store.commit(VQBnamespace('setLoading'), { isLoading: false }); + }); + const callReject = jest.fn((error: BackendError) => { + store.commit(VQBnamespace('logBackendError'), { + backendError: error, + }); + }); + const result = await backendify(mockOperation, callFront, callBack, callReject)( + store, + 'foo', + 'bar', + 'baz', + ); expect(result).toEqual(backendResponse); expect(mockOperation).toHaveBeenCalledTimes(1); expect(mockOperation).toHaveBeenCalledWith(store, 'foo', 'bar', 'baz'); + expect(callFront).toHaveBeenCalledTimes(1); + expect(callBack).toHaveBeenCalledTimes(1); + expect(callReject).toHaveBeenCalledTimes(0); expect(commitSpy).toHaveBeenCalledTimes(2); expect(commitSpy).toHaveBeenNthCalledWith(1, VQBnamespace('setLoading'), { isLoading: true }); expect(commitSpy).toHaveBeenNthCalledWith(2, VQBnamespace('setLoading'), { isLoading: false }); @@ -69,10 +89,29 @@ describe('backendify tests', () => { it('should return the expected no-response', async () => { const backendResponse = { error: { message: 'foo', type: 'error' as 'error' } }; // error backend response const mockOperation = jest.fn((_store, ..._args) => Promise.resolve(backendResponse)); - const result = await backendify(mockOperation)(store, 'foo', 'bar', 'baz'); + const callFront = jest.fn(() => { + store.commit(VQBnamespace('setLoading'), { isLoading: true }); + }); + const callBack = jest.fn(() => { + store.commit(VQBnamespace('setLoading'), { isLoading: false }); + }); + const callReject = jest.fn((error: BackendError) => { + store.commit(VQBnamespace('logBackendError'), { + backendError: error, + }); + }); + const result = await backendify(mockOperation, callFront, callBack, callReject)( + store, + 'foo', + 'bar', + 'baz', + ); expect(result).toEqual(backendResponse); expect(mockOperation).toHaveBeenCalledTimes(1); expect(mockOperation).toHaveBeenCalledWith(store, 'foo', 'bar', 'baz'); + expect(callFront).toHaveBeenCalledTimes(1); + expect(callBack).toHaveBeenCalledTimes(1); + expect(callReject).toHaveBeenCalledTimes(1); expect(store.state[VQB_MODULE_NAME].backendErrors).toEqual([{ message: 'foo', type: 'error' }]); expect(commitSpy).toHaveBeenCalledTimes(3); expect(commitSpy).toHaveBeenNthCalledWith(1, VQBnamespace('setLoading'), { isLoading: true }); @@ -86,13 +125,32 @@ describe('backendify tests', () => { const mockOperation = jest.fn(function(_store, ..._args) { throw new Error('oopsie'); }); - const result = await backendify(mockOperation)(store, 'foo', 'bar', 'baz'); + const callFront = jest.fn(() => { + store.commit(VQBnamespace('setLoading'), { isLoading: true }); + }); + const callBack = jest.fn(() => { + store.commit(VQBnamespace('setLoading'), { isLoading: false }); + }); + const callReject = jest.fn((error: BackendError) => { + store.commit(VQBnamespace('logBackendError'), { + backendError: error, + }); + }); + const result = await backendify(mockOperation, callFront, callBack, callReject)( + store, + 'foo', + 'bar', + 'baz', + ); expect(result).toEqual({ error: { message: 'Error: oopsie', type: 'error' } }); expect(mockOperation).toHaveBeenCalledTimes(1); expect(mockOperation).toHaveBeenCalledWith(store, 'foo', 'bar', 'baz'); expect(store.state[VQB_MODULE_NAME].backendErrors).toEqual([ { message: 'Error: oopsie', type: 'error' }, ]); + expect(callFront).toHaveBeenCalledTimes(1); + expect(callBack).toHaveBeenCalledTimes(1); + expect(callReject).toHaveBeenCalledTimes(1); expect(commitSpy).toHaveBeenCalledTimes(3); expect(commitSpy).toHaveBeenNthCalledWith(1, VQBnamespace('setLoading'), { isLoading: true }); expect(commitSpy).toHaveBeenNthCalledWith(2, 'vqb/logBackendError', {