From 5680001c4e463dd3ea433ac7550fdfbb3efedbca Mon Sep 17 00:00:00 2001 From: Mantra Date: Wed, 6 Nov 2024 12:18:17 +0000 Subject: [PATCH 1/8] less code dup --- .../sensitivity/sensitivityTracesPlot.test.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/app/static/tests/unit/components/sensitivity/sensitivityTracesPlot.test.ts b/app/static/tests/unit/components/sensitivity/sensitivityTracesPlot.test.ts index e2b437e8..fbce7b2d 100644 --- a/app/static/tests/unit/components/sensitivity/sensitivityTracesPlot.test.ts +++ b/app/static/tests/unit/components/sensitivity/sensitivityTracesPlot.test.ts @@ -458,20 +458,7 @@ describe("SensitivityTracesPlot", () => { paramSettings: { parameterToVary: "alpha" }, - result: { - batch: { - solutions: sensitivityHasSolutions ? mockSolutions : null, - allFitData: sensitivityHasData ? mockAllFitData : undefined, - pars: { - varying: [ - { - name: "alpha", - values: [1.11111, 2.22222] - } - ] - } - } - }, + result: getMockResult(sensitivityHasSolutions, sensitivityHasData), parameterSetResults: hasParameterSets ? mockParameterSetResults : {} }, mutations: { From b999e60ffc79870ad2070c588f1ae0e3f17b89be Mon Sep 17 00:00:00 2001 From: Mantra Date: Wed, 6 Nov 2024 12:41:15 +0000 Subject: [PATCH 2/8] emma review: update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0410b648..42d9caf4 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,6 @@ Use the `./scripts/run-version.sh` script setting the branch references for the ## Hot Reloading -This repo has two main parts: `app/server` (Express server) and `app/static` (Vue frontend). The normal way to spin up the app without hot reloading is build frontend, copy build files into public folder in the server and run the server. The html file will then look for its javascript src `wodin.js` and css src `wodin.css` in the `app/server/public` directory and load the app from these. +This repo has two main parts: `app/server` (Express server) and `app/static` (Vue frontend). The normal way to spin up the app without hot reloading is build frontend, copy build files into public folder in the server (`npm run build --prefix=app/static` builds the frontend and copies the files to the server) and run the server (`npm run serve --prefix=app/server`). The html file will then look for its javascript src `wodin.js` and css src `wodin.css` in the `app/server/public` directory and load the app from these. -The hot reloading setup is different. The `server.js` file (from building the server) takes in a `--hot-reload` boolean option which tells it to instead look for the javascript src at `http://localhost:5173/src/wodin.ts` since `wodin.ts` is our entrypoint (`http://localhost:5173` is the default url for `vite` dev mode and it serves the files, after transpiling to javascript, based on your folder structure) and css src at `http://localhost:5173/src/scss/style.scss`. +The hot reloading setup is different. The `server.js` file (from building the server) takes in a `--hot-reload` boolean option which tells it to instead look for the javascript src at `http://localhost:5173/src/wodin.ts` since `wodin.ts` is our entrypoint (`http://localhost:5173` is the default url for `vite` dev mode and it serves the files, after transpiling to javascript, based on your folder structure) and css src at `http://localhost:5173/src/scss/style.scss`. To run it this way we run `npm run dev --prefix=app/static` to start the vite dev server and then we run `npm run serve-hot --prefix=app/server`. From 57246fc1dce94ebc02e6a505bbcff42cc0c90d68 Mon Sep 17 00:00:00 2001 From: Mantra Date: Fri, 8 Nov 2024 12:11:12 +0000 Subject: [PATCH 3/8] add comments to code e2e test about glyph --- app/static/tests/e2e/code.etest.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/static/tests/e2e/code.etest.ts b/app/static/tests/e2e/code.etest.ts index efc65ad9..6d702450 100644 --- a/app/static/tests/e2e/code.etest.ts +++ b/app/static/tests/e2e/code.etest.ts @@ -48,6 +48,8 @@ test.beforeEach(async ({ page }) => { }); const expectMonacoDecoration = async (state: EditorStates, line: number, numOfLines: number, page: Page) => { + // check that the correct line has the correct background color here by looping through + // each line for (let i = 0; i < numOfLines; i += 1) { const lineElement = await page.locator(`.view-overlays div:nth-child(${i + 1}) >> div`); if (i === line - 1) { @@ -59,6 +61,10 @@ const expectMonacoDecoration = async (state: EditorStates, line: number, numOfLi } } + // check that the glyph (our error/warning icon) is vertically aligned with the + // correct line number, monaco editor just sets a "top" css property to vertically + // align it next to the line number so we calculate what that translation should be + // by multiplying the line-height by the number of lines down we have to go down const lineHeight = await page.locator(".margin-view-overlays").evaluate(el => { return window.getComputedStyle(el).getPropertyValue("line-height"); }); From 944ddf6b8684d8c1509d93f01ea82dad14742078 Mon Sep 17 00:00:00 2001 From: Mantra Date: Wed, 13 Nov 2024 22:21:18 +0000 Subject: [PATCH 4/8] add basic eslint rules back in and make types better --- app/static/eslint.config.js | 9 ++++-- app/static/src/apiService.ts | 19 +++++++----- .../src/components/VerticalCollapse.vue | 1 + app/static/src/components/WodinPlot.vue | 9 +++--- app/static/src/components/WodinSession.vue | 1 + app/static/src/components/WodinTabs.vue | 1 + .../components/graphConfig/GraphConfig.vue | 1 + .../components/options/ParameterSetView.vue | 7 +++-- .../components/options/SensitivityOptions.vue | 1 + .../SensitivitySummaryDownload.vue | 1 + app/static/src/directives/tooltip.ts | 10 +++---- app/static/src/excel/wodinExcelDownload.ts | 1 + app/static/src/store/basic/basic.ts | 4 +-- app/static/src/store/fit/fit.ts | 4 +-- app/static/src/store/stochastic/stochastic.ts | 4 +-- app/static/src/types/utilTypes.ts | 3 +- app/static/src/utils.ts | 6 ++-- .../translationPackage/directive/translate.ts | 30 +++++++++---------- .../translationPackage/store/actions.ts | 2 +- 19 files changed, 66 insertions(+), 48 deletions(-) diff --git a/app/static/eslint.config.js b/app/static/eslint.config.js index 82b0022a..cf333985 100644 --- a/app/static/eslint.config.js +++ b/app/static/eslint.config.js @@ -23,16 +23,19 @@ export default [ }, { - files: ["**/*.ts", "**/*.vue"], + files: ["src/**/*.ts", "src/**/*.vue"], rules: { - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-unused-vars": "error", + "vue/no-setup-props-destructure": "error", } }, { files: ["**/tests/**/*.ts"], rules: { - "vitest/expect-expect": "off" + "vitest/expect-expect": "off", + "@typescript-eslint/no-explicit-any": "off", } }, diff --git a/app/static/src/apiService.ts b/app/static/src/apiService.ts index e84f679b..8ce8d394 100644 --- a/app/static/src/apiService.ts +++ b/app/static/src/apiService.ts @@ -10,16 +10,21 @@ export interface ResponseWithType extends ResponseSuccess { data: T; } -export function isAPIError(object: any): object is WodinError { - return typeof object.error === "string" && (object.details === undefined || typeof object.details === "string"); +function isObject(object: unknown): object is Record { + return typeof object === "object" && !Array.isArray(object) && object !== null; } -export function isAPIResponseFailure(object: any): object is ResponseFailure { - return ( +export function isAPIError(object: unknown): object is WodinError { + return isObject(object) && typeof object.error === "string" && (object.detail === undefined || typeof object.detail === "string"); +} + +export function isAPIResponseFailure(object: unknown): object is ResponseFailure { + return !!( object && + isObject(object) && object.status === "failure" && Array.isArray(object.errors) && - object.errors.every((e: any) => isAPIError(e)) + object.errors.every(e => isAPIError(e)) ); } @@ -101,7 +106,7 @@ export class APIService implements API }; withSuccess = (type: S, root = false) => { - this._onSuccess = (data: any) => { + this._onSuccess = (data: unknown) => { const finalData = this._freezeResponse ? freezer.deepFreeze(data) : data; try { this._commit(type, finalData, { root }); @@ -175,7 +180,7 @@ export class APIService implements API return this._handleAxiosResponse(axios.get(fullUrl)); } - async post(url: string, body: any, contentType = "application/json"): Promise> { + async post(url: string, body: unknown, contentType = "application/json"): Promise> { this._verifyHandlers(url); const headers = { "Content-Type": contentType }; const fullUrl = this._fullUrl(url); diff --git a/app/static/src/components/VerticalCollapse.vue b/app/static/src/components/VerticalCollapse.vue index c67223f3..c4a2ca10 100644 --- a/app/static/src/components/VerticalCollapse.vue +++ b/app/static/src/components/VerticalCollapse.vue @@ -37,6 +37,7 @@ export default defineComponent({ VueFeather }, setup(props) { + // eslint-disable-next-line vue/no-setup-props-destructure const collapsed = ref(props.collapsedDefault); const toggleCollapse = () => { diff --git a/app/static/src/components/WodinPlot.vue b/app/static/src/components/WodinPlot.vue index 698681a9..7dcca4cc 100644 --- a/app/static/src/components/WodinPlot.vue +++ b/app/static/src/components/WodinPlot.vue @@ -21,7 +21,8 @@ import { AxisType, Layout, Config, - LayoutAxis + LayoutAxis, + PlotlyHTMLElement } from "plotly.js-basic-dist-min"; import { WodinPlotData, fadePlotStyle, margin, config } from "../plot"; import WodinPlotDataSummary from "./WodinPlotDataSummary.vue"; @@ -46,7 +47,7 @@ export default defineComponent({ // Only used as an indicator that redraw is required when this changes - the data to display is calculated by // plotData function using these solutions redrawWatches: { - type: Array as PropType, + type: Array as PropType, required: true }, recalculateOnRelayout: { @@ -83,7 +84,7 @@ export default defineComponent({ const startTime = 0; - const plot = ref(null); // Picks up the element with 'plot' ref in the template + const plot = ref(null); // Picks up the element with 'plot' ref in the template const baseData = ref([]); const nPoints = 1000; // TODO: appropriate value could be derived from width of element @@ -101,7 +102,7 @@ export default defineComponent({ const lastYAxisFromZoom: Ref | null> = ref(null); const commitYAxisRange = () => { - const plotLayout = (plot.value as any).layout; + const plotLayout = plot.value!.layout; const yRange = plotLayout.yaxis?.range; if (plotLayout) { if (props.fitPlot) { diff --git a/app/static/src/components/WodinSession.vue b/app/static/src/components/WodinSession.vue index 8b2a821b..6b71484a 100644 --- a/app/static/src/components/WodinSession.vue +++ b/app/static/src/components/WodinSession.vue @@ -34,6 +34,7 @@ export default defineComponent({ const appInitialised = computed(() => !!store.state.config && !!store.state.sessions.sessionsMetadata); // These props won't change as provided by server + // eslint-disable-next-line vue/no-setup-props-destructure const { appName, baseUrl, loadSessionId, appsPath, enableI18n, defaultLanguage } = props; store.dispatch(AppStateAction.InitialiseApp, { diff --git a/app/static/src/components/WodinTabs.vue b/app/static/src/components/WodinTabs.vue index 4d981091..b555cf4f 100644 --- a/app/static/src/components/WodinTabs.vue +++ b/app/static/src/components/WodinTabs.vue @@ -33,6 +33,7 @@ export default defineComponent({ }, emits: ["tabSelected"], setup(props: Props, { emit }) { + // eslint-disable-next-line vue/no-setup-props-destructure const selectedTabName = ref(props.tabNames[0]); const tabSelected = (tabName: string) => { diff --git a/app/static/src/components/graphConfig/GraphConfig.vue b/app/static/src/components/graphConfig/GraphConfig.vue index f519e8f2..24d3b3d2 100644 --- a/app/static/src/components/graphConfig/GraphConfig.vue +++ b/app/static/src/components/graphConfig/GraphConfig.vue @@ -59,6 +59,7 @@ export default defineComponent({ }, setup(props, { emit }) { const store = useStore(); + // eslint-disable-next-line vue/no-setup-props-destructure const { startDrag, endDrag, onDrop, removeVariable } = SelectVariables(store, emit, false, props.graphIndex); const selectedVariables = computed( () => store.state.graphs.config[props.graphIndex].selectedVariables diff --git a/app/static/src/components/options/ParameterSetView.vue b/app/static/src/components/options/ParameterSetView.vue index 49d91ccd..96b18d9e 100644 --- a/app/static/src/components/options/ParameterSetView.vue +++ b/app/static/src/components/options/ParameterSetView.vue @@ -97,7 +97,7 @@