mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
3b4f1475df | |||
155154b43d | |||
a95b8d188c | |||
cb1fce6f99 | |||
0014f48079 | |||
fc35f271d7 | |||
65ad0e954d |
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -1 +1,6 @@
|
||||
* text eol=lf
|
||||
* text eol=lf
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.icns binary
|
5
.github/workflows/codeql-analysis.yml
vendored
5
.github/workflows/codeql-analysis.yml
vendored
@@ -31,11 +31,6 @@ jobs:
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
|
11
.travis.yml
11
.travis.yml
@@ -1,9 +1,6 @@
|
||||
language: node_js
|
||||
node_js: 12
|
||||
|
||||
before_install:
|
||||
- npm install
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
@@ -20,6 +17,9 @@ env:
|
||||
jobs:
|
||||
include:
|
||||
- stage: Test
|
||||
before_install:
|
||||
- sudo apt-get install libsecret-1-dev
|
||||
- npm install
|
||||
script:
|
||||
- npm test
|
||||
|
||||
@@ -27,6 +27,9 @@ jobs:
|
||||
if: tag IS present
|
||||
os: linux
|
||||
services: docker
|
||||
before_install:
|
||||
- sudo apt-get install libsecret-1-dev
|
||||
- npm install
|
||||
script:
|
||||
- docker run --rm --env-file <(env | grep -iE 'DEBUG|NODE_|ELECTRON_|NPM_|CI|CIRCLE|TRAVIS|APPVEYOR_|CSC_|_TOKEN|_KEY|AWS_|STRIP|BUILD_') -v ${PWD}:/project -v ~/.cache/electron:/root/.cache/electron -v ~/.cache/electron-builder:/root/.cache/electron-builder electronuserland/builder:wine /bin/bash -c "npm run build -- --linux --win -p always"
|
||||
before_cache:
|
||||
@@ -35,6 +38,8 @@ jobs:
|
||||
- stage: Deploy Mac
|
||||
if: tag IS present
|
||||
os: osx
|
||||
before_install:
|
||||
- npm install
|
||||
osx_image: xcode10.2
|
||||
script:
|
||||
- npm run build -- -p always
|
||||
|
10
CHANGELOG.md
10
CHANGELOG.md
@@ -2,6 +2,16 @@
|
||||
|
||||
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.0.12](https://github.com/Fabio286/antares/compare/v0.0.11...v0.0.12) (2020-12-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* better security connections credentials storage ([fc35f27](https://github.com/Fabio286/antares/commit/fc35f271d7fe384cd786ce33547c0ef17135ddd8))
|
||||
* option to change editor theme ([a95b8d1](https://github.com/Fabio286/antares/commit/a95b8d188cfcc8f563ad73b4f0b676d068775d36))
|
||||
* option to toggle editor auto completion ([155154b](https://github.com/Fabio286/antares/commit/155154b43d0cd02ae875ded3ce865a37a999da5c))
|
||||
* query editor auto-completer for tables and columns ([cb1fce6](https://github.com/Fabio286/antares/commit/cb1fce6f998ea7332886820910e245ab19416a9d))
|
||||
|
||||
### [0.0.11](https://github.com/Fabio286/antares/compare/v0.0.10...v0.0.11) (2020-12-15)
|
||||
|
||||
|
||||
|
@@ -33,9 +33,10 @@ An application created with minimalism and semplicity in mind, with features in
|
||||
- Database management (add/edit/delete).
|
||||
- Full tables management, including indexes and foreign keys.
|
||||
- Run queries on multiple tabs.
|
||||
- Query suggestions.
|
||||
- Query suggestions and auto complete.
|
||||
- Native dark theme.
|
||||
- Multi language.
|
||||
- Secure password storage.
|
||||
- Auto updates.
|
||||
|
||||
## Coming soon
|
||||
@@ -44,13 +45,10 @@ This is a roadmap with major features will come in near future.
|
||||
|
||||
- Stored procedures, views, schedulers and triggers support.
|
||||
- Users management (add/edit/delete).
|
||||
- More secure password storage.
|
||||
- Database tools (variables, process list...).
|
||||
- SSL and SSH tunnel support.
|
||||
- Support for other databases.
|
||||
- UI/UX improvements.
|
||||
- Improvements of query editor area.
|
||||
- Improvements of query suggestions.
|
||||
- Query history.
|
||||
- More context menu shortcuts.
|
||||
- More keyboard shortcuts.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "antares",
|
||||
"productName": "Antares",
|
||||
"version": "0.0.11",
|
||||
"version": "0.0.12",
|
||||
"description": "A cross-platform easy to use SQL client.",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/Fabio286/antares.git",
|
||||
@@ -48,11 +48,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/font": "^5.8.55",
|
||||
"ace-builds": "^1.4.12",
|
||||
"electron-log": "^4.3.0",
|
||||
"electron-store": "^6.0.1",
|
||||
"electron-updater": "^4.3.5",
|
||||
"keytar": "^7.3.0",
|
||||
"lodash": "^4.17.20",
|
||||
"moment": "^2.29.1",
|
||||
"monaco-editor": "^0.20.0",
|
||||
"mssql": "^6.2.3",
|
||||
"mysql": "^2.18.1",
|
||||
"pg": "^8.5.1",
|
||||
@@ -78,7 +80,6 @@
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-vue": "^7.1.0",
|
||||
"monaco-editor-webpack-plugin": "^1.9.1",
|
||||
"node-sass": "^5.0.0",
|
||||
"sass-loader": "^10.1.0",
|
||||
"standard-version": "^9.0.0",
|
||||
|
@@ -2,7 +2,9 @@
|
||||
|
||||
import { app, BrowserWindow, nativeImage } from 'electron';
|
||||
import * as path from 'path';
|
||||
import crypto from 'crypto';
|
||||
import { format as formatUrl } from 'url';
|
||||
import keytar from 'keytar';
|
||||
import ipcHandlers from './ipc-handlers';
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||
@@ -89,7 +91,14 @@ else {
|
||||
});
|
||||
|
||||
// create main BrowserWindow when electron is ready
|
||||
app.on('ready', () => {
|
||||
app.on('ready', async () => {
|
||||
let key = await keytar.getPassword('antares', 'user');
|
||||
|
||||
if (!key) {
|
||||
key = crypto.randomBytes(16).toString('hex');
|
||||
keytar.setPassword('antares', 'user', key);
|
||||
}
|
||||
|
||||
mainWindow = createMainWindow();
|
||||
});
|
||||
}
|
||||
|
@@ -1,7 +1,13 @@
|
||||
import keytar from 'keytar';
|
||||
import { app, ipcMain } from 'electron';
|
||||
|
||||
export default () => {
|
||||
ipcMain.on('close-app', () => {
|
||||
app.exit();
|
||||
});
|
||||
|
||||
ipcMain.on('get-key', async event => {
|
||||
const key = await keytar.getPassword('antares', 'user');
|
||||
event.returnValue = key;
|
||||
});
|
||||
};
|
||||
|
@@ -45,59 +45,139 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedTab === 'general'" class="panel-body py-4">
|
||||
<form class="form-horizontal">
|
||||
<div class="col-8 col-sm-12">
|
||||
<div class="form-group mb-4">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
<i class="mdi mdi-18px mdi-translate mr-1" />
|
||||
{{ $t('word.language') }}:
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-6 col-sm-12">
|
||||
<select
|
||||
v-model="localLocale"
|
||||
class="form-select"
|
||||
@change="changeLocale(localLocale)"
|
||||
>
|
||||
<option
|
||||
v-for="(locale, key) in locales"
|
||||
:key="key"
|
||||
:value="locale.code"
|
||||
<div class="container">
|
||||
<form class="form-horizontal columns">
|
||||
<div class="column col-12 h6 text-uppercase mb-1">
|
||||
{{ $t('word.application') }}
|
||||
</div>
|
||||
<div class="column col-8 col-sm-12 mb-2">
|
||||
<div class="form-group mb-4">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
<i class="mdi mdi-18px mdi-translate mr-1" />
|
||||
{{ $t('word.language') }}:
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-6 col-sm-12">
|
||||
<select
|
||||
v-model="localLocale"
|
||||
class="form-select"
|
||||
@change="changeLocale(localLocale)"
|
||||
>
|
||||
{{ locale.name }}
|
||||
</option>
|
||||
</select>
|
||||
<option
|
||||
v-for="(locale, key) in locales"
|
||||
:key="key"
|
||||
:value="locale.code"
|
||||
>
|
||||
{{ locale.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.notificationsTimeout') }}:
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-6 col-sm-12">
|
||||
<div class="input-group">
|
||||
<input
|
||||
v-model="localTimeout"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
@focusout="checkNotificationsTimeout"
|
||||
>
|
||||
<span class="input-group-addon">{{ $t('word.seconds') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.notificationsTimeout') }}:
|
||||
</label>
|
||||
|
||||
<div class="column col-12 h6 mt-4 text-uppercase mb-1">
|
||||
{{ $t('word.editor') }}
|
||||
</div>
|
||||
<div class="column col-8 col-sm-12">
|
||||
<div class="form-group">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('word.autoCompletion') }}:
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-switch d-inline-block" @click.prevent="toggleAutoComplete">
|
||||
<input type="checkbox" :checked="selectedAutoComplete">
|
||||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-12">
|
||||
<div class="input-group">
|
||||
<input
|
||||
v-model="localTimeout"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
@focusout="checkNotificationsTimeout"
|
||||
>
|
||||
<span class="input-group-addon">{{ $t('word.seconds') }}</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedTab === 'themes'" class="panel-body py-4">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column col-12 h6 text-uppercase mb-2">
|
||||
{{ $t('message.applicationTheme') }}
|
||||
</div>
|
||||
<div class="column col-6 c-hand theme-block" :class="{'selected': applicationTheme === 'dark'}">
|
||||
<img :src="require('@/images/dark.png').default" class="img-responsive img-fit-cover s-rounded">
|
||||
<div class="theme-name">
|
||||
<i class="mdi mdi-moon-waning-crescent mdi-48px" />
|
||||
<div class="h6 mt-4">
|
||||
{{ $t('word.dark') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column col-6 theme-block disabled" :class="{'selected': applicationTheme === 'light'}">
|
||||
<div class="theme-name">
|
||||
<i class="mdi mdi-white-balance-sunny mdi-48px" />
|
||||
<div class="h6 mt-4">
|
||||
{{ $t('word.light') }} (Coming)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedTab === 'themes'" class="panel-body py-4">
|
||||
<div class="text-center">
|
||||
<p>In future releases</p>
|
||||
<div class="columns mt-4">
|
||||
<div class="column col-12 h6 text-uppercase mb-2 mt-4">
|
||||
{{ $t('message.editorTheme') }}
|
||||
</div>
|
||||
<div class="column col-6 h5 mb-4">
|
||||
<select
|
||||
v-model="localEditorTheme"
|
||||
class="form-select"
|
||||
@change="changeEditorTheme(localEditorTheme)"
|
||||
>
|
||||
<optgroup
|
||||
v-for="group in editorThemes"
|
||||
:key="group.group"
|
||||
:label="group.group"
|
||||
>
|
||||
<option
|
||||
v-for="theme in group.themes"
|
||||
:key="theme.name"
|
||||
:value="theme.code"
|
||||
:selected="editorTheme === theme.code"
|
||||
>
|
||||
{{ theme.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="column col-12">
|
||||
<QueryEditor
|
||||
:value="exampleQuery"
|
||||
:workspace="workspace"
|
||||
:read-only="true"
|
||||
:height="270"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -127,18 +207,70 @@
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import localesNames from '@/i18n/supported-locales';
|
||||
import ModalSettingsUpdate from '@/components/ModalSettingsUpdate';
|
||||
import QueryEditor from '@/components/QueryEditor';
|
||||
const { shell } = require('electron');
|
||||
|
||||
export default {
|
||||
name: 'ModalSettings',
|
||||
components: {
|
||||
ModalSettingsUpdate
|
||||
ModalSettingsUpdate,
|
||||
QueryEditor
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
localLocale: null,
|
||||
localTimeout: null,
|
||||
selectedTab: 'general'
|
||||
localEditorTheme: null,
|
||||
selectedTab: 'general',
|
||||
editorThemes: [
|
||||
{
|
||||
group: this.$t('word.light'),
|
||||
themes: [
|
||||
{ code: 'chrome', name: 'Chrome' },
|
||||
{ code: 'clouds', name: 'Clouds' },
|
||||
{ code: 'crimson_editor', name: 'Crimson Editor' },
|
||||
{ code: 'dawn', name: 'Dawn' },
|
||||
{ code: 'dreamweaver', name: 'Dreamweaver' },
|
||||
{ code: 'eclupse', name: 'Eclipse' },
|
||||
{ code: 'github', name: 'GitHub' },
|
||||
{ code: 'iplastic', name: 'IPlastic' },
|
||||
{ code: 'solarized_light', name: 'Solarized Light' },
|
||||
{ code: 'textmate', name: 'TextMate' },
|
||||
{ code: 'tomorrow', name: 'Tomorrow' },
|
||||
{ code: 'xcode', name: 'Xcode' },
|
||||
{ code: 'kuroir', name: 'Kuroir' },
|
||||
{ code: 'katzenmilch', name: 'KatzenMilch' },
|
||||
{ code: 'sqlserver', name: 'SQL Server' }
|
||||
]
|
||||
},
|
||||
{
|
||||
group: this.$t('word.dark'),
|
||||
themes: [
|
||||
{ code: 'ambiance', name: 'Ambiance' },
|
||||
{ code: 'chaos', name: 'Chaos' },
|
||||
{ code: 'clouds_midnight', name: 'Clouds Midnight' },
|
||||
{ code: 'dracula', name: 'Dracula' },
|
||||
{ code: 'cobalt', name: 'Cobalt' },
|
||||
{ code: 'gruvbox', name: 'Gruvbox' },
|
||||
{ code: 'gob', name: 'Green on Black' },
|
||||
{ code: 'idle_fingers', name: 'Idle Fingers' },
|
||||
{ code: 'kr_theme', name: 'krTheme' },
|
||||
{ code: 'merbivore', name: 'Merbivore' },
|
||||
{ code: 'mono_industrial', name: 'Mono Industrial' },
|
||||
{ code: 'monokai', name: 'Monokai' },
|
||||
{ code: 'nord_dark', name: 'Nord Dark' },
|
||||
{ code: 'pastel_on_dark', name: 'Pastel on Dark' },
|
||||
{ code: 'solarized_dark', name: 'Solarized Dark' },
|
||||
{ code: 'terminal', name: 'Terminal' },
|
||||
{ code: 'tomorrow_night', name: 'Tomorrow Night' },
|
||||
{ code: 'tomorrow_night_blue', name: 'Tomorrow Night Blue' },
|
||||
{ code: 'tomorrow_night_bright', name: 'Tomorrow Night Bright' },
|
||||
{ code: 'tomorrow_night_eighties', name: 'Tomorrow Night 80s' },
|
||||
{ code: 'twilight', name: 'Twilight' },
|
||||
{ code: 'vibrant_ink', name: 'Vibrant Ink' }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -147,8 +279,13 @@ export default {
|
||||
appVersion: 'application/appVersion',
|
||||
selectedSettingTab: 'application/selectedSettingTab',
|
||||
selectedLocale: 'settings/getLocale',
|
||||
selectedAutoComplete: 'settings/getAutoComplete',
|
||||
notificationsTimeout: 'settings/getNotificationsTimeout',
|
||||
updateStatus: 'application/getUpdateStatus'
|
||||
applicationTheme: 'settings/getApplicationTheme',
|
||||
editorTheme: 'settings/getEditorTheme',
|
||||
updateStatus: 'application/getUpdateStatus',
|
||||
selectedWorkspace: 'workspaces/getSelected',
|
||||
getWorkspace: 'workspaces/getWorkspace'
|
||||
}),
|
||||
locales () {
|
||||
const locales = [];
|
||||
@@ -159,11 +296,32 @@ export default {
|
||||
},
|
||||
hasUpdates () {
|
||||
return ['available', 'downloading', 'downloaded'].includes(this.updateStatus);
|
||||
},
|
||||
workspace () {
|
||||
return this.getWorkspace(this.selectedWorkspace);
|
||||
},
|
||||
exampleQuery () {
|
||||
return `-- This is an example
|
||||
SELECT
|
||||
employee.id,
|
||||
employee.first_name,
|
||||
employee.last_name,
|
||||
SUM(DATEDIFF("SECOND", call.start, call.end)) AS call_duration
|
||||
FROM call
|
||||
INNER JOIN employee ON call.employee_id = employee.id
|
||||
GROUP BY
|
||||
employee.id,
|
||||
employee.first_name,
|
||||
employee.last_name
|
||||
ORDER BY
|
||||
employee.id ASC;
|
||||
`;
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.localLocale = this.selectedLocale;
|
||||
this.localTimeout = this.notificationsTimeout;
|
||||
this.localEditorTheme = this.editorTheme;
|
||||
this.selectedTab = this.selectedSettingTab;
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -174,6 +332,8 @@ export default {
|
||||
...mapActions({
|
||||
closeModal: 'application/hideSettingModal',
|
||||
changeLocale: 'settings/changeLocale',
|
||||
changeAutoComplete: 'settings/changeAutoComplete',
|
||||
changeEditorTheme: 'settings/changeEditorTheme',
|
||||
updateNotificationsTimeout: 'settings/updateNotificationsTimeout'
|
||||
}),
|
||||
selectTab (tab) {
|
||||
@@ -192,6 +352,9 @@ export default {
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Escape')
|
||||
this.closeModal();
|
||||
},
|
||||
toggleAutoComplete () {
|
||||
this.changeAutoComplete(!this.selectedAutoComplete);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -205,6 +368,34 @@ export default {
|
||||
.panel-body {
|
||||
height: calc(70vh - 70px);
|
||||
overflow: auto;
|
||||
|
||||
.theme-block {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
||||
&.selected {
|
||||
img {
|
||||
box-shadow: 0 0 0 3px $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.theme-name {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-shadow: 0 0 8px #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.badge::after {
|
||||
|
@@ -1,43 +1,171 @@
|
||||
<template>
|
||||
<div class="editor-wrapper">
|
||||
<div ref="editor" class="editor" />
|
||||
<div
|
||||
ref="editor"
|
||||
class="editor"
|
||||
:style="{height: `${height}px`}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||
import { completionItemProvider } from '@/suggestions/sql';
|
||||
|
||||
monaco.languages.registerCompletionItemProvider('sql', completionItemProvider(monaco));
|
||||
import * as ace from 'ace-builds';
|
||||
import 'ace-builds/webpack-resolver';
|
||||
import '../libs/ext-language_tools';
|
||||
import { mapGetters } from 'vuex';
|
||||
import Tables from '@/ipc-api/Tables';
|
||||
|
||||
export default {
|
||||
name: 'QueryEditor',
|
||||
props: {
|
||||
value: String,
|
||||
autoFocus: { type: Boolean, default: false }
|
||||
workspace: Object,
|
||||
schema: { type: String, default: '' },
|
||||
autoFocus: { type: Boolean, default: false },
|
||||
readOnly: { type: Boolean, default: false },
|
||||
height: { type: Number, default: 200 }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
editor: null
|
||||
editor: null,
|
||||
fields: [],
|
||||
baseCompleter: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
editorTheme: 'settings/getEditorTheme',
|
||||
autoComplete: 'settings/getAutoComplete'
|
||||
}),
|
||||
tables () {
|
||||
return this.workspace
|
||||
? this.workspace.structure.filter(schema => schema.name === this.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.tables);
|
||||
return acc;
|
||||
}, []).map(table => {
|
||||
return {
|
||||
name: table.name,
|
||||
comment: table.comment,
|
||||
type: table.type,
|
||||
fields: []
|
||||
};
|
||||
})
|
||||
: [];
|
||||
},
|
||||
mode () {
|
||||
switch (this.workspace.client) {
|
||||
case 'mysql':
|
||||
case 'maria':
|
||||
return 'mysql';
|
||||
case 'mssql':
|
||||
return 'sqlserver';
|
||||
case 'pg':
|
||||
return 'pgsql';
|
||||
default:
|
||||
return 'sql';
|
||||
}
|
||||
},
|
||||
lastWord () {
|
||||
const words = this.value.split(' ');
|
||||
return words[words.length - 1];
|
||||
},
|
||||
isLastWordATable () {
|
||||
return /\w+\.\w*/gm.test(this.lastWord);
|
||||
},
|
||||
fieldsCompleter () {
|
||||
return {
|
||||
getCompletions: (editor, session, pos, prefix, callback) => {
|
||||
const completions = [];
|
||||
this.fields.forEach(field => {
|
||||
completions.push({
|
||||
value: field,
|
||||
meta: 'column',
|
||||
score: 1000
|
||||
});
|
||||
});
|
||||
callback(null, completions);
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
editorTheme () {
|
||||
if (this.editor)
|
||||
this.editor.setTheme(`ace/theme/${this.editorTheme}`);
|
||||
},
|
||||
autoComplete () {
|
||||
if (this.editor) {
|
||||
this.editor.setOptions({
|
||||
enableLiveAutocompletion: this.autoComplete
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.editor = monaco.editor.create(this.$refs.editor, {
|
||||
this.editor = ace.edit(this.$refs.editor, {
|
||||
mode: `ace/mode/${this.mode}`,
|
||||
theme: `ace/theme/${this.editorTheme}`,
|
||||
value: this.value,
|
||||
language: 'sql',
|
||||
theme: 'vs-dark',
|
||||
autoIndent: true,
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
contextmenu: false,
|
||||
wordBasedSuggestions: true,
|
||||
acceptSuggestionOnEnter: 'smart',
|
||||
quickSuggestions: true
|
||||
fontSize: '14px',
|
||||
printMargin: false,
|
||||
readOnly: this.readOnly
|
||||
});
|
||||
|
||||
this.editor.onDidChangeModelContent(e => {
|
||||
this.editor.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: this.autoComplete
|
||||
});
|
||||
|
||||
this.editor.completers.push({
|
||||
getCompletions: (editor, session, pos, prefix, callback) => {
|
||||
const completions = [];
|
||||
this.tables.forEach(table => {
|
||||
completions.push({
|
||||
value: table.name,
|
||||
meta: table.type,
|
||||
caption: table.comment
|
||||
});
|
||||
});
|
||||
callback(null, completions);
|
||||
}
|
||||
});
|
||||
|
||||
this.baseCompleter = this.editor.completers;
|
||||
|
||||
this.editor.commands.on('afterExec', e => {
|
||||
if (['insertstring', 'backspace', 'del'].includes(e.command.name)) {
|
||||
if (this.isLastWordATable || e.args === '.') {
|
||||
if (e.args !== ' ') {
|
||||
const table = this.tables.find(t => t.name === this.lastWord.split('.').pop());
|
||||
|
||||
if (table) {
|
||||
const params = {
|
||||
uid: this.workspace.uid,
|
||||
schema: this.schema,
|
||||
table: table.name
|
||||
};
|
||||
|
||||
Tables.getTableColumns(params).then(res => {
|
||||
if (res.response.length)
|
||||
this.fields = res.response.map(field => field.name);
|
||||
this.editor.completers = [this.fieldsCompleter];
|
||||
this.editor.execCommand('startAutocomplete');
|
||||
}).catch(console.log);
|
||||
}
|
||||
else
|
||||
this.editor.completers = this.baseCompleter;
|
||||
}
|
||||
else
|
||||
this.editor.completers = this.baseCompleter;
|
||||
}
|
||||
else
|
||||
this.editor.completers = this.baseCompleter;
|
||||
}
|
||||
});
|
||||
|
||||
this.editor.session.on('change', () => {
|
||||
const content = this.editor.getValue();
|
||||
this.$emit('update:value', content);
|
||||
});
|
||||
@@ -47,31 +175,34 @@ export default {
|
||||
this.editor.focus();
|
||||
}, 20);
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.editor && this.editor.dispose();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.editor-wrapper {
|
||||
border-bottom: 1px solid #444;
|
||||
.editor-wrapper {
|
||||
border-bottom: 1px solid #444;
|
||||
|
||||
.editor {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
.editor {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
.CodeMirror-scroll {
|
||||
max-width: 100%;
|
||||
}
|
||||
.ace_.mdi {
|
||||
display: inline-block;
|
||||
width: 17px;
|
||||
}
|
||||
|
||||
.CodeMirror-line {
|
||||
word-break: break-word !important;
|
||||
white-space: pre-wrap !important;
|
||||
}
|
||||
}
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {
|
||||
background-color: #c9561a99;
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_line-hover {
|
||||
background-color: #c9571a33;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight {
|
||||
color: #e0d00c;
|
||||
}
|
||||
</style>
|
||||
|
@@ -193,6 +193,7 @@ export default {
|
||||
align-items: flex-start;
|
||||
flex-wrap: nowrap;
|
||||
overflow: auto;
|
||||
margin-bottom: 0;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 2px;
|
||||
|
@@ -5,6 +5,8 @@
|
||||
v-if="isSelected"
|
||||
:auto-focus="true"
|
||||
:value.sync="query"
|
||||
:workspace="workspace"
|
||||
:schema="schema"
|
||||
/>
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
|
@@ -62,7 +62,12 @@ module.exports = {
|
||||
table: 'Table',
|
||||
discard: 'Discard',
|
||||
stay: 'Stay',
|
||||
author: 'Author'
|
||||
author: 'Author',
|
||||
light: 'Light',
|
||||
dark: 'Dark',
|
||||
autoCompletion: 'Auto Completion',
|
||||
application: 'Application',
|
||||
editor: 'Editor'
|
||||
},
|
||||
message: {
|
||||
appWelcome: 'Welcome to Antares SQL Client!',
|
||||
@@ -124,7 +129,9 @@ module.exports = {
|
||||
referenceField: 'Ref. field',
|
||||
foreignFields: 'Foreign fields',
|
||||
invalidDefault: 'Invalid default',
|
||||
onDelete: 'On delete'
|
||||
onDelete: 'On delete',
|
||||
applicationTheme: 'Application Theme',
|
||||
editorTheme: 'Editor Theme'
|
||||
},
|
||||
// Date and Time
|
||||
short: {
|
||||
|
BIN
src/renderer/images/dark.png
Normal file
BIN
src/renderer/images/dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
8
src/renderer/ipc-api/Application.js
Normal file
8
src/renderer/ipc-api/Application.js
Normal file
@@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
export default class {
|
||||
static getKey (params) {
|
||||
return ipcRenderer.sendSync('get-key', params);
|
||||
}
|
||||
}
|
2263
src/renderer/libs/ext-language_tools.js
Normal file
2263
src/renderer/libs/ext-language_tools.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,18 @@
|
||||
'use strict';
|
||||
import Store from 'electron-store';
|
||||
import Application from '../../ipc-api/Application';
|
||||
const key = Application.getKey();
|
||||
|
||||
const persistentStore = new Store({
|
||||
name: 'connections',
|
||||
encryptionKey: key
|
||||
});
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
strict: true,
|
||||
state: {
|
||||
connections: []
|
||||
connections: persistentStore.get('connections') || []
|
||||
},
|
||||
getters: {
|
||||
getConnections: state => state.connections,
|
||||
@@ -20,9 +28,11 @@ export default {
|
||||
mutations: {
|
||||
ADD_CONNECTION (state, connection) {
|
||||
state.connections.push(connection);
|
||||
persistentStore.set('connections', state.connections);
|
||||
},
|
||||
DELETE_CONNECTION (state, connection) {
|
||||
state.connections = state.connections.filter(el => el.uid !== connection.uid);
|
||||
persistentStore.set('connections', state.connections);
|
||||
},
|
||||
EDIT_CONNECTION (state, connection) {
|
||||
const editedConnections = state.connections.map(conn => {
|
||||
@@ -31,9 +41,11 @@ export default {
|
||||
});
|
||||
state.connections = editedConnections;
|
||||
state.selected_conection = {};
|
||||
persistentStore.set('connections', state.connections);
|
||||
},
|
||||
UPDATE_CONNECTIONS (state, connections) {
|
||||
state.connections = connections;
|
||||
persistentStore.set('connections', state.connections);
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
@@ -1,29 +1,47 @@
|
||||
'use strict';
|
||||
import i18n from '@/i18n';
|
||||
import Store from 'electron-store';
|
||||
const persistentStore = new Store({ name: 'settings' });
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
strict: true,
|
||||
state: {
|
||||
locale: 'en-US',
|
||||
explorebar_size: null,
|
||||
notifications_timeout: 5
|
||||
locale: persistentStore.get('locale') || 'en-US',
|
||||
explorebar_size: persistentStore.get('explorebar_size') || null,
|
||||
notifications_timeout: persistentStore.get('notifications_timeout') || 5,
|
||||
auto_complete: persistentStore.get('auto_complete') || true,
|
||||
application_theme: persistentStore.get('application_theme') || 'dark',
|
||||
editor_theme: persistentStore.get('editor_theme') || 'twilight'
|
||||
},
|
||||
getters: {
|
||||
getLocale: state => state.locale,
|
||||
getExplorebarSize: state => state.explorebar_size,
|
||||
getNotificationsTimeout: state => state.notifications_timeout
|
||||
getNotificationsTimeout: state => state.notifications_timeout,
|
||||
getAutoComplete: state => state.auto_complete,
|
||||
getApplicationTheme: state => state.application_theme,
|
||||
getEditorTheme: state => state.editor_theme
|
||||
},
|
||||
mutations: {
|
||||
SET_LOCALE (state, locale) {
|
||||
state.locale = locale;
|
||||
i18n.locale = locale;
|
||||
persistentStore.set('locale', state.locale);
|
||||
},
|
||||
SET_NOTIFICATIONS_TIMEOUT (state, timeout) {
|
||||
state.notifications_timeout = timeout;
|
||||
persistentStore.set('notifications_timeout', state.notifications_timeout);
|
||||
},
|
||||
SET_AUTO_COMPLETE (state, val) {
|
||||
state.auto_complete = val;
|
||||
persistentStore.set('auto_complete', state.auto_complete);
|
||||
},
|
||||
SET_EXPLOREBAR_SIZE (state, size) {
|
||||
state.explorebar_size = size;
|
||||
persistentStore.set('explorebar_size', state.explorebar_size);
|
||||
},
|
||||
SET_EDITOR_THEME (state, theme) {
|
||||
state.editor_theme = theme;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@@ -35,6 +53,12 @@ export default {
|
||||
},
|
||||
changeExplorebarSize ({ commit }, size) {
|
||||
commit('SET_EXPLOREBAR_SIZE', size);
|
||||
},
|
||||
changeAutoComplete ({ commit }, val) {
|
||||
commit('SET_AUTO_COMPLETE', val);
|
||||
},
|
||||
changeEditorTheme ({ commit }, theme) {
|
||||
commit('SET_EDITOR_THEME', theme);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,12 +0,0 @@
|
||||
import { functions } from '@/suggestions/sql/sql-functions';
|
||||
import { keywords } from '@/suggestions/sql/sql-keywords';
|
||||
import { operators } from '@/suggestions/sql/sql-operators';
|
||||
import { variables } from '@/suggestions/sql/sql-variables';
|
||||
|
||||
export const completionItemProvider = (monaco) => {
|
||||
return {
|
||||
provideCompletionItems () {
|
||||
return { suggestions: [...functions(monaco), ...keywords(monaco), ...operators(monaco), ...variables(monaco)] };
|
||||
}
|
||||
};
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,142 +0,0 @@
|
||||
export const operators = (monaco) => {
|
||||
return [{
|
||||
label: 'ALL',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'ALL'
|
||||
},
|
||||
{
|
||||
label: 'AND',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'AND'
|
||||
},
|
||||
{
|
||||
label: 'ANY',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'ANY'
|
||||
},
|
||||
{
|
||||
label: 'BETWEEN',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'BETWEEN'
|
||||
},
|
||||
{
|
||||
label: 'EXISTS',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'EXISTS'
|
||||
},
|
||||
{
|
||||
label: 'IN',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'IN'
|
||||
},
|
||||
{
|
||||
label: 'LIKE',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'LIKE'
|
||||
},
|
||||
{
|
||||
label: 'NOT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'NOT'
|
||||
},
|
||||
{
|
||||
label: 'OR',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'OR'
|
||||
},
|
||||
{
|
||||
label: 'SOME',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'SOME'
|
||||
},
|
||||
{
|
||||
label: 'EXCEPT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'EXCEPT'
|
||||
},
|
||||
{
|
||||
label: 'INTERSECT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'INTERSECT'
|
||||
},
|
||||
{
|
||||
label: 'UNION',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'UNION'
|
||||
},
|
||||
{
|
||||
label: 'APPLY',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'APPLY'
|
||||
},
|
||||
{
|
||||
label: 'CROSS',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'CROSS'
|
||||
},
|
||||
{
|
||||
label: 'FULL',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'FULL'
|
||||
},
|
||||
{
|
||||
label: 'INNER',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'INNER'
|
||||
},
|
||||
{
|
||||
label: 'JOIN',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'JOIN'
|
||||
},
|
||||
{
|
||||
label: 'LEFT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'LEFT'
|
||||
},
|
||||
{
|
||||
label: 'OUTER',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'OUTER'
|
||||
},
|
||||
{
|
||||
label: 'RIGHT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'RIGHT'
|
||||
},
|
||||
{
|
||||
label: 'CONTAINS',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'CONTAINS'
|
||||
},
|
||||
{
|
||||
label: 'FREETEXT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'FREETEXT'
|
||||
},
|
||||
{
|
||||
label: 'IS',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'IS'
|
||||
},
|
||||
{
|
||||
label: 'NULL',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'NULL'
|
||||
},
|
||||
{
|
||||
label: 'PIVOT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'PIVOT'
|
||||
},
|
||||
{
|
||||
label: 'UNPIVOT',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'UNPIVOT'
|
||||
},
|
||||
{
|
||||
label: 'MATCHED',
|
||||
kind: monaco.languages.CompletionItemKind.Operator,
|
||||
insertText: 'MATCHED'
|
||||
}];
|
||||
};
|
@@ -1,172 +0,0 @@
|
||||
export const variables = (monaco) => {
|
||||
return [{
|
||||
label: '@@DATEFIRST',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@DATEFIRST'
|
||||
},
|
||||
{
|
||||
label: '@@DBTS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@DBTS'
|
||||
},
|
||||
{
|
||||
label: '@@LANGID',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@LANGID'
|
||||
},
|
||||
{
|
||||
label: '@@LANGUAGE',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@LANGUAGE'
|
||||
},
|
||||
{
|
||||
label: '@@LOCK_TIMEOUT',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@LOCK_TIMEOUT'
|
||||
},
|
||||
{
|
||||
label: '@@MAX_CONNECTIONS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@MAX_CONNECTIONS'
|
||||
},
|
||||
{
|
||||
label: '@@MAX_PRECISION',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@MAX_PRECISION'
|
||||
},
|
||||
{
|
||||
label: '@@NESTLEVEL',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@NESTLEVEL'
|
||||
},
|
||||
{
|
||||
label: '@@OPTIONS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@OPTIONS'
|
||||
},
|
||||
{
|
||||
label: '@@REMSERVER',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@REMSERVER'
|
||||
},
|
||||
{
|
||||
label: '@@SERVERNAME',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@SERVERNAME'
|
||||
},
|
||||
{
|
||||
label: '@@SERVICENAME',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@SERVICENAME'
|
||||
},
|
||||
{
|
||||
label: '@@SPID',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@SPID'
|
||||
},
|
||||
{
|
||||
label: '@@TEXTSIZE',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@TEXTSIZE'
|
||||
},
|
||||
{
|
||||
label: '@@VERSION',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@VERSION'
|
||||
},
|
||||
{
|
||||
label: '@@CURSOR_ROWS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@CURSOR_ROWS'
|
||||
},
|
||||
{
|
||||
label: '@@FETCH_STATUS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@FETCH_STATUS'
|
||||
},
|
||||
{
|
||||
label: '@@DATEFIRST',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@DATEFIRST'
|
||||
},
|
||||
{
|
||||
label: '@@PROCID',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@PROCID'
|
||||
},
|
||||
{
|
||||
label: '@@ERROR',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@ERROR'
|
||||
},
|
||||
{
|
||||
label: '@@IDENTITY',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@IDENTITY'
|
||||
},
|
||||
{
|
||||
label: '@@ROWCOUNT',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@ROWCOUNT'
|
||||
},
|
||||
{
|
||||
label: '@@TRANCOUNT',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@TRANCOUNT'
|
||||
},
|
||||
{
|
||||
label: '@@CONNECTIONS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@CONNECTIONS'
|
||||
},
|
||||
{
|
||||
label: '@@CPU_BUSY',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@CPU_BUSY'
|
||||
},
|
||||
{
|
||||
label: '@@IDLE',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@IDLE'
|
||||
},
|
||||
{
|
||||
label: '@@IO_BUSY',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@IO_BUSY'
|
||||
},
|
||||
{
|
||||
label: '@@PACKET_ERRORS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@PACKET_ERRORS'
|
||||
},
|
||||
{
|
||||
label: '@@PACK_RECEIVED',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@PACK_RECEIVED'
|
||||
},
|
||||
{
|
||||
label: '@@PACK_SENT',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@PACK_SENT'
|
||||
},
|
||||
{
|
||||
label: '@@TIMETICKS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@TIMETICKS'
|
||||
},
|
||||
{
|
||||
label: '@@TOTAL_ERRORS',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@TOTAL_ERRORS'
|
||||
},
|
||||
{
|
||||
label: '@@TOTAL_READ',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@TOTAL_READ'
|
||||
},
|
||||
{
|
||||
label: '@@TOTAL_WRITE',
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
insertText: '@@TOTAL_WRITE'
|
||||
}];
|
||||
};
|
@@ -1,12 +1,8 @@
|
||||
const webpack = require('webpack');
|
||||
const MonacoEditorPlugin = require('monaco-editor-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
stats: 'errors-warnings',
|
||||
plugins: [
|
||||
new MonacoEditorPlugin({
|
||||
languages: ['sql']
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
PACKAGE_VERSION: JSON.stringify(require('./package.json').version)
|
||||
|
Reference in New Issue
Block a user