Browse Source

feat(gui-v2): add global state

pull/2716/head
Braks 2 years ago committed by Pranav C
parent
commit
132d8de689
  1. 11
      packages/nc-gui-v2/composables/useGlobalState.ts
  2. 19
      packages/nc-gui-v2/composables/user.ts
  3. 22
      packages/nc-gui-v2/layouts/default.vue
  4. 5
      packages/nc-gui-v2/lib/types.ts
  5. 7
      packages/nc-gui-v2/nuxt-shim.d.ts
  6. 2
      packages/nc-gui-v2/nuxt.config.ts
  7. 154
      packages/nc-gui-v2/package-lock.json
  8. 1
      packages/nc-gui-v2/package.json
  9. 6
      packages/nc-gui-v2/plugins/api.ts
  10. 7
      packages/nc-gui-v2/plugins/state.ts
  11. 10
      packages/nc-gui-v2/plugins/tele.ts
  12. 3
      packages/nc-gui-v2/tsconfig.json

11
packages/nc-gui-v2/composables/useGlobalState.ts

@ -0,0 +1,11 @@
import { createGlobalState, usePreferredLanguages, useStorage } from '@vueuse/core'
import type { GlobalState } from '~/lib/types'
const storageKey = 'nocodb-gui-v2'
export const useGlobalState = () => {
const preferredLanguages = $(usePreferredLanguages())
return createGlobalState(() =>
useStorage<GlobalState>(storageKey, { token: undefined, user: undefined, lang: preferredLanguages[0] || 'en' }),
)
}

19
packages/nc-gui-v2/composables/user.ts

@ -1,25 +1,16 @@
import { store } from 'nuxt3-store'
import type { Api } from 'nocodb-sdk'
import { useNuxtApp } from '#app'
const user = store({
name: 'user',
type: 'localstorage',
value: { token: null, user: null },
reactiveType: 'reactive',
version: '1.0.0',
})
export const useUser = () => {
const { $api } = useNuxtApp()
const { $api, $state } = useNuxtApp()
const getUser = async (...args: Parameters<Api<any>['auth']['me']>) => {
user.user = await $api.auth.me(...args)
$state.user = await $api.auth.me(...args)
}
const setToken = (token: string) => {
user.token = token
const setToken = (token?: string) => {
$state.token = token
}
return { user, setToken, getUser }
return { user: $state.user, setToken, getUser }
}

22
packages/nc-gui-v2/layouts/default.vue

@ -1,9 +1,15 @@
<script lang="ts" setup>
import { navigateTo } from '#app'
const route = useRoute()
const openDiscord = () => {
// shell.openExternal('https://discord.gg/5RgZmkW')
}
const isDashboard = computed(() => {
return route.path && (route.path === '/nc' || route.path === '/nc/' || route.path.startsWith('/nc/'))
})
</script>
<script lang="ts">
@ -19,20 +25,20 @@ export default {
<div class="d-flex align-center pt-1" style="flex: 1">
<v-toolbar-title>
<v-tooltip bottom>
<!-- Home -->
{{ $t('general.home') }}
<span class="caption font-weight-light pointer">(version)</span>
</v-tooltip>
<span class="body-1 ml-n1" @click="navigateTo('/projects')">brandname</span>
<span class="body-1" @click="navigateTo('/projects')">NocoDB</span>
</v-toolbar-title>
<!-- loading
<span v-show="$nuxt.$loading.show" class="caption grey--text ml-3"
>{{ $t('general.loading') }} <v-icon small color="grey">mdi-spin mdi-loading</v-icon></span
>
<!-- todo: loading is not yet supported by nuxt 3 - see https://v3.nuxtjs.org/migration/component-options#loading
<span v-show="$nuxt.$loading.show" class="caption grey--text ml-3">
{{ $t('general.loading') }} <v-icon small color="grey">mdi-spin mdi-loading</v-icon>
</span>
todo: replace shortkey?
<span v-shortkey="['ctrl', 'shift', 'd']" @shortkey="openDiscord" />
-->
</div>
@ -47,10 +53,10 @@ export default {
<v-toolbar-items class="hidden-sm-and-down nc-topright-menu">
<!-- todo: implement components
<release-info />
<language class="mr-3" />
-->
<general-language class="mr-3" />
<!-- todo: implement isDashboard
<template v-if="isDashboard">
<div>

5
packages/nc-gui-v2/lib/types.ts

@ -0,0 +1,5 @@
export interface GlobalState {
token?: string
user?: Record<string, any>
lang: string
}

7
packages/nc-gui-v2/nuxt-shim.d.ts vendored

@ -1,8 +1,15 @@
import type { NuxtApp as BaseApp } from '#app/nuxt'
import type { Api } from 'nocodb-sdk'
import type { GlobalState } from '~/lib/types'
declare module '#app/nuxt' {
interface NuxtApp extends BaseApp {
$api: Api<any>;
$tele: {
emit: (event: string, data: any) => void
}
// tele.emit
$e: (event: string, data: any) => void
$state: GlobalState
}
}

2
packages/nc-gui-v2/nuxt.config.ts

@ -14,7 +14,7 @@ export default defineNuxtConfig({
transpile: ['vuetify'],
},
head: {
meta: {
title: 'NocoDB',
description: 'NocoDB GUI V2',
titleTemplate: (titleChunk: string) => {

154
packages/nc-gui-v2/package-lock.json generated

@ -5,6 +5,7 @@
"packages": {
"": {
"dependencies": {
"@vueuse/core": "^8.7.5",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"nocodb-sdk": "file:../nocodb-sdk",
@ -1893,8 +1894,7 @@
"node_modules/@types/web-bluetooth": {
"version": "0.0.14",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==",
"dev": true
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.30.0",
@ -2317,44 +2317,10 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.37.tgz",
"integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw=="
},
"node_modules/@vueuse/head": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/@vueuse/head/-/head-0.7.6.tgz",
"integrity": "sha512-cOWqCkT3WiF5oEpw+VVEWUJd9RLD5rc7DmnFp3cePsejp+t7686uKD9Z9ZU7Twb7R/BI8iexKTmXo9D/F3v6UA==",
"peerDependencies": {
"vue": ">=3"
}
},
"node_modules/@vueuse/metadata": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.7.5.tgz",
"integrity": "sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/nuxt": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/nuxt/-/nuxt-8.7.5.tgz",
"integrity": "sha512-e+JSiNCdWaKyTiBtM856uNJaXeCw8Ka423AGsuvq+D+GXXQe0RhHzqqLS6pQutjWuftNRBRCOiITOzhtjMP+gA==",
"dev": true,
"dependencies": {
"@nuxt/kit": "^3.0.0-rc.4",
"@vueuse/core": "8.7.5",
"@vueuse/metadata": "8.7.5",
"local-pkg": "^0.4.1",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/nuxt/node_modules/@vueuse/core": {
"node_modules/@vueuse/core": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-8.7.5.tgz",
"integrity": "sha512-tqgzeZGoZcXzoit4kOGLWJibDMLp0vdm6ZO41SSUQhkhtrPhAg6dbIEPiahhUu6sZAmSYvVrZgEr5aKD51nrLA==",
"dev": true,
"dependencies": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.7.5",
@ -2377,11 +2343,10 @@
}
}
},
"node_modules/@vueuse/nuxt/node_modules/@vueuse/shared": {
"node_modules/@vueuse/core/node_modules/@vueuse/shared": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-8.7.5.tgz",
"integrity": "sha512-THXPvMBFmg6Gf6AwRn/EdTh2mhqwjGsB2Yfp374LNQSQVKRHtnJ0I42bsZTn7nuEliBxqUrGQm/lN6qUHmhJLw==",
"dev": true,
"dependencies": {
"vue-demi": "*"
},
@ -2401,6 +2366,63 @@
}
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.2.tgz",
"integrity": "sha512-41ukrclEbMddAyP7PvxMSYqnOSzPV6r7GNnyTSKSCNTaz19GehxmTiXyP9kwHSUv2+Dr6hHqiUiF7L1VAw2KdQ==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/head": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/@vueuse/head/-/head-0.7.6.tgz",
"integrity": "sha512-cOWqCkT3WiF5oEpw+VVEWUJd9RLD5rc7DmnFp3cePsejp+t7686uKD9Z9ZU7Twb7R/BI8iexKTmXo9D/F3v6UA==",
"peerDependencies": {
"vue": ">=3"
}
},
"node_modules/@vueuse/metadata": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.7.5.tgz",
"integrity": "sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/nuxt": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/nuxt/-/nuxt-8.7.5.tgz",
"integrity": "sha512-e+JSiNCdWaKyTiBtM856uNJaXeCw8Ka423AGsuvq+D+GXXQe0RhHzqqLS6pQutjWuftNRBRCOiITOzhtjMP+gA==",
"dev": true,
"dependencies": {
"@nuxt/kit": "^3.0.0-rc.4",
"@vueuse/core": "8.7.5",
"@vueuse/metadata": "8.7.5",
"local-pkg": "^0.4.1",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/nuxt/node_modules/vue-demi": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.2.tgz",
@ -12472,8 +12494,7 @@
"@types/web-bluetooth": {
"version": "0.0.14",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==",
"dev": true
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A=="
},
"@typescript-eslint/eslint-plugin": {
"version": "5.30.0",
@ -12785,6 +12806,33 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.37.tgz",
"integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw=="
},
"@vueuse/core": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-8.7.5.tgz",
"integrity": "sha512-tqgzeZGoZcXzoit4kOGLWJibDMLp0vdm6ZO41SSUQhkhtrPhAg6dbIEPiahhUu6sZAmSYvVrZgEr5aKD51nrLA==",
"requires": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.7.5",
"@vueuse/shared": "8.7.5",
"vue-demi": "*"
},
"dependencies": {
"@vueuse/shared": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-8.7.5.tgz",
"integrity": "sha512-THXPvMBFmg6Gf6AwRn/EdTh2mhqwjGsB2Yfp374LNQSQVKRHtnJ0I42bsZTn7nuEliBxqUrGQm/lN6qUHmhJLw==",
"requires": {
"vue-demi": "*"
}
},
"vue-demi": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.2.tgz",
"integrity": "sha512-41ukrclEbMddAyP7PvxMSYqnOSzPV6r7GNnyTSKSCNTaz19GehxmTiXyP9kwHSUv2+Dr6hHqiUiF7L1VAw2KdQ==",
"requires": {}
}
}
},
"@vueuse/head": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/@vueuse/head/-/head-0.7.6.tgz",
@ -12794,8 +12842,7 @@
"@vueuse/metadata": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.7.5.tgz",
"integrity": "sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg==",
"dev": true
"integrity": "sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg=="
},
"@vueuse/nuxt": {
"version": "8.7.5",
@ -12810,27 +12857,6 @@
"vue-demi": "*"
},
"dependencies": {
"@vueuse/core": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-8.7.5.tgz",
"integrity": "sha512-tqgzeZGoZcXzoit4kOGLWJibDMLp0vdm6ZO41SSUQhkhtrPhAg6dbIEPiahhUu6sZAmSYvVrZgEr5aKD51nrLA==",
"dev": true,
"requires": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.7.5",
"@vueuse/shared": "8.7.5",
"vue-demi": "*"
}
},
"@vueuse/shared": {
"version": "8.7.5",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-8.7.5.tgz",
"integrity": "sha512-THXPvMBFmg6Gf6AwRn/EdTh2mhqwjGsB2Yfp374LNQSQVKRHtnJ0I42bsZTn7nuEliBxqUrGQm/lN6qUHmhJLw==",
"dev": true,
"requires": {
"vue-demi": "*"
}
},
"vue-demi": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.2.tgz",

1
packages/nc-gui-v2/package.json

@ -15,6 +15,7 @@
"sass": "^1.53.0"
},
"dependencies": {
"@vueuse/core": "^8.7.5",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"nocodb-sdk": "file:../nocodb-sdk",

6
packages/nc-gui-v2/plugins/api.ts

@ -49,7 +49,7 @@ function addAxiosInterceptors(api: Api<any>) {
// Logout user if token refresh didn't work or user is disabled
if (error.config.url === '/auth/refresh-token') {
// todo: clear token
setToken(null)
setToken()
return new Promise((resolve, reject) => {
reject(error)
@ -65,7 +65,7 @@ function addAxiosInterceptors(api: Api<any>) {
// New request with new token
const config = error.config
config.headers['xc-auth'] = token.data.token
user.token = token.data.token
if (user) user.token = token.data.token
return new Promise((resolve, reject) => {
api.instance
@ -81,7 +81,7 @@ function addAxiosInterceptors(api: Api<any>) {
.catch(async (error) => {
// todo: clear token
// await store.dispatch('users/ActSignOut')
setToken(null)
setToken()
// todo: handle new user
// if (store.state.project.appInfo.firstUser) {
// router.replace('/')

7
packages/nc-gui-v2/plugins/state.ts

@ -0,0 +1,7 @@
import { defineNuxtPlugin } from '#app'
import { useGlobalState } from '~/composables/useGlobalState'
export default defineNuxtPlugin((nuxtApp) => {
const createGlobalState = useGlobalState()
nuxtApp.provide('state', createGlobalState())
})

10
packages/nc-gui-v2/plugins/tele.ts

@ -56,9 +56,6 @@ export default defineNuxtPlugin(async (nuxtApp) => {
},
}
inject('tele', tele)
inject('e', tele.emit)
nuxtApp.vueApp.directive('t', {
created(el, binding, vnode) {
if (vnode.el) vnode.el.addEventListener('click', getListener(binding))
@ -80,13 +77,16 @@ export default defineNuxtPlugin(async (nuxtApp) => {
}
}
if (user.token) await init(user.token)
if (user?.token) await init(user.token)
watch(
() => user.token,
() => user?.token,
(newToken, oldToken) => {
if (newToken !== oldToken) init(newToken)
else if (!newToken) socket.disconnect()
},
)
nuxtApp.provide('tele', tele)
nuxtApp.provide('e', tele.emit)
})

3
packages/nc-gui-v2/tsconfig.json

@ -10,8 +10,9 @@
"noUnusedLocals": false,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"types": ["@intlify/vite-plugin-vue-i18n/client"]
"types": ["@intlify/vite-plugin-vue-i18n/client", "vue-i18n"]
},
"files": ["nuxt-shim.d.ts"],
"exclude": [
"node_modules",
"dist"

Loading…
Cancel
Save