Skip to content

Commit

Permalink
Merge branch 'main' into md-legacy-client
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongnansu authored Sep 29, 2022
2 parents 6244daf + 0279588 commit 5435d9d
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### 📈 Features/Enhancements

* Add updated_at column to objects' tables ([#1218](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/1218))
* [Viz Builder] State validation before dispatching and loading ([#2351](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2351))

### 🐛 Bug Fixes

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
"@types/yauzl": "^2.9.1",
"JSONStream": "1.3.5",
"abortcontroller-polyfill": "^1.4.0",
"ajv": "^8.11.0",
"angular": "^1.8.2",
"angular-elastic": "^2.5.1",
"angular-sanitize": "^1.8.0",
Expand Down
28 changes: 28 additions & 0 deletions src/plugins/wizard/public/application/utils/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "object",
"properties": {
"styleState": {
"type": "object"
},
"visualizationState": {
"type": "object",
"properties": {
"activeVisualization": {
"type": "object",
"properties": {
"name": { "type": "string" },
"aggConfigParams": { "type": "array" }
},
"required": ["name", "aggConfigParams"],
"additionalProperties": false
},
"indexPattern": { "type": "string" },
"searchField": { "type": "string" }
},
"required": ["searchField"],
"additionalProperties": false
}
},
"required": ["styleState", "visualizationState"],
"additionalProperties": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { i18n } from '@osd/i18n';
import { useEffect, useState } from 'react';
import { SavedObject } from '../../../../../saved_objects/public';
import {
InvalidJSONProperty,
redirectWhenMissing,
SavedObjectNotFound,
} from '../../../../../opensearch_dashboards_utils/public';
Expand All @@ -23,6 +24,7 @@ import {
} from '../state_management';
import { useOpenSearchDashboards } from '../../../../../opensearch_dashboards_react/public';
import { setEditorState } from '../state_management/metadata_slice';
import { validateWizardState } from '../wizard_state_validation';

// This function can be used when instantiating a saved vis or creating a new one
// using url parameters, embedding and destroying it in DOM
Expand All @@ -39,6 +41,14 @@ export const useSavedWizardVis = (visualizationIdFromUrl: string | undefined) =>
http: { basePath },
toastNotifications,
} = services;
const toastNotification = (message) => {
toastNotifications.addDanger({
title: i18n.translate('visualize.createVisualization.failedToLoadErrorMessage', {
defaultMessage: 'Failed to load the visualization',
}),
text: message,
});
};
const loadSavedWizardVis = async () => {
try {
const savedWizardVis = await getSavedWizardVis(services, visualizationIdFromUrl);
Expand All @@ -58,7 +68,16 @@ export const useSavedWizardVis = (visualizationIdFromUrl: string | undefined) =>
activeVisualization: vizStateWithoutIndex.activeVisualization,
indexPattern: savedWizardVis.searchSourceFields.index,
};
// TODO: Add validation and transformation, throw/handle errors

const validateResult = validateWizardState({ styleState, visualizationState });
if (!validateResult.valid) {
const err = validateResult.errors;
if (err) {
const errMsg = err[0].instancePath + ' ' + err[0].message;
throw new InvalidJSONProperty(errMsg);
}
}

dispatch(setStyleState<MetricOptionsDefaults>(styleState));
dispatch(setVisualizationState(visualizationState));
}
Expand All @@ -83,14 +102,12 @@ export const useSavedWizardVis = (visualizationIdFromUrl: string | undefined) =>
mapping: managementRedirectTarget,
})(error);
}
if (error instanceof InvalidJSONProperty) {
toastNotification(error.message);
}
} catch (e) {
const message = e instanceof Error ? e.message : '';
toastNotifications.addWarning({
title: i18n.translate('visualize.createVisualization.failedToLoadErrorMessage', {
defaultMessage: 'Failed to load the visualization',
}),
text: message,
});
toastNotification(message);
history.replace(EDIT_PATH);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { validateWizardState } from './wizard_state_validation';

describe('wizard state validation', () => {
const validStyleState = {
addLegend: true,
addTooltip: true,
legendPosition: '',
type: 'metric',
};
const validVisualizationState = {
activeVisualization: {
name: 'metric',
aggConfigParams: [],
},
indexPattern: '',
searchField: '',
};
describe('correct return when validation suceeds', () => {
test('with correct wizard state', () => {
const validationResult = validateWizardState({
styleState: validStyleState,
visualizationState: validVisualizationState,
});
expect(validationResult.valid).toBeTruthy();
expect(validationResult.errors).toBeNull();
});
});
describe('correct return with errors when validation fails', () => {
test('with non object type styleStyle', () => {
const validationResult = validateWizardState({
styleState: [],
visualizationState: validVisualizationState,
});
expect(validationResult.valid).toBeFalsy();
expect(validationResult.errors).toBeDefined();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import Ajv from 'ajv';
import wizardStateSchema from './schema.json';

const ajv = new Ajv();
const validateState = ajv.compile(wizardStateSchema);

export const validateWizardState = (wizardState) => {
const isWizardStateValid = validateState(wizardState);

return {
valid: isWizardStateValid,
errors: validateState.errors,
};
};
18 changes: 9 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4368,7 +4368,7 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.11.0, ajv@^6.12.3, ajv@^6.12.4, ajv
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

ajv@^8.0.1, ajv@^8.6.2:
ajv@^8.0.1, ajv@^8.11.0, ajv@^8.6.2:
version "8.11.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
Expand Down Expand Up @@ -11911,10 +11911,10 @@ [email protected]:
resolved "https://registry.yarnpkg.com/leaflet-responsive-popup/-/leaflet-responsive-popup-0.6.4.tgz#b93d9368ef9f96d6dc911cf5b96d90e08601c6b3"
integrity sha512-2D8G9aQA6NHkulDBPN9kqbUCkCpWQQ6dF0xFL11AuEIWIbsL4UC/ZPP5m8GYM0dpU6YTlmyyCh1Tz+cls5Q4dg==

"leaflet-vega@npm:@amoo-miki/[email protected].7":
version "0.8.7"
resolved "https://registry.yarnpkg.com/@amoo-miki/leaflet-vega/-/leaflet-vega-0.8.7.tgz#8faca1b4b8e2ef7d48667ac6faad9204f4da7153"
integrity sha512-T4M5yziwj3Fi9Adsbce+cdWqPjON0BRwEjwqLlPMoirU1vhifA6YKrlZkVzJrK0IIm+hdfMCLkBz33gD8fdxzQ==
"leaflet-vega@npm:@amoo-miki/[email protected].8":
version "0.8.8"
resolved "https://registry.yarnpkg.com/@amoo-miki/leaflet-vega/-/leaflet-vega-0.8.8.tgz#675abf37d72fbea859755e982f4fd19dea776557"
integrity sha512-W2gGgFDxzy/XUx+fQJfz0NYVXsKl7V+G6QywiMcOV5NEodDId9c60up7NNf+cfM7ggpo+5BuLqrKmosuGO1CsA==
dependencies:
vega-spec-injector "^0.0.2"

Expand Down Expand Up @@ -18353,10 +18353,10 @@ vega-hierarchy@~4.1.0:
vega-dataflow "^5.7.3"
vega-util "^1.15.2"

"vega-interpreter@npm:@amoo-miki/[email protected].5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@amoo-miki/vega-forced-csp-compliant-interpreter/-/vega-forced-csp-compliant-interpreter-1.0.5.tgz#49970be9b00ca7e45ced0617fbf373c77a28aab4"
integrity sha512-lfeU77lVoUbSCC6N1ywdKg+I6K08xpkd82TLon+LebtKyC8aLCe7P5Dd/89zAPyFwRyobKftHu8z0xpV7R7a4Q==
"vega-interpreter@npm:@amoo-miki/[email protected].6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@amoo-miki/vega-forced-csp-compliant-interpreter/-/vega-forced-csp-compliant-interpreter-1.0.6.tgz#5cffdf12b7fe12dc936194edd9e8519506c38716"
integrity sha512-9S5nTTVd8JVKobcWp5iwirIeePiamwH1J9uSZPuG5kcF0TUBvGu++ERKjNdst5Qck7e4R6/7vjx2wVf58XUarg==

vega-label@~1.2.0:
version "1.2.0"
Expand Down

0 comments on commit 5435d9d

Please sign in to comment.