Browse Source

fix: Links modal for mobile

pull/6558/head
Muhammed Mustafa 12 months ago
parent
commit
5f7db89c9b
  1. 2
      packages/nc-gui/components/nc/Modal.vue
  2. 62
      packages/nc-gui/components/virtual-cell/components/Header.vue
  3. 178
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  4. 136
      packages/nc-gui/components/virtual-cell/components/ListItems.vue

2
packages/nc-gui/components/nc/Modal.vue

@ -83,7 +83,7 @@ const slots = useSlots()
@keydown.esc="visible = false"
>
<div
class="flex flex-col nc-modal p-6"
class="flex flex-col nc-modal p-6 h-full"
:style="{
maxHeight: height,
}"

62
packages/nc-gui/components/virtual-cell/components/Header.vue

@ -13,6 +13,8 @@ const { relation, relatedTableTitle, displayValue, showHeader, tableTitle } = de
displayValue?: string
}>()
const { isMobileMode } = useGlobal()
const { t } = useI18n()
const relationMeta = computed(() => {
@ -51,16 +53,14 @@ const relationMeta = computed(() => {
<template>
<div class="flex justify-between relative pb-2 items-center">
<span class="text-base font-bold flex mt-2 justify-center">
<div v-if="!isMobileMode" class="flex text-base font-bold justify-start items-center w-36">
{{ showHeader ? 'Linked Records' : '' }}
</span>
<div class="grid grid-cols-[1fr,auto,1fr] justify-center items-center gap-2 absolute inset-0 m-auto">
<div class="flex justify-end">
<div class="flex flex-shrink-0 rounded-md gap-1 text-brand-500 items-center bg-gray-100 px-2 py-1">
<FileIcon class="w-4 h-4" />
<GeneralTruncateText placement="top" length="25">
{{ displayValue }}
</GeneralTruncateText>
</div>
<div class="flex flex-row flex-grow items-center justify-center gap-2 xs:h-full">
<div class="flex justify-end w-[calc(50%-4rem)] xs:(w-[calc(50%-1rem)] h-full)">
<div class="flex flex-shrink-0 xs:(flex-grow h-full) rounded-md gap-1 text-brand-500 items-center bg-gray-100 px-2 py-1">
<FileIcon class="w-4 h-4 min-w-4" />
{{ displayValue }}
</div>
</div>
<NcTooltip class="flex-shrink-0">
@ -75,9 +75,9 @@ const relationMeta = computed(() => {
}"
/>
</NcTooltip>
<div class="flex justify-start">
<div class="flex justify-start xs:w-[calc(50%-1rem)] w-[calc(50%-4rem)] xs:justify-start">
<div
class="flex rounded-md flex-shrink-0 gap-1 items-center px-2 py-1"
class="flex rounded-md flex-shrink-0 gap-1 items-center px-2 py-1 w-full overflow-hidden"
:class="{
'!bg-orange-50 !text-orange-500': relation === 'hm',
'!bg-pink-50 !text-pink-500': relation === 'mm',
@ -85,34 +85,36 @@ const relationMeta = computed(() => {
}"
>
<MdiFileDocumentMultipleOutline
class="w-4 h-4"
class="w-4 h-4 min-w-4"
:class="{
'!text-orange-500': relation === 'hm',
'!text-pink-500': relation === 'mm',
'!text-blue-500': relation === 'bt',
}"
/>
{{ relatedTableTitle }} Records
<span class="truncate"> {{ relatedTableTitle }} Records </span>
</div>
</div>
</div>
<NcTooltip class="z-10" placement="bottom">
<template #title>
<div class="p-1">
<h1 class="text-white font-bold">{{ relationMeta.title }}</h1>
<div class="text-white">
{{ relationMeta.tooltip_desc }}
<span class="bg-gray-700 px-2 rounded-md">
{{ tableTitle }}
</span>
{{ relationMeta.tooltip_desc2 }}
<span class="bg-gray-700 px-2 rounded-md">
{{ relatedTableTitle }}
</span>
<div v-if="!isMobileMode" class="flex flex-row justify-end w-36">
<NcTooltip class="z-10" placement="bottom">
<template #title>
<div class="p-1">
<h1 class="text-white font-bold">{{ relationMeta.title }}</h1>
<div class="text-white">
{{ relationMeta.tooltip_desc }}
<span class="bg-gray-700 px-2 rounded-md">
{{ tableTitle }}
</span>
{{ relationMeta.tooltip_desc2 }}
<span class="bg-gray-700 px-2 rounded-md">
{{ relatedTableTitle }}
</span>
</div>
</div>
</div>
</template>
<InfoIcon class="w-4 h-4 mt-2" />
</NcTooltip>
</template>
<InfoIcon class="w-4 h-4" />
</NcTooltip>
</div>
</div>
</template>

178
packages/nc-gui/components/virtual-cell/components/ListChildItems.vue

@ -24,6 +24,8 @@ const emit = defineEmits(['update:modelValue', 'attachRecord'])
const vModel = useVModel(props, 'modelValue', emit)
const { isMobileMode } = useGlobal()
const isForm = inject(IsFormInj, ref(false))
const isPublic = inject(IsPublicInj, ref(false))
@ -159,13 +161,14 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
</script>
<template>
<a-modal
<NcModal
v-model:visible="vModel"
:class="{ active: vModel }"
:footer="null"
:closable="false"
size="medium"
:width="isForm ? 600 : 800"
:body-style="{ 'padding': 0, 'margin': 0, 'min-height': isForm ? '300px' : '500px' }"
:body-style="{ 'max-height': '640px', 'height': '85vh' }"
wrap-class-name="nc-modal-child-list"
>
<LazyVirtualCellComponentsHeader
@ -199,95 +202,98 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
</div>
</div>
<div v-if="isDataExist || isChildrenLoading" class="mt-2 mb-2">
<div
:class="{
'h-[420px]': !isForm,
'h-[250px]': isForm,
}"
class="overflow-scroll nc-scrollbar-md cursor-pointer pr-1"
>
<template v-if="isChildrenLoading">
<div
v-for="(x, i) in Array.from({ length: skeltonAmountToShow })"
:key="i"
class="border-2 flex flex-row gap-2 mb-2 transition-all rounded-xl relative border-gray-200 hover:bg-gray-50"
>
<a-skeleton-image class="h-24 w-24 !rounded-xl" />
<div class="flex flex-col m-[.5rem] gap-2 flex-grow justify-center">
<a-skeleton-input class="!w-48 !rounded-xl" active size="small" />
<div class="flex flex-row gap-6 w-10/12">
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
<div class="flex flex-col flex-grow">
<template v-if="(isNew && state?.[colTitle]?.length) || childrenList?.pageInfo?.totalRows">
<div class="mt-2 mb-2">
<div class="nc-scrollbar-md cursor-pointer pr-1">
<template v-if="isChildrenLoading">
<div
v-for="(x, i) in Array.from({ length: 10 })"
:key="i"
class="!border-2 flex flex-row gap-2 mb-2 transition-all !rounded-xl relative !border-gray-200 hover:bg-gray-50"
>
<a-skeleton-image class="h-24 w-24 !rounded-xl" />
<div class="flex flex-col m-[.5rem] gap-2 flex-grow justify-center">
<a-skeleton-input class="!w-48 !rounded-xl" active size="small" />
<div class="flex flex-row gap-6 w-10/12">
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<LazyVirtualCellComponentsListItem
v-for="(refRow, id) in childrenList?.list ?? state?.[colTitle] ?? []"
:key="id"
:row="refRow"
:fields="fields"
data-testid="nc-child-list-item"
:attachment="attachmentCol"
:related-table-display-value-prop="relatedTableDisplayValueProp"
:is-linked="childrenList?.list ? isChildrenListLinked[Number.parseInt(id)] : true"
:is-loading="isChildrenListLoading[Number.parseInt(id)]"
@expand="onClick(refRow)"
@click="
() => {
if (isPublic && !isForm) return
isNew
? unlinkRow(refRow, Number.parseInt(id))
: isChildrenListLinked[Number.parseInt(id)]
? unlinkRow(refRow, Number.parseInt(id))
: linkRow(refRow, Number.parseInt(id))
}
"
/>
</template>
</div>
</template>
<template v-else>
<LazyVirtualCellComponentsListItem
v-for="(refRow, id) in childrenList?.list ?? state?.[colTitle] ?? []"
:key="id"
:row="refRow"
:fields="fields"
data-testid="nc-child-list-item"
:attachment="attachmentCol"
:related-table-display-value-prop="relatedTableDisplayValueProp"
:is-linked="childrenList?.list ? isChildrenListLinked[Number.parseInt(id)] : true"
:is-loading="isChildrenListLoading[Number.parseInt(id)]"
@expand="onClick(refRow)"
@click="linkOrUnLink(refRow, id)"
/>
</template>
</div>
</template>
<div v-else class="pt-1 flex flex-col gap-3 my-auto items-center justify-center text-gray-500">
<InboxIcon class="w-16 h-16 mx-auto" />
<p>
{{ $t('msg.noRecordsAreLinkedFromTable') }}
{{ relatedTableMeta?.title }}
</p>
<NcButton
v-if="!readonly && childrenListCount < 1"
v-e="['c:links:link']"
data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')"
>
<div class="flex items-center gap-1"><MdiPlus /> {{ $t('title.linkMoreRecords') }}</div>
</NcButton>
</div>
</div>
<div
v-else
:class="{
'h-[420px]': !isForm,
'h-[250px]': isForm,
}"
class="pt-1 flex flex-col gap-3 items-center justify-center text-gray-500"
>
<InboxIcon class="w-16 h-16 mx-auto" />
<p>
{{ $t('msg.noRecordsAreLinkedFromTable') }}
{{ relatedTableMeta?.title }}
</p>
<NcButton
v-if="!readonly && childrenListCount < 1"
v-e="['c:links:link']"
data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')"
>
<div class="flex items-center gap-1"><MdiPlus /> {{ $t('title.linkMoreRecords') }}</div>
</NcButton>
</div>
<div class="my-2 bg-gray-50 border-gray-50 border-b-2"></div>
<div class="flex flex-row justify-between bg-white relative pt-1">
<div v-if="!isForm" class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50">
{{ childrenListCount || 0 }} {{ $t('objects.records') }} {{ childrenListCount !== 0 ? $t('general.are') : '' }}
{{ childrenListCount || 0 }} {{ !isMobileMode ? $t('objects.records') : '' }}
{{ !isMobileMode && childrenListCount !== 0 ? $t('general.are') : '' }}
{{ $t('general.linked') }}
</div>
<div v-else class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50">
{{ state?.[colTitle]?.length || 0 }} {{ $t('objects.records') }}
{{ state?.[colTitle]?.length !== 0 ? $t('general.are') : '' }}
{{ $t('general.linked') }}
<span class="">
{{ state?.[colTitle]?.length || 0 }} {{ $t('objects.records') }}
{{ state?.[colTitle]?.length !== 0 ? $t('general.are') : '' }}
{{ $t('general.linked') }}
</span>
</div>
<div class="flex absolute items-center py-2 justify-center w-full">
<a-pagination
@ -310,7 +316,9 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')"
>
<div class="flex items-center gap-1"><MdiPlus /> {{ $t('title.linkMoreRecords') }}</div>
<div class="flex items-center gap-1">
<MdiPlus class="!xs:hidden" /> {{ isMobileMode ? 'Link More' : $t('title.linkMoreRecords') }}
</div>
</NcButton>
</div>
</div>
@ -333,11 +341,21 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
use-meta-fields
/>
</Suspense>
</a-modal>
</NcModal>
</template>
<style scoped lang="scss">
:deep(.nc-nested-list-item .ant-card-body) {
@apply !px-1 !py-0;
}
:deep(.ant-modal-content) {
@apply !p-0;
}
</style>
<style lang="scss">
.nc-modal-child-list > .ant-modal > .ant-modal-content {
@apply !p-0;
}
</style>

136
packages/nc-gui/components/virtual-cell/components/ListItems.vue

@ -21,6 +21,8 @@ const emit = defineEmits(['update:modelValue', 'addNewRecord'])
const vModel = useVModel(props, 'modelValue', emit)
const { isMobileMode } = useGlobal()
const injectedColumn = inject(ColumnInj)
const filterQueryRef = ref()
@ -157,13 +159,13 @@ onKeyStroke('Escape', () => {
</script>
<template>
<a-modal
<NcModal
v-model:visible="vModel"
:class="{ active: vModel }"
:footer="null"
:width="isForm ? 600 : 800"
:closable="false"
:body-style="{ 'padding': 0, 'margin': 0, 'min-height': '500px' }"
:body-style="{ 'max-height': '640px', 'height': '85vh' }"
wrap-class-name="nc-modal-link-record"
>
<LazyVirtualCellComponentsHeader
@ -173,7 +175,7 @@ onKeyStroke('Escape', () => {
:related-table-title="relatedTableMeta?.title"
:display-value="row.row[displayValueProp]"
/>
<div class="m-4 bg-gray-50 border-gray-50 border-b-2"></div>
<div class="my-3 bg-gray-50 border-gray-50 border-b-2"></div>
<div class="flex mt-2 mb-2 items-center gap-2">
<div
class="flex items-center border-1 p-1 rounded-md w-full border-gray-200"
@ -215,83 +217,79 @@ onKeyStroke('Escape', () => {
</NcButton>
</div>
<template v-if="childrenExcludedList?.pageInfo?.totalRows || isChildrenExcludedLoading">
<div class="pb-2 pt-1">
<div class="h-[420px] overflow-scroll nc-scrollbar-md pr-1 cursor-pointer">
<template v-if="isChildrenExcludedLoading">
<div
v-for="(x, i) in Array.from({ length: 10 })"
:key="i"
class="!border-2 flex flex-row gap-2 mb-2 transition-all !rounded-xl relative !border-gray-200 hover:bg-gray-50"
>
<a-skeleton-image class="h-24 w-24 !rounded-xl" />
<div class="flex flex-col m-[.5rem] gap-2 flex-grow justify-center">
<a-skeleton-input class="!w-48 !rounded-xl" active size="small" />
<div class="flex flex-row gap-6 w-10/12">
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<template v-if="childrenExcludedList?.pageInfo?.totalRows">
<div class="overflow-scroll nc-scrollbar-md pr-1 cursor-pointer flex flex-col flex-grow">
<template v-if="isChildrenExcludedLoading">
<div
v-for="(x, i) in Array.from({ length: 10 })"
:key="i"
class="!border-2 flex flex-row gap-2 mb-2 transition-all !rounded-xl relative !border-gray-200 hover:bg-gray-50"
>
<a-skeleton-image class="h-24 w-24 !rounded-xl" />
<div class="flex flex-col m-[.5rem] gap-2 flex-grow justify-center">
<a-skeleton-input class="!w-48 !rounded-xl" active size="small" />
<div class="flex flex-row gap-6 w-10/12">
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
<div class="flex flex-col gap-0.5">
<a-skeleton-input class="!h-4 !w-12" active size="small" />
<a-skeleton-input class="!h-4 !w-24" active size="small" />
</div>
</div>
</div>
</template>
<template v-else>
<LazyVirtualCellComponentsListItem
v-for="(refRow, id) in childrenExcludedList?.list ?? []"
:key="id"
data-testid="nc-excluded-list-item"
:row="refRow"
:fields="fields"
:attachment="attachmentCol"
:related-table-display-value-prop="relatedTableDisplayValueProp"
:is-loading="isChildrenExcludedListLoading[Number.parseInt(id)]"
:is-linked="isChildrenExcludedListLinked[Number.parseInt(id)]"
@expand="
() => {
expandedFormRow = refRow
expandedFormDlg = true
}
"
@click="
() => {
if (isChildrenExcludedListLinked[Number.parseInt(id)]) unlinkRow(refRow, Number.parseInt(id))
else linkRow(refRow, Number.parseInt(id))
}
"
/>
</template>
</div>
</div>
</template>
<template v-else>
<LazyVirtualCellComponentsListItem
v-for="(refRow, id) in childrenExcludedList?.list ?? []"
:key="id"
data-testid="nc-excluded-list-item"
:row="refRow"
:fields="fields"
:attachment="attachmentCol"
:related-table-display-value-prop="relatedTableDisplayValueProp"
:is-loading="isChildrenExcludedListLoading[Number.parseInt(id)]"
:is-linked="isChildrenExcludedListLinked[Number.parseInt(id)]"
@expand="
() => {
expandedFormRow = refRow
expandedFormDlg = true
}
"
@click="
() => {
if (isChildrenExcludedListLinked[Number.parseInt(id)]) unlinkRow(refRow, Number.parseInt(id))
else linkRow(refRow, Number.parseInt(id))
}
"
/>
</template>
</div>
</template>
<div
v-if="!isChildrenExcludedLoading && !childrenExcludedList?.pageInfo?.totalRows"
class="py-2 h-[420px] flex flex-col gap-3 items-center justify-center text-gray-500"
>
<div v-else class="py-2 flex flex-col gap-3 items-center justify-center text-gray-500">
<InboxIcon class="w-16 h-16 mx-auto" />
<p>
{{ $t('msg.thereAreNoRecordsInTable') }}
{{ relatedTableMeta?.title }}
</p>
</div>
<div class="my-2 bg-gray-50 border-gray-50 border-b-2"></div>
<div class="mb-2 bg-gray-50 border-gray-50 border-b-2"></div>
<div class="flex flex-row justify-between bg-white relative pt-1">
<div v-if="!isForm" class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50">
{{ relation === 'bt' ? (row.row[relatedTableMeta?.title] ? '1' : 0) : childrenListCount ?? 'No' }}
{{ $t('objects.records') }} {{ childrenListCount !== 0 ? 'are' : '' }} {{ $t('general.linked') }}
{{ !isMobileMode ? $t('objects.records') : '' }} {{ !isMobileMode && childrenListCount !== 0 ? 'are' : '' }}
{{ $t('general.linked') }}
</div>
<div class="flex absolute items-center py-2 justify-center w-full">
<a-pagination
@ -327,5 +325,11 @@ onKeyStroke('Escape', () => {
use-meta-fields
/>
</Suspense>
</a-modal>
</NcModal>
</template>
<style lang="scss">
.nc-modal-link-record > .ant-modal > .ant-modal-content {
@apply !p-0;
}
</style>

Loading…
Cancel
Save