重构console-ui
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -14,3 +14,8 @@
|
||||
- 🚧工作中(勿动)
|
||||
......
|
||||
```
|
||||
## [V 1.0.0] - 2023.4.20
|
||||
### console-ui
|
||||
- 🧹重构: 重构console-ui,使用vue3.0,vite,typescript进行重构
|
||||
|
||||
|
||||
|
||||
4
console-ui/.browserslistrc
Normal file
@@ -0,0 +1,4 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
||||
5
console-ui/.editorconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
[*.{js,jsx,ts,tsx,vue}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
10
console-ui/.env.dev
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
# Firebase 🔥
|
||||
VITE_FIREBASE_API_KEY=
|
||||
VITE_FIREBASE_AUTH_DOMAIN=
|
||||
VITE_FIREBASE_PROJECT_ID=
|
||||
VITE_FIREBASE_STORAGE_BUCKET=
|
||||
VITE_FIREBASE_MESSAGING_SENDER_ID=
|
||||
VITE_FIREBASE_APP_ID=
|
||||
VITE_FIREBASE_MEASUREMENT_ID=
|
||||
1
console-ui/.env.pro
Normal file
@@ -0,0 +1 @@
|
||||
VITE_API_BASE_URL=https://api.example.com
|
||||
3
console-ui/.env.template
Normal file
@@ -0,0 +1,3 @@
|
||||
VITE_OPENAI_API_KEY = XXXXXXXXXXXX
|
||||
VITE_UNSPLASH_ACCESS_KEY = XXXXXXXXXXXX
|
||||
VITE_GITHUB_CLIENT_ID = XXXXXXXXXXXX
|
||||
2
console-ui/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
6
console-ui/.gitignore
vendored
@@ -1,9 +1,11 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
/.vite_cache
|
||||
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
@@ -21,3 +23,7 @@ pnpm-debug.log*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
.env
|
||||
|
||||
21
console-ui/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 jk.yang
|
||||
|
||||
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.
|
||||
120
console-ui/README.jp.md
Normal file
@@ -0,0 +1,120 @@
|
||||
<br><br>
|
||||
|
||||
<p align='center' >
|
||||
<img src='/src/assets/logo_light.svg' alt='Vuetify3' width='300'/>
|
||||
</p>
|
||||
<br><br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://vuejs.org/">
|
||||
<img src="https://img.shields.io/badge/vue-v3.2.47-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://vuetifyjs.com/">
|
||||
<img src="https://img.shields.io/badge/vuetify-v3.1.13-blue.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://vitejs.dev/">
|
||||
<img src="https://img.shields.io/badge/vite-v4.2.1-blueviolet.svg" alt="element-ui">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/yangjiakai/lux-admin-vuetify3/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h4 align='center'>
|
||||
<a href="https://lux.vuetify3.com/">ライブ・デモ</a>
|
||||
</h4>
|
||||
|
||||
<br>
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/yangjiakai/jk-vuetify3-lux-admin/blob/main/README.md">English</a> | <a href="https://github.com/yangjiakai/jk-vuetify3-lux-admin/blob/main/README.zh-CN.md">简体中文</a>| <b >日本語</b>
|
||||
</p>
|
||||
|
||||
## 序文
|
||||
|
||||
> 目標は、最も優れた Vuetify 3 の Admin オープンソーステンプレートを作成することです。
|
||||
|
||||
Vuetify の洗練されたテーマを基盤に、明確で効率的なプロジェクト構造を構築し、最新の技術フレームワークを統合しています。このプロジェクトは、さまざまな一般的な技術要件や機能に対応することを目指し、AI アシスタントを組み込むことで、よりインテリジェントな体験を提供します。さらに、すべてのページが複数のデバイスで適応的に表示されるようにし、シームレスなクロスプラットフォーム互換性を実現しています。
|
||||
|
||||
## 特徴
|
||||
|
||||
- 📖 [Vue 3.2](https://github.com/vuejs/core)
|
||||
- 📖 [Vite 4.x](https://github.com/vitejs/vite)
|
||||
- 📖 UI Framework [Vuetify 3](https://next.vuetifyjs.com/en/)
|
||||
- 📖 TypeScript
|
||||
- 📦 Component Auto Importing
|
||||
- 🍍 [Pinia](https://pinia.vuejs.org/)
|
||||
- 📔 `<script setup>`
|
||||
- 📚 Use icons from any icon sets in [Iconify](https://icon-sets.iconify.design/)
|
||||
- ☁️ Deploy on Netlify, zero-config
|
||||
- 🔑 Firebase auth
|
||||
- 📈 Echarts, ApexChart
|
||||
- 🧭 Openai, Chatgpt
|
||||
- 🌍 vue-i18n
|
||||
- 📚 virtual-scroller , vuedraggable , perfect-scrollbar
|
||||
- 📝 Rich Text Editor
|
||||
- 📇 Responsive multi-platform adaptive
|
||||
|
||||
## Contact Me
|
||||
|
||||
- Email <a href="mailto:yjkbako@gmail.com">yjkbako@gmail.com</a>
|
||||
- Twitter https://twitter.com/baibaixiang
|
||||
- Wechat <img src='/src/assets/wechat-qrcode.png' alt='DashBoard' width='300' />
|
||||
|
||||
## プレビュー
|
||||
|
||||
<img src='/src/assets/previews/DashBoard.png' alt='DashBoard' />
|
||||
<img src='/src/assets/previews/TaskBoard.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/DataTable.png' alt='DataTable' />
|
||||
<img src='/src/assets/previews/Todo.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/ChatGPT.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Card.png' alt='Card' />
|
||||
<img src='/src/assets/previews/Color.png' alt='Color' />
|
||||
<img src='/src/assets/previews/Gradient.png' alt='Gradient' />
|
||||
<img src='/src/assets/previews/Login.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Unsplash.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Unsplash2.png' alt='ChatGPT' />
|
||||
|
||||
<br>
|
||||
|
||||
## プリパック
|
||||
|
||||
### UI Frameworks
|
||||
|
||||
- [Vuetify3](https://next.vuetifyjs.com/en/) - Vuetify は、美しく手作りされた Vue コンポーネントで構成された、デザインスキル不要の UI フレームワークです。
|
||||
|
||||
### Icons
|
||||
|
||||
- [Iconify](https://iconify.design) - 任意のアイコンセットを使用 [🔍Icônes](https://icones.netlify.app/)
|
||||
- [Pure CSS Icons via UnoCSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||
|
||||
### プラグイン
|
||||
|
||||
- [Vue Router4](https://router.vuejs.org/)
|
||||
- [VueUse](https://github.com/antfu/vueuse) - 便利なコンポジション API 集
|
||||
- [VuedDaggable](https://github.com/SortableJS/Vue.Draggable) - 配列モデルと同期したドラッグ&ドロップによる配置操作が可能
|
||||
- [Vue-Masonry-Wall](https://github.com/DerYeger/yeger/tree/main/packages/vue-masonry-wall) -Vue 3 のレスポンシブな Masonry レイアウト SSR をサポートしています
|
||||
- [Vue-Virtual-Scroller](https://github.com/Akryum/vue-virtual-scroller) - 超高速の任意のデータ量のスクロール
|
||||
|
||||
## 今すぐ試す!
|
||||
|
||||
```
|
||||
git clone https://github.com/yangjiakai/lux-admin-vuetify3.git
|
||||
|
||||
cd lux-admin-vuetify3
|
||||
|
||||
npm install
|
||||
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Set ApiKey
|
||||
|
||||
Find the `.env.template` file in the root directory, remove the `.template` suffix, and replace` VITE_OPENAI_API_KEY`, `VITE_UNSPLASH_ACCESS_KEY`, and `VITE_GITHUB_CLIENT_ID` with your own keys.
|
||||
|
||||
> openai apikey: https://platform.openai.com/account/api-keys
|
||||
|
||||
> unsplash apikey: https://unsplash.com/oauth/applications
|
||||
|
||||
> github apikey: https://github.com/settings/tokens
|
||||
@@ -1,19 +1,119 @@
|
||||
# console-ui
|
||||
<br><br>
|
||||
|
||||
<p align='center' >
|
||||
<img src='/src/assets/logo_light.svg' alt='Vuetify3' width='300'/>
|
||||
</p>
|
||||
<br><br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://vuejs.org/">
|
||||
<img src="https://img.shields.io/badge/vue-v3.2.47-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://vuetifyjs.com/">
|
||||
<img src="https://img.shields.io/badge/vuetify-v3.1.13-blue.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://vitejs.dev/">
|
||||
<img src="https://img.shields.io/badge/vite-v4.2.1-blueviolet.svg" alt="element-ui">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/yangjiakai/lux-admin-vuetify3/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h4 align='center'>
|
||||
<a href="https://lux.vuetify3.com/">Live Demo</a>
|
||||
</h4>
|
||||
|
||||
<br>
|
||||
|
||||
<p align='center'>
|
||||
<b>English</b> | <a href="https://github.com/yangjiakai/jk-vuetify3-lux-admin/blob/main/README.zh-CN.md">简体中文</a>| <a href="https://github.com/yangjiakai/jk-vuetify3-lux-admin/blob/main/README.jp.md">日本語</a>
|
||||
</p>
|
||||
|
||||
## Introduction
|
||||
|
||||
> Goal: Creating the best Vuetify 3 Admin open-source template.
|
||||
|
||||
Built upon the elegant themes of Vuetify, we have established a clear and efficient project structure, integrating the latest technology frameworks. This project aims to address a wide range of common technical requirements and features, while incorporating an AI assistant for a more intelligent experience. Additionally, we ensure that all pages are adaptive across multiple devices, achieving a seamless cross-platform compatibility.
|
||||
|
||||
## Features
|
||||
|
||||
- 📖 [Vue 3.2](https://github.com/vuejs/core)
|
||||
- 📖 [Vite 4.x](https://github.com/vitejs/vite)
|
||||
- 📖 UI Framework [Vuetify 3](https://next.vuetifyjs.com/en/)
|
||||
- 📖 TypeScript
|
||||
- 📦 Component Auto Importing
|
||||
- 🍍 [Pinia](https://pinia.vuejs.org/)
|
||||
- 📔 `<script setup>`
|
||||
- 📚 Use icons from any icon sets in [Iconify](https://icon-sets.iconify.design/)
|
||||
- ☁️ Deploy on Netlify, zero-config
|
||||
- 🔑 Firebase auth
|
||||
- 📈 Echarts, ApexChart
|
||||
- 🧭 Openai, Chatgpt
|
||||
- 🌍 vue-i18n
|
||||
- 📚 virtual-scroller , vuedraggable , perfect-scrollbar
|
||||
- 📝 Rich Text Editor
|
||||
- 📇 Responsive multi-platform adaptive
|
||||
|
||||
## Contact Me
|
||||
|
||||
- Email <a href="mailto:yjkbako@gmail.com">yjkbako@gmail.com</a>
|
||||
- Twitter https://twitter.com/baibaixiang
|
||||
- Wechat <img src='/src/assets/wechat-qrcode.png' alt='DashBoard' width='300' />
|
||||
|
||||
## Preview
|
||||
|
||||
<img src='/src/assets/previews/DashBoard.png' alt='DashBoard' />
|
||||
<img src='/src/assets/previews/TaskBoard.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/DataTable.png' alt='DataTable' />
|
||||
<img src='/src/assets/previews/Todo.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/ChatGPT.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Card.png' alt='Card' />
|
||||
<img src='/src/assets/previews/Color.png' alt='Color' />
|
||||
<img src='/src/assets/previews/Gradient.png' alt='Gradient' />
|
||||
<img src='/src/assets/previews/Login.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Unsplash.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Unsplash2.png' alt='ChatGPT' />
|
||||
|
||||
<br>
|
||||
## Pre-packed
|
||||
|
||||
### UI Frameworks
|
||||
|
||||
- [Vuetify3](https://next.vuetifyjs.com/en/) - Vuetify is a no design skills required UI Framework with beautifully handcrafted Vue Components.
|
||||
|
||||
### Icons
|
||||
|
||||
- [Iconify](https://iconify.design) - use icons from any icon sets [🔍Icônes](https://icones.netlify.app/)
|
||||
- [Pure CSS Icons via UnoCSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||
|
||||
### Plugins
|
||||
|
||||
- [Vue Router4](https://router.vuejs.org/)
|
||||
- [VueUse](https://github.com/antfu/vueuse) - collection of useful composition APIs
|
||||
- [VuedDaggable](https://github.com/SortableJS/Vue.Draggable) - allowing drag-and-drop and synchronization with view model array.
|
||||
- [Vue-Masonry-Wall](https://github.com/DerYeger/yeger/tree/main/packages/vue-masonry-wall) - Responsive masonry layout with SSR support and zero dependencies for Vue 3.
|
||||
- [Vue-Virtual-Scroller](https://github.com/Akryum/vue-virtual-scroller) - Blazing fast scrolling of any amount of data
|
||||
|
||||
## Try it now!
|
||||
|
||||
## Project setup
|
||||
```
|
||||
yarn install
|
||||
git clone https://github.com/yangjiakai/lux-admin-vuetify3.git
|
||||
|
||||
cd lux-admin-vuetify3
|
||||
|
||||
npm install
|
||||
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
yarn serve
|
||||
```
|
||||
### Set ApiKey
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
Find the `.env.template` file in the root directory, remove the `.template` suffix, and replace` VITE_OPENAI_API_KEY`, `VITE_UNSPLASH_ACCESS_KEY`, and `VITE_GITHUB_CLIENT_ID` with your own keys.
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
> openai apikey: https://platform.openai.com/account/api-keys
|
||||
|
||||
> unsplash apikey: https://unsplash.com/oauth/applications
|
||||
|
||||
> github apikey: https://github.com/settings/tokens
|
||||
|
||||
158
console-ui/README.zh-CN.md
Normal file
@@ -0,0 +1,158 @@
|
||||
<br><br>
|
||||
|
||||
<p align='center' >
|
||||
<img src='/src/assets/logo_light.svg' alt='Vuetify3' width='300'/>
|
||||
</p>
|
||||
<br><br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://vuejs.org/">
|
||||
<img src="https://img.shields.io/badge/vue-v3.2.47-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://vuetifyjs.com/">
|
||||
<img src="https://img.shields.io/badge/vuetify-v3.1.13-blue.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://vitejs.dev/">
|
||||
<img src="https://img.shields.io/badge/vite-v4.2.1-blueviolet.svg" alt="element-ui">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/yangjiakai/lux-admin-vuetify3/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h4 align='center'>
|
||||
<a href="https://lux.vuetify3.com/">在线 Demo</a>
|
||||
</h4>
|
||||
|
||||
<br>
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/yangjiakai/jk-vuetify3-lux-admin/blob/main/README.md">English</a> | <b>简体中文</b>| <a href="https://github.com/yangjiakai/jk-vuetify3-lux-admin/blob/main/README.jp.md">日本語</a>
|
||||
</p>
|
||||
|
||||
## 序文
|
||||
|
||||
> 目标创造最优秀的 vuetify3 的 Admin 开源模板
|
||||
|
||||
在 Vuetify 精美的主题基础上,我们构建了一个清晰且高效的项目逻辑架构,整合了最新的技术框架。本项目旨在实现各种常见的技术需求和功能,同时融合了 AI 助手,以提供更智能化的体验。此外,我们确保所有页面在多种设备上均能自适应展示,实现优雅的跨平台兼容性。
|
||||
|
||||
## 特性
|
||||
|
||||
- 📖 [Vue 3.2](https://github.com/vuejs/core)
|
||||
- 📖 [Vite 4.x](https://github.com/vitejs/vite)
|
||||
- 📖 UI Framework [Vuetify 3](https://next.vuetifyjs.com/en/)
|
||||
- 📖 TypeScript
|
||||
- 📦 组件自动导入
|
||||
- 🍍 通过 [Pinia](https://pinia.vuejs.org/)进行状态管理
|
||||
- 📔 使用新的 `<script setup>` 语法
|
||||
- 📚 使用任意的图标集 [Iconify](https://icon-sets.iconify.design/)
|
||||
- ☁️ 零配置部署在 Netlify
|
||||
- 🔑 Firebase 授权
|
||||
- 📈 Echarts, ApexChart
|
||||
- 🧭 Openai, Chatgpt 支持
|
||||
- 🌍 vue-i18n 多语言支持
|
||||
- 📚 virtual-scroller , vuedraggable , perfect-scrollbar
|
||||
- 📝 富文本编辑器
|
||||
- 📇 响应式多平台自适应
|
||||
|
||||
## 联络我
|
||||
|
||||
- 邮箱 <a href="mailto:yjkbako@gmail.com">yjkbako@gmail.com</a>
|
||||
- 推特 https://twitter.com/baibaixiang
|
||||
- 微信 <img src='/src/assets/wechat-qrcode.png' alt='DashBoard' width='300' />
|
||||
|
||||
## 预览
|
||||
|
||||
<img src='/src/assets/previews/DashBoard.png' alt='DashBoard' />
|
||||
<img src='/src/assets/previews/TaskBoard.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/DataTable.png' alt='DataTable' />
|
||||
<img src='/src/assets/previews/Todo.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/ChatGPT.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Card.png' alt='Card' />
|
||||
<img src='/src/assets/previews/Color.png' alt='Color' />
|
||||
<img src='/src/assets/previews/Gradient.png' alt='Gradient' />
|
||||
<img src='/src/assets/previews/Login.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Unsplash.png' alt='ChatGPT' />
|
||||
<img src='/src/assets/previews/Unsplash2.png' alt='ChatGPT' />
|
||||
|
||||
<br>
|
||||
## Pre-packed
|
||||
|
||||
### UI 框架
|
||||
|
||||
- [Vuetify3](https://next.vuetifyjs.com/en/) - Vuetify 是一个不要求设计能力的 Vue 界面组件框架,自带了许多自行设计实现的 Vue 组件。
|
||||
|
||||
### Icons
|
||||
|
||||
- [Iconify](https://iconify.design) - 使用任意的图标集 [🔍Icônes](https://icones.netlify.app/)
|
||||
- [Pure CSS Icons via UnoCSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||
|
||||
## 目标功能
|
||||
|
||||
- [x] 明暗主题切换 -- 完成
|
||||
- [x] 主题色切换 -- 完成
|
||||
- [x] 中日英三语言切换-- 完成
|
||||
- [x] 整合 ChatGpt-- 完成
|
||||
|
||||
## 目标页面
|
||||
|
||||
### 认证相关
|
||||
|
||||
- [x] 登录 -- 完成
|
||||
- [x] 注册 -- 完成
|
||||
- [x] 验证邮件 -- 完成
|
||||
- [ ] 密码重置 -- 施工中
|
||||
|
||||
### 公共页面
|
||||
|
||||
- [x] 404 -- 完成
|
||||
- [x] 500 -- 施工中
|
||||
- [x] 系统维护 -- 施工中
|
||||
- [x] 常见问题 -- 施工中
|
||||
|
||||
### UI 相关
|
||||
|
||||
- [x] 瀑布流布局 -- 完成
|
||||
- [x] 大数据虚拟列表 -- 完成
|
||||
- [ ] 骨架屏 -- 施工中
|
||||
|
||||
### 功能页面
|
||||
|
||||
- [x] 任务版(拖拽功能) -- 完成
|
||||
- [x] 任务列表() -- 施工中
|
||||
|
||||
### 站点仿写
|
||||
|
||||
- [ ] ......
|
||||
|
||||
### 插件
|
||||
|
||||
- [Vue Router4](https://router.vuejs.org/)
|
||||
- [VueUse](https://github.com/antfu/vueuse) - 非常有用的组合式 API 合集
|
||||
- [VuedDaggable](https://github.com/SortableJS/Vue.Draggable) - 允许进行与数组模型同步的拖拽放置操作
|
||||
- [Vue-Masonry-Wall](https://github.com/DerYeger/yeger/tree/main/packages/vue-masonry-wall) - 是一种 Vue3 响应式,支持 SSR,且零依的的瀑布流布局方案
|
||||
- [Vue-Virtual-Scroller](https://github.com/Akryum/vue-virtual-scroller) - 大数据快速虚拟滚动插件
|
||||
|
||||
## 现在可以试试!
|
||||
|
||||
```
|
||||
git clone https://github.com/yangjiakai/lux-admin-vuetify3.git
|
||||
|
||||
cd lux-admin-vuetify3
|
||||
|
||||
npm install
|
||||
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 配置 ApiKey
|
||||
|
||||
找到根目录下的`.env.template`文件,去掉`.template`后缀
|
||||
把`VITE_OPENAI_API_KEY`,`VITE_UNSPLASH_ACCESS_KEY`,`VITE_GITHUB_CLIENT_ID`分别替换成你自己的 Key
|
||||
|
||||
> openai apikey: https://platform.openai.com/account/api-keys
|
||||
|
||||
> unsplash apikey: https://unsplash.com/oauth/applications
|
||||
|
||||
> github apikey: https://github.com/settings/tokens
|
||||
73
console-ui/auto-imports.d.ts
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
export {};
|
||||
declare global {
|
||||
const EffectScope: typeof import("vue")["EffectScope"];
|
||||
const acceptHMRUpdate: typeof import("pinia")["acceptHMRUpdate"];
|
||||
const computed: typeof import("vue")["computed"];
|
||||
const createApp: typeof import("vue")["createApp"];
|
||||
const createPinia: typeof import("pinia")["createPinia"];
|
||||
const customRef: typeof import("vue")["customRef"];
|
||||
const defineAsyncComponent: typeof import("vue")["defineAsyncComponent"];
|
||||
const defineComponent: typeof import("vue")["defineComponent"];
|
||||
const defineStore: typeof import("pinia")["defineStore"];
|
||||
const effectScope: typeof import("vue")["effectScope"];
|
||||
const getActivePinia: typeof import("pinia")["getActivePinia"];
|
||||
const getCurrentInstance: typeof import("vue")["getCurrentInstance"];
|
||||
const getCurrentScope: typeof import("vue")["getCurrentScope"];
|
||||
const h: typeof import("vue")["h"];
|
||||
const inject: typeof import("vue")["inject"];
|
||||
const isProxy: typeof import("vue")["isProxy"];
|
||||
const isReactive: typeof import("vue")["isReactive"];
|
||||
const isReadonly: typeof import("vue")["isReadonly"];
|
||||
const isRef: typeof import("vue")["isRef"];
|
||||
const mapActions: typeof import("pinia")["mapActions"];
|
||||
const mapGetters: typeof import("pinia")["mapGetters"];
|
||||
const mapState: typeof import("pinia")["mapState"];
|
||||
const mapStores: typeof import("pinia")["mapStores"];
|
||||
const mapWritableState: typeof import("pinia")["mapWritableState"];
|
||||
const markRaw: typeof import("vue")["markRaw"];
|
||||
const nextTick: typeof import("vue")["nextTick"];
|
||||
const onActivated: typeof import("vue")["onActivated"];
|
||||
const onBeforeMount: typeof import("vue")["onBeforeMount"];
|
||||
const onBeforeRouteLeave: typeof import("vue-router")["onBeforeRouteLeave"];
|
||||
const onBeforeRouteUpdate: typeof import("vue-router")["onBeforeRouteUpdate"];
|
||||
const onBeforeUnmount: typeof import("vue")["onBeforeUnmount"];
|
||||
const onBeforeUpdate: typeof import("vue")["onBeforeUpdate"];
|
||||
const onDeactivated: typeof import("vue")["onDeactivated"];
|
||||
const onErrorCaptured: typeof import("vue")["onErrorCaptured"];
|
||||
const onMounted: typeof import("vue")["onMounted"];
|
||||
const onRenderTracked: typeof import("vue")["onRenderTracked"];
|
||||
const onRenderTriggered: typeof import("vue")["onRenderTriggered"];
|
||||
const onScopeDispose: typeof import("vue")["onScopeDispose"];
|
||||
const onServerPrefetch: typeof import("vue")["onServerPrefetch"];
|
||||
const onUnmounted: typeof import("vue")["onUnmounted"];
|
||||
const onUpdated: typeof import("vue")["onUpdated"];
|
||||
const provide: typeof import("vue")["provide"];
|
||||
const reactive: typeof import("vue")["reactive"];
|
||||
const readonly: typeof import("vue")["readonly"];
|
||||
const ref: typeof import("vue")["ref"];
|
||||
const resolveComponent: typeof import("vue")["resolveComponent"];
|
||||
const resolveDirective: typeof import("vue")["resolveDirective"];
|
||||
const setActivePinia: typeof import("pinia")["setActivePinia"];
|
||||
const setMapStoreSuffix: typeof import("pinia")["setMapStoreSuffix"];
|
||||
const shallowReactive: typeof import("vue")["shallowReactive"];
|
||||
const shallowReadonly: typeof import("vue")["shallowReadonly"];
|
||||
const shallowRef: typeof import("vue")["shallowRef"];
|
||||
const storeToRefs: typeof import("pinia")["storeToRefs"];
|
||||
const toRaw: typeof import("vue")["toRaw"];
|
||||
const toRef: typeof import("vue")["toRef"];
|
||||
const toRefs: typeof import("vue")["toRefs"];
|
||||
const triggerRef: typeof import("vue")["triggerRef"];
|
||||
const unref: typeof import("vue")["unref"];
|
||||
const useAttrs: typeof import("vue")["useAttrs"];
|
||||
const useCssModule: typeof import("vue")["useCssModule"];
|
||||
const useCssVars: typeof import("vue")["useCssVars"];
|
||||
const useLink: typeof import("vue-router")["useLink"];
|
||||
const useRoute: typeof import("vue-router")["useRoute"];
|
||||
const useRouter: typeof import("vue-router")["useRouter"];
|
||||
const useSlots: typeof import("vue")["useSlots"];
|
||||
const watch: typeof import("vue")["watch"];
|
||||
const watchEffect: typeof import("vue")["watchEffect"];
|
||||
const watchPostEffect: typeof import("vue")["watchPostEffect"];
|
||||
const watchSyncEffect: typeof import("vue")["watchSyncEffect"];
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
||||
19
console-ui/index.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<title>Vuetify-Lux</title>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "esnext",
|
||||
"baseUrl": "./",
|
||||
"moduleResolution": "node",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
}
|
||||
}
|
||||
4615
console-ui/package-lock.json
generated
Normal file
@@ -1,27 +1,66 @@
|
||||
{
|
||||
"name": "console-ui",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"name": "vuetify3-design",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build"
|
||||
"dev": "vite --mode dev",
|
||||
"build": "vite build --mode pro",
|
||||
"preview": "vite preview",
|
||||
"test": "vitest",
|
||||
"test:ui": "vitest --ui",
|
||||
"coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.8.3",
|
||||
"vue": "^2.6.14",
|
||||
"vue-router": "^3.5.1",
|
||||
"vuex": "^3.6.2"
|
||||
"@mdi/font": "7.2.96",
|
||||
"@tiptap/pm": "^2.0.2",
|
||||
"@tiptap/starter-kit": "^2.0.2",
|
||||
"@tiptap/vue-3": "^2.0.2",
|
||||
"@vueup/vue-quill": "^1.1.1",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"@vueuse/integrations": "^9.13.0",
|
||||
"@yeger/vue-masonry-wall": "^3.4.4",
|
||||
"apexcharts": "^3.37.3",
|
||||
"axios": "^1.3.5",
|
||||
"echarts": "^5.4.2",
|
||||
"firebase": "^9.19.1",
|
||||
"flag-icons": "^6.6.6",
|
||||
"focus-trap": "^7.4.0",
|
||||
"happy-dom": "^9.6.1",
|
||||
"md-editor-v3": "^2.11.2",
|
||||
"moment": "^2.29.4",
|
||||
"openai": "^3.2.1",
|
||||
"pinia": "^2.0.34",
|
||||
"pinia-plugin-persist": "^1.0.0",
|
||||
"roboto-fontface": "*",
|
||||
"unsplash-js": "^7.0.15",
|
||||
"vue": "^3.2.47",
|
||||
"vue-echarts": "^6.5.4",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-masonry": "^0.16.0",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-virtual-scroller": "^2.0.0-beta.8",
|
||||
"vue-waterfall-plugin-next": "^2.2.0",
|
||||
"vue3-apexcharts": "^1.4.1",
|
||||
"vue3-lottie": "^2.5.0",
|
||||
"vue3-perfect-scrollbar": "^1.6.1",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuetify": "^3.1.13",
|
||||
"webfontloader": "^1.6.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-plugin-router": "~5.0.0",
|
||||
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"vue-template-compiler": "^2.6.14"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@fortawesome/fontawesome-free": "^6.4.0",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@types/node": "^18.15.11",
|
||||
"@vitejs/plugin-vue": "^4.1.0",
|
||||
"@vitest/ui": "^0.30.1",
|
||||
"@vue/test-utils": "^2.0.0-rc.18",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"postcss": "^8.4.21",
|
||||
"sass": "^1.61.0",
|
||||
"tailwindcss": "^3.3.1",
|
||||
"unplugin-auto-import": "^0.15.2",
|
||||
"vite": "^4.2.1",
|
||||
"vite-plugin-vuetify": "^1.0.2",
|
||||
"vitest": "^0.30.1"
|
||||
}
|
||||
}
|
||||
|
||||
1
console-ui/public/_redirects
Normal file
@@ -0,0 +1 @@
|
||||
/* /index.html 200
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,17 +0,0 @@
|
||||
<!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>
|
||||
@@ -1,32 +1,48 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<nav>
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</nav>
|
||||
<router-view/>
|
||||
</div>
|
||||
<v-app id="app" :theme="customizeTheme.darkTheme ? 'dark' : 'light'">
|
||||
<component :is="currentLayout" v-if="isRouterLoaded">
|
||||
<router-view> </router-view>
|
||||
</component>
|
||||
<CustomizationMenu />
|
||||
<BackToTop />
|
||||
<Snackbar />
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
}
|
||||
<script setup lang="ts">
|
||||
import UILayout from "@/layouts/UILayout.vue";
|
||||
import LandingLayout from "@/layouts/LandingLayout.vue";
|
||||
import DefaultLayout from "@/layouts/DefaultLayout.vue";
|
||||
import AuthLayout from "@/layouts/AuthLayout.vue";
|
||||
import CustomizationMenu from "@/components/CustomizationMenu.vue";
|
||||
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
|
||||
import BackToTop from "@/components/common/BackToTop.vue";
|
||||
import Snackbar from "@/components/common/Snackbar.vue";
|
||||
|
||||
nav {
|
||||
padding: 30px;
|
||||
}
|
||||
const customizeTheme = useCustomizeThemeStore();
|
||||
const route = useRoute();
|
||||
|
||||
nav a {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
}
|
||||
const isRouterLoaded = computed(() => {
|
||||
if (route.name !== null) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
nav a.router-link-exact-active {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
const layouts = {
|
||||
default: DefaultLayout,
|
||||
ui: UILayout,
|
||||
landing: LandingLayout,
|
||||
auth: AuthLayout,
|
||||
};
|
||||
|
||||
type LayoutName = "default" | "ui" | "landing" | "auth" | "error";
|
||||
|
||||
const currentLayout = computed(() => {
|
||||
const layoutName = route.meta.layout as LayoutName;
|
||||
if (!layoutName) {
|
||||
return DefaultLayout;
|
||||
}
|
||||
return layouts[layoutName];
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
59
console-ui/src/api/aiApi.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import axios from "axios";
|
||||
import { useSnackbarStore } from "@/stores/snackbarStore";
|
||||
const gptInstance = axios.create({
|
||||
baseURL: "https://api.openai.com",
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
gptInstance.interceptors.response.use(
|
||||
(response) => {
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
const snackbarStore = useSnackbarStore();
|
||||
if (error.response) {
|
||||
const status = error.response.status;
|
||||
const data = error.response.data;
|
||||
snackbarStore.showErrorMessage(data.error);
|
||||
} else {
|
||||
snackbarStore.showErrorMessage("Network Error");
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Get all models.
|
||||
export const getModelsApi = (apiKey: string) => {
|
||||
return gptInstance.get("/v1/models", {
|
||||
headers: {
|
||||
Authorization: "Bearer " + apiKey,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Get account balance information.
|
||||
export const getBalanceApi = (apiKey: string) => {
|
||||
return gptInstance.get("/dashboard/billing/credit_grants", {
|
||||
headers: {
|
||||
Authorization: "Bearer " + apiKey,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// speech-to-text
|
||||
export const createTranscriptionApi = (formData: any, apiKey: string) => {
|
||||
return gptInstance.post("/v1/audio/transcriptions", formData, {
|
||||
headers: {
|
||||
Authorization: "Bearer " + apiKey,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// completions(Stream UnUsed)
|
||||
export const createCompletionApi = (data: any, apiKey: string) => {
|
||||
return gptInstance.post("/v1/chat/completions", data, {
|
||||
headers: {
|
||||
Authorization: "Bearer " + apiKey,
|
||||
},
|
||||
});
|
||||
};
|
||||
39
console-ui/src/api/githubApi.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import axios from "axios";
|
||||
import { useSnackbarStore } from "@/stores/snackbarStore";
|
||||
const snackbarStore = useSnackbarStore();
|
||||
// change the access key to your own
|
||||
const ACCESS_KEY = import.meta.env.VITE_GITHUB_CLIENT_ID;
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: "https://api.github.com",
|
||||
timeout: 20000,
|
||||
headers: { Authorization: "Bearer" + " " + ACCESS_KEY },
|
||||
});
|
||||
|
||||
instance.interceptors.response.use(
|
||||
(response) => {
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
if (error.response) {
|
||||
const status = error.response.status;
|
||||
const data = error.response.data;
|
||||
snackbarStore.showErrorMessage(data.message);
|
||||
} else {
|
||||
snackbarStore.showErrorMessage("Network Error");
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// https://api.github.com/users/yangjiakai/events/public
|
||||
|
||||
// Get public events for a user
|
||||
export const getPublicEventsApi = (username: string) => {
|
||||
return instance.get("/users/" + username + "/events/public");
|
||||
};
|
||||
|
||||
// Get public events for a network of repositories
|
||||
export const getPublicEventsForNetworkApi = (username: string) => {
|
||||
return instance.get("/networks/" + username + "/events");
|
||||
};
|
||||
33
console-ui/src/api/googleApi.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import axios from "axios";
|
||||
|
||||
export const textToSpeech = async () => {
|
||||
const googleInstance = axios.create({
|
||||
baseURL: "https://us-central1-texttospeech.googleapis.com",
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
const res = await googleInstance.post(
|
||||
"/v1/chat/completions/text:synthesize",
|
||||
{
|
||||
audioConfig: {
|
||||
audioEncoding: "LINEAR16",
|
||||
effectsProfileId: ["small-bluetooth-speaker-class-device"],
|
||||
pitch: 0,
|
||||
speakingRate: 1,
|
||||
},
|
||||
input: {
|
||||
text: "Google Cloud Text-to-Speech enables developers to synthesize natural-sounding speech with 100+ voices, available in multiple languages and variants. It applies DeepMind’s groundbreaking research in WaveNet and Google’s powerful neural networks to deliver the highest fidelity possible. As an easy-to-use API, you can create lifelike interactions with your users, across many applications and devices.",
|
||||
},
|
||||
voice: {
|
||||
languageCode: "en-US",
|
||||
name: "en-US-Neural2-J",
|
||||
},
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-goog-api-key": "AIzaSyBSXdkeyAvIZX5n_bj4KsqSjJf1W-_TfCntvk",
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
160
console-ui/src/api/unsplashApi.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import axios from "axios";
|
||||
import { useSnackbarStore } from "@/stores/snackbarStore";
|
||||
const snackbarStore = useSnackbarStore();
|
||||
// change the access key to your own
|
||||
const ACCESS_KEY = import.meta.env.VITE_UNSPLASH_ACCESS_KEY;
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: "https://api.unsplash.com",
|
||||
timeout: 20000,
|
||||
headers: { Authorization: "Client-ID" + " " + ACCESS_KEY },
|
||||
});
|
||||
|
||||
instance.interceptors.response.use(
|
||||
(response) => {
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
if (error.response) {
|
||||
const status = error.response.status;
|
||||
const data = error.response.data;
|
||||
snackbarStore.showErrorMessage(data.errors[0]);
|
||||
} else {
|
||||
snackbarStore.showErrorMessage("Network Error");
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
interface Query {
|
||||
page?: number;
|
||||
per_page?: number;
|
||||
}
|
||||
|
||||
// List photos 图片一览
|
||||
export const getPhotosApi = (query?: Query) => {
|
||||
return instance.get("/photos/", { params: query });
|
||||
};
|
||||
|
||||
// Get a photo 获取图片信息
|
||||
export const getPhotoApi = (id: string) => {
|
||||
return instance.get("/photos/" + id);
|
||||
};
|
||||
|
||||
// Get a random photo 获取一张随机图片
|
||||
export const getRandomPhotoApi = () => {
|
||||
return instance.get("/photos/random");
|
||||
};
|
||||
|
||||
// Get a photo’s statistics 获取照片的统计数据
|
||||
export const getPhotoStatisticsApi = (id: string) => {
|
||||
return instance.get("/photos/" + id + "/statistics");
|
||||
};
|
||||
|
||||
// Get a photo’s related 获取照片的相关照片
|
||||
export const getPhotoRelatedApi = (id: string) => {
|
||||
return instance.get("/photos/" + id + "/related");
|
||||
};
|
||||
|
||||
// Track a photo download
|
||||
// Update a photo
|
||||
// Like a photo
|
||||
// Unlike a photo
|
||||
|
||||
// Topic
|
||||
// List topics
|
||||
export const getTopicsApi = (query?: Query) => {
|
||||
return instance.get("/topics", { params: query });
|
||||
};
|
||||
|
||||
// Get a topic
|
||||
export const getTopicApi = (id_or_slug: string | string[]) => {
|
||||
return instance.get("/topics/" + id_or_slug);
|
||||
};
|
||||
|
||||
// Get a topic’s photos
|
||||
export const getTopicPhotosApi = (
|
||||
id_or_slug: string | string[],
|
||||
query?: Query
|
||||
) => {
|
||||
return instance.get("/topics/" + id_or_slug + "/photos", { params: query });
|
||||
};
|
||||
|
||||
// Get a user
|
||||
export const getUserApi = (username: string | string[]) => {
|
||||
return instance.get("/users/" + username);
|
||||
};
|
||||
// Get a user’s portfolio
|
||||
export const getUserPortfolioApi = (username: string | string[]) => {
|
||||
return instance.get("/users/" + username + "/portfolio");
|
||||
};
|
||||
// List a user’s photos
|
||||
export const getUserPhotosApi = (
|
||||
username: string | string[],
|
||||
query?: Query
|
||||
) => {
|
||||
return instance.get("/users/" + username + "/photos", { params: query });
|
||||
};
|
||||
// List a user’s liked photos
|
||||
export const getUserLikesApi = (username: string | string[], query?: Query) => {
|
||||
return instance.get("/users/" + username + "/likes", { params: query });
|
||||
};
|
||||
// List a user’s collections
|
||||
export const getUserCollectionsApi = (
|
||||
username: string | string[],
|
||||
query?: Query
|
||||
) => {
|
||||
return instance.get("/users/" + username + "/collections", { params: query });
|
||||
};
|
||||
// Get a user’s statistics
|
||||
export const getUserStatisticsApi = (username: string | string[]) => {
|
||||
return instance.get("/users/" + username + "/statistics");
|
||||
};
|
||||
|
||||
// Collections 图集
|
||||
// List collections 图集一览
|
||||
export const getCollectionsApi = (query?: Query) => {
|
||||
return instance.get("/collections", { params: query });
|
||||
};
|
||||
|
||||
// Get a collection 获取图集信息
|
||||
export const getCollectionApi = (id: string | string[]) => {
|
||||
return instance.get("/collections/" + id);
|
||||
};
|
||||
// Get a collection’s photos 获取该图集下所有图片
|
||||
export const getCollectionPhotosApi = (
|
||||
id: string | string[],
|
||||
query?: Query
|
||||
) => {
|
||||
return instance.get("/collections/" + id + "/photos", { params: query });
|
||||
};
|
||||
// List a collection’s related collections 获取该图集相关联图集
|
||||
export const getCollectionRelatedApi = (id: string | string[]) => {
|
||||
return instance.get("/collections/" + id + "/related");
|
||||
};
|
||||
// Create a new collection 新增图集
|
||||
// Update an existing collection 更新现存图集
|
||||
// Delete a collection 删除某个图集
|
||||
// Add a photo to a collection 添加图片到图集
|
||||
// Remove a photo from a collection 从图集删除图片
|
||||
|
||||
// Search
|
||||
// Search All
|
||||
export const searchAllApi = (query?: Query) => {
|
||||
return instance.get("/search", { params: query });
|
||||
};
|
||||
|
||||
// Search photos
|
||||
export const searchPhotosApi = (query?: Query) => {
|
||||
return instance.get("/search/photos", { params: query });
|
||||
};
|
||||
|
||||
// Search collections
|
||||
export const searchCollectionsApi = (query?: Query) => {
|
||||
return instance.get("/search/collections", { params: query });
|
||||
};
|
||||
|
||||
// Search users
|
||||
export const searchUsersApi = (query?: Query) => {
|
||||
return instance.get("/search/users", { params: query });
|
||||
};
|
||||
24
console-ui/src/api/userApi.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { User } from "firebase/auth";
|
||||
import { db, auth } from "@/firebase";
|
||||
import { doc, setDoc, getDoc, getDocs, collection } from "firebase/firestore";
|
||||
|
||||
export const addUserToUsersCollection = async (user: User) => {
|
||||
const profile = {
|
||||
id: user.uid,
|
||||
name: user.displayName,
|
||||
avatar: user.photoURL,
|
||||
created: false,
|
||||
};
|
||||
|
||||
try {
|
||||
await setDoc(doc(db, "users", user.uid), {
|
||||
name: user.displayName,
|
||||
avatar: user.photoURL,
|
||||
});
|
||||
profile.created = true;
|
||||
} catch (error) {
|
||||
console.error("Error adding document: ", error);
|
||||
}
|
||||
|
||||
return profile;
|
||||
};
|
||||
1
console-ui/src/assets/images/404.svg
Normal file
|
After Width: | Height: | Size: 17 KiB |
1
console-ui/src/assets/images/500.svg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
console-ui/src/assets/images/avatars/avatar_user.jpg
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
console-ui/src/assets/images/card2/yoimiya.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
console-ui/src/assets/images/card2/yoimiya_bg.jpg
Normal file
|
After Width: | Height: | Size: 520 KiB |
BIN
console-ui/src/assets/images/chat-bg-2.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
10
console-ui/src/assets/images/svg1.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect x="0" y="0" width="100" height="100" fill="purple"/>
|
||||
<circle cx="50" cy="50" r="30" fill="white"/>
|
||||
<circle cx="40" cy="40" r="4" fill="black"/>
|
||||
<circle cx="60" cy="40" r="4" fill="black"/>
|
||||
<path d="M 40 60 Q 50 70, 60 60" stroke="black" stroke-width="2" fill="none"/>
|
||||
<polygon points="90,90 80,70 70,90" fill="black"/>
|
||||
<rect x="78" y="65" width="2" height="25" fill="black" transform="rotate(-45, 79, 65)"/>
|
||||
<circle cx="79" cy="65" r="3" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 545 B |
60
console-ui/src/assets/loading.svg
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: rgb(255, 255, 255); display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
|
||||
<g transform="translate(80,50)">
|
||||
<g transform="rotate(0)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="1">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.875s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.875s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(71.21320343559643,71.21320343559643)">
|
||||
<g transform="rotate(45)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.875">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.75s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.75s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(50,80)">
|
||||
<g transform="rotate(90)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.75">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.625s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.625s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(28.786796564403577,71.21320343559643)">
|
||||
<g transform="rotate(135)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.625">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.5s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.5s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(20,50.00000000000001)">
|
||||
<g transform="rotate(180)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.5">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.375s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.375s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(28.78679656440357,28.786796564403577)">
|
||||
<g transform="rotate(225)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.375">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.25s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.25s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(49.99999999999999,20)">
|
||||
<g transform="rotate(270)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.25">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.125s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.125s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(71.21320343559643,28.78679656440357)">
|
||||
<g transform="rotate(315)">
|
||||
<circle cx="0" cy="0" r="6" fill="#72c9ff" fill-opacity="0.125">
|
||||
<animateTransform attributeName="transform" type="scale" begin="0s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="0s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g>
|
||||
<!-- [ldio] generated by https://loading.io/ --></svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
BIN
console-ui/src/assets/logo.back.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
6
console-ui/src/assets/logo.back.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M261.126 140.65L164.624 307.732L256.001 466L377.028 256.5L498.001 47H315.192L261.126 140.65Z" fill="#1697F6"/>
|
||||
<path d="M135.027 256.5L141.365 267.518L231.64 111.178L268.731 47H256H14L135.027 256.5Z" fill="#AEDDFF"/>
|
||||
<path d="M315.191 47C360.935 197.446 256 466 256 466L164.624 307.732L315.191 47Z" fill="#1867C0"/>
|
||||
<path d="M268.731 47C76.0026 47 141.366 267.518 141.366 267.518L268.731 47Z" fill="#7BC6FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 526 B |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 11 KiB |
65
console-ui/src/assets/logo.svg
Normal file
@@ -0,0 +1,65 @@
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="100%" viewBox="0 0 292 350" enable-background="new 0 0 292 350" xml:space="preserve">
|
||||
<path fill="#FEFFFF" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M1.000000,128.000000
|
||||
C1.000000,85.349754 1.000000,43.199505 1.000000,1.024629
|
||||
C98.279007,1.024629 195.558014,1.024629 292.918518,1.024629
|
||||
C292.918518,117.566864 292.918518,234.133804 292.918518,350.850372
|
||||
C195.666840,350.850372 98.333450,350.850372 1.000000,350.850372
|
||||
C1.000000,276.775421 1.000000,202.637711 1.000000,128.000000
|
||||
M60.945122,103.841530
|
||||
C42.713490,103.841530 24.481857,103.841530 5.292197,103.841530
|
||||
C52.947048,186.459473 100.087868,268.186249 147.480728,350.349976
|
||||
C195.001831,268.033112 242.189346,186.294067 289.779907,103.856873
|
||||
C270.104889,103.856873 251.620804,103.856873 233.073532,103.150719
|
||||
C233.940903,101.371254 234.704636,99.532021 235.691330,97.821396
|
||||
C248.489014,75.634048 261.324280,53.468391 274.136688,31.289537
|
||||
C279.085297,22.723295 284.000122,14.137545 289.584625,4.422431
|
||||
C286.640228,5.343472 284.933716,5.822242 283.264526,6.407475
|
||||
C238.979431,21.934256 194.704971,37.491520 150.390533,52.934074
|
||||
C148.682556,53.529266 146.411621,53.569023 144.713531,52.976955
|
||||
C105.802299,39.409748 66.936913,25.711136 28.055904,12.057143
|
||||
C20.953766,9.563058 13.820872,7.156544 5.668715,4.354370
|
||||
C6.763332,6.406374 7.201184,7.288102 7.692324,8.139076
|
||||
C24.146460,36.648350 40.631691,65.139748 57.028324,93.682045
|
||||
C58.893276,96.928444 60.264931,100.458237 60.945122,103.841530
|
||||
z"/>
|
||||
<path fill="#2064EA" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M233.136719,103.856873
|
||||
C251.620804,103.856873 270.104889,103.856873 289.779907,103.856873
|
||||
C242.189346,186.294067 195.001831,268.033112 147.480728,350.349976
|
||||
C100.087868,268.186249 52.947048,186.459473 5.292197,103.841530
|
||||
C24.481857,103.841530 42.713490,103.841530 61.662327,103.928421
|
||||
C62.558861,104.006554 62.738190,103.997810 63.065762,104.306396
|
||||
C91.225380,153.133133 119.236748,201.642517 147.536011,250.650467
|
||||
C175.919067,201.411285 203.997498,152.700562 232.346878,104.002457
|
||||
C232.790787,103.962349 232.963760,103.909615 233.136719,103.856873
|
||||
z"/>
|
||||
<path fill="#7486FB" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M233.105133,103.503799
|
||||
C232.963760,103.909615 232.790787,103.962349 231.872528,103.984970
|
||||
C175.057327,103.966263 118.987419,103.977661 62.917519,103.989059
|
||||
C62.738190,103.997810 62.558861,104.006554 62.122425,103.935959
|
||||
C60.264931,100.458237 58.893276,96.928444 57.028324,93.682045
|
||||
C40.631691,65.139748 24.146460,36.648350 7.692324,8.139076
|
||||
C7.201184,7.288102 6.763332,6.406374 5.668715,4.354370
|
||||
C13.820872,7.156544 20.953766,9.563058 28.055904,12.057143
|
||||
C66.936913,25.711136 105.802299,39.409748 144.713531,52.976955
|
||||
C146.411621,53.569023 148.682556,53.529266 150.390533,52.934074
|
||||
C194.704971,37.491520 238.979431,21.934256 283.264526,6.407475
|
||||
C284.933716,5.822242 286.640228,5.343472 289.584625,4.422431
|
||||
C284.000122,14.137545 279.085297,22.723295 274.136688,31.289537
|
||||
C261.324280,53.468391 248.489014,75.634048 235.691330,97.821396
|
||||
C234.704636,99.532021 233.940903,101.371254 233.105133,103.503799
|
||||
z"/>
|
||||
<path fill="#FEFEFF" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M63.065762,104.306396
|
||||
C118.987419,103.977661 175.057327,103.966263 231.601578,103.972351
|
||||
C203.997498,152.700562 175.919067,201.411285 147.536011,250.650467
|
||||
C119.236748,201.642517 91.225380,153.133133 63.065762,104.306396
|
||||
z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
24
console-ui/src/assets/logo1.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg y="558.665" x="988" viewBox="0 0 356 52" height="52" width="356" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Layer_1">
|
||||
<title>Layer 1</title>
|
||||
<metadata id="svg_28">image/svg+xml</metadata>
|
||||
<g id="svg_3" transform="translate(0 0)">
|
||||
<image id="svg_18" x="-333.96937" y="-358.11919" height="0" width="0"/>
|
||||
<g id="svg_17" transform="translate(0 0)" font-style="normal" font-weight="600" font-size="32px" font-family="Karma" text-anchor="middle"/>
|
||||
<g id="svg_5" transform="translate(0 0)" font-style="normal" font-weight="400" font-size="72px" font-family="Megrim" text-anchor="middle">
|
||||
<path id="svg_16" d="m32.76,53.35921l-16.38,38.6568l-16.38,-38.6568l2.09664,0l14.28336,33.61176l14.28336,-33.61176l2.09664,0z" stroke-width="0" stroke-miterlimit="2" fill="#ec9126" stroke="#ec9126" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_15" d="m41.41887,53.35921l0,19.0008q0,9.76248 3.07944,13.7592q3.14496,3.9312 8.58312,3.9312q5.43816,0 8.5176,-3.9312q3.14496,-3.99672 3.14496,-13.7592l0,-19.0008l1.9656,0l0,19.0008q0,19.656 -13.62816,19.656q-13.62816,0 -13.62816,-19.656l0,-19.0008l1.9656,0z" stroke-width="0" stroke-miterlimit="2" fill="#e58b25" stroke="#e58b25" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_14" d="m103.92086,87.49513q-3.6036,4.52088 -11.7936,4.52088q-8.19,0 -11.72808,-4.65192q-3.53808,-4.65192 -3.53808,-15.00408q0,-10.35216 3.53808,-15.00408q3.53808,-4.65192 11.72808,-4.65192q9.5004,0 12.90744,6.2244l-16.0524,13.4316l-3.07944,0l16.57656,-13.82472q-2.88288,-3.86568 -10.35216,-3.86568q-3.276,0 -5.50368,0.72072q-2.22768,0.6552 -4.12776,2.55528q-1.83456,1.83456 -2.75184,5.43816q-0.91728,3.53808 -0.91728,8.97624q0,5.43816 0.91728,9.04176q0.91728,3.53808 2.75184,5.43816q1.90008,1.83456 4.12776,2.55528q2.22768,0.6552 5.50368,0.6552q7.46928,0 10.35216,-3.86568l1.44144,1.3104z" stroke-width="0" stroke-miterlimit="2" fill="#dd8524" stroke="#dd8524" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_13" d="m139.02831,53.35921l0,1.9656l-13.7592,0l0,36.036l-1.96561,0l0,-36.036l-13.7592,0l0,-1.9656l29.48401,0z" stroke-width="0" stroke-miterlimit="2" fill="#d67f23" stroke="#d67f23" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_12" d="m146.57848,53.35921l1.9656,0l0,38.0016l-1.9656,0l0,-38.0016z" stroke-width="0" stroke-miterlimit="2" fill="#ce7922" stroke="#ce7922" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_11" d="m160.38372,91.36081l0,-19.0008q0,-10.35216 3.53808,-15.00408q3.60361,-4.65192 11.72809,-4.65192q9.5004,0 12.90744,6.2244l-13.69369,11.466l13.95577,0l0,1.9656l-19.39393,0l16.57657,-13.82472q-2.88288,-3.86568 -10.35216,-3.86568q-3.27601,0 -5.50368,0.72072q-2.22769,0.6552 -4.12777,2.55528q-1.83456,1.83456 -2.75184,5.43816q-0.91728,3.53808 -0.91728,8.97624l0,19.0008l-1.9656,0z" stroke-width="0" stroke-miterlimit="2" fill="#c77321" stroke="#c77321" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_10" d="m200.95496,53.35921l25.35624,0l-15.39721,36.3636l0,14.742l-1.9656,0l0,-14.742l-15.39719,-36.3636l2.09664,0l14.28336,33.61176l13.4316,-31.64616l-22.40784,0l0,-1.9656z" stroke-width="0" stroke-miterlimit="2" fill="#c06c20" stroke="#c06c20" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_9" d="m230.71435,97.25761l0,-1.9656l26.208,0l0,1.9656l-26.208,0z" stroke-width="0" stroke-miterlimit="2" fill="#b8661f" stroke="#b8661f" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_8" d="m288.36888,89.39521l0,1.9656l-21.88368,0l0,-38.0016l1.96559,0l0,36.036l19.91809,0z" stroke-width="0" stroke-miterlimit="2" fill="#b1601e" stroke="#b1601e" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_7" d="m297.22841,53.35921l0,19.0008q0,9.76248 3.07944,13.7592q3.14496,3.9312 8.58312,3.9312q5.43816,0 8.51761,-3.9312q3.14496,-3.99672 3.14496,-13.7592l0,-19.0008l1.96559,0l0,19.0008q0,19.656 -13.62816,19.656q-13.62816,0 -13.62816,-19.656l0,-19.0008l1.9656,0z" stroke-width="0" stroke-miterlimit="2" fill="#a95a1d" stroke="#a95a1d" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
<path id="svg_6" d="m344.26767,70.85305l11.79361,20.50776l-2.2932,0l-10.67976,-18.47664l-10.67977,18.47664l-2.2932,0l11.7936,-20.50776l-10.09007,-17.49384l2.2932,0l8.97624,15.52824l8.97623,-15.52824l2.2932,0l-10.09008,17.49384z" stroke-width="0" stroke-miterlimit="2" fill="#a2541c" stroke="#a2541c" transform="translate(0 -357) translate(0 304.296)"/>
|
||||
</g>
|
||||
<image id="svg_4" x="-333.96937" y="-358.11919" height="0" width="0"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
32
console-ui/src/assets/logo2.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<svg y="552.665" x="1007.5" version="1.1" width="317" height="64" viewBox="0 0 317 64" id="svg78192" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata78198">image/svg+xml</metadata>
|
||||
|
||||
<linearGradient id="3d_gradient2-logo-682f3222-452d-46d2-bf30-c93cee4278d2" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop78173"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop78175"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="3d_gradient3-logo-682f3222-452d-46d2-bf30-c93cee4278d2" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad" gradientTransform="rotate(-30)">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop78178"/>
|
||||
<stop offset="50%" stop-color="#cccccc" id="stop78180"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop78182"/>
|
||||
</linearGradient>
|
||||
<g id="logo-group">
|
||||
<g id="logo-center">
|
||||
<image width="0" height="0" y="-351.98328" x="-353.51215" id="icon_container"/>
|
||||
<g text-anchor="middle" font-family="Orienta" font-size="32px" font-weight="400" font-style="normal" transform="translate(0 0)" id="slogan"/>
|
||||
<g text-anchor="middle" font-family="'Brandmark Didone 1'" font-size="72px" font-weight="normal" font-style="normal" transform="translate(0 0)" id="title">
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#3a456c" fill="#3a456c" stroke-miterlimit="2" stroke-width="0" d="m385.6421,97.05592l-11.07,32.454l-9.342,-27.378c-1.08,-3.186 -3.83399,-5.076 -7.12799,-5.076l-4.59,0l0,0.27c2.53799,0 3.99599,1.89 4.91399,4.32l11.34,33.588l3.94201,0l13.01399,-38.178l-1.08,0z" id="path78201"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#465075" fill="#465075" stroke-miterlimit="2" stroke-width="0" d="m421.85332,97.05592l0,23.598c0,7.344 -6.534,13.284 -12.69,13.284c-6.156,0 -9.666,-5.94 -9.666,-13.284l0,-23.598l-10.692,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,18.522c0,8.046 6.534,14.58 14.634,14.58c8.1,0 14.634,-6.534 14.634,-14.58l0,-23.598l-1.08,0z" id="path78203"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#525c7e" fill="#525c7e" stroke-miterlimit="2" stroke-width="0" d="m438.63129,98.13592l16.308,0l0,-1.08l-27,0l0,0.27c2.7,0 4.86001,2.16 4.86001,4.806l0,32.67l22.13999,0l0,-1.08l-16.308,0l0,-21.276l15.012,0l0,-1.08l-15.012,0l0,-13.23z" id="path78205"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#5d6786" fill="#5d6786" stroke-miterlimit="2" stroke-width="0" d="m486.45842,98.13592l0,-1.08l-29.376,0l0,1.08l11.77199,0l0,36.666l5.832,0l0,-36.666l11.77201,0z" id="path78207"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#69728f" fill="#69728f" stroke-miterlimit="2" stroke-width="0" d="m498.85395,97.05592l-10.692,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,32.67l5.832,0l0,-37.746z" id="path78209"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#757e98" fill="#757e98" stroke-miterlimit="2" stroke-width="0" d="m515.09614,98.13592l16.308,0l0,-1.08l-27,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,32.67l5.832,0l0,-22.302l14.256,0l0,-1.08l-14.256,0l0,-13.284z" id="path78211"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#8189a1" fill="#8189a1" stroke-miterlimit="2" stroke-width="0" d="m602.68245,82.52992c-0.054,-0.972 -0.162,-1.944 -0.432,-2.862c-0.54,-1.89 -1.62,-3.618 -2.97,-5.022c-1.404,-1.404 -3.186,-2.43 -5.076,-2.97c-3.726,-1.026 -7.668,-0.324 -10.854,1.458c-1.566,0.918 -2.97,2.052 -4.158,3.402c-0.594,0.648 -1.134,1.404 -1.566,2.106c-0.486,0.756 -0.972,1.458 -1.404,2.214c-1.944,2.808 -3.78,5.724 -5.616,8.64l-2.754,4.32c-0.648,1.134 -1.35,2.16 -1.998,3.294l-11.826,18.522l-10.908,-18.576l-10.26,0l0,0.27c2.7,0 4.752,2.16 6.318,4.86l-0.054,0l9.504,16.146l0,1.08l5.832,0l0,-2.808l0.054,-0.054l12.42,-19.494c0.594,-0.864 1.188,-1.782 1.782,-2.7l2.808,-4.32c1.89,-2.862 3.726,-5.724 5.508,-8.64l1.404,-2.214c0.432,-0.702 0.972,-1.35 1.566,-1.89c1.134,-1.188 2.538,-2.106 4.05,-2.7c0.756,-0.324 1.512,-0.54 2.322,-0.648c0.81,-0.162 1.566,-0.216 2.376,-0.216c0.756,0 1.566,0.108 2.322,0.216c0.756,0.162 1.512,0.378 2.16,0.648c2.808,1.08 4.968,3.294 6.048,6.048c0.54,1.35 0.81,2.862 0.648,4.428c0,0.756 -0.162,1.512 -0.432,2.214c-0.216,0.702 -0.594,1.404 -1.026,1.998c-0.486,0.648 -1.08,1.188 -1.674,1.674c-0.648,0.432 -1.404,0.81 -2.16,1.08c-1.512,0.486 -3.24,0.432 -4.752,-0.108c-1.458,-0.54 -2.754,-1.62 -3.51,-3.024c-0.81,-1.35 -1.026,-3.024 -0.648,-4.59l-1.08,-0.216c-0.432,1.782 -0.162,3.726 0.756,5.346c0.864,1.62 2.376,2.916 4.158,3.51c1.728,0.594 3.618,0.594 5.4,0.162c0.864,-0.216 1.728,-0.54 2.538,-0.972c0.81,-0.486 1.566,-1.026 2.214,-1.728c0.702,-0.648 1.242,-1.458 1.728,-2.268c0.216,-0.432 0.432,-0.864 0.594,-1.35c0.162,-0.432 0.27,-0.918 0.378,-1.35c0.216,-0.972 0.324,-1.944 0.27,-2.916zm-51.948,38.016l-2.106,0l0,14.256l5.832,0l0,-10.476c0,-2.106 -1.674,-3.78 -3.726,-3.78z" id="path78213"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#8c94a9" fill="#8c94a9" stroke-miterlimit="2" stroke-width="0" d="m598.00805,133.72192l-18.576,0l0,-36.666l-10.692,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,32.67l24.408,0l0,-1.08z" id="path78215"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#98a0b2" fill="#98a0b2" stroke-miterlimit="2" stroke-width="0" d="m627.41197,97.05592l0,23.598c0,7.344 -6.534,13.284 -12.69001,13.284c-6.156,0 -9.66599,-5.94 -9.66599,-13.284l0,-23.598l-10.692,0l0,0.27c2.69999,0 4.85999,2.16 4.85999,4.806l0,18.522c0,8.046 6.534,14.58 14.63401,14.58c8.09999,0 14.63399,-6.534 14.63399,-14.58l0,-23.598l-1.07999,0z" id="path78217"/>
|
||||
<path transform="translate(-353.512 -351.983) translate(0 280.783)" stroke="#a4abbb" fill="#a4abbb" stroke-miterlimit="2" stroke-width="0" d="m664.49391,130.58992l-11.772,-18.414l11.88,-15.12l-1.08,0l-11.34,14.364l-7.074,-11.124c-1.35,-2.052 -3.51,-3.24 -5.94,-3.24l-6.102,0l0,0.27c2.7,0 4.914,2.16 6.588,4.806l8.91,13.878l-14.796,18.792l1.134,0l14.148,-17.982l9.45,14.742c1.35,2.052 3.51,3.24 5.94,3.24l6.048,0l0,-0.27c-2.376,0 -4.374,-1.674 -5.994,-3.942z" id="path78219"/>
|
||||
</g>
|
||||
<image width="0" height="0" y="-351.98328" x="-353.51215" id="icon"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
33
console-ui/src/assets/logo3.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<svg y="588.165" x="922" version="1.1" width="488" height="49" viewBox="0 0 488 49" id="svg164351" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata164357">image/svg+xml</metadata>
|
||||
|
||||
<linearGradient id="3d_gradient2-logo-b69ed5b7-9e72-4003-be77-c6c49a364658" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop164332"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop164334"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="3d_gradient3-logo-b69ed5b7-9e72-4003-be77-c6c49a364658" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad" gradientTransform="rotate(-30)">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop164337"/>
|
||||
<stop offset="50%" stop-color="#cccccc" id="stop164339"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop164341"/>
|
||||
</linearGradient>
|
||||
<g id="logo-group">
|
||||
<g id="logo-center">
|
||||
<image width="0" height="0" y="-359.3645" x="-267.7655" id="icon_container"/>
|
||||
<g text-anchor="middle" font-family="'Nunito Sans'" font-size="32px" font-weight="300" font-style="oblique" transform="translate(0 0)" id="slogan"/>
|
||||
<g text-anchor="middle" font-family="'Meedori Sans'" font-size="72px" font-weight="700" font-style="normal" transform="translate(0 0)" id="title">
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#5e636e" fill="#5e636e" stroke-miterlimit="2" stroke-width="0" d="m307.79824,54.932l9.10727,0l-24.57,49.14l-24.57,-49.14l9.95904,0l14.61096,30.99096l15.46273,-30.99096z" id="path164360"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#656a74" fill="#656a74" stroke-miterlimit="2" stroke-width="0" d="m362.42759,54.932l0,30.92544q0,0.6552 -0.13104,2.2932q-0.06552,1.57248 -0.58968,3.6036q-0.52416,2.03112 -1.70351,4.2588q-1.11385,2.16216 -3.27601,3.99672q-2.09663,1.76904 -5.37264,2.9484q-3.21048,1.11384 -7.99344,1.11384q-4.52088,0 -7.66583,-1.11384q-3.14496,-1.17936 -5.17609,-2.9484q-2.03111,-1.83456 -3.14495,-3.99672q-1.04833,-2.22768 -1.57248,-4.2588q-0.45865,-2.03112 -0.58969,-3.6036q-0.06552,-1.638 -0.06552,-2.2932l0,-30.92544l8.19,0l0,30.92544q0,0.72072 0.13104,2.48976q0.19656,1.76904 1.11384,3.66912q0.91729,1.83456 2.9484,3.276q2.09665,1.44144 5.83128,1.44144q4.06224,0 6.2244,-1.44144q2.22769,-1.44144 3.21048,-3.276q1.04832,-1.90008 1.17936,-3.66912q0.19656,-1.76904 0.19656,-2.48976l0,-30.92544l8.25552,0z" id="path164362"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#6c707b" fill="#6c707b" stroke-miterlimit="2" stroke-width="0" d="m408.65397,63.122l-24.63552,0l0,12.25224l20.96641,0l0,8.19l-20.96641,0l0,12.31776l24.63552,0l0,8.19l-32.82552,0l0,-49.14l32.82552,0l0,8.19z" id="path164364"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#727781" fill="#727781" stroke-miterlimit="2" stroke-width="0" d="m458.21678,63.122l-16.38,0l0,40.95l-8.19,0l0,-40.95l-16.38,0l0,-8.19l40.95,0l0,8.19z" id="path164366"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#797d88" fill="#797d88" stroke-miterlimit="2" stroke-width="0" d="m468.09393,54.932l8.12448,0l0,49.14l-8.12448,0l0,-49.14z" id="path164368"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#80848e" fill="#80848e" stroke-miterlimit="2" stroke-width="0" d="m498.0386,84.0884l0,19.9836l-8.19,0l0,-49.14l32.76,0l0,8.19l-24.57,0l0,12.71088l21.88368,0l0,8.25552l-21.88368,0z" id="path164370"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#878b94" fill="#878b94" stroke-miterlimit="2" stroke-width="0" d="m557.82253,81.33656l0,22.73544l-8.19,0l0,-22.73544l-20.04912,-26.40456l10.02457,0l14.61096,18.21456l13.62815,-18.21456l10.94185,0l-20.96641,26.40456z" id="path164372"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#8e919b" fill="#8e919b" stroke-miterlimit="2" stroke-width="0" d="m609.90891,76.68464l0,8.25552l-23.19407,0l0,-8.25552l23.19407,0z" id="path164374"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#9498a1" fill="#9498a1" stroke-miterlimit="2" stroke-width="0" d="m651.95222,95.882l0,8.19l-32.82552,0l0,-49.20552l8.12448,0l0.06552,41.01552l24.63552,0z" id="path164376"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#9b9ea8" fill="#9b9ea8" stroke-miterlimit="2" stroke-width="0" d="m698.34551,54.932l0,30.92544q0,0.6552 -0.13104,2.2932q-0.06552,1.57248 -0.58968,3.6036q-0.52416,2.03112 -1.70352,4.2588q-1.11384,2.16216 -3.276,3.99672q-2.09664,1.76904 -5.37264,2.9484q-3.21048,1.11384 -7.99344,1.11384q-4.52088,0 -7.66584,-1.11384q-3.14496,-1.17936 -5.17608,-2.9484q-2.03112,-1.83456 -3.14496,-3.99672q-1.04832,-2.22768 -1.57248,-4.2588q-0.45864,-2.03112 -0.58968,-3.6036q-0.06552,-1.638 -0.06552,-2.2932l0,-30.92544l8.19,0l0,30.92544q0,0.72072 0.13104,2.48976q0.19656,1.76904 1.11384,3.66912q0.91728,1.83456 2.9484,3.276q2.09664,1.44144 5.83128,1.44144q4.06224,0 6.2244,-1.44144q2.22768,-1.44144 3.21048,-3.276q1.04832,-1.90008 1.17936,-3.66912q0.19656,-1.76904 0.19656,-2.48976l0,-30.92544l8.25552,0z" id="path164378"/>
|
||||
<path transform="translate(-267.766 -359.365) translate(0 304.498)" stroke="#a2a5ae" fill="#a2a5ae" stroke-miterlimit="2" stroke-width="0" d="m707.02898,104.13752l19.06632,-24.50448l-19.06632,-24.70104l10.87632,0l13.62816,18.21456l13.7592,-18.21456l10.94184,0l-18.21456,24.70104l18.21456,24.50448l-10.94184,0l-13.7592,-18.14904l-13.62816,18.14904l-10.87632,0z" id="path164380"/>
|
||||
</g>
|
||||
<image width="0" height="0" y="-359.3645" x="-267.7655" id="icon"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
33
console-ui/src/assets/logo5.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<svg y="563.665" x="996.5" version="1.1" width="335" height="38" viewBox="0 0 335 38" id="svg194368" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata194374">image/svg+xml</metadata>
|
||||
|
||||
<linearGradient id="3d_gradient2-logo-682f3222-452d-46d2-bf30-c93cee4278d2" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop194349"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop194351"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="3d_gradient3-logo-682f3222-452d-46d2-bf30-c93cee4278d2" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad" gradientTransform="rotate(-30)">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop194354"/>
|
||||
<stop offset="50%" stop-color="#cccccc" id="stop194356"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop194358"/>
|
||||
</linearGradient>
|
||||
<g id="logo-group">
|
||||
<g id="logo-center">
|
||||
<image width="0" height="0" y="-364.91104" x="-344.33633" id="icon_container"/>
|
||||
<g text-anchor="middle" font-family="Orienta" font-size="32px" font-weight="400" font-style="normal" transform="translate(0 0)" id="slogan"/>
|
||||
<g text-anchor="middle" font-family="'Brandmark Didone 1'" font-size="72px" font-weight="normal" font-style="normal" transform="translate(0 0)" id="title">
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#3a456c" fill="#3a456c" stroke-miterlimit="2" stroke-width="0" d="m32.13001,-302.32904l-11.07,32.454l-9.342,-27.378c-1.08,-3.186 -3.834,-5.076 -7.128,-5.076l-4.59,0l0,0.27c2.538,0 3.996,1.89 4.914,4.32l11.34,33.588l3.942,0l13.014,-38.178l-1.08,0z" id="path194377"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#454f74" fill="#454f74" stroke-miterlimit="2" stroke-width="0" d="m68.34123,-302.32904l0,23.598c0,7.344 -6.534,13.284 -12.69001,13.284c-6.156,0 -9.66599,-5.94 -9.66599,-13.284l0,-23.598l-10.69201,0l0,0.27c2.70001,0 4.86001,2.16 4.86001,4.806l0,18.522c0,8.046 6.53399,14.58 14.634,14.58c8.1,0 14.634,-6.534 14.634,-14.58l0,-23.598l-1.08,0z" id="path194379"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#4f597c" fill="#4f597c" stroke-miterlimit="2" stroke-width="0" d="m85.11918,-301.24904l16.308,0l0,-1.08l-27,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,32.67l22.14,0l0,-1.08l-16.308,0l0,-21.276l15.012,0l0,-1.08l-15.012,0l0,-13.23z" id="path194381"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#5a6484" fill="#5a6484" stroke-miterlimit="2" stroke-width="0" d="m132.94632,-301.24904l0,-1.08l-29.376,0l0,1.08l11.772,0l0,36.666l5.832,0l0,-36.666l11.772,0z" id="path194383"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#646e8c" fill="#646e8c" stroke-miterlimit="2" stroke-width="0" d="m145.34183,-302.32904l-10.692,0l0,0.27c2.7,0 4.86001,2.16 4.86001,4.806l0,32.67l5.83199,0l0,-37.746z" id="path194385"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#6f7894" fill="#6f7894" stroke-miterlimit="2" stroke-width="0" d="m161.58402,-301.24904l16.308,0l0,-1.08l-27,0l0,0.27c2.7,0 4.86001,2.16 4.86001,4.806l0,32.67l5.83199,0l0,-22.302l14.256,0l0,-1.08l-14.256,0l0,-13.284z" id="path194387"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#7a829b" fill="#7a829b" stroke-miterlimit="2" stroke-width="0" d="m200.94833,-282.78104l12.47401,-19.548l-1.13401,0l-11.826,18.576l-8.856,-15.066c-1.296,-2.268 -3.564,-3.51 -6.156,-3.51l-6.15599,0l0,0.27c2.7,0 4.752,2.16 6.31799,4.806l9.45001,16.146l0,16.524l5.88599,0l0,-18.198z" id="path194389"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#848ca3" fill="#848ca3" stroke-miterlimit="2" stroke-width="0" d="m212.79459,-280.40504l18.57599,0l0,-1.89l-18.57599,0l0,1.89z" id="path194391"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#8f97ab" fill="#8f97ab" stroke-miterlimit="2" stroke-width="0" d="m262.8475,-265.66304l-18.576,0l0,-36.666l-10.69201,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,32.67l24.40801,0l0,-1.08z" id="path194393"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#99a1b3" fill="#99a1b3" stroke-miterlimit="2" stroke-width="0" d="m292.25141,-302.32904l0,23.598c0,7.344 -6.534,13.284 -12.69,13.284c-6.156,0 -9.666,-5.94 -9.666,-13.284l0,-23.598l-10.692,0l0,0.27c2.7,0 4.86,2.16 4.86,4.806l0,18.522c0,8.046 6.534,14.58 14.634,14.58c8.1,0 14.634,-6.534 14.634,-14.58l0,-23.598l-1.08,0z" id="path194395"/>
|
||||
<path transform="translate(1.13687e-13 0) translate(0 302.329)" stroke="#a4abbb" fill="#a4abbb" stroke-miterlimit="2" stroke-width="0" d="m329.33336,-268.79504l-11.77201,-18.414l11.88001,-15.12l-1.08001,0l-11.34,14.364l-7.074,-11.124c-1.34999,-2.052 -3.50999,-3.24 -5.94,-3.24l-6.10199,0l0,0.27c2.69999,0 4.91399,2.16 6.588,4.806l8.91,13.878l-14.79601,18.792l1.13401,0l14.148,-17.982l9.44999,14.742c1.35001,2.052 3.51001,3.24 5.94001,3.24l6.04799,0l0,-0.27c-2.376,0 -4.374,-1.674 -5.99399,-3.942z" id="path194397"/>
|
||||
</g>
|
||||
<image width="0" height="0" y="-364.91104" x="-344.33633" id="icon"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
33
console-ui/src/assets/logo_dark.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<svg y="551.165" x="960" version="1.1" width="412" height="67" viewBox="0 0 412 67" id="svg687764" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata687770">image/svg+xml</metadata>
|
||||
|
||||
<linearGradient id="3d_gradient2-logo-be9fcf93-76f3-4195-b816-3f382377cd48" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop687745"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop687747"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="3d_gradient3-logo-be9fcf93-76f3-4195-b816-3f382377cd48" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad" gradientTransform="rotate(-30)">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop687750"/>
|
||||
<stop offset="50%" stop-color="#cccccc" id="stop687752"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop687754"/>
|
||||
</linearGradient>
|
||||
<g id="logo-group">
|
||||
<g transform="translate(0 0)" id="logo-center">
|
||||
<image width="0" height="0" y="-350.55203" x="-306.10635" id="icon_container"/>
|
||||
<g text-anchor="middle" font-family="Raleway" font-size="32px" font-weight="600" font-style="normal" transform="translate(0 0)" id="slogan"/>
|
||||
<g text-anchor="middle" font-family="'Comfortaa Bold Alt1'" font-size="72px" font-weight="700" font-style="normal" transform="translate(0 0)" id="title">
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#ffffff" fill="#ffffff" stroke-miterlimit="2" stroke-width="0" d="m340.17676,71.96504c-0.3276,-0.45864 -0.78624,-0.85176 -1.3104,-1.11384c-0.45864,-0.19656 -0.9828,-0.3276 -1.50696,-0.3276c-0.58968,0 -1.11384,0.19656 -1.638,0.45864c-0.52416,0.26208 -0.85176,0.6552 -1.11384,1.17936l-11.26944,24.57l-11.40048,-24.57c-0.26208,-0.52416 -0.6552,-0.91728 -1.11384,-1.17936c-0.52416,-0.26208 -0.9828,-0.45864 -1.50696,-0.45864c-0.52416,0 -0.9828,0.13104 -1.37592,0.3276c-1.24488,0.6552 -1.83456,1.50696 -1.83456,2.68632c0,0.45864 0.06552,0.85176 0.26208,1.17936l13.89024,29.28744c0.39312,0.78624 0.78624,1.37592 1.3104,1.70352c0.45864,0.3276 1.04832,0.45864 1.83456,0.45864c1.3104,0 2.35872,-0.72072 3.01392,-2.16216l13.89024,-29.28744c0.19656,-0.39312 0.3276,-0.85176 0.3276,-1.24488c0,-0.52416 -0.19656,-1.04832 -0.45864,-1.50696z" id="path687773"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#fcfcfc" fill="#fcfcfc" stroke-miterlimit="2" stroke-width="0" d="m386.5027,102.89048l0,-29.22192c0,-0.9828 -0.3276,-1.76904 -0.91728,-2.42424c-0.6552,-0.58968 -1.44144,-0.91728 -2.42424,-0.91728c-0.9828,0 -1.76904,0.3276 -2.42424,0.91728c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.42424l0,18.47664c0,1.638 -0.45864,3.01392 -1.3104,4.2588c-0.85176,1.3104 -2.03112,2.2932 -3.53808,3.01392c-1.50696,0.78624 -3.21048,1.11384 -4.97952,1.11384c-3.21048,0 -5.70024,-0.85176 -7.60032,-2.68632c-1.90008,-1.83456 -2.81736,-4.52088 -2.81736,-8.05896l0,-16.11792c0,-0.91728 -0.3276,-1.70352 -0.9828,-2.35872c-0.6552,-0.6552 -1.44144,-0.9828 -2.35872,-0.9828c-0.9828,0 -1.76904,0.3276 -2.42424,0.9828c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,16.11792c0,3.6036 0.6552,6.61752 2.03112,9.10728c1.3104,2.48976 3.21048,4.45536 5.63472,5.70024c2.2932,1.3104 4.78296,1.9656 7.5348,2.03112c0.13104,0 5.17608,0 15.33168,0c0.85176,0 1.57248,-0.3276 2.16216,-0.91728c0.58968,-0.58968 0.91728,-1.3104 0.91728,-2.22768l0,-0.58968z" id="path687775"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#f8f8f8" fill="#f8f8f8" stroke-miterlimit="2" stroke-width="0" d="m435.96133,89.852c0.52416,-0.52416 0.85176,-1.24488 0.85176,-2.09664c0,-3.40704 -0.6552,-6.48648 -1.9656,-9.1728c-1.3104,-2.6208 -3.21048,-4.71744 -5.63472,-6.2244c-2.48976,-1.44144 -5.37264,-2.22768 -8.71416,-2.22768c-3.40704,0 -6.48648,0.78624 -9.1728,2.35872c-2.68632,1.57248 -4.78296,3.73464 -6.28992,6.48648c-1.50696,2.75184 -2.22768,5.8968 -2.22768,9.36936c0,3.53808 0.78624,6.61752 2.35872,9.36936c1.57248,2.75184 3.80016,4.914 6.68304,6.48648c2.81736,1.57248 6.02784,2.2932 9.63144,2.2932c1.9656,0 4.06224,-0.3276 6.28992,-1.11384c2.22768,-0.72072 4.06224,-1.70352 5.5692,-2.88288c0.6552,-0.52416 1.04832,-1.17936 1.04832,-1.9656c0,-0.78624 -0.39312,-1.57248 -1.17936,-2.22768c-0.52416,-0.39312 -1.17936,-0.6552 -1.9656,-0.6552c-0.85176,0 -1.57248,0.26208 -2.16216,0.72072c-0.91728,0.72072 -2.09664,1.3104 -3.53808,1.76904c-1.44144,0.52416 -2.75184,0.72072 -4.06224,0.72072c-3.34152,0 -6.15888,-0.91728 -8.45208,-2.81736c-2.2932,-1.83456 -3.66912,-4.32432 -4.12776,-7.40376l24.8976,0c0.85176,0 1.57248,-0.26208 2.16216,-0.78624zm-23.2596,-11.466c1.9656,-1.70352 4.5864,-2.6208 7.79688,-2.6208c2.88288,0 5.17608,0.91728 7.01064,2.6208c1.76904,1.76904 2.88288,4.12776 3.276,7.01064l-21.81816,0c0.52416,-2.88288 1.76904,-5.2416 3.73464,-7.01064z" id="path687777"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#f5f5f5" fill="#f5f5f5" stroke-miterlimit="2" stroke-width="0" d="m453.21376,71.70296l0,5.63472l0,16.18344c0,2.42424 0.45864,4.5864 1.50696,6.48648c0.9828,1.9656 2.35872,3.47256 4.12776,4.5864c1.76904,1.11384 3.73464,1.638 5.8968,1.638l1.17936,0c1.11384,0 2.03112,-0.26208 2.75184,-0.91728c0.72072,-0.58968 1.11384,-1.37592 1.11384,-2.35872c0,-0.91728 -0.3276,-1.70352 -0.85176,-2.35872c-0.52416,-0.58968 -1.17936,-0.91728 -1.9656,-0.91728l-2.22768,0c-1.44144,0 -2.6208,-0.58968 -3.53808,-1.76904c-0.9828,-1.17936 -1.44144,-2.6208 -1.44144,-4.38984l0,-16.18344l5.5692,0c0.91728,0 1.638,-0.26208 2.22768,-0.78624c0.52416,-0.52416 0.85176,-1.17936 0.85176,-1.9656c0,-0.85176 -0.3276,-1.57248 -0.85176,-2.09664c-0.58968,-0.52416 -1.3104,-0.78624 -2.22768,-0.78624l-5.5692,0l0,-9.43488c0,-0.91728 -0.3276,-1.70352 -0.91728,-2.35872c-0.6552,-0.58968 -1.44144,-0.91728 -2.35872,-0.91728c-0.9828,0 -1.76904,0.3276 -2.35872,0.91728c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,9.43488z" id="path687779"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#f2f2f2" fill="#f2f2f2" stroke-miterlimit="2" stroke-width="0" d="m485.88287,71.30984c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.42424l0,29.1564c0,0.9828 0.26208,1.76904 0.91728,2.42424c0.6552,0.6552 1.44144,0.91728 2.42424,0.91728c0.9828,0 1.76904,-0.26208 2.42424,-0.91728c0.58968,-0.6552 0.91728,-1.44144 0.91728,-2.42424l0,-29.1564c0,-0.9828 -0.3276,-1.76904 -0.91728,-2.42424c-0.6552,-0.58968 -1.44144,-0.91728 -2.42424,-0.91728c-0.9828,0 -1.76904,0.3276 -2.42424,0.91728z" id="path687781"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#efefef" fill="#efefef" stroke-miterlimit="2" stroke-width="0" d="m511.17077,71.70296l0,5.63472l0,25.5528c0,1.04832 0.26208,1.83456 0.91728,2.42424c0.6552,0.6552 1.37592,0.91728 2.2932,0.91728c1.04832,0 1.90008,-0.26208 2.55528,-0.91728c0.58968,-0.58968 0.91728,-1.37592 0.91728,-2.42424l0,-25.5528l6.68304,0c0.91728,0 1.638,-0.26208 2.22768,-0.78624c0.52416,-0.52416 0.85176,-1.17936 0.85176,-1.9656c0,-0.85176 -0.3276,-1.57248 -0.85176,-2.09664c-0.58968,-0.52416 -1.3104,-0.78624 -2.22768,-0.78624l-6.68304,0l0,-1.76904c0,-2.6208 0.72072,-4.78296 2.22768,-6.42096c1.44144,-1.57248 3.40704,-2.42424 5.8968,-2.42424c0.91728,0 1.70352,-0.26208 2.35872,-0.85176c0.6552,-0.52416 0.9828,-1.24488 0.9828,-2.16216c0,-0.85176 -0.3276,-1.57248 -0.9828,-2.16216c-0.6552,-0.52416 -1.44144,-0.85176 -2.35872,-0.85176c-2.9484,0 -5.50368,0.6552 -7.73136,1.9656c-2.22768,1.3104 -3.99672,3.07944 -5.2416,5.43816c-1.24488,2.35872 -1.83456,5.04504 -1.83456,8.12448l0,1.11384z" id="path687783"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#ebebeb" fill="#ebebeb" stroke-miterlimit="2" stroke-width="0" d="m570.36214,73.27544c0,-1.17936 -0.72072,-2.03112 -2.03112,-2.55528c-0.52416,-0.19656 -1.04832,-0.3276 -1.57248,-0.3276c-1.17936,0 -2.03112,0.6552 -2.55528,1.90008l-10.54872,23.78376l-11.99016,-23.84928c-0.6552,-1.17936 -1.57248,-1.83456 -2.75184,-1.83456c-0.52416,0 -0.91728,0.13104 -1.3104,0.26208c-0.58968,0.26208 -1.04832,0.6552 -1.37592,1.11384c-0.39312,0.52416 -0.52416,1.04832 -0.52416,1.57248c0,0.52416 0.06552,0.9828 0.3276,1.37592l14.742,27.97704l-6.552,14.742c-0.26208,0.52416 -0.39312,1.04832 -0.39312,1.57248c0,1.17936 0.6552,2.03112 1.9656,2.55528c0.58968,0.26208 1.11384,0.39312 1.57248,0.39312c1.17936,0 2.03112,-0.6552 2.55528,-2.03112l20.04912,-45.07776c0.26208,-0.58968 0.39312,-1.11384 0.39312,-1.57248z" id="path687785"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#e8e8e8" fill="#e8e8e8" stroke-miterlimit="2" stroke-width="0" d="m599.40619,85.98632c-0.6552,-0.6552 -1.44144,-0.9828 -2.35872,-0.9828l-14.61096,0c-0.9828,0 -1.76904,0.3276 -2.42424,0.9828c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872c0,0.9828 0.26208,1.76904 0.91728,2.35872c0.6552,0.6552 1.44144,0.91728 2.42424,0.91728l14.61096,0c0.91728,0 1.70352,-0.26208 2.35872,-0.91728c0.58968,-0.58968 0.91728,-1.37592 0.91728,-2.35872c0,-0.91728 -0.3276,-1.70352 -0.91728,-2.35872z" id="path687787"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#e5e5e5" fill="#e5e5e5" stroke-miterlimit="2" stroke-width="0" d="m614.20374,55.97816c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,35.77392c0,2.35872 0.39312,4.45536 1.24488,6.28992c0.78624,1.83456 1.9656,3.276 3.47256,4.32432c1.50696,1.04832 3.21048,1.50696 5.11056,1.50696l0.13104,0c1.3104,0 2.35872,-0.26208 3.21048,-0.91728c0.78624,-0.58968 1.24488,-1.37592 1.24488,-2.35872c0,-0.91728 -0.3276,-1.70352 -0.85176,-2.35872c-0.52416,-0.58968 -1.24488,-0.91728 -2.09664,-0.91728l-1.638,0c-0.9828,0 -1.76904,-0.52416 -2.35872,-1.57248c-0.6552,-1.04832 -0.91728,-2.35872 -0.91728,-3.99672l0,-35.77392c0,-0.91728 -0.3276,-1.70352 -0.91728,-2.35872c-0.6552,-0.58968 -1.44144,-0.91728 -2.35872,-0.91728c-0.9828,0 -1.76904,0.3276 -2.35872,0.91728z" id="path687789"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#e1e1e1" fill="#e1e1e1" stroke-miterlimit="2" stroke-width="0" d="m673.56508,102.89048l0,-29.22192c0,-0.9828 -0.3276,-1.76904 -0.91728,-2.42424c-0.6552,-0.58968 -1.44144,-0.91728 -2.42424,-0.91728c-0.9828,0 -1.76904,0.3276 -2.42424,0.91728c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.42424l0,18.47664c0,1.638 -0.45864,3.01392 -1.3104,4.2588c-0.85176,1.3104 -2.03112,2.2932 -3.53808,3.01392c-1.50696,0.78624 -3.21048,1.11384 -4.97952,1.11384c-3.21048,0 -5.70024,-0.85176 -7.60032,-2.68632c-1.90008,-1.83456 -2.81736,-4.52088 -2.81736,-8.05896l0,-16.11792c0,-0.91728 -0.3276,-1.70352 -0.9828,-2.35872c-0.6552,-0.6552 -1.44144,-0.9828 -2.35872,-0.9828c-0.9828,0 -1.76904,0.3276 -2.42424,0.9828c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,16.11792c0,3.6036 0.6552,6.61752 2.03112,9.10728c1.3104,2.48976 3.21048,4.45536 5.63472,5.70024c2.2932,1.3104 4.78296,1.9656 7.5348,2.03112c0.13104,0 5.17608,0 15.33168,0c0.85176,0 1.57248,-0.3276 2.16216,-0.91728c0.58968,-0.58968 0.91728,-1.3104 0.91728,-2.22768l0,-0.58968z" id="path687791"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#dedede" fill="#dedede" stroke-miterlimit="2" stroke-width="0" d="m717.89364,103.48016c0,-0.85176 -0.3276,-1.638 -0.91728,-2.2932l-10.41768,-12.4488l9.89352,-12.90744c0.58968,-0.78624 0.91728,-1.638 0.91728,-2.6208c0,-0.78624 -0.26208,-1.44144 -0.78624,-1.9656c-0.52416,-0.52416 -1.17936,-0.85176 -2.03112,-0.85176c-1.04832,0 -1.90008,0.39312 -2.42424,1.11384l-9.63144,12.84192l-10.74528,-12.84192c-0.6552,-0.72072 -1.44144,-1.11384 -2.48976,-1.11384c-0.91728,0 -1.638,0.26208 -2.16216,0.78624c-0.52416,0.52416 -0.72072,1.17936 -0.72072,1.90008c0,0.91728 0.3276,1.70352 0.9828,2.48976l10.8108,12.7764l-10.1556,12.71088c-0.6552,0.78624 -0.91728,1.57248 -0.91728,2.42424c0,0.78624 0.19656,1.44144 0.72072,1.9656c0.52416,0.52416 1.17936,0.78624 2.09664,0.78624c0.91728,0 1.70352,-0.3276 2.35872,-1.04832l9.89352,-12.4488l10.41768,12.4488c0.52416,0.72072 1.3104,1.04832 2.35872,1.04832c0.85176,0 1.57248,-0.26208 2.09664,-0.78624c0.52416,-0.52416 0.85176,-1.17936 0.85176,-1.9656z" id="path687793"/>
|
||||
</g>
|
||||
<image width="0" height="0" y="-350.55203" x="-306.10635" id="icon"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
33
console-ui/src/assets/logo_light.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<svg y="551.165" x="960" version="1.1" width="412" height="67" viewBox="0 0 412 67" id="svg4578" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata4584">image/svg+xml</metadata>
|
||||
|
||||
<linearGradient id="3d_gradient2-logo-be9fcf93-76f3-4195-b816-3f382377cd48" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop4559"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop4561"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="3d_gradient3-logo-be9fcf93-76f3-4195-b816-3f382377cd48" x1="30%" y1="120%" x2="-10%" y2="30%" spreadMethod="pad" gradientTransform="rotate(-30)">
|
||||
<stop offset="0%" stop-color="#ffffff" id="stop4564"/>
|
||||
<stop offset="50%" stop-color="#cccccc" id="stop4566"/>
|
||||
<stop offset="100%" stop-color="#000000" id="stop4568"/>
|
||||
</linearGradient>
|
||||
<g id="logo-group">
|
||||
<g id="logo-center">
|
||||
<image width="0" height="0" y="-350.55203" x="-306.10635" id="icon_container"/>
|
||||
<g text-anchor="middle" font-family="Raleway" font-size="32px" font-weight="600" font-style="normal" transform="translate(0 0)" id="slogan"/>
|
||||
<g text-anchor="middle" font-family="'Comfortaa Bold Alt1'" font-size="72px" font-weight="700" font-style="normal" transform="translate(0 0)" id="title">
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#5e636e" fill="#5e636e" stroke-miterlimit="2" stroke-width="0" d="m340.17676,71.96504c-0.3276,-0.45864 -0.78624,-0.85176 -1.3104,-1.11384c-0.45864,-0.19656 -0.9828,-0.3276 -1.50696,-0.3276c-0.58968,0 -1.11384,0.19656 -1.638,0.45864c-0.52416,0.26208 -0.85176,0.6552 -1.11384,1.17936l-11.26944,24.57l-11.40048,-24.57c-0.26208,-0.52416 -0.6552,-0.91728 -1.11384,-1.17936c-0.52416,-0.26208 -0.9828,-0.45864 -1.50696,-0.45864c-0.52416,0 -0.9828,0.13104 -1.37592,0.3276c-1.24488,0.6552 -1.83456,1.50696 -1.83456,2.68632c0,0.45864 0.06552,0.85176 0.26208,1.17936l13.89024,29.28744c0.39312,0.78624 0.78624,1.37592 1.3104,1.70352c0.45864,0.3276 1.04832,0.45864 1.83456,0.45864c1.3104,0 2.35872,-0.72072 3.01392,-2.16216l13.89024,-29.28744c0.19656,-0.39312 0.3276,-0.85176 0.3276,-1.24488c0,-0.52416 -0.19656,-1.04832 -0.45864,-1.50696z" id="path4587"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#656a74" fill="#656a74" stroke-miterlimit="2" stroke-width="0" d="m386.5027,102.89048l0,-29.22192c0,-0.9828 -0.3276,-1.76904 -0.91728,-2.42424c-0.6552,-0.58968 -1.44144,-0.91728 -2.42424,-0.91728c-0.9828,0 -1.76904,0.3276 -2.42424,0.91728c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.42424l0,18.47664c0,1.638 -0.45864,3.01392 -1.3104,4.2588c-0.85176,1.3104 -2.03112,2.2932 -3.53808,3.01392c-1.50696,0.78624 -3.21048,1.11384 -4.97952,1.11384c-3.21048,0 -5.70024,-0.85176 -7.60032,-2.68632c-1.90008,-1.83456 -2.81736,-4.52088 -2.81736,-8.05896l0,-16.11792c0,-0.91728 -0.3276,-1.70352 -0.9828,-2.35872c-0.6552,-0.6552 -1.44144,-0.9828 -2.35872,-0.9828c-0.9828,0 -1.76904,0.3276 -2.42424,0.9828c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,16.11792c0,3.6036 0.6552,6.61752 2.03112,9.10728c1.3104,2.48976 3.21048,4.45536 5.63472,5.70024c2.2932,1.3104 4.78296,1.9656 7.5348,2.03112c0.13104,0 5.17608,0 15.33168,0c0.85176,0 1.57248,-0.3276 2.16216,-0.91728c0.58968,-0.58968 0.91728,-1.3104 0.91728,-2.22768l0,-0.58968z" id="path4589"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#6c707b" fill="#6c707b" stroke-miterlimit="2" stroke-width="0" d="m435.96133,89.852c0.52416,-0.52416 0.85176,-1.24488 0.85176,-2.09664c0,-3.40704 -0.6552,-6.48648 -1.9656,-9.1728c-1.3104,-2.6208 -3.21048,-4.71744 -5.63472,-6.2244c-2.48976,-1.44144 -5.37264,-2.22768 -8.71416,-2.22768c-3.40704,0 -6.48648,0.78624 -9.1728,2.35872c-2.68632,1.57248 -4.78296,3.73464 -6.28992,6.48648c-1.50696,2.75184 -2.22768,5.8968 -2.22768,9.36936c0,3.53808 0.78624,6.61752 2.35872,9.36936c1.57248,2.75184 3.80016,4.914 6.68304,6.48648c2.81736,1.57248 6.02784,2.2932 9.63144,2.2932c1.9656,0 4.06224,-0.3276 6.28992,-1.11384c2.22768,-0.72072 4.06224,-1.70352 5.5692,-2.88288c0.6552,-0.52416 1.04832,-1.17936 1.04832,-1.9656c0,-0.78624 -0.39312,-1.57248 -1.17936,-2.22768c-0.52416,-0.39312 -1.17936,-0.6552 -1.9656,-0.6552c-0.85176,0 -1.57248,0.26208 -2.16216,0.72072c-0.91728,0.72072 -2.09664,1.3104 -3.53808,1.76904c-1.44144,0.52416 -2.75184,0.72072 -4.06224,0.72072c-3.34152,0 -6.15888,-0.91728 -8.45208,-2.81736c-2.2932,-1.83456 -3.66912,-4.32432 -4.12776,-7.40376l24.8976,0c0.85176,0 1.57248,-0.26208 2.16216,-0.78624zm-23.2596,-11.466c1.9656,-1.70352 4.5864,-2.6208 7.79688,-2.6208c2.88288,0 5.17608,0.91728 7.01064,2.6208c1.76904,1.76904 2.88288,4.12776 3.276,7.01064l-21.81816,0c0.52416,-2.88288 1.76904,-5.2416 3.73464,-7.01064z" id="path4591"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#727781" fill="#727781" stroke-miterlimit="2" stroke-width="0" d="m453.21376,71.70296l0,5.63472l0,16.18344c0,2.42424 0.45864,4.5864 1.50696,6.48648c0.9828,1.9656 2.35872,3.47256 4.12776,4.5864c1.76904,1.11384 3.73464,1.638 5.8968,1.638l1.17936,0c1.11384,0 2.03112,-0.26208 2.75184,-0.91728c0.72072,-0.58968 1.11384,-1.37592 1.11384,-2.35872c0,-0.91728 -0.3276,-1.70352 -0.85176,-2.35872c-0.52416,-0.58968 -1.17936,-0.91728 -1.9656,-0.91728l-2.22768,0c-1.44144,0 -2.6208,-0.58968 -3.53808,-1.76904c-0.9828,-1.17936 -1.44144,-2.6208 -1.44144,-4.38984l0,-16.18344l5.5692,0c0.91728,0 1.638,-0.26208 2.22768,-0.78624c0.52416,-0.52416 0.85176,-1.17936 0.85176,-1.9656c0,-0.85176 -0.3276,-1.57248 -0.85176,-2.09664c-0.58968,-0.52416 -1.3104,-0.78624 -2.22768,-0.78624l-5.5692,0l0,-9.43488c0,-0.91728 -0.3276,-1.70352 -0.91728,-2.35872c-0.6552,-0.58968 -1.44144,-0.91728 -2.35872,-0.91728c-0.9828,0 -1.76904,0.3276 -2.35872,0.91728c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,9.43488z" id="path4593"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#797d88" fill="#797d88" stroke-miterlimit="2" stroke-width="0" d="m485.88287,71.30984c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.42424l0,29.1564c0,0.9828 0.26208,1.76904 0.91728,2.42424c0.6552,0.6552 1.44144,0.91728 2.42424,0.91728c0.9828,0 1.76904,-0.26208 2.42424,-0.91728c0.58968,-0.6552 0.91728,-1.44144 0.91728,-2.42424l0,-29.1564c0,-0.9828 -0.3276,-1.76904 -0.91728,-2.42424c-0.6552,-0.58968 -1.44144,-0.91728 -2.42424,-0.91728c-0.9828,0 -1.76904,0.3276 -2.42424,0.91728z" id="path4595"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#80848e" fill="#80848e" stroke-miterlimit="2" stroke-width="0" d="m511.17077,71.70296l0,5.63472l0,25.5528c0,1.04832 0.26208,1.83456 0.91728,2.42424c0.6552,0.6552 1.37592,0.91728 2.2932,0.91728c1.04832,0 1.90008,-0.26208 2.55528,-0.91728c0.58968,-0.58968 0.91728,-1.37592 0.91728,-2.42424l0,-25.5528l6.68304,0c0.91728,0 1.638,-0.26208 2.22768,-0.78624c0.52416,-0.52416 0.85176,-1.17936 0.85176,-1.9656c0,-0.85176 -0.3276,-1.57248 -0.85176,-2.09664c-0.58968,-0.52416 -1.3104,-0.78624 -2.22768,-0.78624l-6.68304,0l0,-1.76904c0,-2.6208 0.72072,-4.78296 2.22768,-6.42096c1.44144,-1.57248 3.40704,-2.42424 5.8968,-2.42424c0.91728,0 1.70352,-0.26208 2.35872,-0.85176c0.6552,-0.52416 0.9828,-1.24488 0.9828,-2.16216c0,-0.85176 -0.3276,-1.57248 -0.9828,-2.16216c-0.6552,-0.52416 -1.44144,-0.85176 -2.35872,-0.85176c-2.9484,0 -5.50368,0.6552 -7.73136,1.9656c-2.22768,1.3104 -3.99672,3.07944 -5.2416,5.43816c-1.24488,2.35872 -1.83456,5.04504 -1.83456,8.12448l0,1.11384z" id="path4597"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#878b94" fill="#878b94" stroke-miterlimit="2" stroke-width="0" d="m570.36214,73.27544c0,-1.17936 -0.72072,-2.03112 -2.03112,-2.55528c-0.52416,-0.19656 -1.04832,-0.3276 -1.57248,-0.3276c-1.17936,0 -2.03112,0.6552 -2.55528,1.90008l-10.54872,23.78376l-11.99016,-23.84928c-0.6552,-1.17936 -1.57248,-1.83456 -2.75184,-1.83456c-0.52416,0 -0.91728,0.13104 -1.3104,0.26208c-0.58968,0.26208 -1.04832,0.6552 -1.37592,1.11384c-0.39312,0.52416 -0.52416,1.04832 -0.52416,1.57248c0,0.52416 0.06552,0.9828 0.3276,1.37592l14.742,27.97704l-6.552,14.742c-0.26208,0.52416 -0.39312,1.04832 -0.39312,1.57248c0,1.17936 0.6552,2.03112 1.9656,2.55528c0.58968,0.26208 1.11384,0.39312 1.57248,0.39312c1.17936,0 2.03112,-0.6552 2.55528,-2.03112l20.04912,-45.07776c0.26208,-0.58968 0.39312,-1.11384 0.39312,-1.57248z" id="path4599"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#8e919b" fill="#8e919b" stroke-miterlimit="2" stroke-width="0" d="m599.40619,85.98632c-0.6552,-0.6552 -1.44144,-0.9828 -2.35872,-0.9828l-14.61096,0c-0.9828,0 -1.76904,0.3276 -2.42424,0.9828c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872c0,0.9828 0.26208,1.76904 0.91728,2.35872c0.6552,0.6552 1.44144,0.91728 2.42424,0.91728l14.61096,0c0.91728,0 1.70352,-0.26208 2.35872,-0.91728c0.58968,-0.58968 0.91728,-1.37592 0.91728,-2.35872c0,-0.91728 -0.3276,-1.70352 -0.91728,-2.35872z" id="path4601"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#9498a1" fill="#9498a1" stroke-miterlimit="2" stroke-width="0" d="m614.20374,55.97816c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,35.77392c0,2.35872 0.39312,4.45536 1.24488,6.28992c0.78624,1.83456 1.9656,3.276 3.47256,4.32432c1.50696,1.04832 3.21048,1.50696 5.11056,1.50696l0.13104,0c1.3104,0 2.35872,-0.26208 3.21048,-0.91728c0.78624,-0.58968 1.24488,-1.37592 1.24488,-2.35872c0,-0.91728 -0.3276,-1.70352 -0.85176,-2.35872c-0.52416,-0.58968 -1.24488,-0.91728 -2.09664,-0.91728l-1.638,0c-0.9828,0 -1.76904,-0.52416 -2.35872,-1.57248c-0.6552,-1.04832 -0.91728,-2.35872 -0.91728,-3.99672l0,-35.77392c0,-0.91728 -0.3276,-1.70352 -0.91728,-2.35872c-0.6552,-0.58968 -1.44144,-0.91728 -2.35872,-0.91728c-0.9828,0 -1.76904,0.3276 -2.35872,0.91728z" id="path4603"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#9b9ea8" fill="#9b9ea8" stroke-miterlimit="2" stroke-width="0" d="m673.56508,102.89048l0,-29.22192c0,-0.9828 -0.3276,-1.76904 -0.91728,-2.42424c-0.6552,-0.58968 -1.44144,-0.91728 -2.42424,-0.91728c-0.9828,0 -1.76904,0.3276 -2.42424,0.91728c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.42424l0,18.47664c0,1.638 -0.45864,3.01392 -1.3104,4.2588c-0.85176,1.3104 -2.03112,2.2932 -3.53808,3.01392c-1.50696,0.78624 -3.21048,1.11384 -4.97952,1.11384c-3.21048,0 -5.70024,-0.85176 -7.60032,-2.68632c-1.90008,-1.83456 -2.81736,-4.52088 -2.81736,-8.05896l0,-16.11792c0,-0.91728 -0.3276,-1.70352 -0.9828,-2.35872c-0.6552,-0.6552 -1.44144,-0.9828 -2.35872,-0.9828c-0.9828,0 -1.76904,0.3276 -2.42424,0.9828c-0.6552,0.6552 -0.91728,1.44144 -0.91728,2.35872l0,16.11792c0,3.6036 0.6552,6.61752 2.03112,9.10728c1.3104,2.48976 3.21048,4.45536 5.63472,5.70024c2.2932,1.3104 4.78296,1.9656 7.5348,2.03112c0.13104,0 5.17608,0 15.33168,0c0.85176,0 1.57248,-0.3276 2.16216,-0.91728c0.58968,-0.58968 0.91728,-1.3104 0.91728,-2.22768l0,-0.58968z" id="path4605"/>
|
||||
<path transform="translate(-306.106 -350.552) translate(0 295.491)" stroke="#a2a5ae" fill="#a2a5ae" stroke-miterlimit="2" stroke-width="0" d="m717.89364,103.48016c0,-0.85176 -0.3276,-1.638 -0.91728,-2.2932l-10.41768,-12.4488l9.89352,-12.90744c0.58968,-0.78624 0.91728,-1.638 0.91728,-2.6208c0,-0.78624 -0.26208,-1.44144 -0.78624,-1.9656c-0.52416,-0.52416 -1.17936,-0.85176 -2.03112,-0.85176c-1.04832,0 -1.90008,0.39312 -2.42424,1.11384l-9.63144,12.84192l-10.74528,-12.84192c-0.6552,-0.72072 -1.44144,-1.11384 -2.48976,-1.11384c-0.91728,0 -1.638,0.26208 -2.16216,0.78624c-0.52416,0.52416 -0.72072,1.17936 -0.72072,1.90008c0,0.91728 0.3276,1.70352 0.9828,2.48976l10.8108,12.7764l-10.1556,12.71088c-0.6552,0.78624 -0.91728,1.57248 -0.91728,2.42424c0,0.78624 0.19656,1.44144 0.72072,1.9656c0.52416,0.52416 1.17936,0.78624 2.09664,0.78624c0.91728,0 1.70352,-0.3276 2.35872,-1.04832l9.89352,-12.4488l10.41768,12.4488c0.52416,0.72072 1.3104,1.04832 2.35872,1.04832c0.85176,0 1.57248,-0.26208 2.09664,-0.78624c0.52416,-0.52416 0.85176,-1.17936 0.85176,-1.9656z" id="path4607"/>
|
||||
</g>
|
||||
<image width="0" height="0" y="-350.55203" x="-306.10635" id="icon"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
BIN
console-ui/src/assets/previews/Card.png
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
console-ui/src/assets/previews/ChatGPT.png
Normal file
|
After Width: | Height: | Size: 387 KiB |
BIN
console-ui/src/assets/previews/Color.png
Normal file
|
After Width: | Height: | Size: 371 KiB |
BIN
console-ui/src/assets/previews/DashBoard.png
Normal file
|
After Width: | Height: | Size: 685 KiB |
BIN
console-ui/src/assets/previews/DataTable.png
Normal file
|
After Width: | Height: | Size: 580 KiB |
BIN
console-ui/src/assets/previews/Gradient.png
Normal file
|
After Width: | Height: | Size: 529 KiB |
BIN
console-ui/src/assets/previews/Login.png
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
console-ui/src/assets/previews/TaskBoard.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
console-ui/src/assets/previews/Todo.png
Normal file
|
After Width: | Height: | Size: 379 KiB |
BIN
console-ui/src/assets/previews/Unsplash.png
Normal file
|
After Width: | Height: | Size: 3.1 MiB |
BIN
console-ui/src/assets/previews/Unsplash2.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
console-ui/src/assets/wechat-qrcode.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
console-ui/src/assets/wechat.jpg
Normal file
|
After Width: | Height: | Size: 124 KiB |
56
console-ui/src/components/ApiKeyDialog.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { useChatStore } from "@/views/app/chat/chatStore";
|
||||
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const close = () => {
|
||||
chatStore.apiKeyDialog = false;
|
||||
};
|
||||
|
||||
const key = computed({
|
||||
get: () => chatStore.apiKey,
|
||||
set: (value) => {
|
||||
chatStore.saveApiKey(value); // 假设您有一个名为setApiKey的Pinia store mutation
|
||||
},
|
||||
});
|
||||
|
||||
const apiKeyShow = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog v-model="chatStore.apiKeyDialog" width="600">
|
||||
<v-card>
|
||||
<v-card-title class="font-weight-bold pa-5">
|
||||
Input your Api Key</v-card-title
|
||||
>
|
||||
<hr />
|
||||
<v-card-text>
|
||||
<v-label class="font-weight-medium mb-2 ml-2">YOUR API KEY</v-label>
|
||||
<v-text-field
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
v-model="key"
|
||||
class="px-2 py-1"
|
||||
placeholder="If not input , the ApiKey in the .env will be used."
|
||||
prepend-inner-icon="mdi-key"
|
||||
autofocus
|
||||
clearable
|
||||
hide-details
|
||||
@click:prepend-inner="apiKeyShow = !apiKeyShow"
|
||||
></v-text-field>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn variant="flat" color="primary" @click="close">OK</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
65
console-ui/src/components/BoardCard.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<v-card @click="$emit('edit')" class="pa-5 mt-4 card-shadow">
|
||||
<div class="d-flex align-start font-weight-bold text-title">
|
||||
<span class="flex-1">{{ card.title }}</span>
|
||||
<v-menu location="bottom end" transition="slide-x-transition">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
size="small"
|
||||
variant="text"
|
||||
icon="mdi-dots-vertical"
|
||||
rounded
|
||||
color="primary"
|
||||
class="my-n2"
|
||||
></v-btn>
|
||||
</template>
|
||||
<v-list density="compact">
|
||||
<v-list-item @click="$emit('edit')">
|
||||
<v-list-item-title class="d-inline-flex align-center">
|
||||
<Icon
|
||||
icon="flat-color-icons:edit-image"
|
||||
:rotate="2"
|
||||
:horizontalFlip="true"
|
||||
:verticalFlip="true"
|
||||
class="mr-1"
|
||||
/>
|
||||
<span> Edit</span>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="$emit('delete')">
|
||||
<v-list-item-title class="d-inline-flex align-center">
|
||||
<Icon
|
||||
icon="flat-color-icons:full-trash"
|
||||
:rotate="2"
|
||||
:horizontalFlip="true"
|
||||
:verticalFlip="true"
|
||||
:inline="true"
|
||||
class="mr-1"
|
||||
/>
|
||||
Delete</v-list-item-title
|
||||
>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</div>
|
||||
<div class="text-content">{{ props.card.description }}</div>
|
||||
</v-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
|
||||
const props = defineProps({
|
||||
// Card content to display
|
||||
card: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-shadow {
|
||||
box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px !important;
|
||||
}
|
||||
</style>
|
||||
35
console-ui/src/components/Breadcrumb.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<v-breadcrumbs
|
||||
v-if="breadcrumbs.length > 0"
|
||||
:items="breadcrumbs"
|
||||
class="ml-n3"
|
||||
>
|
||||
<!-- <template v-slot:prepend>
|
||||
<v-icon size="small" icon="mdi-vuetify" color="blue"></v-icon>
|
||||
</template> -->
|
||||
</v-breadcrumbs>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const route = useRoute();
|
||||
|
||||
const breadcrumbs = ref<any>([]);
|
||||
|
||||
watchEffect(() => {
|
||||
// if you go to the redirect page, do not update the breadcrumbs
|
||||
// if (route.path.startsWith('/redirect/')) {
|
||||
// return
|
||||
// }
|
||||
if (route.meta && route.meta.title) {
|
||||
breadcrumbs.value = [
|
||||
{
|
||||
title: route.meta.category,
|
||||
disabled: false,
|
||||
},
|
||||
{ title: route.meta.title, disabled: true },
|
||||
];
|
||||
} else {
|
||||
breadcrumbs.value = [];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
217
console-ui/src/components/CustomizationMenu.vue
Normal file
@@ -0,0 +1,217 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from "vuetify";
|
||||
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
|
||||
import { Icon } from "@iconify/vue";
|
||||
interface Color {
|
||||
colorId: number;
|
||||
colorName: string;
|
||||
colorValue: string;
|
||||
}
|
||||
const customizeTheme = useCustomizeThemeStore();
|
||||
const theme = useTheme();
|
||||
const themeDrawer = ref(false);
|
||||
const currentColor = ref<Color>({
|
||||
colorId: 2,
|
||||
colorName: "grey",
|
||||
colorValue: "#344767",
|
||||
});
|
||||
const primaryColors = ref([
|
||||
{
|
||||
colorId: 1,
|
||||
colorName: "purple",
|
||||
colorValue: "#CB0C9F",
|
||||
},
|
||||
{
|
||||
colorId: 2,
|
||||
colorName: "grey",
|
||||
colorValue: "#344767",
|
||||
},
|
||||
{
|
||||
colorId: 3,
|
||||
colorName: "info",
|
||||
colorValue: "#17C1E8",
|
||||
},
|
||||
{
|
||||
colorId: 4,
|
||||
colorName: "success",
|
||||
colorValue: "#82D616",
|
||||
},
|
||||
{
|
||||
colorId: 5,
|
||||
colorName: "warning",
|
||||
colorValue: "#F2825A",
|
||||
},
|
||||
{
|
||||
colorId: 6,
|
||||
colorName: "error",
|
||||
colorValue: "#EA0606",
|
||||
},
|
||||
]);
|
||||
|
||||
watch(currentColor, (newVal) => {
|
||||
theme.themes.value.light.colors.primary = newVal.colorValue;
|
||||
theme.themes.value.dark.colors.primary = newVal.colorValue;
|
||||
customizeTheme.setPrimaryColor(newVal);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="drawer-button" @click="themeDrawer = true">
|
||||
<v-icon class="text-white">mdi-cog-outline</v-icon>
|
||||
</div>
|
||||
|
||||
<v-navigation-drawer
|
||||
v-model="themeDrawer"
|
||||
location="right"
|
||||
temporary
|
||||
width="300"
|
||||
class="theme-drawer pa-8"
|
||||
>
|
||||
<div class="top-area">
|
||||
<div class="d-flex align-center">
|
||||
<b>UI Configurator</b>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
variant="text"
|
||||
size="small"
|
||||
rounded
|
||||
icon="mdi-close"
|
||||
@click="themeDrawer = false"
|
||||
>
|
||||
</v-btn>
|
||||
</div>
|
||||
<div>See our dashboard options.</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-6" />
|
||||
|
||||
<div class="theme-area">
|
||||
<b>Global Theme Mode</b>
|
||||
<div class="px-3 pt-3" v-if="customizeTheme.darkTheme">
|
||||
<v-btn
|
||||
@click="customizeTheme.darkTheme = !customizeTheme.darkTheme"
|
||||
icon
|
||||
color="grey-darken-4"
|
||||
class="text-white"
|
||||
>
|
||||
<Icon width="30" icon="line-md:moon-filled-loop" />
|
||||
</v-btn>
|
||||
<span class="ml-5">Dark Mode</span>
|
||||
</div>
|
||||
<div class="px-3 pt-3" v-else>
|
||||
<v-btn
|
||||
@click="customizeTheme.darkTheme = !customizeTheme.darkTheme"
|
||||
icon
|
||||
color="white"
|
||||
class="text-red"
|
||||
>
|
||||
<Icon
|
||||
width="30"
|
||||
icon="line-md:moon-filled-alt-to-sunny-filled-loop-transition"
|
||||
/>
|
||||
</v-btn>
|
||||
<span class="ml-5">Light Mode</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-6" />
|
||||
|
||||
<div class="primary-color-area">
|
||||
<b>Primary Colors</b>
|
||||
<v-item-group
|
||||
class="mt-3"
|
||||
v-model="currentColor"
|
||||
selected-class="elevation-12"
|
||||
mandatory
|
||||
>
|
||||
<v-item
|
||||
v-for="color in primaryColors"
|
||||
:key="color.colorId"
|
||||
:value="color"
|
||||
v-slot="{ isSelected, toggle }"
|
||||
>
|
||||
<v-btn
|
||||
@click="toggle"
|
||||
class="text-white mr-1"
|
||||
icon
|
||||
size="30"
|
||||
:color="color.colorValue"
|
||||
>
|
||||
<Icon width="22" v-if="isSelected" icon="line-md:confirm" />
|
||||
</v-btn>
|
||||
</v-item>
|
||||
</v-item-group>
|
||||
</div>
|
||||
<hr class="my-6" />
|
||||
<div class="">
|
||||
<b>MiniSideBar</b>
|
||||
<v-switch
|
||||
color="primary"
|
||||
class="ml-2"
|
||||
hide-details
|
||||
:label="`Mini: ${customizeTheme.miniSidebar}`"
|
||||
></v-switch>
|
||||
</div>
|
||||
<hr class="my-6" />
|
||||
<div>
|
||||
<v-btn color="" class="gradient info" block size="large"
|
||||
>Contact Me</v-btn
|
||||
>
|
||||
</div>
|
||||
<div class="ml-5 mt-5 d-flex align-center">
|
||||
<v-icon color="primary" class="mr-6">mdi-email-outline</v-icon>
|
||||
<a href="mailto:yjkbako@gmail.com">yjkbako@gmail.com</a>
|
||||
</div>
|
||||
<div class="ml-5 d-flex align-center">
|
||||
<img src="@/assets/wechat.jpg" alt="" />
|
||||
</div>
|
||||
</v-navigation-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.drawer-button {
|
||||
position: fixed;
|
||||
background-color: #705cf6;
|
||||
top: 340px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
padding: 0.5rem 1rem;
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
box-shadow: 1px 1px 9px #705cf6;
|
||||
transition: all 0.5s;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
box-shadow: 1px 1px 18px #705cf6;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
|
||||
.v-icon {
|
||||
font-size: 1.3rem;
|
||||
animation: rotation 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
background-image: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(0, 0, 0, 0.4),
|
||||
transparent
|
||||
) !important;
|
||||
background-color: transparent;
|
||||
opacity: 0.25;
|
||||
border: none;
|
||||
height: 1px;
|
||||
}
|
||||
</style>
|
||||
27
console-ui/src/components/GlobalLoading.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import Loading from "@/components/loading/Loading02.vue";
|
||||
const appStore = useAppStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card
|
||||
v-if="appStore.globalLoading"
|
||||
color="white"
|
||||
class="global-loading d-flex align-center justify-center"
|
||||
height="100vh"
|
||||
>
|
||||
<Loading />
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.main-bg {
|
||||
min-height: calc(100vh - 64px);
|
||||
}
|
||||
</style>
|
||||
@@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br>
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
15
console-ui/src/components/PageTitle.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<h1 class="text-h4 mt-5">{{ title }}</h1>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const route = useRoute();
|
||||
|
||||
const title = ref("");
|
||||
|
||||
watchEffect(() => {
|
||||
if (route.meta && route.meta.title) {
|
||||
title.value = route.meta.title as string;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
122
console-ui/src/components/Toolbox.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<!--
|
||||
* @Component: BackToTop
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
import ChatAssistant from "@/components/ai/ChatAssistant.vue";
|
||||
import TranslationAssistant from "@/components/ai/TranslationAssistant.vue";
|
||||
import { useChatStore } from "@/views/app/chat/chatStore";
|
||||
import ApiKeyDialog from "@/components/ApiKeyDialog.vue";
|
||||
const chatStore = useChatStore();
|
||||
const toolboxShow = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-btn
|
||||
class="toolbox-activator elevation-10"
|
||||
@click="toolboxShow = !toolboxShow"
|
||||
size="50"
|
||||
color="white"
|
||||
>
|
||||
<Icon width="30" icon="ri:openai-fill" />
|
||||
</v-btn>
|
||||
|
||||
<transition name="slide-y">
|
||||
<v-card
|
||||
v-if="toolboxShow"
|
||||
elevation="10"
|
||||
class="d-flex flex-column mb-1 toolbox"
|
||||
>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Close Btn -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-btn
|
||||
@click="toolboxShow = false"
|
||||
variant="text"
|
||||
size="50"
|
||||
color="error"
|
||||
>
|
||||
<v-icon size="30">mdi-close</v-icon>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="left"
|
||||
text="Close Toolbox"
|
||||
></v-tooltip>
|
||||
</v-btn>
|
||||
<hr />
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- ApiKey -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-btn
|
||||
@click="chatStore.apiKeyDialog = true"
|
||||
variant="text"
|
||||
size="50"
|
||||
color="blue"
|
||||
>
|
||||
<v-icon size="30">mdi-key-outline</v-icon>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="left"
|
||||
:text="$t('toolbox.apikey.title')"
|
||||
></v-tooltip>
|
||||
</v-btn>
|
||||
<ApiKeyDialog />
|
||||
<hr />
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Chat Assistant -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<ChatAssistant />
|
||||
<hr />
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Translation Assistant -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<TranslationAssistant />
|
||||
<hr />
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Code Assistant -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-btn size="50">
|
||||
<v-icon size="30">mdi-code-tags</v-icon>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="left"
|
||||
:text="$t('toolbox.codeAssistant.title')"
|
||||
></v-tooltip>
|
||||
</v-btn>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Code Assistant -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-btn size="50" to="/playground">
|
||||
<v-icon size="30">mdi-seesaw</v-icon>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="left"
|
||||
:text="$t('toolbox.playGround.title')"
|
||||
></v-tooltip>
|
||||
</v-btn>
|
||||
</v-card>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.toolbox {
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
bottom: 150px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.toolbox-activator {
|
||||
position: fixed;
|
||||
transition: all 0.3s ease;
|
||||
bottom: 100px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
69
console-ui/src/components/ai/ChatAssistant.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { useDisplay } from "vuetify";
|
||||
import InputArea from "@/views/app/chat/components/InputArea.vue";
|
||||
import MessageArea from "@/views/app/chat/components/MessageArea.vue";
|
||||
const dialog = ref(false);
|
||||
const { xs } = useDisplay();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-btn size="50" @click="dialog = !dialog">
|
||||
<v-icon size="30">mdi-chat-outline </v-icon>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="left"
|
||||
:text="$t('toolbox.chatAssistant.title')"
|
||||
></v-tooltip>
|
||||
</v-btn>
|
||||
|
||||
<teleport to="body">
|
||||
<transition name="slide-y">
|
||||
<v-card
|
||||
v-if="dialog"
|
||||
class="dialog-bottom d-flex flex-column"
|
||||
:width="xs ? '100%' : '600px'"
|
||||
height="500px"
|
||||
>
|
||||
<v-card-title>
|
||||
<span class="flex-1">
|
||||
<v-avatar size="40">
|
||||
<img
|
||||
src="https://img.icons8.com/color/96/null/filled-chat.png"
|
||||
alt="alt"
|
||||
/>
|
||||
</v-avatar>
|
||||
|
||||
OpenAi Chat
|
||||
</span>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click.stop="dialog = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<hr />
|
||||
<v-card-text class="overflow-scroll">
|
||||
<MessageArea />
|
||||
</v-card-text>
|
||||
<hr />
|
||||
<v-card-actions>
|
||||
<InputArea />
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</transition>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog-bottom {
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 0px;
|
||||
}
|
||||
</style>
|
||||
354
console-ui/src/components/ai/TranslationAssistant.vue
Normal file
@@ -0,0 +1,354 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { createTranscriptionApi } from "@/api/aiApi";
|
||||
import { useChatStore } from "@/views/app/chat/chatStore";
|
||||
import CopyBtn from "@/components/common/CopyBtn.vue";
|
||||
import { useDisplay } from "vuetify";
|
||||
import { read } from "@/utils/aiUtils";
|
||||
import { useSnackbarStore } from "@/stores/snackbarStore";
|
||||
const snackbarStore = useSnackbarStore();
|
||||
const chatStore = useChatStore();
|
||||
const langs = [
|
||||
{
|
||||
code: "en",
|
||||
name: "English",
|
||||
label: "English",
|
||||
},
|
||||
{
|
||||
code: "zh-CN",
|
||||
name: "Chinese Simplified",
|
||||
label: "中文(简体)",
|
||||
},
|
||||
{
|
||||
code: "zh-TW",
|
||||
name: "Chinese Traditional",
|
||||
label: "中文(繁體)",
|
||||
},
|
||||
{
|
||||
code: "ja",
|
||||
name: "Japanese",
|
||||
label: "日本語",
|
||||
},
|
||||
{
|
||||
code: "ko",
|
||||
name: "Korean",
|
||||
label: "한국어",
|
||||
},
|
||||
{
|
||||
code: "fr",
|
||||
name: "French",
|
||||
label: "Français",
|
||||
},
|
||||
{
|
||||
code: "de",
|
||||
name: "German",
|
||||
label: "Deutsch",
|
||||
},
|
||||
{
|
||||
code: "es",
|
||||
name: "Spanish",
|
||||
label: "Español",
|
||||
},
|
||||
];
|
||||
|
||||
const currentLang = ref({
|
||||
code: "en",
|
||||
name: "English",
|
||||
label: "English",
|
||||
});
|
||||
const setLang = (lang: any) => {
|
||||
currentLang.value = lang;
|
||||
};
|
||||
|
||||
const baseContent = ref("");
|
||||
const targetContent = ref("");
|
||||
|
||||
const prompt = computed(() => {
|
||||
return `Translate into ${currentLang.value.name}`;
|
||||
// return `I want you to act as an ${currentLangName.value} translator, spelling corrector and improver. I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in ${currentLang.value.name}. I want you to replace my simplified A0-level words and sentences with more beautiful and elegant, upper level ${currentLang.value.name} words and sentences. Keep the meaning same, but make them more literary. I want you to only reply the correction, the improvements and nothing else, do not write explanations.”`;
|
||||
});
|
||||
|
||||
const isLoading = ref(false);
|
||||
const translate = async () => {
|
||||
if (baseContent.value === "") {
|
||||
snackbarStore.showErrorMessage("请输入要翻译的内容");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chatStore.getApiKey) {
|
||||
snackbarStore.showErrorMessage("请先输入API KEY");
|
||||
return;
|
||||
}
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const completion = await fetch(
|
||||
"https://api.openai.com/v1/chat/completions",
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${chatStore.getApiKey}`,
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
messages: [
|
||||
{ role: "user", content: prompt.value },
|
||||
{ role: "user", content: baseContent.value },
|
||||
],
|
||||
model: "gpt-3.5-turbo",
|
||||
stream: true,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
// Handle errors
|
||||
if (!completion.ok) {
|
||||
const errorData = await completion.json();
|
||||
snackbarStore.showErrorMessage(errorData.error.message);
|
||||
isLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a reader
|
||||
const reader = completion.body?.getReader();
|
||||
if (!reader) {
|
||||
snackbarStore.showErrorMessage("Cannot read the stream.");
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
// Clear the target content
|
||||
targetContent.value = "";
|
||||
|
||||
// Read the stream
|
||||
read(reader, targetContent);
|
||||
} catch (error) {
|
||||
snackbarStore.showErrorMessage(error.message);
|
||||
}
|
||||
isLoading.value = false;
|
||||
};
|
||||
|
||||
const isBaseContentEmpty = ref(false);
|
||||
const recorder = ref<any>();
|
||||
const isRecording = ref(false);
|
||||
|
||||
const startRecording = async () => {
|
||||
// 获取用户媒体权限,视频的话参数{audio: true, video: true}
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({ audio: true })
|
||||
.then((stream) => {
|
||||
// 创建媒体流
|
||||
recorder.value = new MediaRecorder(stream);
|
||||
const audioChunks = <any>[];
|
||||
// 录音开始
|
||||
recorder.value.start();
|
||||
isRecording.value = true;
|
||||
// 录音数据
|
||||
recorder.value.ondataavailable = (e: any) => {
|
||||
audioChunks.push(e.data);
|
||||
};
|
||||
// 录音结束
|
||||
recorder.value.onstop = async (e: any) => {
|
||||
const blob = new Blob(audioChunks, { type: "audio/wav" });
|
||||
const file = new File([blob], "recording.wav", {
|
||||
type: "audio/wav",
|
||||
});
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
formData.append("model", "whisper-1");
|
||||
const res = await createTranscriptionApi(formData, chatStore.getApiKey);
|
||||
baseContent.value = res.data.text;
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
snackbarStore.showErrorMessage(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
const stopRecording = () => {
|
||||
if (recorder.value) {
|
||||
recorder.value.stop();
|
||||
isRecording.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const record = () => {
|
||||
if (isRecording.value) {
|
||||
stopRecording();
|
||||
} else {
|
||||
startRecording();
|
||||
}
|
||||
};
|
||||
|
||||
const dialog = ref(false);
|
||||
const { xs } = useDisplay();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-btn size="50" @click="dialog = !dialog">
|
||||
<v-icon size="30">mdi-google-translate</v-icon>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="left"
|
||||
:text="$t('toolbox.translationAssistant.title')"
|
||||
></v-tooltip>
|
||||
</v-btn>
|
||||
|
||||
<teleport to="body">
|
||||
<transition name="slide-y">
|
||||
<v-card
|
||||
v-if="dialog"
|
||||
class="dialog-bottom d-flex flex-column"
|
||||
:width="xs ? '100%' : '600px'"
|
||||
>
|
||||
<v-card-title>
|
||||
<span class="flex-1">
|
||||
<v-avatar size="40">
|
||||
<img src="https://img.icons8.com/color/96/null/translation.png" />
|
||||
</v-avatar>
|
||||
|
||||
OpenAi {{ $t("toolbox.translationAssistant.title") }}
|
||||
</span>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click.stop="dialog = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<hr />
|
||||
<v-card-actions class="px-5">
|
||||
<span class="text-body-2"
|
||||
>{{ $t("toolbox.translationAssistant.targetLanguage") }}:</span
|
||||
>
|
||||
<!-- <v-btn-toggle
|
||||
v-model="currentLang"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
mandatory
|
||||
>
|
||||
<v-btn
|
||||
density="compact"
|
||||
size="small"
|
||||
v-for="lang in langs"
|
||||
:value="lang.code"
|
||||
>
|
||||
{{ lang.label }}
|
||||
</v-btn>
|
||||
</v-btn-toggle> -->
|
||||
<v-menu location="bottom end" scroll-y>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn width="108" append-icon="mdi-menu-down" v-bind="props">
|
||||
<span class="text-body-2">{{ currentLang.label }}</span>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
<div v-for="lang in langs">
|
||||
<v-btn block @click="setLang(lang)">{{ lang.label }}</v-btn>
|
||||
</div>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-btn
|
||||
class="ml-2 text-white"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
variant="elevated"
|
||||
color="primary"
|
||||
@click="translate"
|
||||
>{{ $t("toolbox.translationAssistant.translate") }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
<hr />
|
||||
<v-card-text>
|
||||
<v-row no-gutters justify="center" dense>
|
||||
<v-col cols="12">
|
||||
<v-card elevation="0">
|
||||
<div class="pa-2">
|
||||
<v-textarea
|
||||
v-model="baseContent"
|
||||
placeholder="Enter the text to be translated"
|
||||
hide-details
|
||||
variant="solo"
|
||||
class="elevation-1"
|
||||
color="white"
|
||||
clearable
|
||||
@focus="isBaseContentEmpty = false"
|
||||
></v-textarea>
|
||||
</div>
|
||||
<v-card-actions class="bg-grey-lighten-4 text-primary">
|
||||
<v-tooltip
|
||||
location="bottom"
|
||||
:text="$t('toolbox.translationAssistant.speech')"
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<v-btn @click="record" v-bind="props" icon>
|
||||
<v-icon v-if="isRecording">mdi-microphone</v-icon>
|
||||
<v-icon v-else>mdi-microphone-outline</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip
|
||||
location="bottom"
|
||||
:text="$t('toolbox.translationAssistant.read')"
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<v-btn v-bind="props" icon
|
||||
><v-icon>mdi-volume-high</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-spacer></v-spacer>
|
||||
<CopyBtn :text="baseContent" />
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<v-card elevation="0">
|
||||
<div class="pa-2">
|
||||
<v-textarea
|
||||
v-model="targetContent"
|
||||
hide-details
|
||||
variant="solo"
|
||||
class="elevation-1"
|
||||
color="primary"
|
||||
clearable
|
||||
></v-textarea>
|
||||
</div>
|
||||
<v-card-actions
|
||||
class="bg-grey-lighten-4 bg-grey-lighten-4 text-primary"
|
||||
>
|
||||
<v-tooltip
|
||||
location="bottom"
|
||||
:text="$t('toolbox.translationAssistant.read')"
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<v-btn @click="" v-bind="props" icon
|
||||
><v-icon>mdi-volume-high</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-spacer></v-spacer>
|
||||
<CopyBtn :text="targetContent" />
|
||||
</v-card-actions> </v-card
|
||||
></v-col> </v-row
|
||||
></v-card-text>
|
||||
<hr />
|
||||
</v-card>
|
||||
</transition>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog-bottom {
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 0px;
|
||||
}
|
||||
</style>
|
||||
18
console-ui/src/components/animations/Animation404.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { Vue3Lottie } from "vue3-lottie";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Vue3Lottie
|
||||
animationLink="https://assets2.lottiefiles.com/packages/lf20_cr9slsdh.json"
|
||||
:height="500"
|
||||
:width="500"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
31
console-ui/src/components/animations/AnimationBot1.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { Vue3Lottie } from "vue3-lottie";
|
||||
const props = defineProps({
|
||||
size: {
|
||||
type: Number,
|
||||
default: 400,
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.size,
|
||||
(newSize) => {
|
||||
console.log(newSize);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Vue3Lottie
|
||||
animationLink="https://assets6.lottiefiles.com/packages/lf20_ofa3xwo7.json"
|
||||
:height="size"
|
||||
:width="size"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
18
console-ui/src/components/animations/AnimationBot2.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { Vue3Lottie } from "vue3-lottie";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Vue3Lottie
|
||||
animationLink="https://assets4.lottiefiles.com/packages/lf20_zrqthn6o.json"
|
||||
:height="400"
|
||||
:width="400"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
157
console-ui/src/components/charts/apexchart/ApexChartsData.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
const themeColors = ["#ee8a6a", "#0cb9c5", "#fec90f", "#05b187", "#fc4b6c"];
|
||||
const themeColors2 = ["#4782FB", "#47C4F4", "#fec90f", "#05b187", "#fc4b6c"];
|
||||
|
||||
function generateDataHeatMap(count: any, yrange: any) {
|
||||
var i = 0;
|
||||
var series: any[] = [];
|
||||
while (i < count) {
|
||||
var x = "w" + (i + 1).toString();
|
||||
var y =
|
||||
Math.floor(Math.random() * (yrange.max - yrange.min + 1)) + yrange.min;
|
||||
|
||||
series.push({
|
||||
x: x,
|
||||
y: y,
|
||||
});
|
||||
i++;
|
||||
}
|
||||
return series;
|
||||
}
|
||||
|
||||
export const heatMapChart = {
|
||||
series: [
|
||||
{
|
||||
name: "Metric1",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Metric2",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Metric3",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Metric4",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Metric5",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Metric6",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Metric7",
|
||||
data: generateDataHeatMap(18, {
|
||||
min: 0,
|
||||
max: 90,
|
||||
}),
|
||||
},
|
||||
],
|
||||
chartOptions: {
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
},
|
||||
colors: ["#1e88e5"],
|
||||
tooltip: {
|
||||
theme: "dark",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const lineAreaChartSpline = {
|
||||
series: [
|
||||
{
|
||||
name: "Open Rate",
|
||||
data: [0, 5, 6, 8, 25, 9, 8, 24],
|
||||
},
|
||||
{
|
||||
name: "Recurring Payments",
|
||||
data: [0, 3, 1, 2, 8, 1, 5, 1],
|
||||
},
|
||||
],
|
||||
|
||||
chartOptions: {
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: "rgba(0, 0, 0, .3)",
|
||||
strokeDashArray: 3,
|
||||
xaxis: {
|
||||
lines: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
lines: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
},
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
curve: "smooth",
|
||||
width: 2,
|
||||
},
|
||||
colors: themeColors2,
|
||||
fill: {
|
||||
type: "gradient",
|
||||
opacity: ["0.1", "0.1"],
|
||||
},
|
||||
xaxis: {
|
||||
categories: ["1", "2", "3", "4", "5", "6", "7", "8"],
|
||||
labels: {
|
||||
style: {
|
||||
cssClass: "grey--text lighten-2--text fill-color",
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: {
|
||||
cssClass: "grey--text lighten-2--text fill-color",
|
||||
},
|
||||
},
|
||||
},
|
||||
markers: {
|
||||
size: 3,
|
||||
},
|
||||
tooltip: {
|
||||
x: {
|
||||
format: "dd/MM/yy HH:mm",
|
||||
},
|
||||
theme: "dark",
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
* @Component: ApexHeatMapCharts
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description: ApexHeatMapCharts
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { heatMapChart } from "./ApexChartsData";
|
||||
</script>
|
||||
<template>
|
||||
<div class="">ApexHeatMapCharts</div>
|
||||
<apexchart
|
||||
type="heatmap"
|
||||
height="310"
|
||||
:options="heatMapChart.chartOptions"
|
||||
:series="heatMapChart.series"
|
||||
></apexchart>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
* @Component: ApexLineAreaCharts
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description: ApexLineAreaCharts
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { lineAreaChartSpline } from "./ApexChartsData";
|
||||
</script>
|
||||
<template>
|
||||
<h1 class="pl-5">ApexLineAreaCharts</h1>
|
||||
<apexchart
|
||||
type="area"
|
||||
height="350"
|
||||
:options="lineAreaChartSpline.chartOptions"
|
||||
:series="lineAreaChartSpline.series"
|
||||
></apexchart>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
58
console-ui/src/components/common/BackToTop.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<!--
|
||||
* @Component: BackToTop
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
const isVisible = ref(false);
|
||||
|
||||
const handleScroll = () => {
|
||||
isVisible.value = window.scrollY > 200;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
});
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="back-to-top" :class="{ visible: isVisible }" @click="scrollToTop">
|
||||
<Icon class="text-white" width="30" icon="ph:rocket-light" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
background-color: #705cf6;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
bottom: 50px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 1px 1px 9px #705cf6;
|
||||
transition: all 0.5s;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
box-shadow: 1px 1px 18px #705cf6;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
}
|
||||
|
||||
.back-to-top.visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
</style>
|
||||
56
console-ui/src/components/common/CopyBtn.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
* @Component: CopyLabel
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
const { copy } = useClipboard();
|
||||
|
||||
// SnackBar
|
||||
const snackbar = ref(false);
|
||||
const timeout = ref("1000");
|
||||
const copiedText = "Copied to clipboard!";
|
||||
|
||||
// Props
|
||||
const props = defineProps({
|
||||
// Text to copy to clipboard
|
||||
text: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
// Copy Text
|
||||
const copyText = () => {
|
||||
console.log(props.text);
|
||||
copy(props.text);
|
||||
|
||||
snackbar.value = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<v-snackbar v-model="snackbar" :timeout="timeout">
|
||||
{{ copiedText }}
|
||||
<template v-slot:actions>
|
||||
<v-btn color="blue" variant="text" @click="snackbar = false">
|
||||
Close
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
|
||||
<v-btn v-bind="$attrs" icon @click="copyText()"
|
||||
><v-icon>mdi-content-copy</v-icon>
|
||||
<v-tooltip activator="parent" location="bottom" text="Copy"></v-tooltip>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.text {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
74
console-ui/src/components/common/CopyLabel.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<!--
|
||||
* @Component: CopyLabel
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
const { copy } = useClipboard();
|
||||
|
||||
// ToolTip
|
||||
const tooltip = ref("Copy");
|
||||
// SnackBar
|
||||
const snackbar = ref(false);
|
||||
const timeout = ref("1000");
|
||||
const copiedText = "Copied to clipboard!";
|
||||
// Copy Animation Flag
|
||||
const heartBeat = ref(false);
|
||||
// Props
|
||||
const props = defineProps({
|
||||
// Text to copy to clipboard
|
||||
text: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
const { text } = toRefs(props);
|
||||
|
||||
// Copy Text
|
||||
const copyText = (text: string) => {
|
||||
copy(text);
|
||||
heartBeat.value = true;
|
||||
snackbar.value = true;
|
||||
tooltip.value = "Copied!";
|
||||
setTimeout(() => {
|
||||
heartBeat.value = false;
|
||||
tooltip.value = "Copy!";
|
||||
}, 1000);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-snackbar v-model="snackbar" :timeout="timeout">
|
||||
{{ copiedText }}
|
||||
<template v-slot:actions>
|
||||
<v-btn color="blue" variant="text" @click="snackbar = false">
|
||||
Close
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
<v-tooltip location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<span
|
||||
:class="{
|
||||
heartBeat: heartBeat === true,
|
||||
}"
|
||||
class="text"
|
||||
v-bind="props"
|
||||
@click.stop.prevent="copyText(text)"
|
||||
>
|
||||
{{ text }}
|
||||
</span>
|
||||
</template>
|
||||
<span>{{ tooltip }}</span>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.text {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
border-bottom: 1px dashed;
|
||||
}
|
||||
</style>
|
||||
28
console-ui/src/components/common/PercentTrend.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span>
|
||||
<span v-if="value === 0"> {{ value }}% </span>
|
||||
<span v-else-if="value > 0" class="text-success">
|
||||
<v-icon small color="success">mdi-arrow-top-right</v-icon> {{ value }}%
|
||||
</span>
|
||||
<span v-else class="error--text">
|
||||
<v-icon small color="error">mdi-arrow-bottom-right</v-icon>
|
||||
{{ Math.abs(value) }}%
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
38
console-ui/src/components/common/Snackbar.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import { useSnackbarStore } from "@/stores/snackbarStore";
|
||||
const snackbarStore = useSnackbarStore();
|
||||
|
||||
const getIcon = (type) => {
|
||||
const icon = {
|
||||
info: "mdi-information",
|
||||
success: "mdi-check-circle",
|
||||
error: "mdi-alert-circle",
|
||||
warning: "mdi-alert",
|
||||
};
|
||||
|
||||
return icon[type];
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<v-snackbar
|
||||
v-model="snackbarStore.isShow"
|
||||
timeout="2000"
|
||||
:color="snackbarStore.type"
|
||||
class="elevation-10"
|
||||
location="top"
|
||||
multi-line
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-2">{{ getIcon(snackbarStore.type) }}</v-icon>
|
||||
<span> {{ snackbarStore.message }}</span>
|
||||
</div>
|
||||
|
||||
<template v-slot:actions>
|
||||
<v-btn icon variant="text" @click="snackbarStore.isShow = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
204
console-ui/src/components/dashboard/ActivityCard.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
import { getPublicEventsApi } from "@/api/githubApi";
|
||||
import moment from "moment";
|
||||
|
||||
const loading = ref(false);
|
||||
const username = ref("yangjiakai");
|
||||
const activityList = ref([
|
||||
{
|
||||
id: 1,
|
||||
type: "PushEvent",
|
||||
user: "yangjiakai",
|
||||
avatar: "https://avatars.githubusercontent.com/u/35951244?",
|
||||
repo: "yangjiakai/lux-admin-vuetify3",
|
||||
content: "Update Readme",
|
||||
created_at: "2023-04-06T16:01:30Z",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
type: "IssuesEvent",
|
||||
user: "yangjiakai",
|
||||
avatar: "https://avatars.githubusercontent.com/u/35951244?",
|
||||
repo: "yangjiakai/lux-admin-vuetify3",
|
||||
content: "全局的配置管理,比如dev配置,和pro配置隔离开",
|
||||
created_at: "2023-04-06T16:01:30Z",
|
||||
},
|
||||
]);
|
||||
const getPublicEvent = async () => {
|
||||
loading.value = true;
|
||||
const response = await getPublicEventsApi(username.value);
|
||||
|
||||
activityList.value = response.data.map((activity) => {
|
||||
return {
|
||||
id: activity.id,
|
||||
type: activity.type,
|
||||
user: activity.actor.display_login,
|
||||
avatar: activity.actor.avatar_url,
|
||||
repo: activity.repo?.name,
|
||||
content: getContent(activity),
|
||||
action:
|
||||
activity.type === "IssuesEvent" ? activity.payload.action : "Commit",
|
||||
created_at: activity.created_at,
|
||||
};
|
||||
});
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const getContent = (activity: any) => {
|
||||
if (activity.type === "PushEvent") {
|
||||
return convertToHtml(activity.payload.commits[0].message);
|
||||
} else if (activity.type === "CreateEvent") {
|
||||
return activity.payload.ref_type;
|
||||
} else if (activity.type === "IssuesEvent") {
|
||||
return activity.payload.issue.title;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const convertToHtml = (text) => {
|
||||
const lines = text.split("\n");
|
||||
let html = "";
|
||||
|
||||
lines.forEach((line) => {
|
||||
if (line.startsWith("- ")) {
|
||||
html += `<div><span class='mr-1'>✅</span> ${line.slice(2)}</div>`;
|
||||
} else if (line.trim() === "") {
|
||||
html += "<br/>";
|
||||
} else {
|
||||
html += `<p>${line}</p>`;
|
||||
}
|
||||
});
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
const getTagColor = (activity: any) => {
|
||||
if (activity.type === "PushEvent") {
|
||||
return "green";
|
||||
} else if (activity.type === "IssuesEvent") {
|
||||
return "red";
|
||||
} else {
|
||||
return "blue";
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getPublicEvent();
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<!-- loading spinner -->
|
||||
<div
|
||||
v-if="loading"
|
||||
class="h-full d-flex flex-grow-1 align-center justify-center"
|
||||
>
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h6 class="text-h6 pa-5 d-flex align-center">
|
||||
<span class="flex-1 font-weight-bold">Github Activity</span>
|
||||
<v-menu location="bottom end" transition="slide-x-transition">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
size="small"
|
||||
variant="text"
|
||||
icon="mdi-dots-vertical"
|
||||
rounded
|
||||
color="primary"
|
||||
class="my-n2"
|
||||
></v-btn>
|
||||
</template>
|
||||
<v-list density="compact">
|
||||
<v-list-item @click="$emit('edit')">
|
||||
<v-list-item-title class="d-inline-flex align-center">
|
||||
<Icon
|
||||
icon="flat-color-icons:refresh"
|
||||
:rotate="2"
|
||||
:horizontalFlip="true"
|
||||
:verticalFlip="true"
|
||||
class="mr-1"
|
||||
/>
|
||||
<span> Refresh</span>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="$emit('delete')">
|
||||
<v-list-item-title class="d-inline-flex align-center">
|
||||
<Icon
|
||||
icon="icon-park:clear-format"
|
||||
:rotate="2"
|
||||
:horizontalFlip="true"
|
||||
:verticalFlip="true"
|
||||
:inline="true"
|
||||
class="mr-1"
|
||||
/>
|
||||
Clear</v-list-item-title
|
||||
>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</h6>
|
||||
<perfect-scrollbar class="timeline-container">
|
||||
<v-timeline
|
||||
class="time-line text-body-2"
|
||||
density="compact"
|
||||
side="end"
|
||||
truncate-line="start"
|
||||
>
|
||||
<v-timeline-item
|
||||
v-for="activity in activityList"
|
||||
:key="activity.id"
|
||||
size="small"
|
||||
>
|
||||
<template v-slot:icon>
|
||||
<v-avatar>
|
||||
<img :src="activity.avatar" />
|
||||
</v-avatar>
|
||||
</template>
|
||||
<template v-slot:opposite>
|
||||
<span>{{ moment(activity.created_at).format("MM,DD hh:mm") }}</span>
|
||||
</template>
|
||||
<div class="mb-1">
|
||||
<span class="text-h6 font-weight-bold">
|
||||
{{ activity.user }}
|
||||
</span>
|
||||
<span class="ml-2 text-grey">{{
|
||||
moment(activity.created_at).format("MM,DD hh:mm")
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<v-card width="500">
|
||||
<v-card-subtitle class="pt-4">
|
||||
<v-chip
|
||||
:color="getTagColor(activity)"
|
||||
size="small"
|
||||
label
|
||||
class="mr-2 font-weight-bold"
|
||||
>
|
||||
<span>{{ activity.type }}</span>
|
||||
</v-chip>
|
||||
<span class="text-body-2">{{ activity.repo }}</span>
|
||||
</v-card-subtitle>
|
||||
<v-card-text>
|
||||
<div v-html="activity.content"></div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-timeline-item>
|
||||
</v-timeline>
|
||||
</perfect-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.timeline-container {
|
||||
height: 360px;
|
||||
overflow: scroll;
|
||||
}
|
||||
.time-line {
|
||||
margin-left: 60px;
|
||||
}
|
||||
</style>
|
||||
31
console-ui/src/components/dashboard/ChartCard.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
import BarChart1 from "@/views/chart/component/BarChart1.vue";
|
||||
const loading = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<!-- loading spinner -->
|
||||
<div
|
||||
v-if="loading"
|
||||
class="h-full d-flex flex-grow-1 align-center justify-center"
|
||||
>
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h6 class="text-h6 d-flex align-center font-weight-bold">
|
||||
<span class="pa-5">Chart</span>
|
||||
</h6>
|
||||
<v-card class="" variant="flat">
|
||||
<BarChart1 />
|
||||
</v-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
176
console-ui/src/components/dashboard/SalesCard.vue
Normal file
@@ -0,0 +1,176 @@
|
||||
<script lang="ts" setup>
|
||||
import moment from "moment";
|
||||
import { useTheme } from "vuetify";
|
||||
import { formatCurrency } from "@/utils/formatCurrency";
|
||||
import PercentTrend from "@/components/common/PercentTrend.vue";
|
||||
|
||||
const formatDate = (date: string) => {
|
||||
return date ? moment(date).format("D MMM") : "";
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
percentage: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
percentageLabel: {
|
||||
type: String,
|
||||
default: "vs. last week",
|
||||
},
|
||||
series: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
{
|
||||
name: "Sales",
|
||||
data: [11, 32, 45, 13],
|
||||
},
|
||||
],
|
||||
},
|
||||
xaxis: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
type: "category",
|
||||
categories: [
|
||||
"2018-09-19T00:00:00.000Z",
|
||||
"2018-09-20T00:00:00.000Z",
|
||||
"2018-09-22T00:00:00.000Z",
|
||||
"2018-09-23T00:00:00.000Z",
|
||||
],
|
||||
// tickAmount: 3
|
||||
}),
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: "dashboard.sales",
|
||||
},
|
||||
actionLabel: {
|
||||
type: String,
|
||||
default: "View Report",
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const { themes, current } = useTheme();
|
||||
const chartOptions = computed(() => {
|
||||
const primaryColor = current.value.dark
|
||||
? themes.value["dark"].colors.primary
|
||||
: themes.value["light"].colors.primary;
|
||||
|
||||
return {
|
||||
chart: {
|
||||
height: 120,
|
||||
type: "area",
|
||||
sparkline: {
|
||||
enabled: true,
|
||||
},
|
||||
animations: {
|
||||
speed: 400,
|
||||
},
|
||||
},
|
||||
series: props.series,
|
||||
colors: [primaryColor],
|
||||
fill: {
|
||||
type: "solid",
|
||||
colors: [primaryColor],
|
||||
opacity: 0.15,
|
||||
},
|
||||
stroke: {
|
||||
curve: "smooth",
|
||||
width: 2,
|
||||
},
|
||||
xaxis: props.xaxis,
|
||||
tooltip: {
|
||||
followCursor: true,
|
||||
theme: "dark",
|
||||
custom: function ({ ctx, series, seriesIndex, dataPointIndex, w }: any) {
|
||||
const seriesName = w.config.series[seriesIndex].name;
|
||||
|
||||
return `<div class="rounded-lg pa-1 text-caption">
|
||||
<div class="font-weight-bold">${formatDate(
|
||||
w.globals.categoryLabels[dataPointIndex]
|
||||
)}</div>
|
||||
<div>${series[seriesIndex][dataPointIndex]} ${seriesName}</div>
|
||||
</div>`;
|
||||
},
|
||||
},
|
||||
...props.options,
|
||||
};
|
||||
});
|
||||
|
||||
const loading = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<v-card class="d-flex flex-grow-1 bg-primary-darken-4 pa-3" theme="dark">
|
||||
<!-- loading spinner -->
|
||||
<div v-if="loading" class="d-flex flex-grow-1 align-center justify-center">
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
|
||||
<!-- information -->
|
||||
<div v-else class="d-flex flex-column flex-grow-1">
|
||||
<v-card-title class="d-flex">
|
||||
<div class="font-weight-bold">{{ $t(label) }}</div>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
variant="text"
|
||||
color="primary"
|
||||
class="font-weight-bold"
|
||||
@click="$emit('action-clicked')"
|
||||
>{{ actionLabel }}</v-btn
|
||||
>
|
||||
</v-card-title>
|
||||
|
||||
<div class="d-flex flex-column flex-grow-1">
|
||||
<div class="pa-2">
|
||||
<div class="text-h4">
|
||||
{{ formatCurrency(26358.49) }}
|
||||
</div>
|
||||
<div class="text-primary mt-1">
|
||||
{{ formatCurrency(7123.21) }}
|
||||
{{ $t("dashboard.lastweek") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<div class="px-2 pb-2">
|
||||
<div class="title mb-1 font-weight-bold">
|
||||
{{ $t("dashboard.weeklySales") }}
|
||||
</div>
|
||||
<div class="d-flex align-center">
|
||||
<div class="text-h4">
|
||||
{{ formatCurrency(value) }}
|
||||
</div>
|
||||
<v-spacer></v-spacer>
|
||||
<div class="d-flex flex-column text-right">
|
||||
<div class="font-weight-bold">
|
||||
<percent-trend :value="percentage" />
|
||||
</div>
|
||||
<div class="text-caption">{{ percentageLabel }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<apexchart
|
||||
type="area"
|
||||
height="120"
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
></apexchart>
|
||||
</div>
|
||||
</v-card>
|
||||
</template>
|
||||
81
console-ui/src/components/dashboard/SourcesCard.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<h6 class="text-h6 pa-5 d-flex align-center">
|
||||
<span class="flex-1 font-weight-bold">Traffic Sources</span>
|
||||
</h6>
|
||||
|
||||
<v-chart class="chart" :option="option" autoresize />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { use } from "echarts/core";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { PieChart } from "echarts/charts";
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
} from "echarts/components";
|
||||
import VChart from "vue-echarts";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
PieChart,
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
]);
|
||||
|
||||
const option = ref({
|
||||
color: ["#73BFB8", "#3BA2D5", "#2364AA", "#FEC601", "#0096C7"],
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)",
|
||||
},
|
||||
legend: {
|
||||
// orient: "vertical",
|
||||
top: "0%",
|
||||
left: "center",
|
||||
data: ["Direct", "Email", "Ad Networks", "Video Ads", "Search Engines"],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Access From",
|
||||
type: "pie",
|
||||
radius: ["40%", "70%"],
|
||||
center: ["50%", "50%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" },
|
||||
],
|
||||
label: {
|
||||
show: false,
|
||||
position: "center",
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 2,
|
||||
borderColor: "#fff",
|
||||
borderWidth: 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chart {
|
||||
height: 360px;
|
||||
}
|
||||
</style>
|
||||
158
console-ui/src/components/dashboard/TableCard.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<script setup lang="ts">
|
||||
import CopyLabel from "@/components/common/CopyLabel.vue";
|
||||
const loading = ref(true);
|
||||
|
||||
const headers = [
|
||||
{ text: "Order Id", align: "start", value: "id" },
|
||||
{
|
||||
text: "User",
|
||||
sortable: false,
|
||||
value: "user",
|
||||
},
|
||||
{ text: "Date", value: "date" },
|
||||
{ text: "Company", value: "company" },
|
||||
{ text: "Amount", value: "amount" },
|
||||
{ text: "Status", value: "status" },
|
||||
{ text: "", sortable: false, align: "right", value: "action" },
|
||||
];
|
||||
const items = [
|
||||
{
|
||||
id: "2837",
|
||||
user: {
|
||||
name: "John Simon",
|
||||
email: "johnsimon@blobhill.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=1",
|
||||
},
|
||||
date: "2020-05-10",
|
||||
company: "BlobHill",
|
||||
amount: 52877,
|
||||
status: "PAID",
|
||||
},
|
||||
{
|
||||
id: "2838",
|
||||
user: {
|
||||
name: "Greg Cool J",
|
||||
email: "cool@caprimooner.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=2",
|
||||
},
|
||||
date: "2020-05-11",
|
||||
company: "Caprimooner",
|
||||
amount: 2123,
|
||||
status: "PENDING",
|
||||
},
|
||||
{
|
||||
id: "2839",
|
||||
user: {
|
||||
name: "Samantha Bush",
|
||||
email: "bush@catloveisstilllove.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=3",
|
||||
},
|
||||
date: "2020-05-11",
|
||||
company: "CatLovers",
|
||||
amount: 12313,
|
||||
status: "PENDING",
|
||||
},
|
||||
{
|
||||
id: "2840",
|
||||
user: {
|
||||
name: "Ben Howard",
|
||||
email: "ben@indiecoolers.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=4",
|
||||
},
|
||||
date: "2020-05-12",
|
||||
company: "IndieCoolers",
|
||||
amount: 9873,
|
||||
status: "PAID",
|
||||
},
|
||||
{
|
||||
id: "2841",
|
||||
user: {
|
||||
name: "Jack Candy",
|
||||
email: "jack@candylooove.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=5",
|
||||
},
|
||||
date: "2020-05-13",
|
||||
company: "CandyLooove",
|
||||
amount: 29573,
|
||||
status: "PAID",
|
||||
},
|
||||
];
|
||||
|
||||
const open = (item) => {};
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<!-- loading spinner -->
|
||||
<div
|
||||
v-if="loading"
|
||||
class="h-full d-flex flex-grow-1 align-center justify-center"
|
||||
>
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h6 class="text-h6 px-5 pt-5 d-flex align-center font-weight-bold">
|
||||
<span class="flex-1 font-weight-bold">Table</span>
|
||||
</h6>
|
||||
<perfect-scrollbar style="height: 400px">
|
||||
<v-table class="pa-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="header in headers" :key="header.text">
|
||||
{{ header.text }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr v-for="item in items" :key="item.id">
|
||||
<td class="font-weight-bold">
|
||||
<copy-label :text="`# ${item.id}`" />
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-center py-2">
|
||||
<v-avatar size="40" class="elevation-1 grey lighten-3">
|
||||
<img :src="item.user.avatar" />
|
||||
</v-avatar>
|
||||
<div class="ml-1">
|
||||
<div class="font-weight-bold">{{ item.user.name }}</div>
|
||||
<div class="text-caption">
|
||||
<copy-label :text="item.user.email" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ item.date }}</td>
|
||||
<td>{{ item.company }}</td>
|
||||
<td>{{ item.amount }}</td>
|
||||
<td class="font-weight-bold">
|
||||
<div v-if="item.status === 'PENDING'">
|
||||
<v-icon size="small" color="warning">mdi-circle-medium</v-icon>
|
||||
<span>Pending</span>
|
||||
</div>
|
||||
<div v-if="item.status === 'PAID'">
|
||||
<v-icon size="small" color="success">mdi-circle-medium</v-icon>
|
||||
<span>Paid</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<v-btn
|
||||
size="small"
|
||||
variant="text"
|
||||
icon="mdi-open-in-new"
|
||||
@click="open(item)"
|
||||
>
|
||||
</v-btn>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</perfect-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
176
console-ui/src/components/dashboard/TicketsCard.vue
Normal file
@@ -0,0 +1,176 @@
|
||||
<script setup lang="ts">
|
||||
import CopyLabel from "@/components/common/CopyLabel.vue";
|
||||
const loading = ref(true);
|
||||
|
||||
const headers = [
|
||||
{ text: "Ticket Id", align: "start", value: "id" },
|
||||
{
|
||||
text: "User",
|
||||
sortable: false,
|
||||
value: "user",
|
||||
},
|
||||
{ text: "Priority", value: "priority" },
|
||||
{ text: "Status", value: "status" },
|
||||
{ text: "Create Date", value: "date" },
|
||||
{ text: "", sortable: false, align: "right", value: "action" },
|
||||
];
|
||||
const items = [
|
||||
{
|
||||
id: "423",
|
||||
user: {
|
||||
name: "John Simon",
|
||||
email: "johnsimon@blobhill.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=1",
|
||||
},
|
||||
date: "2020-05-10",
|
||||
priority: "Low",
|
||||
status: "OPEN",
|
||||
},
|
||||
{
|
||||
id: "424",
|
||||
user: {
|
||||
name: "Greg Cool J",
|
||||
email: "cool@caprimooner.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=2",
|
||||
},
|
||||
date: "2020-05-11",
|
||||
priority: "High",
|
||||
status: "CLOSED",
|
||||
},
|
||||
{
|
||||
id: "425",
|
||||
user: {
|
||||
name: "Samantha Bush",
|
||||
email: "bush@catloveisstilllove.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=3",
|
||||
},
|
||||
date: "2020-05-11",
|
||||
priority: "Low",
|
||||
status: "CLOSED",
|
||||
},
|
||||
{
|
||||
id: "426",
|
||||
user: {
|
||||
name: "Ben Howard",
|
||||
email: "ben@indiecoolers.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=4",
|
||||
},
|
||||
date: "2020-05-12",
|
||||
priority: "Low",
|
||||
status: "OPEN",
|
||||
},
|
||||
{
|
||||
id: "427",
|
||||
user: {
|
||||
name: "Jack Candy",
|
||||
email: "jack@candylooove.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=5",
|
||||
},
|
||||
date: "2020-05-13",
|
||||
priority: "High",
|
||||
status: "OPEN",
|
||||
},
|
||||
];
|
||||
|
||||
const open = (item) => {};
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- loading spinner -->
|
||||
<div
|
||||
v-if="loading"
|
||||
class="h-full d-flex flex-grow-1 align-center justify-center"
|
||||
>
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h6 class="text-h6 font-weight-bold pa-5 d-flex align-center">
|
||||
<span class="flex-1">Ticket</span>
|
||||
</h6>
|
||||
<v-table class="pa-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left" v-for="header in headers" :key="header.text">
|
||||
{{ header.text }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in items" :key="item.id">
|
||||
<td class="font-weight-bold">
|
||||
<copy-label :text="`# ${item.id}`" />
|
||||
</td>
|
||||
<td>
|
||||
<copy-label :text="item.user.email" />
|
||||
</td>
|
||||
<td>
|
||||
<v-chip
|
||||
size="small"
|
||||
:color="item.priority === 'High' ? 'pink' : 'primary'"
|
||||
class="font-weight-bold"
|
||||
>
|
||||
{{ item.priority }}</v-chip
|
||||
>
|
||||
</td>
|
||||
|
||||
<td class="font-weight-bold">
|
||||
<div v-if="item.status === 'CLOSED'" class="text-secondary">
|
||||
<v-icon size="small" color="secondary">mdi-circle-medium</v-icon>
|
||||
<span>Closed</span>
|
||||
</div>
|
||||
<div v-if="item.status === 'OPEN'" class="text-success">
|
||||
<v-icon size="small" color="success">mdi-circle-medium</v-icon>
|
||||
<span>Open</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ item.date }}</td>
|
||||
<td>
|
||||
<v-btn
|
||||
elevation="4"
|
||||
variant="elevated"
|
||||
size="small"
|
||||
@click="open(item)"
|
||||
>
|
||||
Open Text
|
||||
</v-btn>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.v-table {
|
||||
table {
|
||||
padding: 4px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
th {
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
transition: box-shadow 0.2s, transform 0.2s;
|
||||
|
||||
&:not(.v-data-table__selected):hover {
|
||||
box-shadow: 0 3px 15px -2px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
110
console-ui/src/components/dashboard/TodoCard.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<script setup lang="ts">
|
||||
import { useTodoStore } from "@/views/app/todo/todoStore";
|
||||
const todoStore = useTodoStore();
|
||||
|
||||
const loading = ref(true);
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
const searchKey = ref("");
|
||||
const filterdTodoList = computed(() => {
|
||||
return todoStore.getTodoList.filter((todo) => {
|
||||
return todo.title.toLowerCase().includes(searchKey.value.toLowerCase());
|
||||
});
|
||||
});
|
||||
|
||||
const getLabelColor = (id: string) => {
|
||||
// Find the label by id from the labels array
|
||||
const label = todoStore.labels.find((l) => l.id === id);
|
||||
// Return the color for that label, or an empty string
|
||||
return label ? label.color : "";
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<!-- loading spinner -->
|
||||
<div
|
||||
v-if="loading"
|
||||
class="h-full d-flex flex-grow-1 align-center justify-center"
|
||||
>
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<v-text-field
|
||||
clearable
|
||||
variant="solo"
|
||||
class="elevation-1 ma-3"
|
||||
hide-details
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
placeholder="Filter Tasks"
|
||||
v-model="searchKey"
|
||||
></v-text-field>
|
||||
|
||||
<perfect-scrollbar class="todo-list">
|
||||
<transition-group name="fade">
|
||||
<div v-for="todo in filterdTodoList" :key="todo.id">
|
||||
<div class="todo-item d-flex align-center pa-5">
|
||||
<v-checkbox-btn
|
||||
v-model="todo.completed"
|
||||
color="primary"
|
||||
class="pe-2"
|
||||
></v-checkbox-btn>
|
||||
<v-avatar size="40">
|
||||
<v-img
|
||||
src="https://avatars.githubusercontent.com/u/35951244?v=4"
|
||||
alt="alt"
|
||||
/>
|
||||
</v-avatar>
|
||||
<div class="flex-1 mx-5">
|
||||
<div
|
||||
class="font-weight-bold"
|
||||
:class="todo.completed ? 'text-decoration-line-through' : ''"
|
||||
>
|
||||
{{ todo.title }}
|
||||
</div>
|
||||
<div
|
||||
:class="todo.completed ? 'text-decoration-line-through' : ''"
|
||||
>
|
||||
{{ todo.detail }}
|
||||
</div>
|
||||
<div>
|
||||
<v-chip
|
||||
size="x-small"
|
||||
variant="outlined"
|
||||
class="mr-1 mt-1"
|
||||
:color="getLabelColor(tag)"
|
||||
v-for="tag in todo.tags"
|
||||
>
|
||||
{{ tag }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
<v-btn
|
||||
icon="mdi-delete-outline"
|
||||
variant="text"
|
||||
@click="todoStore.deleteTodoById(todo.id)"
|
||||
></v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
</perfect-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.todo-list {
|
||||
max-height: 400px;
|
||||
overflow: scroll;
|
||||
.todo-item {
|
||||
transition: all 0.3s;
|
||||
&:hover {
|
||||
transition: all 0.3s;
|
||||
background-color: rgba(99, 99, 99, 0.2);
|
||||
box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
180
console-ui/src/components/dashboard/TrackCard.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<!-- loading spinner -->
|
||||
<div
|
||||
v-if="loading"
|
||||
class="h-full d-flex flex-grow-1 align-center justify-center"
|
||||
>
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h6 class="text-h6 pa-5 d-flex align-center">
|
||||
<span class="flex-1">Table</span>
|
||||
</h6>
|
||||
<v-table class="pa-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left" v-for="header in headers" :key="header.text">
|
||||
{{ header.text }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in items" :key="item.id">
|
||||
<td>#{{ item.id }}</td>
|
||||
<td>
|
||||
<div class="d-flex align-center py-1">
|
||||
<v-avatar size="40" class="elevation-1 grey lighten-3">
|
||||
<img :src="item.user.avatar" />
|
||||
</v-avatar>
|
||||
<div class="ml-1">
|
||||
<div class="font-weight-bold">{{ item.user.name }}</div>
|
||||
<div class="caption">
|
||||
{{ item.user.email }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ item.date }}</td>
|
||||
<td>{{ item.company }}</td>
|
||||
<td>{{ item.amount }}</td>
|
||||
<td>
|
||||
<div v-if="item.status === 'PENDING'" class="text-warning">
|
||||
<v-icon size="small" color="warning">mdi-circle-medium</v-icon>
|
||||
<span>Pending</span>
|
||||
</div>
|
||||
<div v-if="item.status === 'PAID'" class="text-success">
|
||||
<v-icon size="small" color="success">mdi-circle-medium</v-icon>
|
||||
<span>Paid</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<v-btn
|
||||
size="small"
|
||||
variant="text"
|
||||
icon="mdi-open-in-new"
|
||||
@click="open(item)"
|
||||
>
|
||||
</v-btn>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const loading = ref(true);
|
||||
|
||||
const headers = [
|
||||
{ text: "Order Id", align: "start", value: "id" },
|
||||
{
|
||||
text: "User",
|
||||
sortable: false,
|
||||
value: "user",
|
||||
},
|
||||
{ text: "Date", value: "date" },
|
||||
{ text: "Company", value: "company" },
|
||||
{ text: "Amount", value: "amount" },
|
||||
{ text: "Status", value: "status" },
|
||||
{ text: "", sortable: false, align: "right", value: "action" },
|
||||
];
|
||||
const items = [
|
||||
{
|
||||
id: "2837",
|
||||
user: {
|
||||
name: "John Simon",
|
||||
email: "johnsimon@blobhill.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=1",
|
||||
},
|
||||
date: "2020-05-10",
|
||||
company: "BlobHill",
|
||||
amount: 52877,
|
||||
status: "PAID",
|
||||
},
|
||||
{
|
||||
id: "2838",
|
||||
user: {
|
||||
name: "Greg Cool J",
|
||||
email: "cool@caprimooner.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=2",
|
||||
},
|
||||
date: "2020-05-11",
|
||||
company: "Caprimooner",
|
||||
amount: 2123,
|
||||
status: "PENDING",
|
||||
},
|
||||
{
|
||||
id: "2839",
|
||||
user: {
|
||||
name: "Samantha Bush",
|
||||
email: "bush@catloveisstilllove.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=3",
|
||||
},
|
||||
date: "2020-05-11",
|
||||
company: "CatLovers",
|
||||
amount: 12313,
|
||||
status: "PENDING",
|
||||
},
|
||||
{
|
||||
id: "2840",
|
||||
user: {
|
||||
name: "Ben Howard",
|
||||
email: "ben@indiecoolers.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=4",
|
||||
},
|
||||
date: "2020-05-12",
|
||||
company: "IndieCoolers",
|
||||
amount: 9873,
|
||||
status: "PAID",
|
||||
},
|
||||
{
|
||||
id: "2841",
|
||||
user: {
|
||||
name: "Jack Candy",
|
||||
email: "jack@candylooove.com",
|
||||
avatar: "https://i.pravatar.cc/150?img=5",
|
||||
},
|
||||
date: "2020-05-13",
|
||||
company: "CandyLooove",
|
||||
amount: 29573,
|
||||
status: "PAID",
|
||||
},
|
||||
];
|
||||
|
||||
const open = (item) => {};
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.v-table {
|
||||
table {
|
||||
padding: 4px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
th {
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
transition: box-shadow 0.2s, transform 0.2s;
|
||||
|
||||
&:not(.v-data-table__selected):hover {
|
||||
box-shadow: 0 3px 15px -2px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
91
console-ui/src/components/loading/Loading01.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<span class="loader"></span>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
<style scoped>
|
||||
.loader {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.loader::before {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -24px;
|
||||
animation: animloader 4s ease infinite;
|
||||
}
|
||||
.loader::after {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
|
||||
animation: animloader2 2s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes animloader {
|
||||
0% {
|
||||
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0),
|
||||
24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0);
|
||||
}
|
||||
12% {
|
||||
box-shadow: 0 24px white, 24px 24px rgba(255, 255, 255, 0),
|
||||
24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
box-shadow: 0 24px white, 24px 24px white, 24px 48px rgba(255, 255, 255, 0),
|
||||
0px 48px rgba(255, 255, 255, 0);
|
||||
}
|
||||
37% {
|
||||
box-shadow: 0 24px white, 24px 24px white, 24px 48px white,
|
||||
0px 48px rgba(255, 255, 255, 0);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 24px white, 24px 24px white, 24px 48px white, 0px 48px white;
|
||||
}
|
||||
62% {
|
||||
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px white, 24px 48px white,
|
||||
0px 48px white;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0),
|
||||
24px 48px white, 0px 48px white;
|
||||
}
|
||||
87% {
|
||||
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0),
|
||||
24px 48px rgba(255, 255, 255, 0), 0px 48px white;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0),
|
||||
24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animloader2 {
|
||||
0% {
|
||||
transform: translate(0, 0) rotateX(0) rotateY(0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(100%, 0) rotateX(0) rotateY(180deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate(0, 0) rotateX(0) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
68
console-ui/src/components/loading/Loading02.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<span class="loader"></span>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.loader {
|
||||
width: 200px;
|
||||
height: 140px;
|
||||
background: #979794;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
.loader:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
border-radius: 8px;
|
||||
background: #f5f5f5 no-repeat;
|
||||
background-size: 60px 10px;
|
||||
background-image: linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0);
|
||||
|
||||
background-position: 15px 30px, 15px 60px, 15px 90px, 105px 30px, 105px 60px,
|
||||
105px 90px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.loader:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: calc(50% - 10px);
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
border-radius: 8px;
|
||||
background: #fff no-repeat;
|
||||
background-size: 60px 10px;
|
||||
background-image: linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0),
|
||||
linear-gradient(#ddd 100px, transparent 0);
|
||||
background-position: 50% 30px, 50% 60px, 50% 90px;
|
||||
transform: rotateY(0deg);
|
||||
transform-origin: left center;
|
||||
animation: paging 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes paging {
|
||||
to {
|
||||
transform: rotateY(-180deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
70
console-ui/src/components/loading/Loading03.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<span class="loader"></span>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.loader {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
}
|
||||
.loader:before {
|
||||
content: "";
|
||||
width: 48px;
|
||||
height: 5px;
|
||||
background: #000;
|
||||
opacity: 0.25;
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 0;
|
||||
border-radius: 50%;
|
||||
animation: shadow 0.5s linear infinite;
|
||||
}
|
||||
.loader:after {
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #29b6f6;
|
||||
animation: bxSpin 0.5s linear infinite;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
@keyframes bxSpin {
|
||||
17% {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
25% {
|
||||
transform: translateY(9px) rotate(22.5deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(18px) scale(1, 0.9) rotate(45deg);
|
||||
border-bottom-right-radius: 40px;
|
||||
}
|
||||
75% {
|
||||
transform: translateY(9px) rotate(67.5deg);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0) rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shadow {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.2, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
104
console-ui/src/components/navigation/MainMenu.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<script setup lang="ts">
|
||||
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
|
||||
const customizeTheme = useCustomizeThemeStore();
|
||||
|
||||
const props = defineProps({
|
||||
// Data
|
||||
menu: {
|
||||
type: Array<any>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<template>
|
||||
<v-list nav dense color="primary">
|
||||
<template v-for="menuArea in props.menu" :key="menuArea.key">
|
||||
<div
|
||||
v-if="!customizeTheme.miniSidebar && (menuArea.key || menuArea.text)"
|
||||
class="pa-1 mt-2 text-overline"
|
||||
>
|
||||
{{ menuArea.key ? $t(menuArea.key) : menuArea.text }}
|
||||
</div>
|
||||
<template v-if="menuArea.items">
|
||||
<template v-for="menuItem in menuArea.items" :key="menuItem.key">
|
||||
<!-- menu level 1 -->
|
||||
<v-list-item
|
||||
v-if="!menuItem.items"
|
||||
:to="menuItem.link"
|
||||
:prepend-icon="menuItem.icon || 'mdi-circle-medium'"
|
||||
:active-class="`active-nav-${customizeTheme.primaryColor.colorName}`"
|
||||
density="compact"
|
||||
>
|
||||
<v-list-item-title
|
||||
v-text="menuItem.key ? $t(menuItem.key) : menuItem.text"
|
||||
></v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-group v-else :value="menuItem.items">
|
||||
<!-- subMenu activator -->
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-list-item
|
||||
v-bind="props"
|
||||
:prepend-icon="menuItem.icon || 'mdi-circle-medium'"
|
||||
:title="menuItem.key ? $t(menuItem.key) : menuItem.text"
|
||||
>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<!-- menu level 2 -->
|
||||
<v-list-item
|
||||
v-for="subMenuItem in menuItem.items"
|
||||
:key="subMenuItem.key"
|
||||
:prepend-icon="subMenuItem.icon || 'mdi-circle-medium'"
|
||||
:title="subMenuItem.key ? $t(subMenuItem.key) : subMenuItem.text"
|
||||
:to="subMenuItem.link"
|
||||
density="compact"
|
||||
></v-list-item>
|
||||
</v-list-group>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.v-list-group .v-list-item {
|
||||
padding-left: 8px !important;
|
||||
}
|
||||
|
||||
.active-nav-grey {
|
||||
border-left: 5px solid;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(to bottom, #3a456c, #a4abbb);
|
||||
}
|
||||
|
||||
.active-nav-purple {
|
||||
border-left: 5px solid;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(to bottom, #e82893, #954bcb);
|
||||
}
|
||||
|
||||
.active-nav-info {
|
||||
border-left: 5px solid;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(to bottom, #487afa, #3fc7f3);
|
||||
}
|
||||
|
||||
.active-nav-success {
|
||||
border-left: 5px solid;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(to bottom, #45b95b, #96dd4c);
|
||||
}
|
||||
|
||||
.active-nav-warning {
|
||||
border-left: 5px solid;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(to bottom, #f0635d, #edc252);
|
||||
}
|
||||
|
||||
.active-nav-error {
|
||||
border-left: 5px solid;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(to bottom, #ea373a, #f07285);
|
||||
}
|
||||
</style>
|
||||
99
console-ui/src/components/navigation/MainSiderbar.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import configs from "@/configs";
|
||||
import MainMenu from "@/components/navigation/MainMenu.vue";
|
||||
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
|
||||
import { Icon } from "@iconify/vue";
|
||||
const customizeTheme = useCustomizeThemeStore();
|
||||
const navigation = ref(configs.navigation);
|
||||
|
||||
const openGithubSite = () => {
|
||||
window.open("https://github.com/yangjiakai", "_blank");
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer
|
||||
v-model="customizeTheme.mainSidebar"
|
||||
elevation="1"
|
||||
id="mainMenu"
|
||||
>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!---Top Area -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<template v-if="!customizeTheme.miniSidebar" v-slot:prepend>
|
||||
<v-card
|
||||
elevation="0"
|
||||
height="100"
|
||||
class="d-flex align-center justify-center"
|
||||
>
|
||||
<img
|
||||
v-if="customizeTheme.darkTheme"
|
||||
width="200"
|
||||
src="@/assets/logo_dark.svg"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
v-else="customizeTheme.darkTheme"
|
||||
width="200"
|
||||
src="@/assets/logo_light.svg"
|
||||
alt=""
|
||||
/>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!---Nav List -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<perfect-scrollbar class="scrollnav">
|
||||
<main-menu :menu="navigation.menu"></main-menu>
|
||||
</perfect-scrollbar>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!---Bottom Area -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<template v-if="!customizeTheme.miniSidebar" v-slot:append>
|
||||
<v-card theme="dark" height="225" class="pa-3" variant="text">
|
||||
<v-card
|
||||
class="d-flex flex-column gradient pa-2"
|
||||
:class="customizeTheme.primaryColor.colorName"
|
||||
height="200"
|
||||
>
|
||||
<v-card-title>
|
||||
<v-btn
|
||||
class="mr-2"
|
||||
size="40"
|
||||
color="white"
|
||||
:class="`text-${customizeTheme.primaryColor.colorName}`"
|
||||
icon
|
||||
>
|
||||
<Icon width="30" icon="line-md:github-loop" />
|
||||
</v-btn>
|
||||
Yang J.K.
|
||||
</v-card-title>
|
||||
<v-card-subtitle> </v-card-subtitle>
|
||||
<v-card-text>
|
||||
<div><b>Github:</b></div>
|
||||
<div>github.com/yangjiakai</div>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
color="white"
|
||||
block
|
||||
prepend-icon="mdi-thumb-up-outline"
|
||||
variant="elevated"
|
||||
@click="openGithubSite"
|
||||
>
|
||||
Star-Me
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
75
console-ui/src/components/toolbar/MainAppbar.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
|
||||
import ToolbarLanguage from "@/components/toolbar/ToolbarLanguage.vue";
|
||||
import ToolbarNotifications from "./ToolbarNotifications.vue";
|
||||
import ToolbarUser from "./ToolbarUser.vue";
|
||||
import { useTodoStore } from "@/views/app/todo/todoStore";
|
||||
|
||||
const todoStore = useTodoStore();
|
||||
const customizeTheme = useCustomizeThemeStore();
|
||||
const showMobileSearch = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!--App Bar -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-app-bar>
|
||||
<!-- search input mobile -->
|
||||
<div class="d-flex flex-grow-1 align-center" v-if="showMobileSearch">
|
||||
<v-text-field
|
||||
color="primary"
|
||||
class="elevation-1"
|
||||
variant="solo"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
append-inner-icon="mdi-close"
|
||||
@click:append-inner="showMobileSearch = false"
|
||||
hide-details
|
||||
placeholder="Search"
|
||||
></v-text-field>
|
||||
</div>
|
||||
<div v-else class="d-flex flex-grow-1 align-center">
|
||||
<v-app-bar-nav-icon
|
||||
@click="customizeTheme.mainSidebar = !customizeTheme.mainSidebar"
|
||||
></v-app-bar-nav-icon>
|
||||
<v-toolbar-title></v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn class="d-block d-md-none" icon @click="showMobileSearch = true">
|
||||
<v-icon>mdi-magnify</v-icon>
|
||||
</v-btn>
|
||||
<!-- search input desktop -->
|
||||
|
||||
<v-text-field
|
||||
color="primary"
|
||||
class="d-none d-md-block elevation-1"
|
||||
variant="solo"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
hide-details
|
||||
placeholder="Search"
|
||||
></v-text-field>
|
||||
|
||||
<v-btn class="text-none" stacked>
|
||||
<v-badge dot color="success">
|
||||
<v-icon>mdi-account-multiple-outline</v-icon>
|
||||
</v-badge>
|
||||
</v-btn>
|
||||
|
||||
<v-btn to="/apps/todo" class="text-none" stacked>
|
||||
<v-badge :content="`${todoStore.getTodoList.length} +`" color="error">
|
||||
<v-icon>mdi-calendar-check</v-icon>
|
||||
</v-badge>
|
||||
</v-btn>
|
||||
<ToolbarLanguage />
|
||||
<ToolbarNotifications />
|
||||
<ToolbarUser />
|
||||
</div>
|
||||
</v-app-bar>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
84
console-ui/src/components/toolbar/StatusMenu.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<!--
|
||||
* @Component:
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
interface UserStatus {
|
||||
code: string;
|
||||
name: string;
|
||||
label: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
const userStatusList = [
|
||||
{
|
||||
code: "online",
|
||||
name: "us",
|
||||
label: "Online",
|
||||
color: "success",
|
||||
},
|
||||
{
|
||||
code: "away",
|
||||
name: "cn",
|
||||
label: "Away",
|
||||
color: "warning",
|
||||
},
|
||||
{
|
||||
code: "busy",
|
||||
name: "jp",
|
||||
label: "Busy",
|
||||
color: "error",
|
||||
},
|
||||
{
|
||||
code: "offline",
|
||||
name: "kr",
|
||||
label: "Offline",
|
||||
color: "grey",
|
||||
},
|
||||
];
|
||||
|
||||
const currentStatus = ref<UserStatus>({
|
||||
code: "online",
|
||||
name: "us",
|
||||
label: "Online",
|
||||
color: "success",
|
||||
});
|
||||
|
||||
const setStatus = (status: string) => {
|
||||
currentStatus.value = userStatusList.find(
|
||||
(userStatus) => userStatus.code === status
|
||||
) as UserStatus;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-menu scroll-y :close-on-content-click="false">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
width="60"
|
||||
variant="text"
|
||||
size="small"
|
||||
v-bind="props"
|
||||
:color="currentStatus.color"
|
||||
>
|
||||
{{ currentStatus.label }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list elevation="1">
|
||||
<v-list-item
|
||||
v-for="status in userStatusList"
|
||||
:key="status.code"
|
||||
@click="setStatus(status.code)"
|
||||
density="compact"
|
||||
>
|
||||
<v-list-item-title class="text-body-2">
|
||||
<v-icon size="small" :color="status.color">mdi-circle-medium</v-icon>
|
||||
{{ status.label }}</v-list-item-title
|
||||
>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
43
console-ui/src/components/toolbar/ToolbarLanguage.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<v-menu scroll-y>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn width="100" v-bind="props">
|
||||
<Icon :icon="`twemoji:flag-${currentLocale.name}`" class="mr-2" />
|
||||
<span class="text-body-2">{{ currentLocale.label }}</span>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list elevation="1" nav>
|
||||
<v-list-item
|
||||
v-for="locale in availableLocaleList"
|
||||
:key="locale.code"
|
||||
@click="setLocale(locale.code)"
|
||||
density="compact"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<Icon :icon="`twemoji:flag-${locale.name}`" class="mr-2" />
|
||||
</template>
|
||||
|
||||
<v-list-item-title> {{ locale.label }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import config from "@/configs";
|
||||
import { Icon } from "@iconify/vue";
|
||||
import { useLocale } from "vuetify";
|
||||
const { current } = useLocale();
|
||||
const { availableLocales } = config.locales;
|
||||
|
||||
const availableLocaleList = computed(() => {
|
||||
return availableLocales.filter((item) => item.code !== current.value);
|
||||
});
|
||||
|
||||
const currentLocale = computed(() => {
|
||||
return availableLocales.filter((item) => item.code === current.value)[0];
|
||||
});
|
||||
|
||||
const setLocale = (locale) => {
|
||||
current.value = locale;
|
||||
};
|
||||
</script>
|
||||
107
console-ui/src/components/toolbar/ToolbarNotifications.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<!--
|
||||
* @Component: ToolbarNotifications
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
const messages = [
|
||||
{
|
||||
title: "Brunch this weekend?",
|
||||
color: "primary",
|
||||
icon: "mdi-account-circle",
|
||||
subtitle:
|
||||
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sint, repudiandae?",
|
||||
time: "3 min",
|
||||
},
|
||||
{
|
||||
title: "Summer BBQ",
|
||||
color: "success",
|
||||
icon: "mdi-email-outline",
|
||||
subtitle:
|
||||
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sint, repudiandae?",
|
||||
time: "3 min",
|
||||
},
|
||||
{
|
||||
title: "Oui oui",
|
||||
color: "teal lighten-1",
|
||||
icon: "mdi-airplane-landing",
|
||||
subtitle:
|
||||
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sint, repudiandae?",
|
||||
time: "4 min",
|
||||
},
|
||||
{
|
||||
title: "Disk capacity is at maximum",
|
||||
color: "teal accent-3",
|
||||
icon: "mdi-server",
|
||||
subtitle:
|
||||
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sint, repudiandae?",
|
||||
time: "3 hr",
|
||||
},
|
||||
{
|
||||
title: "Recipe to try",
|
||||
color: "blue-grey lighten-2",
|
||||
icon: "mdi-noodles",
|
||||
subtitle:
|
||||
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sint, repudiandae?",
|
||||
time: "8 hr",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-menu location="bottom right" transition="slide-y-transition">
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Activator Btn -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn icon v-bind="props" class="text-none">
|
||||
<v-badge content="2" color="error">
|
||||
<v-icon>mdi-bell-outline</v-icon>
|
||||
</v-badge>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list elevation="1" lines="three" density="compact" max-width="400">
|
||||
<v-list-subheader>Notifications</v-list-subheader>
|
||||
<v-list-item v-for="(message, i) in messages" :key="i" @click="">
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Prepend-->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<template v-slot:prepend>
|
||||
<v-avatar size="40" :color="message.color">
|
||||
<v-icon color="white">{{ message.icon }}</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Append-->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<template v-slot:append>
|
||||
<div class="full-h d-flex align-center">
|
||||
<span class="text-body-2 text-grey"> {{ message.time }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Main Content-->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<div>
|
||||
<v-list-item-title class="font-weight-bold text-primary">{{
|
||||
message.title
|
||||
}}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ message.subtitle }}</v-list-item-subtitle>
|
||||
</div>
|
||||
</v-list-item>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- See all Btn-->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<div class="text-center py-5">
|
||||
<v-btn size="small" variant="elevated" elevation="1"> See all </v-btn>
|
||||
</div>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// ::v-deep .v-list-item__append,
|
||||
// ::v-deep .v-list-item__prepend {
|
||||
// height: 100%;
|
||||
// }
|
||||
</style>
|
||||
176
console-ui/src/components/toolbar/ToolbarUser.vue
Normal file
@@ -0,0 +1,176 @@
|
||||
<!--
|
||||
* @Component: ToolbarNotifications
|
||||
* @Maintainer: J.K. Yang
|
||||
* @Description:
|
||||
-->
|
||||
<script setup lang="ts">
|
||||
import StatusMenu from "./StatusMenu.vue";
|
||||
import { useAuthStore } from "@/stores/authStore";
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const handleLogout = () => {
|
||||
authStore.logout();
|
||||
console.log("---");
|
||||
console.log(router);
|
||||
};
|
||||
|
||||
const navs = [
|
||||
{
|
||||
title: "Profile Details",
|
||||
key: "menu.profileDetails",
|
||||
link: "/profile",
|
||||
icon: "mdi-account-box-outline",
|
||||
},
|
||||
{
|
||||
title: "Plans and Billing",
|
||||
key: "menu.plansAndBilling",
|
||||
link: "/plans-and-billing",
|
||||
icon: "mdi-credit-card-outline",
|
||||
},
|
||||
{
|
||||
title: "Team",
|
||||
key: "menu.team",
|
||||
link: "/team",
|
||||
icon: "mdi-account-group-outline",
|
||||
},
|
||||
{
|
||||
title: "API Dashboard",
|
||||
key: "menu.apiDashboard",
|
||||
link: "/api-dashboard",
|
||||
icon: "mdi-monitor-dashboard",
|
||||
},
|
||||
{
|
||||
title: "Integrations",
|
||||
key: "menu.integrations",
|
||||
link: "/integrations",
|
||||
icon: "mdi-puzzle-outline",
|
||||
},
|
||||
{
|
||||
title: "Ask the Community",
|
||||
key: "menu.askCommunity",
|
||||
link: "/ask-the-community",
|
||||
icon: "mdi-help-circle-outline",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-menu
|
||||
:close-on-content-click="false"
|
||||
location="bottom right"
|
||||
transition="slide-y-transition"
|
||||
>
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Activator Btn -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn class="mx-2" icon v-bind="props">
|
||||
<v-badge content="2" color="success" dot bordered>
|
||||
<v-avatar size="40">
|
||||
<v-img
|
||||
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwrAiMevuwrbU9o0Ck2paVf4ufHUDb2dU48MEDrAlrQw&s"
|
||||
></v-img>
|
||||
</v-avatar>
|
||||
</v-badge>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card max-width="300">
|
||||
<v-list lines="three" density="compact">
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Profile Area -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-list-item to="/profile">
|
||||
<template v-slot:prepend>
|
||||
<v-avatar size="40">
|
||||
<v-img
|
||||
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwrAiMevuwrbU9o0Ck2paVf4ufHUDb2dU48MEDrAlrQw&s"
|
||||
></v-img>
|
||||
</v-avatar>
|
||||
</template>
|
||||
|
||||
<v-list-item-title class="font-weight-bold text-primary">
|
||||
YANG J.K.
|
||||
<StatusMenu />
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
<!-- {{ $store.state.user.email }} -->
|
||||
yjkbako@gmail.com
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<hr />
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Menu Area -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
|
||||
<v-list variant="flat" elevation="0" :lines="false" density="compact">
|
||||
<v-list-item
|
||||
color="primary"
|
||||
v-for="(nav, i) in navs"
|
||||
:key="i"
|
||||
:to="nav.link"
|
||||
link
|
||||
density="compact"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<v-avatar size="30">
|
||||
<v-icon>{{ nav.icon }}</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<v-list-item-subtitle class="text-body-2">{{
|
||||
nav.title
|
||||
}}</v-list-item-subtitle>
|
||||
</div>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<hr />
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Logout Area -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-list variant="flat" elevation="0" :lines="false" density="compact">
|
||||
<v-list-item color="primary" to="nav.link" link density="compact">
|
||||
<template v-slot:prepend>
|
||||
<v-avatar size="30">
|
||||
<v-icon>mdi-lifebuoy</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<v-list-item-subtitle class="text-body-2">
|
||||
Help Center
|
||||
</v-list-item-subtitle>
|
||||
</div>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
color="primary"
|
||||
link
|
||||
@click="handleLogout"
|
||||
density="compact"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<v-avatar size="30">
|
||||
<v-icon>mdi-logout</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<v-list-item-subtitle class="text-body-2">
|
||||
Logout
|
||||
</v-list-item-subtitle>
|
||||
</div>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// ::v-deep .v-list-item__append,
|
||||
// ::v-deep .v-list-item__prepend {
|
||||
// height: 100%;
|
||||
// }
|
||||
</style>
|
||||
34
console-ui/src/configs/currencies.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
const config: CurrencyConfig.Config = {
|
||||
currency: {
|
||||
label: "USD",
|
||||
decimalDigits: 2,
|
||||
decimalSeparator: ".",
|
||||
thousandsSeparator: ",",
|
||||
currencySymbol: "$",
|
||||
currencySymbolNumberOfSpaces: 0,
|
||||
currencySymbolPosition: "left",
|
||||
},
|
||||
|
||||
availableCurrencies: [
|
||||
{
|
||||
label: "USD",
|
||||
decimalDigits: 2,
|
||||
decimalSeparator: ".",
|
||||
thousandsSeparator: ",",
|
||||
currencySymbol: "$",
|
||||
currencySymbolNumberOfSpaces: 0,
|
||||
currencySymbolPosition: "left",
|
||||
},
|
||||
{
|
||||
label: "EUR",
|
||||
decimalDigits: 2,
|
||||
decimalSeparator: ".",
|
||||
thousandsSeparator: ",",
|
||||
currencySymbol: "€",
|
||||
currencySymbolNumberOfSpaces: 1,
|
||||
currencySymbolPosition: "right",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
14
console-ui/src/configs/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import navigation from "./navigation";
|
||||
import locales from "./locales";
|
||||
import currency from "./currencies";
|
||||
export default {
|
||||
// product display information
|
||||
product: {
|
||||
name: "ChopperBot",
|
||||
version: "1.0.0",
|
||||
},
|
||||
|
||||
navigation,
|
||||
locales,
|
||||
currency,
|
||||
};
|
||||