feat: support Tabs in the widget visiable when MQE expressions (#353)

This commit is contained in:
Fine0830 2023-12-20 17:58:00 +08:00 committed by GitHub
parent 0d82507a87
commit 001fa25a3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 379 additions and 224 deletions

View File

@ -12,4 +12,4 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M856.32 428.064a32 32 0 0 0-32 32v163.328H372.48c-0.896 0-1.664 0.448-2.56 0.512v-177.696h244.48a32 32 0 1 0 0-64H130.56c-0.896 0-1.664 0.448-2.56 0.512V231.68h488.16a32 32 0 1 0 0-64H96a32 32 0 0 0-32 32v701.824a32 32 0 0 0 32 32h760.32a32 32 0 0 0 32-32V460.064a32 32 0 0 0-32-32zM128 445.728c0.896 0.064 1.664 0.512 2.56 0.512h175.36v423.264H128V445.728z m241.92 423.776v-182.624c0.896 0.064 1.664 0.512 2.56 0.512h451.84v182.08h-454.4zM960 174.656h-61.376V113.28a32 32 0 1 0-64 0v61.344H752.64a32 32 0 1 0 0 64h81.984v81.984a32 32 0 1 0 64 0V238.656H960a32 32 0 1 0 0-64z" fill="#2c2c2c"></path></svg> <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M856.32 428.064a32 32 0 0 0-32 32v163.328H372.48c-0.896 0-1.664 0.448-2.56 0.512v-177.696h244.48a32 32 0 1 0 0-64H130.56c-0.896 0-1.664 0.448-2.56 0.512V231.68h488.16a32 32 0 1 0 0-64H96a32 32 0 0 0-32 32v701.824a32 32 0 0 0 32 32h760.32a32 32 0 0 0 32-32V460.064a32 32 0 0 0-32-32zM128 445.728c0.896 0.064 1.664 0.512 2.56 0.512h175.36v423.264H128V445.728z m241.92 423.776v-182.624c0.896 0.064 1.664 0.512 2.56 0.512h451.84v182.08h-454.4zM960 174.656h-61.376V113.28a32 32 0 1 0-64 0v61.344H752.64a32 32 0 1 0 0 64h81.984v81.984a32 32 0 1 0 64 0V238.656H960a32 32 0 1 0 0-64z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -13,4 +13,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<svg t="1654161407133" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1721" width="16" height="16"><path d="M804.224 86.144c0-19.264-15.616-34.944-34.944-34.944l-734.336 0c-19.264 0-34.944 15.68-34.944 34.944l0 82.048 804.224 0 0-82.048zM738.88 602.432c0 47.072-38.176 85.248-85.248 85.248s-85.248-38.176-85.248-85.248c0-47.072 38.176-85.248 85.248-85.248s85.248 38.176 85.248 85.248zM804.992 264.64l0-62.976-804.224 0 0 665.408c0 18.56 14.656 33.472 32.96 34.56l402.24 0c61.12 44.544 136.192 71.168 217.664 71.168 204.544 0 370.368-165.824 370.368-370.368 0-150.592-89.984-279.936-219.008-337.792zM412.096 298.24l30.528 0c-10.624 7.36-20.8 15.36-30.528 23.744l0-23.744zM63.04 298.24l153.024 0 0 153.024-153.024 0 0-153.024zM216.064 805.056l-153.024 0 0-153.024 153.024 0 0 153.024zM219.136 631.232l-153.024 0 0-153.024 153.024 0 0 153.024zM237.568 805.056l0-153.024 49.408 0c7.488 55.936 27.264 107.904 56.832 153.024l-106.24 0zM284.672 631.232l-44.032 0 0-153.024 64.384 0c-13.824 38.848-21.824 80.576-21.824 124.224 0 9.728 0.768 19.264 1.472 28.8zM390.592 341.76c-31.168 31.424-56.512 68.544-74.88 109.44l-78.144 0 0-152.96 153.024 0 0 43.52zM899.136 638.4l-63.36 12.864c-4.288 16.064-10.688 31.296-18.816 45.376l35.712 53.888-50.944 50.944-53.888-35.712c-14.08 8.128-29.312 14.528-45.376 18.816l-12.864 63.36-72 0-12.864-63.36c-16.064-4.288-31.296-10.688-45.376-18.816l-53.888 35.712-50.944-50.944 35.712-53.888c-8.128-14.08-14.528-29.312-18.816-45.376l-63.36-12.864 0-72 63.36-12.864c4.352-16.064 10.688-31.296 18.816-45.312l-35.712-53.952 50.944-50.944 53.888 35.776c14.08-8.128 29.312-14.464 45.376-18.816l12.864-63.36 72 0 12.864 63.36c16.064 4.288 31.296 10.688 45.376 18.816l53.888-35.712 50.944 50.944-35.712 53.824c8.128 14.08 14.528 29.312 18.816 45.376l63.36 12.864 0 72z" p-id="1722" fill="#707070"></path></svg> <svg t="1654161407133" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1721" width="16" height="16"><path d="M804.224 86.144c0-19.264-15.616-34.944-34.944-34.944l-734.336 0c-19.264 0-34.944 15.68-34.944 34.944l0 82.048 804.224 0 0-82.048zM738.88 602.432c0 47.072-38.176 85.248-85.248 85.248s-85.248-38.176-85.248-85.248c0-47.072 38.176-85.248 85.248-85.248s85.248 38.176 85.248 85.248zM804.992 264.64l0-62.976-804.224 0 0 665.408c0 18.56 14.656 33.472 32.96 34.56l402.24 0c61.12 44.544 136.192 71.168 217.664 71.168 204.544 0 370.368-165.824 370.368-370.368 0-150.592-89.984-279.936-219.008-337.792zM412.096 298.24l30.528 0c-10.624 7.36-20.8 15.36-30.528 23.744l0-23.744zM63.04 298.24l153.024 0 0 153.024-153.024 0 0-153.024zM216.064 805.056l-153.024 0 0-153.024 153.024 0 0 153.024zM219.136 631.232l-153.024 0 0-153.024 153.024 0 0 153.024zM237.568 805.056l0-153.024 49.408 0c7.488 55.936 27.264 107.904 56.832 153.024l-106.24 0zM284.672 631.232l-44.032 0 0-153.024 64.384 0c-13.824 38.848-21.824 80.576-21.824 124.224 0 9.728 0.768 19.264 1.472 28.8zM390.592 341.76c-31.168 31.424-56.512 68.544-74.88 109.44l-78.144 0 0-152.96 153.024 0 0 43.52zM899.136 638.4l-63.36 12.864c-4.288 16.064-10.688 31.296-18.816 45.376l35.712 53.888-50.944 50.944-53.888-35.712c-14.08 8.128-29.312 14.528-45.376 18.816l-12.864 63.36-72 0-12.864-63.36c-16.064-4.288-31.296-10.688-45.376-18.816l-53.888 35.712-50.944-50.944 35.712-53.888c-8.128-14.08-14.528-29.312-18.816-45.376l-63.36-12.864 0-72 63.36-12.864c4.352-16.064 10.688-31.296 18.816-45.312l-35.712-53.952 50.944-50.944 53.888 35.776c14.08-8.128 29.312-14.464 45.376-18.816l12.864-63.36 72 0 12.864 63.36c16.064 4.288 31.296 10.688 45.376 18.816l53.888-35.712 50.944 50.944-35.712 53.824c8.128 14.08 14.528 29.312 18.816 45.376l63.36 12.864 0 72z" p-id="1722"></path></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -12,4 +12,4 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<svg t="1655695739627" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2218" width="48" height="48"><path d="M173.292308 177.230769C86.646154 265.846154 39.384615 382.030769 39.384615 504.123077 39.384615 531.692308 61.046154 551.384615 86.646154 551.384615s47.261538-21.661538 47.261538-47.261538c-1.969231-96.492308 37.415385-189.046154 106.338462-257.969231s163.446154-106.338462 257.969231-106.338461c27.569231 0 47.261538-21.661538 47.261538-47.261539 0-27.569231-21.661538-47.261538-47.261538-47.261538C378.092308 43.323077 259.938462 90.584615 173.292308 177.230769z m57.107692 326.892308c0 27.569231 19.692308 47.261538 47.261538 47.261538s47.261538-21.661538 47.261539-47.261538c0-45.292308 17.723077-90.584615 51.2-122.092308 33.476923-33.476923 76.8-49.230769 122.092308-51.2 27.569231 0 47.261538-21.661538 47.261538-47.261538 0-27.569231-19.692308-47.261538-47.261538-47.261539-70.892308 0-139.815385 27.569231-191.015385 76.8-7.876923 9.846154-80.738462 82.707692-76.8 191.015385z m665.6-204.8c-17.723077-23.630769-41.353846-51.2-45.292308-55.138462-5.907692-3.938462-13.784615-7.876923-21.661538-7.876923-7.876923 0-15.753846 1.969231-19.692308 7.876923L610.461538 441.107692c-47.261538-39.384615-118.153846-37.415385-163.446153 7.876923-45.292308 45.292308-47.261538 116.184615-7.876923 163.446154l-191.015385 191.015385c-5.907692 5.907692-9.846154 13.784615-9.846154 21.661538 0 9.846154 3.938462 19.692308 11.815385 25.6l53.16923 39.384616c72.861538 57.107692 163.446154 88.615385 259.938462 88.615384 232.369231 0 421.415385-189.046154 421.415385-421.415384 0-94.523077-33.476923-185.107692-88.615385-257.969231z" p-id="2219" fill="#707070"></path></svg> <svg t="1655695739627" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2218" width="48" height="48"><path d="M173.292308 177.230769C86.646154 265.846154 39.384615 382.030769 39.384615 504.123077 39.384615 531.692308 61.046154 551.384615 86.646154 551.384615s47.261538-21.661538 47.261538-47.261538c-1.969231-96.492308 37.415385-189.046154 106.338462-257.969231s163.446154-106.338462 257.969231-106.338461c27.569231 0 47.261538-21.661538 47.261538-47.261539 0-27.569231-21.661538-47.261538-47.261538-47.261538C378.092308 43.323077 259.938462 90.584615 173.292308 177.230769z m57.107692 326.892308c0 27.569231 19.692308 47.261538 47.261538 47.261538s47.261538-21.661538 47.261539-47.261538c0-45.292308 17.723077-90.584615 51.2-122.092308 33.476923-33.476923 76.8-49.230769 122.092308-51.2 27.569231 0 47.261538-21.661538 47.261538-47.261538 0-27.569231-19.692308-47.261538-47.261538-47.261539-70.892308 0-139.815385 27.569231-191.015385 76.8-7.876923 9.846154-80.738462 82.707692-76.8 191.015385z m665.6-204.8c-17.723077-23.630769-41.353846-51.2-45.292308-55.138462-5.907692-3.938462-13.784615-7.876923-21.661538-7.876923-7.876923 0-15.753846 1.969231-19.692308 7.876923L610.461538 441.107692c-47.261538-39.384615-118.153846-37.415385-163.446153 7.876923-45.292308 45.292308-47.261538 116.184615-7.876923 163.446154l-191.015385 191.015385c-5.907692 5.907692-9.846154 13.784615-9.846154 21.661538 0 9.846154 3.938462 19.692308 11.815385 25.6l53.16923 39.384616c72.861538 57.107692 163.446154 88.615385 259.938462 88.615384 232.369231 0 421.415385-189.046154 421.415385-421.415384 0-94.523077-33.476923-185.107692-88.615385-257.969231z" p-id="2219"></path></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -53,6 +53,7 @@ limitations under the License. -->
import { addResizeListener, removeResizeListener } from "@/utils/event"; import { addResizeListener, removeResizeListener } from "@/utils/event";
import Trace from "@/views/dashboard/related/trace/Index.vue"; import Trace from "@/views/dashboard/related/trace/Index.vue";
import associateProcessor from "@/hooks/useAssociateProcessor"; import associateProcessor from "@/hooks/useAssociateProcessor";
import { WidgetType } from "@/views/dashboard/data";
/*global Nullable, defineProps, defineEmits, Indexable*/ /*global Nullable, defineProps, defineEmits, Indexable*/
const emits = defineEmits(["select"]); const emits = defineEmits(["select"]);
@ -63,7 +64,7 @@ limitations under the License. -->
const currentParams = ref<Nullable<EventParams>>(null); const currentParams = ref<Nullable<EventParams>>(null);
const showTrace = ref<boolean>(false); const showTrace = ref<boolean>(false);
const traceOptions = ref<{ type: string; filters?: unknown }>({ const traceOptions = ref<{ type: string; filters?: unknown }>({
type: "Trace", type: WidgetType.Trace,
}); });
const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN }); const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
const props = defineProps({ const props = defineProps({

View File

@ -141,6 +141,7 @@ export async function useExpressionsQueryProcessor(config: Indexable) {
return { source, tips, typesOfMQE }; return { source, tips, typesOfMQE };
} }
const params = await expressionsGraphqlPods(); const params = await expressionsGraphqlPods();
if (!params) { if (!params) {
return { source: {}, tips: [], typesOfMQE: [] }; return { source: {}, tips: [], typesOfMQE: [] };
@ -301,6 +302,7 @@ export async function useExpressionsQueryPodsMetrics(
return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips }; return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips };
} }
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const params = await expressionsGraphqlPods(); const params = await expressionsGraphqlPods();
const json = await dashboardStore.fetchMetricValue(params); const json = await dashboardStore.fetchMetricValue(params);

View File

@ -93,7 +93,8 @@ limitations under the License. -->
const savedTheme = window.localStorage.getItem("theme-is-dark"); const savedTheme = window.localStorage.getItem("theme-is-dark");
if (savedTheme === "false") { if (savedTheme === "false") {
theme.value = false; theme.value = false;
} else if (savedTheme === "") { }
if (savedTheme === "") {
// read the theme preference from system setting if there is no user setting // read the theme preference from system setting if there is no user setting
theme.value = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; theme.value = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
} }

View File

@ -384,5 +384,6 @@ const msg = {
unhealthyExpression: "Unhealthy Expression", unhealthyExpression: "Unhealthy Expression",
traceDesc: traceDesc:
"The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.",
tabExpressions: "Tab Expressions",
}; };
export default msg; export default msg;

View File

@ -384,5 +384,6 @@ const msg = {
unhealthyExpression: "Unhealthy Expression", unhealthyExpression: "Unhealthy Expression",
traceDesc: traceDesc:
"The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.",
tabExpressions: "Tab Expressions",
}; };
export default msg; export default msg;

View File

@ -382,5 +382,6 @@ const msg = {
unhealthyExpression: "非健康表达式", unhealthyExpression: "非健康表达式",
traceDesc: traceDesc:
"Trace Segment代表在单一操作系统进程例如JVM中执行的追踪部分。它包含了一组跨度spans这些跨度通常与单一请求或执行上下文关联。", "Trace Segment代表在单一操作系统进程例如JVM中执行的追踪部分。它包含了一组跨度spans这些跨度通常与单一请求或执行上下文关联。",
tabExpressions: "Tab表达式",
}; };
export default msg; export default msg;

View File

@ -14,13 +14,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { WidgetType } from "@/views/dashboard/data";
export const NewControl = { export const NewControl = {
x: 0, x: 0,
y: 0, y: 0,
w: 24, w: 24,
h: 12, h: 12,
i: "0", i: "0",
type: "Widget", type: WidgetType.Widget,
}; };
export const TextConfig = { export const TextConfig = {
fontColor: "white", fontColor: "white",
@ -39,15 +41,15 @@ export const TimeRangeConfig = {
}; };
export const ControlsTypes = [ export const ControlsTypes = [
"Trace", WidgetType.Trace,
"Profile", WidgetType.Profile,
"Log", WidgetType.Log,
"DemandLog", WidgetType.DemandLog,
"Ebpf", WidgetType.Ebpf,
"NetworkProfiling", WidgetType.NetworkProfiling,
"ThirdPartyApp", WidgetType.ThirdPartyApp,
"ContinuousProfiling", WidgetType.ContinuousProfiling,
"TaskTimeline", WidgetType.TaskTimeline,
]; ];
export enum EBPFProfilingTriggerType { export enum EBPFProfilingTriggerType {
FIXED_TIME = "FIXED_TIME", FIXED_TIME = "FIXED_TIME",

View File

@ -25,7 +25,7 @@ import { NewControl, TextConfig, TimeRangeConfig, ControlsTypes } from "../data"
import type { AxiosResponse } from "axios"; import type { AxiosResponse } from "axios";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { EntityType, MetricModes } from "@/views/dashboard/data"; import { EntityType, MetricModes, WidgetType } from "@/views/dashboard/data";
interface DashboardState { interface DashboardState {
showConfig: boolean; showConfig: boolean;
layout: LayoutConfig[]; layout: LayoutConfig[];
@ -78,7 +78,7 @@ export const dashboardStore = defineStore({
setCurrentDashboard(item: DashboardItem) { setCurrentDashboard(item: DashboardItem) {
this.currentDashboard = item; this.currentDashboard = item;
}, },
addControl(type: string) { addControl(type: WidgetType) {
const arr = this.layout.map((d: Recordable) => Number(d.i)); const arr = this.layout.map((d: Recordable) => Number(d.i));
let index = String(Math.max(...arr) + 1); let index = String(Math.max(...arr) + 1);
if (!this.layout.length) { if (!this.layout.length) {
@ -93,10 +93,10 @@ export const dashboardStore = defineStore({
metrics: [""], metrics: [""],
}; };
if (type === "Widget") { if (type === WidgetType.Widget) {
newItem.metricMode = MetricModes.Expression; newItem.metricMode = MetricModes.Expression;
} }
if (type === "Tab") { if (type === WidgetType.Tab) {
newItem.h = 36; newItem.h = 36;
newItem.activedTabIndex = 0; newItem.activedTabIndex = 0;
newItem.children = [ newItem.children = [
@ -110,7 +110,7 @@ export const dashboardStore = defineStore({
}, },
]; ];
} }
if (type === "Topology") { if (type === WidgetType.Topology) {
newItem.h = 36; newItem.h = 36;
newItem.graph = { newItem.graph = {
showDepth: true, showDepth: true,
@ -120,11 +120,11 @@ export const dashboardStore = defineStore({
if (ControlsTypes.includes(type)) { if (ControlsTypes.includes(type)) {
newItem.h = 36; newItem.h = 36;
} }
if (type === "Text") { if (type === WidgetType.Text) {
newItem.h = 6; newItem.h = 6;
newItem.graph = TextConfig; newItem.graph = TextConfig;
} }
if (type === "TimeRange") { if (type === WidgetType.TimeRange) {
newItem.w = 8; newItem.w = 8;
newItem.h = 6; newItem.h = 6;
newItem.graph = TimeRangeConfig; newItem.graph = TimeRangeConfig;
@ -149,7 +149,7 @@ export const dashboardStore = defineStore({
}; };
this.layout[idx].children?.push(i); this.layout[idx].children?.push(i);
}, },
addTabControls(type: string) { addTabControls(type: WidgetType) {
const activedGridItem = this.activedGridItem.split("-")[0]; const activedGridItem = this.activedGridItem.split("-")[0];
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem); const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem);
if (idx < 0) { if (idx < 0) {
@ -171,10 +171,10 @@ export const dashboardStore = defineStore({
metricTypes: [""], metricTypes: [""],
metrics: [""], metrics: [""],
}; };
if (type === "Widget") { if (type === WidgetType.Widget) {
newItem.metricMode = MetricModes.Expression; newItem.metricMode = MetricModes.Expression;
} }
if (type === "Topology") { if (type === WidgetType.Topology) {
newItem.h = 32; newItem.h = 32;
newItem.graph = { newItem.graph = {
showDepth: true, showDepth: true,
@ -184,11 +184,11 @@ export const dashboardStore = defineStore({
if (ControlsTypes.includes(type)) { if (ControlsTypes.includes(type)) {
newItem.h = 32; newItem.h = 32;
} }
if (type === "Text") { if (type === WidgetType.Text) {
newItem.h = 6; newItem.h = 6;
newItem.graph = TextConfig; newItem.graph = TextConfig;
} }
if (type === "TimeRange") { if (type === WidgetType.TimeRange) {
newItem.w = 8; newItem.w = 8;
newItem.h = 6; newItem.h = 6;
newItem.graph = TextConfig; newItem.graph = TextConfig;
@ -292,7 +292,7 @@ export const dashboardStore = defineStore({
}, },
setWidget(param: LayoutConfig) { setWidget(param: LayoutConfig) {
for (let i = 0; i < this.layout.length; i++) { for (let i = 0; i < this.layout.length; i++) {
if (this.layout[i].type === "Tab") { if (this.layout[i].type === WidgetType.Tab) {
if ((this.layout[i].children || []).length) { if ((this.layout[i].children || []).length) {
for (const child of this.layout[i].children || []) { for (const child of this.layout[i].children || []) {
if (child.children && child.children.length) { if (child.children && child.children.length) {

View File

@ -65,7 +65,7 @@ html.dark {
--el-color-primary: #409eff; --el-color-primary: #409eff;
--theme-background: #212224; --theme-background: #212224;
--font-color: #fafbfc; --font-color: #fafbfc;
--disabled-color: #ccc; --disabled-color: #999;
--dashboard-tool-bg: #000; --dashboard-tool-bg: #000;
--text-color-placeholder: #ccc; --text-color-placeholder: #ccc;
--border-color: #262629; --border-color: #262629;

View File

@ -36,7 +36,7 @@ export interface LayoutConfig {
expressions?: string[]; expressions?: string[];
metricTypes?: string[]; metricTypes?: string[];
typesOfMQE?: string[]; typesOfMQE?: string[];
children?: { name: string; children: LayoutConfig[] }[]; children?: { name: string; children: LayoutConfig[]; expression?: string; enable?: boolean }[];
activedTabIndex?: number; activedTabIndex?: number;
metricConfig?: MetricConfigOpt[]; metricConfig?: MetricConfigOpt[];
id?: string; id?: string;

View File

@ -139,6 +139,7 @@ limitations under the License. -->
import { saveFile, readFile } from "@/utils/file"; import { saveFile, readFile } from "@/utils/file";
import { EntityType } from "./data"; import { EntityType } from "./data";
import { isEmptyObject } from "@/utils/is"; import { isEmptyObject } from "@/utils/is";
import { WidgetType } from "@/views/dashboard/data";
/*global Nullable*/ /*global Nullable*/
const { t } = useI18n(); const { t } = useI18n();
@ -271,12 +272,23 @@ limitations under the License. -->
if (!(child.metricConfig && child.metricConfig.length)) { if (!(child.metricConfig && child.metricConfig.length)) {
delete child.metricConfig; delete child.metricConfig;
} }
if (child.type === "Tab") { if (child.type === WidgetType.Tab) {
for (const item of child.children || []) { for (const item of child.children || []) {
optimizeTemplate(item.children); optimizeTemplate(item.children);
} }
} }
if (["Trace", "Topology", "Tab", "Profile", "Ebpf", "Log"].includes(child.type)) { if (
(
[
WidgetType.Trace,
WidgetType.Topology,
WidgetType.Tab,
WidgetType.Profile,
WidgetType.Ebpf,
WidgetType.Log,
] as string[]
).includes(child.type)
) {
delete child.widget; delete child.widget;
} }
} }

View File

@ -0,0 +1,110 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="item">
<span class="label">{{ t("tabExpressions") }}</span>
<div class="mt-10" v-for="(child, index) in widgetTabs || []" :key="index">
<span class="name">{{ child.name }}</span>
<el-input class="input" size="small" v-model="expressions[child.name]" @change="changeExpression(child.name)" />
</div>
</div>
<div class="footer">
<el-button size="small" @click="cancelConfig">
{{ t("cancel") }}
</el-button>
<el-button size="small" type="primary" @click="applyConfig">
{{ t("apply") }}
</el-button>
</div>
</template>
<script lang="ts" setup>
import { useI18n } from "vue-i18n";
import { reactive, computed } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard";
import { ElMessage } from "element-plus";
import { WidgetType, ListEntity } from "@/views/dashboard/data";
const { t } = useI18n();
const dashboardStore = useDashboardStore();
const originConfig = dashboardStore.selectedGrid;
const expressions = reactive<{ [key: string]: string }>({});
const widgetTabs = computed(() =>
(dashboardStore.selectedGrid.children || []).filter((child: any) =>
child.children.find(
(item: any) =>
item.type === WidgetType.Widget &&
!(Object.keys(ListEntity).includes(item.graph.type as string) && child.children.length === 1),
),
),
);
for (const child of originConfig.children || []) {
expressions[child.name] = child.expression || "";
}
function changeExpression(name: string) {
if (expressions[name] && !expressions[name].includes("is_present")) {
ElMessage.error("Only support the is_present function");
return;
}
const children = JSON.parse(JSON.stringify(dashboardStore.selectedGrid.children || []));
for (const item of children) {
if (item.name === name) {
item.expression = expressions[name];
}
}
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, children });
}
function applyConfig() {
dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid);
}
function cancelConfig() {
dashboardStore.selectWidget(originConfig);
dashboardStore.setConfigPanel(false);
}
</script>
<style lang="scss" scoped>
.label {
font-size: 13px;
font-weight: 500;
display: block;
margin-bottom: 5px;
}
.item {
margin-bottom: 10px;
}
.input {
width: 500px;
}
.footer {
position: fixed;
bottom: 0;
right: 0;
border-top: 1px solid $border-color-primary;
padding: 10px;
text-align: right;
width: 100%;
background-color: $theme-background;
}
.name {
width: 180px;
display: inline-block;
}
</style>

View File

@ -22,8 +22,10 @@ import Event from "./Event.vue";
import TimeRange from "./TimeRange.vue"; import TimeRange from "./TimeRange.vue";
import ThirdPartyApp from "./ThirdPartyApp.vue"; import ThirdPartyApp from "./ThirdPartyApp.vue";
import ContinuousProfiling from "./ContinuousProfiling.vue"; import ContinuousProfiling from "./ContinuousProfiling.vue";
import Tab from "./Tab.vue";
export default { export default {
Tab,
Text, Text,
Widget, Widget,
Topology, Topology,

View File

@ -15,29 +15,41 @@ limitations under the License. -->
<template> <template>
<div class="flex-h tab-header"> <div class="flex-h tab-header">
<div class="tabs scroll_bar_style" @click="handleClick"> <div class="tabs scroll_bar_style" @click="handleClick">
<span <template v-for="(child, idx) in data.children || []">
v-for="(child, idx) in data.children || []" <span
:key="idx" :key="idx"
:class="{ active: activeTabIndex === idx }" :class="{ active: activeTabIndex === idx }"
@click="clickTabs($event, idx)" @click="clickTabs($event, idx)"
> v-if="child.enable !== false"
<input >
@click="editTabName($event, idx)" <input
v-model="child.name" @click="editTabName($event, idx)"
placeholder="Please input" v-model="child.name"
class="tab-name" placeholder="Please input"
:readonly="isNaN(editTabIndex) && !canEditTabName" class="tab-name"
:class="{ view: !canEditTabName }" :readonly="isNaN(editTabIndex) && !canEditTabName"
:class="{ view: !canEditTabName }"
:style="{ width: getStringWidth(child.name) + 'px' }"
/>
<Icon
v-show="activeTabIndex === idx"
size="sm"
iconName="cancel"
@click="deleteTabItem($event, idx)"
v-if="dashboardStore.editMode && canEditTabName"
/>
</span>
</template>
<template v-for="(child, idx) in data.children || []">
<span
:key="idx"
:style="{ width: getStringWidth(child.name) + 'px' }" :style="{ width: getStringWidth(child.name) + 'px' }"
/> v-if="child.enable === false"
<Icon class="tab-diabled"
v-show="activeTabIndex === idx" >
size="sm" {{ child.name }}
iconName="cancel" </span>
@click="deleteTabItem($event, idx)" </template>
v-if="dashboardStore.editMode && canEditTabName"
/>
</span>
<span class="tab-icons"> <span class="tab-icons">
<el-tooltip content="Copy Link" placement="bottom"> <el-tooltip content="Copy Link" placement="bottom">
<i @click="copyLink"> <i @click="copyLink">
@ -56,10 +68,13 @@ limitations under the License. -->
<div class="operations" v-if="dashboardStore.editMode"> <div class="operations" v-if="dashboardStore.editMode">
<el-dropdown placement="bottom" trigger="click" :width="200"> <el-dropdown placement="bottom" trigger="click" :width="200">
<span class="icon-operation"> <span class="icon-operation">
<Icon iconName="ellipsis_v" size="middle" /> <Icon class="icon-tool" iconName="ellipsis_v" size="middle" />
</span> </span>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item @click="editConfig">
<span>{{ t("edit") }}</span>
</el-dropdown-item>
<el-dropdown-item @click="canEditTabName = true"> <el-dropdown-item @click="canEditTabName = true">
<span class="edit-tab">{{ t("editTab") }}</span> <span class="edit-tab">{{ t("editTab") }}</span>
</el-dropdown-item> </el-dropdown-item>
@ -112,8 +127,9 @@ limitations under the License. -->
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig } from "@/types/dashboard";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import controls from "./tab"; import controls from "./tab";
import { dragIgnoreFrom } from "../data"; import { dragIgnoreFrom, WidgetType } from "../data";
import copy from "@/utils/copy"; import copy from "@/utils/copy";
import { useExpressionsQueryProcessor } from "@/hooks/useExpressionsProcessor";
const props = { const props = {
data: { data: {
@ -137,13 +153,17 @@ limitations under the License. -->
const editTabIndex = ref<number>(NaN); // edit tab item name const editTabIndex = ref<number>(NaN); // edit tab item name
const canEditTabName = ref<boolean>(false); const canEditTabName = ref<boolean>(false);
const needQuery = ref<boolean>(false); const needQuery = ref<boolean>(false);
dashboardStore.setActiveTabIndex(activeTabIndex);
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i); const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
dashboardStore.setActiveTabIndex(activeTabIndex.value);
if (dashboardStore.layout[l].children.length) { if (dashboardStore.layout[l].children.length) {
dashboardStore.setCurrentTabItems(dashboardStore.layout[l].children[activeTabIndex.value].children); const tab = dashboardStore.layout[l].children[activeTabIndex.value];
dashboardStore.setCurrentTabItems(
tab.enable === false ? [] : dashboardStore.layout[l].children[activeTabIndex.value].children,
);
dashboardStore.setActiveTabIndex(activeTabIndex.value, props.data.i); dashboardStore.setActiveTabIndex(activeTabIndex.value, props.data.i);
} }
queryExpressions();
function clickTabs(e: Event, idx: number) { function clickTabs(e: Event, idx: number) {
e.stopPropagation(); e.stopPropagation();
@ -224,6 +244,53 @@ limitations under the License. -->
copy(path); copy(path);
} }
document.body.addEventListener("click", handleClick, false); document.body.addEventListener("click", handleClick, false);
function editConfig() {
dashboardStore.setConfigPanel(true);
dashboardStore.selectWidget(props.data);
}
async function queryExpressions() {
const tabsProps = props.data;
const metrics = [];
for (const child of tabsProps.children || []) {
child.expression && metrics.push(child.expression);
}
if (!metrics.length) {
return;
}
const params: { [key: string]: any } = (await useExpressionsQueryProcessor({ metrics })) || {};
for (const child of tabsProps.children || []) {
if (params.source[child.expression || ""]) {
child.enable =
!!Number(params.source[child.expression || ""]) &&
!!child.children.find((item: { type: string }) => item.type === WidgetType.Widget);
} else {
child.enable = true;
}
}
dashboardStore.setConfigs(tabsProps);
if (((props.data.children || [])[activeTabIndex.value] || {}).enable === false) {
const index = (props.data.children || []).findIndex((tab: any) => tab.enable !== false) || 0;
const items = ((props.data.children || [])[index] || {}).children;
dashboardStore.setCurrentTabItems(items || []);
dashboardStore.activeGridItem(0);
activeTabIndex.value = index;
dashboardStore.setActiveTabIndex(activeTabIndex.value);
needQuery.value = true;
}
}
watch(
() => (props.data.children || []).map((d: any) => d.expression),
(old: string[], data: string[]) => {
if (JSON.stringify(data) === JSON.stringify(old)) {
return;
}
queryExpressions();
},
);
watch( watch(
() => dashboardStore.activedGridItem, () => dashboardStore.activedGridItem,
(data) => { (data) => {
@ -266,6 +333,7 @@ limitations under the License. -->
clickTabs, clickTabs,
copyLink, copyLink,
getStringWidth, getStringWidth,
editConfig,
...toRefs(props), ...toRefs(props),
activeTabWidget, activeTabWidget,
dashboardStore, dashboardStore,
@ -288,6 +356,7 @@ limitations under the License. -->
white-space: nowrap; white-space: nowrap;
overflow-y: hidden; overflow-y: hidden;
padding: 0 10px; padding: 0 10px;
display: inline-flex;
span { span {
display: inline-block; display: inline-block;
@ -310,6 +379,18 @@ limitations under the License. -->
background-color: $theme-background; background-color: $theme-background;
} }
.tab-diabled {
max-width: 150px;
outline: none;
color: $disabled-color;
font-style: normal;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 20px;
background-color: $theme-background;
cursor: not-allowed;
}
.tab-icons { .tab-icons {
i { i {
margin-right: 3px; margin-right: 3px;

View File

@ -188,87 +188,104 @@ export const SortOrder = [
{ label: "DES", value: "DES" }, { label: "DES", value: "DES" },
{ label: "ASC", value: "ASC" }, { label: "ASC", value: "ASC" },
]; ];
export enum WidgetType {
Widget = "Widget",
Topology = "Topology",
Tab = "Tab",
Text = "Text",
TimeRange = "TimeRange",
Trace = "Trace",
Log = "Log",
Profile = "Profile",
Ebpf = "Ebpf",
DemandLog = "DemandLog",
Event = "Event",
NetworkProfiling = "NetworkProfiling",
ContinuousProfiling = "ContinuousProfiling",
ThirdPartyApp = "ThirdPartyApp",
TaskTimeline = "TaskTimeline",
}
export const AllTools = [ export const AllTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "device_hub", content: "Add Topology", id: WidgetType.Topology },
{ name: "merge", content: "Add Trace", id: "addTrace" }, { name: "merge", content: "Add Trace", id: WidgetType.Trace },
{ name: "assignment", content: "Add Log", id: "addLog" }, { name: "assignment", content: "Add Log", id: WidgetType.Log },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const ServiceTools = [ export const ServiceTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "device_hub", content: "Add Topology", id: WidgetType.Topology },
{ name: "merge", content: "Add Trace", id: "addTrace" }, { name: "merge", content: "Add Trace", id: WidgetType.Trace },
{ name: "timeline", content: "Add Trace Profiling", id: "addProfile" }, { name: "timeline", content: "Add Trace Profiling", id: WidgetType.Profile },
{ name: "insert_chart", content: "Add eBPF Profiling", id: "addEbpf" }, { name: "insert_chart", content: "Add eBPF Profiling", id: WidgetType.Ebpf },
{ name: "continuous_profiling", content: "Add Continuous Profiling", id: "addContinuousProfiling" }, { name: "continuous_profiling", content: "Add Continuous Profiling", id: WidgetType.ContinuousProfiling },
{ name: "assignment", content: "Add Log", id: "addLog" }, { name: "assignment", content: "Add Log", id: WidgetType.Log },
{ name: "demand", content: "Add On Demand Log", id: "addDemandLog" }, { name: "demand", content: "Add On Demand Log", id: WidgetType.DemandLog },
{ name: "event", content: "Add Event", id: "addEvent" }, { name: "event", content: "Add Event", id: WidgetType.Event },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const InstanceTools = [ export const InstanceTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "merge", content: "Add Trace", id: "addTrace" }, { name: "merge", content: "Add Trace", id: WidgetType.Trace },
{ name: "assignment", content: "Add Log", id: "addLog" }, { name: "assignment", content: "Add Log", id: WidgetType.Log },
{ name: "demand", content: "Add On Demand Log", id: "addDemandLog" }, { name: "demand", content: "Add On Demand Log", id: WidgetType.DemandLog },
{ name: "event", content: "Add Event", id: "addEvent" }, { name: "event", content: "Add Event", id: WidgetType.Event },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
{ {
name: "timeline", name: "timeline",
content: "Add Network Profiling", content: "Add Network Profiling",
id: "addNetworkProfiling", id: WidgetType.NetworkProfiling,
}, },
]; ];
export const EndpointTools = [ export const EndpointTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "device_hub", content: "Add Topology", id: WidgetType.Topology },
{ name: "merge", content: "Add Trace", id: "addTrace" }, { name: "merge", content: "Add Trace", id: WidgetType.Trace },
{ name: "assignment", content: "Add Log", id: "addLog" }, { name: "assignment", content: "Add Log", id: WidgetType.Log },
{ name: "event", content: "Add Event", id: "c" }, { name: "event", content: "Add Event", id: WidgetType.Event },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const ProcessTools = [ export const ProcessTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "task_timeline", content: "Add Task Timeline", id: "addTaskTimeline" }, { name: "task_timeline", content: "Add Task Timeline", id: WidgetType.TaskTimeline },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const ProcessRelationTools = [ export const ProcessRelationTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const ServiceRelationTools = [ export const ServiceRelationTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "device_hub", content: "Add Topology", id: WidgetType.Topology },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const EndpointRelationTools = [ export const EndpointRelationTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const InstanceRelationTools = [ export const InstanceRelationTools = [
{ name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "playlist_add", content: "Add Widget", id: WidgetType.Widget },
{ name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "all_inbox", content: "Add Tabs", id: WidgetType.Tab },
{ name: "library_books", content: "Add Text", id: "addText" }, { name: "library_books", content: "Add Text", id: WidgetType.Text },
{ name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "device_hub", content: "Add Topology", id: WidgetType.Topology },
{ name: "add_iframe", content: "Add Iframe", id: "addIframe" }, { name: "add_iframe", content: "Add Iframe", id: WidgetType.ThirdPartyApp },
]; ];
export const ScopeType = [ export const ScopeType = [

View File

@ -65,6 +65,7 @@ limitations under the License. -->
import { TextColors } from "@/views/dashboard/data"; import { TextColors } from "@/views/dashboard/data";
import Trace from "@/views/dashboard/related/trace/Index.vue"; import Trace from "@/views/dashboard/related/trace/Index.vue";
import { QueryOrders, Status, RefIdTypes, ProtocolTypes, ExpressionResultType } from "../data"; import { QueryOrders, Status, RefIdTypes, ProtocolTypes, ExpressionResultType } from "../data";
import { WidgetType } from "@/views/dashboard/data";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
@ -90,7 +91,7 @@ limitations under the License. -->
const { t } = useI18n(); const { t } = useI18n();
const showTrace = ref<boolean>(false); const showTrace = ref<boolean>(false);
const traceOptions = ref<{ type: string; filters?: unknown }>({ const traceOptions = ref<{ type: string; filters?: unknown }>({
type: "Trace", type: WidgetType.Trace,
}); });
const refIdType = computed( const refIdType = computed(
() => (props.config.relatedTrace && props.config.relatedTrace.refIdType) || RefIdTypes[0].value, () => (props.config.relatedTrace && props.config.relatedTrace.refIdType) || RefIdTypes[0].value,

View File

@ -58,7 +58,12 @@ limitations under the License. -->
function clickGrid(item: LayoutConfig, event: Event) { function clickGrid(item: LayoutConfig, event: Event) {
dashboardStore.activeGridItem(item.i); dashboardStore.activeGridItem(item.i);
dashboardStore.selectWidget(item); dashboardStore.selectWidget(item);
if (item.type === "Tab" && (event.target as HTMLDivElement)?.className !== "tab-layout") { if (
item.type === "Tab" &&
!["operations", "tab-layout"].includes((event.target as HTMLDivElement)?.className) &&
(event.target as HTMLDivElement)?.classList[2] !== "icon-tool" &&
(event.target as HTMLDivElement)?.nodeName !== "use"
) {
dashboardStore.setActiveTabIndex(0); dashboardStore.setActiveTabIndex(0);
} }
} }

View File

@ -143,7 +143,8 @@ limitations under the License. -->
ServiceRelationTools, ServiceRelationTools,
ProcessTools, ProcessTools,
ProcessRelationTools, ProcessRelationTools,
} from "../data"; WidgetType,
} from "@/views/dashboard/data";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
@ -154,7 +155,7 @@ limitations under the License. -->
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const params = useRoute().params; const params = useRoute().params;
const toolIcons = ref<{ name: string; content: string; id: string }[]>(AllTools); const toolIcons = ref<{ name: string; content: string; id: WidgetType }[]>(AllTools);
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const states = reactive<{ const states = reactive<{
destService: string; destService: string;
@ -397,7 +398,7 @@ limitations under the License. -->
loading.value = false; loading.value = false;
} }
async function clickIcons(t: { id: string; content: string; name: string }) { async function clickIcons(t: { id: WidgetType; content: string; name: string }) {
if (dashboardStore.selectedGrid && dashboardStore.selectedGrid.type === "Tab") { if (dashboardStore.selectedGrid && dashboardStore.selectedGrid.type === "Tab") {
setTabControls(t.id); setTabControls(t.id);
return; return;
@ -409,106 +410,20 @@ limitations under the License. -->
setControls(t.id); setControls(t.id);
} }
function setTabControls(id: string) { function setTabControls(id: WidgetType) {
switch (id) { if (!WidgetType[id]) {
case "addWidget": ElMessage.info("Don't support this control");
dashboardStore.addTabControls("Widget"); return;
break;
case "addTrace":
dashboardStore.addTabControls("Trace");
break;
case "addLog":
dashboardStore.addTabControls("Log");
break;
case "addProfile":
dashboardStore.addTabControls("Profile");
break;
case "addEbpf":
dashboardStore.addTabControls("Ebpf");
break;
case "addTopology":
dashboardStore.addTabControls("Topology");
break;
case "addText":
dashboardStore.addTabControls("Text");
break;
case "addDemandLog":
dashboardStore.addTabControls("DemandLog");
break;
case "addEvent":
dashboardStore.addTabControls("Event");
break;
case "addNetworkProfiling":
dashboardStore.addTabControls("NetworkProfiling");
break;
case "addContinuousProfiling":
dashboardStore.addTabControls("ContinuousProfiling");
break;
case "addTimeRange":
dashboardStore.addTabControls("TimeRange");
break;
case "addIframe":
dashboardStore.addTabControls("ThirdPartyApp");
break;
case "addTaskTimeline":
dashboardStore.addTabControls("TaskTimeline");
break;
default:
ElMessage.info("Don't support this control");
break;
} }
dashboardStore.addTabControls(id);
} }
function setControls(id: string) { function setControls(id: WidgetType) {
switch (id) { if (!WidgetType[id]) {
case "addWidget": ElMessage.info("Don't support this control");
dashboardStore.addControl("Widget"); return;
break;
case "addTab":
dashboardStore.addControl("Tab");
break;
case "addTrace":
dashboardStore.addControl("Trace");
break;
case "addProfile":
dashboardStore.addControl("Profile");
break;
case "addEbpf":
dashboardStore.addControl("Ebpf");
break;
case "addLog":
dashboardStore.addControl("Log");
break;
case "addTopology":
dashboardStore.addControl("Topology");
break;
case "addText":
dashboardStore.addControl("Text");
break;
case "addDemandLog":
dashboardStore.addControl("DemandLog");
break;
case "addEvent":
dashboardStore.addControl("Event");
break;
case "addNetworkProfiling":
dashboardStore.addControl("NetworkProfiling");
break;
case "addContinuousProfiling":
dashboardStore.addControl("ContinuousProfiling");
break;
case "addTimeRange":
dashboardStore.addControl("TimeRange");
break;
case "addIframe":
dashboardStore.addControl("ThirdPartyApp");
break;
case "addTaskTimeline":
dashboardStore.addControl("TaskTimeline");
break;
default:
dashboardStore.addControl("Widget");
} }
dashboardStore.addControl(id);
} }
async function fetchPods(type: string, serviceId: string, setPod: boolean, param?: { keyword?: string }) { async function fetchPods(type: string, serviceId: string, setPod: boolean, param?: { keyword?: string }) {

View File

@ -29,6 +29,7 @@ limitations under the License. -->
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat"; import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
import getLocalTime from "@/utils/localtime"; import getLocalTime from "@/utils/localtime";
import { WidgetType } from "@/views/dashboard/data";
const eventStore = useEventStore(); const eventStore = useEventStore();
/*global defineProps, Nullable */ /*global defineProps, Nullable */
@ -122,7 +123,9 @@ limitations under the License. -->
}[], }[],
dashboard: LayoutConfig[], dashboard: LayoutConfig[],
) { ) {
const widgets = dashboard.filter((d: { type: string }) => ["Trace", "Log"].includes(d.type)); const widgets = dashboard.filter((d: { type: string }) =>
([WidgetType.Trace, WidgetType.Log] as string[]).includes(d.type),
);
const index = items[0]; const index = items[0];
const i = events[index - 1 || 0]; const i = events[index - 1 || 0];
for (const widget of widgets) { for (const widget of widgets) {

View File

@ -41,6 +41,7 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig } from "@/types/dashboard";
import { dateFormat } from "@/utils/dateFormat"; import { dateFormat } from "@/utils/dateFormat";
import { WidgetType } from "@/views/dashboard/data";
/*global defineProps, defineEmits, Recordable */ /*global defineProps, defineEmits, Recordable */
const props = defineProps({ const props = defineProps({
@ -78,7 +79,7 @@ limitations under the License. -->
traceId: id, traceId: id,
id: props.data.serviceId || "", id: props.data.serviceId || "",
}, },
"Trace", WidgetType.Trace,
); );
} }
</script> </script>

View File

@ -101,6 +101,7 @@ limitations under the License. -->
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig } from "@/types/dashboard";
import { dateFormat } from "@/utils/dateFormat"; import { dateFormat } from "@/utils/dateFormat";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { WidgetType } from "@/views/dashboard/data";
const props = { const props = {
serviceId: { type: String, default: "" }, serviceId: { type: String, default: "" },
@ -145,7 +146,7 @@ limitations under the License. -->
traceId: traceId.value || traceStore.currentTrace.traceIds[0].value, traceId: traceId.value || traceStore.currentTrace.traceIds[0].value,
id: props.serviceId || undefined, id: props.serviceId || undefined,
}, },
"Log", WidgetType.Log,
); );
} }
return { return {

View File

@ -19,7 +19,6 @@
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"], "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"], "exclude": ["src/**/__tests__/*"],
"compilerOptions": { "compilerOptions": {
"composite": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]

View File

@ -18,7 +18,6 @@
"extends": "./tsconfig.app.json", "extends": "./tsconfig.app.json",
"exclude": [], "exclude": [],
"compilerOptions": { "compilerOptions": {
"composite": true,
"lib": [], "lib": [],
"types": ["node", "jsdom"] "types": ["node", "jsdom"]
} }