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

Compare commits

...

14 Commits

35 changed files with 271 additions and 137 deletions

View File

@@ -18,6 +18,12 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 14
- name: Install dependencies
run: npm i
- name: Run tests
run: npm run test
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1

View File

@@ -18,6 +18,12 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 14
- name: Install dependencies
run: npm i
- name: Run tests
run: npm run test
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1

View File

@@ -19,6 +19,12 @@ jobs:
with:
node-version: 14
- name: Install dependencies
run: npm i
- name: Run tests
run: npm run test
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:

View File

@@ -2,6 +2,29 @@
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.4.1](https://github.com/Fabio286/antares/compare/v0.4.0...v0.4.1) (2021-12-11)
### Features
* language format detection for text fields ([a5fdcc1](https://github.com/Fabio286/antares/commit/a5fdcc1a85aa188ff1b9a15b1a768aced026f360))
### Bug Fixes
* cell disappear on edit in one column tables ([aaa5549](https://github.com/Fabio286/antares/commit/aaa5549609664665bd4513632d621cb249b379c1))
* false positive with Windows Defender ([992a033](https://github.com/Fabio286/antares/commit/992a033cb2bede3d1eb52e19482d810f6692de1e))
* **MySQL:** wrong datetime fields default in table filler in some cases ([8da0224](https://github.com/Fabio286/antares/commit/8da022487650039b7f34a9c86a7bd9045eba65e2))
* **MySQL:** wrong value for fields "on update" in some conditions ([359e14a](https://github.com/Fabio286/antares/commit/359e14a9ebd48f86069ba7762fe00a7056f52d47))
* select all rows with ctrl+a when editing a cell ([35cb7e1](https://github.com/Fabio286/antares/commit/35cb7e1dc48d3a74e9d106cb1a37f454c1b4a4d1))
* **SQLite:** update rows with a text primary key ([d7f1aa9](https://github.com/Fabio286/antares/commit/d7f1aa97af32a4c51fc7022498bd47e15fa08430))
### Improvements
* **UI:** avoid columns size change when editing cells or scrolling results ([813aa32](https://github.com/Fabio286/antares/commit/813aa320d9ab799efea38a7110b7c0bdf7549123))
* **UI:** disable save button in table creation when no fields are added ([e8af2d2](https://github.com/Fabio286/antares/commit/e8af2d24a869f7667c069936648808952d2062ab))
## [0.4.0](https://github.com/Fabio286/antares/compare/v0.3.9...v0.4.0) (2021-11-24)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -1,7 +1,7 @@
{
"name": "antares",
"productName": "Antares",
"version": "0.4.0",
"version": "0.4.1",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT",
"repository": "https://github.com/Fabio286/antares.git",
@@ -18,7 +18,7 @@
"release": "standard-version",
"release:pre": "npm run release -- --prerelease alpha",
"postinstall": "electron-builder install-app-deps",
"test": "npm run lint",
"test": "npm run compile && node tests/app.spec.js",
"lint": "eslint . --ext .js,.vue && stylelint \"./src/**/*.{css,scss,sass,vue}\"",
"lint:fix": "eslint . --ext .js,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix",
"contributors:add": "all-contributors add",
@@ -82,6 +82,7 @@
"appx": {
"displayName": "Antares SQL",
"backgroundColor": "transparent",
"showNameOnTiles": true,
"identityName": "62514FabioDiStasio.AntaresSQLClient",
"publisher": "CN=1A2729ED-865C-41D2-9038-39AE2A63AA52",
"applicationId": "FabioDiStasio.AntaresSQLClient"
@@ -104,6 +105,7 @@
"dependencies": {
"@electron/remote": "^2.0.1",
"@mdi/font": "^6.1.95",
"@vscode/vscode-languagedetection": "^1.0.21",
"ace-builds": "^1.4.13",
"better-sqlite3": "^7.4.4",
"electron-log": "^4.4.1",
@@ -134,7 +136,7 @@
"cross-env": "^7.0.2",
"css-loader": "^6.5.0",
"electron": "^16.0.1",
"electron-builder": "^22.13.1",
"electron-builder": "^22.14.10",
"electron-devtools-installer": "^3.2.0",
"eslint": "^7.32.0",
"eslint-config-standard": "^16.0.3",
@@ -146,6 +148,7 @@
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.4.3",
"node-loader": "^2.0.0",
"playwright": "^1.16.3",
"progress-webpack-plugin": "^1.0.12",
"sass": "^1.42.1",
"sass-loader": "^12.3.0",

View File

@@ -7,8 +7,8 @@ module.exports = {
views: true,
triggers: true,
// Settings
elementsWrapper: '',
stringsWrapper: '"',
elementsWrapper: '"',
stringsWrapper: '\'',
tableAdd: true,
viewAdd: true,
triggerAdd: true,

View File

@@ -52,7 +52,7 @@ export default connections => {
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err };
return { status: 'error', response: err.toString() };
}
});

View File

@@ -3,6 +3,7 @@ import faker from 'faker';
import moment from 'moment';
import { sqlEscaper } from 'common/libs/sqlEscaper';
import { TEXT, LONG_TEXT, ARRAY, TEXT_SEARCH, NUMBER, FLOAT, BLOB, BIT, DATE, DATETIME } from 'common/fieldTypes';
import * as customizations from 'common/customizations';
import fs from 'fs';
export default (connections) => {
@@ -85,11 +86,12 @@ export default (connections) => {
ipcMain.handle('update-table-cell', async (event, params) => {
delete params.row._antares_id;
const { stringsWrapper: sw } = customizations[connections[params.uid]._client];
try { // TODO: move to client classes
let escapedParam;
let reload = false;
const id = typeof params.id === 'number' ? params.id : `"${params.id}"`;
const id = typeof params.id === 'number' ? params.id : `${sw}${params.id}${sw}`;
if ([...NUMBER, ...FLOAT].includes(params.type))
escapedParam = params.content;

View File

@@ -440,7 +440,9 @@ export class MySQLClient extends AntaresCore {
charset: field.CHARACTER_SET_NAME,
collation: field.COLLATION_NAME,
autoIncrement: field.EXTRA.includes('auto_increment'),
onUpdate: field.EXTRA.toLowerCase().includes('on update') ? field.EXTRA.replace('on update', '') : '',
onUpdate: field.EXTRA.toLowerCase().includes('on update')
? field.EXTRA.substr(field.EXTRA.indexOf('on update') + 9, field.EXTRA.length).trim()
: '',
comment: field.COLUMN_COMMENT
};
});

View File

@@ -6,13 +6,13 @@
@confirm="runRoutine"
@hide="closeModal"
>
<template slot="header">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-play mr-1" />
<span class="cut-text">{{ $t('word.parameters') }}: {{ localRoutine.name }}</span>
</div>
</template>
<div slot="body">
<template #body>
<div class="content">
<form class="form-horizontal">
<div
@@ -43,7 +43,7 @@
</div>
</form>
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -5,16 +5,16 @@
@confirm="$emit('confirm')"
@hide="$emit('close')"
>
<template slot="header">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-content-save-alert mr-1" /> {{ $t('message.unsavedChanges') }}
</div>
</template>
<div slot="body">
<template #body>
<div>
{{ $t('message.discardUnsavedChanges') }}
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -41,7 +41,7 @@
<label class="form-checkbox ml-3" :title="$t('word.insert')">
<input
type="checkbox"
:checked="!field.autoIncrement"
:checked="!fieldsToExclude.includes(field.name)"
@change.prevent="toggleFields($event, field)"
><i class="form-icon" />
</label>
@@ -264,7 +264,7 @@ export default {
else if (BIT.includes(field.type))
fieldDefault = field.default.replaceAll('\'', '').replaceAll('b', '');
else if (DATETIME.includes(field.type)) {
if (field.default && ['current_timestamp', 'now()'].includes(field.default.toLowerCase())) {
if (field.default && ['current_timestamp', 'now()'].some(term => field.default.toLowerCase().includes(term))) {
let datePrecision = '';
for (let i = 0; i < field.datePrecision; i++)
datePrecision += i === 0 ? '.S' : 'S';
@@ -281,7 +281,7 @@ export default {
rowObj[field.name] = { value: fieldDefault };
if (field.autoIncrement)// Disable by default auto increment fields
if (field.autoIncrement || !!field.onUpdate)// Disable by default auto increment or "on update" fields
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
}

View File

@@ -22,12 +22,12 @@
:hide-footer="true"
@hide="hideInfoModal"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-information-outline mr-1" /> {{ $t('message.processInfo') }}
</div>
</template>
<div :slot="'body'">
<template #body>
<div>
<div>
<TextEditor
@@ -38,7 +38,7 @@
/>
</div>
</div>
</div>
</template>
</ConfirmModal>
</div>
</template>

View File

@@ -15,16 +15,16 @@
@confirm="confirmDeleteConnection"
@hide="hideConfirmModal"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-server-remove mr-1" /> {{ $t('message.deleteConnection') }}
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="mb-2">
{{ $t('message.deleteCorfirm') }} <b>{{ connectionName }}</b>?
</div>
</div>
</template>
</ConfirmModal>
</BaseContextMenu>
</template>

View File

@@ -6,12 +6,12 @@
:hide-footer="true"
@hide="hideScratchpad"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-notebook-edit-outline mr-1" /> {{ $t('word.scratchpad') }}
</div>
</template>
<div :slot="'body'">
<template #body>
<div>
<div>
<TextEditor
@@ -24,7 +24,7 @@
</div>
<small class="text-gray">{{ $t('message.markdownSupported') }}</small>
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -256,56 +256,59 @@
</span>
</a>
</li>
<li
v-if="workspace.customizations.processesList"
slot="header"
class="tab-item dropdown tools-dropdown"
>
<a
class="tab-link workspace-tools-link dropdown-toggle"
tabindex="0"
:title="$t('word.tools')"
<template #header>
<li
v-if="workspace.customizations.processesList"
class="tab-item dropdown tools-dropdown"
>
<i class="mdi mdi-24px mdi-tools" />
</a>
<ul v-if="hasTools" class="menu text-left text-uppercase">
<li class="menu-item">
<a class="c-hand p-vcentered" @click="showProcessesModal">
<i class="mdi mdi-memory mr-1 tool-icon" />
<span>{{ $t('message.processesList') }}</span>
</a>
</li>
<li
v-if="workspace.customizations.variables"
class="menu-item"
title="Coming..."
<a
class="tab-link workspace-tools-link dropdown-toggle"
tabindex="0"
:title="$t('word.tools')"
>
<a class="c-hand p-vcentered disabled">
<i class="mdi mdi-shape mr-1 tool-icon" />
<span>{{ $t('word.variables') }}</span>
</a>
</li>
<li
v-if="workspace.customizations.usersManagement"
class="menu-item"
title="Coming..."
<i class="mdi mdi-24px mdi-tools" />
</a>
<ul v-if="hasTools" class="menu text-left text-uppercase">
<li class="menu-item">
<a class="c-hand p-vcentered" @click="showProcessesModal">
<i class="mdi mdi-memory mr-1 tool-icon" />
<span>{{ $t('message.processesList') }}</span>
</a>
</li>
<li
v-if="workspace.customizations.variables"
class="menu-item"
title="Coming..."
>
<a class="c-hand p-vcentered disabled">
<i class="mdi mdi-shape mr-1 tool-icon" />
<span>{{ $t('word.variables') }}</span>
</a>
</li>
<li
v-if="workspace.customizations.usersManagement"
class="menu-item"
title="Coming..."
>
<a class="c-hand p-vcentered disabled">
<i class="mdi mdi-account-group mr-1 tool-icon" />
<span>{{ $t('message.manageUsers') }}</span>
</a>
</li>
</ul>
</li>
</template>
<template #footer>
<li class="tab-item">
<a
class="tab-add"
:title="$t('message.openNewTab')"
@click="addQueryTab"
>
<a class="c-hand p-vcentered disabled">
<i class="mdi mdi-account-group mr-1 tool-icon" />
<span>{{ $t('message.manageUsers') }}</span>
</a>
</li>
</ul>
</li>
<li slot="footer" class="tab-item">
<a
class="tab-add"
:title="$t('message.openNewTab')"
@click="addQueryTab"
>
<i class="mdi mdi-24px mdi-plus" />
</a>
</li>
<i class="mdi mdi-24px mdi-plus" />
</a>
</li>
</template>
</Draggable>
<WorkspaceEmptyState v-if="!workspace.tabs.length" @new-tab="addQueryTab" />
<template v-for="tab of workspace.tabs">

View File

@@ -42,17 +42,17 @@
@confirm="deleteMisc"
@hide="hideDeleteModal"
>
<template slot="header">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-delete mr-1" />
<span class="cut-text">{{ deleteMessage }}</span>
</div>
</template>
<div slot="body">
<template #body>
<div class="mb-2">
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedMisc.name }}</b>"?
</div>
</div>
</template>
</ConfirmModal>
<ModalAskParameters
v-if="isAskingParameters"

View File

@@ -78,17 +78,17 @@
@confirm="deleteSchema"
@hide="hideDeleteModal"
>
<template slot="header">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-database-remove mr-1" />
<span class="cut-text">{{ $t('message.deleteSchema') }}</span>
</div>
</template>
<div slot="body">
<template #body>
<div class="mb-2">
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedSchema }}</b>"?
</div>
</div>
</template>
</ConfirmModal>
<ModalEditSchema
v-if="isEditModal"

View File

@@ -40,33 +40,33 @@
@confirm="emptyTable"
@hide="hideEmptyModal"
>
<template slot="header">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-table-off mr-1" /> <span class="cut-text">{{ $t('message.emptyTable') }}</span>
</div>
</template>
<div slot="body">
<template #body>
<div class="mb-2">
{{ $t('message.emptyCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
</div>
</div>
</template>
</ConfirmModal>
<ConfirmModal
v-if="isDeleteModal"
@confirm="deleteTable"
@hide="hideDeleteModal"
>
<template slot="header">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-table-remove mr-1" />
<span class="cut-text">{{ selectedTable.type === 'table' ? $t('message.deleteTable') : $t('message.deleteView') }}</span>
</div>
</template>
<div slot="body">
<template #body>
<div class="mb-2">
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
</div>
</div>
</template>
</ConfirmModal>
</BaseContextMenu>
</template>

View File

@@ -5,7 +5,7 @@
<div class="workspace-query-buttons">
<button
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:disabled="!isChanged || !isValid"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
@@ -242,6 +242,9 @@ export default {
JSON.stringify(this.originalKeyUsage) !== JSON.stringify(this.localKeyUsage) ||
JSON.stringify(this.originalIndexes) !== JSON.stringify(this.localIndexes) ||
JSON.stringify(this.tableOptions) !== JSON.stringify(this.localOptions);
},
isValid () {
return !!this.localFields.length && !!this.localOptions.name.trim().length;
}
},
watch: {
@@ -287,7 +290,7 @@ export default {
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
}),
async saveChanges () {
if (this.isSaving) return;
if (this.isSaving || !this.isValid) return;
this.isSaving = true;
const params = {

View File

@@ -6,13 +6,13 @@
@confirm="confirmParametersChange"
@hide="$emit('hide')"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-dots-horizontal mr-1" />
<span class="cut-text">{{ $t('word.parameters') }} "{{ func }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="columns col-gapless">
<div class="column col-5">
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
@@ -167,7 +167,7 @@
</div>
</div>
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -6,13 +6,13 @@
@confirm="confirmParametersChange"
@hide="$emit('hide')"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-dots-horizontal mr-1" />
<span class="cut-text">{{ $t('word.parameters') }} "{{ routine }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="columns col-gapless">
<div class="column col-5">
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
@@ -167,7 +167,7 @@
</div>
</div>
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -5,13 +5,13 @@
@confirm="confirmOptionsChange"
@hide="$emit('hide')"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-timer mr-1" />
<span class="cut-text">{{ $t('word.timing') }} "{{ localOptions.name }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<form class="form-horizontal">
<div class="form-group">
<label class="form-label col-4">
@@ -133,7 +133,7 @@
</div>
</div>
</form>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -6,13 +6,13 @@
@confirm="confirmForeignsChange"
@hide="$emit('hide')"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-key-link mr-1" />
<span class="cut-text">{{ $t('word.foreignKeys') }} "{{ table }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="columns col-gapless">
<div class="column col-5">
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
@@ -197,7 +197,7 @@
</div>
</div>
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -6,13 +6,13 @@
@confirm="confirmIndexesChange"
@hide="$emit('hide')"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-key mdi-rotate-45 mr-1" />
<span class="cut-text">{{ $t('word.indexes') }} "{{ table }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="columns col-gapless">
<div class="column col-5">
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
@@ -133,7 +133,7 @@
</div>
</div>
</div>
</div>
</template>
</ConfirmModal>
</template>

View File

@@ -230,13 +230,13 @@
@confirm="editOFF"
@hide="hideDefaultModal"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-playlist-edit mr-1" />
<span class="cut-text">{{ $t('word.default') }} "{{ row.name }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<form class="form-horizontal">
<div class="mb-2">
<label class="form-radio form-inline">
@@ -324,7 +324,7 @@
</div>
</div>
</form>
</div>
</template>
</ConfirmModal>
</div>
</template>

View File

@@ -5,7 +5,7 @@
tabindex="0"
:style="{'height': resultsSize+'px'}"
@keyup.46="showDeleteConfirmModal"
@keydown.ctrl.65="selectAllRows"
@keydown.ctrl.65="selectAllRows($event)"
@keydown.esc="deselectRows"
>
<TableContext
@@ -53,6 +53,7 @@
class="mdi sort-icon"
:class="currentSortDir === 'asc' ? 'mdi-sort-ascending':'mdi-sort-descending'"
/>
<i v-else class="mdi sort-icon mdi-minus d-invisible" />
</div>
</div>
</div>
@@ -62,7 +63,7 @@
v-if="resultsWithRows[resultsetIndex] && resultsWithRows[resultsetIndex].rows"
ref="resultTable"
:items="sortedResults"
:item-height="23"
:item-height="rowHeight"
class="tbody"
:visible-height="resultsSize"
:scroll-element="scrollElement"
@@ -71,6 +72,7 @@
<WorkspaceTabQueryTableRow
v-for="row in items"
:key="row._antares_id"
:item-height="rowHeight"
:row="row"
:fields="fieldsObj"
:key-usage="keyUsage"
@@ -89,17 +91,17 @@
@confirm="deleteSelected"
@hide="hideDeleteConfirmModal"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-delete mr-1" />
<span class="cut-text">{{ $tc('message.deleteRows', selectedRows.length) }}</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="mb-2">
{{ $tc('message.confirmToDeleteRows', selectedRows.length) }}
</div>
</div>
</template>
</ConfirmModal>
</div>
</template>
@@ -142,7 +144,8 @@ export default {
currentSort: '',
currentSortDir: 'asc',
resultsetIndex: 0,
scrollElement: null
scrollElement: null,
rowHeight: 23
};
},
computed: {
@@ -242,6 +245,11 @@ export default {
if (this.$refs.tableWrapper)
this.scrollElement = this.$refs.tableWrapper;
document.querySelectorAll('.column-resizable').forEach(element => {
if (element.clientWidth !== 0)
element.style.width = element.clientWidth + 'px';
});
},
mounted () {
window.addEventListener('resize', this.resizeResults);
@@ -450,7 +458,9 @@ export default {
else
this.selectedRows = [row];
},
selectAllRows () {
selectAllRows (e) {
if (e.target.classList.contains('editable-field')) return;
this.selectedRows = this.localResults.reduce((acc, curr) => {
acc.push(curr._antares_id);
return acc;

View File

@@ -1,5 +1,9 @@
<template>
<div class="tr" @click="selectRow($event, row._antares_id)">
<div
class="tr"
:style="{height: itemHeight+'px'}"
@click="selectRow($event, row._antares_id)"
>
<div
v-for="(col, cKey) in row"
v-show="cKey !== '_antares_id'"
@@ -72,12 +76,12 @@
@confirm="editOFF"
@hide="hideEditorModal"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-playlist-edit mr-1" /> <span class="cut-text">{{ $t('word.edit') }} "{{ editingField }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="mb-2">
<div>
<TextEditor
@@ -96,23 +100,12 @@
v-model="editorMode"
class="form-select select-sm"
>
<option value="text">
TEXT
</option>
<option value="html">
HTML
</option>
<option value="xml">
XML
</option>
<option value="json">
JSON
</option>
<option value="svg">
SVG
</option>
<option value="yaml">
YAML
<option
v-for="language in availableLanguages"
:key="language.slug"
:value="language.slug"
>
{{ language.name }}
</option>
</select>
</div>
@@ -128,7 +121,7 @@
</div>
</div>
</div>
</div>
</template>
</ConfirmModal>
<ConfirmModal
v-if="isBlobEditor"
@@ -136,13 +129,13 @@
@confirm="editOFF"
@hide="hideEditorModal"
>
<template :slot="'header'">
<template #header>
<div class="d-flex">
<i class="mdi mdi-24px mdi-playlist-edit mr-1" />
<span class="cut-text">{{ $t('word.edit') }} "{{ editingField }}"</span>
</div>
</template>
<div :slot="'body'">
<template #body>
<div class="mb-2">
<transition name="jump-down">
<div v-if="contentInfo.size">
@@ -182,13 +175,14 @@
>
</div>
</div>
</div>
</template>
</ConfirmModal>
</div>
</template>
<script>
import moment from 'moment';
import { ModelOperations } from '@vscode/vscode-languagedetection';
import { mimeFromHex } from 'common/libs/mimeFromHex';
import { formatBytes } from 'common/libs/formatBytes';
import { bufferToBase64 } from 'common/libs/bufferToBase64';
@@ -261,6 +255,7 @@ export default {
row: Object,
fields: Object,
keyUsage: Array,
itemHeight: Number,
elementType: { type: String, default: 'table' }
},
data () {
@@ -280,7 +275,17 @@ export default {
mime: '',
size: null
},
fileToUpload: null
fileToUpload: null,
availableLanguages: [
{ name: 'TEXT', slug: 'text', id: 'text' },
{ name: 'HTML', slug: 'html', id: 'html' },
{ name: 'XML', slug: 'xml', id: 'xml' },
{ name: 'JSON', slug: 'json', id: 'json' },
{ name: 'SVG', slug: 'svg', id: 'svg' },
{ name: 'INI', slug: 'ini', id: 'ini' },
{ name: 'MARKDOWN', slug: 'markdown', id: 'md' },
{ name: 'YAML', slug: 'yaml', id: 'yaml' }
]
};
},
computed: {
@@ -362,6 +367,21 @@ export default {
Object.keys(this.fields).forEach(field => {
this.isInlineEditor[field.name] = false;
});
},
isTextareaEditor (val) {
if (val) {
const modelOperations = new ModelOperations();
(async () => {
const detected = await modelOperations.runModel(this.editingContent);
const filteredLanguages = detected.filter(dLang =>
this.availableLanguages.some(aLang => aLang.id === dLang.languageId) &&
dLang.confidence > 0.1
);
if (filteredLanguages.length)
this.editorMode = this.availableLanguages.find(lang => lang.id === filteredLanguages[0].languageId).slug;
})();
}
}
},
methods: {

50
tests/app.spec.js Normal file
View File

@@ -0,0 +1,50 @@
const { _electron: electron } = require('playwright');
const { strict: assert } = require('assert');
(async () => {
console.log('Starting tests');
// Launch Electron app.
const electronApp = await electron.launch({ args: ['dist/main.js'] });
/**
* App main window state
* @type {{isVisible: boolean; isDevToolsOpened: boolean; isCrashed: boolean}}
*/
const windowState = await electronApp.evaluate(({ BrowserWindow }) => {
const mainWindow = BrowserWindow.getAllWindows()[0];
const getState = () => ({
isVisible: mainWindow.isVisible(),
isDevToolsOpened: mainWindow.webContents.isDevToolsOpened()
});
return new Promise((resolve) => {
if (mainWindow.isVisible())
resolve(getState());
else
mainWindow.once('ready-to-show', () => setTimeout(() => resolve(getState()), 0));
});
});
// Check main window state
assert.ok(windowState.isVisible, 'Main window not visible');
assert.ok(!windowState.isDevToolsOpened, 'DevTools opened');
assert.ok(!windowState.isCrashed, 'Window crashed');
/**
* Rendered Main window web-page
* @type {Page}
*/
const page = await electronApp.firstWindow();
console.log(await page.title());
// Check web-page content
const element = await page.$('#wrapper', { strict: true });
assert.notStrictEqual(element, null, 'Can\'t find root element');
assert.notStrictEqual((await element.innerHTML()).trim(), '', 'Window content is empty');
// Close app
await electronApp.close();
console.log('Tests finished');
})();