Browse Source

Merge pull request #6600 from nocodb/nc-fix/form

Expanded form fixes
pull/6628/head
Raju Udava 1 year ago committed by GitHub
parent
commit
4a14308478
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      packages/nc-gui/assets/nc-icons/owner.svg
  2. 6
      packages/nc-gui/components/cell/Checkbox.vue
  3. 10
      packages/nc-gui/components/general/WorkspaceIcon.vue
  4. 2
      packages/nc-gui/components/smartsheet/column/DefaultValue.vue
  5. 3
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  6. 118
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  7. 36
      packages/nc-gui/components/smartsheet/grid/index.vue
  8. 2
      packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
  9. 27
      packages/nc-gui/components/virtual-cell/QrCode.vue
  10. 58
      packages/nc-gui/components/virtual-cell/barcode/Barcode.vue
  11. 6
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  12. 7
      packages/nc-gui/components/workspace/View.vue
  13. 5
      packages/nc-gui/composables/useExpandedFormStore.ts
  14. 14
      packages/nc-gui/composables/useViewData.ts
  15. 4
      packages/nc-gui/lang/en.json

9
packages/nc-gui/assets/nc-icons/owner.svg

@ -1,8 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_18_1022" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="currentColor"/>
<mask id="mask0_18_1042" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_18_1022)">
<path d="M7.99999 9.20002C7.33332 9.20002 6.76665 8.96668 6.29999 8.50002C5.83332 8.03335 5.59999 7.46668 5.59999 6.80002C5.59999 6.13335 5.83332 5.56668 6.29999 5.10002C6.76665 4.63335 7.33332 4.40002 7.99999 4.40002C8.66665 4.40002 9.23332 4.63335 9.69999 5.10002C10.1667 5.56668 10.4 6.13335 10.4 6.80002C10.4 7.46668 10.1667 8.03335 9.69999 8.50002C9.23332 8.96668 8.66665 9.20002 7.99999 9.20002ZM7.99999 8.00002C8.33332 8.00002 8.61665 7.88335 8.84999 7.65002C9.08332 7.41668 9.19999 7.13335 9.19999 6.80002C9.19999 6.46668 9.08332 6.18335 8.84999 5.95002C8.61665 5.71668 8.33332 5.60002 7.99999 5.60002C7.66665 5.60002 7.38332 5.71668 7.14999 5.95002C6.91665 6.18335 6.79999 6.46668 6.79999 6.80002C6.79999 7.13335 6.91665 7.41668 7.14999 7.65002C7.38332 7.88335 7.66665 8.00002 7.99999 8.00002ZM7.99999 2.88335L3.99999 4.41668V7.41668C3.99999 8.00557 4.08332 8.57779 4.24999 9.13335C4.41665 9.6889 4.64443 10.2056 4.93332 10.6833C5.4111 10.4611 5.90832 10.2917 6.42499 10.175C6.94165 10.0583 7.46665 10 7.99999 10C8.53332 10 9.05832 10.0583 9.57499 10.175C10.0917 10.2917 10.5889 10.4611 11.0667 10.6833C11.3555 10.2056 11.5833 9.6889 11.75 9.13335C11.9167 8.57779 12 8.00557 12 7.41668V4.41668L7.99999 2.88335ZM7.99999 11.2C7.59999 11.2 7.20554 11.2389 6.81665 11.3167C6.42777 11.3945 6.04999 11.5111 5.68332 11.6667C6.00554 12.0111 6.3611 12.3111 6.74999 12.5667C7.13888 12.8222 7.55554 13.0167 7.99999 13.15C8.44443 13.0167 8.8611 12.8222 9.24999 12.5667C9.63888 12.3111 9.99443 12.0111 10.3167 11.6667C9.94999 11.5111 9.57221 11.3945 9.18332 11.3167C8.79443 11.2389 8.39999 11.2 7.99999 11.2ZM7.99999 14.3333C7.93332 14.3333 7.86665 14.3306 7.79999 14.325C7.73332 14.3195 7.67221 14.3056 7.61665 14.2833C6.1611 13.8056 4.99443 12.9222 4.11665 11.6333C3.23888 10.3445 2.79999 8.93891 2.79999 7.41668V4.41668C2.79999 4.16113 2.86943 3.93335 3.00832 3.73335C3.14721 3.53335 3.33332 3.38891 3.56665 3.30002L7.56665 1.76668C7.7111 1.71113 7.85554 1.68335 7.99999 1.68335C8.14443 1.68335 8.28888 1.71113 8.43332 1.76668L12.4333 3.30002C12.6667 3.38891 12.8528 3.53335 12.9917 3.73335C13.1305 3.93335 13.2 4.16113 13.2 4.41668V7.41668C13.2 8.93891 12.7611 10.3445 11.8833 11.6333C11.0055 12.9222 9.83888 13.8056 8.38332 14.2833C8.32777 14.3056 8.26665 14.3195 8.19999 14.325C8.13332 14.3306 8.06665 14.3333 7.99999 14.3333Z" fill="currentColor" stroke="none"/>
<g mask="url(#mask0_18_1042)">
<path d="M6.66665 8.00002C5.93331 8.00002 5.30554 7.73891 4.78331 7.21669C4.26109 6.69447 3.99998 6.06669 3.99998 5.33335C3.99998 4.60002 4.26109 3.97224 4.78331 3.45002C5.30554 2.9278 5.93331 2.66669 6.66665 2.66669C7.39998 2.66669 8.02776 2.9278 8.54998 3.45002C9.0722 3.97224 9.33331 4.60002 9.33331 5.33335C9.33331 6.06669 9.0722 6.69447 8.54998 7.21669C8.02776 7.73891 7.39998 8.00002 6.66665 8.00002ZM1.33331 12V11.4667C1.33331 11.1 1.42776 10.7556 1.61665 10.4334C1.80554 10.1111 2.06665 9.86669 2.39998 9.70002C2.96665 9.41113 3.60554 9.16669 4.31665 8.96669C4.71274 8.85529 4.93609 8.67502 5.79165 8.67502H6.02498C6.09165 8.67502 6.15831 8.68613 6.22498 8.70835C5.99998 9.00002 5.33331 9.66669 4.99998 10C4.99998 10 4.8376 10.2057 4.54165 10.3C3.91387 10.5 3.39998 10.7 2.99998 10.9C2.89998 10.9556 2.81942 11.0334 2.75831 11.1334C2.6972 11.2334 2.66665 11.3445 2.66665 11.4667V12H4.99998C5.33331 12.3334 5.33331 12.3334 5.66665 12.6917C5.90596 12.949 6.19998 13.1334 6.33331 13.3334H2.66665C2.29998 13.3334 1.98609 13.2028 1.72498 12.9417C1.46387 12.6806 1.33331 12.3667 1.33331 12ZM6.66665 6.66669C7.03331 6.66669 7.3472 6.53613 7.60831 6.27502C7.86942 6.01391 7.99998 5.70002 7.99998 5.33335C7.99998 4.96669 7.86942 4.6528 7.60831 4.39169C7.3472 4.13058 7.03331 4.00002 6.66665 4.00002C6.29998 4.00002 5.98609 4.13058 5.72498 4.39169C5.46387 4.6528 5.33331 4.96669 5.33331 5.33335C5.33331 5.70002 5.46387 6.01391 5.72498 6.27502C5.98609 6.53613 6.29998 6.66669 6.66665 6.66669Z" fill="currentColor" stroke="none"/>
<path d="M9.99998 12.6667C10.6555 12.6667 11.2639 12.5167 11.825 12.2167C12.3861 11.9167 12.8333 11.5111 13.1666 11C12.8333 10.4889 12.3861 10.0833 11.825 9.78333C11.2639 9.48333 10.6555 9.33333 9.99998 9.33333C9.34442 9.33333 8.73609 9.48333 8.17498 9.78333C7.61387 10.0833 7.16665 10.4889 6.83331 11C7.16665 11.5111 7.61387 11.9167 8.17498 12.2167C8.73609 12.5167 9.34442 12.6667 9.99998 12.6667ZM9.99998 14C8.93331 14 7.98054 13.7194 7.14165 13.1583C6.30276 12.5972 5.69998 11.8778 5.33331 11C5.69998 10.1222 6.30276 9.40278 7.14165 8.84167C7.98054 8.28056 8.93331 8 9.99998 8C11.0666 8 12.0194 8.28056 12.8583 8.84167C13.6972 9.40278 14.3 10.1222 14.6666 11C14.3 11.8778 13.6972 12.5972 12.8583 13.1583C12.0194 13.7194 11.0666 14 9.99998 14ZM9.99998 12C9.7222 12 9.48609 11.9028 9.29165 11.7083C9.0972 11.5139 8.99998 11.2778 8.99998 11C8.99998 10.7222 9.0972 10.4861 9.29165 10.2917C9.48609 10.0972 9.7222 10 9.99998 10C10.2778 10 10.5139 10.0972 10.7083 10.2917C10.9028 10.4861 11 10.7222 11 11C11 11.2778 10.9028 11.5139 10.7083 11.7083C10.5139 11.9028 10.2778 12 9.99998 12Z" fill="currentColor" stroke="none"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

6
packages/nc-gui/components/cell/Checkbox.vue

@ -40,6 +40,8 @@ const isGallery = inject(IsGalleryInj, ref(false))
const readOnly = inject(ReadonlyInj)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const checkboxMeta = computed(() => {
return {
icon: {
@ -82,8 +84,8 @@ useSelectedCellKeyupListener(active, (e) => {
<div
class="flex cursor-pointer w-full h-full items-center"
:class="{
'justify-center': !isForm || !isGallery,
'w-full flex-start': isForm || isGallery,
'w-full flex-start pl-2': isForm || isGallery || isExpandedFormOpen,
'w-full justify-center': !isForm && !isGallery && !isExpandedFormOpen,
'nc-cell-hover-show': !vModel && !readOnly,
'opacity-0': readOnly && !vModel,
}"

10
packages/nc-gui/components/general/WorkspaceIcon.vue

@ -1,6 +1,6 @@
<script lang="ts" setup>
import type { WorkspaceType } from 'nocodb-sdk'
import { stringToColor } from '~/utils/colorsUtils'
import { isColorDark, stringToColor } from '~/utils/colorsUtils'
const props = defineProps<{
workspace: WorkspaceType | undefined
@ -26,7 +26,13 @@ const size = computed(() => props.size || 'medium')
:style="{ backgroundColor: workspaceColor }"
>
<template v-if="!props.hideLabel">
<div class="font-black">
<div
class="font-semibold"
:class="{
'text-white': isColorDark(workspaceColor),
'text-black': !isColorDark(workspaceColor),
}"
>
{{ props.workspace?.title?.slice(0, 2) }}
</div>
</template>

2
packages/nc-gui/components/smartsheet/column/DefaultValue.vue

@ -54,5 +54,3 @@ onMounted(() => {
</div>
</div>
</template>
<style scoped></style>

3
packages/nc-gui/components/smartsheet/expanded-form/Comments.vue

@ -194,7 +194,7 @@ watch(commentsWrapperEl, () => {
</div>
<div v-if="hasEditPermission" class="p-2 bg-gray-50 gap-2 flex">
<div class="h-14 flex flex-row w-full bg-white py-2.75 px-1.5 items-center rounded-xl border-1 border-gray-200">
<GeneralUserIcon size="base" class="!w-10" />
<GeneralUserIcon size="base" class="!w-10" :email="user?.email" />
<a-input
v-model:value="comment"
class="!rounded-lg border-1 bg-white !px-2.5 !py-2 !border-gray-200 nc-comment-box !outline-none"
@ -230,6 +230,7 @@ watch(commentsWrapperEl, () => {
<div class="flex justify-between">
<div class="flex items-center gap-2">
<GeneralUserIcon size="base" :email="log.user" />
<div class="flex flex-col">
<span class="truncate font-bold max-w-50">
{{ log.display_name ?? log.user.split('@')[0].slice(0, 2) ?? 'Shared source' }}

118
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -67,6 +67,10 @@ const state = toRef(props, 'state')
const meta = toRef(props, 'meta')
const islastRow = toRef(props, 'lastRow')
const isFirstRow = toRef(props, 'firstRow')
const route = useRoute()
const router = useRouter()
@ -76,6 +80,8 @@ const isPublic = inject(IsPublicInj, ref(false))
// to check if a expanded form which is not yet saved exist or not
const isUnsavedFormExist = ref(false)
const isRecordLinkCopied = ref(false)
const { isUIAllowed } = useRoles()
const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook())
@ -120,6 +126,7 @@ const {
syncLTARRefs,
save: _save,
loadCommentsAndLogs,
clearColumns,
} = useProvideExpandedFormStore(meta, row)
const duplicatingRowInProgress = ref(false)
@ -143,8 +150,12 @@ const isExpanded = useVModel(props, 'modelValue', emits, {
})
const onClose = () => {
if (_row.value?.rowMeta?.new) emits('cancel')
isExpanded.value = false
if (changedColumns.value.size > 0) {
isCloseModalOpen.value = true
} else {
if (_row.value?.rowMeta?.new) emits('cancel')
isExpanded.value = false
}
}
const onDuplicateRow = () => {
@ -180,35 +191,57 @@ const save = async () => {
}
const isPreventChangeModalOpen = ref(false)
const isCloseModalOpen = ref(false)
const discardPreventModal = () => {
emits('next')
isPreventChangeModalOpen.value = false
// when user click on next or previous button
if (isPreventChangeModalOpen.value) {
emits('next')
if (_row.value?.rowMeta?.new) emits('cancel')
isPreventChangeModalOpen.value = false
}
// when user click on close button
if (isCloseModalOpen.value) {
isCloseModalOpen.value = false
if (_row.value?.rowMeta?.new) emits('cancel')
isExpanded.value = false
}
// clearing all new modifed change on close
clearColumns()
}
const onNext = async () => {
if (changedColumns.value.size > 0) {
isPreventChangeModalOpen.value = true
} else {
emits('next')
return
}
emits('next')
}
const copyRecordUrl = () => {
copy(
const copyRecordUrl = async () => {
await copy(
encodeURI(
`${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.projectId}/${meta.value?.id}${
`${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.baseId}/${meta.value?.id}${
props.view ? `/${props.view.title}` : ''
}?rowId=${primaryKey.value}`,
),
)
message.success('Copied to clipboard')
isRecordLinkCopied.value = true
}
const saveChanges = async () => {
isUnsavedFormExist.value = false
await save()
emits('next')
if (isPreventChangeModalOpen.value) {
isUnsavedFormExist.value = false
await save()
emits('next')
isPreventChangeModalOpen.value = false
}
if (isCloseModalOpen.value) {
isCloseModalOpen.value = false
await save()
isExpanded.value = false
}
}
const reloadParentRowHook = inject(ReloadRowDataHookInj, createEventHook())
@ -235,6 +268,7 @@ provide(IsExpandedFormOpenInj, isExpanded)
const cellWrapperEl = ref()
onMounted(async () => {
isRecordLinkCopied.value = false
isLoading.value = true
if (props.loadRow) {
await _loadRow()
@ -369,6 +403,8 @@ watch(rowId, async (nRow) => {
const showRightSections = computed(() => {
return !isNew.value && commentsDrawer.value && isUIAllowed('commentList')
})
const preventModalStatus = computed(() => isCloseModalOpen.value || isPreventChangeModalOpen.value)
</script>
<script lang="ts">
@ -395,7 +431,7 @@ export default {
<div class="flex gap-2">
<NcButton
v-if="props.showNextPrevIcons"
:disabled="props.firstRow"
:disabled="isFirstRow"
type="secondary"
class="nc-prev-arrow !w-10"
@click="$emit('prev')"
@ -404,7 +440,7 @@ export default {
</NcButton>
<NcButton
v-if="props.showNextPrevIcons"
:disabled="props.lastRow"
:disabled="islastRow"
type="secondary"
class="nc-next-arrow !w-10"
@click="onNext"
@ -423,6 +459,18 @@ export default {
<div v-if="row.rowMeta?.new" class="flex items-center truncate font-bold text-gray-800 text-xl">New Record</div>
</div>
<div class="flex gap-2">
<NcButton
v-if="!isNew"
type="secondary"
class="!xs:hidden text-gray-700"
@click="!isNew ? copyRecordUrl() : () => {}"
>
<div v-e="['c:row-expand:copy-url']" data-testid="nc-expanded-form-copy-url" class="flex gap-2 items-center">
<component :is="iconMap.check" v-if="isRecordLinkCopied" class="cursor-pointer nc-duplicate-row" />
<component :is="iconMap.link" v-else class="cursor-pointer nc-duplicate-row" />
{{ isRecordLinkCopied ? $t('labels.copiedRecordURL') : $t('labels.copyRecordURL') }}
</div>
</NcButton>
<NcDropdown v-if="!isNew">
<NcButton type="secondary" class="nc-expand-form-more-actions w-10">
<GeneralIcon icon="threeDotVertical" class="text-md text-gray-700" />
@ -435,10 +483,10 @@ export default {
{{ $t('general.reload') }}
</div>
</NcMenuItem>
<NcMenuItem v-if="!isNew" class="text-gray-700" @click="!isNew ? copyRecordUrl() : () => {}">
<NcMenuItem v-if="!isNew && isMobileMode" class="text-gray-700" @click="!isNew ? copyRecordUrl() : () => {}">
<div v-e="['c:row-expand:copy-url']" data-testid="nc-expanded-form-copy-url" class="flex gap-2 items-center">
<component :is="iconMap.link" class="cursor-pointer nc-duplicate-row" />
Copy record URL
{{ $t('labels.copyRecordURL') }}
</div>
</NcMenuItem>
<NcMenuItem
@ -452,7 +500,9 @@ export default {
class="flex gap-2 items-center"
>
<component :is="iconMap.copy" class="cursor-pointer nc-duplicate-row" />
Duplicate record
<span class="-ml-0.25">
{{ $t('labels.duplicateRecord') }}
</span>
</div>
</NcMenuItem>
<NcDivider v-if="isUIAllowed('dataEdit') && !isNew" />
@ -463,7 +513,9 @@ export default {
@click="!isNew && onDeleteRowClick()"
>
<component :is="iconMap.delete" data-testid="nc-expanded-form-delete" class="cursor-pointer nc-delete-row" />
Delete record
<span class="-ml-0.5">
{{ $t('activity.deleteRecord') }}
</span>
</NcMenuItem>
</NcMenu>
</template>
@ -524,15 +576,15 @@ export default {
:col-id="col.id"
:data-testid="`nc-expand-col-${col.title}`"
>
<div class="flex items-start flex-row xs:(flex-col w-full) nc-expanded-cell min-h-10">
<div class="w-[12rem] xs:(w-full) mt-1.5 !h-[35px]">
<div class="flex items-start flex-row sm:(gap-x-6) xs:(flex-col w-full) nc-expanded-cell min-h-10">
<div class="w-[12rem] xs:(w-full) mt-0.25 !h-[35px]">
<LazySmartsheetHeaderVirtualCell
v-if="isVirtualCol(col)"
class="nc-expanded-cell-header !text-gray-600"
class="nc-expanded-cell-header h-full !text-gray-500"
:column="col"
/>
<LazySmartsheetHeaderCell v-else class="nc-expanded-cell-header !text-gray-600" :column="col" />
<LazySmartsheetHeaderCell v-else class="nc-expanded-cell-header !text-gray-500" :column="col" />
</div>
<template v-if="isLoading">
@ -706,7 +758,6 @@ export default {
<template #entity-preview>
<span>
<div class="flex flex-row items-center py-2.25 px-2.5 bg-gray-50 rounded-lg text-gray-700 mb-4">
<component :is="iconMap.record" class="nc-view-icon" />
<div class="capitalize text-ellipsis overflow-hidden select-none w-full pl-1.75 break-keep whitespace-nowrap">
{{ displayValue }}
</div>
@ -716,16 +767,19 @@ export default {
</GeneralDeleteModal>
<!-- Prevent unsaved change modal -->
<NcModal v-model:visible="isPreventChangeModalOpen" size="small">
<template #header>
<div class="flex flex-row items-center gap-x-2">Do you want to save the changes ?</div>
</template>
<div class="mt-2">
<div class="flex flex-row justify-end gap-x-2 mt-6">
<NcButton type="secondary" @click="discardPreventModal">{{ $t('general.quit') }}</NcButton>
<NcModal v-model:visible="preventModalStatus" size="small">
<div class="">
<div class="flex flex-row items-center gap-x-2 text-base font-bold">
{{ $t('tooltip.saveChanges') }}
</div>
<div class="flex font-medium mt-2">
{{ $t('activity.doYouWantToSaveTheChanges') }}
</div>
<div class="flex flex-row justify-end gap-x-2 mt-5">
<NcButton type="secondary" @click="discardPreventModal">{{ $t('labels.discard') }}</NcButton>
<NcButton key="submit" type="primary" label="Rename Table" loading-label="Renaming Table" @click="saveChanges">
{{ $t('activity.saveAndQuit') }}
{{ $t('tooltip.saveChanges') }}
</NcButton>
</div>
</div>

36
packages/nc-gui/components/smartsheet/grid/index.vue

@ -68,6 +68,8 @@ const {
bulkUpdateRows,
bulkUpdateView,
optimisedQuery,
islastRow,
isFirstRow,
} = useViewData(meta, view, xWhere)
const rowHeight = computed(() => {
@ -183,6 +185,30 @@ onMounted(() => {
if (coreWrapperRef.value) resizeObserver.observe(coreWrapperRef.value)
})
})
const goToNextRow = () => {
const currentIndex = getExpandedRowIndex()
/* when last index of current page is reached we should move to next page */
if (!paginationData.value.isLastPage && currentIndex === paginationData.value.pageSize) {
const nextPage = paginationData.value?.page ? paginationData.value?.page + 1 : 1
changePage(nextPage)
}
navigateToSiblingRow(NavigateDir.NEXT)
}
const goToPreviousRow = () => {
const currentIndex = getExpandedRowIndex()
/* when first index of current page is reached and then clicked back
previos page should be loaded
*/
if (!paginationData.value.isFirstPage && currentIndex === 1) {
const nextPage = paginationData.value?.page ? paginationData.value?.page - 1 : 1
changePage(nextPage)
}
navigateToSiblingRow(NavigateDir.PREV)
}
</script>
<template>
@ -226,7 +252,6 @@ onMounted(() => {
:expand-form="expandForm"
:view-width="viewWidth"
/>
<Suspense>
<LazySmartsheetExpandedForm
v-if="expandedFormRow && expandedFormDlg"
@ -238,7 +263,6 @@ onMounted(() => {
@update:model-value="addRowExpandOnClose(expandedFormRow)"
/>
</Suspense>
<SmartsheetExpandedForm
v-if="expandedFormOnRowIdDlg"
v-model="expandedFormOnRowIdDlg"
@ -248,10 +272,10 @@ onMounted(() => {
:row-id="routeQuery.rowId"
:view="view"
show-next-prev-icons
:first-row="getExpandedRowIndex() === 0"
:last-row="getExpandedRowIndex() === data.length - 1"
@next="navigateToSiblingRow(NavigateDir.NEXT)"
@prev="navigateToSiblingRow(NavigateDir.PREV)"
:first-row="isFirstRow"
:last-row="islastRow"
@next="goToNextRow()"
@prev="goToPreviousRow()"
/>
<Suspense>

2
packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts

@ -39,7 +39,7 @@ const renderIcon = (column: ColumnType, relationColumn?: ColumnType) => {
case UITypes.QrCode:
return { icon: iconMap.qrCode, color: 'text-grey' }
case UITypes.Barcode:
return { icon: iconMap.qrCode, color: 'text-grey' }
return { icon: iconMap.barCode, color: 'text-grey' }
case UITypes.Lookup:
switch ((relationColumn?.colOptions as LinkToAnotherRecordType)?.type) {
case RelationTypes.MANY_TO_MANY:

27
packages/nc-gui/components/virtual-cell/QrCode.vue

@ -11,6 +11,8 @@ const isGallery = inject(IsGalleryInj, ref(false))
const qrValue = computed(() => String(cellValue?.value))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const tooManyCharsForQrCode = computed(() => qrValue?.value.length > maxNumberOfAllowedCharsForQrValue)
const showQrCode = computed(() => qrValue?.value?.length > 0 && !tooManyCharsForQrCode.value)
@ -66,15 +68,22 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us
<div v-if="tooManyCharsForQrCode" class="text-left text-wrap mt-2 text-[#e65100] text-[10px]">
{{ $t('labels.qrCodeValueTooLong') }}
</div>
<img
v-if="showQrCode && rowHeight"
:class="{ 'mx-auto': !isGallery }"
:style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }"
:src="qrCode"
:alt="$t('title.qrCode')"
@click="showQrModal"
/>
<img v-else-if="showQrCode" class="mx-auto" :src="qrCode" :alt="$t('title.qrCode')" @click="showQrModal" />
<div
class="pl-2 w-full flex"
:class="{
'flex-start': isExpandedFormOpen,
'justify-center': !isExpandedFormOpen,
}"
>
<img
v-if="showQrCode && rowHeight"
:style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }"
:src="qrCode"
:alt="$t('title.qrCode')"
@click="showQrModal"
/>
<img v-else-if="showQrCode" class="mx-auto" :src="qrCode" :alt="$t('title.qrCode')" @click="showQrModal" />
</div>
<div v-if="showEditNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }}
</div>

58
packages/nc-gui/components/virtual-cell/barcode/Barcode.vue

@ -15,6 +15,8 @@ const tooManyCharsForBarcode = computed(() => barcodeValue.value.length > maxNum
const modalVisible = ref(false)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const showBarcodeModal = () => {
modalVisible.value = true
}
@ -46,31 +48,39 @@ const rowHeight = inject(RowHeightInj, ref(undefined))
>
<JsBarcodeWrapper v-if="showBarcode" :barcode-value="barcodeValue" :barcode-format="barcodeMeta.barcodeFormat" />
</a-modal>
<JsBarcodeWrapper
v-if="showBarcode && rowHeight"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
:custom-style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }"
@on-click-barcode="showBarcodeModal"
>
<template #barcodeRenderError>
<div class="text-left text-wrap mt-2 text-[#e65100] text-xs" data-testid="barcode-invalid-input-message">
{{ $t('msg.warning.barcode.renderError') }}
</div>
</template>
</JsBarcodeWrapper>
<JsBarcodeWrapper
v-else-if="showBarcode"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
@on-click-barcode="showBarcodeModal"
<div
class="flex ml-2 w-full items-center"
:class="{
'justify-start': isExpandedFormOpen,
'justify-center': !isExpandedFormOpen,
}"
>
<template #barcodeRenderError>
<div class="text-left text-wrap mt-2 text-[#e65100] text-xs" data-testid="barcode-invalid-input-message">
{{ $t('msg.warning.barcode.renderError') }}
</div>
</template>
</JsBarcodeWrapper>
<JsBarcodeWrapper
v-if="showBarcode && rowHeight"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
:custom-style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem`, width: 40 }"
@on-click-barcode="showBarcodeModal"
>
<template #barcodeRenderError>
<div class="text-left text-wrap mt-2 text-[#e65100] text-xs" data-testid="barcode-invalid-input-message">
{{ $t('msg.warning.barcode.renderError') }}
</div>
</template>
</JsBarcodeWrapper>
<JsBarcodeWrapper
v-else-if="showBarcode"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
@on-click-barcode="showBarcodeModal"
>
<template #barcodeRenderError>
<div class="text-left text-wrap mt-2 text-[#e65100] text-xs" data-testid="barcode-invalid-input-message">
{{ $t('msg.warning.barcode.renderError') }}
</div>
</template>
</JsBarcodeWrapper>
</div>
<div v-if="tooManyCharsForBarcode" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('labels.barcodeValueTooLong') }}

6
packages/nc-gui/components/virtual-cell/components/ItemChip.vue

@ -1,4 +1,5 @@
<script lang="ts" setup>
import type { ColumnType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk'
import {
ActiveCellInj,
@ -41,12 +42,13 @@ const isLocked = inject(IsLockedInj, ref(false))
const { open } = useExpandedFormDetached()
function openExpandedForm() {
if (!readOnly.value && !isLocked.value && !readonlyProp) {
const rowId = extractPkFromRow(item, relatedTableMeta.value.columns as ColumnType[])
if (!readOnly.value && !isLocked.value && !readonlyProp && rowId) {
open({
isOpen: true,
row: { row: item, rowMeta: {}, oldRow: { ...item } },
meta: relatedTableMeta.value,
loadRow: true,
rowId,
useMetaFields: true,
})
}

7
packages/nc-gui/components/workspace/View.vue

@ -1,6 +1,5 @@
<script lang="ts" setup>
import { useTitle } from '@vueuse/core'
import type { WorkspaceType } from 'nocodb-sdk'
const router = useRouter()
const route = router.currentRoute
@ -21,8 +20,6 @@ const tab = computed({
},
})
const getWorkspaceColor = (workspace: WorkspaceType) => workspace.meta?.color || stringToColor(workspace.id!)
watch(
() => activeWorkspace.value?.title,
(title: string) => {
@ -53,9 +50,7 @@ onMounted(() => {
<template>
<div v-if="activeWorkspace" class="flex flex-col nc-workspace-settings">
<div class="flex gap-2 items-center min-w-0 p-6">
<span class="nc-workspace-avatar !w-8 !h-8" :style="{ backgroundColor: getWorkspaceColor(activeWorkspace) }">
{{ activeWorkspace?.title?.slice(0, 2) }}
</span>
<GeneralWorkspaceIcon :workspace="activeWorkspace" />
<h1 class="text-3xl font-weight-bold tracking-[0.5px] mb-0 nc-workspace-title truncate min-w-10 capitalize">
{{ activeWorkspace?.title }}
</h1>

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

@ -279,6 +279,10 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
return data
}
const clearColumns = () => {
changedColumns.value = new Set()
}
const loadRow = async (rowId?: string) => {
const record = await $api.dbTableRow.read(
NOCO,
@ -344,6 +348,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
primaryKey,
saveRowAndStay,
updateComment,
clearColumns,
}
}, 'expanded-form-store')

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

@ -99,6 +99,16 @@ export function useViewData(
},
})
const islastRow = computed(() => {
const currentIndex = getExpandedRowIndex()
return paginationData.value?.isLastPage && currentIndex === formattedData.value.length - 1
})
const isFirstRow = computed(() => {
const currentIndex = getExpandedRowIndex()
return paginationData.value?.isFirstPage && currentIndex === 0
})
const queryParams = computed(() => ({
offset: ((paginationData.value.page ?? 0) - 1) * (paginationData.value.pageSize ?? appInfoDefaultLimit),
limit: paginationData.value.pageSize ?? appInfoDefaultLimit,
@ -303,6 +313,8 @@ export function useViewData(
}
const navigateToSiblingRow = async (dir: NavigateDir) => {
console.log('test')
const expandedRowIndex = getExpandedRowIndex()
// calculate next row index based on direction
@ -378,5 +390,7 @@ export function useViewData(
navigateToSiblingRow,
getExpandedRowIndex,
optimisedQuery,
islastRow,
isFirstRow,
}
}

4
packages/nc-gui/lang/en.json

@ -397,6 +397,9 @@
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
@ -606,6 +609,7 @@
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",

Loading…
Cancel
Save