Browse Source

chore(gui-v2): linting and other corrections

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/3025/head
Pranav C 2 years ago
parent
commit
04db065153
  1. 33
      packages/nc-gui-v2/components.d.ts
  2. 2
      packages/nc-gui-v2/components/smartsheet-column/FormulaOptions.vue
  3. 4
      packages/nc-gui-v2/components/smartsheet-column/SelectOptions.vue
  4. 1
      packages/nc-gui-v2/components/smartsheet-header/Menu.vue
  5. 89
      packages/nc-gui-v2/components/smartsheet/Grid.vue
  6. 1
      packages/nc-gui-v2/components/smartsheet/Row.vue
  7. 2
      packages/nc-gui-v2/components/smartsheet/expanded-form/Comments.vue
  8. 2
      packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue
  9. 2
      packages/nc-gui-v2/components/smartsheet/expanded-form/index.vue
  10. 8
      packages/nc-gui-v2/components/virtual-cell/BelongsTo.vue
  11. 29
      packages/nc-gui-v2/components/virtual-cell/HasMany.vue
  12. 24
      packages/nc-gui-v2/components/virtual-cell/ManyToMany.vue
  13. 12
      packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue
  14. 2
      packages/nc-gui-v2/composables/useLTARStore.ts
  15. 8
      packages/nc-gui-v2/composables/useSmartsheetRowStore.ts
  16. 30
      packages/nc-gui-v2/package-lock.json
  17. 11
      packages/nc-gui-v2/utils/dataUtils.ts

33
packages/nc-gui-v2/components.d.ts vendored

@ -74,21 +74,14 @@ declare module '@vue/runtime-core' {
MaterialSymbolsChevronLeftRounded: typeof import('~icons/material-symbols/chevron-left-rounded')['default'] MaterialSymbolsChevronLeftRounded: typeof import('~icons/material-symbols/chevron-left-rounded')['default']
MaterialSymbolsChevronRightRounded: typeof import('~icons/material-symbols/chevron-right-rounded')['default'] MaterialSymbolsChevronRightRounded: typeof import('~icons/material-symbols/chevron-right-rounded')['default']
MaterialSymbolsFileCopyOutline: typeof import('~icons/material-symbols/file-copy-outline')['default'] MaterialSymbolsFileCopyOutline: typeof import('~icons/material-symbols/file-copy-outline')['default']
CilFullscreen: typeof import('~icons/cil/fullscreen')['default']
CilFullscreenExit: typeof import('~icons/cil/fullscreen-exit')['default']
IcOutlineInsertDriveFile: typeof import('~icons/ic/outline-insert-drive-file')['default']
IcRoundKeyboardArrowDown: typeof import('~icons/ic/round-keyboard-arrow-down')['default']
MaterialSymbolsAttachFile: typeof import('~icons/material-symbols/attach-file')['default']
MaterialSymbolsFileCopyOutline: typeof import('~icons/material-symbols/file-copy-outline')['default']
MaterialSymbolsMenu: typeof import('~icons/material-symbols/menu')['default'] MaterialSymbolsMenu: typeof import('~icons/material-symbols/menu')['default']
MaterialSymbolsTranslate: typeof import('~icons/material-symbols/translate')['default'] MaterialSymbolsTranslate: typeof import('~icons/material-symbols/translate')['default']
MdiAccountCircle: typeof import('~icons/mdi/account-circle')['default']
MdiAccountGroup: typeof import('~icons/mdi/account-group')['default'] MdiAccountGroup: typeof import('~icons/mdi/account-group')['default']
MdiApi: typeof import('~icons/mdi/api')['default'] MdiApi: typeof import('~icons/mdi/api')['default']
MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default'] MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default']
MdiArrowLeftBold: typeof import('~icons/mdi/arrow-left-bold')['default']
MaterialSymbolsTranslate: typeof import('~icons/material-symbols/translate')['default']
MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default']
MdiArrowExpandIcon: typeof import('~icons/mdi/arrow-expand-icon')['default'] MdiArrowExpandIcon: typeof import('~icons/mdi/arrow-expand-icon')['default']
MdiArrowLeftBold: typeof import('~icons/mdi/arrow-left-bold')['default']
MdiAt: typeof import('~icons/mdi/at')['default'] MdiAt: typeof import('~icons/mdi/at')['default']
MdiCalculator: typeof import('~icons/mdi/calculator')['default'] MdiCalculator: typeof import('~icons/mdi/calculator')['default']
MdiCardsHeart: typeof import('~icons/mdi/cards-heart')['default'] MdiCardsHeart: typeof import('~icons/mdi/cards-heart')['default']
@ -103,10 +96,6 @@ declare module '@vue/runtime-core' {
MdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default'] MdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default']
MdiDiscord: typeof import('~icons/mdi/discord')['default'] MdiDiscord: typeof import('~icons/mdi/discord')['default']
MdiDotsHorizontal: typeof import('~icons/mdi/dots-horizontal')['default'] MdiDotsHorizontal: typeof import('~icons/mdi/dots-horizontal')['default']
MdiCloseCircle: typeof import('~icons/mdi/close-circle')['default']
MdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
MdiContentSave: typeof import('~icons/mdi/content-save')['default']
MdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default']
MdiDotsVertical: typeof import('~icons/mdi/dots-vertical')['default'] MdiDotsVertical: typeof import('~icons/mdi/dots-vertical')['default']
MdiDownload: typeof import('~icons/mdi/download')['default'] MdiDownload: typeof import('~icons/mdi/download')['default']
MdiDrag: typeof import('~icons/mdi/drag')['default'] MdiDrag: typeof import('~icons/mdi/drag')['default']
@ -119,15 +108,9 @@ declare module '@vue/runtime-core' {
MdiHeart: typeof import('~icons/mdi/heart')['default'] MdiHeart: typeof import('~icons/mdi/heart')['default']
MdiHook: typeof import('~icons/mdi/hook')['default'] MdiHook: typeof import('~icons/mdi/hook')['default']
MdiInformation: typeof import('~icons/mdi/information')['default'] MdiInformation: typeof import('~icons/mdi/information')['default']
MdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
MdiLink: typeof import('~icons/mdi/link')['default'] MdiLink: typeof import('~icons/mdi/link')['default']
MdiLinkVariantRemove: typeof import('~icons/mdi/link-variant-remove')['default'] MdiLinkVariantRemove: typeof import('~icons/mdi/link-variant-remove')['default']
MdiDownload: typeof import('~icons/mdi/download')['default']
MdiDrag: typeof import('~icons/mdi/drag')['default']
MdiEyeOffOutline: typeof import('~icons/mdi/eye-off-outline')['default']
MdiFlag: typeof import('~icons/mdi/flag')['default']
MdiHeart: typeof import('~icons/mdi/heart')['default']
MdiHook: typeof import('~icons/mdi/hook')['default']
MdiLinkVariantRemove: typeof import('~icons/mdi/link-variant-remove')['default']
MdiLogout: typeof import('~icons/mdi/logout')['default'] MdiLogout: typeof import('~icons/mdi/logout')['default']
MdiMagnify: typeof import('~icons/mdi/magnify')['default'] MdiMagnify: typeof import('~icons/mdi/magnify')['default']
MdiMenuDown: typeof import('~icons/mdi/menu-down')['default'] MdiMenuDown: typeof import('~icons/mdi/menu-down')['default']
@ -138,26 +121,18 @@ declare module '@vue/runtime-core' {
MdiOperator: typeof import('~icons/mdi/operator')['default'] MdiOperator: typeof import('~icons/mdi/operator')['default']
MdiPlus: typeof import('~icons/mdi/plus')['default'] MdiPlus: typeof import('~icons/mdi/plus')['default']
MdiPlusOutline: typeof import('~icons/mdi/plus-outline')['default'] MdiPlusOutline: typeof import('~icons/mdi/plus-outline')['default']
MdiMagnify: typeof import('~icons/mdi/magnify')['default']
MdiMenuDown: typeof import('~icons/mdi/menu-down')['default']
MdiMoonFull: typeof import('~icons/mdi/moon-full')['default']
MdiOpenInNew: typeof import('~icons/mdi/open-in-new')['default']
MdiPlus: typeof import('~icons/mdi/plus')['default']
MdiReload: typeof import('~icons/mdi/reload')['default'] MdiReload: typeof import('~icons/mdi/reload')['default']
MdiSearch: typeof import('~icons/mdi/search')['default'] MdiSearch: typeof import('~icons/mdi/search')['default']
MdiShieldLockOutline: typeof import('~icons/mdi/shield-lock-outline')['default'] MdiShieldLockOutline: typeof import('~icons/mdi/shield-lock-outline')['default']
MdiSlack: typeof import('~icons/mdi/slack')['default'] MdiSlack: typeof import('~icons/mdi/slack')['default']
MdiStar: typeof import('~icons/mdi/star')['default'] MdiStar: typeof import('~icons/mdi/star')['default']
MdiStore: typeof import('~icons/mdi/store')['default'] MdiStore: typeof import('~icons/mdi/store')['default']
MdiTableArrowRight: typeof import('~icons/mdi/table-arrow-right')['default']
MdiTableBorder: typeof import('~icons/mdi/table-border')['default'] MdiTableBorder: typeof import('~icons/mdi/table-border')['default']
MdiThumbUp: typeof import('~icons/mdi/thumb-up')['default'] MdiThumbUp: typeof import('~icons/mdi/thumb-up')['default']
MdiTrashCan: typeof import('~icons/mdi/trash-can')['default'] MdiTrashCan: typeof import('~icons/mdi/trash-can')['default']
MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default'] MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default']
MdiXml: typeof import('~icons/mdi/xml')['default'] MdiXml: typeof import('~icons/mdi/xml')['default']
MdiStar: typeof import('~icons/mdi/star')['default']
MdiTableArrowRight: typeof import('~icons/mdi/table-arrow-right')['default']
MdiThumbUp: typeof import('~icons/mdi/thumb-up')['default']
MdiXml: typeof import('~icons/mdi/xml')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
} }

2
packages/nc-gui-v2/components/smartsheet-column/FormulaOptions.vue

@ -659,7 +659,7 @@ onMounted(() => {
</div> </div>
</div> </div>
<div v-if="item.type === 'column'" class="float-right mr-5 -mt-2"> <div v-if="item.type === 'column'" class="float-right mr-5 -mt-2">
<a-badge-ribbon :text="item.uidt" color="gray"/> <a-badge-ribbon :text="item.uidt" color="gray" />
</div> </div>
</a-col> </a-col>
</div> </div>

4
packages/nc-gui-v2/components/smartsheet-column/SelectOptions.vue

@ -86,7 +86,7 @@ watch(inputs, () => {
<template> <template>
<div class="w-full"> <div class="w-full">
<draggable :list="options" item-key="id" handle=".nc-child-draggable-icon"> <Draggable :list="options" item-key="id" handle=".nc-child-draggable-icon">
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="flex py-1 align-center"> <div class="flex py-1 align-center">
<MdiDragIcon small class="nc-child-draggable-icon handle" /> <MdiDragIcon small class="nc-child-draggable-icon handle" />
@ -105,7 +105,7 @@ watch(inputs, () => {
<div class="flex align-center"><MdiPlusIcon /><span class="flex-auto">Add option</span></div> <div class="flex align-center"><MdiPlusIcon /><span class="flex-auto">Add option</span></div>
</a-button> </a-button>
</template> </template>
</draggable> </Draggable>
</div> </div>
</template> </template>

1
packages/nc-gui-v2/components/smartsheet-header/Menu.vue

@ -1,5 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onClickOutside } from '@vueuse/core'
import { Modal } from 'ant-design-vue' import { Modal } from 'ant-design-vue'
import { inject } from 'vue' import { inject } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'

89
packages/nc-gui-v2/components/smartsheet/Grid.vue

@ -337,7 +337,7 @@ const expandForm = (row: Row, state: Record<string, any>) => {
<tbody> <tbody>
<SmartsheetRow v-for="(row, rowIndex) of data" :key="rowIndex" :row="row"> <SmartsheetRow v-for="(row, rowIndex) of data" :key="rowIndex" :row="row">
<template #default="{ state }"> <template #default="{ state }">
<tr class="nc-grid-row"> <tr class="nc-grid-row group">
<td key="row-index" class="caption nc-grid-cell"> <td key="row-index" class="caption nc-grid-cell">
<div class="align-center flex w-[80px]"> <div class="align-center flex w-[80px]">
<div class="group-hover:hidden" :class="{ hidden: row.rowMeta.selected }">{{ rowIndex + 1 }}</div> <div class="group-hover:hidden" :class="{ hidden: row.rowMeta.selected }">{{ rowIndex + 1 }}</div>
@ -352,7 +352,8 @@ const expandForm = (row: Row, state: Record<string, any>) => {
class="py-1 px-3 rounded-full text-[11px]" class="py-1 px-3 rounded-full text-[11px]"
:style="{ backgroundColor: enumColor.light[row.rowMeta.commentCount % enumColor.light.length] }" :style="{ backgroundColor: enumColor.light[row.rowMeta.commentCount % enumColor.light.length] }"
@click="expandForm(row, state)" @click="expandForm(row, state)"
>{{ row.rowMeta.commentCount }}</span> >{{ row.rowMeta.commentCount }}</span
>
<div class="cursor-pointer flex items-center border-1 active:ring rounded p-1 hover:bg-primary/10"> <div class="cursor-pointer flex items-center border-1 active:ring rounded p-1 hover:bg-primary/10">
<MdiArrowExpand <MdiArrowExpand
class="select-none transform hover:(text-pink-500 scale-120)" class="select-none transform hover:(text-pink-500 scale-120)"
@ -361,48 +362,47 @@ const expandForm = (row: Row, state: Record<string, any>) => {
</div> </div>
</div> </div>
</div> </div>
</div> </td>
</td> <td
<td v-for="(columnObj, colIndex) of fields"
v-for="(columnObj, colIndex) of fields" :ref="cellRefs.set"
:ref="cellRefs.set" :key="columnObj.id"
:key="columnObj.id" class="cell relative cursor-pointer nc-grid-cell"
class="cell relative cursor-pointer nc-grid-cell" :class="{
:class="{ active: !isPublicView && selected.col === colIndex && selected.row === rowIndex,
active: !isPublicView && selected.col === colIndex && selected.row === rowIndex, }"
}" :data-key="rowIndex + columnObj.id"
:data-key="rowIndex + columnObj.id" :data-col="columnObj.id"
:data-col="columnObj.id" :data-title="columnObj.title"
:data-title="columnObj.title" @click="selectCell(rowIndex, colIndex)"
@click="selectCell(rowIndex, colIndex)" @dblclick="makeEditable(row, columnObj)"
@dblclick="makeEditable(row, columnObj)" @contextmenu="contextMenuTarget = { row: rowIndex, col: colIndex }"
@contextmenu="contextMenuTarget = { row: rowIndex, col: colIndex }" >
> <div class="w-full h-full">
<div class="w-full h-full"> <SmartsheetVirtualCell
<SmartsheetVirtualCell v-if="isVirtualCol(columnObj)"
v-if="isVirtualCol(columnObj)" v-model="row.row[columnObj.title]"
v-model="row.row[columnObj.title]" :column="columnObj"
:column="columnObj" :active="selected.col === colIndex && selected.row === rowIndex"
:active="selected.col === colIndex && selected.row === rowIndex" :row="row"
:row="row" @navigate="onNavigate"
@navigate="onNavigate" />
/>
<SmartsheetCell
<SmartsheetCell v-else
v-else v-model="row.row[columnObj.title]"
v-model="row.row[columnObj.title]" :column="columnObj"
:column="columnObj" :edit-enabled="editEnabled && selected.col === colIndex && selected.row === rowIndex"
:edit-enabled="editEnabled && selected.col === colIndex && selected.row === rowIndex" :row-index="rowIndex"
:row-index="rowIndex" :active="selected.col === colIndex && selected.row === rowIndex"
:active="selected.col === colIndex && selected.row === rowIndex" @update:edit-enabled="editEnabled = false"
@update:edit-enabled="editEnabled = false" @save="updateOrSaveRow(row, columnObj.title)"
@save="updateOrSaveRow(row, columnObj.title)" @navigate="onNavigate"
@navigate="onNavigate" @cancel="editEnabled = false"
@cancel="editEnabled = false" />
/> </div>
</div> </td>
</td> </tr>
</tr>
</template> </template>
</SmartsheetRow> </SmartsheetRow>
@ -442,6 +442,7 @@ const expandForm = (row: Row, state: Record<string, any>) => {
</div> </div>
<SmartsheetPagination /> <SmartsheetPagination />
<SmartsheetExpandedForm <SmartsheetExpandedForm
v-if="expandedFormRow && expandedFormDlg" v-if="expandedFormRow && expandedFormDlg"
v-model="expandedFormDlg" v-model="expandedFormDlg"

1
packages/nc-gui-v2/components/smartsheet/Row.vue

@ -8,7 +8,6 @@ interface Props {
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits(['expandForm', 'selectCell', 'updateOrSaveRow', 'navigate'])
const row = toRef(props, 'row') const row = toRef(props, 'row')
const { meta } = useSmartsheetStoreOrThrow() const { meta } = useSmartsheetStoreOrThrow()

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

@ -3,7 +3,7 @@ import { nextTick, useExpandedFormStoreOrThrow } from '#imports'
import { enumColor, timeAgo } from '~/utils' import { enumColor, timeAgo } from '~/utils'
import MdiAccountIcon from '~icons/mdi/account-circle' import MdiAccountIcon from '~icons/mdi/account-circle'
const { loadCommentsAndLogs, commentsAndLogs, isCommentsLoading, commentsOnly, saveComment, isYou, comment, row } = const { loadCommentsAndLogs, commentsAndLogs, isCommentsLoading, commentsOnly, saveComment, isYou, comment } =
useExpandedFormStoreOrThrow() useExpandedFormStoreOrThrow()
const commentsWrapperEl = ref<HTMLDivElement>() const commentsWrapperEl = ref<HTMLDivElement>()

2
packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue

@ -7,7 +7,7 @@ import MdiDoorClosed from '~icons/mdi/door-closed'
const emit = defineEmits(['cancel']) const emit = defineEmits(['cancel'])
const { meta } = useSmartsheetStoreOrThrow() const { meta } = useSmartsheetStoreOrThrow()
const { commentsDrawer, row, primaryValue, save: _save } = useExpandedFormStoreOrThrow() const { commentsDrawer, primaryValue, save: _save } = useExpandedFormStoreOrThrow()
const { isNew, syncLTARRefs } = useSmartsheetRowStoreOrThrow() const { isNew, syncLTARRefs } = useSmartsheetRowStoreOrThrow()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()

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

@ -8,7 +8,7 @@ import Header from './Header.vue'
import { NOCO } from '~/lib' import { NOCO } from '~/lib'
import { extractPkFromRow } from '~/utils' import { extractPkFromRow } from '~/utils'
import { useNuxtApp } from '#app' import { useNuxtApp } from '#app'
import { useProvideSmartsheetStore, useSmartsheetStoreOrThrow } from '~/composables' import { useProvideSmartsheetStore } from '~/composables'
import type { Row } from '~/composables' import type { Row } from '~/composables'
import { useProvideExpandedFormStore } from '~/composables/useExpandedFormStore' import { useProvideExpandedFormStore } from '~/composables/useExpandedFormStore'
import { FieldsInj, IsFormInj, MetaInj } from '~/context' import { FieldsInj, IsFormInj, MetaInj } from '~/context'

8
packages/nc-gui-v2/components/virtual-cell/BelongsTo.vue

@ -4,10 +4,8 @@ import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue' import ItemChip from './components/ItemChip.vue'
import ListItems from './components/ListItems.vue' import ListItems from './components/ListItems.vue'
import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore' import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore'
import { useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context'
import { inject, ref, useProvideLTARStore } from '#imports' import { inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj,IsFormInj, ColumnInj, ReloadViewDataHookInj, RowInj } from '~/context' import { CellValueInj, ColumnInj, ReloadViewDataHookInj, RowInj } from '~/context'
const column = inject(ColumnInj) const column = inject(ColumnInj)
@ -21,10 +19,8 @@ const active = false
const listItemsDlg = ref(false) const listItemsDlg = ref(false)
const isForm = inject(IsFormInj)
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()
const { relatedTableMeta, loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore( const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>, column as Ref<Required<ColumnType>>,
row, row,
isNew, isNew,

29
packages/nc-gui-v2/components/virtual-cell/HasMany.vue

@ -7,8 +7,6 @@ import ListItems from './components/ListItems.vue'
import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore' import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore'
import { computed, inject, ref, useProvideLTARStore } from '#imports' import { computed, inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context' import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context'
import { useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context'
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -20,14 +18,12 @@ const reloadTrigger = inject(ReloadViewDataHookInj)!
const isForm = inject(IsFormInj) const isForm = inject(IsFormInj)
const isForm = inject(IsFormInj)
const listItemsDlg = ref(false) const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()
const { relatedTableMeta, loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore( const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>, column as Ref<Required<ColumnType>>,
row, row,
isNew, isNew,
@ -56,7 +52,6 @@ const cells = computed(() =>
}, [] as any[]), }, [] as any[]),
) )
const unlinkRef = async (rec: Record<string, any>) => { const unlinkRef = async (rec: Record<string, any>) => {
if (isNew.value) { if (isNew.value) {
removeLTARRef(rec, column?.value as ColumnType) removeLTARRef(rec, column?.value as ColumnType)
@ -71,12 +66,7 @@ const unlinkRef = async (rec: Record<string, any>) => {
<template v-if="!isForm"> <template v-if="!isForm">
<div class="chips flex align-center img-container flex-grow hm-items flex-nowrap min-w-0 overflow-hidden"> <div class="chips flex align-center img-container flex-grow hm-items flex-nowrap min-w-0 overflow-hidden">
<template v-if="cells"> <template v-if="cells">
<ItemChip <ItemChip v-for="(cell, i) of cells" :key="i" :item="ch" :value="cell.value" @unlink="unlinkRef(cell.item)" />
v-for="(cell, i) of cells"
:key="i"
:item="ch"
:value="cell.value"
@unlink="unlinkRef(cell.item)" />
<span v-if="cellValue?.length === 10" class="caption pointer ml-1 grey--text" @click="childListDlg = true" <span v-if="cellValue?.length === 10" class="caption pointer ml-1 grey--text" @click="childListDlg = true"
>more... >more...
</span> </span>
@ -87,14 +77,19 @@ const unlinkRef = async (rec: Record<string, any>) => {
class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500"
@click="childListDlg = true" @click="childListDlg = true"
/> />
<MdiPlus <MdiPlus class="select-none text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="listItemsDlg = true" />
class="select-none text-sm nc-action-icon text-gray-500/50 hover:text-gray-500"
@click="listItemsDlg = true"
/>
</div> </div>
</template> </template>
<ListItems v-model="listItemsDlg" /> <ListItems v-model="listItemsDlg" />
<ListChildItems v-model="childListDlg" @attach-record="() => { childListDlg = false; listItemsDlg = true }" /> <ListChildItems
v-model="childListDlg"
@attach-record="
() => {
childListDlg = false
listItemsDlg = true
}
"
/>
</div> </div>
</template> </template>

24
packages/nc-gui-v2/components/virtual-cell/ManyToMany.vue

@ -5,10 +5,8 @@ import ItemChip from './components/ItemChip.vue'
import ListChildItems from './components/ListChildItems.vue' import ListChildItems from './components/ListChildItems.vue'
import ListItems from './components/ListItems.vue' import ListItems from './components/ListItems.vue'
import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore' import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore'
import { useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context'
import { computed, inject, ref, useProvideLTARStore } from '#imports' import { computed, inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, ReloadViewDataHookInj,IsFormInj, RowInj } from '~/context' import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context'
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -55,8 +53,6 @@ const cells = computed(() =>
}, [] as any[]), }, [] as any[]),
) )
const unlinkRef = async (rec: Record<string, any>) => { const unlinkRef = async (rec: Record<string, any>) => {
if (isNew.value) { if (isNew.value) {
removeLTARRef(rec, column?.value as ColumnType) removeLTARRef(rec, column?.value as ColumnType)
@ -71,13 +67,7 @@ const unlinkRef = async (rec: Record<string, any>) => {
<template v-if="!isForm"> <template v-if="!isForm">
<div class="chips flex align-center img-container flex-grow hm-items flex-nowrap min-w-0 overflow-hidden"> <div class="chips flex align-center img-container flex-grow hm-items flex-nowrap min-w-0 overflow-hidden">
<template v-if="cells"> <template v-if="cells">
<ItemChip <ItemChip v-for="(cell, i) of cells" :key="i" :item="ch" :value="cell.value" @unlink="unlinkRef(cell.item)" />
v-for="(cell, i) of cells"
:key="i"
:item="ch"
:value="cell.value"
@unlink="unlinkRef(cell.item)"
/>
<span v-if="value?.length === 10" class="caption pointer ml-1 grey--text" @click="childListDlg = true">more... </span> <span v-if="value?.length === 10" class="caption pointer ml-1 grey--text" @click="childListDlg = true">more... </span>
</template> </template>
@ -92,7 +82,15 @@ const unlinkRef = async (rec: Record<string, any>) => {
<ListItems v-model="listItemsDlg" /> <ListItems v-model="listItemsDlg" />
<ListChildItems v-model="childListDlg" @attach-record="() => { childListDlg = false; listItemsDlg = true; }" /> <ListChildItems
v-model="childListDlg"
@attach-record="
() => {
childListDlg = false
listItemsDlg = true
}
"
/>
</div> </div>
</template> </template>

12
packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue

@ -1,12 +1,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import { watchEffect } from '@vue/runtime-core'
import { Modal } from 'ant-design-vue' import { Modal } from 'ant-design-vue'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { useLTARStoreOrThrow, useVModel } from '#imports' import { useLTARStoreOrThrow, useVModel, watch } from '#imports'
import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore' import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore'
import { ColumnInj, IsFormInj } from '~/context' import { ColumnInj, IsFormInj } from '~/context'
import { IsFormInj } from '~/context'
import { useLTARStoreOrThrow, useVModel, watch } from '#imports'
const props = defineProps<{ modelValue?: boolean }>() const props = defineProps<{ modelValue?: boolean }>()
const emit = defineEmits(['update:modelValue', 'attachRecord']) const emit = defineEmits(['update:modelValue', 'attachRecord'])
@ -62,7 +59,7 @@ const expandedFormRow = ref()
<div class="flex mb-4 align-center gap-2"> <div class="flex mb-4 align-center gap-2">
<div class="flex-1" /> <div class="flex-1" />
<MdiReload v-if="!isForm" class="cursor-pointer text-gray-500" @click="loadChildrenList" /> <MdiReload v-if="!isForm" class="cursor-pointer text-gray-500" @click="loadChildrenList" />
<a-button type="primary" class="!text-xs" size="small" @click="emit('attachRecord')"> <a-button type="primary" class="!text-xs" size="small" @click="emit('attachRecord')">
<div class="flex align-center gap-1"> <div class="flex align-center gap-1">
@ -91,7 +88,10 @@ const expandedFormRow = ref()
</div> </div>
<div class="flex-1"></div> <div class="flex-1"></div>
<div class="flex gap-2"> <div class="flex gap-2">
<MdiLinkVariantRemove class="text-xs text-grey hover:(!text-red-500) cursor-pointer" @click.stop="unlinkRow(row)" /> <MdiLinkVariantRemove
class="text-xs text-grey hover:(!text-red-500) cursor-pointer"
@click.stop="unlinkRow(row)"
/>
<MdiDeleteOutline <MdiDeleteOutline
class="text-xs text-grey hover:(!text-red-500) cursor-pointer" class="text-xs text-grey hover:(!text-red-500) cursor-pointer"
@click.stop="deleteRelatedRow(row)" @click.stop="deleteRelatedRow(row)"

2
packages/nc-gui-v2/composables/useLTARStore.ts

@ -13,7 +13,7 @@ interface DataApiResponse {
/** Store for managing Link to another cells */ /** Store for managing Link to another cells */
const [useProvideLTARStore, useLTARStore] = useInjectionState( const [useProvideLTARStore, useLTARStore] = useInjectionState(
(column: Ref<Required<ColumnType>>, row?: Ref<Row>, isNewRow: ComputedRef<boolean>, reloadData = () => {}) => { (column: Ref<Required<ColumnType>>, row?: Ref<Row>, isNewRow: ComputedRef<boolean> | Ref<boolean>, reloadData = () => {}) => {
// state // state
const { metas, getMeta } = useMetas() const { metas, getMeta } = useMetas()
const { project } = useProject() const { project } = useProject()

8
packages/nc-gui-v2/composables/useSmartsheetRowStore.ts

@ -20,7 +20,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
const state = ref<Record<string, Record<string, any> | Record<string, any>[] | null>>({}) const state = ref<Record<string, Record<string, any> | Record<string, any>[] | null>>({})
// getters // getters
const isNew = computed(() => row.value?.rowMeta?.new) const isNew = computed(() => row.value?.rowMeta?.new ?? false)
// actions // actions
const addLTARRef = async (value: Record<string, any>, column: ColumnType) => { const addLTARRef = async (value: Record<string, any>, column: ColumnType) => {
@ -54,7 +54,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
column.title as string, column.title as string,
relatedRowId, relatedRowId,
) )
} catch (e) { } catch (e: any) {
notification.error({ notification.error({
message: 'Linking failed', message: 'Linking failed',
description: await extractSdkResponseErrorMsg(e), description: await extractSdkResponseErrorMsg(e),
@ -77,10 +77,10 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
for (const relatedRow of relatedRows) { for (const relatedRow of relatedRows) {
await linkRecord(id, extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]), column, colOptions.type) await linkRecord(id, extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]), column, colOptions.type)
} }
} else if (isBt && state.value?.[column.title!]) { } else if (isBt && state?.value?.[column.title!]) {
await linkRecord( await linkRecord(
id, id,
extractPkFromRow(state.value?.[column.title!], relatedTableMeta.columns as ColumnType[]), extractPkFromRow(state.value?.[column.title!] as Record<string, any>, relatedTableMeta.columns as ColumnType[]),
column, column,
colOptions.type, colOptions.type,
) )

30
packages/nc-gui-v2/package-lock.json generated

@ -22,6 +22,7 @@
"unique-names-generator": "^4.7.1", "unique-names-generator": "^4.7.1",
"url": "^0.11.0", "url": "^0.11.0",
"util": "^0.12.4", "util": "^0.12.4",
"vue-dompurify-html": "^3.0.0",
"vue-i18n": "^9.1.10", "vue-i18n": "^9.1.10",
"vue-toastification": "^2.0.0-rc.5", "vue-toastification": "^2.0.0-rc.5",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
@ -5389,6 +5390,11 @@
"url": "https://github.com/fb55/domhandler?sponsor=1" "url": "https://github.com/fb55/domhandler?sponsor=1"
} }
}, },
"node_modules/dompurify": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz",
"integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g=="
},
"node_modules/domutils": { "node_modules/domutils": {
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
@ -14534,6 +14540,17 @@
"bundle-runner": "^0.0.1" "bundle-runner": "^0.0.1"
} }
}, },
"node_modules/vue-dompurify-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/vue-dompurify-html/-/vue-dompurify-html-3.0.0.tgz",
"integrity": "sha512-S6PMeJU7S3w0TnxMWWd4iydc7oPdOER1GmW9rsgiRwHvcw+nUi2v6BgERcFBULlM+x6PXsfu5P/Rm4reVvWH5A==",
"dependencies": {
"dompurify": "^2.3.4"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-eslint-parser": { "node_modules/vue-eslint-parser": {
"version": "9.0.3", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz",
@ -19300,6 +19317,11 @@
"domelementtype": "^2.2.0" "domelementtype": "^2.2.0"
} }
}, },
"dompurify": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz",
"integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g=="
},
"domutils": { "domutils": {
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
@ -26034,6 +26056,14 @@
"bundle-runner": "^0.0.1" "bundle-runner": "^0.0.1"
} }
}, },
"vue-dompurify-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/vue-dompurify-html/-/vue-dompurify-html-3.0.0.tgz",
"integrity": "sha512-S6PMeJU7S3w0TnxMWWd4iydc7oPdOER1GmW9rsgiRwHvcw+nUi2v6BgERcFBULlM+x6PXsfu5P/Rm4reVvWH5A==",
"requires": {
"dompurify": "^2.3.4"
}
},
"vue-eslint-parser": { "vue-eslint-parser": {
"version": "9.0.3", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz",

11
packages/nc-gui-v2/utils/dataUtils.ts

@ -1,8 +1,11 @@
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
export const extractPkFromRow = (row: Record<string, any>, columns: ColumnType[]) => { export const extractPkFromRow = (row: Record<string, any>, columns: ColumnType[]) => {
return columns return (
?.filter((c) => c.pk) row &&
.map((c) => row?.[c.title as string]) columns
.join('___') ?.filter((c) => c.pk)
.map((c) => row?.[c.title as string])
.join('___')
)
} }

Loading…
Cancel
Save