ktx-vaidehi
2024-04-23 20:53:31 +05:30
committed by GitHub
co-authored by ktx-abhay Kirtan Thakkar
parent f1b92ec40b
commit f01035f915
14 changed files with 447 additions and 102 deletions
@@ -590,7 +590,7 @@ export default defineComponent({
variablesData.value.values.forEach((variable: any) => {
if (variable.type != "dynamic_filters") {
drilldownVariables["var-" + variable.name] = variable.value;
drilldownVariables[variable.name] = variable.value;
}
});
@@ -653,11 +653,11 @@ export default defineComponent({
pos > -1
? window.location.origin +
window.location.pathname.slice(0, pos) +
"/web/"
"/web"
: window.location.origin;
// always, go to view dashboard page
currentUrl += "dashboards/view?";
currentUrl += "/dashboards/view?";
// if pass all variables in url
currentUrl += drilldownData.data.passAllVariables
@@ -670,7 +670,8 @@ export default defineComponent({
drilldownData.data.variables.forEach((variable: any) => {
if (variable?.name?.trim() && variable?.value?.trim()) {
url.searchParams.set(
replacePlaceholders(variable.name, drilldownVariables),
"var-" +
replacePlaceholders(variable.name, drilldownVariables),
replacePlaceholders(variable.value, drilldownVariables)
);
}
@@ -693,7 +694,8 @@ export default defineComponent({
drilldownData.data.variables.forEach((variable: any) => {
if (variable?.name?.trim() && variable?.value?.trim()) {
oldParams[
replacePlaceholders(variable.name, drilldownVariables)
"var-" +
replacePlaceholders(variable.name, drilldownVariables)
] = replacePlaceholders(variable.value, drilldownVariables);
}
});
@@ -298,6 +298,9 @@ export default defineComponent({
const changeInitialVariableValues = async (
newInitialVariableValues: any
) => {
// reject all promises
rejectAllPromises();
// NOTE: need to re-initialize variables data
resetVariablesData();
@@ -307,9 +310,6 @@ export default defineComponent({
// make list of variables using variables config list
initializeVariablesData();
// reject all promises
rejectAllPromises();
// load all variables
loadAllVariablesData();
};
@@ -0,0 +1,145 @@
<template>
<div class="relative" style="margin-top: 5px;">
<q-input
v-model="inputValue"
@update:model-value="onModelValueChanged"
dense
filled
:label="label"
style="width: 100%;"
@focus="showOptions = true"
@blur="hideOptions"
v-bind="$attrs"
>
<template v-if="hasSlot('label')" v-slot:label>
<slot name="label"></slot>
</template>
</q-input>
<div
class="options-container"
v-if="showOptions && fieldsFilteredOptions.length > 0"
:style="{
'background-color': store.state.theme === 'dark' ? '#2d2d2d' : 'white',
}"
>
<div
v-for="(option, index) in fieldsFilteredOptions"
:key="index"
class="option"
@mousedown="selectOption(option)"
>
{{ option.label }}
</div>
</div>
</div>
</template>
<script>
import { ref, toRef, defineComponent, watch } from "vue";
import { useSearchInputUsingRegex } from "@/composables/useSearchInputUsingRegex";
import { useStore } from "vuex";
import { useSlots } from "vue";
export default defineComponent({
name: "CommonAutoComplete",
props: {
modelValue: {
type: String,
},
label: {
type: String,
},
items: {
// always expected to be in [ { label: "", value: ""}] format, search in label, and replace the value
type: Array,
},
searchRegex: {
type: String,
},
valueReplaceFn: {
// special treatment needed to any value replacing function, then this can be used
type: Function,
default: (selectedValue) => selectedValue,
},
},
emits: ["update:modelValue"],
setup(props, { emit }) {
const store = useStore();
const showOptions = ref(false);
// this is used to sync with modelvalue and q-input's v-model
const inputValue = ref(props.modelValue);
watch(
() => props.modelValue,
() => {
inputValue.value = props.modelValue;
}
);
// when q-input's model value updated, update the model value which will be synced back to input value
const onModelValueChanged = (value) => {
emit("update:modelValue", value);
fieldsFilterFn(value);
};
// apply filter on label
const { filterFn: fieldsFilterFn, filteredOptions: fieldsFilteredOptions } =
useSearchInputUsingRegex(toRef(props.items), "label", props.searchRegex);
const hideOptions = () => {
showOptions.value = false;
};
// when any item is selected, replace it with the value and hide the options
const selectOption = (option) => {
emit("update:modelValue", props.valueReplaceFn(option?.value));
showOptions.value = false;
};
const slots = useSlots();
const hasSlot = (name) => {
return !!slots[name];
};
return {
showOptions,
fieldsFilterFn,
fieldsFilteredOptions,
hideOptions,
selectOption,
store,
onModelValueChanged,
inputValue,
hasSlot
};
},
});
</script>
<style scoped>
.options-container {
z-index: 10;
position: absolute;
left: 0;
right: 0;
border: 1px solid #ccc;
max-height: 100px;
overflow-y: auto;
top: 42px;
}
.relative {
position: relative;
width: 100%;
}
.option {
padding: 8px;
cursor: pointer;
}
.option:hover {
background-color: #f0f0f0b1;
}
</style>
@@ -497,23 +497,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</template>
</q-input>
<q-input
<CommonAutoComplete
v-if="promqlMode"
:label="t('common.legend')"
v-model="
dashboardPanelData.data.queries[
dashboardPanelData.layout.currentQueryIndex
].config.promql_legend
"
:label="t('common.legend')"
:items="dashboardSelectfieldPromQlList"
searchRegex="(?:{([^}]*)(?:{.*})*$|([a-zA-Z-_]+)$)"
color="input-border"
bg-color="input-bg"
class="q-py-md showLabelOnTop"
class="showLabelOnTop"
stack-label
outlined
filled
dense
label-slot
data-test="dashboard-config-promql-legend"
style="
top: none !important;
margin-top: none !important;
padding-top: 3px !important;
width: auto !important;
"
:value-replace-fn="selectPromQlNameOption"
>
<template v-slot:label>
<div class="row items-center all-pointer-events">
@@ -535,7 +541,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</div>
</div>
</template>
</q-input>
</CommonAutoComplete>
<div class="space"></div>
@@ -735,10 +741,12 @@ import useDashboardPanelData from "@/composables/useDashboardPanel";
import { computed, defineComponent, onBeforeMount } from "vue";
import { useI18n } from "vue-i18n";
import Drilldown from "./Drilldown.vue";
import CommonAutoComplete from "@/components/dashboards/addPanel/CommonAutoComplete.vue";
export default defineComponent({
components: { Drilldown },
setup() {
components: { Drilldown, CommonAutoComplete },
props: ["dashboardPanelData"],
setup(props) {
const { dashboardPanelData, promqlMode } = useDashboardPanelData();
const { t } = useI18n();
@@ -913,7 +921,30 @@ export default defineComponent({
field[value] = key;
}
};
const selectPromQlNameOption = (option: any) => {
const inputValue =
dashboardPanelData.data.queries[
dashboardPanelData.layout.currentQueryIndex
].config.promql_legend;
const openingBraceIndex = inputValue.lastIndexOf("{");
const newValue =
inputValue.slice(0, openingBraceIndex + 1) + option + "}";
return newValue;
};
const dashboardSelectfieldPromQlList = computed(() =>
props.dashboardPanelData.meta.stream.selectedStreamFields.map(
(it: any) => {
return {
label: it.name,
value: it.name,
};
}
)
);
return {
t,
dashboardPanelData,
@@ -927,6 +958,8 @@ export default defineComponent({
setUnit,
handleBlur,
legendWidthValue,
dashboardSelectfieldPromQlList,
selectPromQlNameOption,
};
},
});
@@ -500,9 +500,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@show="(e) => loadFilterItem(filteredItem.column)"
:data-test="`dashboard-filter-item-${filteredItem.column}-menu`"
>
<div>
<div class="q-pa-xs">
<div class="q-gutter-xs">
<div style="height: 100%">
<div class="q-pa-xs" style="height: 100%">
<div class="q-gutter-xs" style="height: 100%">
<q-tabs
v-model="
dashboardPanelData.data.queries[
@@ -535,6 +535,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
].fields.filter[index].type
"
animated
style="height: 100%"
>
<q-tab-panel
data-test="dashboard-filter-condition-panel"
@@ -542,7 +543,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
name="condition"
class="q-pa-none"
>
<div class="flex justify-between">
<div class="flex column" style="height: 220px;">
<q-select
dense
filled
@@ -557,9 +558,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
style="width: 100%"
:rules="[(val) => !!val || 'Required']"
/>
<q-input
dense
filled
<CommonAutoComplete
v-if="
!['Is Null', 'Is Not Null'].includes(
dashboardPanelData.data.queries[
@@ -567,16 +566,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
].fields?.filter[index]?.operator
)
"
:label="t('common.value')"
v-model="
dashboardPanelData.data.queries[
dashboardPanelData.layout.currentQueryIndex
].fields.filter[index].value
"
data-test="dashboard-filter-condition-input"
:label="t('common.value')"
style="width: 100%; margin-top: 5px"
:rules="[(val) => val?.length > 0 || 'Required']"
/>
:items="dashboardVariablesFilterItems"
searchRegex="(?:^|[^$])\$?(\w+)"
:rules="[(val: any) => val?.length > 0 || 'Required']"
></CommonAutoComplete>
</div>
</q-tab-panel>
<q-tab-panel
@@ -699,11 +698,13 @@ import useDashboardPanelData from "../../../composables/useDashboardPanel";
import { getImageURL } from "../../../utils/zincutils";
import SortByBtnGrp from "@/components/dashboards/addPanel/SortByBtnGrp.vue";
import { useQuasar } from "quasar";
import CommonAutoComplete from "@/components/dashboards/addPanel/CommonAutoComplete.vue";
export default defineComponent({
name: "DashboardMapQueryBuilder",
components: { SortByBtnGrp },
setup() {
components: { SortByBtnGrp, CommonAutoComplete },
props: ["dashboardData"],
setup(props) {
const { t } = useI18n();
const $q = useQuasar();
const expansionItems = reactive({
@@ -712,7 +713,6 @@ export default defineComponent({
weight: true,
filter: false,
});
const {
dashboardPanelData,
addLatitude,
@@ -911,6 +911,13 @@ export default defineComponent({
return commonBtnLabel(weightField);
});
const dashboardVariablesFilterItems = computed(() =>
(props.dashboardData?.variables?.list ?? []).map((it: any) => ({
label: it.name,
value: "'" + "$" + it.name + "'",
}))
);
return {
t,
dashboardPanelData,
@@ -937,6 +944,7 @@ export default defineComponent({
promqlMode,
weightLabel,
onFieldDragStart,
dashboardVariablesFilterItems,
options: [
"=",
"<>",
@@ -702,9 +702,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@show="(e) => loadFilterItem(filteredItem.column)"
:data-test="`dashboard-filter-item-${filteredItem.column}-menu`"
>
<div>
<div class="q-pa-xs">
<div class="q-gutter-xs">
<div style="height: 100%">
<div class="q-pa-xs" style="height: 100%">
<div class="q-gutter-xs" style="height: 100%">
<q-tabs
v-model="
dashboardPanelData.data.queries[
@@ -737,6 +737,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
].fields.filter[index].type
"
animated
style="height: 100%"
>
<q-tab-panel
data-test="dashboard-filter-condition-panel"
@@ -744,7 +745,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
name="condition"
class="q-pa-none"
>
<div class="flex justify-between">
<div class="flex column" style="height: 220px;">
<q-select
dense
filled
@@ -759,9 +760,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
style="width: 100%"
:rules="[(val) => !!val || 'Required']"
/>
<q-input
dense
filled
<CommonAutoComplete
v-if="
!['Is Null', 'Is Not Null'].includes(
dashboardPanelData.data.queries[
@@ -769,16 +768,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
].fields?.filter[index]?.operator
)
"
:label="t('common.value')"
v-model="
dashboardPanelData.data.queries[
dashboardPanelData.layout.currentQueryIndex
].fields.filter[index].value
"
data-test="dashboard-filter-condition-input"
:label="t('common.value')"
style="width: 100%; margin-top: 5px"
:rules="[(val) => val?.length > 0 || 'Required']"
/>
:items="dashboardVariablesFilterItems"
searchRegex="(?:^|[^$])\$?(\w+)"
:rules="[(val: any) => val?.length > 0 || 'Required']"
></CommonAutoComplete>
</div>
</q-tab-panel>
<q-tab-panel
@@ -892,8 +891,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div></div>
</div>
</div>
<DashboardMapQueryBuilder />
<DashboardSankeyChartBuilder />
<DashboardMapQueryBuilder :dashboardData="dashboardData" />
<DashboardSankeyChartBuilder :dashboardData="dashboardData" />
</template>
<script lang="ts">
@@ -906,6 +905,7 @@ import DashboardSankeyChartBuilder from "./DashboardSankeyChartBuilder.vue";
import SortByBtnGrp from "@/components/dashboards/addPanel/SortByBtnGrp.vue";
import HistogramIntervalDropDown from "@/components/dashboards/addPanel/HistogramIntervalDropDown.vue";
import { useQuasar } from "quasar";
import CommonAutoComplete from "@/components/dashboards/addPanel/CommonAutoComplete.vue";
export default defineComponent({
name: "DashboardQueryBuilder",
@@ -913,9 +913,11 @@ export default defineComponent({
DashboardMapQueryBuilder,
SortByBtnGrp,
HistogramIntervalDropDown,
DashboardSankeyChartBuilder
DashboardSankeyChartBuilder,
CommonAutoComplete,
},
setup() {
props: ["dashboardData"],
setup(props) {
const showXAxis = ref(true);
const panelName = ref("");
const panelDesc = ref("");
@@ -928,7 +930,6 @@ export default defineComponent({
config: true,
filter: false,
});
const {
dashboardPanelData,
addXAxisItem,
@@ -1312,6 +1313,13 @@ export default defineComponent({
return zFields.map(commonBtnLabel);
});
const dashboardVariablesFilterItems = computed(() =>
(props.dashboardData?.variables?.list ?? []).map((it: any) => ({
label: it.name,
value: "'" + "$" + it.name + "'",
}))
);
return {
showXAxis,
t,
@@ -1358,6 +1366,7 @@ export default defineComponent({
onFieldDragStart,
getHistoramIntervalField,
onDragEnd,
dashboardVariablesFilterItems,
};
},
});
@@ -500,9 +500,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@show="(e) => loadFilterItem(filteredItem.column)"
:data-test="`dashboard-filter-item-${filteredItem.column}-menu`"
>
<div>
<div class="q-pa-xs">
<div class="q-gutter-xs">
<div style="height: 100%">
<div class="q-pa-xs" style="height: 100%">
<div class="q-gutter-xs" style="height: 100%">
<q-tabs
v-model="
dashboardPanelData.data.queries[
@@ -535,6 +535,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
].fields.filter[index].type
"
animated
style="height: 100%"
>
<q-tab-panel
data-test="dashboard-filter-condition-panel"
@@ -542,7 +543,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
name="condition"
class="q-pa-none"
>
<div class="flex justify-between">
<div class="flex column" style="height: 220px">
<q-select
dense
filled
@@ -557,9 +558,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
style="width: 100%"
:rules="[(val) => !!val || 'Required']"
/>
<q-input
dense
filled
<CommonAutoComplete
v-if="
!['Is Null', 'Is Not Null'].includes(
dashboardPanelData.data.queries[
@@ -567,16 +566,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
].fields?.filter[index]?.operator
)
"
:label="t('common.value')"
v-model="
dashboardPanelData.data.queries[
dashboardPanelData.layout.currentQueryIndex
].fields.filter[index].value
"
data-test="dashboard-filter-condition-input"
:label="t('common.value')"
style="width: 100%; margin-top: 5px"
:rules="[(val) => val?.length > 0 || 'Required']"
/>
:items="dashboardVariablesFilterItems"
searchRegex="(?:^|[^$])\$?(\w+)"
:rules="[(val: any) => val?.length > 0 || 'Required']"
></CommonAutoComplete>
</div>
</q-tab-panel>
<q-tab-panel
@@ -699,11 +698,13 @@ import useDashboardPanelData from "../../../composables/useDashboardPanel";
import { getImageURL } from "../../../utils/zincutils";
import SortByBtnGrp from "@/components/dashboards/addPanel/SortByBtnGrp.vue";
import { useQuasar } from "quasar";
import CommonAutoComplete from "@/components/dashboards/addPanel/CommonAutoComplete.vue";
export default defineComponent({
name: "DashboardSankeyChartBuilder",
components: { SortByBtnGrp },
setup() {
components: { SortByBtnGrp, CommonAutoComplete },
props: ["dashboardData"],
setup(props) {
const { t } = useI18n();
const $q = useQuasar();
const expansionItems = reactive({
@@ -712,7 +713,6 @@ export default defineComponent({
value: true,
filter: false,
});
const {
dashboardPanelData,
addSource,
@@ -902,6 +902,13 @@ export default defineComponent({
return commonBtnLabel(valueField);
});
const dashboardVariablesFilterItems = computed(() =>
(props.dashboardData?.variables?.list ?? []).map((it: any) => ({
label: it.name,
value: "'" + "$" + it.name + "'",
}))
);
return {
t,
dashboardPanelData,
@@ -927,6 +934,7 @@ export default defineComponent({
promqlMode,
valueLabel,
onFieldDragStart,
dashboardVariablesFilterItems,
options: [
"=",
"<>",
@@ -213,25 +213,28 @@
v-for="(variable, index) in drilldownData.data.variables"
:key="index"
>
<div style="display: flex; gap: 10px; margin-bottom: 10px">
<q-input
v-model="variable.name"
<div
style="display: flex; gap: 10px; margin-bottom: 10px"
:key="variableNamesFn?.toString()"
>
<CommonAutoComplete
placeholder="Name"
stack-label
outlined
filled
dense
:data-test="`dashboard-drilldown-variable-name-${index}`"
/>
<q-input
v-model="variable.value"
v-model="variable.name"
searchRegex="(.*)"
:items="variableNamesFn"
style="width: auto !important; padding-top: 3px !important"
></CommonAutoComplete>
<CommonAutoComplete
placeholder="Value"
stack-label
outlined
filled
dense
:data-test="`dashboard-drilldown-variable-value-${index}`"
/>
searchRegex="(.*)"
v-model="variable.value"
:items="options.selectedValue"
style="
width: auto !important;
padding-top: 3px !important;
"
></CommonAutoComplete>
<q-icon
class="q-mr-xs"
size="20px"
@@ -291,7 +294,7 @@
</template>
<script lang="ts">
import { ref } from "vue";
import { reactive, ref, toRef } from "vue";
import { defineComponent } from "vue";
import { useI18n } from "vue-i18n";
import {
@@ -305,14 +308,16 @@ import {
getAllDashboardsByFolderId,
getFoldersList,
} from "../../../utils/commons";
import { onMounted } from "vue";
import { onMounted, onUnmounted } from "vue";
import useDashboardPanelData from "../../../composables/useDashboardPanel";
import DrilldownUserGuide from "@/components/dashboards/addPanel/DrilldownUserGuide.vue";
import CommonAutoComplete from "@/components/dashboards/addPanel/CommonAutoComplete.vue";
export default defineComponent({
name: "DrilldownPopUp",
components: {
DrilldownUserGuide,
CommonAutoComplete,
},
props: {
isEditMode: {
@@ -329,6 +334,7 @@ export default defineComponent({
const { t } = useI18n();
const store = useStore();
const { dashboardPanelData } = useDashboardPanelData();
const getDefaultDrilldownData = () => ({
name: "",
type: "byDashboard",
@@ -542,6 +548,80 @@ export default defineComponent({
drilldownData.value.type = type;
};
const options: any = reactive({
selectedValue: [],
selectedName: [],
});
//want label for dropdown in input and value for its input value
const selectedValue = computed(() => {
let selectedValues: any = [];
if (dashboardPanelData.data.type === "sankey") {
selectedValues = [
{ label: "Edge Source", value: "${edge.__source}" },
{ label: "Edge Target", value: "${edge.__target}" },
{ label: "Edge Value", value: "${edge.__value}" },
{ label: "Node Name", value: "${node.__name}" },
{ label: "Node Value", value: "${node.__value}" },
];
} else if (dashboardPanelData.data.type === "table") {
dashboardPanelData.data.queries.forEach((query: any) => {
const panelFields = [
...query.fields.x,
...query.fields.y,
...query.fields.z,
];
panelFields.forEach((field) => {
selectedValues.push({
label: field.label,
value: '${row.field["' + field.label + '"]}',
});
});
});
} else {
selectedValues = [
{ label: "Series Name", value: "${series.__name}" },
{ label: "Series Value", value: "${series.__value}" },
];
}
return selectedValues;
});
// Assign selectedValue to options object
options.selectedValue = selectedValue;
const variableNamesFn = ref([]);
watch(drilldownData.value, async (newData) => {
if (newData.data.folder && newData.data.dashboard) {
const folder = store.state.organizationData.folders.find(
(folder: any) => folder.name === newData.data.folder
);
const allDashboardData = await getAllDashboardsByFolderId(
store,
folder.folderId
);
const dashboardData = allDashboardData.find(
(dashboard: any) => dashboard.title === newData.data.dashboard
);
if (dashboardData) {
const optionsList = dashboardData.variables.list.map(
(variable: any) => ({
label: variable.name,
value: variable.name,
})
);
variableNamesFn.value = optionsList;
} else {
variableNamesFn.value = [];
}
} else {
variableNamesFn.value = [];
}
});
return {
t,
outlinedDashboard,
@@ -556,6 +636,8 @@ export default defineComponent({
saveDrilldown,
isFormURLValid,
changeTypeOfDrilldown,
options,
variableNamesFn,
};
},
});
@@ -42,10 +42,10 @@
<p>You can reference a variable with the following format:</p>
<ul>
<li>
<span class="bg-highlight">${var-variable_name}</span>
<span class="bg-highlight">${variable_name}</span>
<br />
(For Example, if your variable name is "test", you can use
<span class="bg-highlight">${var-test}</span>)
<span class="bg-highlight">${test}</span>)
</li>
</ul>
@@ -224,17 +224,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
:rules="[(val: any) => !!(val.trim()) || 'Field is required!']"
:options="['=', '!=']"
/>
<q-input
<CommonAutoComplete
v-model="filter.value"
placeholder="Enter Value"
dense
filled
:items="dashboardVariablesFilterItems"
searchRegex="(?:^|[^$])\$?(\w+)"
:rules="[(val: any) => val?.length > 0 || 'Required']"
debounce="1000"
style="width: 125px"
class=""
data-test="dashboard-query-values-filter-value"
:rules="[(val: any) => !!(val.trim()) || 'Field is required!']"
/>
style="
margin-top: none !important;
width: auto !important;
"
placeholder="Enter Value"
></CommonAutoComplete>
<q-btn
size="sm"
padding="12px 5px"
@@ -378,6 +379,7 @@ import {
toRef,
toRaw,
type Ref,
computed,
} from "vue";
import { useI18n } from "vue-i18n";
import { useSelectAutoComplete } from "../../../composables/useSelectAutocomplete";
@@ -396,11 +398,12 @@ import {
buildVariablesDependencyGraph,
isGraphHasCycle,
} from "@/utils/dashboard/variables/variablesDependencyUtils";
import CommonAutoComplete from "@/components/dashboards/addPanel/CommonAutoComplete.vue";
export default defineComponent({
name: "AddSettingVariable",
props: ["variableName"],
components: { DashboardHeader },
props: ["variableName", "dashboardVariablesList"],
components: { DashboardHeader, CommonAutoComplete },
emits: ["close", "save"],
setup(props, { emit }) {
const $q = useQuasar();
@@ -772,6 +775,14 @@ export default defineComponent({
emit("close");
};
const dashboardVariablesFilterItems = computed(() =>
props.dashboardVariablesList
.map((it: any) => ({
label: it.name,
value: "$" + it.name,
}))
.filter((it: any) => it.label !== variableData.name)
);
return {
variableData,
store,
@@ -797,6 +808,7 @@ export default defineComponent({
removeFilter,
filterUpdated,
filterCycleError,
dashboardVariablesFilterItems,
};
},
});
@@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@save="handleSaveVariable"
:variableName="selectedVariable"
@close="goBackToDashboardList"
:dashboardVariablesList="dashboardVariablesList"
/>
</div>
<div v-else class="column full-height">
@@ -0,0 +1,45 @@
import { ref, watch, type Ref } from "vue";
export const useSearchInputUsingRegex = (
options: Ref<any>,
searchKey: string,
searchRegex: string
) => {
const filteredOptions = ref(options.value);
watch(options, (newValue) => {
filteredOptions.value = newValue;
});
const filterFn = (val: any) => {
if (val === "") {
filteredOptions.value = options.value;
return;
}
const regex = new RegExp(searchRegex, "gi");
let match = regex.exec(val)
if(!match) {
filteredOptions.value = [];
return;
}
let needle: any = null;
for (let i = 1; i < match.length; i++) {
if (match[i] !== undefined) {
needle = match[i];
break;
}
}
filteredOptions.value = options.value?.filter((option: any) => {
const value =
typeof option === "object" ? option[searchKey] : option.toString();
const lowerCaseValue = value.toLowerCase();
return lowerCaseValue.includes(needle);
});
};
return { filteredOptions, filterFn };
};
@@ -446,9 +446,9 @@ export default defineComponent({
// NOTE: after variables in variables feature, it works without changing the initial variable values
// then, update the initial variable values
// await variablesValueSelectorRef.value.changeInitialVariableValues(
// ...args
// );
await variablesValueSelectorRef.value.changeInitialVariableValues(
...args
);
};
return {
@@ -173,7 +173,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
class="layout-panel-container col"
style="height: 100%"
>
<DashboardQueryBuilder />
<DashboardQueryBuilder :dashboardData="currentDashboardData.data"/>
<q-separator />
<VariablesValueSelector
:variablesConfig="currentDashboardData.data?.variables"
@@ -252,7 +252,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
:title="t('dashboard.configLabel')"
v-model="dashboardPanelData.layout.isConfigPanelOpen"
>
<ConfigPanel />
<ConfigPanel :dashboardPanelData="dashboardPanelData" />
</PanelSidebar>
</div>
</div>