diff --git a/src/src/services/api/api.ts b/src/src/services/api/api.ts index 715cb821..003e34c8 100644 --- a/src/src/services/api/api.ts +++ b/src/src/services/api/api.ts @@ -54,13 +54,19 @@ function getStream( params?: {}, options?: RequestInit, ) { + const queryString = Object.entries(params || {}) + .map(([key, value]) => { + if (Array.isArray(value)) { + return value.map((v) => `${key}=${v}`).join('&'); + } else { + return `${key}=${value}`; + } + }) + .join('&'); + return createAPIRequestWrapper( `${url}${ - options?.method === 'POST' - ? '' - : params - ? '?' + new URLSearchParams(params).toString() - : '' + options?.method === 'POST' ? '' : queryString ? '?' + queryString : '' }`, { method: 'GET', diff --git a/src/src/services/models/explorer/createAppModel.ts b/src/src/services/models/explorer/createAppModel.ts index c0482c26..4e8b8f0d 100644 --- a/src/src/services/models/explorer/createAppModel.ts +++ b/src/src/services/models/explorer/createAppModel.ts @@ -101,6 +101,7 @@ import getFilteredRow from 'utils/app/getFilteredRow'; import { getGroupingPersistIndex } from 'utils/app/getGroupingPersistIndex'; import getGroupingSelectOptions from 'utils/app/getGroupingSelectOptions'; import getQueryStringFromSelect from 'utils/app/getQueryStringFromSelect'; +import getMetricsListFromSelect from 'utils/app/getMetricsListFromSelect'; import getRunData from 'utils/app/getRunData'; import onAggregationConfigChange from 'utils/app/onAggregationConfigChange'; import onAlignmentMetricChange from 'utils/app/onAlignmentMetricChange'; @@ -542,7 +543,6 @@ function createAppModel(appConfig: IAppInitialConfig) { if (!appId) { setModelDefaultAppConfigData(); } - projectsService .getProjectParams(['metric']) .call() @@ -552,7 +552,7 @@ function createAppModel(appConfig: IAppInitialConfig) { ); model.setState({ selectFormData: { - options: getSelectOptions(data, true), + options: getSelectOptions(data, false, false), suggestions: getSuggestionsByExplorer(appName, data), advancedSuggestions: { ...getSuggestionsByExplorer(appName, data), @@ -618,55 +618,66 @@ function createAppModel(appConfig: IAppInitialConfig) { configData.select.query = queryString; } } - let query = getQueryStringFromSelect(configData?.select); - metricsRequestRef = metricsService.getMetricsData({ + + let metrics = getMetricsListFromSelect(configData?.select); + let query = getQueryStringFromSelect(configData?.select, true); + + let params: { + q: string; + p?: any; + x_axis?: any; + [key: string]: any; + } = { q: query, p: configData?.chart?.densityType, ...(metric ? { x_axis: metric } : {}), + }; + + metrics.forEach((tuple, index) => { + const [metric, context] = tuple; + params[`m[${index}][metric]`] = metric; + params[`m[${index}][context]`] = context; }); + metricsRequestRef = metricsService.getMetricsData(params); setRequestProgress(model); return { call: async () => { - if (query === '()') { - resetModelState(configData, shouldResetSelectedRows!); - } else { - model.setState({ - requestStatus: RequestStatusEnum.Pending, - queryIsEmpty: false, - selectedRows: shouldResetSelectedRows - ? {} - : model.getState()?.selectedRows, + model.setState({ + requestStatus: RequestStatusEnum.Pending, + queryIsEmpty: false, + selectedRows: shouldResetSelectedRows + ? {} + : model.getState()?.selectedRows, + }); + liveUpdateInstance?.stop().then(); + try { + const stream = await metricsRequestRef.call((detail) => { + exceptionHandler({ detail, model }); + resetModelState(configData, shouldResetSelectedRows!); }); - liveUpdateInstance?.stop().then(); - try { - const stream = await metricsRequestRef.call((detail) => { - exceptionHandler({ detail, model }); - resetModelState(configData, shouldResetSelectedRows!); - }); - const runData = await getRunData(stream, (progress) => - setRequestProgress(model, progress), - ); - if (shouldUrlUpdate) { - updateURL({ configData, appName }); - } - saveRecentSearches(appName, query); - updateData(runData); - } catch (ex: Error | any) { - if (ex.name === 'AbortError') { - // Abort Error - } else { - // eslint-disable-next-line no-console - console.log('Unhandled error: ', ex); - } + const runData = await getRunData(stream, (progress) => + setRequestProgress(model, progress), + ); + if (shouldUrlUpdate) { + updateURL({ configData, appName }); + } + saveRecentSearches(appName, query); + updateData(runData); + } catch (ex: Error | any) { + if (ex.name === 'AbortError') { + // Abort Error + } else { + // eslint-disable-next-line no-console + console.log('Unhandled error: ', ex); } - - liveUpdateInstance?.start({ - q: query, - p: configData?.chart?.densityType, - ...(metric && { x_axis: metric }), - }); } + + liveUpdateInstance?.start({ + q: query, + p: configData?.chart?.densityType, + ...(metric && { x_axis: metric }), + }); }, abort: metricsRequestRef.abort, }; diff --git a/src/src/utils/app/getMetricsListFromSelect.ts b/src/src/utils/app/getMetricsListFromSelect.ts new file mode 100644 index 00000000..50ceb67f --- /dev/null +++ b/src/src/utils/app/getMetricsListFromSelect.ts @@ -0,0 +1,39 @@ +import { ISyntaxErrorDetails } from 'types/components/NotificationContainer/NotificationContainer'; +import { ISelectConfig } from 'types/services/models/explorer/createAppModel'; + +import { jsValidVariableRegex } from 'utils/getObjectPaths'; + +import { formatValue } from '../formatValue'; + +export default function getMetricsListFromSelect( + selectData: ISelectConfig, + error?: ISyntaxErrorDetails, +): Array<[string, string]> { + const metricsList: Array<[string, string]> = []; + + if (selectData === undefined) { + return metricsList; + } + + selectData.options?.forEach((option) => { + const metricName = option.value?.option_name ?? ''; + const context: string = + option.value?.context && Object.keys(option.value?.context).length > 0 + ? Object.keys(option.value?.context) + .map((item) => { + const contextKey = !jsValidVariableRegex.test(item) + ? `['${item}']` + : `${item}`; + const contextValue = (option.value?.context as any)[item]; + return `{${formatValue(contextKey)}: ${formatValue( + contextValue, + )}}`; + }) + .join(', ') + : '{}'; + + metricsList.push([metricName, context]); + }); + + return metricsList; +} diff --git a/src/src/utils/app/getSelectOptions.ts b/src/src/utils/app/getSelectOptions.ts index b3bb34c1..0f270dce 100644 --- a/src/src/utils/app/getSelectOptions.ts +++ b/src/src/utils/app/getSelectOptions.ts @@ -15,6 +15,7 @@ import { getMetricLabel } from './getMetricLabel'; export default function getSelectOptions( projectsData: IProjectParamsMetrics, addHighLevelMetrics: boolean = false, + includeParams: boolean = true, ): ISelectOption[] { const comparator = alphabeticalSortComparator({ orderBy: 'label', @@ -72,7 +73,7 @@ export default function getSelectOptions( } } } - if (projectsData?.params && !addHighLevelMetrics) { + if (projectsData?.params && !addHighLevelMetrics && includeParams) { const paramPaths = getObjectPaths(projectsData.params, projectsData.params); paramPaths.forEach((paramPath, index) => { const indexOf =