Skip to content
Snippets Groups Projects
Unverified Commit dc394b51 authored by Martin Weise's avatar Martin Weise
Browse files

added query store listing and query builder connection to backend

parent 8f86a0e4
No related branches found
No related tags found
3 merge requests!81New stable release,!43Merge dev to master,!27Draft: Resolve "Zenodo Sandbox integration for PID (e.g. DOI)"
...@@ -31,6 +31,11 @@ public class GatewayConfig { ...@@ -31,6 +31,11 @@ public class GatewayConfig {
.method("POST","GET","PUT","DELETE") .method("POST","GET","PUT","DELETE")
.and() .and()
.uri("lb://fda-query-service")) .uri("lb://fda-query-service"))
.route("fda-query-service", r -> r.path("/api/database/**/querystore/**")
.and()
.method("POST","GET","PUT","DELETE")
.and()
.uri("lb://fda-query-service"))
.route("fda-table-service", r -> r.path("/api/database/**/table/**") .route("fda-table-service", r -> r.path("/api/database/**/table/**")
.and() .and()
.method("POST","GET","PUT","DELETE") .method("POST","GET","PUT","DELETE")
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
<v-btn :to="`/databases/${$route.params.database_id}/tables/import`" class="mr-2"> <v-btn :to="`/databases/${$route.params.database_id}/tables/import`" class="mr-2">
<v-icon left>mdi-cloud-upload</v-icon> Import CSV <v-icon left>mdi-cloud-upload</v-icon> Import CSV
</v-btn> </v-btn>
<v-btn color="blue-grey" :to="`/databases/${$route.params.database_id}/queries/create`" class="mr-2 white--text">
<v-icon left>mdi-wrench</v-icon> Query Builder
</v-btn>
<v-btn color="primary" :to="`/databases/${$route.params.database_id}/tables/create`"> <v-btn color="primary" :to="`/databases/${$route.params.database_id}/tables/create`">
<v-icon left>mdi-table-large-plus</v-icon> Create Table <v-icon left>mdi-table-large-plus</v-icon> Create Table
</v-btn> </v-btn>
......
<template>
<div>
<v-card v-if="queries.length === 0" flat>
<v-card-title>
(no queries)
</v-card-title>
</v-card>
<v-expansion-panels v-if="queries.length > 0" accordion>
<v-expansion-panel v-for="(item, i) in queries" :key="i" @click="details(item)">
<v-expansion-panel-header>
{{ item.query }}
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-row dense>
<v-col>
<v-list dense>
<v-list-item>
<v-list-item-icon>
<v-icon>mdi-information-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
ID: {{ queryDetails.id }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-icon>
<v-icon>mdi-fingerprint</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
DOI: <code v-if="queryDetails.doi">{{ queryDetails.doi }}</code>
<span v-if="!queryDetails.doi">(no identifier issued)</span>
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-icon>
<v-icon>mdi-api</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
Query Hash: <code>{{ queryDetails.queryHash }}</code>
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-icon>
<v-icon>mdi-clock-outline</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
Execution Timestamp: {{ queryDetails.executionTimestamp }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-icon>
<v-icon>mdi-content-save</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
Query: <code>{{ queryDetails.query }}</code>
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-col>
</v-row>
<v-row dense>
<v-col>
<v-btn color="primary" :to="`/databases/${$route.params.database_id}/tables/${item.id}`" disabled>
<v-icon left>mdi-run</v-icon> Execute Again
</v-btn>
</v-col>
</v-row>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</div>
</template>
<script>
export default {
data () {
return {
queries: [],
queryDetails: {
id: null,
doi: null,
queryHash: null,
executionTimestamp: null,
columns: []
}
}
},
mounted () {
this.$root.$on('query-create', this.refresh)
this.refresh()
},
methods: {
async refresh () {
// XXX same as in QueryBuilder
let res
try {
res = await this.$axios.get(`/api/database/${this.$route.params.database_id}/querystore`)
console.debug('queries', res)
this.queries = res.data
} catch (err) {
this.$toast.error('Could not list queries.')
}
},
details (query) {
this.queryDetails = query
}
}
}
</script>
<style>
</style>
...@@ -22,21 +22,32 @@ ...@@ -22,21 +22,32 @@
@change="buildQuery" /> @change="buildQuery" />
</v-col> </v-col>
</v-row> </v-row>
<QueryFilters <!-- <QueryFilters-->
v-if="table" <!-- v-if="table"-->
v-model="clauses" <!-- v-model="clauses"-->
:columns="columnNames" /> <!-- :columns="columnNames" />-->
<v-row v-if="query.formatted"> <v-row v-if="query.formatted">
<v-col> <v-col>
<highlightjs autodetect :code="query.formatted" /> <highlightjs autodetect :code="query.formatted" />
</v-col> </v-col>
<v-col cols="3" class="actions"> <v-col cols="3" class="actions">
<v-btn class="execute" color="primary"> <v-btn class="execute" color="primary" @click="execute">
<v-icon>mdi-refresh</v-icon> <v-icon>mdi-refresh</v-icon>
Execute Execute
</v-btn> </v-btn>
</v-col> </v-col>
</v-row> </v-row>
<v-row>
<v-col>
<p>Results</p>
<v-data-table
:headers="result.headers"
:items="result.rows"
:loading="loading"
:items-per-page="30"
class="elevation-1" />
</v-col>
</v-row>
</div> </div>
</template> </template>
...@@ -49,7 +60,12 @@ export default { ...@@ -49,7 +60,12 @@ export default {
tableDetails: null, tableDetails: null,
query: {}, query: {},
select: [], select: [],
clauses: [] clauses: [],
result: {
headers: [],
rows: []
},
loading: false
} }
}, },
computed: { computed: {
...@@ -80,6 +96,26 @@ export default { ...@@ -80,6 +96,26 @@ export default {
} }
}, },
methods: { methods: {
async execute () {
const query = this.query.sql.replaceAll('"', '')
this.loading = true
try {
const res = await this.$axios.put(`/api/database/${this.$route.params.database_id}/query`, {
Query: query
})
console.debug('query result', res)
this.$toast.success('Successfully executed query')
this.loading = false
this.result.headers = this.select.map((s) => {
return { text: s.name, value: 'mdb_' + s.name, sortable: false }
})
this.result.rows = res.data.result
} catch (err) {
console.error('query execute', err)
this.$toast.error('Could not execute query')
this.loading = false
}
},
async buildQuery () { async buildQuery () {
if (!this.table) { if (!this.table) {
return return
...@@ -87,7 +123,7 @@ export default { ...@@ -87,7 +123,7 @@ export default {
const url = '/server-middleware/query/build' const url = '/server-middleware/query/build'
const data = { const data = {
table: this.table.internalName, table: this.table.internalName,
select: this.select.map(s => s.name), select: this.select.map(s => 'mdb_' + s.name),
clauses: this.clauses clauses: this.clauses
} }
try { try {
......
<template>
<div>
<v-card class="pb-2">
<v-card-title class="pb-0">
Query Builder
</v-card-title>
<v-card-text>
<QueryBuilder />
</v-card-text>
</v-card>
</div>
</template>
<script>
export default {
data () {
return {}
}
}
</script>
<template> <template>
<div> <div>
<DBToolbar v-model="db" /> <DBToolbar v-model="db" />
<v-card> <QueryList />
<v-card-title>
Query Builder
</v-card-title>
<v-card-text>
<QueryBuilder />
</v-card-text>
</v-card>
</div> </div>
</template> </template>
......
...@@ -1622,7 +1622,7 @@ ...@@ -1622,7 +1622,7 @@
"webpack-node-externals" "^3.0.0" "webpack-node-externals" "^3.0.0"
"webpackbar" "^4.0.0" "webpackbar" "^4.0.0"
"@nuxtjs/axios@^5.12.2": "@nuxtjs/axios@^5.13.6":
"integrity" "sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA==" "integrity" "sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA=="
"resolved" "https://registry.npmjs.org/@nuxtjs/axios/-/axios-5.13.6.tgz" "resolved" "https://registry.npmjs.org/@nuxtjs/axios/-/axios-5.13.6.tgz"
"version" "5.13.6" "version" "5.13.6"
...@@ -8579,7 +8579,7 @@ ...@@ -8579,7 +8579,7 @@
"ufo" "^0.7.7" "ufo" "^0.7.7"
"vue-i18n" "^8.25.0" "vue-i18n" "^8.25.0"
"nuxt@^2.12.2": "nuxt@^2.15.8":
"integrity" "sha512-ceK3qLg/Baj7J8mK9bIxqw9AavrF+LXqwYEreBdY/a4Sj8YV4mIvhqea/6E7VTCNNGvKT2sJ/TTJjtfQ597lTA==" "integrity" "sha512-ceK3qLg/Baj7J8mK9bIxqw9AavrF+LXqwYEreBdY/a4Sj8YV4mIvhqea/6E7VTCNNGvKT2sJ/TTJjtfQ597lTA=="
"resolved" "https://registry.npmjs.org/nuxt/-/nuxt-2.15.8.tgz" "resolved" "https://registry.npmjs.org/nuxt/-/nuxt-2.15.8.tgz"
"version" "2.15.8" "version" "2.15.8"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment