Browse Source

chore(gui-v2): fix types in components

pull/3044/head
braks 2 years ago
parent
commit
704b641ed0
  1. 8
      packages/nc-gui-v2/components/cell/Currency.vue
  2. 59
      packages/nc-gui-v2/components/cell/Json.vue
  3. 6
      packages/nc-gui-v2/components/cell/Url.vue
  4. 5
      packages/nc-gui-v2/components/cell/attachment/Modal.vue
  5. 14
      packages/nc-gui-v2/components/dashboard/settings/UIAcl.vue
  6. 11
      packages/nc-gui-v2/components/general/Language.vue
  7. 6
      packages/nc-gui-v2/components/smartsheet-column/AdvancedOptions.vue
  8. 38
      packages/nc-gui-v2/components/smartsheet-column/RollupOptions.vue
  9. 54
      packages/nc-gui-v2/components/smartsheet-toolbar/FieldsMenu.vue
  10. 8
      packages/nc-gui-v2/components/smartsheet/sidebar/MenuTop.vue
  11. 49
      packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue
  12. 18
      packages/nc-gui-v2/components/virtual-cell/BelongsTo.vue
  13. 25
      packages/nc-gui-v2/components/virtual-cell/HasMany.vue
  14. 24
      packages/nc-gui-v2/components/virtual-cell/ManyToMany.vue
  15. 22
      packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue
  16. 13
      packages/nc-gui-v2/components/virtual-cell/components/ListItems.vue
  17. 8
      packages/nc-gui-v2/components/webhook/List.vue
  18. 1
      packages/nc-gui-v2/composables/useColumnCreateStore.ts

8
packages/nc-gui-v2/components/cell/Currency.vue

@ -26,14 +26,12 @@ const currencyMeta = computed(() => {
})
const currency = computed(() => {
if (!vModel.value) return null
try {
return isNaN(vModel.value)
return !vModel.value || isNaN(vModel.value)
? vModel.value
: new Intl.NumberFormat(currencyMeta?.value?.currency_locale || 'en-US', {
: new Intl.NumberFormat(currencyMeta.value.currency_locale || 'en-US', {
style: 'currency',
currency: currencyMeta?.value?.currency_code || 'USD',
currency: currencyMeta.value.currency_code || 'USD',
}).format(vModel.value)
} catch (e) {
return vModel.value

59
packages/nc-gui-v2/components/cell/Json.vue

@ -1,9 +1,7 @@
<script setup lang="ts">
import { Modal as AModal } from 'ant-design-vue'
import Editor from '~/components/monaco/Editor.vue'
import FullScreenIcon from '~icons/cil/fullscreen'
import FullScreenExitIcon from '~icons/cil/fullscreen-exit'
import { inject } from '#imports'
import { computed, inject, ref, useVModel, watch } from '#imports'
import { EditModeInj } from '~/context'
interface Props {
@ -20,27 +18,29 @@ const emits = defineEmits<Emits>()
const editEnabled = inject(EditModeInj, ref(false))
let vModel = $(useVModel(props, 'modelValue', emits))
const vModel = useVModel(props, 'modelValue', emits)
let localValueState = $ref<string | undefined>(undefined)
let localValue = $(
computed<string | undefined>({
get: () => localValueState,
set: (val: undefined | string | Record<string, any>) => {
localValueState = typeof val === 'object' ? JSON.stringify(val, null, 2) : val
},
}),
)
const localValueState = ref<string | undefined>()
const localValue = computed<string | Record<string, any> | undefined>({
get: () => localValueState.value,
set: (val: undefined | string | Record<string, any>) => {
localValueState.value = typeof val === 'object' ? JSON.stringify(val, null, 2) : val
},
})
let error = $ref<string | undefined>()
let error = $ref<string | undefined>(undefined)
let isExpanded = $ref(false)
const clear = () => {
error = undefined
isExpanded = false
editEnabled.value = false
localValue = vModel
localValue.value = vModel.value
}
const formatJson = (json: string) => {
@ -53,22 +53,26 @@ const formatJson = (json: string) => {
const onSave = () => {
isExpanded = false
editEnabled.value = false
localValue = localValue ? formatJson(localValue) : localValue
vModel = localValue
localValue.value = localValue ? formatJson(localValue.value as string) : localValue
vModel.value = localValue.value
}
watch(
$$(vModel),
vModel,
(val) => {
localValue = val
localValue.value = val
},
{ immediate: true },
)
watch($$(localValue), (val) => {
watch(localValue, (val) => {
try {
JSON.parse(val)
JSON.parse(val as string)
error = undefined
} catch (e: any) {
error = e
@ -77,7 +81,8 @@ watch($$(localValue), (val) => {
watch(editEnabled, () => {
isExpanded = false
localValue = vModel
localValue.value = vModel.value
})
</script>
@ -86,16 +91,20 @@ watch(editEnabled, () => {
<div v-if="editEnabled" class="flex flex-col w-full">
<div class="flex flex-row justify-between pt-1 pb-2">
<a-button type="text" size="small" @click="isExpanded = !isExpanded">
<FullScreenExitIcon v-if="isExpanded" class="h-2.5" />
<FullScreenIcon v-else class="h-2.5" />
<CilFullscreenExit v-if="isExpanded" class="h-2.5" />
<CilFullscreen v-else class="h-2.5" />
</a-button>
<div class="flex flex-row">
<a-button type="text" size="small" :onclick="clear"><div class="text-xs">Cancel</div></a-button>
<a-button type="primary" size="small" :disabled="!!error || localValue === vModel">
<div class="text-xs" :onclick="onSave">Save</div>
</a-button>
</div>
</div>
<Editor
:model-value="localValue"
class="min-w-full w-80"
@ -104,10 +113,12 @@ watch(editEnabled, () => {
:disable-deep-compare="true"
@update:model-value="localValue = $event"
/>
<span v-if="error" class="text-xs w-full py-1 text-red-500">
{{ error.toString() }}
</span>
</div>
<span v-else>{{ vModel }}</span>
</component>
</template>

6
packages/nc-gui-v2/components/cell/Url.vue

@ -12,14 +12,14 @@ const { modelValue: value } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const column = inject(ColumnInj)
const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj, ref(false))
const vModel = computed({
get: () => value,
set: (val) => {
if (!column?.value?.meta?.validate || (val && isValidURL(val))) {
if (!column.value.meta?.validate || (val && isValidURL(val))) {
emit('update:modelValue', val)
}
},
@ -32,7 +32,7 @@ const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
<template>
<input v-if="editEnabled" :ref="focus" v-model="vModel" class="outline-none" @blur="editEnabled = false" />
<nuxt-link v-else-if="isValid" class="py-2 underline hover:opacity-75" :to="value" target="_blank">{{ value }}</nuxt-link>
<nuxt-link v-else-if="isValid" class="py-2 underline hover:opacity-75" :to="value || ''" target="_blank">{{ value }}</nuxt-link>
<span v-else>{{ value }}</span>
</template>

5
packages/nc-gui-v2/components/cell/attachment/Modal.vue

@ -4,11 +4,6 @@ import { useAttachmentCell } from './utils'
import { useSortable } from './sort'
import { ref, useDropZone, useUIPermission } from '#imports'
import { isImage, openLink } from '~/utils'
import MaterialSymbolsAttachFile from '~icons/material-symbols/attach-file'
import MdiCloseCircle from '~icons/mdi/close-circle'
import MdiDownload from '~icons/mdi/download'
import MaterialSymbolsFileCopyOutline from '~icons/material-symbols/file-copy-outline'
import IcOutlineInsertDriveFile from '~icons/ic/outline-insert-drive-file'
const { isUIAllowed } = useUIPermission()

14
packages/nc-gui-v2/components/dashboard/settings/UIAcl.vue

@ -1,18 +1,20 @@
<script setup lang="ts">
import { useToast } from 'vue-toastification'
import { viewIcons } from '~/utils/viewUtils'
import { h, useNuxtApp, useProject } from '#imports'
import MdiReload from '~icons/mdi/reload'
import MdiContentSave from '~icons/mdi/content-save'
import MdiMagnify from '~icons/mdi/magnify'
import { viewIcons } from '~/utils'
import { computed, h, useNuxtApp, useProject } from '#imports'
const { $api, $e } = useNuxtApp()
const { project } = useProject()
const toast = useToast()
const roles = $ref<string[]>(['editor', 'commenter', 'viewer'])
let isLoading = $ref(false)
let tables = $ref<any[]>([])
const searchInput = $ref('')
const filteredTables = computed(() =>
@ -30,7 +32,7 @@ async function loadTableList() {
isLoading = true
// TODO includeM2M
tables = await $api.project.modelVisibilityList(project.value?.id, {
includeM2M: '',
includeM2M: true,
})
} catch (e) {
console.error(e)

11
packages/nc-gui-v2/components/general/Language.vue

@ -1,15 +1,13 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n'
import MaterialSymbolsTranslate from '~icons/material-symbols/translate'
import { Language } from '~/lib/enums'
import { Language } from '~/lib'
import { useNuxtApp } from '#imports'
const { $e, $state } = useNuxtApp()
const { availableLocales = ['en'], locale } = useI18n()
const languages = $computed(() => {
return availableLocales.sort()
})
const languages = $computed(() => availableLocales.sort())
const isRtlLang = $computed(() => ['fa'].includes($state.lang.value))
@ -38,10 +36,11 @@ onMounted(() => {
<template #activator="{ props }">
<MaterialSymbolsTranslate class="md:text-xl cursor-pointer nc-menu-translate" @click="props.onClick" />
</template>
<v-list class="scrollbar min-w-50 max-h-90vh overflow-auto !py-0 dark:(!bg-gray-800 !text-white)">
<v-list-item
v-for="lang of languages"
:key="lang.value"
:key="lang"
:class="lang === locale ? '!bg-primary/10 text-primary dark:(!bg-gray-700 !text-secondary)' : ''"
class="!min-h-8 group"
:value="lang"

6
packages/nc-gui-v2/components/smartsheet-column/AdvancedOptions.vue

@ -1,8 +1,8 @@
<script setup lang="ts">
import type { UITypes } from 'nocodb-sdk'
import { useColumnCreateStoreOrThrow } from '#imports'
import { computed, useColumnCreateStoreOrThrow } from '#imports'
const { formState, validateInfos, sqlUi, onDataTypeChange, onAlter } = useColumnCreateStoreOrThrow()
const { formState, validateInfos, sqlUi, onDataTypeChange, onAlter } = useColumnCreateStoreOrThrow()!
// todo: 2nd argument of `getDataTypeListForUiType` is missing!
const dataTypes = computed(() => sqlUi?.value?.getDataTypeListForUiType(formState.value as { uidt: UITypes }, '' as any))
@ -84,5 +84,3 @@ formState.value.au = !!formState.value.au
</a-form-item>
</div>
</template>
<style scoped></style>

38
packages/nc-gui-v2/components/smartsheet-column/RollupOptions.vue

@ -1,12 +1,15 @@
<script setup lang="ts">
import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk'
import { useColumnCreateStoreOrThrow } from '#imports'
import { inject, useColumnCreateStoreOrThrow, useMetas, useProject } from '#imports'
import { MetaInj } from '~/context'
const { formState, validateInfos, onDataTypeChange, setAdditionalValidations } = $(useColumnCreateStoreOrThrow())
const { tables } = $(useProject())
const meta = $(inject(MetaInj))
const { metas } = $(useMetas())
const { tables } = $(useProject())!
const meta = $(inject(MetaInj)!)
const { metas } = $(useMetas())!
setAdditionalValidations({
fk_relation_column_id: [{ required: true, message: 'Required' }],
@ -40,22 +43,25 @@ const refTables = $computed(() => {
return []
}
return meta.columns
.filter((c) => c.uidt === UITypes.LinkToAnotherRecord && c.colOptions.type !== 'bt' && !c.system)
.map((c) => ({
col: c.colOptions,
column: c,
...tables.find((t) => t.id === c.colOptions.fk_related_model_id),
}))
return (
meta.columns
?.filter((c: any) => c.uidt === UITypes.LinkToAnotherRecord && c.colOptions.type !== 'bt' && !c.system)
.map((c) => ({
col: c.colOptions,
column: c,
...tables.find((t) => t.id === (c.colOptions as any)?.fk_related_model_id),
})) ?? []
)
})
const columns = $computed(() => {
const selectedTable = refTables.find((t) => t.column.id === formState.fk_relation_column_id)
if (!selectedTable?.id) {
return []
}
return metas[selectedTable.id].columns.filter((c) => !isVirtualCol(c.uidt) && !isSystemColumn(c))
return metas[selectedTable.id].columns.filter((c: any) => !isVirtualCol(c.uidt) && !isSystemColumn(c))
})
</script>
@ -64,7 +70,7 @@ const columns = $computed(() => {
<div class="w-full flex flex-row space-x-2">
<a-form-item class="flex w-1/2 pb-2" :label="$t('labels.childTable')" v-bind="validateInfos.fk_relation_column_id">
<a-select v-model:value="formState.fk_relation_column_id" size="small" @change="onDataTypeChange">
<a-select-option v-for="(table, index) in refTables" :key="index" :value="table.col.fk_column_id">
<a-select-option v-for="(table, index) of refTables" :key="index" :value="table.col.fk_column_id">
<div class="flex flex-row items-center space-x-0.5">
<div class="font-weight-bold text-xs">{{ table.column.title }}</div>
<div class="text-[0.45rem]">({{ relationNames[table.col.type] }} {{ table.title || table.table_name }})</div>
@ -79,7 +85,7 @@ const columns = $computed(() => {
size="small"
@change="onDataTypeChange"
>
<a-select-option v-for="(column, index) in columns" :key="index" :value="column.id">
<a-select-option v-for="(column, index) of columns" :key="index" :value="column.id">
{{ column.title }}
</a-select-option>
</a-select>
@ -87,12 +93,10 @@ const columns = $computed(() => {
</div>
<a-form-item label="Aggregate function" v-bind="validateInfos.rollup_function">
<a-select v-model:value="formState.rollup_function" size="small" @change="onDataTypeChange">
<a-select-option v-for="(func, index) in aggrFunctionsList" :key="index" :value="func.value">
<a-select-option v-for="(func, index) of aggrFunctionsList" :key="index" :value="func.value">
{{ func.text }}
</a-select-option>
</a-select>
</a-form-item>
</div>
</template>
<style scoped></style>

54
packages/nc-gui-v2/components/smartsheet-toolbar/FieldsMenu.vue

@ -1,21 +1,11 @@
<script setup lang="ts">
import { computed, inject } from 'vue'
import Draggable from 'vuedraggable'
import { ActiveViewInj, FieldsInj, IsLockedInj, MetaInj, ReloadViewDataHookInj } from '~/context'
import { useViewColumns } from '#imports'
import MdiMenuDownIcon from '~icons/mdi/menu-down'
import MdiEyeIcon from '~icons/mdi/eye-off-outline'
import MdiDragIcon from '~icons/mdi/drag'
const { fieldsOrder, coverImageField, modelValue } = defineProps<{
coverImageField?: string
fieldsOrder?: string[]
modelValue?: Record<string, boolean>
}>()
const meta = inject(MetaInj)
const activeView = inject(ActiveViewInj)
const reloadDataHook = inject(ReloadViewDataHookInj)
import { computed, inject, useNuxtApp, useViewColumns, watch } from '#imports'
const meta = inject(MetaInj)!
const activeView = inject(ActiveViewInj)!
const reloadDataHook = inject(ReloadViewDataHookInj)!
const rootFields = inject(FieldsInj)
const isLocked = inject(IsLockedInj)
@ -31,46 +21,45 @@ const {
showAll,
hideAll,
saveOrUpdate,
// sortedFields,
} = useViewColumns(activeView, meta, false, () => reloadDataHook?.trigger())
} = useViewColumns(activeView, meta, false, () => reloadDataHook.trigger())
watch(
() => (activeView?.value as any)?.id,
() => (activeView.value as any)?.id,
async (newVal, oldVal) => {
if (newVal !== oldVal && meta?.value) {
if (newVal !== oldVal && meta.value) {
await loadViewColumns()
}
},
{ immediate: true },
)
watch(
() => sortedAndFilteredFields.value,
sortedAndFilteredFields,
(v) => {
if (rootFields) rootFields.value = v || []
},
{ immediate: true },
)
const isAnyFieldHidden = computed(() => {
return fields?.value?.some((f) => !(!showSystemFields && f.system) && !f.show)
})
const isAnyFieldHidden = computed(() => fields.value?.some((field) => !(!showSystemFields && field.system) && !field.show))
const onMove = (event: { moved: { newIndex: number } }) => {
// todo : sync with server
if (!fields?.value) return
if (!fields.value) return
if (fields.value.length < 2) return
if (fields?.value.length - 1 === event.moved.newIndex) {
if (fields.value.length - 1 === event.moved.newIndex) {
fields.value[event.moved.newIndex].order = (fields.value[event.moved.newIndex - 1].order || 1) + 1
} else if (event.moved.newIndex === 0) {
fields.value[event.moved.newIndex].order = (fields?.value[1].order || 1) / 2
fields.value[event.moved.newIndex].order = (fields.value[1].order || 1) / 2
} else {
fields.value[event.moved.newIndex].order =
((fields?.value[event.moved.newIndex - 1].order || 1) + (fields?.value[event.moved.newIndex + 1].order || 1)) / 2
// );
((fields.value[event.moved.newIndex - 1].order || 1) + (fields.value[event.moved.newIndex + 1].order || 1)) / 2
}
saveOrUpdate(fields.value[event.moved.newIndex], event.moved.newIndex)
$e('a:fields:reorder')
}
</script>
@ -80,11 +69,12 @@ const onMove = (event: { moved: { newIndex: number } }) => {
<div :class="{ 'nc-badge nc-active-btn': isAnyFieldHidden }">
<a-button v-t="['c:fields']" class="nc-fields-menu-btn nc-toolbar-btn" :disabled="isLocked" size="small">
<div class="flex align-center gap-1">
<!-- <v-icon small class="mr-1" color="#777"> mdi-eye-off-outline </v-icon> -->
<MdiEyeIcon class="text-grey"></MdiEyeIcon>
<MdiEyeOffOutline class="text-grey" />
<!-- Fields -->
<span class="text-xs text-capitalize">{{ $t('objects.fields') }}</span>
<MdiMenuDownIcon class="text-grey"></MdiMenuDownIcon>
<MdiMenuDown class="text-grey" />
</div>
</a-button>
</div>
@ -101,7 +91,7 @@ const onMove = (event: { moved: { newIndex: number } }) => {
<span class="text-xs">{{ field.title }}</span>
</a-checkbox>
<div class="flex-1" />
<MdiDragIcon class="cursor-move" />
<MdiDrag class="cursor-move" />
</div>
</template>
</Draggable>

8
packages/nc-gui-v2/components/smartsheet/sidebar/MenuTop.vue

@ -6,9 +6,9 @@ import { notification } from 'ant-design-vue'
import type { Ref } from 'vue'
import Sortable from 'sortablejs'
import RenameableMenuItem from './RenameableMenuItem.vue'
import { inject, onMounted, ref, useApi, useTabs, watch } from '#imports'
import { inject, onMounted, ref, useApi, useRouter, watch } from '#imports'
import { extractSdkResponseErrorMsg } from '~/utils'
import { ActiveViewInj, MetaInj, ViewListInj } from '~/context'
import { ActiveViewInj, ViewListInj } from '~/context'
interface Emits {
(event: 'openModal', data: { type: ViewTypes; title?: string }): void
@ -22,10 +22,6 @@ const activeView = inject(ActiveViewInj, ref())
const views = inject<Ref<any[]>>(ViewListInj, ref([]))
const meta = inject(MetaInj)
const { addTab } = useTabs()
const { api } = useApi()
const router = useRouter()

49
packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue

@ -1,13 +1,8 @@
<script setup lang="ts">
import { useToast } from 'vue-toastification'
import { useClipboard } from '@vueuse/core'
import OpenInNewIcon from '~icons/mdi/open-in-new'
import { dashboardUrl } from '~/utils/urlUtils'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
import MdiReload from '~icons/mdi/reload'
import DownIcon from '~icons/ic/round-keyboard-arrow-down'
import ContentCopyIcon from '~icons/mdi/content-copy'
import MdiXmlIcon from '~icons/mdi/xml'
import { onMounted, useClipboard, useNuxtApp, useProject } from '#imports'
import { dashboardUrl, extractSdkResponseErrorMsg } from '~/utils'
const toast = useToast()
interface ShareBase {
@ -22,9 +17,13 @@ enum ShareBaseRole {
}
const { $api, $e } = useNuxtApp()
let base = $ref<null | ShareBase>(null)
const showEditBaseDropdown = $ref(false)
const { project } = useProject()
const { copy } = useClipboard()
const url = $computed(() => (base && base.uuid ? `${dashboardUrl()}#/nc/base/${base.uuid}` : null))
@ -33,7 +32,8 @@ const loadBase = async () => {
try {
if (!project.value.id) return
const res = await $api.project.sharedBaseGet(project.value.id)
// todo: result is missing roles in return-type
const res: any = await $api.project.sharedBaseGet(project.value.id)
base = {
uuid: res.uuid,
url: res.url,
@ -41,6 +41,7 @@ const loadBase = async () => {
}
} catch (e: any) {
console.error(e)
toast.error(await extractSdkResponseErrorMsg(e))
}
}
@ -49,16 +50,19 @@ const createShareBase = async (role = ShareBaseRole.Viewer) => {
try {
if (!project.value.id) return
const res = await $api.project.sharedBaseUpdate(project.value.id, {
// todo: returns void?
const res: any = await $api.project.sharedBaseUpdate(project.value.id, {
roles: role,
})
base = res || {}
base.role = role
base = res ?? {}
base!.role = role
} catch (e: any) {
console.error(e)
toast.error(await extractSdkResponseErrorMsg(e))
}
$e('a:shared-base:enable', { role })
}
@ -83,10 +87,13 @@ const recreate = async () => {
const sharedBase = await $api.project.sharedBaseCreate(project.value.id, {
roles: base?.role || ShareBaseRole.Viewer,
})
const newBase = sharedBase || {}
base = { ...newBase, role: base?.role }
} catch (e: any) {
console.error(e)
toast.error(await extractSdkResponseErrorMsg(e))
}
@ -96,7 +103,8 @@ const recreate = async () => {
const copyUrl = async () => {
if (!url) return
copy(url)
await copy(url)
toast.success('Copied shareable base url to clipboard!')
$e('c:shared-base:copy-url')
@ -135,7 +143,8 @@ onMounted(() => {
<template>
<div class="flex flex-col w-full">
<div class="flex flex-row items-center space-x-0.5 pl-2 h-[0.8rem]">
<OpenInNewIcon />
<MdiOpenInNew />
<div class="text-xs">Shared Base Link</div>
</div>
<div v-if="base?.uuid" class="flex flex-row mt-2 bg-red-50 py-4 mx-1 px-2 items-center rounded-sm w-full justify-between">
@ -157,7 +166,7 @@ onMounted(() => {
</template>
<a-button type="text" class="!rounded-md mr-1 -mt-1.5 h-[1rem]" @click="copyUrl">
<template #icon>
<ContentCopyIcon class="flex mx-auto text-gray-600" />
<MdiContentCopy class="flex mx-auto text-gray-600" />
</template>
</a-button>
</a-tooltip>
@ -167,7 +176,7 @@ onMounted(() => {
</template>
<a-button type="text" class="!rounded-md mr-1 -mt-1.5 h-[1rem]" @click="navigateToSharedBase">
<template #icon>
<OpenInNewIcon class="flex mx-auto text-gray-600" />
<MdiOpenInNew class="flex mx-auto text-gray-600" />
</template>
</a-button>
</a-tooltip>
@ -177,7 +186,7 @@ onMounted(() => {
</template>
<a-button type="text" class="!rounded-md mr-1 -mt-1.5 h-[1rem]" @click="generateEmbeddableIframe">
<template #icon>
<MdiXmlIcon class="flex mx-auto text-gray-600" />
<MdiXml class="flex mx-auto text-gray-600" />
</template>
</a-button>
</a-tooltip>
@ -190,7 +199,7 @@ onMounted(() => {
<div class="flex flex-row items-center space-x-2">
<div v-if="base?.uuid">Anyone with the link</div>
<div v-else>Disable shared base</div>
<DownIcon class="h-[1rem]" />
<IcRoundKeyboardArrowDown class="h-[1rem]" />
</div>
</a-button>
@ -207,7 +216,7 @@ onMounted(() => {
<a-select v-if="base?.uuid" v-model:value="base.role" class="flex">
<template #suffixIcon>
<div class="flex flex-row">
<DownIcon class="text-black -mt-0.5 h-[1rem]" />
<IcRoundKeyboardArrowDown class="text-black -mt-0.5 h-[1rem]" />
</div>
</template>
<a-select-option
@ -225,5 +234,3 @@ onMounted(() => {
</div>
</div>
</template>
<style scoped></style>

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

@ -3,23 +3,29 @@ import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue'
import ListItems from './components/ListItems.vue'
import { useProvideLTARStore } from '#imports'
import { inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, ReloadViewDataHookInj, RowInj } from '~/context'
import MdiExpandIcon from '~icons/mdi/arrow-expand'
const column = inject(ColumnInj)
const reloadTrigger = inject(ReloadViewDataHookInj)
const reloadTrigger = inject(ReloadViewDataHookInj)!
const cellValue = inject(CellValueInj)
const row = inject(RowInj)
const active = false
const localState = null
const listItemsDlg = ref(false)
const { relatedTableMeta, loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>,
row,
() => reloadTrigger?.trigger(),
reloadTrigger.trigger,
)
await loadRelatedTableMeta()
</script>
@ -31,7 +37,7 @@ await loadRelatedTableMeta()
</template>
</div>
<div class="flex-1 flex justify-end gap-1 min-h-[30px] align-center">
<MdiExpandIcon
<MdiArrowExpand
class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 select-none group-hover:(text-gray-500)"
@click="listItemsDlg = true"
/>

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

@ -4,24 +4,27 @@ import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue'
import ListChildItems from './components/ListChildItems.vue'
import ListItems from './components/ListItems.vue'
import { useProvideLTARStore } from '#imports'
import { inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, ReloadViewDataHookInj, RowInj } from '~/context'
import MdiExpandIcon from '~icons/mdi/arrow-expand'
import MdiPlusIcon from '~icons/mdi/plus'
const column = inject(ColumnInj)
const cellValue = inject(CellValueInj)
const row = inject(RowInj)
const reloadTrigger = inject(ReloadViewDataHookInj)
const column = inject(ColumnInj)!
const cellValue = inject(CellValueInj)!
const row = inject(RowInj)!
const reloadTrigger = inject(ReloadViewDataHookInj)!
const listItemsDlg = ref(false)
const childListDlg = ref(false)
const { relatedTableMeta, loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>,
row,
() => reloadTrigger?.trigger(),
reloadTrigger.trigger,
)
await loadRelatedTableMeta()
</script>
@ -34,11 +37,11 @@ await loadRelatedTableMeta()
</template>
</div>
<div class="flex-grow flex justify-end gap-1 min-h-[30px] align-center">
<MdiExpandIcon
<MdiArrowExpand
class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500"
@click="childListDlg = true"
/>
<MdiPlusIcon class="select-none text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="listItemsDlg = true" />
<MdiPlus class="select-none text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="listItemsDlg = true" />
</div>
<ListItems v-model="listItemsDlg" />
<ListChildItems v-model="childListDlg" @attach-record=";(childListDlg = false), (listItemsDlg = true)" />

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

@ -4,23 +4,25 @@ import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue'
import ListChildItems from './components/ListChildItems.vue'
import ListItems from './components/ListItems.vue'
import { useProvideLTARStore } from '#imports'
import { inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, ReloadViewDataHookInj, RowInj } from '~/context'
import MdiExpandIcon from '~icons/mdi/arrow-expand'
import MdiPlusIcon from '~icons/mdi/plus'
const column = inject(ColumnInj)
const row = inject(RowInj)
const cellValue = inject(CellValueInj)
const reloadTrigger = inject(ReloadViewDataHookInj)
const column = inject(ColumnInj)!
const row = inject(RowInj)!
const cellValue = inject(CellValueInj)!
const reloadTrigger = inject(ReloadViewDataHookInj)!
const listItemsDlg = ref(false)
const childListDlg = ref(false)
const { relatedTableMeta, loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>,
row,
() => reloadTrigger?.trigger(),
reloadTrigger.trigger,
)
await loadRelatedTableMeta()
@ -37,8 +39,8 @@ await loadRelatedTableMeta()
</template>
</div>
<div class="flex-1 flex justify-end gap-1 min-h-[30px] align-center">
<MdiExpandIcon class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="childListDlg = true" />
<MdiPlusIcon class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="listItemsDlg = true" />
<MdiArrowExpand class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="childListDlg = true" />
<MdiPlus class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500" @click="listItemsDlg = true" />
</div>
<ListItems v-model="listItemsDlg" />
<ListChildItems v-model="childListDlg" @attach-record=";(childListDlg = false), (listItemsDlg = true)" />

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

@ -1,10 +1,8 @@
<script lang="ts" setup>
import { useLTARStoreOrThrow, useVModel } from '#imports'
import MdiReloadIcon from '~icons/mdi/reload'
import MdiDeleteIcon from '~icons/mdi/delete-outline'
import MdiUnlinkIcon from '~icons/mdi/link-variant-remove'
import { useLTARStoreOrThrow, useVModel, watch } from '#imports'
const props = defineProps<{ modelValue?: boolean }>()
const emit = defineEmits(['update:modelValue', 'attachRecord'])
const vModel = useVModel(props, 'modelValue', emit)
@ -20,14 +18,15 @@ const {
getRelatedTableRowId,
} = useLTARStoreOrThrow()
watch(vModel, () => {
if (vModel.value) {
watch(vModel, (nextVal) => {
if (nextVal) {
loadChildrenList()
}
})
const unlinkRow = async (row: Record<string, any>) => {
await unlink(row)
await loadChildrenList()
}
</script>
@ -36,12 +35,13 @@ const unlinkRow = async (row: Record<string, any>) => {
<a-modal v-model:visible="vModel" :footer="null" title="Child list">
<div class="max-h-[max(calc(100vh_-_300px)_,500px)] flex flex-col">
<div class="flex mb-4 align-center gap-2">
<!-- <a-input v-model:value="childrenListPagination.query" class="max-w-[200px]" size="small"></a-input> -->
<div class="flex-1" />
<MdiReloadIcon class="cursor-pointer text-gray-500" @click="loadChildrenList" />
<MdiReload class="cursor-pointer text-gray-500" @click="loadChildrenList" />
<a-button type="primary" size="small" @click="emit('attachRecord')">
<div class="flex align-center gap-1">
<MdiUnlinkIcon class="text-xs text-white" @click="unlinkRow(row)" />
<MdiLinkVariantRemove class="text-xs text-white" @click="unlinkRow(row)" />
Link to '{{ meta.title }}'
</div>
</a-button>
@ -56,8 +56,8 @@ const unlinkRow = async (row: Record<string, any>) => {
</div>
<div class="flex-1"></div>
<div class="flex gap-2">
<MdiUnlinkIcon class="text-xs text-grey hover:(!text-red-500) cursor-pointer" @click="unlinkRow(row)" />
<MdiDeleteIcon class="text-xs text-grey hover:(!text-red-500) cursor-pointer" @click="deleteRelatedRow(row)" />
<MdiLinkVariantRemove class="text-xs text-grey hover:(!text-red-500) cursor-pointer" @click="unlinkRow(row)" />
<MdiDeleteOutline class="text-xs text-grey hover:(!text-red-500) cursor-pointer" @click="deleteRelatedRow(row)" />
</div>
</div>
</a-card>

13
packages/nc-gui-v2/components/virtual-cell/components/ListItems.vue

@ -1,9 +1,9 @@
<script lang="ts" setup>
import { useLTARStoreOrThrow, useVModel } from '#imports'
import MdiReloadIcon from '~icons/mdi/reload'
import { useLTARStoreOrThrow, useVModel, watch } from '#imports'
const props = defineProps<{ modelValue: boolean }>()
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits(['update:modelValue', 'addNewRecord'])
const vModel = useVModel(props, 'modelValue', emit)
@ -16,8 +16,8 @@ const {
getRelatedTableRowId,
} = useLTARStoreOrThrow()
watch(vModel, () => {
if (vModel.value) {
watch(vModel, (nextVal) => {
if (nextVal) {
loadChildrenExcludedList()
}
})
@ -25,7 +25,6 @@ watch(vModel, () => {
const linkRow = async (row: Record<string, any>) => {
await link(row)
vModel.value = false
// await loadChildrenExcludedList()
}
</script>
@ -40,7 +39,7 @@ const linkRow = async (row: Record<string, any>) => {
size="small"
></a-input>
<div class="flex-1" />
<MdiReloadIcon class="cursor-pointer text-gray-500" @click="loadChildrenExcludedList" />
<MdiReload class="cursor-pointer text-gray-500" @click="loadChildrenExcludedList" />
<a-button type="primary" size="small" @click="emit('addNewRecord')">Add new record</a-button>
</div>
<template v-if="childrenExcludedList?.pageInfo?.totalRows">

8
packages/nc-gui-v2/components/webhook/List.vue

@ -1,9 +1,7 @@
<script setup lang="ts">
import { useToast } from 'vue-toastification'
import { onMounted } from '@vue/runtime-core'
import { MetaInj } from '~/context'
import MdiHookIcon from '~icons/mdi/hook'
import MdiDeleteOutlineIcon from '~icons/mdi/delete-outline'
import { inject, onMounted, ref, useNuxtApp } from '#imports'
const emit = defineEmits(['edit'])
@ -75,7 +73,7 @@ onMounted(() => {
</template>
<template #avatar>
<div class="mt-4">
<MdiHookIcon class="text-xl" />
<MdiHook class="text-xl" />
</div>
</template>
</a-list-item-meta>
@ -84,7 +82,7 @@ onMounted(() => {
<!-- Notify Via -->
<div class="mr-2">{{ $t('labels.notifyVia') }} : {{ item?.notification?.type }}</div>
<div class="float-right pt-2 pr-1">
<MdiDeleteOutlineIcon class="text-xl" @click.stop="deleteHook(item, index)" />
<MdiDeleteOutline class="text-xl" @click.stop="deleteHook(item, index)" />
</div>
</div>
</template>

1
packages/nc-gui-v2/composables/useColumnCreateStore.ts

@ -168,6 +168,7 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
formState.value.altered = formState.value.altered || 2
}
// todo: type of onAlter is wrong, the first argument is `CheckboxChangeEvent` not a number.
const onAlter = (val = 2, cdf = false) => {
formState.value.altered = formState.value.altered || val
if (cdf) formState.value.cdf = formState.value.cdf || null

Loading…
Cancel
Save