Browse Source

feat(gui-v2): table rename and minor improvements

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/2830/head
Pranav C 2 years ago
parent
commit
5d37bb97c6
  1. 30
      packages/nc-gui-v2/components/dashboard/TreeView.vue
  2. 117
      packages/nc-gui-v2/components/dlg/TableRename.vue
  3. 3
      packages/nc-gui-v2/pages/nc/[projectId].vue

30
packages/nc-gui-v2/components/dashboard/TreeView.vue

@ -23,7 +23,7 @@ import MdiAPIDocIcon from '~icons/mdi/open-in-new'
const { addTab } = useTabs()
const toast = useToast()
const { $api } = useNuxtApp()
const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission()
const route = useRoute()
const { tables, loadTables } = useProject(route.params.projectId as string)
@ -109,9 +109,11 @@ const contextMenuTarget = reactive<{ type?: 'table' | 'main'; value?: any }>({})
const setMenuContext = (type: 'table' | 'main', value?: any) => {
contextMenuTarget.type = type
contextMenuTarget.value = value
$e('c:table:create:navdraw:right-click')
}
const deleteTable = (table: TableType) => {
$e('c:table:delete');
// 'Click Submit to Delete The table'
Modal.confirm({
title: `Click Yes to Delete The table : ${table.title}`,
@ -155,6 +157,7 @@ const deleteTable = (table: TableType) => {
removeMeta(table.id as string)
toast.info(`Deleted table ${table.title} successfully`)
$e('a:table:delete')
} catch (e: any) {
toast.error(await extractSdkResponseErrorMsg(e))
}
@ -192,7 +195,7 @@ const showRenameTableDlg = (table: TableType) => {
<span class="flex-grow text-bold"
>{{ $t('objects.tables') }} <template v-if="tables?.length">({{ tables.length }})</template></span
>
<MdiPlus class="text-gray-500" @click.stop="tableCreateDlg = true" />
<MdiPlus class="text-gray-500" @click.stop="tableCreateDlg = true" v-t="['c:table:create:navdraw']"/>
<MdiMenuDown
class="transition-transform !duration-100 text-gray-500"
:class="{ 'transform rotate-180': showTableList }"
@ -208,17 +211,19 @@ const showRenameTableDlg = (table: TableType) => {
:data-order="table.order"
:data-id="table.id"
@click="addTab({ type: 'table', title: table.title, id: table.id })"
v-t="['a:table:open']"
>
<div class="flex align-center gap-1" @contextmenu="setMenuContext('table', table)">
<div class="flex align-center gap-1 h-full" @contextmenu="setMenuContext('table', table)">
<MdiDrag class="transition-opacity opacity-0 group-hover:opacity-100 text-gray-500 nc-drag-icon cursor-move" />
<component :is="icon(table)" class="text-xs text-gray-500" />
<component :is="icon(table)" class="text-[10px] text-gray-500" />
<span class="text-xs flex-1">{{ table.title }}</span>
<a-dropdown :trigger="['click']">
<span class="text-xs flex-1 ml-2">{{ table.title }}</span>
<a-dropdown :trigger="['click']" @click.stop>
<MdiMenuIcon class="transition-opacity opacity-0 group-hover:opacity-100" />
<template #overlay>
<a-menu>
<a-menu-item class="!text-xs" @click="showRenameTableDlg(table)"> Rename</a-menu-item>
<a-menu class="cursor-pointer">
<a-menu-item class="!text-xs"
v-t="['c:table:rename:navdraw:options']" @click="showRenameTableDlg(table)"> Rename</a-menu-item>
<a-menu-item class="!text-xs" @click="deleteTable(table)"> Delete</a-menu-item>
</a-menu>
</template>
@ -231,13 +236,14 @@ const showRenameTableDlg = (table: TableType) => {
</div>
<template #overlay>
<a-menu>
<a-menu class="cursor-pointer">
<template v-if="contextMenuTarget.type === 'table'">
<a-menu-item class="!text-xs" @click="showRenameTableDlg(contextMenuTarget.value)">Table Rename</a-menu-item>
<a-menu-item class="!text-xs"
v-t="['c:table:rename:navdraw:right-click']" @click="showRenameTableDlg(contextMenuTarget.value)">Table Rename</a-menu-item>
<a-menu-item class="!text-xs" @click="deleteTable(contextMenuTarget.value)">Table Delete</a-menu-item>
</template>
<template v-else>
<a-menu-item class="!text-xs" @click="loadTables">Tables Refresh</a-menu-item>
<a-menu-item class="!text-xs" @click="loadTables" v-t="['a:table:refresh:navdraw']">Tables Refresh</a-menu-item>
</template>
</a-menu>
</template>
@ -259,7 +265,7 @@ const showRenameTableDlg = (table: TableType) => {
<a-modal v-model:visible="settingsDlg" width="max(90vw, 600px)"> Team and settings</a-modal>
<DlgTableCreate v-model="tableCreateDlg" />
<DlgTableRename v-model="renameTableDlg" :table-meta="renameTableMeta" />
<DlgTableRename v-if="renameTableMeta" v-model="renameTableDlg" :table-meta="renameTableMeta" />
</div>
</template>

117
packages/nc-gui-v2/components/dlg/TableRename.vue

@ -1,92 +1,94 @@
<script setup lang="ts">
import { onMounted, watchEffect } from '@vue/runtime-core'
import { Form } from 'ant-design-vue'
import type { TableType } from 'nocodb-sdk'
import { useToast } from 'vue-toastification'
import { useProject, useTableCreate, useTabs } from '#imports'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
import { validateTableName } from '~/utils/validation'
import { useNuxtApp } from '#app'
import { onMounted, watchEffect } from "@vue/runtime-core";
import { Form } from "ant-design-vue";
import type { TableType } from "nocodb-sdk";
import { useToast } from "vue-toastification";
import { useProject, useTableCreate, useTabs } from "#imports";
import { extractSdkResponseErrorMsg } from "~/utils/errorUtils";
import { validateTableName } from "~/utils/validation";
import { useNuxtApp } from "#app";
interface Props {
modelValue?: boolean
tableMeta: TableType
modelValue?: boolean;
tableMeta: TableType;
}
const { modelValue = false, tableMeta } = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'updated'])
const { $e, $api } = useNuxtApp()
const toast = useToast()
const { modelValue = false, tableMeta } = defineProps<Props>();
const emit = defineEmits(["update:modelValue", "updated"]);
const { $e, $api } = useNuxtApp();
const toast = useToast();
const dialogShow = computed({
get() {
return modelValue
return modelValue;
},
set(v) {
emit('update:modelValue', v)
},
})
emit("update:modelValue", v);
}
});
const { addTab } = useTabs()
const { loadTables } = useProject()
const { project, tables } = useProject()
const { addTab } = useTabs();
const { loadTables } = useProject();
const { project, tables } = useProject();
const prefix = computed(() => project?.value?.prefix || '')
const prefix = computed(() => project?.value?.prefix || "");
const validateDuplicateAlias = (v: string) => {
return (tables?.value || []).every((t) => t.title !== (v || '')) || 'Duplicate table alias'
}
return (tables?.value || []).every((t) => t.title !== (v || "")) || "Duplicate table alias";
};
const validateLeadingOrTrailingWhiteSpace = (v: string) => {
return !/^\s+|\s+$/.test(v) || 'Leading or trailing whitespace not allowed in table name'
}
return !/^\s+|\s+$/.test(v) || "Leading or trailing whitespace not allowed in table name";
};
const validateDuplicate = (v: string) => {
return (tables?.value || []).every((t) => t.table_name.toLowerCase() !== (v || '').toLowerCase()) || 'Duplicate table name'
}
const inputEl = ref<any>()
const useForm = Form.useForm
return (tables?.value || []).every((t) => t.table_name.toLowerCase() !== (v || "").toLowerCase()) || "Duplicate table name";
};
const inputEl = $ref<any>();
const useForm = Form.useForm;
const formState = reactive({
title: '',
})
title: ""
});
const validators = computed(() => {
return {
title: [validateTableName, validateDuplicateAlias],
table_name: [validateTableName],
}
})
const { resetFields, validate, validateInfos } = useForm(formState, validators)
onMounted(() => {
// todo: focus input
})
table_name: [validateTableName]
};
});
const { resetFields, validate, validateInfos } = useForm(formState, validators);
watch(
() => tableMeta?.title,
(title) => {
if (title) formState.title = title
},
)
watchEffect(() => {
if (tableMeta?.title) formState.title = tableMeta?.title;
// todo: replace setTimeout and follow better approach
nextTick(() => {
const input = inputEl?.$el;
input.setSelectionRange(0, formState.title.length);
input.focus();
});
});
const renameTable = async () => {
try {
await $api.dbTable.update(tableMeta?.id as string, {
title: formState.title,
})
title: formState.title
});
loadTables()
toast.success('Table renamed successfully')
$e('a:table:rename')
loadTables();
toast.success("Table renamed successfully");
$e("a:table:rename");
} catch (e) {
toast.error(await extractSdkResponseErrorMsg(e))
toast.error(await extractSdkResponseErrorMsg(e));
}
}
};
</script>
<template>
<a-modal v-model:visible="dialogShow" @keydown.esc="dialogShow = false" @finish="renameTable">
<template #footer>
<a-button key="back" @click="dialogShow = false">{{ $t('general.cancel') }}</a-button>
<a-button key="submit" type="primary" @click="renameTable">{{ $t('general.submit') }}</a-button>
<a-button key="back" @click="dialogShow = false">{{ $t("general.cancel") }}</a-button>
<a-button key="submit" type="primary" @click="renameTable">{{ $t("general.submit") }}</a-button>
</template>
<div class="pl-10 pr-10 pt-5">
<a-form :model="formState" name="create-new-table-form">
<!-- Create A New Table -->
<!-- Rename Table -->
<div class="prose-xl font-bold text-center my-4">Rename Table</div>
<!-- hint="Enter table name" -->
<div class="mb-2">Table Name</div>
@ -97,8 +99,9 @@ const renameTable = async () => {
size="large"
hide-details
:placeholder="$t('msg.info.enterTableName')"
/> </a-form-item
></a-form>
/>
</a-form-item>
</a-form>
</div>
</a-modal>
</template>

3
packages/nc-gui-v2/pages/nc/[projectId].vue

@ -2,6 +2,7 @@
const route = useRoute()
const { loadProject, loadTables } = useProject(route.params.projectId as string)
const { clearTabs, addTab } = useTabs()
const {$state} = useNuxtApp()
addTab({ type: 'auth', title: 'Team & Auth' })
@ -17,6 +18,8 @@ watch(
}
},
)
$state.sidebarOpen.value = true
</script>
<template>

Loading…
Cancel
Save