mirror of
				https://github.com/Fabio286/antares.git
				synced 2025-06-05 21:59:22 +02:00 
			
		
		
		
	Improvements
This commit is contained in:
		| @@ -2,6 +2,7 @@ | |||||||
| import { ipcMain } from 'electron'; | import { ipcMain } from 'electron'; | ||||||
| import knex from 'knex'; | import knex from 'knex'; | ||||||
| import InformationSchema from '../models/InformationSchema'; | import InformationSchema from '../models/InformationSchema'; | ||||||
|  | import { RawQuery } from '../models/RawQuery'; | ||||||
|  |  | ||||||
| const connections = {}; | const connections = {}; | ||||||
|  |  | ||||||
| @@ -74,4 +75,19 @@ export default () => { | |||||||
|          return { status: 'error', response: err.toString() }; |          return { status: 'error', response: err.toString() }; | ||||||
|       } |       } | ||||||
|    }); |    }); | ||||||
|  |  | ||||||
|  |    ipcMain.on('runQuery', async (event, { connection, query, database }) => { | ||||||
|  |       const knexIstance = connections[connection.uid]; | ||||||
|  |       const Query = new RawQuery({ knexIstance, database }); | ||||||
|  |       try { | ||||||
|  |          Query.runQuery(query); | ||||||
|  |  | ||||||
|  |          Query.on('row', row => { | ||||||
|  |             event.sender.send('row', row); | ||||||
|  |          }); | ||||||
|  |       } | ||||||
|  |       catch (err) { | ||||||
|  |          return { status: 'error', response: err.toString() }; | ||||||
|  |       } | ||||||
|  |    }); | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								src/main/models/RawQuery.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/main/models/RawQuery.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | 'use strict'; | ||||||
|  | import { EventEmitter } from 'events'; | ||||||
|  |  | ||||||
|  | export class RawQuery extends EventEmitter { | ||||||
|  |    constructor ({ knexIstance, database }) { | ||||||
|  |       super(); | ||||||
|  |       this.conn = knexIstance; | ||||||
|  |       this.database = database; | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    async runQuery (query) { | ||||||
|  |       if (this.database) await this.conn.raw(`USE \`${this.database}\``); | ||||||
|  |       const stream = this.conn.raw(query).stream(); | ||||||
|  |       stream.on('data', row => { | ||||||
|  |          this.emit('row', row); | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       stream.on('error', err => { | ||||||
|  |          this.emit('error', err); | ||||||
|  |       }); | ||||||
|  |    } | ||||||
|  | } | ||||||
| @@ -89,6 +89,7 @@ export default { | |||||||
|       padding: 0; |       padding: 0; | ||||||
|       justify-content: flex-start; |       justify-content: flex-start; | ||||||
|       height: calc(100vh - #{$excluding-size}); |       height: calc(100vh - #{$excluding-size}); | ||||||
|  |       width: calc(100% - #{$settingbar-width}); | ||||||
|  |  | ||||||
|       > .columns{ |       > .columns{ | ||||||
|          height: calc(100vh - #{$footer-height}); |          height: calc(100vh - #{$footer-height}); | ||||||
|   | |||||||
| @@ -85,7 +85,7 @@ export default { | |||||||
|       overflow: hidden; |       overflow: hidden; | ||||||
|       text-overflow: ellipsis; |       text-overflow: ellipsis; | ||||||
|       display: inline-block; |       display: inline-block; | ||||||
|       max-width: 25rem; |       max-width: 30rem; | ||||||
|       user-select: none; |       user-select: none; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,18 +1,18 @@ | |||||||
| <template> | <template> | ||||||
|    <div v-show="isSelected" class="workspace column columns"> |    <div v-show="isSelected" class="workspace column columns col-gapless"> | ||||||
|       <WorkspaceExploreBar :connection="connection" :is-selected="isSelected" /> |       <WorkspaceExploreBar :connection="connection" :is-selected="isSelected" /> | ||||||
|       <div class="workspace-tabs column p-0"> |       <div v-if="workspace.connected" class="workspace-tabs column columns col-gapless"> | ||||||
|          <ul class="tab tab-block"> |          <ul class="tab tab-block column col-12"> | ||||||
|             <li |             <li | ||||||
|                v-for="(tab, key) of workspace.tabs" |                v-for="(tab, key) of workspace.tabs" | ||||||
|                :key="tab.uid" |                :key="tab.uid" | ||||||
|                class="tab-item" |                class="tab-item" | ||||||
|                :class="{'active': selectedTab === tab.uid}" |                :class="{'active': selectedTab === tab.uid}" | ||||||
|             > |             > | ||||||
|                <a href="#">Query #{{ key }} <span class="btn btn-clear" /></a> |                <a href="#">Query #{{ key }} <span v-if="workspace.tabs.length > 1" class="btn btn-clear" /></a> | ||||||
|             </li> |             </li> | ||||||
|          </ul> |          </ul> | ||||||
|          <QueryEditor v-model="query" /> |          <WorkspaceQueryTab :connection="connection" /> | ||||||
|       </div> |       </div> | ||||||
|    </div> |    </div> | ||||||
| </template> | </template> | ||||||
| @@ -21,22 +21,17 @@ | |||||||
| import { mapGetters, mapActions } from 'vuex'; | import { mapGetters, mapActions } from 'vuex'; | ||||||
| import Connection from '@/ipc-api/Connection'; | import Connection from '@/ipc-api/Connection'; | ||||||
| import WorkspaceExploreBar from '@/components/WorkspaceExploreBar'; | import WorkspaceExploreBar from '@/components/WorkspaceExploreBar'; | ||||||
| import QueryEditor from '@/components/QueryEditor'; | import WorkspaceQueryTab from '@/components/WorkspaceQueryTab'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|    name: 'Workspace', |    name: 'Workspace', | ||||||
|    components: { |    components: { | ||||||
|       WorkspaceExploreBar, |       WorkspaceExploreBar, | ||||||
|       QueryEditor |       WorkspaceQueryTab | ||||||
|    }, |    }, | ||||||
|    props: { |    props: { | ||||||
|       connection: Object |       connection: Object | ||||||
|    }, |    }, | ||||||
|    data () { |  | ||||||
|       return { |  | ||||||
|          query: '' |  | ||||||
|       }; |  | ||||||
|    }, |  | ||||||
|    computed: { |    computed: { | ||||||
|       ...mapGetters({ |       ...mapGetters({ | ||||||
|          selectedWorkspace: 'workspaces/getSelected', |          selectedWorkspace: 'workspaces/getSelected', | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <template> | <template> | ||||||
|    <div class="p-relative"> |    <div class="column col-auto p-relative"> | ||||||
|       <div ref="resizer" class="workspace-explorebar-resizer" /> |       <div ref="resizer" class="workspace-explorebar-resizer" /> | ||||||
|       <div |       <div | ||||||
|          ref="explorebar" |          ref="explorebar" | ||||||
|   | |||||||
							
								
								
									
										145
									
								
								src/renderer/components/WorkspaceQueryTab.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/renderer/components/WorkspaceQueryTab.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | |||||||
|  | <template> | ||||||
|  |    <div class="workspace-query-tab column col-12 columns col-gapless"> | ||||||
|  |       <div class="workspace-query-runner column col-12"> | ||||||
|  |          <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> | ||||||
|  |             </div> | ||||||
|  |             <div> | ||||||
|  |                Schema: <b>{{ workspace.breadcrumbs.database }}</b> | ||||||
|  |             </div> | ||||||
|  |          </div> | ||||||
|  |       </div> | ||||||
|  |       <div ref="resultTable" class="workspace-query-results column col-12"> | ||||||
|  |          <table v-if="results.length" class="table table-hover"> | ||||||
|  |             <thead> | ||||||
|  |                <tr> | ||||||
|  |                   <th v-for="field in fields" :key="field"> | ||||||
|  |                      {{ field }} | ||||||
|  |                   </th> | ||||||
|  |                </tr> | ||||||
|  |             </thead> | ||||||
|  |             <tbody> | ||||||
|  |                <tr v-for="(row, rKey) in results" :key="rKey"> | ||||||
|  |                   <td v-for="(col, cKey) in row" :key="cKey"> | ||||||
|  |                      {{ col }} | ||||||
|  |                   </td> | ||||||
|  |                </tr> | ||||||
|  |             </tbody> | ||||||
|  |          </table> | ||||||
|  |       </div> | ||||||
|  |    </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import { ipcRenderer } from 'electron'; | ||||||
|  | import QueryEditor from '@/components/QueryEditor'; | ||||||
|  | import { mapGetters, mapActions } from 'vuex'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |    name: 'WorkspaceQueryTab', | ||||||
|  |    components: { | ||||||
|  |       QueryEditor | ||||||
|  |    }, | ||||||
|  |    props: { | ||||||
|  |       connection: Object | ||||||
|  |    }, | ||||||
|  |    data () { | ||||||
|  |       return { | ||||||
|  |          query: '', | ||||||
|  |          results: [] | ||||||
|  |       }; | ||||||
|  |    }, | ||||||
|  |    computed: { | ||||||
|  |       ...mapGetters({ | ||||||
|  |          getWorkspace: 'workspaces/getWorkspace' | ||||||
|  |       }), | ||||||
|  |       workspace () { | ||||||
|  |          return this.getWorkspace(this.connection.uid); | ||||||
|  |       }, | ||||||
|  |       fields () { | ||||||
|  |          return Object.keys(this.results[0]); | ||||||
|  |       } | ||||||
|  |    }, | ||||||
|  |    mounted () { | ||||||
|  |       window.addEventListener('resize', this.resizeResults); | ||||||
|  |    }, | ||||||
|  |    destroyed () { | ||||||
|  |       window.removeEventListener('resize', this.resizeResults); | ||||||
|  |    }, | ||||||
|  |    methods: { | ||||||
|  |       ...mapActions({ | ||||||
|  |          addNotification: 'notifications/addNotification' | ||||||
|  |       }), | ||||||
|  |       async runQuery () { | ||||||
|  |          this.results = []; | ||||||
|  |          this.resizeResults(); | ||||||
|  |  | ||||||
|  |          const params = { | ||||||
|  |             connection: this.connection, | ||||||
|  |             query: this.query, | ||||||
|  |             database: this.workspace.breadcrumbs.database | ||||||
|  |          }; | ||||||
|  |  | ||||||
|  |          try { | ||||||
|  |             ipcRenderer.send('runQuery', params); | ||||||
|  |  | ||||||
|  |             ipcRenderer.on('row', (event, row) => { | ||||||
|  |                this.results.push(row); | ||||||
|  |             }); | ||||||
|  |          } | ||||||
|  |          catch (err) { | ||||||
|  |             this.addNotification({ status: 'error', message: err.stack }); | ||||||
|  |          } | ||||||
|  |       }, | ||||||
|  |       resizeResults (e) { | ||||||
|  |          const el = this.$refs.resultTable; | ||||||
|  |          const footer = document.getElementById('footer'); | ||||||
|  |  | ||||||
|  |          if (el) { | ||||||
|  |             const size = window.innerHeight - el.getBoundingClientRect().top - footer.offsetHeight; | ||||||
|  |             el.style.height = size + 'px'; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss"> | ||||||
|  | .workspace-tabs{ | ||||||
|  |    align-content: baseline; | ||||||
|  |  | ||||||
|  |    .workspace-query-runner{ | ||||||
|  |  | ||||||
|  |       .workspace-query-runner-footer{ | ||||||
|  |          display: flex; | ||||||
|  |          justify-content: space-between; | ||||||
|  |          padding: .2rem .6rem; | ||||||
|  |          align-items: center; | ||||||
|  |  | ||||||
|  |          .workspace-query-buttons{ | ||||||
|  |             display: flex; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    .workspace-query-results{ | ||||||
|  |       overflow: auto; | ||||||
|  |       white-space: nowrap; | ||||||
|  |  | ||||||
|  |       th{ | ||||||
|  |          position: sticky; | ||||||
|  |          top: 0; | ||||||
|  |          background: $bg-color; | ||||||
|  |          border-color: $bg-color-light; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       td{ | ||||||
|  |          border-color: $bg-color-light; | ||||||
|  |          padding: 0 .4rem; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | </style> | ||||||
		Reference in New Issue
	
	Block a user