Browse Source

fix(gui): stop event propagation in view rename input

re #4686

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4696/head
Pranav C 2 years ago
parent
commit
c841c767f0
  1. 7
      packages/nc-gui/components/dashboard/TreeView.vue
  2. 2
      packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue
  3. 1
      packages/nc-gui/composables/useGlobal/types.ts
  4. 82
      packages/nc-gui/pages/index/index/create-external.vue
  5. 16
      packages/nocodb/src/lib/Noco.ts
  6. 19
      packages/nocodb/src/lib/db/sql-client/lib/SqlClientFactory.ts
  7. 19
      packages/nocodb/src/lib/db/sql-client/lib/ee/SqlClientFactoryEE.ts
  8. 3
      packages/nocodb/src/lib/meta/api/utilApis.ts
  9. 1
      packages/nocodb/src/lib/migrations/v2/nc_013_sync_source.ts

7
packages/nc-gui/components/dashboard/TreeView.vue

@ -26,6 +26,7 @@ import {
useToggle,
useUIPermission,
watchEffect,
useGlobal
} from '#imports'
import MdiView from '~icons/mdi/eye-circle-outline'
import MdiTableLarge from '~icons/mdi/table-large'
@ -46,6 +47,8 @@ const route = useRoute()
const [searchActive, toggleSearchActive] = useToggle()
const { appInfo } = useGlobal()
const toggleDialog = inject(ToggleDialogInj, () => {})
const keys = $ref<Record<string, number>>({})
@ -414,7 +417,7 @@ const setIcon = async (icon: string, table: TableType) => {
MSSQL
</div>
</a-menu-item>
<a-menu-item key="connect-new-source" @click="toggleDialog(true, 'dataSources', ClientType.SNOWFLAKE)">
<a-menu-item v-if="appInfo.ee" key="connect-new-source" @click="toggleDialog(true, 'dataSources', ClientType.SNOWFLAKE)">
<div class="color-transition nc-project-menu-item group">
<LogosSnowflakeIcon class="group-hover:text-accent" />
Snowflake
@ -530,7 +533,7 @@ const setIcon = async (icon: string, table: TableType) => {
MSSQL
</div>
</a-menu-item>
<a-menu-item key="connect-new-source" @click="toggleDialog(true, 'dataSources', ClientType.SNOWFLAKE)">
<a-menu-item v-if="appInfo.ee" key="connect-new-source" @click="toggleDialog(true, 'dataSources', ClientType.SNOWFLAKE)">
<div class="color-transition nc-project-menu-item group">
<LogosSnowflakeIcon class="group-hover:text-accent" />
Snowflake

2
packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue

@ -179,7 +179,7 @@ function onStopEdit() {
</a-dropdown>
</div>
<a-input v-if="isEditing" :ref="focusInput" v-model:value="vModel.title" @blur="onCancel" @keydown="onKeyDown($event)" />
<a-input v-if="isEditing" :ref="focusInput" v-model:value="vModel.title" @blur="onCancel" @keydown.stop="onKeyDown($event)" />
<div v-else>
<LazyGeneralTruncateText>{{ vModel.alias || vModel.title }}</LazyGeneralTruncateText>

1
packages/nc-gui/composables/useGlobal/types.ts

@ -25,6 +25,7 @@ export interface AppInfo {
teleEnabled: boolean
type: string
version: string
ee?: boolean
}
export interface StoredState {

82
packages/nc-gui/pages/index/index/create-external.vue

@ -7,7 +7,7 @@ import {
Form,
Modal,
SSLUsage,
clientTypes,
clientTypes as _clientTypes,
computed,
extractSdkResponseErrorMsg,
fieldRequiredValidator,
@ -28,6 +28,8 @@ import {
watch,
} from '#imports'
const { appInfo } = useGlobal()
const useForm = Form.useForm
const testSuccess = ref(false)
@ -64,23 +66,29 @@ const customFormState = ref<ProjectCreateForm>({
extraParameters: [],
})
const clientTypes = computed(() => {
return _clientTypes.filter((type) => {
return appInfo.value?.ee || type.value !== ClientType.SNOWFLAKE
})
})
const validators = computed(() => {
return {
'title': [
{
required: true,
message: 'Project name is required',
},
projectTitleValidator,
],
'extraParameters': [extraParameterValidator],
'dataSource.client': [fieldRequiredValidator()],
...(formState.dataSource.client === ClientType.SQLITE
? {
let clientValidations: Record<string, any[]> = {
'dataSource.connection.host': [fieldRequiredValidator()],
'dataSource.connection.port': [fieldRequiredValidator()],
'dataSource.connection.user': [fieldRequiredValidator()],
'dataSource.connection.password': [fieldRequiredValidator()],
'dataSource.connection.database': [fieldRequiredValidator()],
}
switch (formState.dataSource.client) {
case ClientType.SQLITE:
clientValidations = {
'dataSource.connection.connection.filename': [fieldRequiredValidator()],
}
: formState.dataSource.client === ClientType.SNOWFLAKE
? {
break
case ClientType.SNOWFLAKE:
clientValidations = {
'dataSource.connection.account': [fieldRequiredValidator()],
'dataSource.connection.username': [fieldRequiredValidator()],
'dataSource.connection.password': [fieldRequiredValidator()],
@ -88,18 +96,24 @@ const validators = computed(() => {
'dataSource.connection.database': [fieldRequiredValidator()],
'dataSource.connection.schema': [fieldRequiredValidator()],
}
: {
'dataSource.connection.host': [fieldRequiredValidator()],
'dataSource.connection.port': [fieldRequiredValidator()],
'dataSource.connection.user': [fieldRequiredValidator()],
'dataSource.connection.password': [fieldRequiredValidator()],
'dataSource.connection.database': [fieldRequiredValidator()],
...([ClientType.PG, ClientType.MSSQL].includes(formState.dataSource.client)
? {
'dataSource.searchPath.0': [fieldRequiredValidator()],
break
case ClientType.PG:
case ClientType.MSSQL:
clientValidations['dataSource.searchPath.0'] = [fieldRequiredValidator()]
break
}
: {}),
}),
return {
'title': [
{
required: true,
message: 'Project name is required',
},
projectTitleValidator,
],
'extraParameters': [extraParameterValidator],
'dataSource.client': [fieldRequiredValidator()],
...clientValidations,
}
})
@ -483,8 +497,10 @@ onMounted(async () => {
</div>
</template>
<a-form-item label="SSL mode">
<a-select v-model:value="formState.sslUse" dropdown-class-name="nc-dropdown-ssl-mode" @select="onSSLModeChange">
<a-select-option v-for="opt in Object.values(SSLUsage)" :key="opt" :value="opt">{{ opt }}</a-select-option>
<a-select v-model:value="formState.sslUse" dropdown-class-name="nc-dropdown-ssl-mode"
@select="onSSLModeChange">
<a-select-option v-for="opt in Object.values(SSLUsage)" :key="opt" :value="opt">{{ opt }}
</a-select-option>
</a-select>
</a-form-item>
@ -526,14 +542,16 @@ onMounted(async () => {
<input ref="caFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.ca, caFileInput)" />
<input ref="certFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.cert, certFileInput)" />
<input ref="certFileInput" type="file" class="!hidden"
@change="onFileSelect(CertTypes.cert, certFileInput)" />
<input ref="keyFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.key, keyFileInput)" />
<a-divider />
<!-- Extra connection parameters -->
<a-form-item class="mb-2" :label="$t('labels.extraConnectionParameters')" v-bind="validateInfos.extraParameters">
<a-form-item class="mb-2" :label="$t('labels.extraConnectionParameters')"
v-bind="validateInfos.extraParameters">
<a-card>
<div v-for="(item, index) of formState.extraParameters" :key="index">
<div class="flex py-1 items-center gap-1">
@ -547,7 +565,9 @@ onMounted(async () => {
</div>
</div>
<a-button type="dashed" class="w-full caption mt-2" @click="addNewParam">
<div class="flex items-center justify-center"><MdiPlus /></div>
<div class="flex items-center justify-center">
<MdiPlus />
</div>
</a-button>
</a-card>
</a-form-item>

16
packages/nocodb/src/lib/Noco.ts

@ -16,7 +16,9 @@ import requestIp from 'request-ip';
import { v4 as uuidv4 } from 'uuid';
import { NcConfig } from '../interface/config';
import { NC_LICENSE_KEY } from './constants';
import Migrator from './db/sql-migrator/lib/KnexMigrator';
import Store from './models/Store';
import NcConfigFactory from './utils/NcConfigFactory';
import { Tele } from 'nc-help';
@ -53,6 +55,7 @@ const NcProjectBuilder = process.env.EE
export default class Noco {
private static _this: Noco;
private static ee: boolean;
public static get dashboardUrl(): string {
let siteUrl = `http://localhost:${process.env.PORT || 8080}`;
@ -192,6 +195,7 @@ export default class Noco {
}
await Noco._ncMeta.metaInit();
await Noco.loadEEState();
await this.initJwt();
await initAdminFromEnv();
@ -542,4 +546,16 @@ export default class Noco {
public static getConfig(): NcConfig {
return Noco.config;
}
public static isEE(): boolean {
return Noco.ee;
}
public static async loadEEState(): Promise<boolean> {
try {
return (Noco.ee = !!(await Store.get(NC_LICENSE_KEY)));
} catch {
return (Noco.ee = false);
}
}
}

19
packages/nocodb/src/lib/db/sql-client/lib/SqlClientFactory.ts

@ -1,3 +1,5 @@
import Noco from '../../../Noco';
import SqlClientFactoryEE from './ee/SqlClientFactoryEE';
import MySqlClient from './mysql/MysqlClient';
import MssqlClient from './mssql/MssqlClient';
import OracleClient from './oracle/OracleClient';
@ -6,10 +8,8 @@ import PgClient from './pg/PgClient';
import YugabyteClient from './pg/YugabyteClient';
import TidbClient from './mysql/TidbClient';
import VitessClient from './mysql/VitessClient';
import SfClient from './snowflake/SnowflakeClient';
import { SnowflakeClient } from 'nc-help';
class SqlClientFactory {
export class SqlClientFactory {
static create(connectionConfig) {
connectionConfig.meta = connectionConfig.meta || {};
connectionConfig.pool = connectionConfig.pool || { min: 0, max: 5 };
@ -33,13 +33,18 @@ class SqlClientFactory {
if (connectionConfig.meta.dbtype === 'yugabyte')
return new YugabyteClient(connectionConfig);
return new PgClient(connectionConfig);
} else if (connectionConfig.client === 'snowflake') {
connectionConfig.client = SnowflakeClient;
return new SfClient(connectionConfig);
}
throw new Error('Database not supported');
}
}
export default SqlClientFactory;
export default class {
static create(connectionConfig) {
if (Noco.isEE()) {
return SqlClientFactoryEE.create(connectionConfig);
}
return SqlClientFactory.create(connectionConfig);
}
}

19
packages/nocodb/src/lib/db/sql-client/lib/ee/SqlClientFactoryEE.ts

@ -0,0 +1,19 @@
import { SqlClientFactory } from '../SqlClientFactory';
import SfClient from '../snowflake/SnowflakeClient';
import { SnowflakeClient } from 'nc-help';
class SqlClientFactoryEE {
static create(connectionConfig) {
connectionConfig.meta = connectionConfig.meta || {};
connectionConfig.pool = connectionConfig.pool || { min: 0, max: 5 };
connectionConfig.meta.dbtype = connectionConfig.meta.dbtype || '';
if (connectionConfig.client === 'snowflake') {
connectionConfig.client = SnowflakeClient;
return new SfClient(connectionConfig);
}
return SqlClientFactory.create(connectionConfig);
}
}
export default SqlClientFactoryEE;

3
packages/nocodb/src/lib/meta/api/utilApis.ts

@ -3,7 +3,9 @@ import { Request, Response } from 'express';
import { compareVersions, validate } from 'compare-versions';
import { ViewTypes } from 'nocodb-sdk';
import { NC_LICENSE_KEY } from '../../constants';
import Project from '../../models/Project';
import Store from '../../models/Store';
import Noco from '../../Noco';
import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2';
import { MetaTable } from '../../utils/globals';
@ -55,6 +57,7 @@ export async function appInfo(req: Request, res: Response) {
ncMin: !!process.env.NC_MIN,
teleEnabled: !process.env.NC_DISABLE_TELE,
ncSiteUrl: (req as any).ncSiteUrl,
ee: !!(await Store.get(NC_LICENSE_KEY)),
};
res.json(result);

1
packages/nocodb/src/lib/migrations/v2/nc_013_sync_source.ts

@ -38,6 +38,7 @@ const up = async (knex: Knex) => {
};
const down = async (knex) => {
await knex.schema.dropTable(MetaTable.SYNC_LOGS);
await knex.schema.dropTable(MetaTable.SYNC_SOURCE);
};

Loading…
Cancel
Save