Skip to content

Commit 71844a9

Browse files
Merge branch 'LinuxSuRen:master' into master
2 parents d46c441 + cbb07ae commit 71844a9

File tree

23 files changed

+730
-239
lines changed

23 files changed

+730
-239
lines changed

console/atest-ui/src/components/MagicKey.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import { ref, onMounted, onBeforeUnmount } from 'vue'
3+
import { Help } from '@element-plus/icons-vue'
34
import { useI18n } from 'vue-i18n'
45
import { Magic } from '@/views/magicKeys'
56
@@ -24,6 +25,11 @@ onBeforeUnmount(() => {
2425
<el-drawer v-model="keyBindingsDialogVisible" size="50%">
2526
<template #header>
2627
<h4>{{ t('title.keyBindings') }}</h4>
28+
<el-icon>
29+
<el-link href="https://github.com/LinuxSuRen/atest-ext-data-swagger/tree/master/data/key-binding" target="_blank">
30+
<Help />
31+
</el-link>
32+
</el-icon>
2733
</template>
2834
<template #default>
2935
<el-table :data="keyBindings">

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ const queryResultAsJSON = ref('')
3131
const columns = ref([] as string[])
3232
const queryTip = ref('')
3333
const loadingStores = ref(true)
34+
const globalLoading = ref(false)
3435
const showOverflowTooltip = ref(true)
3536
const complexEditor = ref(false)
37+
const sqlEditorView = ref(null as any)
3638
const dataFormat = ref('table')
3739
const dataFormatOptions = ['table', 'json']
3840
const queryDataMeta = ref({} as QueryDataMeta)
@@ -241,7 +243,10 @@ const executeWithQuery = async (sql: string) => {
241243
query.value.sql = sql
242244
243245
try {
244-
const data = await API.DataQueryAsync(query.value);
246+
globalLoading.value = true
247+
const data = await API.DataQueryAsync(query.value, () => {
248+
globalLoading.value = false
249+
});
245250
switch (kind.value) {
246251
case ExtensionKind.ExtensionKindORM:
247252
case ExtensionKind.ExtensionKindCassandra:
@@ -289,26 +294,37 @@ watch(largeContent, (e) => {
289294
largeContentDialogVisible.value = e !== ''
290295
})
291296
292-
Magic.AdvancedKeys([{
293-
Keys: ['Ctrl+E', 'Ctrl+Enter'],
294-
Func: executeQuery,
295-
Description: 'Execute query'
296-
}, {
297-
Keys: ['Ctrl+Shift+O'],
298-
Func: () => {
297+
const sqlEditorReady = (editor: any) => {
298+
sqlEditorView.value = editor.view
299+
}
300+
301+
const executeWithSelectedQuery = () => {
302+
const selectedTextObj = sqlEditorView.value.state.selection.main
303+
const selectedText = sqlEditorView.value.state.sliceDoc(selectedTextObj.from, selectedTextObj.to)
304+
if (selectedText !== '') {
305+
showNativeSQL.value = false
306+
executeWithQuery(selectedText)
307+
}
308+
}
309+
310+
const executeQueryWithoutShowingNativeSQL = () => {
299311
showNativeSQL.value = false
300312
executeWithQuery(sqlQuery.value)
301-
},
302-
Description: 'Execute query without showing native SQL'
303-
}])
313+
}
314+
315+
Magic.LoadMagicKeys(import.meta.url, new Map([
316+
["executeQuery", executeQuery],
317+
["executeWithSelectedQuery", executeWithSelectedQuery],
318+
["executeQueryWithoutShowingNativeSQL", executeQueryWithoutShowingNativeSQL],
319+
]))
304320
</script>
305321

306322
<template>
307323
<div>
308324
<div class="page-header">
309325
<span class="page-title">{{t('title.dataManager')}}</span>
310326
</div>
311-
<el-container style="height: calc(100vh - 80px);">
327+
<el-container style="height: calc(100vh - 80px);" v-loading="globalLoading">
312328
<el-aside v-if="kind === 'atest-store-orm' || kind === 'atest-store-iotdb' || kind === 'atest-store-cassandra' || kind === 'atest-store-elasticsearch' || kind === 'atest-store-opengemini'">
313329
<el-scrollbar>
314330
<el-select v-model="queryDataMeta.currentDatabase" placeholder="Select database"
@@ -380,6 +396,7 @@ Magic.AdvancedKeys([{
380396
</el-row>
381397
</el-form>
382398
<Codemirror
399+
@ready="sqlEditorReady"
383400
v-model="sqlQuery"
384401
v-if="complexEditor"
385402
style="height: var(--sql-editor-height);"

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,10 @@ function addStore() {
108108
createAction.value = true
109109
}
110110
111-
Magic.AdvancedKeys([{
112-
Keys: ['Alt+KeyE', 'ctrl+n'],
113-
Func: addStore,
114-
Description: 'Add a new store'
115-
}, {
116-
Keys: ['Alt+KeyR'],
117-
Func: loadStores,
118-
Description: 'Refresh the store list'
119-
}])
111+
Magic.LoadMagicKeys(import.meta.url, {
112+
"addStore": addStore,
113+
"loadStores": loadStores,
114+
})
120115
121116
const rules = reactive<FormRules<Store>>({
122117
name: [{ required: true, message: 'Name is required', trigger: 'blur' }],

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

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -919,42 +919,30 @@ const renameTestCase = (name: string) => {
919919
})
920920
}
921921
922-
Magic.AdvancedKeys([{
923-
Keys: ['Alt+S', 'Alt+ß'],
924-
Func: sendRequest,
925-
Description: 'Send the request'
926-
}, {
927-
Keys: ['Alt+KeyD'],
928-
Func: openDuplicateTestCaseDialog,
929-
Description: 'Duplicate the test case'
930-
}, {
931-
Keys: ['Alt+KeyO'],
932-
Func: () => {
922+
const openOutputTab = () => {
933923
if (duplicateTestCaseDialog.value) {
934924
duplicateTestCase()
935925
}
936926
testResultActiveTab.value = 'output'
937-
},
938-
Description: 'Open the output tab'
939-
}, {
940-
Keys: ['Alt+KeyB'],
941-
Func: () => {
927+
}
928+
const openBodyTab = () => {
942929
testResultActiveTab.value = 'body'
943-
},
944-
Description: 'Open the body tab'
945-
}, {
946-
Keys: ['Alt+KeyH'],
947-
Func: () => {
930+
}
931+
const openHeaderTab = () => {
948932
testResultActiveTab.value = 'header'
949-
},
950-
Description: 'Open the header tab'
951-
}, {
952-
Keys: ['Alt+KeyQ'],
953-
Func: () => {
933+
}
934+
const openQueryTab = () => {
954935
testResultActiveTab.value = 'query'
955-
},
956-
Description: 'Open the query tab'
957-
}])
936+
}
937+
938+
Magic.LoadMagicKeys(import.meta.url), {
939+
"sendRequest": sendRequest,
940+
"openDuplicateTestCaseDialog": openDuplicateTestCaseDialog,
941+
"openOutputTab": openOutputTab,
942+
"openBodyTab": openBodyTab,
943+
"openHeaderTab": openHeaderTab,
944+
"openQueryTab": openQueryTab
945+
}
958946
</script>
959947

960948
<template>

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,10 @@ function openNewTestCaseDialog() {
153153
querySuggestedAPIs = NewSuggestedAPIsQuery(Cache.GetCurrentStore().name!, props.name!)
154154
}
155155
156-
Magic.AdvancedKeys([{
157-
Keys: ['Alt+N', 'Alt+dead'],
158-
Func: openNewTestCaseDialog,
159-
Description: 'Open new test case dialog',
160-
}, {
161-
Keys: ['Alt+S', 'Alt+ß'],
162-
Func: saveTestSuite,
163-
Description: 'Save test suite',
164-
}])
156+
Magic.LoadMagicKeys(import.meta.url, {
157+
"openNewTestCaseDialog": openNewTestCaseDialog,
158+
"saveTestSuite": saveTestSuite,
159+
})
165160
166161
const submitTestCaseForm = async (formEl: FormInstance | undefined) => {
167162
if (!formEl) return

console/atest-ui/src/views/cache.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2023 API Testing Authors.
2+
Copyright 2023-2025 API Testing Authors.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -153,7 +153,7 @@ interface DataManagerPreference {
153153

154154
const DataManagerPreferenceKey = "data-manager-preference"
155155
export function GetDataManagerPreference(): DataManagerPreference {
156-
const val = localStorage.getItem(DataManagerPreferenceKey)
156+
const val = sessionStorage.getItem(DataManagerPreferenceKey)
157157
if (val && val !== '') {
158158
return JSON.parse(val)
159159
} else {
@@ -178,7 +178,7 @@ export function SetDataManagerPreference(field: string, value: string) {
178178
default:
179179
return
180180
}
181-
localStorage.setItem(DataManagerPreferenceKey, JSON.stringify(preference))
181+
sessionStorage.setItem(DataManagerPreferenceKey, JSON.stringify(preference))
182182
return
183183
}
184184

console/atest-ui/src/views/magicKeys.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616

1717
import { watch } from 'vue'
1818
import { useMagicKeys } from '@vueuse/core'
19+
import { API } from './net'
1920

2021
function Keys(func: (() => void) | ((k: string) => void), keys: string[]) {
2122
const magicKeys = useMagicKeys()
@@ -54,6 +55,46 @@ const AdvancedKeys = (keys: MagicKey[]) => {
5455
})
5556
}
5657

58+
interface KeyBindings {
59+
name: string
60+
pages: Page[]
61+
}
62+
63+
interface Page {
64+
name: string
65+
bindings: KeyBinding[]
66+
}
67+
68+
interface KeyBinding {
69+
keys: string[]
70+
description?: string
71+
action: string
72+
}
73+
74+
const LoadMagicKeys = (url: String, mapping: Map<String, Function>) => {
75+
const fileName = url.substring(url.lastIndexOf('/') + 1);
76+
const pageName = fileName.split(".vue")[0];
77+
API.GetBinding("default", (data) => {
78+
const bindings = JSON.parse(data.message) as KeyBindings;
79+
bindings.pages.forEach((page: Page) => {
80+
if (page.name === pageName) {
81+
const keys = [] as MagicKey[]
82+
page.bindings.forEach((binding: KeyBinding) => {
83+
keys.push({
84+
Keys: binding.keys,
85+
Func: () => {
86+
mapping.has(binding.action) ? mapping.get(binding.action)!() : console.warn(`No action found for ${binding.action}`);
87+
},
88+
Description: binding.description,
89+
});
90+
});
91+
AdvancedKeys(keys);
92+
return;
93+
}
94+
})
95+
})
96+
}
97+
5798
export const Magic = {
58-
Keys, AdvancedKeys, MagicKeyEventName
99+
Keys, AdvancedKeys, MagicKeyEventName, LoadMagicKeys
59100
}

console/atest-ui/src/views/net.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ export interface QueryObject {
851851
offset: number
852852
limit: number
853853
}
854-
const DataQueryAsync = (query: QueryObject) => {
854+
const DataQueryAsync = (query: QueryObject, final?: () => void | undefined | null) => {
855855
const requestOptions = {
856856
method: 'POST',
857857
headers: {
@@ -863,7 +863,7 @@ const DataQueryAsync = (query: QueryObject) => {
863863
body: JSON.stringify(query)
864864
}
865865
return fetch(`/api/v1/data/query`, requestOptions)
866-
.then(DefaultResponseProcess)
866+
.then(DefaultResponseProcess).finally(final)
867867
}
868868

869869
var DataQuery = (store: string, kind: string, currentDatabase: string, query: string, callback: (d: any) => void, errHandler: (d: any) => void) => {
@@ -908,6 +908,11 @@ const GetTheme = (name: string, callback: (d: any) => void | null) => {
908908
.then(DefaultResponseProcess).then(callback)
909909
}
910910

911+
const GetBinding = (name: string, callback: (d: any) => void | null) => {
912+
return fetch(`/api/v1/bindings/${name}`, {})
913+
.then(DefaultResponseProcess).then(callback)
914+
}
915+
911916
export const API = {
912917
DefaultResponseProcess,
913918
GetVersion,
@@ -921,6 +926,6 @@ export const API = {
921926
GetSecrets, DeleteSecret, CreateOrUpdateSecret,
922927
GetSuggestedAPIs, GetSwaggers,
923928
ReloadMockServer, GetMockConfig, SBOM, DataQuery, DataQueryAsync,
924-
GetThemes, GetTheme,
929+
GetThemes, GetTheme, GetBinding,
925930
getToken
926931
}

pkg/server/remote_server.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,35 @@ func (s *server) GetTheme(ctx context.Context, in *SimpleName) (result *CommonRe
13221322
return
13231323
}
13241324

1325+
func (s *server) GetBindings(ctx context.Context, _ *Empty) (result *SimpleList, err error) {
1326+
loader := s.getLoader(ctx)
1327+
defer loader.Close()
1328+
1329+
result = &SimpleList{}
1330+
var bindings []string
1331+
if bindings, err = loader.GetBindings(); err == nil {
1332+
for _, theme := range bindings {
1333+
result.Data = append(result.Data, &Pair{
1334+
Key: theme,
1335+
Value: "",
1336+
})
1337+
}
1338+
}
1339+
return
1340+
}
1341+
1342+
func (s *server) GetBinding(ctx context.Context, in *SimpleName) (result *CommonResult, err error) {
1343+
loader := s.getLoader(ctx)
1344+
defer loader.Close()
1345+
1346+
result = &CommonResult{}
1347+
result.Message, err = loader.GetBinding(in.Name)
1348+
if err != nil {
1349+
result.Message = fmt.Sprintf("failed to get binding: %v", err)
1350+
}
1351+
return
1352+
}
1353+
13251354
// implement the mock server
13261355

13271356
// Start starts the mock server

0 commit comments

Comments
 (0)