Skip to content

Commit 4b42dad

Browse files
committed
fix the conflicts
2 parents 9252000 + 12a0db8 commit 4b42dad

File tree

19 files changed

+785
-749
lines changed

19 files changed

+785
-749
lines changed

console/atest-ui/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

console/atest-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"@vueuse/core": "^10.11.0",
2020
"codemirror": "^5.65.17",
2121
"diff-match-patch": "^1.0.5",
22-
"element-plus": "^2.9.1",
22+
"element-plus": "^2.9.6",
2323
"intro.js": "^7.0.1",
2424
"jsonlint-mod": "^1.7.6",
2525
"jsonpath-plus": "^10.0.7",
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<template>
2+
<el-autocomplete
3+
v-model="input"
4+
clearable
5+
:fetch-suggestions="querySearch"
6+
@select="handleSelect"
7+
@keyup.enter="handleEnter"
8+
:placeholder="props.placeholder"
9+
>
10+
<template #default="{ item }">
11+
<div style="display: flex; justify-content: space-between; align-items: center;">
12+
<span>{{ item.value }}</span>
13+
<el-icon @click.stop="deleteHistoryItem(item)">
14+
<delete />
15+
</el-icon>
16+
</div>
17+
</template>
18+
</el-autocomplete>
19+
</template>
20+
21+
<script setup lang="ts">
22+
import { ref, defineProps } from 'vue'
23+
import { ElAutocomplete, ElIcon } from 'element-plus'
24+
import { Delete } from '@element-plus/icons-vue'
25+
26+
const props = defineProps({
27+
maxItems: {
28+
type: Number,
29+
default: 10
30+
},
31+
key: {
32+
type: String,
33+
default: 'history'
34+
},
35+
storage: {
36+
type: String,
37+
default: 'localStorage'
38+
},
39+
callback: {
40+
type: Function,
41+
default: () => true
42+
},
43+
placeholder: {
44+
type: String,
45+
default: 'Type something'
46+
}
47+
})
48+
49+
const input = ref('')
50+
const suggestions = ref([])
51+
interface HistoryItem {
52+
value: string
53+
count: number
54+
timestamp: number
55+
}
56+
57+
const querySearch = (queryString: string, cb: any) => {
58+
const results = suggestions.value.filter((item: HistoryItem) => item.value.includes(queryString))
59+
cb(results)
60+
}
61+
62+
const handleSelect = (item: HistoryItem) => {
63+
input.value = item.value
64+
}
65+
66+
const handleEnter = async () => {
67+
if (props.callback) {
68+
const result = await props.callback()
69+
if (!result) {
70+
return
71+
}
72+
}
73+
if (input.value === '') {
74+
return;
75+
}
76+
77+
const history = JSON.parse(getStorage().getItem(props.key) || '[]')
78+
const existingItem = history.find((item: HistoryItem) => item.value === input.value)
79+
80+
if (existingItem) {
81+
existingItem.count++
82+
existingItem.timestamp = Date.now()
83+
} else {
84+
history.push({ value: input.value, count: 1, timestamp: Date.now() })
85+
}
86+
87+
if (history.length > props.maxItems) {
88+
history.sort((a: HistoryItem, b: HistoryItem) => a.count - b.count || a.timestamp - b.timestamp)
89+
history.shift()
90+
}
91+
92+
getStorage().setItem(props.key, JSON.stringify(history))
93+
suggestions.value = history
94+
}
95+
96+
const loadHistory = () => {
97+
suggestions.value = JSON.parse(getStorage().getItem('history') || '[]')
98+
}
99+
100+
const deleteHistoryItem = (item: HistoryItem) => {
101+
const history = JSON.parse(getStorage().getItem(props.key) || '[]')
102+
const updatedHistory = history.filter((historyItem: HistoryItem) => historyItem.value !== item.value)
103+
getStorage().setItem(props.key, JSON.stringify(updatedHistory))
104+
suggestions.value = updatedHistory
105+
}
106+
107+
const getStorage = () => {
108+
switch (props.storage) {
109+
case 'localStorage':
110+
return localStorage
111+
case 'sessionStorage':
112+
return sessionStorage
113+
default:
114+
return localStorage
115+
}
116+
}
117+
118+
loadHistory()
119+
</script>

console/atest-ui/src/views/DataManager.vue

Lines changed: 82 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
<script setup lang="ts">
22
import { ref, watch } from 'vue'
33
import { API } from './net'
4+
import type { Store } from './store'
5+
import type { Pair } from './types'
46
import { ElMessage } from 'element-plus'
7+
import { Codemirror } from 'vue-codemirror'
8+
import HistoryInput from '../components/HistoryInput.vue'
59
6-
const stores = ref([])
10+
const stores = ref([] as Store[])
711
const kind = ref('')
812
const store = ref('')
913
const sqlQuery = ref('')
10-
const queryResult = ref([])
11-
const columns = ref([])
14+
const queryResult = ref([] as any[])
15+
const queryResultAsJSON = ref('')
16+
const columns = ref([] as string[])
1217
const queryTip = ref('')
13-
const databases = ref([])
14-
const tables = ref([])
15-
const currentDatabase = ref('')
1618
const loadingStores = ref(true)
19+
const dataFormat = ref('table')
20+
const dataFormatOptions = ['table', 'json']
21+
const queryDataMeta = ref({} as QueryDataMeta)
1722
18-
const tablesTree = ref([])
23+
interface TreeItem {
24+
label: string
25+
}
26+
const tablesTree = ref([] as TreeItem[])
1927
watch(store, (s) => {
2028
kind.value = ''
2129
stores.value.forEach((e: Store) => {
@@ -24,12 +32,28 @@ watch(store, (s) => {
2432
return
2533
}
2634
})
27-
currentDatabase.value = ''
35+
queryDataMeta.value.currentDatabase = ''
2836
sqlQuery.value = ''
2937
executeQuery()
3038
})
31-
const queryDataFromTable = (data) => {
32-
sqlQuery.value = `select * from ${data.label} limit 10`
39+
40+
interface QueryDataMeta {
41+
databases: string[]
42+
tables: string[]
43+
currentDatabase: string
44+
duration: string
45+
labels: Pair[]
46+
}
47+
48+
interface QueryData {
49+
items: any[]
50+
data: any[]
51+
label: string
52+
meta: QueryDataMeta
53+
}
54+
55+
const queryDataFromTable = (data: QueryData) => {
56+
sqlQuery.value = `@selectTableLImit100_${data.label}`
3357
executeQuery()
3458
}
3559
const queryTables = () => {
@@ -61,43 +85,50 @@ API.GetStores((data) => {
6185
loadingStores.value = false
6286
})
6387
64-
const ormDataHandler = (data) => {
65-
const result = []
66-
const cols = new Set()
88+
const ormDataHandler = (data: QueryData) => {
89+
const result = [] as any[]
90+
const cols = new Set<string>()
6791
6892
data.items.forEach(e => {
6993
const obj = {}
70-
e.data.forEach(item => {
94+
e.data.forEach((item: Pair) => {
7195
obj[item.key] = item.value
7296
cols.add(item.key)
7397
})
7498
result.push(obj)
7599
})
76100
77-
databases.value = data.meta.databases
78-
tables.value = data.meta.tables
79-
currentDatabase.value = data.meta.currentDatabase
101+
data.meta.labels = data.meta.labels.filter((item) => {
102+
if (item.key === '_native_sql') {
103+
sqlQuery.value = item.value
104+
return false
105+
}
106+
return !item.key.startsWith('_')
107+
})
108+
109+
queryDataMeta.value = data.meta
80110
queryResult.value = result
111+
queryResultAsJSON.value = JSON.stringify(result, null, 2)
81112
columns.value = Array.from(cols).sort((a, b) => {
82113
if (a === 'id') return -1;
83114
if (b === 'id') return 1;
84115
return a.localeCompare(b);
85116
})
86117
87118
tablesTree.value = []
88-
tables.value.forEach((i) => {
119+
queryDataMeta.value.tables.forEach((i) => {
89120
tablesTree.value.push({
90121
label: i,
91122
})
92123
})
93124
}
94125
95-
const keyValueDataHandler = (data) => {
126+
const keyValueDataHandler = (data: QueryData) => {
96127
queryResult.value = []
97128
data.data.forEach(e => {
98-
const obj = {}
99-
obj['key'] = e.key
100-
obj['value'] = e.value
129+
const obj = new Map<string, string>();
130+
obj.set('key', e.key)
131+
obj.set('value', e.value)
101132
queryResult.value.push(obj)
102133
103134
columns.value = ['key', 'value']
@@ -111,13 +142,14 @@ const executeQuery = async () => {
111142
break;
112143
}
113144
114-
API.DataQuery(store.value, kind.value, currentDatabase.value, sqlQuery.value, (data) => {
145+
let success = false
146+
try {
147+
const data = await API.DataQueryAsync(store.value, kind.value, queryDataMeta.value.currentDatabase, sqlQuery.value);
115148
switch (kind.value) {
116149
case 'atest-store-orm':
117-
ormDataHandler(data)
118-
break;
119150
case 'atest-store-iotdb':
120151
ormDataHandler(data)
152+
success = true
121153
break;
122154
case 'atest-store-etcd':
123155
keyValueDataHandler(data)
@@ -132,23 +164,26 @@ const executeQuery = async () => {
132164
type: 'error'
133165
});
134166
}
135-
}, (e) => {
167+
} catch (e: any) {
136168
ElMessage({
137169
showClose: true,
138170
message: e.message,
139171
type: 'error'
140172
});
141-
})
173+
}
174+
return success
142175
}
143176
</script>
144177

145178
<template>
146179
<div>
147-
<el-container style="height: calc(100vh - 45px);">
148-
<el-aside v-if="kind === 'atest-store-orm' || kind === 'atest-store-iotdb'">
180+
<el-container style="height: calc(100vh - 50px);">
181+
<el-aside v-if="kind === 'atest-store-orm'">
149182
<el-scrollbar>
150-
<el-select v-model="currentDatabase" placeholder="Select database" @change="queryTables" filterable>
151-
<el-option v-for="item in databases" :key="item" :label="item" :value="item"></el-option>
183+
<el-select v-model="queryDataMeta.currentDatabase" placeholder="Select database"
184+
@change="queryTables" filterable>
185+
<el-option v-for="item in queryDataMeta.databases" :key="item" :label="item"
186+
:value="item"></el-option>
152187
</el-select>
153188
<el-tree :data="tablesTree" node-key="label" @node-click="queryDataFromTable" highlight-current
154189
draggable />
@@ -168,24 +203,35 @@ const executeQuery = async () => {
168203
</el-select>
169204
</el-form-item>
170205
</el-col>
171-
<el-col :span="17">
206+
<el-col :span="16">
172207
<el-form-item>
173-
<el-input v-model="sqlQuery" :placeholder="queryTip"
174-
@keyup.enter="executeQuery"></el-input>
208+
<HistoryInput :placeholder="queryTip" :callback="executeQuery" v-model="sqlQuery" />
175209
</el-form-item>
176210
</el-col>
177211
<el-col :span="2">
178212
<el-form-item>
179213
<el-button type="primary" @click="executeQuery">Execute</el-button>
180214
</el-form-item>
181215
</el-col>
216+
<el-col :span="2">
217+
<el-select v-model="dataFormat" placeholder="Select data format">
218+
<el-option v-for="item in dataFormatOptions" :key="item" :label="item"
219+
:value="item"></el-option>
220+
</el-select>
221+
</el-col>
182222
</el-row>
183223
</el-form>
184224
</el-header>
185225
<el-main>
186-
<el-table :data="queryResult">
187-
<el-table-column v-for="col in columns" :key="col" :prop="col" :label="col"></el-table-column>
226+
<div style="display: flex; gap: 8px;">
227+
<el-tag type="primary" v-if="queryResult.length > 0">{{ queryResult.length }} rows</el-tag>
228+
<el-tag type="primary" v-if="queryDataMeta.duration">{{ queryDataMeta.duration }}</el-tag>
229+
<el-tag type="primary" v-for="label in queryDataMeta.labels">{{ label.value }}</el-tag>
230+
</div>
231+
<el-table :data="queryResult" stripe v-if="dataFormat === 'table'">
232+
<el-table-column v-for="col in columns" :key="col" :prop="col" :label="col" sortable />
188233
</el-table>
234+
<Codemirror v-else-if="dataFormat === 'json'" v-model="queryResultAsJSON" />
189235
</el-main>
190236
</el-container>
191237
</el-container>

console/atest-ui/src/views/TestCase.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ const renameTestCase = (name: string) => {
973973
</div>
974974
</el-header>
975975

976-
<el-main style="padding-left: 5px;">
976+
<el-main style="padding-left: 5px; min-height: 280px;">
977977
<el-tabs v-model="requestActiveTab">
978978
<el-tab-pane name="query" v-if="props.kindName !== 'tRPC' && props.kindName !== 'gRPC'">
979979
<template #label>

0 commit comments

Comments
 (0)