mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2026-05-25 16:38:35 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e8a7576ac | ||
|
|
431bcc0891 | ||
|
|
370bfbc87d | ||
|
|
8b004ef316 | ||
|
|
6538cc401d | ||
|
|
93f2e70e6c | ||
|
|
64e2cab386 | ||
|
|
cf330e6cfd | ||
|
|
fc9b68d93d | ||
|
|
6a7cdbf9f8 | ||
|
|
f31aa90b6a | ||
|
|
de6b493bf2 | ||
|
|
6be09fb26b | ||
|
|
1a511ae1a0 | ||
|
|
b7bcbf1740 | ||
|
|
49a51d2a37 | ||
|
|
3c907950e7 | ||
|
|
4e3b1bdeae | ||
|
|
41b323400f | ||
|
|
d90ff89de1 | ||
|
|
fe767250b9 | ||
|
|
0334c28da5 | ||
|
|
f74a59f757 | ||
|
|
a4e9908b43 | ||
|
|
851c89925a | ||
|
|
6eaf7fe26d | ||
|
|
28c2cbd609 |
2
.github/workflows/nodejs.yml
vendored
2
.github/workflows/nodejs.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x, 20.x, 22.x]
|
node-version: [20.x, 22.x, 24.x]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
|||||||
4605
package-lock.json
generated
4605
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -49,11 +49,11 @@
|
|||||||
"@types/d3-tip": "^3.5.5",
|
"@types/d3-tip": "^3.5.5",
|
||||||
"@types/echarts": "^4.9.12",
|
"@types/echarts": "^4.9.12",
|
||||||
"@types/jsdom": "^20.0.1",
|
"@types/jsdom": "^20.0.1",
|
||||||
"@types/node": "^18.11.12",
|
"@types/node": "^22.19.10",
|
||||||
"@types/three": "^0.131.0",
|
"@types/three": "^0.131.0",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||||
"@vitest/coverage-v8": "^3.0.6",
|
"@vitest/coverage-v8": "^4.0.18",
|
||||||
"@vue/eslint-config-prettier": "^7.0.0",
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
"@vue/eslint-config-typescript": "^11.0.0",
|
"@vue/eslint-config-typescript": "^11.0.0",
|
||||||
"@vue/test-utils": "^2.2.6",
|
"@vue/test-utils": "^2.2.6",
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"eslint-plugin-cypress": "^2.12.1",
|
"eslint-plugin-cypress": "^2.12.1",
|
||||||
"eslint-plugin-vue": "^9.3.0",
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
"husky": "^8.0.2",
|
"husky": "^8.0.2",
|
||||||
"jsdom": "^20.0.3",
|
"jsdom": "^28.1.0",
|
||||||
"lint-staged": "^13.2.1",
|
"lint-staged": "^13.2.1",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
"vite": "^6.4.1",
|
"vite": "^6.4.1",
|
||||||
"vite-plugin-monaco-editor": "^1.1.0",
|
"vite-plugin-monaco-editor": "^1.1.0",
|
||||||
"vite-plugin-svg-icons": "^2.0.1",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vitest": "^3.0.5",
|
"vitest": "^4.0.18",
|
||||||
"vue-tsc": "^2.2.2"
|
"vue-tsc": "^2.2.2"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|||||||
16
src/assets/icons/gen_ai.svg
Normal file
16
src/assets/icons/gen_ai.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!-- 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. -->
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="64" height="64" fill="currentColor"><path d="M16.4004 21H14.2461L12.2461 16H5.75391L3.75391 21H1.59961L8 4.99996H10L16.4004 21ZM21 12V21H19V12H21ZM6.55371 14H11.4463L9 7.88473L6.55371 14ZM19.5293 2.3193C19.7058 1.89351 20.2942 1.8935 20.4707 2.3193L20.7236 2.93063C21.1555 3.97343 21.9615 4.80613 22.9746 5.2568L23.6914 5.57613C24.1022 5.75881 24.1022 6.35634 23.6914 6.53902L22.9326 6.87691C21.945 7.31619 21.1534 8.11942 20.7139 9.12789L20.4668 9.69332C20.2863 10.1075 19.7136 10.1075 19.5332 9.69332L19.2861 9.12789C18.8466 8.11941 18.0551 7.31619 17.0674 6.87691L16.3076 6.53902C15.8974 6.35617 15.8974 5.75894 16.3076 5.57613L17.0254 5.2568C18.0384 4.80613 18.8445 3.97343 19.2764 2.93063L19.5293 2.3193Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
17
src/assets/icons/list-tree.svg
Normal file
17
src/assets/icons/list-tree.svg
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!-- 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. -->
|
||||||
|
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||||
|
<path d="M896 469.333333h-341.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h341.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667zM341.333333 298.666667h554.666667c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667H341.333333c-25.6 0-42.666667 17.066667-42.666666 42.666667s17.066667 42.666667 42.666666 42.666667zM896 725.333333h-341.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h341.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667zM213.333333 554.666667h128c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667H213.333333c-25.6 0-42.666667-17.066667-42.666666-42.666666V256c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666667 42.666667v426.666667c0 72.533333 55.466667 128 128 128h128c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667H213.333333c-25.6 0-42.666667-17.066667-42.666666-42.666666v-136.533334c12.8 4.266667 25.6 8.533333 42.666666 8.533334z"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -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="1619507658599" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2073" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M331.840623 793.484755 331.840623 387.450978c0-16.191531-12.457456-28.645338-27.399836-28.645338L222.235197 358.80564c-14.94238 0-27.399836 13.698094-27.399836 28.645338L194.835361 793.484755 331.840623 793.484755 331.840623 793.484755zM506.210956 793.484755 506.210956 213.081861c0-16.192747-12.453808-29.89449-27.401052-29.89449l-82.20559 0c-14.94238 0-27.399836 13.701743-27.399836 29.89449L369.204478 793.484755 506.210956 793.484755 506.210956 793.484755zM680.580073 793.484755 680.580073 536.910048c0-16.191531-12.452591-29.889625-27.399836-29.889625L570.979512 507.020423c-14.947245 0-27.405918 13.698094-27.405918 29.889625L543.573595 793.484755 680.580073 793.484755 680.580073 793.484755zM854.94919 793.484755 854.94919 387.450978c0-16.191531-12.452591-28.645338-27.399836-28.645338l-82.200725 0c-14.947245 0-27.399836 13.698094-27.399836 28.645338L717.948794 793.484755 854.94919 793.484755 854.94919 793.484755zM879.860454 830.84861" p-id="2074" fill="#ffffff"></path></svg>
|
<svg t="1619507658599" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2073" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M331.840623 793.484755 331.840623 387.450978c0-16.191531-12.457456-28.645338-27.399836-28.645338L222.235197 358.80564c-14.94238 0-27.399836 13.698094-27.399836 28.645338L194.835361 793.484755 331.840623 793.484755 331.840623 793.484755zM506.210956 793.484755 506.210956 213.081861c0-16.192747-12.453808-29.89449-27.401052-29.89449l-82.20559 0c-14.94238 0-27.399836 13.701743-27.399836 29.89449L369.204478 793.484755 506.210956 793.484755 506.210956 793.484755zM680.580073 793.484755 680.580073 536.910048c0-16.191531-12.452591-29.889625-27.399836-29.889625L570.979512 507.020423c-14.947245 0-27.405918 13.698094-27.405918 29.889625L543.573595 793.484755 680.580073 793.484755 680.580073 793.484755zM854.94919 793.484755 854.94919 387.450978c0-16.191531-12.452591-28.645338-27.399836-28.645338l-82.200725 0c-14.947245 0-27.399836 13.698094-27.399836 28.645338L717.948794 793.484755 854.94919 793.484755 854.94919 793.484755zM879.860454 830.84861"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
src/assets/img/technologies/GENAI.png
Normal file
BIN
src/assets/img/technologies/GENAI.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export enum TimeType {
|
export enum TimeType {
|
||||||
|
SECOND_TIME = "SECOND",
|
||||||
MINUTE_TIME = "MINUTE",
|
MINUTE_TIME = "MINUTE",
|
||||||
HOUR_TIME = "HOUR",
|
HOUR_TIME = "HOUR",
|
||||||
DAY_TIME = "DAY",
|
DAY_TIME = "DAY",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export const Alarm = {
|
|||||||
key: id
|
key: id
|
||||||
message
|
message
|
||||||
startTime
|
startTime
|
||||||
|
recoveryTime
|
||||||
scope
|
scope
|
||||||
name
|
name
|
||||||
tags {
|
tags {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ vi.mock("@/utils/dateFormat", () => ({
|
|||||||
describe("useDuration hook", () => {
|
describe("useDuration hook", () => {
|
||||||
const mockAppStore = {
|
const mockAppStore = {
|
||||||
utc: false,
|
utc: false,
|
||||||
|
coldStageMode: false,
|
||||||
} as unknown as ReturnType<typeof useAppStoreWithOut>;
|
} as unknown as ReturnType<typeof useAppStoreWithOut>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -66,7 +67,7 @@ describe("useDuration hook", () => {
|
|||||||
setDurationRow(newDuration);
|
setDurationRow(newDuration);
|
||||||
const result = getDurationTime();
|
const result = getDurationTime();
|
||||||
|
|
||||||
expect(result.step).toBe("DAY");
|
expect(result.step).toBe("SECOND");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,9 +78,10 @@ describe("useDuration hook", () => {
|
|||||||
const result = getDurationTime();
|
const result = getDurationTime();
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
start: "2023-01-01",
|
start: "2023-01-01 00",
|
||||||
end: "2023-01-01",
|
end: "2023-01-01 00",
|
||||||
step: "HOUR",
|
step: "SECOND",
|
||||||
|
coldStage: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -152,7 +154,7 @@ describe("useDuration hook", () => {
|
|||||||
|
|
||||||
// Test getDurationTime
|
// Test getDurationTime
|
||||||
const durationTime = getDurationTime();
|
const durationTime = getDurationTime();
|
||||||
expect(durationTime.step).toBe("MINUTE");
|
expect(durationTime.step).toBe("SECOND");
|
||||||
|
|
||||||
// Test getMaxRange
|
// Test getMaxRange
|
||||||
const maxRange = getMaxRange(5);
|
const maxRange = getMaxRange(5);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { useAppStoreWithOut, InitializationDurationRow } from "@/store/modules/a
|
|||||||
import type { Duration, DurationTime } from "@/types/app";
|
import type { Duration, DurationTime } from "@/types/app";
|
||||||
import getLocalTime from "@/utils/localtime";
|
import getLocalTime from "@/utils/localtime";
|
||||||
import dateFormatStep from "@/utils/dateFormat";
|
import dateFormatStep from "@/utils/dateFormat";
|
||||||
|
import { TimeType } from "@/constants/data";
|
||||||
|
|
||||||
export function useDuration() {
|
export function useDuration() {
|
||||||
let durationRow: Duration = InitializationDurationRow;
|
let durationRow: Duration = InitializationDurationRow;
|
||||||
@@ -27,19 +28,24 @@ export function useDuration() {
|
|||||||
return {
|
return {
|
||||||
start: getLocalTime(appStore.utc, durationRow.start),
|
start: getLocalTime(appStore.utc, durationRow.start),
|
||||||
end: getLocalTime(appStore.utc, durationRow.end),
|
end: getLocalTime(appStore.utc, durationRow.end),
|
||||||
step: durationRow.step,
|
step: TimeType.SECOND_TIME,
|
||||||
|
coldStage: appStore.coldStageMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function getDurationTime(): DurationTime {
|
function getDurationTime(): DurationTime {
|
||||||
const { start, step, end } = getDuration();
|
const appStore = useAppStoreWithOut();
|
||||||
|
const { start, end } = getDuration();
|
||||||
|
const step = TimeType.SECOND_TIME;
|
||||||
return {
|
return {
|
||||||
start: dateFormatStep(start, step, true),
|
start: dateFormatStep(start, step, true),
|
||||||
end: dateFormatStep(end, step, true),
|
end: dateFormatStep(end, step, true),
|
||||||
step: step,
|
step,
|
||||||
|
coldStage: appStore.coldStageMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function setDurationRow(data: Duration) {
|
function setDurationRow(data: Duration) {
|
||||||
durationRow = data;
|
const appStore = useAppStoreWithOut();
|
||||||
|
durationRow = { ...data, coldStage: appStore.coldStageMode, step: TimeType.SECOND_TIME };
|
||||||
}
|
}
|
||||||
function getMaxRange(day: number) {
|
function getMaxRange(day: number) {
|
||||||
if (day === undefined || day === null) {
|
if (day === undefined || day === null) {
|
||||||
|
|||||||
@@ -58,6 +58,14 @@ export function useTheme() {
|
|||||||
|
|
||||||
// Handle theme change with transition animation
|
// Handle theme change with transition animation
|
||||||
function handleChangeTheme() {
|
function handleChangeTheme() {
|
||||||
|
const prefersReducedMotion =
|
||||||
|
typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||||
|
|
||||||
|
if (prefersReducedMotion) {
|
||||||
|
applyTheme();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const x = themeSwitchRef.value?.offsetLeft ?? 0;
|
const x = themeSwitchRef.value?.offsetLeft ?? 0;
|
||||||
const y = themeSwitchRef.value?.offsetTop ?? 0;
|
const y = themeSwitchRef.value?.offsetTop ?? 0;
|
||||||
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
|
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ limitations under the License. -->
|
|||||||
<el-switch
|
<el-switch
|
||||||
v-model="coldStage"
|
v-model="coldStage"
|
||||||
inline-prompt
|
inline-prompt
|
||||||
active-text="Active Data"
|
inactive-text="Cold Excluded"
|
||||||
inactive-text="Cold Data"
|
active-text="Cold Only"
|
||||||
@change="changeDataMode"
|
@change="changeDataMode"
|
||||||
width="90px"
|
width="105px"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span class="ml-5" ref="themeSwitchRef">
|
<span class="ml-5" ref="themeSwitchRef">
|
||||||
@@ -174,7 +174,20 @@ limitations under the License. -->
|
|||||||
async function setTTL() {
|
async function setTTL() {
|
||||||
await getMetricsTTL();
|
await getMetricsTTL();
|
||||||
await getRecordsTTL();
|
await getRecordsTTL();
|
||||||
changeDataMode();
|
// Initialize TTL handling without triggering duration update
|
||||||
|
if (coldStage.value) {
|
||||||
|
handleMetricsTTL({
|
||||||
|
minute: appStore.metricsTTL?.coldMinute ?? NaN,
|
||||||
|
hour: appStore.metricsTTL?.coldHour ?? NaN,
|
||||||
|
day: appStore.metricsTTL?.coldDay ?? NaN,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
handleMetricsTTL({
|
||||||
|
minute: appStore.metricsTTL?.minute ?? NaN,
|
||||||
|
hour: appStore.metricsTTL?.hour ?? NaN,
|
||||||
|
day: appStore.metricsTTL?.day ?? NaN,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async function getRecordsTTL() {
|
async function getRecordsTTL() {
|
||||||
const resp = await appStore.queryRecordsTTL();
|
const resp = await appStore.queryRecordsTTL();
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ const msg = {
|
|||||||
timeRange: "Time Range",
|
timeRange: "Time Range",
|
||||||
duration: "Duration",
|
duration: "Duration",
|
||||||
startTime: "Start Time",
|
startTime: "Start Time",
|
||||||
|
recoveryTime: "Recovery Time",
|
||||||
start: "Start",
|
start: "Start",
|
||||||
spans: "Spans",
|
spans: "Spans",
|
||||||
spanInfo: "Span Info",
|
spanInfo: "Span Info",
|
||||||
@@ -327,6 +328,7 @@ const msg = {
|
|||||||
message: "Message",
|
message: "Message",
|
||||||
tooltipsContent: "Tooltip Content",
|
tooltipsContent: "Tooltip Content",
|
||||||
alarmDetail: "Alarm Detail",
|
alarmDetail: "Alarm Detail",
|
||||||
|
recoveredAt: "Recovered At",
|
||||||
scope: "Scope",
|
scope: "Scope",
|
||||||
destService: "Destination Service",
|
destService: "Destination Service",
|
||||||
destServiceInstance: "Destination Service Instance",
|
destServiceInstance: "Destination Service Instance",
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ const msg = {
|
|||||||
timeRange: "Rango de Tiempo",
|
timeRange: "Rango de Tiempo",
|
||||||
duration: "Duración",
|
duration: "Duración",
|
||||||
startTime: "Hora Inicio",
|
startTime: "Hora Inicio",
|
||||||
|
recoveryTime: "Tiempo Recuperación",
|
||||||
start: "Incio",
|
start: "Incio",
|
||||||
spans: "Lapso",
|
spans: "Lapso",
|
||||||
spanInfo: "Info Lapso",
|
spanInfo: "Info Lapso",
|
||||||
@@ -324,6 +325,7 @@ const msg = {
|
|||||||
message: "Mensaje",
|
message: "Mensaje",
|
||||||
tooltipsContent: "Contenido de Información de Herramienta",
|
tooltipsContent: "Contenido de Información de Herramienta",
|
||||||
alarmDetail: "Detalle Alarma",
|
alarmDetail: "Detalle Alarma",
|
||||||
|
recoveredAt: "Recuperado En",
|
||||||
scope: "Alcance",
|
scope: "Alcance",
|
||||||
destService: "Servicio Destinación",
|
destService: "Servicio Destinación",
|
||||||
destServiceInstance: "Instancia Servicio Destinación",
|
destServiceInstance: "Instancia Servicio Destinación",
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ const titles = {
|
|||||||
"Observe services and relative direct dependencies through telemetry data collected from SkyWalking Agents.",
|
"Observe services and relative direct dependencies through telemetry data collected from SkyWalking Agents.",
|
||||||
general_service_services: "Services",
|
general_service_services: "Services",
|
||||||
general_service_services_desc: "Observe services through telemetry data collected from SkyWalking Agent.",
|
general_service_services_desc: "Observe services through telemetry data collected from SkyWalking Agent.",
|
||||||
general_service_virtual_database: "Visual Database",
|
general_service_virtual_database: "Virtual Database",
|
||||||
general_service_virtual_database_desc:
|
general_service_virtual_database_desc:
|
||||||
"Observe the virtual databases which are conjectured by language agents through various plugins.",
|
"Observe the virtual databases which are conjectured by language agents through various plugins.",
|
||||||
general_service_virtual_cache: "Visual Cache",
|
general_service_virtual_cache: "Virtual Cache",
|
||||||
general_service_virtual_cache_desc:
|
general_service_virtual_cache_desc:
|
||||||
"Observe the virtual cache servers which are conjectured by language agents through various plugins.",
|
"Observe the virtual cache servers which are conjectured by language agents through various plugins.",
|
||||||
general_service_virtual_mq: "Virtual MQ",
|
general_service_virtual_mq: "Virtual MQ",
|
||||||
@@ -144,6 +144,14 @@ const titles = {
|
|||||||
data_processing_engine_flink: "Flink",
|
data_processing_engine_flink: "Flink",
|
||||||
data_processing_engine_flink_desc:
|
data_processing_engine_flink_desc:
|
||||||
"Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.",
|
"Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.",
|
||||||
|
gen_ai: "Generative AI",
|
||||||
|
gen_ai_desc:
|
||||||
|
"Generative AI (GenAI) refers to a category of artificial intelligence that can create new content. Provide monitoring for GenAI providers and model calls.",
|
||||||
|
virtual_gen_ai: "Virtual GenAI",
|
||||||
|
virtual_gen_ai_desc:
|
||||||
|
"Observe the virtual GenAI services and models which are conjectured by language agents through various plugins.",
|
||||||
|
envoy_ai_gateway: "Envoy AI Gateway",
|
||||||
|
envoy_ai_gateway_desc: "Provide Envoy AI Gateway monitoring through OpenTelemetry OTLP metrics and access logs.",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default titles;
|
export default titles;
|
||||||
|
|||||||
@@ -146,6 +146,15 @@ const titles = {
|
|||||||
data_processing_engine_flink: "Flink",
|
data_processing_engine_flink: "Flink",
|
||||||
data_processing_engine_flink_desc:
|
data_processing_engine_flink_desc:
|
||||||
"Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.",
|
"Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.",
|
||||||
|
gen_ai: "IA Generativa",
|
||||||
|
gen_ai_desc:
|
||||||
|
"La Inteligencia Artificial Generativa (GenAI) es una categoría de IA capaz de crear contenido nuevo. Permite monitorear proveedores de GenAI e invocaciones a sus modelos.",
|
||||||
|
virtual_gen_ai: "IA Generativa Virtual",
|
||||||
|
virtual_gen_ai_desc:
|
||||||
|
"Monitorea los servicios y modelos de IA generativa virtual detectados por los agentes a través de diversos complementos (plugins).",
|
||||||
|
envoy_ai_gateway: "Puerta de Enlace de IA Envoy",
|
||||||
|
envoy_ai_gateway_desc:
|
||||||
|
"Proporciona monitoreo de Envoy AI Gateway a través de métricas OTLP y logs de acceso de OpenTelemetry.",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default titles;
|
export default titles;
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ const titles = {
|
|||||||
data_processing_engine_flink: "Flink",
|
data_processing_engine_flink: "Flink",
|
||||||
data_processing_engine_flink_desc:
|
data_processing_engine_flink_desc:
|
||||||
"Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。",
|
"Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。",
|
||||||
|
gen_ai: "生成式人工智能 (GenAI)",
|
||||||
|
gen_ai_desc: "提供对 GenAI 供应商及模型调用的性能指标、用量和成本的全面监控。",
|
||||||
|
virtual_gen_ai: "虚拟 GenAI",
|
||||||
|
virtual_gen_ai_desc: "由语言探针通过拦截 AI SDK 调用,自动推导出的虚拟 GenAI 逻辑服务与模型视图。",
|
||||||
|
envoy_ai_gateway: "Envoy AI 网关",
|
||||||
|
envoy_ai_gateway_desc: "通过 OpenTelemetry OTLP 指标和访问日志提供 Envoy AI 网关监控。",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default titles;
|
export default titles;
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ const msg = {
|
|||||||
timeRange: "时间范围",
|
timeRange: "时间范围",
|
||||||
duration: "持续时间",
|
duration: "持续时间",
|
||||||
startTime: "开始时间",
|
startTime: "开始时间",
|
||||||
|
recoveryTime: "恢复时间",
|
||||||
start: "起始点",
|
start: "起始点",
|
||||||
spans: "跨度",
|
spans: "跨度",
|
||||||
spanInfo: "跨度信息",
|
spanInfo: "跨度信息",
|
||||||
@@ -324,6 +325,7 @@ const msg = {
|
|||||||
message: "信息",
|
message: "信息",
|
||||||
tooltipsContent: "提示内容",
|
tooltipsContent: "提示内容",
|
||||||
alarmDetail: "警告详情",
|
alarmDetail: "警告详情",
|
||||||
|
recoveredAt: "恢复于",
|
||||||
scope: "范围",
|
scope: "范围",
|
||||||
destService: "终点服务",
|
destService: "终点服务",
|
||||||
destServiceInstance: "终点实例",
|
destServiceInstance: "终点实例",
|
||||||
|
|||||||
@@ -124,16 +124,6 @@ describe("Router Guards", () => {
|
|||||||
expect(mockNext).toHaveBeenCalledWith();
|
expect(mockNext).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should redirect to NotFound for routes with invalid parameters", () => {
|
|
||||||
const validationGuard = createValidationGuard();
|
|
||||||
const to = { path: "/invalid", params: { id: "", name: null } };
|
|
||||||
const from = { path: "/some-path" };
|
|
||||||
|
|
||||||
validationGuard(to, from, mockNext);
|
|
||||||
|
|
||||||
expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should redirect to NotFound for routes with undefined parameters", () => {
|
it("should redirect to NotFound for routes with undefined parameters", () => {
|
||||||
const validationGuard = createValidationGuard();
|
const validationGuard = createValidationGuard();
|
||||||
const to = { path: "/invalid", params: { id: undefined } };
|
const to = { path: "/invalid", params: { id: undefined } };
|
||||||
@@ -144,14 +134,14 @@ describe("Router Guards", () => {
|
|||||||
expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
|
expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle mixed valid and invalid parameters", () => {
|
it("should allow empty or null parameters (only undefined is invalid)", () => {
|
||||||
const validationGuard = createValidationGuard();
|
const validationGuard = createValidationGuard();
|
||||||
const to = { path: "/mixed", params: { id: "123", name: "" } };
|
const to = { path: "/mixed", params: { id: "", name: null } };
|
||||||
const from = { path: "/some-path" };
|
const from = { path: "/some-path" };
|
||||||
|
|
||||||
validationGuard(to, from, mockNext);
|
validationGuard(to, from, mockNext);
|
||||||
|
|
||||||
expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
|
expect(mockNext).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ export function createValidationGuard() {
|
|||||||
// Validate route parameters if needed
|
// Validate route parameters if needed
|
||||||
if (to.params && Object.keys(to.params).length > 0) {
|
if (to.params && Object.keys(to.params).length > 0) {
|
||||||
// Add custom validation logic here
|
// Add custom validation logic here
|
||||||
const hasValidParams = Object.values(to.params).every(
|
const hasValidParams = Object.values(to.params).every((param) => param !== undefined);
|
||||||
(param) => param !== undefined && param !== null && param !== "",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasValidParams) {
|
if (!hasValidParams) {
|
||||||
next({ name: "NotFound" });
|
next({ name: "NotFound" });
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ describe("App Store", () => {
|
|||||||
expect(store.durationRow.start).toBeInstanceOf(Date);
|
expect(store.durationRow.start).toBeInstanceOf(Date);
|
||||||
expect(store.durationRow.end).toBeInstanceOf(Date);
|
expect(store.durationRow.end).toBeInstanceOf(Date);
|
||||||
expect(store.durationRow.step).toBe(TimeType.MINUTE_TIME);
|
expect(store.durationRow.step).toBe(TimeType.MINUTE_TIME);
|
||||||
|
expect(store.durationRow.coldStage).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ describe("App Store", () => {
|
|||||||
expect(duration.start).toBeInstanceOf(Date);
|
expect(duration.start).toBeInstanceOf(Date);
|
||||||
expect(duration.end).toBeInstanceOf(Date);
|
expect(duration.end).toBeInstanceOf(Date);
|
||||||
expect(duration.step).toBe(TimeType.MINUTE_TIME);
|
expect(duration.step).toBe(TimeType.MINUTE_TIME);
|
||||||
|
expect(duration.coldStage).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return correct duration time", () => {
|
it("should return correct duration time", () => {
|
||||||
@@ -104,6 +106,7 @@ describe("App Store", () => {
|
|||||||
expect(durationTime.start).toBe("2023-01-01 12:00");
|
expect(durationTime.start).toBe("2023-01-01 12:00");
|
||||||
expect(durationTime.end).toBe("2023-01-01 12:00");
|
expect(durationTime.end).toBe("2023-01-01 12:00");
|
||||||
expect(durationTime.step).toBe(TimeType.MINUTE_TIME);
|
expect(durationTime.step).toBe(TimeType.MINUTE_TIME);
|
||||||
|
expect(durationTime.coldStage).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should calculate interval unix correctly for MINUTE", () => {
|
it("should calculate interval unix correctly for MINUTE", () => {
|
||||||
@@ -156,7 +159,7 @@ describe("App Store", () => {
|
|||||||
|
|
||||||
store.setDuration(newDuration);
|
store.setDuration(newDuration);
|
||||||
|
|
||||||
expect(store.durationRow).toEqual(newDuration);
|
expect(store.durationRow).toEqual({ ...newDuration, coldStage: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should update duration row correctly", () => {
|
it("should update duration row correctly", () => {
|
||||||
@@ -169,7 +172,7 @@ describe("App Store", () => {
|
|||||||
|
|
||||||
store.updateDurationRow(newDuration);
|
store.updateDurationRow(newDuration);
|
||||||
|
|
||||||
expect(store.durationRow).toEqual(newDuration);
|
expect(store.durationRow).toEqual({ ...newDuration, coldStage: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set max range correctly", () => {
|
it("should set max range correctly", () => {
|
||||||
@@ -231,6 +234,55 @@ describe("App Store", () => {
|
|||||||
expect(store.coldStageMode).toBe(true);
|
expect(store.coldStageMode).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should set duration with coldStage when coldStageMode is enabled", () => {
|
||||||
|
const store = appStore();
|
||||||
|
store.setColdStageMode(true);
|
||||||
|
|
||||||
|
const newDuration = {
|
||||||
|
start: new Date("2023-01-01"),
|
||||||
|
end: new Date("2023-01-02"),
|
||||||
|
step: "HOUR",
|
||||||
|
};
|
||||||
|
|
||||||
|
store.setDuration(newDuration);
|
||||||
|
|
||||||
|
expect(store.durationRow).toEqual({ ...newDuration, coldStage: true });
|
||||||
|
expect(store.duration.coldStage).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should update duration row with coldStage when coldStageMode is enabled", () => {
|
||||||
|
const store = appStore();
|
||||||
|
store.setColdStageMode(true);
|
||||||
|
|
||||||
|
const newDuration = {
|
||||||
|
start: new Date("2023-02-01"),
|
||||||
|
end: new Date("2023-02-02"),
|
||||||
|
step: "DAY",
|
||||||
|
};
|
||||||
|
|
||||||
|
store.updateDurationRow(newDuration);
|
||||||
|
|
||||||
|
expect(store.durationRow).toEqual({ ...newDuration, coldStage: true });
|
||||||
|
expect(store.duration.coldStage).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return correct duration time with coldStage when coldStageMode is enabled", () => {
|
||||||
|
const store = appStore();
|
||||||
|
store.setColdStageMode(true);
|
||||||
|
|
||||||
|
// Need to update duration row after setting cold stage mode
|
||||||
|
const newDuration = {
|
||||||
|
start: new Date("2023-01-01"),
|
||||||
|
end: new Date("2023-01-02"),
|
||||||
|
step: "HOUR",
|
||||||
|
};
|
||||||
|
store.setDuration(newDuration);
|
||||||
|
|
||||||
|
const durationTime = store.durationTime;
|
||||||
|
|
||||||
|
expect(durationTime.coldStage).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("should set reload timer correctly", () => {
|
it("should set reload timer correctly", () => {
|
||||||
const store = appStore();
|
const store = appStore();
|
||||||
const mockTimer = setInterval(() => {
|
const mockTimer = setInterval(() => {
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ import { defineStore } from "pinia";
|
|||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import type { Alarm } from "@/types/alarm";
|
import type { Alarm } from "@/types/alarm";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useDuration } from "@/hooks/useDuration";
|
||||||
|
|
||||||
|
const { getDurationTime } = useDuration();
|
||||||
|
|
||||||
interface AlarmState {
|
interface AlarmState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@@ -48,10 +50,14 @@ export const alarmStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getAlarmTagKeys() {
|
async getAlarmTagKeys() {
|
||||||
return await graphql.query("queryAlarmTagKeys").params({ duration: useAppStoreWithOut().durationTime });
|
return await graphql
|
||||||
|
.query("queryAlarmTagKeys")
|
||||||
|
.params({ duration: { ...getDurationTime(), coldStage: undefined } });
|
||||||
},
|
},
|
||||||
async getAlarmTagValues(tagKey: string) {
|
async getAlarmTagValues(tagKey: string) {
|
||||||
return await graphql.query("queryAlarmTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
return await graphql
|
||||||
|
.query("queryAlarmTagValues")
|
||||||
|
.params({ tagKey, duration: { ...getDurationTime(), coldStage: undefined } });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const InitializationDurationRow = {
|
|||||||
start: new Date(new Date().getTime() - 1800000),
|
start: new Date(new Date().getTime() - 1800000),
|
||||||
end: new Date(),
|
end: new Date(),
|
||||||
step: TimeType.MINUTE_TIME,
|
step: TimeType.MINUTE_TIME,
|
||||||
|
coldStage: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const appStore = defineStore({
|
export const appStore = defineStore({
|
||||||
@@ -62,7 +63,7 @@ export const appStore = defineStore({
|
|||||||
reloadTimer: null,
|
reloadTimer: null,
|
||||||
allMenus: [],
|
allMenus: [],
|
||||||
theme: Themes.Dark,
|
theme: Themes.Dark,
|
||||||
coldStageMode: false,
|
coldStageMode: InitializationDurationRow.coldStage || false,
|
||||||
maxRange: [],
|
maxRange: [],
|
||||||
metricsTTL: null,
|
metricsTTL: null,
|
||||||
recordsTTL: null,
|
recordsTTL: null,
|
||||||
@@ -73,6 +74,7 @@ export const appStore = defineStore({
|
|||||||
start: getLocalTime(this.utc, this.durationRow.start),
|
start: getLocalTime(this.utc, this.durationRow.start),
|
||||||
end: getLocalTime(this.utc, this.durationRow.end),
|
end: getLocalTime(this.utc, this.durationRow.end),
|
||||||
step: this.durationRow.step,
|
step: this.durationRow.step,
|
||||||
|
coldStage: this.durationRow.coldStage,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
durationTime(): DurationTime {
|
durationTime(): DurationTime {
|
||||||
@@ -80,6 +82,7 @@ export const appStore = defineStore({
|
|||||||
start: dateFormatStep(this.duration.start, this.duration.step, true),
|
start: dateFormatStep(this.duration.start, this.duration.step, true),
|
||||||
end: dateFormatStep(this.duration.end, this.duration.step, true),
|
end: dateFormatStep(this.duration.end, this.duration.step, true),
|
||||||
step: this.duration.step,
|
step: this.duration.step,
|
||||||
|
coldStage: this.duration.coldStage,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
intervalUnix(): number[] {
|
intervalUnix(): number[] {
|
||||||
@@ -124,10 +127,10 @@ export const appStore = defineStore({
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setDuration(data: Duration): void {
|
setDuration(data: Duration): void {
|
||||||
this.durationRow = data;
|
this.durationRow = { ...data, coldStage: this.coldStageMode };
|
||||||
},
|
},
|
||||||
updateDurationRow(data: Duration) {
|
updateDurationRow(data: Duration) {
|
||||||
this.durationRow = data;
|
this.durationRow = { ...data, coldStage: this.coldStageMode };
|
||||||
},
|
},
|
||||||
setMaxRange(times: Date[]) {
|
setMaxRange(times: Date[]) {
|
||||||
this.maxRange = times;
|
this.maxRange = times;
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ interface LogState {
|
|||||||
}
|
}
|
||||||
const { getDurationTime } = useDuration();
|
const { getDurationTime } = useDuration();
|
||||||
|
|
||||||
|
export const PageSizeDefault = 21;
|
||||||
|
|
||||||
export const logStore = defineStore({
|
export const logStore = defineStore({
|
||||||
id: "log",
|
id: "log",
|
||||||
state: (): LogState => ({
|
state: (): LogState => ({
|
||||||
@@ -45,7 +47,7 @@ export const logStore = defineStore({
|
|||||||
endpoints: [{ value: "0", label: "All" }],
|
endpoints: [{ value: "0", label: "All" }],
|
||||||
conditions: {
|
conditions: {
|
||||||
queryDuration: getDurationTime(),
|
queryDuration: getDurationTime(),
|
||||||
paging: { pageNum: 1, pageSize: 15 },
|
paging: { pageNum: 1, pageSize: PageSizeDefault },
|
||||||
},
|
},
|
||||||
supportQueryLogsByKeywords: true,
|
supportQueryLogsByKeywords: true,
|
||||||
selectorStore: useSelectorStore(),
|
selectorStore: useSelectorStore(),
|
||||||
@@ -61,7 +63,7 @@ export const logStore = defineStore({
|
|||||||
this.logs = [];
|
this.logs = [];
|
||||||
this.conditions = {
|
this.conditions = {
|
||||||
queryDuration: getDurationTime(),
|
queryDuration: getDurationTime(),
|
||||||
paging: { pageNum: 1, pageSize: 15 },
|
paging: { pageNum: 1, pageSize: PageSizeDefault },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setLogHeaderType(type: string) {
|
setLogHeaderType(type: string) {
|
||||||
@@ -150,10 +152,14 @@ export const logStore = defineStore({
|
|||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async getLogTagKeys() {
|
async getLogTagKeys() {
|
||||||
return await graphql.query("queryLogTagKeys").params({ duration: useAppStoreWithOut().durationTime });
|
return await graphql
|
||||||
|
.query("queryLogTagKeys")
|
||||||
|
.params({ duration: { ...getDurationTime(), coldStage: undefined } });
|
||||||
},
|
},
|
||||||
async getLogTagValues(tagKey: string) {
|
async getLogTagValues(tagKey: string) {
|
||||||
return await graphql.query("queryLogTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
return await graphql
|
||||||
|
.query("queryLogTagValues")
|
||||||
|
.params({ tagKey, duration: { ...getDurationTime(), coldStage: undefined } });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -237,10 +237,14 @@ export const traceStore = defineStore({
|
|||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async getTagKeys() {
|
async getTagKeys() {
|
||||||
return await graphql.query("queryTraceTagKeys").params({ duration: useAppStoreWithOut().durationTime });
|
return await graphql
|
||||||
|
.query("queryTraceTagKeys")
|
||||||
|
.params({ duration: { ...getDurationTime(), coldStage: undefined } });
|
||||||
},
|
},
|
||||||
async getTagValues(tagKey: string) {
|
async getTagValues(tagKey: string) {
|
||||||
return await graphql.query("queryTraceTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
return await graphql
|
||||||
|
.query("queryTraceTagValues")
|
||||||
|
.params({ tagKey, duration: { ...getDurationTime(), coldStage: undefined } });
|
||||||
},
|
},
|
||||||
async getHasQueryTracesV2Support() {
|
async getHasQueryTracesV2Support() {
|
||||||
const response = await graphql.query("queryHasQueryTracesV2Support").params({});
|
const response = await graphql.query("queryHasQueryTracesV2Support").params({});
|
||||||
|
|||||||
@@ -15,135 +15,308 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
|
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
ANIMATIONS
|
||||||
|
============================================ */
|
||||||
@keyframes topo-dash {
|
@keyframes topo-dash {
|
||||||
from {
|
from {
|
||||||
stroke-dashoffset: 10;
|
stroke-dashoffset: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
stroke-dashoffset: 0;
|
stroke-dashoffset: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes theme-fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
BASE THEME TOKENS
|
||||||
|
============================================ */
|
||||||
:root {
|
:root {
|
||||||
|
/* Brand Colors */
|
||||||
--sw-green: #70c877;
|
--sw-green: #70c877;
|
||||||
--sw-orange: #e6a23c;
|
--sw-orange: #e6a23c;
|
||||||
|
--sw-red: #e66;
|
||||||
|
--sw-blue-primary: #409eff;
|
||||||
|
|
||||||
|
/* Animation */
|
||||||
--sw-topo-animation: topo-dash 0.3s linear infinite;
|
--sw-topo-animation: topo-dash 0.3s linear infinite;
|
||||||
|
|
||||||
|
/* Timing Functions */
|
||||||
|
--sw-ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
--sw-ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||||
|
|
||||||
|
/* Transitions */
|
||||||
|
--sw-transition-fast: 150ms var(--sw-ease-smooth);
|
||||||
|
--sw-transition-base: 250ms var(--sw-ease-smooth);
|
||||||
|
--sw-transition-slow: 350ms var(--sw-ease-smooth);
|
||||||
|
|
||||||
|
/* Shadows */
|
||||||
|
--sw-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--sw-shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||||
|
--sw-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
|
--sw-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
LIGHT THEME
|
||||||
|
============================================ */
|
||||||
html {
|
html {
|
||||||
--el-color-primary: #409eff;
|
color-scheme: light;
|
||||||
|
|
||||||
|
/* === Element Plus Integration === */
|
||||||
|
--el-color-primary: var(--sw-blue-primary);
|
||||||
--el-color-info-light-9: #666;
|
--el-color-info-light-9: #666;
|
||||||
--theme-background: #fff;
|
--el-fill-color-blank: transparent;
|
||||||
--font-color: #3d444f;
|
|
||||||
--disabled-color: #ccc;
|
/* === Foundation === */
|
||||||
--dashboard-tool-bg: rgb(240 242 245);
|
--theme-background: hsl(0, 0%, 100%);
|
||||||
--text-color-placeholder: #666;
|
--layout-background: hsl(210, 20%, 98%);
|
||||||
--border-color: #dcdfe6;
|
|
||||||
--border-color-primary: #eee;
|
/* === Typography === */
|
||||||
--layout-background: #f7f9fa;
|
--font-color: hsl(220, 13%, 28%);
|
||||||
--box-shadow-color: #ccc;
|
--font-color-secondary: hsl(220, 9%, 46%);
|
||||||
--sw-bg-color-overlay: #fff;
|
--font-grey-color: hsl(220, 12%, 68%);
|
||||||
--sw-border-color-light: #e4e7ed;
|
--text-color-placeholder: hsl(0, 0%, 40%);
|
||||||
--popper-hover-bg: #eee;
|
--disabled-color: hsl(0, 0%, 80%);
|
||||||
--sw-icon-btn-bg: #eee;
|
|
||||||
--sw-icon-btn-color: #666;
|
/* === Surfaces & Overlays === */
|
||||||
--sw-icon-btn-border: #ccc;
|
--sw-bg-color-overlay: hsl(0, 0%, 100%);
|
||||||
--sw-table-col: #fff;
|
--sw-config-header: hsl(208, 100%, 97%);
|
||||||
--sw-config-header: aliceblue;
|
--dashboard-tool-bg: hsl(220, 14%, 96%);
|
||||||
--sw-topology-color: #666;
|
--sw-alarm-tool: hsl(220, 14%, 94%);
|
||||||
--vis-tooltip-bg: #fff;
|
--sw-table-header: hsl(225, 25%, 97%);
|
||||||
--sw-topology-switch-icon: rgba(0, 0, 0, 0.3);
|
|
||||||
--sw-topology-box-shadow: #eee 1px 2px 10px;
|
/* === Borders === */
|
||||||
--sw-topology-setting-bg: #fff;
|
--border-color: hsl(214, 15%, 91%);
|
||||||
--sw-topology-border: 1px solid #999;
|
--border-color-primary: hsl(0, 0%, 93%);
|
||||||
--sw-trace-success: rgb(46 47 51 / 10%);
|
--sw-border-color-light: hsl(214, 18%, 91%);
|
||||||
--sw-trace-list-border: rgb(0 0 0 / 10%);
|
--sw-alarm-tool-border: hsl(220 13% 80% / 0.25);
|
||||||
--sw-list-selected: #ededed;
|
--sw-marketplace-border: hsl(220, 5%, 87%);
|
||||||
--sw-table-header: #f3f4f9;
|
|
||||||
--sw-list-hover: rgb(0 0 0 / 4%);
|
/* === Interactive States === */
|
||||||
--sw-setting-color: #606266;
|
--sw-list-hover: hsl(0 0% 0% / 0.04);
|
||||||
--sw-alarm-tool: #f0f2f5;
|
--sw-list-selected: hsl(0, 0%, 93%);
|
||||||
--sw-alarm-tool-border: #c1c5ca41;
|
--popper-hover-bg: hsl(0, 0%, 93%);
|
||||||
--sw-table-color: #000;
|
--sw-grid-item-active: hsl(222, 13%, 85%);
|
||||||
--sw-event-vis-selected: #1a1a1a;
|
|
||||||
--sw-time-axis-text: #4d4d4d;
|
/* === Buttons & Icons === */
|
||||||
--sw-drawer-header: #72767b;
|
--sw-icon-btn-bg: hsl(0, 0%, 93%);
|
||||||
--sw-marketplace-border: #dedfe0;
|
--sw-icon-btn-color: hsl(0, 0%, 40%);
|
||||||
--sw-grid-item-active: #d4d7de;
|
--sw-icon-btn-border: hsl(0, 0%, 80%);
|
||||||
--sw-trace-line: #999;
|
|
||||||
--sw-scrollbar-track: #eee;
|
/* === Tables === */
|
||||||
--sw-scrollbar-thumb: #aaa;
|
--sw-table-col: hsl(0, 0%, 100%);
|
||||||
--sw-font-grey-color: #a7aebb;
|
--sw-table-color: hsl(0, 0%, 0%);
|
||||||
--sw-trace-list-path: rgba(0, 0, 0, 0.1);
|
--sw-setting-color: hsl(220, 18%, 38%);
|
||||||
--sw-trace-table-selected: rgba(0, 0, 0, 0.1);
|
|
||||||
|
/* === Topology === */
|
||||||
|
--sw-topology-color: hsl(0, 0%, 40%);
|
||||||
|
--sw-topology-switch-icon: hsl(0 0% 0% / 0.3);
|
||||||
|
--sw-topology-box-shadow: var(--sw-shadow-lg);
|
||||||
|
--sw-topology-setting-bg: hsl(0, 0%, 100%);
|
||||||
|
--sw-topology-border: 1px solid hsl(0, 0%, 60%);
|
||||||
|
|
||||||
|
/* === Trace & Events === */
|
||||||
|
--sw-trace-success: hsl(220 13% 18% / 0.1);
|
||||||
|
--sw-trace-list-border: hsl(0 0% 0% / 0.1);
|
||||||
|
--sw-trace-list-path: hsl(0 0% 0% / 0.1);
|
||||||
|
--sw-trace-table-selected: hsl(0 0% 0% / 0.1);
|
||||||
|
--sw-trace-line: hsl(0, 0%, 60%);
|
||||||
|
--sw-event-vis-selected: hsl(0, 0%, 10%);
|
||||||
|
--sw-time-axis-text: hsl(0, 0%, 30%);
|
||||||
|
|
||||||
|
/* === Tooltips & Popovers === */
|
||||||
|
--vis-tooltip-bg: hsl(0, 0%, 100%);
|
||||||
|
|
||||||
|
/* === Drawer & Modal === */
|
||||||
|
--sw-drawer-header: hsl(220, 9%, 46%);
|
||||||
|
|
||||||
|
/* === Scrollbars === */
|
||||||
|
--sw-scrollbar-track: hsl(0, 0%, 93%);
|
||||||
|
--sw-scrollbar-thumb: hsl(0, 0%, 67%);
|
||||||
|
|
||||||
|
/* === Shadows === */
|
||||||
|
--box-shadow-color: hsl(0, 0%, 80%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
DARK THEME
|
||||||
|
============================================ */
|
||||||
html.dark {
|
html.dark {
|
||||||
--el-color-primary: #409eff;
|
color-scheme: dark;
|
||||||
--el-color-info-light-9: #333;
|
|
||||||
--theme-background: #212224;
|
/* === Element Plus Integration === */
|
||||||
--font-color: #fafbfc;
|
--el-color-primary: var(--sw-blue-primary);
|
||||||
--disabled-color: #999;
|
--el-color-info-light-9: hsl(0, 0%, 20%);
|
||||||
--dashboard-tool-bg: #000;
|
--el-fill-color-blank: transparent;
|
||||||
--text-color-placeholder: #ccc;
|
|
||||||
--border-color: #333;
|
/* === Foundation === */
|
||||||
--border-color-primary: #4b4b52;
|
--theme-background: hsl(220, 6%, 13%);
|
||||||
--layout-background: #000;
|
--layout-background: hsl(0, 0%, 0%);
|
||||||
--box-shadow-color: #606266;
|
|
||||||
--sw-bg-color-overlay: #1d1e1f;
|
/* === Typography === */
|
||||||
--sw-border-color-light: #414243;
|
--font-color: hsl(210, 17%, 98%);
|
||||||
--popper-hover-bg: rgb(64, 158, 255, 0.1);
|
--font-color-secondary: hsl(220, 9%, 78%);
|
||||||
--sw-icon-btn-bg: #222;
|
--font-grey-color: hsl(220, 12%, 68%);
|
||||||
--sw-icon-btn-color: #ccc;
|
--text-color-placeholder: hsl(0, 0%, 80%);
|
||||||
--sw-icon-btn-border: #999;
|
--disabled-color: hsl(0, 0%, 60%);
|
||||||
|
|
||||||
|
/* === Surfaces & Overlays === */
|
||||||
|
--sw-bg-color-overlay: hsl(220, 7%, 12%);
|
||||||
|
--sw-config-header: hsl(210, 6%, 19%);
|
||||||
|
--dashboard-tool-bg: hsl(0, 0%, 0%);
|
||||||
|
--sw-alarm-tool: hsl(210, 6%, 19%);
|
||||||
|
--sw-table-header: hsl(210, 6%, 19%);
|
||||||
|
|
||||||
|
/* === Borders === */
|
||||||
|
--border-color: hsl(0, 0%, 20%);
|
||||||
|
--border-color-primary: hsl(225, 5%, 30%);
|
||||||
|
--sw-border-color-light: hsl(214, 5%, 26%);
|
||||||
|
--sw-alarm-tool-border: hsl(0, 0%, 27%);
|
||||||
|
--sw-marketplace-border: hsl(220, 7%, 38%);
|
||||||
|
|
||||||
|
/* === Interactive States === */
|
||||||
|
--sw-list-hover: hsl(220, 6%, 15%);
|
||||||
|
--sw-list-selected: hsl(220, 13%, 28%);
|
||||||
|
--popper-hover-bg: hsl(207 100% 62% / 0.1);
|
||||||
|
--sw-grid-item-active: hsl(220, 5%, 46%);
|
||||||
|
|
||||||
|
/* === Buttons & Icons === */
|
||||||
|
--sw-icon-btn-bg: hsl(0, 0%, 13%);
|
||||||
|
--sw-icon-btn-color: hsl(0, 0%, 80%);
|
||||||
|
--sw-icon-btn-border: hsl(0, 0%, 60%);
|
||||||
|
|
||||||
|
/* === Tables === */
|
||||||
--sw-table-col: none;
|
--sw-table-col: none;
|
||||||
--sw-config-header: #303133;
|
--sw-table-color: hsl(0, 0%, 100%);
|
||||||
--sw-topology-color: #ccc;
|
--sw-setting-color: hsl(0, 0%, 93%);
|
||||||
--vis-tooltip-bg: #414243;
|
|
||||||
--sw-topology-switch-icon: #999;
|
/* === Topology === */
|
||||||
--sw-topology-box-shadow: 0 0 2px 0 #444;
|
--sw-topology-color: hsl(0, 0%, 80%);
|
||||||
--sw-topology-setting-bg: #333;
|
--sw-topology-switch-icon: hsl(0, 0%, 60%);
|
||||||
--sw-topology-border: 1px solid #666;
|
--sw-topology-box-shadow: 0 0 2px 0 hsl(0, 0%, 27%);
|
||||||
--sw-trace-success: #aaa;
|
--sw-topology-setting-bg: hsl(0, 0%, 20%);
|
||||||
--sw-trace-list-border: #333133;
|
--sw-topology-border: 1px solid hsl(0, 0%, 40%);
|
||||||
--sw-list-hover: #262629;
|
|
||||||
--sw-table-header: #303133;
|
/* === Trace & Events === */
|
||||||
--sw-list-selected: #3d444f;
|
--sw-trace-success: hsl(0, 0%, 67%);
|
||||||
--sw-setting-color: #eee;
|
--sw-trace-list-border: hsl(220, 3%, 20%);
|
||||||
--sw-alarm-tool: #303133;
|
--sw-trace-list-path: hsl(0 0% 96% / 0.4);
|
||||||
--sw-alarm-tool-border: #444;
|
--sw-trace-table-selected: hsl(0 0% 100% / 0.1);
|
||||||
--sw-table-color: #fff;
|
--sw-trace-line: hsl(0, 0%, 91%);
|
||||||
--sw-event-vis-selected: #fff;
|
--sw-event-vis-selected: hsl(0, 0%, 100%);
|
||||||
--sw-time-axis-text: #aaa;
|
--sw-time-axis-text: hsl(0, 0%, 67%);
|
||||||
--sw-drawer-header: #e9e9eb;
|
|
||||||
--sw-marketplace-border: #606266;
|
/* === Tooltips & Popovers === */
|
||||||
--sw-grid-item-active: #73767a;
|
--vis-tooltip-bg: hsl(214, 5%, 26%);
|
||||||
--sw-trace-line: #e8e8e8;
|
|
||||||
--sw-scrollbar-track: #252a2f;
|
/* === Drawer & Modal === */
|
||||||
--sw-scrollbar-thumb: #888;
|
--sw-drawer-header: hsl(240, 5%, 91%);
|
||||||
--sw-font-grey-color: #a7aebb;
|
|
||||||
--sw-trace-list-path: rgba(244, 244, 244, 0.4);
|
/* === Scrollbars === */
|
||||||
--sw-trace-table-selected: rgba(255, 255, 255, 0.1);
|
--sw-scrollbar-track: hsl(210, 11%, 15%);
|
||||||
|
--sw-scrollbar-thumb: hsl(0, 0%, 53%);
|
||||||
|
|
||||||
|
/* === Shadows === */
|
||||||
|
--box-shadow-color: hsl(220, 7%, 38%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
ELEMENT PLUS OVERRIDES
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
/* === Drawer === */
|
||||||
.el-drawer__header {
|
.el-drawer__header {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-left: 10px;
|
||||||
|
font-size: 16px;
|
||||||
color: var(--sw-drawer-header);
|
color: var(--sw-drawer-header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-drawer__body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === Table === */
|
||||||
.el-table {
|
.el-table {
|
||||||
--el-table-tr-bg-color: var(--theme-background);
|
--el-table-tr-bg-color: var(--theme-background);
|
||||||
--el-table-header-bg-color: var(--theme-background);
|
--el-table-header-bg-color: var(--theme-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Popper === */
|
||||||
.el-popper.is-light {
|
.el-popper.is-light {
|
||||||
background: var(--sw-bg-color-overlay);
|
background: var(--sw-bg-color-overlay);
|
||||||
border: 1px solid var(--sw-border-color-light);
|
border: 1px solid var(--sw-border-color-light);
|
||||||
|
box-shadow: var(--sw-shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Switch === */
|
||||||
.el-switch {
|
.el-switch {
|
||||||
--el-switch-off-color: #aaa;
|
--el-switch-off-color: var(--disabled-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Menu === */
|
||||||
|
.el-menu {
|
||||||
|
--el-menu-item-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item-group__title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-sub-menu {
|
||||||
|
.el-menu-item {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
padding: 0 0 0 56px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-sub-menu__title {
|
||||||
|
.el-icon.menu-icons {
|
||||||
|
margin-top: -5px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === Input === */
|
||||||
|
.el-input-number .el-input__inner {
|
||||||
|
text-align: left !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input--small .el-input__inner {
|
||||||
|
--el-input-inner-height: calc(var(--el-input-height, 24px));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === Loading === */
|
||||||
|
.el-loading-mask {
|
||||||
|
background-color: var(--theme-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
|
||||||
|
.el-loading-mask {
|
||||||
|
backdrop-filter: blur(1px);
|
||||||
|
-webkit-backdrop-filter: blur(1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-transparency: reduce), (prefers-reduced-motion: reduce) {
|
||||||
|
.el-loading-mask {
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* ============================================
|
||||||
|
SCSS VARIABLES (Legacy Support)
|
||||||
|
============================================ */
|
||||||
$tool-icon-btn-bg: var(--sw-icon-btn-bg);
|
$tool-icon-btn-bg: var(--sw-icon-btn-bg);
|
||||||
$tool-icon-btn-color: var(--sw-icon-btn-color);
|
$tool-icon-btn-color: var(--sw-icon-btn-color);
|
||||||
$popper-hover-bg-color: var(--popper-hover-bg);
|
$popper-hover-bg-color: var(--popper-hover-bg);
|
||||||
@@ -160,90 +333,26 @@ $theme-background: var(--theme-background);
|
|||||||
$active-background: var(--el-color-primary);
|
$active-background: var(--el-color-primary);
|
||||||
$font-size-smaller: 12px;
|
$font-size-smaller: 12px;
|
||||||
$font-size-normal: 14px;
|
$font-size-normal: 14px;
|
||||||
$error-color: #e66;
|
$error-color: var(--sw-red);
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
COMPONENT STYLES
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
/* === Interactive Elements === */
|
||||||
|
.opt {
|
||||||
|
transition: background-color var(--sw-transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
.opt:hover {
|
.opt:hover {
|
||||||
background-color: var(--sw-list-hover) !important;
|
background-color: var(--sw-list-hover) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-loading-mask {
|
|
||||||
background-color: var(--theme-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-menu {
|
|
||||||
--el-menu-item-height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-menu-item-group__title {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-sub-menu .el-menu-item {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
padding: 0 0 0 56px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-sub-menu__title {
|
|
||||||
.el-icon.menu-icons {
|
|
||||||
margin-top: -5px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-drawer__header {
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding-left: 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-drawer__body {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch {
|
.switch {
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.vis-tooltip {
|
/* === Menu Visibility === */
|
||||||
max-width: 600px;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: var(--vis-tooltip-bg) !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
font-size: $font-size-smaller !important;
|
|
||||||
color: var(--font-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-item {
|
|
||||||
cursor: pointer;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-item.Error {
|
|
||||||
background-color: $error-color;
|
|
||||||
opacity: 0.8;
|
|
||||||
border-color: $error-color;
|
|
||||||
color: var(--sw-event-vis-selected) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-item.Normal {
|
|
||||||
background-color: #fac858;
|
|
||||||
border-color: #fac858;
|
|
||||||
color: var(--sw-event-vis-selected) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-item .vis-item-content {
|
|
||||||
padding: 0 3px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-item.vis-selected.Error,
|
|
||||||
.vis-item.vis-selected.Normal {
|
|
||||||
color: var(--sw-event-vis-selected) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-time-axis .vis-text {
|
|
||||||
color: var(--sw-time-axis-text) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-menu--vertical.sub-list {
|
.el-menu--vertical.sub-list {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -252,34 +361,149 @@ div:has(> a.menu-title) {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-input-number .el-input__inner {
|
/* ============================================
|
||||||
text-align: left !important;
|
VIS.JS TIMELINE CUSTOMIZATION
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
/* === Tooltip === */
|
||||||
|
div.vis-tooltip {
|
||||||
|
max-width: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--vis-tooltip-bg) !important;
|
||||||
|
border: 1px solid var(--border-color) !important;
|
||||||
|
box-shadow: var(--sw-shadow-md) !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
font-size: $font-size-smaller !important;
|
||||||
|
color: var(--font-color) !important;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-input--small .el-input__inner {
|
/* === Timeline Items === */
|
||||||
--el-input-inner-height: calc(var(--el-input-height, 24px));
|
.vis-item {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: transform var(--sw-transition-fast), box-shadow var(--sw-transition-fast);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: var(--sw-shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Error {
|
||||||
|
background-color: $error-color;
|
||||||
|
opacity: 0.8;
|
||||||
|
border-color: $error-color;
|
||||||
|
color: var(--sw-event-vis-selected) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Normal {
|
||||||
|
background-color: #fac858;
|
||||||
|
border-color: #fac858;
|
||||||
|
color: var(--sw-event-vis-selected) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item-content {
|
||||||
|
padding: 0 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.vis-selected {
|
||||||
|
&.Error,
|
||||||
|
&.Normal {
|
||||||
|
color: var(--sw-event-vis-selected) !important;
|
||||||
|
box-shadow: var(--sw-shadow-base);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Time Axis === */
|
||||||
|
.vis-time-axis .vis-text {
|
||||||
|
color: var(--sw-time-axis-text) !important;
|
||||||
|
font-size: $font-size-smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
VIEW TRANSITIONS
|
||||||
|
============================================ */
|
||||||
html {
|
html {
|
||||||
|
/* Smooth theme switching with fade */
|
||||||
&::view-transition-old(root),
|
&::view-transition-old(root),
|
||||||
&::view-transition-new(root) {
|
&::view-transition-new(root) {
|
||||||
animation: none;
|
animation: none;
|
||||||
mix-blend-mode: normal;
|
mix-blend-mode: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Light to Dark: Fade out light, fade in dark */
|
||||||
&.dark {
|
&.dark {
|
||||||
&::view-transition-old(root) {
|
&::view-transition-old(root) {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
animation: theme-fade-out 0.35s var(--sw-ease-smooth);
|
||||||
}
|
}
|
||||||
&::view-transition-new(root) {
|
&::view-transition-new(root) {
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
animation: theme-fade-in 0.35s var(--sw-ease-smooth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark to Light: Fade out dark, fade in light */
|
||||||
&::view-transition-old(root) {
|
&::view-transition-old(root) {
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
animation: theme-fade-out 0.35s var(--sw-ease-smooth);
|
||||||
}
|
}
|
||||||
&::view-transition-new(root) {
|
&::view-transition-new(root) {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
animation: theme-fade-in 0.35s var(--sw-ease-smooth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes theme-fade-out {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
ACCESSIBILITY: REDUCED MOTION
|
||||||
|
============================================ */
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
/* Disable view transition animations */
|
||||||
|
html {
|
||||||
|
&::view-transition-old(root),
|
||||||
|
&::view-transition-new(root) {
|
||||||
|
animation: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark {
|
||||||
|
&::view-transition-old(root),
|
||||||
|
&::view-transition-new(root) {
|
||||||
|
animation: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable component animations */
|
||||||
|
.vis-item {
|
||||||
|
transition: none !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opt:hover {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable all keyframe animations */
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,25 +36,29 @@ Object.defineProperty(window, "matchMedia", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Mock ResizeObserver
|
// Mock ResizeObserver
|
||||||
global.ResizeObserver = vi.fn().mockImplementation(() => ({
|
globalThis.ResizeObserver = class ResizeObserver {
|
||||||
observe: vi.fn(),
|
observe = vi.fn();
|
||||||
unobserve: vi.fn(),
|
unobserve = vi.fn();
|
||||||
disconnect: vi.fn(),
|
disconnect = vi.fn();
|
||||||
}));
|
};
|
||||||
|
|
||||||
// Mock IntersectionObserver
|
// Mock IntersectionObserver
|
||||||
global.IntersectionObserver = vi.fn().mockImplementation(() => ({
|
globalThis.IntersectionObserver = class IntersectionObserver {
|
||||||
observe: vi.fn(),
|
root = null;
|
||||||
unobserve: vi.fn(),
|
rootMargin = "";
|
||||||
disconnect: vi.fn(),
|
thresholds = [];
|
||||||
}));
|
observe = vi.fn();
|
||||||
|
unobserve = vi.fn();
|
||||||
|
disconnect = vi.fn();
|
||||||
|
takeRecords = vi.fn(() => []);
|
||||||
|
} as any;
|
||||||
|
|
||||||
// Mock requestAnimationFrame
|
// Mock requestAnimationFrame
|
||||||
global.requestAnimationFrame = vi.fn((cb: FrameRequestCallback) => {
|
globalThis.requestAnimationFrame = vi.fn((cb: FrameRequestCallback) => {
|
||||||
const id = setTimeout(cb, 0);
|
const id = setTimeout(cb, 0);
|
||||||
return id as unknown as number;
|
return id as unknown as number;
|
||||||
});
|
});
|
||||||
global.cancelAnimationFrame = vi.fn();
|
globalThis.cancelAnimationFrame = vi.fn();
|
||||||
|
|
||||||
// Configure Vue Test Utils
|
// Configure Vue Test Utils
|
||||||
config.global.plugins = [ElementPlus];
|
config.global.plugins = [ElementPlus];
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface Alarm {
|
|||||||
message: string;
|
message: string;
|
||||||
key: string;
|
key: string;
|
||||||
startTime: string;
|
startTime: string;
|
||||||
|
recoveryTime: string;
|
||||||
scope: string;
|
scope: string;
|
||||||
tags: Array<{ key: string; value: string }>;
|
tags: Array<{ key: string; value: string }>;
|
||||||
events: Event[];
|
events: Event[];
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ export interface Duration {
|
|||||||
start: Date;
|
start: Date;
|
||||||
end: Date;
|
end: Date;
|
||||||
step: string;
|
step: string;
|
||||||
|
coldStage?: boolean;
|
||||||
}
|
}
|
||||||
export interface DurationTime {
|
export interface DurationTime {
|
||||||
start: string;
|
start: string;
|
||||||
end: string;
|
end: string;
|
||||||
step: string;
|
step: string;
|
||||||
|
coldStage?: boolean;
|
||||||
}
|
}
|
||||||
export type Paging = {
|
export type Paging = {
|
||||||
pageNum: number;
|
pageNum: number;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="timeline-table clear" v-loading="alarmStore.loading">
|
<div class="timeline-table clear" v-loading="alarmStore.loading">
|
||||||
<div v-for="(i, index) in alarmStore.alarms" :key="index" class="clear timeline-item">
|
<div v-for="(i, index) in displayAlarms" :key="index" class="clear timeline-item">
|
||||||
<div class="g-sm-3 grey sm hide-xs time-line tr">
|
<div class="g-sm-3 grey sm hide-xs time-line tr">
|
||||||
{{ dateFormat(parseInt(i.startTime)) }}
|
{{ dateFormat(parseInt(i.startTime)) }}
|
||||||
</div>
|
</div>
|
||||||
@@ -37,9 +37,12 @@ limitations under the License. -->
|
|||||||
<div class="grey sm show-xs">
|
<div class="grey sm show-xs">
|
||||||
{{ dateFormat(parseInt(i.startTime)) }}
|
{{ dateFormat(parseInt(i.startTime)) }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grey sm" v-if="i.recoveryTime">
|
||||||
|
{{ t("recoveredAt") }} {{ dateFormat(parseInt(i.recoveryTime)) }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!alarmStore.alarms.length" class="tips">{{ t("noData") }}</div>
|
<div v-if="!displayAlarms.length" class="tips">{{ t("noData") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="isShowDetails"
|
v-model="isShowDetails"
|
||||||
@@ -53,6 +56,9 @@ limitations under the License. -->
|
|||||||
<span v-if="item.label === 'startTime'">
|
<span v-if="item.label === 'startTime'">
|
||||||
{{ dateFormat(currentDetail[item.label]) }}
|
{{ dateFormat(currentDetail[item.label]) }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else-if="item.label === 'recoveryTime'">
|
||||||
|
{{ currentDetail[item.label] ? dateFormat(currentDetail[item.label]) : "" }}
|
||||||
|
</span>
|
||||||
<span v-else-if="item.label === 'tags'">
|
<span v-else-if="item.label === 'tags'">
|
||||||
<div v-for="(d, index) in alarmTags" :key="index">{{ d }}</div>
|
<div v-for="(d, index) in alarmTags" :key="index">{{ d }}</div>
|
||||||
</span>
|
</span>
|
||||||
@@ -119,11 +125,11 @@ limitations under the License. -->
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref, computed } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import type { Alarm, Event } from "@/types/alarm";
|
import type { Alarm, Event } from "@/types/alarm";
|
||||||
import { useAlarmStore } from "@/store/modules/alarm";
|
import { useAlarmStore } from "@/store/modules/alarm";
|
||||||
import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys } from "./data";
|
import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys, PageSizeDefaultAlarm } from "./data";
|
||||||
import { dateFormat } from "@/utils/dateFormat";
|
import { dateFormat } from "@/utils/dateFormat";
|
||||||
import Snapshot from "./components/Snapshot.vue";
|
import Snapshot from "./components/Snapshot.vue";
|
||||||
|
|
||||||
@@ -135,6 +141,11 @@ limitations under the License. -->
|
|||||||
const alarmTags = ref<string[]>([]);
|
const alarmTags = ref<string[]>([]);
|
||||||
const currentEvents = ref<any[]>([]);
|
const currentEvents = ref<any[]>([]);
|
||||||
const currentEvent = ref<Event | any>({});
|
const currentEvent = ref<Event | any>({});
|
||||||
|
const pageSize = PageSizeDefaultAlarm;
|
||||||
|
|
||||||
|
const displayAlarms = computed(() =>
|
||||||
|
alarmStore.alarms.length >= pageSize ? alarmStore.alarms.slice(0, pageSize - 1) : alarmStore.alarms,
|
||||||
|
);
|
||||||
|
|
||||||
function showDetails(item: Alarm) {
|
function showDetails(item: Alarm) {
|
||||||
isShowDetails.value = true;
|
isShowDetails.value = true;
|
||||||
|
|||||||
@@ -41,19 +41,11 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<el-pagination
|
<Pagination
|
||||||
v-model="pageNum"
|
v-model:currentPage="pageNum"
|
||||||
:page-size="pageSize"
|
:pageSize="pageSize"
|
||||||
layout="prev, pager, next"
|
:total="alarmStore.alarms.length"
|
||||||
:total="total"
|
@change="changePage"
|
||||||
@current-change="changePage"
|
|
||||||
:pager-count="5"
|
|
||||||
size="small"
|
|
||||||
:style="
|
|
||||||
appStore.theme === Themes.Light
|
|
||||||
? `--el-pagination-bg-color: #f0f2f5; --el-pagination-button-disabled-bg-color: #f0f2f5;`
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,19 +62,19 @@ limitations under the License. -->
|
|||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import ConditionTags from "@/views/components/ConditionTags.vue";
|
import ConditionTags from "@/views/components/ConditionTags.vue";
|
||||||
import { AlarmOptions } from "./data";
|
import Pagination from "@/views/components/Pagination.vue";
|
||||||
|
import { AlarmOptions, PageSizeDefaultAlarm } from "./data";
|
||||||
import { useAppStoreWithOut, InitializationDurationRow } from "@/store/modules/app";
|
import { useAppStoreWithOut, InitializationDurationRow } from "@/store/modules/app";
|
||||||
import { useAlarmStore } from "@/store/modules/alarm";
|
import { useAlarmStore } from "@/store/modules/alarm";
|
||||||
import { useDuration } from "@/hooks/useDuration";
|
import { useDuration } from "@/hooks/useDuration";
|
||||||
import timeFormat from "@/utils/timeFormat";
|
import timeFormat from "@/utils/timeFormat";
|
||||||
import type { DurationTime, Duration } from "@/types/app";
|
import type { DurationTime, Duration } from "@/types/app";
|
||||||
import { Themes } from "@/constants/data";
|
|
||||||
/*global Indexable */
|
/*global Indexable */
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const alarmStore = useAlarmStore();
|
const alarmStore = useAlarmStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { setDurationRow, getDurationTime, getMaxRange } = useDuration();
|
const { setDurationRow, getDurationTime, getMaxRange } = useDuration();
|
||||||
const pageSize = 20;
|
const pageSize = PageSizeDefaultAlarm;
|
||||||
const entity = ref<string>("");
|
const entity = ref<string>("");
|
||||||
const keyword = ref<string>("");
|
const keyword = ref<string>("");
|
||||||
const pageNum = ref<number>(1);
|
const pageNum = ref<number>(1);
|
||||||
@@ -90,9 +82,6 @@ limitations under the License. -->
|
|||||||
const durationRow = ref<Duration>(InitializationDurationRow);
|
const durationRow = ref<Duration>(InitializationDurationRow);
|
||||||
const tagsMap = ref<{ key: string; value: string }[]>();
|
const tagsMap = ref<{ key: string; value: string }[]>();
|
||||||
|
|
||||||
const total = computed(() =>
|
|
||||||
alarmStore.alarms.length === pageSize ? pageSize * pageNum.value + 1 : pageSize * pageNum.value,
|
|
||||||
);
|
|
||||||
const maxRange = computed(() =>
|
const maxRange = computed(() =>
|
||||||
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL?.coldNormal || 0 : appStore.recordsTTL?.normal || 0),
|
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL?.coldNormal || 0 : appStore.recordsTTL?.normal || 0),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
export const PageSizeDefaultAlarm = 21;
|
||||||
|
|
||||||
export const AlarmOptions = [
|
export const AlarmOptions = [
|
||||||
{ label: "All", value: "" },
|
{ label: "All", value: "" },
|
||||||
{ label: "Service", value: "Service" },
|
{ label: "Service", value: "Service" },
|
||||||
@@ -40,6 +42,10 @@ export const AlarmDetailCol = [
|
|||||||
label: "startTime",
|
label: "startTime",
|
||||||
value: "startTime",
|
value: "startTime",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "recoveryTime",
|
||||||
|
value: "recoveryTime",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "tags",
|
label: "tags",
|
||||||
value: "tags",
|
value: "tags",
|
||||||
|
|||||||
102
src/views/components/Pagination.vue
Normal file
102
src/views/components/Pagination.vue
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<!-- 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="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="currentPageModel"
|
||||||
|
:page-size="displayPageSize"
|
||||||
|
size="small"
|
||||||
|
layout="prev, pager, next"
|
||||||
|
:total="computedTotal"
|
||||||
|
:pager-count="pagerCount"
|
||||||
|
@current-change="handlePageChange"
|
||||||
|
:style="paginationStyle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
/*global defineProps, defineEmits*/
|
||||||
|
const props = defineProps({
|
||||||
|
currentPage: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
pageSize: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
pagerCount: {
|
||||||
|
type: Number,
|
||||||
|
default: 5,
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
type: String as () => "left" | "center" | "right",
|
||||||
|
default: "right",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: "update:currentPage", page: number): void;
|
||||||
|
(e: "change", page: number): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// The display page size is pageSize - 1 because we fetch pageSize items
|
||||||
|
// but the last item is only used to check if there are more pages
|
||||||
|
const displayPageSize = computed(() => props.pageSize - 1);
|
||||||
|
|
||||||
|
// Calculate total for pagination display based on fetched items
|
||||||
|
// If we fetched pageSize items, there might be more pages
|
||||||
|
const computedTotal = computed(() => {
|
||||||
|
if (props.total >= props.pageSize) {
|
||||||
|
return displayPageSize.value * props.currentPage + 1;
|
||||||
|
}
|
||||||
|
return displayPageSize.value * props.currentPage;
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentPageModel = computed({
|
||||||
|
get: () => props.currentPage,
|
||||||
|
set: (val: number) => {
|
||||||
|
void val;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const paginationStyle = computed(() => {
|
||||||
|
const alignMap = {
|
||||||
|
left: "flex-start",
|
||||||
|
center: "center",
|
||||||
|
right: "flex-end",
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: alignMap[props.align],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function handlePageChange(page: number) {
|
||||||
|
emits("update:currentPage", page);
|
||||||
|
emits("change", page);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.pagination-container {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -539,8 +539,8 @@ limitations under the License. -->
|
|||||||
cancelButtonText: "Cancel",
|
cancelButtonText: "Cancel",
|
||||||
inputValue: row.name,
|
inputValue: row.name,
|
||||||
})
|
})
|
||||||
.then(({ value }) => {
|
.then(() => {
|
||||||
updateName(row, value);
|
updateName(row);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
@@ -549,8 +549,8 @@ limitations under the License. -->
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function updateName(d: DashboardItem, value: string) {
|
async function updateName(d: DashboardItem) {
|
||||||
if (new RegExp(/\s/).test(value)) {
|
if (new RegExp(/\s/).test(d.name)) {
|
||||||
ElMessage.error("The name cannot contain spaces, carriage returns, etc");
|
ElMessage.error("The name cannot contain spaces, carriage returns, etc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -559,7 +559,7 @@ limitations under the License. -->
|
|||||||
const c = {
|
const c = {
|
||||||
...JSON.parse(layout).configuration,
|
...JSON.parse(layout).configuration,
|
||||||
...d,
|
...d,
|
||||||
name: value,
|
name: d.name,
|
||||||
};
|
};
|
||||||
delete c.id;
|
delete c.id;
|
||||||
delete c.filters;
|
delete c.filters;
|
||||||
@@ -575,7 +575,7 @@ limitations under the License. -->
|
|||||||
}
|
}
|
||||||
dashboardStore.setCurrentDashboard({
|
dashboardStore.setCurrentDashboard({
|
||||||
...d,
|
...d,
|
||||||
name: value,
|
name: d.name,
|
||||||
});
|
});
|
||||||
dashboards.value = dashboardStore.dashboards.map((item: DashboardItem) => {
|
dashboards.value = dashboardStore.dashboards.map((item: DashboardItem) => {
|
||||||
if (dashboardStore.currentDashboard?.id === item.id) {
|
if (dashboardStore.currentDashboard?.id === item.id) {
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ limitations under the License. -->
|
|||||||
ElMessage.error("No this dashboard");
|
ElMessage.error("No this dashboard");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
selectorStore.setCurrentService(scope.row);
|
||||||
const path = `/dashboard/${dashboard.layer}/${dashboard.entity}/${scope.row.id}/${dashboard.name}`;
|
const path = `/dashboard/${dashboard.layer}/${dashboard.entity}/${scope.row.id}/${dashboard.name}`;
|
||||||
|
|
||||||
router.push(path);
|
router.push(path);
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ limitations under the License. -->
|
|||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useLogStore } from "@/store/modules/log";
|
import { useLogStore, PageSizeDefault } from "@/store/modules/log";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useAppStoreWithOut, InitializationDurationRow } from "@/store/modules/app";
|
import { useAppStoreWithOut, InitializationDurationRow } from "@/store/modules/app";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
@@ -274,7 +274,7 @@ limitations under the License. -->
|
|||||||
serviceId: selectorStore.currentService ? selectorStore.currentService.id : state.service.id,
|
serviceId: selectorStore.currentService ? selectorStore.currentService.id : state.service.id,
|
||||||
pagePathId: endpoint || state.endpoint.id || undefined,
|
pagePathId: endpoint || state.endpoint.id || undefined,
|
||||||
serviceVersionId: instance || state.instance.id || undefined,
|
serviceVersionId: instance || state.instance.id || undefined,
|
||||||
paging: { pageNum: 1, pageSize: 15 },
|
paging: { pageNum: 1, pageSize: PageSizeDefault },
|
||||||
queryDuration: duration,
|
queryDuration: duration,
|
||||||
category: state.category.value,
|
category: state.category.value,
|
||||||
});
|
});
|
||||||
@@ -292,7 +292,7 @@ limitations under the License. -->
|
|||||||
keywordsOfContent: keywordsOfContent.value,
|
keywordsOfContent: keywordsOfContent.value,
|
||||||
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
|
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
|
||||||
tags: tagsMap.value.length ? tagsMap.value : undefined,
|
tags: tagsMap.value.length ? tagsMap.value : undefined,
|
||||||
paging: { pageNum: 1, pageSize: 15 },
|
paging: { pageNum: 1, pageSize: PageSizeDefault },
|
||||||
relatedTrace: traceId.value ? { traceId: traceId.value, segmentId, spanId } : undefined,
|
relatedTrace: traceId.value ? { traceId: traceId.value, segmentId, spanId } : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,21 +14,15 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<LogTable v-loading="logStore.loadLogs" :tableData="logStore.logs || []" :type="type" :noLink="false" :data="data">
|
<LogTable v-loading="logStore.loadLogs" :tableData="displayLogs" :type="type" :noLink="false" :data="data">
|
||||||
<div class="log-tips" v-if="!logStore.logs.length">{{ t("noData") }}</div>
|
<div class="log-tips" v-if="!logStore.logs.length">{{ t("noData") }}</div>
|
||||||
</LogTable>
|
</LogTable>
|
||||||
<div class="mt-5 mb-5">
|
<Pagination
|
||||||
<el-pagination
|
v-model:currentPage="logStore.conditions.paging.pageNum"
|
||||||
v-model="logStore.conditions.paging.pageNum"
|
:pageSize="pageSize"
|
||||||
:page-size="pageSize"
|
:total="logStore.logs.length"
|
||||||
size="small"
|
@change="updatePage"
|
||||||
layout="prev, pager, next"
|
/>
|
||||||
:pager-count="5"
|
|
||||||
:total="total"
|
|
||||||
@current-change="updatePage"
|
|
||||||
:style="`float: right`"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -37,7 +31,8 @@ limitations under the License. -->
|
|||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import type { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig } from "@/types/dashboard";
|
||||||
import LogTable from "./LogTable/Index.vue";
|
import LogTable from "./LogTable/Index.vue";
|
||||||
import { useLogStore } from "@/store/modules/log";
|
import Pagination from "@/views/components/Pagination.vue";
|
||||||
|
import { useLogStore, PageSizeDefault } from "@/store/modules/log";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
@@ -54,15 +49,13 @@ limitations under the License. -->
|
|||||||
const logStore = useLogStore();
|
const logStore = useLogStore();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const type = ref<string>(dashboardStore.layerId === "BROWSER" ? "browser" : "service");
|
const type = ref<string>(dashboardStore.layerId === "BROWSER" ? "browser" : "service");
|
||||||
const pageSize = ref<number>(15);
|
const pageSize = PageSizeDefault;
|
||||||
const total = computed(() =>
|
const displayLogs = computed(() =>
|
||||||
logStore.logs.length === pageSize.value
|
logStore.logs.length === pageSize ? logStore.logs.slice(0, pageSize - 1) : logStore.logs,
|
||||||
? pageSize.value * logStore.conditions.paging.pageNum + 1
|
|
||||||
: pageSize.value * logStore.conditions.paging.pageNum,
|
|
||||||
);
|
);
|
||||||
function updatePage(p: number) {
|
function updatePage(p: number) {
|
||||||
logStore.setLogCondition({
|
logStore.setLogCondition({
|
||||||
paging: { pageNum: p, pageSize: pageSize.value },
|
paging: { pageNum: p, pageSize: pageSize },
|
||||||
});
|
});
|
||||||
queryLogs();
|
queryLogs();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ limitations under the License. -->
|
|||||||
selectedMinTimestamp: props.selectedMinTimestamp,
|
selectedMinTimestamp: props.selectedMinTimestamp,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
tree.value.draw(() => {
|
tree.value?.draw(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ limitations under the License. -->
|
|||||||
import { EntityType, QueryOrders, Status } from "@/views/dashboard/data";
|
import { EntityType, QueryOrders, Status } from "@/views/dashboard/data";
|
||||||
import type { LayoutConfig, FilterDuration } from "@/types/dashboard";
|
import type { LayoutConfig, FilterDuration } from "@/types/dashboard";
|
||||||
import { useDuration } from "@/hooks/useDuration";
|
import { useDuration } from "@/hooks/useDuration";
|
||||||
|
import { TimeType } from "@/constants/data";
|
||||||
|
|
||||||
/*global defineProps, defineEmits, Recordable */
|
/*global defineProps, defineEmits, Recordable */
|
||||||
const emits = defineEmits(["get", "search"]);
|
const emits = defineEmits(["get", "search"]);
|
||||||
@@ -126,7 +127,7 @@ limitations under the License. -->
|
|||||||
const { duration: filtersDuration } = filters.value;
|
const { duration: filtersDuration } = filters.value;
|
||||||
const duration = ref<DurationTime | FilterDuration>(
|
const duration = ref<DurationTime | FilterDuration>(
|
||||||
filtersDuration
|
filtersDuration
|
||||||
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: filtersDuration.step || "" }
|
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: TimeType.SECOND_TIME }
|
||||||
: getDurationTime(),
|
: getDurationTime(),
|
||||||
);
|
);
|
||||||
const minTraceDuration = ref<number>();
|
const minTraceDuration = ref<number>();
|
||||||
@@ -152,7 +153,6 @@ limitations under the License. -->
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
duration.value = filters.value.duration || appStore.durationTime;
|
|
||||||
if (dashboardStore.entity === EntityType[1].value) {
|
if (dashboardStore.entity === EntityType[1].value) {
|
||||||
await getServices();
|
await getServices();
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ limitations under the License. -->
|
|||||||
? {
|
? {
|
||||||
start: filtersDuration.startTime || "",
|
start: filtersDuration.startTime || "",
|
||||||
end: filtersDuration.endTime || "",
|
end: filtersDuration.endTime || "",
|
||||||
step: filtersDuration.step || "",
|
step: TimeType.SECOND_TIME,
|
||||||
}
|
}
|
||||||
: getDurationTime();
|
: getDurationTime();
|
||||||
init();
|
init();
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ limitations under the License. -->
|
|||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { EntityType, QueryOrders, Status } from "@/views/dashboard/data";
|
import { EntityType, QueryOrders, Status } from "@/views/dashboard/data";
|
||||||
import type { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig } from "@/types/dashboard";
|
||||||
|
import { TimeType } from "@/constants/data";
|
||||||
|
import { useDuration } from "@/hooks/useDuration";
|
||||||
|
|
||||||
const FiltersKeys: { [key: string]: string } = {
|
const FiltersKeys: { [key: string]: string } = {
|
||||||
status: "traceState",
|
status: "traceState",
|
||||||
@@ -130,10 +132,11 @@ limitations under the License. -->
|
|||||||
const tagsMap = ref<Option[]>([]);
|
const tagsMap = ref<Option[]>([]);
|
||||||
const traceId = ref<string>(filters.refId || "");
|
const traceId = ref<string>(filters.refId || "");
|
||||||
const { duration: filtersDuration } = props.data.filters || {};
|
const { duration: filtersDuration } = props.data.filters || {};
|
||||||
|
const { getDurationTime } = useDuration();
|
||||||
const duration = ref<DurationTime>(
|
const duration = ref<DurationTime>(
|
||||||
filtersDuration
|
filtersDuration
|
||||||
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: filtersDuration.step || "" }
|
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: TimeType.SECOND_TIME }
|
||||||
: appStore.durationTime,
|
: getDurationTime(),
|
||||||
);
|
);
|
||||||
const state = reactive<Recordable>({
|
const state = reactive<Recordable>({
|
||||||
instance: "",
|
instance: "",
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ export enum TraceGraphType {
|
|||||||
export const GraphTypeOptions = [
|
export const GraphTypeOptions = [
|
||||||
{ value: "List", icon: "list-bulleted", label: "list" },
|
{ value: "List", icon: "list-bulleted", label: "list" },
|
||||||
{ value: "Tree", icon: "issue-child", label: "tree" },
|
{ value: "Tree", icon: "issue-child", label: "tree" },
|
||||||
{ value: "Table", icon: "table", label: "table" },
|
{ value: "Table", icon: "list-tree", label: "table" },
|
||||||
{ value: "Statistics", icon: "statistics-bulleted", label: "statistics" },
|
{ value: "Statistics", icon: "statistics-bulleted", label: "statistics" },
|
||||||
] as const;
|
] as const;
|
||||||
|
|||||||
Reference in New Issue
Block a user