Browse Source

fix(gui-v2): shared form view with password

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/3188/head
Pranav C 2 years ago
parent
commit
00d135417c
  1. 37
      packages/nc-gui-v2/components/shared-view/Form.vue
  2. 4
      packages/nc-gui-v2/composables/useLTARStore.ts
  3. 35
      packages/nc-gui-v2/composables/useSharedFormViewStore.ts
  4. 1
      packages/nc-gui-v2/context/index.ts
  5. 4
      packages/nc-gui-v2/pages/[projectType]/form/[viewId].vue

37
packages/nc-gui-v2/components/shared-view/Form.vue

@ -2,7 +2,19 @@
import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
import { useSharedFormStoreOrThrow } from '#imports'
const { sharedView, submitForm, v$, formState, notFound, formColumns, submitted, secondsRemain } = useSharedFormStoreOrThrow()
const {
sharedView,
submitForm,
v$,
formState,
notFound,
formColumns,
submitted,
secondsRemain,
passwordDlg,
password,
loadSharedView,
} = useSharedFormStoreOrThrow()
function isRequired(_columnObj: Record<string, any>, required = false) {
let columnObj = _columnObj
@ -32,7 +44,8 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
<template v-else-if="submitted">
<div class="flex justify-center">
<div v-if="sharedView.view" style="min-width: 350px" class="mt-3">
<a-alert type="success" outlined :message="sharedView.view.success_msg || 'Successfully submitted form data'"> </a-alert>
<a-alert type="success" outlined :message="sharedView.view.success_msg || 'Successfully submitted form data'">
</a-alert>
<p v-if="sharedView.view.show_blank_form" class="text-xs text-gray-500 text-center my-4">
New form will be loaded after {{ secondsRemain }} seconds
</p>
@ -119,6 +132,26 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
</a-row>
</div>
</div>
<a-modal
v-model:visible="passwordDlg"
:closable="false"
width="28rem"
centered
:footer="null"
:mask-closable="false"
@close="passwordDlg = false"
>
<div class="w-full flex flex-col">
<a-typography-title :level="4">This shared view is protected</a-typography-title>
<a-form ref="formRef" :model="{ password }" class="mt-2" @finish="loadSharedView">
<a-form-item name="password" :rules="[{ required: true, message: 'Password is required' }]">
<a-input-password v-model:value="password" placeholder="Enter password" />
</a-form-item>
<a-button type="primary" html-type="submit">Unlock</a-button>
</a-form>
</div>
</a-modal>
</div>
</template>

4
packages/nc-gui-v2/composables/useLTARStore.ts

@ -14,6 +14,7 @@ import {
useProject,
} from '#imports'
import type { Row } from '~/composables'
import { SharedViewPasswordInj } from '~/context'
interface DataApiResponse {
list: Record<string, any>
@ -27,6 +28,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
const { metas, getMeta } = useMetas()
const { project } = useProject()
const { $api } = useNuxtApp()
const sharedViewPassword = inject(SharedViewPasswordInj, ref(null))
const childrenExcludedList = ref<DataApiResponse | undefined>()
const childrenList = ref<DataApiResponse | undefined>()
const childrenExcludedListPagination = reactive({
@ -90,7 +92,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
{},
{
headers: {
'xc-password': '',
'xc-password': sharedViewPassword.value,
},
query: {
limit: childrenExcludedListPagination.size,

35
packages/nc-gui-v2/composables/useSharedFormViewStore.ts

@ -3,17 +3,20 @@ import { minLength, required } from '@vuelidate/validators'
import { message } from 'ant-design-vue'
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { ErrorMessages, RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
import { SharedViewPasswordInj } from '~/context'
import { extractSdkResponseErrorMsg } from '~/utils'
import { useInjectionState } from '#imports'
import { useInjectionState, useMetas } from '#imports'
const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() => {
const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((sharedViewId: string) => {
const progress = ref(false)
const notFound = ref(false)
const showPasswordModal = ref(false)
const submitted = ref(false)
const passwordDlg = ref(false)
const password = ref(null)
const secondsRemain = ref(0)
provide(SharedViewPasswordInj, password)
// todo: type
const sharedView = ref<any>()
const meta = ref<TableType>()
@ -45,10 +48,17 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() =>
required: !!(c.required || 0),
})) ?? [],
)
const loadSharedView = async (viewId: string) => {
const loadSharedView = async () => {
try {
// todo: swagget type correction
const viewMeta: any = await $api.public.sharedViewMetaGet(viewId)
// todo: swagger type correction
const viewMeta: any = await $api.public.sharedViewMetaGet(sharedViewId, {
headers: {
'xc-password': password.value,
},
})
passwordDlg.value = false
sharedView.value = viewMeta
meta.value = viewMeta.model
columns.value = viewMeta.model.columns
@ -61,7 +71,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() =>
if (e.response && e.response.status === 404) {
notFound.value = true
} else if ((await extractSdkResponseErrorMsg(e)) === ErrorMessages.INVALID_SHARED_VIEW_PASSWORD) {
showPasswordModal.value = true
passwordDlg.value = true
}
}
}
@ -129,15 +139,15 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() =>
...attachment,
},
{
// todo: add password support
// headers: { 'xc-password': password },
headers: {
'xc-password': password.value,
},
},
)
submitted.value = true
progress.value = false
await message.success(sharedView.value.success_msg || 'Saved successfully.')
} catch (e: any) {
console.log(e)
@ -152,7 +162,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() =>
if (nextVal && sharedView.value?.view?.show_blank_form) {
secondsRemain.value = 5
const intvl = setInterval(() => {
secondsRemain.value = secondsRemain.value -1
secondsRemain.value = secondsRemain.value - 1
if (secondsRemain.value < 0) {
submitted.value = false
clearInterval(intvl)
@ -161,7 +171,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() =>
}
/** reset form state and validation */
if(!nextVal){
if (!nextVal) {
additionalState.value = {}
formState.value = {}
v$.value?.$reset()
@ -183,6 +193,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState(() =>
password,
submitted,
secondsRemain,
passwordDlg,
}
}, 'expanded-form-store')

1
packages/nc-gui-v2/context/index.ts

@ -25,3 +25,4 @@ export const FieldsInj: InjectionKey<Ref<any[]>> = Symbol('fields-injection')
export const ViewListInj: InjectionKey<Ref<ViewType[]>> = Symbol('view-list-injection')
export const RightSidebarInj: InjectionKey<Ref<boolean>> = Symbol('right-sidebar-injection')
export const EditModeInj: InjectionKey<Ref<boolean>> = Symbol('edit-mode-injection')
export const SharedViewPasswordInj: InjectionKey<Ref<string>> = Symbol('shared-view-password-injection')

4
packages/nc-gui-v2/pages/[projectType]/form/[viewId].vue

@ -13,9 +13,9 @@ const route = useRoute()
const reloadEventHook = createEventHook<void>()
const { loadSharedView, sharedView, meta, notFound, formColumns } = useProvideSharedFormStore()
const { loadSharedView, sharedView, meta, notFound, formColumns } = useProvideSharedFormStore(route.params.viewId)
await loadSharedView(route.params.viewId as string)
await loadSharedView()
if (!notFound.value) {
provide(ReloadViewDataHookInj, reloadEventHook)
provide(MetaInj, meta)

Loading…
Cancel
Save