Browse Source

fix: null handling and edit column validation

Signed-off-by: Pranav C Balan <pranavxc@gmail.com>
pull/292/head
Pranav C Balan 3 years ago
parent
commit
e95cfbdcf7
  1. 535
      packages/nc-gui/components/project/spreadsheet/editColumn/editColumn.vue
  2. 19
      packages/nc-gui/components/project/spreadsheet/editColumn/relationOptions.vue
  3. 2
      packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js

535
packages/nc-gui/components/project/spreadsheet/editColumn/editColumn.vue

@ -1,288 +1,290 @@
<template> <template>
<v-card min-width="300px" max-width="400px" max-height="95vh" style="overflow: auto" <v-card min-width="300px" max-width="400px" max-height="95vh" style="overflow: auto"
class="elevation-0 card"> class="elevation-0 card">
<v-container fluid @click.stop.prevent> <v-form v-model="valid">
<v-row> <v-container fluid @click.stop.prevent>
<v-col cols="12" class="d-flex pb-0"> <v-row>
<v-col cols="12" class="d-flex pb-0">
<v-spacer></v-spacer>
<v-btn small outlined @click="close">Cancel</v-btn> <v-spacer></v-spacer>
<v-btn small color="primary" @click="save">Save</v-btn> <v-btn small outlined @click="close">Cancel</v-btn>
</v-col> <v-btn small color="primary" @click="save" :disabled="!valid">Save</v-btn>
<v-col cols="12"> </v-col>
<v-text-field <v-col cols="12">
ref="column" <v-text-field
hide-details ref="column"
color="primary" hide-details
v-model="newColumn.cn" color="primary"
@input="newColumn.altered = newColumn.altered || 8" v-model="newColumn.cn"
class="caption" @input="newColumn.altered = newColumn.altered || 8"
label="Column name" class="caption"
dense outlined></v-text-field> label="Column name"
dense outlined></v-text-field>
</v-col>
<div :class="{ </v-col>
<div :class="{
editDisabled :isEditDisabled editDisabled :isEditDisabled
}"> }">
<v-col cols="12" v-if="relation"> <v-col cols="12" v-if="relation">
<div class="caption"> <div class="caption">
<p class="mb-1">Foreign Key </p> <p class="mb-1">Foreign Key </p>
<v-icon small class="mt-n1">mdi-table</v-icon> <v-icon small class="mt-n1">mdi-table</v-icon>
<span class="text-capitalize font-weight-bold body-1"> {{ relation._rtn }}</span> <span class="text-capitalize font-weight-bold body-1"> {{ relation._rtn }}</span>
<v-icon small <v-icon small
class="ml-3 mt-n1" class="ml-3 mt-n1"
@click="deleteRelation('showDialog', column)" @click="deleteRelation('showDialog', column)"
color="error" color="error"
v-ge="['columns','fk-delete']" v-ge="['columns','fk-delete']"
>mdi-delete-forever >mdi-delete-forever
</v-icon> </v-icon>
<span v-if="relation.type=== 'virtual'" class="caption">(v)</span> <span v-if="relation.type=== 'virtual'" class="caption">(v)</span>
</div> </div>
</v-col> </v-col>
<template v-else> <template v-else>
<v-col cols="12"> <v-col cols="12">
<v-autocomplete <v-autocomplete
@change="onUiTypeChange" @change="onUiTypeChange"
v-model="newColumn.uidt" v-model="newColumn.uidt"
hide-details hide-details
item-value="name" item-value="name"
item-text="name" item-text="name"
class="caption ui-type" class="caption ui-type"
:class="{'primary lighten-5' : newColumn.uidt }" :class="{'primary lighten-5' : newColumn.uidt }"
label="Column type" label="Column type"
dense dense
outlined outlined
:items="uiTypes"> :items="uiTypes">
<template v-slot:selection="{item}"> <template v-slot:selection="{item}">
<div> <div>
<v-icon color="grey darken-4" small class="mr-1">{{ item.icon }}</v-icon> <v-icon color="grey darken-4" small class="mr-1">{{ item.icon }}</v-icon>
<span class="caption grey--text text--darken-4"> {{ item.name }}</span> <span class="caption grey--text text--darken-4"> {{ item.name }}</span>
</div> </div>
</template> </template>
<template v-slot:item="{item}"> <template v-slot:item="{item}">
<div class="caption"> <div class="caption">
<v-icon small class="mr-1">{{ item.icon }}</v-icon> <v-icon small class="mr-1">{{ item.icon }}</v-icon>
{{ item.name }} {{ item.name }}
</div> </div>
</template> </template>
</v-autocomplete> </v-autocomplete>
<!-- <v-list dense max-height="calc(100vh - 300px)" style="overflow: auto">--> <!-- <v-list dense max-height="calc(100vh - 300px)" style="overflow: auto">-->
<!-- <v-list-item v-for="item in uiTypes" @click.stop :key="item">--> <!-- <v-list-item v-for="item in uiTypes" @click.stop :key="item">-->
<!-- <span class="caption">{{ item }}</span>--> <!-- <span class="caption">{{ item }}</span>-->
<!-- </v-list-item>--> <!-- </v-list-item>-->
<!-- </v-list>--> <!-- </v-list>-->
</v-col> </v-col>
<template v-if="newColumn.uidt !== 'Formula'"> <template v-if="newColumn.uidt !== 'Formula'">
<v-col cols="12" <v-col cols="12"
v-if="isLinkToAnotherRecord"> v-if="isLinkToAnotherRecord">
<linked-to-another-options <linked-to-another-options
ref="relation" ref="relation"
:column="newColumn" :column="newColumn"
:nodes="nodes" :nodes="nodes"
@onColumnSelect="onRelColumnSelect" @onColumnSelect="onRelColumnSelect"
></linked-to-another-options> ></linked-to-another-options>
</v-col> </v-col>
<v-col cols="12" <v-col cols="12"
v-if="isRelation"> v-if="isRelation">
<relation-options <relation-options
ref="relation" ref="relation"
:column="newColumn" :column="newColumn"
:nodes="nodes" :nodes="nodes"
@onColumnSelect="onRelColumnSelect" @onColumnSelect="onRelColumnSelect"
></relation-options> :isSQLite="isSQLite"
</v-col> ></relation-options>
</v-col>
<v-col cols="12" v-if="isSelect">
<custom-select-options
v-model="newColumn.dtxp"
@input="newColumn.altered = newColumn.altered || 2"
></custom-select-options>
</v-col>
<v-col cols="12" v-if="isSelect">
<custom-select-options
v-model="newColumn.dtxp"
@input="newColumn.altered = newColumn.altered || 2"
></custom-select-options>
</v-col>
<template v-if="newColumn.cn && newColumn.uidt && !isLinkToAnotherRecord">
<v-col cols="12">
<v-container fluid class="wrapper">
<v-row>
<v-col cols="12">
<div class="d-flex justify-space-between caption">
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox
:disabled="newColumn.pk || !sqlUi.columnEditable(newColumn)"
class="mr-2 mt-0" dense hide-details label="NN"
@input="newColumn.altered = newColumn.altered || 2"
v-model="newColumn.rqd">
<template v-slot:label>
<span class="caption font-weight-bold">NN</span>
</template>
</v-checkbox>
</div>
</template>
<span>Not Null</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox
v-model="newColumn.pk"
:disabled="!sqlUi.columnEditable(newColumn)"
@input="newColumn.altered = newColumn.altered || 2"
class="mr-2 mt-0" dense hide-details label="PK">
<template v-slot:label>
<span class="caption font-weight-bold">PK</span>
</template>
</v-checkbox>
</div>
</template>
<span>Primary Key</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox
<template v-if="newColumn.cn && newColumn.uidt && !isLinkToAnotherRecord">
<v-col cols="12">
<v-container fluid class="wrapper">
<v-row>
<v-col cols="12">
<div class="d-flex justify-space-between caption">
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox
:disabled="newColumn.pk || !sqlUi.columnEditable(newColumn)"
class="mr-2 mt-0" dense hide-details label="NN"
@input="newColumn.altered = newColumn.altered || 2"
v-model="newColumn.rqd">
<template v-slot:label>
<span class="caption font-weight-bold">NN</span>
</template>
</v-checkbox>
</div>
</template>
<span>Not Null</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox
v-model="newColumn.pk"
:disabled="!sqlUi.columnEditable(newColumn)"
@input="newColumn.altered = newColumn.altered || 2"
class="mr-2 mt-0" dense hide-details label="PK">
<template v-slot:label>
<span class="caption font-weight-bold">PK</span>
</template>
</v-checkbox>
</div>
</template>
<span>Primary Key</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox
@input="newColumn.altered = newColumn.altered || 2"
:disabled="sqlUi.colPropUNDisabled(newColumn) || !sqlUi.columnEditable(newColumn)"
class="mr-2 mt-0" dense hide-details label="AI"
v-model="newColumn.ai">
<template v-slot:label>
<span class="caption font-weight-bold">AI</span>
</template>
</v-checkbox>
</div>
</template>
<span>Auto Increment</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox class="mr-2 mt-0" dense hide-details label="UN"
@input="newColumn.altered = newColumn.altered || 2"
:disabled="sqlUi.colPropUNDisabled(newColumn) || !sqlUi.columnEditable(newColumn)"
v-model="newColumn.un">
<template v-slot:label>
<span class="caption font-weight-bold">UN</span>
</template>
</v-checkbox>
</div>
</template>
<span>Unsigned</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox class="mr-2 mt-0" dense hide-details label="UN"
@input="newColumn.altered = newColumn.altered || 2"
:disabled=" sqlUi.colPropAuDisabled(newColumn) || !sqlUi.columnEditable(newColumn)"
v-model="newColumn.au">
<template v-slot:label>
<span class="caption font-weight-bold">AU</span>
</template>
</v-checkbox>
</div>
</template>
<span>Auto Update Timestamp</span>
</v-tooltip>
</div>
</v-col>
<v-col cols="12">
<v-autocomplete
v-model="newColumn.dt"
hide-details
class="caption data-type"
label="Type in Database"
dense
outlined
:items="dataTypes">
</v-autocomplete>
</v-col>
<v-col :cols="sqlUi.showScale(newColumn) && !isSelect ? 6 : 12">
<v-text-field
v-if="!isSelect"
dense
:disabled="sqlUi.getDefaultLengthIsDisabled(newColumn.dt) || !sqlUi.columnEditable(newColumn)"
class="caption"
label="Length / Values"
outlined
hide-details v-model="newColumn.dtxp"
@input="newColumn.altered = newColumn.altered || 2"
></v-text-field>
</v-col>
<v-col :cols="isSelect ?12 : 6" v-if="sqlUi.showScale(newColumn)">
<v-text-field
dense
:disabled=" !sqlUi.columnEditable(newColumn)"
class="caption"
label="Scale"
outlined
@input="newColumn.altered = newColumn.altered || 2"
hide-details v-model="newColumn.dtxs"></v-text-field>
</v-col>
<v-col cols="12">
<v-textarea v-model="newColumn.cdf"
@input="newColumn.altered = newColumn.altered || 2" @input="newColumn.altered = newColumn.altered || 2"
label="Default value" :disabled="sqlUi.colPropUNDisabled(newColumn) || !sqlUi.columnEditable(newColumn)"
:hint="sqlUi.getDefaultValueForDatatype(newColumn.dt)" class="mr-2 mt-0" dense hide-details label="AI"
persistent-hint v-model="newColumn.ai">
rows="3" <template v-slot:label>
outlined dense class="caption"></v-textarea> <span class="caption font-weight-bold">AI</span>
</v-col> </template>
</v-row> </v-checkbox>
</v-container> </div>
</template>
<span>Auto Increment</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox class="mr-2 mt-0" dense hide-details label="UN"
@input="newColumn.altered = newColumn.altered || 2"
:disabled="sqlUi.colPropUNDisabled(newColumn) || !sqlUi.columnEditable(newColumn)"
v-model="newColumn.un">
<template v-slot:label>
<span class="caption font-weight-bold">UN</span>
</template>
</v-checkbox>
</div>
</template>
<span>Unsigned</span>
</v-tooltip>
<v-tooltip bottom z-index="99999">
<template v-slot:activator="{on}">
<div v-on="on">
<v-checkbox class="mr-2 mt-0" dense hide-details label="UN"
@input="newColumn.altered = newColumn.altered || 2"
:disabled=" sqlUi.colPropAuDisabled(newColumn) || !sqlUi.columnEditable(newColumn)"
v-model="newColumn.au">
<template v-slot:label>
<span class="caption font-weight-bold">AU</span>
</template>
</v-checkbox>
</div>
</template>
<span>Auto Update Timestamp</span>
</v-tooltip>
</div>
</v-col>
<v-col cols="12">
<v-autocomplete
v-model="newColumn.dt"
hide-details
class="caption data-type"
label="Type in Database"
dense
outlined
:items="dataTypes">
</v-autocomplete>
</v-col>
<v-col :cols="sqlUi.showScale(newColumn) && !isSelect ? 6 : 12">
<v-text-field
v-if="!isSelect"
dense
:disabled="sqlUi.getDefaultLengthIsDisabled(newColumn.dt) || !sqlUi.columnEditable(newColumn)"
class="caption"
label="Length / Values"
outlined
hide-details v-model="newColumn.dtxp"
@input="newColumn.altered = newColumn.altered || 2"
></v-text-field>
</v-col>
<v-col :cols="isSelect ?12 : 6" v-if="sqlUi.showScale(newColumn)">
<v-text-field
dense
:disabled=" !sqlUi.columnEditable(newColumn)"
class="caption"
label="Scale"
outlined
@input="newColumn.altered = newColumn.altered || 2"
hide-details v-model="newColumn.dtxs"></v-text-field>
</v-col>
<v-col cols="12">
<v-textarea v-model="newColumn.cdf"
@input="newColumn.altered = newColumn.altered || 2"
label="Default value"
:hint="sqlUi.getDefaultValueForDatatype(newColumn.dt)"
persistent-hint
rows="3"
outlined dense class="caption"></v-textarea>
</v-col>
</v-row>
</v-container>
</v-col>
</template>
</template>
<template v-else>
<v-col cols12>
<v-autocomplete
label="Formula"
hide-details
class="caption formula-type"
outlined
dense
:items="formulas"
>
<template v-slot:item="{item}">
<span class="green--text text--darken-2 caption font-weight-regular">{{ item }}</span>
</template>
</v-autocomplete>
</v-col> </v-col>
</template> </template>
</template> </template>
<template v-else>
<v-col cols12>
<v-autocomplete
label="Formula"
hide-details
class="caption formula-type"
outlined
dense
:items="formulas"
>
<template v-slot:item="{item}">
<span class="green--text text--darken-2 caption font-weight-regular">{{ item }}</span>
</template>
</v-autocomplete> <div class="disabled-info" :class="{'d-none':!isEditDisabled}">
</v-col> <v-alert dense type="warning" icon="info" class="caption mx-2" outlined>
</template> This spreadsheet is connected to an SQLite DB.<br>
</template> For production please see <a href="https://github.com/nocodb/nocodb#production-setup"
target="_blank">here</a>.
<div class="disabled-info" :class="{'d-none':!isEditDisabled}"> </v-alert>
<v-alert dense type="warning" icon="info" class="caption mx-2" outlined> </div>
This spreadsheet is connected to an SQLite DB.<br>
For production please see <a href="https://github.com/nocodb/nocodb#production-setup"
target="_blank">here</a>.
</v-alert>
</div> </div>
</div>
</v-row>
</v-container>
</v-row>
</v-container>
</v-form>
<dlg-label-submit-cancel <dlg-label-submit-cancel
type="primary" type="primary"
v-if="relationDeleteDlg" v-if="relationDeleteDlg"
@ -290,6 +292,7 @@
:actionsMtd="deleteRelation" :actionsMtd="deleteRelation"
heading="Click Submit to Delete the Relation" heading="Click Submit to Delete the Relation"
/> />
</v-card> </v-card>
</template> </template>
@ -314,6 +317,7 @@ export default {
value: Boolean value: Boolean
}, },
data: () => ({ data: () => ({
valid: false,
relationDeleteDlg: false, relationDeleteDlg: false,
newColumn: {}, newColumn: {},
uiTypes, uiTypes,
@ -489,7 +493,10 @@ export default {
}, },
computed: { computed: {
isEditDisabled() { isEditDisabled() {
return this.editColumn && this.sqlUi === SqliteUi; return this.editColumn && this.isSQLite && !this.relation;
},
isSQLite() {
return this.sqlUi === SqliteUi
}, },
dataTypes() { dataTypes() {
return this.sqlUi.getDataTypeListForUiType(this.newColumn) return this.sqlUi.getDataTypeListForUiType(this.newColumn)

19
packages/nc-gui/components/project/spreadsheet/editColumn/relationOptions.vue

@ -3,6 +3,7 @@
<v-row> <v-row>
<v-col cols="6"> <v-col cols="6">
<v-autocomplete <v-autocomplete
:rules="[v=>!!v || 'Reference Table required']"
outlined outlined
class="caption" class="caption"
hide-details hide-details
@ -21,6 +22,7 @@
> >
<v-col cols="6"> <v-col cols="6">
<v-autocomplete <v-autocomplete
:rules="[v=>!!v || 'Reference Column required']"
outlined outlined
class="caption" class="caption"
hide-details hide-details
@ -76,6 +78,7 @@
<v-col> <v-col>
<v-checkbox <v-checkbox
:disabled="isSQLite"
false-value="real" false-value="real"
true-value="virtual" true-value="virtual"
label="Virtual Relation" label="Virtual Relation"
@ -94,7 +97,7 @@
<script> <script>
export default { export default {
name: "relationOptions", name: "relationOptions",
props: ['nodes', 'column'], props: ['nodes', 'column', 'isSQLite'],
data: () => ({ data: () => ({
refTables: [], refTables: [],
refColumns: [], refColumns: [],
@ -119,7 +122,7 @@ export default {
onDelete: "CASCADE", onDelete: "CASCADE",
onUpdate: "CASCADE", onUpdate: "CASCADE",
updateRelation: this.column.rtn ? true : false, updateRelation: this.column.rtn ? true : false,
type: 'real' type: this.isSQLite ? 'virtual' : 'real'
} }
}, },
methods: { methods: {
@ -160,7 +163,7 @@ export default {
}, 'tableList']); }, 'tableList']);
this.refTables = result.data.list.map(({tn,_tn}) => ({tn,_tn})) this.refTables = result.data.list.map(({tn, _tn}) => ({tn, _tn}))
this.isRefTablesLoading = false; this.isRefTablesLoading = false;
}, },
async saveRelation() { async saveRelation() {
@ -170,7 +173,7 @@ export default {
env: this.nodes.env, env: this.nodes.env,
dbAlias: this.nodes.dbAlias dbAlias: this.nodes.dbAlias
}, },
this.relation.type === 'real' ? "relationCreate" : 'xcVirtualRelationCreate', this.relation.type === 'real' && !this.isSQLite ? "relationCreate" : 'xcVirtualRelationCreate',
this.relation this.relation
]); ]);
} catch (e) { } catch (e) {
@ -183,9 +186,15 @@ export default {
} }
}, },
watch: { watch: {
'column.cn': (c) => { 'column.cn': function (c) {
this.$set(this.relation, 'childColumn', c); this.$set(this.relation, 'childColumn', c);
},
isSQLite(v) {
this.$set(this.relation, 'type', v ? 'virtual' : 'real');
} }
},
mounted() {
this.$set(this.relation, 'type', this.isSqlite ? 'virtual' : 'real');
} }
} }
</script> </script>

2
packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js

@ -130,7 +130,7 @@ export default {
}, },
belongsTo() { belongsTo() {
return this.meta && this.meta.belongsTo ? this.meta.belongsTo.reduce((bt, o) => { return this.meta && this.meta.belongsTo ? this.meta.belongsTo.reduce((bt, o) => {
const _cn = this.meta.columns.find(c => c.cn === o.cn)._cn const _cn = (this.meta.columns.find(c => c.cn === o.cn)||{})._cn
bt[_cn] = o; bt[_cn] = o;
return bt; return bt;
}, {}) : {}; }, {}) : {};

Loading…
Cancel
Save