Browse Source

feat(gui-v2): add `useApi` composable

# What's changed?

* useApi provides a loading, error and response ref
* also provides event cb for error and response
pull/2837/head
braks 2 years ago
parent
commit
67c8bf47d9
  1. 35
      packages/nc-gui-v2/components/dlg/ViewCreate.vue
  2. 63
      packages/nc-gui-v2/composables/useApi.ts
  3. 45463
      packages/nc-gui-v2/package-lock.json
  4. 1
      packages/nc-gui-v2/package.json
  5. 13
      packages/nc-gui-v2/tsconfig.json

35
packages/nc-gui-v2/components/dlg/ViewCreate.vue

@ -3,13 +3,12 @@ import type { ComponentPublicInstance } from '@vue/runtime-core'
import { notification } from 'ant-design-vue' import { notification } from 'ant-design-vue'
import type { Form as AntForm } from 'ant-design-vue' import type { Form as AntForm } from 'ant-design-vue'
import { capitalize, inject } from '@vue/runtime-core' import { capitalize, inject } from '@vue/runtime-core'
import type { GalleryType, GridType, KanbanType, ViewType } from 'nocodb-sdk' import type { FormType, GalleryType, GridType, KanbanType } from 'nocodb-sdk'
import { ViewTypes } from 'nocodb-sdk' import { ViewTypes } from 'nocodb-sdk'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { MetaInj, ViewListInj } from '~/context' import { MetaInj, ViewListInj } from '~/context'
import { generateUniqueTitle } from '~/utils' import { generateUniqueTitle } from '~/utils'
import { useNuxtApp } from '#app' import { computed, nextTick, reactive, unref, useApi, useVModel, watch } from '#imports'
import { computed, nextTick, onMounted, reactive, unref, useVModel, watch } from '#imports'
interface Props { interface Props {
modelValue: boolean modelValue: boolean
@ -18,7 +17,7 @@ interface Props {
interface Emits { interface Emits {
(event: 'update:modelValue', value: boolean): void (event: 'update:modelValue', value: boolean): void
(event: 'created', value: ViewType): void (event: 'created', value: GridType | KanbanType | GalleryType | FormType): void
} }
interface Form { interface Form {
@ -39,6 +38,8 @@ const vModel = useVModel(props, 'modelValue', emits)
const { t } = useI18n() const { t } = useI18n()
const { isLoading: loading, api } = useApi()
const meta = inject(MetaInj) const meta = inject(MetaInj)
const viewList = inject(ViewListInj) const viewList = inject(ViewListInj)
@ -64,10 +65,6 @@ const formRules = [
}, },
] ]
let loading = $ref(false)
const { $api } = useNuxtApp()
const typeAlias = computed( const typeAlias = computed(
() => () =>
({ ({
@ -102,38 +99,38 @@ async function onSubmit() {
const isValid = await formValidator.value?.validate() const isValid = await formValidator.value?.validate()
if (isValid && form.type) { if (isValid && form.type) {
loading = true
const _meta = unref(meta) const _meta = unref(meta)
if (!_meta || !_meta.id) return if (!_meta || !_meta.id) return
try { try {
let data let data: GridType | KanbanType | GalleryType | FormType | null = null
switch (form.type) { switch (form.type) {
case ViewTypes.GRID: case ViewTypes.GRID:
data = await $api.dbView.gridCreate(_meta.id, form) data = await api.dbView.gridCreate(_meta.id, form)
break break
case ViewTypes.GALLERY: case ViewTypes.GALLERY:
data = await $api.dbView.galleryCreate(_meta.id, form) data = await api.dbView.galleryCreate(_meta.id, form)
break break
case ViewTypes.FORM: case ViewTypes.FORM:
data = await $api.dbView.formCreate(_meta.id, form) data = await api.dbView.formCreate(_meta.id, form)
break break
} }
notification.success({ if (data) {
message: 'View created successfully', notification.success({
}) message: 'View created successfully',
})
emits('created', data) emits('created', data)
}
} catch (e: any) { } catch (e: any) {
notification.error({ notification.error({
message: e.message, message: e.message,
}) })
} }
loading = false
vModel.value = false vModel.value = false
} }
} }

63
packages/nc-gui-v2/composables/useApi.ts

@ -0,0 +1,63 @@
import type { AxiosError, AxiosResponse } from 'axios'
import type { Api } from 'nocodb-sdk'
import type { Ref } from 'vue'
import type { EventHook } from '@vueuse/core'
import { createEventHook, ref, useNuxtApp } from '#imports'
interface UseApiReturn<D = any, R = any> {
api: Api<any>
isLoading: Ref<boolean>
error: Ref<AxiosError<D, R> | null>
response: Ref<AxiosResponse<D, R> | null>
onError: EventHook<AxiosError<D, R>>['on']
onResponse: EventHook<AxiosResponse<D, R>>['on']
}
/** todo: add props? */
type UseApiProps = never
export function useApi<Data = any, RequestConfig = any>(_?: UseApiProps): UseApiReturn<Data, RequestConfig> {
const isLoading = ref(false)
const error = ref(null)
const response = ref<any>(null)
const errorHook = createEventHook<AxiosError<Data, RequestConfig>>()
const responseHook = createEventHook<AxiosResponse<Data, RequestConfig>>()
const { $api } = useNuxtApp()
$api.instance.interceptors.request.use(
(config) => {
error.value = null
response.value = null
isLoading.value = true
return config
},
(requestError) => {
errorHook.trigger(requestError)
error.value = requestError
response.value = null
isLoading.value = false
},
)
$api.instance.interceptors.response.use(
(apiResponse) => {
responseHook.trigger(apiResponse as AxiosResponse<Data, RequestConfig>)
// can't properly typecast
response.value = apiResponse
isLoading.value = false
},
(apiError) => {
errorHook.trigger(apiError)
error.value = apiError
isLoading.value = false
},
)
return { api: $api, isLoading, response, error, onError: errorHook.on, onResponse: responseHook.on }
}

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

File diff suppressed because it is too large Load Diff

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

@ -39,6 +39,7 @@
"@iconify-json/mdi": "^1.1.25", "@iconify-json/mdi": "^1.1.25",
"@iconify-json/ri": "^1.1.3", "@iconify-json/ri": "^1.1.3",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^4.0.0",
"@types/axios": "^0.14.0",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/sortablejs": "^1.13.0", "@types/sortablejs": "^1.13.0",
"@vitejs/plugin-vue": "^2.3.3", "@vitejs/plugin-vue": "^2.3.3",

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

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

Loading…
Cancel
Save