Browse Source

Merge pull request #4959 from nocodb/fix/attachments-gallery

fix(nc-gui): cater new attachments in gallery view
pull/4972/head
աɨռɢӄաօռɢ 2 years ago committed by GitHub
parent
commit
cf7c6194f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      packages/nc-gui/composables/useKanbanViewStore.ts
  2. 5
      packages/nc-gui/composables/useSmartsheetStore.ts
  3. 62
      packages/nc-gui/composables/useViewData.ts
  4. 14
      packages/nocodb/src/lib/meta/api/attachmentApis.ts

6
packages/nc-gui/composables/useKanbanViewStore.ts

@ -71,7 +71,9 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { sqlUis } = useProject() const { sqlUis } = useProject()
const sqlUi = ref(meta.value?.base_id ? sqlUis.value[meta.value?.base_id] : Object.values(sqlUis.value)[0]) const sqlUi = ref(
(meta.value as TableType)?.base_id ? sqlUis.value[(meta.value as TableType)?.base_id!] : Object.values(sqlUis.value)[0],
)
const xWhere = computed(() => { const xWhere = computed(() => {
let where let where
@ -198,6 +200,8 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
// See /packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts for the details // See /packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts for the details
for (const record of data.value.list) { for (const record of data.value.list) {
for (const attachmentColumn of attachmentColumns.value) { for (const attachmentColumn of attachmentColumns.value) {
// attachment column can be hidden
if (!record[attachmentColumn!]) continue
const oldAttachment = JSON.parse(record[attachmentColumn!]) const oldAttachment = JSON.parse(record[attachmentColumn!])
const newAttachment = [] const newAttachment = []
for (const attachmentObj of oldAttachment) { for (const attachmentObj of oldAttachment) {

5
packages/nc-gui/composables/useSmartsheetStore.ts

@ -13,9 +13,12 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
initialFilters?: Ref<FilterType[]>, initialFilters?: Ref<FilterType[]>,
) => { ) => {
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { sqlUis } = useProject() const { sqlUis } = useProject()
const sqlUi = ref(meta.value?.base_id ? sqlUis.value[meta.value?.base_id] : Object.values(sqlUis.value)[0]) const sqlUi = ref(
(meta.value as TableType)?.base_id ? sqlUis.value[(meta.value as TableType)?.base_id!] : Object.values(sqlUis.value)[0],
)
const cellRefs = ref<HTMLTableDataCellElement[]>([]) const cellRefs = ref<HTMLTableDataCellElement[]>([])

62
packages/nc-gui/composables/useViewData.ts

@ -1,5 +1,15 @@
import { UITypes, ViewTypes } from 'nocodb-sdk' import { UITypes, ViewTypes } from 'nocodb-sdk'
import type { Api, ColumnType, FormColumnType, FormType, GalleryType, PaginatedType, TableType, ViewType } from 'nocodb-sdk' import type {
Api,
AttachmentType,
ColumnType,
FormColumnType,
FormType,
GalleryType,
PaginatedType,
TableType,
ViewType,
} from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import { import {
IsPublicInj, IsPublicInj,
@ -81,6 +91,10 @@ export function useViewData(
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const attachmentColumns = computed(() =>
(meta.value?.columns as ColumnType[])?.filter((c) => c.uidt === UITypes.Attachment).map((c) => c.title),
)
const routeQuery = $computed(() => route.query as Record<string, string>) const routeQuery = $computed(() => route.query as Record<string, string>)
const paginationData = computed({ const paginationData = computed({
@ -187,6 +201,28 @@ export function useViewData(
} }
} }
// TODO: refactor
async function getAttachmentUrl(item: AttachmentType) {
const path = item?.path
// if path doesn't exist, use `item.url`
if (path) {
// try ${appInfo.value.ncSiteUrl}/${item.path} first
const url = `${appInfo.ncSiteUrl}/${item.path}`
try {
const res = await fetch(url)
if (res.ok) {
// use `url` if it is accessible
return Promise.resolve(url)
}
} catch {
// for some cases, `url` is not accessible as expected
// do nothing here
}
}
// if it fails, use the original url
return Promise.resolve(item.url)
}
async function loadData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) { async function loadData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) {
if ((!project?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return if ((!project?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return
const response = !isPublic.value const response = !isPublic.value
@ -198,7 +234,27 @@ export function useViewData(
where: where?.value, where: where?.value,
}) })
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: nestedFilters.value }) : await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: nestedFilters.value })
formattedData.value = formatData(response.list) // reconstruct the url
// See /packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts for the details
const records = []
for (const record of response.list) {
for (const attachmentColumn of attachmentColumns.value) {
// attachment column can be hidden
if (!record[attachmentColumn!]) continue
const oldAttachment =
typeof record[attachmentColumn!] === 'string' ? JSON.parse(record[attachmentColumn!]) : record[attachmentColumn!]
const newAttachment = []
for (const attachmentObj of oldAttachment) {
newAttachment.push({
...attachmentObj,
url: await getAttachmentUrl(attachmentObj),
})
}
record[attachmentColumn!] = newAttachment
}
records.push(record)
}
formattedData.value = formatData(records)
paginationData.value = response.pageInfo paginationData.value = response.pageInfo
// to cater the case like when querying with a non-zero offset // to cater the case like when querying with a non-zero offset
@ -455,7 +511,7 @@ export function useViewData(
order: (fieldById[c.id] && fieldById[c.id].order) || order++, order: (fieldById[c.id] && fieldById[c.id].order) || order++,
id: fieldById[c.id] && fieldById[c.id].id, id: fieldById[c.id] && fieldById[c.id].id,
})) }))
.sort((a: Record<string, any>, b: Record<string, any>) => a.order - b.order) as Record<string, any> .sort((a: Record<string, any>, b: Record<string, any>) => a.order - b.order) as Record<string, any>[]
} catch (e: any) { } catch (e: any) {
return message.error(`${t('msg.error.setFormDataFailed')}: ${await extractSdkResponseErrorMsg(e)}`) return message.error(`${t('msg.error.setFormDataFailed')}: ${await extractSdkResponseErrorMsg(e)}`)
} }

14
packages/nocodb/src/lib/meta/api/attachmentApis.ts

@ -96,21 +96,25 @@ export async function uploadViaURL(req: Request, res: Response) {
req.body?.map?.(async (urlMeta) => { req.body?.map?.(async (urlMeta) => {
const { url, fileName: _fileName } = urlMeta; const { url, fileName: _fileName } = urlMeta;
const fileName = `${nanoid(6)}${_fileName || url.split('/').pop()}`; const fileName = `${nanoid(18)}${_fileName || url.split('/').pop()}`;
let attachmentUrl = await (storageAdapter as any).fileCreateByUrl( let attachmentUrl = await (storageAdapter as any).fileCreateByUrl(
slash(path.join(destPath, fileName)), slash(path.join(destPath, fileName)),
url url
); );
let attachmentPath;
// if `attachmentUrl` is null, then it is local attachment
if (!attachmentUrl) { if (!attachmentUrl) {
attachmentUrl = `${(req as any).ncSiteUrl}/download/${filePath.join( // then store the attachement path only
'/' // url will be constructued in `useAttachmentCell`
)}/${fileName}`; attachmentPath = `download/${filePath.join('/')}/${fileName}`;
} }
return { return {
url: attachmentUrl, ...(attachmentUrl ? { url: attachmentUrl } : {}),
...(attachmentPath ? { path: attachmentPath } : {}),
title: fileName, title: fileName,
mimetype: urlMeta.mimetype, mimetype: urlMeta.mimetype,
size: urlMeta.size, size: urlMeta.size,

Loading…
Cancel
Save