Browse Source

refactor(gui-v2): ui improvements

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/2730/head
Pranav C 2 years ago
parent
commit
3c5237d821
  1. 2
      packages/nc-gui-v2/components/monaco/index.vue
  2. 231
      packages/nc-gui-v2/pages/projects/index/create-external.vue

2
packages/nc-gui-v2/components/monaco/index.vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import * as monaco from 'monaco-editor' import * as monaco from 'monaco-editor'
import { onMounted } from '#imports' import { onMounted } from '#imports'
import { deepCompare } from "~/utils/deepCompare"; import { deepCompare } from '~/utils/deepCompare'
const { modelValue } = defineProps<{ modelValue: any }>() const { modelValue } = defineProps<{ modelValue: any }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])

231
packages/nc-gui-v2/pages/projects/index/create-external.vue

@ -1,116 +1,116 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useI18n } from "vue-i18n"; import { useI18n } from 'vue-i18n'
import { useToast } from "vue-toastification"; import { useToast } from 'vue-toastification'
import { Form, Modal } from "ant-design-vue"; import { Form, Modal } from 'ant-design-vue'
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 type { ProjectCreateForm } from '~/lib/types'
import { extractSdkResponseErrorMsg } from "~/utils/errorUtils"; import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
import { import {
clientTypes, clientTypes,
fieldRequiredValidator, fieldRequiredValidator,
getDefaultConnectionConfig, getDefaultConnectionConfig,
getTestDatabaseName, getTestDatabaseName,
projectTitleValidator, projectTitleValidator,
sslUsage sslUsage,
} from "~/utils/projectCreateUtils"; } from '~/utils/projectCreateUtils'
import { readFile } from "~/utils/fileUtils"; import { readFile } from '~/utils/fileUtils'
const useForm = Form.useForm; const useForm = Form.useForm
const loading = ref(false); const loading = ref(false)
const testSuccess = ref(false); const testSuccess = ref(false)
const { $api, $e } = useNuxtApp(); const { $api, $e } = useNuxtApp()
const toast = useToast(); const toast = useToast()
const { t } = useI18n(); const { t } = useI18n()
const formState = $ref<ProjectCreateForm>({ const formState = $ref<ProjectCreateForm>({
title: "", title: '',
dataSource: { ...getDefaultConnectionConfig("mysql2") }, dataSource: { ...getDefaultConnectionConfig('mysql2') },
inflection: { inflection: {
inflection_column: "camelize", inflection_column: 'camelize',
inflection_table: "camelize" inflection_table: 'camelize',
} },
}); })
const validators = computed(() => { const validators = computed(() => {
return { return {
"title": [ 'title': [
{ {
required: true, required: true,
message: "Please input project title" message: 'Please input project title',
}, },
projectTitleValidator projectTitleValidator,
], ],
"dataSource.client": [fieldRequiredValidator], 'dataSource.client': [fieldRequiredValidator],
...(formState.dataSource.client === "sqlite3" ...(formState.dataSource.client === 'sqlite3'
? { ? {
"dataSource.connection.connection.filename": [fieldRequiredValidator] 'dataSource.connection.connection.filename': [fieldRequiredValidator],
} }
: { : {
"dataSource.connection.host": [fieldRequiredValidator], 'dataSource.connection.host': [fieldRequiredValidator],
"dataSource.connection.port": [fieldRequiredValidator], 'dataSource.connection.port': [fieldRequiredValidator],
"dataSource.connection.user": [fieldRequiredValidator], 'dataSource.connection.user': [fieldRequiredValidator],
"dataSource.connection.password": [fieldRequiredValidator], 'dataSource.connection.password': [fieldRequiredValidator],
"dataSource.connection.database": [fieldRequiredValidator], 'dataSource.connection.database': [fieldRequiredValidator],
...(["pg", "mssql"].includes(formState.dataSource.client) ...(['pg', 'mssql'].includes(formState.dataSource.client)
? { ? {
"dataSource.connection.searchPath.0": [fieldRequiredValidator] 'dataSource.connection.searchPath.0': [fieldRequiredValidator],
} }
: {}) : {}),
}) }),
}; }
}); })
const { resetFields, validate, validateInfos } = useForm(formState, validators); const { resetFields, validate, validateInfos } = useForm(formState, validators)
const onClientChange = () => { const onClientChange = () => {
formState.dataSource = { ...getDefaultConnectionConfig(formState.dataSource.client) }; formState.dataSource = { ...getDefaultConnectionConfig(formState.dataSource.client) }
}; }
const inflectionTypes = ["camelize", "none"]; const inflectionTypes = ['camelize', 'none']
const configEditDlg = ref(false); const configEditDlg = ref(false)
// populate database name based on title // populate database name based on title
watch( watch(
() => formState.title, () => formState.title,
(v) => (formState.dataSource.connection.database = `${v}_noco`) (v) => (formState.dataSource.connection.database = `${v}_noco`),
); )
const caFileInput = ref<HTMLInputElement>(); const caFileInput = ref<HTMLInputElement>()
const keyFileInput = ref<HTMLInputElement>(); const keyFileInput = ref<HTMLInputElement>()
const certFileInput = ref<HTMLInputElement>(); const certFileInput = ref<HTMLInputElement>()
const onFileSelect = (key: "ca" | "cert" | "key", el: HTMLInputElement) => { const onFileSelect = (key: 'ca' | 'cert' | 'key', el: HTMLInputElement) => {
readFile(el, (content) => { readFile(el, (content) => {
if ("ssl" in formState.dataSource.connection && formState.dataSource.connection.ssl) if ('ssl' in formState.dataSource.connection && formState.dataSource.connection.ssl)
formState.dataSource.connection.ssl[key] = content ?? ""; formState.dataSource.connection.ssl[key] = content ?? ''
}); })
}; }
const sslFilesRequired = computed<boolean>(() => { const sslFilesRequired = computed<boolean>(() => {
return formState?.sslUse && formState.sslUse !== "No"; return formState?.sslUse && formState.sslUse !== 'No'
}); })
function getConnectionConfig() { function getConnectionConfig() {
const connection = { const connection = {
...formState.dataSource.connection ...formState.dataSource.connection,
}; }
if ("ssl" in connection && connection.ssl && (!sslFilesRequired || Object.values(connection.ssl).every((v) => !v))) { if ('ssl' in connection && connection.ssl && (!sslFilesRequired || Object.values(connection.ssl).every((v) => !v))) {
delete connection.ssl; delete connection.ssl
} }
return connection; return connection
} }
const createProject = async () => { const createProject = async () => {
if (!(await validate())) { if (!(await validate())) {
return; return
} }
loading.value = true; loading.value = true
try { try {
const connection = getConnectionConfig(); const connection = getConnectionConfig()
const config = { ...formState.dataSource, connection }; const config = { ...formState.dataSource, connection }
const result = await $api.project.create({ const result = await $api.project.create({
title: formState.title, title: formState.title,
bases: [ bases: [
@ -118,74 +118,77 @@ const createProject = async () => {
type: formState.dataSource.client, type: formState.dataSource.client,
config, config,
inflection_column: formState.inflection.inflection_column, inflection_column: formState.inflection.inflection_column,
inflection_table: formState.inflection.inflection_table inflection_table: formState.inflection.inflection_table,
} },
], ],
external: true external: true,
}); })
$e("a:project:create:extdb"); $e('a:project:create:extdb')
await navigateTo(`/nc/${result.id}`); await navigateTo(`/nc/${result.id}`)
} catch (e: any) { } catch (e: any) {
// todo: toast // todo: toast
toast.error(await extractSdkResponseErrorMsg(e)); toast.error(await extractSdkResponseErrorMsg(e))
} }
loading.value = false; loading.value = false
}; }
const testConnection = async () => { const testConnection = async () => {
if (!(await validate())) { if (!(await validate())) {
return; return
} }
$e("a:project:create:extdb:test-connection", []); $e('a:project:create:extdb:test-connection', [])
try { try {
if (formState.dataSource.client === "sqlite3") { if (formState.dataSource.client === 'sqlite3') {
testSuccess.value = true; testSuccess.value = true
} else { } else {
const connection: any = getConnectionConfig(); const connection: any = getConnectionConfig()
connection.database = getTestDatabaseName(formState.dataSource); connection.database = getTestDatabaseName(formState.dataSource)
const testConnectionConfig = { const testConnectionConfig = {
...formState.dataSource, ...formState.dataSource,
connection connection,
}; }
const result = await $api.utils.testConnection(testConnectionConfig); const result = await $api.utils.testConnection(testConnectionConfig)
if (result.code === 0) { if (result.code === 0) {
testSuccess.value = true; testSuccess.value = true
Modal.confirm({ Modal.confirm({
title: t("msg.info.dbConnected"), title: t('msg.info.dbConnected'),
icon: null, icon: null,
type: "success", type: 'success',
okText: t("activity.OkSaveProject"), okText: t('activity.OkSaveProject'),
okType: "primary", okType: 'primary',
cancelText: "Cancel", cancelText: 'Cancel',
onOk: createProject onOk: createProject,
}); })
} else { } else {
testSuccess.value = false; testSuccess.value = false
toast.error(`${t("msg.error.dbConnectionFailed")} ${result.message}`); toast.error(`${t('msg.error.dbConnectionFailed')} ${result.message}`)
} }
} }
} catch (e: any) { } catch (e: any) {
testSuccess.value = false; testSuccess.value = false
toast.error(await extractSdkResponseErrorMsg(e)); toast.error(await extractSdkResponseErrorMsg(e))
} }
}; }
</script> </script>
<template> <template>
<a-card class="max-w-[600px] mx-auto !mt-100px" :title="$t('activity.createProject')"> <a-card
<a-form :model="formState" name="validate_other" layout="horizontal" :label-col="{ span: 8 }" class="max-w-[600px] mx-auto !mt-5"
:wrapper-col="{ span: 18 }"> :title="$t('activity.createProject')"
:head-style="{ textAlign: 'center', fontWeight: '700' }"
>
<a-form :model="formState" name="validate_other" layout="horizontal" :label-col="{ span: 8 }" :wrapper-col="{ span: 18 }">
<a-form-item :label="$t('placeholder.projName')" v-bind="validateInfos.title"> <a-form-item :label="$t('placeholder.projName')" v-bind="validateInfos.title">
<a-input v-model:value="formState.title" size="small" /> <a-input v-model:value="formState.title" size="small" />
</a-form-item> </a-form-item>
<a-form-item :label="$t('labels.dbType')" v-bind="validateInfos['dataSource.client']"> <a-form-item :label="$t('labels.dbType')" v-bind="validateInfos['dataSource.client']">
<a-select v-model:value="formState.dataSource.client" size="small" @change="onClientChange"> <a-select v-model:value="formState.dataSource.client" size="small" @change="onClientChange">
<a-select-option v-for="client in clientTypes" :key="client.value" :value="client.value" <a-select-option v-for="client in clientTypes" :key="client.value" :value="client.value"
>{{ client.text }} >{{ client.text }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
@ -252,28 +255,28 @@ const testConnection = async () => {
<a-tooltip placement="top"> <a-tooltip placement="top">
<!-- Select .cert file --> <!-- Select .cert file -->
<template #title> <template #title>
<span>{{ $t("tooltip.clientCert") }}</span> <span>{{ $t('tooltip.clientCert') }}</span>
</template> </template>
<a-button :disabled="!sslFilesRequired" size="small" @click="certFileInput.click()"> <a-button :disabled="!sslFilesRequired" size="small" @click="certFileInput.click()">
{{ $t("labels.clientCert") }} {{ $t('labels.clientCert') }}
</a-button> </a-button>
</a-tooltip> </a-tooltip>
<a-tooltip placement="top"> <a-tooltip placement="top">
<!-- Select .key file --> <!-- Select .key file -->
<template #title> <template #title>
<span>{{ $t("tooltip.clientKey") }}</span> <span>{{ $t('tooltip.clientKey') }}</span>
</template> </template>
<a-button :disabled="!sslFilesRequired" size="small" @click="keyFileInput.click()"> <a-button :disabled="!sslFilesRequired" size="small" @click="keyFileInput.click()">
{{ $t("labels.clientKey") }} {{ $t('labels.clientKey') }}
</a-button> </a-button>
</a-tooltip> </a-tooltip>
<a-tooltip placement="top"> <a-tooltip placement="top">
<!-- Select CA file --> <!-- Select CA file -->
<template #title> <template #title>
<span>{{ $t("tooltip.clientCA") }}</span> <span>{{ $t('tooltip.clientCA') }}</span>
</template> </template>
<a-button :disabled="!sslFilesRequired" size="small" @click="caFileInput.click()"> <a-button :disabled="!sslFilesRequired" size="small" @click="caFileInput.click()">
{{ $t("labels.serverCA") }} {{ $t('labels.serverCA') }}
</a-button> </a-button>
</a-tooltip> </a-tooltip>
</div> </div>
@ -296,14 +299,14 @@ const testConnection = async () => {
<div class="flex justify-end"> <div class="flex justify-end">
<a-button size="small" @click="configEditDlg = true"> <a-button size="small" @click="configEditDlg = true">
<!-- Edit connection JSON --> <!-- Edit connection JSON -->
{{ $t("activity.editConnJson") }} {{ $t('activity.editConnJson') }}
</a-button> </a-button>
</div> </div>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
</template> </template>
<a-form-item class="flex justify-center"> <a-form-item class="flex justify-center mt-5">
<div class="flex justify-center gap-2"> <div class="flex justify-center gap-2">
<a-button type="primary" :disabled="!testSuccess" @click="createProject">Submit</a-button> <a-button type="primary" :disabled="!testSuccess" @click="createProject">Submit</a-button>
<a-button type="primary" @click="testConnection">Test Connection</a-button> <a-button type="primary" @click="testConnection">Test Connection</a-button>
@ -327,4 +330,8 @@ const testConnection = async () => {
:deep(.ant-collapse-content-box) { :deep(.ant-collapse-content-box) {
@apply !pr-0; @apply !pr-0;
} }
:deep(.ant-form-item-explain-error) {
@apply !text-xs;
}
</style> </style>

Loading…
Cancel
Save