Browse Source

refactor(gui-v2): cleanup project create utils

# What's changed?

* move form type to utils file
* move ClientType enum to enums file
* use ClientType enum where appropriate
* add default host (localhost)
* lint files
pull/2830/head
braks 2 years ago
parent
commit
13c35c4aca
  1. 8
      packages/nc-gui-v2/lib/enums.ts
  2. 40
      packages/nc-gui-v2/lib/types.ts
  3. 69
      packages/nc-gui-v2/pages/index/index.vue
  4. 14
      packages/nc-gui-v2/pages/project/index/create-external.vue
  5. 4
      packages/nc-gui-v2/pages/signin.vue
  6. 6
      packages/nc-gui-v2/pages/signup.vue
  7. 118
      packages/nc-gui-v2/utils/projectCreateUtils.ts

8
packages/nc-gui-v2/lib/enums.ts

@ -4,7 +4,13 @@ export enum Role {
User = 'user',
}
export type Roles = Record<Role, boolean>
export enum ClientType {
MYSQL = 'mysql2',
MSSQL = 'mssql',
PG = 'pg',
SQLITE = 'sqlite3',
VITESS = 'vitess',
}
export enum Language {
de = 'Deutsch',

40
packages/nc-gui-v2/lib/types.ts

@ -1,5 +1,5 @@
import type { ComputedRef, ToRefs } from 'vue'
import type { Roles } from '~/lib/enums'
import type { Role } from './enums'
export interface User {
id: string
@ -33,40 +33,4 @@ export type ReadonlyState = Readonly<Pick<State, 'token' | 'user'>> & Omit<State
export type GlobalState = Getters & Actions & ToRefs<ReadonlyState>
export enum ClientType {
MYSQL = 'mysql2',
MSSQL = 'mssql',
PG = 'pg',
SQLITE = 'sqlite3',
VITESS = 'vitess',
}
export interface ProjectCreateForm {
title: string
dataSource: {
client: ClientType
connection:
| {
host: string
database: string
user: string
password: string
port: number | string
ssl?: Record<string, string>
searchPath?: string[]
}
| {
client?: 'sqlite3'
database: string
connection?: {
filename?: string
}
useNullAsDefault?: boolean
}
}
inflection: {
inflectionColumn?: string
inflectionTable?: string
}
sslUse?: any
}
export type Roles = Record<Role, boolean>

69
packages/nc-gui-v2/pages/index/index.vue

@ -1,10 +1,10 @@
<script lang="ts" setup>
import {Modal} from 'ant-design-vue'
import type {ProjectType} from 'nocodb-sdk'
import {useToast} from 'vue-toastification'
import {navigateTo} from '#app'
import {computed, onMounted} from '#imports'
import {extractSdkResponseErrorMsg} from '~/utils/errorUtils'
import { Modal } from 'ant-design-vue'
import type { ProjectType } from 'nocodb-sdk'
import { useToast } from 'vue-toastification'
import { navigateTo } from '#app'
import { computed, onMounted } from '#imports'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
import MdiDeleteOutline from '~icons/mdi/delete-outline'
import MdiEditOutline from '~icons/mdi/edit-outline'
@ -13,7 +13,7 @@ import MdiMenuDown from '~icons/mdi/menu-down'
import MdiPlus from '~icons/mdi/plus'
import MdiDatabaseOutline from '~icons/mdi/database-outline'
const {$api, $state, $e} = useNuxtApp()
const { $api, $state, $e } = useNuxtApp()
const toast = useToast()
const filterQuery = ref('')
@ -29,7 +29,7 @@ const loadProjects = async () => {
const filteredProjects = computed(() => {
return projects.value.filter(
(project) => !filterQuery.value || project.title?.toLowerCase?.().includes(filterQuery.value.toLowerCase()),
(project) => !filterQuery.value || project.title?.toLowerCase?.().includes(filterQuery.value.toLowerCase()),
)
})
@ -68,17 +68,17 @@ $state.sidebarOpen.value = false
<b>{{ $t('title.myProject') }}</b>
<MdiRefresh
v-t="['a:project:refresh']"
class="text-sm text-gray-500 hover:text-primary mt-1 cursor-pointer"
@click="loadProjects"
v-t="['a:project:refresh']"
class="text-sm text-gray-500 hover:text-primary mt-1 cursor-pointer"
@click="loadProjects"
></MdiRefresh>
</h1>
<div class="flex mb-6">
<a-input-search
v-model:value="filterQuery"
class="max-w-[200px] nc-project-page-search"
:placeholder="$t('activity.searchProject')"
v-model:value="filterQuery"
class="max-w-[200px] nc-project-page-search"
:placeholder="$t('activity.searchProject')"
></a-input-search>
<div class="flex-grow"></div>
@ -86,27 +86,27 @@ $state.sidebarOpen.value = false
<a-button class="nc-new-project-menu !shadow">
<div class="flex align-center">
{{ $t('title.newProj') }}
<MdiMenuDown class="menu-icon"/>
<MdiMenuDown class="menu-icon" />
</div>
</a-button>
<template #overlay>
<a-menu>
<div
v-t="['c:project:create:xcdb']"
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2 nc-create-xc-db-project"
@click="navigateTo('/project/create')"
v-t="['c:project:create:xcdb']"
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2 nc-create-xc-db-project"
@click="navigateTo('/project/create')"
>
<MdiPlus class="col-span-2 mr-1 mt-[1px] text-primary text-lg"/>
<MdiPlus class="col-span-2 mr-1 mt-[1px] text-primary text-lg" />
<div class="col-span-10 text-sm xl:text-md">{{ $t('activity.createProject') }}</div>
</div>
<div
v-t="['c:project:create:extdb']"
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2 nc-create-external-db-project"
@click="navigateTo('/project/create-external')"
v-t="['c:project:create:extdb']"
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2 nc-create-external-db-project"
@click="navigateTo('/project/create-external')"
>
<MdiDatabaseOutline class="col-span-2 mr-1 mt-[1px] text-green-500 text-lg"/>
<div class="col-span-10 text-sm xl:text-md" v-html="$t('activity.createProjectExtended.extDB')"/>
<MdiDatabaseOutline class="col-span-2 mr-1 mt-[1px] text-green-500 text-lg" />
<div class="col-span-10 text-sm xl:text-md" v-html="$t('activity.createProjectExtended.extDB')" />
</div>
</a-menu>
</template>
@ -114,12 +114,12 @@ $state.sidebarOpen.value = false
</div>
<div v-if="loading">
<a-skeleton/>
<a-skeleton />
</div>
<a-table
v-else
:custom-row="
v-else
:custom-row="
(record) => ({
onClick: () => {
$e('a:project:open')
@ -127,14 +127,13 @@ $state.sidebarOpen.value = false
},
})
"
:data-source="filteredProjects"
:pagination="{ position: ['bottomCenter'] }"
:data-source="filteredProjects"
:pagination="{ position: ['bottomCenter'] }"
>
<!-- Title -->
<a-table-column key="title" :title="$t('general.title')" data-index="title">
<template #default="{ text }">
<div class="capitalize !w-[400px] overflow-hidden overflow-ellipsis whitespace-nowrap nc-project-row"
:title="text">
<div class="capitalize !w-[400px] overflow-hidden overflow-ellipsis whitespace-nowrap nc-project-row" :title="text">
{{ text }}
</div>
</template>
@ -144,11 +143,11 @@ $state.sidebarOpen.value = false
<template #default="{ text, record }">
<div class="flex align-center">
<MdiEditOutline
v-t="['c:project:edit:rename']"
class="nc-action-btn"
@click.stop="navigateTo(`/project/${text}`)"
v-t="['c:project:edit:rename']"
class="nc-action-btn"
@click.stop="navigateTo(`/project/${text}`)"
/>
<MdiDeleteOutline class="nc-action-btn" @click.stop="deleteProject(record)"/>
<MdiDeleteOutline class="nc-action-btn" @click.stop="deleteProject(record)" />
</div>
</template>
</a-table-column>

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

@ -310,7 +310,7 @@ onMounted(() => {
<template #title>
<span>{{ $t('tooltip.clientCert') }}</span>
</template>
<a-button :disabled="!sslFilesRequired" size="small" @click="certFileInput.click()" class="shadow">
<a-button :disabled="!sslFilesRequired" size="small" class="shadow" @click="certFileInput.click()">
{{ $t('labels.clientCert') }}
</a-button>
</a-tooltip>
@ -319,7 +319,7 @@ onMounted(() => {
<template #title>
<span>{{ $t('tooltip.clientKey') }}</span>
</template>
<a-button :disabled="!sslFilesRequired" size="small" @click="keyFileInput.click()" class="shadow">
<a-button :disabled="!sslFilesRequired" size="small" class="shadow" @click="keyFileInput.click()">
{{ $t('labels.clientKey') }}
</a-button>
</a-tooltip>
@ -328,7 +328,7 @@ onMounted(() => {
<template #title>
<span>{{ $t('tooltip.clientCA') }}</span>
</template>
<a-button :disabled="!sslFilesRequired" size="small" @click="caFileInput.click()" class="shadow">
<a-button :disabled="!sslFilesRequired" size="small" class="shadow" @click="caFileInput.click()">
{{ $t('labels.serverCA') }}
</a-button>
</a-tooltip>
@ -364,7 +364,9 @@ onMounted(() => {
<a-button type="primary" ghost class="nc-extdb-btn-test-connection" @click="testConnection">
{{ $t('activity.testDbConn') }}
</a-button>
<a-button type="primary" :disabled="!testSuccess" class="nc-extdb-btn-submit !shadow" @click="createProject"> Submit </a-button>
<a-button type="primary" :disabled="!testSuccess" class="nc-extdb-btn-submit !shadow" @click="createProject">
Submit
</a-button>
</div>
</a-form-item>
</a-form>
@ -398,7 +400,7 @@ onMounted(() => {
@apply !min-h-0;
}
:deep(.ant-card-head-title){
@apply !text-3xl
:deep(.ant-card-head-title) {
@apply !text-3xl;
}
</style>

4
packages/nc-gui-v2/pages/signin.vue

@ -111,7 +111,9 @@ const resetError = () => {
</nuxt-link>
</div>
<div class="self-center flex flex-column flex-wrap gap-4 items-center mt-4 md:mx-8 md:justify-between justify-center w-full">
<div
class="self-center flex flex-column flex-wrap gap-4 items-center mt-4 md:mx-8 md:justify-between justify-center w-full"
>
<button class="submit" type="submit">
<span class="flex items-center gap-2"><MdiLogin /> {{ $t('general.signIn') }}</span>
</button>

6
packages/nc-gui-v2/pages/signup.vue

@ -19,7 +19,7 @@ let error = $ref<string | null>(null)
const form = reactive({
email: '',
password: ''
password: '',
})
const formRules = {
@ -102,7 +102,9 @@ const resetError = () => {
/>
</a-form-item>
<div class="self-center flex flex-column flex-wrap gap-4 items-center mt-4 md:mx-8 md:justify-between justify-center w-full">
<div
class="self-center flex flex-column flex-wrap gap-4 items-center mt-4 md:mx-8 md:justify-between justify-center w-full"
>
<button class="submit" type="submit">
<span class="flex items-center gap-2"><MaterialSymbolsRocketLaunchOutline /> {{ $t('general.signUp') }}</span>
</button>

118
packages/nc-gui-v2/utils/projectCreateUtils.ts

@ -1,43 +1,75 @@
import { adjectives, animals, starWars, uniqueNamesGenerator } from 'unique-names-generator'
import type { ClientType, ProjectCreateForm } from '~/lib/types'
import { ClientType } from '~/lib/enums'
export interface ProjectCreateForm {
title: string
dataSource: {
client: ClientType
connection:
| {
host: string
database: string
user: string
password: string
port: number | string
ssl?: Record<string, string>
searchPath?: string[]
}
| {
client?: ClientType.SQLITE
database: string
connection?: {
filename?: string
}
useNullAsDefault?: boolean
}
}
inflection: {
inflectionColumn?: string
inflectionTable?: string
}
sslUse?: any
}
const defaultHost = 'localhost'
const testDataBaseNames = {
mysql2: null,
[ClientType.MYSQL]: null,
mysql: null,
pg: 'postgres',
[ClientType.PG]: 'postgres',
oracledb: 'xe',
mssql: undefined,
sqlite3: 'a.sqlite',
[ClientType.MSSQL]: undefined,
[ClientType.SQLITE]: 'a.sqlite',
}
export const getTestDatabaseName = (db: { client: ClientType; connection?: { database?: string } }) => {
if (db.client === 'pg') return db.connection?.database
if (db.client === ClientType.PG) return db.connection?.database
return testDataBaseNames[db.client as keyof typeof testDataBaseNames]
}
export const clientTypes = [
{
text: 'MySql',
value: 'mysql2',
value: ClientType.MYSQL,
},
{
text: 'MSSQL',
value: 'mssql',
value: ClientType.MSSQL,
},
{
text: 'PostgreSQL',
value: 'pg',
value: ClientType.PG,
},
{
text: 'SQLite',
value: 'sqlite3',
value: ClientType.SQLITE,
},
]
const homeDir = ''
const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataSource']['connection']> = {
pg: {
host: 'localhost',
[ClientType.PG]: {
host: defaultHost,
port: '5432',
user: 'postgres',
password: 'password',
@ -49,8 +81,8 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
cert: '',
},
},
mysql2: {
host: 'localhost',
[ClientType.MYSQL]: {
host: defaultHost,
port: '3306',
user: 'root',
password: 'password',
@ -61,8 +93,8 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
cert: '',
},
},
vitess: {
host: 'localhost',
[ClientType.VITESS]: {
host: defaultHost,
port: '15306',
user: 'root',
password: 'password',
@ -73,8 +105,29 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
cert: '',
},
},
[ClientType.MSSQL]: {
host: defaultHost,
port: 1433,
user: 'sa',
password: 'Password123.',
database: '_test',
searchPath: ['dbo'],
ssl: {
ca: '',
key: '',
cert: '',
},
},
[ClientType.SQLITE]: {
client: ClientType.SQLITE,
database: homeDir,
connection: {
filename: homeDir,
},
useNullAsDefault: true,
},
tidb: {
host: 'localhost',
host: defaultHost,
port: '4000',
user: 'root',
password: '',
@ -86,7 +139,7 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
},
},
yugabyte: {
host: 'localhost',
host: defaultHost,
port: '5432',
user: 'postgres',
password: '',
@ -98,7 +151,7 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
},
},
citusdb: {
host: 'localhost',
host: defaultHost,
port: '5432',
user: 'postgres',
password: '',
@ -110,7 +163,7 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
},
},
cockroachdb: {
host: 'localhost',
host: defaultHost,
port: '5432',
user: 'postgres',
password: '',
@ -122,7 +175,7 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
},
},
greenplum: {
host: 'localhost',
host: defaultHost,
port: '5432',
user: 'postgres',
password: '',
@ -133,21 +186,8 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
cert: '',
},
},
mssql: {
host: 'localhost',
port: 1433,
user: 'sa',
password: 'Password123.',
database: '_test',
searchPath: ['dbo'],
ssl: {
ca: '',
key: '',
cert: '',
},
},
oracledb: {
host: 'localhost',
host: defaultHost,
port: '1521',
user: 'system',
password: 'Oracle18',
@ -158,14 +198,6 @@ const sampleConnectionData: Record<ClientType | string, ProjectCreateForm['dataS
cert: '',
},
},
sqlite3: {
client: 'sqlite3',
database: homeDir,
connection: {
filename: homeDir,
},
useNullAsDefault: true,
},
}
export const getDefaultConnectionConfig = (client: ClientType): ProjectCreateForm['dataSource'] => {

Loading…
Cancel
Save