Browse Source

Merge pull request #8629 from nocodb/nc-chore/design-expanded-record

Nc chore/design expanded record
pull/8640/head
Ramesh Mane 4 weeks ago committed by GitHub
parent
commit
adb08017c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      packages/nc-gui/components/general/Loader.vue
  2. 6
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  3. 66
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  4. 14
      packages/nc-gui/components/smartsheet/header/Menu.vue
  5. 2
      packages/nc-gui/composables/useExpandedFormStore.ts

8
packages/nc-gui/components/general/Loader.vue

@ -2,7 +2,7 @@
import { LoadingOutlined } from '@ant-design/icons-vue'
const props = defineProps<{
size?: 'small' | 'medium' | 'large' | 'xlarge'
size?: 'small' | 'medium' | 'large' | 'xlarge' | 'regular'
loaderClass?: string
}>()
@ -18,17 +18,19 @@ function getFontSize() {
return 'text-xl'
case 'xlarge':
return 'text-3xl'
case 'regular':
return 'text-[16px] leading-4'
}
}
const indicator = h(LoadingOutlined, {
class: `!${getFontSize()} flex flex-row items-center !bg-inherit !hover:bg-inherit !text-inherit ${props.loaderClass}}`,
class: `!${getFontSize()} flex flex-row items-center !bg-inherit !hover:bg-inherit !text-inherit ${props.loaderClass || ''}}`,
spin: true,
})
</script>
<template>
<a-spin class="nc-loader flex flex-row items-center" :indicator="indicator" />
<a-spin class="nc-loader !flex flex-row items-center" :indicator="indicator" />
</template>
<style lang="scss" scoped>

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

@ -175,7 +175,7 @@ watch(commentsWrapperEl, () => {
<div v-for="comment of comments" :key="comment.id" class="nc-comment-item">
<div
:class="{
'hover:bg-gray-50 bg-white': comment.id !== editComment?.id,
'hover:bg-gray-200': comment.id !== editComment?.id,
}"
class="group gap-3 overflow-hidden flex items-start px-3 py-1"
>
@ -313,9 +313,7 @@ watch(commentsWrapperEl, () => {
<a-tab-pane key="audits" class="w-full" :disabled="appInfo.ee">
<template #tab>
<NcTooltip v-if="appInfo.ee" class="tab flex-1">
<template #title>
<span class="!text-base"> Coming soon </span>
</template>
<template #title>{{ $t('title.comingSoon') }}</template>
<div v-e="['c:row-expand:audit']" class="flex items-center gap-2 text-gray-400">
<GeneralIcon icon="audit" class="w-4 h-4" />

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

@ -87,6 +87,11 @@ const { isExpandedFormCommentMode } = storeToRefs(useConfigStore())
// override cell click hook to avoid unexpected behavior at form fields
provide(CellClickHookInj, undefined)
const loadingEmit = (event: 'update:modelValue' | 'cancel' | 'next' | 'prev' | 'createdRecord') => {
emits(event)
isLoading.value = true
}
const fields = computedInject(FieldsInj, (_fields) => {
if (props.useMetaFields) {
return (meta.value.columns ?? []).filter((col) => !isSystemColumn(col))
@ -124,7 +129,6 @@ const {
isNew,
loadRow: _loadRow,
primaryKey,
saveRowAndStay,
row: _row,
save: _save,
loadComments,
@ -240,7 +244,7 @@ const isCloseModalOpen = ref(false)
const discardPreventModal = () => {
// when user click on next or previous button
if (isPreventChangeModalOpen.value) {
emits('next')
loadingEmit('next')
if (_row.value?.rowMeta?.new) emits('cancel')
isPreventChangeModalOpen.value = false
}
@ -259,7 +263,7 @@ const onNext = async () => {
isPreventChangeModalOpen.value = true
return
}
emits('next')
loadingEmit('next')
}
const copyRecordUrl = async () => {
@ -278,7 +282,7 @@ const saveChanges = async () => {
if (isPreventChangeModalOpen.value) {
isUnsavedFormExist.value = false
await save()
emits('next')
loadingEmit('next')
isPreventChangeModalOpen.value = false
}
if (isCloseModalOpen.value) {
@ -313,6 +317,7 @@ provide(IsExpandedFormOpenInj, isExpanded)
const triggerRowLoad = async (rowId?: string) => {
await Promise.allSettled([loadComments(), loadAudits(), _loadRow(rowId)])
isLoading.value = false
}
const cellWrapperEl = ref()
@ -362,7 +367,7 @@ useActiveKeyupListener(
if (!e.altKey) return
if (e.key === 'ArrowLeft') {
e.stopPropagation()
emits('prev')
loadingEmit('prev')
} else if (e.key === 'ArrowRight') {
e.stopPropagation()
onNext()
@ -382,9 +387,6 @@ useActiveKeyupListener(
await save()
reloadHook?.trigger(null)
}
if (!saveRowAndStay.value) {
onClose()
}
} catch (e: any) {
if (isNew.value) {
message.error(`Add row failed: ${await extractSdkResponseErrorMsg(e)}`)
@ -571,7 +573,7 @@ export default {
class="nc-prev-arrow !w-7 !h-7 !text-gray-500 !disabled:text-gray-300"
type="text"
size="xsmall"
@click="$emit('prev')"
@click="loadingEmit('prev')"
>
<GeneralIcon icon="chevronDown" class="transform rotate-180" />
</NcButton>
@ -600,16 +602,6 @@ export default {
'xs:max-w-[calc(100%_-_82px)]': !isNew,
}"
>
<div v-if="meta.title" class="flex items-center gap-2 px-2 py-1 rounded-lg bg-gray-100 text-gray-800">
<GeneralTableIcon :meta="meta" class="!text-gray-800 !mx-0" />
<NcTooltip class="truncate text-sm max-w-[100px] xs:(max-w-[82px]) align-middle" show-on-truncate-only>
<template #title>
{{ meta.title }}
</template>
<span class="font-weight-500 truncate text-sm">{{ meta.title }}</span>
</NcTooltip>
</div>
<div
v-if="row.rowMeta?.new || props.newRecordHeader"
class="flex items-center truncate font-bold text-gray-800 text-base overflow-hidden"
@ -642,24 +634,22 @@ export default {
<div class="xs:px-1">{{ newRecordSubmitBtnText ?? 'Save Record' }}</div>
</NcButton>
</NcTooltip>
<NcButton
v-if="!isNew && rowId && !isMobileMode"
:disabled="isLoading"
class="!<lg:hidden text-gray-700 !h-7 !px-2"
type="text"
size="xsmall"
@click="copyRecordUrl()"
>
<div
v-e="['c:row-expand:copy-url']"
data-testid="nc-expanded-form-copy-url"
class="flex gap-2 items-center text-small"
<NcTooltip>
<template #title> {{ isRecordLinkCopied ? $t('labels.copiedRecordURL') : $t('labels.copyRecordURL') }} </template>
<NcButton
v-if="!isNew && rowId && !isMobileMode"
:disabled="isLoading"
class="!<lg:hidden text-gray-700 !h-7 !w-7"
type="text"
size="xsmall"
@click="copyRecordUrl()"
>
<component :is="iconMap.check" v-if="isRecordLinkCopied" class="cursor-pointer nc-duplicate-row" />
<component :is="iconMap.copy" v-else class="cursor-pointer nc-duplicate-row" />
{{ isRecordLinkCopied ? $t('labels.copiedRecordURL') : $t('labels.copyRecordURL') }}
</div>
</NcButton>
<div v-e="['c:row-expand:copy-url']" data-testid="nc-expanded-form-copy-url" class="flex items-center">
<component :is="iconMap.check" v-if="isRecordLinkCopied" class="cursor-pointer nc-duplicate-row h-4 w-4" />
<component :is="iconMap.copy" v-else class="cursor-pointer nc-duplicate-row h-4 w-4" />
</div>
</NcButton>
</NcTooltip>
<NcDropdown v-if="!isNew && rowId && !isMobileMode" placement="bottomRight">
<NcButton type="text" size="xsmall" class="nc-expand-form-more-actions !w-7 !h-7" :disabled="isLoading">
<GeneralIcon icon="threeDotVertical" class="text-md" :class="isLoading ? 'text-gray-300' : 'text-gray-700'" />
@ -871,7 +861,7 @@ export default {
<div
v-if="isUIAllowed('dataEdit')"
class="w-full flex items-center justify-end px-2 py-[9px] xs:(p-0 gap-x-4 justify-between)"
class="w-full flex items-center justify-end px-2 xs:(p-0 gap-x-4 justify-between)"
:class="{
'xs(border-t-1 border-gray-200)': !isNew,
}"
@ -896,7 +886,7 @@ export default {
class="flex gap-2 items-center"
data-testid="nc-expanded-form-copy-url"
>
<component :is="iconMap.link" class="cursor-pointer nc-duplicate-row" />
<component :is="iconMap.copy" class="cursor-pointer nc-duplicate-row" />
{{ $t('labels.copyRecordURL') }}
</div>
</NcMenuItem>

14
packages/nc-gui/components/smartsheet/header/Menu.vue

@ -43,7 +43,10 @@ const { gridViewCols } = useViewColumnsOrThrow()
const { fieldsToGroupBy, groupByLimit } = useViewGroupByOrThrow(view)
const isLoading = ref<'' | 'hideOrShow' | 'setDisplay'>('')
const setAsDisplayValue = async () => {
isLoading.value = 'setDisplay'
try {
const currentDisplayValue = meta?.value?.columns?.find((f) => f.pv)
@ -91,6 +94,8 @@ const setAsDisplayValue = async () => {
})
} catch (e) {
message.error(t('msg.error.primaryColumnUpdateFailed'))
} finally {
isLoading.value = ''
}
}
@ -233,6 +238,7 @@ const addColumn = async (before = false) => {
// hide the field in view
const hideOrShowField = async () => {
isLoading.value = 'hideOrShow'
const gridViewColumnList = (await $api.dbViewColumn.list(view.value?.id as string)).list
const currentColumn = gridViewColumnList.find((f) => f.fk_column_id === column!.value.id)
@ -288,6 +294,8 @@ const hideOrShowField = async () => {
},
scope: defineViewScope({ view: view.value }),
})
isLoading.value = ''
}
const handleDelete = () => {
@ -383,7 +391,8 @@ const filterOrGroupByThisField = (event: SmartsheetStoreEvents) => {
<a-divider v-if="!column?.pv" class="!my-0" />
<NcMenuItem v-if="!column?.pv" @click="hideOrShowField">
<div v-e="['a:field:hide']" class="nc-column-insert-before nc-header-menu-item">
<component :is="isHiddenCol ? iconMap.eye : iconMap.eyeSlash" class="text-gray-700 !w-3.75 !h-3.75" />
<GeneralLoader v-if="isLoading === 'hideOrShow'" size="regular" />
<component v-else :is="isHiddenCol ? iconMap.eye : iconMap.eyeSlash" class="text-gray-700 !w-4 !h-4" />
<!-- Hide Field -->
{{ isHiddenCol ? $t('general.showField') : $t('general.hideField') }}
</div>
@ -393,7 +402,8 @@ const filterOrGroupByThisField = (event: SmartsheetStoreEvents) => {
@click="setAsDisplayValue"
>
<div class="nc-column-set-primary nc-header-menu-item item">
<GeneralIcon icon="star" class="text-gray-700 !w-4.25 !h-4.25" />
<GeneralLoader v-if="isLoading === 'setDisplay'" size="regular" />
<GeneralIcon v-else icon="star" class="text-gray-700 !w-4.25 !h-4.25" />
<!-- todo : tooltip -->
<!-- Set as Display value -->

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

@ -193,7 +193,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
await $api.utils.commentRow({
fk_model_id: meta.value?.id as string,
row_id: rowId,
comment: `${comment.value}`,
comment: `${comment.value}`.replace(/(<br \/>)+$/g, ''),
})
reloadTrigger?.trigger()

Loading…
Cancel
Save