1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-06-05 21:59:22 +02:00

Compare commits

..

20 Commits

Author SHA1 Message Date
275344eb8b chore(release): 0.7.19-beta.1 2023-10-26 01:07:15 +02:00
cf24adf99e Merge branch 'develop' of https://github.com/antares-sql/antares into beta 2023-10-26 01:06:54 +02:00
2eae580e18 chore: update electron 2023-10-22 19:04:31 +02:00
e4eb27d503 feat(MySQL): RLIKE and NOT RLIKE regular expression filters, closes #688 2023-10-18 18:08:01 +02:00
580973fd04 chore(release): 0.7.19-beta.0 2023-10-14 15:04:00 +02:00
215ab783ab chore: email change 2023-10-14 15:03:09 +02:00
72148e991c Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-10-13 09:23:41 +02:00
6e4c16741a chore: Update CODE_OF_CONDUCT.md 2023-10-13 09:22:04 +02:00
9f9c63bfcc feat: "now" and "random" options added in datetime related data in insert rows tool, closes #402 2023-10-10 18:36:35 +02:00
c0dcf30e73 fix: IN and NOT IN filters not working properly, fixes #687 2023-10-09 18:13:30 +02:00
ddd290c903 fix: timeout issue on long time sql import 2023-10-03 18:19:16 +02:00
267c017921 chore(release): 0.7.18 2023-10-03 09:31:58 +02:00
b3b698b3a2 fix: hotfix for Microsoft Store unauthorized process 2023-10-03 09:31:26 +02:00
71ac3a5164 chore(release): 0.7.17 2023-09-30 16:46:49 +02:00
6fc4418c02 chore(release): 0.7.17-beta.2 2023-09-28 18:11:10 +02:00
b37781df84 fix(UI): small icons in foreign key modal 2023-09-26 18:31:58 +02:00
9c66fd51cb feat: add NOT LIKE to table filters, closes #672 2023-09-25 18:16:07 +02:00
98c1f43a4d refactor: removed icon fonts in ace editor 2023-09-25 18:14:21 +02:00
12825c69d4 Merge branch 'beta' of https://github.com/antares-sql/antares into develop 2023-09-24 23:06:01 +02:00
198ff0103b fix: nsis updater not working 2023-09-24 23:04:35 +02:00
40 changed files with 268 additions and 156 deletions

View File

@@ -2,6 +2,48 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.7.19-beta.1](https://github.com/antares-sql/antares/compare/v0.7.19-beta.0...v0.7.19-beta.1) (2023-10-25)
### Features
* **MySQL:** RLIKE and NOT RLIKE regular expression filters, closes [#688](https://github.com/antares-sql/antares/issues/688) ([e4eb27d](https://github.com/antares-sql/antares/commit/e4eb27d503e8f912178359c01c62a9b523d17848))
### [0.7.19-beta.0](https://github.com/antares-sql/antares/compare/v0.7.18...v0.7.19-beta.0) (2023-10-14)
### Features
* "now" and "random" options added in datetime related data in insert rows tool, closes [#402](https://github.com/antares-sql/antares/issues/402) ([9f9c63b](https://github.com/antares-sql/antares/commit/9f9c63bfcc3423bfeef143cd835f48c62900a799))
### Bug Fixes
* IN and NOT IN filters not working properly, fixes [#687](https://github.com/antares-sql/antares/issues/687) ([c0dcf30](https://github.com/antares-sql/antares/commit/c0dcf30e73a69b25b01ba31d21b27c1983ed2db6))
* timeout issue on long time sql import ([ddd290c](https://github.com/antares-sql/antares/commit/ddd290c90344241eaa70cb528552e942fd7edec0))
### [0.7.18](https://github.com/antares-sql/antares/compare/v0.7.17...v0.7.18) (2023-10-03)
### Bug Fixes
* hotfix for Microsoft Store unauthorized process ([b3b698b](https://github.com/antares-sql/antares/commit/b3b698b3a23a3c848921ab40fc0fec5d8178ef0e))
### [0.7.17](https://github.com/antares-sql/antares/compare/v0.7.17-beta.2...v0.7.17) (2023-09-30)
### [0.7.17-beta.2](https://github.com/antares-sql/antares/compare/v0.7.17-beta.1...v0.7.17-beta.2) (2023-09-28)
### Features
* add NOT LIKE to table filters, closes [#672](https://github.com/antares-sql/antares/issues/672) ([9c66fd5](https://github.com/antares-sql/antares/commit/9c66fd51cbbe6f21a1fa6a34cc962496d3db7a98))
### Bug Fixes
* nsis updater not working ([198ff01](https://github.com/antares-sql/antares/commit/198ff0103bfa95e3491296d352c944165f31b87e))
* **UI:** small icons in foreign key modal ([b37781d](https://github.com/antares-sql/antares/commit/b37781df84cf7ee99a69ecaa54480d662d79c4aa))
### [0.7.17-beta.1](https://github.com/antares-sql/antares/compare/v0.7.17-beta.0...v0.7.17-beta.1) (2023-09-23)

View File

@@ -61,7 +61,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
fabio286@gmail.com.
info@fabiodistasio.it.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

18
package-lock.json generated
View File

@@ -1,19 +1,18 @@
{
"name": "antares",
"version": "0.7.17-beta.1",
"version": "0.7.19-beta.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "antares",
"version": "0.7.17-beta.1",
"version": "0.7.19-beta.1",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@electron/remote": "~2.0.1",
"@faker-js/faker": "~6.1.2",
"@jamescoyle/vue-icon": "~0.1.2",
"@mdi/font": "~7.2.96",
"@mdi/js": "~7.2.96",
"@turf/helpers": "~6.5.0",
"@vueuse/core": "~10.4.1",
@@ -64,7 +63,7 @@
"chalk": "~4.1.2",
"cross-env": "~7.0.2",
"css-loader": "~6.5.0",
"electron": "~22.3.23",
"electron": "~22.3.27",
"electron-builder": "~22.10.3",
"eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3",
@@ -2107,11 +2106,6 @@
"node": ">= 10"
}
},
"node_modules/@mdi/font": {
"version": "7.2.96",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.2.96.tgz",
"integrity": "sha512-e//lmkmpFUMZKhmCY9zdjRe4zNXfbOIJnn6xveHbaV2kSw5aJ5dLXUxcRt1Gxfi7ZYpFLUWlkG2MGSFAiqAu7w=="
},
"node_modules/@mdi/js": {
"version": "7.2.96",
"resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.2.96.tgz",
@@ -5750,9 +5744,9 @@
}
},
"node_modules/electron": {
"version": "22.3.23",
"resolved": "https://registry.npmjs.org/electron/-/electron-22.3.23.tgz",
"integrity": "sha512-2p6NsLFPfM2RmgATchjKZKBUP3O6NxQMWOrHt9W5U2GRtfI8qWlicUR1wnh5D1VLt4c1YsjvpF6dct+1JNRubA==",
"version": "22.3.27",
"resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz",
"integrity": "sha512-7Rht21vHqj4ZFRnKuZdFqZFsvMBCmDqmjetiMqPtF+TmTBiGne1mnstVXOA/SRGhN2Qy5gY5bznJKpiqogjM8A==",
"hasInstallScript": true,
"dependencies": {
"@electron/get": "^2.0.0",

View File

@@ -1,7 +1,7 @@
{
"name": "antares",
"productName": "Antares",
"version": "0.7.17-beta.1",
"version": "0.7.19-beta.1",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT",
"repository": "https://github.com/antares-sql/antares.git",
@@ -27,7 +27,7 @@
"contributors:add": "all-contributors add",
"contributors:generate": "all-contributors generate"
},
"author": "Fabio Di Stasio <fabio286@gmail.com>",
"author": "Fabio Di Stasio <info@fabiodistasio.it>",
"main": "./dist/main.js",
"antares": {
"devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd"
@@ -121,7 +121,6 @@
"@electron/remote": "~2.0.1",
"@faker-js/faker": "~6.1.2",
"@jamescoyle/vue-icon": "~0.1.2",
"@mdi/font": "~7.2.96",
"@mdi/js": "~7.2.96",
"@turf/helpers": "~6.5.0",
"@vueuse/core": "~10.4.1",
@@ -172,7 +171,7 @@
"chalk": "~4.1.2",
"cross-env": "~7.0.2",
"css-loader": "~6.5.0",
"electron": "~22.3.23",
"electron": "~22.3.27",
"electron-builder": "~22.10.3",
"eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3",

View File

@@ -51,6 +51,7 @@ export default class {
{ name: 'collation', group: 'database', types: ['string'] },
{ name: 'engine', group: 'database', types: ['string'] },
{ name: 'now', group: 'date', types: ['string', 'datetime'] },
{ name: 'past', group: 'date', types: ['string', 'datetime'] },
{ name: 'future', group: 'date', types: ['string', 'datetime'] },
// { name: 'between', group: 'date', types: ['string'] },
@@ -161,7 +162,9 @@ export default class {
{ name: 'filePath', group: 'system', types: ['string'] },
{ name: 'semver', group: 'system', types: ['string'] },
{ name: 'now', group: 'time', types: ['string', 'time'] },
{ name: 'recent', group: 'time', types: ['string', 'time'] },
{ name: 'random', group: 'time', types: ['string', 'time'] },
{ name: 'vehicle', group: 'vehicle', types: ['string'] },
{ name: 'manufacturer', group: 'vehicle', types: ['string'] },

View File

@@ -9,6 +9,7 @@ export const defaults: Customizations = {
dataTypes: [],
indexTypes: [],
foreignActions: [],
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
// Core
database: false,
collations: false,

View File

@@ -9,6 +9,7 @@ export const customizations: Customizations = {
defaultUser: 'root',
defaultDatabase: null,
dataTypes: mysqlTypes,
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'RLIKE', 'NOT RLIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
indexTypes: [
'PRIMARY',
'INDEX',

View File

@@ -363,8 +363,7 @@ export interface QueryBuilderObject {
offset: number;
join: string[];
update: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
insert: {[key: string]: any}[];
insert: {[key: string]: string | boolean | number }[];
delete: boolean;
}

View File

@@ -1,4 +1,5 @@
import { TypesGroup } from './antares';
import { TableFilterOperator } from './tableApis';
export interface Customizations {
// Defaults
@@ -8,6 +9,7 @@ export interface Customizations {
dataTypes?: TypesGroup[];
indexTypes?: string[];
foreignActions?: string[];
operators?: TableFilterOperator[];
// Core
database?: boolean;
collations?: boolean;

View File

@@ -21,10 +21,12 @@ export interface TableDeleteParams {
rows: {[key: string]: any};
}
export type TableFilterOperator = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'NOT LIKE' | 'RLIKE' | 'NOT RLIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL'
export interface TableFilterClausole {
active: boolean;
field: string;
op: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL';
op:TableFilterOperator;
value: '';
value2: '';
}

View File

@@ -0,0 +1,17 @@
import { faker } from '@faker-js/faker';
import * as moment from 'moment';
export const fakerCustom = {
seed: faker.seed,
setLocale: faker.setLocale,
...faker,
date: {
now: () => moment().format('YYYY-MM-DD HH:mm:ss'),
...faker.date
},
time: {
now: () => moment().format('HH:mm:ss'),
random: () => moment(faker.date.recent()).format('HH:mm:ss'),
...faker.time
}
};

View File

@@ -1,8 +1,8 @@
import { faker } from '@faker-js/faker';
import customizations from 'common/customizations';
import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import { InsertRowsParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { sqlEscaper } from 'common/libs/sqlUtils';
import { ipcMain } from 'electron';
import * as fs from 'fs';
@@ -371,19 +371,19 @@ export default (connections: {[key: string]: antares.Client}) => {
let fakeValue;
if (params.locale)
faker.locale = params.locale;
fakerCustom.locale = params.locale;
if (Object.keys(params.row[key].params).length) {
Object.keys(params.row[key].params).forEach(param => {
if (!isNaN(params.row[key].params[param]))
parsedParams[param] = +params.row[key].params[param];
if (!isNaN(params.row[key].params[param]))// Converts string numerics params to number
parsedParams[param] = Number(params.row[key].params[param]);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](parsedParams);
fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method](parsedParams);
}
else
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method]();
fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method]();
if (typeof fakeValue === 'string') {
if (params.row[key].length)

View File

@@ -2,8 +2,6 @@ import { ipcMain } from 'electron';
import * as Store from 'electron-store';
import { autoUpdater } from 'electron-updater';
import { validateSender } from '../libs/misc/validateSender';
const persistentStore = new Store({
name: 'settings',
clearInvalidConfig: true,
@@ -20,8 +18,6 @@ autoUpdater.allowPrerelease = persistentStore.get('allow_prerelease', false) as
export default () => {
ipcMain.on('check-for-updates', event => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
mainWindow = event;
if (process.windowsStore || (process.platform === 'linux' && !process.env.APPIMAGE))
mainWindow.reply('no-auto-update');
@@ -35,38 +31,31 @@ export default () => {
}
});
ipcMain.on('restart-to-update', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
ipcMain.on('restart-to-update', () => {
autoUpdater.quitAndInstall();
});
// auto-updater events
autoUpdater.on('checking-for-update', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('checking-for-update', () => {
mainWindow.reply('checking-for-update');
});
autoUpdater.on('update-available', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('update-available', () => {
if (isMacOS)
mainWindow.reply('link-to-download');
else
mainWindow.reply('update-available');
});
autoUpdater.on('update-not-available', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('update-not-available', () => {
mainWindow.reply('update-not-available');
});
autoUpdater.on('download-progress', event => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
mainWindow.reply('download-progress', event);
});
autoUpdater.on('update-downloaded', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('update-downloaded', () => {
mainWindow.reply('update-downloaded');
});

View File

@@ -256,9 +256,12 @@ export class MySQLClient extends AntaresCore {
}
private async keepAlive () {
const connection = await (this._connection as mysql.Pool).getConnection();
await connection.ping();
connection.release();
try {
const connection = await (this._connection as mysql.Pool).getConnection();
await connection.ping();
connection.release();
}
catch (_) {}
}
use (schema: string) {

View File

@@ -240,9 +240,12 @@ export class PostgreSQLClient extends AntaresCore {
}
private async keepAlive () {
const connection = await this._connection.connect() as pg.PoolClient;
await connection.query('SELECT 1+1');
connection.release();
try {
const connection = await this._connection.connect() as pg.PoolClient;
await connection.query('SELECT 1+1');
connection.release();
}
catch (_) {}
}
use (schema: string, connection?: pg.Client | pg.PoolClient) {

View File

@@ -6,6 +6,7 @@ const isWindows = process.platform === 'win32';
const indexPath = path.resolve(__dirname, 'index.html').split(path.sep).join('/');
export function validateSender (frame: WebFrameMain) {
if (process.windowsStore) return true; // TEMP HOTFIX
const frameUrl = new URL(frame.url);
const prefix = isWindows ? 'file:///' : 'file://';
const framePath = frameUrl.href.replace(prefix, '');

View File

@@ -136,9 +136,4 @@ onMounted(() => {
width: 100%;
}
}
.ace_.mdi {
display: inline-block;
width: 17px;
}
</style>

View File

@@ -403,11 +403,6 @@ defineExpose({ editor });
}
}
.ace_.mdi {
display: inline-block;
width: 17px;
}
.ace_gutter-cell.ace_breakpoint {
&::before {
content: '\F0403';

View File

@@ -56,7 +56,7 @@
<div class="tile-icon">
<div>
<BaseIcon
class="mr-1"
class="mr-1 mt-1"
icon-name="mdiKeyLink"
:size="24"
/>
@@ -78,6 +78,7 @@
class="mr-1"
icon-name="mdiTable"
:size="14"
:style="'min-width:14px'"
/>
<span>{{ foreign.table }}.{{ foreign.field }}</span>
</span>
@@ -86,6 +87,7 @@
class="mr-1"
icon-name="mdiTable"
:size="14"
:style="'min-width:14px'"
/>
<span>{{ foreign.refTable }}.{{ foreign.refField }}</span>
</span>

View File

@@ -27,11 +27,7 @@
:title="t('general.cancel')"
@click="killTabQuery()"
>
<BaseIcon
class="mr-1"
icon-name="mdiWindowCLose"
:size="24"
/>
<BaseIcon icon-name="mdiWindowClose" :size="24" />
<span class="d-invisible pr-1">{{ t('general.run') }}</span>
</button>
<button

View File

@@ -3,7 +3,7 @@
ref="tableWrapper"
class="vscroll no-outline"
tabindex="0"
:style="{'height': resultsSize+'px'}"
:style="{ 'height': resultsSize + 'px' }"
@blur="deselectRows"
@focus="hasFocus = true"
@keyup.delete="showDeleteConfirmModal"
@@ -28,7 +28,7 @@
v-for="(result, index) in resultsWithRows"
:key="index"
class="tab-item"
:class="{'active': resultsetIndex === index}"
:class="{ 'active': resultsetIndex === index }"
@click="selectResultset(index)"
>
<a>{{ result.fields ? result.fields[0]?.table : '' }} ({{ result.rows.length }})</a>
@@ -57,7 +57,7 @@
<span>{{ field.alias || field.name }}</span>
<BaseIcon
v-if="isSortable && currentSort === field.name || currentSort === `${field.table}.${field.name}`"
:icon-name="currentSortDir === 'asc' ? 'mdiSortAscending':'mdiSortDescending'"
:icon-name="currentSortDir === 'asc' ? 'mdiSortAscending' : 'mdiSortDescending'"
:size="18"
class="sort-icon ml-1"
/>
@@ -90,7 +90,7 @@
:fields="fieldsObj"
:key-usage="keyUsage"
:element-type="elementType"
:class="{'selected': selectedRows.includes(row._antares_id)}"
:class="{ 'selected': selectedRows.includes(row._antares_id) }"
:selected="selectedRows.includes(row._antares_id)"
:selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null"
@start-editing="isEditingRow = true"
@@ -163,7 +163,7 @@
<BaseSelect
v-model="sqlExportOptions.sqlInsertDivider"
class="form-select"
:options="[{value: 'bytes', label: 'KiB'}, {value: 'rows', label: t('database.row', 2)}]"
:options="[{ value: 'bytes', label: 'KiB' }, { value: 'rows', label: t('database.row', 2) }]"
/>
</div>
</div>
@@ -208,9 +208,9 @@
v-model="csvExportOptions.stringDelimiter"
class="form-select"
:options="[
{value: '', label: t('general.none')},
{value: 'single', label: t('general.singleQuote')},
{value: 'double', label: t('general.doubleQuote')}
{ value: '', label: t('general.none') },
{ value: 'single', label: t('general.singleQuote') },
{ value: 'double', label: t('general.doubleQuote') }
]"
/>
</div>
@@ -235,7 +235,10 @@
</label>
</div>
<div class="column col-7">
<label class="form-switch d-inline-block" @click.prevent="csvExportOptions.header = !csvExportOptions.header">
<label
class="form-switch d-inline-block"
@click.prevent="csvExportOptions.header = !csvExportOptions.header"
>
<input type="checkbox" :checked="csvExportOptions.header">
<i class="form-icon" />
</label>
@@ -249,10 +252,10 @@
<script setup lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */
import faker from '@faker-js/faker';
import { BLOB, DATE, DATETIME, LONG_TEXT, TEXT, TIME } from 'common/fieldTypes';
import { QueryResult, TableField } from 'common/interfaces/antares';
import { TableUpdateParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { jsonToSqlInsert } from 'common/libs/sqlUtils';
import { uidGen } from 'common/libs/uidGen';
import * as json2php from 'json2php';
@@ -299,7 +302,7 @@ const emit = defineEmits([
'duplicate-row'
]);
const resultTable: Ref<Component & {updateWindow: () => void}> = ref(null);
const resultTable: Ref<Component & { updateWindow: () => void }> = ref(null);
const tableWrapper: Ref<HTMLDivElement> = ref(null);
const table: Ref<HTMLDivElement> = ref(null);
const resultsSize = ref(0);
@@ -377,7 +380,7 @@ const keyUsage = computed(() => resultsWithRows.value.length ? resultsWithRows.v
const fieldsObj = computed(() => {
if (sortedResults.value.length) {
const fieldsObj: {[key: string]: TableField} = {};
const fieldsObj: { [key: string]: TableField } = {};
for (const key in sortedResults.value[0]) {
if (key === '_antares_id') continue;
@@ -483,7 +486,7 @@ const resizeResults = () => {
const refreshScroller = () => resizeResults();
const updateField = (payload: { field: string; type: string; content: any }, row: {[key: string]: any}) => {
const updateField = (payload: { field: string; type: string; content: any }, row: { [key: string]: any }) => {
const orgRow: any = localResults.value.find((lr: any) => lr._antares_id === row._antares_id);
Object.keys(orgRow).forEach(key => { // remap the row
@@ -598,7 +601,7 @@ const copyRow = (format: string) => {
json: contentToCopy,
client: workspaceClient.value,
fields: fieldsObj.value as {
[key: string]: {type: string; datePrecision: number};
[key: string]: { type: string; datePrecision: number };
},
table: getTable(resultsetIndex.value)
});
@@ -670,28 +673,18 @@ const fillCell = (event: { name: string; group: string; type: string }) => {
datePrecision += i === 0 ? '.S' : 'S';
}
if (event.group === 'custom') {
if (event.type === 'time' && event.name === 'now')
fakeValue = moment().format(`HH:mm:ss${datePrecision}`);
else if (event.type === 'time' && event.name === 'random')
fakeValue = moment(faker.date.recent()).format(`HH:mm:ss${datePrecision}`);
else if (event.type === 'datetime' && event.name === 'now')
fakeValue = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
}
else {
fakeValue = (faker as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number')
fakeValue = String(fakeValue);
fakeValue = (fakerCustom as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number')
fakeValue = String(fakeValue);
if (selectedCell.value.length)
fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024);
}
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
if (selectedCell.value.length)
fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024);
}
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
const params = {
primary: primaryField.value?.name,
@@ -859,12 +852,12 @@ const downloadTable = (format: 'csv' | 'json' | 'sql' | 'php', table: string, po
type: format,
content: rows,
fields: JSON.parse(JSON.stringify(fieldsObj.value)) as {
[key: string]: {type: string; datePrecision: number};
[key: string]: { type: string; datePrecision: number };
},
client: workspaceClient.value,
table,
sqlOptions: popup ? { ...sqlExportOptions.value }: null,
csvOptions: popup ? { ...csvExportOptions.value }: null
sqlOptions: popup ? { ...sqlExportOptions.value } : null,
csvOptions: popup ? { ...csvExportOptions.value } : null
});
};
@@ -897,7 +890,7 @@ const onKey = async (e: KeyboardEvent) => {
if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) {
e.preventDefault();
const aviableFields= Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id
const aviableFields = Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id
if (!selectedField.value)
selectedField.value = aviableFields[0];
@@ -914,8 +907,8 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex + 1;
nextFieldIndex = selectedFieldIndex;
if (nextIndex > sortedResults.value.length -1)
nextIndex = sortedResults.value.length -1;
if (nextIndex > sortedResults.value.length - 1)
nextIndex = sortedResults.value.length - 1;
break;
case 'ArrowUp':
@@ -931,7 +924,7 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex;
nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1)
if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0;
break;
@@ -941,7 +934,7 @@ const onKey = async (e: KeyboardEvent) => {
nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1;
nextFieldIndex = aviableFields.length - 1;
break;
@@ -950,11 +943,11 @@ const onKey = async (e: KeyboardEvent) => {
if (e.shiftKey) {
nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1;
nextFieldIndex = aviableFields.length - 1;
}
else {
nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1)
if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0;
}
}
@@ -1049,32 +1042,33 @@ onUnmounted(() => {
<style lang="scss" scoped>
.vscroll {
height: 1000px;
overflow: auto;
overflow-anchor: none;
height: 1000px;
overflow: auto;
overflow-anchor: none;
}
.column-resizable {
&:hover,
&:active {
resize: horizontal;
overflow: hidden;
}
&:hover,
&:active {
resize: horizontal;
overflow: hidden;
}
}
.table-column-title {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.sort-icon {
font-size: 0.7rem;
line-height: 1;
margin-left: 0.2rem;
font-size: 0.7rem;
line-height: 1;
margin-left: 0.2rem;
}
.result-tabs {
background: transparent !important;
margin: 0;
background: transparent !important;
margin: 0;
}
</style>

View File

@@ -197,13 +197,13 @@ const fakerMethods = {
{ name: 'amount', group: 'finance' }
],
datetime: [
{ name: 'now', group: 'custom' },
{ name: 'now', group: 'date' },
{ name: 'past', group: 'date' },
{ name: 'future', group: 'date' }
],
time: [
{ name: 'now', group: 'custom' },
{ name: 'random', group: 'custom' }
{ name: 'now', group: 'time' },
{ name: 'random', group: 'time' }
],
uuid: [
{ name: 'uuid', group: 'random' }

View File

@@ -183,6 +183,7 @@
<WorkspaceTabTableFilters
v-if="isSearch"
:fields="fields"
:is-quering="isQuering"
:conn-client="connection.client"
@filter="updateFilters"
@filter-change="onFilterChange"

View File

@@ -9,6 +9,7 @@
<input
v-model="row.active"
type="checkbox"
:disabled="isQuering"
@change="doFilter"
><i class="form-icon" />
</label>
@@ -18,11 +19,13 @@
:options="fields"
option-track-by="name"
option-label="name"
:disabled="isQuering"
/>
<BaseSelect
v-model="row.op"
class="form-select ml-2 col-auto select-sm"
:options="operators"
:disabled="isQuering"
/>
<div class="workspace-table-filters-row-value ml-2">
<input
@@ -30,12 +33,14 @@
v-model="row.value"
type="text"
class="form-input input-sm"
:disabled="isQuering"
>
<input
v-if="row.op === 'BETWEEN'"
v-model="row.value2"
type="text"
class="form-input ml-2 input-sm"
:disabled="isQuering"
>
</div>
<button
@@ -76,7 +81,7 @@
import customizations from 'common/customizations';
import { FLOAT, NUMBER } from 'common/fieldTypes';
import { ClientCode, TableField } from 'common/interfaces/antares';
import { TableFilterClausole } from 'common/interfaces/tableApis';
import { TableFilterClausole, TableFilterOperator } from 'common/interfaces/tableApis';
import { computed, Prop, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -87,15 +92,14 @@ const { t } = useI18n();
const props = defineProps({
fields: Array as Prop<TableField[]>,
connClient: String as Prop<ClientCode>
connClient: String as Prop<ClientCode>,
isQuering: Boolean
});
const emit = defineEmits(['filter-change', 'filter']);
const rows = ref([]);
const operators = ref([
'=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'
]);
const operators: TableFilterOperator[] = customizations[props.connClient].operators;
const clientCustomizations = computed(() => customizations[props.connClient]);
@@ -122,7 +126,7 @@ const createClausole = (filter: TableFilterClausole) => {
const { elementsWrapper: ew, stringsWrapper: sw } = clientCustomizations.value;
let value;
if (isNumeric) {
if (isNumeric && !['IN', 'NOT IN', 'RLIKE', 'NOT RLIKE'].includes(filter.op)) {
if (isNaN(Number(filter.value)))
filter.value = '';
if (isNaN(Number(filter.value2)))
@@ -145,13 +149,14 @@ const createClausole = (filter: TableFilterClausole) => {
val = val.trim();
return isNumeric ? val : `${sw}${val}${sw}`;
}).join(',');
value = `(${filter.value})`;
value = `(${value})`;
break;
case 'IS NULL':
case 'IS NOT NULL':
value = '';
break;
case 'LIKE':
case 'NOT LIKE':
value = `${sw}%${filter.value}%${sw}`;
break;
default:

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 7A2 2 0 0 0 1 9V17H3V13H5V17H7V9A2 2 0 0 0 5 7H3M3 9H5V11H3M15 10.5V9A2 2 0 0 0 13 7H9V17H13A2 2 0 0 0 15 15V13.5A1.54 1.54 0 0 0 13.5 12A1.54 1.54 0 0 0 15 10.5M13 15H11V13H13V15M13 11H11V9H13M19 7A2 2 0 0 0 17 9V15A2 2 0 0 0 19 17H21A2 2 0 0 0 23 15V14H21V15H19V9H21V10H23V9A2 2 0 0 0 21 7Z" /></svg>

After

Width:  |  Height:  |  Size: 374 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,19V5A2,2 0 0,1 5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19M17,12L12,7V10H8V14H12V17L17,12Z" /></svg>

After

Width:  |  Height:  |  Size: 186 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15,13H16.5V15.82L18.94,17.23L18.19,18.53L15,16.69V13M19,8H5V19H9.67C9.24,18.09 9,17.07 9,16A7,7 0 0,1 16,9C17.07,9 18.09,9.24 19,9.67V8M5,21C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H6V1H8V3H16V1H18V3H19A2,2 0 0,1 21,5V11.1C22.24,12.36 23,14.09 23,16A7,7 0 0,1 16,23C14.09,23 12.36,22.24 11.1,21H5M16,11.15A4.85,4.85 0 0,0 11.15,16C11.15,18.68 13.32,20.85 16,20.85A4.85,4.85 0 0,0 20.85,16C20.85,13.32 18.68,11.15 16,11.15Z" /></svg>

After

Width:  |  Height:  |  Size: 501 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 155 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z" /></svg>

After

Width:  |  Height:  |  Size: 339 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15Z" /></svg>

After

Width:  |  Height:  |  Size: 412 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C11.5 2 11 2.19 10.59 2.59L2.59 10.59C1.8 11.37 1.8 12.63 2.59 13.41L10.59 21.41C11.37 22.2 12.63 22.2 13.41 21.41L21.41 13.41C22.2 12.63 22.2 11.37 21.41 10.59L13.41 2.59C13 2.19 12.5 2 12 2M12 4L15.29 7.29L12 10.59L8.71 7.29L12 4M7.29 8.71L10.59 12L7.29 15.29L4 12L7.29 8.71M16.71 8.71L20 12L16.71 15.29L13.41 12L16.71 8.71M12 13.41L15.29 16.71L12 20L8.71 16.71L12 13.41Z" /></svg>

After

Width:  |  Height:  |  Size: 457 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2 12A10 10 0 1 0 12 2A10 10 0 0 0 2 12M15.6 13.72A4 4 0 0 0 16 12A4 4 0 0 0 12 8V10L8.88 7L12 4V6A6 6 0 0 1 18 12A5.9 5.9 0 0 1 17.07 15.19M6 12A5.9 5.9 0 0 1 6.93 8.81L8.4 10.28A4 4 0 0 0 8 12A4 4 0 0 0 12 16V14L15 17L12 20V18A6 6 0 0 1 6 12Z" /></svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 3H17C18.11 3 19 3.9 19 5V12.08C17.45 11.82 15.92 12.18 14.68 13H11V17H12.08C11.97 17.68 11.97 18.35 12.08 19H3C1.9 19 1 18.11 1 17V5C1 3.9 1.9 3 3 3M3 7V11H9V7H3M11 7V11H17V7H11M3 13V17H9V13H3M22.78 19.32L21.71 18.5C21.73 18.33 21.75 18.17 21.75 18S21.74 17.67 21.71 17.5L22.77 16.68C22.86 16.6 22.89 16.47 22.83 16.36L21.83 14.63C21.77 14.5 21.64 14.5 21.5 14.5L20.28 15C20 14.82 19.74 14.65 19.43 14.53L19.24 13.21C19.23 13.09 19.12 13 19 13H17C16.88 13 16.77 13.09 16.75 13.21L16.56 14.53C16.26 14.66 15.97 14.82 15.71 15L14.47 14.5C14.36 14.5 14.23 14.5 14.16 14.63L13.16 16.36C13.1 16.47 13.12 16.6 13.22 16.68L14.28 17.5C14.26 17.67 14.25 17.83 14.25 18S14.26 18.33 14.28 18.5L13.22 19.32C13.13 19.4 13.1 19.53 13.16 19.64L14.16 21.37C14.22 21.5 14.35 21.5 14.47 21.5L15.71 21C15.97 21.18 16.25 21.35 16.56 21.47L16.75 22.79C16.77 22.91 16.87 23 17 23H19C19.12 23 19.23 22.91 19.25 22.79L19.44 21.47C19.74 21.34 20 21.18 20.28 21L21.5 21.5C21.64 21.5 21.77 21.5 21.84 21.37L22.84 19.64C22.9 19.53 22.87 19.4 22.78 19.32M18 19.5C17.17 19.5 16.5 18.83 16.5 18S17.18 16.5 18 16.5 19.5 17.17 19.5 18 18.84 19.5 18 19.5Z" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 16.88C17.56 16.88 18 17.32 18 17.88S17.56 18.88 17 18.88 16 18.43 16 17.88 16.44 16.88 17 16.88M17 13.88C19.73 13.88 22.06 15.54 23 17.88C22.06 20.22 19.73 21.88 17 21.88S11.94 20.22 11 17.88C11.94 15.54 14.27 13.88 17 13.88M17 15.38C15.62 15.38 14.5 16.5 14.5 17.88S15.62 20.38 17 20.38 19.5 19.26 19.5 17.88 18.38 15.38 17 15.38M18 3H4C2.9 3 2 3.9 2 5V17C2 18.1 2.9 19 4 19H9.42C9.26 18.68 9.12 18.34 9 18C9.12 17.66 9.26 17.32 9.42 17H4V13H10V15.97C10.55 15.11 11.23 14.37 12 13.76V13H13.15C14.31 12.36 15.62 12 17 12C18.06 12 19.07 12.21 20 12.59V5C20 3.9 19.1 3 18 3M10 11H4V7H10V11M18 11H12V7H18V11Z" /></svg>

After

Width:  |  Height:  |  Size: 688 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5,4H19A2,2 0 0,1 21,6V18A2,2 0 0,1 19,20H5A2,2 0 0,1 3,18V6A2,2 0 0,1 5,4M5,8V12H11V8H5M13,8V12H19V8H13M5,14V18H11V14H5M13,14V18H19V14H13Z" /></svg>

After

Width:  |  Height:  |  Size: 218 B

View File

@@ -1,5 +1,4 @@
'use strict';
import '@mdi/font/css/materialdesignicons.css';
import 'floating-vue/dist/style.css';
import 'leaflet/dist/leaflet.css';
import '@/scss/main.scss';

View File

@@ -1227,42 +1227,42 @@ ace.define('ace/autocomplete/popup', ['require', 'exports', 'module', 'ace/virtu
switch (meta) {
case 'table':
iconClass = 'mdi-table';
iconClass = 'editor-icon-table';
break;
case 'column':
iconClass = 'mdi-rhombus-split-outline';
iconClass = 'editor-icon-rhombus-split-outline';
break;
case 'view':
iconClass = 'mdi-table-eye';
iconClass = 'editor-icon-table-eye';
break;
case 'trigger':
iconClass = 'mdi-table-cog';
iconClass = 'editor-icon-table-cog';
break;
case 'routine':
iconClass = 'mdi-sync-circle';
iconClass = 'editor-icon-sync-circle';
break;
case 'function':
iconClass = 'mdi-arrow-right-bold-box';
iconClass = 'editor-icon-arrow-right-bold-box';
break;
case 'scheduler':
iconClass = 'mdi-calendar-clock';
iconClass = 'editor-icon-calendar-clock';
break;
case 'keyword':
iconClass = 'mdi-cube';
iconClass = 'editor-icon-cube';
break;
case 'snippet':
iconClass = 'mdi-code-braces';
iconClass = 'editor-icon-code-braces';
break;
case 'local':
iconClass = 'mdi-alphabetical-variant';
iconClass = 'editor-icon-alphabetical-variant';
break;
default:
iconClass = 'mdi-circle';
iconClass = 'editor-icon-circle';
break;
}
iconClass && tokens.push({
type: ` mdi ${iconClass}`,
type: ` editor-icon ${iconClass}`,
value: ' '
});
}

View File

@@ -0,0 +1,67 @@
/* stylelint-disable selector-class-pattern */
/* Only used in ext-language_tools.js */
.editor-icon {
display: inline-block;
width: 17px;
height: 17px;
background-size: cover;
position: relative;
top: 2px;
margin-right: 1px;
opacity: 0.7;
&.editor-icon-table {
background-image: url("../images/svg/table.svg");
}
&.editor-icon-rhombus-split-outline {
background-image: url("../images/svg/rhombus-split-outline.svg");
}
&.editor-icon-table-eye {
background-image: url("../images/svg/table-eye.svg");
}
&.editor-icon-table-cog {
background-image: url("../images/svg/table-cog.svg");
}
&.editor-icon-sync-circle {
background-image: url("../images/svg/sync-circle.svg");
}
&.editor-icon-arrow-right-bold-box {
background-image: url("../images/svg/arrow-right-bold-box.svg");
}
&.editor-icon-calendar-clock {
background-image: url("../images/svg/calendar-clock.svg");
}
&.editor-icon-cube {
background-image: url("../images/svg/cube.svg");
}
&.editor-icon-code-braces {
background-image: url("../images/svg/code-braces.svg");
}
&.editor-icon-alphabetical-variant {
background-image: url("../images/svg/alphabetical-variant.svg");
}
&.editor-icon-circle {
background-image: url("../images/svg/circle.svg");
}
&::before {
line-height: 1;
}
}
.ace_dark {
.editor-icon {
filter: invert(100%);
}
}

View File

@@ -1,9 +0,0 @@
.mdi {
display: flex;
align-items: center;
justify-content: center;
&::before {
line-height: 1;
}
}

View File

@@ -5,7 +5,7 @@
@import "data-types";
@import "table-keys";
@import "fake-tables";
@import "mdi-additions";
@import "editor-icons";
@import "db-icons";
@import "themes/dark-theme";
@import "themes/light-theme";