Additions

This commit is contained in:
Fabio 2020-06-10 19:29:10 +02:00
parent beb48eaf2e
commit 1c3323b537
14 changed files with 320 additions and 100 deletions

85
package-lock.json generated
View File

@ -1146,6 +1146,12 @@
"integrity": "sha512-q95SP4FdkmF0CwO0F2q0H6ZgudsApaY/yCtAQNRn1gduef5fGpyEphzy0YCq/N0UFvDSnLg5V8jFK/YGXlDiCw==",
"dev": true
},
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@ -4151,9 +4157,9 @@
}
},
"electron-log": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.2.0.tgz",
"integrity": "sha512-Yy1X8iZEzoBA8pu5b7YU07dRHi1GPM9C5jLEOn87Uqtdc9rbe6KbvvQ/AAAtGvn4/GC3azRW/eeiSI4ZF+Hm2A=="
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.2.1.tgz",
"integrity": "sha512-tUI9w3kUP3qhwXJ92RDUPFVZfwtBwKCy/1TsSHndXYLlNCB/7+vkiQG0uxv9D2Leuxc/DJKfYyrdEBpzi/vyZg=="
},
"electron-publish": {
"version": "22.7.0",
@ -4858,23 +4864,24 @@
}
},
"eslint-plugin-import": {
"version": "2.20.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz",
"integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==",
"version": "2.21.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.1.tgz",
"integrity": "sha512-qYOOsgUv63vHof7BqbzuD+Ud34bXHxFJxntuAC1ZappFZXYbRIek3aJ7jc9i2dHDGDyZ/0zlO0cpioES265Lsw==",
"dev": true,
"requires": {
"array-includes": "^3.0.3",
"array.prototype.flat": "^1.2.1",
"array-includes": "^3.1.1",
"array.prototype.flat": "^1.2.3",
"contains-path": "^0.1.0",
"debug": "^2.6.9",
"doctrine": "1.5.0",
"eslint-import-resolver-node": "^0.3.2",
"eslint-module-utils": "^2.4.1",
"eslint-import-resolver-node": "^0.3.3",
"eslint-module-utils": "^2.6.0",
"has": "^1.0.3",
"minimatch": "^3.0.4",
"object.values": "^1.1.0",
"object.values": "^1.1.1",
"read-pkg-up": "^2.0.0",
"resolve": "^1.12.0"
"resolve": "^1.17.0",
"tsconfig-paths": "^3.9.0"
},
"dependencies": {
"debug": {
@ -10924,6 +10931,11 @@
"ajv-keywords": "^3.4.1"
}
},
"scrollparent": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.0.1.tgz",
"integrity": "sha1-cV1bnMV3YPsivczDvvtb/gaxoxc="
},
"scss-tokenizer": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
@ -12246,6 +12258,29 @@
"utf8-byte-length": "^1.0.1"
}
},
"tsconfig-paths": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
"integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==",
"dev": true,
"requires": {
"@types/json5": "^0.0.29",
"json5": "^1.0.1",
"minimist": "^1.2.0",
"strip-bom": "^3.0.0"
},
"dependencies": {
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
}
}
}
},
"tslib": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
@ -12796,9 +12831,9 @@
}
},
"vue-i18n": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.18.1.tgz",
"integrity": "sha512-K+hFQJksF8Ph23pnhbwSyoQx+4Y1q/rh2o7GiXI/3rLCCrwanUbzudC8+trp0Mb8rn9y83DYF6RXNrMd+VsuCw=="
"version": "8.18.2",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.18.2.tgz",
"integrity": "sha512-0X5nBTCZAVjlwcrPaYJwNs3iipBBTv0AUHwQUOa8yP3XbQGWKbRHqBb3OhCYtum/IHDD21d/df5Xd2VgyxbxfA=="
},
"vue-loader": {
"version": "15.9.1",
@ -12813,6 +12848,16 @@
"vue-style-loader": "^4.1.0"
}
},
"vue-observe-visibility": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-0.4.6.tgz",
"integrity": "sha512-xo0CEVdkjSjhJoDdLSvoZoQrw/H2BlzB5jrCBKGZNXN2zdZgMuZ9BKrxXDjNP2AxlcCoKc8OahI3F3r3JGLv2Q=="
},
"vue-resize": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz",
"integrity": "sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg=="
},
"vue-style-loader": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
@ -12839,6 +12884,16 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"vue-virtual-scroller": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/vue-virtual-scroller/-/vue-virtual-scroller-1.0.10.tgz",
"integrity": "sha512-Hn4qSBDhRY4XdngPioYy/ykDjrLX/NMm1fQXm/4UQQ/Xv1x8JbHGFZNftQowTcfICgN7yc31AKnUk1UGLJ2ndA==",
"requires": {
"scrollparent": "^2.0.1",
"vue-observe-visibility": "^0.4.4",
"vue-resize": "^0.4.5"
}
},
"vuedraggable": {
"version": "2.23.2",
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.23.2.tgz",

View File

@ -2,7 +2,7 @@
"name": "antares",
"productName": "Antares",
"version": "0.0.0",
"description": "A cross-platform easy to use SQL client. ",
"description": "A cross-platform easy to use SQL client.",
"license": "MIT",
"repository": "https://github.com/Fabio286/antares.git",
"scripts": {
@ -29,7 +29,7 @@
},
"dependencies": {
"codemirror": "^5.54.0",
"electron-log": "^4.2.0",
"electron-log": "^4.2.1",
"electron-updater": "^4.3.1",
"lodash": "^4.17.15",
"material-design-icons": "^3.0.1",
@ -40,7 +40,8 @@
"source-map-support": "^0.5.16",
"spectre.css": "^0.5.8",
"vue-click-outside": "^1.1.0",
"vue-i18n": "^8.18.1",
"vue-i18n": "^8.18.2",
"vue-virtual-scroller": "^1.0.10",
"vuedraggable": "^2.23.2",
"vuex": "^3.4.0",
"vuex-persist": "^2.2.0"
@ -55,7 +56,7 @@
"electron-webpack-vue": "^2.4.0",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-import": "^2.21.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",

View File

@ -24,28 +24,19 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import TheTitleBar from '@/components/TheTitleBar';
import TheSettingBar from '@/components/TheSettingBar';
import TheFooter from '@/components/TheFooter';
import TheNotificationsBoard from '@/components/TheNotificationsBoard';
import TheAppWelcome from '@/components/TheAppWelcome';
import Workspace from '@/components/Workspace';
import ModalNewConnection from '@/components/ModalNewConnection';
import ModalEditConnection from '@/components/ModalEditConnection';
import ModalSettings from '@/components/ModalSettings';
export default {
name: 'App',
components: {
TheTitleBar,
TheSettingBar,
TheFooter,
TheNotificationsBoard,
TheAppWelcome,
Workspace,
ModalNewConnection,
ModalEditConnection,
ModalSettings
TheTitleBar: () => import(/* webpackChunkName: "TheTitleBar" */'@/components/TheTitleBar'),
TheSettingBar: () => import(/* webpackChunkName: "TheSettingBar" */'@/components/TheSettingBar'),
TheFooter: () => import(/* webpackChunkName: "TheFooter" */'@/components/TheFooter'),
TheNotificationsBoard: () => import(/* webpackChunkName: "TheNotificationsBoard" */'@/components/TheNotificationsBoard'),
TheAppWelcome: () => import(/* webpackChunkName: "TheAppWelcome" */'@/components/TheAppWelcome'),
Workspace: () => import(/* webpackChunkName: "Workspace" */'@/components/Workspace'),
ModalNewConnection: () => import(/* webpackChunkName: "ModalNewConnection" */'@/components/ModalNewConnection'),
ModalEditConnection: () => import(/* webpackChunkName: "ModalEditConnection" */'@/components/ModalEditConnection'),
ModalSettings: () => import(/* webpackChunkName: "ModalSettings" */'@/components/ModalSettings')
},
data () {
return {

View File

@ -31,7 +31,10 @@
<div class="col-8 col-sm-12">
<select v-model="localConnection.client" class="form-select">
<option value="mysql">
MySQL/MariaDB
MySQL
</option>
<option value="maria">
MariaDB
</option>
<option value="mssql">
Microsoft SQL

View File

@ -35,7 +35,10 @@
@change="setDefaults"
>
<option value="mysql">
MySQL/MariaDB
MySQL
</option>
<option value="maria">
MariaDB
</option>
<option value="mssql">
Microsoft SQL

View File

@ -102,9 +102,11 @@ export default {
changeExplorebarSize: 'settings/changeExplorebarSize'
}),
async refresh () {
this.isRefreshing = true;
await this.refreshStructure(this.connection.uid);
this.isRefreshing = false;
if (!this.isRefreshing) {
this.isRefreshing = true;
await this.refreshStructure(this.connection.uid);
this.isRefreshing = false;
}
},
resize (e) {
const el = this.$refs.explorebar;

View File

@ -10,7 +10,7 @@
<span>{{ database.name }}</span>
</summary>
<div class="accordion-body">
<div class="database-bables">
<div class="database-tables">
<ul class="menu menu-nav pt-0">
<li
v-for="table of database.tables"
@ -63,6 +63,7 @@ export default {
align-items: center;
padding: .1rem;
cursor: pointer;
font-size: .7rem;
> span{
overflow: hidden;
@ -78,7 +79,11 @@ export default {
}
}
.database-bables{
.menu-item{
line-height: 1.2;
}
.database-tables{
margin-left: 1.2rem;
}
}

View File

@ -4,34 +4,26 @@
<QueryEditor v-model="query" />
<div class="workspace-query-runner-footer">
<div class="workspace-query-buttons">
<i class="material-icons text-success" @click="runQuery">play_arrow</i>
<button
class="btn btn-link btn-sm"
:class="{'loading':isQuering}"
@click="runQuery"
>
<span>{{ $t('word.run') }}</span>
<i class="material-icons text-success">play_arrow</i>
</button>
<button class="btn btn-link btn-sm">
<span>{{ $t('word.save') }}</span>
<i class="material-icons ml-1">save</i>
</button>
</div>
<div>
Schema: <b>{{ workspace.breadcrumbs.database }}</b>
<div v-if="workspace.breadcrumbs.database">
{{ $t('word.schema') }}: <b>{{ workspace.breadcrumbs.database }}</b>
</div>
</div>
</div>
<div ref="resultTable" class="workspace-query-results column col-12">
<table v-if="results" class="table table-hover">
<thead>
<tr>
<th v-for="field in results.fields" :key="field.name">
{{ field.name }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rKey) in results.rows" :key="rKey">
<td
v-for="(col, cKey) in row"
:key="cKey"
:class="fieldType(col)"
>
{{ col }}
</td>
</tr>
</tbody>
</table>
<WorkspaceQueryTable v-if="results" :results="results" />
</div>
</div>
</template>
@ -39,12 +31,14 @@
<script>
import Connection from '@/ipc-api/Connection';
import QueryEditor from '@/components/QueryEditor';
import WorkspaceQueryTable from '@/components/WorkspaceQueryTable';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'WorkspaceQueryTab',
components: {
QueryEditor
QueryEditor,
WorkspaceQueryTable
},
props: {
connection: Object
@ -52,6 +46,7 @@ export default {
data () {
return {
query: '',
isQuering: false,
results: {}
};
},
@ -75,6 +70,7 @@ export default {
}),
async runQuery () {
if (!this.query) return;
this.isQuering = true;
this.results = {};
this.resizeResults();
@ -94,6 +90,8 @@ export default {
catch (err) {
this.addNotification({ status: 'error', message: err.stack });
}
this.isQuering = false;
},
resizeResults (e) {
const el = this.$refs.resultTable;
@ -126,11 +124,18 @@ export default {
.workspace-query-runner-footer{
display: flex;
justify-content: space-between;
padding: .2rem .6rem;
padding: .3rem .6rem .4rem;
align-items: center;
.workspace-query-buttons{
display: flex;
.btn{
display: flex;
align-self: center;
color: $body-font-color;
margin-right: .4rem;
}
}
}
}
@ -139,38 +144,33 @@ export default {
overflow: auto;
white-space: nowrap;
th{
position: sticky;
top: 0;
background: $bg-color;
border-color: $bg-color-light;
}
.table{
width: auto;
td{
border-color: $bg-color-light;
padding: 0 .4rem;
text-overflow: ellipsis;
max-width: 200px;
white-space: nowrap;
overflow: hidden;
.tr:focus{
background: rgba($color: #000000, $alpha: .3);
}
&.type-string{
color: seagreen;
.th{
position: sticky;
top: 0;
background: $bg-color;
border-color: $bg-color-light;
padding: .1rem .4rem;
font-weight: 400;
}
&.type-number{
color: cornflowerblue;
text-align: right;
}
&.type-date{
color: coral;
}
&.type-blob{
color: darkorchid;
}
&.type-null{
color: gray;
&::after{
content: 'NULL';
.td{
border-left: 1px solid;
border-color: $bg-color-light;
padding: 0 .4rem;
text-overflow: ellipsis;
max-width: 200px;
white-space: nowrap;
overflow: hidden;
&:first-child{
border-left: none;
}
}
}

View File

@ -0,0 +1,56 @@
<template>
<div v-if="results" class="table table-hover">
<div class="thead">
<div class="tr">
<div
v-for="field in results.fields"
:key="field.name"
class="th"
>
{{ field.name }}
</div>
</div>
</div>
<div class="tbody">
<div
v-for="(row, rKey) in results.rows"
:key="rKey"
class="tr"
tabindex="0"
>
<div
v-for="(col, cKey) in row"
:key="cKey"
class="td"
:class="fieldType(col)"
>
{{ col }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'WorkspaceQueryTable',
props: {
results: Object
},
methods: {
fieldType (col) {
let type = typeof col;
if (type === 'object')
if (col instanceof Date) type = 'date';
if (col instanceof Uint8Array) type = 'blob';
if (col === null) type = 'null';
return `type-${type}`;
}
}
};
</script>
<style>
</style>

View File

@ -26,7 +26,9 @@ module.exports = {
about: 'About',
language: 'Language',
version: 'Version',
donate: 'Donate'
donate: 'Donate',
run: 'Run',
schema: 'Schema'
},
message: {
appWelcome: 'Welcome to Antares SQL Client!',

View File

@ -26,7 +26,8 @@ module.exports = {
about: 'Informazioni',
language: 'Lingua',
version: 'Versione',
donate: 'Dona'
donate: 'Dona',
run: 'Esegui'
},
message: {
appWelcome: 'Benvenuto in Antares SQL Client!',

View File

@ -0,0 +1,25 @@
@mixin type-colors($types) {
@each $type, $color in $types {
.type-#{$type} {
color: $color;
@if $type == 'null'{
&::after{
content: 'NULL';
}
}
@if $type == 'number'{
text-align: right;
}
}
}
}
@include type-colors((
"string": seagreen,
"number": cornflowerblue,
"date": coral,
"blob": darkorchid,
"null": gray,
))

View File

@ -0,0 +1,65 @@
.table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
display: table;
&.table-striped {
.tbody {
.tr:nth-of-type(odd) {
background: $bg-color;
}
}
}
&,
&.table-striped {
.tbody {
.tr {
&.active {
background: $bg-color-dark;
}
}
}
}
&.table-hover {
.tbody {
.tr {
&:hover {
background: $bg-color-dark;
}
}
}
}
// Scollable tables
&.table-scroll {
display: block;
overflow-x: auto;
padding-bottom: .75rem;
white-space: nowrap;
}
.thead{
display: table-header-group;
}
.tbody{
display: table-row-group;
}
.tr{
display: table-row;
}
.td,
.th {
border-bottom: $border-width solid $border-color;
padding: $unit-3 $unit-2;
display: table-cell;
}
.th {
border-bottom-width: $border-width-lg;
}
}

View File

@ -1,5 +1,9 @@
@import "~spectre.css/src/variables";
@import "variables";
@import "transitions";
@import "data-types";
@import "fake-tables";
@import "mdi-additions";
@import "db-icons";
@import "~spectre.css/src/spectre";
@ -131,4 +135,11 @@ body{
.accordion-body {
max-height: 500rem!important;
}
.btn.loading {
> .material-icons,
> span{
visibility: hidden;
}
}