Browse Source

chore(gui-v2): sync with refactor/gui-v2

pull/2795/head
Wing-Kam Wong 2 years ago
parent
commit
c248cfdc4f
  1. 2
      packages/nc-gui-v2/components/cell/Duration.vue
  2. 97
      packages/nc-gui-v2/components/cell/JsonEditableCell.vue
  3. 18
      packages/nc-gui-v2/components/cell/Time.vue
  4. 10
      packages/nc-gui-v2/components/dlg/TableCreate.vue
  5. 5
      packages/nc-gui-v2/components/smartsheet-header/VirtualCellIcon.vue
  6. 74
      packages/nc-gui-v2/components/smartsheet-toolbar/LockMenu.vue
  7. 12
      packages/nc-gui-v2/components/smartsheet-toolbar/MoreActions.vue
  8. 4
      packages/nc-gui-v2/components/smartsheet-toolbar/SortListMenu.vue
  9. 5
      packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue
  10. 6
      packages/nc-gui-v2/components/virtual-cell/components/ListChildItemsModal.vue
  11. 3
      packages/nc-gui-v2/components/virtual-cell/components/ListItems.vue
  12. 7
      packages/nc-gui-v2/composables/useViewCreate.ts
  13. 5
      packages/nc-gui-v2/pages/project/index/create-external.vue
  14. 6
      packages/nc-gui-v2/plugins/i18n.ts

2
packages/nc-gui-v2/components/cell/Duration.vue

@ -66,7 +66,7 @@ const submitDuration = () => {
@keypress="checkDurationFormat($event)" @keypress="checkDurationFormat($event)"
@keydown.enter="submitDuration" @keydown.enter="submitDuration"
/> />
<div v-if="showWarningMessage == true" class="duration-warning"> <div v-if="showWarningMessage" class="duration-warning">
<!-- TODO: i18n --> <!-- TODO: i18n -->
Please enter a number Please enter a number
</div> </div>

97
packages/nc-gui-v2/components/cell/JsonEditableCell.vue

@ -1,66 +1,47 @@
<script> <script lang="ts" setup>
import MonacoJsonObjectEditor from '@/components/monaco/MonacoJsonObjectEditor' import MonacoJsonObjectEditor from '@/components/monaco/Editor.vue'
const editEnabled = inject < boolean > 'editEnabled' import { inject } from '#imports'
export default { interface Props {
name: 'JsonEditableCell', modelValue: string | Record<string, any>
components: { MonacoJsonObjectEditor }, isForm: boolean
props: { }
value: [String, Object],
isForm: Boolean,
},
data: () => ({
localState: '',
expand: false,
isValid: true,
error: undefined,
}),
computed: {
parentListeners() {
const $listeners = {}
if (this.$listeners.blur) { const props = defineProps<Props>()
$listeners.blur = this.$listeners.blur
}
if (this.$listeners.focus) {
$listeners.focus = this.$listeners.focus
}
return $listeners const emits = defineEmits(['update:modelValue', 'cancel'])
},
}, const editEnabled = inject('editEnabled')
watch: {
value(val) { let expand = $ref(false)
try {
this.localState = typeof val === 'string' ? JSON.parse(val) : val let isValid = $ref(true)
} catch (e) {
// ignore parse error for invalid JSON let error = $ref()
}
}, const localState = computed({
localState(val) { get: () => (typeof props.modelValue === 'string' ? JSON.parse(props.modelValue) : props.modelValue),
if (this.isForm) { set: (val) => {
this.$emit('input', JSON.stringify(val)) if (props.isForm) {
} emits('update:modelValue', JSON.stringify(val))
},
},
created() {
try {
this.localState = typeof this.value === 'string' ? JSON.parse(this.value) : this.value
} catch (e) {
// ignore parse error for invalid JSON
} }
}, },
mounted() {}, })
methods: {
save() { function save() {
this.expand = false expand = false
this.$emit('input', JSON.stringify(this.localState)) emits('update:modelValue', JSON.stringify(props.modelValue))
}, }
validate(n, e) {
this.isValid = n function validate(n: boolean, e: any) {
this.error = e isValid = n
}, error = e
}, }
</script>
<script lang="ts">
export default {
name: 'JsonEditableCell',
} }
</script> </script>

18
packages/nc-gui-v2/components/cell/Time.vue

@ -1,17 +1,27 @@
<script setup lang="ts"> <script setup lang="ts">
import { inject } from 'vue' import { inject } from 'vue'
interface Props {
modelValue: any
}
const props = defineProps<Props>()
const emits = defineEmits(['update:modelValue', 'save'])
const vModel = useVModel(props, 'modelValue', emits)
const editEnabled = inject<boolean>('editEnabled') const editEnabled = inject<boolean>('editEnabled')
</script> </script>
<template> <template>
<v-menu> <v-menu>
<template #activator="{ on }"> <template #activator="{ props: menuProps }">
<input v-model="localState" class="value" v-on="on" /> <input v-model="vModel" class="value" v-bind="menuProps.onClick" />
</template> </template>
<div class="d-flex flex-column justify-center" @click.stop> <div class="d-flex flex-column justify-center" @click.stop>
<v-time-picker v-model="localState" v-on="parentListeners" /> <v-time-picker v-model="vModel" />
<v-btn small color="primary" @click="$emit('save')"> <v-btn small color="primary" @click="emits('save')">
<!-- Save --> <!-- Save -->
{{ $t('general.save') }} {{ $t('general.save') }}
</v-btn> </v-btn>

10
packages/nc-gui-v2/components/dlg/TableCreate.vue

@ -8,7 +8,9 @@ import { validateTableName } from '~/utils/validation'
interface Props { interface Props {
modelValue?: boolean modelValue?: boolean
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'create']) const emit = defineEmits(['update:modelValue', 'create'])
const dialogShow = useVModel(props, 'modelValue', emit) const dialogShow = useVModel(props, 'modelValue', emit)
@ -17,16 +19,18 @@ const idTypes = [
{ value: 'AI', text: 'Auto increment number' }, { value: 'AI', text: 'Auto increment number' },
{ value: 'AG', text: 'Auto generated string' }, { value: 'AG', text: 'Auto generated string' },
] ]
const toast = useToast() const toast = useToast()
const valid = ref(false)
const isIdToggleAllowed = ref(false) const isIdToggleAllowed = ref(false)
const isAdvanceOptVisible = ref(false) const isAdvanceOptVisible = ref(false)
const { addTab } = useTabs() const { addTab } = useTabs()
const { loadTables } = useProject() const { loadTables } = useProject()
const { table, createTable, generateUniqueTitle, tables, project } = useTableCreate(async (table) => { const { table, createTable, generateUniqueTitle, tables, project } = useTableCreate(async (table) => {
await loadTables() await loadTables()
addTab({ addTab({
id: table.id as string, id: table.id as string,
title: table.title, title: table.title,
@ -48,7 +52,6 @@ const validateDuplicate = (v: string) => {
} }
const inputEl = ref<ComponentPublicInstance>() const inputEl = ref<ComponentPublicInstance>()
const useForm = Form.useForm const useForm = Form.useForm
const formState = reactive({ const formState = reactive({
title: '', title: '',
@ -70,6 +73,7 @@ const { resetFields, validate, validateInfos } = useForm(formState, validators)
onMounted(() => { onMounted(() => {
generateUniqueTitle() generateUniqueTitle()
nextTick(() => { nextTick(() => {
const el = inputEl.value?.$el const el = inputEl.value?.$el
el?.querySelector('input')?.focus() el?.querySelector('input')?.focus()

5
packages/nc-gui-v2/components/smartsheet-header/VirtualCellIcon.vue

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { LinkToAnotherRecordType, RelationTypes, UITypes } from "nocodb-sdk"; import type { LinkToAnotherRecordType } from 'nocodb-sdk'
import { RelationTypes, UITypes } from 'nocodb-sdk'
import { ColumnInj } from '~/context' import { ColumnInj } from '~/context'
import GenericIcon from '~icons/mdi/square-rounded' import GenericIcon from '~icons/mdi/square-rounded'
import HMIcon from '~icons/mdi/table-arrow-right' import HMIcon from '~icons/mdi/table-arrow-right'
@ -13,7 +14,7 @@ const column = inject(ColumnInj)
const icon = computed(() => { const icon = computed(() => {
switch (column?.uidt) { switch (column?.uidt) {
case UITypes.LinkToAnotherRecord: case UITypes.LinkToAnotherRecord:
switch ((<LinkToAnotherRecordType>column?.colOptions)?.type) { switch ((column?.colOptions as LinkToAnotherRecordType)?.type) {
case RelationTypes.MANY_TO_MANY: case RelationTypes.MANY_TO_MANY:
return MMIcon return MMIcon
case RelationTypes.HAS_MANY: case RelationTypes.HAS_MANY:

74
packages/nc-gui-v2/components/smartsheet-toolbar/LockMenu.vue

@ -1,32 +1,60 @@
<script> <script lang="ts" setup>
import { useToast } from 'vue-toastification'
interface Props {
modelValue?: LockType
}
const props = defineProps<Props>()
const emits = defineEmits(['update:modelValue'])
enum LockType {
Personal = 'personal',
Locked = 'locked',
Collaborative = 'collaborative',
}
const vModel = useVModel(props, 'modelValue', emits)
const { $e } = useNuxtApp()
const toast = useToast()
function changeLockType(type: LockType) {
$e('a:grid:lockmenu', { lockType: type })
if (type === 'personal') {
return toast.info('Coming soon', { timeout: 3000 })
}
vModel.value = type
toast.success(`Successfully Switched to ${type} view`, { timeout: 3000 })
}
</script>
<script lang="ts">
export default { export default {
name: 'LockMenu', name: 'LockMenu',
props: ['value'],
data: () => ({}),
methods: {
changeLockType(type) {
this.$e('a:grid:lockmenu', { lockType: type })
if (type === 'personal') {
return this.$toast.info('Coming soon').goAway(3000)
}
this.$emit('input', type)
this.$toast.success(`Successfully Switched to ${type} view`).goAway(3000)
},
},
} }
</script> </script>
<template> <template>
<v-menu offset-y max-width="350"> <v-menu offset-y max-width="350">
<template #activator="{ on }"> <template #activator="{ props: menuProps }">
<v-icon v-if="value === 'locked'" small class="mx-1 nc-view-lock-menu" v-on="on"> mdi-lock-outline </v-icon> <v-icon v-if="vModel === LockType.Locked" small class="mx-1 nc-view-lock-menu" v-bind="menuProps.onClick">
<v-icon v-else-if="value === 'personal'" small class="mx-1 nc-view-lock-menu" v-on="on"> mdi-account </v-icon> mdi-lock-outline
<v-icon v-else small class="mx-1 nc-view-lock-menu" v-on="on"> mdi-account-group-outline </v-icon> </v-icon>
<v-icon v-else-if="vModel === LockType.Personal" small class="mx-1 nc-view-lock-menu" v-bind="menuProps.onClick">
mdi-account
</v-icon>
<v-icon v-else small class="mx-1 nc-view-lock-menu" v-bind="menuProps.onClick"> mdi-account-group-outline </v-icon>
</template> </template>
<v-list maxc-width="350"> <v-list maxc-width="350">
<v-list-item two-line class="pb-4" @click="changeLockType('collaborative')"> <v-list-item two-line class="pb-4" @click="changeLockType(LockType.Collaborative)">
<v-list-item-icon class="mr-1 align-self-center"> <v-list-item-icon class="mr-1 align-self-center">
<v-icon v-if="!value || value === 'collaborative'" small> mdi-check-bold </v-icon> <v-icon v-if="!vModel || vModel === LockType.Collaborative" small> mdi-check-bold </v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content class="pb-1"> <v-list-item-content class="pb-1">
<v-list-item-title> <v-list-item-title>
@ -39,9 +67,9 @@ export default {
</v-list-item-subtitle> </v-list-item-subtitle>
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
<v-list-item two-line class="pb-4" @click="changeLockType('locked')"> <v-list-item two-line class="pb-4" @click="changeLockType(LockType.Locked)">
<v-list-item-icon class="mr-1 align-self-center"> <v-list-item-icon class="mr-1 align-self-center">
<v-icon v-if="value === 'locked'" small> mdi-check-bold </v-icon> <v-icon v-if="vModel === LockType.Locked" small> mdi-check-bold </v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content class="pb-1"> <v-list-item-content class="pb-1">
@ -56,9 +84,9 @@ export default {
<span class="caption mt-3"><v-icon class="mr-1 mt-n1" x-small color="#fcb401"> mdi-star</v-icon>Locked view.</span> <span class="caption mt-3"><v-icon class="mr-1 mt-n1" x-small color="#fcb401"> mdi-star</v-icon>Locked view.</span>
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
<v-list-item three-line @click="changeLockType('personal')"> <v-list-item three-line @click="changeLockType(LockType.Personal)">
<v-list-item-icon class="mr-1 align-self-center"> <v-list-item-icon class="mr-1 align-self-center">
<v-icon v-if="value === 'personal'" small> mdi-check-bold </v-icon> <v-icon v-if="vModel === LockType.Personal" small> mdi-check-bold </v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-list-item-content>

12
packages/nc-gui-v2/components/smartsheet-toolbar/MoreActions.vue

@ -13,7 +13,6 @@ export default {
name: 'ExportImport', name: 'ExportImport',
components: { components: {
WebhookSlider, WebhookSlider,
WebhookModal,
ColumnMappingModal, ColumnMappingModal,
DropOrSelectFileModal, DropOrSelectFileModal,
}, },
@ -26,6 +25,7 @@ export default {
isView: Boolean, isView: Boolean,
reqPayload: Object, reqPayload: Object,
}, },
emits: ['reload', 'showAdditionalFeatOverlay'],
data() { data() {
return { return {
importModal: false, importModal: false,
@ -206,19 +206,19 @@ export default {
const v = this.meta && this.meta.columns.find((c) => c.title === col.destCn) const v = this.meta && this.meta.columns.find((c) => c.title === col.destCn)
let input = row[col.sourceCn] let input = row[col.sourceCn]
// parse potential boolean values // parse potential boolean values
if (v.uidt == UITypes.Checkbox) { if (v.uidt === UITypes.Checkbox) {
input = input.replace(/["']/g, '').toLowerCase().trim() input = input.replace(/["']/g, '').toLowerCase().trim()
if (input == 'false' || input == 'no' || input == 'n') { if (input === 'false' || input === 'no' || input === 'n') {
input = '0' input = '0'
} else if (input == 'true' || input == 'yes' || input == 'y') { } else if (input === 'true' || input === 'yes' || input === 'y') {
input = '1' input = '1'
} }
} else if (v.uidt === UITypes.Number) { } else if (v.uidt === UITypes.Number) {
if (input == '') { if (input === '') {
input = null input = null
} }
} else if (v.uidt === UITypes.SingleSelect || v.uidt === UITypes.MultiSelect) { } else if (v.uidt === UITypes.SingleSelect || v.uidt === UITypes.MultiSelect) {
if (input == '') { if (input === '') {
input = null input = null
} }
} }

4
packages/nc-gui-v2/components/smartsheet-toolbar/SortListMenu.vue

@ -62,7 +62,7 @@ watch(
class="caption nc-sort-field-select" class="caption nc-sort-field-select"
:columns="columns" :columns="columns"
@click.stop @click.stop
@update:modelValue="saveOrUpdate(sort, i)" @update:model-value="saveOrUpdate(sort, i)"
/> />
<v-select <v-select
v-model="sort.direction" v-model="sort.direction"
@ -73,7 +73,7 @@ watch(
variant="solo" variant="solo"
hide-details hide-details
@click.stop @click.stop
@update:modelValue="saveOrUpdate(sort, i)" @update:model-value="saveOrUpdate(sort, i)"
/> />
<!-- <template #item="{ item }"> --> <!-- <template #item="{ item }"> -->
<!-- <span class="caption font-weight-regular">{{ item.text }}</span> --> <!-- <span class="caption font-weight-regular">{{ item.text }}</span> -->

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

@ -36,6 +36,7 @@ export default {
type: String, type: String,
password: String, password: String,
}, },
emits: ['input', 'edit', 'delete', 'unlink', 'newRecord'],
data: () => ({ data: () => ({
RelationTypes, RelationTypes,
data: null, data: null,
@ -121,7 +122,7 @@ export default {
small small
class="caption" class="caption"
color="primary" color="primary"
@click="$emit('new-record')" @click="$emit('newRecord')"
> >
<v-icon small> mdi-link </v-icon>&nbsp; Link to '{{ meta.title }}' <v-icon small> mdi-link </v-icon>&nbsp; Link to '{{ meta.title }}'
</v-btn> </v-btn>
@ -129,7 +130,7 @@ export default {
<v-card-text> <v-card-text>
<div class="items-container pt-2 mb-n4" :class="{ 'mx-n2': isForm }"> <div class="items-container pt-2 mb-n4" :class="{ 'mx-n2': isForm }">
<div v-if="!readOnly && (isPublic || _isUIAllowed('xcDatatableEditable'))" class="text-right mb-2 mt-n2 mx-2"> <div v-if="!readOnly && (isPublic || _isUIAllowed('xcDatatableEditable'))" class="text-right mb-2 mt-n2 mx-2">
<v-btn v-if="isForm" x-small class="caption" color="primary" outlined @click="$emit('new-record')"> <v-btn v-if="isForm" x-small class="caption" color="primary" outlined @click="$emit('newRecord')">
<v-icon x-small> mdi-link </v-icon>&nbsp; Link to '{{ meta.title }}' <v-icon x-small> mdi-link </v-icon>&nbsp; Link to '{{ meta.title }}'
</v-btn> </v-btn>
</div> </div>

6
packages/nc-gui-v2/components/virtual-cell/components/ListChildItemsModal.vue

@ -1,5 +1,5 @@
<script> <script>
import ListChildItems from '~/components/project/spreadsheet/components/virtualCell/components/ListChildItems' import ListChildItems from './ListChildItems.vue'
export default { export default {
name: 'ListChildItemsModal', name: 'ListChildItemsModal',
@ -32,6 +32,7 @@ export default {
rowId: [String, Number], rowId: [String, Number],
column: Object, column: Object,
}, },
emits: ['input'],
data: () => ({ data: () => ({
data: null, data: null,
page: 1, page: 1,
@ -50,7 +51,7 @@ export default {
methods: { methods: {
async loadData() { async loadData() {
if (this.$refs && this.$refs.child) { if (this.$refs && this.$refs.child) {
this.$refs.child.loadData() await this.$refs.child.loadData()
} }
}, },
}, },
@ -79,7 +80,6 @@ export default {
:read-only="readOnly" :read-only="readOnly"
:is-public="isPublic" :is-public="isPublic"
:column="column" :column="column"
v-on="$listeners"
/> />
</v-dialog> </v-dialog>
</template> </template>

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

@ -32,6 +32,7 @@ export default {
column: Object, column: Object,
rowId: [Number, String], rowId: [Number, String],
}, },
emits: ['input', 'add', 'addNewRecord'],
data: () => ({ data: () => ({
data: null, data: null,
page: 1, page: 1,
@ -127,7 +128,7 @@ export default {
<v-spacer /> <v-spacer />
<v-icon small class="mr-1" @click="loadData()"> mdi-reload </v-icon> <v-icon small class="mr-1" @click="loadData()"> mdi-reload </v-icon>
<v-btn v-if="!isPublic" small class="caption mr-2" color="primary" @click="$emit('add-new-record')"> <v-btn v-if="!isPublic" small class="caption mr-2" color="primary" @click="$emit('addNewRecord')">
<v-icon small> mdi-plus </v-icon>&nbsp; New Record <v-icon small> mdi-plus </v-icon>&nbsp; New Record
</v-btn> </v-btn>
</v-card-title> </v-card-title>

7
packages/nc-gui-v2/composables/useViewCreate.ts

@ -3,7 +3,7 @@ import { ViewTypes } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { useToast } from 'vue-toastification' import { useToast } from 'vue-toastification'
import { useNuxtApp } from '#app' import { useNuxtApp } from '#app'
import useMetas from '~/composables/useMetas' // import useMetas from '~/composables/useMetas'
export default (meta: Ref<TableType>, onViewCreate?: (viewMeta: any) => void) => { export default (meta: Ref<TableType>, onViewCreate?: (viewMeta: any) => void) => {
const view = reactive<{ title: string; type?: ViewTypes }>({ const view = reactive<{ title: string; type?: ViewTypes }>({
@ -14,7 +14,8 @@ export default (meta: Ref<TableType>, onViewCreate?: (viewMeta: any) => void) =>
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const toast = useToast() const toast = useToast()
const { metas } = useMetas() // unused
// const { metas } = useMetas()
const createView = async (viewType: ViewTypes, selectedViewId = null) => { const createView = async (viewType: ViewTypes, selectedViewId = null) => {
loading.value = true loading.value = true
@ -53,7 +54,7 @@ export default (meta: Ref<TableType>, onViewCreate?: (viewMeta: any) => void) =>
} }
toast.success('View created successfully') toast.success('View created successfully')
onViewCreate?.(data) onViewCreate?.(data)
} catch (e) { } catch (e: any) {
toast.error(e.message) toast.error(e.message)
} }

5
packages/nc-gui-v2/pages/project/index/create-external.vue

@ -5,10 +5,11 @@ import { useI18n } from 'vue-i18n'
import { useToast } from 'vue-toastification' import { useToast } from 'vue-toastification'
import { ref } from '#imports' import { ref } from '#imports'
import { navigateTo, useNuxtApp } from '#app' import { navigateTo, useNuxtApp } from '#app'
import type { ProjectCreateForm } from '~/lib/types' import { ClientType } from '~/lib/enums'
import { ClientType } from '~/lib/types'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils' import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
import { readFile } from '~/utils/fileUtils' import { readFile } from '~/utils/fileUtils'
import type { ProjectCreateForm } from '~/utils/projectCreateUtils'
import { import {
clientTypes, clientTypes,
generateUniqueName, generateUniqueName,

6
packages/nc-gui-v2/plugins/i18n.ts

@ -1,10 +1,10 @@
import { defineNuxtPlugin } from 'nuxt/app' import { defineNuxtPlugin } from 'nuxt/app'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import type en from '~/lang/en.json' // import type en from '~/lang/en.json'
// Type-define 'en' as the master schema for the resource // todo: Type-define 'en' as the master schema for the resource
type MessageSchema = typeof en // type MessageSchema = typeof en
export const createI18nPlugin = async () => export const createI18nPlugin = async () =>
createI18n({ createI18n({

Loading…
Cancel
Save