diff --git a/src/state/sagas/scenario/FindAllScenarios/FindAllScenariosData.js b/src/state/sagas/scenario/FindAllScenarios/FindAllScenariosData.js index 8082b8dd5..9a72edb3f 100644 --- a/src/state/sagas/scenario/FindAllScenarios/FindAllScenariosData.js +++ b/src/state/sagas/scenario/FindAllScenarios/FindAllScenariosData.js @@ -10,18 +10,21 @@ import { SCENARIO_ACTIONS_KEY } from '../../../commons/ScenarioConstants'; const getUserEmail = (state) => state.auth.userEmail; const getUserId = (state) => state.auth.userId; const getScenariosPermissionsMapping = (state) => state.application.permissionsMapping.scenario; +const getSolutionParameters = (state) => state.solution?.current?.data?.parameters; const keepOnlyReadableScenarios = (scenarios) => scenarios.filter((scenario) => scenario.security.currentUserPermissions.includes(ACL_PERMISSIONS.SCENARIO.READ)); -// generators function export function* getAllScenariosData(organizationId, workspaceId) { - // yield keyword is here to milestone and save the action const userEmail = yield select(getUserEmail); const userId = yield select(getUserId); const scenariosPermissionsMapping = yield select(getScenariosPermissionsMapping); + const solutionParameters = yield select(getSolutionParameters); const { data } = yield call(Api.Scenarios.findAllScenarios, organizationId, workspaceId); + data.forEach((scenario) => + ScenariosUtils.patchScenarioParameterValues(solutionParameters, scenario.parametersValues) + ); data.forEach((scenario) => (scenario.parametersValues = ApiUtils.formatParametersFromApi(scenario.parametersValues))); data.forEach((scenario) => ScenariosUtils.patchScenarioWithCurrentUserPermissions(scenario, userEmail, userId, scenariosPermissionsMapping) @@ -34,8 +37,6 @@ export function* getAllScenariosData(organizationId, workspaceId) { }); } -// generators function -// Here is a watcher that takes EVERY action dispatched named GET_ALL_SCENARIOS and binds getAllScenariosData saga to it function* findAllScenariosData() { yield takeEvery(SCENARIO_ACTIONS_KEY.GET_ALL_SCENARIOS, getAllScenariosData); } diff --git a/src/state/sagas/scenario/FindScenarioById/FindScenarioByIdData.js b/src/state/sagas/scenario/FindScenarioById/FindScenarioByIdData.js index cd1321daa..af9e29f10 100644 --- a/src/state/sagas/scenario/FindScenarioById/FindScenarioByIdData.js +++ b/src/state/sagas/scenario/FindScenarioById/FindScenarioByIdData.js @@ -13,12 +13,15 @@ import { dispatchSetApplicationErrorMessage } from '../../../dispatchers/app/App const getUserEmail = (state) => state.auth.userEmail; const getUserId = (state) => state.auth.userId; const getScenariosPermissionsMapping = (state) => state.application.permissionsMapping.scenario; +const getSolutionParameters = (state) => state.solution?.current?.data?.parameters; export function* fetchScenarioByIdData(action) { try { const userEmail = yield select(getUserEmail); const userId = yield select(getUserId); const scenariosPermissionsMapping = yield select(getScenariosPermissionsMapping); + const solutionParameters = yield select(getSolutionParameters); + yield put({ type: SCENARIO_ACTIONS_KEY.SET_CURRENT_SCENARIO, status: STATUSES.LOADING, @@ -30,6 +33,7 @@ export function* fetchScenarioByIdData(action) { action.workspaceId, action.scenarioId ); + ScenariosUtils.patchScenarioParameterValues(solutionParameters, data.parametersValues); data.parametersValues = ApiUtils.formatParametersFromApi(data.parametersValues); ScenariosUtils.patchScenarioWithCurrentUserPermissions(data, userEmail, userId, scenariosPermissionsMapping); diff --git a/src/state/sagas/workspace/SelectWorkspace/SelectWorkspace.js b/src/state/sagas/workspace/SelectWorkspace/SelectWorkspace.js index fc072966b..a04662ea5 100644 --- a/src/state/sagas/workspace/SelectWorkspace/SelectWorkspace.js +++ b/src/state/sagas/workspace/SelectWorkspace/SelectWorkspace.js @@ -77,9 +77,10 @@ export function* selectWorkspace(action) { yield put({ type: POWER_BI_ACTIONS_KEY.CLEAR_EMBED_INFO }); - yield call(getAllScenariosData, organizationId, selectedWorkspaceId); const solutionId = yield select(selectSolutionIdFromCurrentWorkspace); yield call(fetchSolutionByIdData, organizationId, solutionId); + + yield call(getAllScenariosData, organizationId, selectedWorkspaceId); const scenarioList = yield select(selectScenarioList); yield put({ diff --git a/src/utils/ScenariosUtils.js b/src/utils/ScenariosUtils.js index 9605c7033..41c897adf 100644 --- a/src/utils/ScenariosUtils.js +++ b/src/utils/ScenariosUtils.js @@ -10,6 +10,20 @@ const _getUserPermissionsForScenario = (scenario, userEmail, userId, permissions return SecurityUtils.getUserPermissionsForResource(scenario.security, userEmail, permissionsMapping); }; +const patchScenarioParameterValues = (solutionParameters, parameterValues) => { + if (!Array.isArray(parameterValues) || !Array.isArray(solutionParameters)) return; + + parameterValues.forEach((value) => { + if (value.varType != null || value.parameterId == null) return; + + const parameterDefinition = solutionParameters.find( + (solutionParameter) => solutionParameter.id === value.parameterId + ); + if (parameterDefinition) value.varType = parameterDefinition.varType; + else console.warn(`Unknown parameter value ${value.parameterId} without any varType found in scenario data`); + }); +}; + const patchScenarioWithCurrentUserPermissions = (scenario, userEmail, userId, permissionsMapping) => { // scenario.security seems to be read-only, we have to create a new object to add a "currentUserPermissions" key scenario.security = { @@ -19,5 +33,6 @@ const patchScenarioWithCurrentUserPermissions = (scenario, userEmail, userId, pe }; export const ScenariosUtils = { + patchScenarioParameterValues, patchScenarioWithCurrentUserPermissions, }; diff --git a/src/utils/__test__/ScenariosUtils.spec.js b/src/utils/__test__/ScenariosUtils.spec.js new file mode 100644 index 000000000..5f4e7bae3 --- /dev/null +++ b/src/utils/__test__/ScenariosUtils.spec.js @@ -0,0 +1,63 @@ +// Copyright (c) Cosmo Tech. +// Licensed under the MIT license. +import { ScenariosUtils } from '../ScenariosUtils'; + +describe('patchScenarioParameterValues', () => { + test.each` + solutionParameters | parameterValues + ${undefined} | ${undefined} + ${undefined} | ${null} + ${undefined} | ${[]} + ${undefined} | ${0} + ${undefined} | ${false} + ${undefined} | ${''} + ${undefined} | ${'foo'} + ${null} | ${undefined} + ${null} | ${null} + ${null} | ${[]} + ${null} | ${0} + ${null} | ${false} + ${null} | ${''} + ${null} | ${'foo'} + ${[]} | ${undefined} + ${[]} | ${null} + ${[]} | ${[]} + ${[]} | ${0} + ${[]} | ${false} + ${[]} | ${''} + ${[]} | ${'foo'} + `( + 'should do nothing without error when arguments are nullish or not arrays', + ({ solutionParameters, parameterValues }) => { + expect(() => ScenariosUtils.patchScenarioParameterValues(solutionParameters, parameterValues)).not.toThrow(); + } + ); + + test('should fill missing varTypes based on solution description', () => { + const spyConsoleWarn = jest.spyOn(console, 'warn').mockImplementation(() => {}); + + const solutionParameters = [ + { id: 'p0', varType: 'bool' }, + { id: 'p1', varType: 'date' }, + { id: 'p3', varType: 'string' }, + ]; + const parameterValues = [ + { parameterId: 'p0', value: 'p0' }, + { parameterId: 'p1', varType: null, value: 'p1' }, + { parameterId: 'p2', varType: null, value: 'p2' }, + { parameterId: 'p3', varType: 'string', value: 'p3' }, + ]; + const expectedParameterValues = [ + { parameterId: 'p0', varType: 'bool', value: 'p0' }, + { parameterId: 'p1', varType: 'date', value: 'p1' }, + { parameterId: 'p2', varType: null, value: 'p2' }, // Not defined in solution + { parameterId: 'p3', varType: 'string', value: 'p3' }, + ]; + + ScenariosUtils.patchScenarioParameterValues(solutionParameters, parameterValues); + expect(parameterValues).toStrictEqual(expectedParameterValues); + expect(spyConsoleWarn).toHaveBeenCalledTimes(1); + + spyConsoleWarn.mockClear(); + }); +});