mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 08:09:22 +00:00
feat: dashboard stop unnecessary api call for config change (#7713)
### **PR Type** Enhancement, Bug fix ___ ### **Description** Add config-change detection to avoid API calls Debounce and auto-apply non-API config updates Fix metric panel field resets and builder UI Refactor panel data conversion into reusable helper ___ ### Diagram Walkthrough ```mermaid flowchart LR A["Dashboard/Logs/Metrics configs"] -- "watch changes" --> B["checkConfigChangeApiCallOrNot"] B -- "needs API" --> C["loadData() / keep state"] B -- "no API" --> D["apply local config + resize"] E["PanelSchemaRenderer"] -- "convertPanelDataCommon" --> F["panelData refresh"] ``` <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>7 files</summary><table> <tr> <td><strong>PanelSchemaRenderer.vue</strong><dd><code>Refactor data conversion and watch schema changes</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-e5376e7e77bf3aaf6590c2522d8c2dbffcc95a8006ae0d6dc0040a37825367d6">+70/-52</a> </td> </tr> <tr> <td><strong>DashboardQueryBuilder.vue</strong><dd><code>Hide X-axis controls for metric panels</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-a4f9abbeaad1156ab6ba5740d59ccb869d6a9172ca1c64b89cff78f3d7783409">+3/-0</a> </td> </tr> <tr> <td><strong>Index.vue</strong><dd><code>Debounce config updates; skip API when unnecessary</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-0323c3da69b369843c5d72bf4df5b00ca6b5147192a213baf331659ecf92af62">+23/-0</a> </td> </tr> <tr> <td><strong>Index.vue</strong><dd><code>Debounced config watcher with API necessity check</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-a6734928ea4dcb5244e90de5a16fe6f5cafa95ccf58430ac7b548a065daf3d61">+21/-1</a> </td> </tr> <tr> <td><strong>AddPanel.vue</strong><dd><code>Outdated detection uses API-need; debounce updates</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-c9632db1ad95af95aba10161bcbc7c5608318919f228637bdafae3f3a31267e8">+32/-5</a> </td> </tr> <tr> <td><strong>usePanelDataLoader.ts</strong><dd><code>Separate schema/time watchers; API-need gating</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-5a42e9493a7bcd722b88e61fd38883c4f61001bc9cafa399f65f8eafda3aace9">+22/-1</a> </td> </tr> <tr> <td><strong>checkConfigChangeApiCall.ts</strong><dd><code>Add utility to detect API-required config changes</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-5c85b8000a7da159a0fe523af41fa5db2cc5318b164e81a0755178f6df9e0b9d">+65/-0</a> </td> </tr> </table></details></td></tr><tr><td><strong>Bug fix</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>useDashboardPanel.ts</strong><dd><code>Reset fields for metric type on type switch</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/7713/files#diff-fbba1700750053b9eaf38ddd30dab84531bc44131c795ebb713811e4930cd7cb">+43/-0</a> </td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___ --------- Co-authored-by: ktx-abhay <abhay.padamani@kiara.tech>
This commit is contained in:
@@ -616,6 +616,74 @@ export default defineComponent({
|
||||
tableRendererRef.value = null;
|
||||
parser = null;
|
||||
});
|
||||
const convertPanelDataCommon = async () => {
|
||||
if (
|
||||
!errorDetail?.value?.message &&
|
||||
validatePanelData?.value?.length === 0
|
||||
) {
|
||||
try {
|
||||
panelData.value = await convertPanelData(
|
||||
panelSchema.value,
|
||||
data.value,
|
||||
store,
|
||||
chartPanelRef,
|
||||
hoveredSeriesState,
|
||||
resultMetaData,
|
||||
metadata.value,
|
||||
chartPanelStyle.value,
|
||||
annotations,
|
||||
loading.value,
|
||||
);
|
||||
|
||||
limitNumberOfSeriesWarningMessage.value =
|
||||
panelData.value?.extras?.limitNumberOfSeriesWarningMessage ?? "";
|
||||
|
||||
errorDetail.value = {
|
||||
message: "",
|
||||
code: "",
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.error("error", error);
|
||||
errorDetail.value = {
|
||||
message: error?.message,
|
||||
code: error?.code || "",
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// if no data is available, then show the default data
|
||||
// if there is an error config in the panel schema, then show the default data on error
|
||||
// if no default data on error is set, then show the custom error message
|
||||
if (
|
||||
panelSchema.value?.error_config?.custom_error_handeling &&
|
||||
panelSchema.value?.error_config?.default_data_on_error
|
||||
) {
|
||||
data.value = JSON.parse(
|
||||
panelSchema.value?.error_config?.default_data_on_error,
|
||||
);
|
||||
errorDetail.value = {
|
||||
message: "",
|
||||
code: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Watch for panel schema changes to re-convert panel data
|
||||
watch(
|
||||
panelSchema,
|
||||
async () => {
|
||||
// Re-convert panel data when schema changes (for non-whitelisted config changes)
|
||||
if (
|
||||
!errorDetail?.value?.message &&
|
||||
validatePanelData?.value?.length === 0 &&
|
||||
data.value?.length
|
||||
) {
|
||||
await convertPanelDataCommon();
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
[data, store?.state],
|
||||
async () => {
|
||||
@@ -648,58 +716,8 @@ export default defineComponent({
|
||||
code: "",
|
||||
};
|
||||
|
||||
// panelData.value = convertPanelData(panelSchema.value, data.value, store);
|
||||
if (
|
||||
!errorDetail?.value?.message &&
|
||||
validatePanelData?.value?.length === 0
|
||||
) {
|
||||
try {
|
||||
// passing chartpanelref to get width and height of DOM element
|
||||
panelData.value = await convertPanelData(
|
||||
panelSchema.value,
|
||||
data.value,
|
||||
store,
|
||||
chartPanelRef,
|
||||
hoveredSeriesState,
|
||||
resultMetaData,
|
||||
metadata.value,
|
||||
chartPanelStyle.value,
|
||||
annotations,
|
||||
loading.value,
|
||||
);
|
||||
|
||||
limitNumberOfSeriesWarningMessage.value =
|
||||
panelData.value?.extras?.limitNumberOfSeriesWarningMessage ?? "";
|
||||
|
||||
errorDetail.value = {
|
||||
message: "",
|
||||
code: "",
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.error("error", error);
|
||||
|
||||
errorDetail.value = {
|
||||
message: error?.message,
|
||||
code: error?.code || "",
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// if no data is available, then show the default data
|
||||
// if there is an error config in the panel schema, then show the default data on error
|
||||
// if no default data on error is set, then show the custom error message
|
||||
if (
|
||||
panelSchema.value?.error_config?.custom_error_handeling &&
|
||||
panelSchema.value?.error_config?.default_data_on_error
|
||||
) {
|
||||
data.value = JSON.parse(
|
||||
panelSchema.value?.error_config?.default_data_on_error,
|
||||
);
|
||||
errorDetail.value = {
|
||||
message: "",
|
||||
code: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
// Use the common function to convert panel data
|
||||
await convertPanelDataCommon();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
@@ -27,6 +27,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div
|
||||
style="display: flex; flex-direction: row; width: 100%"
|
||||
class="q-pl-md"
|
||||
v-if="
|
||||
dashboardPanelData.data.type != 'metric'
|
||||
"
|
||||
>
|
||||
<div style="flex: 1">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
|
||||
@@ -45,6 +45,7 @@ import { convertOffsetToSeconds } from "@/utils/dashboard/convertDataIntoUnitVal
|
||||
import useSearchWebSocket from "@/composables/useSearchWebSocket";
|
||||
import { useAnnotations } from "./useAnnotations";
|
||||
import useHttpStreamingSearch from "../useStreamingSearch";
|
||||
import { checkIfConfigChangeRequiredApiCallOrNot } from "@/utils/dashboard/checkConfigChangeApiCall";
|
||||
|
||||
/**
|
||||
* debounce time in milliseconds for panel data loader
|
||||
@@ -1644,13 +1645,33 @@ export const usePanelDataLoader = (
|
||||
|
||||
watch(
|
||||
// Watching for changes in panelSchema, selectedTimeObj and forceLoad
|
||||
() => [panelSchema?.value, selectedTimeObj?.value, forceLoad?.value],
|
||||
() => [selectedTimeObj?.value, forceLoad?.value],
|
||||
async () => {
|
||||
log("PanelSchema/Time Wather: called");
|
||||
loadData(); // Loading the data
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => [panelSchema?.value],
|
||||
async (newVal, oldVal) => {
|
||||
const [newSchema] = newVal;
|
||||
const [oldSchema] = oldVal;
|
||||
|
||||
const configNeedsApiCall = checkIfConfigChangeRequiredApiCallOrNot(
|
||||
oldSchema,
|
||||
newSchema,
|
||||
);
|
||||
|
||||
if (!configNeedsApiCall) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadData();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
/**
|
||||
* Replaces the query with the corresponding variable values.
|
||||
*
|
||||
|
||||
@@ -1061,6 +1061,49 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => {
|
||||
dashboardPanelData.data.customChartContent =
|
||||
getDefaultCustomChartText();
|
||||
|
||||
dashboardPanelData.data.queries[
|
||||
dashboardPanelData.layout.currentQueryIndex
|
||||
].config.time_shift = [];
|
||||
break;
|
||||
case "metric":
|
||||
dashboardPanelData.data.queries[
|
||||
dashboardPanelData.layout.currentQueryIndex
|
||||
].fields.x = [];
|
||||
dashboardPanelData.data.queries[
|
||||
dashboardPanelData.layout.currentQueryIndex
|
||||
].fields.y.forEach((itemY: any) => {
|
||||
if (itemY.aggregationFunction === null && !itemY.isDerived) {
|
||||
itemY.aggregationFunction = "count";
|
||||
}
|
||||
});
|
||||
dashboardPanelData.data.queries[
|
||||
dashboardPanelData.layout.currentQueryIndex
|
||||
].fields.z = [];
|
||||
dashboardPanelData.data.queries[
|
||||
dashboardPanelData.layout.currentQueryIndex
|
||||
].fields.breakdown = [];
|
||||
// we have multiple queries for geomap, so if we are moving away, we need to reset
|
||||
// the values of lat, lng and weight in all the queries
|
||||
dashboardPanelData.data.queries?.forEach((query: any) => {
|
||||
query.fields.latitude = null;
|
||||
query.fields.longitude = null;
|
||||
query.fields.weight = null;
|
||||
query.fields.name = null;
|
||||
query.fields.value_for_maps = null;
|
||||
query.fields.source = null;
|
||||
query.fields.target = null;
|
||||
query.fields.value = null;
|
||||
});
|
||||
if (dashboardPanelData.data.queryType === "sql") {
|
||||
dashboardPanelData.layout.currentQueryIndex = 0;
|
||||
dashboardPanelData.data.queries =
|
||||
dashboardPanelData.data.queries.slice(0, 1);
|
||||
}
|
||||
dashboardPanelData.data.htmlContent = "";
|
||||
dashboardPanelData.data.markdownContent = "";
|
||||
dashboardPanelData.data.customChartContent =
|
||||
getDefaultCustomChartText();
|
||||
|
||||
dashboardPanelData.data.queries[
|
||||
dashboardPanelData.layout.currentQueryIndex
|
||||
].config.time_shift = [];
|
||||
@@ -2035,7 +2078,8 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => {
|
||||
const { sqlParser }: any = useSqlParser.default();
|
||||
parser = await sqlParser();
|
||||
|
||||
updateQueryValue();
|
||||
// do not allow to modify custom query fields for logs page
|
||||
updateQueryValue(pageKey == "logs" ? true : false);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -389,6 +389,7 @@ import {
|
||||
getFieldsFromQuery,
|
||||
} from "@/utils/query/sqlUtils";
|
||||
import useNotifications from "@/composables/useNotifications";
|
||||
import { checkIfConfigChangeRequiredApiCallOrNot } from "@/utils/dashboard/checkConfigChangeApiCall";
|
||||
import SearchBar from "@/plugins/logs/SearchBar.vue";
|
||||
import SearchHistory from "@/plugins/logs/SearchHistory.vue";
|
||||
import SearchSchedulersList from "@/plugins/logs/SearchSchedulersList.vue";
|
||||
@@ -1666,6 +1667,26 @@ export default defineComponent({
|
||||
},
|
||||
);
|
||||
|
||||
// Auto-apply config changes that don't require API calls (similar to dashboard)
|
||||
const debouncedUpdateChartConfig = debounce((newVal) => {
|
||||
if (searchObj.meta.logsVisualizeToggle === "visualize") {
|
||||
|
||||
let configNeedsApiCall = checkIfConfigChangeRequiredApiCallOrNot(
|
||||
visualizeChartData.value,
|
||||
newVal,
|
||||
);
|
||||
|
||||
if (!configNeedsApiCall) {
|
||||
visualizeChartData.value = JSON.parse(JSON.stringify(newVal));
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
watch(() => dashboardPanelData.data, debouncedUpdateChartConfig, {
|
||||
deep: true,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [
|
||||
searchObj.data.datetime.type,
|
||||
|
||||
@@ -404,6 +404,7 @@ import { isEqual } from "lodash-es";
|
||||
import { onActivated } from "vue";
|
||||
import useNotifications from "@/composables/useNotifications";
|
||||
import CustomChartEditor from "@/components/dashboards/addPanel/CustomChartEditor.vue";
|
||||
import { checkIfConfigChangeRequiredApiCallOrNot } from "@/utils/dashboard/checkConfigChangeApiCall";
|
||||
|
||||
const ConfigPanel = defineAsyncComponent(() => {
|
||||
return import("@/components/dashboards/addPanel/ConfigPanel.vue");
|
||||
@@ -466,6 +467,7 @@ export default defineComponent({
|
||||
const { dashboardPanelData, resetAggregationFunction, validatePanel } =
|
||||
useDashboardPanelData(dashboardPanelDataPageKey);
|
||||
const metaData = ref(null);
|
||||
const resultMetaData = ref(null);
|
||||
const seriesData = ref([] as any[]);
|
||||
const seriesDataUpdate = (data: any) => {
|
||||
seriesData.value = data;
|
||||
@@ -492,12 +494,17 @@ export default defineComponent({
|
||||
);
|
||||
|
||||
const isOutDated = computed(() => {
|
||||
//compare chartdata and dashboardpaneldata
|
||||
// ignore histogram query comparison
|
||||
return (
|
||||
!is_ui_histogram.value &&
|
||||
!isEqual(chartData.value, dashboardPanelData.data)
|
||||
);
|
||||
const configChanged = !isEqual(chartData.value, dashboardPanelData.data);
|
||||
|
||||
// skip outdate check if doesnt require to call api
|
||||
let configNeedsApiCall = false;
|
||||
if (configChanged) {
|
||||
configNeedsApiCall = checkIfConfigChangeRequiredApiCallOrNot(
|
||||
chartData.value,
|
||||
dashboardPanelData.data,
|
||||
);
|
||||
}
|
||||
return configNeedsApiCall;
|
||||
});
|
||||
|
||||
watch(isOutDated, () => {
|
||||
@@ -569,6 +576,13 @@ export default defineComponent({
|
||||
provide("hoveredSeriesState", hoveredSeriesState);
|
||||
|
||||
const addToDashboard = () => {
|
||||
|
||||
// only copy if is_ui_histogram is true
|
||||
if (resultMetaData.value?.[0]?.converted_histogram_query && is_ui_histogram.value === true) {
|
||||
dashboardPanelData.data.queries[0].query =
|
||||
resultMetaData.value?.[0]?.converted_histogram_query;
|
||||
}
|
||||
|
||||
const errors: any = [];
|
||||
// will push errors in errors array
|
||||
validatePanel(errors, true);
|
||||
@@ -581,6 +595,7 @@ export default defineComponent({
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
|
||||
showAddToDashboardDialog.value = true;
|
||||
}
|
||||
};
|
||||
@@ -767,15 +782,15 @@ export default defineComponent({
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
};
|
||||
|
||||
const onResultMetadataUpdate = (resultMetaData: any) => {
|
||||
const onResultMetadataUpdate = (resultMetaDataParam: any) => {
|
||||
// Store the result metadata
|
||||
resultMetaData.value = resultMetaDataParam;
|
||||
|
||||
// only copy if is_ui_histogram is true
|
||||
if (
|
||||
resultMetaData?.[0]?.converted_histogram_query &&
|
||||
is_ui_histogram.value === true
|
||||
) {
|
||||
dashboardPanelData.data.queries[0].query =
|
||||
resultMetaData?.[0]?.converted_histogram_query;
|
||||
}
|
||||
// if (resultMetaDataParam?.[0]?.converted_histogram_query && is_ui_histogram.value === true) {
|
||||
// dashboardPanelData.data.queries[0].query =
|
||||
// resultMetaDataParam?.[0]?.converted_histogram_query;
|
||||
// }
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -522,12 +522,13 @@ import DashboardErrorsComponent from "@/components/dashboards/addPanel/Dashboard
|
||||
import VariablesValueSelector from "@/components/dashboards/VariablesValueSelector.vue";
|
||||
import PanelSchemaRenderer from "@/components/dashboards/PanelSchemaRenderer.vue";
|
||||
import RelativeTime from "@/components/common/RelativeTime.vue";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { isEqual, debounce } from "lodash-es";
|
||||
import { provide } from "vue";
|
||||
import useNotifications from "@/composables/useNotifications";
|
||||
import config from "@/aws-exports";
|
||||
import useCancelQuery from "@/composables/dashboard/useCancelQuery";
|
||||
import AutoRefreshInterval from "@/components/AutoRefreshInterval.vue";
|
||||
import { checkIfConfigChangeRequiredApiCallOrNot } from "@/utils/dashboard/checkConfigChangeApiCall";
|
||||
import CustomChartEditor from "@/components/dashboards/addPanel/CustomChartEditor.vue";
|
||||
const AddToDashboard = defineAsyncComponent(() => {
|
||||
return import("./../metrics/AddToDashboard.vue");
|
||||
@@ -779,6 +780,25 @@ export default defineComponent({
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
// Auto-apply config changes that don't require API calls (similar to dashboard)
|
||||
const debouncedUpdateChartConfig = debounce((newVal, oldVal) => {
|
||||
if (!isEqual(chartData.value, newVal)) {
|
||||
const configNeedsApiCall = checkIfConfigChangeRequiredApiCallOrNot(
|
||||
chartData.value,
|
||||
newVal,
|
||||
);
|
||||
|
||||
if (!configNeedsApiCall) {
|
||||
chartData.value = JSON.parse(JSON.stringify(newVal));
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
watch(() => dashboardPanelData.data, debouncedUpdateChartConfig, {
|
||||
deep: true,
|
||||
});
|
||||
|
||||
//validate the data
|
||||
const isValid = (onlyChart = false, isFieldsValidationRequired = true) => {
|
||||
const errors = errorData.errors;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// Whitelist of config keys that require API calls when changed
|
||||
const API_REQUIRING_CHANGES = new Set(["queries", "variables"]);
|
||||
|
||||
/**
|
||||
* Flattens an object's keys with dot notation
|
||||
*/
|
||||
const flattenObject = (obj: any, prefix = ""): Record<string, any> => {
|
||||
if (obj === null || obj === undefined) {
|
||||
return {};
|
||||
}
|
||||
return Object.keys(obj).reduce((acc: Record<string, any>, k: string) => {
|
||||
const pre = prefix.length ? prefix + "." : "";
|
||||
if (
|
||||
typeof obj[k] === "object" &&
|
||||
obj[k] !== null &&
|
||||
!Array.isArray(obj[k])
|
||||
) {
|
||||
Object.assign(acc, flattenObject(obj[k], pre + k));
|
||||
} else {
|
||||
acc[pre + k] = obj[k];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets changed keys between two objects
|
||||
*/
|
||||
const getChangedKeys = (oldObj: any, newObj: any): string[] => {
|
||||
const flatOld = flattenObject(oldObj);
|
||||
const flatNew = flattenObject(newObj);
|
||||
const changedKeys: string[] = [];
|
||||
|
||||
// Check all keys in both objects
|
||||
const allKeys = Array.from(
|
||||
new Set([...Object.keys(flatOld), ...Object.keys(flatNew)]),
|
||||
);
|
||||
|
||||
for (const key of allKeys) {
|
||||
if (JSON.stringify(flatOld[key]) !== JSON.stringify(flatNew[key])) {
|
||||
changedKeys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return changedKeys;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the changes between old and new config require an API call
|
||||
*/
|
||||
export const checkIfConfigChangeRequiredApiCallOrNot = (
|
||||
oldConfig: any,
|
||||
newConfig: any,
|
||||
): boolean => {
|
||||
const changedKeys = getChangedKeys(oldConfig, newConfig);
|
||||
const configNeedsApiCall = changedKeys.some((key) =>
|
||||
Array.from(API_REQUIRING_CHANGES).some((apiKey) => key.startsWith(apiKey)),
|
||||
);
|
||||
|
||||
if (configNeedsApiCall) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
@@ -510,13 +510,14 @@ import VariablesValueSelector from "../../../components/dashboards/VariablesValu
|
||||
import PanelSchemaRenderer from "../../../components/dashboards/PanelSchemaRenderer.vue";
|
||||
import RelativeTime from "@/components/common/RelativeTime.vue";
|
||||
import { useLoading } from "@/composables/useLoading";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { debounce, isEqual } from "lodash-es";
|
||||
import { provide } from "vue";
|
||||
import useNotifications from "@/composables/useNotifications";
|
||||
import config from "@/aws-exports";
|
||||
import useCancelQuery from "@/composables/dashboard/useCancelQuery";
|
||||
import useAiChat from "@/composables/useAiChat";
|
||||
import useStreams from "@/composables/useStreams";
|
||||
import { checkIfConfigChangeRequiredApiCallOrNot } from "@/utils/dashboard/checkConfigChangeApiCall";
|
||||
|
||||
const ConfigPanel = defineAsyncComponent(() => {
|
||||
return import("../../../components/dashboards/addPanel/ConfigPanel.vue");
|
||||
@@ -899,11 +900,19 @@ export default defineComponent({
|
||||
|
||||
const normalizedCurrent = normalizeVariables(variablesData);
|
||||
const normalizedRefreshed = normalizeVariables(updatedVariablesData);
|
||||
const variablesChanged = !isEqual(normalizedCurrent, normalizedRefreshed);
|
||||
|
||||
return (
|
||||
!isEqual(chartData.value, dashboardPanelData.data) ||
|
||||
!isEqual(normalizedCurrent, normalizedRefreshed)
|
||||
);
|
||||
const configChanged = !isEqual(chartData.value, dashboardPanelData.data);
|
||||
let configNeedsApiCall = false;
|
||||
|
||||
if (configChanged) {
|
||||
configNeedsApiCall = checkIfConfigChangeRequiredApiCallOrNot(
|
||||
chartData.value,
|
||||
dashboardPanelData.data,
|
||||
);
|
||||
}
|
||||
|
||||
return configNeedsApiCall || variablesChanged;
|
||||
});
|
||||
|
||||
watch(isOutDated, () => {
|
||||
@@ -1561,6 +1570,24 @@ export default defineComponent({
|
||||
return { width: `${contentWidth}px` };
|
||||
});
|
||||
|
||||
const debouncedUpdateChartConfig = debounce((newVal, oldVal) => {
|
||||
if (!isEqual(chartData.value, newVal)) {
|
||||
const configNeedsApiCall = checkIfConfigChangeRequiredApiCallOrNot(
|
||||
chartData.value,
|
||||
newVal,
|
||||
);
|
||||
|
||||
if (!configNeedsApiCall) {
|
||||
chartData.value = JSON.parse(JSON.stringify(newVal));
|
||||
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
watch(() => dashboardPanelData.data, debouncedUpdateChartConfig, {
|
||||
deep: true,
|
||||
});
|
||||
// [START] ai chat
|
||||
|
||||
// [START] O2 AI Context Handler
|
||||
|
||||
Reference in New Issue
Block a user