Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support to show databases and tables on ui #631

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
115 changes: 83 additions & 32 deletions console/atest-ui/src/views/DataManager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ const sqlQuery = ref('')
const queryResult = ref([])
const columns = ref([])
const queryTip = ref('')
const databases = ref([])
const tables = ref([])
const currentDatabase = ref('')
const loadingStores = ref(true)

const tablesTree = ref([])
watch(store, (s) => {
stores.value.forEach((e: Store) => {
if (e.name === s) {
Expand All @@ -19,27 +24,37 @@ watch(store, (s) => {
}
})
})
const queryDataFromTable = (data) => {
sqlQuery.value = `select * from ${data.label} limit 10`
executeQuery()
}
const queryTables = () => {
sqlQuery.value = `show tables`
executeQuery()
}
watch(kind, (k) => {
switch (k) {
case 'atest-store-orm':
sqlQuery.value = 'show tables'
queryTip.value = 'Enter SQL query'
break;
case 'atest-store-etcd':
case 'atest-store-etcd', 'atest-store-redis':
sqlQuery.value = ''
queryTip.value = 'Enter key'
break;
}
})

API.GetStores((data) => {
stores.value = data.data
stores.value = data.data
}, (e) => {
ElMessage({
showClose: true,
message: e.message,
type: 'error'
});
ElMessage({
showClose: true,
message: e.message,
type: 'error'
});
}, () => {
loadingStores.value = false
})

const ormDataHandler = (data) => {
Expand All @@ -55,12 +70,22 @@ const ormDataHandler = (data) => {
result.push(obj)
})

databases.value = data.meta.databases
tables.value = data.meta.tables
currentDatabase.value = data.meta.currentDatabase
queryResult.value = result
columns.value = Array.from(cols).sort((a, b) => {
if (a === 'id') return -1;
if (b === 'id') return 1;
return a.localeCompare(b);
})

tablesTree.value = []
tables.value.forEach((i) => {
tablesTree.value.push({
label: i,
})
})
}

const keyValueDataHandler = (data) => {
Expand All @@ -76,14 +101,23 @@ const keyValueDataHandler = (data) => {
}

const executeQuery = async () => {
API.DataQuery(store.value, kind.value, sqlQuery.value, (data) => {
switch (kind.value) {
case 'atest-store-etcd':
sqlQuery.value = '*'
break;
}

API.DataQuery(store.value, kind.value, currentDatabase.value, sqlQuery.value, (data) => {
switch (kind.value) {
case 'atest-store-orm':
ormDataHandler(data)
break;
case 'atest-store-etcd':
keyValueDataHandler(data)
break;
case 'atest-store-redis':
keyValueDataHandler(data)
break;
default:
ElMessage({
showClose: true,
Expand All @@ -103,30 +137,47 @@ const executeQuery = async () => {

<template>
<div>
<el-form @submit.prevent="executeQuery">
<el-row :gutter="10">
<el-col :span="2">
<el-form-item>
<el-select v-model="store" placeholder="Select store">
<el-option v-for="item in stores" :key="item.name" :label="item.name"
:value="item.name" :disabled="!item.ready" :kind="item.kind.name"></el-option>
<el-container style="height: calc(100vh - 45px);">
<el-aside v-if="kind === 'atest-store-orm'">
<el-scrollbar>
<el-select v-model="currentDatabase" placeholder="Select database" @change="queryTables" filterable>
<el-option v-for="item in databases" :key="item" :label="item"
:value="item"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="18">
<el-form-item>
<el-input v-model="sqlQuery" :placeholder="queryTip" @keyup.enter="executeQuery"></el-input>
</el-form-item>
</el-col>
<el-col :span="2">
<el-form-item>
<el-button type="primary" @click="executeQuery">Execute</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table :data="queryResult">
<el-table-column v-for="col in columns" :key="col" :prop="col" :label="col"></el-table-column>
</el-table>
<el-tree :data="tablesTree" node-key="label" @node-click="queryDataFromTable" highlight-current draggable/>
</el-scrollbar>
</el-aside>
<el-container>
<el-header>
<el-form @submit.prevent="executeQuery">
<el-row :gutter="10">
<el-col :span="4">
<el-form-item>
<el-select v-model="store" placeholder="Select store" filterable :loading="loadingStores">
<el-option v-for="item in stores" :key="item.name" :label="item.name"
:value="item.name" :disabled="!item.ready" :kind="item.kind.name"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="17">
<el-form-item>
<el-input v-model="sqlQuery" :placeholder="queryTip" @keyup.enter="executeQuery"></el-input>
</el-form-item>
</el-col>
<el-col :span="2">
<el-form-item>
<el-button type="primary" @click="executeQuery">Execute</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-header>
<el-main>
<el-table :data="queryResult">
<el-table-column v-for="col in columns" :key="col" :prop="col" :label="col"></el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
</div>
</template>
9 changes: 7 additions & 2 deletions console/atest-ui/src/views/net.ts
Original file line number Diff line number Diff line change
Expand Up @@ -773,20 +773,25 @@ var SBOM = (callback: (d: any) => void) => {
.then(callback)
}

var DataQuery = (store: string, kind: string, query: string, callback: (d: any) => void, errHandler: (d: any) => void) => {
var DataQuery = (store: string, kind: string, currentDatabase: string, query: string, callback: (d: any) => void, errHandler: (d: any) => void) => {
const queryObj = {}
switch (kind) {
case 'atest-store-orm':
queryObj['sql'] = query;
queryObj['key'] = currentDatabase;
break;
case 'atest-store-etcd':
queryObj['key'] = query;
break;
case 'atest-store-redis':
queryObj['key'] = query;
break;
}
const requestOptions = {
method: 'POST',
headers: {
'X-Store-Name': store
'X-Store-Name': store,
'X-Database': currentDatabase
},
body: JSON.stringify(queryObj)
}
Expand Down
5 changes: 5 additions & 0 deletions console/atest-ui/src/views/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ const storeExtensions = [
params: [],
link: 'https://github.com/LinuxSuRen/atest-ext-store-etcd'
},
{
name: 'atest-store-redis',
params: [],
link: 'https://github.com/LinuxSuRen/atest-ext-store-redis'
},
{
name: 'atest-store-mongodb',
params: [{
Expand Down
12 changes: 12 additions & 0 deletions pkg/render/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"fmt"
"io"
mathrand "math/rand"
"net/url"
"strings"
"text/template"
"time"
Expand Down Expand Up @@ -224,6 +225,17 @@ var advancedFuncs = []AdvancedFunc{{
Func: func() float64 {
return time.Since(uptime).Seconds()
},
}, {
FuncName: "urlEncode",
Func: func(text string) string {
return url.QueryEscape(text)
},
}, {
FuncName: "urlDecode",
Func: func(text string) (result string) {
result, _ = url.QueryUnescape(text)
return
},
}}

// WeightEnum is a weight enum
Expand Down
12 changes: 12 additions & 0 deletions pkg/render/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ func TestRender(t *testing.T) {
verify: func(t *testing.T, s string) {
assert.NotEmpty(t, s)
},
}, {
name: "url encode",
text: `{{urlEncode "hello world"}}`,
verify: func(t *testing.T, s string) {
assert.Equal(t, "hello+world", s)
},
}, {
name: "url decode",
text: `{{urlDecode "hello+world"}}`,
verify: func(t *testing.T, s string) {
assert.Equal(t, "hello world", s)
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/runner/monitor/monitor.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/runner/monitor/monitor_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading