From bd812756b7107d22cd4536b603ca3ee76cbce29f Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:38:17 +0100 Subject: [PATCH 01/27] chore: fix README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a4a068..ebb7a4d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Status iterface for ZTerton services +# Status interface for ZTerton services Fork me on GitHub From 971cdc87d5888668c02a87f11d02d88b816de210 Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:40:34 +0100 Subject: [PATCH 02/27] chore: fix svg --- assets/images/status.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/images/status.svg b/assets/images/status.svg index 3b7917e..dd647f8 100644 --- a/assets/images/status.svg +++ b/assets/images/status.svg @@ -1 +1 @@ -Artboard 1Status \ No newline at end of file +Artboard 1Status \ No newline at end of file From d3e880d1d42c374b63d6e024b546d4c465d1585c Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:42:01 +0100 Subject: [PATCH 03/27] chore: fix svg --- assets/images/status.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/images/status.svg b/assets/images/status.svg index dd647f8..7305ce8 100644 --- a/assets/images/status.svg +++ b/assets/images/status.svg @@ -1 +1 @@ -Artboard 1Status \ No newline at end of file +Recurso 4Status \ No newline at end of file From 49e9edae14e77c79867039f4e4885a7da6d3580a Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:42:52 +0100 Subject: [PATCH 04/27] chore: add src --- src/App.vue | 26 ++ src/components/AccordionView.vue | 46 ++ src/components/CloudGroups.vue | 63 +++ src/components/CloudServices.vue | 99 +++++ src/components/Footer.vue | 16 + src/components/NavMenu.vue | 107 +++++ src/components/ProfileView.vue | 125 ++++++ src/components/README.md | 9 + src/components/icons/AppImg.vue | 5 + src/components/icons/AppLogoText.vue | 5 + src/components/icons/AppLogoV.vue | 7 + src/components/menus/MenuLocales.vue | 99 +++++ src/hooks/useState.ts | 46 ++ src/hooks/utils.ts | 341 +++++++++++++++ src/layouts/AppLayout.vue | 7 + src/layouts/GuestLayout.vue | 7 + src/layouts/Page404.vue | 27 ++ src/layouts/_AppLayout.vue | 300 +++++++++++++ src/layouts/default.vue | 9 + src/layouts/home.vue | 30 ++ src/logic/dark.ts | 2 + src/logic/index.ts | 1 + src/main.ts | 53 +++ src/modules/README.md | 11 + src/modules/i18n.ts | 25 ++ src/modules/nprogress.ts | 9 + src/modules/sw.ts | 12 + src/pages/README.md | 20 + src/pages/[...all].vue | 5 + src/pages/base.vue | 52 +++ src/pages/hi/[name].vue | 27 ++ src/router.ts | 191 +++++++++ src/shims.d.ts | 57 +++ src/store/index.ts | 61 +++ src/store/modules/app/check/actions.ts | 44 ++ src/store/modules/app/check/getters.ts | 13 + src/store/modules/app/check/index.ts | 49 +++ src/store/modules/app/check/mutations.ts | 48 +++ src/store/modules/app/data/actions.ts | 44 ++ src/store/modules/app/data/getters.ts | 13 + src/store/modules/app/data/index.ts | 49 +++ src/store/modules/app/data/mutations.ts | 48 +++ src/store/modules/app/defs/actions.ts | 44 ++ src/store/modules/app/defs/getters.ts | 13 + src/store/modules/app/defs/index.ts | 49 +++ src/store/modules/app/defs/mutations.ts | 47 +++ src/store/modules/app/index.ts | 35 ++ src/store/modules/app/lang/actions.ts | 68 +++ src/store/modules/app/lang/getters.ts | 25 ++ src/store/modules/app/lang/index.ts | 51 +++ src/store/modules/app/lang/mutations.ts | 108 +++++ src/store/modules/app/profile/actions.ts | 44 ++ src/store/modules/app/profile/getters.ts | 13 + src/store/modules/app/profile/index.ts | 49 +++ src/store/modules/app/profile/mutations.ts | 37 ++ src/store/modules/index.ts | 1 + src/store/store_module.ts | 97 +++++ src/store/types.ts | 78 ++++ src/styles/main.css | 25 ++ src/typs/clouds/index.ts | 56 +++ src/typs/index.ts | 13 + src/views/404.vue | 26 ++ src/views/Home.vue | 168 ++++++++ src/views/Login.vue | 470 +++++++++++++++++++++ src/views/Logout.vue | 130 ++++++ 65 files changed, 3855 insertions(+) create mode 100644 src/App.vue create mode 100644 src/components/AccordionView.vue create mode 100644 src/components/CloudGroups.vue create mode 100644 src/components/CloudServices.vue create mode 100644 src/components/Footer.vue create mode 100644 src/components/NavMenu.vue create mode 100644 src/components/ProfileView.vue create mode 100644 src/components/README.md create mode 100644 src/components/icons/AppImg.vue create mode 100644 src/components/icons/AppLogoText.vue create mode 100644 src/components/icons/AppLogoV.vue create mode 100644 src/components/menus/MenuLocales.vue create mode 100644 src/hooks/useState.ts create mode 100644 src/hooks/utils.ts create mode 100644 src/layouts/AppLayout.vue create mode 100644 src/layouts/GuestLayout.vue create mode 100644 src/layouts/Page404.vue create mode 100644 src/layouts/_AppLayout.vue create mode 100644 src/layouts/default.vue create mode 100644 src/layouts/home.vue create mode 100644 src/logic/dark.ts create mode 100644 src/logic/index.ts create mode 100644 src/main.ts create mode 100644 src/modules/README.md create mode 100644 src/modules/i18n.ts create mode 100644 src/modules/nprogress.ts create mode 100644 src/modules/sw.ts create mode 100644 src/pages/README.md create mode 100755 src/pages/[...all].vue create mode 100644 src/pages/base.vue create mode 100644 src/pages/hi/[name].vue create mode 100644 src/router.ts create mode 100644 src/shims.d.ts create mode 100644 src/store/index.ts create mode 100644 src/store/modules/app/check/actions.ts create mode 100644 src/store/modules/app/check/getters.ts create mode 100644 src/store/modules/app/check/index.ts create mode 100644 src/store/modules/app/check/mutations.ts create mode 100644 src/store/modules/app/data/actions.ts create mode 100644 src/store/modules/app/data/getters.ts create mode 100644 src/store/modules/app/data/index.ts create mode 100644 src/store/modules/app/data/mutations.ts create mode 100644 src/store/modules/app/defs/actions.ts create mode 100644 src/store/modules/app/defs/getters.ts create mode 100644 src/store/modules/app/defs/index.ts create mode 100644 src/store/modules/app/defs/mutations.ts create mode 100644 src/store/modules/app/index.ts create mode 100644 src/store/modules/app/lang/actions.ts create mode 100644 src/store/modules/app/lang/getters.ts create mode 100644 src/store/modules/app/lang/index.ts create mode 100644 src/store/modules/app/lang/mutations.ts create mode 100644 src/store/modules/app/profile/actions.ts create mode 100644 src/store/modules/app/profile/getters.ts create mode 100644 src/store/modules/app/profile/index.ts create mode 100644 src/store/modules/app/profile/mutations.ts create mode 100644 src/store/modules/index.ts create mode 100644 src/store/store_module.ts create mode 100644 src/store/types.ts create mode 100755 src/styles/main.css create mode 100644 src/typs/clouds/index.ts create mode 100644 src/typs/index.ts create mode 100644 src/views/404.vue create mode 100644 src/views/Home.vue create mode 100644 src/views/Login.vue create mode 100644 src/views/Logout.vue diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..f99a068 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,26 @@ + + \ No newline at end of file diff --git a/src/components/AccordionView.vue b/src/components/AccordionView.vue new file mode 100644 index 0000000..d0f6ba9 --- /dev/null +++ b/src/components/AccordionView.vue @@ -0,0 +1,46 @@ + + diff --git a/src/components/CloudGroups.vue b/src/components/CloudGroups.vue new file mode 100644 index 0000000..9727ac6 --- /dev/null +++ b/src/components/CloudGroups.vue @@ -0,0 +1,63 @@ + + diff --git a/src/components/CloudServices.vue b/src/components/CloudServices.vue new file mode 100644 index 0000000..6651639 --- /dev/null +++ b/src/components/CloudServices.vue @@ -0,0 +1,99 @@ + + + diff --git a/src/components/Footer.vue b/src/components/Footer.vue new file mode 100644 index 0000000..61db7f2 --- /dev/null +++ b/src/components/Footer.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/NavMenu.vue b/src/components/NavMenu.vue new file mode 100644 index 0000000..0c354ae --- /dev/null +++ b/src/components/NavMenu.vue @@ -0,0 +1,107 @@ + + diff --git a/src/components/ProfileView.vue b/src/components/ProfileView.vue new file mode 100644 index 0000000..5dc881e --- /dev/null +++ b/src/components/ProfileView.vue @@ -0,0 +1,125 @@ + + diff --git a/src/components/README.md b/src/components/README.md new file mode 100644 index 0000000..ccafa35 --- /dev/null +++ b/src/components/README.md @@ -0,0 +1,9 @@ +## Components + +Components in this dir will be auto-registered and on-demand, powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components). + +### Icons + +You can use icons from almost any icon sets by the power of [Iconify](https://iconify.design/). + +It will only bundle the icons you use. Check out [`unplugin-icons`](https://github.com/antfu/unplugin-icons) for more details. diff --git a/src/components/icons/AppImg.vue b/src/components/icons/AppImg.vue new file mode 100644 index 0000000..eb51d2f --- /dev/null +++ b/src/components/icons/AppImg.vue @@ -0,0 +1,5 @@ + + diff --git a/src/components/icons/AppLogoText.vue b/src/components/icons/AppLogoText.vue new file mode 100644 index 0000000..78b6043 --- /dev/null +++ b/src/components/icons/AppLogoText.vue @@ -0,0 +1,5 @@ + + diff --git a/src/components/icons/AppLogoV.vue b/src/components/icons/AppLogoV.vue new file mode 100644 index 0000000..0f20a3b --- /dev/null +++ b/src/components/icons/AppLogoV.vue @@ -0,0 +1,7 @@ + + diff --git a/src/components/menus/MenuLocales.vue b/src/components/menus/MenuLocales.vue new file mode 100644 index 0000000..f350b7f --- /dev/null +++ b/src/components/menus/MenuLocales.vue @@ -0,0 +1,99 @@ + + + diff --git a/src/hooks/useState.ts b/src/hooks/useState.ts new file mode 100644 index 0000000..d9a253f --- /dev/null +++ b/src/hooks/useState.ts @@ -0,0 +1,46 @@ +import { ref, computed } from 'vue' +// import type { ListCloudBoxesType } from '~/typs/clouds' +// import type { SideMenuItemType } from '~/typs/cmpnts' + +const reqError = ref({ defs: '', lang: '', data: '', gql: '', api: '' }) + +const currentMapKey = ref('') +const isSidebarOpen = ref(false) +const toggleSidebar = () => { + isSidebarOpen.value = !isSidebarOpen.value +} +const bcPath = ref('') + +const tsksrvcs = 'tsksrvcs' +const appsrvcs = 'appsrvcs' +const srvcstatus = 'srvcstatus' + +const menu_items = ref([ + { id: tsksrvcs, title: 'Tasks', active: false, link: '#' }, + { id: appsrvcs, title: 'Applications', active: false, link: '#' }, + { id: srvcstatus, title: 'Services Status', active: false, link: '#' }, +]) + +const showModal = ref(false) + +const checkin = ref(false) +const connection = ref({ + state: '', +}) + +export default function useState() { + return { + tsksrvcs, + appsrvcs, + srvcstatus, + menu_items, + reqError, + currentMapKey, + isSidebarOpen, + toggleSidebar, + bcPath, + showModal, + checkin, + connection, + } +} diff --git a/src/hooks/utils.ts b/src/hooks/utils.ts new file mode 100644 index 0000000..c54ab11 --- /dev/null +++ b/src/hooks/utils.ts @@ -0,0 +1,341 @@ +// import { +// FixedAdjust, +// DenseFixedAdjust, +// ProminentFixedAdjust, +// ShortFixedAdjust, +// } from "@smui/top-app-bar"; + +import Toastify from 'toastify-js' +import store from '~/store' +import useState from '~/hooks/useState' +import { AppDefsAction } from '~/store/types' +import { MessageType } from '~/typs' +import 'toastify-js/src/toastify.css' +const { connection } = useState() + +// import { postData, sendData } from './api.js' + +// https://www.carlrippon.com/fetch-with-async-await-and-typescript/ + +/* +const headers: HeadersInit = { + 'Content-Type': 'application/json', + 'X-Request-Id': uuidv4(), + 'Authorization': `Bearer ` +} +*/ +// https://github.com/Maronato/vue-toastification#installation + +export const show_message = (typ: MessageType, msg: string, timeout?: number): void => { + // switch (typ) { + // case MessageType.Show: + // toast.show(msg) + // break + // case MessageType.Success: + // toast.success(msg) + // break + // case MessageType.Error: + // toast.error(msg) + // break + // case MessageType.Warning: + // toast.warning(msg) + // break + // case MessageType.Info: + // toast.info(msg) + // break + // } + // if (timeout && timeout > 0) + // setTimeout(toast.clear, timeout) + // https://github.com/apvarun/toastify-js + Toastify({ + text: msg, + duration: timeout || 3000, + destination: 'https://github.com/apvarun/toastify-js', + newWindow: true, + className: '', + offset: { + x: 10, // horizontal axis - can be a number or a string indicating unity. eg: '2em' + y: 50, // vertical axis - can be a number or a string indicating unity. eg: '2em + }, + close: true, + gravity: 'top', // `top` or `bottom` + position: 'left', // `left`, `center` or `right` + backgroundColor: 'linear-gradient(to right, #00b09b, #96c93d)', + stopOnFocus: true, // Prevents dismissing of toast on hover + onClick() {}, // Callback after click + }).showToast() +} + +export const translate = (store: any, map: string, ky: string, ctx: string, dflt?: string): string => { + const val = dflt || ky + const lang = store.state.app_lang.lang.get(map) + // switch (ctx) { + // case 'main': + // val = lang.value.main && lang.value.main[ky] ? lang.value.main[ky] : val + // break + // case 'data': + // val = lang.value.main && lang.value.main[ky] ? lang.value.main[ky] : val + // val = lang.value.data[ky] || val + // break + // case 'forms': + // val = lang.value.forms && lang.value.forms[ky] ? lang.value.forms[ky] : val + // break + // } + if (lang && lang.value) + return lang.value[ctx] && lang.value[ctx][ky] ? lang.value[ctx][ky] : val + else if (lang && lang[ctx]) + return lang[ctx][ky] ? lang[ctx][ky] : val + else + return val +} + +export const senddata = async(url: RequestInfo, data: BlobPart, file_name?: string, cllbck?: any): Promise => { + const formData = new FormData() + // formData.append('blob', new Blob([JSON.stringify(rowData)]), 'test') + // let response: Ref < T | undefined > = ref() + + formData.append('blob', new Blob([data]), file_name) + try { + const response = await fetch(url, { + mode: 'no-cors', // 'cors' by default + method: 'POST', + body: formData, + }) + return response + } + catch (err) { + if (cllbck) + cllbck(err) + else + console.log(err) + } +} +export const postdata = (url: string, data: any, file_name: string, cllbck?: any): void => { + if (data && file_name) { + senddata(url, data, file_name, cllbck).then((result: any) => { + if (result.status !== 0) { + console.log( + // throw Error( + `Data sent to ${url} (${file_name}) - Network response NOT OK`, + ) + } + else { + console.log( + `Save data to ${url} (${file_name}) status: ${result.status}`, + ) + } + if (cllbck) + cllbck(result) + }) + } +} +export const fetch_text = async(path: RequestInfo): Promise => { + try { + const response = await fetch(path) + return !response.ok ? response.text() : new Error('No items found') + } + catch (err) { + return err + } +} + +export const fetch_json = async(path: RequestInfo, timeout = 2000): Promise => { + // eslint-disable-next-line no-async-promise-executor + return new Promise(async(resolve, reject) => { + try { + const response = await self.fetch(path) + setTimeout(async() => { + resolve(await response.json()) + }, timeout) + } + catch (err) { + reject(err) + } + }) +} + +export const load_data = async(data_path: RequestInfo, ato: number, timeout = 2000, cllbck?: any) => { + // eslint-disable-next-line no-async-promise-executor + // return await new Promise(async(resolve, reject) => { + useState().connection.value.state = '' + const token = localStorage.getItem('auth') || '' + // if (token === '') + // return `error no auth for ${data_path}` + + try { + const res = await self.fetch(data_path, { + headers: { + Authorization: `Bearer ${token}`, + // 'content-type': 'application/json', + }, + + }) + // setTimeout(async() => { + let dataloaded = {} + try { + let strData = await res.text() + for (let i = 0; i < ato; i++) + strData = atob(strData) + dataloaded = JSON.parse(strData) + } + catch (e) { + return `error ${e} with ${data_path}` + } + if (Object.keys(dataloaded).length) { + if (cllbck) + cllbck(dataloaded) + return '' + } + else { + return new Error('No definitions found') + } + // }, timeout) + } + catch (err) { + show_message(MessageType.Error, `'Data Load' -> ${err}`) + useState().connection.value.state = 'connection.error' + return err + } + // }) +} +export const post_data = async(url: string, formData: any, with_auth = true) => { + connection.value.state = '' + let headers = {} + if (with_auth) { + const token = localStorage.getItem('auth') || '' + if (token === '') + return `error no auth for ${url}` + headers = { + 'content-type': 'application/json', + 'Authorization': `Bearer ${token}`, + // 'Access-Control-Allow-Origin': '*', + // 'Accept': 'application/json', + } + } + else { + headers = { 'content-type': 'application/json' } + } + let formDataJsonString = '' + try { + formDataJsonString = JSON.stringify(formData) + } + catch (e) { + console.log(e) + return + } + try { + const response = await fetch(url, { + method: 'POST', + headers, + body: formDataJsonString, + }) + if (!response.ok && response.status !== 200) { + const errorMessage = await response.text() + console.log(errorMessage) + // throw new Error(errorMessage) + } + if (response.ok && response.status === 200) + return response.json() + } + catch (e) { + connection.value.state = 'connection.error' + console.log(e) + } +} + +export const check_credentials = async(url: string, data: any): Promise => { + let dataJsonString = '' + try { + dataJsonString = JSON.stringify(data) + } + catch (e) { + console.log(e) + return + } + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'content-type': 'application/json', + }, + body: dataJsonString, + }) + if (!response.ok) { + const errorMessage = await response.text() + // throw new Error(errorMessage) + console.log(errorMessage) + return + } + if (response.ok && response.status === 200) + return response.json() + } + catch (e) { + useState().connection.value.state = 'connection.error' + console.log(e) + } +} + +export const run_task = (val: number, task: Function) => { + const now = new Date().getTime() + const timePassed = now % val + const run_at = val - timePassed + setTimeout(task, run_at) +} + +export const verify_auth = async(mapkey: string, check_url: string, login_url: string) => { + const auth = localStorage.getItem('auth') || '' + const res = await check_credentials(check_url, { data: auth, mapkey }) + if (res && res.token === auth) { + if (res.defs) + store.dispatch(AppDefsAction.addDefs, { key: mapkey, defs: res.defs }) + if (res.defs.checkin && res.defs.checkin > 0) { + run_task(res.defs.checkin, async() => { + // console.log('run_task') + const res_task = await verify_auth(mapkey, check_url, login_url) + if (res_task) + return + if (useState().connection.value.state === '') + location.href = login_url + }) + } + return res + } + return res +} + +export const auth_data = () => { + const auth = localStorage.getItem('auth') || '' + let uidefs = {} + if (store && store.state && store.state.app_defs && store.state.app_defs.main) { + uidefs = store.state.app_defs.main.get('ui') + } + return {auth, uidefs} +} + +export const parse_str_json_data = (src: string, dflt: object|any) => { + let data = dflt + try { + data = JSON.parse(src) + } + catch (e) { + data = dflt + } + return data +} + +export default { + fetch_text, + fetch_json, + postdata, + senddata, + load_data, + post_data, + // store_data, + show_message, + translate, + check_credentials, + run_task, + verify_auth, + auth_data, + parse_str_json_data, +} diff --git a/src/layouts/AppLayout.vue b/src/layouts/AppLayout.vue new file mode 100644 index 0000000..939379f --- /dev/null +++ b/src/layouts/AppLayout.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/layouts/GuestLayout.vue b/src/layouts/GuestLayout.vue new file mode 100644 index 0000000..f3247a7 --- /dev/null +++ b/src/layouts/GuestLayout.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/layouts/Page404.vue b/src/layouts/Page404.vue new file mode 100644 index 0000000..463849e --- /dev/null +++ b/src/layouts/Page404.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/layouts/_AppLayout.vue b/src/layouts/_AppLayout.vue new file mode 100644 index 0000000..e8657c0 --- /dev/null +++ b/src/layouts/_AppLayout.vue @@ -0,0 +1,300 @@ + + + + diff --git a/src/layouts/default.vue b/src/layouts/default.vue new file mode 100644 index 0000000..bcedc18 --- /dev/null +++ b/src/layouts/default.vue @@ -0,0 +1,9 @@ + diff --git a/src/layouts/home.vue b/src/layouts/home.vue new file mode 100644 index 0000000..751176c --- /dev/null +++ b/src/layouts/home.vue @@ -0,0 +1,30 @@ + + diff --git a/src/logic/dark.ts b/src/logic/dark.ts new file mode 100644 index 0000000..a2a21dd --- /dev/null +++ b/src/logic/dark.ts @@ -0,0 +1,2 @@ +export const isDark = useDark() +export const toggleDark = useToggle(isDark) diff --git a/src/logic/index.ts b/src/logic/index.ts new file mode 100644 index 0000000..e8d1566 --- /dev/null +++ b/src/logic/index.ts @@ -0,0 +1 @@ +export * from './dark' diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..b6bb402 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,53 @@ +// windicss layers +import 'virtual:windi-base.css' +import 'virtual:windi-components.css' +// your custom styles here +import './styles/main.css' +// windicss utilities should be the last style import +import 'virtual:windi-utilities.css' +// windicss devtools support (dev only) +import 'virtual:windi-devtools' + +// register vue composition api globally +import { createApp } from 'vue' +// import { createRouter, createWebHistory } from 'vue-router' +import { createI18n } from 'vue-i18n' +import { createHead, useHead } from '@vueuse/head' + +import App from './App.vue' + +import routes from './router' +import store from './store' + +import 'a17t' + +import { messages } from './modules/i18n' +// import GuestLayout from '~/layouts/GuestLayout.vue' +import AppLayout from '~/layouts/AppLayout.vue' + +const app = createApp(App) + +const i18n = createI18n({ + locale: 'es', + legacy: false, + fallbackLocale: ['es'], + fallbackWarn: false, + missing: (locale, key, instance) => { + console.warn(`detect '${key}' key missing in '${locale}'`) + }, + messages, +}) + +const head = createHead() +// const router = createRouter({ +// history: createWebHistory(), +// routes, +// }) +app.use(store) +app.use(i18n) +app.use(routes) +// app.use(router) +app.use(head) +app.component('AppLayout', AppLayout) +// app.component('GuestLayout', GuestLayout) +app.mount('#app') diff --git a/src/modules/README.md b/src/modules/README.md new file mode 100644 index 0000000..adda9ef --- /dev/null +++ b/src/modules/README.md @@ -0,0 +1,11 @@ +## Modules + +A custom user module system. Place a `.ts` file with the following template, it will be installed automatically. + +```ts +import { UserModule } from '~/types' + +export const install: UserModule = ({ app, router, isClient }) => { + // do something +} +``` diff --git a/src/modules/i18n.ts b/src/modules/i18n.ts new file mode 100644 index 0000000..f7528a1 --- /dev/null +++ b/src/modules/i18n.ts @@ -0,0 +1,25 @@ +import { createI18n } from 'vue-i18n' +// import { UserModule } from '~/types' + +// import i18n resources +// https://vitejs.dev/guide/features.html#glob-import +export const messages = Object.fromEntries( + Object.entries( + import.meta.globEager('../../locales/*.y(a)?ml')) + .map(([key, value]) => { + const yaml = key.endsWith('.yaml') + return [key.slice(14, yaml ? -5 : -4), value.default] + }), +) +/* +export const install: UserModule = ({ app }) => { + const i18n = createI18n({ + legacy: false, + locale: 'en', + messages, + }) + + app.use(i18n) +} + +*/ \ No newline at end of file diff --git a/src/modules/nprogress.ts b/src/modules/nprogress.ts new file mode 100644 index 0000000..8019b41 --- /dev/null +++ b/src/modules/nprogress.ts @@ -0,0 +1,9 @@ +import NProgress from 'nprogress' +import { UserModule } from '~/types' + +export const install: UserModule = ({ isClient, router }) => { + if (isClient) { + router.beforeEach(() => { NProgress.start() }) + router.afterEach(() => { NProgress.done() }) + } +} diff --git a/src/modules/sw.ts b/src/modules/sw.ts new file mode 100644 index 0000000..fd7f7ca --- /dev/null +++ b/src/modules/sw.ts @@ -0,0 +1,12 @@ +import { UserModule } from '~/types' + +export const install: UserModule = ({ isClient, router }) => { + if (isClient) { + router.isReady().then(async() => { + if (isClient) { + const { registerSW } = await import('virtual:pwa-register') + registerSW({ immediate: true }) + } + }) + } +} diff --git a/src/pages/README.md b/src/pages/README.md new file mode 100644 index 0000000..0db483b --- /dev/null +++ b/src/pages/README.md @@ -0,0 +1,20 @@ +## File-based Routing + +Routes will be auto-generated for Vue files in this dir with the same file structure. +Check out [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) for more details. + +### Path Aliasing + +`~/` is aliased to `./src/` folder. + +For example, instead of having + +```ts +import { isDark } from '../../../../logic' +``` + +now, you can use + +```ts +import { isDark } from '~/logic' +``` diff --git a/src/pages/[...all].vue b/src/pages/[...all].vue new file mode 100755 index 0000000..241e7e2 --- /dev/null +++ b/src/pages/[...all].vue @@ -0,0 +1,5 @@ + diff --git a/src/pages/base.vue b/src/pages/base.vue new file mode 100644 index 0000000..9e88ff6 --- /dev/null +++ b/src/pages/base.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/pages/hi/[name].vue b/src/pages/hi/[name].vue new file mode 100644 index 0000000..79ccd2a --- /dev/null +++ b/src/pages/hi/[name].vue @@ -0,0 +1,27 @@ + + + diff --git a/src/router.ts b/src/router.ts new file mode 100644 index 0000000..9825928 --- /dev/null +++ b/src/router.ts @@ -0,0 +1,191 @@ +// eslint-disable-next-line no-unused-vars +import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' + +// import { defineAsyncComponent } from 'vue' + +import { setupLayouts } from 'virtual:generated-layouts' +import generatedRoutes from 'virtual:generated-pages' +// import generatedRoutes from 'pages-generated' +// import { setupLayouts } from 'layouts-generated' + +import useState from '~/hooks/useState' + +// const Login = defineAsyncComponent(() => import('./views/Login.vue')) +import store from '~/store' + +import Home from '~/views/Home.vue' +// import Register from '~/views/auth/Register.vue' +import Login from '~/views/Login.vue' +import Logout from '~/views/Logout.vue' + +import { verify_auth, check_credentials } from '~/hooks/utils' +// import { +// lang_url, +// req_lang, +// } from '~/defs/ta_defs' +// const DataGrid = () => import('~/views/DataGrid.vue') +//const SambaModel = () => import('~/views/SambaModel.vue') + +const layoutsRoutes = setupLayouts(generatedRoutes) +/* +// import routes generated by Voie +import pgRoutes from 'voie-pages' + +const UIElements = defineAsyncComponent(() => import('./views/UIElements.vue')) +const Tables = defineAsyncComponent(() => import('./views/Tables.vue')) +const Dashboard = defineAsyncComponent(() => import('./views/Dashboard.vue')) +const Forms = defineAsyncComponent(() => import('./views/Forms.vue')) +const Input = defineAsyncComponent(() => import('./views/Input.vue')) +const Home = defineAsyncComponent(() => import('./views/Home.vue')) +const Modal = defineAsyncComponent(() => import('./views/Modal.vue')) +const Blank = defineAsyncComponent(() => import('./views/Blank.vue')) +const OLogin = defineAsyncComponent(() => import('./views/OLogin.vue')) +const Entry = defineAsyncComponent(() => import('./views/Entry.vue')) +*/ + +// https://medium.com/swlh/adding-meta-fields-and-transitions-to-vue-router-routes-f5cb78a7ed97 +// router.beforeEach((to, from, next) => { +// if (to.meta.requireAuth) { +// if (!localStorage.getItem("auth")) { +// next('/notfound') +// } else { +// next(); +// } +// } else { +// next(); +// } +// }); + +// const get_lang = (_to: any, _from: any, next: any) => { +// req_lang(lang_url, (lang: any) => { lng: lang }) +// // req_lang(lang_url, () => next()) +// } + +const rooturl = window.ROOT_LOCATION || location.origin + +const check_auth = async(to: any, _from: any, next: any) => { + useState().bcPath.value = '' + const auth = localStorage.getItem('auth') || '' + const check_url = `${window.ROOT_LOCATION || location.origin}/checkin` + const login_url = `${location.origin}/ui/login` + const mapkey = to.meta.uimapkey || 'ui' + if (auth !== '') { + const defs = store.state.app_defs.main.get(mapkey) + if (defs && defs.checkin && useState().checkin.value) { + next() + } + else { + useState().checkin.value = true + const res = await verify_auth(mapkey, check_url, login_url) + // if (useState().connection.value.state === '') + // TODO redirect to a connection error page or consider PWA offline mode + if (res && res.defs) + next() + else next('/login') + } + } + else { next('/login') } +} + +const get_defs = async(mapkey: string) => { + const auth = localStorage.getItem('auth') || '' + const url = `${window.ROOT_LOCATION || location.origin}/checkin` + if (auth !== '') { + const res = await check_credentials(url, { data: auth, mapkey }) + if (res.token === auth) + return res.defs || {} + else + return {} + } + else { + return {} + } +} + +const routes: RouteRecordRaw[] = [ +/* + { + path: '/home', + alias: '/', + name: 'Home', + component: Home, + meta: { layout: 'empty' }, + }, + { + path: '/ui/samba', + name: 'Samba', + component: SambaModel, + meta: { layout: 'AppLayout' }, + }, + */ + { + path: '/', + name: 'Home', + component: Home, + meta: { + requireAuth: true, + layout: 'AppLayout', + mapkey: 'kloud', + uiMapkey: 'ui', + rooturl, + }, + // beforeEnter: check_auth, + // (_to: any, _from: any, next: any) => { + // req_lang(lang_url, () => next()) + // }, + }, + { + path: '/login', + name: 'Login', + component: Login, + meta: { layout: 'empty', rooturl, use_logo: true, allow_register: false, allow_reset: false }, + }, + { + path: '/logout', + name: 'Logout', + component: Logout, + meta: { layout: 'empty', rooturl, use_logo: true }, + }, + // { + // path: '/auth/register', + // name: 'Register', + // component: Register, + // meta: { layout: 'GuestLayout' }, + // }, + /* + { + path: '/datalist', + name: 'DataGrid', + component: DataGrid, + meta: { + requireAuth: true, + layout: 'AppLayout', + uiMapkey: 'ui', + mapkey: 'kloud', + rooturl, + bcpath: '#fa-book/librecloud/klouds', + }, + beforeEnter: check_auth, + // props: { lang: 'es' }, // get_lang, + // beforeEnter: get_lang, + // (_to: any, _from: any, next: any) => { + // req_lang(lang_url, () => next()) + // }, + }, + */ + { + path: '/:catchAll(.*)', + name: '404', + meta: { layout: 'Page404' }, + component: () => import('./views/404.vue'), + }, + ...layoutsRoutes, +] + +// const routes: RouteRecordRaw[] = pgRoutes +const router: any = createRouter({ + history: createWebHistory(), + routes, +}) +// routes, +export default router diff --git a/src/shims.d.ts b/src/shims.d.ts new file mode 100644 index 0000000..7990f5d --- /dev/null +++ b/src/shims.d.ts @@ -0,0 +1,57 @@ +/* eslint-disable import/no-duplicates */ + +declare interface Window { + // extend the window + ROOT_LOCATION: string +} + +// with vite-plugin-md, markdowns can be treat as Vue components +declare module '*.md' { + import { ComponentOptions } from 'vue' + const component: ComponentOptions + export default component +} +/* +declare module '*.vue' { + import Vue from 'vue' + export default Vue +} +*/ +declare const _APP_VERSION: string +/* + * Keep states in the global scope to be reusable across Vue instances. + * + * @see {@link /createGlobalState} + * @param stateFactory A factory function to create the state +*/ +/* +declare function createGlobalState( + stateFactory: () => T +): () => T +*/ +interface EventTarget { + value: EventTarget|null + name: string| null + /** + * Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. + * + * The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. + * + * When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. + * + * When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. + * + * When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. + * + * The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. + */ + addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void + /** + * Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. + */ + dispatchEvent(event: Event): boolean + /** + * Removes the event listener in target's event listener list with the same type, callback, and options. + */ + removeEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean): void +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..8f785c4 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,61 @@ +import { InjectionKey } from 'vue' +import { + createStore, + createLogger, + Store as VuexStore, + useStore as baseUseStore, +} from 'vuex' + +import { + app_data, + AppDataState, + app_check, + AppCheckState, + app_defs, + AppDefsState, + app_profile, + AppProfileState, + AppLangState, + app_lang, +} from './modules' + +import { Store as AppDataStore } from './modules/app/data' +import { Store as AppCheckStore } from './modules/app/check' +import { Store as AppDefsStore } from './modules/app/defs' +import { Store as AppProfileStore } from './modules/app/profile' +import { Store as AppLangStore } from './modules/app/lang' + +export interface RootState { + data: AppDataState + check: AppCheckState + defs: AppDefsState + profile: AppProfileState + lang: AppLangState +} + +export type RootStore = AppDataStore> +& AppCheckStore> +& AppDefsStore> +& AppProfileStore> +& AppLangStore> + +// eslint-disable-next-line symbol-description +export const key: InjectionKey> = Symbol() + +const debug = process.env.NODE_ENV !== 'production' + +export default createStore({ + modules: { + app_data, + app_check, + app_defs, + app_profile, + app_lang, + }, + strict: debug, + plugins: debug ? [createLogger()] : [], +}) + +// export const useStore = (): RootStore => { +// return baseUseStore(key) +// } diff --git a/src/store/modules/app/check/actions.ts b/src/store/modules/app/check/actions.ts new file mode 100644 index 0000000..a4cbf5e --- /dev/null +++ b/src/store/modules/app/check/actions.ts @@ -0,0 +1,44 @@ +import { ActionContext, ActionTree } from 'vuex' +import { Mutations, MutationTypes } from './mutations' +import { State } from './index' +import { RootState } from '~/store/index' + +export enum ActionTypes { + addCheck = 'addCheck', + removeCheck = 'removeCheck', + editCheck = 'editCheck' +} + +type AppCheckActionContext = { + commit( + key: K, + payload: Parameters[1] + ): ReturnType +} & Omit, 'commit'> + +export interface Actions { + [ActionTypes.addCheck]( + { commit }: AppCheckActionContext, + payload: any + ): void + [ActionTypes.removeCheck]( + { commit }: AppCheckActionContext, + payload: any + ): void + [ActionTypes.editCheck]( + { commit }: AppCheckActionContext, + payload: any + ): void +} + +export const actions: ActionTree & Actions = { + [ActionTypes.addCheck]({ commit }, payload) { + commit(MutationTypes.addCheck, payload) + }, + [ActionTypes.removeCheck]({ commit }, payload) { + commit(MutationTypes.removeCheck, payload) + }, + [ActionTypes.editCheck]({ commit }, payload) { + commit(MutationTypes.editCheck, payload) + }, +} diff --git a/src/store/modules/app/check/getters.ts b/src/store/modules/app/check/getters.ts new file mode 100644 index 0000000..06e8a25 --- /dev/null +++ b/src/store/modules/app/check/getters.ts @@ -0,0 +1,13 @@ +import { GetterTree } from 'vuex' +import { State } from './index' +import { RootState } from '~/store/index' + +export type Getters = { + check(state: S, key: string): any +} + +export const getters: GetterTree & Getters = { + check: (state, key: string) => { + return state.check.get(key) + }, +} diff --git a/src/store/modules/app/check/index.ts b/src/store/modules/app/check/index.ts new file mode 100644 index 0000000..d464385 --- /dev/null +++ b/src/store/modules/app/check/index.ts @@ -0,0 +1,49 @@ +import { + Store as VuexStore, + Module, + CommitOptions, + DispatchOptions, +} from 'vuex' + +import { getters, Getters } from './getters' +import { mutations, Mutations, MutationTypes } from './mutations' +import { actions, Actions, ActionTypes } from './actions' + +import { RootState } from '~/store/index' + +interface State { + check: Map +} + +const state: State = { + check: new Map(), +} + +const data_module: Module = { + state, + mutations, + actions, + getters, +} + +export default data_module + +type Store = Omit, 'commit' | 'getters' | 'dispatch' > & { + commit[1]>( + key: K, + payload: P, + options?: CommitOptions + ): ReturnType +} & { + getters: { + [K in keyof Getters]: ReturnType + } +} & { + dispatch( + key: K, + payload: Parameters[1], + options?: DispatchOptions + ): ReturnType +} + +export { State, ActionTypes, MutationTypes, Store } diff --git a/src/store/modules/app/check/mutations.ts b/src/store/modules/app/check/mutations.ts new file mode 100644 index 0000000..99dd5e5 --- /dev/null +++ b/src/store/modules/app/check/mutations.ts @@ -0,0 +1,48 @@ +import { MutationTree } from 'vuex' +import { State } from './index' +import { AppCheck } from '~/store/types' + +export enum MutationTypes { + addCheck = 'addCheck', + removeCheck = 'removeCheck', + editCheck = 'editCheck' +} + +interface CheckMap { + key: string + check: any +} + +export type Mutations = { + [MutationTypes.addCheck](state: S, check_map: CheckMap): void + [MutationTypes.removeCheck](state: S, check_map: CheckMap): void + [MutationTypes.editCheck](state: S, check_map: CheckMap, key: string): void +} + +export const mutations: MutationTree & Mutations = { + [MutationTypes.addCheck](state: State, check_map: CheckMap) { + if (check_map.key && check_map.check) + state.check.set(check_map.key, check_map.check) + }, + [MutationTypes.removeCheck](state: State, check_map: CheckMap) { + if (check_map.key && check_map.check) { + const check = state.check.get(check_map.key) + check.splice(check.indexOf(check_map.check), 1) + state.check.set(check_map.key, check) + } + }, + [MutationTypes.editCheck](state: State, check_map: CheckMap) { + if (check_map.key && check_map.check) { + const new_check = [] as unknown as any + const check = state.check.get(check_map.key) + const key = check_map.check.id + check.forEach((it: any) => { + if (it.id === key) + new_check.push(check) + else + new_check.push(it) + }) + state.check.set(check_map.key, new_check) + } + }, +} diff --git a/src/store/modules/app/data/actions.ts b/src/store/modules/app/data/actions.ts new file mode 100644 index 0000000..794e7c5 --- /dev/null +++ b/src/store/modules/app/data/actions.ts @@ -0,0 +1,44 @@ +import { ActionContext, ActionTree } from 'vuex' +import { Mutations, MutationTypes } from './mutations' +import { State } from './index' +import { RootState } from '~/store/index' + +export enum ActionTypes { + addData = 'addData', + removeData = 'removeData', + editData = 'editData' +} + +type AppDataActionContext = { + commit( + key: K, + payload: Parameters[1] + ): ReturnType +} & Omit, 'commit'> + +export interface Actions { + [ActionTypes.addData]( + { commit }: AppDataActionContext, + payload: any + ): void + [ActionTypes.removeData]( + { commit }: AppDataActionContext, + payload: any + ): void + [ActionTypes.editData]( + { commit }: AppDataActionContext, + payload: any + ): void +} + +export const actions: ActionTree & Actions = { + [ActionTypes.addData]({ commit }, payload) { + commit(MutationTypes.addData, payload) + }, + [ActionTypes.removeData]({ commit }, payload) { + commit(MutationTypes.removeData, payload) + }, + [ActionTypes.editData]({ commit }, payload) { + commit(MutationTypes.editData, payload) + }, +} diff --git a/src/store/modules/app/data/getters.ts b/src/store/modules/app/data/getters.ts new file mode 100644 index 0000000..4550997 --- /dev/null +++ b/src/store/modules/app/data/getters.ts @@ -0,0 +1,13 @@ +import { GetterTree } from 'vuex' +import { State } from './index' +import { RootState } from '~/store/index' + +export type Getters = { + data(state: S, key: string): any +} + +export const getters: GetterTree & Getters = { + data: (state, key: string) => { + return state.data.get(key) + }, +} diff --git a/src/store/modules/app/data/index.ts b/src/store/modules/app/data/index.ts new file mode 100644 index 0000000..f0ae33c --- /dev/null +++ b/src/store/modules/app/data/index.ts @@ -0,0 +1,49 @@ +import { + Store as VuexStore, + Module, + CommitOptions, + DispatchOptions, +} from 'vuex' + +import { getters, Getters } from './getters' +import { mutations, Mutations, MutationTypes } from './mutations' +import { actions, Actions, ActionTypes } from './actions' + +import { RootState } from '~/store/index' + +interface State { + data: Map +} + +const state: State = { + data: new Map(), +} + +const data_module: Module = { + state, + mutations, + actions, + getters, +} + +export default data_module + +type Store = Omit, 'commit' | 'getters' | 'dispatch' > & { + commit[1]>( + key: K, + payload: P, + options?: CommitOptions + ): ReturnType +} & { + getters: { + [K in keyof Getters]: ReturnType + } +} & { + dispatch( + key: K, + payload: Parameters[1], + options?: DispatchOptions + ): ReturnType +} + +export { State, ActionTypes, MutationTypes, Store } diff --git a/src/store/modules/app/data/mutations.ts b/src/store/modules/app/data/mutations.ts new file mode 100644 index 0000000..bb6bfe5 --- /dev/null +++ b/src/store/modules/app/data/mutations.ts @@ -0,0 +1,48 @@ +import { MutationTree } from 'vuex' +import { State } from './index' +import { AppData } from '~/store/types' + +export enum MutationTypes { + addData = 'addData', + removeData = 'removeData', + editData = 'editData' +} + +interface DataMap { + key: string + data: any +} + +export type Mutations = { + [MutationTypes.addData](state: S, data_map: DataMap): void + [MutationTypes.removeData](state: S, data_map: DataMap): void + [MutationTypes.editData](state: S, data_map: DataMap, key: string): void +} + +export const mutations: MutationTree & Mutations = { + [MutationTypes.addData](state: State, data_map: DataMap) { + if (data_map.key && data_map.data) + state.data.set(data_map.key, data_map.data) + }, + [MutationTypes.removeData](state: State, data_map: DataMap) { + if (data_map.key && data_map.data) { + const data = state.data.get(data_map.key) + data.splice(data.indexOf(data_map.data), 1) + state.data.set(data_map.key, data) + } + }, + [MutationTypes.editData](state: State, data_map: DataMap) { + if (data_map.key && data_map.data) { + const new_data = [] as unknown as any + const data = state.data.get(data_map.key) + const key = data_map.data.id + data.forEach((it: any) => { + if (it.id === key) + new_data.push(data) + else + new_data.push(it) + }) + state.data.set(data_map.key, new_data) + } + }, +} diff --git a/src/store/modules/app/defs/actions.ts b/src/store/modules/app/defs/actions.ts new file mode 100644 index 0000000..30527e5 --- /dev/null +++ b/src/store/modules/app/defs/actions.ts @@ -0,0 +1,44 @@ +import { ActionContext, ActionTree } from 'vuex' +import { Mutations, MutationTypes } from './mutations' +import { State } from './index' +import { RootState } from '~/store/index' + +export enum ActionTypes { + addDefs = 'addDefs', + removeDefs = 'removeDefs', + editDefs = 'editDefs' +} + +type AppDefsActionContext = { + commit( + key: K, + payload: Parameters[1] + ): ReturnType +} & Omit, 'commit'> + +export interface Actions { + [ActionTypes.addDefs]( + { commit }: AppDefsActionContext, + payload: any + ): void + [ActionTypes.removeDefs]( + { commit }: AppDefsActionContext, + payload: any + ): void + [ActionTypes.editDefs]( + { commit }: AppDefsActionContext, + payload: any + ): void +} + +export const actions: ActionTree & Actions = { + [ActionTypes.addDefs]({ commit }, payload) { + commit(MutationTypes.addDefs, payload) + }, + [ActionTypes.removeDefs]({ commit }, payload) { + commit(MutationTypes.removeDefs, payload) + }, + [ActionTypes.editDefs]({ commit }, payload) { + commit(MutationTypes.editDefs, payload) + }, +} diff --git a/src/store/modules/app/defs/getters.ts b/src/store/modules/app/defs/getters.ts new file mode 100644 index 0000000..4740c71 --- /dev/null +++ b/src/store/modules/app/defs/getters.ts @@ -0,0 +1,13 @@ +import { GetterTree } from 'vuex' +import { State } from './index' +import { RootState } from '~/store/index' + +export type Getters = { + defs(state: S, key: string): any +} + +export const getters: GetterTree & Getters = { + defs: (state, key: string) => { + return state.main.get(key) + }, +} diff --git a/src/store/modules/app/defs/index.ts b/src/store/modules/app/defs/index.ts new file mode 100644 index 0000000..0c140df --- /dev/null +++ b/src/store/modules/app/defs/index.ts @@ -0,0 +1,49 @@ +import { + Store as VuexStore, + Module, + CommitOptions, + DispatchOptions, +} from 'vuex' + +import { getters, Getters } from './getters' +import { mutations, Mutations, MutationTypes } from './mutations' +import { actions, Actions, ActionTypes } from './actions' + +import { RootState } from '~/store/index' + +interface State { + main: Map +} + +const state: State = { + main: new Map(), +} + +const data_module: Module = { + state, + mutations, + actions, + getters, +} + +export default data_module + +type Store = Omit, 'commit' | 'getters' | 'dispatch' > & { + commit[1]>( + key: K, + payload: P, + options?: CommitOptions + ): ReturnType +} & { + getters: { + [K in keyof Getters]: ReturnType + } +} & { + dispatch( + key: K, + payload: Parameters[1], + options?: DispatchOptions + ): ReturnType +} + +export { State, ActionTypes, MutationTypes, Store } diff --git a/src/store/modules/app/defs/mutations.ts b/src/store/modules/app/defs/mutations.ts new file mode 100644 index 0000000..6341080 --- /dev/null +++ b/src/store/modules/app/defs/mutations.ts @@ -0,0 +1,47 @@ +import { MutationTree } from 'vuex' +import { State } from './index' + +export enum MutationTypes { + addDefs = 'addDefs', + removeDefs = 'removeDefs', + editDefs = 'editDefs' +} + +interface DefsMap { + key: string + defs: any +} + +export type Mutations = { + [MutationTypes.addDefs](state: S, defs_map: DefsMap): void + [MutationTypes.removeDefs](state: S, defs_map: DefsMap): void + [MutationTypes.editDefs](state: S, defs_map: DefsMap, key: string): void +} + +export const mutations: MutationTree & Mutations = { + [MutationTypes.addDefs](state: State, defs_map: DefsMap) { + if (defs_map.key && defs_map.defs) + state.main.set(defs_map.key, defs_map.defs) + }, + [MutationTypes.removeDefs](state: State, defs_map: DefsMap) { + if (defs_map.key && defs_map.defs) { + const defs = state.main.get(defs_map.key) + defs.splice(defs.indexOf(defs_map.defs), 1) + state.main.set(defs_map.key, defs) + } + }, + [MutationTypes.editDefs](state: State, defs_map: DefsMap) { + if (defs_map.key && defs_map.defs) { + const new_defs = [] as unknown as any + const defs = state.main.get(defs_map.key) + const key = defs_map.defs.id + defs.forEach((it: any) => { + if (it.id === key) + new_defs.push(defs) + else + new_defs.push(it) + }) + state.main.set(defs_map.key, new_defs) + } + }, +} diff --git a/src/store/modules/app/index.ts b/src/store/modules/app/index.ts new file mode 100644 index 0000000..52e78e1 --- /dev/null +++ b/src/store/modules/app/index.ts @@ -0,0 +1,35 @@ +import data_module, { State as DataState, MutationTypes as DataMutationTypes, ActionTypes as DataActionTypes, Store as DataStore } from './data' +import check_module, { State as CheckState, MutationTypes as CheckMutationTypes, ActionTypes as CheckActionTypes, Store as CheckStore } from './check' +import defs_module, { State as DefsState, MutationTypes as DefsMutationTypes, ActionTypes as DefsActionTypes, Store as DefsStore } from './defs' +import profile_module, { State as ProfileState, MutationTypes as ProfileMutationTypes, ActionTypes as ProfileActionTypes, Store as ProfileStore } from './profile' +import lang_module, { State as LangState, MutationTypes as LangMutationTypes, ActionTypes as LangActionTypes, Store as LangStore } from './lang' + +export const AppDataMutationTypes = DataMutationTypes +export const AppCheckMutationTypes = CheckMutationTypes +export const AppDefsMutationTypes = DefsMutationTypes +export const AppProfileMutationTypes = ProfileMutationTypes +export const AppLangMutationTypes = LangMutationTypes + +export const AppDataActionTypes = DataActionTypes +export const AppCheckActionTypes = CheckActionTypes +export const AppDefsActionTypes = DefsActionTypes +export const AppProfileActionTypes = ProfileActionTypes +export const AppLangActionTypes = LangActionTypes + +export type AppDataState= DataState +export type AppCheckState= CheckState +export type AppDefsState= DefsState +export type AppProfileState= ProfileState +export type AppLangState= LangState + +export type AppDataStore = DataStore +export type AppCheckStore = CheckStore +export type AppDefsStore = DefsStore +export type AppProfileStore = ProfileStore +export type AppLangStore = LangStore + +export const app_data = data_module +export const app_check = check_module +export const app_defs = defs_module +export const app_profile = profile_module +export const app_lang = lang_module diff --git a/src/store/modules/app/lang/actions.ts b/src/store/modules/app/lang/actions.ts new file mode 100644 index 0000000..d536b49 --- /dev/null +++ b/src/store/modules/app/lang/actions.ts @@ -0,0 +1,68 @@ +import { ActionContext, ActionTree } from 'vuex' +import { Mutations, MutationTypes } from './mutations' +import { State } from './index' +import { RootState } from '~/store/index' + +export enum ActionTypes { + addLang = 'addLang', + addLangMain = 'addLangMain', + addLangData = 'addLangData', + addLangForms = 'addLangForms', + removeLang = 'removeLang', + editLang = 'editLang' +} + +type AppLangActionContext = { + commit( + key: K, + payload: Parameters[1] + ): ReturnType +} & Omit, 'commit'> + +export interface Actions { + [ActionTypes.addLang]( + { commit }: AppLangActionContext, + payload: any + ): void + [ActionTypes.addLangMain]( + { commit }: AppLangActionContext, + payload: any + ): void + [ActionTypes.addLangData]( + { commit }: AppLangActionContext, + payload: any + ): void + [ActionTypes.addLangForms]( + { commit }: AppLangActionContext, + payload: any + ): void + [ActionTypes.removeLang]( + { commit }: AppLangActionContext, + payload: any + ): void + [ActionTypes.editLang]( + { commit }: AppLangActionContext, + payload: any + ): void +} + +export const actions: ActionTree & Actions = { + [ActionTypes.addLang]({ commit }, payload) { + commit(MutationTypes.addLang, payload) + }, + [ActionTypes.addLangMain]({ commit }, payload) { + commit(MutationTypes.addLangMain, payload) + }, + [ActionTypes.addLangData]({ commit }, payload) { + commit(MutationTypes.addLangData, payload) + }, + [ActionTypes.addLangForms]({ commit }, payload) { + commit(MutationTypes.addLangForms, payload) + }, + [ActionTypes.removeLang]({ commit }, payload) { + commit(MutationTypes.removeLang, payload) + }, + [ActionTypes.editLang]({ commit }, payload) { + commit(MutationTypes.editLang, payload) + }, +} diff --git a/src/store/modules/app/lang/getters.ts b/src/store/modules/app/lang/getters.ts new file mode 100644 index 0000000..9d82c12 --- /dev/null +++ b/src/store/modules/app/lang/getters.ts @@ -0,0 +1,25 @@ +import { GetterTree } from 'vuex' +import { State } from './index' +import { RootState } from '~/store/index' + +export type Getters = { + lang(state: S, key: string): any + langMain(state: S, key: string): any + langData(state: S, key: string): any + langForms(state: S, key: string): any +} + +export const getters: GetterTree & Getters = { + lang: (state: State, key: string) => { + return state.lang.get(key) + }, + langMain: (state: State, key: string) => { + return state.lang.get(key)?.main || null + }, + langData: (state: State, key: string) => { + return state.lang.get(key)?.data || null + }, + langForms: (state: State, key: string) => { + return state.lang.get(key)?.forms || null + }, +} diff --git a/src/store/modules/app/lang/index.ts b/src/store/modules/app/lang/index.ts new file mode 100644 index 0000000..7b196dd --- /dev/null +++ b/src/store/modules/app/lang/index.ts @@ -0,0 +1,51 @@ +import { + Store as VuexStore, + Module, + CommitOptions, + DispatchOptions, +} from 'vuex' + +import { getters, Getters } from './getters' +import { mutations, Mutations, MutationTypes } from './mutations' +import { actions, Actions, ActionTypes } from './actions' + +import { RootState } from '~/store/index' + +import { AppLang } from '~/store/types' + +interface State { + lang: Map +} + +const state: State = { + lang: new Map(), +} + +const data_module: Module = { + state, + mutations, + actions, + getters, +} + +export default data_module + +type Store = Omit, 'commit' | 'getters' | 'dispatch' > & { + commit[1]>( + key: K, + payload: P, + options?: CommitOptions + ): ReturnType +} & { + getters: { + [K in keyof Getters]: ReturnType + } +} & { + dispatch( + key: K, + payload: Parameters[1], + options?: DispatchOptions + ): ReturnType +} + +export { State, ActionTypes, MutationTypes, Store } diff --git a/src/store/modules/app/lang/mutations.ts b/src/store/modules/app/lang/mutations.ts new file mode 100644 index 0000000..258abbb --- /dev/null +++ b/src/store/modules/app/lang/mutations.ts @@ -0,0 +1,108 @@ +import { MutationTree } from 'vuex' +import { State } from './index' +import { AppLang, AppCtxLang, LangMain, LangData, LangForms } from '~/store/types' + +export enum MutationTypes { + addLang = 'addLang', + addLangMain = 'addLangMain', + addLangData = 'addLangData', + addLangForms = 'addLangForms', + removeLang = 'removeLang', + editLang = 'editLang' +} +interface LangMap { + key: string + lang: AppLang +} +interface LangSection { + key: string + section: any +} +interface CtxLangMap { + key: string + lang: AppCtxLang +} + +export type Mutations = { + [MutationTypes.addLang](state: S, lang_map: LangMap): void + [MutationTypes.addLangMain](state: S, lang_map: LangSection): void + [MutationTypes.addLangData](state: S, lang_map: LangSection): void + [MutationTypes.addLangForms](state: S, lang_map: LangSection): void + [MutationTypes.removeLang](state: S, lang_map: CtxLangMap): void + [MutationTypes.editLang](state: S, lang_map: CtxLangMap): void +} + +const get_lang_map = (state: State, mapkey: string): AppLang => { + const lng = state.lang.get(mapkey) + return lng || { main: {}, data: {}, forms: {} } +} + +export const mutations: MutationTree & Mutations = { + [MutationTypes.addLang](state: State, lang_map: LangMap) { + state.lang.set(lang_map.key, lang_map.lang) + }, + [MutationTypes.addLangMain](state, lang_map: LangSection) { + const lng = get_lang_map(state, lang_map.key) + lng.main = lang_map.section + state.lang.set(lang_map.key, lng) + }, + [MutationTypes.addLangData](state, lang_map: LangSection) { + const lng = get_lang_map(state, lang_map.key) + lng.data = lang_map.section + state.lang.set(lang_map.key, lng) + }, + [MutationTypes.addLangForms](state, lang_map: LangSection) { + const lng = get_lang_map(state, lang_map.key) + lng.data = lang_map.section + state.lang.set(lang_map.key, lng) + }, + [MutationTypes.removeLang](state: State, lang_map: CtxLangMap) { + const lang = get_lang_map(state, lang_map.key) + const key = lang_map.lang.lng.key + switch (lang_map.lang.ctx) { + case 'main': + if (lang.main[key]) { + delete lang.main[key] + state.lang.set(lang_map.key, lang) + } + break + case 'data': + if (lang.data[key]) { + delete lang.data[key] + state.lang.set(lang_map.key, lang) + } + break + case 'forms': + if (lang.forms[key]) { + delete lang.forms[key] + state.lang.set(lang_map.key, lang) + } + break + } + }, + [MutationTypes.editLang](state: State, lang_map: CtxLangMap) { + const lang = get_lang_map(state, lang_map.key) + const key = lang_map.lang.lng.key + const val = lang_map.lang.lng.text + switch (lang_map.lang.ctx) { + case 'main': + if (lang.main[key]) { + lang.main[key] = val + state.lang.set(lang_map.key, lang) + } + break + case 'data': + if (lang.data[key]) { + lang.data[key] = val + state.lang.set(lang_map.key, lang) + } + break + case 'forms': + if (lang.forms[key]) { + lang.forms[key] = val + state.lang.set(lang_map.key, lang) + } + break + } + }, +} diff --git a/src/store/modules/app/profile/actions.ts b/src/store/modules/app/profile/actions.ts new file mode 100644 index 0000000..d5e8ee9 --- /dev/null +++ b/src/store/modules/app/profile/actions.ts @@ -0,0 +1,44 @@ +import { ActionContext, ActionTree } from 'vuex' +import { Mutations, MutationTypes } from './mutations' +import { State } from './index' +import { RootState } from '~/store/index' + +export enum ActionTypes { + addProfile = 'addProfile', + removeProfile = 'removeProfile', + editProfile = 'editProfile' +} + +type AppProfileActionContext = { + commit( + key: K, + payload: Parameters[1] + ): ReturnType +} & Omit, 'commit'> + +export interface Actions { + [ActionTypes.addProfile]( + { commit }: AppProfileActionContext, + payload: any + ): void + [ActionTypes.removeProfile]( + { commit }: AppProfileActionContext, + payload: any + ): void + [ActionTypes.editProfile]( + { commit }: AppProfileActionContext, + payload: any + ): void +} + +export const actions: ActionTree & Actions = { + [ActionTypes.addProfile]({ commit }, payload) { + commit(MutationTypes.addProfile, payload) + }, + [ActionTypes.removeProfile]({ commit }, payload) { + commit(MutationTypes.removeProfile, payload) + }, + [ActionTypes.editProfile]({ commit }, payload) { + commit(MutationTypes.editProfile, payload) + }, +} diff --git a/src/store/modules/app/profile/getters.ts b/src/store/modules/app/profile/getters.ts new file mode 100644 index 0000000..75986d0 --- /dev/null +++ b/src/store/modules/app/profile/getters.ts @@ -0,0 +1,13 @@ +import { GetterTree } from 'vuex' +import { State } from './index' +import { RootState } from '~/store/index' + +export type Getters = { + profile(state: S): any +} + +export const getters: GetterTree & Getters = { + profile: (state: State) => { + return state.profile + }, +} diff --git a/src/store/modules/app/profile/index.ts b/src/store/modules/app/profile/index.ts new file mode 100644 index 0000000..23a1e58 --- /dev/null +++ b/src/store/modules/app/profile/index.ts @@ -0,0 +1,49 @@ +import { + Store as VuexStore, + Module, + CommitOptions, + DispatchOptions, +} from 'vuex' + +import { getters, Getters } from './getters' +import { mutations, Mutations, MutationTypes } from './mutations' +import { actions, Actions, ActionTypes } from './actions' + +import { RootState } from '~/store/index' + +interface State { + profile: any +} + +const state: State = { + profile: {}, +} + +const data_module: Module = { + state, + mutations, + actions, + getters, +} + +export default data_module + +type Store = Omit, 'commit' | 'getters' | 'dispatch' > & { + commit[1]>( + key: K, + payload: P, + options?: CommitOptions + ): ReturnType +} & { + getters: { + [K in keyof Getters]: ReturnType + } +} & { + dispatch( + key: K, + payload: Parameters[1], + options?: DispatchOptions + ): ReturnType +} + +export { State, ActionTypes, MutationTypes, Store } diff --git a/src/store/modules/app/profile/mutations.ts b/src/store/modules/app/profile/mutations.ts new file mode 100644 index 0000000..dc4d5e9 --- /dev/null +++ b/src/store/modules/app/profile/mutations.ts @@ -0,0 +1,37 @@ +import { MutationTree } from 'vuex' +import { State } from './index' + +export enum MutationTypes { + addProfile = 'addProfile', + removeProfile = 'removeProfile', + editProfile = 'editProfile' +} + +export type Mutations = { + [MutationTypes.addProfile](state: S, profile: any): void + [MutationTypes.removeProfile](state: S, target: any): void + [MutationTypes.editProfile](state: S, target: any, key: string): void +} + +export const mutations: MutationTree & Mutations = { + [MutationTypes.addProfile](state: State, profile: any) { + state.profile = profile + }, + [MutationTypes.removeProfile](state: State, target: any) { + const profile = state.profile as any + const key = target.key + if (profile[key]) { + delete profile[key] + state.profile = profile + } + }, + [MutationTypes.editProfile](state: State, target: any) { + const profile = state.profile as any + const key = target.key + const data = target.data + if (profile[key]) { + profile[key] = data + state.profile = profile + } + }, +} diff --git a/src/store/modules/index.ts b/src/store/modules/index.ts new file mode 100644 index 0000000..57a8338 --- /dev/null +++ b/src/store/modules/index.ts @@ -0,0 +1 @@ +export * from './app' diff --git a/src/store/store_module.ts b/src/store/store_module.ts new file mode 100644 index 0000000..3feff73 --- /dev/null +++ b/src/store/store_module.ts @@ -0,0 +1,97 @@ +import { useStore, Store } from 'vuex' + +interface InternalModule { + state: S + actions: A + mutations: M + getters: G +} + +/** + * This function allows us to access the internal vuex properties and + * maps them in a way which removes the module prefix. + */ +function getFromStoreByType( + moduleName: string, + type: unknown, + isNamespaced: boolean, +) { + if (isNamespaced) { + return Object.keys(type) + .filter(t => t.startsWith(`${moduleName}/`)) + .reduce((acc, curr) => { + const typeName = curr.split('/').pop() + const typeValue = type[curr][0] + + return { [typeName]: typeValue, ...acc } + }, {}) as T + } + + return Object.keys(type).reduce((acc, curr) => { + const typeValue = type[curr][0] + + return { [curr]: typeValue, ...acc } + }, {}) as T +} + +/* + * We have to wrap the getters in a Proxy because we only want to + * "access" the getter if it actually being accessed. + * + * We could technically use the getFromStoreByType function but + * the getter would be invoked multiple types on store instantiation. + * + * This is just a little cheeky workaround. Proxy <3 + */ +function wrapGettersInProxy( + moduleName: string, + getters: G, + isNamespaced: boolean, +) { + return new Proxy(getters as Object, { + get(_, prop: string) { + if (isNamespaced) + return getters[`${moduleName}/${prop}`] + + return getters[prop] + }, + }) as G +} + +function isModuleNamespaced(moduleName: string, store: Store): boolean { + // @ts-ignore internal Vuex object that isn't typed. + return Boolean(store._modulesNamespaceMap[`${moduleName}/`]) +} + +export default function useStoreModule( + moduleName: string, + storeName?: string, +): InternalModule { + // @ts-ignore useStore doesn't yet accept a key as arg + const store = storeName ? useStore(storeName) : useStore() + const state = store.state[moduleName] + const isNamespaced = isModuleNamespaced(moduleName, store) + + const actions = getFromStoreByType( + moduleName, + // @ts-ignore internal Vuex object that isn't typed. + store._actions, + isNamespaced, + ) + + const mutations = getFromStoreByType( + moduleName, + // @ts-ignore internal Vuex object that isn't typed. + store._mutations, + isNamespaced, + ) + + const getters = wrapGettersInProxy(moduleName, store.getters, isNamespaced) + + return { + actions, + mutations, + state, + getters, + } +} diff --git a/src/store/types.ts b/src/store/types.ts new file mode 100644 index 0000000..95a83c8 --- /dev/null +++ b/src/store/types.ts @@ -0,0 +1,78 @@ +import { + AppDataMutationTypes, + AppDataActionTypes, + AppCheckMutationTypes, + AppCheckActionTypes, + AppDefsMutationTypes, + AppDefsActionTypes, + AppProfileMutationTypes, + AppProfileActionTypes, + AppLangMutationTypes, + AppLangActionTypes, +} from './modules/app/index' + +export const AppDataMutation = AppDataMutationTypes +export const AppDataAction = AppDataActionTypes +export const AppCheckMutation = AppCheckMutationTypes +export const AppCheckAction = AppCheckActionTypes +export const AppDefsMutation = AppDefsMutationTypes +export const AppDefsAction = AppDefsActionTypes +export const AppProfileMutation = AppProfileMutationTypes +export const AppProfileAction = AppProfileActionTypes +export const AppLangMutation = AppLangMutationTypes +export const AppLangAction = AppLangActionTypes + +export interface LangCtxKey { + ctx: string + key: string +} + +export interface LangItem { + key: string + text: string +} + +export interface LangMain { + [key: string]: string +} +export interface LangData { + [key: string]: string +} +export interface LangForms { + [key: string]: string +} + +export interface AppLang { + main: LangMain + data: LangData + forms: LangForms +} + +export interface AppCtxLang { + ctx: string + lng: LangItem +} +export interface AppDefs { + [key: string]: string +} + +export interface AppProfile { + [key: string]: string +} + +export interface AppData { + [key: string]: string +} + +export interface AppCheck { + [key: string]: string +} + +/* +export interface AppStore { + defs: AppDefs + profile: AppProfile + data: [AppData] + lang: AppLang +} +*/ diff --git a/src/styles/main.css b/src/styles/main.css new file mode 100755 index 0000000..6829bd1 --- /dev/null +++ b/src/styles/main.css @@ -0,0 +1,25 @@ +html, +body, +#app { + height: 100%; + margin: 0; + padding: 0; +} + +html.dark { + background: #121212; +} + +.btn { + @apply px-4 py-1 rounded inline-block + bg-teal-600 text-white cursor-pointer + hover:bg-teal-700 + disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50; +} + +.icon-btn { + @apply inline-block cursor-pointer select-none + opacity-75 transition duration-200 ease-in-out + hover:opacity-100 hover:text-teal-600; + font-size: 0.9em; +} diff --git a/src/typs/clouds/index.ts b/src/typs/clouds/index.ts new file mode 100644 index 0000000..8db77a0 --- /dev/null +++ b/src/typs/clouds/index.ts @@ -0,0 +1,56 @@ +export interface StatusItemType { + [key: string]: any + title: string + text: string + isOpen: boolean +} +export interface StatusItemDataType { + [key: string]: any + title: string + text: string +} +export const enum ReqType { + tcp = 'tcp', + https = 'https', + NotSet = 'NotSet', +} +export const enum CriticalType { + yes = 'yes', + cloud = 'cloud', + group = 'group', + ifresized = 'ifresized', + no = 'no', +} +export interface SrvcType { + name: string + path: string + req: ReqType + target: string + liveness: string + critical: CriticalType +} +export interface SrvcInfoType { + [key: string]: any + name: string + info: string + srvc: SrvcType +} +export interface CloudGroupItemType { + [key: string]: any + hostname: string + tsksrvcs: SrvcType[] + appsrvcs: SrvcType[] +} +export interface CloudGroupServcType { + [key: string]: any + hostname: string + name: string + tsksrvcs: SrvcInfoElemType[] + appsrvcs: SrvcInfoElemType[] +} + +export interface ResCloudDataCheck { + group_cloud: CloudGroupSrvcType + group_apps: CloudGroupSrvcType + statusentries: StatusItemDataType[] +} diff --git a/src/typs/index.ts b/src/typs/index.ts new file mode 100644 index 0000000..d4eadde --- /dev/null +++ b/src/typs/index.ts @@ -0,0 +1,13 @@ +export enum MessageType { + Show, + Success, + Error, + Warning, + Info, +} +export interface MenuItemType { + id: string + title: string + active: boolean + link: string +} diff --git a/src/views/404.vue b/src/views/404.vue new file mode 100644 index 0000000..4f4f9b4 --- /dev/null +++ b/src/views/404.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/views/Home.vue b/src/views/Home.vue new file mode 100644 index 0000000..405b25d --- /dev/null +++ b/src/views/Home.vue @@ -0,0 +1,168 @@ + + + diff --git a/src/views/Login.vue b/src/views/Login.vue new file mode 100644 index 0000000..b054cb3 --- /dev/null +++ b/src/views/Login.vue @@ -0,0 +1,470 @@ + + + + diff --git a/src/views/Logout.vue b/src/views/Logout.vue new file mode 100644 index 0000000..2222a20 --- /dev/null +++ b/src/views/Logout.vue @@ -0,0 +1,130 @@ + + + + From b496d51ece6c1a1b8a82de7c076943382bec9422 Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:43:47 +0100 Subject: [PATCH 05/27] chore: add env --- auto-imports.d.ts | 172 ++++++++++++++++++++++++++++++++++++++++++++++ components.d.ts | 34 +++++++++ index.html | 26 +++++++ locales/README.md | 7 ++ locales/en.yml | 132 +++++++++++++++++++++++++++++++++++ locales/es.yml | 135 ++++++++++++++++++++++++++++++++++++ package.json | 47 +++++++++++++ vite.config.ts | 90 ++++++++++++++++++++++++ windi.config.ts | 71 +++++++++++++++++++ 9 files changed, 714 insertions(+) create mode 100644 auto-imports.d.ts create mode 100644 components.d.ts create mode 100644 index.html create mode 100644 locales/README.md create mode 100644 locales/en.yml create mode 100644 locales/es.yml create mode 100644 package.json create mode 100644 vite.config.ts create mode 100644 windi.config.ts diff --git a/auto-imports.d.ts b/auto-imports.d.ts new file mode 100644 index 0000000..2c4df58 --- /dev/null +++ b/auto-imports.d.ts @@ -0,0 +1,172 @@ +// Generated by 'unplugin-auto-import' +// We suggest you to commit this file into source control +declare global { + const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] + const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] + const biSyncRef: typeof import('@vueuse/core')['biSyncRef'] + const computed: typeof import('vue')['computed'] + const computedInject: typeof import('@vueuse/core')['computedInject'] + const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] + const controlledRef: typeof import('@vueuse/core')['controlledRef'] + const createApp: typeof import('vue')['createApp'] + const createEventHook: typeof import('@vueuse/core')['createEventHook'] + const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] + const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] + const customRef: typeof import('vue')['customRef'] + const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] + const extendRef: typeof import('@vueuse/core')['extendRef'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const h: typeof import('vue')['h'] + const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] + const inject: typeof import('vue')['inject'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] + 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 onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] + const provide: typeof import('vue')['provide'] + const reactify: typeof import('@vueuse/core')['reactify'] + const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] + const reactive: typeof import('vue')['reactive'] + const reactivePick: typeof import('@vueuse/core')['reactivePick'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const syncRef: typeof import('@vueuse/core')['syncRef'] + const templateRef: typeof import('@vueuse/core')['templateRef'] + const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] + const toRaw: typeof import('vue')['toRaw'] + const toReactive: typeof import('@vueuse/core')['toReactive'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const triggerRef: typeof import('vue')['triggerRef'] + const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] + const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] + const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] + const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] + const unref: typeof import('vue')['unref'] + const unrefElement: typeof import('@vueuse/core')['unrefElement'] + const until: typeof import('@vueuse/core')['until'] + const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] + const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] + const useAttrs: typeof import('vue')['useAttrs'] + const useBattery: typeof import('@vueuse/core')['useBattery'] + const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] + const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] + const useClipboard: typeof import('@vueuse/core')['useClipboard'] + const useCounter: typeof import('@vueuse/core')['useCounter'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVar: typeof import('@vueuse/core')['useCssVar'] + const useDark: typeof import('@vueuse/core')['useDark'] + const useDebounce: typeof import('@vueuse/core')['useDebounce'] + const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] + const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] + const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] + const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] + const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] + const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] + const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] + const useDraggable: typeof import('@vueuse/core')['useDraggable'] + const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] + const useElementSize: typeof import('@vueuse/core')['useElementSize'] + const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] + const useEventBus: typeof import('@vueuse/core')['useEventBus'] + const useEventListener: typeof import('@vueuse/core')['useEventListener'] + const useEventSource: typeof import('@vueuse/core')['useEventSource'] + const useFavicon: typeof import('@vueuse/core')['useFavicon'] + const useFetch: typeof import('@vueuse/core')['useFetch'] + const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] + const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] + const useHead: typeof import('@vueuse/head')['useHead'] + const useI18n: typeof import('vue-i18n')['useI18n'] + const useIdle: typeof import('@vueuse/core')['useIdle'] + const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] + const useInterval: typeof import('@vueuse/core')['useInterval'] + const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] + const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] + const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] + const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] + const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] + const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] + const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] + const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] + const useMouse: typeof import('@vueuse/core')['useMouse'] + const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] + const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] + const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] + const useNetwork: typeof import('@vueuse/core')['useNetwork'] + const useNow: typeof import('@vueuse/core')['useNow'] + const useOnline: typeof import('@vueuse/core')['useOnline'] + const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] + const useParallax: typeof import('@vueuse/core')['useParallax'] + const usePermission: typeof import('@vueuse/core')['usePermission'] + const usePointer: typeof import('@vueuse/core')['usePointer'] + const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] + const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] + const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] + const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] + const useRafFn: typeof import('@vueuse/core')['useRafFn'] + const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] + const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] + const useScroll: typeof import('@vueuse/core')['useScroll'] + const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] + const useShare: typeof import('@vueuse/core')['useShare'] + const useSlots: typeof import('vue')['useSlots'] + const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] + const useStorage: typeof import('@vueuse/core')['useStorage'] + const useSwipe: typeof import('@vueuse/core')['useSwipe'] + const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] + const useThrottle: typeof import('@vueuse/core')['useThrottle'] + const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] + const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] + const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] + const useTimeout: typeof import('@vueuse/core')['useTimeout'] + const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] + const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] + const useTitle: typeof import('@vueuse/core')['useTitle'] + const useToggle: typeof import('@vueuse/core')['useToggle'] + const useTransition: typeof import('@vueuse/core')['useTransition'] + const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] + const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] + const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] + const useVModel: typeof import('@vueuse/core')['useVModel'] + const useVModels: typeof import('@vueuse/core')['useVModels'] + const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] + const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] + const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] + const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] + const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] + const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] + const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] + const watch: typeof import('vue')['watch'] + const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchOnce: typeof import('@vueuse/core')['watchOnce'] + const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] + const whenever: typeof import('@vueuse/core')['whenever'] +} +export {} diff --git a/components.d.ts b/components.d.ts new file mode 100644 index 0000000..7eb6ec1 --- /dev/null +++ b/components.d.ts @@ -0,0 +1,34 @@ +// generated by unplugin-vue-components +// We suggest you to commit this file into source control +// Read more: https://github.com/vuejs/vue-next/pull/3399 + +declare module 'vue' { + export interface GlobalComponents { + AccordionView: typeof import('./src/components/AccordionView.vue')['default'] + AppImg: typeof import('./src/components/icons/AppImg.vue')['default'] + AppLogoText: typeof import('./src/components/icons/AppLogoText.vue')['default'] + AppLogoV: typeof import('./src/components/icons/AppLogoV.vue')['default'] + CarbonCampsite: typeof import('~icons/carbon/campsite')['default'] + CarbonCheck: typeof import('~icons/carbon/check')['default'] + CarbonCheckmark: typeof import('~icons/carbon/checkmark')['default'] + CarbonLanguage: typeof import('~icons/carbon/language')['default'] + CarbonLogin: typeof import('~icons/carbon/login')['default'] + CarbonLogoGithub: typeof import('~icons/carbon/logo-github')['default'] + CarbonLogout: typeof import('~icons/carbon/logout')['default'] + CarbonMoon: typeof import('~icons/carbon/moon')['default'] + CarbonPedestrian: typeof import('~icons/carbon/pedestrian')['default'] + CarbonScript: typeof import('~icons/carbon/script')['default'] + CarbonSearch: typeof import('~icons/carbon/search')['default'] + CarbonSun: typeof import('~icons/carbon/sun')['default'] + CarbonWarning: typeof import('~icons/carbon/warning')['default'] + CloudGroups: typeof import('./src/components/CloudGroups.vue')['default'] + CloudServices: typeof import('./src/components/CloudServices.vue')['default'] + CloudSrvc: typeof import('./src/components/CloudSrvc.vue')['default'] + Footer: typeof import('./src/components/Footer.vue')['default'] + MenuLocales: typeof import('./src/components/menus/MenuLocales.vue')['default'] + NavMenu: typeof import('./src/components/NavMenu.vue')['default'] + ProfileView: typeof import('./src/components/ProfileView.vue')['default'] + } +} + +export { } diff --git a/index.html b/index.html new file mode 100644 index 0000000..a69b9b0 --- /dev/null +++ b/index.html @@ -0,0 +1,26 @@ + + + + + + + Vitesse Lite + + + +
+ + + + diff --git a/locales/README.md b/locales/README.md new file mode 100644 index 0000000..4b24ec2 --- /dev/null +++ b/locales/README.md @@ -0,0 +1,7 @@ +## i18n + +This directory is to serve your locale translation files. YAML under this folder would be loaded automatically and register with their filenames as locale code. + +Check out [`vue-i18n`](https://github.com/intlify/vue-i18n-next) for more details. + +If you are using VS Code, [`i18n Ally`](https://github.com/lokalise/i18n-ally) is recommended to make the i18n experience better. diff --git a/locales/en.yml b/locales/en.yml new file mode 100644 index 0000000..35d1e6e --- /dev/null +++ b/locales/en.yml @@ -0,0 +1,132 @@ +All: All +auth: + invalidcredentials: Invalid credentials + loginForm: '' + newaccount: new account + password: password + register: Register + signin: Sign in + subHeading: Login info + subTitle: '' + wellcome: Wellcome ! +bc: + home: librecloud + topographic_anatomy: klouds +bm: + topographic-anatomy: Topographic Anatomy +button: + about: About + back: Back + cancel: Cancel + close-panel: Close panel + delete: Delete + go: Go + home: Home + new: Nuevo + reset: Reset + save: Save + toggle_dark: Toggle dark mode + toggle_langs: Change language + login: Login + logout: Logout +connection: + error: Error conexión +dashboard: Dashboard +en: English +entry: + Apps: Apps + Code: Code + DB: DB + Data: Data + DataCode: Data / Code + Document: Document + Documents: Documents + Macro: Macro + Profiles: Profiles/roles + Schema: Schema + Services: Services + Shortcut: Shortcut + Template: Template + Trans: Translations +es: Español +form: + delete_done: Delete done + delete_error: Delete Error + save_done: Data saved + save_error: Data save Error +intro: + desc: Opinionated Vite Starter Template + dynamic-route: Demo of dynamic route + hi: Hi, {name}! + whats-your-name: What's your name? +login: + end_session: End session + form: Credentials + invalidcredentials: Incorrect data + newuser: New user + nodata: No data + password: Password + register: Register + reset: Reset + see_you_soon: See You soon ! + signin: Signin + subHeading: Access + subtitle: LibreCloud online + user_email: User / email + wellcome: Wellcome +menu: + copy: Copy + data-grid: Data Grid + edit: Edit + edit-items: Edit items + home: Home + login: Init session + logout: Close session + new: New + open-recent: Open recent + paste: Paste + save: Save + settings: Configuration + sign-in: Signin + sign-out: Signout + your-profile: Your profile +message: + loadding: Loading +not-found: Not found +notes: Notes +notifications: + content: content + notifications: Notifications +search: + search: Search +settings: + above-noedit: ALL above options in "off" configure mode for + aside: Aside + col: Col + columns-settings: Columns + filter: Filter + grid: Grid + grid-options: Grid options + hidden: Hide + id: Id + list: List + main: Main + no-edition: no edition + pagination: Pagination + panels: Panels + pos: Pos + position: position + select: Select + select-config: Select configuration + select-grid-type: Select grid type + setting-id: Identificator + settings: Configuration + slide: Modal + sort: Sort + table: Table + undefined: Undefined +srvc: + mailserver::smtp::imap: mail imap + mailserver::smtp::pop: mail pop + mailserver::smtp::tls: mail tls + mailserver::smtp: mail smtp diff --git a/locales/es.yml b/locales/es.yml new file mode 100644 index 0000000..04e0869 --- /dev/null +++ b/locales/es.yml @@ -0,0 +1,135 @@ +All: All +auth: + invalidcredentials: Invalid credentials + loginForm: '' + newaccount: new account + password: password + register: Register + signin: Sign in + subHeading: Login info + subTitle: '' + wellcome: Wellcome ! +bc: + home: librecloud + topographic_anatomy: klouds +bm: + topographic-anatomy: Anatomía topográfica +button: + about: Acerca de + back: Atrás + cancel: Cancelar + close-panel: Cerarr panel + delete: Borrar + go: Ir + home: Inicio + new: Nuevo + reset: Reset + save: Guardar + toggle_dark: Alternar modo oscuro + toggle_langs: Cambiar idiomas + login: Login + logout: Desconectar +connection: + error: Error conexión +dashboard: Panel de control +en: English +entry: + Apps: Apps + Code: Code + DB: DB + Data: Data + DataCode: Data / Code + Document: Document + Documents: Documents + Macro: Macro + Profiles: Profiles/roles + Schema: Schema + Services: Services + Shortcut: Shortcut + Template: Template + Trans: Translations +es: Español +form: + delete_done: Borrado realizado + delete_error: Error al borrar datos + save_done: Datos guardados + save_error: Error al guardar datos +intro: + desc: Plantilla de Inicio de Vite Dogmática + dynamic-route: Demo de ruta dinámica + hi: ¡Hola, {name}! + whats-your-name: ¿Cómo te llamas? +login: + end_session: Sesión finalizada + form: Credenciales + invalidcredentials: Datos incorrectos + newuser: Nuevo usuario + nodata: No hay datos + password: Password + register: Registrarse + reset: Reset + see_you_soon: ¡ Nos vemos pronto ! + signin: Iniciar sesión + subHeading: Acceso + subtitle: LibreCloud online + user_email: Usuario / email + wellcome: Bienvenido/a +menu: + copy: Copiar + data-grid: Cuadrícula de datos + edit: Editar + edit-items: Editar items + home: Inicio + login: Inicio sesión + logout: Cerrar sesión + new: Nuevo + open-recent: Abrir reciente + paste: Pegar + save: Guardar + settings: Configuración + sign-in: Registrarse + sign-out: Desconectar + your-profile: Tu perfil +message: + loadding: Cargando +not-found: No se ha encontrado +notes: Notas +notifications: + content: contenido + notifications: Notificiaciones +search: + search: Buscar +settings: + above-noedit: TODAS las opciones de arriba en "off" configuran el modo + aside: Al lado + col: Col + columns-settings: Columnas + filter: Filtrar + grid: Cuadrícula + grid-options: Opciones cuadrícula + hidden: Ocultar + id: Id + list: Lista + main: Principal + no-edition: no edición + pagination: Paginación + panels: Paneles + pos: Pos + position: posición + select: Seleccionar + select-config: Seleccionar configuración + select-grid-type: Seleccionar tipo cuadrícula + setting-id: Identificador + settings: Configuración + slide: Modal + sort: Ordenar + table: Tabla + undefined: No definido +graphsettings: + clouds: Clouds + groups: Grupos +srvc: + mailserver::smtp::imap: correo imap + mailserver::smtp::pop: correo pop + mailserver::smtp::tls: correo tls + mailserver::smtp: correo smtp diff --git a/package.json b/package.json new file mode 100644 index 0000000..37e2c5f --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "private": true, + "scripts": { + "dev": "vite --port 3333 --open", + "build": "cross-env NODE_ENV=production vite build", + "preview": "vite preview" + }, + "dependencies": { + "@intlify/vite-plugin-vue-i18n": "^2.4.0", + "@vueuse/core": "^6.5.3", + "@vueuse/head": "^0.6.0", + "a17t": "^0.5.1", + "nprogress": "^0.2.0", + "toastify-js": "^1.11.2", + "vite-imagetools": "^3.8.0", + "vue": "^3.2.20", + "vue-demi": "^0.11.4", + "vue-i18n": "^9.1.9", + "vue-router": "^4.0.11", + "vuex": "^4.0.2" + }, + "devDependencies": { + "@antfu/eslint-config": "^0.9.0", + "@iconify-json/carbon": "^1.0.5", + "@types/node": "^16.10.3", + "@vitejs/plugin-vue": "^1.9.3", + "cross-env": "^7.0.3", + "eslint": "^7.32.0", + "pnpm": "^6.17.0", + "typescript": "^4.4.3", + "unplugin-auto-import": "^0.4.12", + "unplugin-icons": "^0.12.13", + "unplugin-vue-components": "^0.15.6", + "vite": "^2.6.7", + "vite-plugin-md": "^0.11.1", + "vite-plugin-pages": "^0.18.1", + "vite-plugin-vue-layouts": "^0.5.0", + "vite-plugin-windicss": "^1.4.10" + }, + "eslintConfig": { + "extends": "@antfu/eslint-config", + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "off" + } + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..cc4af68 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,90 @@ +import path from 'path' +import { defineConfig } from 'vite' +import Vue from '@vitejs/plugin-vue' +import Pages from 'vite-plugin-pages' +import { imagetools } from 'vite-imagetools' +import Layouts from 'vite-plugin-vue-layouts'; +import Icons from 'unplugin-icons/vite' +import IconsResolver from 'unplugin-icons/resolver' +import Components from 'unplugin-vue-components/vite' +import WindiCSS from 'vite-plugin-windicss' +import AutoImport from 'unplugin-auto-import/vite' +import VueI18n from '@intlify/vite-plugin-vue-i18n' + +export default defineConfig({ + resolve: { + alias: { + '~/': `${path.resolve(__dirname, 'src')}/`, + '@/': `${path.resolve(__dirname, 'src/components')}/`, + }, + }, + plugins: [ + Vue(), + + // https://github.com/hannoeru/vite-plugin-pages + Pages(), + imagetools(), + // https://github.com/JohnCampionJr/vite-plugin-vue-layouts + Layouts({ + layoutsDir: 'src/layouts', + defaultLayout: 'Default' + }), + + // https://github.com/antfu/unplugin-auto-import + AutoImport({ + imports: [ + 'vue', + 'vue-router', + 'vue-i18n', + '@vueuse/head', + '@vueuse/core', + ], + dts: true, + }), + + // https://github.com/antfu/vite-plugin-components + Components({ + resolvers: [ + // auto import icons + // https://github.com/antfu/vite-plugin-icons + IconsResolver({ + componentPrefix: '', + enabledCollections: ['carbon'], + }), + ], + dts: true, + }), + + // https://github.com/antfu/vite-plugin-icons + Icons({ + autoInstall: true, + }), + + // https://github.com/antfu/vite-plugin-windicss + WindiCSS({ + }), + VueI18n({ + runtimeOnly: true, + compositionOnly: true, + include: [path.resolve(__dirname, 'locales/**')], + }), + ], + + server: { + fs: { + strict: true, + }, + }, + + optimizeDeps: { + include: [ + 'vue', + 'vue-router', + '@vueuse/core', + '@vueuse/head', + ], + exclude: [ + 'vue-demi', + ], + }, +}) diff --git a/windi.config.ts b/windi.config.ts new file mode 100644 index 0000000..d05b218 --- /dev/null +++ b/windi.config.ts @@ -0,0 +1,71 @@ +import { defineConfig } from 'windicss/helpers' +import colors from 'windicss/colors' +import typography from 'windicss/plugin/typography' + +export default defineConfig({ + darkMode: 'class', + // https://windicss.org/posts/v30.html#attributify-mode + attributify: true, + + plugins: [ + typography(), + ], + theme: { + extend: { + typography: { + DEFAULT: { + css: { + maxWidth: '65ch', + color: 'inherit', + a: { + 'color': 'inherit', + 'opacity': 0.75, + 'fontWeight': '500', + 'textDecoration': 'underline', + '&:hover': { + opacity: 1, + color: colors.teal[600], + }, + }, + b: { color: 'inherit' }, + strong: { color: 'inherit' }, + em: { color: 'inherit' }, + h1: { color: 'inherit' }, + h2: { color: 'inherit' }, + h3: { color: 'inherit' }, + h4: { color: 'inherit' }, + code: { color: 'inherit' }, + }, + }, + }, + }, + }, + shortcuts: { + 'cont-box': { + 'border-color': 'rgb(128 128 128 / 41%)', + 'border-radius': '5px', + 'background-color': 'rgb(55 65 81 / 12%)', + // 'background-color': 'rgb(8 8 8 / 25%)', + '@apply': 'border border-opacity-10 p-2', + }, + 'dark cont-box': { 'background-color': 'rgb(55 65 81 / 38%)' }, + 'box': { + 'border-color': 'lightslategray', + '@apply': + 'py-5 px-5 max-w-sm mx-auto border border-opacity-10 ' + + 'bg-white dark:bg-gray-800 dark:bg-opacity-90 ' + + 'rounded-xl shadow-m space-y-2 ' + + 'sm:py-6 sm:items-center sm:space-y-0 sm:space-x-6 ', + }, + 'btn': { + '@apply': + 'px-4 py-1 text-sm text-purple-600 font-semibold ' + + 'rounded-full border border-purple-200 dark:border-purple-800 ' + + 'hover:text-white hover:bg-purple-600 hover:border-transparent ' + + 'focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-offset-2 ', + }, + 'cloud': { + 'background-image': 'url("data:image/svg+xml;utf8, cloud_blue")', + }, + }, +}) From 53d5bdc08b5ec858f7f34dda0b37cb7b438e4159 Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:44:10 +0100 Subject: [PATCH 06/27] chore: add env --- .eslintignore | 3 +++ .eslintrc | 13 +++++++++++++ netlify.toml | 17 +++++++++++++++++ tsconfig.json | 28 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 .eslintignore create mode 100644 .eslintrc create mode 100755 netlify.toml create mode 100644 tsconfig.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..e6a8276 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +dist +node_modules +public diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..44240d4 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "@antfu" + ], + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "off", + "camelcase": "off" + }, + "plugins": [ + "snakecasejs" + ] +} diff --git a/netlify.toml b/netlify.toml new file mode 100755 index 0000000..0512635 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,17 @@ +[build.environment] + NPM_FLAGS = "--prefix=/dev/null" + NODE_VERSION = "14" + +[build] + publish = "dist" + command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm run build" + +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 + +[[headers]] + for = "/manifest.webmanifest" + [headers.values] + Content-Type = "application/manifest+json" \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..abcdd07 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "module": "ESNext", + "target": "es2016", + "lib": ["DOM", "ESNext"], + "strict": true, + "esModuleInterop": true, + "incremental": false, + "skipLibCheck": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "noUnusedLocals": true, + "strictNullChecks": true, + "forceConsistentCasingInFileNames": true, + "types": [ + "vite/client", + "vite-plugin-pages/client", + "vite-plugin-vue-layouts/client" + ], + "paths": { + "~/*": ["src/*"], + "@/*": ["src/components/*"], + }, + "allowJs": true, + }, + "exclude": ["dist", "node_modules"] +} From 381970563a34e1603dc046a06d54ae879b7030fb Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:44:45 +0100 Subject: [PATCH 07/27] chore: add env --- public/favicon.svg | 9 +++++++++ public/robots.txt | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 public/favicon.svg create mode 100644 public/robots.txt diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..12d3b56 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,9 @@ + + + + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..c2a49f4 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / From c881fb4a975cd56951090745765814753967cfd3 Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:45:42 +0100 Subject: [PATCH 08/27] chore: license --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..249909f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Jesú Pérez Lorenzo based in Anthony Fu developments + +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. From fcb30e52fd97857387147f2914335b2704340b22 Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:46:24 +0100 Subject: [PATCH 09/27] chore: fix name --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 249909f..5cbf7f8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2021 Jesú Pérez Lorenzo based in Anthony Fu developments +Copyright (c) 2020-2021 Jesús Pérez Lorenzo based in Anthony Fu developments Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From d9f96c980a70e2c241097e43d4fa47829322381f Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Thu, 14 Oct 2021 15:49:52 +0100 Subject: [PATCH 10/27] chore: remove all AppLayout --- src/layouts/_AppLayout.vue | 300 ------------------------------------- 1 file changed, 300 deletions(-) delete mode 100644 src/layouts/_AppLayout.vue diff --git a/src/layouts/_AppLayout.vue b/src/layouts/_AppLayout.vue deleted file mode 100644 index e8657c0..0000000 --- a/src/layouts/_AppLayout.vue +++ /dev/null @@ -1,300 +0,0 @@ - - - - From d5fcb864a927ffa1064ad170fc7098a1079f904d Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Tue, 19 Oct 2021 21:38:04 +0100 Subject: [PATCH 11/27] chore: fix request and ui events --- src/components/CloudGroups.vue | 56 ++++++----- src/components/CloudServices.vue | 143 +++++++++++++++++----------- src/components/Footer.vue | 156 ++++++++++++++++++++++++++++--- src/components/NavMenu.vue | 59 ++++++------ src/components/Profile.vue | 137 +++++++++++++++++++++++++++ 5 files changed, 427 insertions(+), 124 deletions(-) create mode 100644 src/components/Profile.vue diff --git a/src/components/CloudGroups.vue b/src/components/CloudGroups.vue index 9727ac6..aabc171 100644 --- a/src/components/CloudGroups.vue +++ b/src/components/CloudGroups.vue @@ -1,24 +1,7 @@ - + \ No newline at end of file diff --git a/src/components/CloudServices.vue b/src/components/CloudServices.vue index 6651639..baaa96f 100644 --- a/src/components/CloudServices.vue +++ b/src/components/CloudServices.vue @@ -1,4 +1,58 @@ - + - + \ No newline at end of file diff --git a/src/components/Footer.vue b/src/components/Footer.vue index 61db7f2..4e8bf59 100644 --- a/src/components/Footer.vue +++ b/src/components/Footer.vue @@ -1,16 +1,146 @@ - - + diff --git a/src/components/NavMenu.vue b/src/components/NavMenu.vue index 0c354ae..d670afc 100644 --- a/src/components/NavMenu.vue +++ b/src/components/NavMenu.vue @@ -1,24 +1,4 @@ - + \ No newline at end of file diff --git a/src/components/Profile.vue b/src/components/Profile.vue new file mode 100644 index 0000000..a337069 --- /dev/null +++ b/src/components/Profile.vue @@ -0,0 +1,137 @@ + + From 1ceaa772bb0e038767843d938de4e1576b6f737f Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Tue, 19 Oct 2021 21:42:10 +0100 Subject: [PATCH 12/27] chore: clean ui, profile --- src/hooks/useState.ts | 119 ++++++++++++++++---- src/hooks/utils.ts | 8 +- src/layouts/AppLayout.vue | 223 +++++++++++++++++++++++++++++++++++++- src/main.ts | 6 + src/router.ts | 52 ++++++++- 5 files changed, 377 insertions(+), 31 deletions(-) diff --git a/src/hooks/useState.ts b/src/hooks/useState.ts index d9a253f..46d4e60 100644 --- a/src/hooks/useState.ts +++ b/src/hooks/useState.ts @@ -1,6 +1,5 @@ import { ref, computed } from 'vue' -// import type { ListCloudBoxesType } from '~/typs/clouds' -// import type { SideMenuItemType } from '~/typs/cmpnts' +import type { SideMenuItemType, UiPanelsType } from '~/typs/cmpnts' const reqError = ref({ defs: '', lang: '', data: '', gql: '', api: '' }) @@ -9,38 +8,120 @@ const isSidebarOpen = ref(false) const toggleSidebar = () => { isSidebarOpen.value = !isSidebarOpen.value } +const showModal = ref(false) + +const isAsidePanelOpen = ref(false) + +const sideSettingButton = ref(false) + +const isSettingsPanelOpen = ref(false) + +const isSearchPanelOpen = ref(false) +const usideSettingButton = ref(false) + +const isNotificationsPanelOpen = ref(false) + +const useSettings = ref(false) + +const useSearch = ref(false) + +const search = ref('') + const bcPath = ref('') +const navTitle = ref({ + text: '', + textclick: null as null | Function, + title: '', + cmpnt: '', + ops: [] as any[], + btntype: '', + cllbck: null as null | Function, +}) +const dfltNavTitle = () => { + navTitle.value = { + text: '', + textclick: null as null | Function, + title: '', + cmpnt: '', + ops: [] as any[], + btntype: '', + cllbck: null as null | Function, + } +} +// '#fa-book/biomagnetismo/microorganismos/virus' + +const bookCllbck = ref() +const bookSelec = (data: string) => { + if (data === '#') { + bcPath.value = '' + dfltNavTitle() + } + else { + if (bookCllbck.value) + bookCllbck.value(data) + // else ... + } +} +const sidebarMenuItems = ref([] as SideMenuItemType[]) + +const checkin = ref(false) +const connection = ref({ + state: '', +}) + const tsksrvcs = 'tsksrvcs' const appsrvcs = 'appsrvcs' const srvcstatus = 'srvcstatus' -const menu_items = ref([ - { id: tsksrvcs, title: 'Tasks', active: false, link: '#' }, - { id: appsrvcs, title: 'Applications', active: false, link: '#' }, - { id: srvcstatus, title: 'Services Status', active: false, link: '#' }, -]) +// const menu_items = ref([ +// { id: tsksrvcs, title: 'Tasks', active: false, link: '#' }, +// { id: appsrvcs, title: 'Applications', active: false, link: '#' }, +// { id: srvcstatus, title: 'Informations', active: false, link: '#' }, +// ]) -const showModal = ref(false) +const side_menu_click = ref() +const app_home_click = ref() -const checkin = ref(false) -const connection = ref({ - state: '', -}) +const backdrop_blur = ref(14) +const back_opacity = ref(60) +const panels = ref({} as UiPanelsType) + +const show_profile = ref(false) export default function useState() { return { - tsksrvcs, - appsrvcs, - srvcstatus, - menu_items, - reqError, + reqError, currentMapKey, isSidebarOpen, toggleSidebar, - bcPath, - showModal, + isAsidePanelOpen, + isSettingsPanelOpen, + isSearchPanelOpen, + isNotificationsPanelOpen, + useSettings, + usideSettingButton, + sideSettingButton, + bcPath, + bookSelec, + bookCllbck, + navTitle, + dfltNavTitle, checkin, connection, + sidebarMenuItems, + showModal, + tsksrvcs, + appsrvcs, + srvcstatus, + // menu_items, + side_menu_click, + app_home_click, + useSearch, + search, + back_opacity, + backdrop_blur, + panels, + show_profile, } } diff --git a/src/hooks/utils.ts b/src/hooks/utils.ts index c54ab11..8811ac5 100644 --- a/src/hooks/utils.ts +++ b/src/hooks/utils.ts @@ -163,12 +163,10 @@ export const load_data = async(data_path: RequestInfo, ato: number, timeout = 20 // return `error no auth for ${data_path}` try { + const headers = token !== "" ? { Authorization: `Bearer ${token}`} : {} + // 'content-type': 'application/json', const res = await self.fetch(data_path, { - headers: { - Authorization: `Bearer ${token}`, - // 'content-type': 'application/json', - }, - + headers }) // setTimeout(async() => { let dataloaded = {} diff --git a/src/layouts/AppLayout.vue b/src/layouts/AppLayout.vue index 939379f..8695fc8 100644 --- a/src/layouts/AppLayout.vue +++ b/src/layouts/AppLayout.vue @@ -1,7 +1,224 @@ - + + diff --git a/src/main.ts b/src/main.ts index b6bb402..5f681d2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,9 @@ import 'virtual:windi-utilities.css' // windicss devtools support (dev only) import 'virtual:windi-devtools' +import VueAnimXYZ from '@animxyz/vue' // import AnimXZY vue package +import '@animxyz/core' + // register vue composition api globally import { createApp } from 'vue' // import { createRouter, createWebHistory } from 'vue-router' @@ -24,6 +27,7 @@ import 'a17t' import { messages } from './modules/i18n' // import GuestLayout from '~/layouts/GuestLayout.vue' import AppLayout from '~/layouts/AppLayout.vue' +import SimpleLayout from '~/layouts/SimpleLayout.vue' const app = createApp(App) @@ -43,11 +47,13 @@ const head = createHead() // history: createWebHistory(), // routes, // }) +app.use(VueAnimXYZ) app.use(store) app.use(i18n) app.use(routes) // app.use(router) app.use(head) app.component('AppLayout', AppLayout) +app.component('SimpleLayout', SimpleLayout) // app.component('GuestLayout', GuestLayout) app.mount('#app') diff --git a/src/router.ts b/src/router.ts index 9825928..1eea5fc 100644 --- a/src/router.ts +++ b/src/router.ts @@ -14,9 +14,11 @@ import useState from '~/hooks/useState' import store from '~/store' import Home from '~/views/Home.vue' +import About from '~/views/about.md' // import Register from '~/views/auth/Register.vue' import Login from '~/views/Login.vue' import Logout from '~/views/Logout.vue' +import Profile from '~/components/Profile.vue' import { verify_auth, check_credentials } from '~/hooks/utils' // import { @@ -68,7 +70,18 @@ const check_auth = async(to: any, _from: any, next: any) => { const auth = localStorage.getItem('auth') || '' const check_url = `${window.ROOT_LOCATION || location.origin}/checkin` const login_url = `${location.origin}/ui/login` + const login_route = '/login' const mapkey = to.meta.uimapkey || 'ui' + const map_route_to = () => { + if (to.meta.requireAuth) { + return login_route + } + if (to.meta.pubLayout) { + to.meta.layout = to.meta.pubLayout + to.meta.useNav = !to.meta.useNav + } + return + } if (auth !== '') { const defs = store.state.app_defs.main.get(mapkey) if (defs && defs.checkin && useState().checkin.value) { @@ -81,10 +94,16 @@ const check_auth = async(to: any, _from: any, next: any) => { // TODO redirect to a connection error page or consider PWA offline mode if (res && res.defs) next() - else next('/login') + else { + const route=map_route_to() + next(route) + } } } - else { next('/login') } + else { + const route=map_route_to() + next(route) + } } const get_defs = async(mapkey: string) => { @@ -123,13 +142,16 @@ const routes: RouteRecordRaw[] = [ name: 'Home', component: Home, meta: { - requireAuth: true, + requireAuth: false, layout: 'AppLayout', + ctx: 'home', +// useNav: false, +// pubLayout: 'SimpleLayout', mapkey: 'kloud', uiMapkey: 'ui', rooturl, }, - // beforeEnter: check_auth, + beforeEnter: check_auth, // (_to: any, _from: any, next: any) => { // req_lang(lang_url, () => next()) // }, @@ -146,6 +168,28 @@ const routes: RouteRecordRaw[] = [ component: Logout, meta: { layout: 'empty', rooturl, use_logo: true }, }, + { + path: '/about', + name: 'About', + meta: { + layout: 'AppLayout', + ctx: 'about', + rooturl, + use_loog: true, + }, + component: About, + }, + { + path: '/profile', + name: 'Profile', + meta: { + layout: 'AppLayout', + ctx: 'profile', + rooturl, + use_loog: true, + }, + component: Profile, + }, // { // path: '/auth/register', // name: 'Register', From 59d4d7d099bd30ee00f2b98c0208d018e8c32e52 Mon Sep 17 00:00:00 2001 From: JesusPerez Date: Tue, 19 Oct 2021 21:43:23 +0100 Subject: [PATCH 13/27] chore: clean ui, profile --- src/App.vue | 13 ++++++++++++- src/styles/main.css | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/App.vue b/src/App.vue index f99a068..64fcfe4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,5 @@ @@ -7,11 +7,17 @@ //