Compare commits
106 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
56a02293cf | ||
![]() |
b7115a4e47 | ||
![]() |
6b1a2fa9f8 | ||
![]() |
ce4608ad4b | ||
![]() |
dce1035f2e | ||
![]() |
60a4232759 | ||
![]() |
8c1ddb109c | ||
![]() |
08db5a0440 | ||
![]() |
344f2a6608 | ||
![]() |
39c584bce6 | ||
![]() |
eb0b860c3a | ||
![]() |
1e55eb2029 | ||
![]() |
90505810ab | ||
![]() |
169793bdff | ||
![]() |
3bdd1d1c67 | ||
![]() |
7478ec85b1 | ||
![]() |
115deecff1 | ||
![]() |
077b68ebbd | ||
![]() |
5367af47c4 | ||
![]() |
a521e041a7 | ||
![]() |
64293da11c | ||
![]() |
30a9cb1c87 | ||
![]() |
9827b6766a | ||
![]() |
9ac1265e7f | ||
![]() |
63db3fbc2e | ||
![]() |
cc367dd29c | ||
![]() |
1ba56ca0cd | ||
![]() |
6c4991bc56 | ||
![]() |
77c1694383 | ||
![]() |
7fe3257c32 | ||
![]() |
8c9c339417 | ||
![]() |
62a82590c9 | ||
![]() |
22db68646c | ||
![]() |
7738695601 | ||
![]() |
9b1a5f7a74 | ||
![]() |
54997794b4 | ||
![]() |
372aee2eb6 | ||
![]() |
d662a0fb54 | ||
![]() |
b293f4ddb5 | ||
![]() |
279ec60915 | ||
![]() |
05688f0888 | ||
![]() |
15cd839480 | ||
![]() |
dc22f8da6e | ||
![]() |
ec67b4148c | ||
![]() |
986fe8b90e | ||
![]() |
fe28fae27d | ||
![]() |
359197a1c5 | ||
![]() |
903cf8e9bd | ||
![]() |
921c961dc1 | ||
![]() |
d129c75c8c | ||
![]() |
a4a2c4fefc | ||
![]() |
7dde4820de | ||
![]() |
7257858921 | ||
![]() |
ce585d6e08 | ||
![]() |
3f178f89f8 | ||
![]() |
ceae10cbfa | ||
![]() |
49a5481fb0 | ||
![]() |
8bb45bb453 | ||
![]() |
8077043c7e | ||
![]() |
0e15c023cc | ||
![]() |
55e4828adc | ||
![]() |
68eea52e88 | ||
![]() |
5973632f0f | ||
![]() |
1d189e82a7 | ||
![]() |
2491ab7176 | ||
![]() |
449dccdf36 | ||
![]() |
8031c1b463 | ||
![]() |
1c905aeb06 | ||
![]() |
4e64b9a4b1 | ||
![]() |
1be572a95f | ||
![]() |
5cc913a332 | ||
![]() |
220525a2d9 | ||
![]() |
72060f8227 | ||
![]() |
b247ed1c24 | ||
![]() |
b2707e0e62 | ||
![]() |
a1066f09e4 | ||
![]() |
efed817f73 | ||
![]() |
4613149759 | ||
![]() |
1877776720 | ||
![]() |
2b88266d67 | ||
![]() |
17b627a5d9 | ||
![]() |
5b0a68fe18 | ||
![]() |
d93ed2c5d3 | ||
![]() |
c73322a504 | ||
![]() |
4486684183 | ||
![]() |
1768a1641c | ||
![]() |
224053c0f4 | ||
![]() |
ca38366a60 | ||
![]() |
45f2985549 | ||
![]() |
3ef790dc07 | ||
![]() |
70df7605cb | ||
![]() |
4fc451f370 | ||
![]() |
163de5e5cf | ||
![]() |
8785817efe | ||
![]() |
db793e6c05 | ||
![]() |
d11ceab59d | ||
![]() |
1278454148 | ||
![]() |
7768f6ef16 | ||
![]() |
210b9ba491 | ||
![]() |
969580b770 | ||
![]() |
44dcb1e7f6 | ||
![]() |
1e0c253488 | ||
![]() |
141a288542 | ||
![]() |
154372615e | ||
![]() |
253f5c9261 | ||
![]() |
aa11a681ce |
33
.eslintignore
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
*.sh
|
||||||
|
node_modules
|
||||||
|
*.md
|
||||||
|
*.woff
|
||||||
|
*.ttf
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
dist
|
||||||
|
/public
|
||||||
|
/docs
|
||||||
|
.husky
|
||||||
|
.local
|
||||||
|
/bin
|
||||||
|
Dockerfile
|
53
.eslintrc.cjs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require("@rushstack/eslint-patch/modern-module-resolution");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: [
|
||||||
|
"plugin:vue/vue3-essential",
|
||||||
|
"eslint:recommended",
|
||||||
|
"@vue/eslint-config-typescript",
|
||||||
|
"@vue/eslint-config-prettier",
|
||||||
|
],
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}"],
|
||||||
|
extends: ["plugin:cypress/recommended"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"vue/script-setup-uses-vars": "error",
|
||||||
|
"@typescript-eslint/ban-ts-ignore'": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/no-this-alias": "off",
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
},
|
||||||
|
};
|
3
.github/workflows/nodejs.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [12.x, 14.x, 16.x]
|
node-version: [14.x, 16.x, 18.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 }}
|
||||||
@@ -49,6 +49,7 @@ jobs:
|
|||||||
npm ci
|
npm ci
|
||||||
npm run lint
|
npm run lint
|
||||||
npm run build --if-present
|
npm run build --if-present
|
||||||
|
npm run check-components-types
|
||||||
npm run test:unit
|
npm run test:unit
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
|
34
.gitignore
vendored
@@ -16,24 +16,40 @@
|
|||||||
# specific language governing permissions and limitations
|
# specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
.DS_Store
|
|
||||||
node_modules
|
|
||||||
/dist
|
|
||||||
/node
|
|
||||||
|
|
||||||
/tests/e2e/videos/
|
|
||||||
/tests/e2e/screenshots/
|
|
||||||
|
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
||||||
# Log files
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
pnpm-debug.log*
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.idea
|
.idea
|
||||||
|
27
.husky/commit-msg
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# shellcheck source=./_/husky.sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
PATH="/usr/local/bin:$PATH"
|
||||||
|
|
||||||
|
npx --no-install commitlint --edit "$1"
|
27
.husky/common.sh
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
command_exists () {
|
||||||
|
command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
if command_exists winpty && test -t 1; then
|
||||||
|
exec < /dev/tty
|
||||||
|
fi
|
29
.husky/pre-commit
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
. "$(dirname "$0")/common.sh"
|
||||||
|
|
||||||
|
[ -n "$CI" ] && exit 0
|
||||||
|
|
||||||
|
PATH="/usr/local/bin:$PATH"
|
||||||
|
|
||||||
|
# Format and submit code according to lintstagedrc configuration
|
||||||
|
npm run lint:lint-staged
|
22
.stylelintignore
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
/dist/*
|
||||||
|
/public/*
|
||||||
|
public/*
|
22
README.md
@@ -1,20 +1,20 @@
|
|||||||
Apache SkyWalking Booster UI
|
# Apache SkyWalking Booster UI
|
||||||
===============
|
|
||||||
|
|
||||||
<img src="http://skywalking.apache.org/assets/logo.svg" alt="Sky Walking logo" height="90px" align="right" />
|
<img src="http://skywalking.apache.org/assets/logo.svg" alt="Sky Walking logo" height="90px" align="right" />
|
||||||
|
|
||||||
[Apache SkyWalking](https://github.com/apache/skywalking) Booster UI.
|
[Apache SkyWalking](https://github.com/apache/skywalking) Booster UI.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This UI starts from SkyWalking OAP v9 core.
|
This UI starts from SkyWalking OAP v9 core.
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
This repo wouldn't release separately. All source codes have been included in the main repo release. The tags match the [main repo](https://github.com/apache/skywalking) tags.
|
This repo wouldn't release separately. All source codes have been included in the main repo release. The tags match the [main repo](https://github.com/apache/skywalking) tags.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
The app was built with [Vue3.x + Typescript](https://github.com/vuejs/vue).
|
The app was built with [Vue3.x + Typescript](https://github.com/vuejs/vue).
|
||||||
|
|
||||||
### Prepare
|
### Prepare
|
||||||
|
|
||||||
@@ -28,19 +28,21 @@ npm install
|
|||||||
### Build
|
### Build
|
||||||
|
|
||||||
**All following builds are for dev.**
|
**All following builds are for dev.**
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
npm run serve
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
The default UI address is `http://localhost:8080`.
|
The default UI address is `http://localhost:8080`.
|
||||||
|
|
||||||
|
|
||||||
# Contact Us
|
# Contact Us
|
||||||
* Submit an [issue](https://github.com/apache/skywalking/issues) if you face some issues. Submit a [discussion](https://github.com/apache/skywalking/discussions) if you want to propose new feature or have any question.
|
|
||||||
* Mailing list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe the mailing list.
|
- Submit an [issue](https://github.com/apache/skywalking/issues) if you face some issues. Submit a [discussion](https://github.com/apache/skywalking/discussions) if you want to propose new feature or have any question.
|
||||||
* Join Slack. Send `Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in.
|
- Mailing list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe the mailing list.
|
||||||
* QQ Group: 392443393, 901167865
|
- Join Slack. Send `Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in.
|
||||||
|
- QQ Group: 392443393, 901167865
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
[Apache 2.0 License.](/LICENSE)
|
[Apache 2.0 License.](/LICENSE)
|
||||||
|
@@ -15,32 +15,37 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default [
|
module.exports = {
|
||||||
{
|
ignores: [(commit) => commit.includes("init")],
|
||||||
path: "",
|
extends: ["@commitlint/config-conventional"],
|
||||||
name: "Browser",
|
rules: {
|
||||||
meta: {
|
"body-leading-blank": [2, "always"],
|
||||||
title: "browser",
|
"footer-leading-blank": [1, "always"],
|
||||||
icon: "language",
|
"header-max-length": [2, "always", 108],
|
||||||
},
|
"subject-empty": [2, "never"],
|
||||||
redirect: "/browser",
|
"type-empty": [2, "never"],
|
||||||
children: [
|
"subject-case": [0],
|
||||||
{
|
"type-enum": [
|
||||||
path: "/browser",
|
2,
|
||||||
name: "Browser",
|
"always",
|
||||||
meta: {
|
[
|
||||||
title: "browser",
|
"feat",
|
||||||
layer: "BROWSER",
|
"fix",
|
||||||
},
|
"perf",
|
||||||
},
|
"style",
|
||||||
{
|
"docs",
|
||||||
path: "/browser/tab/:activeTabIndex",
|
"test",
|
||||||
name: "BrowserActiveTabIndex",
|
"refactor",
|
||||||
meta: {
|
"build",
|
||||||
notShow: true,
|
"ci",
|
||||||
layer: "BROWSER",
|
"chore",
|
||||||
},
|
"revert",
|
||||||
},
|
"wip",
|
||||||
|
"workflow",
|
||||||
|
"types",
|
||||||
|
"release",
|
||||||
|
"merge",
|
||||||
|
],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
};
|
13
src/assets/icons/index.ts → cypress.config.ts
Executable file → Normal file
@@ -14,7 +14,12 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
const requireAll = (requireContext: Recordable) =>
|
|
||||||
requireContext.keys().map(requireContext);
|
import { defineConfig } from "cypress";
|
||||||
const req = require.context("./", true, /\.svg$/);
|
|
||||||
requireAll(req);
|
export default defineConfig({
|
||||||
|
e2e: {
|
||||||
|
specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}",
|
||||||
|
baseUrl: "http://localhost:4173",
|
||||||
|
},
|
||||||
|
});
|
@@ -14,10 +14,9 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
describe("My First Test", () => {
|
describe("My First Test", () => {
|
||||||
it("renders props.msg when passed", () => {
|
it("visits the app root url", () => {
|
||||||
const msg = "new message";
|
cy.visit("/");
|
||||||
console.log(msg);
|
cy.contains("h1", "You did it!");
|
||||||
});
|
});
|
||||||
});
|
});
|
26
cypress/e2e/tsconfig.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||||
|
"include": ["./**/*", "../support/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"isolatedModules": false,
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["es5", "dom"],
|
||||||
|
"types": ["cypress"]
|
||||||
|
}
|
||||||
|
}
|
@@ -14,13 +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.
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
{
|
||||||
plugins: ["cypress"],
|
"name": "Using fixtures to represent data",
|
||||||
env: {
|
"email": "hello@cypress.io",
|
||||||
mocha: true,
|
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||||
"cypress/globals": true,
|
}
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
strict: "off",
|
|
||||||
},
|
|
||||||
};
|
|
@@ -14,8 +14,9 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
/// <reference types="cypress" />
|
||||||
// ***********************************************
|
// ***********************************************
|
||||||
// This example commands.js shows you how to
|
// This example commands.ts shows you how to
|
||||||
// create various custom commands and overwrite
|
// create various custom commands and overwrite
|
||||||
// existing commands.
|
// existing commands.
|
||||||
//
|
//
|
||||||
@@ -26,16 +27,29 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
// -- This is a parent command --
|
// -- This is a parent command --
|
||||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// -- This is a child command --
|
// -- This is a child command --
|
||||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// -- This is a dual command --
|
// -- This is a dual command --
|
||||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// -- This is will overwrite an existing command --
|
// -- This will overwrite an existing command --
|
||||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||||
|
//
|
||||||
|
// declare global {
|
||||||
|
// namespace Cypress {
|
||||||
|
// interface Chainable {
|
||||||
|
// login(email: string, password: string): Chainable<void>
|
||||||
|
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||||
|
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||||
|
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
export {};
|
@@ -14,6 +14,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ***********************************************************
|
// ***********************************************************
|
||||||
// This example support/index.js is processed and
|
// This example support/index.js is processed and
|
||||||
// loaded automatically before your test files.
|
// loaded automatically before your test files.
|
26
env.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_SW_PROXY_TARGET: string;
|
||||||
|
readonly VITE_DROP_CONSOLE: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
@@ -15,17 +15,13 @@ limitations under the License. -->
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<title>Apache SkyWalking</title>
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
|
||||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
50765
package-lock.json
generated
166
package.json
@@ -1,13 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "skywalking-booster-ui",
|
"name": "skywalking-booster-ui",
|
||||||
"version": "9.3.0",
|
"version": "9.4.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"dev": "vite",
|
||||||
"build": "vue-cli-service build",
|
"build": "run-p type-check build-only",
|
||||||
"test:unit": "vue-cli-service test:unit",
|
"preview": "vite preview",
|
||||||
"test:e2e": "vue-cli-service test:e2e",
|
"test:unit": "vitest --environment jsdom --root src/",
|
||||||
"lint": "vue-cli-service lint"
|
"test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'",
|
||||||
|
"build-only": "vite build",
|
||||||
|
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
|
||||||
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||||
|
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||||
|
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||||
|
"lint:lint-staged": "lint-staged",
|
||||||
|
"prepare": "husky install",
|
||||||
|
"check-components-types": "if (! git diff --quiet -U0 ./src/types); then echo 'type files are not updated correctly'; git diff -U0 ./src/types; exit 1; fi"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
@@ -15,134 +23,82 @@
|
|||||||
"d3-flame-graph": "^4.1.3",
|
"d3-flame-graph": "^4.1.3",
|
||||||
"d3-tip": "^0.9.1",
|
"d3-tip": "^0.9.1",
|
||||||
"echarts": "^5.2.2",
|
"echarts": "^5.2.2",
|
||||||
"element-plus": "^2.0.2",
|
"element-plus": "^2.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"monaco-editor": "^0.27.0",
|
"monaco-editor": "^0.34.1",
|
||||||
"pinia": "^2.0.5",
|
"pinia": "^2.0.28",
|
||||||
"vis-timeline": "^7.5.1",
|
"vis-timeline": "^7.5.1",
|
||||||
"vue": "^3.0.0",
|
"vue": "^3.2.45",
|
||||||
"vue-grid-layout": "^3.0.0-beta1",
|
"vue-grid-layout": "^3.0.0-beta1",
|
||||||
"vue-i18n": "^9.1.9",
|
"vue-i18n": "^9.1.9",
|
||||||
"vue-router": "^4.0.0-0",
|
"vue-router": "^4.1.6",
|
||||||
"vue-types": "^4.1.1"
|
"vue-types": "^4.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^17.6.6",
|
||||||
|
"@commitlint/config-conventional": "^17.6.6",
|
||||||
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@types/d3": "^7.1.0",
|
"@types/d3": "^7.1.0",
|
||||||
"@types/d3-tip": "^3.5.5",
|
"@types/d3-tip": "^3.5.5",
|
||||||
"@types/echarts": "^4.9.12",
|
"@types/echarts": "^4.9.12",
|
||||||
"@types/jest": "^24.0.19",
|
"@types/jsdom": "^20.0.1",
|
||||||
"@types/lodash": "^4.14.179",
|
"@types/lodash": "^4.14.179",
|
||||||
|
"@types/node": "^18.11.12",
|
||||||
"@types/three": "^0.131.0",
|
"@types/three": "^0.131.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@typescript-eslint/parser": "^4.18.0",
|
"@vitejs/plugin-vue-jsx": "^3.0.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
"@vue/cli-plugin-e2e-cypress": "~5.0.8",
|
"@vue/eslint-config-typescript": "^11.0.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/test-utils": "^2.2.6",
|
||||||
"@vue/cli-plugin-router": "~4.5.0",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
"@vueuse/core": "^9.6.0",
|
||||||
"@vue/cli-plugin-unit-jest": "~4.5.0",
|
"cypress": "^12.0.2",
|
||||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
"eslint": "^8.22.0",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"eslint-plugin-cypress": "^2.12.1",
|
||||||
"@vue/compiler-sfc": "^3.0.0",
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
"@vue/eslint-config-prettier": "^6.0.0",
|
"husky": "^8.0.2",
|
||||||
"@vue/eslint-config-typescript": "^7.0.0",
|
"jsdom": "^20.0.3",
|
||||||
"@vue/test-utils": "^2.0.0-0",
|
"lint-staged": "^13.2.1",
|
||||||
"babel-jest": "^24.9.0",
|
"mockjs": "^1.1.0",
|
||||||
"eslint": "^6.7.2",
|
"npm-run-all": "^4.1.5",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
|
||||||
"eslint-plugin-vue": "^7.0.0",
|
|
||||||
"husky": "^7.0.4",
|
|
||||||
"lint-staged": "^12.1.3",
|
|
||||||
"monaco-editor-webpack-plugin": "^4.1.2",
|
|
||||||
"node-sass": "^6.0.1",
|
|
||||||
"postcss-html": "^1.3.0",
|
"postcss-html": "^1.3.0",
|
||||||
"postcss-scss": "^4.0.2",
|
"postcss-scss": "^4.0.2",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.7.1",
|
||||||
"sass-loader": "^10.2.0",
|
"sass": "^1.56.1",
|
||||||
"stylelint": "^14.1.0",
|
"start-server-and-test": "^1.15.2",
|
||||||
|
"stylelint": "15.9.0",
|
||||||
"stylelint-config-html": "^1.0.0",
|
"stylelint-config-html": "^1.0.0",
|
||||||
"stylelint-config-prettier": "^9.0.3",
|
"stylelint-config-prettier": "9.0.4",
|
||||||
"stylelint-config-standard": "^24.0.0",
|
"stylelint-config-standard": "^33.0.0",
|
||||||
"stylelint-order": "^5.0.0",
|
"stylelint-order": "^6.0.3",
|
||||||
"svg-sprite-loader": "^6.0.11",
|
"typescript": "~4.7.4",
|
||||||
"typescript": "~4.4.4",
|
|
||||||
"unplugin-auto-import": "^0.7.0",
|
"unplugin-auto-import": "^0.7.0",
|
||||||
"unplugin-vue-components": "^0.19.2",
|
"unplugin-vue-components": "^0.19.2",
|
||||||
"vue-jest": "^5.0.0-0"
|
"vite": "^4.0.5",
|
||||||
|
"vite-plugin-monaco-editor": "^1.1.0",
|
||||||
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
|
"vitest": "^0.25.6",
|
||||||
|
"vue-tsc": "^1.0.12"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:vue/vue3-essential",
|
|
||||||
"eslint:recommended",
|
|
||||||
"@vue/typescript/recommended",
|
|
||||||
"@vue/prettier",
|
|
||||||
"@vue/prettier/@typescript-eslint"
|
|
||||||
],
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2020
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
||||||
"vue/script-setup-uses-vars": "error",
|
|
||||||
"@typescript-eslint/ban-ts-ignore'": "off",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
|
||||||
"no-use-before-define": "off",
|
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
|
||||||
"@typescript-eslint/no-this-alias": "off"
|
|
||||||
},
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": [
|
|
||||||
"**/__tests__/*.{j,t}s?(x)",
|
|
||||||
"**/tests/unit/**/*.spec.{j,t}s?(x)"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"jest": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"eslintIgnore": [
|
|
||||||
"vue.config.js"
|
|
||||||
],
|
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
"last 2 versions",
|
"last 2 versions",
|
||||||
"not dead"
|
"not dead"
|
||||||
],
|
],
|
||||||
"jest": {
|
|
||||||
"preset": "@vue/cli-plugin-unit-jest/presets/typescript-and-babel",
|
|
||||||
"transform": {
|
|
||||||
"^.+\\.vue$": "vue-jest"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gitHooks": {
|
|
||||||
"pre-commit": "lint-staged"
|
|
||||||
},
|
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,jsx,ts,tsx}": [
|
"*.{js,jsx,ts,tsx,vue}": [
|
||||||
"eslint --fix",
|
"eslint . --ext .vue,.js,.jsx,.ts,.tsx --fix --ignore-path .gitignore",
|
||||||
"prettier --write"
|
"prettier --write \"src/**/*.{js,tsx,css,less,scss,vue,html,md}\"",
|
||||||
|
"stylelint --cache --fix \"**/*.{vue}\" --cache --cache-location node_modules/.cache/stylelint/"
|
||||||
],
|
],
|
||||||
"*.vue": [
|
"*.{scss,less}": [
|
||||||
"eslint --fix",
|
"prettier --write \"src/**/*.{js,tsx,css,less,scss,vue,html,md}\"",
|
||||||
"prettier --write",
|
"stylelint --cache --fix \"**/*.{less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/"
|
||||||
"stylelint --fix --custom-syntax postcss-html"
|
|
||||||
],
|
],
|
||||||
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
|
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
|
||||||
"prettier --write--parser json"
|
|
||||||
],
|
|
||||||
"package.json": [
|
|
||||||
"prettier --write"
|
"prettier --write"
|
||||||
],
|
],
|
||||||
"*.{scss,less,styl}": [
|
"package.json": [
|
||||||
"stylelint --fix",
|
|
||||||
"prettier --write"
|
"prettier --write"
|
||||||
],
|
],
|
||||||
"*.md": [
|
"*.md": [
|
||||||
|
@@ -14,8 +14,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
autoprefixer: {},
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
26
prettier.config.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
printWidth: 120,
|
||||||
|
semi: true,
|
||||||
|
vueIndentScriptAndStyle: true,
|
||||||
|
trailingComma: "all",
|
||||||
|
proseWrap: "never",
|
||||||
|
htmlWhitespaceSensitivity: "strict",
|
||||||
|
endOfLine: "auto",
|
||||||
|
};
|
23
src/App.vue
@@ -15,11 +15,22 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<router-view />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (route.name === "ViewWidget") {
|
||||||
|
(document.querySelector("#app") as any).style.minWidth = "120px";
|
||||||
|
} else {
|
||||||
|
(document.querySelector("#app") as any).style.minWidth = "1024px";
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
</script>
|
||||||
<style>
|
<style>
|
||||||
#app {
|
#app {
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 1024px;
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
15
src/assets/icons/add_iframe.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!-- 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="M856.32 428.064a32 32 0 0 0-32 32v163.328H372.48c-0.896 0-1.664 0.448-2.56 0.512v-177.696h244.48a32 32 0 1 0 0-64H130.56c-0.896 0-1.664 0.448-2.56 0.512V231.68h488.16a32 32 0 1 0 0-64H96a32 32 0 0 0-32 32v701.824a32 32 0 0 0 32 32h760.32a32 32 0 0 0 32-32V460.064a32 32 0 0 0-32-32zM128 445.728c0.896 0.064 1.664 0.512 2.56 0.512h175.36v423.264H128V445.728z m241.92 423.776v-182.624c0.896 0.064 1.664 0.512 2.56 0.512h451.84v182.08h-454.4zM960 174.656h-61.376V113.28a32 32 0 1 0-64 0v61.344H752.64a32 32 0 1 0 0 64h81.984v81.984a32 32 0 1 0 64 0V238.656H960a32 32 0 1 0 0-64z" fill="#2c2c2c"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@@ -12,6 +12,6 @@ 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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg t="1684376918107" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7954">
|
||||||
<path d="M15 15.984h6v3q0 0.797-0.609 1.406t-1.406 0.609h-13.969q-0.797 0-1.406-0.609t-0.609-1.406v-3h6q0 1.219 0.891 2.109t2.109 0.891 2.109-0.891 0.891-2.109zM18.984 9v-3.984h-13.969v3.984h3.984q0 1.219 0.891 2.109t2.109 0.891 2.109-0.891 0.891-2.109h3.984zM18.984 3q0.797 0 1.406 0.609t0.609 1.406v6.984q0 0.797-0.609 1.406t-1.406 0.609h-13.969q-0.797 0-1.406-0.609t-0.609-1.406v-6.984q0-0.797 0.609-1.406t1.406-0.609h13.969z"></path>
|
<path d="M243.921917 780.038686l357.445972 0L601.367889 422.592714 243.921917 422.592714 243.921917 780.038686zM288.679283 467.350081l268.036639 0 0 268.035616L288.679283 735.385696 288.679283 467.350081zM779.993149 65.25112 243.921917 65.25112c-98.640578 0-178.6314 79.990822-178.6314 178.716334L65.290517 780.038686c0 98.640578 79.990822 178.710194 178.6314 178.710194l536.071232 0c98.725512 0 178.716334-80.069617 178.716334-178.710194L958.709483 243.967454C958.709483 145.242965 878.717637 65.25112 779.993149 65.25112zM869.404528 735.385696c0 73.992201-60.07319 133.972271-134.084834 133.972271L288.679283 869.357967c-74.096579 0-134.063345-59.98007-134.063345-133.972271L154.615938 288.61328c0-73.984015 59.966767-134.057205 134.063345-134.057205l446.639386 0c74.011644 0 134.084834 60.07319 134.084834 134.057205L869.403504 735.385696zM511.957533 243.967454l268.035616 0 0 89.319282 0 268.035616-89.326445 0-44.645826 0 0-44.673455 89.298815 0L735.319693 288.61328l-268.014126 0 0 89.326445-44.652989 0 0-133.971247L511.957533 243.968477z" p-id="7955"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.9 KiB |
17
src/assets/icons/aws_cloud.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 version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path d="M18.984 18q1.219 0 2.109-0.891t0.891-2.109-0.891-2.109-2.109-0.891h-1.5v-0.516q0-2.297-1.594-3.891t-3.891-1.594q-1.875 0-3.328 1.125t-1.969 2.859h-0.703q-1.641 0-2.813 1.195t-1.172 2.836 1.172 2.813 2.813 1.172h12.984zM19.359 10.031q1.922 0.141 3.281 1.57t1.359 3.398q0 2.063-1.477 3.539t-3.539 1.477h-12.984q-2.484 0-4.242-1.758t-1.758-4.242q0-2.203 1.57-3.961t3.773-1.992q0.984-1.828 2.766-2.953t3.891-1.125q2.531 0 4.711 1.781t2.648 4.266z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
17
src/assets/icons/browser.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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M16.359 14.016h3.375q0.281-1.313 0.281-2.016t-0.281-2.016h-3.375q0.141 0.984 0.141 2.016t-0.141 2.016zM14.578 19.547q1.172-0.375 2.438-1.43t1.922-2.133h-2.953q-0.469 1.875-1.406 3.563zM14.344 14.016q0.141-0.984 0.141-2.016t-0.141-2.016h-4.688q-0.141 0.984-0.141 2.016t0.141 2.016h4.688zM12 19.969q1.313-1.922 1.922-3.984h-3.844q0.609 2.063 1.922 3.984zM8.016 8.016q0.563-2.016 1.406-3.563-1.172 0.375-2.461 1.43t-1.898 2.133h2.953zM5.063 15.984q0.609 1.078 1.898 2.133t2.461 1.43q-0.938-1.688-1.406-3.563h-2.953zM4.266 14.016h3.375q-0.141-0.984-0.141-2.016t0.141-2.016h-3.375q-0.281 1.313-0.281 2.016t0.281 2.016zM12 4.031q-1.313 1.922-1.922 3.984h3.844q-0.609-2.063-1.922-3.984zM18.938 8.016q-0.656-1.078-1.922-2.133t-2.438-1.43q0.844 1.547 1.406 3.563h2.953zM12 2.016q4.125 0 7.055 2.93t2.93 7.055-2.93 7.055-7.055 2.93-7.055-2.93-2.93-7.055 2.93-7.055 7.055-2.93z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
@@ -12,6 +12,6 @@ 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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M18.984 18q1.219 0 2.109-0.891t0.891-2.109-0.891-2.109-2.109-0.891h-1.5v-0.516q0-2.297-1.594-3.891t-3.891-1.594q-1.875 0-3.328 1.125t-1.969 2.859h-0.703q-1.641 0-2.813 1.195t-1.172 2.836 1.172 2.813 2.813 1.172h12.984zM19.359 10.031q1.922 0.141 3.281 1.57t1.359 3.398q0 2.063-1.477 3.539t-3.539 1.477h-12.984q-2.484 0-4.242-1.758t-1.758-4.242q0-2.203 1.57-3.961t3.773-1.992q0.984-1.828 2.766-2.953t3.891-1.125q2.531 0 4.711 1.781t2.648 4.266z"></path>
|
<path d="M18.984 18q1.219 0 2.109-0.891t0.891-2.109-0.891-2.109-2.109-0.891h-1.5v-0.516q0-2.297-1.594-3.891t-3.891-1.594q-1.875 0-3.328 1.125t-1.969 2.859h-0.703q-1.641 0-2.813 1.195t-1.172 2.836 1.172 2.813 2.813 1.172h12.984zM19.359 10.031q1.922 0.141 3.281 1.57t1.359 3.398q0 2.063-1.477 3.539t-3.539 1.477h-12.984q-2.484 0-4.242-1.758t-1.758-4.242q0-2.203 1.57-3.961t3.773-1.992q0.984-1.828 2.766-2.953t3.891-1.125q2.531 0 4.711 1.781t2.648 4.266z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
17
src/assets/icons/continuous_profiling.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 t="1684390612367" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12207">
|
||||||
|
<path d="M202.66008 885.33784A10.66632 10.66632 0 0 0 213.3264 874.67152v-85.33056a42.66528 42.66528 0 0 0-42.66528-42.66528H85.33056a42.66528 42.66528 0 0 0-42.66528 42.66528v85.33056a10.66632 10.66632 0 0 0 10.66632 10.66632zM458.65176 885.33784a10.66632 10.66632 0 0 0 10.66632-10.66632v-298.65696a42.66528 42.66528 0 0 0-42.66528-42.665281H341.32224a42.66528 42.66528 0 0 0-42.66528 42.665281v298.65696a10.66632 10.66632 0 0 0 10.66632 10.66632zM714.643441 885.33784a10.66632 10.66632 0 0 0 10.66632-10.66632v-213.3264a42.66528 42.66528 0 0 0-42.66528-42.66528h-85.33056a42.66528 42.66528 0 0 0-42.66528 42.66528v213.3264a10.66632 10.66632 0 0 0 10.66632 10.66632zM970.635121 885.33784a10.66632 10.66632 0 0 0 10.66632-10.66632v-511.983361a42.66528 42.66528 0 0 0-42.66528-42.66528h-85.33056a42.66528 42.66528 0 0 0-42.66528 42.66528v511.983361a10.66632 10.66632 0 0 0 10.66632 10.66632z" p-id="12208"></path><path d="M149.32848 576.01456a85.33056 85.33056 0 0 0 85.33056-85.330561 84.51992 84.51992 0 0 0-4.266528-25.599168l135.120942-112.636339a83.410622 83.410622 0 0 0 104.273945-19.626029l106.6632 35.582844A85.33056 85.33056 0 0 0 746.642401 362.688159a83.79461 83.79461 0 0 0-9.85568-38.910735l140.240776-163.621349A85.074568 85.074568 0 1 0 831.972961 85.363839a83.709279 83.709279 0 0 0 3.967871 24.361875L688.190967 282.136111a82.429321 82.429321 0 0 0-91.346364 25.300511l-106.663201-35.540179A85.117234 85.117234 0 1 0 324.256128 302.956767L189.263182 415.763768A84.263928 84.263928 0 0 0 149.32848 405.353439a85.33056 85.33056 0 0 0 0 170.661121zM981.301441 938.66944H42.66528a43.347925 43.347925 0 0 0-42.66528 42.66528 42.66528 42.66528 0 0 0 42.66528 42.66528h938.636161a42.66528 42.66528 0 0 0 42.66528-42.66528 43.305259 43.305259 0 0 0-42.66528-42.66528z" p-id="12209"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
15
src/assets/icons/cross.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!-- 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 t="1680101648371" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15649" width="48" height="48"><path d="M832 272c0-62.4-51-112.9-113.6-112-60.7 0.9-110 50.6-110.4 111.3-0.3 52.6 35.6 96.8 84.2 109.2 14 3.6 23.8 16 24.1 30.4 0.5 27.3-4.4 57.4-22.3 82.5-28.7 40.3-80.7 54.9-126.6 67.8-29 8.1-50.1 10.2-68.7 12-26.4 2.6-51.4 5.1-82.6 23-6.6 3.8-13.1 8-19.2 12.6-5.3 4-12.8 0.2-12.8-6.4V241.3c0-12.2 6.8-23.5 17.7-28.9 37.1-18.4 62.6-56.8 62.3-101.1-0.5-62.8-53.2-113.4-116-111.2C288.1 2.1 240 51.4 240 112c0 44 25.4 82.1 62.3 100.4 10.9 5.4 17.7 16.5 17.7 28.6v541.7c0 12.2-6.8 23.5-17.7 28.9-37.1 18.4-62.6 56.8-62.3 101.1 0.4 62.8 53.1 113.3 115.9 111.2C416 1021.9 464 972.5 464 912c0-44-25.4-82.1-62.3-100.4-10.9-5.4-17.7-16.5-17.7-28.6v-19.2c0-42 19.9-81.8 54.3-105.9 3.1-2.2 6.4-4.3 9.7-6.2 19.3-11.1 33.5-12.5 57-14.8 20.2-2 45.3-4.5 79.7-14.1 50.5-14.2 119.6-33.5 161.4-92.3 24-33.7 35.4-75 34.1-123-0.2-6.9-0.7-13.8-1.4-20.9-1.1-10.7 3.5-21 11.8-27.8 25.3-20.4 41.4-51.7 41.4-86.8zM304 112c0-26.5 21.5-48 48-48s48 21.5 48 48-21.5 48-48 48-48-21.5-48-48z m96 800c0 26.5-21.5 48-48 48s-48-21.5-48-48 21.5-48 48-48 48 21.5 48 48z m320-592c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48z" p-id="15650"></path></svg>
|
After Width: | Height: | Size: 2.0 KiB |
17
src/assets/icons/database.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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M3.984 11.016v1.969h2.016v-1.969h-2.016zM2.016 14.016v-4.031h19.969v4.031h-19.969zM6 6.984v-1.969h-2.016v1.969h2.016zM2.016 3.984h19.969v4.031h-19.969v-4.031zM3.984 17.016v1.969h2.016v-1.969h-2.016zM2.016 20.016v-4.031h19.969v4.031h-19.969z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
17
src/assets/icons/edit.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 t="1684722897341" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2408">
|
||||||
|
<path d="M853.333333 501.333333c-17.066667 0-32 14.933333-32 32v320c0 6.4-4.266667 10.666667-10.666666 10.666667H170.666667c-6.4 0-10.666667-4.266667-10.666667-10.666667V213.333333c0-6.4 4.266667-10.666667 10.666667-10.666666h320c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32H170.666667c-40.533333 0-74.666667 34.133333-74.666667 74.666666v640c0 40.533333 34.133333 74.666667 74.666667 74.666667h640c40.533333 0 74.666667-34.133333 74.666666-74.666667V533.333333c0-17.066667-14.933333-32-32-32z" fill="#666666" p-id="2409"></path><path d="M405.333333 484.266667l-32 125.866666c-2.133333 10.666667 0 23.466667 8.533334 29.866667 6.4 6.4 14.933333 8.533333 23.466666 8.533333h8.533334l125.866666-32c6.4-2.133333 10.666667-4.266667 14.933334-8.533333l300.8-300.8c38.4-38.4 38.4-102.4 0-140.8-38.4-38.4-102.4-38.4-140.8 0L413.866667 469.333333c-4.266667 4.266667-6.4 8.533333-8.533334 14.933334z m59.733334 23.466666L761.6 213.333333c12.8-12.8 36.266667-12.8 49.066667 0 12.8 12.8 12.8 36.266667 0 49.066667L516.266667 558.933333l-66.133334 17.066667 14.933334-68.266667z" p-id="2410"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
15
src/assets/icons/entry.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!-- 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 t="1680083488716" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1096" width="48" height="48"><path d="M853.333333 512a42.666667 42.666667 0 0 0-42.666666-42.666667h-323.84l98.133333-97.706666a42.666667 42.666667 0 1 0-60.586667-60.586667l-170.666666 170.666667a42.666667 42.666667 0 0 0-8.96 14.08 42.666667 42.666667 0 0 0 0 32.426666 42.666667 42.666667 0 0 0 8.96 14.08l170.666666 170.666667a42.666667 42.666667 0 0 0 60.586667 0 42.666667 42.666667 0 0 0 0-60.586667L486.826667 554.666667H810.666667a42.666667 42.666667 0 0 0 42.666666-42.666667zM725.333333 85.333333H298.666667a128 128 0 0 0-128 128v597.333334a128 128 0 0 0 128 128h426.666666a128 128 0 0 0 128-128v-128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 1-42.666667 42.666666H298.666667a42.666667 42.666667 0 0 1-42.666667-42.666666V213.333333a42.666667 42.666667 0 0 1 42.666667-42.666666h426.666666a42.666667 42.666667 0 0 1 42.666667 42.666666v128a42.666667 42.666667 0 0 0 85.333333 0V213.333333a128 128 0 0 0-128-128z" p-id="1097"></path></svg>
|
After Width: | Height: | Size: 1.8 KiB |
15
src/assets/icons/exit.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!-- 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 t="1680104481890" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7991" width="16" height="16"><path d="M918.4 489.6l-160-160c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l105.6 105.6L512 480c-19.2 0-32 12.8-32 32s12.8 32 32 32l307.2 0-105.6 105.6c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l160-163.2c0 0 0-3.2 3.2-3.2C931.2 518.4 931.2 499.2 918.4 489.6zM832 736c-19.2 0-32 12.8-32 32l0 64c0 19.2-12.8 32-32 32L224 864c-19.2 0-32-12.8-32-32L192 192c0-19.2 12.8-32 32-32l544 0c19.2 0 32 12.8 32 32l0 64c0 19.2 12.8 32 32 32s32-12.8 32-32L864 192c0-54.4-41.6-96-96-96L224 96C169.6 96 128 137.6 128 192l0 640c0 54.4 41.6 96 96 96l544 0c54.4 0 96-41.6 96-96l0-64C864 748.8 851.2 736 832 736z" p-id="7992"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
15
src/assets/icons/functions.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!-- 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 t="1670381479745" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2930"><path d="M577.450256 639.9892c0-104.678234 33.919428-206.436516 96.018379-289.895108 10.339826-13.879766 8.89985-33.079442-4.299927-44.279253l-49.379167-41.959292c-13.999764-11.899799-35.659398-10.179828-46.759211 4.459925C492.171695 374.833675 447.99244 505.551469 447.99244 639.9892c0 134.457731 44.179254 265.175525 125.03789 371.673728 11.119812 14.639753 32.759447 16.359724 46.759211 4.459925l49.379167-41.979292c13.179778-11.219811 14.619753-30.399487 4.299927-44.279252-62.118952-83.418592-96.01838-185.196875-96.018379-289.875109zM447.99244 31.99946c0-17.679702-14.319758-31.99946-31.99946-31.99946h-95.99838C205.116539 0 111.99811 93.118429 111.99811 207.99649v127.99784H31.99946c-17.679702 0-31.99946 14.319758-31.99946 31.99946v95.99838c0 17.679702 14.319758 31.99946 31.99946 31.99946h79.99865v255.99568c0 26.399555-21.599636 47.99919-47.99919 47.99919H31.99946c-17.679702 0-31.99946 14.319758-31.99946 31.99946v95.99838c0 17.679702 14.319758 31.99946 31.99946 31.99946h31.99946c114.878061 0 207.99649-93.118429 207.99649-207.99649V495.99163h79.99865c17.679702 0 31.99946-14.319758 31.99946-31.99946v-95.99838c0-17.679702-14.319758-31.99946-31.99946-31.99946h-79.99865v-127.99784c0-26.399555 21.599636-47.99919 47.99919-47.99919h95.99838c17.679702 0 31.99946-14.319758 31.99946-31.99946V31.99946z m706.94807 236.316012c-11.119812-14.639753-32.759447-16.359724-46.759211-4.459925l-49.379166 41.959292c-13.179778 11.219811-14.619753 30.399487-4.299928 44.279253 62.098952 83.418592 96.01838 185.216874 96.01838 289.895108 0 104.678234-33.919428 206.456516-96.01838 289.895108-10.339826 13.879766-8.89985 33.079442 4.299928 44.279253l49.379166 41.979292c13.999764 11.899799 35.659398 10.179828 46.759211-4.459925C1235.799146 905.124726 1279.9784 774.426932 1279.9784 639.9892c0-134.457731-44.179254-265.175525-125.03789-371.673728z m-108.338171 463.792174L954.483893 639.9892l92.118446-92.118445c12.499789-12.499789 12.499789-32.759447 0-45.259237l-45.239237-45.239236c-12.499789-12.499789-32.759447-12.499789-45.259236 0L863.98542 549.490727l-92.118445-92.118445c-12.499789-12.499789-32.759447-12.499789-45.259237 0l-45.239236 45.239236c-12.499789 12.499789-12.499789 32.759447 0 45.259237L773.486947 639.9892l-92.118445 92.118446c-12.499789 12.499789-12.499789 32.759447 0 45.259236l45.239236 45.239237c12.499789 12.499789 32.759447 12.499789 45.259237 0L863.98542 730.487673l92.118446 92.118446c12.499789 12.499789 32.759447 12.499789 45.259236 0l45.239237-45.239237c12.499789-12.499789 12.499789-32.759447 0-45.259236z" p-id="2931"></path></svg>
|
After Width: | Height: | Size: 3.4 KiB |
16
src/assets/icons/general_service.svg
Executable 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 width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/chart</title><path d="M5.55 3.824L6.853 5.78a.3.3 0 0 0 .384.102l1.526-.764a.3.3 0 0 1 .384.102l1.65 2.476a.3.3 0 0 0 .462.045l1.229-1.229a.3.3 0 0 1 .512.212v4.243H5V3.99a.3.3 0 0 1 .55-.167zM13 12a1 1 0 0 1 0 2H3.833A1.833 1.833 0 0 1 2 12.167V3a1 1 0 1 1 2 0v9h9z" id="a"/></svg>
|
After Width: | Height: | Size: 1.2 KiB |
18
src/assets/icons/infrastructure.svg
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!-- 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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<title>scatter_plot</title>
|
||||||
|
<path d="M13.594 17.578q0-1.219 0.891-2.109t2.109-0.891 2.109 0.891 0.891 2.109-0.891 2.109-2.109 0.891-2.109-0.891-0.891-2.109zM8.016 6q0-1.219 0.891-2.109t2.109-0.891 2.109 0.891 0.891 2.109-0.891 2.109-2.109 0.891-2.109-0.891-0.891-2.109zM3.984 14.016q0-1.219 0.891-2.109t2.109-0.891 2.109 0.891 0.891 2.109-0.891 2.109-2.109 0.891-2.109-0.891-0.891-2.109z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
17
src/assets/icons/kubernetes.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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M12.984 14.859q1.266-0.375 1.875-1.875h7.125q-0.375 3.609-2.836 6.141t-6.164 2.859v-7.125zM14.859 11.016q-0.563-1.5-1.875-1.875v-7.125q3.703 0.328 6.164 2.859t2.836 6.141h-7.125zM11.016 9.141q-0.797 0.328-1.406 1.125t-0.609 1.734 0.609 1.734 1.406 1.125v7.125q-3.797-0.375-6.398-3.234t-2.602-6.75 2.602-6.75 6.398-3.234v7.125z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
15
src/assets/icons/marketplace.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!-- 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 t="1688979849484" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2698"><path d="M384 469.333333H213.333333c-46.933333 0-85.333333-38.4-85.333333-85.333333V213.333333c0-46.933333 38.4-85.333333 85.333333-85.333333h170.666667c46.933333 0 85.333333 38.4 85.333333 85.333333v170.666667c0 46.933333-38.4 85.333333-85.333333 85.333333zM213.333333 213.333333v170.666667h170.666667V213.333333H213.333333z" p-id="2699"></path><path d="M170.666667 554.666667h256c25.6 0 42.666667 17.066667 42.666666 42.666666v256c0 25.6-17.066667 42.666667-42.666666 42.666667H170.666667c-25.6 0-42.666667-17.066667-42.666667-42.666667v-256c0-25.6 17.066667-42.666667 42.666667-42.666666z" p-id="2700"></path><path d="M384 896H213.333333c-46.933333 0-85.333333-38.4-85.333333-85.333333v-170.666667c0-46.933333 38.4-85.333333 85.333333-85.333333h170.666667c46.933333 0 85.333333 38.4 85.333333 85.333333v170.666667c0 46.933333-38.4 85.333333-85.333333 85.333333z m-170.666667-256v170.666667h170.666667v-170.666667H213.333333z" p-id="2701"></path><path d="M695.466667 115.2c17.066667-17.066667 42.666667-17.066667 59.733333 0l149.333333 149.333333c17.066667 17.066667 17.066667 42.666667 0 59.733334l-149.333333 149.333333c-17.066667 17.066667-42.666667 17.066667-59.733333 0l-149.333334-145.066667c-17.066667-17.066667-17.066667-42.666667 0-59.733333l149.333334-153.6z" p-id="2702"></path><path d="M810.666667 896h-170.666667c-46.933333 0-85.333333-38.4-85.333333-85.333333v-170.666667c0-46.933333 38.4-85.333333 85.333333-85.333333h170.666667c46.933333 0 85.333333 38.4 85.333333 85.333333v170.666667c0 46.933333-38.4 85.333333-85.333333 85.333333z m-170.666667-256v170.666667h170.666667v-170.666667h-170.666667z" p-id="2703"></path></svg>
|
After Width: | Height: | Size: 2.5 KiB |
16
src/assets/icons/mq.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 class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M750.08 657.92c-16.384 0-30.208 2.56-44.032 8.192l-44.032-52.224c33.28-38.4 55.296-90.624 55.296-145.92s-19.456-101.888-52.224-140.288l27.648-24.576c16.384 8.192 33.28 13.824 52.224 13.824 63.488 0 115.712-52.224 115.712-115.712s-52.224-115.712-115.712-115.712c-63.488 0-115.712 52.224-115.712 115.712 0 13.824 2.56 30.208 8.192 41.472l-35.84 30.208c-34.304-19.968-73.216-30.208-112.64-30.208-44.032 0-85.504 13.824-121.344 32.768l-41.472-52.224c0-5.632 2.56-13.824 2.56-19.456 0-40.96-32.768-74.24-73.728-74.24h-0.512c-40.96 0-74.24 32.768-74.24 73.728v0.512c0 40.96 32.768 74.24 73.728 74.24H262.656L306.688 332.8c-27.648 38.4-46.592 85.504-46.592 134.656 0 35.84 8.192 71.68 24.576 101.888l-35.84 30.208c-8.192-5.632-19.456-5.632-30.208-5.632-49.664 0-90.624 41.472-90.624 90.624 0 49.664 41.472 90.624 90.624 90.624s90.624-41.472 90.624-90.624c0-8.192 0-16.384-2.56-24.576l30.208-27.648c41.472 35.84 93.696 57.856 154.112 57.856 33.28 0 63.488-5.632 90.624-19.456l46.592 57.856c-11.264 19.456-19.456 44.032-19.456 68.608 0 77.312 63.488 140.288 143.36 140.288s143.36-63.488 143.36-140.288c0.512-75.776-65.536-139.264-145.408-139.264z m-261.632-11.264c-99.328 0-181.76-79.872-181.76-178.688C306.688 368.64 389.12 289.28 488.448 289.28s181.76 79.872 181.76 178.688c0 99.328-82.432 178.688-181.76 178.688zM430.592 465.408c0.512 18.432-13.824 33.28-32.256 33.792-18.432 0.512-33.28-13.824-33.792-32.256v-1.536c0-18.432 14.848-32.768 33.28-32.768 18.432-0.512 32.768 14.336 32.768 32.768z m88.064 0c0 18.432-14.848 33.28-32.768 33.28-18.432 0-33.28-14.848-33.28-32.768 0-18.432 14.848-32.768 33.28-32.768s32.768 13.824 32.768 32.256z m91.136 0c0 18.432-14.848 33.28-32.768 33.28s-33.28-14.848-33.28-32.768c0-18.432 14.848-32.768 33.28-32.768 17.92-1.024 32.768 13.824 32.768 32.256z"></path></svg>
|
After Width: | Height: | Size: 2.6 KiB |
29
src/assets/icons/self_observability.svg
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!-- 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. -->
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="3450px" height="1823px" viewBox="0 0 3450 1823" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Group" transform="translate(0.000000, -29.000000)">
|
||||||
|
<path d="M1050.01772,1394.31899 C1050.01772,1615.24051 912.21519,1851.47342 474.746835,1851.47342 C310.696203,1851.47342 192.579747,1836.16203 87.5873418,1812.10127 C65.7139241,1807.72658 46.0278481,1792.41519 46.0278481,1768.35443 L46.0278481,1610.86582 C46.0278481,1586.80506 65.7139241,1569.30633 87.5873418,1569.30633 L91.9620253,1569.30633 C179.455696,1580.24304 398.189873,1591.17975 479.121519,1591.17975 C673.794937,1591.17975 732.853165,1521.18481 732.853165,1394.31899 C732.853165,1309.01266 691.293671,1265.26582 546.929114,1179.95949 L258.2,1007.15949 C54.7772152,886.855696 0.0936708861,759.989873 0.0936708861,606.875949 C0.0936708861,366.268354 140.083544,191.281013 546.929114,191.281013 C691.293671,191.281013 892.529114,213.15443 966.898734,230.653165 C988.772152,235.027848 1006.27089,250.339241 1006.27089,272.212658 L1006.27089,434.075949 C1006.27089,455.949367 990.959494,473.448101 969.086076,473.448101 L964.711392,473.448101 C820.346835,460.324051 675.982278,451.574684 533.805063,451.574684 C371.941772,451.574684 304.134177,508.44557 304.134177,606.875949 C304.134177,679.058228 341.318987,722.805063 483.496203,801.549367 L745.977215,948.101266 C986.58481,1081.52911 1050.01772,1221.51899 1050.01772,1394.31899 Z M2852.63038,644.060759 C2852.63038,646.248101 2852.63038,648.435443 2852.63038,650.622785 L2653.58228,1656.8 C2627.33418,1788.04051 2592.33671,1840.53671 2458.90886,1840.53671 L2399.85063,1840.53671 C2281.73418,1840.53671 2220.48861,1783.66582 2192.05316,1669.92405 L2019.25316,1000.59747 C2017.06582,991.848101 2017.06582,989.660759 2012.69114,989.660759 C2008.31646,989.660759 2008.31646,991.848101 2006.12911,1000.59747 L1833.32911,1669.92405 C1804.89367,1783.66582 1743.6481,1840.53671 1625.53165,1840.53671 L1566.47342,1840.53671 C1433.04557,1840.53671 1398.0481,1788.04051 1371.8,1656.8 L1172.7519,650.622785 C1172.7519,648.435443 1172.7519,646.248101 1172.7519,644.060759 C1172.7519,620 1192.43797,600.313924 1216.49873,600.313924 L1428.67089,600.313924 C1450.5443,600.313924 1465.8557,620 1468.04304,639.686076 L1605.84557,1564.93165 C1608.03291,1584.61772 1612.40759,1595.55443 1616.78228,1595.55443 C1621.15696,1595.55443 1627.71899,1586.80506 1632.09367,1564.93165 L1813.64304,829.98481 C1835.51646,744.678481 1861.76456,735.929114 1936.13418,735.929114 L2089.2481,735.929114 C2163.61772,735.929114 2189.86582,744.678481 2211.73924,829.98481 L2393.28861,1564.93165 C2397.66329,1586.80506 2404.22532,1595.55443 2408.6,1595.55443 C2412.97468,1595.55443 2417.34937,1584.61772 2419.53671,1564.93165 L2557.33924,639.686076 C2559.52658,620 2574.83797,600.313924 2596.71139,600.313924 L2808.88354,600.313924 C2832.9443,600.313924 2852.63038,620 2852.63038,644.060759 Z" id="Sw" fill="#1368B3"></path>
|
||||||
|
<g id="moon-o" transform="translate(2932.164557, 596.000000) rotate(-183.000000) translate(-2932.164557, -596.000000) translate(2415.708861, 26.379747)" fill="#D8D8D8" fill-rule="nonzero">
|
||||||
|
<path d="M1025.31646,927.371333 C992.796119,932.841177 959.292071,935.576099 925.845888,935.576099 C590.40035,935.576099 318.259524,661.909325 318.259524,324.582876 C318.259524,209.134252 351.705707,96.3623597 412.290747,0 C171.802278,71.8062511 0,293.684076 0,557.342199 C0,878.317305 259.46831,1139.24051 578.65368,1139.24051 C753.17563,1139.24051 916.818891,1059.22949 1025.31646,927.371333 Z" id="Shape"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
16
src/assets/icons/service_mesh.svg
Executable 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 width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/epic</title><path d="M5.156 4l-.811 2h7.31l-.811-2H5.156zM4.55 2h6.9c.368 0 .702.235.85.6l1.622 4c.205.505-.009 1.095-.478 1.316a.87.87 0 0 1-.371.084H2.927C2.415 8 2 7.552 2 7c0-.138.026-.274.078-.4l1.622-4c.148-.365.481-.6.85-.6zM3 9h10a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2zm0 3h10a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2z" id="a"/></svg>
|
After Width: | Height: | Size: 1.2 KiB |
@@ -12,6 +12,6 @@ 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 version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M12 15.516q1.453 0 2.484-1.031t1.031-2.484-1.031-2.484-2.484-1.031-2.484 1.031-1.031 2.484 1.031 2.484 2.484 1.031zM19.453 12.984l2.109 1.641q0.328 0.234 0.094 0.656l-2.016 3.469q-0.188 0.328-0.609 0.188l-2.484-0.984q-0.984 0.703-1.688 0.984l-0.375 2.625q-0.094 0.422-0.469 0.422h-4.031q-0.375 0-0.469-0.422l-0.375-2.625q-0.891-0.375-1.688-0.984l-2.484 0.984q-0.422 0.141-0.609-0.188l-2.016-3.469q-0.234-0.422 0.094-0.656l2.109-1.641q-0.047-0.328-0.047-0.984t0.047-0.984l-2.109-1.641q-0.328-0.234-0.094-0.656l2.016-3.469q0.188-0.328 0.609-0.188l2.484 0.984q0.984-0.703 1.688-0.984l0.375-2.625q0.094-0.422 0.469-0.422h4.031q0.375 0 0.469 0.422l0.375 2.625q0.891 0.375 1.688 0.984l2.484-0.984q0.422-0.141 0.609 0.188l2.016 3.469q0.234 0.422-0.094 0.656l-2.109 1.641q0.047 0.328 0.047 0.984t-0.047 0.984z"></path>
|
<path d="M12 15.516q1.453 0 2.484-1.031t1.031-2.484-1.031-2.484-2.484-1.031-2.484 1.031-1.031 2.484 1.031 2.484 2.484 1.031zM19.453 12.984l2.109 1.641q0.328 0.234 0.094 0.656l-2.016 3.469q-0.188 0.328-0.609 0.188l-2.484-0.984q-0.984 0.703-1.688 0.984l-0.375 2.625q-0.094 0.422-0.469 0.422h-4.031q-0.375 0-0.469-0.422l-0.375-2.625q-0.891-0.375-1.688-0.984l-2.484 0.984q-0.422 0.141-0.609-0.188l-2.016-3.469q-0.234-0.422 0.094-0.656l2.109-1.641q-0.047-0.328-0.047-0.984t0.047-0.984l-2.109-1.641q-0.328-0.234-0.094-0.656l2.016-3.469q0.188-0.328 0.609-0.188l2.484 0.984q0.984-0.703 1.688-0.984l0.375-2.625q0.094-0.422 0.469-0.422h4.031q0.375 0 0.469 0.422l0.375 2.625q0.891 0.375 1.688 0.984l2.484-0.984q0.422-0.141 0.609 0.188l2.016 3.469q0.234 0.422-0.094 0.656l-2.109 1.641q0.047 0.328 0.047 0.984t-0.047 0.984z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
17
src/assets/icons/task_timeline.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 t="1685973573331" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2708">
|
||||||
|
<path d="M138 573.8V450.2c48.2-12.1 84-55.8 84-107.7 0-51.9-35.8-95.6-84-107.7V68.1c0-14.9-12.1-27-27-27s-27 12.1-27 27v166.7C35.8 246.9 0 290.6 0 342.5c0 51.9 35.8 95.6 84 107.7v123.7c-48.2 12-84 55.7-84 107.6s35.8 95.6 84 107.7v166.7c0 14.9 12.1 27 27 27s27-12.1 27-27V789.2c48.2-12.1 84-55.8 84-107.7s-35.8-95.6-84-107.7zM60 342.5c0-28.1 22.9-51 51-51s51 22.9 51 51-22.9 51-51 51-51-22.9-51-51z m51 390c-28.1 0-51-22.9-51-51s22.9-51 51-51 51 22.9 51 51-22.9 51-51 51zM942 283H352c-16.6 0-30-13.4-30-30s13.4-30 30-30h590c16.6 0 30 13.4 30 30s-13.4 30-30 30zM771.4 457H347.6c-14.2 0-25.6-11.5-25.6-25.6v-8.7c0-14.2 11.5-25.6 25.6-25.6h423.7c14.2 0 25.6 11.5 25.6 25.6v8.7c0.1 14.1-11.4 25.6-25.5 25.6z" p-id="2709"></path><path d="M942 625H352c-16.6 0-30-13.4-30-30s13.4-30 30-30h590c16.6 0 30 13.4 30 30s-13.4 30-30 30zM771.4 799H347.6c-14.2 0-25.6-11.5-25.6-25.6v-8.7c0-14.2 11.5-25.6 25.6-25.6h423.7c14.2 0 25.6 11.5 25.6 25.6v8.7c0.1 14.1-11.4 25.6-25.5 25.6z" p-id="2710"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@@ -14,8 +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.
|
||||||
*/
|
*/
|
||||||
const requireComponent = require.context("./technologies", false, /\.png$/);
|
const requireComponent = import.meta.glob("./technologies/*.png", { eager: true });
|
||||||
const requireTool = require.context("./tools", false, /\.png$/);
|
const requireTool = import.meta.glob("./tools/*.png", { eager: true });
|
||||||
const result: { [key: string]: string } = {};
|
const result: { [key: string]: string } = {};
|
||||||
const t: { [key: string]: string } = {};
|
const t: { [key: string]: string } = {};
|
||||||
|
|
||||||
@@ -24,25 +24,19 @@ function capitalizeFirstLetter(str: string) {
|
|||||||
}
|
}
|
||||||
function validateFileName(str: string): string | undefined {
|
function validateFileName(str: string): string | undefined {
|
||||||
if (/^\S+\.png$/.test(str)) {
|
if (/^\S+\.png$/.test(str)) {
|
||||||
return str.replace(/^\S+\/(\w+)\.png$/, (rs, $1) =>
|
return str.replace(/^\S+\/(\w+)\.png$/, (rs, $1) => capitalizeFirstLetter($1));
|
||||||
capitalizeFirstLetter($1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[...requireComponent.keys()].forEach((filePath: string) => {
|
Object.keys(requireComponent).forEach((filePath: string) => {
|
||||||
const componentConfig = requireComponent(filePath);
|
|
||||||
|
|
||||||
const fileName = validateFileName(filePath);
|
const fileName = validateFileName(filePath);
|
||||||
if (fileName) {
|
if (fileName) {
|
||||||
result[fileName] = componentConfig;
|
result[fileName] = (requireComponent as Indexable)[filePath].default;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
[...requireTool.keys()].forEach((filePath: string) => {
|
Object.keys(requireTool).forEach((filePath: string) => {
|
||||||
const componentConfig = requireTool(filePath);
|
|
||||||
|
|
||||||
const fileName = validateFileName(filePath);
|
const fileName = validateFileName(filePath);
|
||||||
if (fileName) {
|
if (fileName) {
|
||||||
t[fileName] = componentConfig;
|
t[fileName] = (requireTool as Indexable)[filePath].default;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
BIN
src/assets/img/technologies/FASTAPI.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/assets/img/technologies/GRIZZLY.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/img/technologies/HTTPX.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
src/assets/img/technologies/JERSEY.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
src/assets/img/technologies/MICROMETER.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
src/assets/img/technologies/WEBSOCKETS.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/img/tools/ENTRY.png
Normal file
After Width: | Height: | Size: 262 B |
BIN
src/assets/img/tools/EXIT.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
src/assets/img/tools/STREAM.png
Normal file
After Width: | Height: | Size: 373 B |
@@ -15,15 +15,19 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div class="chart" ref="chartRef" :style="`height:${height};width:${width};`">
|
<div class="chart" ref="chartRef" :style="`height:${height};width:${width};`">
|
||||||
<div v-if="!available" class="no-data">No Data</div>
|
<div v-if="!available" class="no-data">No Data</div>
|
||||||
<div class="menus" v-show="visMenus" ref="menus">
|
<div
|
||||||
|
class="menus"
|
||||||
|
v-show="visMenus"
|
||||||
|
:style="{
|
||||||
|
top: menuPos.y + 'px',
|
||||||
|
left: menuPos.x + 'px',
|
||||||
|
}"
|
||||||
|
@mouseenter="hideTooltips"
|
||||||
|
>
|
||||||
<div class="tools" @click="associateMetrics" v-if="associate.length">
|
<div class="tools" @click="associateMetrics" v-if="associate.length">
|
||||||
{{ t("associateMetrics") }}
|
{{ t("associateMetrics") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="tools" @click="viewTrace" v-if="relatedTrace && relatedTrace.enableRelate">
|
||||||
class="tools"
|
|
||||||
@click="viewTrace"
|
|
||||||
v-if="relatedTrace && relatedTrace.enableRelate"
|
|
||||||
>
|
|
||||||
{{ t("viewTrace") }}
|
{{ t("viewTrace") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,224 +44,230 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import { watch, ref, onMounted, onBeforeUnmount, unref, computed, reactive } from "vue";
|
||||||
watch,
|
import type { PropType, Ref } from "vue";
|
||||||
ref,
|
import { useI18n } from "vue-i18n";
|
||||||
Ref,
|
import type { EventParams } from "@/types/app";
|
||||||
onMounted,
|
import type { Filters, RelatedTrace } from "@/types/dashboard";
|
||||||
onBeforeUnmount,
|
import { useECharts } from "@/hooks/useEcharts";
|
||||||
unref,
|
import { addResizeListener, removeResizeListener } from "@/utils/event";
|
||||||
computed,
|
import Trace from "@/views/dashboard/related/trace/Index.vue";
|
||||||
} from "vue";
|
import associateProcessor from "@/hooks/useAssociateProcessor";
|
||||||
import type { PropType } from "vue";
|
|
||||||
import { useI18n } from "vue-i18n";
|
|
||||||
import { EventParams } from "@/types/app";
|
|
||||||
import { Filters, RelatedTrace } from "@/types/dashboard";
|
|
||||||
import { useECharts } from "@/hooks/useEcharts";
|
|
||||||
import { addResizeListener, removeResizeListener } from "@/utils/event";
|
|
||||||
import Trace from "@/views/dashboard/related/trace/Index.vue";
|
|
||||||
import associateProcessor from "@/hooks/useAssociateProcessor";
|
|
||||||
|
|
||||||
/*global Nullable, defineProps, defineEmits*/
|
/*global Nullable, defineProps, defineEmits, Indexable*/
|
||||||
const emits = defineEmits(["select"]);
|
const emits = defineEmits(["select"]);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const chartRef = ref<Nullable<HTMLDivElement>>(null);
|
const chartRef = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const menus = ref<Nullable<HTMLDivElement>>(null);
|
const visMenus = ref<boolean>(false);
|
||||||
const visMenus = ref<boolean>(false);
|
const { setOptions, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);
|
||||||
const { setOptions, resize, getInstance } = useECharts(
|
const currentParams = ref<Nullable<EventParams>>(null);
|
||||||
chartRef as Ref<HTMLDivElement>
|
const showTrace = ref<boolean>(false);
|
||||||
);
|
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
||||||
const currentParams = ref<Nullable<EventParams>>(null);
|
type: "Trace",
|
||||||
const showTrace = ref<boolean>(false);
|
});
|
||||||
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
|
||||||
type: "Trace",
|
const props = defineProps({
|
||||||
});
|
height: { type: String, default: "100%" },
|
||||||
const props = defineProps({
|
width: { type: String, default: "100%" },
|
||||||
height: { type: String, default: "100%" },
|
option: {
|
||||||
width: { type: String, default: "100%" },
|
type: Object as PropType<Indexable>,
|
||||||
option: {
|
default: () => ({}),
|
||||||
type: Object as PropType<{ [key: string]: any }>,
|
},
|
||||||
default: () => ({}),
|
filters: {
|
||||||
},
|
type: Object as PropType<Filters>,
|
||||||
filters: {
|
},
|
||||||
type: Object as PropType<Filters>,
|
relatedTrace: {
|
||||||
},
|
type: Object as PropType<RelatedTrace>,
|
||||||
relatedTrace: {
|
},
|
||||||
type: Object as PropType<RelatedTrace>,
|
associate: {
|
||||||
},
|
type: Array as PropType<{ widgetId: string }[]>,
|
||||||
associate: {
|
default: () => [],
|
||||||
type: Array as PropType<{ widgetId: string }[]>,
|
},
|
||||||
default: () => [],
|
});
|
||||||
},
|
const available = computed(
|
||||||
});
|
() =>
|
||||||
const available = computed(
|
(Array.isArray(props.option.series) && props.option.series[0] && props.option.series[0].data) ||
|
||||||
() =>
|
(Array.isArray(props.option.series.data) && props.option.series.data[0]),
|
||||||
(Array.isArray(props.option.series) &&
|
);
|
||||||
props.option.series[0] &&
|
onMounted(async () => {
|
||||||
props.option.series[0].data) ||
|
await setOptions(props.option);
|
||||||
(Array.isArray(props.option.series.data) && props.option.series.data[0])
|
chartRef.value && addResizeListener(unref(chartRef), resize);
|
||||||
);
|
instanceEvent();
|
||||||
onMounted(async () => {
|
});
|
||||||
await setOptions(props.option);
|
|
||||||
chartRef.value && addResizeListener(unref(chartRef), resize);
|
|
||||||
instanceEvent();
|
|
||||||
});
|
|
||||||
|
|
||||||
function instanceEvent() {
|
function instanceEvent() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
const instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance.on("click", (params: EventParams) => {
|
||||||
|
currentParams.value = params;
|
||||||
|
if (props.option.series.type === "sankey") {
|
||||||
|
emits("select", currentParams.value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "hideTip",
|
||||||
|
});
|
||||||
|
visMenus.value = true;
|
||||||
|
if (!chartRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const w = chartRef.value.getBoundingClientRect().width || 0;
|
||||||
|
const h = chartRef.value.getBoundingClientRect().height || 0;
|
||||||
|
if (w - params.event.offsetX > 120) {
|
||||||
|
menuPos.x = params.event.offsetX;
|
||||||
|
} else {
|
||||||
|
menuPos.x = params.event.offsetX - 120;
|
||||||
|
}
|
||||||
|
if (h - params.event.offsetY < 50) {
|
||||||
|
menuPos.y = params.event.offsetY - 40;
|
||||||
|
} else {
|
||||||
|
menuPos.y = params.event.offsetY;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (props.option.series.type === "sankey") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance.on("mouseover", () => {
|
||||||
|
visMenus.value = false;
|
||||||
|
});
|
||||||
|
instance.on("mouseout", () => {
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "hideTip",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.addEventListener(
|
||||||
|
"click",
|
||||||
|
() => {
|
||||||
|
if (instance.isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visMenus.value = false;
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "hideTip",
|
||||||
|
});
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "updateAxisPointer",
|
||||||
|
currTrigger: "leave",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function associateMetrics() {
|
||||||
|
emits("select", currentParams.value);
|
||||||
|
updateOptions(currentParams.value || undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOptions(params?: EventParams) {
|
||||||
const instance = getInstance();
|
const instance = getInstance();
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
instance.on("click", (params: EventParams) => {
|
if (!props.filters) {
|
||||||
currentParams.value = params;
|
return;
|
||||||
if (!menus.value || !chartRef.value) {
|
}
|
||||||
|
if (props.filters.isRange) {
|
||||||
|
const { eventAssociate } = associateProcessor(props);
|
||||||
|
const options = eventAssociate();
|
||||||
|
setOptions(options || props.option);
|
||||||
|
} else {
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "showTip",
|
||||||
|
dataIndex: params ? params.dataIndex : props.filters.dataIndex,
|
||||||
|
seriesIndex: params ? params.seriesIndex : 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewTrace() {
|
||||||
|
const item = associateProcessor(props).traceFilters(currentParams.value);
|
||||||
|
traceOptions.value = {
|
||||||
|
...traceOptions.value,
|
||||||
|
filters: item,
|
||||||
|
};
|
||||||
|
showTrace.value = true;
|
||||||
|
visMenus.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideTooltips() {
|
||||||
|
const instance = getInstance();
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "hideTip",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.option,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
if (!available.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visMenus.value = true;
|
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) {
|
||||||
const w = chartRef.value.getBoundingClientRect().width || 0;
|
return;
|
||||||
const h = chartRef.value.getBoundingClientRect().height || 0;
|
|
||||||
if (w - params.event.offsetX > 120) {
|
|
||||||
menus.value.style.left = params.event.offsetX + "px";
|
|
||||||
} else {
|
|
||||||
menus.value.style.left = params.event.offsetX - 120 + "px";
|
|
||||||
}
|
}
|
||||||
if (h - params.event.offsetY < 50) {
|
let options;
|
||||||
menus.value.style.top = params.event.offsetY - 40 + "px";
|
if (props.filters && props.filters.isRange) {
|
||||||
} else {
|
const { eventAssociate } = associateProcessor(props);
|
||||||
menus.value.style.top = params.event.offsetY + 2 + "px";
|
options = eventAssociate();
|
||||||
}
|
}
|
||||||
});
|
setOptions(options || props.option);
|
||||||
document.addEventListener(
|
},
|
||||||
"click",
|
);
|
||||||
() => {
|
watch(
|
||||||
if (instance.isDisposed()) {
|
() => props.filters,
|
||||||
return;
|
() => {
|
||||||
}
|
updateOptions();
|
||||||
visMenus.value = false;
|
},
|
||||||
instance.dispatchAction({
|
);
|
||||||
type: "updateAxisPointer",
|
|
||||||
currTrigger: "leave",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function associateMetrics() {
|
onBeforeUnmount(() => {
|
||||||
emits("select", currentParams.value);
|
removeResizeListener(unref(chartRef), resize);
|
||||||
const { dataIndex, seriesIndex } = currentParams.value || {
|
});
|
||||||
dataIndex: 0,
|
|
||||||
seriesIndex: 0,
|
|
||||||
};
|
|
||||||
updateOptions({ dataIndex, seriesIndex });
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateOptions(params?: { dataIndex: number; seriesIndex: number }) {
|
|
||||||
const instance = getInstance();
|
|
||||||
if (!instance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!props.filters) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (props.filters.isRange) {
|
|
||||||
const { eventAssociate } = associateProcessor(props);
|
|
||||||
const options = eventAssociate();
|
|
||||||
setOptions(options || props.option);
|
|
||||||
} else {
|
|
||||||
instance.dispatchAction({
|
|
||||||
type: "updateAxisPointer",
|
|
||||||
dataIndex: params ? params.dataIndex : props.filters.dataIndex,
|
|
||||||
seriesIndex: params ? params.seriesIndex : 0,
|
|
||||||
});
|
|
||||||
const ids = props.option.series.map((_: unknown, index: number) => index);
|
|
||||||
instance.dispatchAction({
|
|
||||||
type: "highlight",
|
|
||||||
dataIndex: params ? params.dataIndex : props.filters.dataIndex,
|
|
||||||
seriesIndex: ids,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewTrace() {
|
|
||||||
const item = associateProcessor(props).traceFilters(currentParams.value);
|
|
||||||
traceOptions.value = {
|
|
||||||
...traceOptions.value,
|
|
||||||
filters: item,
|
|
||||||
};
|
|
||||||
showTrace.value = true;
|
|
||||||
visMenus.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.option,
|
|
||||||
(newVal, oldVal) => {
|
|
||||||
if (!available.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let options;
|
|
||||||
if (props.filters && props.filters.isRange) {
|
|
||||||
const { eventAssociate } = associateProcessor(props);
|
|
||||||
options = eventAssociate();
|
|
||||||
}
|
|
||||||
setOptions(options || props.option);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
watch(
|
|
||||||
() => props.filters,
|
|
||||||
() => {
|
|
||||||
updateOptions();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
removeResizeListener(unref(chartRef), resize);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.no-data {
|
.no-data {
|
||||||
font-size: 12px;
|
font-size: $font-size-smaller;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-box-orient: horizontal;
|
-webkit-box-orient: horizontal;
|
||||||
-webkit-box-pack: center;
|
-webkit-box-pack: center;
|
||||||
-webkit-box-align: center;
|
-webkit-box-align: center;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menus {
|
.menus {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
z-index: 9999999;
|
z-index: 9999999;
|
||||||
box-shadow: #ddd 1px 2px 10px;
|
box-shadow: #ddd 1px 2px 10px;
|
||||||
transition: all cubic-bezier(0.075, 0.82, 0.165, 1) linear;
|
transition: all cubic-bezier(0.075, 0.82, 0.165, 1) linear;
|
||||||
background-color: rgb(255, 255, 255);
|
background-color: rgb(255 255 255);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: rgb(51, 51, 51);
|
color: rgb(51 51 51);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tools {
|
.tools {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
color: #999;
|
color: #999;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #409eff;
|
color: $active-color;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -24,64 +24,62 @@ limitations under the License. -->
|
|||||||
loading,
|
loading,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<use :xlink:href="`#${iconName}`"></use>
|
<use :href="`#${iconName}`"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import "@/assets/icons/index";
|
/*global defineProps */
|
||||||
|
defineProps({
|
||||||
/*global defineProps */
|
iconName: { type: String, default: "" },
|
||||||
defineProps({
|
size: { type: String, default: "sm" },
|
||||||
iconName: { type: String, default: "" },
|
loading: { type: Boolean, default: false },
|
||||||
size: { type: String, default: "sm" },
|
});
|
||||||
loading: { type: Boolean, default: false },
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.icon {
|
.icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
|
|
||||||
&.sm {
|
&.sm {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.middle {
|
&.middle {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.lg {
|
&.lg {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.loading {
|
&.loading {
|
||||||
animation: loading 1.5s linear infinite;
|
animation: loading 1.5s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.logo {
|
&.logo {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.xl {
|
&.xl {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@keyframes loading {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: rotate(0deg);
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
}
|
||||||
|
@keyframes loading {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
-webkit-transform: rotate(1turn);
|
-webkit-transform: rotate(1turn);
|
||||||
transform: rotate(1turn);
|
transform: rotate(1turn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -20,31 +20,31 @@ limitations under the License. -->
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
|
|
||||||
interface Option {
|
/*global defineProps, defineEmits */
|
||||||
label: string | number;
|
const emit = defineEmits(["change"]);
|
||||||
value: string | number;
|
const props = defineProps({
|
||||||
}
|
options: {
|
||||||
|
type: Array as PropType<
|
||||||
|
{
|
||||||
|
label: string | number;
|
||||||
|
value: string | number;
|
||||||
|
}[]
|
||||||
|
>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String as PropType<string>,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
size: { type: null, default: "default" },
|
||||||
|
});
|
||||||
|
|
||||||
/*global defineProps, defineEmits */
|
const selected = ref<string>(props.value);
|
||||||
const emit = defineEmits(["change"]);
|
|
||||||
const props = defineProps({
|
|
||||||
options: {
|
|
||||||
type: Array as PropType<Option[]>,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
type: String as PropType<string>,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
size: { type: null, default: "default" },
|
|
||||||
});
|
|
||||||
|
|
||||||
const selected = ref<string>(props.value);
|
function checked(opt: unknown) {
|
||||||
|
emit("change", opt);
|
||||||
function checked(opt: unknown) {
|
}
|
||||||
emit("change", opt);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
@@ -19,9 +19,7 @@ limitations under the License. -->
|
|||||||
{{ selected.label }}
|
{{ selected.label }}
|
||||||
</span>
|
</span>
|
||||||
<span class="no-data" v-else>Please select a option</span>
|
<span class="no-data" v-else>Please select a option</span>
|
||||||
<span class="remove-icon" @click="removeSelected" v-if="clearable">
|
<span class="remove-icon" @click="removeSelected" v-if="clearable"> × </span>
|
||||||
×
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="opt-wrapper" v-show="visible">
|
<div class="opt-wrapper" v-show="visible">
|
||||||
<div
|
<div
|
||||||
@@ -37,141 +35,141 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { Option } from "@/types/app";
|
import type { Option } from "@/types/app";
|
||||||
|
|
||||||
/*global defineProps, defineEmits*/
|
/*global defineProps, defineEmits*/
|
||||||
const emit = defineEmits(["change"]);
|
const emit = defineEmits(["change"]);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
options: {
|
options: {
|
||||||
type: Array as PropType<Option[]>,
|
type: Array as PropType<Option[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: String as PropType<string>,
|
type: String as PropType<string>,
|
||||||
default: () => "",
|
default: () => "",
|
||||||
},
|
},
|
||||||
clearable: { type: Boolean, default: false },
|
clearable: { type: Boolean, default: false },
|
||||||
});
|
});
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const opt = props.options.find((d: Option) => props.value === d.value);
|
const opt = props.options.find((d: Option) => props.value === d.value);
|
||||||
const selected = ref<Option>(opt || { label: "", value: "" });
|
const selected = ref<Option>(opt || { label: "", value: "" });
|
||||||
|
|
||||||
function handleSelect(i: Option) {
|
function handleSelect(i: Option) {
|
||||||
selected.value = i;
|
selected.value = i;
|
||||||
emit("change", i.value);
|
emit("change", i.value);
|
||||||
}
|
|
||||||
function removeSelected() {
|
|
||||||
selected.value = { label: "", value: "" };
|
|
||||||
emit("change", "");
|
|
||||||
}
|
|
||||||
watch(
|
|
||||||
() => props.value,
|
|
||||||
(data) => {
|
|
||||||
const opt = props.options.find((d: Option) => data === d.value);
|
|
||||||
selected.value = opt || { label: "", value: "" };
|
|
||||||
}
|
}
|
||||||
);
|
function removeSelected() {
|
||||||
document.body.addEventListener("click", handleClick, false);
|
selected.value = { label: "", value: "" };
|
||||||
|
emit("change", "");
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(data) => {
|
||||||
|
const opt = props.options.find((d: Option) => data === d.value);
|
||||||
|
selected.value = opt || { label: "", value: "" };
|
||||||
|
},
|
||||||
|
);
|
||||||
|
document.body.addEventListener("click", handleClick, false);
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
function setPopper(event: any) {
|
function setPopper(event: MouseEvent) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
visible.value = !visible.value;
|
visible.value = !visible.value;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.bar-select {
|
.bar-select {
|
||||||
position: relative;
|
position: relative;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
background: #fff;
|
background: $theme-background;
|
||||||
border-radius: 3px;
|
|
||||||
color: #000;
|
|
||||||
font-size: 12px;
|
|
||||||
height: 24px;
|
|
||||||
|
|
||||||
.selected {
|
|
||||||
padding: 0 3px;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin: 3px;
|
color: #000;
|
||||||
color: #409eff;
|
font-size: $font-size-smaller;
|
||||||
background-color: #fafafa;
|
height: 24px;
|
||||||
border: 1px solid #e8e8e8;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-data {
|
.selected {
|
||||||
color: #c0c4cc;
|
padding: 0 3px;
|
||||||
}
|
border-radius: 3px;
|
||||||
|
margin: 3px;
|
||||||
.bar-i {
|
color: $active-color;
|
||||||
height: 100%;
|
background-color: #fafafa;
|
||||||
width: 100%;
|
border: 1px solid #e8e8e8;
|
||||||
padding: 2px 10px;
|
text-align: center;
|
||||||
overflow: auto;
|
|
||||||
color: #606266;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.remove-icon {
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.remove-icon {
|
.no-data {
|
||||||
position: absolute;
|
color: #c0c4cc;
|
||||||
right: 5px;
|
}
|
||||||
top: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
display: none;
|
|
||||||
color: #aaa;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.opt-wrapper {
|
.bar-i {
|
||||||
color: #606266;
|
height: 100%;
|
||||||
position: absolute;
|
width: 100%;
|
||||||
top: 26px;
|
padding: 2px 10px;
|
||||||
left: 0;
|
overflow: auto;
|
||||||
background: #fff;
|
color: #606266;
|
||||||
box-shadow: 0 1px 6px rgba(99, 99, 99, 0.2);
|
position: relative;
|
||||||
border: 1px solid #ddd;
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 0 0 3px 3px;
|
|
||||||
border-right-width: 1px !important;
|
|
||||||
z-index: 10;
|
|
||||||
overflow: auto;
|
|
||||||
max-height: 200px;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
|
|
||||||
.close {
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
top: 12px;
|
|
||||||
opacity: 0.6;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
.remove-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.opt {
|
.remove-icon {
|
||||||
padding: 7px 15px;
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
&.select-disabled {
|
top: 0;
|
||||||
color: #409eff;
|
font-size: $font-size-normal;
|
||||||
cursor: not-allowed;
|
display: none;
|
||||||
|
color: #aaa;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
.opt-wrapper {
|
||||||
background-color: #f5f5f5;
|
color: #606266;
|
||||||
|
position: absolute;
|
||||||
|
top: 26px;
|
||||||
|
left: 0;
|
||||||
|
background-color: $theme-background;
|
||||||
|
box-shadow: 0 1px 6px rgb(99 99 99 / 20%);
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 0 0 3px 3px;
|
||||||
|
border-right-width: 1px !important;
|
||||||
|
z-index: 10;
|
||||||
|
overflow: auto;
|
||||||
|
max-height: 200px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 12px;
|
||||||
|
opacity: 0.6;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opt {
|
||||||
|
padding: 7px 15px;
|
||||||
|
|
||||||
|
&.select-disabled {
|
||||||
|
color: $active-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -32,68 +32,72 @@ limitations under the License. -->
|
|||||||
:key="item.value || ''"
|
:key="item.value || ''"
|
||||||
:label="item.label || ''"
|
:label="item.label || ''"
|
||||||
:value="item.value || ''"
|
:value="item.value || ''"
|
||||||
|
:disabled="item.disabled || false"
|
||||||
>
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
|
|
||||||
interface Option {
|
// interface Option {
|
||||||
label: string | number;
|
// label: string | number;
|
||||||
value: string | number;
|
// value: string | number;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*global defineProps, defineEmits*/
|
/*global defineProps, defineEmits, Indexable*/
|
||||||
const emit = defineEmits(["change", "query"]);
|
const emit = defineEmits(["change", "query"]);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
options: {
|
options: {
|
||||||
type: Array as PropType<(Option & { disabled?: boolean })[]>,
|
type: Array as PropType<
|
||||||
default: () => [],
|
({
|
||||||
},
|
label: string | number;
|
||||||
value: {
|
value: string | number;
|
||||||
type: [Array, String, Number, undefined] as PropType<any>,
|
} & { disabled?: boolean })[]
|
||||||
default: () => [],
|
>,
|
||||||
},
|
default: () => [],
|
||||||
size: { type: null, default: "default" },
|
},
|
||||||
placeholder: {
|
value: {
|
||||||
type: [String, undefined] as PropType<string>,
|
type: [Array, String, Number, undefined] as PropType<any>,
|
||||||
default: "Select a option",
|
default: () => [],
|
||||||
},
|
},
|
||||||
borderRadius: { type: Number, default: 3 },
|
size: { type: null, default: "default" },
|
||||||
multiple: { type: Boolean, default: false },
|
placeholder: {
|
||||||
disabled: { type: Boolean, default: false },
|
type: [String, undefined] as PropType<string>,
|
||||||
clearable: { type: Boolean, default: false },
|
default: "Select a option",
|
||||||
isRemote: { type: Boolean, default: false },
|
},
|
||||||
filterable: { type: Boolean, default: true },
|
borderRadius: { type: Number, default: 3 },
|
||||||
});
|
multiple: { type: Boolean, default: false },
|
||||||
|
disabled: { type: Boolean, default: false },
|
||||||
|
clearable: { type: Boolean, default: false },
|
||||||
|
isRemote: { type: Boolean, default: false },
|
||||||
|
filterable: { type: Boolean, default: true },
|
||||||
|
});
|
||||||
|
|
||||||
const selected = ref<string[] | string>(props.value);
|
const selected = ref<string[] | string>(props.value);
|
||||||
function changeSelected() {
|
function changeSelected() {
|
||||||
const options = props.options.filter((d: any) =>
|
const options = props.options.filter((d: Indexable) =>
|
||||||
props.multiple
|
props.multiple ? selected.value.includes(d.value) : selected.value === d.value,
|
||||||
? selected.value.includes(d.value)
|
);
|
||||||
: selected.value === d.value
|
emit("change", options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteMethod(query: string) {
|
||||||
|
if (props.isRemote) {
|
||||||
|
emit("query", query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(data) => {
|
||||||
|
selected.value = data;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
emit("change", options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function remoteMethod(query: string) {
|
|
||||||
if (props.isRemote) {
|
|
||||||
emit("query", query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.value,
|
|
||||||
(data) => {
|
|
||||||
selected.value = data;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.el-input__inner {
|
.el-input__inner {
|
||||||
border-radius: unset !important;
|
border-radius: unset !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
87
src/components/Tags.vue
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<!-- 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>
|
||||||
|
<span :class="vertical ? 'vertical' : 'horizontal'" v-for="tag in dynamicTags" :key="tag">
|
||||||
|
<el-tag closable :disable-transitions="false" @close="handleClose(tag)">
|
||||||
|
{{ tag }}
|
||||||
|
</el-tag>
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
v-if="inputVisible"
|
||||||
|
ref="InputRef"
|
||||||
|
v-model="inputValue"
|
||||||
|
class="ml-5 input-name"
|
||||||
|
size="small"
|
||||||
|
@keyup.enter="handleInputConfirm"
|
||||||
|
@blur="handleInputConfirm"
|
||||||
|
/>
|
||||||
|
<el-button v-else size="small" @click="showInput"> + {{ text }} </el-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
|
import type { PropType } from "vue";
|
||||||
|
import { ElInput } from "element-plus";
|
||||||
|
|
||||||
|
/*global defineProps, defineEmits*/
|
||||||
|
const emits = defineEmits(["change"]);
|
||||||
|
const props = defineProps({
|
||||||
|
tags: {
|
||||||
|
type: Array as PropType<string[]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
text: { type: String, default: "" },
|
||||||
|
vertical: { type: Boolean, default: false },
|
||||||
|
});
|
||||||
|
const inputValue = ref("");
|
||||||
|
const dynamicTags = ref<string[]>(props.tags || []);
|
||||||
|
const inputVisible = ref(false);
|
||||||
|
const InputRef = ref<InstanceType<typeof ElInput>>();
|
||||||
|
|
||||||
|
const handleClose = (tag: string) => {
|
||||||
|
dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showInput = () => {
|
||||||
|
inputVisible.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
InputRef.value!.input!.focus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputConfirm = () => {
|
||||||
|
if (inputValue.value) {
|
||||||
|
dynamicTags.value.push(inputValue.value);
|
||||||
|
}
|
||||||
|
inputVisible.value = false;
|
||||||
|
inputValue.value = "";
|
||||||
|
emits("change", dynamicTags.value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.input-name {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -35,56 +35,28 @@ limitations under the License. -->
|
|||||||
<transition name="datepicker-anim">
|
<transition name="datepicker-anim">
|
||||||
<div
|
<div
|
||||||
class="datepicker-popup"
|
class="datepicker-popup"
|
||||||
:class="[
|
:class="[popupClass, { 'datepicker-inline': type === 'inline' }, position]"
|
||||||
popupClass,
|
|
||||||
{ 'datepicker-inline': type === 'inline' },
|
|
||||||
position,
|
|
||||||
]"
|
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
v-if="show || type === 'inline'"
|
v-if="show || type === 'inline'"
|
||||||
>
|
>
|
||||||
<template v-if="range">
|
<template v-if="range">
|
||||||
<div class="datepicker-popup__sidebar">
|
<div class="datepicker-popup__sidebar">
|
||||||
<button
|
<button type="button" class="datepicker-popup__shortcut" @click="quickPick('quarter')">
|
||||||
type="button"
|
|
||||||
class="datepicker-popup__shortcut"
|
|
||||||
@click="quickPick('quarter')"
|
|
||||||
>
|
|
||||||
{{ local.quarterHourCutTip }}
|
{{ local.quarterHourCutTip }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" class="datepicker-popup__shortcut" @click="quickPick('half')">
|
||||||
type="button"
|
|
||||||
class="datepicker-popup__shortcut"
|
|
||||||
@click="quickPick('half')"
|
|
||||||
>
|
|
||||||
{{ local.halfHourCutTip }}
|
{{ local.halfHourCutTip }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" class="datepicker-popup__shortcut" @click="quickPick('hour')">
|
||||||
type="button"
|
|
||||||
class="datepicker-popup__shortcut"
|
|
||||||
@click="quickPick('hour')"
|
|
||||||
>
|
|
||||||
{{ local.hourCutTip }}
|
{{ local.hourCutTip }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" class="datepicker-popup__shortcut" @click="quickPick('day')">
|
||||||
type="button"
|
|
||||||
class="datepicker-popup__shortcut"
|
|
||||||
@click="quickPick('day')"
|
|
||||||
>
|
|
||||||
{{ local.dayCutTip }}
|
{{ local.dayCutTip }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" class="datepicker-popup__shortcut" @click="quickPick('week')">
|
||||||
type="button"
|
|
||||||
class="datepicker-popup__shortcut"
|
|
||||||
@click="quickPick('week')"
|
|
||||||
>
|
|
||||||
{{ local.weekCutTip }}
|
{{ local.weekCutTip }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" class="datepicker-popup__shortcut" @click="quickPick('month')">
|
||||||
type="button"
|
|
||||||
class="datepicker-popup__shortcut"
|
|
||||||
@click="quickPick('month')"
|
|
||||||
>
|
|
||||||
{{ local.monthCutTip }}
|
{{ local.monthCutTip }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,16 +95,10 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="showButtons" class="datepicker__buttons">
|
<div v-if="showButtons" class="datepicker__buttons">
|
||||||
<button
|
<button @click.prevent.stop="cancel" class="datepicker__button-cancel">
|
||||||
@click.prevent.stop="cancel"
|
|
||||||
class="datepicker__button-cancel"
|
|
||||||
>
|
|
||||||
{{ local.cancelTip }}
|
{{ local.cancelTip }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button @click.prevent.stop="submit" class="datepicker__button-select">
|
||||||
@click.prevent.stop="submit"
|
|
||||||
class="datepicker__button-select"
|
|
||||||
>
|
|
||||||
{{ local.submitTip }}
|
{{ local.submitTip }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,438 +108,430 @@ limitations under the License. -->
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue";
|
import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import DateCalendar from "./DateCalendar.vue";
|
import DateCalendar from "./DateCalendar.vue";
|
||||||
import { useTimeoutFn } from "@/hooks/useTimeout";
|
import { useTimeoutFn } from "@/hooks/useTimeout";
|
||||||
/*global defineProps, defineEmits */
|
/*global defineProps, defineEmits*/
|
||||||
const datepicker = ref(null);
|
const datepicker = ref(null);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const show = ref<boolean>(false);
|
const show = ref<boolean>(false);
|
||||||
const dates = ref<Date | string[] | any>([]);
|
const dates = ref<Date | string[] | any>([]);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
position: { type: String, default: "bottom" },
|
position: { type: String, default: "bottom" },
|
||||||
name: [String],
|
name: [String],
|
||||||
inputClass: [String],
|
inputClass: [String],
|
||||||
popupClass: [String],
|
popupClass: [String],
|
||||||
value: [Date, Array, String],
|
value: [Date, Array, String],
|
||||||
disabled: [Boolean],
|
disabled: [Boolean],
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "normal",
|
default: "normal",
|
||||||
},
|
},
|
||||||
rangeSeparator: {
|
rangeSeparator: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "~",
|
default: "~",
|
||||||
},
|
},
|
||||||
clearable: {
|
clearable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
placeholder: [String],
|
placeholder: [String],
|
||||||
disabledDate: {
|
disabledDate: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: () => false,
|
default: () => false,
|
||||||
},
|
},
|
||||||
format: {
|
format: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "YYYY-MM-DD",
|
default: "YYYY-MM-DD",
|
||||||
},
|
},
|
||||||
showButtons: {
|
showButtons: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
dateRangeSelect: [Function],
|
dateRangeSelect: [Function],
|
||||||
});
|
});
|
||||||
const emit = defineEmits(["clear", "input", "confirm", "cancel"]);
|
const emit = defineEmits(["clear", "input", "confirm", "cancel"]);
|
||||||
const local = computed(() => {
|
const local = computed(() => {
|
||||||
return {
|
return {
|
||||||
dow: 1, // Monday is the first day of the week
|
dow: 1, // Monday is the first day of the week
|
||||||
hourTip: t("hourTip"), // tip of select hour
|
hourTip: t("hourTip"), // tip of select hour
|
||||||
minuteTip: t("minuteTip"), // tip of select minute
|
minuteTip: t("minuteTip"), // tip of select minute
|
||||||
secondTip: t("secondTip"), // tip of select second
|
secondTip: t("secondTip"), // tip of select second
|
||||||
yearSuffix: t("yearSuffix"), // format of head
|
yearSuffix: t("yearSuffix"), // format of head
|
||||||
monthsHead: t("monthsHead").split("_"), // months of head
|
monthsHead: t("monthsHead").split("_"), // months of head
|
||||||
months: t("months").split("_"), // months of panel
|
months: t("months").split("_"), // months of panel
|
||||||
weeks: t("weeks").split("_"), // weeks
|
weeks: t("weeks").split("_"), // weeks
|
||||||
cancelTip: t("cancel"), // default text for cancel button
|
cancelTip: t("cancel"), // default text for cancel button
|
||||||
submitTip: t("confirm"), // default text for submit button
|
submitTip: t("confirm"), // default text for submit button
|
||||||
quarterHourCutTip: t("quarterHourCutTip"),
|
quarterHourCutTip: t("quarterHourCutTip"),
|
||||||
halfHourCutTip: t("halfHourCutTip"),
|
halfHourCutTip: t("halfHourCutTip"),
|
||||||
hourCutTip: t("hourCutTip"),
|
hourCutTip: t("hourCutTip"),
|
||||||
dayCutTip: t("dayCutTip"),
|
dayCutTip: t("dayCutTip"),
|
||||||
weekCutTip: t("weekCutTip"),
|
weekCutTip: t("weekCutTip"),
|
||||||
monthCutTip: t("monthCutTip"),
|
monthCutTip: t("monthCutTip"),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const tf = (time: Date, format?: any): string => {
|
||||||
|
const year = time.getFullYear();
|
||||||
|
const month = time.getMonth();
|
||||||
|
const day = time.getDate();
|
||||||
|
const hours24 = time.getHours();
|
||||||
|
const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
|
||||||
|
const minutes = time.getMinutes();
|
||||||
|
const seconds = time.getSeconds();
|
||||||
|
const milliseconds = time.getMilliseconds();
|
||||||
|
const dd = (t: number) => `0${t}`.slice(-2);
|
||||||
|
const map: { [key: string]: string | number } = {
|
||||||
|
YYYY: year,
|
||||||
|
MM: dd(month + 1),
|
||||||
|
MMM: local.value.months[month],
|
||||||
|
MMMM: local.value.monthsHead[month],
|
||||||
|
M: month + 1,
|
||||||
|
DD: dd(day),
|
||||||
|
D: day,
|
||||||
|
HH: dd(hours24),
|
||||||
|
H: hours24,
|
||||||
|
hh: dd(hours),
|
||||||
|
h: hours,
|
||||||
|
mm: dd(minutes),
|
||||||
|
m: minutes,
|
||||||
|
ss: dd(seconds),
|
||||||
|
s: seconds,
|
||||||
|
S: milliseconds,
|
||||||
|
};
|
||||||
|
return (format || props.format).replace(/Y+|M+|D+|H+|h+|m+|s+|S+/g, (str: string) => map[str]);
|
||||||
};
|
};
|
||||||
});
|
const range = computed(() => {
|
||||||
const tf = (time: Date, format?: any): string => {
|
return dates.value.length === 2;
|
||||||
const year = time.getFullYear();
|
});
|
||||||
const month = time.getMonth();
|
const text = computed(() => {
|
||||||
const day = time.getDate();
|
const val = props.value;
|
||||||
const hours24 = time.getHours();
|
const txt = dates.value.map((date: Date) => tf(date)).join(` ${props.rangeSeparator} `);
|
||||||
const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
|
if (Array.isArray(val)) {
|
||||||
const minutes = time.getMinutes();
|
return val.length > 1 ? txt : "";
|
||||||
const seconds = time.getSeconds();
|
}
|
||||||
const milliseconds = time.getMilliseconds();
|
return val ? txt : "";
|
||||||
const dd = (t: number) => `0${t}`.slice(-2);
|
});
|
||||||
const map: { [key: string]: string | number } = {
|
const get = () => {
|
||||||
YYYY: year,
|
return Array.isArray(props.value) ? dates.value : dates.value[0];
|
||||||
MM: dd(month + 1),
|
|
||||||
MMM: local.value.months[month],
|
|
||||||
MMMM: local.value.monthsHead[month],
|
|
||||||
M: month + 1,
|
|
||||||
DD: dd(day),
|
|
||||||
D: day,
|
|
||||||
HH: dd(hours24),
|
|
||||||
H: hours24,
|
|
||||||
hh: dd(hours),
|
|
||||||
h: hours,
|
|
||||||
mm: dd(minutes),
|
|
||||||
m: minutes,
|
|
||||||
ss: dd(seconds),
|
|
||||||
s: seconds,
|
|
||||||
S: milliseconds,
|
|
||||||
};
|
};
|
||||||
return (format || props.format).replace(
|
const cls = () => {
|
||||||
/Y+|M+|D+|H+|h+|m+|s+|S+/g,
|
emit("clear");
|
||||||
(str: string) => map[str]
|
emit("input", range.value ? [] : "");
|
||||||
|
};
|
||||||
|
const vi = (val: any) => {
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
return val.length > 1 ? val.map((item) => new Date(item)) : [new Date(), new Date()];
|
||||||
|
}
|
||||||
|
return val ? [new Date(val)] : [new Date()];
|
||||||
|
};
|
||||||
|
const ok = (leaveOpened: boolean) => {
|
||||||
|
emit("input", get());
|
||||||
|
!leaveOpened &&
|
||||||
|
!props.showButtons &&
|
||||||
|
useTimeoutFn(() => {
|
||||||
|
show.value = range.value;
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
const setDates = (d: Date, pos: string) => {
|
||||||
|
if (pos === "right") {
|
||||||
|
dates.value[1] = d;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dates.value[0] = d;
|
||||||
|
};
|
||||||
|
const dc = (e: MouseEvent) => {
|
||||||
|
show.value = (datepicker.value as any).contains(e.target) && !props.disabled;
|
||||||
|
};
|
||||||
|
const quickPick = (type: string) => {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
switch (type) {
|
||||||
|
case "quarter":
|
||||||
|
start.setTime(start.getTime() - 60 * 15 * 1000); //15 mins
|
||||||
|
break;
|
||||||
|
case "half":
|
||||||
|
start.setTime(start.getTime() - 60 * 30 * 1000); //30 mins
|
||||||
|
break;
|
||||||
|
case "hour":
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000); //1 hour
|
||||||
|
break;
|
||||||
|
case "day":
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24); //1 day
|
||||||
|
break;
|
||||||
|
case "week":
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); //1 week
|
||||||
|
break;
|
||||||
|
case "month":
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); //1 month
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dates.value = [start, end];
|
||||||
|
emit("input", get());
|
||||||
|
};
|
||||||
|
const submit = () => {
|
||||||
|
emit("confirm", get());
|
||||||
|
show.value = false;
|
||||||
|
};
|
||||||
|
const cancel = () => {
|
||||||
|
emit("cancel");
|
||||||
|
show.value = false;
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
dates.value = vi(props.value);
|
||||||
|
document.addEventListener("click", dc, true);
|
||||||
|
});
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
document.removeEventListener("click", dc, true);
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(val: unknown) => {
|
||||||
|
dates.value = vi(val);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
};
|
|
||||||
const range = computed(() => {
|
|
||||||
return dates.value.length === 2;
|
|
||||||
});
|
|
||||||
const text = computed(() => {
|
|
||||||
const val = props.value;
|
|
||||||
const txt = dates.value
|
|
||||||
.map((date: Date) => tf(date))
|
|
||||||
.join(` ${props.rangeSeparator} `);
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
return val.length > 1 ? txt : "";
|
|
||||||
}
|
|
||||||
return val ? txt : "";
|
|
||||||
});
|
|
||||||
const get = () => {
|
|
||||||
return Array.isArray(props.value) ? dates.value : dates.value[0];
|
|
||||||
};
|
|
||||||
const cls = () => {
|
|
||||||
emit("clear");
|
|
||||||
emit("input", range.value ? [] : "");
|
|
||||||
};
|
|
||||||
const vi = (val: any) => {
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
return val.length > 1
|
|
||||||
? val.map((item) => new Date(item))
|
|
||||||
: [new Date(), new Date()];
|
|
||||||
}
|
|
||||||
return val ? [new Date(val)] : [new Date()];
|
|
||||||
};
|
|
||||||
const ok = (leaveOpened: boolean) => {
|
|
||||||
emit("input", get());
|
|
||||||
!leaveOpened &&
|
|
||||||
!props.showButtons &&
|
|
||||||
useTimeoutFn(() => {
|
|
||||||
show.value = range.value;
|
|
||||||
}, 1);
|
|
||||||
};
|
|
||||||
const setDates = (d: Date, pos: string) => {
|
|
||||||
if (pos === "right") {
|
|
||||||
dates.value[1] = d;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dates.value[0] = d;
|
|
||||||
};
|
|
||||||
const dc = (e: any) => {
|
|
||||||
show.value = (datepicker.value as any).contains(e.target) && !props.disabled;
|
|
||||||
};
|
|
||||||
const quickPick = (type: string) => {
|
|
||||||
const end = new Date();
|
|
||||||
const start = new Date();
|
|
||||||
switch (type) {
|
|
||||||
case "quarter":
|
|
||||||
start.setTime(start.getTime() - 60 * 15 * 1000); //15 mins
|
|
||||||
break;
|
|
||||||
case "half":
|
|
||||||
start.setTime(start.getTime() - 60 * 30 * 1000); //30 mins
|
|
||||||
break;
|
|
||||||
case "hour":
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000); //1 hour
|
|
||||||
break;
|
|
||||||
case "day":
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24); //1 day
|
|
||||||
break;
|
|
||||||
case "week":
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); //1 week
|
|
||||||
break;
|
|
||||||
case "month":
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); //1 month
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dates.value = [start, end];
|
|
||||||
emit("input", get());
|
|
||||||
};
|
|
||||||
const submit = () => {
|
|
||||||
emit("confirm", get());
|
|
||||||
show.value = false;
|
|
||||||
};
|
|
||||||
const cancel = () => {
|
|
||||||
emit("cancel");
|
|
||||||
show.value = false;
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
|
||||||
dates.value = vi(props.value);
|
|
||||||
document.addEventListener("click", dc, true);
|
|
||||||
});
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
document.removeEventListener("click", dc, true);
|
|
||||||
});
|
|
||||||
watch(
|
|
||||||
() => props.value,
|
|
||||||
(val: unknown) => {
|
|
||||||
dates.value = vi(val);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@keyframes datepicker-anim-in {
|
@keyframes datepicker-anim-in {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleY(0.8);
|
transform: scaleY(0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleY(1);
|
transform: scaleY(1);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes datepicker-anim-out {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scaleY(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scaleY(0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-icon {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 8px;
|
|
||||||
left: 8px;
|
|
||||||
color: #515a6ecc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-close {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
width: 34px;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-close:before {
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
margin-left: -8px;
|
|
||||||
margin-top: -8px;
|
|
||||||
text-align: center;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #ccc
|
|
||||||
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3IDciIHdpZHRoPSI3IiBoZWlnaHQ9IjciPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01LjU4LDVsMi44LTIuODFBLjQxLjQxLDAsMSwwLDcuOCwxLjZMNSw0LjQxLDIuMiwxLjZhLjQxLjQxLDAsMCwwLS41OC41OGgwTDQuNDIsNSwxLjYyLDcuOGEuNDEuNDEsMCwwLDAsLjU4LjU4TDUsNS41OCw3LjgsOC4zOWEuNDEuNDEsMCwwLDAsLjU4LS41OGgwWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuNSAtMS40OCkiIHN0eWxlPSJmaWxsOiNmZmYiLz48L3N2Zz4NCg==")
|
|
||||||
no-repeat 50% 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker__clearable:hover:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker__clearable:hover .datepicker-close {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-close:hover:before {
|
|
||||||
background-color: #afafaf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker > input {
|
|
||||||
color: inherit;
|
|
||||||
// transition: all 200ms ease;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 0;
|
|
||||||
background: none;
|
|
||||||
height: 28px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
outline: none;
|
|
||||||
padding: 0 5px;
|
|
||||||
width: 100%;
|
|
||||||
user-select: none;
|
|
||||||
font-family: "Monaco";
|
|
||||||
letter-spacing: -0.7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// .datepicker > input.focus {
|
|
||||||
// border-color: #3f97e3;
|
|
||||||
// -webkit-box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
|
|
||||||
// box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
|
|
||||||
// }
|
|
||||||
|
|
||||||
.datepicker > input:disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
background-color: #ebebe4;
|
|
||||||
border-color: #e5e5e5;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-popup {
|
|
||||||
border-radius: 4px;
|
|
||||||
position: absolute;
|
|
||||||
transition: all 200ms ease;
|
|
||||||
opacity: 1;
|
|
||||||
transform: scaleY(1);
|
|
||||||
font-size: 12px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 1px 6px rgba(99, 99, 99, 0.2);
|
|
||||||
margin-top: 2px;
|
|
||||||
outline: 0;
|
|
||||||
padding: 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 999;
|
|
||||||
|
|
||||||
&.top {
|
|
||||||
bottom: 30px;
|
|
||||||
right: 0;
|
|
||||||
transform-origin: center bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.bottom {
|
|
||||||
top: 30px;
|
|
||||||
right: 0;
|
|
||||||
transform-origin: center top;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.left {
|
|
||||||
top: 30px;
|
|
||||||
transform-origin: center top;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
right: -80px;
|
|
||||||
top: 30px;
|
|
||||||
transform-origin: center top;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__sidebar {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100px;
|
|
||||||
height: 100%;
|
|
||||||
padding: 5px;
|
|
||||||
border-right: solid 1px #eaeaea;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__shortcut {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
line-height: 34px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
text-align: left;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #3f97e3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__body {
|
@keyframes datepicker-anim-out {
|
||||||
margin-left: 100px;
|
0% {
|
||||||
padding-left: 5px;
|
opacity: 1;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0.8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-inline {
|
.datepicker {
|
||||||
position: relative;
|
display: inline-block;
|
||||||
margin-top: 0;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-range {
|
.datepicker-icon {
|
||||||
min-width: 238px;
|
display: block;
|
||||||
}
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
left: 8px;
|
||||||
|
color: #515a6ecc;
|
||||||
|
}
|
||||||
|
|
||||||
.datepicker-range .datepicker-popup {
|
.datepicker-close {
|
||||||
width: 520px;
|
display: none;
|
||||||
}
|
position: absolute;
|
||||||
|
width: 34px;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.datepicker-bottom {
|
.datepicker-close::before {
|
||||||
float: left;
|
display: block;
|
||||||
width: 100%;
|
content: "";
|
||||||
text-align: right;
|
position: absolute;
|
||||||
}
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
margin-left: -8px;
|
||||||
|
margin-top: -8px;
|
||||||
|
text-align: center;
|
||||||
|
color: $text-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: $disabled-color
|
||||||
|
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3IDciIHdpZHRoPSI3IiBoZWlnaHQ9IjciPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01LjU4LDVsMi44LTIuODFBLjQxLjQxLDAsMSwwLDcuOCwxLjZMNSw0LjQxLDIuMiwxLjZhLjQxLjQxLDAsMCwwLS41OC41OGgwTDQuNDIsNSwxLjYyLDcuOGEuNDEuNDEsMCwwLDAsLjU4LjU4TDUsNS41OCw3LjgsOC4zOWEuNDEuNDEsMCwwLDAsLjU4LS41OGgwWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuNSAtMS40OCkiIHN0eWxlPSJmaWxsOiNmZmYiLz48L3N2Zz4NCg==")
|
||||||
|
no-repeat 50% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
.datepicker-btn {
|
.datepicker__clearable:hover::before {
|
||||||
padding: 5px 10px;
|
display: none;
|
||||||
background: #3f97e3;
|
}
|
||||||
color: #fff;
|
|
||||||
border-radius: 2px;
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-anim-enter-active {
|
.datepicker__clearable:hover .datepicker-close {
|
||||||
transform-origin: 0 0;
|
display: block;
|
||||||
animation: datepicker-anim-in 0.2s cubic-bezier(0.23, 1, 0.32, 1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker-anim-leave-active {
|
.datepicker-close:hover::before {
|
||||||
transform-origin: 0 0;
|
background-color: #afafaf;
|
||||||
animation: datepicker-anim-out 0.2s cubic-bezier(0.755, 0.05, 0.855, 0.06);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker__buttons {
|
.datepicker > input {
|
||||||
display: block;
|
color: inherit;
|
||||||
text-align: right;
|
// transition: all 200ms ease;
|
||||||
}
|
border-radius: 4px;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
height: 28px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: none;
|
||||||
|
padding: 0 5px;
|
||||||
|
width: 100%;
|
||||||
|
user-select: none;
|
||||||
|
font-family: Monaco;
|
||||||
|
letter-spacing: -0.7px;
|
||||||
|
}
|
||||||
|
|
||||||
.datepicker__buttons button {
|
// .datepicker > input.focus {
|
||||||
display: inline-block;
|
// border-color: #3f97e3;
|
||||||
font-size: 13px;
|
// -webkit-box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
|
||||||
border: none;
|
// box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
|
||||||
cursor: pointer;
|
// }
|
||||||
margin: 10px 0 0 5px;
|
|
||||||
padding: 5px 15px;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.datepicker__buttons .datepicker__button-select {
|
.datepicker > input:disabled {
|
||||||
background: #3f97e3;
|
cursor: not-allowed;
|
||||||
}
|
background-color: #ebebe4;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.datepicker__buttons .datepicker__button-cancel {
|
.datepicker-popup {
|
||||||
background: #666;
|
border-radius: 4px;
|
||||||
}
|
position: absolute;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
opacity: 1;
|
||||||
|
transform: scaleY(1);
|
||||||
|
font-size: $font-size-smaller;
|
||||||
|
background: $theme-background;
|
||||||
|
box-shadow: 0 1px 6px rgb(99 99 99 / 20%);
|
||||||
|
margin-top: 2px;
|
||||||
|
outline: 0;
|
||||||
|
padding: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
&.top {
|
||||||
|
bottom: 30px;
|
||||||
|
right: 0;
|
||||||
|
transform-origin: center bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bottom {
|
||||||
|
top: 30px;
|
||||||
|
right: 0;
|
||||||
|
transform-origin: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
top: 30px;
|
||||||
|
transform-origin: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
right: -80px;
|
||||||
|
top: 30px;
|
||||||
|
transform-origin: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sidebar {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100px;
|
||||||
|
height: 100%;
|
||||||
|
padding: 5px;
|
||||||
|
border-right: solid 1px #eaeaea;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__shortcut {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
line-height: 34px;
|
||||||
|
font-size: $font-size-smaller;
|
||||||
|
color: #666;
|
||||||
|
text-align: left;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #3f97e3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
margin-left: 100px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-inline {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-range {
|
||||||
|
min-width: 238px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-range .datepicker-popup {
|
||||||
|
width: 520px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-bottom {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-btn {
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #3f97e3;
|
||||||
|
color: $text-color;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-anim-enter-active {
|
||||||
|
transform-origin: 0 0;
|
||||||
|
animation: datepicker-anim-in 0.2s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker-anim-leave-active {
|
||||||
|
transform-origin: 0 0;
|
||||||
|
animation: datepicker-anim-out 0.2s cubic-bezier(0.755, 0.05, 0.855, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker__buttons {
|
||||||
|
display: block;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker__buttons button {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 13px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 10px 0 0 5px;
|
||||||
|
padding: 5px 15px;
|
||||||
|
color: $text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker__buttons .datepicker__button-select {
|
||||||
|
background: #3f97e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datepicker__buttons .datepicker__button-cancel {
|
||||||
|
background: #666;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
33
src/components/__tests__/HelloWorld.spec.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import { describe, it } from "vitest";
|
||||||
|
|
||||||
|
// import { mount } from '@vue/test-utils'
|
||||||
|
// import HelloWorld from '../HelloWorld.vue'
|
||||||
|
|
||||||
|
// describe('HelloWorld', () => {
|
||||||
|
// it('renders properly', () => {
|
||||||
|
// const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
|
||||||
|
// expect(wrapper.text()).toContain('Hello Vitest')
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
describe("My First Test", () => {
|
||||||
|
it("renders props.msg when passed", () => {
|
||||||
|
const msg = "new message";
|
||||||
|
console.log(msg);
|
||||||
|
});
|
||||||
|
});
|
@@ -21,9 +21,10 @@ import Selector from "./Selector.vue";
|
|||||||
import Graph from "./Graph.vue";
|
import Graph from "./Graph.vue";
|
||||||
import Radio from "./Radio.vue";
|
import Radio from "./Radio.vue";
|
||||||
import SelectSingle from "./SelectSingle.vue";
|
import SelectSingle from "./SelectSingle.vue";
|
||||||
|
import Tags from "./Tags.vue";
|
||||||
import VueGridLayout from "vue-grid-layout";
|
import VueGridLayout from "vue-grid-layout";
|
||||||
|
|
||||||
const components: { [key: string]: any } = {
|
const components: Indexable = {
|
||||||
Icon,
|
Icon,
|
||||||
TimePicker,
|
TimePicker,
|
||||||
VueGridLayout,
|
VueGridLayout,
|
||||||
@@ -31,6 +32,7 @@ const components: { [key: string]: any } = {
|
|||||||
Graph,
|
Graph,
|
||||||
Radio,
|
Radio,
|
||||||
SelectSingle,
|
SelectSingle,
|
||||||
|
Tags,
|
||||||
};
|
};
|
||||||
const componentsName: string[] = Object.keys(components);
|
const componentsName: string[] = Object.keys(components);
|
||||||
|
|
||||||
|
@@ -14,22 +14,18 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import axios, { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
|
import axios from "axios";
|
||||||
import { cancelToken } from "@/utils/cancelToken";
|
import { cancelToken } from "@/utils/cancelToken";
|
||||||
|
|
||||||
async function query(param: {
|
async function query(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
|
||||||
queryStr: string;
|
|
||||||
conditions: { [key: string]: unknown };
|
|
||||||
}) {
|
|
||||||
const res: AxiosResponse = await axios.post(
|
const res: AxiosResponse = await axios.post(
|
||||||
"/graphql",
|
"/graphql",
|
||||||
{ query: param.queryStr, variables: { ...param.conditions } },
|
{ query: param.queryStr, variables: { ...param.conditions } },
|
||||||
{ cancelToken: cancelToken() }
|
{ cancelToken: cancelToken() },
|
||||||
);
|
);
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
res.data.errors = res.data.errors
|
res.data.errors = res.data.errors.map((e: { message: string }) => e.message).join(" ");
|
||||||
.map((e: { message: string }) => e.message)
|
|
||||||
.join(" ");
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@@ -16,8 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const Alarm = {
|
export const Alarm = {
|
||||||
variable:
|
variable: "$keyword: String, $scope: Scope, $duration:Duration!, $tags:[AlarmTag], $paging: Pagination!",
|
||||||
"$keyword: String, $scope: Scope, $duration:Duration!, $tags:[AlarmTag], $paging: Pagination!",
|
|
||||||
query: `
|
query: `
|
||||||
getAlarm(keyword: $keyword, scope: $scope, duration: $duration, paging: $paging, tags: $tags) {
|
getAlarm(keyword: $keyword, scope: $scope, duration: $duration, paging: $paging, tags: $tags) {
|
||||||
items: msgs {
|
items: msgs {
|
||||||
|
@@ -26,3 +26,26 @@ export const OAPTimeInfo = {
|
|||||||
export const OAPVersion = {
|
export const OAPVersion = {
|
||||||
query: `version { version }`,
|
query: `version { version }`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const MenuItems = {
|
||||||
|
query: `
|
||||||
|
getMenuItems {
|
||||||
|
title
|
||||||
|
icon
|
||||||
|
layer
|
||||||
|
activate
|
||||||
|
description
|
||||||
|
documentLink
|
||||||
|
i18nKey
|
||||||
|
subItems {
|
||||||
|
title
|
||||||
|
icon
|
||||||
|
layer
|
||||||
|
activate
|
||||||
|
description
|
||||||
|
documentLink
|
||||||
|
i18nKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
@@ -34,20 +34,36 @@ export const createEBPFTask = {
|
|||||||
};
|
};
|
||||||
export const queryEBPFTasks = {
|
export const queryEBPFTasks = {
|
||||||
variable:
|
variable:
|
||||||
"$serviceId: ID, $serviceInstanceId: ID, $targets: [EBPFProfilingTargetType!]",
|
"$serviceId: ID, $serviceInstanceId: ID, $targets: [EBPFProfilingTargetType!], $triggerType: EBPFProfilingTriggerType",
|
||||||
query: `
|
query: `
|
||||||
queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, targets: $targets) {
|
queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, targets: $targets, triggerType: $triggerType) {
|
||||||
taskId
|
taskId
|
||||||
serviceName
|
serviceName
|
||||||
serviceId
|
serviceId
|
||||||
serviceInstanceId
|
serviceInstanceId
|
||||||
serviceInstanceName
|
serviceInstanceName
|
||||||
processLabels
|
processLabels
|
||||||
|
processName
|
||||||
|
processId
|
||||||
taskStartTime
|
taskStartTime
|
||||||
triggerType
|
triggerType
|
||||||
fixedTriggerDuration
|
fixedTriggerDuration
|
||||||
targetType
|
targetType
|
||||||
createTime
|
createTime
|
||||||
|
continuousProfilingCauses {
|
||||||
|
type
|
||||||
|
singleValue {
|
||||||
|
threshold
|
||||||
|
current
|
||||||
|
}
|
||||||
|
uri {
|
||||||
|
uriRegex
|
||||||
|
uriPath
|
||||||
|
threshold
|
||||||
|
current
|
||||||
|
}
|
||||||
|
message
|
||||||
|
}
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
export const queryEBPFSchedules = {
|
export const queryEBPFSchedules = {
|
||||||
@@ -112,3 +128,26 @@ export const keepNetworkProfiling = {
|
|||||||
errorReason
|
errorReason
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const monitoringInstances = {
|
||||||
|
variable: "$serviceId: ID!, $target: ContinuousProfilingTargetType!",
|
||||||
|
query: `
|
||||||
|
instances: queryContinuousProfilingMonitoringInstances(serviceId: $serviceId, target: $target) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
|
triggeredCount
|
||||||
|
lastTriggerTimestamp
|
||||||
|
processes {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
detectType
|
||||||
|
labels
|
||||||
|
lastTriggerTimestamp
|
||||||
|
triggeredCount
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
@@ -15,37 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const ProfileSegment = {
|
|
||||||
variable: "$segmentId: String",
|
|
||||||
query: `
|
|
||||||
segment: getProfiledSegment(segmentId: $segmentId) {
|
|
||||||
spans {
|
|
||||||
spanId
|
|
||||||
parentSpanId
|
|
||||||
serviceCode
|
|
||||||
startTime
|
|
||||||
endTime
|
|
||||||
endpointName
|
|
||||||
type
|
|
||||||
peer
|
|
||||||
component
|
|
||||||
isError
|
|
||||||
layer
|
|
||||||
tags {
|
|
||||||
key value
|
|
||||||
}
|
|
||||||
logs {
|
|
||||||
time
|
|
||||||
data {
|
|
||||||
key
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CreateProfileTask = {
|
export const CreateProfileTask = {
|
||||||
variable: "$creationRequest: ProfileTaskCreationRequest",
|
variable: "$creationRequest: ProfileTaskCreationRequest",
|
||||||
query: `
|
query: `
|
||||||
@@ -79,23 +48,55 @@ export const GetProfileTaskList = {
|
|||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
export const GetProfileTaskSegmentList = {
|
export const GetProfileTaskSegmentList = {
|
||||||
variable: "$taskID: String",
|
variable: "$taskID: ID!",
|
||||||
query: `
|
query: `
|
||||||
segmentList: getProfileTaskSegmentList(taskID: $taskID) {
|
segmentList: getProfileTaskSegments(taskID: $taskID) {
|
||||||
segmentId
|
traceId
|
||||||
|
instanceId
|
||||||
|
instanceName
|
||||||
endpointNames
|
endpointNames
|
||||||
start
|
|
||||||
duration
|
duration
|
||||||
traceIds
|
start
|
||||||
isError
|
spans {
|
||||||
|
spanId
|
||||||
|
parentSpanId
|
||||||
|
segmentId
|
||||||
|
refs {
|
||||||
|
traceId
|
||||||
|
parentSegmentId
|
||||||
|
parentSpanId
|
||||||
|
type
|
||||||
|
}
|
||||||
|
serviceCode
|
||||||
|
serviceInstanceName
|
||||||
|
startTime
|
||||||
|
endTime
|
||||||
|
endpointName
|
||||||
|
type
|
||||||
|
peer
|
||||||
|
component
|
||||||
|
isError
|
||||||
|
layer
|
||||||
|
tags {
|
||||||
|
key value
|
||||||
|
}
|
||||||
|
logs {
|
||||||
|
time
|
||||||
|
data {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
profiled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GetProfileAnalyze = {
|
export const GetProfileAnalyze = {
|
||||||
variable: "$segmentId: String!, $timeRanges: [ProfileAnalyzeTimeRange!]!",
|
variable: "$queries: [SegmentProfileAnalyzeQuery!]!",
|
||||||
query: `
|
query: `
|
||||||
analyze: getProfileAnalyze(segmentId: $segmentId, timeRanges: $timeRanges) {
|
analyze: getSegmentsProfileAnalyze(queries: $queries) {
|
||||||
tip
|
tip
|
||||||
trees {
|
trees {
|
||||||
elements {
|
elements {
|
||||||
@@ -122,3 +123,29 @@ export const GetProfileTaskLogs = {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
export const GetStrategyList = {
|
||||||
|
variable: "$serviceId: ID!",
|
||||||
|
query: `
|
||||||
|
strategyList: queryContinuousProfilingServiceTargets(serviceId: $serviceId) {
|
||||||
|
type
|
||||||
|
checkItems {
|
||||||
|
type
|
||||||
|
threshold
|
||||||
|
period
|
||||||
|
count
|
||||||
|
uriList
|
||||||
|
uriRegex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EditStrategy = {
|
||||||
|
variable: "$request: ContinuousProfilingPolicyCreation!",
|
||||||
|
query: `
|
||||||
|
strategy: setContinuousProfilingPolicy(request: $request) {
|
||||||
|
errorReason
|
||||||
|
status
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
@@ -53,8 +53,7 @@ export const EndpointTopology = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
export const InstanceTopology = {
|
export const InstanceTopology = {
|
||||||
variable:
|
variable: "$clientServiceId: ID!, $serverServiceId: ID!, $duration: Duration!",
|
||||||
"$clientServiceId: ID!, $serverServiceId: ID!, $duration: Duration!",
|
|
||||||
query: `
|
query: `
|
||||||
topology: getServiceInstanceTopology(clientServiceId: $clientServiceId,
|
topology: getServiceInstanceTopology(clientServiceId: $clientServiceId,
|
||||||
serverServiceId: $serverServiceId, duration: $duration) {
|
serverServiceId: $serverServiceId, duration: $duration) {
|
||||||
|
@@ -14,7 +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.
|
||||||
*/
|
*/
|
||||||
import axios, { AxiosPromise, AxiosResponse } from "axios";
|
import type { AxiosPromise, AxiosResponse } from "axios";
|
||||||
|
import axios from "axios";
|
||||||
import { cancelToken } from "@/utils/cancelToken";
|
import { cancelToken } from "@/utils/cancelToken";
|
||||||
import * as app from "./query/app";
|
import * as app from "./query/app";
|
||||||
import * as selector from "./query/selector";
|
import * as selector from "./query/selector";
|
||||||
@@ -55,13 +56,11 @@ class Graphql {
|
|||||||
query: query[this.queryData],
|
query: query[this.queryData],
|
||||||
variables: variablesData,
|
variables: variablesData,
|
||||||
},
|
},
|
||||||
{ cancelToken: cancelToken() }
|
{ cancelToken: cancelToken() },
|
||||||
)
|
)
|
||||||
.then((res: AxiosResponse) => {
|
.then((res: AxiosResponse) => {
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
res.data.errors = res.data.errors
|
res.data.errors = res.data.errors.map((e: { message: string }) => e.message).join(" ");
|
||||||
.map((e: { message: string }) => e.message)
|
|
||||||
.join(" ");
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
})
|
})
|
||||||
|
@@ -14,8 +14,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { OAPTimeInfo, OAPVersion } from "../fragments/app";
|
import { OAPTimeInfo, OAPVersion, MenuItems } from "../fragments/app";
|
||||||
|
|
||||||
export const queryOAPTimeInfo = `query queryOAPTimeInfo {${OAPTimeInfo.query}}`;
|
export const queryOAPTimeInfo = `query queryOAPTimeInfo {${OAPTimeInfo.query}}`;
|
||||||
|
|
||||||
export const queryOAPVersion = `query ${OAPVersion.query}`;
|
export const queryOAPVersion = `query ${OAPVersion.query}`;
|
||||||
|
|
||||||
|
export const queryMenuItems = `query menuItems {${MenuItems.query}}`;
|
||||||
|
@@ -23,6 +23,7 @@ import {
|
|||||||
analysisEBPFResult,
|
analysisEBPFResult,
|
||||||
createNetworkProfiling,
|
createNetworkProfiling,
|
||||||
keepNetworkProfiling,
|
keepNetworkProfiling,
|
||||||
|
monitoringInstances,
|
||||||
} from "../fragments/ebpf";
|
} from "../fragments/ebpf";
|
||||||
|
|
||||||
export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`;
|
export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`;
|
||||||
@@ -38,3 +39,5 @@ export const getEBPFResult = `query analysisEBPFResult(${analysisEBPFResult.vari
|
|||||||
export const newNetworkProfiling = `mutation createNetworkProfiling(${createNetworkProfiling.variable}) {${createNetworkProfiling.query}}`;
|
export const newNetworkProfiling = `mutation createNetworkProfiling(${createNetworkProfiling.variable}) {${createNetworkProfiling.query}}`;
|
||||||
|
|
||||||
export const aliveNetworkProfiling = `mutation keepNetworkProfiling(${keepNetworkProfiling.variable}) {${keepNetworkProfiling.query}}`;
|
export const aliveNetworkProfiling = `mutation keepNetworkProfiling(${keepNetworkProfiling.variable}) {${keepNetworkProfiling.query}}`;
|
||||||
|
|
||||||
|
export const getMonitoringInstances = `query continuousProfilingMonitoringInstances(${monitoringInstances.variable}) {${monitoringInstances.query}}`;
|
||||||
|
@@ -16,16 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ProfileSegment,
|
|
||||||
CreateProfileTask,
|
CreateProfileTask,
|
||||||
GetProfileTaskList,
|
GetProfileTaskList,
|
||||||
GetProfileTaskSegmentList,
|
GetProfileTaskSegmentList,
|
||||||
GetProfileAnalyze,
|
GetProfileAnalyze,
|
||||||
GetProfileTaskLogs,
|
GetProfileTaskLogs,
|
||||||
|
GetStrategyList,
|
||||||
|
EditStrategy,
|
||||||
} from "../fragments/profile";
|
} from "../fragments/profile";
|
||||||
|
|
||||||
export const queryProfileSegment = `query queryProfileSegment(${ProfileSegment.variable}) {${ProfileSegment.query}}`;
|
|
||||||
|
|
||||||
export const saveProfileTask = `mutation createProfileTask(${CreateProfileTask.variable}) {${CreateProfileTask.query}}`;
|
export const saveProfileTask = `mutation createProfileTask(${CreateProfileTask.variable}) {${CreateProfileTask.query}}`;
|
||||||
|
|
||||||
export const getProfileTaskList = `query getProfileTaskList(${GetProfileTaskList.variable}) {
|
export const getProfileTaskList = `query getProfileTaskList(${GetProfileTaskList.variable}) {
|
||||||
@@ -37,3 +36,7 @@ export const getProfileTaskSegmentList = `query getProfileTaskSegmentList(${GetP
|
|||||||
export const getProfileAnalyze = `query getProfileAnalyze(${GetProfileAnalyze.variable}) {${GetProfileAnalyze.query}}`;
|
export const getProfileAnalyze = `query getProfileAnalyze(${GetProfileAnalyze.variable}) {${GetProfileAnalyze.query}}`;
|
||||||
|
|
||||||
export const getProfileTaskLogs = `query profileTaskLogs(${GetProfileTaskLogs.variable}) {${GetProfileTaskLogs.query}}`;
|
export const getProfileTaskLogs = `query profileTaskLogs(${GetProfileTaskLogs.variable}) {${GetProfileTaskLogs.query}}`;
|
||||||
|
|
||||||
|
export const getStrategyList = `query getStrategyList(${GetStrategyList.variable}) {${GetStrategyList.query}}`;
|
||||||
|
|
||||||
|
export const editStrategy = `mutation editStrategy(${EditStrategy.variable}) {${EditStrategy.query}}`;
|
||||||
|
@@ -14,12 +14,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { InstanceTopology, EndpointTopology, ServicesTopology, ProcessTopology } from "../fragments/topology";
|
||||||
InstanceTopology,
|
|
||||||
EndpointTopology,
|
|
||||||
ServicesTopology,
|
|
||||||
ProcessTopology,
|
|
||||||
} from "../fragments/topology";
|
|
||||||
|
|
||||||
export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`;
|
export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`;
|
||||||
export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`;
|
export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`;
|
||||||
|
@@ -15,12 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { Traces, TraceSpans, TraceTagKeys, TraceTagValues } from "../fragments/trace";
|
||||||
Traces,
|
|
||||||
TraceSpans,
|
|
||||||
TraceTagKeys,
|
|
||||||
TraceTagValues,
|
|
||||||
} from "../fragments/trace";
|
|
||||||
|
|
||||||
export const queryTraces = `query queryTraces(${Traces.variable}) {${Traces.query}}`;
|
export const queryTraces = `query queryTraces(${Traces.variable}) {${Traces.query}}`;
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@ export enum MetricQueryTypes {
|
|||||||
READHEATMAP = "readHeatMap",
|
READHEATMAP = "readHeatMap",
|
||||||
ReadSampledRecords = "readSampledRecords",
|
ReadSampledRecords = "readSampledRecords",
|
||||||
ReadRecords = "readRecords",
|
ReadRecords = "readRecords",
|
||||||
|
ReadNullableMetricsValue = "readNullableMetricsValue",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Calculations {
|
export enum Calculations {
|
||||||
@@ -30,7 +31,6 @@ export enum Calculations {
|
|||||||
ByteToMB = "byteToMB",
|
ByteToMB = "byteToMB",
|
||||||
ByteToGB = "byteToGB",
|
ByteToGB = "byteToGB",
|
||||||
Apdex = "apdex",
|
Apdex = "apdex",
|
||||||
Precision = "precision",
|
|
||||||
ConvertSeconds = "convertSeconds",
|
ConvertSeconds = "convertSeconds",
|
||||||
ConvertMilliseconds = "convertMilliseconds",
|
ConvertMilliseconds = "convertMilliseconds",
|
||||||
MsToS = "msTos",
|
MsToS = "msTos",
|
||||||
@@ -67,14 +67,18 @@ screenMap.set(sizeEnum.LG, screenEnum.LG);
|
|||||||
screenMap.set(sizeEnum.XL, screenEnum.XL);
|
screenMap.set(sizeEnum.XL, screenEnum.XL);
|
||||||
screenMap.set(sizeEnum.XXL, screenEnum.XXL);
|
screenMap.set(sizeEnum.XXL, screenEnum.XXL);
|
||||||
|
|
||||||
export const RespFields: any = {
|
export const RespFields: Indexable = {
|
||||||
readMetricsValues: `{
|
readMetricsValues: `{
|
||||||
label
|
label
|
||||||
values {
|
values {
|
||||||
values {value}
|
values {value isEmptyValue}
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
readMetricsValue: "",
|
readMetricsValue: ``,
|
||||||
|
readNullableMetricsValue: `{
|
||||||
|
value
|
||||||
|
isEmptyValue
|
||||||
|
}`,
|
||||||
sortMetrics: `{
|
sortMetrics: `{
|
||||||
name
|
name
|
||||||
id
|
id
|
||||||
@@ -84,7 +88,7 @@ export const RespFields: any = {
|
|||||||
readLabeledMetricsValues: `{
|
readLabeledMetricsValues: `{
|
||||||
label
|
label
|
||||||
values {
|
values {
|
||||||
values {value}
|
values {value isEmptyValue}
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
readHeatMap: `{
|
readHeatMap: `{
|
||||||
@@ -108,4 +112,21 @@ export const RespFields: any = {
|
|||||||
value
|
value
|
||||||
refId
|
refId
|
||||||
}`,
|
}`,
|
||||||
|
execExpression: `{
|
||||||
|
type
|
||||||
|
results {
|
||||||
|
metric {
|
||||||
|
labels {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
name: id
|
||||||
|
value
|
||||||
|
refId: traceID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error
|
||||||
|
}`,
|
||||||
};
|
};
|
||||||
|
@@ -17,9 +17,9 @@
|
|||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import dateFormatStep from "@/utils/dateFormat";
|
import dateFormatStep from "@/utils/dateFormat";
|
||||||
import getLocalTime from "@/utils/localtime";
|
import getLocalTime from "@/utils/localtime";
|
||||||
import { EventParams } from "@/types/app";
|
import type { EventParams } from "@/types/app";
|
||||||
|
|
||||||
export default function associateProcessor(props: any) {
|
export default function associateProcessor(props: Indexable) {
|
||||||
function eventAssociate() {
|
function eventAssociate() {
|
||||||
if (!props.filters) {
|
if (!props.filters) {
|
||||||
return;
|
return;
|
||||||
@@ -30,9 +30,7 @@ export default function associateProcessor(props: any) {
|
|||||||
if (!props.option.series[0]) {
|
if (!props.option.series[0]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const list = props.option.series[0].data.map(
|
const list = props.option.series[0].data.map((d: (number | string)[]) => d[0]);
|
||||||
(d: (number | string)[]) => d[0]
|
|
||||||
);
|
|
||||||
if (!list.includes(props.filters.duration.endTime)) {
|
if (!list.includes(props.filters.duration.endTime)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -77,16 +75,8 @@ export default function associateProcessor(props: any) {
|
|||||||
if (start) {
|
if (start) {
|
||||||
const end = start;
|
const end = start;
|
||||||
duration = {
|
duration = {
|
||||||
start: dateFormatStep(
|
start: dateFormatStep(getLocalTime(appStore.utc, new Date(start)), step, true),
|
||||||
getLocalTime(appStore.utc, new Date(start)),
|
end: dateFormatStep(getLocalTime(appStore.utc, new Date(end)), step, true),
|
||||||
step,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
end: dateFormatStep(
|
|
||||||
getLocalTime(appStore.utc, new Date(end)),
|
|
||||||
step,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
step,
|
step,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -95,44 +85,36 @@ export default function associateProcessor(props: any) {
|
|||||||
const queryOrder = relatedTrace.queryOrder;
|
const queryOrder = relatedTrace.queryOrder;
|
||||||
const latency = relatedTrace.latency;
|
const latency = relatedTrace.latency;
|
||||||
const series = props.option.series || [];
|
const series = props.option.series || [];
|
||||||
const item: any = {
|
const item: Indexable = {
|
||||||
duration,
|
duration,
|
||||||
queryOrder,
|
queryOrder,
|
||||||
status,
|
status,
|
||||||
};
|
};
|
||||||
if (latency) {
|
if (latency) {
|
||||||
const latencyList = series.map(
|
const latencyList = series.map((d: { name: string; data: number[][] }, index: number) => {
|
||||||
(d: { name: string; data: number[][] }, index: number) => {
|
const data = [
|
||||||
const data = [
|
d.data[currentParams.dataIndex][1],
|
||||||
d.data[currentParams.dataIndex][1],
|
series[index + 1] ? series[index + 1].data[currentParams.dataIndex][1] : Infinity,
|
||||||
series[index + 1]
|
];
|
||||||
? series[index + 1].data[currentParams.dataIndex][1]
|
return {
|
||||||
: Infinity,
|
label: d.name + "--" + (series[index + 1] ? series[index + 1].name : "Infinity"),
|
||||||
];
|
value: String(index),
|
||||||
return {
|
data,
|
||||||
label:
|
};
|
||||||
d.name +
|
});
|
||||||
"--" +
|
|
||||||
(series[index + 1] ? series[index + 1].name : "Infinity"),
|
|
||||||
value: String(index),
|
|
||||||
data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
item.latency = latencyList;
|
item.latency = latencyList;
|
||||||
}
|
}
|
||||||
const value = series.map(
|
const value = series.map((d: { name: string; data: number[][] }, index: number) => {
|
||||||
(d: { name: string; data: number[][] }, index: number) => {
|
return {
|
||||||
return {
|
label: d.name,
|
||||||
label: d.name,
|
value: String(index),
|
||||||
value: String(index),
|
data: d.data[currentParams.dataIndex][1],
|
||||||
data: d.data[currentParams.dataIndex][1],
|
date: d.data[currentParams.dataIndex][0],
|
||||||
date: d.data[currentParams.dataIndex][0],
|
};
|
||||||
};
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
item.metricValue = value;
|
item.metricValue = value;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { eventAssociate, traceFilters };
|
return { eventAssociate, traceFilters };
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +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.
|
||||||
*/
|
*/
|
||||||
import { ref, computed, ComputedRef, unref } from "vue";
|
import type { ComputedRef } from "vue";
|
||||||
|
import { ref, computed, unref } from "vue";
|
||||||
import { useEventListener } from "./useEventListener";
|
import { useEventListener } from "./useEventListener";
|
||||||
import { screenMap, sizeEnum, screenEnum } from "./data";
|
import { screenMap, sizeEnum, screenEnum } from "./data";
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ export interface CreateCallbackParams {
|
|||||||
sizeEnum: typeof sizeEnum;
|
sizeEnum: typeof sizeEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useBreakpoint(): any {
|
export function useBreakpoint(): Indexable {
|
||||||
return {
|
return {
|
||||||
screenRef: computed(() => unref(globalScreenRef)),
|
screenRef: computed(() => unref(globalScreenRef)),
|
||||||
widthRef: globalWidthRef,
|
widthRef: globalWidthRef,
|
||||||
@@ -40,9 +41,7 @@ export function useBreakpoint(): any {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createBreakpointListen(
|
export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void): Indexable {
|
||||||
fn?: (opt: CreateCallbackParams) => void
|
|
||||||
): any {
|
|
||||||
const screenRef = ref<sizeEnum>(sizeEnum.XL || "");
|
const screenRef = ref<sizeEnum>(sizeEnum.XL || "");
|
||||||
const realWidthRef = ref(window.innerWidth);
|
const realWidthRef = ref(window.innerWidth);
|
||||||
|
|
||||||
|
@@ -16,19 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig } from "@/types/dashboard";
|
||||||
|
|
||||||
export default function getDashboard(param?: {
|
export default function getDashboard(param?: { name: string; layer: string; entity: string }) {
|
||||||
name: string;
|
|
||||||
layer: string;
|
|
||||||
entity: string;
|
|
||||||
}) {
|
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const opt = param || dashboardStore.currentDashboard;
|
const opt = param || dashboardStore.currentDashboard;
|
||||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
const dashboard = list.find(
|
const dashboard = list.find(
|
||||||
(d: { name: string; layer: string; entity: string }) =>
|
(d: { name: string; layer: string; entity: string }) =>
|
||||||
d.name === opt.name && d.entity === opt.entity && d.layer === opt.layer
|
d.name === opt.name && d.entity === opt.entity && d.layer === opt.layer,
|
||||||
);
|
);
|
||||||
const all = dashboardStore.layout;
|
const all = dashboardStore.layout;
|
||||||
const widgets: LayoutConfig[] = [];
|
const widgets: LayoutConfig[] = [];
|
||||||
@@ -63,7 +59,7 @@ export default function getDashboard(param?: {
|
|||||||
if (targetTabIndex[1] === undefined) {
|
if (targetTabIndex[1] === undefined) {
|
||||||
container = document.querySelector(".ds-main");
|
container = document.querySelector(".ds-main");
|
||||||
} else {
|
} else {
|
||||||
const w = widgets.find((d: any) => d.id === targetTabIndex[0]);
|
const w = widgets.find((d: Indexable) => d.id === targetTabIndex[0]);
|
||||||
container = document.querySelector(".tab-layout");
|
container = document.querySelector(".tab-layout");
|
||||||
const layout: Nullable<Element> = document.querySelector(".ds-main");
|
const layout: Nullable<Element> = document.querySelector(".ds-main");
|
||||||
if (w && layout) {
|
if (w && layout) {
|
||||||
|
@@ -14,13 +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.
|
||||||
*/
|
*/
|
||||||
import {
|
import type { BarSeriesOption, LineSeriesOption, HeatmapSeriesOption, SankeySeriesOption } from "echarts/charts";
|
||||||
BarSeriesOption,
|
import type {
|
||||||
LineSeriesOption,
|
|
||||||
HeatmapSeriesOption,
|
|
||||||
SankeySeriesOption,
|
|
||||||
} from "echarts/charts";
|
|
||||||
import {
|
|
||||||
TitleComponentOption,
|
TitleComponentOption,
|
||||||
TooltipComponentOption,
|
TooltipComponentOption,
|
||||||
GridComponentOption,
|
GridComponentOption,
|
||||||
@@ -48,10 +43,7 @@ export type ECOption = echarts.ComposeOption<
|
|||||||
| SankeySeriesOption
|
| SankeySeriesOption
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export function useECharts(
|
export function useECharts(elRef: Ref<HTMLDivElement>, theme: "light" | "dark" | "default" = "default"): Indexable {
|
||||||
elRef: Ref<HTMLDivElement>,
|
|
||||||
theme: "light" | "dark" | "default" = "default"
|
|
||||||
): any {
|
|
||||||
const getDarkMode = computed(() => {
|
const getDarkMode = computed(() => {
|
||||||
return theme === "default" ? "light" : theme;
|
return theme === "default" ? "light" : theme;
|
||||||
});
|
});
|
||||||
@@ -131,7 +123,7 @@ export function useECharts(
|
|||||||
initCharts(theme as "default");
|
initCharts(theme as "default");
|
||||||
setOptions(cacheOptions.value);
|
setOptions(cacheOptions.value);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
tryOnUnmounted(() => {
|
tryOnUnmounted(() => {
|
||||||
|
@@ -20,7 +20,7 @@ import { useThrottleFn, useDebounceFn } from "@vueuse/core";
|
|||||||
|
|
||||||
export type RemoveEventFn = () => void;
|
export type RemoveEventFn = () => void;
|
||||||
export interface UseEventParams {
|
export interface UseEventParams {
|
||||||
el?: Element | Ref<Element | undefined> | Window | any;
|
el?: Element | Ref<Element | undefined> | Window | Recordable;
|
||||||
name: string;
|
name: string;
|
||||||
listener: EventListener;
|
listener: EventListener;
|
||||||
options?: boolean | AddEventListenerOptions;
|
options?: boolean | AddEventListenerOptions;
|
||||||
@@ -43,16 +43,13 @@ export function useEventListener({
|
|||||||
if (el) {
|
if (el) {
|
||||||
const element = ref(el as Element) as Ref<Element>;
|
const element = ref(el as Element) as Ref<Element>;
|
||||||
|
|
||||||
const handler = isDebounce
|
const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait);
|
||||||
? useDebounceFn(listener, wait)
|
|
||||||
: useThrottleFn(listener, wait);
|
|
||||||
const realHandler = wait ? handler : listener;
|
const realHandler = wait ? handler : listener;
|
||||||
const removeEventListener = (e: Element) => {
|
const removeEventListener = (e: Element) => {
|
||||||
isAddRef.value = true;
|
isAddRef.value = true;
|
||||||
e.removeEventListener(name, realHandler, options);
|
e.removeEventListener(name, realHandler, options);
|
||||||
};
|
};
|
||||||
const addEventListener = (e: Element) =>
|
const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options);
|
||||||
e.addEventListener(name, realHandler, options);
|
|
||||||
|
|
||||||
const removeWatch = watch(
|
const removeWatch = watch(
|
||||||
element,
|
element,
|
||||||
@@ -64,7 +61,7 @@ export function useEventListener({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
remove = () => {
|
remove = () => {
|
||||||
|
400
src/hooks/useExpressionsProcessor.ts
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import { RespFields } from "./data";
|
||||||
|
import { EntityType, ExpressionResultType } from "@/views/dashboard/data";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import type { MetricConfigOpt } from "@/types/dashboard";
|
||||||
|
import type { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
|
import type { Node, Call } from "@/types/topology";
|
||||||
|
|
||||||
|
export async function useExpressionsQueryProcessor(config: Indexable) {
|
||||||
|
function expressionsGraphqlPods() {
|
||||||
|
if (!(config.metrics && config.metrics[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const selectorStore = useSelectorStore();
|
||||||
|
|
||||||
|
if (!selectorStore.currentService && dashboardStore.entity !== "All") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const conditions: Recordable = {
|
||||||
|
duration: appStore.durationTime,
|
||||||
|
};
|
||||||
|
const variables: string[] = [`$duration: Duration!`];
|
||||||
|
const isRelation = ["ServiceRelation", "ServiceInstanceRelation", "EndpointRelation", "ProcessRelation"].includes(
|
||||||
|
dashboardStore.entity,
|
||||||
|
);
|
||||||
|
if (isRelation && !selectorStore.currentDestService) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fragment = config.metrics.map((name: string, index: number) => {
|
||||||
|
variables.push(`$expression${index}: String!`, `$entity${index}: Entity!`);
|
||||||
|
conditions[`expression${index}`] = name;
|
||||||
|
const entity = {
|
||||||
|
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
|
||||||
|
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
|
||||||
|
serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation", "Process"].includes(
|
||||||
|
dashboardStore.entity,
|
||||||
|
)
|
||||||
|
? selectorStore.currentPod && selectorStore.currentPod.value
|
||||||
|
: undefined,
|
||||||
|
endpointName: dashboardStore.entity.includes("Endpoint")
|
||||||
|
? selectorStore.currentPod && selectorStore.currentPod.value
|
||||||
|
: undefined,
|
||||||
|
processName: dashboardStore.entity.includes("Process")
|
||||||
|
? selectorStore.currentProcess && selectorStore.currentProcess.value
|
||||||
|
: undefined,
|
||||||
|
destNormal: isRelation ? selectorStore.currentDestService.normal : undefined,
|
||||||
|
destServiceName: isRelation ? selectorStore.currentDestService.value : undefined,
|
||||||
|
destServiceInstanceName: ["ServiceInstanceRelation", "ProcessRelation"].includes(dashboardStore.entity)
|
||||||
|
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
||||||
|
: undefined,
|
||||||
|
destEndpointName:
|
||||||
|
dashboardStore.entity === "EndpointRelation"
|
||||||
|
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
||||||
|
: undefined,
|
||||||
|
destProcessName: dashboardStore.entity.includes("ProcessRelation")
|
||||||
|
? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
conditions[`entity${index}`] = entity;
|
||||||
|
|
||||||
|
return `expression${index}: execExpression(expression: $expression${index}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
|
||||||
|
});
|
||||||
|
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
queryStr,
|
||||||
|
conditions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function expressionsSource(resp: { errors: string; data: Indexable }) {
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return { source: {}, tips: [], typesOfMQE: [] };
|
||||||
|
}
|
||||||
|
if (!resp.data) {
|
||||||
|
ElMessage.error("The query is wrong");
|
||||||
|
return { source: {}, tips: [], typesOfMQE: [] };
|
||||||
|
}
|
||||||
|
const tips: string[] = [];
|
||||||
|
const source: { [key: string]: unknown } = {};
|
||||||
|
const keys = Object.keys(resp.data);
|
||||||
|
const typesOfMQE: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < config.metrics.length; i++) {
|
||||||
|
const c: MetricConfigOpt = (config.metricConfig && config.metricConfig[i]) || {};
|
||||||
|
const obj = resp.data[keys[i]] || {};
|
||||||
|
const results = obj.results || [];
|
||||||
|
const name = config.metrics[i];
|
||||||
|
const type = obj.type;
|
||||||
|
|
||||||
|
tips.push(obj.error);
|
||||||
|
typesOfMQE.push(type);
|
||||||
|
if (!obj.error) {
|
||||||
|
if (type === ExpressionResultType.TIME_SERIES_VALUES) {
|
||||||
|
if (results.length === 1) {
|
||||||
|
const label = results[0].metric && results[0].metric.labels[0] && results[0].metric.labels[0].value;
|
||||||
|
source[c.label || label || name] = results[0].values.map((d: { value: unknown }) => d.value) || [];
|
||||||
|
} else {
|
||||||
|
const labels = (c.label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
for (const item of results) {
|
||||||
|
const values = item.values.map((d: { value: unknown }) => d.value) || [];
|
||||||
|
const index = item.metric.labels[0].value;
|
||||||
|
const indexNum = labels.findIndex((_, i: number) => i === Number(index));
|
||||||
|
if (labels[indexNum] && indexNum > -1) {
|
||||||
|
source[labels[indexNum]] = values;
|
||||||
|
} else {
|
||||||
|
source[index] = values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type === ExpressionResultType.SINGLE_VALUE) {
|
||||||
|
source[c.label || name] = (results[0].values[0] || {}).value;
|
||||||
|
}
|
||||||
|
if (([ExpressionResultType.RECORD_LIST, ExpressionResultType.SORTED_LIST] as string[]).includes(type)) {
|
||||||
|
source[name] = results[0].values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { source, tips, typesOfMQE };
|
||||||
|
}
|
||||||
|
const params = await expressionsGraphqlPods();
|
||||||
|
if (!params) {
|
||||||
|
return { source: {}, tips: [], typesOfMQE: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const json = await dashboardStore.fetchMetricValue(params);
|
||||||
|
if (json.errors) {
|
||||||
|
ElMessage.error(json.errors);
|
||||||
|
return { source: {}, tips: [], typesOfMQE: [] };
|
||||||
|
}
|
||||||
|
const data = expressionsSource(json);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function useExpressionsQueryPodsMetrics(
|
||||||
|
pods: Array<(Instance | Endpoint | Service) & Indexable>,
|
||||||
|
config: {
|
||||||
|
expressions: string[];
|
||||||
|
subExpressions: string[];
|
||||||
|
metricConfig: MetricConfigOpt[];
|
||||||
|
},
|
||||||
|
scope: string,
|
||||||
|
) {
|
||||||
|
function expressionsGraphqlPods() {
|
||||||
|
const metrics: string[] = [];
|
||||||
|
const subMetrics: string[] = [];
|
||||||
|
config.expressions = config.expressions || [];
|
||||||
|
config.subExpressions = config.subExpressions || [];
|
||||||
|
|
||||||
|
for (let i = 0; i < config.expressions.length; i++) {
|
||||||
|
if (config.expressions[i]) {
|
||||||
|
metrics.push(config.expressions[i]);
|
||||||
|
subMetrics.push(config.subExpressions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!metrics.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
const selectorStore = useSelectorStore();
|
||||||
|
const conditions: { [key: string]: unknown } = {
|
||||||
|
duration: appStore.durationTime,
|
||||||
|
};
|
||||||
|
const variables: string[] = [`$duration: Duration!`];
|
||||||
|
const currentService = selectorStore.currentService || {};
|
||||||
|
const fragmentList = pods.map((d: (Instance | Endpoint | Service) & Indexable, index: number) => {
|
||||||
|
const entity = {
|
||||||
|
serviceName: scope === "Service" ? d.label : currentService.label,
|
||||||
|
serviceInstanceName: scope === "ServiceInstance" ? d.label : undefined,
|
||||||
|
endpointName: scope === "Endpoint" ? d.label : undefined,
|
||||||
|
normal: scope === "Service" ? d.normal : currentService.normal,
|
||||||
|
};
|
||||||
|
variables.push(`$entity${index}: Entity!`);
|
||||||
|
conditions[`entity${index}`] = entity;
|
||||||
|
const f = metrics.map((name: string, idx: number) => {
|
||||||
|
variables.push(`$expression${index}${idx}: String!`);
|
||||||
|
conditions[`expression${index}${idx}`] = name;
|
||||||
|
let str = "";
|
||||||
|
if (config.subExpressions[idx]) {
|
||||||
|
variables.push(`$subExpression${index}${idx}: String!`);
|
||||||
|
conditions[`subExpression${index}${idx}`] = config.subExpressions[idx];
|
||||||
|
str = `subexpression${index}${idx}: execExpression(expression: $subExpression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
str +
|
||||||
|
`expression${index}${idx}: execExpression(expression: $expression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return f;
|
||||||
|
});
|
||||||
|
const fragment = fragmentList.flat(1).join(" ");
|
||||||
|
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
|
||||||
|
return { queryStr, conditions };
|
||||||
|
}
|
||||||
|
|
||||||
|
function expressionsPodsSource(resp: { errors: string; data: Indexable }): Indexable {
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const names: string[] = [];
|
||||||
|
const subNames: string[] = [];
|
||||||
|
const metricConfigArr: MetricConfigOpt[] = [];
|
||||||
|
const metricTypesArr: string[] = [];
|
||||||
|
const expressionsTips: string[] = [];
|
||||||
|
const subExpressionsTips: string[] = [];
|
||||||
|
const data = pods.map((d: any, idx: number) => {
|
||||||
|
for (let index = 0; index < config.expressions.length; index++) {
|
||||||
|
const c: MetricConfigOpt = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
|
const k = "expression" + idx + index;
|
||||||
|
const sub = "subexpression" + idx + index;
|
||||||
|
const obj = resp.data[k] || {};
|
||||||
|
const results = obj.results || [];
|
||||||
|
const typesOfMQE = obj.type || "";
|
||||||
|
const subObj = resp.data[sub] || {};
|
||||||
|
const subResults = subObj.results || [];
|
||||||
|
|
||||||
|
expressionsTips.push(obj.error);
|
||||||
|
subExpressionsTips.push(subObj.error);
|
||||||
|
if (results.length > 1) {
|
||||||
|
const labels = (c.label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
const labelsIdx = (c.labelsIndex || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
let name = results[i].metric.labels[0].value || "";
|
||||||
|
const subValues = subResults[i] && subResults[i].values.map((d: { value: unknown }) => d.value);
|
||||||
|
const num = labelsIdx.findIndex((d: string) => d === results[i].metric.labels[0].value);
|
||||||
|
|
||||||
|
if (labels[num]) {
|
||||||
|
name = labels[num];
|
||||||
|
}
|
||||||
|
if (!d[name]) {
|
||||||
|
d[name] = {};
|
||||||
|
}
|
||||||
|
if (subValues) {
|
||||||
|
d[name]["values"] = subValues;
|
||||||
|
}
|
||||||
|
d[name]["avg"] = (results[i].values[0] || {}).value;
|
||||||
|
|
||||||
|
const j = names.find((d: string) => d === name);
|
||||||
|
|
||||||
|
if (!j) {
|
||||||
|
names.push(name);
|
||||||
|
metricConfigArr.push({ ...c, index: i });
|
||||||
|
metricTypesArr.push(typesOfMQE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!results[0]) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
const name = config.expressions[index] || "";
|
||||||
|
const subName = config.subExpressions[index] || "";
|
||||||
|
if (!d[name]) {
|
||||||
|
d[name] = {};
|
||||||
|
}
|
||||||
|
d[name]["avg"] = [(results[0].values[0] || {}).value];
|
||||||
|
if (subResults[0]) {
|
||||||
|
if (!d[subName]) {
|
||||||
|
d[subName] = {};
|
||||||
|
}
|
||||||
|
d[subName]["values"] = subResults[0].values.map((d: { value: number }) => d.value);
|
||||||
|
}
|
||||||
|
const j = names.find((d: string) => d === name);
|
||||||
|
if (!j) {
|
||||||
|
names.push(name);
|
||||||
|
subNames.push(subName);
|
||||||
|
metricConfigArr.push(c);
|
||||||
|
metricTypesArr.push(typesOfMQE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips };
|
||||||
|
}
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const params = await expressionsGraphqlPods();
|
||||||
|
const json = await dashboardStore.fetchMetricValue(params);
|
||||||
|
|
||||||
|
if (json.errors) {
|
||||||
|
ElMessage.error(json.errors);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const expressionParams = expressionsPodsSource(json);
|
||||||
|
|
||||||
|
return expressionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useQueryTopologyExpressionsProcessor(metrics: string[], instances: (Call | Node)[]) {
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
|
function getExpressionQuery() {
|
||||||
|
const conditions: { [key: string]: unknown } = {
|
||||||
|
duration: appStore.durationTime,
|
||||||
|
};
|
||||||
|
const variables: string[] = [`$duration: Duration!`];
|
||||||
|
const fragmentList = instances.map((d: any, index: number) => {
|
||||||
|
let serviceName;
|
||||||
|
let destServiceName;
|
||||||
|
let endpointName;
|
||||||
|
let serviceInstanceName;
|
||||||
|
let destServiceInstanceName;
|
||||||
|
let destEndpointName;
|
||||||
|
if (d.sourceObj && d.targetObj) {
|
||||||
|
// instances = Calls
|
||||||
|
serviceName = d.sourceObj.serviceName || d.sourceObj.name;
|
||||||
|
destServiceName = d.targetObj.serviceName || d.targetObj.name;
|
||||||
|
if (EntityType[4].value === dashboardStore.entity) {
|
||||||
|
serviceInstanceName = d.sourceObj.name;
|
||||||
|
destServiceInstanceName = d.targetObj.name;
|
||||||
|
}
|
||||||
|
if (EntityType[2].value === dashboardStore.entity) {
|
||||||
|
endpointName = d.sourceObj.name;
|
||||||
|
destEndpointName = d.targetObj.name;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// instances = Nodes
|
||||||
|
serviceName = d.serviceName || d.name;
|
||||||
|
if (EntityType[4].value === dashboardStore.entity) {
|
||||||
|
serviceInstanceName = d.name;
|
||||||
|
}
|
||||||
|
if (EntityType[2].value === dashboardStore.entity) {
|
||||||
|
endpointName = d.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const entity = {
|
||||||
|
serviceName,
|
||||||
|
normal: true,
|
||||||
|
serviceInstanceName,
|
||||||
|
endpointName,
|
||||||
|
destServiceName,
|
||||||
|
destNormal: destServiceName ? true : undefined,
|
||||||
|
destServiceInstanceName,
|
||||||
|
destEndpointName,
|
||||||
|
};
|
||||||
|
variables.push(`$entity${index}: Entity!`);
|
||||||
|
conditions[`entity${index}`] = entity;
|
||||||
|
const f = metrics.map((name: string, idx: number) => {
|
||||||
|
if (index === 0) {
|
||||||
|
variables.push(`$expression${idx}: String!`);
|
||||||
|
conditions[`expression${idx}`] = name;
|
||||||
|
}
|
||||||
|
return `expression${index}${idx}: execExpression(expression: $expression${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
|
||||||
|
});
|
||||||
|
return f;
|
||||||
|
});
|
||||||
|
const fragment = fragmentList.flat(1).join(" ");
|
||||||
|
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
|
||||||
|
return { queryStr, conditions };
|
||||||
|
}
|
||||||
|
function handleExpressionValues(resp: { [key: string]: any }) {
|
||||||
|
const obj: any = {};
|
||||||
|
for (let idx = 0; idx < instances.length; idx++) {
|
||||||
|
for (let index = 0; index < metrics.length; index++) {
|
||||||
|
const k = "expression" + idx + index;
|
||||||
|
if (metrics[index]) {
|
||||||
|
if (!obj[metrics[index]]) {
|
||||||
|
obj[metrics[index]] = {
|
||||||
|
values: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
obj[metrics[index]].values.push({ value: resp[k].results[0].values[0].value, id: instances[idx].id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getExpressionQuery, handleExpressionValues };
|
||||||
|
}
|
@@ -14,7 +14,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { LegendOptions } from "@/types/dashboard";
|
import type { LegendOptions } from "@/types/dashboard";
|
||||||
import { isDef } from "@/utils/is";
|
import { isDef } from "@/utils/is";
|
||||||
|
|
||||||
export default function useLegendProcess(legend?: LegendOptions) {
|
export default function useLegendProcess(legend?: LegendOptions) {
|
||||||
@@ -37,14 +37,9 @@ export default function useLegendProcess(legend?: LegendOptions) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
function aggregations(
|
function aggregations(data: { [key: string]: number[] }, intervalTime: string[]) {
|
||||||
data: { [key: string]: number[] },
|
|
||||||
intervalTime: string[]
|
|
||||||
) {
|
|
||||||
const source: { [key: string]: unknown }[] = [];
|
const source: { [key: string]: unknown }[] = [];
|
||||||
const keys = Object.keys(data || {}).filter(
|
const keys = Object.keys(data || {}).filter((i: string) => Array.isArray(data[i]) && data[i].length);
|
||||||
(i: any) => Array.isArray(data[i]) && data[i].length
|
|
||||||
);
|
|
||||||
const headers = [];
|
const headers = [];
|
||||||
|
|
||||||
for (const [key, value] of keys.entries()) {
|
for (const [key, value] of keys.entries()) {
|
||||||
@@ -58,12 +53,7 @@ export default function useLegendProcess(legend?: LegendOptions) {
|
|||||||
value: d,
|
value: d,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort(
|
.sort((a: { key: string; value: number }, b: { key: string; value: number }) => b.value - a.value)
|
||||||
(
|
|
||||||
a: { key: string; value: number },
|
|
||||||
b: { key: string; value: number }
|
|
||||||
) => b.value - a.value
|
|
||||||
)
|
|
||||||
.filter((_: unknown, index: number) => index < 10),
|
.filter((_: unknown, index: number) => index < 10),
|
||||||
};
|
};
|
||||||
if (legend) {
|
if (legend) {
|
||||||
|
@@ -15,27 +15,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { MetricQueryTypes, Calculations } from "./data";
|
import { MetricQueryTypes, Calculations } from "./data";
|
||||||
export function useListConfig(config: any, index: string) {
|
import { MetricModes } from "@/views/dashboard/data";
|
||||||
|
|
||||||
|
export function useListConfig(config: Indexable, index: number) {
|
||||||
|
if (config.metricModes === MetricModes.Expression) {
|
||||||
|
return {
|
||||||
|
isLinear: false,
|
||||||
|
isAvg: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
const i = Number(index);
|
const i = Number(index);
|
||||||
const types = [
|
const types = [Calculations.Average, Calculations.ApdexAvg, Calculations.PercentageAvg];
|
||||||
Calculations.Average,
|
const calculation = config.metricConfig && config.metricConfig[i] && config.metricConfig[i].calculation;
|
||||||
Calculations.ApdexAvg,
|
|
||||||
Calculations.PercentageAvg,
|
|
||||||
];
|
|
||||||
const calculation =
|
|
||||||
config.metricConfig &&
|
|
||||||
config.metricConfig[i] &&
|
|
||||||
config.metricConfig[i].calculation;
|
|
||||||
const isLinear =
|
const isLinear =
|
||||||
[
|
[MetricQueryTypes.ReadMetricsValues, MetricQueryTypes.ReadLabeledMetricsValues].includes(config.metricTypes[i]) &&
|
||||||
MetricQueryTypes.ReadMetricsValues,
|
!types.includes(calculation);
|
||||||
MetricQueryTypes.ReadLabeledMetricsValues,
|
|
||||||
].includes(config.metricTypes[i]) && !types.includes(calculation);
|
|
||||||
const isAvg =
|
const isAvg =
|
||||||
[
|
[MetricQueryTypes.ReadMetricsValues, MetricQueryTypes.ReadLabeledMetricsValues].includes(config.metricTypes[i]) &&
|
||||||
MetricQueryTypes.ReadMetricsValues,
|
types.includes(calculation);
|
||||||
MetricQueryTypes.ReadLabeledMetricsValues,
|
|
||||||
].includes(config.metricTypes[i]) && types.includes(calculation);
|
|
||||||
return {
|
return {
|
||||||
isLinear,
|
isLinear,
|
||||||
isAvg,
|
isAvg,
|
||||||
|
@@ -20,11 +20,10 @@ import { ElMessage } from "element-plus";
|
|||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import type { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
import { MetricConfigOpt } from "@/types/dashboard";
|
import type { MetricConfigOpt } from "@/types/dashboard";
|
||||||
import { MetricCatalog } from "@/views/dashboard/data";
|
|
||||||
|
|
||||||
export function useQueryProcessor(config: any) {
|
export function useQueryProcessor(config: Indexable) {
|
||||||
if (!(config.metrics && config.metrics[0])) {
|
if (!(config.metrics && config.metrics[0])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -38,57 +37,35 @@ export function useQueryProcessor(config: any) {
|
|||||||
if (!selectorStore.currentService && dashboardStore.entity !== "All") {
|
if (!selectorStore.currentService && dashboardStore.entity !== "All") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const conditions: { [key: string]: unknown } = {
|
const conditions: Recordable = {
|
||||||
duration: appStore.durationTime,
|
duration: appStore.durationTime,
|
||||||
};
|
};
|
||||||
const variables: string[] = [`$duration: Duration!`];
|
const variables: string[] = [`$duration: Duration!`];
|
||||||
const isRelation = [
|
const isRelation = ["ServiceRelation", "ServiceInstanceRelation", "EndpointRelation", "ProcessRelation"].includes(
|
||||||
"ServiceRelation",
|
dashboardStore.entity,
|
||||||
"ServiceInstanceRelation",
|
);
|
||||||
"EndpointRelation",
|
|
||||||
"ProcessRelation",
|
|
||||||
].includes(dashboardStore.entity);
|
|
||||||
if (isRelation && !selectorStore.currentDestService) {
|
if (isRelation && !selectorStore.currentDestService) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fragment = config.metrics.map((name: string, index: number) => {
|
const fragment = config.metrics.map((name: string, index: number) => {
|
||||||
const metricType = config.metricTypes[index] || "";
|
const metricType = config.metricTypes[index] || "";
|
||||||
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
if (
|
if ([MetricQueryTypes.ReadSampledRecords, MetricQueryTypes.SortMetrics].includes(metricType)) {
|
||||||
[
|
|
||||||
MetricQueryTypes.ReadSampledRecords,
|
|
||||||
MetricQueryTypes.SortMetrics,
|
|
||||||
].includes(metricType)
|
|
||||||
) {
|
|
||||||
variables.push(`$condition${index}: TopNCondition!`);
|
variables.push(`$condition${index}: TopNCondition!`);
|
||||||
conditions[`condition${index}`] = {
|
conditions[`condition${index}`] = {
|
||||||
name,
|
name,
|
||||||
parentService: ["All"].includes(dashboardStore.entity)
|
parentService: ["All"].includes(dashboardStore.entity) ? null : selectorStore.currentService.value,
|
||||||
? null
|
normal: selectorStore.currentService ? selectorStore.currentService.normal : true,
|
||||||
: selectorStore.currentService.value,
|
topN: Number(c.topN) || 10,
|
||||||
normal: selectorStore.currentService
|
|
||||||
? selectorStore.currentService.normal
|
|
||||||
: true,
|
|
||||||
scope: config.catalog,
|
|
||||||
topN: c.topN || 10,
|
|
||||||
order: c.sortOrder || "DES",
|
order: c.sortOrder || "DES",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
const entity = {
|
const entity = {
|
||||||
scope: config.catalog,
|
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
|
||||||
serviceName:
|
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
|
||||||
dashboardStore.entity === "All"
|
serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation"].includes(
|
||||||
? undefined
|
dashboardStore.entity,
|
||||||
: selectorStore.currentService.value,
|
)
|
||||||
normal:
|
|
||||||
dashboardStore.entity === "All"
|
|
||||||
? undefined
|
|
||||||
: selectorStore.currentService.normal,
|
|
||||||
serviceInstanceName: [
|
|
||||||
"ServiceInstance",
|
|
||||||
"ServiceInstanceRelation",
|
|
||||||
"ProcessRelation",
|
|
||||||
].includes(dashboardStore.entity)
|
|
||||||
? selectorStore.currentPod && selectorStore.currentPod.value
|
? selectorStore.currentPod && selectorStore.currentPod.value
|
||||||
: undefined,
|
: undefined,
|
||||||
endpointName: dashboardStore.entity.includes("Endpoint")
|
endpointName: dashboardStore.entity.includes("Endpoint")
|
||||||
@@ -97,16 +74,9 @@ export function useQueryProcessor(config: any) {
|
|||||||
processName: dashboardStore.entity.includes("Process")
|
processName: dashboardStore.entity.includes("Process")
|
||||||
? selectorStore.currentProcess && selectorStore.currentProcess.value
|
? selectorStore.currentProcess && selectorStore.currentProcess.value
|
||||||
: undefined,
|
: undefined,
|
||||||
destNormal: isRelation
|
destNormal: isRelation ? selectorStore.currentDestService.normal : undefined,
|
||||||
? selectorStore.currentDestService.normal
|
destServiceName: isRelation ? selectorStore.currentDestService.value : undefined,
|
||||||
: undefined,
|
destServiceInstanceName: ["ServiceInstanceRelation", "ProcessRelation"].includes(dashboardStore.entity)
|
||||||
destServiceName: isRelation
|
|
||||||
? selectorStore.currentDestService.value
|
|
||||||
: undefined,
|
|
||||||
destServiceInstanceName: [
|
|
||||||
"ServiceInstanceRelation",
|
|
||||||
"ProcessRelation",
|
|
||||||
].includes(dashboardStore.entity)
|
|
||||||
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
||||||
: undefined,
|
: undefined,
|
||||||
destEndpointName:
|
destEndpointName:
|
||||||
@@ -114,8 +84,7 @@ export function useQueryProcessor(config: any) {
|
|||||||
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
||||||
: undefined,
|
: undefined,
|
||||||
destProcessName: dashboardStore.entity.includes("ProcessRelation")
|
destProcessName: dashboardStore.entity.includes("ProcessRelation")
|
||||||
? selectorStore.currentDestProcess &&
|
? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value
|
||||||
selectorStore.currentDestProcess.value
|
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
if ([MetricQueryTypes.ReadRecords].includes(metricType)) {
|
if ([MetricQueryTypes.ReadRecords].includes(metricType)) {
|
||||||
@@ -123,15 +92,12 @@ export function useQueryProcessor(config: any) {
|
|||||||
conditions[`condition${index}`] = {
|
conditions[`condition${index}`] = {
|
||||||
name,
|
name,
|
||||||
parentEntity: entity,
|
parentEntity: entity,
|
||||||
topN: c.topN || 10,
|
topN: Number(c.topN) || 10,
|
||||||
order: c.sortOrder || "DES",
|
order: c.sortOrder || "DES",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
entity.scope = dashboardStore.entity;
|
|
||||||
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
const labels = (c.labelsIndex || "")
|
const labels = (c.labelsIndex || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
.split(",")
|
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
|
||||||
variables.push(`$labels${index}: [String!]!`);
|
variables.push(`$labels${index}: [String!]!`);
|
||||||
conditions[`labels${index}`] = labels;
|
conditions[`labels${index}`] = labels;
|
||||||
}
|
}
|
||||||
@@ -144,9 +110,10 @@ export function useQueryProcessor(config: any) {
|
|||||||
}
|
}
|
||||||
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
return `${name}${index}: ${metricType}(condition: $condition${index}, labels: $labels${index}, duration: $duration)${RespFields[metricType]}`;
|
return `${name}${index}: ${metricType}(condition: $condition${index}, labels: $labels${index}, duration: $duration)${RespFields[metricType]}`;
|
||||||
} else {
|
|
||||||
return `${name}${index}: ${metricType}(condition: $condition${index}, duration: $duration)${RespFields[metricType]}`;
|
|
||||||
}
|
}
|
||||||
|
const t = metricType === MetricQueryTypes.ReadMetricsValue ? MetricQueryTypes.ReadNullableMetricsValue : metricType;
|
||||||
|
|
||||||
|
return `${name}${index}: ${t}(condition: $condition${index}, duration: $duration)${RespFields[t]}`;
|
||||||
});
|
});
|
||||||
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
|
||||||
@@ -156,12 +123,12 @@ export function useQueryProcessor(config: any) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
export function useSourceProcessor(
|
export function useSourceProcessor(
|
||||||
resp: { errors: string; data: { [key: string]: any } },
|
resp: { errors: string; data: Indexable },
|
||||||
config: {
|
config: {
|
||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
metricConfig: MetricConfigOpt[];
|
metricConfig: MetricConfigOpt[];
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
if (resp.errors) {
|
if (resp.errors) {
|
||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
@@ -179,22 +146,15 @@ export function useSourceProcessor(
|
|||||||
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
|
|
||||||
if (type === MetricQueryTypes.ReadMetricsValues) {
|
if (type === MetricQueryTypes.ReadMetricsValues) {
|
||||||
source[c.label || m] =
|
source[c.label || m] = (resp.data[keys[index]] && calculateExp(resp.data[keys[index]].values.values, c)) || [];
|
||||||
(resp.data[keys[index]] &&
|
|
||||||
calculateExp(resp.data[keys[index]].values.values, c)) ||
|
|
||||||
[];
|
|
||||||
}
|
}
|
||||||
if (type === MetricQueryTypes.ReadLabeledMetricsValues) {
|
if (type === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
const resVal = Object.values(resp.data)[0] || [];
|
const resVal = Object.values(resp.data)[0] || [];
|
||||||
const labels = (c.label || "")
|
const labels = (c.label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
.split(",")
|
const labelsIdx = (c.labelsIndex || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
|
||||||
const labelsIdx = (c.labelsIndex || "")
|
|
||||||
.split(",")
|
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
|
||||||
for (const item of resVal) {
|
for (const item of resVal) {
|
||||||
const values = item.values.values.map((d: { value: number }) =>
|
const values = item.values.values.map((d: { value: number; isEmptyValue: boolean }) =>
|
||||||
aggregation(Number(d.value), c)
|
d.isEmptyValue ? NaN : aggregation(Number(d.value), c),
|
||||||
);
|
);
|
||||||
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
||||||
if (labels[indexNum] && indexNum > -1) {
|
if (labels[indexNum] && indexNum > -1) {
|
||||||
@@ -205,28 +165,23 @@ export function useSourceProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type === MetricQueryTypes.ReadMetricsValue) {
|
if (type === MetricQueryTypes.ReadMetricsValue) {
|
||||||
source[m] = aggregation(Number(Object.values(resp.data)[0]), c);
|
const v = Object.values(resp.data)[0] || {};
|
||||||
|
source[m] = v.isEmptyValue ? NaN : aggregation(Number(v.value), c);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
[
|
[MetricQueryTypes.ReadRecords, MetricQueryTypes.ReadSampledRecords, MetricQueryTypes.SortMetrics] as string[]
|
||||||
MetricQueryTypes.ReadRecords,
|
|
||||||
MetricQueryTypes.ReadSampledRecords,
|
|
||||||
MetricQueryTypes.SortMetrics,
|
|
||||||
] as string[]
|
|
||||||
).includes(type)
|
).includes(type)
|
||||||
) {
|
) {
|
||||||
source[m] = (Object.values(resp.data)[0] || []).map(
|
source[m] = (Object.values(resp.data)[0] || []).map((d: { value: unknown; name: string }) => {
|
||||||
(d: { value: unknown; name: string }) => {
|
d.value = aggregation(Number(d.value), c);
|
||||||
d.value = aggregation(Number(d.value), c);
|
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (type === MetricQueryTypes.READHEATMAP) {
|
if (type === MetricQueryTypes.READHEATMAP) {
|
||||||
const resVal = Object.values(resp.data)[0] || {};
|
const resVal = Object.values(resp.data)[0] || {};
|
||||||
const nodes = [] as any;
|
const nodes = [] as Indexable[];
|
||||||
if (!(resVal && resVal.values)) {
|
if (!(resVal && resVal.values)) {
|
||||||
source[m] = { nodes: [] };
|
source[m] = { nodes: [] };
|
||||||
return;
|
return;
|
||||||
@@ -236,14 +191,9 @@ export function useSourceProcessor(
|
|||||||
|
|
||||||
nodes.push(...grids);
|
nodes.push(...grids);
|
||||||
});
|
});
|
||||||
let buckets = [] as any;
|
let buckets = [] as Indexable[];
|
||||||
if (resVal.buckets.length) {
|
if (resVal.buckets.length) {
|
||||||
buckets = [
|
buckets = [resVal.buckets[0].min, ...resVal.buckets.map((item: { min: string; max: string }) => item.max)];
|
||||||
resVal.buckets[0].min,
|
|
||||||
...resVal.buckets.map(
|
|
||||||
(item: { min: string; max: string }) => item.max
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source[m] = { nodes, buckets }; // nodes: number[][]
|
source[m] = { nodes, buckets }; // nodes: number[][]
|
||||||
@@ -254,13 +204,13 @@ export function useSourceProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useQueryPodsMetrics(
|
export function useQueryPodsMetrics(
|
||||||
pods: Array<Instance | Endpoint | Service | any>,
|
pods: Array<(Instance | Endpoint | Service) & Indexable>,
|
||||||
config: {
|
config: {
|
||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
metricConfig: MetricConfigOpt[];
|
metricConfig: MetricConfigOpt[];
|
||||||
},
|
},
|
||||||
scope: string
|
scope: string,
|
||||||
) {
|
) {
|
||||||
const metricTypes = (config.metricTypes || []).filter((m: string) => m);
|
const metricTypes = (config.metricTypes || []).filter((m: string) => m);
|
||||||
if (!metricTypes.length) {
|
if (!metricTypes.length) {
|
||||||
@@ -277,40 +227,34 @@ export function useQueryPodsMetrics(
|
|||||||
};
|
};
|
||||||
const variables: string[] = [`$duration: Duration!`];
|
const variables: string[] = [`$duration: Duration!`];
|
||||||
const currentService = selectorStore.currentService || {};
|
const currentService = selectorStore.currentService || {};
|
||||||
const fragmentList = pods.map(
|
const fragmentList = pods.map((d: (Instance | Endpoint | Service) & Indexable, index: number) => {
|
||||||
(
|
const param = {
|
||||||
d: (Instance | Endpoint | Service) & { normal: boolean },
|
serviceName: scope === "Service" ? d.label : currentService.label,
|
||||||
index: number
|
serviceInstanceName: scope === "ServiceInstance" ? d.label : undefined,
|
||||||
) => {
|
endpointName: scope === "Endpoint" ? d.label : undefined,
|
||||||
const param = {
|
normal: scope === "Service" ? d.normal : currentService.normal,
|
||||||
scope,
|
};
|
||||||
serviceName: scope === "Service" ? d.label : currentService.label,
|
const f = metrics.map((name: string, idx: number) => {
|
||||||
serviceInstanceName: scope === "ServiceInstance" ? d.label : undefined,
|
const metricType = metricTypes[idx] || "";
|
||||||
endpointName: scope === "Endpoint" ? d.label : undefined,
|
variables.push(`$condition${index}${idx}: MetricsCondition!`);
|
||||||
normal: scope === "Service" ? d.normal : currentService.normal,
|
conditions[`condition${index}${idx}`] = {
|
||||||
|
name,
|
||||||
|
entity: param,
|
||||||
};
|
};
|
||||||
const f = metrics.map((name: string, idx: number) => {
|
let labelStr = "";
|
||||||
const metricType = metricTypes[idx] || "";
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
variables.push(`$condition${index}${idx}: MetricsCondition!`);
|
const c = config.metricConfig[idx] || {};
|
||||||
conditions[`condition${index}${idx}`] = {
|
variables.push(`$labels${index}${idx}: [String!]!`);
|
||||||
name,
|
labelStr = `labels: $labels${index}${idx}, `;
|
||||||
entity: param,
|
const labels = (c.labelsIndex || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
};
|
conditions[`labels${index}${idx}`] = labels;
|
||||||
let labelStr = "";
|
}
|
||||||
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
const t =
|
||||||
const c = config.metricConfig[idx] || {};
|
metricType === MetricQueryTypes.ReadMetricsValue ? MetricQueryTypes.ReadNullableMetricsValue : metricType;
|
||||||
variables.push(`$labels${index}${idx}: [String!]!`);
|
return `${name}${index}${idx}: ${t}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[t]}`;
|
||||||
labelStr = `labels: $labels${index}${idx}, `;
|
});
|
||||||
const labels = (c.labelsIndex || "")
|
return f;
|
||||||
.split(",")
|
});
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
|
||||||
conditions[`labels${index}${idx}`] = labels;
|
|
||||||
}
|
|
||||||
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[metricType]}`;
|
|
||||||
});
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const fragment = fragmentList.flat(1).join(" ");
|
const fragment = fragmentList.flat(1).join(" ");
|
||||||
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
|
||||||
@@ -319,13 +263,13 @@ export function useQueryPodsMetrics(
|
|||||||
|
|
||||||
export function usePodsSource(
|
export function usePodsSource(
|
||||||
pods: Array<Instance | Endpoint>,
|
pods: Array<Instance | Endpoint>,
|
||||||
resp: { errors: string; data: { [key: string]: any } },
|
resp: { errors: string; data: Indexable },
|
||||||
config: {
|
config: {
|
||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
metricConfig: MetricConfigOpt[];
|
metricConfig: MetricConfigOpt[];
|
||||||
}
|
},
|
||||||
): any {
|
): Indexable {
|
||||||
if (resp.errors) {
|
if (resp.errors) {
|
||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
return {};
|
return {};
|
||||||
@@ -333,12 +277,13 @@ export function usePodsSource(
|
|||||||
const names: string[] = [];
|
const names: string[] = [];
|
||||||
const metricConfigArr: MetricConfigOpt[] = [];
|
const metricConfigArr: MetricConfigOpt[] = [];
|
||||||
const metricTypesArr: string[] = [];
|
const metricTypesArr: string[] = [];
|
||||||
const data = pods.map((d: Instance | any, idx: number) => {
|
const data = pods.map((d: any, idx: number) => {
|
||||||
config.metrics.map((name: string, index: number) => {
|
config.metrics.map((name: string, index: number) => {
|
||||||
const c: any = (config.metricConfig && config.metricConfig[index]) || {};
|
const c: any = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
const key = name + idx + index;
|
const key = name + idx + index;
|
||||||
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) {
|
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) {
|
||||||
d[name] = aggregation(resp.data[key], c);
|
const v = resp.data[key];
|
||||||
|
d[name] = v.isEmptyValue ? NaN : aggregation(v.value, c);
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
names.push(name);
|
names.push(name);
|
||||||
metricConfigArr.push(c);
|
metricConfigArr.push(c);
|
||||||
@@ -347,17 +292,11 @@ export function usePodsSource(
|
|||||||
}
|
}
|
||||||
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
|
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
|
||||||
d[name] = {};
|
d[name] = {};
|
||||||
if (
|
if ([Calculations.Average, Calculations.ApdexAvg, Calculations.PercentageAvg].includes(c.calculation)) {
|
||||||
[
|
|
||||||
Calculations.Average,
|
|
||||||
Calculations.ApdexAvg,
|
|
||||||
Calculations.PercentageAvg,
|
|
||||||
].includes(c.calculation)
|
|
||||||
) {
|
|
||||||
d[name]["avg"] = calculateExp(resp.data[key].values.values, c);
|
d[name]["avg"] = calculateExp(resp.data[key].values.values, c);
|
||||||
}
|
}
|
||||||
d[name]["values"] = resp.data[key].values.values.map(
|
d[name]["values"] = resp.data[key].values.values.map((val: { value: number; isEmptyValue: boolean }) =>
|
||||||
(val: { value: number }) => aggregation(val.value, c)
|
val.isEmptyValue ? NaN : aggregation(val.value, c),
|
||||||
);
|
);
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
names.push(name);
|
names.push(name);
|
||||||
@@ -365,20 +304,14 @@ export function usePodsSource(
|
|||||||
metricTypesArr.push(config.metricTypes[index]);
|
metricTypesArr.push(config.metricTypes[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (config.metricTypes[index] === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
config.metricTypes[index] === MetricQueryTypes.ReadLabeledMetricsValues
|
|
||||||
) {
|
|
||||||
const resVal = resp.data[key] || [];
|
const resVal = resp.data[key] || [];
|
||||||
const labels = (c.label || "")
|
const labels = (c.label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
.split(",")
|
const labelsIdx = (c.labelsIndex || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
|
||||||
const labelsIdx = (c.labelsIndex || "")
|
|
||||||
.split(",")
|
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
|
||||||
for (let i = 0; i < resVal.length; i++) {
|
for (let i = 0; i < resVal.length; i++) {
|
||||||
const item = resVal[i];
|
const item = resVal[i];
|
||||||
const values = item.values.values.map((d: { value: number }) =>
|
const values = item.values.values.map((d: { value: number; isEmptyValue: boolean }) =>
|
||||||
aggregation(Number(d.value), c)
|
d.isEmptyValue ? NaN : aggregation(Number(d.value), c),
|
||||||
);
|
);
|
||||||
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
||||||
let key = item.label;
|
let key = item.label;
|
||||||
@@ -388,13 +321,7 @@ export function usePodsSource(
|
|||||||
if (!d[key]) {
|
if (!d[key]) {
|
||||||
d[key] = {};
|
d[key] = {};
|
||||||
}
|
}
|
||||||
if (
|
if ([Calculations.Average, Calculations.ApdexAvg, Calculations.PercentageAvg].includes(c.calculation)) {
|
||||||
[
|
|
||||||
Calculations.Average,
|
|
||||||
Calculations.ApdexAvg,
|
|
||||||
Calculations.PercentageAvg,
|
|
||||||
].includes(c.calculation)
|
|
||||||
) {
|
|
||||||
d[key]["avg"] = calculateExp(item.values.values, c);
|
d[key]["avg"] = calculateExp(item.values.values, c);
|
||||||
}
|
}
|
||||||
d[key]["values"] = values;
|
d[key]["values"] = values;
|
||||||
@@ -435,13 +362,12 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
|||||||
|
|
||||||
return { queryStr, conditions };
|
return { queryStr, conditions };
|
||||||
}
|
}
|
||||||
function calculateExp(
|
export function calculateExp(
|
||||||
arr: { value: number }[],
|
list: { value: number; isEmptyValue: boolean }[],
|
||||||
config: { calculation?: string }
|
config: { calculation?: string },
|
||||||
): (number | string)[] {
|
): (number | string)[] {
|
||||||
const sum = arr
|
const arr = list.filter((d: { value: number; isEmptyValue: boolean }) => !d.isEmptyValue);
|
||||||
.map((d: { value: number }) => d.value)
|
const sum = arr.length ? arr.map((d: { value: number }) => Number(d.value)).reduce((a, b) => a + b) : 0;
|
||||||
.reduce((a, b) => a + b);
|
|
||||||
let data: (number | string)[] = [];
|
let data: (number | string)[] = [];
|
||||||
switch (config.calculation) {
|
switch (config.calculation) {
|
||||||
case Calculations.Average:
|
case Calculations.Average:
|
||||||
@@ -454,16 +380,15 @@ function calculateExp(
|
|||||||
data = [(sum / arr.length / 10000).toFixed(2)];
|
data = [(sum / arr.length / 10000).toFixed(2)];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
data = arr.map((d) => aggregation(d.value, config));
|
data = list.map((d: { value: number; isEmptyValue: boolean }) =>
|
||||||
|
d.isEmptyValue ? NaN : aggregation(d.value, config),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function aggregation(
|
export function aggregation(val: number, config: { calculation?: string }): number | string {
|
||||||
val: number,
|
|
||||||
config: { calculation?: string }
|
|
||||||
): number | string {
|
|
||||||
let data: number | string = Number(val);
|
let data: number | string = Number(val);
|
||||||
|
|
||||||
switch (config.calculation) {
|
switch (config.calculation) {
|
||||||
@@ -491,9 +416,6 @@ export function aggregation(
|
|||||||
case Calculations.ConvertMilliseconds:
|
case Calculations.ConvertMilliseconds:
|
||||||
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
||||||
break;
|
break;
|
||||||
case Calculations.Precision:
|
|
||||||
data = data.toFixed(2);
|
|
||||||
break;
|
|
||||||
case Calculations.MsToS:
|
case Calculations.MsToS:
|
||||||
data = (val / 1000).toFixed(2);
|
data = (val / 1000).toFixed(2);
|
||||||
break;
|
break;
|
||||||
@@ -503,6 +425,9 @@ export function aggregation(
|
|||||||
case Calculations.NanosecondToMillisecond:
|
case Calculations.NanosecondToMillisecond:
|
||||||
data = (val / 1000 / 1000).toFixed(2);
|
data = (val / 1000 / 1000).toFixed(2);
|
||||||
break;
|
break;
|
||||||
|
case Calculations.ApdexAvg:
|
||||||
|
data = (val / 10000).toFixed(2);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
data;
|
data;
|
||||||
break;
|
break;
|
||||||
@@ -510,28 +435,3 @@ export function aggregation(
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function useGetMetricEntity(metric: string, metricType: any) {
|
|
||||||
if (!metric || !metricType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let catalog = "";
|
|
||||||
const dashboardStore = useDashboardStore();
|
|
||||||
if (
|
|
||||||
[
|
|
||||||
MetricQueryTypes.ReadSampledRecords,
|
|
||||||
MetricQueryTypes.SortMetrics,
|
|
||||||
MetricQueryTypes.ReadRecords,
|
|
||||||
].includes(metricType)
|
|
||||||
) {
|
|
||||||
const res = await dashboardStore.fetchMetricList(metric);
|
|
||||||
if (res.errors) {
|
|
||||||
ElMessage.error(res.errors);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const c: string = res.data.metrics[0].catalog;
|
|
||||||
catalog = (MetricCatalog as any)[c];
|
|
||||||
}
|
|
||||||
|
|
||||||
return catalog;
|
|
||||||
}
|
|
||||||
|
@@ -18,11 +18,7 @@ import { ref, watch } from "vue";
|
|||||||
import { tryOnUnmounted } from "@vueuse/core";
|
import { tryOnUnmounted } from "@vueuse/core";
|
||||||
import { isFunction } from "@/utils/is";
|
import { isFunction } from "@/utils/is";
|
||||||
|
|
||||||
export function useTimeoutFn(
|
export function useTimeoutFn(handle: Fn<any>, wait: number, native = false): any {
|
||||||
handle: Fn<any>,
|
|
||||||
wait: number,
|
|
||||||
native = false
|
|
||||||
): any {
|
|
||||||
if (!isFunction(handle)) {
|
if (!isFunction(handle)) {
|
||||||
throw new Error("handle is not Function!");
|
throw new Error("handle is not Function!");
|
||||||
}
|
}
|
||||||
@@ -36,13 +32,13 @@ export function useTimeoutFn(
|
|||||||
(maturity) => {
|
(maturity) => {
|
||||||
maturity && handle();
|
maturity && handle();
|
||||||
},
|
},
|
||||||
{ immediate: false }
|
{ immediate: false },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return { readyRef, stop, start };
|
return { readyRef, stop, start };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useTimeoutRef(wait: number): any {
|
export function useTimeoutRef(wait: number) {
|
||||||
const readyRef = ref(false);
|
const readyRef = ref(false);
|
||||||
|
|
||||||
let timer: TimeoutHandle;
|
let timer: TimeoutHandle;
|
||||||
|
@@ -22,15 +22,15 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { AppMain, SideBar, NavBar } from "./components";
|
import { AppMain, SideBar, NavBar } from "./components";
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-wrapper {
|
.app-wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -22,8 +22,9 @@ limitations under the License. -->
|
|||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-main {
|
.app-main {
|
||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
background: #f7f9fa;
|
background: #f7f9fa;
|
||||||
}
|
overflow: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -14,7 +14,31 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="nav-bar flex-h">
|
<div class="nav-bar flex-h">
|
||||||
<div class="title">{{ appStore.pageTitle || t(pageName) }}</div>
|
<el-breadcrumb
|
||||||
|
:separator-icon="ArrowRight"
|
||||||
|
class="title flex-h"
|
||||||
|
v-if="pathNames.length"
|
||||||
|
:style="{ '--el-text-color-placeholder': '#666' }"
|
||||||
|
>
|
||||||
|
<el-breadcrumb-item
|
||||||
|
v-for="(path, index) in pathNames"
|
||||||
|
:key="index"
|
||||||
|
:replace="true"
|
||||||
|
:to="{ path: getName(path).path || '' }"
|
||||||
|
>
|
||||||
|
<el-dropdown size="small" placement="bottom" :persistent="false">
|
||||||
|
<span class="cp name">{{ getName(path).name }}</span>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item @click="setName(p)" v-for="(p, index) in path" :key="index">
|
||||||
|
<span>{{ p.name }}</span>
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
</el-breadcrumb>
|
||||||
|
<div class="title" v-else>{{ pageTitle }}</div>
|
||||||
<div class="app-config">
|
<div class="app-config">
|
||||||
<span class="red" v-show="timeRange">{{ t("timeTips") }}</span>
|
<span class="red" v-show="timeRange">{{ t("timeTips") }}</span>
|
||||||
<TimePicker
|
<TimePicker
|
||||||
@@ -23,21 +47,12 @@ limitations under the License. -->
|
|||||||
format="YYYY-MM-DD HH:mm"
|
format="YYYY-MM-DD HH:mm"
|
||||||
@input="changeTimeRange"
|
@input="changeTimeRange"
|
||||||
/>
|
/>
|
||||||
<span>
|
<span> UTC{{ appStore.utcHour >= 0 ? "+" : "" }}{{ `${appStore.utcHour}:${appStore.utcMin}` }} </span>
|
||||||
UTC{{ appStore.utcHour >= 0 ? "+" : ""
|
|
||||||
}}{{ `${appStore.utcHour}:${appStore.utcMin}` }}
|
|
||||||
</span>
|
|
||||||
<span title="refresh" class="ghost ml-5 cp" @click="handleReload">
|
<span title="refresh" class="ghost ml-5 cp" @click="handleReload">
|
||||||
<Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" />
|
<Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" />
|
||||||
</span>
|
</span>
|
||||||
<span class="version ml-5 cp">
|
<span class="version ml-5 cp">
|
||||||
<el-popover
|
<el-popover trigger="hover" width="250" placement="bottom" effect="light" :content="appStore.version">
|
||||||
trigger="hover"
|
|
||||||
width="250"
|
|
||||||
placement="bottom"
|
|
||||||
effect="light"
|
|
||||||
:content="appStore.version"
|
|
||||||
>
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<span>
|
<span>
|
||||||
<Icon iconName="info_outline" size="middle" />
|
<Icon iconName="info_outline" size="middle" />
|
||||||
@@ -49,92 +64,255 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import timeFormat from "@/utils/timeFormat";
|
import timeFormat from "@/utils/timeFormat";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { ElMessage } from "element-plus";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { MetricCatalog } from "@/views/dashboard/data";
|
||||||
|
import type { DashboardItem } from "@/types/dashboard";
|
||||||
|
import router from "@/router";
|
||||||
|
import { ArrowRight } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
const { t } = useI18n();
|
/*global Indexable */
|
||||||
const appStore = useAppStoreWithOut();
|
const { t, te } = useI18n();
|
||||||
const route = useRoute();
|
const appStore = useAppStoreWithOut();
|
||||||
const pageName = ref<string>("");
|
const dashboardStore = useDashboardStore();
|
||||||
const timeRange = ref<number>(0);
|
const route = useRoute();
|
||||||
|
const pathNames = ref<{ path?: string; name: string; selected: boolean }[][]>([]);
|
||||||
|
const timeRange = ref<number>(0);
|
||||||
|
const pageTitle = ref<string>("");
|
||||||
|
|
||||||
resetDuration();
|
resetDuration();
|
||||||
getVersion();
|
getVersion();
|
||||||
const setConfig = (value: string) => {
|
getNavPaths();
|
||||||
pageName.value = value || "";
|
|
||||||
};
|
|
||||||
|
|
||||||
function handleReload() {
|
function getName(list: any[]) {
|
||||||
const gap =
|
return list.find((d: any) => d.selected) || {};
|
||||||
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
|
||||||
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
|
||||||
appStore.setDuration(timeFormat(dates));
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeTimeRange(val: Date[] | any) {
|
|
||||||
timeRange.value =
|
|
||||||
val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
|
|
||||||
if (timeRange.value) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
appStore.setDuration(timeFormat(val));
|
|
||||||
}
|
|
||||||
setConfig(String(route.meta.title));
|
|
||||||
watch(
|
|
||||||
() => route.meta.title,
|
|
||||||
(title: unknown) => {
|
|
||||||
setConfig(String(title));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
async function getVersion() {
|
|
||||||
const res = await appStore.fetchVersion();
|
|
||||||
if (res.errors) {
|
|
||||||
ElMessage.error(res.errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function resetDuration() {
|
|
||||||
const { duration }: any = route.params;
|
|
||||||
if (duration) {
|
|
||||||
const d = JSON.parse(duration);
|
|
||||||
|
|
||||||
appStore.updateDurationRow({
|
function setName(item: any) {
|
||||||
start: new Date(d.start),
|
pathNames.value = pathNames.value.map((list: { path?: string; name: string; selected: boolean }[]) => {
|
||||||
end: new Date(d.end),
|
const p = list.find((i: any) => i.entity === item.entity && item.layer === i.layer && i.name === item.name);
|
||||||
step: d.step,
|
if (p) {
|
||||||
|
list = list.map((d: any) => {
|
||||||
|
d.selected = false;
|
||||||
|
if (d.entity === item.entity && item.layer === d.layer && d.name === item.name) {
|
||||||
|
d.selected = true;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
});
|
});
|
||||||
appStore.updateUTC(d.utc);
|
item.path && router.push(item.path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
function handleReload() {
|
||||||
|
const gap = appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
||||||
|
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
||||||
|
appStore.setDuration(timeFormat(dates));
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTimeRange(val: Date[]) {
|
||||||
|
timeRange.value = val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
|
||||||
|
if (timeRange.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appStore.setDuration(timeFormat(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNavPaths() {
|
||||||
|
pathNames.value = [];
|
||||||
|
pageTitle.value = "";
|
||||||
|
const dashboard = dashboardStore.currentDashboard;
|
||||||
|
|
||||||
|
if (!(dashboard && dashboard.name)) {
|
||||||
|
updateNavTitle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const root =
|
||||||
|
dashboardStore.dashboards.filter((d: DashboardItem) => d.isRoot && dashboard.layer === d.layer)[0] || {};
|
||||||
|
for (const item of appStore.allMenus) {
|
||||||
|
if (item.subItems && item.subItems.length) {
|
||||||
|
for (const subItem of item.subItems) {
|
||||||
|
if (subItem.layer === root.layer) {
|
||||||
|
root.path = subItem.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (item.layer === root.layer) {
|
||||||
|
root.path = item.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pathNames.value.push([{ ...root, selected: true }]);
|
||||||
|
if (dashboard.entity === MetricCatalog.ALL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dashboard.entity === MetricCatalog.SERVICE) {
|
||||||
|
pathNames.value.push([
|
||||||
|
{
|
||||||
|
name: dashboard.name,
|
||||||
|
selected: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const serviceDashboards = dashboardStore.dashboards.filter(
|
||||||
|
(d: DashboardItem) => MetricCatalog.SERVICE === d.entity && dashboard.layer === d.layer,
|
||||||
|
);
|
||||||
|
if (!serviceDashboards.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const serviceId = route.params.serviceId;
|
||||||
|
const list = serviceDashboards.map((d: { path: string } & DashboardItem, index: number) => {
|
||||||
|
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
|
||||||
|
if (serviceId) {
|
||||||
|
path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${d.name}`;
|
||||||
|
}
|
||||||
|
const selected = index === 0;
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
path,
|
||||||
|
selected,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
pathNames.value.push(list);
|
||||||
|
const podId = route.params.podId;
|
||||||
|
if (dashboard.entity === MetricCatalog.ENDPOINT_RELATION) {
|
||||||
|
const endpointDashboards = dashboardStore.dashboards.filter(
|
||||||
|
(d: DashboardItem) => MetricCatalog.ENDPOINT === d.entity && dashboard.layer === d.layer,
|
||||||
|
);
|
||||||
|
const list = endpointDashboards.map((d: { path: string } & DashboardItem, index: number) => {
|
||||||
|
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
|
||||||
|
if (podId) {
|
||||||
|
path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${podId}/${d.name}`;
|
||||||
|
}
|
||||||
|
const selected = index === 0;
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
path,
|
||||||
|
selected,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
pathNames.value.push(list);
|
||||||
|
}
|
||||||
|
const destServiceId = route.params.destServiceId;
|
||||||
|
if (dashboard.entity === MetricCatalog.SERVICE_INSTANCE_RELATION) {
|
||||||
|
const serviceRelationDashboards = dashboardStore.dashboards.filter(
|
||||||
|
(d: DashboardItem) => MetricCatalog.SERVICE_RELATION === d.entity && dashboard.layer === d.layer,
|
||||||
|
);
|
||||||
|
const list = serviceRelationDashboards.map((d: { path: string } & DashboardItem, index: number) => {
|
||||||
|
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
|
||||||
|
if (destServiceId) {
|
||||||
|
path = `/dashboard/related/${d.layer}/${d.entity}/${serviceId}/${destServiceId}/${d.name}`;
|
||||||
|
}
|
||||||
|
const selected = index === 0;
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
path,
|
||||||
|
selected,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
pathNames.value.push(list);
|
||||||
|
}
|
||||||
|
if ([MetricCatalog.Process, MetricCatalog.PROCESS_RELATION].includes(dashboard.entity)) {
|
||||||
|
const InstanceDashboards = dashboardStore.dashboards.filter(
|
||||||
|
(d: DashboardItem) => MetricCatalog.SERVICE_INSTANCE === d.entity && dashboard.layer === d.layer,
|
||||||
|
);
|
||||||
|
const list = InstanceDashboards.map((d: { path: string } & DashboardItem, index: number) => {
|
||||||
|
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
|
||||||
|
if (podId) {
|
||||||
|
path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${podId}/${d.name}`;
|
||||||
|
}
|
||||||
|
const selected = index === 0;
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
path,
|
||||||
|
selected,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
pathNames.value.push(list);
|
||||||
|
}
|
||||||
|
pathNames.value.push([
|
||||||
|
{
|
||||||
|
name: dashboard.name,
|
||||||
|
selected: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getVersion() {
|
||||||
|
const res = await appStore.fetchVersion();
|
||||||
|
if (res.errors) {
|
||||||
|
ElMessage.error(res.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetDuration() {
|
||||||
|
const { duration }: Indexable = route.params;
|
||||||
|
if (duration) {
|
||||||
|
const d = JSON.parse(duration);
|
||||||
|
|
||||||
|
appStore.updateDurationRow({
|
||||||
|
start: new Date(d.start),
|
||||||
|
end: new Date(d.end),
|
||||||
|
step: d.step,
|
||||||
|
});
|
||||||
|
appStore.updateUTC(d.utc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateNavTitle() {
|
||||||
|
const key = String(route.meta.i18nKey);
|
||||||
|
pageTitle.value = te(key) ? t(key) : String(route.meta.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [dashboardStore.currentDashboard, route.name],
|
||||||
|
() => {
|
||||||
|
getNavPaths();
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.nav-bar {
|
.nav-bar {
|
||||||
padding: 5px 10px 5px 28px;
|
padding: 5px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
background-color: #fafbfc;
|
background-color: #fafbfc;
|
||||||
border-bottom: 1px solid #dfe4e8;
|
border-bottom: 1px solid #dfe4e8;
|
||||||
color: #222;
|
color: #222;
|
||||||
font-size: 12px;
|
font-size: $font-size-smaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-bar.dark {
|
.nav-bar.dark {
|
||||||
background-color: #333840;
|
background-color: #333840;
|
||||||
border-bottom: 1px solid #252a2f;
|
border-bottom: 1px solid #252a2f;
|
||||||
color: #fafbfc;
|
color: #fafbfc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 14px;
|
font-size: $font-size-normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
height: 28px;
|
}
|
||||||
line-height: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs {
|
.nav-tabs {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 250px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -13,190 +13,194 @@ 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. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="side-bar">
|
<div class="side-bar" v-if="showMenu" @click="isCollapse = false" @mouseleave="closeMenu">
|
||||||
<div :class="isCollapse ? 'logo-icon-collapse' : 'logo-icon'">
|
<div :class="isCollapse ? 'logo-icon-collapse' : 'logo-icon'">
|
||||||
<Icon
|
<Icon :size="isCollapse ? 'xl' : 'logo'" :iconName="isCollapse ? 'logo' : 'logo-sw'" />
|
||||||
:size="isCollapse ? 'xl' : 'logo'"
|
|
||||||
:iconName="isCollapse ? 'logo' : 'logo-sw'"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<el-menu
|
<div class="menu scroll_bar_dark" :style="isCollapse ? {} : { width: '220px' }">
|
||||||
active-text-color="#448dfe"
|
<el-menu
|
||||||
background-color="#252a2f"
|
active-text-color="#448dfe"
|
||||||
class="el-menu-vertical"
|
background-color="#252a2f"
|
||||||
:default-active="name"
|
class="el-menu-vertical"
|
||||||
text-color="#efefef"
|
:default-active="name"
|
||||||
:unique-opened="true"
|
text-color="#efefef"
|
||||||
:collapse="isCollapse"
|
:collapse="isCollapse"
|
||||||
:style="{ border: 'none' }"
|
:collapse-transition="false"
|
||||||
>
|
:style="{ border: 'none' }"
|
||||||
<template v-for="(menu, index) in routes" :key="index">
|
>
|
||||||
<el-sub-menu :index="String(menu.name)" v-if="menu.meta.hasGroup">
|
<template v-for="(menu, index) in routes" :key="index">
|
||||||
<template #title>
|
<el-sub-menu :index="String(menu.name)" v-if="menu.meta.hasGroup" popper-class="sub-list">
|
||||||
<router-link class="items" :to="menu.path">
|
<template #title>
|
||||||
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
<router-link class="items" :to="menu.path">
|
||||||
<Icon size="lg" :iconName="menu.meta.icon" />
|
<el-icon class="menu-icons" :style="{ marginRight: '12px' }" @mouseover="setCollapse">
|
||||||
</el-icon>
|
<Icon size="lg" :iconName="menu.meta.icon" />
|
||||||
<span class="title" :class="isCollapse ? 'collapse' : ''">
|
</el-icon>
|
||||||
{{ t(menu.meta.title) }}
|
<span class="title" :class="isCollapse ? 'collapse' : ''">
|
||||||
</span>
|
{{ te(menu.meta.i18nKey) ? t(menu.meta.i18nKey) : menu.meta.title }}
|
||||||
</router-link>
|
</span>
|
||||||
</template>
|
|
||||||
<el-menu-item-group>
|
|
||||||
<el-menu-item
|
|
||||||
v-for="(m, idx) in filterMenus(menu.children)"
|
|
||||||
:index="m.name"
|
|
||||||
:key="idx"
|
|
||||||
>
|
|
||||||
<router-link class="items" :to="m.path">
|
|
||||||
<span class="title">{{ m.meta && t(m.meta.title) }}</span>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</el-menu-item>
|
</template>
|
||||||
</el-menu-item-group>
|
<el-menu-item-group>
|
||||||
</el-sub-menu>
|
<el-menu-item v-for="(m, idx) in filterMenus(menu.children)" :index="m.name" :key="idx">
|
||||||
<el-menu-item
|
<router-link class="items" :to="m.path">
|
||||||
:index="String(menu.name)"
|
<span class="title">
|
||||||
@click="changePage(menu)"
|
{{ m.meta && (te(m.meta.i18nKey) ? t(m.meta.i18nKey) : m.meta.title) }}
|
||||||
v-else
|
</span>
|
||||||
>
|
</router-link>
|
||||||
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
</el-menu-item>
|
||||||
<router-link class="items" :to="menu.children[0].path">
|
</el-menu-item-group>
|
||||||
<Icon size="lg" :iconName="menu.meta.icon" />
|
</el-sub-menu>
|
||||||
</router-link>
|
<el-menu-item :index="String(menu.name)" @click="changePage(menu)" v-else>
|
||||||
</el-icon>
|
<el-icon class="menu-icons" :style="{ marginRight: '12px' }" @mouseover="setCollapse">
|
||||||
<template #title>
|
<router-link class="items menu-title" :to="menu.children[0].path">
|
||||||
<router-link class="items" :to="menu.children[0].path">
|
<Icon size="lg" :iconName="menu.meta.icon" />
|
||||||
<span class="title">{{ t(menu.meta.title) }}</span>
|
</router-link>
|
||||||
</router-link>
|
</el-icon>
|
||||||
</template>
|
<template #title>
|
||||||
</el-menu-item>
|
<router-link class="items menu-title" :to="menu.children[0].path">
|
||||||
</template>
|
<span class="title">
|
||||||
</el-menu>
|
{{ te(menu.meta.i18nKey) ? t(menu.meta.i18nKey) : menu.meta.title }}
|
||||||
<div
|
</span>
|
||||||
class="menu-control"
|
</router-link>
|
||||||
:class="isCollapse ? 'collapse' : ''"
|
</template>
|
||||||
:style="{
|
</el-menu-item>
|
||||||
color: theme === 'light' ? '#eee' : '#252a2f',
|
</template>
|
||||||
}"
|
</el-menu>
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
size="middle"
|
|
||||||
iconName="format_indent_decrease"
|
|
||||||
@click="controlMenu"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { useRouter, RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import Icon from "@/components/Icon.vue";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import Icon from "@/components/Icon.vue";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut();
|
/*global Recordable*/
|
||||||
const { t } = useI18n();
|
const { t, te } = useI18n();
|
||||||
const name = ref<string>(String(useRouter().currentRoute.value.name));
|
const appStore = useAppStoreWithOut();
|
||||||
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "")
|
const router = useRouter();
|
||||||
? ref("light")
|
const name = ref<string>(String(router.currentRoute.value.name));
|
||||||
: ref("black");
|
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "") ? ref("light") : ref("black");
|
||||||
const routes = ref<RouteRecordRaw[] | any>(useRouter().options.routes);
|
const routes = ref<RouteRecordRaw[] | any>(
|
||||||
if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
(router.options.routes || []).filter((d: any) => d.meta && d.meta.activate),
|
||||||
appStore.setIsMobile(true);
|
);
|
||||||
} else {
|
const route = useRoute();
|
||||||
appStore.setIsMobile(false);
|
const isCollapse = ref(true);
|
||||||
}
|
const showMenu = ref(true);
|
||||||
const isCollapse = ref(false);
|
const open = ref<boolean>(false);
|
||||||
const controlMenu = () => {
|
|
||||||
isCollapse.value = !isCollapse.value;
|
if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
||||||
};
|
appStore.setIsMobile(true);
|
||||||
const changePage = (menu: RouteRecordRaw) => {
|
} else {
|
||||||
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name))
|
appStore.setIsMobile(false);
|
||||||
? "light"
|
}
|
||||||
: "black";
|
if (route.name === "ViewWidget") {
|
||||||
};
|
showMenu.value = false;
|
||||||
const filterMenus = (menus: any[]) => {
|
}
|
||||||
return menus.filter((d) => d.meta && !d.meta.notShow);
|
const changePage = (menu: RouteRecordRaw) => {
|
||||||
};
|
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name)) ? "light" : "black";
|
||||||
|
};
|
||||||
|
const filterMenus = (menus: Recordable[]) => {
|
||||||
|
return menus.filter((d) => d.meta && !d.meta.notShow && d.meta.activate);
|
||||||
|
};
|
||||||
|
function setCollapse() {
|
||||||
|
open.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
if (open.value) {
|
||||||
|
isCollapse.value = false;
|
||||||
|
}
|
||||||
|
open.value = false;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
function closeMenu() {
|
||||||
|
isCollapse.value = true;
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.name,
|
||||||
|
() => {
|
||||||
|
name.value = String(route.name);
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.side-bar {
|
.side-bar {
|
||||||
background: #252a2f;
|
background: #252a2f;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-bottom: 100px;
|
margin-bottom: 180px;
|
||||||
overflow-y: auto;
|
}
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-menu-vertical:not(.el-menu--collapse) {
|
.menu {
|
||||||
width: 220px;
|
height: calc(100% - 30px);
|
||||||
font-size: 16px;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-icon-collapse {
|
.menu:hover {
|
||||||
width: 65px;
|
overflow-y: auto;
|
||||||
margin: 15px 0 10px 0;
|
}
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.collapse {
|
.el-menu-vertical:not(.el-menu--collapse) {
|
||||||
height: 0;
|
width: 220px;
|
||||||
width: 0;
|
font-size: $font-size-normal;
|
||||||
overflow: hidden;
|
}
|
||||||
visibility: hidden;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-icon {
|
.logo-icon-collapse {
|
||||||
margin: 15px 0 10px 20px;
|
width: 65px;
|
||||||
width: 110px;
|
margin: 5px 0 10px;
|
||||||
}
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-control {
|
span.collapse {
|
||||||
position: absolute;
|
height: 0;
|
||||||
top: 7px;
|
width: 0;
|
||||||
left: 220px;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
visibility: hidden;
|
||||||
transition: all 0.2s linear;
|
display: inline-block;
|
||||||
z-index: 99;
|
}
|
||||||
color: #252a2f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-control.collapse {
|
.logo-icon {
|
||||||
left: 70px;
|
margin: 15px 0 10px 20px;
|
||||||
}
|
width: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
.el-icon.el-sub-menu__icon-arrow {
|
.menu-control.collapse {
|
||||||
height: 12px;
|
left: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.items {
|
.el-icon.el-sub-menu__icon-arrow {
|
||||||
display: inline-block;
|
height: 12px;
|
||||||
width: 100%;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.version {
|
.items {
|
||||||
color: #eee;
|
display: inline-block;
|
||||||
font-size: 12px;
|
width: 100%;
|
||||||
cursor: pointer;
|
}
|
||||||
padding-left: 23px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty {
|
.version {
|
||||||
width: 100%;
|
color: #eee;
|
||||||
height: 60px;
|
font-size: $font-size-smaller;
|
||||||
}
|
cursor: pointer;
|
||||||
|
padding-left: 23px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.empty {
|
||||||
display: inline-block;
|
width: 100%;
|
||||||
max-width: 110px;
|
height: 60px;
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
overflow: hidden;
|
|
||||||
}
|
.title {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 200px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -32,6 +32,7 @@ if (!savedLanguage) {
|
|||||||
}
|
}
|
||||||
language = savedLanguage ? savedLanguage : language;
|
language = savedLanguage ? savedLanguage : language;
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
|
legacy: false,
|
||||||
locale: language,
|
locale: language,
|
||||||
messages,
|
messages,
|
||||||
});
|
});
|
||||||
|
@@ -14,15 +14,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import enTitles from "./menus/en";
|
||||||
const msg = {
|
const msg = {
|
||||||
general: "General Service",
|
...enTitles,
|
||||||
services: "Services",
|
services: "Services",
|
||||||
service: "Service",
|
service: "Service",
|
||||||
traces: "Traces",
|
traces: "Traces",
|
||||||
metrics: "Metrics",
|
metrics: "Metrics",
|
||||||
serviceMesh: "Service Mesh",
|
|
||||||
infrastructure: "Infrastructure",
|
|
||||||
virtualMachine: "Virtual Machine",
|
|
||||||
dashboardNew: "New Dashboard",
|
dashboardNew: "New Dashboard",
|
||||||
dashboardList: "Dashboard List",
|
dashboardList: "Dashboard List",
|
||||||
logs: "Logs",
|
logs: "Logs",
|
||||||
@@ -32,15 +30,12 @@ const msg = {
|
|||||||
dashboards: "Dashboards",
|
dashboards: "Dashboards",
|
||||||
profiles: "Profiles",
|
profiles: "Profiles",
|
||||||
database: "Database",
|
database: "Database",
|
||||||
mySQL: "MySQL",
|
mySQL: "MySQL/MariaDB",
|
||||||
serviceName: "Service Name",
|
serviceName: "Service Name",
|
||||||
technologies: "Technologies",
|
technologies: "Technologies",
|
||||||
generalServicePanel: "General Service Panel",
|
|
||||||
health: "Health",
|
health: "Health",
|
||||||
groupName: "Group Name",
|
groupName: "Group Name",
|
||||||
topologies: "Topologies",
|
topologies: "Topologies",
|
||||||
dataPanel: "Data Plane",
|
|
||||||
controlPanel: "Control Plane",
|
|
||||||
eventList: "Event List",
|
eventList: "Event List",
|
||||||
newDashboard: "Create a new dashboard",
|
newDashboard: "Create a new dashboard",
|
||||||
dashboardEdit: "Edit the dashboard",
|
dashboardEdit: "Edit the dashboard",
|
||||||
@@ -117,20 +112,9 @@ const msg = {
|
|||||||
rename: "Rename",
|
rename: "Rename",
|
||||||
deleteTitle: "Are you sure you want to delete this?",
|
deleteTitle: "Are you sure you want to delete this?",
|
||||||
rootTitle: "Are you sure you want to set this?",
|
rootTitle: "Are you sure you want to set this?",
|
||||||
selfObservability: "Self Observability",
|
|
||||||
satellite: "Satellite",
|
|
||||||
skyWalkingServer: "SkyWalking Server",
|
|
||||||
functions: "Functions",
|
|
||||||
browser: "Browser",
|
|
||||||
linux: "Linux",
|
|
||||||
editWarning: "You are entering edit mode",
|
editWarning: "You are entering edit mode",
|
||||||
viewWarning: "You are entering view mode",
|
viewWarning: "You are entering view mode",
|
||||||
virtualDatabase: "Virtual Database",
|
|
||||||
virtualCache: "Virtual Cache",
|
|
||||||
reloadDashboards: "Reload dashboards",
|
reloadDashboards: "Reload dashboards",
|
||||||
kubernetesService: "Service",
|
|
||||||
kubernetesCluster: "Cluster",
|
|
||||||
kubernetes: "Kubernetes",
|
|
||||||
textUrl: "Text Hyperlink",
|
textUrl: "Text Hyperlink",
|
||||||
textAlign: "Text Align",
|
textAlign: "Text Align",
|
||||||
metricLabel: "Metric Label",
|
metricLabel: "Metric Label",
|
||||||
@@ -156,9 +140,7 @@ const msg = {
|
|||||||
enableAssociate: "Enable association",
|
enableAssociate: "Enable association",
|
||||||
text: "Text",
|
text: "Text",
|
||||||
query: "Query",
|
query: "Query",
|
||||||
postgreSQL: "PostgreSQL",
|
|
||||||
endpointTips: "The table shows up to 20 pieces of endpoints.",
|
endpointTips: "The table shows up to 20 pieces of endpoints.",
|
||||||
apisix: "APISIX",
|
|
||||||
viewTrace: "View Related Traces",
|
viewTrace: "View Related Traces",
|
||||||
relatedTraceOptions: "Related Trace Options",
|
relatedTraceOptions: "Related Trace Options",
|
||||||
setLatencyDuration: "Latency Related Metrics",
|
setLatencyDuration: "Latency Related Metrics",
|
||||||
@@ -176,11 +158,16 @@ const msg = {
|
|||||||
toTheRight: "To The Right",
|
toTheRight: "To The Right",
|
||||||
legendValues: "Legend Values",
|
legendValues: "Legend Values",
|
||||||
minDuration: "Minimal Request Duration",
|
minDuration: "Minimal Request Duration",
|
||||||
when4xx:
|
when4xx: "Sample HTTP requests and responses with tracing when response code between 400 and 499",
|
||||||
"Sample HTTP requests and responses with tracing when response code between 400 and 499",
|
when5xx: "Sample HTTP requests and responses with tracing when response code between 500 and 599",
|
||||||
when5xx:
|
|
||||||
"Sample HTTP requests and responses with tracing when response code between 500 and 599",
|
|
||||||
taskTitle: "HTTP request and response collecting rules",
|
taskTitle: "HTTP request and response collecting rules",
|
||||||
|
iframeWidgetTip: "Add a link to a widget",
|
||||||
|
iframeSrc: "Iframe Link",
|
||||||
|
generateLink: "Generate Link",
|
||||||
|
setDuration: "Lock Query Duration",
|
||||||
|
openFunction: "OpenFunction",
|
||||||
|
period: "Period",
|
||||||
|
windows: "Windows",
|
||||||
seconds: "Seconds",
|
seconds: "Seconds",
|
||||||
hourTip: "Select Hour",
|
hourTip: "Select Hour",
|
||||||
minuteTip: "Select Minute",
|
minuteTip: "Select Minute",
|
||||||
@@ -199,7 +186,7 @@ const msg = {
|
|||||||
topology: "Topology",
|
topology: "Topology",
|
||||||
trace: "Trace",
|
trace: "Trace",
|
||||||
alarm: "Alerting",
|
alarm: "Alerting",
|
||||||
auto: "Auto",
|
auto: "Auto Fresh",
|
||||||
reload: "Reload",
|
reload: "Reload",
|
||||||
version: "Version",
|
version: "Version",
|
||||||
copy: "Copy",
|
copy: "Copy",
|
||||||
@@ -277,7 +264,6 @@ const msg = {
|
|||||||
aggregation: "Calculation",
|
aggregation: "Calculation",
|
||||||
unit: "Unit",
|
unit: "Unit",
|
||||||
labelsIndex: "Label Subscript",
|
labelsIndex: "Label Subscript",
|
||||||
group: "Service Group",
|
|
||||||
browserView: "Browser",
|
browserView: "Browser",
|
||||||
sortOrder: "Sort Order",
|
sortOrder: "Sort Order",
|
||||||
chartType: "Chart Type",
|
chartType: "Chart Type",
|
||||||
@@ -315,10 +301,10 @@ const msg = {
|
|||||||
viewLogs: "View Logs",
|
viewLogs: "View Logs",
|
||||||
logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable.
|
logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable.
|
||||||
Check more details on the Configuration Vocabulary page`,
|
Check more details on the Configuration Vocabulary page`,
|
||||||
keywordsOfContentLogTips:
|
keywordsOfContentLogTips: "Current storage of SkyWalking OAP server does not support this.",
|
||||||
"Current storage of SkyWalking OAP server does not support this.",
|
|
||||||
setEvent: "Set Event",
|
setEvent: "Set Event",
|
||||||
viewAttributes: "View",
|
viewAttributes: "View",
|
||||||
|
attributes: "Attributes",
|
||||||
serviceEvents: "Service Events",
|
serviceEvents: "Service Events",
|
||||||
select: "Select",
|
select: "Select",
|
||||||
eventID: "Event ID",
|
eventID: "Event ID",
|
||||||
@@ -370,10 +356,31 @@ const msg = {
|
|||||||
addKeywordsOfContent: "Please input a keyword of content",
|
addKeywordsOfContent: "Please input a keyword of content",
|
||||||
addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
|
addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
|
||||||
noticeTag: "Please press Enter after inputting a tag(key=value).",
|
noticeTag: "Please press Enter after inputting a tag(key=value).",
|
||||||
conditionNotice:
|
conditionNotice: "Notice: Please press Enter after inputting a key of content, exclude key of content(key=value).",
|
||||||
"Notice: Please press Enter after inputting a key of content, exclude key of content(key=value).",
|
|
||||||
language: "Language",
|
language: "Language",
|
||||||
gateway: "Gateway",
|
save: "Save",
|
||||||
virtualMQ: "Virtual MQ",
|
editStrategy: "Edit Policies",
|
||||||
|
policyList: "Policy List",
|
||||||
|
targetTypes: "Target Type",
|
||||||
|
monitorType: "Monitor Type",
|
||||||
|
count: "Count",
|
||||||
|
threshold: "Threshold",
|
||||||
|
uriRegex: "URI Regex",
|
||||||
|
uriList: "URI List",
|
||||||
|
processes: "Processes",
|
||||||
|
monitorInstances: "Monitoring Instances",
|
||||||
|
processDashboards: "Process Dashboards",
|
||||||
|
instanceDashboards: "Instance Dashboards",
|
||||||
|
detailLabel: "Detail Label",
|
||||||
|
summary: "Summary",
|
||||||
|
detail: "Detail",
|
||||||
|
marketplace: "Marketplace",
|
||||||
|
menus: "Menus",
|
||||||
|
saveReload: "Save and reload the page",
|
||||||
|
document: "Documentation",
|
||||||
|
metricMode: "Metric Mode",
|
||||||
|
addExpressions: "Add Expressions",
|
||||||
|
expressions: "Expression",
|
||||||
|
unhealthyExpression: "Unhealthy Expression",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -14,15 +14,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import esTitles from "./menus/es";
|
||||||
const msg = {
|
const msg = {
|
||||||
|
...esTitles,
|
||||||
general: "Servicio General",
|
general: "Servicio General",
|
||||||
services: "Servicios",
|
services: "Servicios",
|
||||||
service: "Servicio",
|
service: "Servicio",
|
||||||
traces: "Trazas",
|
traces: "Trazas",
|
||||||
metrics: "Métricas",
|
metrics: "Métricas",
|
||||||
serviceMesh: "Malla de Servicios",
|
|
||||||
infrastructure: "Infraestructura",
|
|
||||||
virtualMachine: "Máquina Virtual",
|
|
||||||
dashboardNew: "Nuevo Panel",
|
dashboardNew: "Nuevo Panel",
|
||||||
dashboardList: "Listado Paneles",
|
dashboardList: "Listado Paneles",
|
||||||
logs: "Logs",
|
logs: "Logs",
|
||||||
@@ -32,15 +31,12 @@ const msg = {
|
|||||||
dashboards: "Paneles",
|
dashboards: "Paneles",
|
||||||
profiles: "Perfiles",
|
profiles: "Perfiles",
|
||||||
database: "Base de Datos",
|
database: "Base de Datos",
|
||||||
mySQL: "MySQL",
|
mySQL: "MySQL/MariaDB",
|
||||||
serviceName: "Nombre Servicio",
|
serviceName: "Nombre Servicio",
|
||||||
technologies: "Tecnologías",
|
technologies: "Tecnologías",
|
||||||
generalServicePanel: "Panel Servicio General",
|
|
||||||
health: "Salud",
|
health: "Salud",
|
||||||
groupName: "Nombre Grupo",
|
groupName: "Nombre Grupo",
|
||||||
topologies: "Topologías",
|
topologies: "Topologías",
|
||||||
dataPanel: "Plano de Datos",
|
|
||||||
controlPanel: "Plano de Control",
|
|
||||||
eventList: "Listado Eventos",
|
eventList: "Listado Eventos",
|
||||||
newDashboard: "Crear panel nuevo",
|
newDashboard: "Crear panel nuevo",
|
||||||
dashboardEdit: "Editar el panel",
|
dashboardEdit: "Editar el panel",
|
||||||
@@ -77,10 +73,8 @@ const msg = {
|
|||||||
editGraph: "Editar Opciones",
|
editGraph: "Editar Opciones",
|
||||||
dashboardName: "Selecciona Nombre del Panel",
|
dashboardName: "Selecciona Nombre del Panel",
|
||||||
linkDashboard: "Nombre del panel relacionado con llamadas de la topología",
|
linkDashboard: "Nombre del panel relacionado con llamadas de la topología",
|
||||||
linkServerMetrics:
|
linkServerMetrics: "Métricas de servidor relacionadas con llamadas de la topología",
|
||||||
"Métricas de servidor relacionadas con llamadas de la topología",
|
linkClientMetrics: "Métricas de cliente relacionadas con llamadas de la topología",
|
||||||
linkClientMetrics:
|
|
||||||
"Métricas de cliente relacionadas con llamadas de la topología",
|
|
||||||
nodeDashboard: "Nombre del panel relacionado con nodos de la topología",
|
nodeDashboard: "Nombre del panel relacionado con nodos de la topología",
|
||||||
nodeMetrics: "Mêtricas relacionas con nodos de la topología",
|
nodeMetrics: "Mêtricas relacionas con nodos de la topología",
|
||||||
instanceDashboard: "Nombre del panel relacionado con instancias de servicio",
|
instanceDashboard: "Nombre del panel relacionado con instancias de servicio",
|
||||||
@@ -119,20 +113,9 @@ const msg = {
|
|||||||
rename: "Renombrar",
|
rename: "Renombrar",
|
||||||
deleteTitle: "¿Está seguro que quiere eliminarlo?",
|
deleteTitle: "¿Está seguro que quiere eliminarlo?",
|
||||||
rootTitle: "¿Está seguro que quiere establecerlo?",
|
rootTitle: "¿Está seguro que quiere establecerlo?",
|
||||||
selfObservability: "Autoobservabilidad",
|
|
||||||
satellite: "Satéllite",
|
|
||||||
skyWalkingServer: "Servidor SkyWalking",
|
|
||||||
functions: "Funciones",
|
|
||||||
browser: "Navegador",
|
|
||||||
linux: "Linux",
|
|
||||||
editWarning: "Estás entrando en modo edición",
|
editWarning: "Estás entrando en modo edición",
|
||||||
viewWarning: "Estás entrando en modo visualización",
|
viewWarning: "Estás entrando en modo visualización",
|
||||||
virtualDatabase: "Base de Datos Virtual",
|
|
||||||
virtualCache: "Caché virtual",
|
|
||||||
reloadDashboards: "Recargar Panel",
|
reloadDashboards: "Recargar Panel",
|
||||||
kubernetesService: "Servicio",
|
|
||||||
kubernetesCluster: "Cluster",
|
|
||||||
kubernetes: "Kubernetes",
|
|
||||||
textUrl: "Hipervínculo de Texto",
|
textUrl: "Hipervínculo de Texto",
|
||||||
textAlign: "Alineación de Texto",
|
textAlign: "Alineación de Texto",
|
||||||
metricLabel: "Etiqueta de Métrica",
|
metricLabel: "Etiqueta de Métrica",
|
||||||
@@ -156,14 +139,17 @@ const msg = {
|
|||||||
"El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres",
|
"El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres",
|
||||||
enableAssociate: "Activar asociación",
|
enableAssociate: "Activar asociación",
|
||||||
query: "Consulta",
|
query: "Consulta",
|
||||||
postgreSQL: "PostgreSQL",
|
|
||||||
endpointTips: "Aquí, la tabla muestra hasta 20 punto final.",
|
endpointTips: "Aquí, la tabla muestra hasta 20 punto final.",
|
||||||
apisix: "APISIX",
|
|
||||||
queryOrder: "Consulta por duración",
|
queryOrder: "Consulta por duración",
|
||||||
setOrder: "Orden de consulta",
|
setOrder: "Orden de consulta",
|
||||||
latency: "Retraso",
|
latency: "Retraso",
|
||||||
metricValues: "Valor métrico",
|
metricValues: "Valor métrico",
|
||||||
legendValues: "Valor de la leyenda",
|
legendValues: "Valor de la leyenda",
|
||||||
|
iframeWidgetTip: "Añadir enlaces a los gadgets",
|
||||||
|
iframeSrc: "Enlace Iframe",
|
||||||
|
generateLink: "Generar enlaces",
|
||||||
|
setDuration: "Duración de la consulta de bloqueo",
|
||||||
|
openFunction: "OpenFunction",
|
||||||
seconds: "Segundos",
|
seconds: "Segundos",
|
||||||
hourTip: "Seleccione Hora",
|
hourTip: "Seleccione Hora",
|
||||||
minuteTip: "Seleccione Minuto",
|
minuteTip: "Seleccione Minuto",
|
||||||
@@ -180,11 +166,11 @@ const msg = {
|
|||||||
asTable: "Como tabla",
|
asTable: "Como tabla",
|
||||||
toTheRight: "Derecha",
|
toTheRight: "Derecha",
|
||||||
minDuration: "Duración mínima de la solicitud",
|
minDuration: "Duración mínima de la solicitud",
|
||||||
when4xx:
|
when4xx: "Ejemplo de solicitud y respuesta http con seguimiento cuando el Código de respuesta está entre 400 y 499",
|
||||||
"Ejemplo de solicitud y respuesta http con seguimiento cuando el Código de respuesta está entre 400 y 499",
|
when5xx: "Ejemplo de solicitud y respuesta http con seguimiento cuando el Código de respuesta está entre 500 y 599",
|
||||||
when5xx:
|
|
||||||
"Ejemplo de solicitud y respuesta http con seguimiento cuando el Código de respuesta está entre 500 y 599",
|
|
||||||
taskTitle: "Reglas de recolección de peticiones y respuestas HTTP",
|
taskTitle: "Reglas de recolección de peticiones y respuestas HTTP",
|
||||||
|
period: "Period",
|
||||||
|
windows: "Windows",
|
||||||
second: "s",
|
second: "s",
|
||||||
yearSuffix: "Año",
|
yearSuffix: "Año",
|
||||||
monthsHead: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Set_Oct_Nov_Dic",
|
monthsHead: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Set_Oct_Nov_Dic",
|
||||||
@@ -199,7 +185,7 @@ const msg = {
|
|||||||
topology: "Topología",
|
topology: "Topología",
|
||||||
trace: "Traza",
|
trace: "Traza",
|
||||||
alarm: "Recordatorio en curso",
|
alarm: "Recordatorio en curso",
|
||||||
auto: "Auto",
|
auto: "Auto Fresh",
|
||||||
reload: "Recargar",
|
reload: "Recargar",
|
||||||
version: "Versión",
|
version: "Versión",
|
||||||
copy: "Copiar",
|
copy: "Copiar",
|
||||||
@@ -277,7 +263,6 @@ const msg = {
|
|||||||
aggregation: "Cálculo",
|
aggregation: "Cálculo",
|
||||||
unit: "Unidad",
|
unit: "Unidad",
|
||||||
labelsIndex: "Subíndice Etiqueta",
|
labelsIndex: "Subíndice Etiqueta",
|
||||||
group: "Grupo Servicio",
|
|
||||||
browserView: "Navegador",
|
browserView: "Navegador",
|
||||||
sortOrder: "Orden de clasificación",
|
sortOrder: "Orden de clasificación",
|
||||||
chartType: "Tipo Gráfico",
|
chartType: "Tipo Gráfico",
|
||||||
@@ -315,8 +300,7 @@ const msg = {
|
|||||||
viewLogs: "Ver Registro de Datos",
|
viewLogs: "Ver Registro de Datos",
|
||||||
logsTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas.
|
logsTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas.
|
||||||
Más información en la página de Vocabulario de Configuración`,
|
Más información en la página de Vocabulario de Configuración`,
|
||||||
keywordsOfContentLogTips:
|
keywordsOfContentLogTips: "El almacenamiento actual del servidor SkyWalking OAP no lo soporta.",
|
||||||
"El almacenamiento actual del servidor SkyWalking OAP no lo soporta.",
|
|
||||||
setEvent: "Establecer Evento",
|
setEvent: "Establecer Evento",
|
||||||
viewAttributes: "Ver",
|
viewAttributes: "Ver",
|
||||||
serviceEvents: "Eventos Servico",
|
serviceEvents: "Eventos Servico",
|
||||||
@@ -347,8 +331,7 @@ const msg = {
|
|||||||
destEndpoint: "Endpoint Destinación",
|
destEndpoint: "Endpoint Destinación",
|
||||||
eventSource: "Fuente Envento",
|
eventSource: "Fuente Envento",
|
||||||
modalTitle: "Inspección",
|
modalTitle: "Inspección",
|
||||||
selectRedirectPage:
|
selectRedirectPage: "Quiere inspeccionar las Trazas or Registros de datos del servicio %s?",
|
||||||
"Quiere inspeccionar las Trazas or Registros de datos del servicio %s?",
|
|
||||||
logAnalysis: "Lenguaje de Análisis de Registro de Datos",
|
logAnalysis: "Lenguaje de Análisis de Registro de Datos",
|
||||||
logDataBody: "Contenido del Registro de Datos",
|
logDataBody: "Contenido del Registro de Datos",
|
||||||
addType: "Por favor introduzca un tipo",
|
addType: "Por favor introduzca un tipo",
|
||||||
@@ -369,14 +352,35 @@ const msg = {
|
|||||||
addTraceID: "Por favor introduzca el ID de la traza",
|
addTraceID: "Por favor introduzca el ID de la traza",
|
||||||
addTags: "Por favor introduzaca una etiqueta",
|
addTags: "Por favor introduzaca una etiqueta",
|
||||||
addKeywordsOfContent: "Por favor introduzca una clave de contenido",
|
addKeywordsOfContent: "Por favor introduzca una clave de contenido",
|
||||||
addExcludingKeywordsOfContent:
|
addExcludingKeywordsOfContent: "Por favor introduzca una clave excluyente de contenido",
|
||||||
"Por favor introduzca una clave excluyente de contenido",
|
noticeTag: "Por favor presione Intro después de introducir una etiqueta(clave=valor).",
|
||||||
noticeTag:
|
|
||||||
"Por favor presione Intro después de introducir una etiqueta(clave=valor).",
|
|
||||||
conditionNotice:
|
conditionNotice:
|
||||||
"Aviso: Por favor presione Intro después de introducir una clave de contenido, excluir clave de contenido(clave=valor).",
|
"Aviso: Por favor presione Intro después de introducir una clave de contenido, excluir clave de contenido(clave=valor).",
|
||||||
language: "Lenguaje",
|
language: "Lenguaje",
|
||||||
gateway: "Puerta",
|
save: "Salvar",
|
||||||
virtualMQ: "MQ virtual",
|
editStrategy: "Estrategia editorial",
|
||||||
|
policyList: "Lista de políticas",
|
||||||
|
targetTypes: "Tipo de objetivo",
|
||||||
|
monitorType: "Tipo de Monitor",
|
||||||
|
count: "Contar",
|
||||||
|
threshold: "Umbral",
|
||||||
|
uriRegex: "Lista URI",
|
||||||
|
uriList: "Lista URI",
|
||||||
|
processes: "Proceso",
|
||||||
|
attributes: "Atributos",
|
||||||
|
monitorInstances: "Ejemplo de Monitor",
|
||||||
|
processDashboards: "Tablero de proceso",
|
||||||
|
instanceDashboards: "Tablero de ejemplo",
|
||||||
|
detailLabel: "Detail Label",
|
||||||
|
summary: "Summary",
|
||||||
|
detail: "Detail",
|
||||||
|
marketplace: "Marketplace",
|
||||||
|
menus: "Menus",
|
||||||
|
saveReload: "Save and reload the page",
|
||||||
|
document: "Documentation",
|
||||||
|
metricMode: "Metric Mode",
|
||||||
|
addExpressions: "Add Expressions",
|
||||||
|
expressions: "Expression",
|
||||||
|
unhealthyExpression: "Unhealthy Expression",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
124
src/locales/lang/menus/en.ts
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
const titles = {
|
||||||
|
// General Service
|
||||||
|
general_service: "General Service",
|
||||||
|
general_service_desc:
|
||||||
|
"Observe services and relative direct dependencies through telemetry data collected from SkyWalking Agents.",
|
||||||
|
general_service_services: "Services",
|
||||||
|
general_service_services_desc: "Observe services through telemetry data collected from SkyWalking Agent.",
|
||||||
|
general_service_virtual_database: "Visual Database",
|
||||||
|
general_service_virtual_database_desc:
|
||||||
|
"Observe the virtual databases which are conjectured by language agents through various plugins.",
|
||||||
|
general_service_virtual_cache: "Visual Cache",
|
||||||
|
general_service_virtual_cache_desc:
|
||||||
|
"Observe the virtual cache servers which are conjectured by language agents through various plugins.",
|
||||||
|
general_service_virtual_mq: "Virtual MQ",
|
||||||
|
general_service_virtual_mq_desc:
|
||||||
|
"Observe the virtual message queue servers which are conjectured by language agents through various plugins.",
|
||||||
|
// Service Mesh
|
||||||
|
service_mesh: "Service Mesh",
|
||||||
|
service_mesh_desc:
|
||||||
|
"Service Mesh(Istio) addresses the challenges developers and operators face with a distributed or microservices architecture.",
|
||||||
|
service_mesh_service: "Services",
|
||||||
|
service_mesh_service_desc:
|
||||||
|
"Observe Service Mesh through telemetry data collected from Envoy Access Log Service (ALS).",
|
||||||
|
service_mesh_control_plane: "Control Plane",
|
||||||
|
service_mesh_control_plane_desc: "Provide monitoring of the behavior of Istio through its self-monitoring metrics.",
|
||||||
|
service_mesh_data_plane: "Data Plane",
|
||||||
|
service_mesh_data_plane_desc: "Observe Envoy Proxy through Envoy Metrics Service.",
|
||||||
|
// Functions
|
||||||
|
functions: "Functions",
|
||||||
|
functions_desc:
|
||||||
|
"FaaS (Function-as-a-Service) is a type of cloud-computing service that allows you to execute code in response to events without the complex infrastructure typically associated with building and launching microservices applications.",
|
||||||
|
functions_openfunction: "OpenFunction",
|
||||||
|
functions_openfunction_desc:
|
||||||
|
"OpenFunction as a FaaS platform, provides out-of-box observability with SkyWalking integration.",
|
||||||
|
// Kubernetes
|
||||||
|
kubernetes: "Kubernetes",
|
||||||
|
kubernetes_desc:
|
||||||
|
"Kubernetes is an open-source container orchestration system for automating software deployment, scaling, and management.",
|
||||||
|
kubernetes_cluster: "Cluster",
|
||||||
|
kubernetes_cluster_desc: "Provide monitoring of the status and resources of the K8S Cluster.",
|
||||||
|
kubernetes_service: "Service",
|
||||||
|
kubernetes_service_desc: "Observe Service status and resources from Kubernetes.",
|
||||||
|
// Infrastructure
|
||||||
|
infrastructure: "Infrastructure",
|
||||||
|
infrastructure_desc:
|
||||||
|
"Operation Systems act as the infrastructure of the whole IT system. Its observabilities provide the fundamentals for all distributed and modern complex systems running.",
|
||||||
|
infrastructure_linux: "Linux",
|
||||||
|
infrastructure_linux_desc: "Provide Linux Operation System(OS) monitoring.",
|
||||||
|
infrastructure_windows: "Windows",
|
||||||
|
infrastructure_windows_desc: "Provide Windows Operation System(OS) monitoring.",
|
||||||
|
// AWS Cloud
|
||||||
|
aws_cloud: "AWS Cloud",
|
||||||
|
aws_cloud_desc: "Amazon Web Services(AWS) offers reliable, scalable, and inexpensive cloud computing services.",
|
||||||
|
aws_cloud_eks: "EKS",
|
||||||
|
aws_cloud_eks_desc: "Provide AWS Cloud EKS monitoring through AWS Container Insights Receiver.",
|
||||||
|
aws_cloud_s3: "S3",
|
||||||
|
aws_cloud_s3_desc: "Provide AWS Cloud S3 monitoring through AWS FireHose Receiver.",
|
||||||
|
aws_cloud_dynamodb: "DynamoDB",
|
||||||
|
aws_cloud_dynamodb_desc: "Provide DynamoDB monitoring through AWS FireHose Receiver.",
|
||||||
|
aws_cloud_api_gateway: "API Gateway",
|
||||||
|
aws_cloud_api_gateway_desc: "Provide AWS Cloud API Gateway monitoring through AWS FireHose Receiver.",
|
||||||
|
// Browser
|
||||||
|
browser: "Browser",
|
||||||
|
browser_desc: "Provide Browser-Side monitoring of Web-App, Versions and Pages, through Apache SkyWalking Client JS.",
|
||||||
|
// Gateway
|
||||||
|
gateway: "Gateway",
|
||||||
|
gateway_desc:
|
||||||
|
"API gateway is an API management tool that sits between a client and a collection of backend services.",
|
||||||
|
gateway_apisix: "APISIX",
|
||||||
|
gateway_apisix_desc: "Provide APISIX monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
gateway_aws_api_gateway: "AWS API Gateway",
|
||||||
|
gateway_aws_api_gateway_desc: "Provide AWS Cloud API Gateway monitoring through AWS FireHose Receiver.",
|
||||||
|
// Database
|
||||||
|
database: "Database",
|
||||||
|
database_desc:
|
||||||
|
"The database is the organized collection of structured information, or data, typically stored electronically in a computer system.",
|
||||||
|
database_mysql_mariadb: "MySQL/MariaDB",
|
||||||
|
database_mysql_mariadb_desc:
|
||||||
|
"Provide MySQL and MariaDB Server monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_postgresql: "PostgreSQL",
|
||||||
|
database_postgresql_desc: "Provide PostgreSQL monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_dynamodb: "DynamoDB",
|
||||||
|
database_dynamodb_desc: "Provide DynamoDB monitoring through Amazon CloudWatch.",
|
||||||
|
database_redis: "Redis",
|
||||||
|
database_redis_desc: "Provide Redis monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_elasticsearch: "Elasticsearch",
|
||||||
|
database_elasticsearch_desc: "Provide Elasticsearch Server monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_mongodb: "MongoDB",
|
||||||
|
database_mongodb_desc: "Provide MongoDB monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
// Message Queue
|
||||||
|
mq: "Message Queue",
|
||||||
|
mq_desc:
|
||||||
|
"A message queue is a form of asynchronous service-to-service communication used in serverless and microservices architectures.",
|
||||||
|
mq_rabbitmq: "RabbitMQ",
|
||||||
|
mq_rabbitmq_desc: "Provide RabbitMQ monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
// self observability
|
||||||
|
self_observability: "Self Observability",
|
||||||
|
self_observability_desc:
|
||||||
|
"Self Observability provides the observabilities for running components and servers from the SkyWalking ecosystem.",
|
||||||
|
self_observability_oap: "SkyWalking Server",
|
||||||
|
self_observability_oap_desc:
|
||||||
|
"The OAP backend cluster itself is a distributed streaming process system, this is the monitoring for the OAP backend itself.",
|
||||||
|
self_observability_satellite: "Satellite",
|
||||||
|
self_observability_satellite_desc:
|
||||||
|
"Satellite: an open-source agent designed for the cloud-native infrastructures, which provides a low-cost, high-efficient, and more secure way to collect telemetry data. It is the recommended load balancer for telemetry collecting.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default titles;
|
124
src/locales/lang/menus/es.ts
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
const titles = {
|
||||||
|
// General Service
|
||||||
|
general_service: "Servicio General",
|
||||||
|
general_service_desc:
|
||||||
|
"Observar el servicio y las dependencias relativamente directas a través de los datos de telemetría recopilados del agente skywalking.",
|
||||||
|
general_service_services: "Servicios",
|
||||||
|
general_service_services_desc: "Observe services through telemetry data collected from SkyWalking Agent.",
|
||||||
|
general_service_virtual_database: "Base de Datos Virtual",
|
||||||
|
general_service_virtual_database_desc:
|
||||||
|
"Observe the virtual databases which are conjectured by language agents through various plugins.",
|
||||||
|
general_service_virtual_cache: "Caché virtual",
|
||||||
|
general_service_virtual_cache_desc:
|
||||||
|
"Observe the virtual cache servers which are conjectured by language agents through various plugins.",
|
||||||
|
general_service_virtual_mq: "MQ virtual",
|
||||||
|
general_service_virtual_mq_desc:
|
||||||
|
"Observe the virtual message queue servers which are conjectured by language agents through various plugins.",
|
||||||
|
// Service Mesh
|
||||||
|
service_mesh: "Malla de Servicios",
|
||||||
|
service_mesh_desc:
|
||||||
|
"La red de servicios (istio) resuelve los desafíos que enfrentan los desarrolladores y operadores a través de una arquitectura distribuida o de microservicio.",
|
||||||
|
service_mesh_service: "Servicios",
|
||||||
|
service_mesh_service_desc:
|
||||||
|
"Observe Service Mesh through telemetry data collected from Envoy Access Log Service (ALS).",
|
||||||
|
service_mesh_control_plane: "Plano de Control",
|
||||||
|
service_mesh_control_plane_desc: "Provide monitoring of the behavior of Istio through its self-monitoring metrics.",
|
||||||
|
service_mesh_data_plane: "Plano de Datos",
|
||||||
|
service_mesh_data_plane_desc: "Observe Envoy Proxy through Envoy Metrics Service.",
|
||||||
|
// Functions
|
||||||
|
functions: "Funciones",
|
||||||
|
functions_desc:
|
||||||
|
"FaaS (Function-as-a-Service) is a type of cloud-computing service that allows you to execute code in response to events without the complex infrastructure typically associated with building and launching microservices applications.",
|
||||||
|
functions_openfunction: "OpenFunction",
|
||||||
|
functions_openfunction_desc:
|
||||||
|
"OpenFunction as a FaaS platform, provides out-of-box observability with SkyWalking integration.",
|
||||||
|
// Kubernetes
|
||||||
|
kubernetes: "Kubernetes",
|
||||||
|
kubernetes_desc:
|
||||||
|
"Kubernetes is an open-source container orchestration system for automating software deployment, scaling, and management.",
|
||||||
|
kubernetes_cluster: "Cluster",
|
||||||
|
kubernetes_cluster_desc: "Provide monitoring of the status and resources of the K8S Cluster.",
|
||||||
|
kubernetes_service: "Servicio",
|
||||||
|
kubernetes_service_desc: "Observe Service status and resources from Kubernetes.",
|
||||||
|
// Infrastructure
|
||||||
|
infrastructure: "Infraestructura",
|
||||||
|
infrastructure_desc:
|
||||||
|
"Operation Systems act as the infrastructure of the whole IT system. Its observabilities provide the fundamentals for all distributed and modern complex systems running.",
|
||||||
|
infrastructure_linux: "Linux",
|
||||||
|
infrastructure_linux_desc: "Provide Linux Operation System(OS) monitoring.",
|
||||||
|
infrastructure_windows: "Windows",
|
||||||
|
infrastructure_windows_desc: "Provide Windows Operation System(OS) monitoring.",
|
||||||
|
// AWS Cloud
|
||||||
|
aws_cloud: "AWS Cloud",
|
||||||
|
aws_cloud_desc: "Amazon Web Services(AWS) offers reliable, scalable, and inexpensive cloud computing services.",
|
||||||
|
aws_cloud_eks: "EKS",
|
||||||
|
aws_cloud_eks_desc: "Provide AWS Cloud EKS monitoring through AWS Container Insights Receiver.",
|
||||||
|
aws_cloud_s3: "S3",
|
||||||
|
aws_cloud_s3_desc: "Provide AWS Cloud S3 monitoring through AWS FireHose Receiver.",
|
||||||
|
aws_cloud_dynamodb: "DynamoDB",
|
||||||
|
aws_cloud_dynamodb_desc: "Provide DynamoDB monitoring through Amazon CloudWatch.",
|
||||||
|
aws_cloud_api_gateway: "API Gateway",
|
||||||
|
aws_cloud_api_gateway_desc: "Provide AWS Cloud API Gateway monitoring through AWS FireHose Receiver.",
|
||||||
|
// Browser
|
||||||
|
browser: "Navegador",
|
||||||
|
browser_desc: "Provide Browser-Side monitoring of Web-App, Versions and Pages, through Apache SkyWalking Client JS.",
|
||||||
|
// Gateway
|
||||||
|
gateway: "Puerta",
|
||||||
|
gateway_desc:
|
||||||
|
"API gateway is an API management tool that sits between a client and a collection of backend services.",
|
||||||
|
gateway_apisix: "APISIX",
|
||||||
|
gateway_apisix_desc: "Provide APISIX monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
gateway_aws_api_gateway: "AWS API Gateway",
|
||||||
|
gateway_aws_api_gateway_desc: "Provide AWS Cloud API Gateway monitoring through AWS FireHose Receiver.",
|
||||||
|
// Database
|
||||||
|
database: "Base de Datos",
|
||||||
|
database_desc:
|
||||||
|
"The database is the organized collection of structured information, or data, typically stored electronically in a computer system.",
|
||||||
|
database_mysql_mariadb: "MySQL/MariaDB",
|
||||||
|
database_mysql_mariadb_desc:
|
||||||
|
"Provide MySQL and MariaDB Server monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_postgresql: "PostgreSQL",
|
||||||
|
database_postgresql_desc: "Provide PostgreSQL monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_dynamodb: "DynamoDB",
|
||||||
|
database_dynamodb_desc: "Provide DynamoDB monitoring through Amazon CloudWatch.",
|
||||||
|
database_redis: "Redis",
|
||||||
|
database_redis_desc: "Provide Redis monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_elasticsearch: "Elasticsearch",
|
||||||
|
database_elasticsearch_desc: "Provide Elasticsearch Server monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
database_mongodb: "MongoDB",
|
||||||
|
database_mongodb_desc: "Provide MongoDB monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
// Message Queue
|
||||||
|
mq: "Message Queue",
|
||||||
|
mq_desc:
|
||||||
|
"A message queue is a form of asynchronous service-to-service communication used in serverless and microservices architectures.",
|
||||||
|
mq_rabbitmq: "RabbitMQ",
|
||||||
|
mq_rabbitmq_desc: "Provide RabbitMQ monitoring through OpenTelemetry's Prometheus Receiver.",
|
||||||
|
// self observability
|
||||||
|
self_observability: "Self Observability",
|
||||||
|
self_observability_desc:
|
||||||
|
"Self Observability provides the observabilities for running components and servers from the SkyWalking ecosystem.",
|
||||||
|
self_observability_oap: "SkyWalking Server",
|
||||||
|
self_observability_oap_desc:
|
||||||
|
"The OAP backend cluster itself is a distributed streaming process system, this is the monitoring for the OAP backend itself.",
|
||||||
|
self_observability_satellite: "Satellite",
|
||||||
|
self_observability_satellite_desc:
|
||||||
|
"Satellite: an open-source agent designed for the cloud-native infrastructures, which provides a low-cost, high-efficient, and more secure way to collect telemetry data. It is the recommended load balancer for telemetry collecting.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default titles;
|
109
src/locales/lang/menus/zh.ts
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
const titles = {
|
||||||
|
// General Service
|
||||||
|
general_service: "常规服务",
|
||||||
|
general_service_desc: "通过从SkyWalking代理收集的遥测数据来观察服务和相对直接的依赖关系。",
|
||||||
|
general_service_services: "服务",
|
||||||
|
general_service_services_desc: "通过SkyWalking Agent收集的遥测数据观察服务。",
|
||||||
|
general_service_virtual_database: "虚拟数据库",
|
||||||
|
general_service_virtual_database_desc: "观察语言代理通过各种插件推测的虚拟数据库。",
|
||||||
|
general_service_virtual_cache: "虚拟缓存",
|
||||||
|
general_service_virtual_cache_desc: "观察语言代理通过各种插件推测的虚拟缓存服务器。",
|
||||||
|
general_service_virtual_mq: "虚拟消息队列",
|
||||||
|
general_service_virtual_mq_desc: "观察语言代理通过各种插件推测的虚拟消息队列服务器。",
|
||||||
|
// Service Mesh
|
||||||
|
service_mesh: "服务网格",
|
||||||
|
service_mesh_desc: "服务网格(Istio)通过分布式或微服务架构解决了开发人员和运营商面临的挑战。",
|
||||||
|
service_mesh_service: "服务",
|
||||||
|
service_mesh_service_desc: "通过从Envoy访问日志服务(ALS)收集的遥测数据观察服务网格。",
|
||||||
|
service_mesh_control_plane: "控制平面",
|
||||||
|
service_mesh_control_plane_desc: "通过Istio的自我监控指标提供对其行为的监控。",
|
||||||
|
service_mesh_data_plane: "数据平面",
|
||||||
|
service_mesh_data_plane_desc: "通过Envoy Metrics Service观察Envoy Proxy。",
|
||||||
|
// Functions
|
||||||
|
functions: "Functions",
|
||||||
|
functions_desc:
|
||||||
|
"FaaS(功能即服务)是一种云计算服务,允许您在没有通常与构建和启动微服务应用程序相关的复杂基础设施的情况下执行代码以响应事件。",
|
||||||
|
functions_openfunction: "OpenFunction",
|
||||||
|
functions_openfunction_desc: "OpenFunction作为一个FaaS平台,通过SkyWalking集成提供开箱即用的可观察性。",
|
||||||
|
// Kubernetes
|
||||||
|
kubernetes: "Kubernetes",
|
||||||
|
kubernetes_desc: "Kubernetes是一个开源的容器编排系统,用于自动化软件部署、扩展和管理。",
|
||||||
|
kubernetes_cluster: "集群",
|
||||||
|
kubernetes_cluster_desc: "提供对K8S集群的状态和资源的监控。",
|
||||||
|
kubernetes_service: "服务",
|
||||||
|
kubernetes_service_desc: "从Kubernetes中观察服务状态和资源。",
|
||||||
|
// Infrastructure
|
||||||
|
infrastructure: "基础设施",
|
||||||
|
infrastructure_desc: "操作系统是整个IT系统的基础设施。它的可观察性为所有分布式和现代复杂系统的运行提供了基础。",
|
||||||
|
infrastructure_linux: "Linux",
|
||||||
|
infrastructure_linux_desc: "提供Linux操作系统(OS)监控。",
|
||||||
|
infrastructure_windows: "Windows",
|
||||||
|
infrastructure_windows_desc: "提供Windows操作系统(OS)监控。",
|
||||||
|
// AWS Cloud
|
||||||
|
aws_cloud: "AWS云服务",
|
||||||
|
aws_cloud_desc: "亚马逊网络服务(AWS)提供可靠、可扩展且价格低廉的云计算服务。",
|
||||||
|
aws_cloud_eks: "EKS",
|
||||||
|
aws_cloud_eks_desc: "通过AWS Container Insights Receiver提供AWS Cloud EKS监控。",
|
||||||
|
aws_cloud_s3: "S3",
|
||||||
|
aws_cloud_s3_desc: "通过AWS FireHose Receiver提供AWS Cloud S3监控",
|
||||||
|
aws_cloud_dynamodb: "DynamoDB",
|
||||||
|
aws_cloud_dynamodb_desc: "通过AWS FireHose Receiver提供DynamoDB监控。",
|
||||||
|
aws_cloud_api_gateway: "API Gateway",
|
||||||
|
aws_cloud_api_gateway_desc: "通过AWS FireHose Receiver提供AWS Cloud API网关监控。",
|
||||||
|
// Browser
|
||||||
|
browser: "Browser",
|
||||||
|
browser_desc: "通过Apache SkyWalking Client JS提供Web应用程序、版本和页面的浏览器端监控。",
|
||||||
|
// Gateway
|
||||||
|
gateway: "网关",
|
||||||
|
gateway_desc: "API网关是位于客户端和后端服务集合之间的API管理工具。",
|
||||||
|
gateway_apisix: "APISIX",
|
||||||
|
gateway_apisix_desc: "通过OpenTelemetry的Prometheus接收器提供APISIX监控。",
|
||||||
|
gateway_aws_api_gateway: "AWS API Gateway",
|
||||||
|
gateway_aws_api_gateway_desc: "通过AWS FireHose Receiver提供AWS Cloud API网关监控。",
|
||||||
|
// Database
|
||||||
|
database: "数据库",
|
||||||
|
database_desc: "数据库是结构化信息或数据的有组织的集合,通常以电子方式存储在计算机系统中。",
|
||||||
|
database_mysql_mariadb: "MySQL/MariaDB",
|
||||||
|
database_mysql_mariadb_desc: "通过OpenTelemetry的Prometheus接收器提供MySQL和MariaDB服务器监控。",
|
||||||
|
database_postgresql: "PostgreSQL",
|
||||||
|
database_postgresql_desc: "通过OpenTelemetry的Prometheus接收器提供PostgreSQL监控。",
|
||||||
|
database_dynamodb: "DynamoDB",
|
||||||
|
database_dynamodb_desc: "通过AWS FireHose Receiver提供DynamoDB监控。",
|
||||||
|
database_redis: "Redis",
|
||||||
|
database_redis_desc: "通过OpenTelemetry的Prometheus接收器提供Redis监控。",
|
||||||
|
database_elasticsearch: "Elasticsearch",
|
||||||
|
database_elasticsearch_desc: "通过OpenTelemetry的Prometheus接收器提供Elasticsearch服务器监控。",
|
||||||
|
database_mongodb: "MongoDB",
|
||||||
|
database_mongodb_desc: "通过OpenTelemetry的Prometheus接收器提供MongoDB监控。",
|
||||||
|
// Message Queue
|
||||||
|
mq: "消息队列",
|
||||||
|
mq_desc: "消息队列是无服务器和微服务架构中使用的异步服务对服务通信的一种形式。",
|
||||||
|
mq_rabbitmq: "RabbitMQ",
|
||||||
|
mq_rabbitmq_desc: "通过OpenTelemetry的Prometheus接收器提供RabbitMQ监控。",
|
||||||
|
// self observability
|
||||||
|
self_observability: "自监控",
|
||||||
|
self_observability_desc: "自观察性为运行SkyWalking生态系统中的组件和服务器提供了可观察性。",
|
||||||
|
self_observability_oap: "SkyWalking服务",
|
||||||
|
self_observability_oap_desc: "OAP后端集群本身是一个分布式流处理系统,这是对OAP后端本身的监控。",
|
||||||
|
self_observability_satellite: "Satellite",
|
||||||
|
self_observability_satellite_desc:
|
||||||
|
"Satellite:为云原生基础设施设计的开源代理,提供了一种低成本、高效、更安全的遥测数据收集方式。它是遥测采集的推荐负载均衡器。",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default titles;
|
@@ -14,14 +14,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import zhTitles from "./menus/zh";
|
||||||
const msg = {
|
const msg = {
|
||||||
general: "普通服务",
|
...zhTitles,
|
||||||
services: "服务",
|
services: "服务",
|
||||||
traces: "跟踪",
|
traces: "跟踪",
|
||||||
metrics: "指标",
|
metrics: "指标",
|
||||||
serviceMesh: "服务网格",
|
|
||||||
infrastructure: "基础设施",
|
|
||||||
virtualMachine: "虚拟机",
|
|
||||||
dashboardNew: "新建仪表板",
|
dashboardNew: "新建仪表板",
|
||||||
dashboardHome: "仪表盘首页",
|
dashboardHome: "仪表盘首页",
|
||||||
dashboardList: "仪表盘列表",
|
dashboardList: "仪表盘列表",
|
||||||
@@ -32,14 +30,12 @@ const msg = {
|
|||||||
dashboards: "仪表盘",
|
dashboards: "仪表盘",
|
||||||
profiles: "性能剖析",
|
profiles: "性能剖析",
|
||||||
database: "数据库",
|
database: "数据库",
|
||||||
mySQL: "MySQL",
|
mySQL: "MySQL/MariaDB",
|
||||||
serviceName: "服务名称",
|
serviceName: "服务名称",
|
||||||
technologies: "技术",
|
technologies: "技术",
|
||||||
health: "健康",
|
health: "健康",
|
||||||
groupName: "群名称",
|
groupName: "群名称",
|
||||||
topologies: "拓扑图",
|
topologies: "拓扑图",
|
||||||
dataPanel: "数据平面",
|
|
||||||
controlPanel: "控制平面",
|
|
||||||
eventList: "事件列表",
|
eventList: "事件列表",
|
||||||
newDashboard: "新增仪表盘",
|
newDashboard: "新增仪表盘",
|
||||||
dashboardEdit: "编辑仪表盘",
|
dashboardEdit: "编辑仪表盘",
|
||||||
@@ -115,20 +111,9 @@ const msg = {
|
|||||||
rename: "重命名",
|
rename: "重命名",
|
||||||
deleteTitle: "确定删除吗?",
|
deleteTitle: "确定删除吗?",
|
||||||
rootTitle: "确定设置为Root吗?",
|
rootTitle: "确定设置为Root吗?",
|
||||||
selfObservability: "自监控",
|
|
||||||
satellite: "Satellite",
|
|
||||||
skyWalkingServer: "SkyWalking服务",
|
|
||||||
functions: "Functions",
|
|
||||||
linux: "Linux",
|
|
||||||
browser: "浏览器",
|
|
||||||
editWarning: "你正在进入编辑模式",
|
editWarning: "你正在进入编辑模式",
|
||||||
viewWarning: "你正在进入预览模式",
|
viewWarning: "你正在进入预览模式",
|
||||||
virtualDatabase: "虚拟数据库",
|
|
||||||
virtualCache: "虚拟缓存",
|
|
||||||
reloadDashboards: "重新加载仪表盘",
|
reloadDashboards: "重新加载仪表盘",
|
||||||
kubernetesService: "服务",
|
|
||||||
kubernetesCluster: "集群",
|
|
||||||
kubernetes: "Kubernetes",
|
|
||||||
textUrl: "文本超链接",
|
textUrl: "文本超链接",
|
||||||
textAlign: "文本对齐",
|
textAlign: "文本对齐",
|
||||||
metricLabel: "指标标签",
|
metricLabel: "指标标签",
|
||||||
@@ -153,9 +138,7 @@ const msg = {
|
|||||||
duplicateName: "重复的名称",
|
duplicateName: "重复的名称",
|
||||||
text: "文本",
|
text: "文本",
|
||||||
query: "查询",
|
query: "查询",
|
||||||
postgreSQL: "PostgreSQL",
|
|
||||||
endpointTips: "这里最多展示20条endpoints。",
|
endpointTips: "这里最多展示20条endpoints。",
|
||||||
apisix: "APISIX",
|
|
||||||
viewTrace: "查看相关Trace",
|
viewTrace: "查看相关Trace",
|
||||||
relatedTraceOptions: "相关的Trace选项",
|
relatedTraceOptions: "相关的Trace选项",
|
||||||
setLatencyDuration: "延迟相关指标",
|
setLatencyDuration: "延迟相关指标",
|
||||||
@@ -176,6 +159,13 @@ const msg = {
|
|||||||
when4xx: "当响应代码介于400和499之间时,带有跟踪的HTTP请求和响应示例",
|
when4xx: "当响应代码介于400和499之间时,带有跟踪的HTTP请求和响应示例",
|
||||||
when5xx: "当响应代码介于500和599之间时,带有跟踪的HTTP请求和响应示例",
|
when5xx: "当响应代码介于500和599之间时,带有跟踪的HTTP请求和响应示例",
|
||||||
taskTitle: "HTTP请求和响应收集规则",
|
taskTitle: "HTTP请求和响应收集规则",
|
||||||
|
iframeWidgetTip: "添加widget的链接",
|
||||||
|
iframeSrc: "Iframe链接",
|
||||||
|
generateLink: "生成链接",
|
||||||
|
setDuration: "锁定查询持续时间",
|
||||||
|
openFunction: "OpenFunction",
|
||||||
|
period: "周期",
|
||||||
|
windows: "Windows",
|
||||||
seconds: "秒",
|
seconds: "秒",
|
||||||
hourTip: "选择小时",
|
hourTip: "选择小时",
|
||||||
minuteTip: "选择分钟",
|
minuteTip: "选择分钟",
|
||||||
@@ -194,7 +184,7 @@ const msg = {
|
|||||||
trace: "追踪",
|
trace: "追踪",
|
||||||
alarm: "告警",
|
alarm: "告警",
|
||||||
event: "事件",
|
event: "事件",
|
||||||
auto: "自动",
|
auto: "自动更新",
|
||||||
reload: "刷新",
|
reload: "刷新",
|
||||||
editmode: "编辑模式",
|
editmode: "编辑模式",
|
||||||
version: "版本",
|
version: "版本",
|
||||||
@@ -276,18 +266,14 @@ const msg = {
|
|||||||
aggregation: "计算",
|
aggregation: "计算",
|
||||||
unit: "单位",
|
unit: "单位",
|
||||||
labelsIndex: "标签下标",
|
labelsIndex: "标签下标",
|
||||||
group: "服务组",
|
|
||||||
browserView: "浏览器视图",
|
browserView: "浏览器视图",
|
||||||
sortOrder: "排序方式",
|
sortOrder: "排序方式",
|
||||||
chartType: "图表类型",
|
chartType: "图表类型",
|
||||||
currentDepth: "当前深度",
|
currentDepth: "当前深度",
|
||||||
defaultDepth: "默认深度",
|
defaultDepth: "默认深度",
|
||||||
traceTagsTip:
|
traceTagsTip: "只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
||||||
"只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
logTagsTip: "只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
||||||
logTagsTip:
|
alarmTagsTip: "只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
||||||
"只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
|
||||||
alarmTagsTip:
|
|
||||||
"只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
|
||||||
tagsLink: "配置词汇页",
|
tagsLink: "配置词汇页",
|
||||||
addTag: "请添加标签",
|
addTag: "请添加标签",
|
||||||
logCategory: "日志类别",
|
logCategory: "日志类别",
|
||||||
@@ -310,8 +296,7 @@ const msg = {
|
|||||||
contentType: "内容类型",
|
contentType: "内容类型",
|
||||||
content: "内容",
|
content: "内容",
|
||||||
viewLogs: "查看日志",
|
viewLogs: "查看日志",
|
||||||
logsTagsTip:
|
logsTagsTip: "只有core/default/searchableLogsTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
||||||
"只有core/default/searchableLogsTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
|
|
||||||
keywordsOfContentLogTips: "SkyWalking OAP服务器的当前存储不支持此操作",
|
keywordsOfContentLogTips: "SkyWalking OAP服务器的当前存储不支持此操作",
|
||||||
setEvent: "设置事件",
|
setEvent: "设置事件",
|
||||||
viewAttributes: "查看",
|
viewAttributes: "查看",
|
||||||
@@ -368,10 +353,32 @@ const msg = {
|
|||||||
addKeywordsOfContent: "请输入一个内容关键词",
|
addKeywordsOfContent: "请输入一个内容关键词",
|
||||||
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
|
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
|
||||||
noticeTag: "请输入一个标签(key=value)之后回车",
|
noticeTag: "请输入一个标签(key=value)之后回车",
|
||||||
conditionNotice:
|
conditionNotice: "请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
||||||
"请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
|
||||||
language: "语言",
|
language: "语言",
|
||||||
gateway: "网关",
|
save: "保存",
|
||||||
virtualMQ: "虚拟消息队列",
|
editStrategy: "编辑策略",
|
||||||
|
policyList: "策略列表",
|
||||||
|
targetTypes: "目标类型",
|
||||||
|
monitorType: "监视器类型",
|
||||||
|
count: "总数",
|
||||||
|
threshold: "阈值",
|
||||||
|
uriRegex: "URI规则",
|
||||||
|
uriList: "URI列表",
|
||||||
|
processes: "进程",
|
||||||
|
attributes: "属性",
|
||||||
|
monitorInstances: "监视实例",
|
||||||
|
processDashboards: "进程仪表板",
|
||||||
|
instanceDashboards: "实例仪表板",
|
||||||
|
detailLabel: "详细标签",
|
||||||
|
summary: "概括",
|
||||||
|
detail: "详细",
|
||||||
|
marketplace: "市场",
|
||||||
|
menusManagement: "菜单",
|
||||||
|
saveReload: "保存并重新加载页面",
|
||||||
|
document: "文档",
|
||||||
|
metricMode: "指标模式",
|
||||||
|
addExpressions: "添加表达式",
|
||||||
|
expressions: "表达式",
|
||||||
|
unhealthyExpression: "非健康表达式",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -16,12 +16,12 @@
|
|||||||
*/
|
*/
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
|
||||||
import { store } from "./store";
|
import { store } from "./store";
|
||||||
import components from "@/components";
|
import components from "@/components";
|
||||||
import i18n from "./locales";
|
import i18n from "./locales";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import "./styles/index.ts";
|
import "./styles/index.ts";
|
||||||
|
import "virtual:svg-icons-register";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
@@ -32,6 +32,9 @@ app.use(store);
|
|||||||
mountApp();
|
mountApp();
|
||||||
|
|
||||||
async function mountApp() {
|
async function mountApp() {
|
||||||
|
await appStore.getActivateMenus();
|
||||||
await appStore.queryOAPTimeInfo();
|
await appStore.queryOAPTimeInfo();
|
||||||
app.use(router).mount("#app");
|
|
||||||
|
const router = await import("./router");
|
||||||
|
app.use(router.default).mount("#app");
|
||||||
}
|
}
|
||||||
|
@@ -14,34 +14,37 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import Mock from "mockjs";
|
||||||
|
|
||||||
export default [
|
const Random = Mock.Random;
|
||||||
{
|
const nodes = Mock.mock({
|
||||||
path: "",
|
"nodes|500": [
|
||||||
name: "Gateway",
|
{
|
||||||
meta: {
|
//id
|
||||||
title: "gateway",
|
id: "@guid",
|
||||||
icon: "gateway",
|
name: "@name",
|
||||||
hasGroup: true,
|
"type|1": ["ActiveMQ", "activemq-consumer", "H2", "APISIX", "Express", "USER", "Flash"],
|
||||||
|
"isReal|1": [true, false],
|
||||||
},
|
},
|
||||||
redirect: "/apisix",
|
],
|
||||||
children: [
|
});
|
||||||
{
|
const calls = Mock.mock({
|
||||||
path: "/apisix",
|
"links|500": [
|
||||||
name: "APISIX",
|
{
|
||||||
meta: {
|
//id
|
||||||
title: "apisix",
|
id: "@guid",
|
||||||
layer: "APISIX",
|
detectPoints: ["SERVER", "CLIENT"],
|
||||||
},
|
source: function () {
|
||||||
|
const d = Random.integer(0, 250);
|
||||||
|
return nodes.nodes[d].id;
|
||||||
},
|
},
|
||||||
{
|
target: function () {
|
||||||
path: "/apisix/tab/:activeTabIndex",
|
const d = Random.integer(250, 499);
|
||||||
name: "APISIXActiveTabIndex",
|
return nodes.nodes[d].id;
|
||||||
meta: {
|
|
||||||
notShow: true,
|
|
||||||
layer: "APISIX",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
},
|
],
|
||||||
];
|
});
|
||||||
|
const callsMock = calls.links;
|
||||||
|
const nodesMock = nodes.nodes;
|
||||||
|
export { callsMock, nodesMock };
|