mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-06 00:09:22 +00:00
feat: dashboard query editor vertical scroll (#7453)
### **PR Type** Enhancement ___ ### **Description** - Enable dashboard query bar by default - Refactor AddPanel layout with scrollable containers - Simplify overflow styles; remove outdated splitters - Adjust component height calculations ___ ### **Changes walkthrough** 📝 <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table> <tr> <td> <details> <summary><strong>DashboardQueryEditor.vue</strong><dd><code>Simplify query editor bar styling</code> </dd></summary> <hr> web/src/components/dashboards/addPanel/DashboardQueryEditor.vue <li>Removed query bar toggle icon wrapper<br> <li> Commented out cursor pointer on <code>.sql-bar</code> </details> </td> <td><a href="https://github.com/openobserve/openobserve/pull/7453/files#diff-68bf1b319223d103f1b99e0b681764e4eb76942399397779c81c2cd18f6485ff">+1/-14</a> </td> </tr> <tr> <td> <details> <summary><strong>AddPanel.vue</strong><dd><code>Refactor AddPanel layout and scrolling</code> </dd></summary> <hr> web/src/views/Dashboards/addPanel/AddPanel.vue <li>Replaced nested <code>q-splitter</code> with scrollable <code>div</code> wrappers<br> <li> Moved <code>DashboardQueryBuilder</code> and <code>VariablesValueSelector</code><br> <li> Simplified outdated chart notification styling<br> <li> Updated wrappers heights for renderer and editor </details> </td> <td><a href="https://github.com/openobserve/openobserve/pull/7453/files#diff-c9632db1ad95af95aba10161bcbc7c5608318919f228637bdafae3f3a31267e8">+143/-215</a></td> </tr> </table></td></tr><tr><td><strong>Configuration changes</strong></td><td><table> <tr> <td> <details> <summary><strong>useDashboardPanel.ts</strong><dd><code>Enable query bar by default</code> </dd></summary> <hr> web/src/composables/useDashboardPanel.ts - Set default `showQueryBar` to `true` </details> </td> <td><a href="https://github.com/openobserve/openobserve/pull/7453/files#diff-fbba1700750053b9eaf38ddd30dab84531bc44131c795ebb713811e4930cd7cb">+1/-1</a> </td> </tr> </table></td></tr></tr></tbody></table> ___ > <details> <summary> Need help?</summary><li>Type <code>/help how to ...</code> in the comments thread for any questions about PR-Agent usage.</li><li>Check out the <a href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a> for more information.</li></details> --------- Co-authored-by: ktx-akshay <akshay.patil@kiara.tech>
This commit is contained in:
co-authored by
ktx-akshay
parent
f8b2bd0061
commit
0253616aa5
@@ -2,11 +2,10 @@ import { test, expect } from "../baseFixtures";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import logsdata from "../../../test-data/logs_data.json";
|
||||
import { DashboardPage } from '../../pages/dashboardPage';
|
||||
import { DashboardPage } from "../../pages/dashboardPage";
|
||||
|
||||
// Function to handle login
|
||||
async function login(page) {
|
||||
|
||||
await page.goto(process.env["ZO_BASE_URL"]);
|
||||
if (await page.getByText("Login as internal user").isVisible()) {
|
||||
await page.getByText("Login as internal user").click();
|
||||
@@ -14,8 +13,12 @@ async function login(page) {
|
||||
console.log("ZO_BASE_URL", process.env["ZO_BASE_URL"]);
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.locator('[data-cy="login-user-id"]').fill(process.env["ZO_ROOT_USER_EMAIL"]);
|
||||
await page.locator('[data-cy="login-password"]').fill(process.env["ZO_ROOT_USER_PASSWORD"]);
|
||||
await page
|
||||
.locator('[data-cy="login-user-id"]')
|
||||
.fill(process.env["ZO_ROOT_USER_EMAIL"]);
|
||||
await page
|
||||
.locator('[data-cy="login-password"]')
|
||||
.fill(process.env["ZO_ROOT_USER_PASSWORD"]);
|
||||
await page.locator('[data-cy="login-sign-in"]').click();
|
||||
await page.waitForTimeout(4000);
|
||||
await page.goto(process.env["ZO_BASE_URL"]);
|
||||
@@ -29,23 +32,29 @@ async function ingestion(page) {
|
||||
).toString("base64");
|
||||
|
||||
const headers = {
|
||||
"Authorization": `Basic ${basicAuthCredentials}`,
|
||||
Authorization: `Basic ${basicAuthCredentials}`,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const response = await page.evaluate(async ({ url, headers, orgId, streamName, logsdata }) => {
|
||||
const fetchResponse = await fetch(`${url}/api/${orgId}/${streamName}/_json`, {
|
||||
method: "POST",
|
||||
const response = await page.evaluate(
|
||||
async ({ url, headers, orgId, streamName, logsdata }) => {
|
||||
const fetchResponse = await fetch(
|
||||
`${url}/api/${orgId}/${streamName}/_json`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(logsdata),
|
||||
}
|
||||
);
|
||||
return await fetchResponse.json();
|
||||
},
|
||||
{
|
||||
url: process.env.INGESTION_URL,
|
||||
headers: headers,
|
||||
body: JSON.stringify(logsdata)
|
||||
});
|
||||
return await fetchResponse.json();
|
||||
}, {
|
||||
url: process.env.INGESTION_URL,
|
||||
headers: headers,
|
||||
orgId: orgId,
|
||||
streamName: streamName,
|
||||
logsdata: logsdata
|
||||
});
|
||||
orgId: orgId,
|
||||
streamName: streamName,
|
||||
logsdata: logsdata,
|
||||
}
|
||||
);
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
@@ -59,27 +68,23 @@ function readJsonFile(filename) {
|
||||
return fs.readFileSync(filePath, "utf8");
|
||||
}
|
||||
|
||||
test.describe("Sanity Tests", () => { let dashboardPage
|
||||
test.describe("Sanity Tests", () => {
|
||||
let dashboardPage;
|
||||
let pictorialJSON, lineJSON;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
|
||||
dashboardPage = new DashboardPage(page);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeAll(() => {
|
||||
|
||||
const jsonString = readJsonFile("pictorial.json");
|
||||
pictorialJSON = jsonString
|
||||
pictorialJSON = jsonString;
|
||||
lineJSON = readJsonFile("line.json");
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
|
||||
await login(page);
|
||||
|
||||
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await ingestion(page);
|
||||
});
|
||||
@@ -90,38 +95,43 @@ test.describe("Sanity Tests", () => { let dashboardPage
|
||||
return;
|
||||
}
|
||||
await dashboardPage.addCustomChart();
|
||||
// Type the content with raw modifier to bypass autocomplete
|
||||
await page.keyboard.insertText(pictorialJSON);
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="dashboard-panel-error-bar-icon"]').click();
|
||||
await page.locator('[data-test="dashboard-panel-query-editor"]').getByRole("textbox").fill('select * from "e2e_automate"');
|
||||
await page.waitForTimeout(2000);
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
await expect(page.getByText("Unsafe code detected: Access to 'document' is not allowed")).toBeVisible();
|
||||
// Type the content with raw modifier to bypass autocomplete
|
||||
await page.keyboard.insertText(pictorialJSON);
|
||||
|
||||
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
// await page.locator('[data-test="dashboard-panel-error-bar-icon"]').click();
|
||||
await page
|
||||
.locator('[data-test="dashboard-panel-query-editor"]')
|
||||
.getByRole("textbox")
|
||||
.fill('select * from "e2e_automate"');
|
||||
await page.waitForTimeout(2000);
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Unsafe code detected: Access to 'document' is not allowed"
|
||||
)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("Add line JSON in Monaco Editor", async ({ page }) => {
|
||||
test("Add line JSON in Monaco Editor", async ({ page }) => {
|
||||
if (!lineJSON) {
|
||||
console.error("Skipping test: pictorial.json not found");
|
||||
return;
|
||||
}
|
||||
await dashboardPage.addCustomChart();
|
||||
// Type the content with raw modifier to bypass autocomplete
|
||||
await page.keyboard.insertText(lineJSON);
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="dashboard-panel-error-bar-icon"]').click();
|
||||
await page.locator('[data-test="dashboard-panel-query-editor"]').getByRole("textbox").fill('select * from "e2e_automate"');
|
||||
await page.waitForTimeout(3000);
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
// await expect(page.getByText("Unsafe code detected: Access to 'document' is not allowed")).toBeVisible();
|
||||
|
||||
|
||||
});
|
||||
// Type the content with raw modifier to bypass autocomplete
|
||||
await page.keyboard.insertText(lineJSON);
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
// await page.locator('[data-test="dashboard-panel-error-bar-icon"]').click();
|
||||
await page
|
||||
.locator('[data-test="dashboard-panel-query-editor"]')
|
||||
.getByRole("textbox")
|
||||
.fill('select * from "e2e_automate"');
|
||||
await page.waitForTimeout(3000);
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
// await expect(page.getByText("Unsafe code detected: Access to 'document' is not allowed")).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -347,7 +347,7 @@ test.describe("dashboard filter testcases", () => {
|
||||
await page.getByLabel("Value").fill("$variablename");
|
||||
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.getByText("arrow_rightQueryAutoPromQLCustom SQL").click();
|
||||
// await page.getByText("arrow_rightQueryAutoPromQLCustom SQL").click();
|
||||
await expect(page.getByText("'$variablename'").first()).toBeVisible();
|
||||
await page
|
||||
.locator('[data-test="dashboard-panel-data-view-query-inspector-btn"]')
|
||||
@@ -596,7 +596,7 @@ test.describe("dashboard filter testcases", () => {
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.getByText("arrow_rightQueryAutoPromQLCustom SQL").click();
|
||||
// await page.getByText("arrow_rightQueryAutoPromQLCustom SQL").click();
|
||||
await expect(page.getByText("'$variablename'").first()).toBeVisible();
|
||||
await page
|
||||
.locator('[data-test="dashboard-panel-data-view-query-inspector-btn"]')
|
||||
|
||||
@@ -515,7 +515,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
await page.getByRole("button", { name: "9" }).last().click();
|
||||
await page.getByRole("button", { name: "16" }).last().click();
|
||||
await page.locator('[data-test="chart-renderer"] div').click();
|
||||
// await page.locator('[data-test="chart-renderer"] div').click();
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
|
||||
await page.reload();
|
||||
|
||||
@@ -25,19 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
style="display: flex; flex-direction: row; align-items: center"
|
||||
data-test="dashboard-query-data"
|
||||
>
|
||||
<div>
|
||||
<q-icon
|
||||
flat
|
||||
:name="
|
||||
!dashboardPanelData.layout.showQueryBar
|
||||
? 'arrow_right'
|
||||
: 'arrow_drop_down'
|
||||
"
|
||||
text-color="black"
|
||||
class="q-mr-sm"
|
||||
data-test="dashboard-panel-error-bar-icon"
|
||||
/>
|
||||
</div>
|
||||
<q-space />
|
||||
<div style="max-width: 600px">
|
||||
<q-tabs
|
||||
@@ -602,7 +589,7 @@ export default defineComponent({
|
||||
.sql-bar {
|
||||
height: 40px !important;
|
||||
// overflow: hidden;
|
||||
cursor: pointer;
|
||||
// cursor: pointer;
|
||||
}
|
||||
|
||||
.dashboard-query-remove-icon:hover {
|
||||
|
||||
@@ -157,7 +157,7 @@ const getDefaultDashboardPanelData: any = (store: any) => ({
|
||||
layout: {
|
||||
splitter: 20,
|
||||
querySplitter: 41,
|
||||
showQueryBar: false,
|
||||
showQueryBar: true,
|
||||
isConfigPanelOpen: false,
|
||||
currentQueryIndex: 0,
|
||||
vrlFunctionToggle: false,
|
||||
|
||||
@@ -180,138 +180,99 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/>
|
||||
</template>
|
||||
<template #after>
|
||||
<div
|
||||
class="row"
|
||||
style="height: calc(100vh - 99px); overflow-y: auto"
|
||||
>
|
||||
<div class="col" style="height: 100%">
|
||||
<q-splitter
|
||||
class="query-editor-splitter"
|
||||
v-model="dashboardPanelData.layout.querySplitter"
|
||||
horizontal
|
||||
@update:model-value="querySplitterUpdated"
|
||||
reverse
|
||||
unit="px"
|
||||
:limits="
|
||||
!dashboardPanelData.layout.showQueryBar
|
||||
? [43, 400]
|
||||
: [140, 400]
|
||||
"
|
||||
:disable="!dashboardPanelData.layout.showQueryBar"
|
||||
style="height: 100%"
|
||||
>
|
||||
<template #before>
|
||||
<div
|
||||
class="layout-panel-container col"
|
||||
style="height: 100%"
|
||||
>
|
||||
<DashboardQueryBuilder
|
||||
:dashboardData="currentDashboardData.data"
|
||||
/>
|
||||
<q-separator />
|
||||
<VariablesValueSelector
|
||||
v-if="dateTimeForVariables ||
|
||||
(dashboardPanelData.meta.dateTime
|
||||
&& dashboardPanelData.meta.dateTime.start_time
|
||||
&& dashboardPanelData.meta.dateTime.end_time)"
|
||||
:variablesConfig="currentDashboardData.data?.variables"
|
||||
:showDynamicFilters="
|
||||
currentDashboardData.data?.variables
|
||||
?.showDynamicFilters
|
||||
"
|
||||
:selectedTimeDate="
|
||||
dateTimeForVariables ||
|
||||
dashboardPanelData.meta.dateTime
|
||||
"
|
||||
@variablesData="variablesDataUpdated"
|
||||
:initialVariableValues="initialVariableValues"
|
||||
/>
|
||||
<div class="row">
|
||||
<div
|
||||
class="col scroll"
|
||||
style="height: calc(100vh - 99px); overflow-y: auto"
|
||||
>
|
||||
<div class="layout-panel-container col">
|
||||
<DashboardQueryBuilder
|
||||
:dashboardData="currentDashboardData.data"
|
||||
/>
|
||||
<q-separator />
|
||||
<VariablesValueSelector
|
||||
v-if="
|
||||
dateTimeForVariables ||
|
||||
(dashboardPanelData.meta.dateTime &&
|
||||
dashboardPanelData.meta.dateTime.start_time &&
|
||||
dashboardPanelData.meta.dateTime.end_time)
|
||||
"
|
||||
:variablesConfig="currentDashboardData.data?.variables"
|
||||
:showDynamicFilters="
|
||||
currentDashboardData.data?.variables?.showDynamicFilters
|
||||
"
|
||||
:selectedTimeDate="
|
||||
dateTimeForVariables || dashboardPanelData.meta.dateTime
|
||||
"
|
||||
@variablesData="variablesDataUpdated"
|
||||
:initialVariableValues="initialVariableValues"
|
||||
/>
|
||||
|
||||
<div v-if="isOutDated" class="tw-p-2">
|
||||
<div
|
||||
:style="{
|
||||
borderColor: '#c3920d',
|
||||
borderWidth: '1px',
|
||||
borderStyle: 'solid',
|
||||
backgroundColor:
|
||||
store.state.theme == 'dark'
|
||||
? '#2a1f03'
|
||||
: '#faf2da',
|
||||
padding: '1%',
|
||||
borderRadius: '5px',
|
||||
}"
|
||||
>
|
||||
<div style="font-weight: 700">
|
||||
Your chart is not up to date
|
||||
</div>
|
||||
<div>
|
||||
Chart Configuration / Variables has been updated,
|
||||
but the chart was not updated automatically. Click
|
||||
on the "Apply" button to run the query again
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-flex tw-justify-end tw-mr-2">
|
||||
<span v-if="lastTriggeredAt" class="lastRefreshedAt">
|
||||
<span class="lastRefreshedAtIcon">🕑</span
|
||||
><RelativeTime
|
||||
:timestamp="lastTriggeredAt"
|
||||
fullTimePrefix="Last Refreshed At: "
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col" style="flex: 1">
|
||||
<PanelSchemaRenderer
|
||||
v-if="chartData"
|
||||
@metadata-update="metaDataValue"
|
||||
:key="dashboardPanelData.data.type"
|
||||
:panelSchema="chartData"
|
||||
:dashboard-id="queryParams?.dashboard"
|
||||
:folder-id="queryParams?.folder"
|
||||
:selectedTimeObj="dashboardPanelData.meta.dateTime"
|
||||
:variablesData="updatedVariablesData"
|
||||
:allowAnnotationsAdd="editMode"
|
||||
:width="6"
|
||||
@error="handleChartApiError"
|
||||
@updated:data-zoom="onDataZoom"
|
||||
@updated:vrlFunctionFieldList="
|
||||
updateVrlFunctionFieldList
|
||||
"
|
||||
@last-triggered-at-update="
|
||||
handleLastTriggeredAtUpdate
|
||||
"
|
||||
searchType="dashboards"
|
||||
/>
|
||||
<q-dialog v-model="showViewPanel">
|
||||
<QueryInspector
|
||||
:metaData="metaData"
|
||||
:data="panelTitle"
|
||||
></QueryInspector>
|
||||
</q-dialog>
|
||||
</div>
|
||||
<DashboardErrorsComponent
|
||||
:errors="errorData"
|
||||
class="col-auto"
|
||||
style="flex-shrink: 0"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #separator>
|
||||
<div v-if="isOutDated" class="tw-p-2">
|
||||
<div
|
||||
class="splitter"
|
||||
:class="
|
||||
dashboardPanelData.layout.showQueryBar
|
||||
? 'splitter-enabled'
|
||||
: ''
|
||||
"
|
||||
></div>
|
||||
</template>
|
||||
<template #after>
|
||||
<div style="height: 100%; width: 100%" class="row column">
|
||||
<DashboardQueryEditor />
|
||||
:style="{
|
||||
borderColor: '#c3920d',
|
||||
borderWidth: '1px',
|
||||
borderStyle: 'solid',
|
||||
backgroundColor:
|
||||
store.state.theme == 'dark' ? '#2a1f03' : '#faf2da',
|
||||
padding: '1%',
|
||||
borderRadius: '5px',
|
||||
}"
|
||||
>
|
||||
<div style="font-weight: 700">
|
||||
Your chart is not up to date
|
||||
</div>
|
||||
<div>
|
||||
Chart Configuration / Variables has been updated, but
|
||||
the chart was not updated automatically. Click on the
|
||||
"Apply" button to run the query again
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</q-splitter>
|
||||
</div>
|
||||
<div class="tw-flex tw-justify-end tw-mr-2">
|
||||
<span v-if="lastTriggeredAt" class="lastRefreshedAt">
|
||||
<span class="lastRefreshedAtIcon">🕑</span
|
||||
><RelativeTime
|
||||
:timestamp="lastTriggeredAt"
|
||||
fullTimePrefix="Last Refreshed At: "
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tw-h-[calc(100vh-500px)]">
|
||||
<PanelSchemaRenderer
|
||||
v-if="chartData"
|
||||
@metadata-update="metaDataValue"
|
||||
:key="dashboardPanelData.data.type"
|
||||
:panelSchema="chartData"
|
||||
:dashboard-id="queryParams?.dashboard"
|
||||
:folder-id="queryParams?.folder"
|
||||
:selectedTimeObj="dashboardPanelData.meta.dateTime"
|
||||
:variablesData="updatedVariablesData"
|
||||
:allowAnnotationsAdd="editMode"
|
||||
:width="6"
|
||||
@error="handleChartApiError"
|
||||
@updated:data-zoom="onDataZoom"
|
||||
@updated:vrlFunctionFieldList="updateVrlFunctionFieldList"
|
||||
@last-triggered-at-update="handleLastTriggeredAtUpdate"
|
||||
searchType="dashboards"
|
||||
/>
|
||||
<q-dialog v-model="showViewPanel">
|
||||
<QueryInspector
|
||||
:metaData="metaData"
|
||||
:data="panelTitle"
|
||||
></QueryInspector>
|
||||
</q-dialog>
|
||||
</div>
|
||||
<DashboardErrorsComponent
|
||||
:errors="errorData"
|
||||
class="col-auto"
|
||||
style="flex-shrink: 0"
|
||||
/>
|
||||
</div>
|
||||
<div class="row column tw-h-[calc(100vh-180px)]">
|
||||
<DashboardQueryEditor />
|
||||
</div>
|
||||
</div>
|
||||
<q-separator vertical />
|
||||
<div class="col-auto">
|
||||
@@ -432,96 +393,63 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
class="row"
|
||||
style="height: calc(100vh - 99px); overflow-y: auto"
|
||||
>
|
||||
<div class="col" style="height: 100%">
|
||||
<q-splitter
|
||||
class="query-editor-splitter"
|
||||
v-model="dashboardPanelData.layout.querySplitter"
|
||||
horizontal
|
||||
@update:model-value="querySplitterUpdated"
|
||||
reverse
|
||||
unit="px"
|
||||
:limits="
|
||||
!dashboardPanelData.layout.showQueryBar
|
||||
? [43, 400]
|
||||
: [140, 400]
|
||||
"
|
||||
:disable="!dashboardPanelData.layout.showQueryBar"
|
||||
style="height: 100%"
|
||||
<div class="col scroll" style="height: 100%">
|
||||
<div
|
||||
class="layout-panel-container tw-h-[calc(100vh-200px)] col"
|
||||
>
|
||||
<template #before>
|
||||
<div
|
||||
class="layout-panel-container col"
|
||||
style="height: 100%"
|
||||
>
|
||||
<q-splitter
|
||||
class="query-editor-splitter"
|
||||
v-model="splitterModel"
|
||||
style="height: 100%"
|
||||
@update:model-value="layoutSplitterUpdated"
|
||||
>
|
||||
<template #before>
|
||||
<CustomChartEditor
|
||||
v-model="dashboardPanelData.data.customChartContent"
|
||||
style="width: 100%; height: 100%"
|
||||
/>
|
||||
</template>
|
||||
<template #separator>
|
||||
<div class="splitter-vertical splitter-enabled"></div>
|
||||
<q-avatar
|
||||
color="primary"
|
||||
text-color="white"
|
||||
size="20px"
|
||||
icon="drag_indicator"
|
||||
style="top: 10px; left: 3.5px"
|
||||
data-test="dashboard-markdown-editor-drag-indicator"
|
||||
/>
|
||||
</template>
|
||||
<template #after>
|
||||
<PanelSchemaRenderer
|
||||
v-if="chartData"
|
||||
@metadata-update="metaDataValue"
|
||||
:key="dashboardPanelData.data.type"
|
||||
:panelSchema="chartData"
|
||||
:dashboard-id="queryParams?.dashboard"
|
||||
:folder-id="queryParams?.folder"
|
||||
:selectedTimeObj="dashboardPanelData.meta.dateTime"
|
||||
:variablesData="updatedVariablesData"
|
||||
:width="6"
|
||||
@error="handleChartApiError"
|
||||
@updated:data-zoom="onDataZoom"
|
||||
@updated:vrlFunctionFieldList="
|
||||
updateVrlFunctionFieldList
|
||||
"
|
||||
@last-triggered-at-update="
|
||||
handleLastTriggeredAtUpdate
|
||||
"
|
||||
searchType="dashboards"
|
||||
/>
|
||||
</template>
|
||||
</q-splitter>
|
||||
<DashboardErrorsComponent
|
||||
:errors="errorData"
|
||||
class="col-auto"
|
||||
style="flex-shrink: 0"
|
||||
<q-splitter
|
||||
class="query-editor-splitter"
|
||||
v-model="splitterModel"
|
||||
style="height: 100%"
|
||||
@update:model-value="layoutSplitterUpdated"
|
||||
>
|
||||
<template #before>
|
||||
<CustomChartEditor
|
||||
v-model="dashboardPanelData.data.customChartContent"
|
||||
style="width: 100%; height: 100%"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #separator>
|
||||
<div
|
||||
class="splitter"
|
||||
:class="
|
||||
dashboardPanelData.layout.showQueryBar
|
||||
? 'splitter-enabled'
|
||||
: ''
|
||||
"
|
||||
></div>
|
||||
</template>
|
||||
<template #after>
|
||||
<div style="height: 100%; width: 100%" class="row column">
|
||||
<DashboardQueryEditor />
|
||||
</div>
|
||||
</template>
|
||||
</q-splitter>
|
||||
</template>
|
||||
<template #separator>
|
||||
<div class="splitter-vertical splitter-enabled"></div>
|
||||
<q-avatar
|
||||
color="primary"
|
||||
text-color="white"
|
||||
size="20px"
|
||||
icon="drag_indicator"
|
||||
style="top: 10px; left: 3.5px"
|
||||
data-test="dashboard-markdown-editor-drag-indicator"
|
||||
/>
|
||||
</template>
|
||||
<template #after>
|
||||
<PanelSchemaRenderer
|
||||
v-if="chartData"
|
||||
@metadata-update="metaDataValue"
|
||||
:key="dashboardPanelData.data.type"
|
||||
:panelSchema="chartData"
|
||||
:dashboard-id="queryParams?.dashboard"
|
||||
:folder-id="queryParams?.folder"
|
||||
:selectedTimeObj="dashboardPanelData.meta.dateTime"
|
||||
:variablesData="updatedVariablesData"
|
||||
:width="6"
|
||||
@error="handleChartApiError"
|
||||
@updated:data-zoom="onDataZoom"
|
||||
@updated:vrlFunctionFieldList="
|
||||
updateVrlFunctionFieldList
|
||||
"
|
||||
@last-triggered-at-update="handleLastTriggeredAtUpdate"
|
||||
searchType="dashboards"
|
||||
/>
|
||||
</template>
|
||||
</q-splitter>
|
||||
<DashboardErrorsComponent
|
||||
:errors="errorData"
|
||||
class="col-auto"
|
||||
style="flex-shrink: 0"
|
||||
/>
|
||||
</div>
|
||||
<div class="row column tw-h-[calc(100vh-180px)]">
|
||||
<DashboardQueryEditor />
|
||||
</div>
|
||||
</div>
|
||||
<q-separator vertical />
|
||||
<div class="col-auto">
|
||||
|
||||
Reference in New Issue
Block a user