mirror of
https://github.com/beekeeper-studio/beekeeper-studio.git
synced 2026-03-13 10:12:54 +08:00
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:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
29
apps/studio/src/mixins/selectableCell.ts
Normal file
29
apps/studio/src/mixins/selectableCell.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user