Merge pull request #2879 from RodrigoPerestrelo/fix-select-copy-relation-names

Fix #2489: Cannot select / copy relation names in UI
This commit is contained in:
Day Matchullis
2025-03-21 19:24:55 -06:00
committed by GitHub
4 changed files with 57 additions and 17 deletions

View File

@@ -126,6 +126,7 @@ import { mapGetters, mapState } from 'vuex'
const log = rawLog.scope('TableIndexVue')
import { escapeHtml } from '@shared/lib/tabulator'
import { parseIndexColumn as mysqlParseIndexColumn } from '@/common/utils'
import { SelectableCellMixin } from '@/mixins/selectableCell';
interface State {
mysqlTypes: string[]
@@ -141,7 +142,7 @@ export default Vue.extend({
StatusBar,
ErrorAlert,
},
mixins: [data_mutators],
mixins: [data_mutators, SelectableCellMixin],
props: ["table", "tabId", "active", "properties", 'tabState'],
data(): State {
return {
@@ -213,13 +214,14 @@ export default Vue.extend({
tableColumns() {
const editable = (cell) => this.newRows.includes(cell.getRow()) && !this.loading
const result = [
(this.dialectData?.disabledFeatures?.index?.id ? null : {title: 'Id', field: 'id', widthGrow: 0.5}),
(this.dialectData?.disabledFeatures?.index?.id ? null : {title: 'Id', field: 'id', widthGrow: 0.5, cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)}),
{
title:'Name',
field: 'name',
editable,
editor: vueEditor(NullableInputEditorVue),
formatter: this.cellFormatter,
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell),
},
{
title: 'Unique',
@@ -251,7 +253,8 @@ export default Vue.extend({
autocomplete: true,
listOnEmpty: true,
freetext: true,
}
},
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
trashButton(this.removeRow)
]
@@ -381,7 +384,6 @@ export default Vue.extend({
// headerSort: false,
// })
}
},
mounted() {
// this.initializeTabulator()

View File

@@ -115,8 +115,10 @@ import rawLog from '@bksLogger'
import ErrorAlert from '../common/ErrorAlert.vue'
const log = rawLog.scope('TableRelations');
import { escapeHtml } from '@shared/lib/tabulator'
import { SelectableCellMixin } from '@/mixins/selectableCell';
export default Vue.extend({
mixins: [SelectableCellMixin],
props: ["table", "tabId", "active", "properties", 'tabState'],
components: {
StatusBar,
@@ -185,7 +187,7 @@ export default Vue.extend({
widthGrow: 2,
editable,
editor: vueEditor(NullableInputEditorVue),
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
{
field: 'fromColumn',
@@ -195,7 +197,8 @@ export default Vue.extend({
editorParams: {
// @ts-expect-error Incorrectly typed
valuesLookup: () => this.table.columns.map((c) => escapeHtml(c.columnName))
}
},
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
...( showSchema ? [{
field: 'toSchema',
@@ -217,7 +220,8 @@ export default Vue.extend({
// @ts-expect-error Incorrectly typed
valuesLookup: this.getTables
},
cellEdited: (cell) => cell.getRow().getCell('toColumn')?.setValue(null)
cellEdited: (cell) => cell.getRow().getCell('toColumn')?.setValue(null),
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
{
field: 'toColumn',
@@ -228,6 +232,7 @@ export default Vue.extend({
// @ts-expect-error Incorrectly typed
valuesLookup: this.getColumns
},
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
{
field: 'onUpdate',
@@ -237,7 +242,8 @@ export default Vue.extend({
editorParams: {
values: this.dialectData.constraintActions,
defaultValue: 'NO ACTION'
}
},
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
{
field: 'onDelete',
@@ -248,7 +254,8 @@ export default Vue.extend({
editorParams: {
values: this.dialectData.constraintActions,
defaultValue: 'NO ACTION',
}
},
cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)
},
]
return this.canDrop ? [...results, trashButton(this.removeRow)] : results

View File

@@ -41,12 +41,14 @@ import {Tabulator, TabulatorFull} from 'tabulator-tables'
import data_mutators from '../../mixins/data_mutators'
import StatusBar from '../common/StatusBar.vue'
import { mapGetters, mapState } from 'vuex'
import { SelectableCellMixin } from '@/mixins/selectableCell';
export default {
components: {
StatusBar,
},
mixins: [data_mutators],
mixins: [data_mutators, SelectableCellMixin],
props: ["table", "tabId", "active", "properties"],
data() {
return {
@@ -65,17 +67,17 @@ export default {
},
sqliteTableColumns() {
return [
{ field: 'name', title: 'Name', tooltip: true},
{ field: 'sql', title: 'SQL', tooltip: true}
{ field: 'name', title: 'Name', tooltip: true, cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)},
{ field: 'sql', title: 'SQL', tooltip: true, cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)}
]
},
normalTableColumns() {
return [
{ field: 'name', title: "Name", tooltip: true},
{ field: 'timing', title: "Timing"},
{ field: 'manipulation', title: "Manipulation"},
{ field: 'action', title: "Action", tooltip: true, widthGrow: 2.5},
{ field: 'condition', title: "Condition", formatter: this.cellFormatter}
{ field: 'name', title: "Name", tooltip: true, cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)},
{ field: 'timing', title: "Timing", cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)},
{ field: 'manipulation', title: "Manipulation", cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)},
{ field: 'action', title: "Action", tooltip: true, widthGrow: 2.5, cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)},
{ field: 'condition', title: "Condition", formatter: this.cellFormatter, cellDblClick: (e, cell) => this.handleCellDoubleClick(cell)}
]
},
tableData() {

View File

@@ -0,0 +1,29 @@
export const SelectableCellMixin = {
methods: {
handleCellDoubleClick(cell) {
const element = cell.getElement();
// If already editable, remove contenteditable and stop execution
if (element.hasAttribute("contenteditable")) {
element.removeAttribute("contenteditable");
window.getSelection().removeAllRanges();
return;
}
// Enable text selection
element.setAttribute("contenteditable", "true");
element.focus();
document.execCommand("selectAll");
const removeEditable = () => {
element.removeAttribute("contenteditable");
window.getSelection().removeAllRanges();
document.removeEventListener("click", removeEditable);
};
setTimeout(() => {
document.addEventListener("click", removeEditable);
}, 0);
}
}
}