Skip to content

Commit a038dea

Browse files
authored
feat: support loading key bindings from data file (#728)
Co-authored-by: rick <[email protected]>
1 parent 866a376 commit a038dea

File tree

20 files changed

+716
-229
lines changed

20 files changed

+716
-229
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: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const loadingStores = ref(true)
3434
const globalLoading = ref(false)
3535
const showOverflowTooltip = ref(true)
3636
const complexEditor = ref(false)
37+
const sqlEditorView = ref(null as any)
3738
const dataFormat = ref('table')
3839
const dataFormatOptions = ['table', 'json']
3940
const queryDataMeta = ref({} as QueryDataMeta)
@@ -293,18 +294,29 @@ watch(largeContent, (e) => {
293294
largeContentDialogVisible.value = e !== ''
294295
})
295296
296-
Magic.AdvancedKeys([{
297-
Keys: ['Ctrl+E', 'Ctrl+Enter'],
298-
Func: executeQuery,
299-
Description: 'Execute query'
300-
}, {
301-
Keys: ['Ctrl+Shift+O'],
302-
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 = () => {
303311
showNativeSQL.value = false
304312
executeWithQuery(sqlQuery.value)
305-
},
306-
Description: 'Execute query without showing native SQL'
307-
}])
313+
}
314+
315+
Magic.LoadMagicKeys(import.meta.url, new Map([
316+
["executeQuery", executeQuery],
317+
["executeWithSelectedQuery", executeWithSelectedQuery],
318+
["executeQueryWithoutShowingNativeSQL", executeQueryWithoutShowingNativeSQL],
319+
]))
308320
</script>
309321

310322
<template>
@@ -384,6 +396,7 @@ Magic.AdvancedKeys([{
384396
</el-row>
385397
</el-form>
386398
<Codemirror
399+
@ready="sqlEditorReady"
387400
v-model="sqlQuery"
388401
v-if="complexEditor"
389402
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/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: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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)