diff --git a/CHANGELOG.md b/CHANGELOG.md index 980f438d3..2c2387412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # ChangeLog +### 4.2.6 + - Fixed MongoDB import + - Configurable thousands separator #136 + - Using case insensitive text search in postgres + ### 4.2.5 - FIXED: Fixed crash when using large model on some installations - FIXED: Postgre SQL CREATE function diff --git a/README.md b/README.md index a818c4565..22a4ff147 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ There are many database managers now, so why DbGate? * Backend - NodeJs, ExpressJs, socket.io, database connection drivers * JavaScript + TypeScript * App - electron -* Platform independed - will run as web application in single docker container on server, or as application using Electron platform on Linux, Windows and Mac +* Platform independent - will run as web application in single docker container on server, or as application using Electron platform on Linux, Windows and Mac ## Plugins Plugins are standard NPM packages published on [npmjs.com](https://www.npmjs.com). diff --git a/package.json b/package.json index 7dc596f42..4658893ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "4.2.6-beta.2", + "version": "4.2.7", "name": "dbgate-all", "workspaces": [ "packages/*", diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index 9b5678a82..714da9384 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -75,6 +75,7 @@ export abstract class GridDisplay { } changeSetKeyFields: string[] = null; sortable = false; + groupable = false; filterable = false; editable = false; isLoadedCorrectly = true; diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index 46bc64d5a..044f5aa65 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -35,6 +35,7 @@ export class TableGridDisplay extends GridDisplay { this.columns = this.getDisplayColumns(this.table, []); this.filterable = true; this.sortable = true; + this.groupable = true; this.editable = true; this.supportsReload = true; this.baseTable = this.table; diff --git a/packages/datalib/src/ViewGridDisplay.ts b/packages/datalib/src/ViewGridDisplay.ts index bc785426b..f8d24e756 100644 --- a/packages/datalib/src/ViewGridDisplay.ts +++ b/packages/datalib/src/ViewGridDisplay.ts @@ -17,6 +17,7 @@ export class ViewGridDisplay extends GridDisplay { this.columns = this.getDisplayColumns(view); this.filterable = true; this.sortable = true; + this.groupable = true; this.editable = false; this.supportsReload = true; } diff --git a/packages/web/src/appobj/AppObjectCore.svelte b/packages/web/src/appobj/AppObjectCore.svelte index facb0e1d9..7370635ae 100644 --- a/packages/web/src/appobj/AppObjectCore.svelte +++ b/packages/web/src/appobj/AppObjectCore.svelte @@ -38,6 +38,14 @@ } } + function handleMouseUp(e) { + if (e.button == 1) { + dispatch('middleclick'); + e.preventDefault(); + e.stopPropagation(); + } + } + function setChecked(value) { if (!value && isChecked) { checkedObjectsStore.update(x => x.filter(y => module.extractKey(data) != module.extractKey(y))); @@ -53,6 +61,7 @@ class:isBold draggable={true} on:click={handleClick} + on:mouseup={handleMouseUp} use:contextMenu={disableContextMenu ? null : menu} on:dragstart={e => { e.dataTransfer.setData('app_object_drag_data', JSON.stringify(data)); diff --git a/packages/web/src/appobj/ConnectionAppObject.svelte b/packages/web/src/appobj/ConnectionAppObject.svelte index 1d4f07612..829a8c85e 100644 --- a/packages/web/src/appobj/ConnectionAppObject.svelte +++ b/packages/web/src/appobj/ConnectionAppObject.svelte @@ -123,7 +123,7 @@ text: 'Connect', onClick: handleConnect, }, - { onClick: handleNewQuery, text: 'New query' }, + { onClick: handleNewQuery, text: 'New query', isNewQuery: true }, $openedConnections.includes(data._id) && data.status && { text: 'Refresh', @@ -190,4 +190,9 @@ on:click={handleConnect} on:click on:expand + on:middleclick={() => { + _.flattenDeep(getContextMenu()) + .find(x => x.isNewQuery) + .onClick(); + }} /> diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte index 53a7f97a6..f275c5987 100644 --- a/packages/web/src/appobj/DatabaseAppObject.svelte +++ b/packages/web/src/appobj/DatabaseAppObject.svelte @@ -54,7 +54,7 @@ }; return [ - { onClick: handleNewQuery, text: 'New query' }, + { onClick: handleNewQuery, text: 'New query', isNewQuery: true }, { onClick: handleImport, text: 'Import' }, { onClick: handleExport, text: 'Export' }, { onClick: handleSqlGenerator, text: 'SQL Generator' }, @@ -68,7 +68,7 @@ handleClick()} + on:middleclick={() => handleClick(true)} on:expand /> diff --git a/packages/web/src/datagrid/ColumnHeaderControl.svelte b/packages/web/src/datagrid/ColumnHeaderControl.svelte index e6f0a2a1d..715925ef6 100644 --- a/packages/web/src/datagrid/ColumnHeaderControl.svelte +++ b/packages/web/src/datagrid/ColumnHeaderControl.svelte @@ -6,6 +6,7 @@ import ColumnLabel from '../elements/ColumnLabel.svelte'; import { isTypeDateTime } from 'dbgate-tools'; import { openDatabaseObjectDetail } from '../appobj/DatabaseObjectAppObject.svelte'; + import { copyTextToClipboard } from '../utility/clipboard'; export let column; export let conid = undefined; @@ -27,19 +28,20 @@ function getMenu() { return [ - { onClick: () => setSort('ASC'), text: 'Sort ascending' }, - { onClick: () => setSort('DESC'), text: 'Sort descending' }, + setSort && { onClick: () => setSort('ASC'), text: 'Sort ascending' }, + setSort && { onClick: () => setSort('DESC'), text: 'Sort descending' }, + { onClick: () => copyTextToClipboard(column.columnName), text: 'Copy column name' }, column.foreignKey && [{ divider: true }, { onClick: openReferencedTable, text: column.foreignKey.refTableName }], - { divider: true }, - { onClick: () => setGrouping('GROUP'), text: 'Group by' }, - { onClick: () => setGrouping('MAX'), text: 'MAX' }, - { onClick: () => setGrouping('MIN'), text: 'MIN' }, - { onClick: () => setGrouping('SUM'), text: 'SUM' }, - { onClick: () => setGrouping('AVG'), text: 'AVG' }, - { onClick: () => setGrouping('COUNT'), text: 'COUNT' }, - { onClick: () => setGrouping('COUNT DISTINCT'), text: 'COUNT DISTINCT' }, + setGrouping && { divider: true }, + setGrouping && { onClick: () => setGrouping('GROUP'), text: 'Group by' }, + setGrouping && { onClick: () => setGrouping('MAX'), text: 'MAX' }, + setGrouping && { onClick: () => setGrouping('MIN'), text: 'MIN' }, + setGrouping && { onClick: () => setGrouping('SUM'), text: 'SUM' }, + setGrouping && { onClick: () => setGrouping('AVG'), text: 'AVG' }, + setGrouping && { onClick: () => setGrouping('COUNT'), text: 'COUNT' }, + setGrouping && { onClick: () => setGrouping('COUNT DISTINCT'), text: 'COUNT DISTINCT' }, isTypeDateTime(column.dataType) && [ { divider: true }, diff --git a/packages/web/src/datagrid/DataGridCell.svelte b/packages/web/src/datagrid/DataGridCell.svelte index 454dfa4ef..ee7bf99af 100644 --- a/packages/web/src/datagrid/DataGridCell.svelte +++ b/packages/web/src/datagrid/DataGridCell.svelte @@ -12,7 +12,8 @@ return value; } - const dateTimeRegex = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\d)?Z?$/; + // const dateTimeRegex = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\d)?Z?$/; + const dateTimeRegex = /^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|()|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$/; function formatNumber(value) { if (value >= 10000 || value <= -10000) { @@ -25,12 +26,15 @@ return value.toString(); } + + function formatDateTime(testedString) { + const m = testedString.match(dateTimeRegex); + return `${m[1]}-${m[2]}-${m[3]} ${m[4]}:${m[5]}:${m[6]}`; + }