diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 11e7a9fd..8f3b34af 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -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
diff --git a/README.md b/README.md
index a3e30ee9..cade9c91 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ 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.
@@ -49,8 +49,6 @@ This is a roadmap with major features will come in near future.
- 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.
diff --git a/src/renderer/components/ModalSettings.vue b/src/renderer/components/ModalSettings.vue
index 7bf6778e..1ac2e129 100644
--- a/src/renderer/components/ModalSettings.vue
+++ b/src/renderer/components/ModalSettings.vue
@@ -96,8 +96,65 @@
-
-
In future releases
+
+
+
+ {{ $t('message.applicationTheme') }}
+
+
+
+
+
+
+ {{ $t('word.dark') }}
+
+
+
+
+
+
+
+ {{ $t('word.light') }} (Coming)
+
+
+
+
+
+
+
+ {{ $t('message.editorTheme') }}
+
+
+
+
+
+ {{ theme.name }}
+
+
+
+
+
+
+
+
@@ -127,18 +184,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: {
@@ -148,7 +257,11 @@ export default {
selectedSettingTab: 'application/selectedSettingTab',
selectedLocale: 'settings/getLocale',
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 +272,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 +308,7 @@ export default {
...mapActions({
closeModal: 'application/hideSettingModal',
changeLocale: 'settings/changeLocale',
+ changeEditorTheme: 'settings/changeEditorTheme',
updateNotificationsTimeout: 'settings/updateNotificationsTimeout'
}),
selectTab (tab) {
@@ -205,6 +340,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 {
diff --git a/src/renderer/components/QueryEditor.vue b/src/renderer/components/QueryEditor.vue
index 0557219a..9db5f6dc 100644
--- a/src/renderer/components/QueryEditor.vue
+++ b/src/renderer/components/QueryEditor.vue
@@ -1,6 +1,10 @@
@@ -8,15 +12,18 @@
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,
- schema: String,
+ workspace: Object,
+ schema: { type: String, default: '' },
autoFocus: { type: Boolean, default: false },
- workspace: Object
+ readOnly: { type: Boolean, default: false },
+ height: { type: Number, default: 200 }
},
data () {
return {
@@ -26,6 +33,9 @@ export default {
};
},
computed: {
+ ...mapGetters({
+ editorTheme: 'settings/getEditorTheme'
+ }),
tables () {
return this.workspace.structure.filter(schema => schema.name === this.schema)
.reduce((acc, curr) => {
@@ -36,7 +46,7 @@ export default {
name: table.name,
comment: table.comment,
type: table.type,
- fields: ['TODO']
+ fields: []
};
});
},
@@ -76,13 +86,20 @@ export default {
};
}
},
+ watch: {
+ editorTheme () {
+ if (this.editor)
+ this.editor.setTheme(`ace/theme/${this.editorTheme}`);
+ }
+ },
mounted () {
this.editor = ace.edit(this.$refs.editor, {
mode: `ace/mode/${this.mode}`,
- theme: 'ace/theme/twilight',
+ theme: `ace/theme/${this.editorTheme}`,
value: this.value,
fontSize: '14px',
- printMargin: false
+ printMargin: false,
+ readOnly: this.readOnly
});
this.editor.setOptions({
@@ -157,7 +174,6 @@ export default {
border-bottom: 1px solid #444;
.editor {
- height: 200px;
width: 100%;
}
}
diff --git a/src/renderer/components/Workspace.vue b/src/renderer/components/Workspace.vue
index f77dbc76..4bea670d 100644
--- a/src/renderer/components/Workspace.vue
+++ b/src/renderer/components/Workspace.vue
@@ -193,6 +193,7 @@ export default {
align-items: flex-start;
flex-wrap: nowrap;
overflow: auto;
+ margin-bottom: 0;
&::-webkit-scrollbar {
width: 2px;
diff --git a/src/renderer/i18n/en-US.js b/src/renderer/i18n/en-US.js
index 19ff198f..c09450b6 100644
--- a/src/renderer/i18n/en-US.js
+++ b/src/renderer/i18n/en-US.js
@@ -62,7 +62,9 @@ module.exports = {
table: 'Table',
discard: 'Discard',
stay: 'Stay',
- author: 'Author'
+ author: 'Author',
+ light: 'Light',
+ dark: 'Dark'
},
message: {
appWelcome: 'Welcome to Antares SQL Client!',
@@ -124,7 +126,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: {
diff --git a/src/renderer/images/dark.png b/src/renderer/images/dark.png
new file mode 100644
index 00000000..136134cf
Binary files /dev/null and b/src/renderer/images/dark.png differ
diff --git a/src/renderer/store/modules/settings.store.js b/src/renderer/store/modules/settings.store.js
index 1b5cb6a5..e2d88cde 100644
--- a/src/renderer/store/modules/settings.store.js
+++ b/src/renderer/store/modules/settings.store.js
@@ -9,12 +9,16 @@ export default {
state: {
locale: persistentStore.get('locale') || 'en-US',
explorebar_size: persistentStore.get('explorebar_size') || null,
- notifications_timeout: persistentStore.get('notifications_timeout') || 5
+ notifications_timeout: persistentStore.get('notifications_timeout') || 5,
+ 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,
+ getApplicationTheme: state => state.application_theme,
+ getEditorTheme: state => state.editor_theme
},
mutations: {
SET_LOCALE (state, locale) {
@@ -29,6 +33,9 @@ export default {
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: {
@@ -40,6 +47,9 @@ export default {
},
changeExplorebarSize ({ commit }, size) {
commit('SET_EXPLOREBAR_SIZE', size);
+ },
+ changeEditorTheme ({ commit }, theme) {
+ commit('SET_EDITOR_THEME', theme);
}
}
};