mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-02 02:04:13 +00:00
build: migrate the build tool from vue-cli to vite4 (#208)
This commit is contained in:
parent
1e0c253488
commit
44dcb1e7f6
33
.eslintignore
Normal file
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
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",
|
||||||
|
},
|
||||||
|
};
|
2
.github/workflows/nodejs.yml
vendored
2
.github/workflows/nodejs.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [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 }}
|
||||||
|
33
.gitignore
vendored
33
.gitignore
vendored
@ -16,24 +16,39 @@
|
|||||||
# 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_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
27
.husky/commit-msg
Executable 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
|
||||||
|
|
||||||
|
# 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
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
29
.husky/pre-commit
Executable 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
. "$(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
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/*
|
50
commitlint.config.js
Normal file
50
commitlint.config.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* 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 = {
|
||||||
|
ignores: [(commit) => commit.includes("init")],
|
||||||
|
extends: ["@commitlint/config-conventional"],
|
||||||
|
rules: {
|
||||||
|
"body-leading-blank": [2, "always"],
|
||||||
|
"footer-leading-blank": [1, "always"],
|
||||||
|
"header-max-length": [2, "always", 108],
|
||||||
|
"subject-empty": [2, "never"],
|
||||||
|
"type-empty": [2, "never"],
|
||||||
|
"subject-case": [0],
|
||||||
|
"type-enum": [
|
||||||
|
2,
|
||||||
|
"always",
|
||||||
|
[
|
||||||
|
"feat",
|
||||||
|
"fix",
|
||||||
|
"perf",
|
||||||
|
"style",
|
||||||
|
"docs",
|
||||||
|
"test",
|
||||||
|
"refactor",
|
||||||
|
"build",
|
||||||
|
"ci",
|
||||||
|
"chore",
|
||||||
|
"revert",
|
||||||
|
"wip",
|
||||||
|
"workflow",
|
||||||
|
"types",
|
||||||
|
"release",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
25
cypress.config.ts
Normal file
25
cypress.config.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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 { defineConfig } from "cypress";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
e2e: {
|
||||||
|
specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}",
|
||||||
|
baseUrl: "http://localhost:4173",
|
||||||
|
},
|
||||||
|
});
|
@ -14,6 +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.
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
describe("My First Test", () => {
|
||||||
presets: ["@vue/cli-plugin-babel/preset"],
|
it("visits the app root url", () => {
|
||||||
};
|
cy.visit("/");
|
||||||
|
cy.contains("h1", "You did it!");
|
||||||
|
});
|
||||||
|
});
|
26
cypress/e2e/tsconfig.json
Normal file
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"]
|
||||||
|
}
|
||||||
|
}
|
9
src/assets/icons/index.ts → cypress/fixtures/example.json
Executable file → Normal file
9
src/assets/icons/index.ts → cypress/fixtures/example.json
Executable file → Normal file
@ -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.
|
||||||
*/
|
*/
|
||||||
const requireAll = (requireContext: Recordable) =>
|
{
|
||||||
requireContext.keys().map(requireContext);
|
"name": "Using fixtures to represent data",
|
||||||
const req = require.context("./", true, /\.svg$/);
|
"email": "hello@cypress.io",
|
||||||
requireAll(req);
|
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||||
|
}
|
55
cypress/support/commands.ts
Normal file
55
cypress/support/commands.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* 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="cypress" />
|
||||||
|
// ***********************************************
|
||||||
|
// This example commands.ts shows you how to
|
||||||
|
// create various custom commands and overwrite
|
||||||
|
// existing commands.
|
||||||
|
//
|
||||||
|
// For more comprehensive examples of custom
|
||||||
|
// commands please read more here:
|
||||||
|
// https://on.cypress.io/custom-commands
|
||||||
|
// ***********************************************
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a parent command --
|
||||||
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a child command --
|
||||||
|
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a dual command --
|
||||||
|
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This will overwrite an existing command --
|
||||||
|
// 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 {};
|
37
cypress/support/e2e.ts
Normal file
37
cypress/support/e2e.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ***********************************************************
|
||||||
|
// This example support/index.js is processed and
|
||||||
|
// loaded automatically before your test files.
|
||||||
|
//
|
||||||
|
// This is a great place to put global configuration and
|
||||||
|
// behavior that modifies Cypress.
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off
|
||||||
|
// automatically serving support files with the
|
||||||
|
// 'supportFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/configuration
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// Import commands.js using ES2015 syntax:
|
||||||
|
import "./commands";
|
||||||
|
|
||||||
|
// Alternatively you can use CommonJS syntax:
|
||||||
|
// require('./commands')
|
26
env.d.ts
vendored
Normal file
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>
|
50727
package-lock.json
generated
50727
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
151
package.json
151
package.json
@ -1,13 +1,20 @@
|
|||||||
{
|
{
|
||||||
"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"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
@ -17,132 +24,76 @@
|
|||||||
"echarts": "^5.2.2",
|
"echarts": "^5.2.2",
|
||||||
"element-plus": "^2.0.2",
|
"element-plus": "^2.0.2",
|
||||||
"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.3.0",
|
||||||
|
"@commitlint/config-conventional": "^17.3.0",
|
||||||
|
"@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",
|
|
||||||
"babel-jest": "^24.9.0",
|
|
||||||
"eslint": "^6.7.2",
|
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
|
||||||
"eslint-plugin-vue": "^7.0.0",
|
|
||||||
"husky": "^7.0.4",
|
|
||||||
"lint-staged": "^12.1.3",
|
"lint-staged": "^12.1.3",
|
||||||
"monaco-editor-webpack-plugin": "^4.1.2",
|
"node-sass": "^8.0.0",
|
||||||
"node-sass": "^6.0.1",
|
"npm-run-all": "^4.1.5",
|
||||||
"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",
|
||||||
|
"start-server-and-test": "^1.15.2",
|
||||||
"stylelint": "^14.1.0",
|
"stylelint": "^14.1.0",
|
||||||
"stylelint-config-html": "^1.0.0",
|
"stylelint-config-html": "^1.0.0",
|
||||||
"stylelint-config-prettier": "^9.0.3",
|
"stylelint-config-prettier": "^9.0.3",
|
||||||
"stylelint-config-standard": "^24.0.0",
|
"stylelint-config-standard": "^24.0.0",
|
||||||
"stylelint-order": "^5.0.0",
|
"stylelint-order": "^5.0.0",
|
||||||
"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.0",
|
||||||
|
"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,scss,less}": [
|
||||||
"eslint --fix",
|
"eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||||
"prettier --write"
|
"prettier --write \"src/**/*.{js,tsx,css,less,scss,vue,html,md}\"",
|
||||||
],
|
"stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/"
|
||||||
"*.vue": [
|
|
||||||
"eslint --fix",
|
|
||||||
"prettier --write",
|
|
||||||
"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
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",
|
||||||
|
};
|
@ -16,10 +16,10 @@ limitations under the License. -->
|
|||||||
<router-view />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
<style>
|
<style>
|
||||||
#app {
|
#app {
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 1024px;
|
min-width: 1024px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -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 { [key: string]: any })[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 { [key: string]: any })[filePath].default;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,35 +15,18 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div :class="`${state.pre}`">
|
<div :class="`${state.pre}`">
|
||||||
<div :class="`${state.pre}-head`">
|
<div :class="`${state.pre}-head`">
|
||||||
<a
|
<a :class="`${state.pre}-prev-decade-btn`" v-show="state.showYears" @click="state.year -= 10">
|
||||||
:class="`${state.pre}-prev-decade-btn`"
|
|
||||||
v-show="state.showYears"
|
|
||||||
@click="state.year -= 10"
|
|
||||||
>
|
|
||||||
<Icon size="sm" iconName="angle-double-left" />
|
<Icon size="sm" iconName="angle-double-left" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a :class="`${state.pre}-prev-year-btn`" v-show="!state.showYears" @click="state.year--">
|
||||||
:class="`${state.pre}-prev-year-btn`"
|
|
||||||
v-show="!state.showYears"
|
|
||||||
@click="state.year--"
|
|
||||||
>
|
|
||||||
<Icon size="sm" iconName="angle-double-left" />
|
<Icon size="sm" iconName="angle-double-left" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a :class="`${state.pre}-prev-month-btn`" v-show="!state.showYears && !state.showMonths" @click="pm">
|
||||||
:class="`${state.pre}-prev-month-btn`"
|
|
||||||
v-show="!state.showYears && !state.showMonths"
|
|
||||||
@click="pm"
|
|
||||||
>
|
|
||||||
<Icon size="middle" iconName="chevron-left" />
|
<Icon size="middle" iconName="chevron-left" />
|
||||||
</a>
|
</a>
|
||||||
<a :class="`${state.pre}-year-select`" v-show="state.showYears">{{
|
<a :class="`${state.pre}-year-select`" v-show="state.showYears">{{ ys + "-" + ye }}</a>
|
||||||
ys + "-" + ye
|
|
||||||
}}</a>
|
|
||||||
<template v-if="local.yearSuffix">
|
<template v-if="local.yearSuffix">
|
||||||
<a
|
<a :class="`${state.pre}-year-select`" @click="state.showYears = !state.showYears" v-show="!state.showYears"
|
||||||
:class="`${state.pre}-year-select`"
|
|
||||||
@click="state.showYears = !state.showYears"
|
|
||||||
v-show="!state.showYears"
|
|
||||||
>{{ state.year }}{{ local.yearSuffix }}</a
|
>{{ state.year }}{{ local.yearSuffix }}</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@ -60,54 +43,29 @@ limitations under the License. -->
|
|||||||
v-show="!state.showYears && !state.showMonths"
|
v-show="!state.showYears && !state.showMonths"
|
||||||
>{{ local.monthsHead[state.month] }}</a
|
>{{ local.monthsHead[state.month] }}</a
|
||||||
>
|
>
|
||||||
<a
|
<a :class="`${state.pre}-year-select`" @click="state.showYears = !state.showYears" v-show="!state.showYears">{{
|
||||||
:class="`${state.pre}-year-select`"
|
state.year
|
||||||
@click="state.showYears = !state.showYears"
|
}}</a>
|
||||||
v-show="!state.showYears"
|
|
||||||
>{{ state.year }}</a
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
<a
|
<a :class="`${state.pre}-next-month-btn`" v-show="!state.showYears && !state.showMonths" @click="nm">
|
||||||
:class="`${state.pre}-next-month-btn`"
|
|
||||||
v-show="!state.showYears && !state.showMonths"
|
|
||||||
@click="nm"
|
|
||||||
>
|
|
||||||
<Icon size="middle" iconName="chevron-right" />
|
<Icon size="middle" iconName="chevron-right" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a :class="`${state.pre}-next-year-btn`" v-show="!state.showYears" @click="state.year++">
|
||||||
:class="`${state.pre}-next-year-btn`"
|
|
||||||
v-show="!state.showYears"
|
|
||||||
@click="state.year++"
|
|
||||||
>
|
|
||||||
<Icon size="sm" iconName="angle-double-right" />
|
<Icon size="sm" iconName="angle-double-right" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a :class="`${state.pre}-next-decade-btn`" v-show="state.showYears" @click="state.year += 10">
|
||||||
:class="`${state.pre}-next-decade-btn`"
|
|
||||||
v-show="state.showYears"
|
|
||||||
@click="state.year += 10"
|
|
||||||
>
|
|
||||||
<Icon size="sm" iconName="angle-double-right" />
|
<Icon size="sm" iconName="angle-double-right" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div :class="`${state.pre}-body`">
|
<div :class="`${state.pre}-body`">
|
||||||
<div :class="`${state.pre}-days`">
|
<div :class="`${state.pre}-days`">
|
||||||
<a :class="`${state.pre}-week`" v-for="i in local.weeks" :key="i">{{
|
<a :class="`${state.pre}-week`" v-for="i in local.weeks" :key="i">{{ i }}</a>
|
||||||
i
|
|
||||||
}}</a>
|
|
||||||
<a
|
<a
|
||||||
v-for="(j, i) in days"
|
v-for="(j, i) in days"
|
||||||
@click="is($event) && ((state.day = j.i), ok(j))"
|
@click="is($event) && ((state.day = j.i), ok(j))"
|
||||||
:class="[
|
:class="[
|
||||||
j.p || j.n ? `${state.pre}-date-out` : '',
|
j.p || j.n ? `${state.pre}-date-out` : '',
|
||||||
status(
|
status(j.y, j.m, j.i, state.hour, state.minute, state.second, 'YYYYMMDD'),
|
||||||
j.y,
|
|
||||||
j.m,
|
|
||||||
j.i,
|
|
||||||
state.hour,
|
|
||||||
state.minute,
|
|
||||||
state.second,
|
|
||||||
'YYYYMMDD'
|
|
||||||
),
|
|
||||||
]"
|
]"
|
||||||
:key="i"
|
:key="i"
|
||||||
>{{ j.i }}</a
|
>{{ j.i }}</a
|
||||||
@ -116,23 +74,8 @@ limitations under the License. -->
|
|||||||
<div :class="`${state.pre}-months`" v-show="state.showMonths">
|
<div :class="`${state.pre}-months`" v-show="state.showMonths">
|
||||||
<a
|
<a
|
||||||
v-for="(i, j) in local.months"
|
v-for="(i, j) in local.months"
|
||||||
@click="
|
@click="is($event) && ((state.showMonths = state.m === 'M'), (state.month = j), state.m === 'M' && ok('m'))"
|
||||||
is($event) &&
|
:class="[status(state.year, j, state.day, state.hour, state.minute, state.second, 'YYYYMM')]"
|
||||||
((state.showMonths = state.m === 'M'),
|
|
||||||
(state.month = j),
|
|
||||||
state.m === 'M' && ok('m'))
|
|
||||||
"
|
|
||||||
:class="[
|
|
||||||
status(
|
|
||||||
state.year,
|
|
||||||
j,
|
|
||||||
state.day,
|
|
||||||
state.hour,
|
|
||||||
state.minute,
|
|
||||||
state.second,
|
|
||||||
'YYYYMM'
|
|
||||||
),
|
|
||||||
]"
|
|
||||||
:key="j"
|
:key="j"
|
||||||
>{{ i }}</a
|
>{{ i }}</a
|
||||||
>
|
>
|
||||||
@ -140,23 +83,10 @@ limitations under the License. -->
|
|||||||
<div :class="`${state.pre}-years`" v-show="state.showYears">
|
<div :class="`${state.pre}-years`" v-show="state.showYears">
|
||||||
<a
|
<a
|
||||||
v-for="(i, j) in years"
|
v-for="(i, j) in years"
|
||||||
@click="
|
@click="is($event) && ((state.showYears = state.m === 'Y'), (state.year = i), state.m === 'Y' && ok('y'))"
|
||||||
is($event) &&
|
|
||||||
((state.showYears = state.m === 'Y'),
|
|
||||||
(state.year = i),
|
|
||||||
state.m === 'Y' && ok('y'))
|
|
||||||
"
|
|
||||||
:class="[
|
:class="[
|
||||||
j === 0 || j === 11 ? `${state.pre}-date-out` : '',
|
j === 0 || j === 11 ? `${state.pre}-date-out` : '',
|
||||||
status(
|
status(i, state.month, state.day, state.hour, state.minute, state.second, 'YYYY'),
|
||||||
i,
|
|
||||||
state.month,
|
|
||||||
state.day,
|
|
||||||
state.hour,
|
|
||||||
state.minute,
|
|
||||||
state.second,
|
|
||||||
'YYYY'
|
|
||||||
),
|
|
||||||
]"
|
]"
|
||||||
:key="j"
|
:key="j"
|
||||||
>{{ i }}</a
|
>{{ i }}</a
|
||||||
@ -167,21 +97,8 @@ limitations under the License. -->
|
|||||||
<div class="scroll_hide calendar-overflow">
|
<div class="scroll_hide calendar-overflow">
|
||||||
<a
|
<a
|
||||||
v-for="(j, i) in 24"
|
v-for="(j, i) in 24"
|
||||||
@click="
|
@click="is($event) && ((state.showHours = false), (state.hour = i), ok('h'))"
|
||||||
is($event) &&
|
:class="[status(state.year, state.month, state.day, i, state.minute, state.second, 'YYYYMMDDHH')]"
|
||||||
((state.showHours = false), (state.hour = i), ok('h'))
|
|
||||||
"
|
|
||||||
:class="[
|
|
||||||
status(
|
|
||||||
state.year,
|
|
||||||
state.month,
|
|
||||||
state.day,
|
|
||||||
i,
|
|
||||||
state.minute,
|
|
||||||
state.second,
|
|
||||||
'YYYYMMDDHH'
|
|
||||||
),
|
|
||||||
]"
|
|
||||||
:key="i"
|
:key="i"
|
||||||
>{{ i }}</a
|
>{{ i }}</a
|
||||||
>
|
>
|
||||||
@ -192,21 +109,8 @@ limitations under the License. -->
|
|||||||
<div class="scroll_hide calendar-overflow">
|
<div class="scroll_hide calendar-overflow">
|
||||||
<a
|
<a
|
||||||
v-for="(j, i) in 60"
|
v-for="(j, i) in 60"
|
||||||
@click="
|
@click="is($event) && ((state.showMinutes = false), (state.minute = i), ok('h'))"
|
||||||
is($event) &&
|
:class="[status(state.year, state.month, state.day, state.hour, i, state.second, 'YYYYMMDDHHmm')]"
|
||||||
((state.showMinutes = false), (state.minute = i), ok('h'))
|
|
||||||
"
|
|
||||||
:class="[
|
|
||||||
status(
|
|
||||||
state.year,
|
|
||||||
state.month,
|
|
||||||
state.day,
|
|
||||||
state.hour,
|
|
||||||
i,
|
|
||||||
state.second,
|
|
||||||
'YYYYMMDDHHmm'
|
|
||||||
),
|
|
||||||
]"
|
|
||||||
:key="i"
|
:key="i"
|
||||||
>{{ i }}</a
|
>{{ i }}</a
|
||||||
>
|
>
|
||||||
@ -217,21 +121,8 @@ limitations under the License. -->
|
|||||||
<div class="scroll_hide calendar-overflow">
|
<div class="scroll_hide calendar-overflow">
|
||||||
<a
|
<a
|
||||||
v-for="(j, i) in 60"
|
v-for="(j, i) in 60"
|
||||||
@click="
|
@click="is($event) && ((state.showSeconds = false), (state.second = i), ok('h'))"
|
||||||
is($event) &&
|
:class="[status(state.year, state.month, state.day, state.hour, state.minute, i, 'YYYYMMDDHHmmss')]"
|
||||||
((state.showSeconds = false), (state.second = i), ok('h'))
|
|
||||||
"
|
|
||||||
:class="[
|
|
||||||
status(
|
|
||||||
state.year,
|
|
||||||
state.month,
|
|
||||||
state.day,
|
|
||||||
state.hour,
|
|
||||||
state.minute,
|
|
||||||
i,
|
|
||||||
'YYYYMMDDHHmmss'
|
|
||||||
),
|
|
||||||
]"
|
|
||||||
:key="i"
|
:key="i"
|
||||||
>{{ i }}</a
|
>{{ i }}</a
|
||||||
>
|
>
|
||||||
@ -242,20 +133,14 @@ limitations under the License. -->
|
|||||||
<div :class="`${state.pre}-hour`">
|
<div :class="`${state.pre}-hour`">
|
||||||
<a
|
<a
|
||||||
:title="local.hourTip"
|
:title="local.hourTip"
|
||||||
@click="
|
@click="(state.showHours = !state.showHours), (state.showMinutes = state.showSeconds = false)"
|
||||||
(state.showHours = !state.showHours),
|
|
||||||
(state.showMinutes = state.showSeconds = false)
|
|
||||||
"
|
|
||||||
:class="{ on: state.showHours }"
|
:class="{ on: state.showHours }"
|
||||||
>{{ dd(state.hour) }}</a
|
>{{ dd(state.hour) }}</a
|
||||||
>
|
>
|
||||||
<span>:</span>
|
<span>:</span>
|
||||||
<a
|
<a
|
||||||
:title="local.minuteTip"
|
:title="local.minuteTip"
|
||||||
@click="
|
@click="(state.showMinutes = !state.showMinutes), (state.showHours = state.showSeconds = false)"
|
||||||
(state.showMinutes = !state.showMinutes),
|
|
||||||
(state.showHours = state.showSeconds = false)
|
|
||||||
"
|
|
||||||
:class="{ on: state.showMinutes }"
|
:class="{ on: state.showMinutes }"
|
||||||
>{{ dd(state.minute) }}</a
|
>{{ dd(state.minute) }}</a
|
||||||
>
|
>
|
||||||
@ -263,10 +148,7 @@ limitations under the License. -->
|
|||||||
<span>:</span>
|
<span>:</span>
|
||||||
<a
|
<a
|
||||||
:title="local.secondTip"
|
:title="local.secondTip"
|
||||||
@click="
|
@click="(state.showSeconds = !state.showSeconds), (state.showHours = state.showMinutes = false)"
|
||||||
(state.showSeconds = !state.showSeconds),
|
|
||||||
(state.showHours = state.showMinutes = false)
|
|
||||||
"
|
|
||||||
:class="{ on: state.showSeconds }"
|
:class="{ on: state.showSeconds }"
|
||||||
>{{ dd(state.second) }}</a
|
>{{ dd(state.second) }}</a
|
||||||
>
|
>
|
||||||
@ -277,13 +159,13 @@ limitations under the License. -->
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, watch, reactive } from "vue";
|
import { computed, onMounted, watch, reactive } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
/*global defineProps, defineEmits */
|
/*global defineProps, defineEmits */
|
||||||
const emit = defineEmits(["input", "setDates", "ok"]);
|
const emit = defineEmits(["input", "setDates", "ok"]);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
value: { type: Date },
|
value: { type: Date },
|
||||||
left: { type: Boolean, default: false },
|
left: { type: Boolean, default: false },
|
||||||
right: { type: Boolean, default: false },
|
right: { type: Boolean, default: false },
|
||||||
@ -293,8 +175,8 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: "YYYY-MM-DD",
|
default: "YYYY-MM-DD",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
pre: "",
|
pre: "",
|
||||||
m: "",
|
m: "",
|
||||||
showYears: false,
|
showYears: false,
|
||||||
@ -308,8 +190,8 @@ const state = reactive({
|
|||||||
hour: 0,
|
hour: 0,
|
||||||
minute: 0,
|
minute: 0,
|
||||||
second: 0,
|
second: 0,
|
||||||
});
|
});
|
||||||
const get = (time: Date): { [key: string]: any } => {
|
const get = (time: Date): { [key: string]: any } => {
|
||||||
return {
|
return {
|
||||||
year: time.getFullYear(),
|
year: time.getFullYear(),
|
||||||
month: time.getMonth(),
|
month: time.getMonth(),
|
||||||
@ -318,8 +200,8 @@ const get = (time: Date): { [key: string]: any } => {
|
|||||||
minute: time.getMinutes(),
|
minute: time.getMinutes(),
|
||||||
second: time.getSeconds(),
|
second: time.getSeconds(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (props.value) {
|
if (props.value) {
|
||||||
const time = get(props.value);
|
const time = get(props.value);
|
||||||
state.pre = "calendar";
|
state.pre = "calendar";
|
||||||
state.m = "D";
|
state.m = "D";
|
||||||
@ -334,8 +216,8 @@ if (props.value) {
|
|||||||
state.hour = time.hour;
|
state.hour = time.hour;
|
||||||
state.minute = time.minute;
|
state.minute = time.minute;
|
||||||
state.second = time.second;
|
state.second = time.second;
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(val: Date | undefined) => {
|
(val: Date | undefined) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
@ -348,32 +230,32 @@ watch(
|
|||||||
state.hour = time.hour;
|
state.hour = time.hour;
|
||||||
state.minute = time.minute;
|
state.minute = time.minute;
|
||||||
state.second = time.second;
|
state.second = time.second;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
const parse = (num: number): number => {
|
const parse = (num: number): number => {
|
||||||
return num / 100000;
|
return num / 100000;
|
||||||
};
|
};
|
||||||
const start = computed(() => {
|
const start = computed(() => {
|
||||||
return parse(Number(props.dates[0]));
|
return parse(Number(props.dates[0]));
|
||||||
});
|
});
|
||||||
const end = computed(() => {
|
const end = computed(() => {
|
||||||
return parse(Number(props.dates[1]));
|
return parse(Number(props.dates[1]));
|
||||||
});
|
});
|
||||||
const ys = computed(() => {
|
const ys = computed(() => {
|
||||||
return Math.floor(state.year / 10) * 10;
|
return Math.floor(state.year / 10) * 10;
|
||||||
});
|
});
|
||||||
const ye = computed(() => {
|
const ye = computed(() => {
|
||||||
return ys.value + 10;
|
return ys.value + 10;
|
||||||
});
|
});
|
||||||
const years = computed(() => {
|
const years = computed(() => {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
let start = ys.value - 1;
|
let start = ys.value - 1;
|
||||||
while (arr.length < 12) {
|
while (arr.length < 12) {
|
||||||
arr.push((start += 1));
|
arr.push((start += 1));
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
});
|
});
|
||||||
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
|
||||||
@ -392,8 +274,8 @@ const local = computed(() => {
|
|||||||
weekCutTip: t("weekCutTip"),
|
weekCutTip: t("weekCutTip"),
|
||||||
monthCutTip: t("monthCutTip"),
|
monthCutTip: t("monthCutTip"),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const days = computed(() => {
|
const days = computed(() => {
|
||||||
const days = [];
|
const days = [];
|
||||||
const year = state.year;
|
const year = state.year;
|
||||||
const month = state.month;
|
const month = state.month;
|
||||||
@ -431,26 +313,19 @@ const days = computed(() => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return days;
|
return days;
|
||||||
});
|
});
|
||||||
const dd = (val: number) => ("0" + val).slice(-2);
|
const dd = (val: number) => ("0" + val).slice(-2);
|
||||||
const status = (
|
const status = (
|
||||||
year: number,
|
year: number,
|
||||||
month: number,
|
month: number,
|
||||||
day: number,
|
day: number,
|
||||||
hour: number,
|
hour: number,
|
||||||
minute: number,
|
minute: number,
|
||||||
second: number,
|
second: number,
|
||||||
format: string
|
format: string,
|
||||||
) => {
|
) => {
|
||||||
const maxDay = new Date(year, month + 1, 0).getDate();
|
const maxDay = new Date(year, month + 1, 0).getDate();
|
||||||
const time: any = new Date(
|
const time: any = new Date(year, month, day > maxDay ? maxDay : day, hour, minute, second);
|
||||||
year,
|
|
||||||
month,
|
|
||||||
day > maxDay ? maxDay : day,
|
|
||||||
hour,
|
|
||||||
minute,
|
|
||||||
second
|
|
||||||
);
|
|
||||||
const t = parse(time);
|
const t = parse(time);
|
||||||
const tf = (time?: Date, format?: any): string => {
|
const tf = (time?: Date, format?: any): string => {
|
||||||
if (!time) {
|
if (!time) {
|
||||||
@ -482,10 +357,7 @@ const status = (
|
|||||||
s: seconds,
|
s: seconds,
|
||||||
S: milliseconds,
|
S: milliseconds,
|
||||||
};
|
};
|
||||||
return (format || props.format).replace(
|
return (format || props.format).replace(/Y+|M+|D+|H+|h+|m+|s+|S+/g, (str: string) => map[str]);
|
||||||
/Y+|M+|D+|H+|h+|m+|s+|S+/g,
|
|
||||||
(str: string) => map[str]
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
const classObj: any = {};
|
const classObj: any = {};
|
||||||
let flag = false;
|
let flag = false;
|
||||||
@ -497,33 +369,31 @@ const status = (
|
|||||||
flag = tf(props.value, format) === tf(time, format);
|
flag = tf(props.value, format) === tf(time, format);
|
||||||
}
|
}
|
||||||
classObj[`${state.pre}-date`] = true;
|
classObj[`${state.pre}-date`] = true;
|
||||||
classObj[`${state.pre}-date-disabled`] =
|
classObj[`${state.pre}-date-disabled`] = (props.right && t < start.value) || props.disabledDate(time, format);
|
||||||
(props.right && t < start.value) || props.disabledDate(time, format);
|
classObj[`${state.pre}-date-on`] = (props.left && t > start.value) || (props.right && t < end.value);
|
||||||
classObj[`${state.pre}-date-on`] =
|
|
||||||
(props.left && t > start.value) || (props.right && t < end.value);
|
|
||||||
classObj[`${state.pre}-date-selected`] = flag;
|
classObj[`${state.pre}-date-selected`] = flag;
|
||||||
return classObj;
|
return classObj;
|
||||||
};
|
};
|
||||||
const nm = () => {
|
const nm = () => {
|
||||||
if (state.month < 11) {
|
if (state.month < 11) {
|
||||||
state.month++;
|
state.month++;
|
||||||
} else {
|
} else {
|
||||||
state.month = 0;
|
state.month = 0;
|
||||||
state.year++;
|
state.year++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const pm = () => {
|
const pm = () => {
|
||||||
if (state.month > 0) {
|
if (state.month > 0) {
|
||||||
state.month--;
|
state.month--;
|
||||||
} else {
|
} else {
|
||||||
state.month = 11;
|
state.month = 11;
|
||||||
state.year--;
|
state.year--;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const is = (e: any) => {
|
const is = (e: any) => {
|
||||||
return e.target.className.indexOf(`${state.pre}-date-disabled`) === -1;
|
return e.target.className.indexOf(`${state.pre}-date-disabled`) === -1;
|
||||||
};
|
};
|
||||||
const ok = (info: any) => {
|
const ok = (info: any) => {
|
||||||
let year = "";
|
let year = "";
|
||||||
let month = "";
|
let month = "";
|
||||||
let day = "";
|
let day = "";
|
||||||
@ -544,7 +414,7 @@ const ok = (info: any) => {
|
|||||||
day ? Number(day) : state.day,
|
day ? Number(day) : state.day,
|
||||||
state.hour,
|
state.hour,
|
||||||
state.minute,
|
state.minute,
|
||||||
state.second
|
state.second,
|
||||||
);
|
);
|
||||||
if (props.left && _time.getTime() / 100000 < end.value) {
|
if (props.left && _time.getTime() / 100000 < end.value) {
|
||||||
emit("setDates", _time, "left");
|
emit("setDates", _time, "left");
|
||||||
@ -556,8 +426,8 @@ const ok = (info: any) => {
|
|||||||
emit("setDates", _time);
|
emit("setDates", _time);
|
||||||
}
|
}
|
||||||
emit("ok", info === "h");
|
emit("ok", info === "h");
|
||||||
};
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const is = (c: string) => props.format.indexOf(c) !== -1;
|
const is = (c: string) => props.format.indexOf(c) !== -1;
|
||||||
if (is("s") && is("m") && (is("h") || is("H"))) {
|
if (is("s") && is("m") && (is("h") || is("H"))) {
|
||||||
state.m = "H";
|
state.m = "H";
|
||||||
@ -570,30 +440,30 @@ onMounted(() => {
|
|||||||
state.m = "Y";
|
state.m = "Y";
|
||||||
state.showYears = true;
|
state.showYears = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.calendar {
|
.calendar {
|
||||||
float: left;
|
float: left;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
color: #3d444f;
|
color: #3d444f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar + .calendar {
|
.calendar + .calendar {
|
||||||
border-left: solid 1px #eaeaea;
|
border-left: solid 1px #eaeaea;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-head {
|
.calendar-head {
|
||||||
line-height: 34px;
|
line-height: 34px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-head a {
|
.calendar-head a {
|
||||||
color: #666;
|
color: #666;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -601,50 +471,50 @@ onMounted(() => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-head a:hover {
|
.calendar-head a:hover {
|
||||||
color: #3f97e3;
|
color: #3f97e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-head .calendar-year-select,
|
.calendar-head .calendar-year-select,
|
||||||
.calendar-head .calendar-month-select {
|
.calendar-head .calendar-month-select {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-prev-decade-btn,
|
.calendar-prev-decade-btn,
|
||||||
.calendar-prev-year-btn {
|
.calendar-prev-year-btn {
|
||||||
left: 6px;
|
left: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-prev-month-btn {
|
.calendar-prev-month-btn {
|
||||||
left: 24px;
|
left: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-next-decade-btn,
|
.calendar-next-decade-btn,
|
||||||
.calendar-next-year-btn {
|
.calendar-next-year-btn {
|
||||||
right: 6px;
|
right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-next-month-btn {
|
.calendar-next-month-btn {
|
||||||
right: 24px;
|
right: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-body {
|
.calendar-body {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 196px;
|
width: 196px;
|
||||||
height: 196px;
|
height: 196px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-days {
|
.calendar-days {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-week,
|
.calendar-week,
|
||||||
.calendar-date {
|
.calendar-date {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
width: 14.28%;
|
width: 14.28%;
|
||||||
height: 14.28%;
|
height: 14.28%;
|
||||||
@ -652,96 +522,96 @@ onMounted(() => {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-week:before,
|
.calendar-week:before,
|
||||||
.calendar-date:before {
|
.calendar-date:before {
|
||||||
content: "";
|
content: "";
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-date {
|
.calendar-date {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 29px;
|
line-height: 29px;
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-date-out {
|
.calendar-date-out {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-date:hover,
|
.calendar-date:hover,
|
||||||
.calendar-date-on {
|
.calendar-date-on {
|
||||||
color: #3f97e3;
|
color: #3f97e3;
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-date-selected,
|
.calendar-date-selected,
|
||||||
.calendar-date-selected:hover {
|
.calendar-date-selected:hover {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
background: #3f97e3;
|
background: #3f97e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-date-disabled {
|
.calendar-date-disabled {
|
||||||
cursor: not-allowed !important;
|
cursor: not-allowed !important;
|
||||||
color: #ccc !important;
|
color: #ccc !important;
|
||||||
background: #fff !important;
|
background: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-foot {
|
.calendar-foot {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-hour {
|
.calendar-hour {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid #e6e5e5;
|
border: 1px solid #e6e5e5;
|
||||||
color: #9e9e9e;
|
color: #9e9e9e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-hour a {
|
.calendar-hour a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-hour a:hover,
|
.calendar-hour a:hover,
|
||||||
.calendar-hour a.on {
|
.calendar-hour a.on {
|
||||||
color: #3f97e3;
|
color: #3f97e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-years,
|
.calendar-years,
|
||||||
.calendar-months,
|
.calendar-months,
|
||||||
.calendar-hours,
|
.calendar-hours,
|
||||||
.calendar-minutes,
|
.calendar-minutes,
|
||||||
.calendar-seconds {
|
.calendar-seconds {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-months a {
|
.calendar-months a {
|
||||||
width: 33.33%;
|
width: 33.33%;
|
||||||
height: 25%;
|
height: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-years a {
|
.calendar-years a {
|
||||||
width: 33.33%;
|
width: 33.33%;
|
||||||
height: 25%;
|
height: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-overflow {
|
.calendar-overflow {
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .calendar-hours a {
|
/* .calendar-hours a {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
height: 20%;
|
height: 20%;
|
||||||
}
|
}
|
||||||
@ -752,12 +622,12 @@ onMounted(() => {
|
|||||||
height: 10%;
|
height: 10%;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
.calendar-title {
|
.calendar-title {
|
||||||
margin-top: -30px;
|
margin-top: -30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -19,11 +19,7 @@ limitations under the License. -->
|
|||||||
<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,39 +36,29 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import { watch, ref, onMounted, onBeforeUnmount, unref, computed } 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*/
|
||||||
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 menus = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const visMenus = ref<boolean>(false);
|
const visMenus = ref<boolean>(false);
|
||||||
const { setOptions, resize, getInstance } = useECharts(
|
const { setOptions, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);
|
||||||
chartRef as Ref<HTMLDivElement>
|
const currentParams = ref<Nullable<EventParams>>(null);
|
||||||
);
|
const showTrace = ref<boolean>(false);
|
||||||
const currentParams = ref<Nullable<EventParams>>(null);
|
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
||||||
const showTrace = ref<boolean>(false);
|
|
||||||
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
|
||||||
type: "Trace",
|
type: "Trace",
|
||||||
});
|
});
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
height: { type: String, default: "100%" },
|
height: { type: String, default: "100%" },
|
||||||
width: { type: String, default: "100%" },
|
width: { type: String, default: "100%" },
|
||||||
option: {
|
option: {
|
||||||
@ -89,21 +75,19 @@ const props = defineProps({
|
|||||||
type: Array as PropType<{ widgetId: string }[]>,
|
type: Array as PropType<{ widgetId: string }[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const available = computed(
|
const available = computed(
|
||||||
() =>
|
() =>
|
||||||
(Array.isArray(props.option.series) &&
|
(Array.isArray(props.option.series) && props.option.series[0] && props.option.series[0].data) ||
|
||||||
props.option.series[0] &&
|
(Array.isArray(props.option.series.data) && props.option.series.data[0]),
|
||||||
props.option.series[0].data) ||
|
);
|
||||||
(Array.isArray(props.option.series.data) && props.option.series.data[0])
|
onMounted(async () => {
|
||||||
);
|
|
||||||
onMounted(async () => {
|
|
||||||
await setOptions(props.option);
|
await setOptions(props.option);
|
||||||
chartRef.value && addResizeListener(unref(chartRef), resize);
|
chartRef.value && addResizeListener(unref(chartRef), resize);
|
||||||
instanceEvent();
|
instanceEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
function instanceEvent() {
|
function instanceEvent() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const instance = getInstance();
|
const instance = getInstance();
|
||||||
|
|
||||||
@ -141,21 +125,21 @@ function instanceEvent() {
|
|||||||
currTrigger: "leave",
|
currTrigger: "leave",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function associateMetrics() {
|
function associateMetrics() {
|
||||||
emits("select", currentParams.value);
|
emits("select", currentParams.value);
|
||||||
const { dataIndex, seriesIndex } = currentParams.value || {
|
const { dataIndex, seriesIndex } = currentParams.value || {
|
||||||
dataIndex: 0,
|
dataIndex: 0,
|
||||||
seriesIndex: 0,
|
seriesIndex: 0,
|
||||||
};
|
};
|
||||||
updateOptions({ dataIndex, seriesIndex });
|
updateOptions({ dataIndex, seriesIndex });
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOptions(params?: { dataIndex: number; seriesIndex: number }) {
|
function updateOptions(params?: { dataIndex: number; seriesIndex: number }) {
|
||||||
const instance = getInstance();
|
const instance = getInstance();
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
return;
|
return;
|
||||||
@ -180,9 +164,9 @@ function updateOptions(params?: { dataIndex: number; seriesIndex: number }) {
|
|||||||
seriesIndex: ids,
|
seriesIndex: ids,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function viewTrace() {
|
function viewTrace() {
|
||||||
const item = associateProcessor(props).traceFilters(currentParams.value);
|
const item = associateProcessor(props).traceFilters(currentParams.value);
|
||||||
traceOptions.value = {
|
traceOptions.value = {
|
||||||
...traceOptions.value,
|
...traceOptions.value,
|
||||||
@ -190,9 +174,9 @@ function viewTrace() {
|
|||||||
};
|
};
|
||||||
showTrace.value = true;
|
showTrace.value = true;
|
||||||
visMenus.value = true;
|
visMenus.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.option,
|
() => props.option,
|
||||||
(newVal, oldVal) => {
|
(newVal, oldVal) => {
|
||||||
if (!available.value) {
|
if (!available.value) {
|
||||||
@ -207,21 +191,21 @@ watch(
|
|||||||
options = eventAssociate();
|
options = eventAssociate();
|
||||||
}
|
}
|
||||||
setOptions(options || props.option);
|
setOptions(options || props.option);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
watch(
|
watch(
|
||||||
() => props.filters,
|
() => props.filters,
|
||||||
() => {
|
() => {
|
||||||
updateOptions();
|
updateOptions();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
removeResizeListener(unref(chartRef), resize);
|
removeResizeListener(unref(chartRef), resize);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.no-data {
|
.no-data {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -230,14 +214,14 @@ onBeforeUnmount(() => {
|
|||||||
-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;
|
||||||
@ -248,9 +232,9 @@ onBeforeUnmount(() => {
|
|||||||
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;
|
||||||
@ -259,5 +243,5 @@ onBeforeUnmount(() => {
|
|||||||
color: #409eff;
|
color: #409eff;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -24,21 +24,19 @@ 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 */
|
|
||||||
defineProps({
|
|
||||||
iconName: { type: String, default: "" },
|
iconName: { type: String, default: "" },
|
||||||
size: { type: String, default: "sm" },
|
size: { type: String, default: "sm" },
|
||||||
loading: { type: Boolean, default: false },
|
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;
|
||||||
@ -72,8 +70,8 @@ defineProps({
|
|||||||
height: 30px;
|
height: 30px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@keyframes loading {
|
@keyframes loading {
|
||||||
0% {
|
0% {
|
||||||
-webkit-transform: rotate(0deg);
|
-webkit-transform: rotate(0deg);
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
@ -83,5 +81,5 @@ defineProps({
|
|||||||
-webkit-transform: rotate(1turn);
|
-webkit-transform: rotate(1turn);
|
||||||
transform: rotate(1turn);
|
transform: rotate(1turn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -20,19 +20,19 @@ 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 */
|
||||||
|
const emit = defineEmits(["change"]);
|
||||||
|
const props = defineProps({
|
||||||
|
options: {
|
||||||
|
type: Array as PropType<
|
||||||
|
{
|
||||||
label: string | number;
|
label: string | number;
|
||||||
value: string | number;
|
value: string | number;
|
||||||
}
|
}[]
|
||||||
|
>,
|
||||||
/*global defineProps, defineEmits */
|
|
||||||
const emit = defineEmits(["change"]);
|
|
||||||
const props = defineProps({
|
|
||||||
options: {
|
|
||||||
type: Array as PropType<Option[]>,
|
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
@ -40,11 +40,11 @@ const props = defineProps({
|
|||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
size: { type: null, default: "default" },
|
size: { type: null, default: "default" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const selected = ref<string>(props.value);
|
const selected = ref<string>(props.value);
|
||||||
|
|
||||||
function checked(opt: unknown) {
|
function checked(opt: unknown) {
|
||||||
emit("change", opt);
|
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,13 +35,13 @@ 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: () => [],
|
||||||
@ -53,38 +51,38 @@ const props = defineProps({
|
|||||||
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() {
|
function removeSelected() {
|
||||||
selected.value = { label: "", value: "" };
|
selected.value = { label: "", value: "" };
|
||||||
emit("change", "");
|
emit("change", "");
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(data) => {
|
(data) => {
|
||||||
const opt = props.options.find((d: Option) => data === d.value);
|
const opt = props.options.find((d: Option) => data === d.value);
|
||||||
selected.value = opt || { label: "", value: "" };
|
selected.value = opt || { label: "", value: "" };
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
document.body.addEventListener("click", handleClick, false);
|
document.body.addEventListener("click", handleClick, false);
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
function setPopper(event: any) {
|
function setPopper(event: any) {
|
||||||
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;
|
||||||
@ -103,13 +101,13 @@ function setPopper(event: any) {
|
|||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-data {
|
.no-data {
|
||||||
color: #c0c4cc;
|
color: #c0c4cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar-i {
|
.bar-i {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
@ -122,9 +120,9 @@ function setPopper(event: any) {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-icon {
|
.remove-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -132,9 +130,9 @@ function setPopper(event: any) {
|
|||||||
display: none;
|
display: none;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opt-wrapper {
|
.opt-wrapper {
|
||||||
color: #606266;
|
color: #606266;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 26px;
|
top: 26px;
|
||||||
@ -160,9 +158,9 @@ function setPopper(event: any) {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.opt {
|
.opt {
|
||||||
padding: 7px 15px;
|
padding: 7px 15px;
|
||||||
|
|
||||||
&.select-disabled {
|
&.select-disabled {
|
||||||
@ -173,5 +171,5 @@ function setPopper(event: any) {
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -27,29 +27,29 @@ limitations under the License. -->
|
|||||||
:remote-method="remoteMethod"
|
:remote-method="remoteMethod"
|
||||||
:filterable="filterable"
|
:filterable="filterable"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option v-for="item in options" :key="item.value || ''" :label="item.label || ''" :value="item.value || ''">
|
||||||
v-for="item in options"
|
|
||||||
:key="item.value || ''"
|
|
||||||
:label="item.label || ''"
|
|
||||||
:value="item.value || ''"
|
|
||||||
>
|
|
||||||
</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;
|
||||||
|
// value: string | number;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*global defineProps, defineEmits*/
|
||||||
|
const emit = defineEmits(["change", "query"]);
|
||||||
|
const props = defineProps({
|
||||||
|
options: {
|
||||||
|
type: Array as PropType<
|
||||||
|
({
|
||||||
label: string | number;
|
label: string | number;
|
||||||
value: string | number;
|
value: string | number;
|
||||||
}
|
} & { disabled?: boolean })[]
|
||||||
|
>,
|
||||||
/*global defineProps, defineEmits*/
|
|
||||||
const emit = defineEmits(["change", "query"]);
|
|
||||||
const props = defineProps({
|
|
||||||
options: {
|
|
||||||
type: Array as PropType<(Option & { disabled?: boolean })[]>,
|
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
@ -67,33 +67,31 @@ const props = defineProps({
|
|||||||
clearable: { type: Boolean, default: false },
|
clearable: { type: Boolean, default: false },
|
||||||
isRemote: { type: Boolean, default: false },
|
isRemote: { type: Boolean, default: false },
|
||||||
filterable: { type: Boolean, default: true },
|
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: any) =>
|
||||||
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);
|
emit("change", options);
|
||||||
}
|
}
|
||||||
|
|
||||||
function remoteMethod(query: string) {
|
function remoteMethod(query: string) {
|
||||||
if (props.isRemote) {
|
if (props.isRemote) {
|
||||||
emit("query", query);
|
emit("query", query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(data) => {
|
(data) => {
|
||||||
selected.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>
|
||||||
|
@ -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,16 +108,16 @@ 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],
|
||||||
@ -184,9 +150,9 @@ const props = defineProps({
|
|||||||
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
|
||||||
@ -205,8 +171,8 @@ const local = computed(() => {
|
|||||||
weekCutTip: t("weekCutTip"),
|
weekCutTip: t("weekCutTip"),
|
||||||
monthCutTip: t("monthCutTip"),
|
monthCutTip: t("monthCutTip"),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const tf = (time: Date, format?: any): string => {
|
const tf = (time: Date, format?: any): string => {
|
||||||
const year = time.getFullYear();
|
const year = time.getFullYear();
|
||||||
const month = time.getMonth();
|
const month = time.getMonth();
|
||||||
const day = time.getDate();
|
const day = time.getDate();
|
||||||
@ -234,58 +200,51 @@ const tf = (time: Date, format?: any): string => {
|
|||||||
s: seconds,
|
s: seconds,
|
||||||
S: milliseconds,
|
S: milliseconds,
|
||||||
};
|
};
|
||||||
return (format || props.format).replace(
|
return (format || props.format).replace(/Y+|M+|D+|H+|h+|m+|s+|S+/g, (str: string) => map[str]);
|
||||||
/Y+|M+|D+|H+|h+|m+|s+|S+/g,
|
};
|
||||||
(str: string) => map[str]
|
const range = computed(() => {
|
||||||
);
|
|
||||||
};
|
|
||||||
const range = computed(() => {
|
|
||||||
return dates.value.length === 2;
|
return dates.value.length === 2;
|
||||||
});
|
});
|
||||||
const text = computed(() => {
|
const text = computed(() => {
|
||||||
const val = props.value;
|
const val = props.value;
|
||||||
const txt = dates.value
|
const txt = dates.value.map((date: Date) => tf(date)).join(` ${props.rangeSeparator} `);
|
||||||
.map((date: Date) => tf(date))
|
|
||||||
.join(` ${props.rangeSeparator} `);
|
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
return val.length > 1 ? txt : "";
|
return val.length > 1 ? txt : "";
|
||||||
}
|
}
|
||||||
return val ? txt : "";
|
return val ? txt : "";
|
||||||
});
|
});
|
||||||
const get = () => {
|
const get = () => {
|
||||||
return Array.isArray(props.value) ? dates.value : dates.value[0];
|
return Array.isArray(props.value) ? dates.value : dates.value[0];
|
||||||
};
|
};
|
||||||
const cls = () => {
|
const cls = () => {
|
||||||
emit("clear");
|
emit("clear");
|
||||||
emit("input", range.value ? [] : "");
|
emit("input", range.value ? [] : "");
|
||||||
};
|
};
|
||||||
const vi = (val: any) => {
|
const vi = (val: any) => {
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
return val.length > 1
|
return val.length > 1 ? val.map((item) => new Date(item)) : [new Date(), new Date()];
|
||||||
? val.map((item) => new Date(item))
|
|
||||||
: [new Date(), new Date()];
|
|
||||||
}
|
}
|
||||||
return val ? [new Date(val)] : [new Date()];
|
return val ? [new Date(val)] : [new Date()];
|
||||||
};
|
};
|
||||||
const ok = (leaveOpened: boolean) => {
|
const ok = (leaveOpened: boolean) => {
|
||||||
emit("input", get());
|
emit("input", get());
|
||||||
!leaveOpened &&
|
!leaveOpened &&
|
||||||
!props.showButtons &&
|
!props.showButtons &&
|
||||||
useTimeoutFn(() => {
|
useTimeoutFn(() => {
|
||||||
show.value = range.value;
|
show.value = range.value;
|
||||||
}, 1);
|
}, 1);
|
||||||
};
|
};
|
||||||
const setDates = (d: Date, pos: string) => {
|
const setDates = (d: Date, pos: string) => {
|
||||||
if (pos === "right") {
|
if (pos === "right") {
|
||||||
dates.value[1] = d;
|
dates.value[1] = d;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dates.value[0] = d;
|
dates.value[0] = d;
|
||||||
};
|
};
|
||||||
const dc = (e: any) => {
|
const dc = (e: any) => {
|
||||||
show.value = (datepicker.value as any).contains(e.target) && !props.disabled;
|
show.value = (datepicker.value as any).contains(e.target) && !props.disabled;
|
||||||
};
|
};
|
||||||
const quickPick = (type: string) => {
|
const quickPick = (type: string) => {
|
||||||
const end = new Date();
|
const end = new Date();
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -312,32 +271,32 @@ const quickPick = (type: string) => {
|
|||||||
}
|
}
|
||||||
dates.value = [start, end];
|
dates.value = [start, end];
|
||||||
emit("input", get());
|
emit("input", get());
|
||||||
};
|
};
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
emit("confirm", get());
|
emit("confirm", get());
|
||||||
show.value = false;
|
show.value = false;
|
||||||
};
|
};
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
emit("cancel");
|
emit("cancel");
|
||||||
show.value = false;
|
show.value = false;
|
||||||
};
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
dates.value = vi(props.value);
|
dates.value = vi(props.value);
|
||||||
document.addEventListener("click", dc, true);
|
document.addEventListener("click", dc, true);
|
||||||
});
|
});
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
document.removeEventListener("click", dc, true);
|
document.removeEventListener("click", dc, true);
|
||||||
});
|
});
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(val: unknown) => {
|
(val: unknown) => {
|
||||||
dates.value = vi(val);
|
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);
|
||||||
@ -347,9 +306,9 @@ watch(
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleY(1);
|
transform: scaleY(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes datepicker-anim-out {
|
@keyframes datepicker-anim-out {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleY(1);
|
transform: scaleY(1);
|
||||||
@ -359,22 +318,22 @@ watch(
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleY(0.8);
|
transform: scaleY(0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker {
|
.datepicker {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-icon {
|
.datepicker-icon {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
left: 8px;
|
left: 8px;
|
||||||
color: #515a6ecc;
|
color: #515a6ecc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-close {
|
.datepicker-close {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
@ -382,9 +341,9 @@ watch(
|
|||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-close:before {
|
.datepicker-close:before {
|
||||||
display: block;
|
display: block;
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -400,21 +359,21 @@ watch(
|
|||||||
background: #ccc
|
background: #ccc
|
||||||
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3IDciIHdpZHRoPSI3IiBoZWlnaHQ9IjciPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01LjU4LDVsMi44LTIuODFBLjQxLjQxLDAsMSwwLDcuOCwxLjZMNSw0LjQxLDIuMiwxLjZhLjQxLjQxLDAsMCwwLS41OC41OGgwTDQuNDIsNSwxLjYyLDcuOGEuNDEuNDEsMCwwLDAsLjU4LjU4TDUsNS41OCw3LjgsOC4zOWEuNDEuNDEsMCwwLDAsLjU4LS41OGgwWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuNSAtMS40OCkiIHN0eWxlPSJmaWxsOiNmZmYiLz48L3N2Zz4NCg==")
|
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3IDciIHdpZHRoPSI3IiBoZWlnaHQ9IjciPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01LjU4LDVsMi44LTIuODFBLjQxLjQxLDAsMSwwLDcuOCwxLjZMNSw0LjQxLDIuMiwxLjZhLjQxLjQxLDAsMCwwLS41OC41OGgwTDQuNDIsNSwxLjYyLDcuOGEuNDEuNDEsMCwwLDAsLjU4LjU4TDUsNS41OCw3LjgsOC4zOWEuNDEuNDEsMCwwLDAsLjU4LS41OGgwWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuNSAtMS40OCkiIHN0eWxlPSJmaWxsOiNmZmYiLz48L3N2Zz4NCg==")
|
||||||
no-repeat 50% 50%;
|
no-repeat 50% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker__clearable:hover:before {
|
.datepicker__clearable:hover:before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker__clearable:hover .datepicker-close {
|
.datepicker__clearable:hover .datepicker-close {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-close:hover:before {
|
.datepicker-close:hover:before {
|
||||||
background-color: #afafaf;
|
background-color: #afafaf;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker > input {
|
.datepicker > input {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
// transition: all 200ms ease;
|
// transition: all 200ms ease;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@ -428,23 +387,23 @@ watch(
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
font-family: "Monaco";
|
font-family: "Monaco";
|
||||||
letter-spacing: -0.7px;
|
letter-spacing: -0.7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// .datepicker > input.focus {
|
// .datepicker > input.focus {
|
||||||
// border-color: #3f97e3;
|
// border-color: #3f97e3;
|
||||||
// -webkit-box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
|
// -webkit-box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
|
||||||
// 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 {
|
.datepicker > input:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
background-color: #ebebe4;
|
background-color: #ebebe4;
|
||||||
border-color: #e5e5e5;
|
border-color: #e5e5e5;
|
||||||
-webkit-box-shadow: none;
|
-webkit-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-popup {
|
.datepicker-popup {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: all 200ms ease;
|
transition: all 200ms ease;
|
||||||
@ -514,52 +473,52 @@ watch(
|
|||||||
margin-left: 100px;
|
margin-left: 100px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-inline {
|
.datepicker-inline {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-range {
|
.datepicker-range {
|
||||||
min-width: 238px;
|
min-width: 238px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-range .datepicker-popup {
|
.datepicker-range .datepicker-popup {
|
||||||
width: 520px;
|
width: 520px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-bottom {
|
.datepicker-bottom {
|
||||||
float: left;
|
float: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-btn {
|
.datepicker-btn {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
background: #3f97e3;
|
background: #3f97e3;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-anim-enter-active {
|
.datepicker-anim-enter-active {
|
||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
animation: datepicker-anim-in 0.2s cubic-bezier(0.23, 1, 0.32, 1);
|
animation: datepicker-anim-in 0.2s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-anim-leave-active {
|
.datepicker-anim-leave-active {
|
||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
animation: datepicker-anim-out 0.2s cubic-bezier(0.755, 0.05, 0.855, 0.06);
|
animation: datepicker-anim-out 0.2s cubic-bezier(0.755, 0.05, 0.855, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker__buttons {
|
.datepicker__buttons {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker__buttons button {
|
.datepicker__buttons button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
border: none;
|
border: none;
|
||||||
@ -567,13 +526,13 @@ watch(
|
|||||||
margin: 10px 0 0 5px;
|
margin: 10px 0 0 5px;
|
||||||
padding: 5px 15px;
|
padding: 5px 15px;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker__buttons .datepicker__button-select {
|
.datepicker__buttons .datepicker__button-select {
|
||||||
background: #3f97e3;
|
background: #3f97e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker__buttons .datepicker__button-cancel {
|
.datepicker__buttons .datepicker__button-cancel {
|
||||||
background: #666;
|
background: #666;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
33
src/components/__tests__/HelloWorld.spec.ts
Normal file
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);
|
||||||
|
});
|
||||||
|
});
|
@ -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 {
|
||||||
|
@ -33,8 +33,7 @@ export const createEBPFTask = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
export const queryEBPFTasks = {
|
export const queryEBPFTasks = {
|
||||||
variable:
|
variable: "$serviceId: ID, $serviceInstanceId: ID, $targets: [EBPFProfilingTargetType!]",
|
||||||
"$serviceId: ID, $serviceInstanceId: ID, $targets: [EBPFProfilingTargetType!]",
|
|
||||||
query: `
|
query: `
|
||||||
queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, targets: $targets) {
|
queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, targets: $targets) {
|
||||||
taskId
|
taskId
|
||||||
|
@ -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,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}}`;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
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: any) {
|
||||||
function eventAssociate() {
|
function eventAssociate() {
|
||||||
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -101,36 +91,27 @@ export default function associateProcessor(props: any) {
|
|||||||
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] ? series[index + 1].data[currentParams.dataIndex][1] : Infinity,
|
||||||
? series[index + 1].data[currentParams.dataIndex][1]
|
|
||||||
: Infinity,
|
|
||||||
];
|
];
|
||||||
return {
|
return {
|
||||||
label:
|
label: d.name + "--" + (series[index + 1] ? series[index + 1].name : "Infinity"),
|
||||||
d.name +
|
|
||||||
"--" +
|
|
||||||
(series[index + 1] ? series[index + 1].name : "Infinity"),
|
|
||||||
value: String(index),
|
value: String(index),
|
||||||
data,
|
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;
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
|
||||||
@ -40,9 +41,7 @@ export function useBreakpoint(): any {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createBreakpointListen(
|
export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void): any {
|
||||||
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[] = [];
|
||||||
|
@ -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"): any {
|
||||||
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(() => {
|
||||||
|
@ -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 = () => {
|
||||||
|
@ -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: any) => 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) {
|
||||||
|
@ -17,25 +17,14 @@
|
|||||||
import { MetricQueryTypes, Calculations } from "./data";
|
import { MetricQueryTypes, Calculations } from "./data";
|
||||||
export function useListConfig(config: any, index: string) {
|
export function useListConfig(config: any, index: string) {
|
||||||
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,8 +20,8 @@ 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";
|
import { MetricCatalog } from "@/views/dashboard/data";
|
||||||
|
|
||||||
export function useQueryProcessor(config: any) {
|
export function useQueryProcessor(config: any) {
|
||||||
@ -42,33 +42,21 @@ export function useQueryProcessor(config: any) {
|
|||||||
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,
|
|
||||||
normal: selectorStore.currentService
|
|
||||||
? selectorStore.currentService.normal
|
|
||||||
: true,
|
|
||||||
scope: config.catalog,
|
scope: config.catalog,
|
||||||
topN: c.topN || 10,
|
topN: c.topN || 10,
|
||||||
order: c.sortOrder || "DES",
|
order: c.sortOrder || "DES",
|
||||||
@ -76,19 +64,11 @@ export function useQueryProcessor(config: any) {
|
|||||||
} else {
|
} else {
|
||||||
const entity = {
|
const entity = {
|
||||||
scope: config.catalog,
|
scope: config.catalog,
|
||||||
serviceName:
|
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
|
||||||
dashboardStore.entity === "All"
|
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
|
||||||
? undefined
|
serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation"].includes(
|
||||||
: selectorStore.currentService.value,
|
dashboardStore.entity,
|
||||||
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 +77,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 +87,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)) {
|
||||||
@ -129,9 +101,7 @@ export function useQueryProcessor(config: any) {
|
|||||||
} else {
|
} else {
|
||||||
entity.scope = dashboardStore.entity;
|
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;
|
||||||
}
|
}
|
||||||
@ -161,7 +131,7 @@ export function useSourceProcessor(
|
|||||||
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,23 +149,14 @@ 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 }) => aggregation(Number(d.value), c));
|
||||||
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) {
|
||||||
source[labels[indexNum]] = values;
|
source[labels[indexNum]] = values;
|
||||||
@ -209,20 +170,14 @@ export function useSourceProcessor(
|
|||||||
}
|
}
|
||||||
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] || {};
|
||||||
@ -238,12 +193,7 @@ export function useSourceProcessor(
|
|||||||
});
|
});
|
||||||
let buckets = [] as any;
|
let buckets = [] as any;
|
||||||
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[][]
|
||||||
@ -260,7 +210,7 @@ export function useQueryPodsMetrics(
|
|||||||
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,11 +227,7 @@ 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) & { normal: boolean }, index: number) => {
|
||||||
(
|
|
||||||
d: (Instance | Endpoint | Service) & { normal: boolean },
|
|
||||||
index: number
|
|
||||||
) => {
|
|
||||||
const param = {
|
const param = {
|
||||||
scope,
|
scope,
|
||||||
serviceName: scope === "Service" ? d.label : currentService.label,
|
serviceName: scope === "Service" ? d.label : currentService.label,
|
||||||
@ -301,16 +247,13 @@ export function useQueryPodsMetrics(
|
|||||||
const c = config.metricConfig[idx] || {};
|
const c = config.metricConfig[idx] || {};
|
||||||
variables.push(`$labels${index}${idx}: [String!]!`);
|
variables.push(`$labels${index}${idx}: [String!]!`);
|
||||||
labelStr = `labels: $labels${index}${idx}, `;
|
labelStr = `labels: $labels${index}${idx}, `;
|
||||||
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, ""));
|
|
||||||
conditions[`labels${index}${idx}`] = labels;
|
conditions[`labels${index}${idx}`] = labels;
|
||||||
}
|
}
|
||||||
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[metricType]}`;
|
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[metricType]}`;
|
||||||
});
|
});
|
||||||
return f;
|
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}}`;
|
||||||
|
|
||||||
@ -324,7 +267,7 @@ export function usePodsSource(
|
|||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
metricConfig: MetricConfigOpt[];
|
metricConfig: MetricConfigOpt[];
|
||||||
}
|
},
|
||||||
): any {
|
): any {
|
||||||
if (resp.errors) {
|
if (resp.errors) {
|
||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
@ -347,39 +290,23 @@ 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 }) => aggregation(val.value, c));
|
||||||
(val: { value: number }) => aggregation(val.value, c)
|
|
||||||
);
|
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
names.push(name);
|
names.push(name);
|
||||||
metricConfigArr.push(c);
|
metricConfigArr.push(c);
|
||||||
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 }) => aggregation(Number(d.value), c));
|
||||||
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;
|
||||||
if (labels[indexNum] && indexNum > -1) {
|
if (labels[indexNum] && indexNum > -1) {
|
||||||
@ -388,13 +315,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 +356,8 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
|||||||
|
|
||||||
return { queryStr, conditions };
|
return { queryStr, conditions };
|
||||||
}
|
}
|
||||||
function calculateExp(
|
function calculateExp(arr: { value: number }[], config: { calculation?: string }): (number | string)[] {
|
||||||
arr: { value: number }[],
|
const sum = arr.map((d: { value: number }) => d.value).reduce((a, b) => a + b);
|
||||||
config: { calculation?: string }
|
|
||||||
): (number | string)[] {
|
|
||||||
const sum = arr
|
|
||||||
.map((d: { value: number }) => d.value)
|
|
||||||
.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:
|
||||||
@ -460,10 +376,7 @@ function calculateExp(
|
|||||||
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) {
|
||||||
@ -518,11 +431,9 @@ export async function useGetMetricEntity(metric: string, metricType: any) {
|
|||||||
let catalog = "";
|
let catalog = "";
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
if (
|
if (
|
||||||
[
|
[MetricQueryTypes.ReadSampledRecords, MetricQueryTypes.SortMetrics, MetricQueryTypes.ReadRecords].includes(
|
||||||
MetricQueryTypes.ReadSampledRecords,
|
metricType,
|
||||||
MetricQueryTypes.SortMetrics,
|
)
|
||||||
MetricQueryTypes.ReadRecords,
|
|
||||||
].includes(metricType)
|
|
||||||
) {
|
) {
|
||||||
const res = await dashboardStore.fetchMetricList(metric);
|
const res = await dashboardStore.fetchMetricList(metric);
|
||||||
if (res.errors) {
|
if (res.errors) {
|
||||||
|
@ -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,7 +32,7 @@ export function useTimeoutFn(
|
|||||||
(maturity) => {
|
(maturity) => {
|
||||||
maturity && handle();
|
maturity && handle();
|
||||||
},
|
},
|
||||||
{ immediate: false }
|
{ immediate: false },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return { readyRef, stop, start };
|
return { readyRef, stop, start };
|
||||||
|
@ -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,8 @@ 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;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -23,21 +23,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,54 +40,52 @@ 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 { ElMessage } from "element-plus";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const pageName = ref<string>("");
|
const pageName = ref<string>("");
|
||||||
const timeRange = ref<number>(0);
|
const timeRange = ref<number>(0);
|
||||||
|
|
||||||
resetDuration();
|
resetDuration();
|
||||||
getVersion();
|
getVersion();
|
||||||
const setConfig = (value: string) => {
|
const setConfig = (value: string) => {
|
||||||
pageName.value = value || "";
|
pageName.value = value || "";
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleReload() {
|
function handleReload() {
|
||||||
const gap =
|
const gap = appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
||||||
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
|
||||||
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
||||||
appStore.setDuration(timeFormat(dates));
|
appStore.setDuration(timeFormat(dates));
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTimeRange(val: Date[] | any) {
|
function changeTimeRange(val: Date[] | any) {
|
||||||
timeRange.value =
|
timeRange.value = val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
|
||||||
val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
|
|
||||||
if (timeRange.value) {
|
if (timeRange.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
appStore.setDuration(timeFormat(val));
|
appStore.setDuration(timeFormat(val));
|
||||||
}
|
}
|
||||||
setConfig(String(route.meta.title));
|
setConfig(String(route.meta.title));
|
||||||
watch(
|
watch(
|
||||||
() => route.meta.title,
|
() => route.meta.title,
|
||||||
(title: unknown) => {
|
(title: unknown) => {
|
||||||
setConfig(String(title));
|
setConfig(String(title));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
async function getVersion() {
|
async function getVersion() {
|
||||||
const res = await appStore.fetchVersion();
|
const res = await appStore.fetchVersion();
|
||||||
if (res.errors) {
|
if (res.errors) {
|
||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function resetDuration() {
|
function resetDuration() {
|
||||||
const { duration }: any = route.params;
|
const { duration }: any = route.params;
|
||||||
if (duration) {
|
if (duration) {
|
||||||
const d = JSON.parse(duration);
|
const d = JSON.parse(duration);
|
||||||
@ -108,10 +97,10 @@ function resetDuration() {
|
|||||||
});
|
});
|
||||||
appStore.updateUTC(d.utc);
|
appStore.updateUTC(d.utc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.nav-bar {
|
.nav-bar {
|
||||||
padding: 5px 10px 5px 28px;
|
padding: 5px 10px 5px 28px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -119,22 +108,22 @@ function resetDuration() {
|
|||||||
border-bottom: 1px solid #dfe4e8;
|
border-bottom: 1px solid #dfe4e8;
|
||||||
color: #222;
|
color: #222;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-tabs {
|
.nav-tabs {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -15,10 +15,7 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div class="side-bar">
|
<div class="side-bar">
|
||||||
<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
|
<el-menu
|
||||||
active-text-color="#448dfe"
|
active-text-color="#448dfe"
|
||||||
@ -43,22 +40,14 @@ limitations under the License. -->
|
|||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
<el-menu-item-group>
|
<el-menu-item-group>
|
||||||
<el-menu-item
|
<el-menu-item v-for="(m, idx) in filterMenus(menu.children)" :index="m.name" :key="idx">
|
||||||
v-for="(m, idx) in filterMenus(menu.children)"
|
|
||||||
:index="m.name"
|
|
||||||
:key="idx"
|
|
||||||
>
|
|
||||||
<router-link class="items" :to="m.path">
|
<router-link class="items" :to="m.path">
|
||||||
<span class="title">{{ m.meta && t(m.meta.title) }}</span>
|
<span class="title">{{ m.meta && t(m.meta.title) }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-menu-item-group>
|
</el-menu-item-group>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
<el-menu-item
|
<el-menu-item :index="String(menu.name)" @click="changePage(menu)" v-else>
|
||||||
:index="String(menu.name)"
|
|
||||||
@click="changePage(menu)"
|
|
||||||
v-else
|
|
||||||
>
|
|
||||||
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
||||||
<router-link class="items" :to="menu.children[0].path">
|
<router-link class="items" :to="menu.children[0].path">
|
||||||
<Icon size="lg" :iconName="menu.meta.icon" />
|
<Icon size="lg" :iconName="menu.meta.icon" />
|
||||||
@ -79,82 +68,75 @@ limitations under the License. -->
|
|||||||
color: theme === 'light' ? '#eee' : '#252a2f',
|
color: theme === 'light' ? '#eee' : '#252a2f',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon size="middle" iconName="format_indent_decrease" @click="controlMenu" />
|
||||||
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 } from "vue";
|
||||||
import { useRouter, RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useRouter } 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();
|
const appStore = useAppStoreWithOut();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const name = ref<string>(String(useRouter().currentRoute.value.name));
|
const name = ref<string>(String(useRouter().currentRoute.value.name));
|
||||||
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "")
|
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "") ? ref("light") : ref("black");
|
||||||
? ref("light")
|
const routes = ref<RouteRecordRaw[] | any>(useRouter().options.routes);
|
||||||
: ref("black");
|
if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
||||||
const routes = ref<RouteRecordRaw[] | any>(useRouter().options.routes);
|
|
||||||
if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
|
||||||
appStore.setIsMobile(true);
|
appStore.setIsMobile(true);
|
||||||
} else {
|
} else {
|
||||||
appStore.setIsMobile(false);
|
appStore.setIsMobile(false);
|
||||||
}
|
}
|
||||||
const isCollapse = ref(false);
|
const isCollapse = ref(false);
|
||||||
const controlMenu = () => {
|
const controlMenu = () => {
|
||||||
isCollapse.value = !isCollapse.value;
|
isCollapse.value = !isCollapse.value;
|
||||||
};
|
};
|
||||||
const changePage = (menu: RouteRecordRaw) => {
|
const changePage = (menu: RouteRecordRaw) => {
|
||||||
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name))
|
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name)) ? "light" : "black";
|
||||||
? "light"
|
};
|
||||||
: "black";
|
const filterMenus = (menus: any[]) => {
|
||||||
};
|
|
||||||
const filterMenus = (menus: any[]) => {
|
|
||||||
return menus.filter((d) => d.meta && !d.meta.notShow);
|
return menus.filter((d) => d.meta && !d.meta.notShow);
|
||||||
};
|
};
|
||||||
</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: 100px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu-vertical:not(.el-menu--collapse) {
|
.el-menu-vertical:not(.el-menu--collapse) {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-icon-collapse {
|
.logo-icon-collapse {
|
||||||
width: 65px;
|
width: 65px;
|
||||||
margin: 15px 0 10px 0;
|
margin: 15px 0 10px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.collapse {
|
span.collapse {
|
||||||
height: 0;
|
height: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-icon {
|
.logo-icon {
|
||||||
margin: 15px 0 10px 20px;
|
margin: 15px 0 10px 20px;
|
||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-control {
|
.menu-control {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
left: 220px;
|
left: 220px;
|
||||||
@ -162,22 +144,22 @@ span.collapse {
|
|||||||
transition: all 0.2s linear;
|
transition: all 0.2s linear;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
color: #252a2f;
|
color: #252a2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-control.collapse {
|
.menu-control.collapse {
|
||||||
left: 70px;
|
left: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-icon.el-sub-menu__icon-arrow {
|
.el-icon.el-sub-menu__icon-arrow {
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.items {
|
.items {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version {
|
.version {
|
||||||
color: #eee;
|
color: #eee;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -186,17 +168,17 @@ span.collapse {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 110px;
|
max-width: 110px;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
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,
|
||||||
});
|
});
|
||||||
|
@ -176,10 +176,8 @@ 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",
|
||||||
seconds: "Seconds",
|
seconds: "Seconds",
|
||||||
hourTip: "Select Hour",
|
hourTip: "Select Hour",
|
||||||
@ -315,8 +313,7 @@ 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",
|
||||||
serviceEvents: "Service Events",
|
serviceEvents: "Service Events",
|
||||||
@ -370,8 +367,7 @@ 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",
|
gateway: "Gateway",
|
||||||
virtualMQ: "Virtual MQ",
|
virtualMQ: "Virtual MQ",
|
||||||
|
@ -77,10 +77,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",
|
||||||
@ -180,10 +178,8 @@ 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",
|
||||||
second: "s",
|
second: "s",
|
||||||
yearSuffix: "Año",
|
yearSuffix: "Año",
|
||||||
@ -315,8 +311,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 +342,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,10 +363,8 @@ 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",
|
||||||
|
@ -282,12 +282,9 @@ const msg = {
|
|||||||
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 +307,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,8 +364,7 @@ const msg = {
|
|||||||
addKeywordsOfContent: "请输入一个内容关键词",
|
addKeywordsOfContent: "请输入一个内容关键词",
|
||||||
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
|
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
|
||||||
noticeTag: "请输入一个标签(key=value)之后回车",
|
noticeTag: "请输入一个标签(key=value)之后回车",
|
||||||
conditionNotice:
|
conditionNotice: "请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
||||||
"请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
|
||||||
language: "语言",
|
language: "语言",
|
||||||
gateway: "网关",
|
gateway: "网关",
|
||||||
virtualMQ: "虚拟消息队列",
|
virtualMQ: "虚拟消息队列",
|
||||||
|
@ -22,6 +22,7 @@ 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();
|
||||||
|
@ -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 { RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import Layout from "@/layout/Index.vue";
|
import Layout from "@/layout/Index.vue";
|
||||||
|
|
||||||
export const routesAlarm: Array<RouteRecordRaw> = [
|
export const routesAlarm: Array<RouteRecordRaw> = [
|
||||||
@ -31,8 +31,7 @@ export const routesAlarm: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: "/alerting",
|
path: "/alerting",
|
||||||
name: "Alarm",
|
name: "Alarm",
|
||||||
component: () =>
|
component: () => import("@/views/Alarm.vue"),
|
||||||
import(/* webpackChunkName: "alerting" */ "@/views/Alarm.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -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 { RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import Layout from "@/layout/Index.vue";
|
import Layout from "@/layout/Index.vue";
|
||||||
|
|
||||||
export const routesDashboard: Array<RouteRecordRaw> = [
|
export const routesDashboard: Array<RouteRecordRaw> = [
|
||||||
@ -30,10 +30,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/list",
|
path: "/dashboard/list",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/List.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/List.vue"
|
|
||||||
),
|
|
||||||
name: "List",
|
name: "List",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardList",
|
title: "dashboardList",
|
||||||
@ -41,10 +38,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/new",
|
path: "/dashboard/new",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/New.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/New.vue"
|
|
||||||
),
|
|
||||||
name: "New",
|
name: "New",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardNew",
|
title: "dashboardNew",
|
||||||
@ -54,38 +48,26 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
path: "",
|
path: "",
|
||||||
redirect: "/dashboard/:layerId/:entity/:name",
|
redirect: "/dashboard/:layerId/:entity/:name",
|
||||||
name: "Create",
|
name: "Create",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
meta: {
|
meta: {
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:name",
|
path: "/dashboard/:layerId/:entity/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "CreateChild",
|
name: "CreateChild",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:name/tab/:activeTabIndex",
|
path: "/dashboard/:layerId/:entity/:name/tab/:activeTabIndex",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "CreateActiveTabIndex",
|
name: "CreateActiveTabIndex",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "View",
|
name: "View",
|
||||||
redirect: "/dashboard/:layerId/:entity/:serviceId/:name",
|
redirect: "/dashboard/:layerId/:entity/:serviceId/:name",
|
||||||
meta: {
|
meta: {
|
||||||
@ -94,30 +76,20 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewChild",
|
name: "ViewChild",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:name/tab/:activeTabIndex",
|
path: "/dashboard/:layerId/:entity/:serviceId/:name/tab/:activeTabIndex",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewActiveTabIndex",
|
name: "ViewActiveTabIndex",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
redirect:
|
redirect: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
||||||
"/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewServiceRelation",
|
name: "ViewServiceRelation",
|
||||||
meta: {
|
meta: {
|
||||||
notShow: true,
|
notShow: true,
|
||||||
@ -125,18 +97,12 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewServiceRelation",
|
name: "ViewServiceRelation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name/tab/:activeTabIndex",
|
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name/tab/:activeTabIndex",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewServiceRelationActiveTabIndex",
|
name: "ViewServiceRelationActiveTabIndex",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -144,10 +110,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewPod",
|
name: "ViewPod",
|
||||||
meta: {
|
meta: {
|
||||||
notShow: true,
|
notShow: true,
|
||||||
@ -155,30 +118,20 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewPod",
|
name: "ViewPod",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name/tab/:activeTabIndex",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name/tab/:activeTabIndex",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewPodActiveTabIndex",
|
name: "ViewPodActiveTabIndex",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
redirect:
|
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
||||||
"/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "PodRelation",
|
name: "PodRelation",
|
||||||
meta: {
|
meta: {
|
||||||
notShow: true,
|
notShow: true,
|
||||||
@ -186,18 +139,12 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewPodRelation",
|
name: "ViewPodRelation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name/tab/:activeTabIndex",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name/tab/:activeTabIndex",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewPodRelationActiveTabIndex",
|
name: "ViewPodRelationActiveTabIndex",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -206,10 +153,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
path: "",
|
path: "",
|
||||||
redirect:
|
redirect:
|
||||||
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
|
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ProcessRelation",
|
name: "ProcessRelation",
|
||||||
meta: {
|
meta: {
|
||||||
notShow: true,
|
notShow: true,
|
||||||
@ -217,26 +161,17 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewProcessRelation",
|
name: "ViewProcessRelation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/tab/:activeTabIndex",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/tab/:activeTabIndex",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewProcessRelationActiveTabIndex",
|
name: "ViewProcessRelationActiveTabIndex",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/duration/:duration",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/duration/:duration",
|
||||||
component: () =>
|
component: () => import("@/views/dashboard/Edit.vue"),
|
||||||
import(
|
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
|
||||||
),
|
|
||||||
name: "ViewProcessRelationDuration",
|
name: "ViewProcessRelationDuration",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -14,21 +14,17 @@
|
|||||||
* 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 { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import { routesDashboard } from "./dashboard";
|
import { routesDashboard } from "./dashboard";
|
||||||
import { routesSetting } from "./setting";
|
import { routesSetting } from "./setting";
|
||||||
import { routesAlarm } from "./alarm";
|
import { routesAlarm } from "./alarm";
|
||||||
import routesLayers from "./layer";
|
import routesLayers from "./layer";
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [...routesLayers, ...routesDashboard, ...routesAlarm, ...routesSetting];
|
||||||
...routesLayers,
|
|
||||||
...routesDashboard,
|
|
||||||
...routesAlarm,
|
|
||||||
...routesSetting,
|
|
||||||
];
|
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(process.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes,
|
routes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@ function layerDashboards() {
|
|||||||
item.component = Layout;
|
item.component = Layout;
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
item.children = item.children.map((d: any) => {
|
item.children = item.children.map((d: any) => {
|
||||||
d.component = () =>
|
d.component = () => import("@/views/Layer.vue");
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue");
|
|
||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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 { RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import Layout from "@/layout/Index.vue";
|
import Layout from "@/layout/Index.vue";
|
||||||
|
|
||||||
export const routesSetting: Array<RouteRecordRaw> = [
|
export const routesSetting: Array<RouteRecordRaw> = [
|
||||||
@ -36,8 +36,7 @@ export const routesSetting: Array<RouteRecordRaw> = [
|
|||||||
icon: "settings",
|
icon: "settings",
|
||||||
hasGroup: false,
|
hasGroup: false,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () => import("@/views/Settings.vue"),
|
||||||
import(/* webpackChunkName: "settings" */ "@/views/Settings.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { Alarm } from "@/types/alarm";
|
import type { Alarm } from "@/types/alarm";
|
||||||
|
|
||||||
interface AlarmState {
|
interface AlarmState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@ -35,9 +35,7 @@ export const alarmStore = defineStore({
|
|||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async getAlarms(params: any) {
|
async getAlarms(params: any) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryAlarms").params(params);
|
||||||
.query("queryAlarms")
|
|
||||||
.params(params);
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { Duration, DurationTime } from "@/types/app";
|
import type { Duration, DurationTime } from "@/types/app";
|
||||||
import getLocalTime from "@/utils/localtime";
|
import getLocalTime from "@/utils/localtime";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
|
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
|
||||||
import { TimeType } from "@/constants/data";
|
import { TimeType } from "@/constants/data";
|
||||||
/*global Nullable*/
|
/*global Nullable*/
|
||||||
@ -92,9 +92,7 @@ export const appStore = defineStore({
|
|||||||
this.duration.start.getMonth());
|
this.duration.start.getMonth());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const utcSpace =
|
const utcSpace = (this.utcHour + new Date().getTimezoneOffset() / 60) * 3600000 + this.utcMin * 60000;
|
||||||
(this.utcHour + new Date().getTimezoneOffset() / 60) * 3600000 +
|
|
||||||
this.utcMin * 60000;
|
|
||||||
const startUnix: number = this.duration.start.getTime();
|
const startUnix: number = this.duration.start.getTime();
|
||||||
const endUnix: number = this.duration.end.getTime();
|
const endUnix: number = this.duration.end.getTime();
|
||||||
const timeIntervals: number[] = [];
|
const timeIntervals: number[] = [];
|
||||||
@ -157,13 +155,11 @@ export const appStore = defineStore({
|
|||||||
this.eventStack.forEach((event: any) => {
|
this.eventStack.forEach((event: any) => {
|
||||||
setTimeout(event(), 0);
|
setTimeout(event(), 0);
|
||||||
}),
|
}),
|
||||||
500
|
500,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async queryOAPTimeInfo() {
|
async queryOAPTimeInfo() {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryOAPTimeInfo").params({});
|
||||||
.query("queryOAPTimeInfo")
|
|
||||||
.params({});
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.utc = -(new Date().getTimezoneOffset() / 60) + ":0";
|
this.utc = -(new Date().getTimezoneOffset() / 60) + ":0";
|
||||||
} else {
|
} else {
|
||||||
@ -176,9 +172,7 @@ export const appStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async fetchVersion(): Promise<void> {
|
async fetchVersion(): Promise<void> {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryOAPVersion").params({});
|
||||||
.query("queryOAPVersion")
|
|
||||||
.params({});
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig } from "@/types/dashboard";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import query from "@/graphql/fetch";
|
import query from "@/graphql/fetch";
|
||||||
import { DashboardItem } from "@/types/dashboard";
|
import type { DashboardItem } from "@/types/dashboard";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { NewControl, TextConfig, TimeRangeConfig } from "../data";
|
import { NewControl, TextConfig, TimeRangeConfig } from "../data";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { EntityType } from "@/views/dashboard/data";
|
import { EntityType } from "@/views/dashboard/data";
|
||||||
@ -105,24 +105,10 @@ export const dashboardStore = defineStore({
|
|||||||
newItem.h = 36;
|
newItem.h = 36;
|
||||||
newItem.graph = {
|
newItem.graph = {
|
||||||
showDepth: true,
|
showDepth: true,
|
||||||
depth:
|
depth: this.entity === EntityType[1].value ? 1 : this.entity === EntityType[0].value ? 2 : 3,
|
||||||
this.entity === EntityType[1].value
|
|
||||||
? 1
|
|
||||||
: this.entity === EntityType[0].value
|
|
||||||
? 2
|
|
||||||
: 3,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (["Trace", "Profile", "Log", "DemandLog", "Ebpf", "NetworkProfiling"].includes(type)) {
|
||||||
[
|
|
||||||
"Trace",
|
|
||||||
"Profile",
|
|
||||||
"Log",
|
|
||||||
"DemandLog",
|
|
||||||
"Ebpf",
|
|
||||||
"NetworkProfiling",
|
|
||||||
].includes(type)
|
|
||||||
) {
|
|
||||||
newItem.h = 36;
|
newItem.h = 36;
|
||||||
}
|
}
|
||||||
if (type === "Text") {
|
if (type === "Text") {
|
||||||
@ -156,14 +142,12 @@ export const dashboardStore = defineStore({
|
|||||||
},
|
},
|
||||||
addTabControls(type: string) {
|
addTabControls(type: string) {
|
||||||
const activedGridItem = this.activedGridItem.split("-")[0];
|
const activedGridItem = this.activedGridItem.split("-")[0];
|
||||||
const idx = this.layout.findIndex(
|
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem);
|
||||||
(d: LayoutConfig) => d.i === activedGridItem
|
|
||||||
);
|
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const tabIndex = this.layout[idx].activedTabIndex || 0;
|
const tabIndex = this.layout[idx].activedTabIndex || 0;
|
||||||
const { children } = this.layout[idx].children[tabIndex];
|
const { children } = (this.layout[idx].children || [])[tabIndex];
|
||||||
const arr = children.map((d: any) => Number(d.i));
|
const arr = children.map((d: any) => Number(d.i));
|
||||||
let index = String(Math.max(...arr) + 1);
|
let index = String(Math.max(...arr) + 1);
|
||||||
if (!children.length) {
|
if (!children.length) {
|
||||||
@ -184,16 +168,7 @@ export const dashboardStore = defineStore({
|
|||||||
showDepth: true,
|
showDepth: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (["Trace", "Profile", "Log", "DemandLog", "Ebpf", "NetworkProfiling"].includes(type)) {
|
||||||
[
|
|
||||||
"Trace",
|
|
||||||
"Profile",
|
|
||||||
"Log",
|
|
||||||
"DemandLog",
|
|
||||||
"Ebpf",
|
|
||||||
"NetworkProfiling",
|
|
||||||
].includes(type)
|
|
||||||
) {
|
|
||||||
newItem.h = 32;
|
newItem.h = 32;
|
||||||
}
|
}
|
||||||
if (type === "Text") {
|
if (type === "Text") {
|
||||||
@ -211,7 +186,7 @@ export const dashboardStore = defineStore({
|
|||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
items.push(newItem);
|
items.push(newItem);
|
||||||
this.layout[idx].children[tabIndex].children = items;
|
(this.layout[idx].children || [])[tabIndex].children = items;
|
||||||
this.currentTabItems = items;
|
this.currentTabItems = items;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -238,19 +213,15 @@ export const dashboardStore = defineStore({
|
|||||||
},
|
},
|
||||||
removeControls(item: LayoutConfig) {
|
removeControls(item: LayoutConfig) {
|
||||||
const actived = this.activedGridItem.split("-");
|
const actived = this.activedGridItem.split("-");
|
||||||
const index = this.layout.findIndex(
|
const index = this.layout.findIndex((d: LayoutConfig) => actived[0] === d.i);
|
||||||
(d: LayoutConfig) => actived[0] === d.i
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.selectedGrid && this.selectedGrid.i === item.i) {
|
if (this.selectedGrid && this.selectedGrid.i === item.i) {
|
||||||
this.selectedGrid = null;
|
this.selectedGrid = null;
|
||||||
}
|
}
|
||||||
if (actived.length === 3) {
|
if (actived.length === 3) {
|
||||||
const tabIndex = Number(actived[1]);
|
const tabIndex = Number(actived[1]);
|
||||||
this.currentTabItems = this.currentTabItems.filter(
|
this.currentTabItems = this.currentTabItems.filter((d: LayoutConfig) => actived[2] !== d.i);
|
||||||
(d: LayoutConfig) => actived[2] !== d.i
|
(this.layout[index].children || [])[tabIndex].children = this.currentTabItems;
|
||||||
);
|
|
||||||
this.layout[index].children[tabIndex].children = this.currentTabItems;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.layout = this.layout.filter((d: LayoutConfig) => d.i !== item.i);
|
this.layout = this.layout.filter((d: LayoutConfig) => d.i !== item.i);
|
||||||
@ -258,8 +229,8 @@ export const dashboardStore = defineStore({
|
|||||||
removeTabItem(item: LayoutConfig, index: number) {
|
removeTabItem(item: LayoutConfig, index: number) {
|
||||||
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === item.i);
|
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === item.i);
|
||||||
if (this.selectedGrid) {
|
if (this.selectedGrid) {
|
||||||
for (const item of this.layout[idx].children[index].children) {
|
for (const item of (this.layout[idx].children || [])[index].children) {
|
||||||
if (this.selectedGrid.i === item.i) {
|
if (this.selectedGrid?.i === item.i) {
|
||||||
this.selectedGrid = null;
|
this.selectedGrid = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,22 +256,19 @@ export const dashboardStore = defineStore({
|
|||||||
},
|
},
|
||||||
setConfigs(param: { [key: string]: unknown }) {
|
setConfigs(param: { [key: string]: unknown }) {
|
||||||
const actived = this.activedGridItem.split("-");
|
const actived = this.activedGridItem.split("-");
|
||||||
const index = this.layout.findIndex(
|
const index = this.layout.findIndex((d: LayoutConfig) => actived[0] === d.i);
|
||||||
(d: LayoutConfig) => actived[0] === d.i
|
|
||||||
);
|
|
||||||
if (actived.length === 3) {
|
if (actived.length === 3) {
|
||||||
const tabIndex = Number(actived[1]);
|
const tabIndex = Number(actived[1]);
|
||||||
const itemIndex = this.layout[index].children[
|
const itemIndex = (this.layout[index].children || [])[tabIndex].children.findIndex(
|
||||||
tabIndex
|
(d: LayoutConfig) => actived[2] === d.i,
|
||||||
].children.findIndex((d: LayoutConfig) => actived[2] === d.i);
|
);
|
||||||
|
|
||||||
this.layout[index].children[tabIndex].children[itemIndex] = {
|
(this.layout[index].children || [])[tabIndex].children[itemIndex] = {
|
||||||
...this.layout[index].children[tabIndex].children[itemIndex],
|
...(this.layout[index].children || [])[tabIndex].children[itemIndex],
|
||||||
...param,
|
...param,
|
||||||
};
|
};
|
||||||
this.selectedGrid =
|
this.selectedGrid = (this.layout[index].children || [])[tabIndex].children[itemIndex];
|
||||||
this.layout[index].children[tabIndex].children[itemIndex];
|
this.setCurrentTabItems((this.layout[index].children || [])[tabIndex].children);
|
||||||
this.setCurrentTabItems(this.layout[index].children[tabIndex].children);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.layout[index] = {
|
this.layout[index] = {
|
||||||
@ -312,8 +280,8 @@ export const dashboardStore = defineStore({
|
|||||||
setWidget(param: LayoutConfig) {
|
setWidget(param: LayoutConfig) {
|
||||||
for (let i = 0; i < this.layout.length; i++) {
|
for (let i = 0; i < this.layout.length; i++) {
|
||||||
if (this.layout[i].type === "Tab") {
|
if (this.layout[i].type === "Tab") {
|
||||||
if (this.layout[i].children && this.layout[i].children.length) {
|
if ((this.layout[i].children || []).length) {
|
||||||
for (const child of this.layout[i].children) {
|
for (const child of this.layout[i].children || []) {
|
||||||
if (child.children && child.children.length) {
|
if (child.children && child.children.length) {
|
||||||
for (let c = 0; c < child.children.length; c++) {
|
for (let c = 0; c < child.children.length; c++) {
|
||||||
if (child.children[c].id === param.id) {
|
if (child.children[c].id === param.id) {
|
||||||
@ -332,23 +300,16 @@ export const dashboardStore = defineStore({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetchMetricType(item: string) {
|
async fetchMetricType(item: string) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryTypeOfMetrics").params({ name: item });
|
||||||
.query("queryTypeOfMetrics")
|
|
||||||
.params({ name: item });
|
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async fetchMetricList(regex: string) {
|
async fetchMetricList(regex: string) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryMetrics").params({ regex });
|
||||||
.query("queryMetrics")
|
|
||||||
.params({ regex });
|
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async fetchMetricValue(param: {
|
async fetchMetricValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
|
||||||
queryStr: string;
|
|
||||||
conditions: { [key: string]: unknown };
|
|
||||||
}) {
|
|
||||||
const res: AxiosResponse = await query(param);
|
const res: AxiosResponse = await query(param);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
@ -371,10 +332,7 @@ export const dashboardStore = defineStore({
|
|||||||
name: c.name,
|
name: c.name,
|
||||||
isRoot: c.isRoot,
|
isRoot: c.isRoot,
|
||||||
});
|
});
|
||||||
sessionStorage.setItem(
|
sessionStorage.setItem(key, JSON.stringify({ id: t.id, configuration: c }));
|
||||||
key,
|
|
||||||
JSON.stringify({ id: t.id, configuration: c })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
list = list.sort((a, b) => {
|
list = list.sort((a, b) => {
|
||||||
const nameA = a.name.toUpperCase();
|
const nameA = a.name.toUpperCase();
|
||||||
@ -399,9 +357,7 @@ export const dashboardStore = defineStore({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.dashboards = JSON.parse(
|
this.dashboards = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
sessionStorage.getItem("dashboards") || "[]"
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
async resetTemplates() {
|
async resetTemplates() {
|
||||||
const res = await this.fetchTemplates();
|
const res = await this.fetchTemplates();
|
||||||
@ -410,9 +366,7 @@ export const dashboardStore = defineStore({
|
|||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.dashboards = JSON.parse(
|
this.dashboards = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
sessionStorage.getItem("dashboards") || "[]"
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
async updateDashboard(setting: { id: string; configuration: string }) {
|
async updateDashboard(setting: { id: string; configuration: string }) {
|
||||||
const res: AxiosResponse = await graphql.query("updateTemplate").params({
|
const res: AxiosResponse = await graphql.query("updateTemplate").params({
|
||||||
@ -431,7 +385,7 @@ export const dashboardStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async saveDashboard() {
|
async saveDashboard() {
|
||||||
if (!this.currentDashboard.name) {
|
if (!this.currentDashboard?.name) {
|
||||||
ElMessage.error("The dashboard name is needed.");
|
ElMessage.error("The dashboard name is needed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -452,18 +406,16 @@ export const dashboardStore = defineStore({
|
|||||||
c.isRoot = false;
|
c.isRoot = false;
|
||||||
const index = this.dashboards.findIndex(
|
const index = this.dashboards.findIndex(
|
||||||
(d: DashboardItem) =>
|
(d: DashboardItem) =>
|
||||||
d.name === this.currentDashboard.name &&
|
d.name === this.currentDashboard?.name &&
|
||||||
d.entity === this.currentDashboard.entity &&
|
d.entity === this.currentDashboard.entity &&
|
||||||
d.layer === this.currentDashboard.layerId
|
d.layer === this.currentDashboard?.layer,
|
||||||
);
|
);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
ElMessage.error(t("nameError"));
|
ElMessage.error(t("nameError"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res = await graphql
|
res = await graphql.query("addNewTemplate").params({ setting: { configuration: JSON.stringify(c) } });
|
||||||
.query("addNewTemplate")
|
|
||||||
.params({ setting: { configuration: JSON.stringify(c) } });
|
|
||||||
|
|
||||||
json = res.data.data.addTemplate;
|
json = res.data.data.addTemplate;
|
||||||
}
|
}
|
||||||
@ -478,17 +430,11 @@ export const dashboardStore = defineStore({
|
|||||||
if (!this.currentDashboard.id) {
|
if (!this.currentDashboard.id) {
|
||||||
ElMessage.success("Saved successfully");
|
ElMessage.success("Saved successfully");
|
||||||
}
|
}
|
||||||
const key = [
|
const key = [this.currentDashboard.layer, this.currentDashboard.entity, this.currentDashboard.name].join("_");
|
||||||
this.currentDashboard.layer,
|
|
||||||
this.currentDashboard.entity,
|
|
||||||
this.currentDashboard.name,
|
|
||||||
].join("_");
|
|
||||||
this.currentDashboard.id = json.id;
|
this.currentDashboard.id = json.id;
|
||||||
if (this.currentDashboard.id) {
|
if (this.currentDashboard.id) {
|
||||||
sessionStorage.removeItem(key);
|
sessionStorage.removeItem(key);
|
||||||
this.dashboards = this.dashboards.filter(
|
this.dashboards = this.dashboards.filter((d: DashboardItem) => d.id !== this.currentDashboard?.id);
|
||||||
(d: DashboardItem) => d.id !== this.currentDashboard.id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this.dashboards.push(this.currentDashboard);
|
this.dashboards.push(this.currentDashboard);
|
||||||
const l = { id: json.id, configuration: c };
|
const l = { id: json.id, configuration: c };
|
||||||
@ -498,9 +444,7 @@ export const dashboardStore = defineStore({
|
|||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
async deleteDashboard() {
|
async deleteDashboard() {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("removeTemplate").params({ id: this.currentDashboard?.id });
|
||||||
.query("removeTemplate")
|
|
||||||
.params({ id: this.currentDashboard.id });
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
ElMessage.error(res.data.errors);
|
ElMessage.error(res.data.errors);
|
||||||
@ -511,14 +455,8 @@ export const dashboardStore = defineStore({
|
|||||||
ElMessage.error(json.message);
|
ElMessage.error(json.message);
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.dashboards = this.dashboards.filter(
|
this.dashboards = this.dashboards.filter((d: any) => d.id !== this.currentDashboard?.id);
|
||||||
(d: any) => d.id !== this.currentDashboard.id
|
const key = [this.currentDashboard?.layer, this.currentDashboard?.entity, this.currentDashboard?.name].join("_");
|
||||||
);
|
|
||||||
const key = [
|
|
||||||
this.currentDashboard.layer,
|
|
||||||
this.currentDashboard.entity,
|
|
||||||
this.currentDashboard.name,
|
|
||||||
].join("_");
|
|
||||||
sessionStorage.removeItem(key);
|
sessionStorage.removeItem(key);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Instance } from "@/types/selector";
|
import type { Instance } from "@/types/selector";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { Conditions, Log } from "@/types/demand-log";
|
import type { Conditions, Log } from "@/types/demand-log";
|
||||||
|
|
||||||
interface DemandLogState {
|
interface DemandLogState {
|
||||||
containers: Instance[];
|
containers: Instance[];
|
||||||
@ -59,9 +59,7 @@ export const demandLogStore = defineStore({
|
|||||||
this.message = message || "";
|
this.message = message || "";
|
||||||
},
|
},
|
||||||
async getInstances(id: string) {
|
async getInstances(id: string) {
|
||||||
const serviceId = this.selectorStore.currentService
|
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
|
||||||
? this.selectorStore.currentService.id
|
|
||||||
: id;
|
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -75,16 +73,12 @@ export const demandLogStore = defineStore({
|
|||||||
},
|
},
|
||||||
async getContainers(serviceInstanceId: string) {
|
async getContainers(serviceInstanceId: string) {
|
||||||
if (!serviceInstanceId) {
|
if (!serviceInstanceId) {
|
||||||
return new Promise((resolve) =>
|
return new Promise((resolve) => resolve({ errors: "No service instance" }));
|
||||||
resolve({ errors: "No service instance" })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const condition = {
|
const condition = {
|
||||||
serviceInstanceId,
|
serviceInstanceId,
|
||||||
};
|
};
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("fetchContainers").params({ condition });
|
||||||
.query("fetchContainers")
|
|
||||||
.params({ condition });
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -100,21 +94,17 @@ export const demandLogStore = defineStore({
|
|||||||
},
|
},
|
||||||
async getDemandLogs() {
|
async getDemandLogs() {
|
||||||
this.loadLogs = true;
|
this.loadLogs = true;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("fetchDemandPodLogs").params({ condition: this.conditions });
|
||||||
.query("fetchDemandPodLogs")
|
|
||||||
.params({ condition: this.conditions });
|
|
||||||
this.loadLogs = false;
|
this.loadLogs = false;
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
if (res.data.data.logs.errorReason) {
|
if (res.data.data.logs.errorReason) {
|
||||||
this.setLogs("", res.data.data.logs.errorReason);
|
this.setLogs([], res.data.data.logs.errorReason);
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.total = res.data.data.logs.logs.length;
|
this.total = res.data.data.logs.logs.length;
|
||||||
const logs = res.data.data.logs.logs
|
const logs = res.data.data.logs.logs.map((d: Log) => d.content).join("\n");
|
||||||
.map((d: Log) => d.content)
|
|
||||||
.join("\n");
|
|
||||||
this.setLogs(logs);
|
this.setLogs(logs);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
@ -15,18 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Option } from "@/types/app";
|
import type { Option } from "@/types/app";
|
||||||
import {
|
import type { EBPFTaskCreationRequest, EBPFProfilingSchedule, EBPFTaskList, AnalyzationTrees } from "@/types/ebpf";
|
||||||
EBPFTaskCreationRequest,
|
|
||||||
EBPFProfilingSchedule,
|
|
||||||
EBPFTaskList,
|
|
||||||
AnalyzationTrees,
|
|
||||||
} from "@/types/ebpf";
|
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
interface EbpfState {
|
interface EbpfState {
|
||||||
taskList: EBPFTaskList[];
|
taskList: Array<Recordable<EBPFTaskList>>;
|
||||||
eBPFSchedules: EBPFProfilingSchedule[];
|
eBPFSchedules: EBPFProfilingSchedule[];
|
||||||
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
||||||
analyzeTrees: AnalyzationTrees[];
|
analyzeTrees: AnalyzationTrees[];
|
||||||
@ -51,7 +46,7 @@ export const ebpfStore = defineStore({
|
|||||||
aggregateType: "COUNT",
|
aggregateType: "COUNT",
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setSelectedTask(task: EBPFTaskList) {
|
setSelectedTask(task: Recordable<EBPFTaskList>) {
|
||||||
this.selectedTask = task || {};
|
this.selectedTask = task || {};
|
||||||
},
|
},
|
||||||
setCurrentSchedule(s: EBPFProfilingSchedule) {
|
setCurrentSchedule(s: EBPFProfilingSchedule) {
|
||||||
@ -61,9 +56,7 @@ export const ebpfStore = defineStore({
|
|||||||
this.analyzeTrees = tree;
|
this.analyzeTrees = tree;
|
||||||
},
|
},
|
||||||
async getCreateTaskData(serviceId: string) {
|
async getCreateTaskData(serviceId: string) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getCreateTaskData").params({ serviceId });
|
||||||
.query("getCreateTaskData")
|
|
||||||
.params({ serviceId });
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -76,9 +69,7 @@ export const ebpfStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async createTask(param: EBPFTaskCreationRequest) {
|
async createTask(param: EBPFTaskCreationRequest) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("saveEBPFTask").params({ request: param });
|
||||||
.query("saveEBPFTask")
|
|
||||||
.params({ request: param });
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -89,17 +80,11 @@ export const ebpfStore = defineStore({
|
|||||||
});
|
});
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskList(params: {
|
async getTaskList(params: { serviceId: string; targets: string[] }) {
|
||||||
serviceId: string;
|
|
||||||
serviceInstanceId: string;
|
|
||||||
targets: string[];
|
|
||||||
}) {
|
|
||||||
if (!params.serviceId) {
|
if (!params.serviceId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
|
||||||
.query("getEBPFTasks")
|
|
||||||
.params(params);
|
|
||||||
|
|
||||||
this.tip = "";
|
this.tip = "";
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -111,16 +96,14 @@ export const ebpfStore = defineStore({
|
|||||||
if (!this.taskList.length) {
|
if (!this.taskList.length) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.getEBPFSchedules({ taskId: this.taskList[0].taskId });
|
this.getEBPFSchedules({ taskId: String(this.taskList[0].taskId) });
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEBPFSchedules(params: { taskId: string }) {
|
async getEBPFSchedules(params: { taskId: string }) {
|
||||||
if (!params.taskId) {
|
if (!params.taskId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getEBPFSchedules").params({ ...params });
|
||||||
.query("getEBPFSchedules")
|
|
||||||
.params({ ...params });
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.eBPFSchedules = [];
|
this.eBPFSchedules = [];
|
||||||
@ -148,9 +131,7 @@ export const ebpfStore = defineStore({
|
|||||||
if (!params.timeRanges.length) {
|
if (!params.timeRanges.length) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getEBPFResult").params(params);
|
||||||
.query("getEBPFResult")
|
|
||||||
.params(params);
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { Event, QueryEventCondition } from "@/types/events";
|
import type { Event, QueryEventCondition } from "@/types/events";
|
||||||
import { Instance, Endpoint } from "@/types/selector";
|
import type { Instance, Endpoint } from "@/types/selector";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
|
||||||
@ -45,9 +45,7 @@ export const eventStore = defineStore({
|
|||||||
this.condition = data;
|
this.condition = data;
|
||||||
},
|
},
|
||||||
async getInstances() {
|
async getInstances() {
|
||||||
const serviceId = useSelectorStore().currentService
|
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
|
||||||
? useSelectorStore().currentService.id
|
|
||||||
: "";
|
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -56,15 +54,11 @@ export const eventStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.instances = [{ value: "", label: "All" }, ...res.data.data.pods] || [
|
this.instances = [{ value: "", label: "All" }, ...res.data.data.pods] || [{ value: "", label: "All" }];
|
||||||
{ value: "", label: "All" },
|
|
||||||
];
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEndpoints() {
|
async getEndpoints() {
|
||||||
const serviceId = useSelectorStore().currentService
|
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
|
||||||
? useSelectorStore().currentService.id
|
|
||||||
: "";
|
|
||||||
if (!serviceId) {
|
if (!serviceId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -76,9 +70,7 @@ export const eventStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.endpoints = [{ value: "", label: "All" }, ...res.data.data.pods] || [
|
this.endpoints = [{ value: "", label: "All" }, ...res.data.data.pods] || [{ value: "", label: "All" }];
|
||||||
{ value: "", label: "All" },
|
|
||||||
];
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEvents() {
|
async getEvents() {
|
||||||
@ -94,8 +86,7 @@ export const eventStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
if (res.data.data.fetchEvents) {
|
if (res.data.data.fetchEvents) {
|
||||||
this.events = (res.data.data.fetchEvents.events || []).map(
|
this.events = (res.data.data.fetchEvents.events || []).map((item: Event) => {
|
||||||
(item: Event) => {
|
|
||||||
let scope = "Service";
|
let scope = "Service";
|
||||||
if (item.source.serviceInstance) {
|
if (item.source.serviceInstance) {
|
||||||
scope = "ServiceInstance";
|
scope = "ServiceInstance";
|
||||||
@ -108,8 +99,7 @@ export const eventStore = defineStore({
|
|||||||
item.endTime = Number(item.startTime) + 60000;
|
item.endTime = Number(item.startTime) + 60000;
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import type { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
@ -71,9 +71,7 @@ export const logStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getInstances(id: string) {
|
async getInstances(id: string) {
|
||||||
const serviceId = this.selectorStore.currentService
|
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
|
||||||
? this.selectorStore.currentService.id
|
|
||||||
: id;
|
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -82,16 +80,11 @@ export const logStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.instances = [
|
this.instances = [{ value: "0", label: "All" }, ...res.data.data.pods] || [{ value: " 0", label: "All" }];
|
||||||
{ value: "0", label: "All" },
|
|
||||||
...res.data.data.pods,
|
|
||||||
] || [{ value: " 0", label: "All" }];
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEndpoints(id: string, keyword?: string) {
|
async getEndpoints(id: string, keyword?: string) {
|
||||||
const serviceId = this.selectorStore.currentService
|
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
|
||||||
? this.selectorStore.currentService.id
|
|
||||||
: id;
|
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -100,16 +93,11 @@ export const logStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.endpoints = [
|
this.endpoints = [{ value: "0", label: "All" }, ...res.data.data.pods] || [{ value: "0", label: "All" }];
|
||||||
{ value: "0", label: "All" },
|
|
||||||
...res.data.data.pods,
|
|
||||||
] || [{ value: "0", label: "All" }];
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getLogsByKeywords() {
|
async getLogsByKeywords() {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryLogsByKeywords").params({});
|
||||||
.query("queryLogsByKeywords")
|
|
||||||
.params({});
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -127,9 +115,7 @@ export const logStore = defineStore({
|
|||||||
},
|
},
|
||||||
async getServiceLogs() {
|
async getServiceLogs() {
|
||||||
this.loadLogs = true;
|
this.loadLogs = true;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryServiceLogs").params({ condition: this.conditions });
|
||||||
.query("queryServiceLogs")
|
|
||||||
.params({ condition: this.conditions });
|
|
||||||
this.loadLogs = false;
|
this.loadLogs = false;
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -140,9 +126,7 @@ export const logStore = defineStore({
|
|||||||
},
|
},
|
||||||
async getBrowserLogs() {
|
async getBrowserLogs() {
|
||||||
this.loadLogs = true;
|
this.loadLogs = true;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryBrowserErrorLogs").params({ condition: this.conditions });
|
||||||
.query("queryBrowserErrorLogs")
|
|
||||||
.params({ condition: this.conditions });
|
|
||||||
|
|
||||||
this.loadLogs = false;
|
this.loadLogs = false;
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { EBPFTaskList, ProcessNode } from "@/types/ebpf";
|
import type { EBPFTaskList, ProcessNode } from "@/types/ebpf";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { Call } from "@/types/topology";
|
import type { Call } from "@/types/topology";
|
||||||
import { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig } from "@/types/dashboard";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
interface NetworkProfilingState {
|
interface NetworkProfilingState {
|
||||||
networkTasks: EBPFTaskList[];
|
networkTasks: Array<Recordable<EBPFTaskList>>;
|
||||||
networkTip: string;
|
networkTip: string;
|
||||||
selectedNetworkTask: Recordable<EBPFTaskList>;
|
selectedNetworkTask: Recordable<EBPFTaskList>;
|
||||||
nodes: ProcessNode[];
|
nodes: ProcessNode[];
|
||||||
@ -55,10 +55,10 @@ export const networkProfilingStore = defineStore({
|
|||||||
loadNodes: false,
|
loadNodes: false,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setSelectedNetworkTask(task: EBPFTaskList) {
|
setSelectedNetworkTask(task: Recordable<EBPFTaskList>) {
|
||||||
this.selectedNetworkTask = task || {};
|
this.selectedNetworkTask = task || {};
|
||||||
},
|
},
|
||||||
setNode(node: Node) {
|
setNode(node: Nullable<ProcessNode>) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
},
|
},
|
||||||
setLink(link: Call) {
|
setLink(link: Call) {
|
||||||
@ -117,11 +117,9 @@ export const networkProfilingStore = defineStore({
|
|||||||
when4xx: string;
|
when4xx: string;
|
||||||
when5xx: string;
|
when5xx: string;
|
||||||
minDuration: number;
|
minDuration: number;
|
||||||
}[]
|
}[],
|
||||||
) {
|
) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("newNetworkProfiling").params({
|
||||||
.query("newNetworkProfiling")
|
|
||||||
.params({
|
|
||||||
request: {
|
request: {
|
||||||
instanceId,
|
instanceId,
|
||||||
samplings: params,
|
samplings: params,
|
||||||
@ -133,17 +131,11 @@ export const networkProfilingStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskList(params: {
|
async getTaskList(params: { serviceId: string; serviceInstanceId: string; targets: string[] }) {
|
||||||
serviceId: string;
|
|
||||||
serviceInstanceId: string;
|
|
||||||
targets: string[];
|
|
||||||
}) {
|
|
||||||
if (!params.serviceId) {
|
if (!params.serviceId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
|
||||||
.query("getEBPFTasks")
|
|
||||||
.params(params);
|
|
||||||
|
|
||||||
this.networkTip = "";
|
this.networkTip = "";
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -162,11 +154,8 @@ export const networkProfilingStore = defineStore({
|
|||||||
if (!taskId) {
|
if (!taskId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("aliveNetworkProfiling").params({ taskId });
|
||||||
.query("aliveNetworkProfiling")
|
|
||||||
.params({ taskId });
|
|
||||||
|
|
||||||
this.aliveMessage = "";
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
@ -176,14 +165,9 @@ export const networkProfilingStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getProcessTopology(params: {
|
async getProcessTopology(params: { duration: any; serviceInstanceId: string }) {
|
||||||
duration: any;
|
|
||||||
serviceInstanceId: string;
|
|
||||||
}) {
|
|
||||||
this.loadNodes = true;
|
this.loadNodes = true;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getProcessTopology").params(params);
|
||||||
.query("getProcessTopology")
|
|
||||||
.params(params);
|
|
||||||
this.loadNodes = false;
|
this.loadNodes = false;
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
|
@ -15,18 +15,18 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Endpoint } from "@/types/selector";
|
import type { Endpoint } from "@/types/selector";
|
||||||
import {
|
import type {
|
||||||
TaskListItem,
|
TaskListItem,
|
||||||
SegmentSpan,
|
SegmentSpan,
|
||||||
ProfileAnalyzationTrees,
|
ProfileAnalyzationTrees,
|
||||||
TaskLog,
|
TaskLog,
|
||||||
ProfileTaskCreationRequest,
|
ProfileTaskCreationRequest,
|
||||||
} from "@/types/profile";
|
} from "@/types/profile";
|
||||||
import { Trace, Span } from "@/types/trace";
|
import type { Trace } from "@/types/trace";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
interface ProfileState {
|
interface ProfileState {
|
||||||
@ -35,9 +35,9 @@ interface ProfileState {
|
|||||||
condition: { serviceId: string; endpointName: string };
|
condition: { serviceId: string; endpointName: string };
|
||||||
taskList: TaskListItem[];
|
taskList: TaskListItem[];
|
||||||
segmentList: Trace[];
|
segmentList: Trace[];
|
||||||
currentSegment: Trace | Record<string, never>;
|
currentSegment: Recordable<Trace>;
|
||||||
segmentSpans: SegmentSpan[];
|
segmentSpans: Array<Recordable<SegmentSpan>>;
|
||||||
currentSpan: SegmentSpan | Record<string, never>;
|
currentSpan: Recordable<SegmentSpan>;
|
||||||
analyzeTrees: ProfileAnalyzationTrees;
|
analyzeTrees: ProfileAnalyzationTrees;
|
||||||
taskLogs: TaskLog[];
|
taskLogs: TaskLog[];
|
||||||
highlightTop: boolean;
|
highlightTop: boolean;
|
||||||
@ -65,10 +65,10 @@ export const profileStore = defineStore({
|
|||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setCurrentSpan(span: Span) {
|
setCurrentSpan(span: Recordable<SegmentSpan>) {
|
||||||
this.currentSpan = span;
|
this.currentSpan = span;
|
||||||
},
|
},
|
||||||
setCurrentSegment(s: Trace) {
|
setCurrentSegment(s: Recordable<Trace>) {
|
||||||
this.currentSegment = s;
|
this.currentSegment = s;
|
||||||
},
|
},
|
||||||
setHighlightTop() {
|
setHighlightTop() {
|
||||||
@ -99,9 +99,7 @@ export const profileStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskList() {
|
async getTaskList() {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getProfileTaskList").params(this.condition);
|
||||||
.query("getProfileTaskList")
|
|
||||||
.params(this.condition);
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -122,9 +120,7 @@ export const profileStore = defineStore({
|
|||||||
if (!params.taskID) {
|
if (!params.taskID) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getProfileTaskSegmentList").params(params);
|
||||||
.query("getProfileTaskSegmentList")
|
|
||||||
.params(params);
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.segmentList = [];
|
this.segmentList = [];
|
||||||
@ -143,7 +139,7 @@ export const profileStore = defineStore({
|
|||||||
this.currentSegment = segmentList[0];
|
this.currentSegment = segmentList[0];
|
||||||
this.getSegmentSpans({ segmentId: segmentList[0].segmentId });
|
this.getSegmentSpans({ segmentId: segmentList[0].segmentId });
|
||||||
} else {
|
} else {
|
||||||
this.currentSegment = null;
|
this.currentSegment = {};
|
||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
@ -151,9 +147,7 @@ export const profileStore = defineStore({
|
|||||||
if (!params.segmentId) {
|
if (!params.segmentId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryProfileSegment").params(params);
|
||||||
.query("queryProfileSegment")
|
|
||||||
.params(params);
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.segmentSpans = [];
|
this.segmentSpans = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -167,8 +161,8 @@ export const profileStore = defineStore({
|
|||||||
this.segmentSpans = segment.spans.map((d: SegmentSpan) => {
|
this.segmentSpans = segment.spans.map((d: SegmentSpan) => {
|
||||||
return {
|
return {
|
||||||
...d,
|
...d,
|
||||||
segmentId: this.currentSegment.segmentId,
|
segmentId: this.currentSegment?.segmentId,
|
||||||
traceId: this.currentSegment.traceIds[0],
|
traceId: (this.currentSegment.traceIds as any)[0],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
if (!(segment.spans && segment.spans.length)) {
|
if (!(segment.spans && segment.spans.length)) {
|
||||||
@ -179,19 +173,14 @@ export const profileStore = defineStore({
|
|||||||
this.currentSpan = segment.spans[index];
|
this.currentSpan = segment.spans[index];
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getProfileAnalyze(params: {
|
async getProfileAnalyze(params: { segmentId: string; timeRanges: Array<{ start: number; end: number }> }) {
|
||||||
segmentId: string;
|
|
||||||
timeRanges: Array<{ start: number; end: number }>;
|
|
||||||
}) {
|
|
||||||
if (!params.segmentId) {
|
if (!params.segmentId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
if (!params.timeRanges.length) {
|
if (!params.timeRanges.length) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getProfileAnalyze").params(params);
|
||||||
.query("getProfileAnalyze")
|
|
||||||
.params(params);
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
@ -211,9 +200,7 @@ export const profileStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async createTask(param: ProfileTaskCreationRequest) {
|
async createTask(param: ProfileTaskCreationRequest) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("saveProfileTask").params({ creationRequest: param });
|
||||||
.query("saveProfileTask")
|
|
||||||
.params({ creationRequest: param });
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -222,9 +209,7 @@ export const profileStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskLogs(param: { taskID: string }) {
|
async getTaskLogs(param: { taskID: string }) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getProfileTaskLogs").params(param);
|
||||||
.query("getProfileTaskLogs")
|
|
||||||
.params(param);
|
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Service, Instance, Endpoint, Process } from "@/types/selector";
|
import type { Service, Instance, Endpoint, Process } from "@/types/selector";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
interface SelectorState {
|
interface SelectorState {
|
||||||
services: Service[];
|
services: Service[];
|
||||||
@ -82,9 +82,7 @@ export const selectorStore = defineStore({
|
|||||||
return res.data || {};
|
return res.data || {};
|
||||||
},
|
},
|
||||||
async fetchServices(layer: string): Promise<AxiosResponse> {
|
async fetchServices(layer: string): Promise<AxiosResponse> {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryServices").params({ layer });
|
||||||
.query("queryServices")
|
|
||||||
.params({ layer });
|
|
||||||
|
|
||||||
if (!res.data.errors) {
|
if (!res.data.errors) {
|
||||||
this.services = res.data.data.services || [];
|
this.services = res.data.data.services || [];
|
||||||
@ -92,10 +90,7 @@ export const selectorStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getServiceInstances(param?: {
|
async getServiceInstances(param?: { serviceId: string; isRelation: boolean }): Promise<Nullable<AxiosResponse>> {
|
||||||
serviceId: string;
|
|
||||||
isRelation: boolean;
|
|
||||||
}): Promise<Nullable<AxiosResponse>> {
|
|
||||||
const serviceId = param ? param.serviceId : this.currentService?.id;
|
const serviceId = param ? param.serviceId : this.currentService?.id;
|
||||||
if (!serviceId) {
|
if (!serviceId) {
|
||||||
return null;
|
return null;
|
||||||
@ -113,10 +108,7 @@ export const selectorStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getProcesses(param?: {
|
async getProcesses(param?: { instanceId: string; isRelation: boolean }): Promise<Nullable<AxiosResponse>> {
|
||||||
instanceId: string;
|
|
||||||
isRelation: boolean;
|
|
||||||
}): Promise<Nullable<AxiosResponse>> {
|
|
||||||
const instanceId = param ? param.instanceId : this.currentPod?.id;
|
const instanceId = param ? param.instanceId : this.currentPod?.id;
|
||||||
if (!instanceId) {
|
if (!instanceId) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import { Service } from "@/types/selector";
|
import type { Service } from "@/types/selector";
|
||||||
import { Node, Call } from "@/types/topology";
|
import type { Node, Call } from "@/types/topology";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
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 { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import query from "@/graphql/fetch";
|
import query from "@/graphql/fetch";
|
||||||
import { useQueryTopologyMetrics } from "@/hooks/useMetricsProcessor";
|
import { useQueryTopologyMetrics } from "@/hooks/useMetricsProcessor";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
@ -105,21 +105,19 @@ export const topologyStore = defineStore({
|
|||||||
this.calls = calls;
|
this.calls = calls;
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
},
|
},
|
||||||
setNodeMetricValue(m: { id: string; value: unknown }[]) {
|
setNodeMetricValue(m: MetricVal) {
|
||||||
this.nodeMetricValue = m;
|
this.nodeMetricValue = m;
|
||||||
},
|
},
|
||||||
setLinkServerMetrics(m: { id: string; value: unknown }[]) {
|
setLinkServerMetrics(m: MetricVal) {
|
||||||
this.linkServerMetrics = m;
|
this.linkServerMetrics = m;
|
||||||
},
|
},
|
||||||
setLinkClientMetrics(m: { id: string; value: unknown }[]) {
|
setLinkClientMetrics(m: MetricVal) {
|
||||||
this.linkClientMetrics = m;
|
this.linkClientMetrics = m;
|
||||||
},
|
},
|
||||||
async getDepthServiceTopology(serviceIds: string[], depth: number) {
|
async getDepthServiceTopology(serviceIds: string[], depth: number) {
|
||||||
const res = await this.getServicesTopology(serviceIds);
|
const res = await this.getServicesTopology(serviceIds);
|
||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
const ids = (res.nodes || [])
|
const ids = (res.nodes || []).map((item: Node) => item.id).filter((d: string) => !serviceIds.includes(d));
|
||||||
.map((item: Node) => item.id)
|
|
||||||
.filter((d: string) => !serviceIds.includes(d));
|
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
this.setTopology(res);
|
this.setTopology(res);
|
||||||
return;
|
return;
|
||||||
@ -139,9 +137,7 @@ export const topologyStore = defineStore({
|
|||||||
if (depth > 3) {
|
if (depth > 3) {
|
||||||
const services = topo.nodes
|
const services = topo.nodes
|
||||||
.map((item: Node) => item.id)
|
.map((item: Node) => item.id)
|
||||||
.filter(
|
.filter((d: string) => ![...ids, ...pods, ...serviceIds].includes(d));
|
||||||
(d: string) => ![...ids, ...pods, ...serviceIds].includes(d)
|
|
||||||
);
|
|
||||||
if (!services.length) {
|
if (!services.length) {
|
||||||
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
|
||||||
const calls = [...res.calls, ...json.calls, ...topo.calls];
|
const calls = [...res.calls, ...json.calls, ...topo.calls];
|
||||||
@ -152,55 +148,20 @@ export const topologyStore = defineStore({
|
|||||||
if (depth > 4) {
|
if (depth > 4) {
|
||||||
const nodeIds = data.nodes
|
const nodeIds = data.nodes
|
||||||
.map((item: Node) => item.id)
|
.map((item: Node) => item.id)
|
||||||
.filter(
|
.filter((d: string) => ![...services, ...ids, ...pods, ...serviceIds].includes(d));
|
||||||
(d: string) =>
|
|
||||||
![...services, ...ids, ...pods, ...serviceIds].includes(d)
|
|
||||||
);
|
|
||||||
if (!nodeIds.length) {
|
if (!nodeIds.length) {
|
||||||
const nodes = [
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
|
||||||
...res.nodes,
|
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
|
||||||
...json.nodes,
|
|
||||||
...topo.nodes,
|
|
||||||
...data.nodes,
|
|
||||||
];
|
|
||||||
const calls = [
|
|
||||||
...res.calls,
|
|
||||||
...json.calls,
|
|
||||||
...topo.calls,
|
|
||||||
...data.calls,
|
|
||||||
];
|
|
||||||
this.setTopology({ nodes, calls });
|
this.setTopology({ nodes, calls });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const toposObj = await this.getServicesTopology(nodeIds);
|
const toposObj = await this.getServicesTopology(nodeIds);
|
||||||
const nodes = [
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes, ...toposObj.nodes];
|
||||||
...res.nodes,
|
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls, ...toposObj.calls];
|
||||||
...json.nodes,
|
|
||||||
...topo.nodes,
|
|
||||||
...data.nodes,
|
|
||||||
...toposObj.nodes,
|
|
||||||
];
|
|
||||||
const calls = [
|
|
||||||
...res.calls,
|
|
||||||
...json.calls,
|
|
||||||
...topo.calls,
|
|
||||||
...data.calls,
|
|
||||||
...toposObj.calls,
|
|
||||||
];
|
|
||||||
this.setTopology({ nodes, calls });
|
this.setTopology({ nodes, calls });
|
||||||
} else {
|
} else {
|
||||||
const nodes = [
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
|
||||||
...res.nodes,
|
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
|
||||||
...json.nodes,
|
|
||||||
...topo.nodes,
|
|
||||||
...data.nodes,
|
|
||||||
];
|
|
||||||
const calls = [
|
|
||||||
...res.calls,
|
|
||||||
...json.calls,
|
|
||||||
...topo.calls,
|
|
||||||
...data.calls,
|
|
||||||
];
|
|
||||||
this.setTopology({ nodes, calls });
|
this.setTopology({ nodes, calls });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -220,9 +181,7 @@ export const topologyStore = defineStore({
|
|||||||
},
|
},
|
||||||
async getServicesTopology(serviceIds: string[]) {
|
async getServicesTopology(serviceIds: string[]) {
|
||||||
const duration = useAppStoreWithOut().durationTime;
|
const duration = useAppStoreWithOut().durationTime;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getServicesTopology").params({
|
||||||
.query("getServicesTopology")
|
|
||||||
.params({
|
|
||||||
serviceIds,
|
serviceIds,
|
||||||
duration,
|
duration,
|
||||||
});
|
});
|
||||||
@ -235,9 +194,7 @@ export const topologyStore = defineStore({
|
|||||||
const serverServiceId = useSelectorStore().currentService.id;
|
const serverServiceId = useSelectorStore().currentService.id;
|
||||||
const clientServiceId = useSelectorStore().currentDestService.id;
|
const clientServiceId = useSelectorStore().currentDestService.id;
|
||||||
const duration = useAppStoreWithOut().durationTime;
|
const duration = useAppStoreWithOut().durationTime;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("getInstanceTopology").params({
|
||||||
.query("getInstanceTopology")
|
|
||||||
.params({
|
|
||||||
clientServiceId,
|
clientServiceId,
|
||||||
serverServiceId,
|
serverServiceId,
|
||||||
duration,
|
duration,
|
||||||
@ -250,9 +207,7 @@ export const topologyStore = defineStore({
|
|||||||
async updateEndpointTopology(endpointIds: string[], depth: number) {
|
async updateEndpointTopology(endpointIds: string[], depth: number) {
|
||||||
const res = await this.getEndpointTopology(endpointIds);
|
const res = await this.getEndpointTopology(endpointIds);
|
||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
const ids = res.nodes
|
const ids = res.nodes.map((item: Node) => item.id).filter((d: string) => !endpointIds.includes(d));
|
||||||
.map((item: Node) => item.id)
|
|
||||||
.filter((d: string) => !endpointIds.includes(d));
|
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
this.setTopology(res);
|
this.setTopology(res);
|
||||||
return;
|
return;
|
||||||
@ -272,9 +227,7 @@ export const topologyStore = defineStore({
|
|||||||
if (depth > 3) {
|
if (depth > 3) {
|
||||||
const endpoints = topo.nodes
|
const endpoints = topo.nodes
|
||||||
.map((item: Node) => item.id)
|
.map((item: Node) => item.id)
|
||||||
.filter(
|
.filter((d: string) => ![...ids, ...pods, ...endpointIds].includes(d));
|
||||||
(d: string) => ![...ids, ...pods, ...endpointIds].includes(d)
|
|
||||||
);
|
|
||||||
if (!endpoints.length) {
|
if (!endpoints.length) {
|
||||||
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
|
||||||
const calls = [...res.calls, ...json.calls, ...topo.calls];
|
const calls = [...res.calls, ...json.calls, ...topo.calls];
|
||||||
@ -285,55 +238,20 @@ export const topologyStore = defineStore({
|
|||||||
if (depth > 4) {
|
if (depth > 4) {
|
||||||
const nodeIds = data.nodes
|
const nodeIds = data.nodes
|
||||||
.map((item: Node) => item.id)
|
.map((item: Node) => item.id)
|
||||||
.filter(
|
.filter((d: string) => ![...endpoints, ...ids, ...pods, ...endpointIds].includes(d));
|
||||||
(d: string) =>
|
|
||||||
![...endpoints, ...ids, ...pods, ...endpointIds].includes(d)
|
|
||||||
);
|
|
||||||
if (!nodeIds.length) {
|
if (!nodeIds.length) {
|
||||||
const nodes = [
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
|
||||||
...res.nodes,
|
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
|
||||||
...json.nodes,
|
|
||||||
...topo.nodes,
|
|
||||||
...data.nodes,
|
|
||||||
];
|
|
||||||
const calls = [
|
|
||||||
...res.calls,
|
|
||||||
...json.calls,
|
|
||||||
...topo.calls,
|
|
||||||
...data.calls,
|
|
||||||
];
|
|
||||||
this.setTopology({ nodes, calls });
|
this.setTopology({ nodes, calls });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const toposObj = await this.getEndpointTopology(nodeIds);
|
const toposObj = await this.getEndpointTopology(nodeIds);
|
||||||
const nodes = [
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes, ...toposObj.nodes];
|
||||||
...res.nodes,
|
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls, ...toposObj.calls];
|
||||||
...json.nodes,
|
|
||||||
...topo.nodes,
|
|
||||||
...data.nodes,
|
|
||||||
...toposObj.nodes,
|
|
||||||
];
|
|
||||||
const calls = [
|
|
||||||
...res.calls,
|
|
||||||
...json.calls,
|
|
||||||
...topo.calls,
|
|
||||||
...data.calls,
|
|
||||||
...toposObj.calls,
|
|
||||||
];
|
|
||||||
this.setTopology({ nodes, calls });
|
this.setTopology({ nodes, calls });
|
||||||
} else {
|
} else {
|
||||||
const nodes = [
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
|
||||||
...res.nodes,
|
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
|
||||||
...json.nodes,
|
|
||||||
...topo.nodes,
|
|
||||||
...data.nodes,
|
|
||||||
];
|
|
||||||
const calls = [
|
|
||||||
...res.calls,
|
|
||||||
...json.calls,
|
|
||||||
...topo.calls,
|
|
||||||
...data.calls,
|
|
||||||
];
|
|
||||||
this.setTopology({ nodes, calls });
|
this.setTopology({ nodes, calls });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -390,10 +308,7 @@ export const topologyStore = defineStore({
|
|||||||
|
|
||||||
return { calls, nodes };
|
return { calls, nodes };
|
||||||
},
|
},
|
||||||
async getNodeMetricValue(param: {
|
async getNodeMetricValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
|
||||||
queryStr: string;
|
|
||||||
conditions: { [key: string]: unknown };
|
|
||||||
}) {
|
|
||||||
const res: AxiosResponse = await query(param);
|
const res: AxiosResponse = await query(param);
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -407,9 +322,7 @@ export const topologyStore = defineStore({
|
|||||||
this.setLinkClientMetrics({});
|
this.setLinkClientMetrics({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const idsC = this.calls
|
const idsC = this.calls.filter((i: Call) => i.detectPoints.includes("CLIENT")).map((b: Call) => b.id);
|
||||||
.filter((i: Call) => i.detectPoints.includes("CLIENT"))
|
|
||||||
.map((b: Call) => b.id);
|
|
||||||
if (!idsC.length) {
|
if (!idsC.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -425,9 +338,7 @@ export const topologyStore = defineStore({
|
|||||||
this.setLinkServerMetrics({});
|
this.setLinkServerMetrics({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const idsS = this.calls
|
const idsS = this.calls.filter((i: Call) => i.detectPoints.includes("SERVER")).map((b: Call) => b.id);
|
||||||
.filter((i: Call) => i.detectPoints.includes("SERVER"))
|
|
||||||
.map((b: Call) => b.id);
|
|
||||||
if (!idsS.length) {
|
if (!idsS.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -454,10 +365,7 @@ export const topologyStore = defineStore({
|
|||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getLegendMetrics(param: {
|
async getLegendMetrics(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
|
||||||
queryStr: string;
|
|
||||||
conditions: { [key: string]: unknown };
|
|
||||||
}) {
|
|
||||||
const res: AxiosResponse = await query(param);
|
const res: AxiosResponse = await query(param);
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -477,10 +385,7 @@ export const topologyStore = defineStore({
|
|||||||
});
|
});
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getCallServerMetrics(param: {
|
async getCallServerMetrics(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
|
||||||
queryStr: string;
|
|
||||||
conditions: { [key: string]: unknown };
|
|
||||||
}) {
|
|
||||||
const res: AxiosResponse = await query(param);
|
const res: AxiosResponse = await query(param);
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -489,10 +394,7 @@ export const topologyStore = defineStore({
|
|||||||
this.setLinkServerMetrics(res.data.data);
|
this.setLinkServerMetrics(res.data.data);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getCallClientMetrics(param: {
|
async getCallClientMetrics(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
|
||||||
queryStr: string;
|
|
||||||
conditions: { [key: string]: unknown };
|
|
||||||
}) {
|
|
||||||
const res: AxiosResponse = await query(param);
|
const res: AxiosResponse = await query(param);
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import type { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
import { Trace, Span } from "@/types/trace";
|
import type { Trace, Span } from "@/types/trace";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { QueryOrders } from "@/views/dashboard/data";
|
import { QueryOrders } from "@/views/dashboard/data";
|
||||||
@ -30,7 +30,7 @@ interface TraceState {
|
|||||||
endpoints: Endpoint[];
|
endpoints: Endpoint[];
|
||||||
traceList: Trace[];
|
traceList: Trace[];
|
||||||
traceSpans: Span[];
|
traceSpans: Span[];
|
||||||
currentTrace: Trace | any;
|
currentTrace: Recordable<Trace>;
|
||||||
conditions: any;
|
conditions: any;
|
||||||
traceSpanLogs: any[];
|
traceSpanLogs: any[];
|
||||||
selectorStore: any;
|
selectorStore: any;
|
||||||
@ -58,10 +58,10 @@ export const traceStore = defineStore({
|
|||||||
setTraceCondition(data: any) {
|
setTraceCondition(data: any) {
|
||||||
this.conditions = { ...this.conditions, ...data };
|
this.conditions = { ...this.conditions, ...data };
|
||||||
},
|
},
|
||||||
setCurrentTrace(trace: Trace) {
|
setCurrentTrace(trace: Recordable<Trace>) {
|
||||||
this.currentTrace = trace;
|
this.currentTrace = trace;
|
||||||
},
|
},
|
||||||
setTraceSpans(spans: Span) {
|
setTraceSpans(spans: Span[]) {
|
||||||
this.traceSpans = spans;
|
this.traceSpans = spans;
|
||||||
},
|
},
|
||||||
resetState() {
|
resetState() {
|
||||||
@ -116,9 +116,7 @@ export const traceStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getInstances(id: string) {
|
async getInstances(id: string) {
|
||||||
const serviceId = this.selectorStore.currentService
|
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
|
||||||
? this.selectorStore.currentService.id
|
|
||||||
: id;
|
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId: serviceId,
|
serviceId: serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -131,9 +129,7 @@ export const traceStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEndpoints(id: string, keyword?: string) {
|
async getEndpoints(id: string, keyword?: string) {
|
||||||
const serviceId = this.selectorStore.currentService
|
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
|
||||||
? this.selectorStore.currentService.id
|
|
||||||
: id;
|
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -146,9 +142,7 @@ export const traceStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTraces() {
|
async getTraces() {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryTraces").params({ condition: this.conditions });
|
||||||
.query("queryTraces")
|
|
||||||
.params({ condition: this.conditions });
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
@ -169,9 +163,7 @@ export const traceStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTraceSpans(params: { traceId: string }) {
|
async getTraceSpans(params: { traceId: string }) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryTrace").params(params);
|
||||||
.query("queryTrace")
|
|
||||||
.params(params);
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
@ -180,9 +172,7 @@ export const traceStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getSpanLogs(params: any) {
|
async getSpanLogs(params: any) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryServiceLogs").params(params);
|
||||||
.query("queryServiceLogs")
|
|
||||||
.params(params);
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.traceSpanLogs = [];
|
this.traceSpanLogs = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
|
@ -20,9 +20,8 @@ body {
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #3d444f;
|
color: #3d444f;
|
||||||
font-family: Helvetica, Arial, "Source Han Sans CN", "Microsoft YaHei",
|
font-family: Helvetica, Arial, "Source Han Sans CN", "Microsoft YaHei", sans-serif;
|
||||||
sans-serif;
|
text-rendering: optimizelegibility;
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
text-size-adjust: 100%;
|
text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
src/types/components.d.ts
vendored
5
src/types/components.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
// generated by unplugin-vue-components
|
// generated by unplugin-vue-components
|
||||||
// We suggest you to commit this file into source control
|
// We suggest you to commit this file into source control
|
||||||
// Read more: https://github.com/vuejs/vue-next/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
@ -46,4 +47,4 @@ declare module '@vue/runtime-core' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { }
|
export {}
|
||||||
|
1
src/types/dashboard.d.ts
vendored
1
src/types/dashboard.d.ts
vendored
@ -1,4 +1,3 @@
|
|||||||
import { DurationTime } from "@/types/app";
|
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
@ -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 { DurationTime } from "./app";
|
import type { DurationTime } from "./app";
|
||||||
|
|
||||||
export interface Conditions {
|
export interface Conditions {
|
||||||
container: string;
|
container: string;
|
||||||
|
2
src/types/ebpf.d.ts
vendored
2
src/types/ebpf.d.ts
vendored
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Process } from "./selector";
|
import type { Process } from "./selector";
|
||||||
export interface EBPFTaskCreationRequest {
|
export interface EBPFTaskCreationRequest {
|
||||||
serviceId: string;
|
serviceId: string;
|
||||||
processLabels: string[];
|
processLabels: string[];
|
||||||
|
4
src/types/global.d.ts
vendored
4
src/types/global.d.ts
vendored
@ -110,7 +110,5 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare module "vue" {
|
declare module "vue" {
|
||||||
export type JSXComponent<Props = any> =
|
export type JSXComponent<Props = any> = { new (): ComponentPublicInstance<Props> } | FunctionalComponent<Props>;
|
||||||
| { new (): ComponentPublicInstance<Props> }
|
|
||||||
| FunctionalComponent<Props>;
|
|
||||||
}
|
}
|
||||||
|
3
src/types/index.d.ts
vendored
3
src/types/index.d.ts
vendored
@ -38,7 +38,6 @@ declare interface ComponentElRef<T extends HTMLElement = HTMLDivElement> {
|
|||||||
$el: T;
|
$el: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare type ComponentRef<T extends HTMLElement = HTMLDivElement> =
|
declare type ComponentRef<T extends HTMLElement = HTMLDivElement> = ComponentElRef<T> | null;
|
||||||
ComponentElRef<T> | null;
|
|
||||||
|
|
||||||
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
|
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
|
||||||
|
@ -15,3 +15,4 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
declare module "monaco-editor";
|
declare module "monaco-editor";
|
||||||
|
export {};
|
||||||
|
1
src/types/selector.d.ts
vendored
1
src/types/selector.d.ts
vendored
@ -29,6 +29,7 @@ export type Instance = {
|
|||||||
language?: string;
|
language?: string;
|
||||||
instanceUUID?: string;
|
instanceUUID?: string;
|
||||||
attributes?: { name: string; value: string }[];
|
attributes?: { name: string; value: string }[];
|
||||||
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Endpoint = {
|
export type Endpoint = {
|
||||||
|
@ -15,11 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
export default function dateFormatStep(
|
export default function dateFormatStep(date: Date, step: string, monthDayDiff?: boolean): string {
|
||||||
date: Date,
|
|
||||||
step: string,
|
|
||||||
monthDayDiff?: boolean
|
|
||||||
): string {
|
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
const monthTemp = date.getMonth() + 1;
|
const monthTemp = date.getMonth() + 1;
|
||||||
let month = `${monthTemp}`;
|
let month = `${monthTemp}`;
|
||||||
@ -101,5 +97,4 @@ export const dateFormatTime = (date: Date, step: string): string => {
|
|||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
export const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") => dayjs(new Date(date)).format(pattern);
|
||||||
dayjs(new Date(date)).format(pattern);
|
|
||||||
|
@ -39,10 +39,7 @@ export function addResizeListener(element: any, fn: () => unknown): void {
|
|||||||
|
|
||||||
export function removeResizeListener(element: any, fn: () => unknown): void {
|
export function removeResizeListener(element: any, fn: () => unknown): void {
|
||||||
if (!element || !element.__resizeListeners__) return;
|
if (!element || !element.__resizeListeners__) return;
|
||||||
element.__resizeListeners__.splice(
|
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
|
||||||
element.__resizeListeners__.indexOf(fn),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
if (!element.__resizeListeners__.length) {
|
if (!element.__resizeListeners__.length) {
|
||||||
element.__ro__.disconnect();
|
element.__ro__.disconnect();
|
||||||
}
|
}
|
||||||
|
@ -53,12 +53,7 @@ export function isNumber(val: unknown): val is number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isPromise<T = any>(val: unknown): val is Promise<T> {
|
export function isPromise<T = any>(val: unknown): val is Promise<T> {
|
||||||
return (
|
return is(val, "Promise") && isObject(val) && isFunction(val.then) && isFunction(val.catch);
|
||||||
is(val, "Promise") &&
|
|
||||||
isObject(val) &&
|
|
||||||
isFunction(val.then) &&
|
|
||||||
isFunction(val.catch)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isString(val: unknown): val is string {
|
export function isString(val: unknown): val is string {
|
||||||
|
@ -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 { Duration } from "@/types/app";
|
import type { Duration } from "@/types/app";
|
||||||
import { TimeType } from "@/constants/data";
|
import { TimeType } from "@/constants/data";
|
||||||
|
|
||||||
const timeFormat = (time: Date[]): Duration => {
|
const timeFormat = (time: Date[]): Duration => {
|
||||||
|
@ -17,11 +17,7 @@
|
|||||||
class Vec2 extends Float32Array {
|
class Vec2 extends Float32Array {
|
||||||
constructor(v?: unknown, y?: unknown) {
|
constructor(v?: unknown, y?: unknown) {
|
||||||
super(2);
|
super(2);
|
||||||
if (
|
if (v instanceof Vec2 || v instanceof Float32Array || (v instanceof Array && v.length == 2)) {
|
||||||
v instanceof Vec2 ||
|
|
||||||
v instanceof Float32Array ||
|
|
||||||
(v instanceof Array && v.length == 2)
|
|
||||||
) {
|
|
||||||
this[0] = v[0];
|
this[0] = v[0];
|
||||||
this[1] = v[1];
|
this[1] = v[1];
|
||||||
} else if (typeof v === "number" && typeof y === "number") {
|
} else if (typeof v === "number" && typeof y === "number") {
|
||||||
|
@ -17,19 +17,11 @@
|
|||||||
class Vec3 extends Float32Array {
|
class Vec3 extends Float32Array {
|
||||||
constructor(v?: unknown, y?: unknown, z?: unknown) {
|
constructor(v?: unknown, y?: unknown, z?: unknown) {
|
||||||
super(3);
|
super(3);
|
||||||
if (
|
if (v instanceof Vec3 || v instanceof Float32Array || (v instanceof Array && v.length == 3)) {
|
||||||
v instanceof Vec3 ||
|
|
||||||
v instanceof Float32Array ||
|
|
||||||
(v instanceof Array && v.length == 3)
|
|
||||||
) {
|
|
||||||
this[0] = v[0];
|
this[0] = v[0];
|
||||||
this[1] = v[1];
|
this[1] = v[1];
|
||||||
this[2] = v[2];
|
this[2] = v[2];
|
||||||
} else if (
|
} else if (typeof v === "number" && typeof y === "number" && typeof z === "number") {
|
||||||
typeof v === "number" &&
|
|
||||||
typeof y === "number" &&
|
|
||||||
typeof z === "number"
|
|
||||||
) {
|
|
||||||
this[0] = v;
|
this[0] = v;
|
||||||
this[1] = y;
|
this[1] = y;
|
||||||
this[2] = z;
|
this[2] = z;
|
||||||
@ -158,17 +150,9 @@ class Vec3 extends Float32Array {
|
|||||||
}
|
}
|
||||||
static norm(x: unknown, y: unknown, z: unknown): Vec3 {
|
static norm(x: unknown, y: unknown, z: unknown): Vec3 {
|
||||||
const rtn = new Vec3();
|
const rtn = new Vec3();
|
||||||
if (
|
if (x instanceof Vec3 || x instanceof Float32Array || (x instanceof Array && x.length == 3)) {
|
||||||
x instanceof Vec3 ||
|
|
||||||
x instanceof Float32Array ||
|
|
||||||
(x instanceof Array && x.length == 3)
|
|
||||||
) {
|
|
||||||
rtn.copy(x);
|
rtn.copy(x);
|
||||||
} else if (
|
} else if (typeof x === "number" && typeof y === "number" && typeof z === "number") {
|
||||||
typeof x === "number" &&
|
|
||||||
typeof y === "number" &&
|
|
||||||
typeof z === "number"
|
|
||||||
) {
|
|
||||||
rtn.xyz(x, y, z);
|
rtn.xyz(x, y, z);
|
||||||
}
|
}
|
||||||
return rtn.norm();
|
return rtn.norm();
|
||||||
|
@ -19,17 +19,17 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import Header from "./alarm/Header.vue";
|
import Header from "./alarm/Header.vue";
|
||||||
import Content from "./alarm/Content.vue";
|
import Content from "./alarm/Content.vue";
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
appStore.setPageTitle("Alerting");
|
appStore.setPageTitle("Alerting");
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.alarm {
|
.alarm {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -19,18 +19,18 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import Header from "./event/Header.vue";
|
import Header from "./event/Header.vue";
|
||||||
import Content from "./event/Content.vue";
|
import Content from "./event/Content.vue";
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
|
|
||||||
appStore.setPageTitle("Events");
|
appStore.setPageTitle("Events");
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.event {
|
.event {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,38 +14,34 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<Dashboard v-if="dashboardStore.currentDashboard" />
|
<Dashboard v-if="dashboardStore.currentDashboard" />
|
||||||
<div v-else class="no-root">
|
<div v-else class="no-root"> {{ t("noRoot") }} {{ dashboardStore.layerId }} </div>
|
||||||
{{ t("noRoot") }} {{ dashboardStore.layerId }}
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { EntityType } from "./dashboard/data";
|
import { EntityType } from "./dashboard/data";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import Dashboard from "./dashboard/Edit.vue";
|
import Dashboard from "./dashboard/Edit.vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const layer = ref<string>("GENERAL");
|
const layer = ref<string>("GENERAL");
|
||||||
|
|
||||||
getDashboard();
|
getDashboard();
|
||||||
|
|
||||||
async function getDashboard() {
|
async function getDashboard() {
|
||||||
layer.value = String(route.meta.layer);
|
layer.value = String(route.meta.layer);
|
||||||
dashboardStore.setLayer(layer.value);
|
dashboardStore.setLayer(layer.value);
|
||||||
dashboardStore.setMode(false);
|
dashboardStore.setMode(false);
|
||||||
await dashboardStore.setDashboards();
|
await dashboardStore.setDashboards();
|
||||||
const item = dashboardStore.dashboards.find(
|
const item = dashboardStore.dashboards.find(
|
||||||
(d: { name: string; isRoot: boolean; layer: string; entity: string }) =>
|
(d: { name: string; isRoot: boolean; layer: string; entity: string }) =>
|
||||||
d.layer === dashboardStore.layerId &&
|
d.layer === dashboardStore.layerId && [EntityType[0].value, EntityType[1].value].includes(d.entity) && d.isRoot,
|
||||||
[EntityType[0].value, EntityType[1].value].includes(d.entity) &&
|
|
||||||
d.isRoot
|
|
||||||
);
|
);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
appStore.setPageTitle(dashboardStore.layer);
|
appStore.setPageTitle(dashboardStore.layer);
|
||||||
@ -55,13 +51,13 @@ async function getDashboard() {
|
|||||||
}
|
}
|
||||||
dashboardStore.setEntity(item.entity);
|
dashboardStore.setEntity(item.entity);
|
||||||
dashboardStore.setCurrentDashboard(item);
|
dashboardStore.setCurrentDashboard(item);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.no-root {
|
.no-root {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -30,24 +30,10 @@ limitations under the License. -->
|
|||||||
<div>
|
<div>
|
||||||
<span>UTC</span>
|
<span>UTC</span>
|
||||||
<span class="ml-5 mr-5">{{ utcHour >= 0 ? "+" : "" }}</span>
|
<span class="ml-5 mr-5">{{ utcHour >= 0 ? "+" : "" }}</span>
|
||||||
<input
|
<input type="number" v-model="utcHour" min="-12" max="14" class="utc-input" @change="setUTCHour" />
|
||||||
type="number"
|
|
||||||
v-model="utcHour"
|
|
||||||
min="-12"
|
|
||||||
max="14"
|
|
||||||
class="utc-input"
|
|
||||||
@change="setUTCHour"
|
|
||||||
/>
|
|
||||||
<span class="ml-5 mr-5">:</span>
|
<span class="ml-5 mr-5">:</span>
|
||||||
<span class="utc-min">{{ utcMin > 9 || utcMin === 0 ? null : 0 }}</span>
|
<span class="utc-min">{{ utcMin > 9 || utcMin === 0 ? null : 0 }}</span>
|
||||||
<input
|
<input type="number" v-model="utcMin" min="0" max="59" class="utc-input" @change="setUTCMin" />
|
||||||
type="number"
|
|
||||||
v-model="utcMin"
|
|
||||||
min="0"
|
|
||||||
max="59"
|
|
||||||
class="utc-input"
|
|
||||||
@change="setUTCMin"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-h item">
|
<div class="flex-h item">
|
||||||
@ -55,12 +41,7 @@ limitations under the License. -->
|
|||||||
<el-switch v-model="auto" @change="handleAuto" style="height: 25px" />
|
<el-switch v-model="auto" @change="handleAuto" style="height: 25px" />
|
||||||
<div class="auto-time ml-5">
|
<div class="auto-time ml-5">
|
||||||
<span class="auto-select">
|
<span class="auto-select">
|
||||||
<input
|
<input type="number" v-model="autoTime" @change="changeAutoTime" min="1" />
|
||||||
type="number"
|
|
||||||
v-model="autoTime"
|
|
||||||
@change="changeAutoTime"
|
|
||||||
min="1"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
{{ t("second") }}
|
{{ t("second") }}
|
||||||
<i class="ml-10">{{ t("timeReload") }}</i>
|
<i class="ml-10">{{ t("timeReload") }}</i>
|
||||||
@ -69,33 +50,32 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import timeFormat from "@/utils/timeFormat";
|
import timeFormat from "@/utils/timeFormat";
|
||||||
import { Languages } from "@/constants/data";
|
import { Languages } from "@/constants/data";
|
||||||
import Selector from "@/components/Selector.vue";
|
import Selector from "@/components/Selector.vue";
|
||||||
import getLocalTime from "@/utils/localtime";
|
import getLocalTime from "@/utils/localtime";
|
||||||
|
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const lang = ref<string>(locale.value || "en");
|
const lang = ref<string>(locale.value || "en");
|
||||||
const autoTime = ref<number>(6);
|
const autoTime = ref<number>(6);
|
||||||
const auto = ref<boolean>(appStore.autoRefresh || false);
|
const auto = ref<boolean>(appStore.autoRefresh || false);
|
||||||
const utcHour = ref<number>(appStore.utcHour);
|
const utcHour = ref<number>(appStore.utcHour);
|
||||||
const utcMin = ref<number>(appStore.utcMin);
|
const utcMin = ref<number>(appStore.utcMin);
|
||||||
|
|
||||||
appStore.setPageTitle("Setting");
|
appStore.setPageTitle("Setting");
|
||||||
const handleReload = () => {
|
const handleReload = () => {
|
||||||
const gap =
|
const gap = appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
||||||
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
|
||||||
const dates: Date[] = [
|
const dates: Date[] = [
|
||||||
getLocalTime(appStore.utc, new Date(new Date().getTime() - gap)),
|
getLocalTime(appStore.utc, new Date(new Date().getTime() - gap)),
|
||||||
getLocalTime(appStore.utc, new Date()),
|
getLocalTime(appStore.utc, new Date()),
|
||||||
];
|
];
|
||||||
appStore.setDuration(timeFormat(dates));
|
appStore.setDuration(timeFormat(dates));
|
||||||
};
|
};
|
||||||
const handleAuto = () => {
|
const handleAuto = () => {
|
||||||
if (autoTime.value < 1) {
|
if (autoTime.value < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,8 +88,8 @@ const handleAuto = () => {
|
|||||||
clearInterval(appStore.reloadTimer);
|
clearInterval(appStore.reloadTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const changeAutoTime = () => {
|
const changeAutoTime = () => {
|
||||||
if (autoTime.value < 1) {
|
if (autoTime.value < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -120,12 +100,12 @@ const changeAutoTime = () => {
|
|||||||
handleReload();
|
handleReload();
|
||||||
appStore.setReloadTimer(setInterval(handleReload, autoTime.value * 1000));
|
appStore.setReloadTimer(setInterval(handleReload, autoTime.value * 1000));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const setLang = (): void => {
|
const setLang = (): void => {
|
||||||
locale.value = lang.value;
|
locale.value = lang.value;
|
||||||
window.localStorage.setItem("language", lang.value);
|
window.localStorage.setItem("language", lang.value);
|
||||||
};
|
};
|
||||||
const setUTCHour = () => {
|
const setUTCHour = () => {
|
||||||
if (utcHour.value < -12) {
|
if (utcHour.value < -12) {
|
||||||
utcHour.value = -12;
|
utcHour.value = -12;
|
||||||
}
|
}
|
||||||
@ -136,8 +116,8 @@ const setUTCHour = () => {
|
|||||||
utcHour.value = 0;
|
utcHour.value = 0;
|
||||||
}
|
}
|
||||||
appStore.setUTC(utcHour.value, utcMin.value);
|
appStore.setUTC(utcHour.value, utcMin.value);
|
||||||
};
|
};
|
||||||
const setUTCMin = () => {
|
const setUTCMin = () => {
|
||||||
if (utcMin.value < 0) {
|
if (utcMin.value < 0) {
|
||||||
utcMin.value = 0;
|
utcMin.value = 0;
|
||||||
}
|
}
|
||||||
@ -148,23 +128,23 @@ const setUTCMin = () => {
|
|||||||
utcMin.value = 0;
|
utcMin.value = 0;
|
||||||
}
|
}
|
||||||
appStore.setUTC(utcHour.value, utcMin.value);
|
appStore.setUTC(utcHour.value, utcMin.value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.utc-input {
|
.utc-input {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
background: 0;
|
background: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.utc-min {
|
.utc-min {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auto-select {
|
.auto-select {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
@ -174,9 +154,9 @@ const setUTCMin = () => {
|
|||||||
border-style: unset;
|
border-style: unset;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings {
|
.settings {
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@ -201,5 +181,5 @@ const setUTCMin = () => {
|
|||||||
color: #000;
|
color: #000;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,11 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="timeline-table clear">
|
<div class="timeline-table clear">
|
||||||
<div
|
<div v-for="(i, index) in alarmStore.alarms" :key="index" class="clear timeline-item">
|
||||||
v-for="(i, index) in alarmStore.alarms"
|
|
||||||
:key="index"
|
|
||||||
class="clear timeline-item"
|
|
||||||
>
|
|
||||||
<div class="g-sm-3 grey sm hide-xs time-line tr">
|
<div class="g-sm-3 grey sm hide-xs time-line tr">
|
||||||
{{ dateFormat(parseInt(i.startTime)) }}
|
{{ dateFormat(parseInt(i.startTime)) }}
|
||||||
</div>
|
</div>
|
||||||
@ -50,11 +46,7 @@ limitations under the License. -->
|
|||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
@closed="isShowDetails = false"
|
@closed="isShowDetails = false"
|
||||||
>
|
>
|
||||||
<div
|
<div class="mb-10 clear alarm-detail" v-for="(item, index) in AlarmDetailCol" :key="index">
|
||||||
class="mb-10 clear alarm-detail"
|
|
||||||
v-for="(item, index) in AlarmDetailCol"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<span class="g-sm-2 grey">{{ t(item.value) }}:</span>
|
<span class="g-sm-2 grey">{{ t(item.value) }}:</span>
|
||||||
<span v-if="item.label === 'startTime'">
|
<span v-if="item.label === 'startTime'">
|
||||||
{{ dateFormat(currentDetail[item.label]) }}
|
{{ dateFormat(currentDetail[item.label]) }}
|
||||||
@ -66,24 +58,12 @@ limitations under the License. -->
|
|||||||
<div>
|
<div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<span
|
<span v-for="(i, index) of EventsDetailHeaders" :class="i.class" :key="i.class + index">
|
||||||
v-for="(i, index) of EventsDetailHeaders"
|
|
||||||
:class="i.class"
|
|
||||||
:key="i.class + index"
|
|
||||||
>
|
|
||||||
{{ t(i.text) }}
|
{{ t(i.text) }}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li v-for="event in currentEvents" :key="event.uuid" @click="viewEventDetail(event)">
|
||||||
v-for="event in currentEvents"
|
<span v-for="(d, index) of EventsDetailHeaders" :class="d.class" :key="event.uuid + index">
|
||||||
:key="event.uuid"
|
|
||||||
@click="viewEventDetail(event)"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
v-for="(d, index) of EventsDetailHeaders"
|
|
||||||
:class="d.class"
|
|
||||||
:key="event.uuid + index"
|
|
||||||
>
|
|
||||||
<span v-if="d.class === 'startTime' || d.class === 'endTime'">
|
<span v-if="d.class === 'startTime' || d.class === 'endTime'">
|
||||||
{{ dateFormat(event[d.class]) }}
|
{{ dateFormat(event[d.class]) }}
|
||||||
</span>
|
</span>
|
||||||
@ -106,29 +86,16 @@ limitations under the License. -->
|
|||||||
@closed="showEventDetails = false"
|
@closed="showEventDetails = false"
|
||||||
>
|
>
|
||||||
<div class="event-detail">
|
<div class="event-detail">
|
||||||
<div
|
<div class="mb-10" v-for="(eventKey, index) in EventsDetailKeys" :key="index">
|
||||||
class="mb-10"
|
|
||||||
v-for="(eventKey, index) in EventsDetailKeys"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<span class="keys">{{ t(eventKey.text) }}</span>
|
<span class="keys">{{ t(eventKey.text) }}</span>
|
||||||
<span v-if="eventKey.class === 'parameters'">
|
<span v-if="eventKey.class === 'parameters'">
|
||||||
<span v-for="(d, index) of currentEvent[eventKey.class]" :key="index">
|
<span v-for="(d, index) of currentEvent[eventKey.class]" :key="index"> {{ d.key }}={{ d.value }}; </span>
|
||||||
{{ d.key }}={{ d.value }};
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
<span v-else-if="eventKey.class === 'startTime' || eventKey.class === 'endTime'">
|
||||||
<span
|
|
||||||
v-else-if="
|
|
||||||
eventKey.class === 'startTime' || eventKey.class === 'endTime'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ dateFormat(currentEvent[eventKey.class]) }}
|
{{ dateFormat(currentEvent[eventKey.class]) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="eventKey.class === 'source'" class="source">
|
<span v-else-if="eventKey.class === 'source'" class="source">
|
||||||
<span
|
<span>{{ t("service") }}: {{ currentEvent[eventKey.class].service }}</span>
|
||||||
>{{ t("service") }}:
|
|
||||||
{{ currentEvent[eventKey.class].service }}</span
|
|
||||||
>
|
|
||||||
<div v-show="currentEvent[eventKey.class].endpoint">
|
<div v-show="currentEvent[eventKey.class].endpoint">
|
||||||
{{ t("endpoint") }}:
|
{{ t("endpoint") }}:
|
||||||
{{ currentEvent[eventKey.class].endpoint }}
|
{{ currentEvent[eventKey.class].endpoint }}
|
||||||
@ -144,45 +111,43 @@ limitations under the License. -->
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { Alarm, Event } from "@/types/alarm";
|
import type { Alarm, Event } from "@/types/alarm";
|
||||||
import { useAlarmStore } from "@/store/modules/alarm";
|
import { useAlarmStore } from "@/store/modules/alarm";
|
||||||
import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys } from "./data";
|
import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys } from "./data";
|
||||||
import { dateFormat } from "@/utils/dateFormat";
|
import { dateFormat } from "@/utils/dateFormat";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const alarmStore = useAlarmStore();
|
const alarmStore = useAlarmStore();
|
||||||
const isShowDetails = ref<boolean>(false);
|
const isShowDetails = ref<boolean>(false);
|
||||||
const showEventDetails = ref<boolean>(false);
|
const showEventDetails = ref<boolean>(false);
|
||||||
const currentDetail = ref<Alarm | any>({});
|
const currentDetail = ref<Alarm | any>({});
|
||||||
const alarmTags = ref<string[]>([]);
|
const alarmTags = ref<string[]>([]);
|
||||||
const currentEvents = ref<any[]>([]);
|
const currentEvents = ref<any[]>([]);
|
||||||
const currentEvent = ref<Event | any>({});
|
const currentEvent = ref<Event | any>({});
|
||||||
|
|
||||||
function showDetails(item: Alarm) {
|
function showDetails(item: Alarm) {
|
||||||
isShowDetails.value = true;
|
isShowDetails.value = true;
|
||||||
currentDetail.value = item;
|
currentDetail.value = item;
|
||||||
currentEvents.value = item.events;
|
currentEvents.value = item.events;
|
||||||
alarmTags.value = currentDetail.value.tags.map(
|
alarmTags.value = currentDetail.value.tags.map((d: { key: string; value: string }) => {
|
||||||
(d: { key: string; value: string }) => {
|
|
||||||
return `${d.key} = ${d.value}`;
|
return `${d.key} = ${d.value}`;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewEventDetail(event: Event) {
|
function viewEventDetail(event: Event) {
|
||||||
currentEvent.value = event;
|
currentEvent.value = event;
|
||||||
showEventDetails.value = true;
|
showEventDetails.value = true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "../components/style.scss";
|
@import "../components/style.scss";
|
||||||
|
|
||||||
.tips {
|
.tips {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -28,12 +28,7 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
<div class="mr-10 ml-10">
|
<div class="mr-10 ml-10">
|
||||||
<span class="grey">{{ t("searchKeyword") }}: </span>
|
<span class="grey">{{ t("searchKeyword") }}: </span>
|
||||||
<el-input
|
<el-input size="small" v-model="keyword" class="alarm-tool-input" @change="refreshAlarms({ pageNum: 1 })" />
|
||||||
size="small"
|
|
||||||
v-model="keyword"
|
|
||||||
class="alarm-tool-input"
|
|
||||||
@change="refreshAlarms({ pageNum: 1 })"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@ -48,37 +43,32 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ConditionTags
|
<ConditionTags :type="'ALARM'" @update="(data) => refreshAlarms({ pageNum: 1, tagsMap: data.tagsMap })" />
|
||||||
:type="'ALARM'"
|
|
||||||
@update="(data) => refreshAlarms({ pageNum: 1, tagsMap: data.tagsMap })"
|
|
||||||
/>
|
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from "vue";
|
import { ref, computed } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import ConditionTags from "@/views/components/ConditionTags.vue";
|
import ConditionTags from "@/views/components/ConditionTags.vue";
|
||||||
import { AlarmOptions } from "./data";
|
import { AlarmOptions } from "./data";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useAlarmStore } from "@/store/modules/alarm";
|
import { useAlarmStore } from "@/store/modules/alarm";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const alarmStore = useAlarmStore();
|
const alarmStore = useAlarmStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const pageSize = 20;
|
const pageSize = 20;
|
||||||
const entity = ref<string>("");
|
const entity = ref<string>("");
|
||||||
const keyword = ref<string>("");
|
const keyword = ref<string>("");
|
||||||
const pageNum = ref<number>(1);
|
const pageNum = ref<number>(1);
|
||||||
const total = computed(() =>
|
const total = computed(() =>
|
||||||
alarmStore.alarms.length === pageSize
|
alarmStore.alarms.length === pageSize ? pageSize * pageNum.value + 1 : pageSize * pageNum.value,
|
||||||
? pageSize * pageNum.value + 1
|
);
|
||||||
: pageSize * pageNum.value
|
|
||||||
);
|
|
||||||
|
|
||||||
refreshAlarms({ pageNum: 1 });
|
refreshAlarms({ pageNum: 1 });
|
||||||
|
|
||||||
async function refreshAlarms(param: { pageNum: number; tagsMap?: any }) {
|
async function refreshAlarms(param: { pageNum: number; tagsMap?: any }) {
|
||||||
const params: any = {
|
const params: any = {
|
||||||
duration: appStore.durationTime,
|
duration: appStore.durationTime,
|
||||||
paging: {
|
paging: {
|
||||||
@ -94,38 +84,38 @@ async function refreshAlarms(param: { pageNum: number; tagsMap?: any }) {
|
|||||||
if (res.errors) {
|
if (res.errors) {
|
||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeEntity(param: any) {
|
function changeEntity(param: any) {
|
||||||
entity.value = param[0].value;
|
entity.value = param[0].value;
|
||||||
refreshAlarms({ pageNum: 1 });
|
refreshAlarms({ pageNum: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePage(p: number) {
|
function changePage(p: number) {
|
||||||
pageNum.value = p;
|
pageNum.value = p;
|
||||||
refreshAlarms({ pageNum: p });
|
refreshAlarms({ pageNum: p });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.alarm-tool {
|
.alarm-tool {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-bottom: 1px solid #c1c5ca41;
|
border-bottom: 1px solid #c1c5ca41;
|
||||||
background-color: #f0f2f5;
|
background-color: #f0f2f5;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alarm-tool-input {
|
.alarm-tool-input {
|
||||||
border-style: unset;
|
border-style: unset;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -42,20 +42,12 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<span
|
<span v-for="(item, index) in tagList" :key="index" @click="selectTag(item)" class="tag-item">
|
||||||
v-for="(item, index) in tagList"
|
|
||||||
:key="index"
|
|
||||||
@click="selectTag(item)"
|
|
||||||
class="tag-item"
|
|
||||||
>
|
|
||||||
{{ item }}
|
{{ item }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<span
|
<span class="tags-tip" :class="type !== 'ALARM' && tagArr.length ? 'link-tips' : ''">
|
||||||
class="tags-tip"
|
|
||||||
:class="type !== 'ALARM' && tagArr.length ? 'link-tips' : ''"
|
|
||||||
>
|
|
||||||
<a
|
<a
|
||||||
target="blank"
|
target="blank"
|
||||||
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
|
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
|
||||||
@ -72,50 +64,50 @@ 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 { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useTraceStore } from "@/store/modules/trace";
|
import { useTraceStore } from "@/store/modules/trace";
|
||||||
import { useLogStore } from "@/store/modules/log";
|
import { useLogStore } from "@/store/modules/log";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
/*global defineEmits, defineProps */
|
/*global defineEmits, defineProps */
|
||||||
const emit = defineEmits(["update"]);
|
const emit = defineEmits(["update"]);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: { type: String, default: "TRACE" },
|
type: { type: String, default: "TRACE" },
|
||||||
});
|
});
|
||||||
const traceStore = useTraceStore();
|
const traceStore = useTraceStore();
|
||||||
const logStore = useLogStore();
|
const logStore = useLogStore();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tags = ref<string>("");
|
const tags = ref<string>("");
|
||||||
const tagsList = ref<string[]>([]);
|
const tagsList = ref<string[]>([]);
|
||||||
const tagArr = ref<string[]>([]);
|
const tagArr = ref<string[]>([]);
|
||||||
const tagList = ref<string[]>([]);
|
const tagList = ref<string[]>([]);
|
||||||
const tagKeys = ref<string[]>([]);
|
const tagKeys = ref<string[]>([]);
|
||||||
const keysList = ref<string[]>([]);
|
const keysList = ref<string[]>([]);
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const tipsMap = {
|
const tipsMap = {
|
||||||
LOG: "logTagsTip",
|
LOG: "logTagsTip",
|
||||||
TRACE: "traceTagsTip",
|
TRACE: "traceTagsTip",
|
||||||
ALARM: "alarmTagsTip",
|
ALARM: "alarmTagsTip",
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchTagKeys();
|
fetchTagKeys();
|
||||||
|
|
||||||
function removeTags(index: number) {
|
function removeTags(index: number) {
|
||||||
tagsList.value.splice(index, 1);
|
tagsList.value.splice(index, 1);
|
||||||
updateTags();
|
updateTags();
|
||||||
}
|
}
|
||||||
function addLabels() {
|
function addLabels() {
|
||||||
if (!tags.value) {
|
if (!tags.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tagsList.value.push(tags.value);
|
tagsList.value.push(tags.value);
|
||||||
tags.value = "";
|
tags.value = "";
|
||||||
updateTags();
|
updateTags();
|
||||||
}
|
}
|
||||||
function updateTags() {
|
function updateTags() {
|
||||||
const tagsMap = tagsList.value.map((item: string) => {
|
const tagsMap = tagsList.value.map((item: string) => {
|
||||||
const key = item.substring(0, item.indexOf("="));
|
const key = item.substring(0, item.indexOf("="));
|
||||||
return {
|
return {
|
||||||
@ -124,8 +116,8 @@ function updateTags() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
emit("update", { tagsMap, tagsList: tagsList.value });
|
emit("update", { tagsMap, tagsList: tagsList.value });
|
||||||
}
|
}
|
||||||
async function fetchTagKeys() {
|
async function fetchTagKeys() {
|
||||||
let resp: any = {};
|
let resp: any = {};
|
||||||
if (props.type === "TRACE") {
|
if (props.type === "TRACE") {
|
||||||
resp = await traceStore.getTagKeys();
|
resp = await traceStore.getTagKeys();
|
||||||
@ -141,9 +133,9 @@ async function fetchTagKeys() {
|
|||||||
tagKeys.value = resp.data.tagKeys;
|
tagKeys.value = resp.data.tagKeys;
|
||||||
keysList.value = resp.data.tagKeys;
|
keysList.value = resp.data.tagKeys;
|
||||||
searchTags();
|
searchTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchTagValues() {
|
async function fetchTagValues() {
|
||||||
const param = tags.value.split("=")[0];
|
const param = tags.value.split("=")[0];
|
||||||
let resp: any = {};
|
let resp: any = {};
|
||||||
if (props.type === "TRACE") {
|
if (props.type === "TRACE") {
|
||||||
@ -158,9 +150,9 @@ async function fetchTagValues() {
|
|||||||
}
|
}
|
||||||
tagArr.value = resp.data.tagValues;
|
tagArr.value = resp.data.tagValues;
|
||||||
searchTags();
|
searchTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
function inputTags() {
|
function inputTags() {
|
||||||
if (!tags.value) {
|
if (!tags.value) {
|
||||||
tagArr.value = keysList.value;
|
tagArr.value = keysList.value;
|
||||||
tagKeys.value = keysList.value;
|
tagKeys.value = keysList.value;
|
||||||
@ -175,18 +167,18 @@ function inputTags() {
|
|||||||
search = tags.value;
|
search = tags.value;
|
||||||
}
|
}
|
||||||
tagList.value = tagArr.value.filter((d: string) => d.includes(search));
|
tagList.value = tagArr.value.filter((d: string) => d.includes(search));
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTags() {
|
function addTags() {
|
||||||
if (!tags.value.includes("=")) {
|
if (!tags.value.includes("=")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addLabels();
|
addLabels();
|
||||||
tagArr.value = tagKeys.value;
|
tagArr.value = tagKeys.value;
|
||||||
searchTags();
|
searchTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectTag(item: string) {
|
function selectTag(item: string) {
|
||||||
if (tags.value.includes("=")) {
|
if (tags.value.includes("=")) {
|
||||||
const key = tags.value.split("=")[0];
|
const key = tags.value.split("=")[0];
|
||||||
tags.value = key + "=" + item;
|
tags.value = key + "=" + item;
|
||||||
@ -195,9 +187,9 @@ function selectTag(item: string) {
|
|||||||
}
|
}
|
||||||
tags.value = item + "=";
|
tags.value = item + "=";
|
||||||
fetchTagValues();
|
fetchTagValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchTags() {
|
function searchTags() {
|
||||||
let search = "";
|
let search = "";
|
||||||
if (tags.value.includes("=")) {
|
if (tags.value.includes("=")) {
|
||||||
search = tags.value.split("=")[1];
|
search = tags.value.split("=")[1];
|
||||||
@ -205,25 +197,25 @@ function searchTags() {
|
|||||||
search = tags.value;
|
search = tags.value;
|
||||||
}
|
}
|
||||||
tagList.value = tagArr.value.filter((d: string) => d.includes(search));
|
tagList.value = tagArr.value.filter((d: string) => d.includes(search));
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => appStore.durationTime,
|
() => appStore.durationTime,
|
||||||
() => {
|
() => {
|
||||||
fetchTagKeys();
|
fetchTagKeys();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.trace-tags {
|
.trace-tags {
|
||||||
padding: 1px 5px 0 0;
|
padding: 1px 5px 0 0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@ -231,23 +223,23 @@ watch(
|
|||||||
border: 1px dashed #aaa;
|
border: 1px dashed #aaa;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin: 3px 2px 0 2px;
|
margin: 3px 2px 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-new-tag {
|
.trace-new-tag {
|
||||||
border-style: unset;
|
border-style: unset;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-icon {
|
.remove-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-item {
|
.tag-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
min-width: 210px;
|
min-width: 210px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -256,17 +248,17 @@ watch(
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-tip {
|
.tags-tip {
|
||||||
color: #a7aebb;
|
color: #a7aebb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-tips {
|
.link-tips {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.light {
|
.light {
|
||||||
color: #3d444f;
|
color: #3d444f;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@ -276,15 +268,15 @@ watch(
|
|||||||
.selected {
|
.selected {
|
||||||
color: #3d444f;
|
color: #3d444f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-help {
|
.icon-help {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -33,17 +33,17 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ref, defineComponent } from "vue";
|
import { ref, defineComponent } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import GridLayout from "./panel/Layout.vue";
|
import GridLayout from "./panel/Layout.vue";
|
||||||
import Tool from "./panel/Tool.vue";
|
import Tool from "./panel/Tool.vue";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import Configuration from "./configuration";
|
import Configuration from "./configuration";
|
||||||
import { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig } from "@/types/dashboard";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Dashboard",
|
name: "Dashboard",
|
||||||
components: { ...Configuration, GridLayout, Tool },
|
components: { ...Configuration, GridLayout, Tool },
|
||||||
setup() {
|
setup() {
|
||||||
@ -63,9 +63,7 @@ export default defineComponent({
|
|||||||
const { layer, entity, name } = dashboardStore.currentDashboard;
|
const { layer, entity, name } = dashboardStore.currentDashboard;
|
||||||
layoutKey.value = `${layer}_${entity}_${name}`;
|
layoutKey.value = `${layer}_${entity}_${name}`;
|
||||||
}
|
}
|
||||||
const c: { configuration: string; id: string } = JSON.parse(
|
const c: { configuration: string; id: string } = JSON.parse(sessionStorage.getItem(layoutKey.value) || "{}");
|
||||||
sessionStorage.getItem(layoutKey.value) || "{}"
|
|
||||||
);
|
|
||||||
const layout: any = c.configuration || {};
|
const layout: any = c.configuration || {};
|
||||||
|
|
||||||
dashboardStore.setLayout(setWidgetsID(layout.children || []));
|
dashboardStore.setLayout(setWidgetsID(layout.children || []));
|
||||||
@ -112,10 +110,10 @@ export default defineComponent({
|
|||||||
dashboardStore,
|
dashboardStore,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.ds-main {
|
.ds-main {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -33,9 +33,7 @@ limitations under the License. -->
|
|||||||
{{ t("reloadDashboards") }}
|
{{ t("reloadDashboards") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<router-link to="/dashboard/new">
|
<router-link to="/dashboard/new">
|
||||||
<el-button size="small" type="primary">
|
<el-button size="small" type="primary"> + {{ t("newDashboard") }} </el-button>
|
||||||
+ {{ t("newDashboard") }}
|
|
||||||
</el-button>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="table">
|
<div class="table">
|
||||||
@ -74,10 +72,7 @@ limitations under the License. -->
|
|||||||
<el-button size="small" @click="handleRename(scope.row)">
|
<el-button size="small" @click="handleRename(scope.row)">
|
||||||
{{ t("rename") }}
|
{{ t("rename") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-popconfirm
|
<el-popconfirm :title="t('deleteTitle')" @confirm="handleDelete(scope.row)">
|
||||||
:title="t('deleteTitle')"
|
|
||||||
@confirm="handleDelete(scope.row)"
|
|
||||||
>
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button size="small" type="danger">
|
<el-button size="small" type="danger">
|
||||||
{{ t("delete") }}
|
{{ t("delete") }}
|
||||||
@ -87,11 +82,7 @@ limitations under the License. -->
|
|||||||
<el-popconfirm
|
<el-popconfirm
|
||||||
:title="t('rootTitle')"
|
:title="t('rootTitle')"
|
||||||
@confirm="setRoot(scope.row)"
|
@confirm="setRoot(scope.row)"
|
||||||
v-if="
|
v-if="[EntityType[0].value, EntityType[1].value].includes(scope.row.entity)"
|
||||||
[EntityType[0].value, EntityType[1].value].includes(
|
|
||||||
scope.row.entity
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button size="small" style="width: 110px" type="danger">
|
<el-button size="small" style="width: 110px" type="danger">
|
||||||
@ -140,48 +131,47 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ElMessageBox, ElMessage } from "element-plus";
|
import { ElMessageBox, ElMessage } from "element-plus";
|
||||||
import type { ElTable } from "element-plus";
|
import { ElTable } from "element-plus";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { DashboardItem, LayoutConfig } from "@/types/dashboard";
|
import type { DashboardItem, LayoutConfig } from "@/types/dashboard";
|
||||||
import { saveFile, readFile } from "@/utils/file";
|
import { saveFile, readFile } from "@/utils/file";
|
||||||
import { EntityType } from "./data";
|
import { EntityType } from "./data";
|
||||||
import { isEmptyObject } from "@/utils/is";
|
import { isEmptyObject } from "@/utils/is";
|
||||||
|
|
||||||
/*global Nullable*/
|
/*global Nullable*/
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const pageSize = 20;
|
const pageSize = 20;
|
||||||
const dashboards = ref<DashboardItem[]>([]);
|
const dashboards = ref<DashboardItem[]>([]);
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
const currentPage = ref<number>(1);
|
const currentPage = ref<number>(1);
|
||||||
const total = ref<number>(0);
|
const total = ref<number>(0);
|
||||||
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
||||||
const multipleSelection = ref<DashboardItem[]>([]);
|
const multipleSelection = ref<DashboardItem[]>([]);
|
||||||
const dashboardFile = ref<Nullable<HTMLDivElement>>(null);
|
const dashboardFile = ref<Nullable<HTMLDivElement>>(null);
|
||||||
|
|
||||||
appStore.setPageTitle("Dashboard List");
|
appStore.setPageTitle("Dashboard List");
|
||||||
const handleSelectionChange = (val: DashboardItem[]) => {
|
const handleSelectionChange = (val: DashboardItem[]) => {
|
||||||
multipleSelection.value = val;
|
multipleSelection.value = val;
|
||||||
};
|
};
|
||||||
setList();
|
setList();
|
||||||
async function setList() {
|
async function setList() {
|
||||||
await dashboardStore.setDashboards();
|
await dashboardStore.setDashboards();
|
||||||
searchDashboards(1);
|
searchDashboards(1);
|
||||||
}
|
}
|
||||||
async function importTemplates(event: any) {
|
async function importTemplates(event: any) {
|
||||||
const arr: any = await readFile(event);
|
const arr: any = await readFile(event);
|
||||||
for (const item of arr) {
|
for (const item of arr) {
|
||||||
const { layer, name, entity } = item.configuration;
|
const { layer, name, entity } = item.configuration;
|
||||||
const index = dashboardStore.dashboards.findIndex(
|
const index = dashboardStore.dashboards.findIndex(
|
||||||
(d: DashboardItem) =>
|
(d: DashboardItem) => d.name === name && d.entity === entity && d.layer === layer && !item.id,
|
||||||
d.name === name && d.entity === entity && d.layer === layer && !item.id
|
|
||||||
);
|
);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
return ElMessage.error(t("nameError"));
|
return ElMessage.error(t("nameError"));
|
||||||
@ -190,9 +180,7 @@ async function importTemplates(event: any) {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
for (const item of arr) {
|
for (const item of arr) {
|
||||||
const { layer, name, entity, isRoot, children } = item.configuration;
|
const { layer, name, entity, isRoot, children } = item.configuration;
|
||||||
const index = dashboardStore.dashboards.findIndex(
|
const index = dashboardStore.dashboards.findIndex((d: DashboardItem) => d.id === item.id);
|
||||||
(d: DashboardItem) => d.id === item.id
|
|
||||||
);
|
|
||||||
const p: DashboardItem = {
|
const p: DashboardItem = {
|
||||||
name: name.split(" ").join("-"),
|
name: name.split(" ").join("-"),
|
||||||
layer: layer,
|
layer: layer,
|
||||||
@ -210,16 +198,14 @@ async function importTemplates(event: any) {
|
|||||||
dashboards.value = dashboardStore.dashboards;
|
dashboards.value = dashboardStore.dashboards;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
dashboardFile.value = null;
|
dashboardFile.value = null;
|
||||||
}
|
}
|
||||||
function exportTemplates() {
|
function exportTemplates() {
|
||||||
if (!multipleSelection.value.length) {
|
if (!multipleSelection.value.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const arr = multipleSelection.value.sort(
|
const arr = multipleSelection.value.sort((a: DashboardItem, b: DashboardItem) => {
|
||||||
(a: DashboardItem, b: DashboardItem) => {
|
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
const templates = arr.map((d: DashboardItem) => {
|
const templates = arr.map((d: DashboardItem) => {
|
||||||
const key = [d.layer, d.entity, d.name].join("_");
|
const key = [d.layer, d.entity, d.name].join("_");
|
||||||
const layout = JSON.parse(sessionStorage.getItem(key) || "{}");
|
const layout = JSON.parse(sessionStorage.getItem(key) || "{}");
|
||||||
@ -233,15 +219,15 @@ function exportTemplates() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
multipleTableRef.value!.clearSelection();
|
multipleTableRef.value!.clearSelection();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
function optimizeTemplate(
|
function optimizeTemplate(
|
||||||
children: (LayoutConfig & {
|
children: (LayoutConfig & {
|
||||||
moved?: boolean;
|
moved?: boolean;
|
||||||
standard?: unknown;
|
standard?: unknown;
|
||||||
label?: string;
|
label?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
})[]
|
})[],
|
||||||
) {
|
) {
|
||||||
for (const child of children || []) {
|
for (const child of children || []) {
|
||||||
delete child.moved;
|
delete child.moved;
|
||||||
delete child.activedTabIndex;
|
delete child.activedTabIndex;
|
||||||
@ -266,9 +252,7 @@ function optimizeTemplate(
|
|||||||
if (!(child.metrics && child.metrics.length && child.metrics[0])) {
|
if (!(child.metrics && child.metrics.length && child.metrics[0])) {
|
||||||
delete child.metrics;
|
delete child.metrics;
|
||||||
}
|
}
|
||||||
if (
|
if (!(child.metricTypes && child.metricTypes.length && child.metricTypes[0])) {
|
||||||
!(child.metricTypes && child.metricTypes.length && child.metricTypes[0])
|
|
||||||
) {
|
|
||||||
delete child.metricTypes;
|
delete child.metricTypes;
|
||||||
}
|
}
|
||||||
if (child.metricConfig && child.metricConfig.length) {
|
if (child.metricConfig && child.metricConfig.length) {
|
||||||
@ -295,32 +279,28 @@ function optimizeTemplate(
|
|||||||
optimizeTemplate(item.children);
|
optimizeTemplate(item.children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (["Trace", "Topology", "Tab", "Profile", "Ebpf", "Log"].includes(child.type)) {
|
||||||
["Trace", "Topology", "Tab", "Profile", "Ebpf", "Log"].includes(
|
|
||||||
child.type
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
delete child.widget;
|
delete child.widget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleEdit(row: DashboardItem) {
|
function handleEdit(row: DashboardItem) {
|
||||||
dashboardStore.setMode(true);
|
dashboardStore.setMode(true);
|
||||||
dashboardStore.setEntity(row.entity);
|
dashboardStore.setEntity(row.entity);
|
||||||
dashboardStore.setLayer(row.layer);
|
dashboardStore.setLayer(row.layer);
|
||||||
dashboardStore.setCurrentDashboard(row);
|
dashboardStore.setCurrentDashboard(row);
|
||||||
router.push(`/dashboard/${row.layer}/${row.entity}/${row.name}`);
|
router.push(`/dashboard/${row.layer}/${row.entity}/${row.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleView(row: DashboardItem) {
|
function handleView(row: DashboardItem) {
|
||||||
dashboardStore.setMode(false);
|
dashboardStore.setMode(false);
|
||||||
dashboardStore.setEntity(row.entity);
|
dashboardStore.setEntity(row.entity);
|
||||||
dashboardStore.setLayer(row.layer);
|
dashboardStore.setLayer(row.layer);
|
||||||
dashboardStore.setCurrentDashboard(row);
|
dashboardStore.setCurrentDashboard(row);
|
||||||
router.push(`/dashboard/${row.layer}/${row.entity}/${row.name}`);
|
router.push(`/dashboard/${row.layer}/${row.entity}/${row.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setRoot(row: DashboardItem) {
|
async function setRoot(row: DashboardItem) {
|
||||||
const items: DashboardItem[] = [];
|
const items: DashboardItem[] = [];
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
for (const d of dashboardStore.dashboards) {
|
for (const d of dashboardStore.dashboards) {
|
||||||
@ -345,7 +325,7 @@ async function setRoot(row: DashboardItem) {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
id: d.id,
|
id: d.id,
|
||||||
configuration: c,
|
configuration: c,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -373,7 +353,7 @@ async function setRoot(row: DashboardItem) {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
id: d.id,
|
id: d.id,
|
||||||
configuration: c,
|
configuration: c,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,8 +363,8 @@ async function setRoot(row: DashboardItem) {
|
|||||||
dashboardStore.resetDashboards(items);
|
dashboardStore.resetDashboards(items);
|
||||||
searchDashboards(1);
|
searchDashboards(1);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
function handleRename(row: DashboardItem) {
|
function handleRename(row: DashboardItem) {
|
||||||
ElMessageBox.prompt("Please input dashboard name", "Edit", {
|
ElMessageBox.prompt("Please input dashboard name", "Edit", {
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
cancelButtonText: "Cancel",
|
cancelButtonText: "Cancel",
|
||||||
@ -399,8 +379,8 @@ function handleRename(row: DashboardItem) {
|
|||||||
message: "Input canceled",
|
message: "Input canceled",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function updateName(d: DashboardItem, value: string) {
|
async function updateName(d: DashboardItem, value: string) {
|
||||||
if (new RegExp(/\s/).test(value)) {
|
if (new RegExp(/\s/).test(value)) {
|
||||||
ElMessage.error("The name cannot contain spaces, carriage returns, etc");
|
ElMessage.error("The name cannot contain spaces, carriage returns, etc");
|
||||||
return;
|
return;
|
||||||
@ -447,11 +427,11 @@ async function updateName(d: DashboardItem, value: string) {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
id: d.id,
|
id: d.id,
|
||||||
configuration: c,
|
configuration: c,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
searchText.value = "";
|
searchText.value = "";
|
||||||
}
|
}
|
||||||
async function handleDelete(row: DashboardItem) {
|
async function handleDelete(row: DashboardItem) {
|
||||||
dashboardStore.setCurrentDashboard(row);
|
dashboardStore.setCurrentDashboard(row);
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await dashboardStore.deleteDashboard();
|
await dashboardStore.deleteDashboard();
|
||||||
@ -459,47 +439,44 @@ async function handleDelete(row: DashboardItem) {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
sessionStorage.setItem("dashboards", JSON.stringify(dashboards.value));
|
sessionStorage.setItem("dashboards", JSON.stringify(dashboards.value));
|
||||||
sessionStorage.removeItem(`${row.layer}_${row.entity}_${row.name}`);
|
sessionStorage.removeItem(`${row.layer}_${row.entity}_${row.name}`);
|
||||||
}
|
}
|
||||||
function searchDashboards(pageIndex?: any) {
|
function searchDashboards(pageIndex?: any) {
|
||||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
const arr = list.filter((d: { name: string }) =>
|
const arr = list.filter((d: { name: string }) => d.name.includes(searchText.value));
|
||||||
d.name.includes(searchText.value)
|
|
||||||
);
|
|
||||||
|
|
||||||
total.value = arr.length;
|
total.value = arr.length;
|
||||||
dashboards.value = arr.filter(
|
dashboards.value = arr.filter(
|
||||||
(d: { name: string }, index: number) =>
|
(d: { name: string }, index: number) => index < pageIndex * pageSize && index >= (pageIndex - 1) * pageSize,
|
||||||
index < pageIndex * pageSize && index >= (pageIndex - 1) * pageSize
|
|
||||||
);
|
);
|
||||||
currentPage.value = pageIndex;
|
currentPage.value = pageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reloadTemplates() {
|
async function reloadTemplates() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await dashboardStore.resetTemplates();
|
await dashboardStore.resetTemplates();
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
function changePage(pageIndex: number) {
|
function changePage(pageIndex: number) {
|
||||||
currentPage.value = pageIndex;
|
currentPage.value = pageIndex;
|
||||||
searchDashboards(pageIndex);
|
searchDashboards(pageIndex);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.header {
|
.header {
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-list {
|
.dashboard-list {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-with-search {
|
.input-with-search {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
padding: 20px 10px;
|
padding: 20px 10px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0px 1px 4px 0px #00000029;
|
box-shadow: 0px 1px 4px 0px #00000029;
|
||||||
@ -507,43 +484,43 @@ function changePage(pageIndex: number) {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-selection {
|
.toggle-selection {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.import-template {
|
.import-template {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-label {
|
.input-label {
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 220px;
|
width: 220px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reload {
|
.reload {
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reload-btn {
|
.reload-btn {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,11 +17,7 @@ limitations under the License. -->
|
|||||||
<div class="title">{{ t("newDashboard") }}</div>
|
<div class="title">{{ t("newDashboard") }}</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">{{ t("name") }}</div>
|
<div class="label">{{ t("name") }}</div>
|
||||||
<el-input
|
<el-input size="default" v-model="states.name" placeholder="Please input name" />
|
||||||
size="default"
|
|
||||||
v-model="states.name"
|
|
||||||
placeholder="Please input name"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">{{ t("layer") }}</div>
|
<div class="label">{{ t("layer") }}</div>
|
||||||
@ -51,35 +47,33 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { EntityType } from "./data";
|
import { EntityType } from "./data";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
appStore.setPageTitle("Dashboard New");
|
appStore.setPageTitle("Dashboard New");
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
const states = reactive({
|
const states = reactive({
|
||||||
name: "",
|
name: "",
|
||||||
selectedLayer: "",
|
selectedLayer: "",
|
||||||
entity: EntityType[0].value,
|
entity: EntityType[0].value,
|
||||||
layers: [],
|
layers: [],
|
||||||
});
|
});
|
||||||
setLayers();
|
setLayers();
|
||||||
dashboardStore.setDashboards();
|
dashboardStore.setDashboards();
|
||||||
|
|
||||||
const onCreate = () => {
|
const onCreate = () => {
|
||||||
const index = dashboardStore.dashboards.findIndex(
|
const index = dashboardStore.dashboards.findIndex(
|
||||||
(d: { name: string; entity: string; layer: string }) =>
|
(d: { name: string; entity: string; layer: string }) =>
|
||||||
d.name === states.name &&
|
d.name === states.name && states.entity === d.entity && states.selectedLayer === d.layer,
|
||||||
states.entity === d.entity &&
|
|
||||||
states.selectedLayer === d.layer
|
|
||||||
);
|
);
|
||||||
if (!states.name) {
|
if (!states.name) {
|
||||||
ElMessage.error(t("nameEmptyError"));
|
ElMessage.error(t("nameEmptyError"));
|
||||||
@ -97,8 +91,8 @@ const onCreate = () => {
|
|||||||
const name = states.name;
|
const name = states.name;
|
||||||
const path = `/dashboard/${states.selectedLayer}/${states.entity}/${name}`;
|
const path = `/dashboard/${states.selectedLayer}/${states.entity}/${name}`;
|
||||||
router.push(path);
|
router.push(path);
|
||||||
};
|
};
|
||||||
async function setLayers() {
|
async function setLayers() {
|
||||||
const resp = await selectorStore.fetchLayers();
|
const resp = await selectorStore.fetchLayers();
|
||||||
if (resp.errors) {
|
if (resp.errors) {
|
||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
@ -107,39 +101,39 @@ async function setLayers() {
|
|||||||
states.layers = resp.data.layers.map((d: string) => {
|
states.layers = resp.data.layers.map((d: string) => {
|
||||||
return { label: d, value: d };
|
return { label: d, value: d };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function changeLayer(opt: { label: string; value: string }[] | any) {
|
function changeLayer(opt: { label: string; value: string }[] | any) {
|
||||||
states.selectedLayer = opt[0].value;
|
states.selectedLayer = opt[0].value;
|
||||||
}
|
}
|
||||||
function changeEntity(opt: { label: string; value: string }[] | any) {
|
function changeEntity(opt: { label: string; value: string }[] | any) {
|
||||||
states.entity = opt[0].value;
|
states.entity = opt[0].value;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.title {
|
.title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-dashboard {
|
.new-dashboard {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-dashboard,
|
.new-dashboard,
|
||||||
.selectors {
|
.selectors {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.create {
|
.create {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -13,12 +13,7 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<span class="label">{{ t("enableAssociate") }}</span>
|
<span class="label">{{ t("enableAssociate") }}</span>
|
||||||
<el-switch
|
<el-switch v-model="eventAssociate" active-text="Yes" inactive-text="No" @change="updateConfig" />
|
||||||
v-model="eventAssociate"
|
|
||||||
active-text="Yes"
|
|
||||||
inactive-text="No"
|
|
||||||
@change="updateConfig"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<el-button size="small" @click="cancelConfig">
|
<el-button size="small" @click="cancelConfig">
|
||||||
@ -30,46 +25,46 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const originConfig = dashboardStore.selectedGrid;
|
const originConfig = dashboardStore.selectedGrid;
|
||||||
const eventAssociate = ref(dashboardStore.selectedGrid.eventAssociate || false);
|
const eventAssociate = ref(dashboardStore.selectedGrid.eventAssociate || false);
|
||||||
|
|
||||||
function updateConfig() {
|
function updateConfig() {
|
||||||
dashboardStore.selectedGrid = {
|
dashboardStore.selectedGrid = {
|
||||||
...dashboardStore.selectedGrid,
|
...dashboardStore.selectedGrid,
|
||||||
eventAssociate,
|
eventAssociate,
|
||||||
};
|
};
|
||||||
dashboardStore.selectWidget(dashboardStore.selectedGrid);
|
dashboardStore.selectWidget(dashboardStore.selectedGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyConfig() {
|
function applyConfig() {
|
||||||
dashboardStore.setConfigPanel(false);
|
dashboardStore.setConfigPanel(false);
|
||||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelConfig() {
|
function cancelConfig() {
|
||||||
dashboardStore.selectWidget(originConfig);
|
dashboardStore.selectWidget(originConfig);
|
||||||
dashboardStore.setConfigPanel(false);
|
dashboardStore.setConfigPanel(false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.label {
|
.label {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -78,5 +73,5 @@ function cancelConfig() {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -13,21 +13,11 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<span class="label">{{ t("textUrl") }}</span>
|
<span class="label">{{ t("textUrl") }}</span>
|
||||||
<el-input
|
<el-input class="input" v-model="url" size="small" @change="changeConfig({ url })" />
|
||||||
class="input"
|
|
||||||
v-model="url"
|
|
||||||
size="small"
|
|
||||||
@change="changeConfig({ url })"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<span class="label">{{ t("content") }}</span>
|
<span class="label">{{ t("content") }}</span>
|
||||||
<el-input
|
<el-input class="input" v-model="content" size="small" @change="changeConfig({ content })" />
|
||||||
class="input"
|
|
||||||
v-model="content"
|
|
||||||
size="small"
|
|
||||||
@change="changeConfig({ content })"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<span class="label">{{ t("textAlign") }}</span>
|
<span class="label">{{ t("textAlign") }}</span>
|
||||||
@ -85,20 +75,20 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const originConfig = dashboardStore.selectedGrid;
|
const originConfig = dashboardStore.selectedGrid;
|
||||||
const graph = originConfig.graph || {};
|
const graph = originConfig.graph || {};
|
||||||
const url = ref(graph.url || "");
|
const url = ref(graph.url || "");
|
||||||
const backgroundColor = ref(graph.backgroundColor || "green");
|
const backgroundColor = ref(graph.backgroundColor || "green");
|
||||||
const fontColor = ref(graph.fontColor || "white");
|
const fontColor = ref(graph.fontColor || "white");
|
||||||
const content = ref<string>(graph.content || "");
|
const content = ref<string>(graph.content || "");
|
||||||
const fontSize = ref<number>(graph.fontSize || 12);
|
const fontSize = ref<number>(graph.fontSize || 12);
|
||||||
const textAlign = ref(graph.textAlign || "left");
|
const textAlign = ref(graph.textAlign || "left");
|
||||||
const Colors = [
|
const Colors = [
|
||||||
{
|
{
|
||||||
label: "Green",
|
label: "Green",
|
||||||
value: "green",
|
value: "green",
|
||||||
@ -109,55 +99,55 @@ const Colors = [
|
|||||||
{ label: "White", value: "white" },
|
{ label: "White", value: "white" },
|
||||||
{ label: "Black", value: "black" },
|
{ label: "Black", value: "black" },
|
||||||
{ label: "Orange", value: "orange" },
|
{ label: "Orange", value: "orange" },
|
||||||
];
|
];
|
||||||
const AlignStyle = [
|
const AlignStyle = [
|
||||||
{
|
{
|
||||||
label: "Left",
|
label: "Left",
|
||||||
value: "left",
|
value: "left",
|
||||||
},
|
},
|
||||||
{ label: "Center", value: "center" },
|
{ label: "Center", value: "center" },
|
||||||
{ label: "Right", value: "right" },
|
{ label: "Right", value: "right" },
|
||||||
];
|
];
|
||||||
function changeConfig(param: { [key: string]: unknown }) {
|
function changeConfig(param: { [key: string]: unknown }) {
|
||||||
const { selectedGrid } = dashboardStore;
|
const { selectedGrid } = dashboardStore;
|
||||||
const graph = {
|
const graph = {
|
||||||
...selectedGrid.graph,
|
...selectedGrid.graph,
|
||||||
...param,
|
...param,
|
||||||
};
|
};
|
||||||
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
||||||
}
|
}
|
||||||
function applyConfig() {
|
function applyConfig() {
|
||||||
dashboardStore.setConfigPanel(false);
|
dashboardStore.setConfigPanel(false);
|
||||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelConfig() {
|
function cancelConfig() {
|
||||||
dashboardStore.selectWidget(originConfig);
|
dashboardStore.selectWidget(originConfig);
|
||||||
dashboardStore.setConfigPanel(false);
|
dashboardStore.setConfigPanel(false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.slider {
|
.slider {
|
||||||
width: 500px;
|
width: 500px;
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
width: 500px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -166,5 +156,5 @@ function cancelConfig() {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user