Browse Source

fix: Improved UI of expanded form

pull/6490/head
Muhammed Mustafa 1 year ago
parent
commit
377832c585
  1. 3
      packages/nc-gui/assets/nc-icons/comment_here.svg
  2. 51
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  3. 256
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  4. 3
      packages/nc-gui/lang/en.json
  5. 4
      packages/nc-gui/utils/iconUtils.ts

3
packages/nc-gui/assets/nc-icons/comment_here.svg

@ -0,0 +1,3 @@
<svg width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Vector" d="M38 19.5001C38.0069 22.1398 37.3901 24.7438 36.2 27.1001C34.7889 29.9235 32.6195 32.2984 29.9349 33.9586C27.2503 35.6188 24.1565 36.4988 21 36.5001C18.3603 36.5069 15.7562 35.8902 13.4 34.7001L2 38.5001L5.8 27.1001C4.60986 24.7438 3.99312 22.1398 4 19.5001C4.00122 16.3436 4.88122 13.2498 6.54144 10.5652C8.20165 7.88055 10.5765 5.71119 13.4 4.30006C15.7562 3.10992 18.3603 2.49317 21 2.50006H22C26.1687 2.73004 30.1061 4.48958 33.0583 7.44177C36.0105 10.394 37.77 14.3314 38 18.5001V19.5001Z" stroke="#6A7184" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 701 B

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

@ -97,11 +97,20 @@ watch(
},
{ immediate: true },
)
// Ignore first line if its the only one
const processedAudit = (log: string) => {
const dotSplit = log.split('.')
if (dotSplit.length === 1) return log
return log.substring(log.indexOf('.') + 1)
}
</script>
<template>
<div class="flex flex-col h-full w-full bg-gray-50 rounded-lg">
<div class="bg-white rounded-t-lg border-gray-200 border-b-1">
<div class="flex flex-col h-full w-full">
<div class="h-16 bg-white rounded-t-lg border-gray-200 border-b-1">
<div class="flex flex-row gap-2 m-2 p-1 bg-gray-100 rounded-lg">
<div
class="tab flex-1 px-4 py-2 transition-all text-gray-600 cursor-pointer rounded-lg"
@ -129,16 +138,21 @@ watch(
</div>
</div>
</div>
<div>
<div v-if="tab === 'comments'" ref="commentsWrapperEl" class="flex flex-col h-[74vh] max-h-[680px]">
<div
class="h-[calc(100%-4rem)]"
:class="{
'pb-2': tab !== 'comments',
}"
>
<div v-if="tab === 'comments'" ref="commentsWrapperEl" class="flex flex-col h-full">
<div v-if="comments.length === 0" class="flex flex-col my-1 text-center justify-center h-full">
<div class="text-center text-3xl text-gray-700">
<MdiChatProcessingOutline />
<GeneralIcon icon="commentHere" />
</div>
<div class="font-bold text-center my-1 text-gray-700">Start a conversation</div>
<div class="font-bold text-center my-6 text-gray-500">{{ $t('activity.startCommenting') }}</div>
</div>
<div v-else class="flex-grow-1 my-2 px-2 space-y-2 overflow-y-scroll nc-scrollbar-md">
<div v-for="log of comments" :key="log.id" class="!last:mb-11">
<div v-else class="flex flex-col h-full p-2 space-y-2 nc-scrollbar-md">
<div v-for="log of comments" :key="log.id">
<div class="bg-white rounded-xl group border-1 gap-2 border-gray-200">
<div class="flex flex-col p-4 gap-3">
<div class="flex justify-between">
@ -153,7 +167,7 @@ watch(
</div>
</div>
</div>
<NcButton
<!-- <NcButton
v-if="log.user === user.email && !editLog"
type="secondary"
class="!px-2 opacity-0 group-hover:opacity-100 transition-all"
@ -161,7 +175,7 @@ watch(
@click="editComment(log)"
>
<Icon class="iconify text-gray-800" icon="lucide:pen" />
</NcButton>
</NcButton> -->
</div>
<textarea
v-if="log.id === editLog?.id"
@ -182,10 +196,7 @@ watch(
</div>
</div>
</div>
<div
v-if="hasEditPermission"
class="mt-1 absolute bottom-0 left-0 right-0 w-[285px] p-2 rounded-b-xl border-t-1 bg-white gap-2 flex"
>
<div v-if="hasEditPermission" class="h-14 p-2 rounded-b-xl border-t-1 bg-white gap-2 flex">
<a-input
v-model:value="comment"
class="!rounded-lg border-1 bg-white !px-4 !py-2 !border-gray-200 nc-comment-box"
@ -193,16 +204,12 @@ watch(
@keyup.enter.prevent="saveComment"
>
</a-input>
<NcButton type="secondary" size="medium" @click="saveComment">
<Icon class="iconify text-gray-800" icon="lucide:send" />
<NcButton type="secondary" size="medium" class="!w-8" :disabled="!comment.length" @click="saveComment">
<GeneralIcon icon="send" />
</NcButton>
</div>
</div>
<div
v-else
ref="commentsWrapperEl"
class="flex flex-col m-1 p-1 h-[74vh] max-h-[680px] overflow-y-scroll nc-scrollbar-md space-y-2"
>
<div v-else ref="commentsWrapperEl" class="flex flex-col h-full pl-1.5 pr-1 pt-1 nc-scrollbar-md space-y-2">
<template v-if="audits.length === 0">
<div class="flex flex-col text-center justify-center h-full">
<div class="text-center text-3xl text-gray-600">
@ -229,7 +236,7 @@ watch(
</div>
</div>
<div class="text-sm font-medium text-gray-700">
{{ log.description.split('.')[1] }}
{{ processedAudit(log.description) }}
</div>
</div>
</div>

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

@ -338,137 +338,95 @@ export default {
</script>
<template>
<a-modal
<NcModal
:key="key"
v-model:visible="isExpanded"
:footer="null"
:width="commentsDrawer && isUIAllowed('commentList') ? 'min(90vw,1280px)' : 'min(90vw,1280px)'"
:width="commentsDrawer && isUIAllowed('commentList') ? 'min(80vw,1280px)' : 'min(80vw,1280px)'"
:body-style="{ padding: 0 }"
:closable="false"
class="nc-drawer-expanded-form max-h-[856px]"
size="large"
class="nc-drawer-expanded-form"
:class="{ active: isExpanded }"
>
<div class="flex flex-shrink-0 w-full items-center nc-expanded-form-header relative pb-2 justify-between">
<div class="flex gap-3">
<div class="flex gap-1">
<NcButton v-if="props.showNextPrevIcons" type="secondary" size="small" class="nc-prev-arrow" @click="$emit('prev')">
<MdiChevronUp class="text-md text-gray-700" />
</NcButton>
<NcButton v-if="!props.lastRow" type="secondary" size="small" class="nc-next-arrow" @click="onNext">
<MdiChevronDown class="text-md text-gray-700" />
</NcButton>
</div>
<div v-if="displayValue" class="flex items-center truncate max-w-32 font-bold text-gray-800 text-xl">
{{ displayValue }}
</div>
<div class="bg-gray-100 px-2 gap-1 flex items-center rounded-md text-gray-800">
<TableIcon class="w-6 h-6 text-sm" />
All {{ meta.title }}
<div class="h-[80vh] max-h-215 flex flex-col">
<div class="flex h-8 flex-shrink-0 w-full items-center nc-expanded-form-header relative mb-4 justify-between">
<div class="flex gap-3">
<div class="flex gap-2">
<NcButton v-if="props.showNextPrevIcons" type="secondary" class="nc-prev-arrow !w-10" @click="$emit('prev')">
<MdiChevronUp class="text-md text-gray-700" />
</NcButton>
<NcButton v-if="!props.lastRow" type="secondary" class="nc-next-arrow !w-10" @click="onNext">
<MdiChevronDown class="text-md text-gray-700" />
</NcButton>
</div>
<div v-if="displayValue" class="flex items-center truncate max-w-32 font-bold text-gray-800 text-xl">
{{ displayValue }}
</div>
<div class="bg-gray-100 px-2 gap-1 flex my-1 items-center rounded-lg text-gray-800 font-medium">
<TableIcon class="w-6 h-6 text-sm" />
All {{ meta.title }}
</div>
</div>
</div>
<div class="flex gap-1">
<NcDropdown v-if="!isNew">
<NcButton type="secondary" size="small" class="nc-expand-form-more-actions">
<MdiMoreVert class="text-md text-gray-700" />
<div class="flex gap-2">
<NcDropdown v-if="!isNew">
<NcButton type="secondary" class="nc-expand-form-more-actions w-10">
<GeneralIcon icon="threeDotVertical" class="text-md text-gray-700" />
</NcButton>
<template #overlay>
<NcMenu>
<NcMenuItem v-if="!isNew" class="text-gray-700" @click="_loadRow()">
<div v-e="['c:row-expand:reload']" class="flex gap-2 items-center">
<component :is="iconMap.reload" class="cursor-pointer" />
{{ $t('general.reload') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('dataEdit') && !isNew"
class="text-gray-700"
@click="!isNew ? onDuplicateRow() : () => {}"
>
<div v-e="['c:row-expand:duplicate']" class="flex gap-2 items-center">
<component :is="iconMap.copy" class="cursor-pointer nc-duplicate-row" />
Duplicate record
</div>
</NcMenuItem>
<a-menu-divider class="my-1" />
<NcMenuItem
v-if="isUIAllowed('dataEdit') && !isNew"
v-e="['c:row-expand:delete']"
class="!text-red-500"
@click="!isNew && onDeleteRowClick()"
>
<component :is="iconMap.delete" class="cursor-pointer nc-delete-row" />
Delete record
</NcMenuItem>
</NcMenu>
</template>
</NcDropdown>
<NcButton type="secondary" class="nc-expand-form-close-btn w-10" @click="onClose">
<GeneralIcon icon="close" class="text-md text-gray-700" />
</NcButton>
<template #overlay>
<NcMenu>
<NcMenuItem v-if="!isNew" class="text-gray-700" @click="_loadRow()">
<div v-e="['c:row-expand:reload']" class="flex gap-2 items-center">
<component :is="iconMap.reload" class="cursor-pointer" />
{{ $t('general.reload') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('dataEdit') && !isNew"
class="text-gray-700"
@click="!isNew ? onDuplicateRow() : () => {}"
>
<div v-e="['c:row-expand:duplicate']" class="flex gap-2 items-center">
<component :is="iconMap.copy" class="cursor-pointer nc-duplicate-row" />
Duplicate record
</div>
</NcMenuItem>
<a-menu-divider class="my-1" />
<NcMenuItem
v-if="isUIAllowed('dataEdit') && !isNew"
v-e="['c:row-expand:delete']"
class="!text-red-500"
@click="!isNew && onDeleteRowClick()"
>
<component :is="iconMap.delete" class="cursor-pointer nc-delete-row" />
Delete record
</NcMenuItem>
</NcMenu>
</template>
</NcDropdown>
<NcButton type="secondary" size="small" class="nc-expand-form-close-btn" @click="onClose">
<MdiClose class="text-md text-gray-700" />
</NcButton>
</div>
</div>
</div>
<div class="flex flex-row w-full gap-4">
<div class="flex w-full flex-col h-[85vh] max-h-[770px] border-1 rounded-xl border-gray-200">
<div
class="flex flex-grow-1 h-full flex-col !pb-12 nc-scrollbar-md overflow-y-scroll items-center w-full rounded-xl bg-white p-4"
>
<div class="flex flex-row h-[calc(100%-6rem)] w-full h-full gap-4">
<div class="flex w-full h-full flex-col border-1 rounded-xl overflow-hidden border-gray-200">
<div
v-for="(col, i) of fields"
v-show="isFormula(col) || !isVirtualCol(col) || !isNew || isLinksOrLTAR(col)"
:key="col.title"
class="mt-2 py-2"
:class="`nc-expand-col-${col.title}`"
:data-testid="`nc-expand-col-${col.title}`"
class="flex flex-grow-1 mt-2 h-[calc(100%-3.5rem)] nc-scrollbar-md flex-col !pb-12 items-center w-full bg-white p-4"
>
<div class="flex items-start flex-row">
<div class="w-[12rem] mt-2.5 scale-110">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" />
<LazySmartsheetHeaderCell v-else :column="col" />
</div>
<LazySmartsheetDivDataCell
v-if="col.title"
:ref="i ? null : (el: any) => (cellWrapperEl = el)"
class="!bg-white rounded-lg !w-[20rem] border-1 border-gray-200 px-1 min-h-[35px] flex items-center relative"
>
<LazySmartsheetVirtualCell v-if="isVirtualCol(col)" v-model="row.row[col.title]" :row="row" :column="col" />
<LazySmartsheetCell
v-else
v-model="row.row[col.title]"
:column="col"
:edit-enabled="true"
:active="true"
:read-only="isPublic"
@update:model-value="changedColumns.add(col.title)"
/>
</LazySmartsheetDivDataCell>
</div>
</div>
<div v-if="hiddenFields.length > 0" class="flex w-full px-12 items-center py-3">
<div class="flex-grow h-px mr-1 bg-gray-100"></div>
<NcButton type="secondary" size="small" class="flex-shrink-1 !text-sm" @click="toggleHiddenFields">
{{ showHiddenFields ? `Hide ${hiddenFields.length} hidden` : `Show ${hiddenFields.length} hidden` }}
{{ hiddenFields.length > 1 ? `fields` : `field` }}
<MdiChevronDown class="ml-1" :class="showHiddenFields ? 'transform rotate-180' : ''" />
</NcButton>
<div class="flex-grow h-px ml-1 bg-gray-100"></div>
</div>
<div v-if="hiddenFields.length > 0 && showHiddenFields" class="mb-3">
<div
v-for="(col, i) of hiddenFields"
v-for="(col, i) of fields"
v-show="isFormula(col) || !isVirtualCol(col) || !isNew || isLinksOrLTAR(col)"
:key="col.title"
class="mt-2 py-2"
:class="`nc-expand-col-${col.title}`"
:data-testid="`nc-expand-col-${col.title}`"
>
<div class="flex flex-row items-start">
<div class="w-[12rem] scale-110 mt-2.5">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" />
<div class="flex items-start flex-row">
<div class="w-[12rem] mt-1.5">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" class="nc-expanded-cell-header" :column="col" />
<LazySmartsheetHeaderCell v-else :column="col" />
<LazySmartsheetHeaderCell v-else class="nc-expanded-cell-header" :column="col" />
</div>
<LazySmartsheetDivDataCell
@ -490,24 +448,69 @@ export default {
</LazySmartsheetDivDataCell>
</div>
</div>
<div v-if="hiddenFields.length > 0" class="flex w-full px-12 items-center py-3">
<div class="flex-grow h-px mr-1 bg-gray-100"></div>
<NcButton type="secondary" size="small" class="flex-shrink-1 !text-sm" @click="toggleHiddenFields">
{{ showHiddenFields ? `Hide ${hiddenFields.length} hidden` : `Show ${hiddenFields.length} hidden` }}
{{ hiddenFields.length > 1 ? `fields` : `field` }}
<MdiChevronDown class="ml-1" :class="showHiddenFields ? 'transform rotate-180' : ''" />
</NcButton>
<div class="flex-grow h-px ml-1 bg-gray-100"></div>
</div>
<div v-if="hiddenFields.length > 0 && showHiddenFields" class="mb-3">
<div
v-for="(col, i) of hiddenFields"
v-show="isFormula(col) || !isVirtualCol(col) || !isNew || isLinksOrLTAR(col)"
:key="col.title"
class="mt-2 py-2"
:class="`nc-expand-col-${col.title}`"
:data-testid="`nc-expand-col-${col.title}`"
>
<div class="flex flex-row items-start">
<div class="w-[12rem] scale-110 mt-2.5">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" />
<LazySmartsheetHeaderCell v-else :column="col" />
</div>
<LazySmartsheetDivDataCell
v-if="col.title"
:ref="i ? null : (el: any) => (cellWrapperEl = el)"
class="!bg-white rounded-lg !w-[20rem] border-1 border-gray-200 px-1 min-h-[35px] flex items-center relative"
>
<LazySmartsheetVirtualCell v-if="isVirtualCol(col)" v-model="row.row[col.title]" :row="row" :column="col" />
<LazySmartsheetCell
v-else
v-model="row.row[col.title]"
:column="col"
:edit-enabled="true"
:active="true"
:read-only="isPublic"
@update:model-value="changedColumns.add(col.title)"
/>
</LazySmartsheetDivDataCell>
</div>
</div>
</div>
</div>
<div
v-if="isUIAllowed('dataEdit')"
class="w-full h-14 border-t-1 border-gray-200 bottom-0 z-10 bg-white flex items-center justify-end p-2"
>
<NcButton type="primary" size="medium" class="nc-expand-form-save-btn" @click="save"> Save </NcButton>
</div>
</div>
<div
v-if="isUIAllowed('dataEdit')"
class="w-full flex-shrink-1 rounded-xl border-t-1 border-gray-200 bottom-0 z-10 bg-white flex justify-end p-2"
v-if="!isNew && commentsDrawer && isUIAllowed('commentList')"
class="nc-comments-drawer border-1 relative border-gray-200 w-[380px] bg-gray-50 rounded-xl min-w-0 overflow-hidden h-full"
:class="{ active: commentsDrawer && isUIAllowed('commentList') }"
>
<NcButton type="primary" size="medium" class="nc-expand-form-save-btn" @click="save"> Save </NcButton>
<LazySmartsheetExpandedFormComments />
</div>
</div>
<div
v-if="!isNew && commentsDrawer && isUIAllowed('commentList')"
class="nc-comments-drawer border-1 relative border-gray-200 w-[380px] bg-gray-50 rounded-lg min-w-0"
:class="{ active: commentsDrawer && isUIAllowed('commentList') }"
>
<LazySmartsheetExpandedFormComments />
</div>
</div>
</a-modal>
</NcModal>
<GeneralModal v-model:visible="showDeleteRowModal" class="!w-[25rem]">
<div class="p-4">
@ -521,4 +524,11 @@ export default {
</GeneralModal>
</template>
<style scoped lang="scss"></style>
<style lang="scss">
.nc-expanded-cell-header > :nth-child(2) {
@apply !text-sm;
}
.nc-expanded-cell-header > :first-child {
@apply !text-xl;
}
</style>

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

@ -566,7 +566,8 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!"
},
"tooltip": {
"saveChanges": "Save changes",

4
packages/nc-gui/utils/iconUtils.ts

@ -76,6 +76,8 @@ import Left from '~icons/material-symbols/chevron-left-rounded'
import Up from '~icons/material-symbols/keyboard-arrow-up-rounded'
import Down from '~icons/material-symbols/keyboard-arrow-down-rounded'
import PhTriangleFill from '~icons/ph/triangle-fill'
import LcSend from '~icons/lucide/send'
import NcCommentHere from '~icons/nc-icons/comment-here'
// Roles
import MaterialSymbolsManageAccountsOutline from '~icons/material-symbols/manage-accounts-outline'
@ -343,6 +345,7 @@ export const iconMap = {
number: h('span', { class: 'material-symbols' }, 'looks_one'),
email: h('span', { class: 'material-symbols' }, 'email'),
sendEmail: h('span', { class: 'material-symbols' }, 'email'),
send: LcSend,
currency: h('span', { class: 'material-symbols' }, 'attach_money'),
percent: h('span', { class: 'material-symbols' }, 'percent'),
decimal: h('span', { class: 'material-symbols' }, 'decimal_increase'),
@ -417,6 +420,7 @@ export const iconMap = {
role_commenter: MdiCommentAccountOutline,
role_viewer: MaterialSymbolsPersonSearchOutline,
role_no_access: MaterialSymbolsBlock,
commentHere: NcCommentHere,
}
export const getMdiIcon = (type: string): any => {

Loading…
Cancel
Save