import codes

This commit is contained in:
Qiuxia Fan 2021-12-08 16:06:25 +08:00
commit ffcdd1939a
118 changed files with 27480 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
.DS_Store
node_modules
/lib
/tests/e2e/videos/
/tests/e2e/screenshots/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

34
.licenserc.yaml Normal file
View File

@ -0,0 +1,34 @@
#
# 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.
#
header:
license:
spdx-id: Apache-2.0
copyright-owner: Apache Software Foundation
paths-ignore:
- 'lib'
- 'dist'
- 'LICENSE'
- '.gitignore'
- '.prettierrc'
- '.browserslistrc'
- '**/*.md'
- '**/*.json'
comment: on-failure

201
LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed 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.

31
README.md Normal file
View File

@ -0,0 +1,31 @@
# skywalking-x-ui
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your unit tests
```
npm run test:unit
```
### Run your end-to-end tests
```
npm run test:e2e
```
### Lints and fixes files
```
npm run lint
```

19
babel.config.js Normal file
View File

@ -0,0 +1,19 @@
/**
* 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 = {
presets: ["@vue/cli-plugin-babel/preset"],
};

19
cypress.json Normal file
View File

@ -0,0 +1,19 @@
/**
* 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.
*/
{
"pluginsFile": "tests/e2e/plugins/index.js"
}

21
dist/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
MIT licenses
========================================
vue 3.2.21: https://github.com/vuejs/vue MIT
vue-router 4.0.12: https://github.com/vuejs/vue-router MIT
vuex 4.0.2: https://github.com/vuejs/vuex MIT
dayjs 1.10.7: https://github.com/iamkun/dayjs MIT
lodash 4.17.21: https://github.com/lodash/lodash MIT
vue-i18n 9.1.9: https://github.com/kazupon/vue-i18n MIT
pinia 2.0.5: github.com/posva/pinia MIT
normalize-wheel-es 1.1.1: github.com/sxzz/normalize-wheel-es MIT
async-validator 4.0.7: github.com/yiminghe/async-validator MIT
axios 0.24.0: github.com/axios/axios MIT
memoize-one 6.0.0: github.com/alexreardon/memoize-one MIT
popperjs/core 2.10.2: github.com/popperjs/popper-core MIT
three 0.131.3: github.com/mrdoob/three.js MIT
three-orbit-controls 82.1.0: github.com/mattdesl/three-orbit-controls MIT
vue-demi 0.12.1: github.com/antfu/vue-demi MIT
vueuse/core 6.8.0: github.com/vueuse/vueuse MIT
vue/devtools-api 6.0.0-beta.20.1: github.com/vuejs/vue-devtools MIT
element-plus 1.2.0-beta.3: github.com/element-plus/element-plus MIT

19
dist/licenses/LICENSE-async-validator vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2014-present Matt Zabriskie
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-axios vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-dayjs vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-element-plus vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-lodash vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-present Evan You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-memoize-one vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-present Evan You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-present Evan You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-pinia vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-popperjs-core vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-three vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-vue vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-vue-demi vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-vue-devtools-api vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

20
dist/licenses/LICENSE-vue-i18n vendored Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2016 kazuya kawaguchi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

21
dist/licenses/LICENSE-vue-router vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-present Evan You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

21
dist/licenses/LICENSE-vueuse vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

21
dist/licenses/LICENSE-vuex vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-present Evan You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

20067
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

89
package.json Normal file
View File

@ -0,0 +1,89 @@
{
"name": "skywalking-x-ui",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.24.0",
"element-plus": "^1.2.0-beta.3",
"pinia": "^2.0.5",
"three": "^0.131.3",
"three-orbit-controls": "^82.1.0",
"vue": "^3.0.0",
"vue-i18n": "^9.1.9",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@types/jest": "^24.0.19",
"@types/three": "^0.131.0",
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-e2e-cypress": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-unit-jest": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"@vue/test-utils": "^2.0.0-0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"node-sass": "^6.0.1",
"prettier": "^2.2.1",
"sass-loader": "^10.2.0",
"svg-sprite-loader": "^6.0.11",
"typescript": "~4.1.5",
"vue-jest": "^5.0.0-0"
},
"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": {},
"overrides": [
{
"files": [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
"env": {
"jest": true
}
}
]
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"jest": {
"preset": "@vue/cli-plugin-unit-jest/presets/typescript-and-babel",
"transform": {
"^.+\\.vue$": "vue-jest"
}
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

31
public/index.html Normal file
View File

@ -0,0 +1,31 @@
<!-- 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. -->
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<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>
<!-- built files will be auto injected -->
</body>
</html>

42
run.sh Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
# 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.
set -x
set -e
absolute_path="/etc/nginx/nginx.conf"
#absolute_path="nginx.conf"
ngx_upstream_file=$absolute_path
pool_name="skywalkingLB"
# mv ${absolute_path} ${absolute_path}.old
# cat ${absolute_path}.old | sed s#SKYWALKING_URL#${SKYWALKING_URL}#g > ${absolute_path}
skywalking_collector=${SKYWALKING_URL}
# skywalking_collector=localhost:1234,127.0.0.1:1235
# pool_ip is a comma-separated list of IP
pool_ip=`awk 'BEGIN{list="'${skywalking_collector}'";split(list,ip_list,",");for(ip in ip_list){print ip_list[ip];}}'`
for ip in ${pool_ip[*]};do
echo "add ${pool_name} ${ip} in ${ngx_upstream_file}"
sed -i '/upstream '${pool_name}'[^-]*{/a\\server '${ip}';' ${ngx_upstream_file}
done
echo -e "\033[31m ====add nginx.conf :==== \033[0m"
cat $absolute_path

25
src/App.vue Normal file
View 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. -->
<template>
<router-view />
</template>
<style>
#app {
text-align: center;
color: #2c3e50;
height: 100%;
}
</style>

View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M9.828 8.064l4.243 4.243a1 1 0 1 1-1.414 1.414l-4.95-4.95a1 1 0 0 1 0-1.414l4.95-4.95a1 1 0 0 1 1.414 1.414L9.828 8.064zm-6 0l4.243 4.243a1 1 0 1 1-1.414 1.414l-4.95-4.95a1 1 0 0 1 0-1.414l4.95-4.95A1 1 0 0 1 8.07 3.821L3.828 8.064z" fill="#000" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5.95 8.064L1.707 3.821a1 1 0 0 1 1.414-1.414l4.95 4.95a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.414-1.414L5.95 8.064zm6 0L7.707 3.821a1 1 0 0 1 1.414-1.414l4.95 4.95a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.414-1.414l4.243-4.243z" fill="#000" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

16
src/assets/icons/arrow-down.svg Executable file
View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path id="a" d="m10.472352 7.28232367c.3431062-.36783247.904419-.36783247 1.2592596-.00644059.3578153.36442148.3578153.95850784.0002156 1.28561559l-3.10532264 3.16826253c-.17025689.1734002-.39845625.2702388-.62654793.2702388-.24380864 0-.45151514-.0919745-.62697852-.2706782l-3.09835734-3.16693764c-.36405333-.352236-.36405333-.94614513-.01248284-1.28566765.34310619-.36783247.90441901-.36783247 1.25901327-.0066912l2.48658215 2.52737493z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,20 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>assignment</title>
<path d="M17.016 9v-2.016h-10.031v2.016h10.031zM17.016 12.984v-1.969h-10.031v1.969h10.031zM14.016 17.016v-2.016h-7.031v2.016h7.031zM12 3q-0.422 0-0.703 0.281t-0.281 0.703 0.281 0.727 0.703 0.305 0.703-0.305 0.281-0.727-0.281-0.703-0.703-0.281zM18.984 3q0.797 0 1.406 0.609t0.609 1.406v13.969q0 0.797-0.609 1.406t-1.406 0.609h-13.969q-0.797 0-1.406-0.609t-0.609-1.406v-13.969q0-0.797 0.609-1.406t1.406-0.609h4.172q0.328-0.891 1.078-1.453t1.734-0.563 1.734 0.563 1.078 1.453h4.172z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,19 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>av_timer</title>
<path d="M6 12q0-0.422 0.281-0.703t0.703-0.281 0.727 0.281 0.305 0.703-0.305 0.703-0.727 0.281-0.703-0.281-0.281-0.703zM18 12q0 0.422-0.281 0.703t-0.703 0.281-0.727-0.281-0.305-0.703 0.305-0.703 0.727-0.281 0.703 0.281 0.281 0.703zM11.016 3h0.984q3.75 0 6.375 2.625t2.625 6.375-2.625 6.375-6.375 2.625-6.375-2.625-2.625-6.375q0-4.5 3.609-7.172v-0.047l6.797 6.797-1.406 1.406-5.438-5.391q-1.547 1.922-1.547 4.406 0 2.906 2.039 4.945t4.945 2.039 4.945-2.039 2.039-4.945q0-2.625-1.734-4.594t-4.266-2.344v1.922h-1.969v-3.984zM11.016 17.016q0-0.422 0.281-0.727t0.703-0.305 0.703 0.305 0.281 0.727-0.281 0.703-0.703 0.281-0.703-0.281-0.281-0.703z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,19 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>bar_chart</title>
<path d="M16.219 12.984h2.766v6h-2.766v-6zM10.594 5.016h2.813v13.969h-2.813v-13.969zM5.016 9.188h3v9.797h-3v-9.797z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1021 B

16
src/assets/icons/chart.svg Executable file
View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/chart</title><path d="M5.55 3.824L6.853 5.78a.3.3 0 0 0 .384.102l1.526-.764a.3.3 0 0 1 .384.102l1.65 2.476a.3.3 0 0 0 .462.045l1.229-1.229a.3.3 0 0 1 .512.212v4.243H5V3.99a.3.3 0 0 1 .55-.167zM13 12a1 1 0 0 1 0 2H3.833A1.833 1.833 0 0 1 2 12.167V3a1 1 0 1 1 2 0v9h9z" id="a"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/chevron-left</title><path d="M7.414 7.989l2.295 2.306a1 1 0 1 1-1.418 1.41l-3-3.015a1 1 0 0 1 .004-1.414l3-2.985a1 1 0 1 1 1.41 1.418l-2.29 2.28z" id="a"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/chevron-right</title><path d="M8.586 7.989l-2.291-2.28a1 1 0 1 1 1.41-1.418l3 2.985a1 1 0 0 1 .004 1.414l-3 3.015a1 1 0 0 1-1.418-1.41l2.295-2.306z" id="a"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,19 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>dashboard_customize</title>
<path d="M18 12.984v3h3v2.016h-3v3h-2.016v-3h-3v-2.016h3v-3h2.016zM3 12.984h8.016v8.016h-8.016v-8.016zM12.984 3h8.016v8.016h-8.016v-8.016zM3 3h8.016v8.016h-8.016v-8.016z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

16
src/assets/icons/epic.svg Executable file
View File

@ -0,0 +1,16 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/epic</title><path d="M5.156 4l-.811 2h7.31l-.811-2H5.156zM4.55 2h6.9c.368 0 .702.235.85.6l1.622 4c.205.505-.009 1.095-.478 1.316a.87.87 0 0 1-.371.084H2.927C2.415 8 2 7.552 2 7c0-.138.026-.274.078-.4l1.622-4c.148-.365.481-.6.85-.6zM3 9h10a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2zm0 3h10a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2z" id="a"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,18 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>format_indent_decrease</title>
<path d="M11.016 12.984v-1.969h9.984v1.969h-9.984zM11.016 9v-2.016h9.984v2.016h-9.984zM3 3h18v2.016h-18v-2.016zM3 21v-2.016h18v2.016h-18zM3 12l3.984-3.984v7.969zM11.016 17.016v-2.016h9.984v2.016h-9.984z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,15 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="16px" height="16.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M432 617.6l-121.6-121.6L265.6 544l166.4 166.4L758.4 384l-44.8-48z" /></svg>

20
src/assets/icons/index.ts Executable file
View File

@ -0,0 +1,20 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const requireAll = (requireContext: Recordable) =>
requireContext.keys().map(requireContext);
const req = require.context("./", true, /\.svg$/);
requireAll(req);

File diff suppressed because one or more lines are too long

29
src/assets/icons/logo.svg Normal file
View File

@ -0,0 +1,29 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<?xml version="1.0" encoding="UTF-8"?>
<svg width="3450px" height="1823px" viewBox="0 0 3450 1823" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(0.000000, -29.000000)">
<path d="M1050.01772,1394.31899 C1050.01772,1615.24051 912.21519,1851.47342 474.746835,1851.47342 C310.696203,1851.47342 192.579747,1836.16203 87.5873418,1812.10127 C65.7139241,1807.72658 46.0278481,1792.41519 46.0278481,1768.35443 L46.0278481,1610.86582 C46.0278481,1586.80506 65.7139241,1569.30633 87.5873418,1569.30633 L91.9620253,1569.30633 C179.455696,1580.24304 398.189873,1591.17975 479.121519,1591.17975 C673.794937,1591.17975 732.853165,1521.18481 732.853165,1394.31899 C732.853165,1309.01266 691.293671,1265.26582 546.929114,1179.95949 L258.2,1007.15949 C54.7772152,886.855696 0.0936708861,759.989873 0.0936708861,606.875949 C0.0936708861,366.268354 140.083544,191.281013 546.929114,191.281013 C691.293671,191.281013 892.529114,213.15443 966.898734,230.653165 C988.772152,235.027848 1006.27089,250.339241 1006.27089,272.212658 L1006.27089,434.075949 C1006.27089,455.949367 990.959494,473.448101 969.086076,473.448101 L964.711392,473.448101 C820.346835,460.324051 675.982278,451.574684 533.805063,451.574684 C371.941772,451.574684 304.134177,508.44557 304.134177,606.875949 C304.134177,679.058228 341.318987,722.805063 483.496203,801.549367 L745.977215,948.101266 C986.58481,1081.52911 1050.01772,1221.51899 1050.01772,1394.31899 Z M2852.63038,644.060759 C2852.63038,646.248101 2852.63038,648.435443 2852.63038,650.622785 L2653.58228,1656.8 C2627.33418,1788.04051 2592.33671,1840.53671 2458.90886,1840.53671 L2399.85063,1840.53671 C2281.73418,1840.53671 2220.48861,1783.66582 2192.05316,1669.92405 L2019.25316,1000.59747 C2017.06582,991.848101 2017.06582,989.660759 2012.69114,989.660759 C2008.31646,989.660759 2008.31646,991.848101 2006.12911,1000.59747 L1833.32911,1669.92405 C1804.89367,1783.66582 1743.6481,1840.53671 1625.53165,1840.53671 L1566.47342,1840.53671 C1433.04557,1840.53671 1398.0481,1788.04051 1371.8,1656.8 L1172.7519,650.622785 C1172.7519,648.435443 1172.7519,646.248101 1172.7519,644.060759 C1172.7519,620 1192.43797,600.313924 1216.49873,600.313924 L1428.67089,600.313924 C1450.5443,600.313924 1465.8557,620 1468.04304,639.686076 L1605.84557,1564.93165 C1608.03291,1584.61772 1612.40759,1595.55443 1616.78228,1595.55443 C1621.15696,1595.55443 1627.71899,1586.80506 1632.09367,1564.93165 L1813.64304,829.98481 C1835.51646,744.678481 1861.76456,735.929114 1936.13418,735.929114 L2089.2481,735.929114 C2163.61772,735.929114 2189.86582,744.678481 2211.73924,829.98481 L2393.28861,1564.93165 C2397.66329,1586.80506 2404.22532,1595.55443 2408.6,1595.55443 C2412.97468,1595.55443 2417.34937,1584.61772 2419.53671,1564.93165 L2557.33924,639.686076 C2559.52658,620 2574.83797,600.313924 2596.71139,600.313924 L2808.88354,600.313924 C2832.9443,600.313924 2852.63038,620 2852.63038,644.060759 Z" id="Sw" fill="#1368B3"></path>
<g id="moon-o" transform="translate(2932.164557, 596.000000) rotate(-183.000000) translate(-2932.164557, -596.000000) translate(2415.708861, 26.379747)" fill="#D8D8D8" fill-rule="nonzero">
<path d="M1025.31646,927.371333 C992.796119,932.841177 959.292071,935.576099 925.845888,935.576099 C590.40035,935.576099 318.259524,661.909325 318.259524,324.582876 C318.259524,209.134252 351.705707,96.3623597 412.290747,0 C171.802278,71.8062511 0,293.684076 0,557.342199 C0,878.317305 259.46831,1139.24051 578.65368,1139.24051 C753.17563,1139.24051 916.818891,1059.22949 1025.31646,927.371333 Z" id="Shape"></path>
</g>
</g>
</g>
</svg>

View File

@ -0,0 +1,18 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>notification_important</title>
<path d="M12 21.984q-0.844 0-1.43-0.563t-0.586-1.406h4.031q0 0.797-0.609 1.383t-1.406 0.586zM12.984 12v-3.984h-1.969v3.984h1.969zM12.984 15.984v-1.969h-1.969v1.969h1.969zM18 15.984l2.016 2.016v0.984h-16.031v-0.984l2.016-2.016v-4.969q0-2.344 1.195-4.078t3.305-2.25v-0.703q0-0.609 0.422-1.055t1.078-0.445 1.078 0.445 0.422 1.055v0.703q2.109 0.516 3.305 2.25t1.195 4.078v4.969z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,18 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>playlist_add</title>
<path d="M2.016 15.984v-1.969h7.969v1.969h-7.969zM18 14.016h3.984v1.969h-3.984v4.031h-2.016v-4.031h-3.984v-1.969h3.984v-4.031h2.016v4.031zM14.016 6v2.016h-12v-2.016h12zM14.016 9.984v2.016h-12v-2.016h12z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,18 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>scatter_plot</title>
<path d="M13.594 17.578q0-1.219 0.891-2.109t2.109-0.891 2.109 0.891 0.891 2.109-0.891 2.109-2.109 0.891-2.109-0.891-0.891-2.109zM8.016 6q0-1.219 0.891-2.109t2.109-0.891 2.109 0.891 0.891 2.109-0.891 2.109-2.109 0.891-2.109-0.891-0.891-2.109zM3.984 14.016q0-1.219 0.891-2.109t2.109-0.891 2.109 0.891 0.891 2.109-0.891 2.109-2.109 0.891-2.109-0.891-0.891-2.109z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,18 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>settings</title>
<path d="M12 15.516q1.453 0 2.484-1.031t1.031-2.484-1.031-2.484-2.484-1.031-2.484 1.031-1.031 2.484 1.031 2.484 2.484 1.031zM19.453 12.984l2.109 1.641q0.328 0.234 0.094 0.656l-2.016 3.469q-0.188 0.328-0.609 0.188l-2.484-0.984q-0.984 0.703-1.688 0.984l-0.375 2.625q-0.094 0.422-0.469 0.422h-4.031q-0.375 0-0.469-0.422l-0.375-2.625q-0.891-0.375-1.688-0.984l-2.484 0.984q-0.422 0.141-0.609-0.188l-2.016-3.469q-0.234-0.422 0.094-0.656l2.109-1.641q-0.047-0.328-0.047-0.984t0.047-0.984l-2.109-1.641q-0.328-0.234-0.094-0.656l2.016-3.469q0.188-0.328 0.609-0.188l2.484 0.984q0.984-0.703 1.688-0.984l0.375-2.625q0.094-0.422 0.469-0.422h4.031q0.375 0 0.469 0.422l0.375 2.625q0.891 0.375 1.688 0.984l2.484-0.984q0.422-0.141 0.609 0.188l2.016 3.469q0.234 0.422-0.094 0.656l-2.109 1.641q0.047 0.328 0.047 0.984t-0.047 0.984z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,18 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>timeline</title>
<path d="M23.016 8.016q0 0.797-0.609 1.383t-1.406 0.586h-0.047q-0.328 0-0.469-0.047l-3.563 3.563q0.094 0.281 0.094 0.516 0 0.797-0.609 1.383t-1.406 0.586-1.406-0.586-0.609-1.383q0-0.234 0.094-0.516l-2.578-2.578q-0.281 0.094-0.516 0.094t-0.516-0.094l-4.547 4.547q0.094 0.281 0.094 0.516 0 0.797-0.609 1.406t-1.406 0.609-1.406-0.609-0.609-1.406 0.609-1.383 1.406-0.586q0.375 0 0.516 0.047l4.547-4.547q-0.047-0.141-0.047-0.516 0-0.797 0.586-1.406t1.383-0.609 1.406 0.609 0.609 1.406q0 0.375-0.047 0.516l2.531 2.531q0.141-0.047 0.516-0.047t0.516 0.047l3.563-3.516q-0.094-0.281-0.094-0.516 0-0.797 0.609-1.406t1.406-0.609 1.406 0.609 0.609 1.406z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

765
src/components/DateCalendar.vue Executable file
View File

@ -0,0 +1,765 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div :class="`${state.pre}`">
<div :class="`${state.pre}-head`">
<a
:class="`${state.pre}-prev-decade-btn`"
v-show="state.showYears"
@click="state.year -= 10"
>
<Icon size="sm" iconName="angle-double-left" />
</a>
<a
:class="`${state.pre}-prev-year-btn`"
v-show="!state.showYears"
@click="state.year--"
>
<Icon size="sm" iconName="angle-double-left" />
</a>
<a
:class="`${state.pre}-prev-month-btn`"
v-show="!state.showYears && !state.showMonths"
@click="pm"
>
<Icon size="middle" iconName="chevron-left" />
</a>
<a :class="`${state.pre}-year-select`" v-show="state.showYears">{{
ys + "-" + ye
}}</a>
<template v-if="local.yearSuffix">
<a
:class="`${state.pre}-year-select`"
@click="state.showYears = !state.showYears"
v-show="!state.showYears"
>{{ state.year }}{{ local.yearSuffix }}</a
>
<a
:class="`${state.pre}-month-select`"
@click="state.showMonths = !state.showMonths"
v-show="!state.showYears && !state.showMonths"
>{{ local.monthsHead[state.month] }}</a
>
</template>
<template v-else>
<a
:class="`${state.pre}-month-select`"
@click="state.showMonths = !state.showMonths"
v-show="!state.showYears && !state.showMonths"
>{{ local.monthsHead[state.month] }}</a
>
<a
:class="`${state.pre}-year-select`"
@click="state.showYears = !state.showYears"
v-show="!state.showYears"
>{{ state.year }}</a
>
</template>
<a
:class="`${state.pre}-next-month-btn`"
v-show="!state.showYears && !state.showMonths"
@click="nm"
>
<Icon size="middle" iconName="chevron-right" />
</a>
<a
:class="`${state.pre}-next-year-btn`"
v-show="!state.showYears"
@click="state.year++"
>
<Icon size="sm" iconName="angle-double-right" />
</a>
<a
:class="`${state.pre}-next-decade-btn`"
v-show="state.showYears"
@click="state.year += 10"
>
<Icon size="sm" iconName="angle-double-right" />
</a>
</div>
<div :class="`${state.pre}-body`">
<div :class="`${state.pre}-days`">
<a :class="`${state.pre}-week`" v-for="i in local.weeks" :key="i">{{
i
}}</a>
<a
v-for="(j, i) in days"
@click="is($event) && ((state.day = j.i), ok(j))"
:class="[
j.p || j.n ? `${state.pre}-date-out` : '',
status(
j.y,
j.m,
j.i,
state.hour,
state.minute,
state.second,
'YYYYMMDD'
),
]"
:key="i"
>{{ j.i }}</a
>
</div>
<div :class="`${state.pre}-months`" v-show="state.showMonths">
<a
v-for="(i, j) in local.months"
@click="
is($event) &&
((state.showMonths = m === 'M'),
(state.month = j),
m === 'M' && ok('m'))
"
:class="[
status(
state.year,
j,
state.day,
state.hour,
state.minute,
state.second,
'YYYYMM'
),
]"
:key="j"
>{{ i }}</a
>
</div>
<div :class="`${state.pre}-years`" v-show="state.showYears">
<a
v-for="(i, j) in years"
@click="
is($event) &&
((state.showYears = m === 'Y'),
(state.year = i),
state.m === 'Y' && ok('y'))
"
:class="[
j === 0 || j === 11 ? `${state.pre}-date-out` : '',
status(
i,
state.month,
state.day,
state.hour,
state.minute,
state.second,
'YYYY'
),
]"
:key="j"
>{{ i }}</a
>
</div>
<div :class="`${state.pre}-hours scroll_hide`" v-show="state.showHours">
<div :class="`${state.pre}-title`">{{ local.hourTip }}</div>
<div class="scroll_hide calendar-overflow">
<a
v-for="(j, i) in 24"
@click="
is($event) &&
((state.showHours = false), (state.hour = i), ok('h'))
"
:class="[
status(
state.year,
state.month,
state.day,
i,
state.minute,
state.second,
'YYYYMMDDHH'
),
]"
:key="i"
>{{ i }}</a
>
</div>
</div>
<div :class="`${state.pre}-minutes`" v-show="state.showMinutes">
<div :class="`${state.pre}-title`">{{ local.minuteTip }}</div>
<div class="scroll_hide calendar-overflow">
<a
v-for="(j, i) in 60"
@click="
is($event) &&
((state.showMinutes = false), (state.minute = i), ok('h'))
"
:class="[
status(
state.year,
state.month,
state.day,
state.hour,
i,
state.second,
'YYYYMMDDHHmm'
),
]"
:key="i"
>{{ i }}</a
>
</div>
</div>
<div :class="`${state.pre}-seconds`" v-show="state.showSeconds">
<div :class="`${state.pre}-title`">{{ local.secondTip }}</div>
<div class="scroll_hide calendar-overflow">
<a
v-for="(j, i) in 60"
@click="
is($event) &&
((state.showSeconds = false), (state.second = i), ok('h'))
"
:class="[
status(
state.year,
state.month,
state.day,
state.hour,
state.minute,
i,
'YYYYMMDDHHmmss'
),
]"
:key="i"
>{{ i }}</a
>
</div>
</div>
</div>
<div :class="`${state.pre}-foot`">
<div :class="`${state.pre}-hour`">
<a
:title="local.hourTip"
@click="
(state.showHours = !state.showHours),
(state.showMinutes = state.showSeconds = false)
"
:class="{ on: state.showHours }"
>{{ state.hour || dd }}</a
>
<span>:</span>
<a
:title="local.minuteTip"
@click="
(state.showMinutes = !state.showMinutes),
(state.showHours = state.showSeconds = false)
"
:class="{ on: state.showMinutes }"
>{{ state.minute || dd }}</a
>
<span v-show="state.m !== 'D'">
<span>:</span>
<a
:title="local.secondTip"
@click="
(state.showSeconds = !state.showSeconds),
(state.showHours = state.showMinutes = false)
"
:class="{ on: state.showSeconds }"
>{{ state.second || dd }}</a
>
</span>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {
defineProps,
computed,
defineEmits,
onMounted,
watch,
reactive,
} from "vue";
import { useI18n } from "vue-i18n";
const emit = defineEmits(["input", "setDates", "ok"]);
const { t } = useI18n();
const props = defineProps({
value: { type: Date },
left: { type: Boolean, default: false },
right: { type: Boolean, default: false },
dates: { default: [] },
disabledDate: { type: Function, default: () => false },
format: {
type: String,
default: "YYYY-MM-DD",
},
});
const state = reactive({
pre: "",
m: "",
showYears: false,
showMonths: false,
showHours: false,
showMinutes: false,
showSeconds: false,
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
});
const get = (time: Date): { [key: string]: any } => {
return {
year: time.getFullYear(),
month: time.getMonth(),
day: time.getDate(),
hour: time.getHours(),
minute: time.getMinutes(),
second: time.getSeconds(),
};
};
if (props.value) {
const time = get(props.value);
state.pre = "calendar";
state.m = "D";
state.showYears = false;
state.showMonths = false;
state.showHours = false;
state.showMinutes = false;
state.showSeconds = false;
state.year = time.year;
state.month = time.month;
state.day = time.day;
state.hour = time.hour;
state.minute = time.minute;
state.second = time.second;
}
watch(
() => props.value,
(val: Date | undefined) => {
if (!val) {
return;
}
const time = get(val);
state.year = time.year;
state.month = time.month;
state.day = time.day;
state.hour = time.hour;
state.minute = time.minute;
state.second = time.second;
}
);
const parse = (num: number): number => {
return Math.floor(num / 1000);
};
const start = computed(() => {
return parse(props.dates[0]);
});
const end = computed(() => {
return parse(props.dates[1]);
});
const ys = computed(() => {
return Math.floor(state.year / 10) * 10;
});
const ye = computed(() => {
return ys.value + 10;
});
const years = computed(() => {
const arr = [];
let start = ys.value - 1;
while (arr.length < 12) {
arr.push((start += 1));
}
return arr;
});
const local = computed(() => {
return {
dow: 1, // Monday is the first day of the week
hourTip: t("hourTip"), // tip of select hour
minuteTip: t("minuteTip"), // tip of select minute
secondTip: t("secondTip"), // tip of select second
yearSuffix: t("yearSuffix"), // format of head
monthsHead: t("monthsHead").split("_"), // months of head
months: t("months").split("_"), // months of panel
weeks: t("weeks").split("_"), // weeks
cancelTip: t("cancel"), // default text for cancel button
submitTip: t("confirm"), // default text for submit button
quarterHourCutTip: t("quarterHourCutTip"),
halfHourCutTip: t("halfHourCutTip"),
hourCutTip: t("hourCutTip"),
dayCutTip: t("dayCutTip"),
weekCutTip: t("weekCutTip"),
monthCutTip: t("monthCutTip"),
};
});
const days = computed(() => {
const days = [];
const year = state.year;
const month = state.month;
const time = new Date(year, month, 1);
const dow = local.value.dow || 7;
time.setDate(0); // switch to the last day of last month
let lastDay = time.getDate();
const week = time.getDay() || 7;
let count = dow <= week ? week - dow + 1 : week + (7 - dow + 1);
while (count > 0) {
days.push({
i: lastDay - count + 1,
y: month > 0 ? year : year - 1,
m: month > 0 ? month - 1 : 11,
p: true,
});
count--;
}
time.setMonth(time.getMonth() + 2, 0); // switch to the last day of the current month
lastDay = time.getDate();
let i = 1;
for (i = 1; i <= lastDay; i++) {
days.push({
i: i,
y: year,
m: month,
});
}
for (i = 1; days.length < 42; i++) {
days.push({
i: i,
y: month < 11 ? year : year + 1,
m: month < 11 ? month + 1 : 0,
n: true,
});
}
return days;
});
const dd = (val: number) => ("0" + val).slice(-2);
const status = (
year: number,
month: number,
day: number,
hour: number,
minute: number,
second: number,
format: string
) => {
const maxDay = new Date(year, month + 1, 0).getDate();
const time: any = new Date(
year,
month,
day > maxDay ? maxDay : day,
hour,
minute,
second
);
const t = parse(time);
const tf = (time?: Date, format?: any): string => {
if (!time) {
return "";
}
const year = time.getFullYear();
const month = time.getMonth();
const day = time.getDate();
const hours24 = time.getHours();
const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
const minutes = time.getMinutes();
const seconds = time.getSeconds();
const milliseconds = time.getMilliseconds();
const dd = (t: number) => `0${t}`.slice(-2);
const map: { [key: string]: string | number } = {
YYYY: year,
MM: dd(month + 1),
MMM: local.value.months[month],
MMMM: local.value.monthsHead[month],
M: month + 1,
DD: dd(day),
D: day,
HH: dd(hours24),
H: hours24,
hh: dd(hours),
h: hours,
mm: dd(minutes),
m: minutes,
ss: dd(seconds),
s: seconds,
S: milliseconds,
};
return (format || props.format).replace(
/Y+|M+|D+|H+|h+|m+|s+|S+/g,
(str: string) => map[str]
);
};
const classObj: any = {};
let flag = false;
if (format === "YYYY") {
flag = year === state.year;
} else if (format === "YYYYMM") {
flag = month === state.month;
} else {
flag = tf(props.value, format) === tf(time, format);
}
classObj[`${state.pre}-date`] = true;
classObj[`${state.pre}-date-disabled`] =
(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-selected`] = flag;
return classObj;
};
const nm = () => {
if (state.month < 11) {
state.month++;
} else {
state.month = 0;
state.year++;
}
};
const pm = () => {
if (state.month > 0) {
state.month--;
} else {
state.month = 11;
state.year--;
}
};
const is = (e: any) => {
return e.target.className.indexOf(`${state.pre}-date-disabled`) === -1;
};
const ok = (info: any) => {
let year = "";
let month = "";
let day = "";
info && info.n && nm();
info && info.p && pm();
if (info === "h") {
if (props.value) {
const time = get(props.value);
year = time.year;
month = time.month;
}
} else if (info === "m" || info === "y") {
day = "1";
}
const _time: Date = new Date(
year ? Number(year) : state.year,
month ? Number(month) : state.month,
day ? Number(day) : state.day,
state.hour,
state.minute,
state.second
);
if (props.left && Math.floor(_time.getTime() / 1000) > end.value) {
emit("setDates", _time);
}
emit("input", _time);
ok(info === "h");
};
onMounted(() => {
const is = (c: string) => props.format.indexOf(c) !== -1;
if (is("s") && is("m") && (is("h") || is("H"))) {
state.m = "H";
} else if (is("D")) {
state.m = "D";
} else if (is("M")) {
state.m = "M";
state.showMonths = true;
} else if (is("Y")) {
state.m = "Y";
state.showYears = true;
}
});
</script>
<style scoped>
.calendar {
float: left;
user-select: none;
color: #3d444f;
}
.calendar + .calendar {
border-left: solid 1px #eaeaea;
margin-left: 5px;
padding-left: 5px;
}
.calendar-head {
line-height: 34px;
height: 34px;
text-align: center;
position: relative;
}
.calendar-head a {
color: #666;
cursor: pointer;
display: inline-block;
text-align: center;
position: absolute;
padding: 0 5px;
font-size: 16px;
}
.calendar-head a:hover {
color: #3f97e3;
}
.calendar-head .calendar-year-select,
.calendar-head .calendar-month-select {
font-size: 12px;
padding: 0 2px;
position: relative;
}
.calendar-prev-decade-btn,
.calendar-prev-year-btn {
left: 6px;
}
.calendar-prev-month-btn {
left: 24px;
}
.calendar-next-decade-btn,
.calendar-next-year-btn {
right: 6px;
}
.calendar-next-month-btn {
right: 24px;
}
.calendar-next-month-btn .middle,
.calendar-prev-month-btn .middle {
margin-top: 8px;
}
.calendar-body {
position: relative;
width: 196px;
height: 196px;
}
.calendar-days {
width: 100%;
height: 100%;
}
.calendar-week,
.calendar-date {
font-weight: normal;
width: 14.28%;
height: 14.28%;
text-align: center;
box-sizing: border-box;
overflow: hidden;
float: left;
}
.calendar-week:before,
.calendar-date:before {
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.calendar-date {
cursor: pointer;
line-height: 29px;
transition: background-color 0.3s;
}
.calendar-date-out {
color: #ccc;
}
.calendar-date:hover,
.calendar-date-on {
color: #3f97e3;
background-color: #f8f8f8;
}
.calendar-date-selected,
.calendar-date-selected:hover {
color: #fff;
font-weight: bold;
border-radius: 14px;
background: #3f97e3;
}
.calendar-date-disabled {
cursor: not-allowed !important;
color: #ccc !important;
background: #fff !important;
}
.calendar-foot {
margin-top: 5px;
}
.calendar-hour {
display: inline-block;
border: 1px solid #e6e5e5;
color: #9e9e9e;
}
.calendar-hour a {
display: inline-block;
padding: 2px 4px;
cursor: pointer;
}
.calendar-hour a:hover,
.calendar-hour a.on {
color: #3f97e3;
}
.calendar-years,
.calendar-months,
.calendar-hours,
.calendar-minutes,
.calendar-seconds {
width: 100%;
height: 100%;
position: absolute;
background: #fff;
left: 0;
top: 0;
}
.calendar-months a {
width: 33.33%;
height: 25%;
}
.calendar-years a {
width: 33.33%;
height: 25%;
}
.calendar-overflow {
overflow-x: scroll;
height: 100%;
}
/* .calendar-hours a {
width: 20%;
height: 20%;
}
.calendar-minutes a,
.calendar-seconds a {
width: 16.66%;
height: 10%;
} */
.calendar-title {
margin-top: -30px;
height: 30px;
line-height: 30px;
background: #fff;
text-align: center;
font-weight: bold;
}
</style>

69
src/components/Icon.vue Normal file
View File

@ -0,0 +1,69 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<svg
class="icon"
:class="{
sm: size === 'sm',
middle: size === 'middle',
lg: size === 'lg',
xl: size === 'xl',
logo: size === 'logo',
loading: loading,
}"
>
<use :xlink:href="`#${iconName}`"></use>
</svg>
</template>
<script lang="ts" setup>
import { defineProps } from "vue";
import "@/assets/icons/index";
defineProps({
iconName: { type: String, default: "" },
size: { type: String, default: "sm" },
loading: { type: Boolean, default: false },
});
</script>
<style lang="scss" scope>
.icon {
width: 16px;
height: 16px;
vertical-align: middle;
fill: currentColor;
&.sm {
width: 14px;
height: 14px;
}
&.middle {
width: 18px;
height: 18px;
}
&.lg {
width: 24px;
height: 24px;
}
&.loading {
animation: loading 1.5s linear infinite;
}
&.logo {
height: 30px;
width: 110px;
}
&.xl {
height: 30px;
width: 30px;
}
}
</style>

570
src/components/TimePicker.vue Executable file
View File

@ -0,0 +1,570 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div
class="datepicker cp"
:class="{
'datepicker-range': range,
datepicker__clearable: clearable && text && !disabled,
}"
ref="datepicker"
>
<input
class="cp"
readonly
:value="text"
:class="[show ? 'focus' : '', inputClass]"
:disabled="disabled"
:placeholder="placeholder"
:name="name"
v-if="type !== 'inline'"
/>
<a class="datepicker-close" @click.stop="cls"></a>
<transition name="datepicker-anim">
<div
class="datepicker-popup"
:class="[
popupClass,
{ 'datepicker-inline': type === 'inline' },
position,
]"
tabindex="-1"
v-if="show || type === 'inline'"
>
<template v-if="range">
<div class="datepicker-popup__sidebar">
<button
type="button"
class="datepicker-popup__shortcut"
@click="quickPick('quarter')"
>
{{ local.quarterHourCutTip }}
</button>
<button
type="button"
class="datepicker-popup__shortcut"
@click="quickPick('half')"
>
{{ local.halfHourCutTip }}
</button>
<button
type="button"
class="datepicker-popup__shortcut"
@click="quickPick('hour')"
>
{{ local.hourCutTip }}
</button>
<button
type="button"
class="datepicker-popup__shortcut"
@click="quickPick('day')"
>
{{ local.dayCutTip }}
</button>
<button
type="button"
class="datepicker-popup__shortcut"
@click="quickPick('week')"
>
{{ local.weekCutTip }}
</button>
<button
type="button"
class="datepicker-popup__shortcut"
@click="quickPick('month')"
>
{{ local.monthCutTip }}
</button>
</div>
<div class="datepicker-popup__body">
<DateCalendar
v-model="dates[0]"
:value="dates[0]"
:dates="dates"
:left="true"
:disabledDate="disabledDate"
:format="format"
@ok="ok"
@setDates="setDates"
/>
<DateCalendar
v-model="dates[1]"
:value="dates[1]"
:dates="dates"
:right="true"
:disabledDate="disabledDate"
:format="format"
@ok="ok"
@setDates="setDates"
/>
</div>
</template>
<template v-else>
<DateCalendar
v-model="dates[0]"
:value="dates[0]"
:disabledDate="disabledDate"
:dates="dates"
:format="format"
@ok="ok"
@setDates="setDates"
/>
</template>
<div v-if="showButtons" class="datepicker__buttons">
<button
@click.prevent.stop="cancel"
class="datepicker__button-cancel"
>
{{ local.cancelTip }}
</button>
<button
@click.prevent.stop="submit"
class="datepicker__button-select"
>
{{ local.submitTip }}
</button>
</div>
</div>
</transition>
</div>
</template>
<script lang="ts" setup>
import {
defineProps,
ref,
computed,
defineEmits,
onMounted,
onBeforeUnmount,
watch,
} from "vue";
import { useI18n } from "vue-i18n";
import DateCalendar from "./DateCalendar.vue";
const datepicker = ref(null);
const { t } = useI18n();
const show = ref<boolean>(false);
const dates = ref<Date[]>([]);
const props = defineProps({
position: { type: String, default: "bottom" },
name: [String],
inputClass: [String],
popupClass: [String],
value: [Date, Array, String],
disabled: [Boolean],
type: {
type: String,
default: "normal",
},
rangeSeparator: {
type: String,
default: "~",
},
clearable: {
type: Boolean,
default: false,
},
placeholder: [String],
disabledDate: {
type: Function,
default: () => false,
},
format: {
type: String,
default: "YYYY-MM-DD",
},
showButtons: {
type: Boolean,
default: false,
},
dateRangeSelect: [Function],
});
const emit = defineEmits(["clear", "input", "confirm", "cancel"]);
const local = computed(() => {
return {
dow: 1, // Monday is the first day of the week
hourTip: t("hourTip"), // tip of select hour
minuteTip: t("minuteTip"), // tip of select minute
secondTip: t("secondTip"), // tip of select second
yearSuffix: t("yearSuffix"), // format of head
monthsHead: t("monthsHead").split("_"), // months of head
months: t("months").split("_"), // months of panel
weeks: t("weeks").split("_"), // weeks
cancelTip: t("cancel"), // default text for cancel button
submitTip: t("confirm"), // default text for submit button
quarterHourCutTip: t("quarterHourCutTip"),
halfHourCutTip: t("halfHourCutTip"),
hourCutTip: t("hourCutTip"),
dayCutTip: t("dayCutTip"),
weekCutTip: t("weekCutTip"),
monthCutTip: t("monthCutTip"),
};
});
const tf = (time: Date, format?: any): string => {
const year = time.getFullYear();
const month = time.getMonth();
const day = time.getDate();
const hours24 = time.getHours();
const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
const minutes = time.getMinutes();
const seconds = time.getSeconds();
const milliseconds = time.getMilliseconds();
const dd = (t: number) => `0${t}`.slice(-2);
const map: { [key: string]: string | number } = {
YYYY: year,
MM: dd(month + 1),
MMM: local.value.months[month],
MMMM: local.value.monthsHead[month],
M: month + 1,
DD: dd(day),
D: day,
HH: dd(hours24),
H: hours24,
hh: dd(hours),
h: hours,
mm: dd(minutes),
m: minutes,
ss: dd(seconds),
s: seconds,
S: milliseconds,
};
return (format || props.format).replace(
/Y+|M+|D+|H+|h+|m+|s+|S+/g,
(str: string) => map[str]
);
};
const range = computed(() => {
return dates.value.length === 2;
});
const text = computed(() => {
const val = props.value;
const txt = dates.value
.map((date) => tf(date))
.join(` ${props.rangeSeparator} `);
if (Array.isArray(val)) {
return val.length > 1 ? txt : "";
}
return val ? txt : "";
});
const get = () => {
return Array.isArray(props.value) ? dates.value : dates.value[0];
};
const cls = () => {
emit("clear");
emit("input", range.value ? [] : "");
};
const vi = (val: any) => {
if (Array.isArray(val)) {
return val.length > 1
? val.map((item) => new Date(item))
: [new Date(), new Date()];
}
return val ? [new Date(val)] : [new Date()];
};
const ok = (leaveOpened: boolean) => {
emit("input", get());
!leaveOpened &&
!props.showButtons &&
setTimeout(() => {
show.value = range.value;
});
};
const setDates = (d: Date) => {
dates.value[1] = d;
};
const dc = (e: any) => {
show.value = (datepicker.value as any).contains(e.target) && !props.disabled;
};
const quickPick = (type: string) => {
const end = new Date();
const start = new Date();
switch (type) {
case "quarter":
start.setTime(start.getTime() - 60 * 15 * 1000); //15 mins
break;
case "half":
start.setTime(start.getTime() - 60 * 30 * 1000); //30 mins
break;
case "hour":
start.setTime(start.getTime() - 3600 * 1000); //1 hour
break;
case "day":
start.setTime(start.getTime() - 3600 * 1000 * 24); //1 day
break;
case "week":
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); //1 week
break;
case "month":
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); //1 month
break;
default:
break;
}
dates.value = [start, end];
emit("input", get());
};
const submit = () => {
emit("confirm", get());
show.value = false;
};
const cancel = () => {
emit("cancel");
show.value = false;
};
onMounted(() => {
dates.value = vi(props.value);
document.addEventListener("click", dc, true);
});
onBeforeUnmount(() => {
document.removeEventListener("click", dc, true);
});
watch(
() => props.value,
(val: unknown) => {
dates.value = vi(val);
}
);
</script>
<style lang="scss" scoped>
.datepicker {
display: inline-block;
position: relative;
}
.datepicker-icon {
display: block;
position: absolute;
top: 8px;
left: 8px;
color: #515a6ecc;
}
.datepicker-close {
display: none;
position: absolute;
width: 34px;
height: 100%;
top: 0;
right: 0;
cursor: pointer;
}
.datepicker-close:before {
display: block;
content: "";
position: absolute;
width: 16px;
height: 16px;
left: 50%;
top: 50%;
margin-left: -8px;
margin-top: -8px;
text-align: center;
background: #ccc;
color: #fff;
border-radius: 50%;
background: #ccc
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3IDciIHdpZHRoPSI3IiBoZWlnaHQ9IjciPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01LjU4LDVsMi44LTIuODFBLjQxLjQxLDAsMSwwLDcuOCwxLjZMNSw0LjQxLDIuMiwxLjZhLjQxLjQxLDAsMCwwLS41OC41OGgwTDQuNDIsNSwxLjYyLDcuOGEuNDEuNDEsMCwwLDAsLjU4LjU4TDUsNS41OCw3LjgsOC4zOWEuNDEuNDEsMCwwLDAsLjU4LS41OGgwWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuNSAtMS40OCkiIHN0eWxlPSJmaWxsOiNmZmYiLz48L3N2Zz4NCg==")
no-repeat 50% 50%;
}
.datepicker__clearable:hover:before {
display: none;
}
.datepicker__clearable:hover .datepicker-close {
display: block;
}
.datepicker-close:hover:before {
background-color: #afafaf;
}
.datepicker > input {
color: inherit;
// transition: all 200ms ease;
border-radius: 4px;
border: 0;
background: none;
height: 28px;
box-sizing: border-box;
outline: none;
padding: 0 5px;
width: 100%;
user-select: none;
font-family: "Monaco";
letter-spacing: -0.7px;
}
// .datepicker > input.focus {
// border-color: #3f97e3;
// -webkit-box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
// box-shadow: 0 0 5px rgba(59, 180, 242, 0.3);
// }
.datepicker > input:disabled {
cursor: not-allowed;
background-color: #ebebe4;
border-color: #e5e5e5;
-webkit-box-shadow: none;
box-shadow: none;
}
.datepicker-popup {
border-radius: 4px;
position: absolute;
transition: all 200ms ease;
opacity: 1;
transform: scaleY(1);
font-size: 12px;
background: #fff;
box-shadow: 0 1px 6px rgba(99, 99, 99, 0.2);
margin-top: 2px;
outline: 0;
padding: 5px;
overflow: hidden;
z-index: 999;
&.top {
bottom: 30px;
right: 0;
transform-origin: center bottom;
}
&.bottom {
top: 30px;
right: 0;
transform-origin: center top;
}
&.left {
top: 30px;
transform-origin: center top;
}
&.right {
right: -80px;
top: 30px;
transform-origin: center top;
}
&__sidebar {
position: absolute;
top: 0;
bottom: 0;
width: 100px;
height: 100%;
padding: 5px;
border-right: solid 1px #eaeaea;
}
&__shortcut {
display: block;
width: 100%;
border: 0;
background-color: transparent;
line-height: 34px;
font-size: 12px;
color: #666;
text-align: left;
outline: none;
cursor: pointer;
white-space: nowrap;
&:hover {
color: #3f97e3;
}
}
&__body {
margin-left: 100px;
padding-left: 5px;
}
}
.datepicker-inline {
position: relative;
margin-top: 0;
}
.datepicker-range {
min-width: 238px;
}
.datepicker-range .datepicker-popup {
width: 520px;
}
.datepicker-bottom {
float: left;
width: 100%;
text-align: right;
}
.datepicker-btn {
padding: 5px 10px;
background: #3f97e3;
color: #fff;
border-radius: 2px;
display: inline-block;
cursor: pointer;
}
.datepicker-anim-enter-active {
transform-origin: 0 0;
animation: datepicker-anim-in 0.2s cubic-bezier(0.23, 1, 0.32, 1);
}
.datepicker-anim-leave-active {
transform-origin: 0 0;
animation: datepicker-anim-out 0.2s cubic-bezier(0.755, 0.05, 0.855, 0.06);
}
.datepicker__buttons {
display: block;
text-align: right;
}
.datepicker__buttons button {
display: inline-block;
font-size: 13px;
border: none;
cursor: pointer;
margin: 10px 0 0 5px;
padding: 5px 15px;
color: #ffffff;
}
.datepicker__buttons .datepicker__button-select {
background: #3f97e3;
}
.datepicker__buttons .datepicker__button-cancel {
background: #666;
}
@keyframes datepicker-anim-in {
0% {
opacity: 0;
transform: scaleY(0.8);
}
to {
opacity: 1;
transform: scaleY(1);
}
}
@keyframes datepicker-anim-out {
0% {
opacity: 1;
transform: scaleY(1);
}
to {
opacity: 0;
transform: scaleY(0.8);
}
}
</style>

30
src/components/index.ts Normal file
View File

@ -0,0 +1,30 @@
/**
* 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 Icon from "./Icon.vue";
import TimePicker from "./TimePicker.vue";
import type { App } from "vue";
const components: { [key: string]: any } = { Icon, TimePicker };
const componentsName: string[] = Object.keys(components);
export default {
install: (vue: App): void => {
componentsName.forEach((i) => {
vue.component(i, components[i]);
});
},
};

21
src/constants/data.ts Normal file
View File

@ -0,0 +1,21 @@
/**
* 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.
*/
export enum TimeType {
MINUTE_TIME = "MINUTE",
HOUR_TIME = "HOUR",
DAY_TIME = "DAY",
}

View File

@ -0,0 +1,28 @@
/**
* 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.
*/
export const OAPTimeInfo = {
query: `
getTimeInfo {
timezone
currentTimestamp
}
`,
};
export const OAPVersion = {
query: `version { version }`,
};

52
src/graph/index.ts Normal file
View File

@ -0,0 +1,52 @@
/**
* 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 axios, { AxiosPromise, AxiosResponse } from "axios";
import { cancelToken } from "@/utils/cancelToken";
import * as global from "./query/global";
const query: { [key: string]: string } = { ...global };
class Graph {
private queryData = "";
public query(queryData: string) {
this.queryData = queryData;
return this;
}
public params(variablesData: unknown): AxiosPromise<void> {
return axios
.post(
"/graphql",
{
query: query[this.queryData],
variables: variablesData,
},
{ cancelToken: cancelToken() }
)
.then((res: AxiosResponse) => {
if (res.data.errors) {
res.data.errors = res.data.errors
.map((e: { message: string }) => e.message)
.join(" ");
}
return res;
})
.catch((err: Error) => {
throw err;
});
}
}
export default new Graph();

21
src/graph/query/global.ts Normal file
View File

@ -0,0 +1,21 @@
/**
* 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 { OAPTimeInfo, OAPVersion } from "../fragments/global";
export const queryOAPTimeInfo = `query queryOAPTimeInfo {${OAPTimeInfo.query}}`;
export const queryOAPVersion = `query ${OAPVersion.query}`;

35
src/layout/Index.vue Normal file
View File

@ -0,0 +1,35 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="app-wrapper flex-h">
<SideBar />
<div class="main-container">
<NavBar />
<AppMain />
</div>
</div>
</template>
<script lang="ts" setup>
import { AppMain, SideBar, NavBar } from "./components";
</script>
<style lang="scss" scope>
.app-wrapper {
height: 100%;
}
.main-container {
flex-grow: 2;
height: 100%;
}
</style>

View File

@ -0,0 +1,36 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<section class="app-main">
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</section>
</template>
<script lang="ts" setup>
import { useRoute } from "vue-router";
const route = useRoute();
const key = () => {
return route.path;
};
</script>
<style lang="scss" scoped>
.app-main {
height: calc(100% - 128px);
}
</style>

View File

@ -0,0 +1,109 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="nav-bar flex-h" :class="{ dark: theme === 'dark' }">
<div class="title">{{ t(pageName) }}</div>
<div class="app-config">
<span class="red" v-show="timeRange">{{ t("timeTips") }}</span>
<TimePicker
v-model="time"
:value="time"
position="bottom"
format="YYYY-MM-DD HH:mm"
/>
<span>
UTC{{ utcHour >= 0 ? "+" : ""
}}{{ `${appStore.utcHour}:${appStore.utcMin}` }}
</span>
<!-- <span @click="handleReload" title="refresh">
<Icon icon="retry" :loading="auto" class="middle" />
</span> -->
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, computed } from "vue";
import { useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import timeFormat from "@/utils/timeFormat";
import { useAppStoreWithOut } from "@/store/modules/app";
const { t } = useI18n();
const appStore = useAppStoreWithOut();
const route = useRoute();
const pageName = ref<string>("");
const timeRange = ref<number>(0);
const theme = ref<string>("light");
let utc = localStorage.getItem("utc") || "";
if (!utc.includes(":")) {
utc =
(localStorage.getItem("utc") || -(new Date().getTimezoneOffset() / 60)) +
":0";
}
const utcArr = (utc || "").split(":");
const utcHour = isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]);
const utcMin = isNaN(Number(utcArr[1])) ? 0 : Number(utcArr[1]);
appStore.setUTC(utcHour, utcMin);
console.log(route);
const setConfig = (value: string) => {
pageName.value = value || "";
theme.value = route.path.includes("/infrastructure/") ? "dark" : "light";
};
const time = computed({
get() {
return [appStore.durationRow.start, appStore.durationRow.end];
},
set(val: Date[]) {
timeRange.value =
val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
if (timeRange.value) {
return;
}
appStore.setDuration(timeFormat(val));
},
});
setConfig(String(route.meta.title));
watch(
() => route.meta.title,
(title: unknown) => {
setConfig(String(title));
}
);
</script>
<style lang="scss" scoped>
.nav-bar {
padding: 5px 10px 5px 28px;
text-align: left;
justify-content: space-between;
background-color: #fafbfc;
border-bottom: 1px solid #dfe4e8;
color: #222;
}
.nav-bar.dark {
background-color: #333840;
border-bottom: 1px solid #252a2f;
color: #fafbfc;
}
.title {
font-size: 14px;
font-weight: 500;
height: 28px;
line-height: 28px;
}
.nav-tabs {
padding: 10px;
}
</style>

View File

@ -0,0 +1,161 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="side-bar">
<div :class="isCollapse ? 'logo-icon-collapse' : 'logo-icon'">
<Icon
:size="isCollapse ? 'xl' : 'logo'"
:iconName="isCollapse ? 'logo' : 'logo-sw'"
/>
</div>
<el-menu
active-text-color="#448dfe"
background-color="#252a2f"
class="el-menu-vertical"
default-active="0"
text-color="#efefef"
:unique-opened="true"
:collapse="isCollapse"
:style="{ border: 'none' }"
>
<template v-for="(menu, index) in routes" :key="index">
<el-sub-menu :index="String(index)" v-if="menu.meta.hasGroup">
<template #title>
<router-link :to="menu.path" :exact="menu.meta.exact || false">
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
<Icon size="lg" :iconName="menu.meta.icon" />
</el-icon>
<span>{{ t(menu.meta.title) }}</span>
</router-link>
</template>
<el-menu-item-group>
<el-menu-item
v-for="(m, idx) in filterMenus(menu.children)"
:index="`${index}-${idx}`"
:key="idx"
>
<router-link :to="m.path" :exact="m.meta.exact || false">
<span>{{ t(m.meta.title) }}</span>
</router-link>
</el-menu-item>
</el-menu-item-group>
</el-sub-menu>
<el-menu-item :index="String(index)" @click="changePage(menu)" v-else>
<el-icon class="menu-icons" :style="{ margin: '-10px 12px 0 0' }">
<router-link :to="menu.children[0].path" :exact="menu.meta.exact">
<Icon size="lg" :iconName="menu.meta.icon" />
</router-link>
</el-icon>
<template #title>
<router-link :to="menu.children[0].path" :exact="menu.meta.exact">
<span>{{ t(menu.meta.title) }}</span>
</router-link>
</template>
</el-menu-item>
</template>
</el-menu>
<div
class="menu-control"
:class="isCollapse ? 'collapse' : ''"
:style="{
color: theme === 'light' ? '#eee' : '#252a2f',
}"
>
<Icon
size="middle"
iconName="format_indent_decrease"
@click="controlMenu"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { useRouter, RouteRecordRaw, RouteRecordName } from "vue-router";
import { useI18n } from "vue-i18n";
import {
ElMenu,
ElMenuItem,
ElSubMenu,
ElMenuItemGroup,
ElIcon,
} from "element-plus";
const { t } = useI18n();
const name: RouteRecordName | null | undefined = String(
useRouter().currentRoute.value.name
);
const theme = ["VirtualMachine", "Kubernetes"].includes(name || "")
? ref("light")
: ref("black");
const routes = useRouter().options.routes;
const isCollapse = ref(false);
const controlMenu = () => {
isCollapse.value = !isCollapse.value;
};
const changePage = (menu: RouteRecordRaw) => {
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name))
? "light"
: "black";
};
const filterMenus = (menus: any[]) => {
return menus.filter((d) => d.meta && !d.meta.notShow);
};
</script>
<style lang="scss" scope>
.side-bar {
position: relative;
height: 100%;
background: #252a2f;
font-weight: bold;
// box-shadow: 1px 5px 3px #888;
}
.el-menu-vertical:not(.el-menu--collapse) {
width: 210px;
font-size: 18px;
}
.logo-icon-collapse {
width: 65px;
margin: 15px 0 30px 0;
}
.logo-icon {
margin: 15px 0 30px 15px;
width: 110px;
}
.el-sub-menu .el-icon {
height: 26px;
margin-right: 0;
}
.el-sub-menu__title {
font-size: 16px;
font-weight: bold;
}
.menu-control {
position: absolute;
top: 8px;
left: 215px;
cursor: pointer;
transition: all 0.2s linear;
z-index: 9999;
color: #252a2f;
}
.menu-control.collapse {
left: 70px;
}
.el-icon.el-sub-menu__icon-arrow {
height: 12px;
}
</style>

View File

@ -0,0 +1,19 @@
/**
* 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.
*/
export { default as AppMain } from "./AppMain.vue";
export { default as SideBar } from "./SideBar.vue";
export { default as NavBar } from "./NavBar.vue";

38
src/locales/index.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* 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 { createI18n } from "vue-i18n";
import zh from "./lang/zh";
import en from "./lang/en";
const messages = {
en,
zh,
};
const savedLanguage = window.localStorage.getItem("lang");
let language = navigator.language.split("-")[0];
if (!savedLanguage) {
window.localStorage.setItem("lang", language);
}
language = savedLanguage ? savedLanguage : language;
const i18n = createI18n({
locale: language,
messages,
});
export default i18n;

291
src/locales/lang/en.ts Normal file
View File

@ -0,0 +1,291 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const msg = {
generalService: "General Service",
services: "Services",
traces: "Traces",
metrics: "Metrics",
serviceMesh: "Service Mesh",
infrastructure: "Infrastructure",
virtualMachine: "Virtual Machine",
kubernetes: "Kubernetes",
dashboardHome: "Dashboard Home",
dashboardList: "Dashboard List",
logs: "Logs",
events: "Events",
alerts: "Alerts",
settings: "Settings",
dashboards: "Dashboards",
profiles: "Profiles",
database: "Database",
serviceName: "Service Name",
technologies: "Technologies",
generalServicePanel: "General Service Panel",
health: "Health",
groupName: "Group Name",
topologies: "Topologies",
dataPanel: "Data Panel",
controlPanel: "Control Panel",
eventList: "Event List",
databasePanel: "Database Panel",
meshServicePanel: "Service Panel",
hourTip: "Select Hour",
minuteTip: "Select Minute",
secondTip: "Select Second",
second: "s",
yearSuffix: "Year",
monthsHead: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec",
months: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec",
weeks: "Mon_Tue_Wed_Thu_Fir_Sat_Sun",
hello: "Hello",
helloMessage: "Welcome Back, Apache SkyWalking APM System !",
username: "Username",
password: "Password",
title: "Title",
width: "Width",
height: "Height",
login: "Login Now",
signout: "Sign Out",
dashboard: "Dashboard",
topology: "Topology",
trace: "Trace",
alarm: "Alarm",
event: "Event",
auto: "Auto",
reload: "Reload",
usermode: "User Mode",
editmode: "Edit Mode",
currentService: "Current Service",
currentEndpoint: "Current Endpoint",
currentInstance: "Current Instance",
currentVersion: "Current Version",
currentPage: "Current Page",
version: "Version",
page: "Page",
currentDatabase: "Current Database",
templateConfig: "Template Configuration",
copy: "Copy",
reset: "Reset",
apply: "Apply",
createTemplate: "Create Template",
templateType: "Template Type",
templateName: "Template Name",
template: "Template",
confirm: "Confirm",
cancel: "Cancel",
createTab: "Create Tab",
tabName: "Tab Name",
nouse: "No Use",
allServices: "All Services",
serviceDetail: "Service Detail",
detectPoint: "Detect Point",
callType: "Call Type",
server: "Server",
client: "Client",
name: "Name",
types: "Types",
cpm: "Cpm",
sla: "SLA",
latency: "Latency",
avgResponseTime: "Avg Response Time ( ms )",
avgThroughput: "Load (CPM - calls per minute)",
avgSLA: "Successful Rate ( % )",
all: "All",
success: "Success",
error: "Error",
service: "Service",
instance: "Instance",
endpoints: "Endpoints",
cache: "Cache",
global: "Global",
serviceendpoint: "ServiceEndpoint",
serviceinstance: "ServiceInstance",
databaseaccess: "DatabaseAccess",
servicerelation: "ServiceRelation",
serviceinstancerelation: "ServiceInstanceRelation",
endpointrelation: "EndpointRelation",
status: "Status",
endpointName: "Endpoint Name",
search: "Search",
clear: "Clear",
more: "More",
traceID: "Trace ID",
range: "Range",
timeRange: "Time Range",
duration: "Duration",
startTime: "Start Time",
start: "Start",
spans: "Spans",
spanInfo: "Span Info",
spanType: "Span Type",
time: "Time",
tags: "Tags",
component: "Component",
table: "Table",
list: "List",
tree: "Tree",
filterScope: "Filter Scope",
searchKeyword: "Search Keyword",
quarterHourCutTip: "Last 15 mins",
halfHourCutTip: "Last 30 mins",
hourCutTip: "Last 1 hour",
dayCutTip: "Last 1 day",
weekCutTip: "Last 1 week",
monthCutTip: "Last 1 month",
serverZone: "Server Zone",
percentResponse: "Response Time Percentile ( ms )",
exportImage: "Export image",
queryData: "Query",
previousService: "Previous Service",
nextService: "Next Service",
object: "Object",
ShowInstanceDependency: "Show Instance Dependency",
InstanceDependencyTitle: "Service Instance Dependency",
profile: "Profile",
newTask: "New Task",
monitorTime: "Monitor Time",
monitorDuration: "Monitor Duration",
minThreshold: "Min Duration Threshold",
dumpPeriod: "Dump Period",
createTask: "Create Task",
maxSamplingCount: "Max Sampling Count",
analyze: "Analyze",
noData: "No Data",
taskInfo: "Task Information",
task: "Task",
operationType: "Operation Type",
operationTime: "Operation Time",
taskView: "View Task",
includeChildren: "Include Children",
excludeChildren: "Exclude Children",
view: "View",
timeTips: "Time interval cannot exceed 60 days",
standardAPM: "Standard",
entityType: "Entity type",
maxItemNum: "Max number of Item",
independentSelector: "Selectors",
unknownMetrics: "Unknown Metrics",
labels: "Labels",
aggregation: "Data Calculation",
unit: "Unit",
labelsIndex: "Label Subscript",
parentService: "Parent Service",
isParentService: "Set Parent Service",
noneParentService: "No Parent Service",
serviceGroup: "Service Group",
endpointFilter: "Endpoint Filter",
editConfig: "Edit Config",
databaseView: "Database",
browserView: "Browser",
metricsView: "NOC - Network Operation Center",
sortOrder: "Sort Order",
descendOrder: "Descend Order",
increaseOrder: "Increase Order",
defaultOrder: "Default Order",
chartType: "Chart Type",
currentDepth: "Current Depth",
traceTagsTip: `Only tags defined in the core/default/searchableTracesTags are searchable.
Check more details on the Configuration Vocabulary page`,
tagsLink: "Configuration Vocabulary page",
addTag: "Please input a tag",
log: "Log",
logCategory: "Log Category",
errorCatalog: "Error Catalog",
logDetail: "Log Detail ",
timeReload: "Notice: The time interval must be greater than 0",
errorInfo: "Error Info",
stack: "Stack",
serviceVersion: "Service Version",
errorPage: "Error Page",
category: "Category",
grade: "Grade",
relatedTraceLogs: "Related Logs",
setConditions: "More Conditions",
metricName: "Metric Name",
keywordsOfContent: "Keys Of Content",
excludingKeywordsOfContent: "Exclude Keys Of Content",
return: "Return",
isError: "Error",
contentType: "Content Type",
content: "Content",
viewLogs: "View Logs",
logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable.
Check more details on the Configuration Vocabulary page`,
keywordsOfContentLogTips:
"Current storage of SkyWalking OAP server does not support this.",
setEvent: "Set Event",
instanceAttributes: "Instance Attributes",
serviceEvents: "Service Events",
select: "Select",
eventID: "Event ID",
eventName: "Event Name",
endTime: "End Time",
instanceEvents: "Instance Events",
endpointEvents: "Endpoint Events",
enableEvents: "Enable Events",
disableEvents: "Disable Events",
eventSeries: "Events Series",
eventsType: "Event Type",
eventsMessage: "Event Message",
eventsParameters: "Event Parameters",
eventDetail: "Event Detail",
value: "Value",
tableHeader: "Header Names",
tableValues: "Table Values",
show: "Show",
hide: "Hide",
statistics: "Statistics",
message: "Message",
tooltipsContent: "Tooltip Content",
alarmDetail: "Alarm Detail",
scope: "Scope",
destService: "Destination Service",
destServiceInstance: "Destination Service Instance",
eventSource: "Event Source",
modalTitle: "Inspection",
selectRedirectPage: "Do you want to inspect Traces or Logs of %s service?",
logAnalysis: "Log Analysis Language",
logDataBody: "The content of the log",
addType: "Please input a type",
traceContext: "Logs with trace context",
traceSegmentId: "Trace Segment ID",
spanId: "Span ID",
inputTraceSegmentId: "Please input the trace segment ID",
inputSpanId: "Please input the span ID",
inputTraceId: "Please input the trace ID",
dsl: "Script input for LAL",
logContentType: "The type of the log content",
logRespContent: "Log Content",
analysis: "Analysis",
waitLoading: "Loading",
dslEmpty: "Script input of LAL should not be empty",
logContentEmpty: "The content of the log should not be empty.",
debug: "Debug",
addTraceID: "Please input a trace ID",
addKeywordsOfContent: "Please input a keyword of content",
addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
noticeTag: "Please press enter after inputting a tag.",
conditionNotice:
"Notice: Please press enter after inputting a tag, key of content, exclude key of content.",
cacheModalTitle: "Clear cache reminder",
yes: "Yes",
no: "No",
cacheReminderContent:
"SkyWalking detected dashboard template updates, do you want to update?",
language: "Language",
};
export default msg;

287
src/locales/lang/zh.ts Normal file
View File

@ -0,0 +1,287 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const msg = {
generalService: "普通服务",
services: "服务",
traces: "跟踪",
metrics: "指标",
serviceMesh: "服务网格",
infrastructure: "基础结构",
virtualMachine: "虚拟机",
kubernetes: "Kubernetes",
dashboardHome: "仪表盘首页",
dashboardList: "仪表盘列表",
log: "日志",
events: "事件",
alerts: "警告",
settings: "设置",
dashboards: "仪表盘",
profiles: "性能剖析",
database: "数据库",
serviceName: "服务名称",
technologies: "技术",
health: "健康",
groupName: "群名称",
generalServicePanel: "普通服务面板",
topologies: "拓扑图",
dataPanel: "数据面板",
controlPanel: "控制面板",
eventList: "事件列表",
databasePanel: "数据库面板",
meshServicePanel: "服务面板",
hourTip: "选择小时",
minuteTip: "选择分钟",
secondTip: "选择秒数",
second: "秒",
yearSuffix: "年",
monthsHead: "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月",
months: "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月",
weeks: "一_二_三_四_五_六_日",
hello: "你好",
helloMessage: "欢迎来到, Apache SkyWalking APM 系统 !",
username: "用户名",
password: "密码",
title: "标题",
width: "宽度",
height: "高度",
login: "登录",
signout: "登出",
topology: "拓扑图",
trace: "追踪",
alarm: "告警",
event: "事件",
auto: "自动",
reload: "刷新",
usermode: "用户模式",
editmode: "编辑模式",
currentService: "当前服务",
currentEndpoint: "当前端点",
currentInstance: "当前实例",
currentVersion: "当前版本",
currentPage: "当前页面",
version: "版本",
page: "页面",
currentDatabase: "当前数据库",
templateConfig: "模版配置",
copy: "拷贝",
reset: "重制",
apply: "应用",
createTemplate: "创建模板",
templateType: "模板类型",
templateName: "模板名称",
template: "模版",
confirm: "确定",
cancel: "取消",
createTab: "创建分页",
tabName: "分页名",
nouse: "不使用",
allServices: "所有服务",
serviceDetail: "服务详情",
detectPoint: "侦察端",
callType: "调用类型",
server: "服务端",
client: "客户端",
name: "名称",
types: "类型",
cpm: "每分钟请求量",
sla: "SLA",
latency: "延迟",
avgResponseTime: "平均响应时间",
avgThroughput: "平均吞吐量",
avgSLA: "平均SLA",
all: "全部",
success: "成功",
error: "失败",
service: "服务",
instance: "实例",
endpoints: "端点",
cache: "存储器",
global: "全局",
serviceendpoint: "服务端点",
serviceinstance: "服务实例",
databaseaccess: "数据库存取",
servicerelation: "服务关系",
serviceinstancerelation: "服务实例关系",
endpointrelation: "服务端点关系",
status: "状态",
endpointName: "端点名称",
search: "搜索",
clear: "清空",
more: "更多",
traceID: "追踪ID",
range: "范围",
timeRange: "时间范围",
duration: "持续时间",
startTime: "开始时间",
start: "起始点",
spans: "跨度",
spanInfo: "跨度信息",
spanType: "跨度类型",
time: "时间",
tags: "标记",
logs: "日志",
component: "组件",
table: "表格",
list: "列表",
tree: "树结构",
filterScope: "过滤范围",
searchKeyword: "关键字搜索",
quarterHourCutTip: "最近15分钟",
halfHourCutTip: "最近30分钟",
hourCutTip: "最近1小时",
dayCutTip: "最近1天",
weekCutTip: "最近1周",
monthCutTip: "最近1月",
serverZone: "服务器时区",
percentResponse: "百分比响应",
exportImage: "导出为图片",
queryData: "数据查询",
previousService: "上一个服务",
nextService: "下一个服务",
object: "粒度",
ShowInstanceDependency: "展示实例依赖",
InstanceDependencyTitle: "实例依赖",
profile: "性能剖析",
newTask: "新建任务",
monitorTime: "监控时间",
monitorDuration: "监控持续时间",
minThreshold: "起始监控时间",
dumpPeriod: "监控间隔",
createTask: "新建任务",
maxSamplingCount: "最大采样数",
analyze: "分析",
noData: "数据为空",
taskInfo: "任务详情",
task: "任务",
operationType: "操作类型",
operationTime: "操作时间",
taskView: "查看任务详情",
includeChildren: "包含子部分",
excludeChildren: "不包含子部分",
view: "查看",
timeTips: "时间区间不能超过60天",
standardAPM: "标准APM",
entityType: "实体类型",
maxItemNum: "最多条目数",
independentSelector: "独立选择器",
unknownMetrics: "未知指标",
labels: "标签",
aggregation: "数据计算",
unit: "单位",
labelsIndex: "标签下标",
parentService: "父级服务",
isParentService: "设置父服务",
noneParentService: "不设置父服务",
serviceGroup: "服务组",
endpointFilter: "端点过滤器",
editConfig: "编辑",
databaseView: "数据库视图",
browserView: "浏览器视图",
metricsView: "大屏视图",
sortOrder: "排序方式",
descendOrder: "递减顺序",
increaseOrder: "递增顺序",
defaultOrder: "默认顺序",
chartType: "图表类型",
currentDepth: "当前深度",
traceTagsTip:
"只有core/default/searchableTracesTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
tagsLink: "配置词汇页",
addTag: "请添加标签",
logCategory: "日志类别",
errorCatalog: "错误类目",
logDetail: "日志详情",
timeReload: "注意时间间隔必须大于0",
errorInfo: "错误信息",
stack: "堆栈",
serviceVersion: "服务版本",
errorPage: "错误页面",
category: "类别",
grade: "等级",
relatedTraceLogs: "相关的日志",
setConditions: "更多条件",
metricName: "指标名称",
keywordsOfContent: "内容关键词",
excludingKeywordsOfContent: "内容不包含的关键词",
return: "返回",
isError: "错误",
contentType: "内容类型",
content: "内容",
viewLogs: "查看日志",
logsTagsTip:
"只有core/default/searchableLogsTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
keywordsOfContentLogTips: "SkyWalking OAP服务器的当前存储不支持此操作",
setEvent: "设置事件",
instanceAttributes: "实例属性",
serviceEvents: "服务事件",
select: "选择",
eventID: "事件ID",
eventName: "事件名称",
endTime: "结束时间",
instanceEvents: "实例事件",
endpointEvents: "端点事件",
enableEvents: "启动事件",
disableEvents: "禁用事件",
eventSeries: "事件系列",
eventsType: "事件类型",
eventsMessage: "事件消息",
eventsParameters: "事件参数",
eventDetail: "事件详情",
value: "数值",
tableHeader: "表头名称",
tableValues: "表值",
show: "展示",
hide: "隐藏",
statistics: "统计",
message: "信息",
tooltipsContent: "提示内容",
alarmDetail: "警告详情",
scope: "范围",
destService: "终点服务",
destServiceInstance: "终点实例",
eventSource: "事件资源",
modalTitle: "查看",
selectRedirectPage: "查看 %s 服务的追踪或日志?",
logAnalysis: "日志分析语言",
logDataBody: "日志数据的内容",
addType: "请输入一个类型",
traceContext: "具有跟踪上下文的日志",
traceSegmentId: "跟踪段ID",
spanId: "跨度ID",
inputTraceSegmentId: "请输入跟踪段ID",
inputSpanId: "请输入跨度ID",
inputTraceId: "请输入跟踪ID",
dsl: "LAL的脚本输入",
logContentType: "日志内容的类型",
logRespContent: "日志内容",
analysis: "分析",
waitLoading: "加载中",
dslEmpty: "LAL的脚本输入不应该是空",
logContentEmpty: "日志数据的内容不应该是空。",
debug: "调试",
addTraceID: "请输入一个Trace ID",
addKeywordsOfContent: "请输入一个内容关键词",
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
noticeTag: "请输入一个标签之后回车",
conditionNotice: "请输入一个标签、内容关键词或者内容不包含的关键词之后回车",
cacheModalTitle: "清除缓存提醒",
yes: "是的",
no: "不",
cacheReminderContent: "SkyWalking检测到仪表板模板更新是否需要更新",
language: "语言",
};
export default msg;

32
src/main.ts Normal file
View File

@ -0,0 +1,32 @@
/**
* 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 { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { store } from "./store";
import components from "@/components";
import i18n from "./locales";
import "element-plus/dist/index.css";
import "./styles/lib.scss";
import "./styles/reset.scss";
const app = createApp(App);
app.use(components);
app.use(i18n);
app.use(store);
app.use(router).mount("#app");

45
src/router/alert.ts Normal file
View File

@ -0,0 +1,45 @@
/**
* 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 { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesAlert: Array<RouteRecordRaw> = [
{
path: "",
name: "Alerts",
meta: {
title: "alerts",
icon: "notification_important",
hasGroup: false,
exact: false,
},
component: Layout,
children: [
{
path: "/alerts",
name: "Alerts",
meta: {
title: "alerts",
icon: "notification_important",
hasGroup: false,
exact: false,
},
component: () => import("@/views/Log.vue"),
},
],
},
];

52
src/router/dashboard.ts Normal file
View File

@ -0,0 +1,52 @@
/**
* 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 { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesDashboard: Array<RouteRecordRaw> = [
{
path: "",
component: Layout,
name: "Dashboard",
meta: {
title: "dashboards",
icon: "dashboard_customize",
hasGroup: true,
exact: true,
},
children: [
{
path: "/dashboard/home",
component: () => import("@/views/Service.vue"),
name: "Home",
meta: {
title: "dashboardHome",
exact: false,
},
},
{
path: "/dashboard/list",
component: () => import("@/views/Log.vue"),
name: "List",
meta: {
title: "dashboardList",
exact: false,
},
},
],
},
];

53
src/router/database.ts Normal file
View 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.
*/
import { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesDatabase: Array<RouteRecordRaw> = [
{
path: "",
name: "Database",
meta: {
title: "database",
icon: "epic",
},
redirect: "/database",
component: Layout,
children: [
{
path: "/database",
name: "Database",
meta: {
title: "database",
headPath: "/database",
exact: true,
},
component: () => import("@/views/Service.vue"),
},
{
path: "/database/:id/:type",
name: "DatabasePanel",
meta: {
title: "databasePanel",
headPath: "/database",
exact: true,
},
component: () => import("@/views/service/Panel.vue"),
},
],
},
];

43
src/router/event.ts Normal file
View File

@ -0,0 +1,43 @@
/**
* 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 { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesEvent: Array<RouteRecordRaw> = [
{
path: "",
name: "Events",
meta: {
title: "events",
icon: "av_timer",
hasGroup: false,
exact: true,
},
component: Layout,
children: [
{
path: "/events",
name: "Events",
meta: {
title: "eventList",
exact: false,
},
component: () => import("@/views/Log.vue"),
},
],
},
];

View 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.
*/
import { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesGen: Array<RouteRecordRaw> = [
{
path: "",
name: "GeneralService",
redirect: "/generalService",
meta: {
title: "generalService",
icon: "chart",
hasGroup: false,
exact: true,
},
component: Layout,
children: [
{
path: "/generalService",
name: "Services",
meta: {
title: "services",
headPath: "/generalService/service",
exact: true,
},
component: () => import("@/views/Service.vue"),
},
{
path: "/generalService/service/:id/:type",
name: "GeneralServicePanel",
meta: {
title: "generalServicePanel",
headPath: "/generalService/service",
exact: true,
},
component: () => import("@/views/service/Panel.vue"),
},
],
},
];

46
src/router/index.ts Normal file
View File

@ -0,0 +1,46 @@
/**
* 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 { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
// import Layout from "@/layout/Index.vue";
import { routesGen } from "./generalService";
import { routesMesh } from "./serviceMesh";
import { routesDatabase } from "./database";
import { routesInfra } from "./infrastructure";
import { routesDashboard } from "./dashboard";
import { routesLog } from "./log";
import { routesEvent } from "./event";
import { routesAlert } from "./alert";
import { routesSetting } from "./setting";
const routes: Array<RouteRecordRaw> = [
...routesGen,
...routesMesh,
...routesDatabase,
...routesInfra,
...routesDashboard,
...routesLog,
...routesEvent,
...routesAlert,
...routesSetting,
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
export default router;

View 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.
*/
import { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesInfra: Array<RouteRecordRaw> = [
{
path: "",
name: "Infrastructure",
meta: {
title: "infrastructure",
icon: "scatter_plot",
exact: true,
hasGroup: true,
},
component: Layout,
children: [
{
path: "/infrastructure/vm",
name: "VirtualMachine",
meta: {
title: "virtualMachine",
},
component: () => import("@/views/Infrastructure.vue"),
},
{
path: "/infrastructure/k8s",
name: "Kubernetes",
meta: {
title: "kubernetes",
},
component: () => import("@/views/Infrastructure.vue"),
},
],
},
];

47
src/router/log.ts Normal file
View File

@ -0,0 +1,47 @@
/**
* 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 { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesLog: Array<RouteRecordRaw> = [
{
path: "",
name: "Logs",
meta: {
title: "logs",
icon: "assignment",
hasGroup: false,
exact: false,
},
component: Layout,
children: [
{
path: "/log",
name: "Logs",
meta: {
title: "log",
exact: false,
},
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "@/views/Log.vue"),
},
],
},
];

94
src/router/serviceMesh.ts Normal file
View File

@ -0,0 +1,94 @@
/**
* 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 { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesMesh: Array<RouteRecordRaw> = [
{
path: "",
name: "ServiceMesh",
redirect: "/mesh/services",
meta: {
title: "serviceMesh",
icon: "bar_chart",
hasGroup: true,
},
component: Layout,
children: [
{
path: "/mesh/services",
name: "MeshServices",
meta: {
title: "services",
headPath: "/mesh/services",
},
component: () => import("@/views/Service.vue"),
},
{
path: "/mesh/controlPanel",
name: "ControlPanel",
meta: {
title: "controlPanel",
headPath: "/mesh/controlPanel",
},
component: () => import("@/views/Service.vue"),
},
{
path: "/mesh/dataPanel",
name: "DataPanel",
meta: {
title: "dataPanel",
headPath: "/mesh/dataPanel",
},
component: () => import("@/views/Service.vue"),
},
{
path: "/mesh/services/:id/:type",
name: "MeshServicePanel",
meta: {
title: "meshServicePanel",
headPath: "/mesh/services",
exact: true,
notShow: true,
},
component: () => import("@/views/service/Panel.vue"),
},
{
path: "/mesh/controlPanel/:id/:type",
name: "MeshControlPanel",
meta: {
title: "controlPanel",
headPath: "/mesh/controlPanel",
exact: true,
notShow: true,
},
component: () => import("@/views/service/Panel.vue"),
},
{
path: "/mesh/dataPanel/:id/:type",
name: "MeshDataPanel",
meta: {
title: "dataPanel",
headPath: "/mesh/dataPanel",
exact: true,
notShow: true,
},
component: () => import("@/views/service/Panel.vue"),
},
],
},
];

45
src/router/setting.ts Normal file
View File

@ -0,0 +1,45 @@
/**
* 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 { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesSetting: Array<RouteRecordRaw> = [
{
path: "",
name: "Settings",
meta: {
title: "settings",
icon: "settings",
hasGroup: false,
exact: false,
},
component: Layout,
children: [
{
path: "/settings",
name: "Settings",
meta: {
title: "settings",
icon: "settings",
hasGroup: false,
exact: false,
},
component: () => import("@/views/Settings.vue"),
},
],
},
];

21
src/shims-vue.d.ts vendored Normal file
View File

@ -0,0 +1,21 @@
/**
* 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.
*/
declare module "*.vue" {
import { defineComponent } from "vue";
const Component: ReturnType<typeof defineComponent>;
export default Component;
}

21
src/store/index.ts Normal file
View File

@ -0,0 +1,21 @@
/**
* 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 { createPinia } from "pinia";
const store = createPinia();
export { store };

View File

@ -0,0 +1,108 @@
/**
* 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 { defineStore } from "pinia";
import { store } from "@/store";
import { Duration, DurationTime } from "@/types/app";
import getLocalTime from "@/utils/localtime";
import getDurationRow from "@/utils/dateTime";
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
interface AppState {
durationRow: any;
utc: string;
utcHour: number;
utcMin: number;
}
export const appStore = defineStore({
id: "app",
state: (): AppState => ({
durationRow: getDurationRow(),
utc: "",
utcHour: 0,
utcMin: 0,
}),
getters: {
duration(): Duration {
return {
start: getLocalTime(this.utc, this.durationRow.start),
end: getLocalTime(this.utc, this.durationRow.end),
step: this.durationRow.step,
};
},
durationTime(): DurationTime {
return {
start: dateFormatStep(this.duration.start, this.duration.step, true),
end: dateFormatStep(this.duration.end, this.duration.step, true),
step: this.duration.step,
};
},
intervalTime(): string[] {
let interval = 946080000000;
switch (this.duration.step) {
case "MINUTE":
interval = 60000;
break;
case "HOUR":
interval = 3600000;
break;
case "DAY":
interval = 86400000;
break;
case "MONTH":
interval =
(this.duration.end.getTime() - this.duration.start.getTime()) /
(this.duration.end.getFullYear() * 12 +
this.duration.end.getMonth() -
this.duration.start.getFullYear() * 12 -
this.duration.start.getMonth());
break;
}
const utcArr = this.utc.split(":");
const utcHour = isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]);
const utcMin = isNaN(Number(utcArr[1])) ? 0 : Number(utcArr[1]);
const utcSpace =
(utcHour + new Date().getTimezoneOffset() / 60) * 3600000 +
utcMin * 60000;
const startUnix: number = this.duration.start.getTime();
const endUnix: number = this.duration.end.getTime();
const timeIntervals: string[] = [];
for (let i = 0; i <= endUnix - startUnix; i += interval) {
const temp: string = dateFormatTime(
new Date(startUnix + i - utcSpace),
this.duration.step
);
timeIntervals.push(temp);
}
return timeIntervals;
},
},
actions: {
setDuration(data: Duration) {
this.durationRow = data;
},
setUTC(utcHour: number, utcMin: number) {
this.utcMin = utcMin;
this.utcHour = utcHour;
this.utc = `${utcHour}:${utcMin}`;
localStorage.setItem("utc", this.utc);
},
},
});
export function useAppStoreWithOut() {
return appStore(store);
}

99
src/styles/lib.scss Normal file
View File

@ -0,0 +1,99 @@
/**
* 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.
*/
.flex-v {
display: flex;
flex-direction: column;
}
.flex-h {
display: flex;
flex-direction: row;
}
.ell {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.cp {
cursor: pointer;
}
.cm {
cursor: move;
}
.auto {
margin-right: auto;
margin-left: auto;
}
.green {
color: #4caf50;
}
.red {
color: #e54c17;
}
.blue {
color: #448dfe;
}
.purple {
color: #6e40aa;
}
.yellow {
color: #fbb03b;
}
.grey {
color: #a7aebb;
}
.bg-green {
background-color: #4caf50;
}
.bg-red {
background-color: #e54c17;
}
.bg-blue {
background-color: #448dfe;
}
.bg-purple {
background-color: #6e40aa;
}
.bg-yellow {
background-color: #fbb03b;
}
.bg-grey {
background-color: #a7aebb;
}
.ml-5 {
margin-left: 5px;
}
.ml-10 {
margin-left: 10px;
}
.ml-15 {
margin-left: 15px;
}
.ml-20 {
margin-left: 20px;
}
.mr-5 {
margin-right: 5px;
}
.mr-10 {
margin-right: 10px;
}
.mr-15 {
margin-right: 15px;
}
.mr-20 {
margin-right: 20px;
}

177
src/styles/reset.scss Normal file
View File

@ -0,0 +1,177 @@
/**
* 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.
*/
body {
margin: 0;
line-height: 1.5;
font-size: 13px;
color: #3d444f;
font-family: 'Helvetica', 'Arial', 'Source Han Sans CN', 'Microsoft YaHei', 'sans-serif';
text-rendering: optimizeLegibility;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
html,
body {
height: 100%;
}
div,
header,
footer,
nav,
article,
section,
aside,
label,
input,
textarea,
select,
button,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
a,
img {
box-sizing: border-box;
}
input,
textarea,
select,
button {
font-size: 100%;
font-family: inherit;
}
h1 {
font-size: 26px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 21px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 1em;
}
ul,
ol {
margin: 0;
padding-left: 0;
list-style-type: none;
}
a {
text-decoration: none;
cursor: pointer;
color: inherit;
-webkit-tap-highlight-color: transparent;
-webkit-appearance: none;
}
hr {
border-width: 0;
border-bottom: 1px solid #e0e0e0;
}
blockquote {
margin-left: 0;
margin-right: 0;
padding-left: 1.2em;
border-left: 4px solid #cacaca;
}
code,
pre {
font-family: Consolas, Menlo, Courier, monospace;
}
/*webkit core*/
.scroll_hide::-webkit-scrollbar {
width: 0px;
height: 0px;
}
.scroll_hide::-webkit-scrollbar-button {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-webkit-scrollbar-track {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-webkit-scrollbar-track-piece {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-webkit-scrollbar-corner {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-webkit-scrollbar-resizer {
background-color: rgba(0, 0, 0, 0);
}
/*o core*/
.scroll_hide .-o-scrollbar {
-moz-appearance: none !important;
background: rgba(0, 255, 0, 0) !important;
}
.scroll_hide::-o-scrollbar-button {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-o-scrollbar-track {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-o-scrollbar-track-piece {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-o-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-o-scrollbar-corner {
background-color: rgba(0, 0, 0, 0);
}
.scroll_hide::-o-scrollbar-resizer {
background-color: rgba(0, 0, 0, 0);
}
/*IE10,IE11,IE12*/
.scroll_hide {
-ms-scroll-chaining: chained;
-ms-overflow-style: none;
-ms-content-zooming: zoom;
-ms-scroll-rails: none;
-ms-content-zoom-limit-min: 100%;
-ms-content-zoom-limit-max: 500%;
-ms-scroll-snap-points-x: snapList(100%, 200%, 300%, 400%, 500%);
-ms-overflow-style: none;
overflow: auto;
}
.scroll_bar_style::-webkit-scrollbar {
width: 9px;
height: 6px;
}
.scroll_bar_style::-webkit-scrollbar-track {
background-color: #3d444f;
}
.scroll_bar_style::-webkit-scrollbar-thumb {
border-radius: 5px;
background: rgba(196, 200, 225, .2);
}

114
src/type.d.ts vendored Normal file
View File

@ -0,0 +1,114 @@
/**
* 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 type {
ComponentRenderProxy,
VNode,
VNodeChild,
ComponentPublicInstance,
FunctionalComponent,
PropType as VuePropType,
} from "vue";
declare module "three";
declare module "three-orbit-controls";
declare module "element-plus";
declare global {
const __APP_INFO__: {
pkg: {
name: string;
version: string;
dependencies: Recordable<string>;
devDependencies: Recordable<string>;
};
lastBuildTime: string;
};
// vue
declare type PropType<T> = VuePropType<T>;
declare type VueNode = VNodeChild | JSX.Element;
export type Writable<T> = {
-readonly [P in keyof T]: T[P];
};
declare type Nullable<T> = T | null;
declare type NonNullable<T> = T extends null | undefined ? never : T;
declare type Recordable<T = any> = Record<string, T>;
declare type ReadonlyRecordable<T = any> = {
readonly [key: string]: T;
};
declare type Indexable<T = any> = {
[key: string]: T;
};
declare type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
declare type TimeoutHandle = ReturnType<typeof setTimeout>;
declare type IntervalHandle = ReturnType<typeof setInterval>;
declare interface ChangeEvent extends Event {
target: HTMLInputElement;
}
declare interface WheelEvent {
path?: EventTarget[];
}
interface ImportMetaEnv extends ViteEnv {
__: unknown;
}
declare interface ViteEnv {
VITE_PORT: number;
VITE_USE_MOCK: boolean;
VITE_USE_PWA: boolean;
VITE_PUBLIC_PATH: string;
VITE_PROXY: [string, string][];
VITE_GLOB_APP_TITLE: string;
VITE_GLOB_APP_SHORT_NAME: string;
VITE_USE_CDN: boolean;
VITE_DROP_CONSOLE: boolean;
VITE_BUILD_COMPRESS: "gzip" | "brotli" | "none";
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
VITE_LEGACY: boolean;
VITE_USE_IMAGEMIN: boolean;
VITE_GENERATE_UI: string;
}
declare function parseInt(s: string | number, radix?: number): number;
declare function parseFloat(string: string | number): number;
namespace JSX {
type Element = VNode;
type ElementClass = ComponentRenderProxy;
interface ElementAttributesProperty {
$props: any;
}
interface IntrinsicElements {
[elem: string]: any;
}
interface IntrinsicAttributes {
[elem: string]: any;
}
}
}
declare module "vue" {
export type JSXComponent<Props = any> =
| { new (): ComponentPublicInstance<Props> }
| FunctionalComponent<Props>;
}

30
src/types/app.d.ts vendored Normal file
View File

@ -0,0 +1,30 @@
/**
* 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.
*/
export interface Option {
key: string | number;
label: string;
}
export interface Duration {
start: Date;
end: Date;
step: string;
}
export interface DurationTime {
start: string;
end: string;
step: string;
}

31
src/types/infrastructure.d.ts vendored Normal file
View File

@ -0,0 +1,31 @@
/**
* 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.
*/
export interface HexagonCreateParams {
hexagonParam: number[];
count: number;
radius: number;
origin?: number[];
getShader?: any;
}
export interface HexagonGeo {
vertices: number[];
normals: number[];
insCenters: number[];
indices: number[];
origins: number[];
}

24
src/utils/cancelToken.ts Normal file
View File

@ -0,0 +1,24 @@
/**
* 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 axios from "axios";
const CancelToken = axios.CancelToken;
export const cancelToken = () =>
new CancelToken(function executor(c) {
const w = window as any;
w.axiosCancel.push(c);
});

101
src/utils/dateFormat.ts Normal file
View File

@ -0,0 +1,101 @@
/**
* 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.
*/
export default function dateFormatStep(
date: Date,
step: string,
monthDayDiff?: boolean
): string {
const year = date.getFullYear();
const monthTemp = date.getMonth() + 1;
let month = `${monthTemp}`;
if (monthTemp < 10) {
month = `0${monthTemp}`;
}
if (step === "MONTH" && monthDayDiff) {
return `${year}-${month}`;
}
const dayTemp = date.getDate();
let day = `${dayTemp}`;
if (dayTemp < 10) {
day = `0${dayTemp}`;
}
if (step === "DAY" || step === "MONTH") {
return `${year}-${month}-${day}`;
}
const hourTemp = date.getHours();
let hour = `${hourTemp}`;
if (hourTemp < 10) {
hour = `0${hourTemp}`;
}
if (step === "HOUR") {
return `${year}-${month}-${day} ${hour}`;
}
const minuteTemp = date.getMinutes();
let minute = `${minuteTemp}`;
if (minuteTemp < 10) {
minute = `0${minuteTemp}`;
}
if (step === "MINUTE") {
return `${year}-${month}-${day} ${hour}${minute}`;
}
const secondTemp = date.getSeconds();
let second = `${secondTemp}`;
if (secondTemp < 10) {
second = `0${secondTemp}`;
}
if (step === "SECOND") {
return `${year}-${month}-${day} ${hour}${minute}${second}`;
}
return "";
}
export const dateFormatTime = (date: Date, step: string): string => {
const year = date.getFullYear();
const monthTemp = date.getMonth() + 1;
let month = `${monthTemp}`;
if (monthTemp < 10) {
month = `0${monthTemp}`;
}
if (step === "MONTH") {
return `${year}-${month}`;
}
const dayTemp = date.getDate();
let day = `${dayTemp}`;
if (dayTemp < 10) {
day = `0${dayTemp}`;
}
if (step === "DAY") {
return `${month}-${day}`;
}
const hourTemp = date.getHours();
let hour = `${hourTemp}`;
if (hourTemp < 10) {
hour = `0${hourTemp}`;
}
if (step === "HOUR") {
return `${month}-${day} ${hour}`;
}
const minuteTemp = date.getMinutes();
let minute = `${minuteTemp}`;
if (minuteTemp < 10) {
minute = `0${minuteTemp}`;
}
if (step === "MINUTE") {
return `${hour}:${minute}\n${month}-${day}`;
}
return "";
};

44
src/utils/dateTime.ts Normal file
View File

@ -0,0 +1,44 @@
/**
* 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 { Duration } from "@/types/app";
import { TimeType } from "@/constants/data";
/**
* init or generate durationRow Obj and save localStorage.
*/
const getDurationRow = (): Duration => {
const durationRowString = localStorage.getItem("durationRow");
let durationRow: Duration;
if (durationRowString && durationRowString !== "") {
durationRow = JSON.parse(durationRowString);
durationRow = {
start: new Date(durationRow.start),
end: new Date(durationRow.end),
step: durationRow.step,
};
} else {
durationRow = {
start: new Date(new Date().getTime() - 900000),
end: new Date(),
step: TimeType.MINUTE_TIME,
};
localStorage.setItem("durationRow", JSON.stringify(durationRow, null, 0));
}
return durationRow;
};
export default getDurationRow;

56
src/utils/localtime.ts Normal file
View File

@ -0,0 +1,56 @@
/**
* 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 graph from "@/graph";
import { AxiosResponse } from "axios";
const getLocalTime = (utc: string, time: Date): Date => {
const utcArr = utc.split(":");
const utcHour = isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]);
const utcMin = isNaN(Number(utcArr[1])) ? 0 : Number(utcArr[1]);
const d = new Date(time);
const len = d.getTime();
const offset = d.getTimezoneOffset() * 60000;
const utcTime = len + offset;
return new Date(utcTime + 3600000 * utcHour + utcMin * 60000);
};
const setTimezoneOffset = () => {
window.localStorage.setItem(
"utc",
-(new Date().getTimezoneOffset() / 60) + ":0"
);
};
export const queryOAPTimeInfo = async (): Promise<void> => {
let utc = window.localStorage.getItem("utc");
if (!utc) {
const res: AxiosResponse = await graph.query("queryOAPTimeInfo").params({});
if (
!res.data ||
!res.data.data ||
!res.data.data.getTimeInfo ||
!res.data.data.getTimeInfo.timezone
) {
setTimezoneOffset();
return;
}
utc = res.data.data.getTimeInfo.timezone / 100 + ":0";
window.localStorage.setItem("utc", utc);
}
};
export default getLocalTime;

33
src/utils/timeFormat.ts Normal file
View 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 { Duration } from "@/types/app";
import { TimeType } from "@/constants/data";
const timeFormat = (time: Date[]): Duration => {
let step: TimeType;
const unix = Math.round(time[1].getTime()) - Math.round(time[0].getTime());
if (unix <= 60 * 60 * 1000) {
step = TimeType.MINUTE_TIME;
} else if (unix <= 24 * 60 * 60 * 1000) {
step = TimeType.HOUR_TIME;
} else {
step = TimeType.DAY_TIME;
}
return { start: time[0], end: time[1], step };
};
export default timeFormat;

163
src/utils/vec2.ts Normal file
View File

@ -0,0 +1,163 @@
/**
* 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.
*/
class Vec2 extends Float32Array {
constructor(v?: unknown, y?: unknown) {
super(2);
if (
v instanceof Vec2 ||
v instanceof Float32Array ||
(v instanceof Array && v.length == 2)
) {
this[0] = v[0];
this[1] = v[1];
} else if (typeof v === "number" && typeof y === "number") {
this[0] = v;
this[1] = y;
} else if (typeof v === "number") {
this[0] = v;
this[1] = v;
}
}
xy(x: number, y: number): Vec2 {
if (y != undefined) {
this[0] = x;
this[1] = y;
} else this[0] = this[1] = x;
return this;
}
get x(): number {
return this[0];
}
set x(v: number) {
this[0] = v;
}
get y(): number {
return this[1];
}
set y(v: number) {
this[1] = v;
}
len(): number {
return Math.sqrt(this[0] * this[0] + this[1] * this[1]);
}
fromAdd(a: number[], b: number[]): Vec2 {
this[0] = a[0] + b[0];
this[1] = a[1] + b[1];
return this;
}
fromSub(a: number[] | Vec2, b: number[] | Vec2): Vec2 {
this[0] = a[0] - b[0];
this[1] = a[1] - b[1];
return this;
}
fromScale(a: number[] | Vec2, s: number): Vec2 {
this[0] = a[0] * s;
this[1] = a[1] * s;
return this;
}
fromLerp(a: number[] | Vec2, b: number[] | Vec2, t: number): Vec2 {
const tt = 1 - t;
this[0] = a[0] * tt + b[0] * t;
this[1] = a[1] * tt + b[1] * t;
return this;
}
/** Used to get data from a flat buffer of vectors, useful when building geometery */
fromBuf(ary: number[], idx: number): Vec2 {
this[0] = ary[idx];
this[1] = ary[idx + 1];
return this;
}
/** Pust vector components onto an array, useful when building geometery */
pushTo(ary: number[]): Vec2 {
ary.push(this[0], this[1]);
return this;
}
add(v: number[]): Vec2 {
this[0] += v[0];
this[1] += v[1];
return this;
}
addRaw(x: number, y: number): Vec2 {
this[0] += x;
this[1] += y;
return this;
}
sub(v: number[]): Vec2 {
this[0] -= v[0];
this[1] -= v[1];
return this;
}
scale(v: number): Vec2 {
this[0] *= v;
this[1] *= v;
return this;
}
norm(out?: number[] | Vec2): number[] | Vec2 | undefined {
const mag = Math.sqrt(this[0] * this[0] + this[1] * this[1]);
if (mag == 0) return this;
out = out || this;
out[0] = this[0] / mag;
out[1] = this[1] / mag;
return out;
}
perpCCW(): Vec2 {
const x = this[0];
this[0] = -this[1];
this[1] = x;
return this;
}
static add(a: number[], b: number[]): Vec2 {
return new Vec2().fromAdd(a, b);
}
static sub(a: number[], b: number[]): Vec2 {
return new Vec2().fromSub(a, b);
}
static scale(v: number[], s: number): Vec2 {
return new Vec2().fromScale(v, s);
}
static lerp(v0: number[], v1: number[], t: number): Vec2 {
return new Vec2().fromLerp(v0, v1, t);
}
static len(v0: Vec2, v1: Vec2): number {
return Math.sqrt((v0[0] - v1[0]) ** 2 + (v0[1] - v1[1]) ** 2);
}
/** Create an Iterator Object that allows an easy way to loop a Float32Buffer
* @example
* let buf = new Float32Array( 2 * 10 );
* for( let v of Vec3.bufIter( buf ) ){console.log( v )};
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static bufIter(buf: number[]) {
let i = 0;
const result = { value: new Vec2(), done: false },
len = buf.length,
next = () => {
if (i >= len) result.done = true;
else {
result.value.fromBuf(buf, i);
i += 2;
}
return result;
};
return {
[Symbol.iterator]() {
return { next };
},
};
}
}
export default Vec2;

177
src/utils/vec3.ts Normal file
View File

@ -0,0 +1,177 @@
/**
* 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.
*/
class Vec3 extends Float32Array {
constructor(v?: unknown, y?: unknown, z?: unknown) {
super(3);
if (
v instanceof Vec3 ||
v instanceof Float32Array ||
(v instanceof Array && v.length == 3)
) {
this[0] = v[0];
this[1] = v[1];
this[2] = v[2];
} else if (
typeof v === "number" &&
typeof y === "number" &&
typeof z === "number"
) {
this[0] = v;
this[1] = y;
this[2] = z;
} else if (typeof v === "number") {
this[0] = v;
this[1] = v;
this[2] = v;
}
}
xyz(x: number, y: number, z: number): Vec3 {
if (y != undefined && z != undefined) {
this[0] = x;
this[1] = y;
this[2] = z;
} else this[0] = this[1] = this[2] = x;
return this;
}
get x(): number {
return this[0];
}
set x(v: number) {
this[0] = v;
}
get y(): number {
return this[1];
}
set y(v: number) {
this[1] = v;
}
get z(): number {
return this[2];
}
set z(v: number) {
this[2] = v;
}
fromVec2(v: Vec3, useZ = false): Vec3 {
this[0] = v[0];
if (useZ) {
this[1] = 0;
this[2] = v[1];
} else {
this[1] = v[1];
this[2] = 0;
}
return this;
}
norm(): Vec3 {
let mag = Math.sqrt(this[0] ** 2 + this[1] ** 2 + this[2] ** 2);
if (mag != 0) {
mag = 1 / mag;
this[0] *= mag;
this[1] *= mag;
this[2] *= mag;
}
return this;
}
/** Pust vector components onto an array, useful when building geometery */
pushTo(ary: number[]): Vec3 {
ary.push(this[0], this[1], this[2]);
return this;
}
// INTERPOLATION SETTERS
fromLerp(a: Vec3, b: Vec3, t: number): Vec3 {
const ti = 1 - t; // Linear Interpolation : (1 - t) * v0 + t * v1;
this[0] = a[0] * ti + b[0] * t;
this[1] = a[1] * ti + b[1] * t;
this[2] = a[2] * ti + b[2] * t;
return this;
}
/** Add vector to current vector */
add(a: Vec3 | number[]): Vec3 {
this[0] += a[0];
this[1] += a[1];
this[2] += a[2];
return this;
}
sub(v: Vec3 | number[]): Vec3 {
this[0] -= v[0];
this[1] -= v[1];
this[2] -= v[2];
return this;
}
scale(v: number): Vec3 {
this[0] *= v;
this[1] *= v;
this[2] *= v;
return this;
}
/** Scale a vector */
fromScale(a: Vec3, s: number): Vec3 {
this[0] = a[0] * s;
this[1] = a[1] * s;
this[2] = a[2] * s;
return this;
}
/** Add two vectors together */
fromAdd(a: Vec3, b: number[]): Vec3 {
this[0] = a[0] + b[0];
this[1] = a[1] + b[1];
this[2] = a[2] + b[2];
return this;
}
/** Subtract two vectors together */
fromSub(a: number[], b: number[]): Vec3 {
this[0] = a[0] - b[0];
this[1] = a[1] - b[1];
this[2] = a[2] - b[2];
return this;
}
/** Copy in vector data */
copy(v: any[] | Float32Array): Vec3 {
this[0] = v[0];
this[1] = v[1];
this[2] = v[2];
return this;
}
static add(a: Vec3, b: number[]): Vec3 {
return new Vec3().fromAdd(a, b);
}
static sub(a: number[], b: number[]): Vec3 {
return new Vec3().fromSub(a, b);
}
static scale(a: Vec3, s: number): Vec3 {
return new Vec3().fromScale(a, s);
}
static norm(x: unknown, y: unknown, z: unknown): Vec3 {
const rtn = new Vec3();
if (
x instanceof Vec3 ||
x instanceof Float32Array ||
(x instanceof Array && x.length == 3)
) {
rtn.copy(x);
} else if (
typeof x === "number" &&
typeof y === "number" &&
typeof z === "number"
) {
rtn.xyz(x, y, z);
}
return rtn.norm();
}
}
export default Vec3;

View 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. -->
<template>
<div class="Infrastructure">
<InfrastructureMap />
</div>
</template>
<script lang="ts" setup>
import InfrastructureMap from "./infrastructure/InfrastructureMap.vue";
</script>
<style scoped>
.Infrastructure {
width: 100%;
height: 100%;
}
</style>

23
src/views/Log.vue Normal file
View File

@ -0,0 +1,23 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="about">{{ props.msg }}</div>
</template>
<script lang="ts" setup>
import { defineProps } from "vue";
const props = defineProps({
msg: String,
});
</script>

131
src/views/Service.vue Normal file
View File

@ -0,0 +1,131 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="service-table">
<el-table :data="tableData" :span-method="objectSpanMethod" border>
<el-table-column
v-for="(h, index) in tableHeader"
:label="t(h)"
:key="h + index"
>
<template #default="scope">
<router-link
:to="`${state.path}/${scope.row.serviceName}/metrics`"
v-if="h === tableHeader[1] && index !== 0"
>
<span class="service-name cp">{{ scope.row[h] }}</span>
</router-link>
<span v-else>{{ scope.row[h] }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch } from "vue";
import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router";
import { ElTable, ElTableColumn } from "element-plus";
const route = useRoute();
const { t } = useI18n();
const tableHeader = [
"groupName",
"serviceName",
"types",
"technologies",
"endpoints",
"health",
];
const tableData = [
{
endpoints: 2,
groupName: "group 1",
serviceName: "discount",
types: "HTTP",
health: true,
technologies: "Spring Boot",
},
{
endpoints: 3,
groupName: "group 1",
serviceName: "frontend",
types: "HTTP",
health: true,
technologies: "Node.js",
},
{
endpoints: 3,
groupName: "group 2",
serviceName: "web",
types: "",
health: true,
technologies: "Nginx",
},
{
endpoints: 3,
groupName: "group 2",
serviceName: "shipping",
types: "HTTP",
health: true,
technologies: "JVM",
},
{
endpoints: 3,
groupName: "group 3",
serviceName: "payment",
types: "HTTP MESSAGING",
health: true,
technologies: "RabbitMQ Python",
},
];
const state = reactive({
path: route.meta.headPath,
});
const objectSpanMethod = (item: { columnIndex: number; rowIndex: number }) => {
if (item.columnIndex === 0) {
if (item.rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
};
watch(
() => route.meta.headPath,
(path: unknown) => {
if (!path) {
return;
}
state.path = path;
}
);
</script>
<style lang="scss" scoped>
.service-name {
color: #448edf;
cursor: pointer;
}
.service-table {
padding: 15px;
}
</style>

201
src/views/Settings.vue Normal file
View File

@ -0,0 +1,201 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="settings">
<!-- <div class="flex-h item">
<span class="label">{{ t("version") }}</span>
<span>{{ rocketbotGlobal.version }}</span>
</div> -->
<div class="flex-h item">
<span class="label">{{ t("language") }}</span>
<el-switch
v-model="lang"
:change="setLang"
active-text="En"
inactive-text="Zh"
style="height: 25px"
/>
</div>
<div class="flex-h item">
<span class="label">{{ t("serverZone") }}</span>
<div>
<span>UTC</span>
<span class="ml-5 mr-5">{{ utcHour >= 0 ? "+" : "" }}</span>
<input
type="number"
v-model="utcHour"
min="-12"
max="14"
class="utc-input"
@change="setUTCHour"
/>
<span class="ml-5 mr-5">:</span>
<span class="utc-min">{{ utcMin > 9 || utcMin === 0 ? null : 0 }}</span>
<input
type="number"
v-model="utcMin"
min="0"
max="59"
class="utc-input"
@change="setUTCMin"
/>
</div>
</div>
<div class="flex-h item">
<span class="label">{{ t("auto") }}</span>
<el-switch :change="handleAuto" style="height: 25px" />
<div class="auto-time ml-5">
<span class="auto-select">
<input
type="number"
v-model="autoTime"
@change="changeAutoTime"
min="1"
/>
</span>
{{ t("second") }}
<i class="ml-10">{{ t("timeReload") }}</i>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from "vue";
import { useI18n } from "vue-i18n";
import { useAppStoreWithOut } from "@/store/modules/app";
import timeFormat from "@/utils/timeFormat";
import { ElSwitch } from "element-plus";
const { t, locale } = useI18n();
const state = reactive<{ timer: any }>({
timer: null,
});
const lang = ref<boolean>(locale.value === "zh" ? false : true);
const autoTime = ref<number>(6);
const auto = ref<boolean>(false);
const appStore = useAppStoreWithOut();
const utcArr = appStore.utc.split(":");
const utcHour = ref<number>(isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]));
const utcMin = ref<number>(isNaN(Number(utcArr[1])) ? 0 : Number(utcArr[1]));
const handleReload = () => {
const gap =
appStore.duration.end.getTime() - appStore.duration.start.getTime();
const time: Date[] = [new Date(new Date().getTime() - gap), new Date()];
appStore.setDuration(timeFormat(time));
};
const handleAuto = (status: boolean) => {
if (autoTime.value < 1) {
return;
}
auto.value = status;
if (auto.value) {
handleReload();
state.timer = setInterval(handleReload, autoTime.value * 1000);
} else {
clearInterval(state.timer);
}
};
const changeAutoTime = () => {
if (autoTime.value < 1) {
return;
}
clearInterval(state.timer);
if (auto.value) {
handleReload();
state.timer = setInterval(handleReload, autoTime.value * 1000);
}
};
const setLang = (): void => {
if (lang.value) {
locale.value = "en";
window.localStorage.setItem("lang", "en");
} else {
locale.value = "zh";
window.localStorage.setItem("lang", "zh");
}
};
const setUTCHour = () => {
if (utcHour.value < -12) {
utcHour.value = -12;
}
if (utcHour.value > 14) {
utcHour.value = 14;
}
if (isNaN(utcHour.value)) {
utcHour.value = 0;
}
appStore.setUTC(utcHour.value, utcMin.value);
};
const setUTCMin = () => {
if (utcMin.value < 0) {
utcMin.value = 0;
}
if (utcMin.value > 59) {
utcMin.value = 59;
}
if (isNaN(utcMin.value)) {
utcMin.value = 0;
}
appStore.setUTC(utcHour.value, utcMin.value);
};
</script>
<style lang="scss" scoped>
.utc-input {
color: inherit;
background: 0;
border: 0;
outline: none;
padding-bottom: 0;
}
.utc-min {
display: inline-block;
padding-top: 2px;
}
.auto-select {
border-radius: 3px;
background-color: #fff;
padding: 1px;
border-radius: 3px;
input {
width: 38px;
border-style: unset;
outline: 0;
}
}
.settings {
color: #222;
font-family: inherit;
font-size: 14px;
padding: 20px;
.item {
margin-top: 10px;
}
input {
outline: 0;
width: 50px;
border-radius: 3px;
border: 1px solid #ccc;
text-align: center;
height: 25px;
}
.label {
width: 100px;
display: inline-block;
font-weight: 500;
}
}
</style>

View File

@ -0,0 +1,339 @@
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="infrastructure-box">
<div ref="mapRef" class="map"></div>
<div class="info-box" v-show="showInfo">
{{ nodeTypes[type] }} Information
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import fac from "three-orbit-controls";
import { Line2 } from "three/examples/jsm/lines/Line2";
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial";
import { HexagonCreateParams } from "@/types/infrastructure";
import HexagonPillar from "./geometry/hexagon-pillar";
import { Layout } from "./geometry/hexagon-layout";
import { NodeTypes } from "./data";
const animateCallbacks: Array<() => void> = [];
const showInfo = ref<boolean>(false);
const objSelected = ref<any>(null);
const meshColors = ref([0xa1cffb, 0x333333, 0x333840, 0x999999]); //[0xa489b2, 0xf2bfd0, 0xf0eaea, 0xef6775, 0xfbc580];
const nodeTypes = ref(NodeTypes);
const type = ref<number>(0);
const width = ref<number>(1920);
const height = ref<number>(900);
const mapRef = ref<HTMLDivElement | null>(null);
let lineObj: any;
let scene: any;
let camera: any;
let raycaster: any;
let pointer: any;
onMounted(() => {
if (mapRef.value) {
init(mapRef.value);
}
window.addEventListener("click", onMouseClick, false);
animate();
});
function init(dom: HTMLDivElement): void {
width.value = dom.offsetWidth;
height.value = dom.offsetHeight + 74;
camera = new THREE.PerspectiveCamera(
45,
width.value / height.value,
1,
10000
);
camera.position.set(0, 30, 140);
scene = new THREE.Scene();
let light = new THREE.DirectionalLight(0xffffff, 0.8);
light.position.set(4, 10, 4);
scene.add(light);
scene.add(new THREE.AmbientLight(0x404040));
scene.background = new THREE.Color(0x333840);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.setSize(width.value, height.value);
dom.appendChild(renderer.domElement);
const window = Window as any;
const OrbitControls = fac(THREE);
window.controls = new OrbitControls(camera, renderer.domElement);
window.controls.enableZoom = true;
window.controls.enablePan = true;
const helper = new THREE.GridHelper(10000, 40, 0x04002c, 0x04002c);
helper.position.y = -1000;
// this.scene.add(helper);
const axis = new THREE.AxesHelper(15000);
// this.scene.add(axis);
// add mesh
createInfrastructure();
raycaster = new THREE.Raycaster();
pointer = new THREE.Vector2();
animateCallbacks.push(() => {
renderer.render(scene, camera);
});
}
function createInfrastructure() {
//layer mesh
const l = {
hexagonParam: [27, 0.04, 5, 0.04, 0],
count: 1,
radius: 28, // layout hexagons radius
};
const [originVectors] = createHexagonLine(l, [0, 0, 0], 0);
// group mesh
const g: HexagonCreateParams = {
hexagonParam: [8, 0.04, 5, 0.04, 0.01],
count: 1,
radius: 8.5,
};
const [gVecs] = createPillarMesh(g, originVectors, 1);
// service mesh
const s: HexagonCreateParams = {
hexagonParam: [2, 0.04, 5, 0.04, 0.2],
count: 1,
radius: 2.2,
};
const [sVecs] = createPillarMesh(s, gVecs, 2);
// instance mesh
const i: HexagonCreateParams = {
hexagonParam: [0.2, 0.04, 5, 0.04, 0.3],
count: 2,
radius: 0.3,
};
createPillarMesh(i, sVecs, 3);
}
function createHexagonLine(
p: HexagonCreateParams,
originVectors: number[],
type: number
) {
lineObj = new THREE.Object3D();
const centers: number[] = [];
const geo = HexagonPillar.getVertices(false, ...p.hexagonParam);
for (let i = 0; i < originVectors.length / 3; i++) {
const c = [originVectors[3 * i], originVectors[3 * i + 2]];
const [origins] = hexGrid(p.count, p.radius, c);
centers.push(...origins);
}
for (let c = 0; c < centers.length / 3; c++) {
const vertices = [];
for (let v = 0; v < geo.vertices.length; v++) {
vertices.push(
centers[3 * c] + geo.vertices[v].x,
centers[3 * c + 1] + geo.vertices[v].y,
centers[3 * c + 2] + geo.vertices[v].z
);
}
const geometry = new LineGeometry().setPositions(vertices);
geometry.setAttribute(
"id",
new THREE.BufferAttribute(new Int8Array([type]), 1)
);
const material = new LineMaterial({
color: meshColors.value[type],
linewidth: 4,
// opacity: 0.2,
dashed: false,
});
material.resolution.set(width.value, height.value);
const line = new Line2(geometry, material);
line.computeLineDistances();
lineObj.add(line);
}
scene.add(lineObj);
return [centers];
}
function createPillarMesh(
p: HexagonCreateParams,
originVectors: number[],
type: number
) {
const centers: number[] = [];
const geo = HexagonPillar.get(false, ...p.hexagonParam);
for (let i = 0; i < originVectors.length / 3; i++) {
const c = [originVectors[3 * i], originVectors[3 * i + 2]];
const [origins] = hexGrid(p.count, p.radius, c);
centers.push(...origins);
}
const hMat = new THREE.MeshStandardMaterial({
side: THREE.DoubleSide,
transparent: true,
});
const geometry = new THREE.BufferGeometry();
geometry.setIndex(geo.indices);
geometry.setAttribute(
"position",
new THREE.BufferAttribute(new Float32Array(geo.vertices), 3)
);
geometry.setAttribute(
"normal",
new THREE.BufferAttribute(new Float32Array(geo.normals), 3)
);
geometry.setAttribute(
"type",
new THREE.BufferAttribute(new Int8Array([type]), 1)
);
const mesh = new THREE.InstancedMesh(geometry, hMat, centers.length / 3);
for (let c = 0; c < centers.length / 3; c++) {
const matrix = new THREE.Matrix4();
const color = new THREE.Color();
color.setHex(meshColors.value[type]);
for (let j = 0; j < geo.vertices.length / 3; j++) {
matrix.setPosition(
geo.vertices[3 * j] + centers[3 * c],
geo.vertices[3 * j + 1] + centers[3 * c + 1],
geo.vertices[3 * j + 2] + centers[3 * c + 2]
);
}
mesh.setMatrixAt(c, matrix);
mesh.setColorAt(c, color);
}
mesh.instanceMatrix.needsUpdate = true;
scene.add(mesh);
return [centers];
}
function hexGrid(n = 1, radius = 1, origin = [0, 0]) {
let x, y, yn, p;
const gLayout = new Layout(radius, origin);
// const coord = [];
const pos = [];
// x = -1; n = 1.5
for (x = -n; x <= n; x++) {
y = Math.max(-n, -x - n); // 0
yn = Math.min(n, -x + n); // 1
// y = 0 yn = 1
for (y; y <= yn; y++) {
p = gLayout.axialToPixel(x, y);
pos.push(p[0], 0, p[1]);
// coord.push(x, y);
}
}
return [pos];
}
function onMouseClick(event: MouseEvent) {
pointer.x = ((event.clientX - 210) / width.value) * 2 - 1;
pointer.y = -((event.clientY - 0) / height.value) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
let meshes = scene.children.filter((d: any) => d instanceof THREE.Mesh);
meshes = [...meshes, ...lineObj.children];
const intersects = raycaster.intersectObjects(meshes, true);
const intersect = intersects[0];
if (objSelected.value) {
for (const m of meshes) {
if (m instanceof Line2) {
m.material.color.setHex(meshColors.value[0]);
m.material.needsUpdate = true;
} else {
const mType = m.geometry.getAttribute("type").array[0];
m.setColorAt(
objSelected.value.instanceId,
new THREE.Color(meshColors.value[mType])
);
m.instanceColor.needsUpdate = true;
}
}
}
if (intersect) {
showInfo.value = true;
if (intersect.object instanceof Line2) {
intersect.object.material.color.setHex(0x73b3b9);
objSelected.value = intersect;
type.value = 0;
intersect.object.material.needsUpdate = true;
} else {
intersect.object.setColorAt(
intersect.instanceId,
new THREE.Color(0x73b3b9)
);
intersect.object.instanceColor.needsUpdate = true;
objSelected.value = intersect;
type.value =
objSelected.value.object.geometry.getAttribute("type").array[0];
}
} else {
if (objSelected.value) {
for (const m of meshes) {
if (m instanceof Line2) {
m.material.color.setHex(meshColors.value[0]);
m.material.needsUpdate = true;
} else {
const mType = m.geometry.getAttribute("type").array[0];
m.setColorAt(
objSelected.value.instanceId,
new THREE.Color(meshColors.value[mType])
);
m.instanceColor.needsUpdate = true;
}
}
}
objSelected.value = null;
type.value = NaN;
showInfo.value = false;
}
}
function animate(): void {
animateCallbacks.forEach((fn) => fn());
requestAnimationFrame(animate);
}
</script>
<style scoped>
.info-box {
position: absolute;
top: 10px;
left: 10px;
background: #fff;
color: #000;
height: 700px;
width: 300px;
border-radius: 3px;
padding: 10px;
}
.infrastructure-box {
position: relative;
width: 100%;
height: 100%;
}
.map {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,23 @@
/**
* 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.
*/
export const NodeTypes = [
"Layer",
"Group",
"Service",
"Service Instance",
"endpoint",
];

Some files were not shown because too many files have changed in this diff Show More