Browse Source

fix(gui-v2): attachment cell not accepting files in shared form view

pull/3300/head
braks 2 years ago
parent
commit
e9474292a6
  1. 20
      packages/nc-gui-v2/components/cell/attachment/index.vue
  2. 27
      packages/nc-gui-v2/components/cell/attachment/utils.ts
  3. 17
      packages/nc-gui-v2/components/shared-view/Form.vue
  4. 12
      packages/nc-gui-v2/components/smartsheet/Form.vue
  5. 1
      packages/nc-gui-v2/composables/useViewColumns.ts

20
packages/nc-gui-v2/components/cell/attachment/index.vue

@ -5,7 +5,9 @@ import { useSortable } from './sort'
import Modal from './Modal.vue' import Modal from './Modal.vue'
import Carousel from './Carousel.vue' import Carousel from './Carousel.vue'
import { import {
IsFormInj,
computed, computed,
inject,
isImage, isImage,
openLink, openLink,
ref, ref,
@ -28,6 +30,10 @@ const { modelValue, rowIndex } = defineProps<Props>()
const emits = defineEmits<Emits>() const emits = defineEmits<Emits>()
const isForm = inject(IsFormInj, ref(false))
const attachmentCellRef = ref<HTMLDivElement>()
const sortableRef = ref<HTMLDivElement>() const sortableRef = ref<HTMLDivElement>()
const { cellRefs } = useSmartsheetStoreOrThrow()! const { cellRefs } = useSmartsheetStoreOrThrow()!
@ -46,7 +52,9 @@ const {
storedFiles, storedFiles,
} = useProvideAttachmentCell(updateModelValue) } = useProvideAttachmentCell(updateModelValue)
const currentCellRef = computed(() => cellRefs.value.find((cell) => cell.dataset.key === `${rowIndex}${column.value.id}`)) const currentCellRef = computed(() =>
isForm.value ? attachmentCellRef.value : cellRefs.value.find((cell) => cell.dataset.key === `${rowIndex}${column.value.id}`),
)
const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, isReadonly) const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, isReadonly)
@ -93,7 +101,10 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
</script> </script>
<template> <template>
<div class="nc-attachment-cell relative flex-1 color-transition flex items-center justify-between gap-1"> <div
ref="attachmentCellRef"
class="nc-attachment-cell relative flex-1 color-transition flex items-center justify-between gap-1"
>
<Carousel /> <Carousel />
<template v-if="isSharedForm || (!isReadonly && !dragging && !!currentCellRef)"> <template v-if="isSharedForm || (!isReadonly && !dragging && !!currentCellRef)">
@ -135,9 +146,8 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
> >
<div <div
v-for="(item, i) of visibleItems" v-for="(item, i) of visibleItems"
:id="item.url"
:key="item.url || item.title" :key="item.url || item.title"
:class="isImage(item.title, item.mimetype) ? '' : 'border-1 rounded'" :class="isImage(item.title, item.mimetype ?? item.type) ? '' : 'border-1 rounded'"
class="nc-attachment flex items-center justify-center min-h-[50px]" class="nc-attachment flex items-center justify-center min-h-[50px]"
> >
<a-tooltip placement="bottom"> <a-tooltip placement="bottom">
@ -146,7 +156,7 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
</template> </template>
<nuxt-img <nuxt-img
v-if="isImage(item.title, item.mimetype)" v-if="isImage(item.title, item.mimetype ?? item.type) && (item.url || item.data)"
quality="75" quality="75"
placeholder placeholder
:alt="item.title || `#${i}`" :alt="item.title || `#${i}`"

27
packages/nc-gui-v2/components/cell/attachment/utils.ts

@ -48,7 +48,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
const storedFilesData = ref<{ title: string; file: File }[]>([]) const storedFilesData = ref<{ title: string; file: File }[]>([])
/** keep user selected File object */ /** keep user selected File object */
const storedFiles = ref<File[]>([]) const storedFiles = ref<{ title: string; file: File }[]>([])
const attachments = ref<File[]>([]) const attachments = ref<File[]>([])
@ -60,7 +60,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
const { api, isLoading } = useApi() const { api, isLoading } = useApi()
const { files, open } = useFileDialog() const { files, open, reset } = useFileDialog()
/** remove a file from our stored attachments (either locally stored or saved ones) */ /** remove a file from our stored attachments (either locally stored or saved ones) */
function removeFile(i: number) { function removeFile(i: number) {
@ -81,22 +81,27 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
if (!selectedFiles.length || isPublicGrid) return if (!selectedFiles.length || isPublicGrid) return
if (isPublic.value) { if (isPublic.value) {
storedFiles.value.push(...selectedFiles) storedFiles.value.push(
storedFilesData.value.push(
...(await Promise.all<AttachmentProps>( ...(await Promise.all<AttachmentProps>(
Array.from(selectedFiles).map( Array.from(selectedFiles).map(
(file) => (file) =>
new Promise<AttachmentProps>((resolve) => { new Promise<AttachmentProps>((resolve) => {
const res: AttachmentProps = { file, title: file.name } const res: any = { ...file, file, title: file.name }
if (isImage(file.name, (file as any).mimetype)) {
console.log(res)
if (isImage(file.name, (<any>file).mimetype ?? file.type)) {
const reader = new FileReader() const reader = new FileReader()
reader.onload = (e: any) => {
reader.onload = (e) => {
res.data = e.target?.result res.data = e.target?.result
resolve(res) resolve(res)
} }
reader.onerror = () => { reader.onerror = () => {
resolve(res) resolve(res)
} }
reader.readAsDataURL(file) reader.readAsDataURL(file)
} else { } else {
resolve(res) resolve(res)
@ -106,7 +111,9 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
)), )),
) )
return updateModelValue(storedFilesData.value.map((storedFile) => storedFile.file)) reset()
return updateModelValue(storedFiles.value.map((next) => next.file))
} }
const newAttachments = [] const newAttachments = []
@ -129,6 +136,8 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
} }
} }
reset()
updateModelValue([...attachments.value, ...newAttachments]) updateModelValue([...attachments.value, ...newAttachments])
} }
@ -161,7 +170,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
} }
/** our currently visible items, either the locally stored or the ones from db, depending on isPublicForm status */ /** our currently visible items, either the locally stored or the ones from db, depending on isPublicForm status */
const visibleItems = computed<any[]>(() => [...attachments.value, ...storedFiles.value]) const visibleItems = computed<any[]>(() => (isPublic.value ? storedFiles.value : attachments.value))
watch(files, (nextFiles) => nextFiles && onFileSelect(nextFiles)) watch(files, (nextFiles) => nextFiles && onFileSelect(nextFiles))

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

@ -29,33 +29,32 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
> >
} }
return required || (columnObj && columnObj.rqd && !columnObj.cdf) return !!(required || (columnObj && columnObj.rqd && !columnObj.cdf))
} }
</script> </script>
<template> <template>
<div class="bg-primary !h-[100vh] overflow-auto w-full flex flex-col"> <div class="!h-[100vh] overflow-auto w-full flex flex-col">
<div>
<img src="~/assets/img/icons/512x512-trans.png" width="30" class="mx-4 mt-2" />
</div>
<div class="m-4 mt-2 bg-white rounded p-2 flex-1"> <div class="m-4 mt-2 bg-white rounded p-2 flex-1">
<a-alert v-if="notFound" type="warning" class="mx-auto mt-10 max-w-[300px]" message="Not found"> </a-alert> <a-alert v-if="notFound" type="warning" class="mx-auto mt-10 max-w-[300px]" message="Not found"> </a-alert>
<template v-else-if="submitted"> <template v-else-if="submitted">
<div class="flex justify-center"> <div class="flex justify-center">
<div v-if="sharedFormView" style="min-width: 350px" class="mt-3"> <div v-if="sharedFormView" style="min-width: 350px" class="mt-3">
<a-alert type="success" outlined :message="sharedFormView.success_msg || 'Successfully submitted form data'"> <a-alert type="success" outlined :message="sharedFormView.success_msg || 'Successfully submitted form data'" />
</a-alert>
<p v-if="sharedFormView.show_blank_form" class="text-xs text-gray-500 text-center my-4"> <p v-if="sharedFormView.show_blank_form" class="text-xs text-gray-500 text-center my-4">
New form will be loaded after {{ secondsRemain }} seconds New form will be loaded after {{ secondsRemain }} seconds
</p> </p>
<div v-if="sharedFormView.submit_another_form" class="text-center"> <div v-if="sharedFormView.submit_another_form" class="text-center">
<a-button type="primary" @click="submitted = false"> Submit Another Form</a-button> <a-button type="primary" @click="submitted = false"> Submit Another Form</a-button>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<div v-else-if="sharedFormView" class="">
<div v-else-if="sharedFormView">
<a-row class="justify-center"> <a-row class="justify-center">
<a-col :md="20"> <a-col :md="20">
<div> <div>
@ -81,6 +80,7 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
<div class="text-lg text-left mx-4 py-2 px-1 text-gray-500"> <div class="text-lg text-left mx-4 py-2 px-1 text-gray-500">
{{ sharedFormView.subheading }} {{ sharedFormView.subheading }}
</div> </div>
<div class="h-full"> <div class="h-full">
<div v-for="(field, index) in formColumns" :key="index" class="flex flex-col mt-4 px-4 space-y-2"> <div v-for="(field, index) in formColumns" :key="index" class="flex flex-col mt-4 px-4 space-y-2">
<div class="flex"> <div class="flex">
@ -90,6 +90,7 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
:required="isRequired(field, field.required)" :required="isRequired(field, field.required)"
:hide-menu="true" :hide-menu="true"
/> />
<SmartsheetHeaderCell <SmartsheetHeaderCell
v-else v-else
:column="{ ...field, title: field.label || field.title }" :column="{ ...field, title: field.label || field.title }"

12
packages/nc-gui-v2/components/smartsheet/Form.vue

@ -152,9 +152,8 @@ function onMoveCallback(event: any) {
function onMove(event: any) { function onMove(event: any) {
const { newIndex, element, oldIndex } = event.added || event.moved || event.removed const { newIndex, element, oldIndex } = event.added || event.moved || event.removed
console.log(event)
if (shouldSkipColumn(element)) { if (shouldSkipColumn(element)) {
console.log('SKIPPED')
return return
} }
@ -408,7 +407,14 @@ onMounted(async () => {
</div> </div>
</div> </div>
</div> </div>
<Draggable :list="hiddenColumns" draggable=".item" group="form-inputs" @start="drag = true" @end="drag = false"> <Draggable
:list="hiddenColumns"
item-key="id"
draggable=".item"
group="form-inputs"
@start="drag = true"
@end="drag = false"
>
<template #item="{ element }"> <template #item="{ element }">
<a-card <a-card
size="small" size="small"

1
packages/nc-gui-v2/composables/useViewColumns.ts

@ -51,6 +51,7 @@ export function useViewColumns(view: Ref<ViewType> | undefined, meta: ComputedRe
[curr.fk_column_id]: curr, [curr.fk_column_id]: curr,
} }
}, {}) }, {})
fields.value = meta.value?.columns fields.value = meta.value?.columns
?.map((column: ColumnType) => { ?.map((column: ColumnType) => {
const currentColumnField = fieldById[column.id!] || {} const currentColumnField = fieldById[column.id!] || {}

Loading…
Cancel
Save