fastapi-voyager 0.10.3__py3-none-any.whl → 0.10.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastapi_voyager/render.py +1 -1
- fastapi_voyager/version.py +1 -1
- fastapi_voyager/web/component/schema-field-filter.js +5 -6
- fastapi_voyager/web/graph-ui.js +56 -25
- fastapi_voyager/web/index.html +41 -44
- fastapi_voyager/web/vue-main.js +55 -52
- {fastapi_voyager-0.10.3.dist-info → fastapi_voyager-0.10.5.dist-info}/METADATA +16 -2
- {fastapi_voyager-0.10.3.dist-info → fastapi_voyager-0.10.5.dist-info}/RECORD +11 -11
- {fastapi_voyager-0.10.3.dist-info → fastapi_voyager-0.10.5.dist-info}/WHEEL +0 -0
- {fastapi_voyager-0.10.3.dist-info → fastapi_voyager-0.10.5.dist-info}/entry_points.txt +0 -0
- {fastapi_voyager-0.10.3.dist-info → fastapi_voyager-0.10.5.dist-info}/licenses/LICENSE +0 -0
fastapi_voyager/render.py
CHANGED
|
@@ -37,7 +37,7 @@ class Renderer:
|
|
|
37
37
|
fields_parts.append(field_str)
|
|
38
38
|
|
|
39
39
|
header_color = 'tomato' if node.id == self.schema else '#009485'
|
|
40
|
-
header = f"""<tr><td cellpadding="
|
|
40
|
+
header = f"""<tr><td cellpadding="6" bgcolor="{header_color}" align="center" colspan="1" port="{PK}"> <font color="white"> {node.name} </font></td> </tr>"""
|
|
41
41
|
field_content = ''.join(fields_parts) if fields_parts else ''
|
|
42
42
|
return f"""<<table border="1" cellborder="0" cellpadding="0" bgcolor="white"> {header} {field_content} </table>>"""
|
|
43
43
|
|
fastapi_voyager/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "0.10.
|
|
2
|
+
__version__ = "0.10.5"
|
|
@@ -42,11 +42,12 @@ export default defineComponent({
|
|
|
42
42
|
async function loadSchemas() {
|
|
43
43
|
// Use externally provided props.schemas dict directly; no network call.
|
|
44
44
|
state.error = null;
|
|
45
|
-
const dict =
|
|
45
|
+
const dict =
|
|
46
|
+
props.schemas && typeof props.schemas === "object" ? props.schemas : {};
|
|
46
47
|
// Flatten to array for local operations
|
|
47
48
|
state.schemas = Object.values(dict);
|
|
48
49
|
state.schemaOptions = state.schemas.map((s) => ({
|
|
49
|
-
label: `${s.name}
|
|
50
|
+
label: `${s.name} - ${s.id}`,
|
|
50
51
|
value: s.id,
|
|
51
52
|
}));
|
|
52
53
|
// Maintain compatibility: loadingSchemas flag toggled quickly (no async work)
|
|
@@ -57,7 +58,7 @@ export default defineComponent({
|
|
|
57
58
|
const needle = (val || "").toLowerCase();
|
|
58
59
|
update(() => {
|
|
59
60
|
let opts = state.schemas.map((s) => ({
|
|
60
|
-
label: `${s.name}
|
|
61
|
+
label: `${s.name} - ${s.id}`,
|
|
61
62
|
value: s.id,
|
|
62
63
|
}));
|
|
63
64
|
if (needle) {
|
|
@@ -127,7 +128,6 @@ export default defineComponent({
|
|
|
127
128
|
}
|
|
128
129
|
});
|
|
129
130
|
|
|
130
|
-
|
|
131
131
|
function close() {
|
|
132
132
|
emit("close");
|
|
133
133
|
}
|
|
@@ -178,13 +178,12 @@ export default defineComponent({
|
|
|
178
178
|
:disable="!state.schemaFullname"
|
|
179
179
|
:loading="state.querying"
|
|
180
180
|
@click="onQuery" />
|
|
181
|
-
</div>
|
|
182
181
|
<q-btn
|
|
183
182
|
flat dense round icon="close"
|
|
184
183
|
aria-label="Close"
|
|
185
184
|
@click="close"
|
|
186
|
-
style="position:absolute; top:6px; right:6px; z-index:11; background:rgba(255,255,255,0.85);"
|
|
187
185
|
/>
|
|
186
|
+
</div>
|
|
188
187
|
<div v-if="state.error" style="position:absolute; top:52px; left:8px; z-index:10; color:#c10015; font-size:12px;">{{ state.error }}</div>
|
|
189
188
|
<div id="graph-schema-field" style="width:100%; height:100%; overflow:auto; background:#fafafa"></div>
|
|
190
189
|
</div>
|
fastapi_voyager/web/graph-ui.js
CHANGED
|
@@ -57,6 +57,13 @@ export class GraphUI {
|
|
|
57
57
|
return $result;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
highlightSchemaBanner(node) {
|
|
61
|
+
const ele = node.querySelector("polygon[fill='#009485']")
|
|
62
|
+
if (ele) {
|
|
63
|
+
ele.setAttribute('fill', 'tomato');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
_init() {
|
|
61
68
|
const self = this;
|
|
62
69
|
$(this.selector).graphviz({
|
|
@@ -65,6 +72,26 @@ export class GraphUI {
|
|
|
65
72
|
ready: function () {
|
|
66
73
|
self.gv = this;
|
|
67
74
|
|
|
75
|
+
self.gv.nodes().dblclick(function (event) {
|
|
76
|
+
event.stopPropagation();
|
|
77
|
+
try {
|
|
78
|
+
self.highlightSchemaBanner(this)
|
|
79
|
+
} catch(e) {
|
|
80
|
+
console.log(e)
|
|
81
|
+
}
|
|
82
|
+
const set = $();
|
|
83
|
+
set.push(this);
|
|
84
|
+
// const obj = { set, direction: "bidirectional" };
|
|
85
|
+
const schemaName = event.currentTarget.dataset.name;
|
|
86
|
+
// self.currentSelection = [obj];
|
|
87
|
+
if (schemaName) {
|
|
88
|
+
try {
|
|
89
|
+
self.options.onSchemaClick(schemaName);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
console.warn("onSchemaClick callback failed", e);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
68
95
|
self.gv.nodes().click(function (event) {
|
|
69
96
|
const set = $();
|
|
70
97
|
set.push(this);
|
|
@@ -83,12 +110,10 @@ export class GraphUI {
|
|
|
83
110
|
} else {
|
|
84
111
|
self.currentSelection = [obj];
|
|
85
112
|
self._highlight();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
console.warn("onSchemaClick callback failed", e);
|
|
91
|
-
}
|
|
113
|
+
try {
|
|
114
|
+
self.options.resetCb();
|
|
115
|
+
} catch (e) {
|
|
116
|
+
console.warn("resetCb callback failed", e);
|
|
92
117
|
}
|
|
93
118
|
}
|
|
94
119
|
});
|
|
@@ -107,28 +132,34 @@ export class GraphUI {
|
|
|
107
132
|
|
|
108
133
|
// svg 背景点击高亮清空
|
|
109
134
|
|
|
110
|
-
$(document)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
135
|
+
$(document)
|
|
136
|
+
.off("click.graphui")
|
|
137
|
+
.on("click.graphui", function (evt) {
|
|
138
|
+
// 如果点击目标不在 graph 容器内,直接退出
|
|
139
|
+
const graphContainer = $(self.selector)[0];
|
|
140
|
+
if (
|
|
141
|
+
!graphContainer ||
|
|
142
|
+
!evt.target ||
|
|
143
|
+
!graphContainer.contains(evt.target)
|
|
144
|
+
) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
116
147
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
let isNode = false;
|
|
149
|
+
const $nodes = self.gv.nodes();
|
|
150
|
+
const node = evt.target.parentNode;
|
|
151
|
+
$nodes.each(function () {
|
|
152
|
+
if (this === node) {
|
|
153
|
+
isNode = true;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
if (!isNode && self.gv) {
|
|
157
|
+
self.gv.highlight();
|
|
158
|
+
if (self.options.resetCb) {
|
|
159
|
+
self.options.resetCb();
|
|
160
|
+
}
|
|
123
161
|
}
|
|
124
162
|
});
|
|
125
|
-
if (!isNode && self.gv) {
|
|
126
|
-
self.gv.highlight();
|
|
127
|
-
if (self.options.resetCb) {
|
|
128
|
-
self.options.resetCb();
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
163
|
|
|
133
164
|
$(document).on("keydown.graphui", function (evt) {
|
|
134
165
|
if (evt.keyCode === 27 && self.gv) {
|
fastapi_voyager/web/index.html
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
<div id="q-app">
|
|
65
65
|
<q-layout view="hHh lpR fff">
|
|
66
66
|
<q-header bordered class="bg-primary text-white">
|
|
67
|
-
<q-toolbar class="row text-grey-9 bg-white" style="width: 100
|
|
67
|
+
<q-toolbar class="row text-grey-9 bg-white" style="width: 100%; border-bottom: 2px solid #009485;">
|
|
68
68
|
<div
|
|
69
69
|
class="col-auto text-primary"
|
|
70
70
|
style="font-size: 18px; font-weight: bold; display: flex; align-items: baseline;"
|
|
@@ -86,39 +86,21 @@
|
|
|
86
86
|
/>
|
|
87
87
|
</div>
|
|
88
88
|
<div class="col-auto q-ml-auto">
|
|
89
|
-
<q-toggle
|
|
90
|
-
v-if="state.enableBriefMode"
|
|
91
|
-
class="q-mr-md"
|
|
92
|
-
v-model="state.brief"
|
|
93
|
-
label="Brief Mode"
|
|
94
|
-
@update:model-value="(val) => toggleBrief(val)"
|
|
95
|
-
title="skip middle classes, config module_prefix to enable it"
|
|
96
|
-
dense
|
|
97
|
-
/>
|
|
98
|
-
</div>
|
|
99
|
-
<div class="col-auto">
|
|
100
|
-
<q-toggle
|
|
101
|
-
v-model="state.hidePrimitiveRoute"
|
|
102
|
-
@update:model-value="(val) => toggleHidePrimitiveRoute(val)"
|
|
103
|
-
label="Hide Primitive"
|
|
104
|
-
title="hide routes return primitive"
|
|
105
|
-
class="q-mr-md"
|
|
106
|
-
dense
|
|
107
|
-
/>
|
|
108
|
-
</div>
|
|
109
|
-
<div class="col-auto">
|
|
110
89
|
<q-btn
|
|
111
90
|
outline
|
|
112
91
|
@click="onReset"
|
|
113
92
|
title="may be very slow"
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
icon="border_all"
|
|
94
|
+
flat
|
|
95
|
+
class="q-mr-sm"
|
|
96
|
+
label="Full Graph"
|
|
116
97
|
/>
|
|
117
98
|
</div>
|
|
118
99
|
<div class="col-auto">
|
|
119
100
|
<q-btn
|
|
120
101
|
outline
|
|
121
102
|
icon="search"
|
|
103
|
+
flat
|
|
122
104
|
label="Search"
|
|
123
105
|
class="q-mr-md"
|
|
124
106
|
@click="showDialog()"
|
|
@@ -131,7 +113,7 @@
|
|
|
131
113
|
flat
|
|
132
114
|
icon="help_outline"
|
|
133
115
|
aria-label="Help"
|
|
134
|
-
|
|
116
|
+
style="margin-right: 40px"
|
|
135
117
|
>
|
|
136
118
|
<q-tooltip
|
|
137
119
|
anchor="bottom middle"
|
|
@@ -145,18 +127,16 @@
|
|
|
145
127
|
<ul>
|
|
146
128
|
<li>scroll to zoom in/out</li>
|
|
147
129
|
<li>
|
|
148
|
-
click node to
|
|
149
|
-
chart, esc to unselect
|
|
130
|
+
double click node to view details.
|
|
150
131
|
</li>
|
|
151
132
|
<li>
|
|
152
|
-
shift + click to see schema's dependencies without
|
|
153
|
-
unrelated nodes
|
|
133
|
+
shift + click to see schema's dependencies without unrelated nodes.
|
|
154
134
|
</li>
|
|
155
135
|
</ul>
|
|
156
136
|
</div>
|
|
157
137
|
</q-tooltip>
|
|
158
138
|
</q-btn>
|
|
159
|
-
</div>
|
|
139
|
+
<a href="https://github.com/allmonday/fastapi-voyager" target="_blank" class="github-corner" aria-label="View source on GitHub"><svg width="52" height="52" viewBox="0 0 250 250" style="fill:#009485; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style></div>
|
|
160
140
|
<!-- <q-toolbar-title class="text-primary row">
|
|
161
141
|
</q-toolbar-title> -->
|
|
162
142
|
</q-toolbar>
|
|
@@ -167,7 +147,6 @@
|
|
|
167
147
|
:width="state.drawerWidth"
|
|
168
148
|
side="right"
|
|
169
149
|
style="border-left: 1px solid #888;"
|
|
170
|
-
overlay
|
|
171
150
|
bordered
|
|
172
151
|
>
|
|
173
152
|
<!-- 可拖拽的调整栏 -->
|
|
@@ -232,14 +211,13 @@
|
|
|
232
211
|
content-class="q-pa-none"
|
|
233
212
|
>
|
|
234
213
|
<template #header>
|
|
235
|
-
<div class="
|
|
236
|
-
<div class="row items-center">
|
|
214
|
+
<div class="" style="white-space: nowrap; width: 100%">
|
|
237
215
|
<q-icon
|
|
216
|
+
style="vertical-align: top;"
|
|
238
217
|
class="q-mr-sm"
|
|
239
218
|
:name="state.tag == tag.name ? 'folder' : 'folder_open'"
|
|
240
219
|
></q-icon>
|
|
241
|
-
<span>{{ tag.name }} <q-chip class="q-ml-sm" dense>{{ tag.routes.length }}</q-chip></span>
|
|
242
|
-
</div>
|
|
220
|
+
<span>{{ tag.name }} <q-chip style="position:relative; top: -1px;" class="q-ml-sm" dense>{{ tag.routes.length }}</q-chip></span>
|
|
243
221
|
</div>
|
|
244
222
|
</template>
|
|
245
223
|
<q-list separator style="overflow: auto; max-height: 60vh;">
|
|
@@ -280,15 +258,34 @@
|
|
|
280
258
|
<template #after>
|
|
281
259
|
<div style="position: relative; width: 100%; height: 100%;">
|
|
282
260
|
<div id="graph" class="adjust-fit"></div>
|
|
283
|
-
<
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
261
|
+
<div style="position: absolute; left: 8px; bottom: 8px; z-index: 10; background: rgba(255,255,255,0.85); border-radius: 4px; padding: 2px 8px;">
|
|
262
|
+
<div>
|
|
263
|
+
<q-toggle
|
|
264
|
+
v-model="state.focus"
|
|
265
|
+
v-show="schemaCodeName"
|
|
266
|
+
@update:model-value="val => onFocusChange(val)"
|
|
267
|
+
label="Focus"
|
|
268
|
+
title="pick a schema and toggle focus on to display related nodes only"
|
|
269
|
+
/>
|
|
270
|
+
</div>
|
|
271
|
+
<div>
|
|
272
|
+
<q-toggle
|
|
273
|
+
v-if="state.enableBriefMode"
|
|
274
|
+
v-model="state.brief"
|
|
275
|
+
label="Brief Mode"
|
|
276
|
+
@update:model-value="(val) => toggleBrief(val)"
|
|
277
|
+
title="skip middle classes, config module_prefix to enable it"
|
|
278
|
+
/>
|
|
279
|
+
</div>
|
|
280
|
+
<div>
|
|
281
|
+
<q-toggle
|
|
282
|
+
v-model="state.hidePrimitiveRoute"
|
|
283
|
+
@update:model-value="(val) => toggleHidePrimitiveRoute(val)"
|
|
284
|
+
label="Hide Primitive"
|
|
285
|
+
title="hide routes return primitive"
|
|
286
|
+
/>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
292
289
|
</div>
|
|
293
290
|
</template>
|
|
294
291
|
</q-splitter>
|
fastapi_voyager/web/vue-main.js
CHANGED
|
@@ -48,6 +48,7 @@ const app = createApp({
|
|
|
48
48
|
const schemaCodeName = ref("");
|
|
49
49
|
const routeCodeId = ref("");
|
|
50
50
|
const showRouteDetail = ref(false);
|
|
51
|
+
let graphUI = null;
|
|
51
52
|
|
|
52
53
|
function openDetail() {
|
|
53
54
|
showDetail.value = true;
|
|
@@ -88,17 +89,18 @@ const app = createApp({
|
|
|
88
89
|
|
|
89
90
|
async function onFocusChange(val) {
|
|
90
91
|
if (val) {
|
|
91
|
-
await onGenerate(
|
|
92
|
+
await onGenerate(true); // target could be out of view when switchingfrom big to small
|
|
92
93
|
} else {
|
|
93
|
-
await onGenerate(false
|
|
94
|
+
await onGenerate(false);
|
|
94
95
|
setTimeout(() => {
|
|
95
|
-
const ele = $(`[data-name='${schemaCodeName.value}'] polygon`)
|
|
96
|
-
ele.
|
|
97
|
-
}, 1)
|
|
96
|
+
const ele = $(`[data-name='${schemaCodeName.value}'] polygon`);
|
|
97
|
+
ele.dblclick();
|
|
98
|
+
}, 1);
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
async function onGenerate(resetZoom = true
|
|
102
|
+
async function onGenerate(resetZoom = true) {
|
|
103
|
+
const schema_name = state.focus ? schemaCodeName.value : null;
|
|
102
104
|
state.generating = true;
|
|
103
105
|
try {
|
|
104
106
|
const payload = {
|
|
@@ -117,30 +119,31 @@ const app = createApp({
|
|
|
117
119
|
const dotText = await res.text();
|
|
118
120
|
|
|
119
121
|
// create graph instance once
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
122
|
+
if (!graphUI) {
|
|
123
|
+
graphUI = new GraphUI("#graph", {
|
|
124
|
+
onSchemaShiftClick: (id) => {
|
|
125
|
+
if (state.rawSchemas.has(id)) {
|
|
126
|
+
resetDetailPanels();
|
|
127
|
+
schemaFieldFilterSchema.value = id;
|
|
128
|
+
showSchemaFieldFilter.value = true;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
onSchemaClick: (id) => {
|
|
132
|
+
resetDetailPanels();
|
|
133
|
+
if (state.rawSchemas.has(id)) {
|
|
134
|
+
schemaCodeName.value = id;
|
|
135
|
+
state.detailDrawer = true;
|
|
136
|
+
}
|
|
137
|
+
if (id in state.routeItems) {
|
|
138
|
+
routeCodeId.value = id;
|
|
139
|
+
showRouteDetail.value = true;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
resetCb: () => {
|
|
143
|
+
resetDetailPanels();
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}
|
|
144
147
|
await graphUI.render(dotText, resetZoom);
|
|
145
148
|
} catch (e) {
|
|
146
149
|
console.error("Generate failed", e);
|
|
@@ -212,9 +215,9 @@ const app = createApp({
|
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
function resetDetailPanels() {
|
|
215
|
-
state.detailDrawer = false
|
|
218
|
+
state.detailDrawer = false;
|
|
216
219
|
showRouteDetail.value = false;
|
|
217
|
-
schemaCodeName.value =
|
|
220
|
+
schemaCodeName.value = "";
|
|
218
221
|
}
|
|
219
222
|
|
|
220
223
|
async function onReset() {
|
|
@@ -223,8 +226,8 @@ const app = createApp({
|
|
|
223
226
|
state.schemaId = null;
|
|
224
227
|
// state.showFields = "object";
|
|
225
228
|
state.brief = false;
|
|
226
|
-
state.focus = false
|
|
227
|
-
schemaCodeName.value =
|
|
229
|
+
state.focus = false;
|
|
230
|
+
schemaCodeName.value = "";
|
|
228
231
|
onGenerate();
|
|
229
232
|
}
|
|
230
233
|
|
|
@@ -233,11 +236,11 @@ const app = createApp({
|
|
|
233
236
|
state._tag = tagName;
|
|
234
237
|
state.tag = tagName;
|
|
235
238
|
state.routeId = "";
|
|
236
|
-
state.focus = false
|
|
237
|
-
schemaCodeName.value =
|
|
239
|
+
state.focus = false;
|
|
240
|
+
schemaCodeName.value = "";
|
|
238
241
|
onGenerate();
|
|
239
242
|
} else {
|
|
240
|
-
state._tag = null
|
|
243
|
+
state._tag = null;
|
|
241
244
|
}
|
|
242
245
|
|
|
243
246
|
state.detailDrawer = false;
|
|
@@ -252,8 +255,8 @@ const app = createApp({
|
|
|
252
255
|
}
|
|
253
256
|
state.detailDrawer = false;
|
|
254
257
|
showRouteDetail.value = false;
|
|
255
|
-
state.focus = false
|
|
256
|
-
schemaCodeName.value =
|
|
258
|
+
state.focus = false;
|
|
259
|
+
schemaCodeName.value = "";
|
|
257
260
|
onGenerate();
|
|
258
261
|
}
|
|
259
262
|
|
|
@@ -275,24 +278,24 @@ const app = createApp({
|
|
|
275
278
|
function startDragDrawer(e) {
|
|
276
279
|
const startX = e.clientX;
|
|
277
280
|
const startWidth = state.drawerWidth;
|
|
278
|
-
|
|
281
|
+
|
|
279
282
|
function onMouseMove(moveEvent) {
|
|
280
|
-
const deltaX = startX - moveEvent.clientX;
|
|
283
|
+
const deltaX = startX - moveEvent.clientX;
|
|
281
284
|
const newWidth = Math.max(300, Math.min(800, startWidth + deltaX));
|
|
282
285
|
state.drawerWidth = newWidth;
|
|
283
286
|
}
|
|
284
|
-
|
|
287
|
+
|
|
285
288
|
function onMouseUp() {
|
|
286
|
-
document.removeEventListener(
|
|
287
|
-
document.removeEventListener(
|
|
288
|
-
document.body.style.cursor =
|
|
289
|
-
document.body.style.userSelect =
|
|
289
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
290
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
291
|
+
document.body.style.cursor = "";
|
|
292
|
+
document.body.style.userSelect = "";
|
|
290
293
|
}
|
|
291
|
-
|
|
292
|
-
document.addEventListener(
|
|
293
|
-
document.addEventListener(
|
|
294
|
-
document.body.style.cursor =
|
|
295
|
-
document.body.style.userSelect =
|
|
294
|
+
|
|
295
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
296
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
297
|
+
document.body.style.cursor = "col-resize";
|
|
298
|
+
document.body.style.userSelect = "none";
|
|
296
299
|
e.preventDefault();
|
|
297
300
|
}
|
|
298
301
|
|
|
@@ -332,7 +335,7 @@ const app = createApp({
|
|
|
332
335
|
renderCoreData,
|
|
333
336
|
toggleShowField,
|
|
334
337
|
startDragDrawer,
|
|
335
|
-
onFocusChange
|
|
338
|
+
onFocusChange,
|
|
336
339
|
};
|
|
337
340
|
},
|
|
338
341
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-voyager
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.5
|
|
4
4
|
Summary: Visualize FastAPI application's routing tree and dependencies
|
|
5
5
|
Project-URL: Homepage, https://github.com/allmonday/fastapi-voyager
|
|
6
6
|
Project-URL: Source, https://github.com/allmonday/fastapi-voyager
|
|
@@ -32,7 +32,9 @@ Description-Content-Type: text/markdown
|
|
|
32
32
|
|
|
33
33
|
> This repo is still in early stage, it supports pydantic v2 only
|
|
34
34
|
|
|
35
|
-
Inspect your API interactively!
|
|
35
|
+
Inspect your API interactively!
|
|
36
|
+
|
|
37
|
+
[visit online demo](https://www.newsyeah.fun/voyager/) of project: [composition oriented development pattern](https://github.com/allmonday/composition-oriented-development-pattern)
|
|
36
38
|
|
|
37
39
|
<p align="center"><img src="./voyager.jpg" alt="" /></p>
|
|
38
40
|
<p align="center"><a target="_blank" rel="" href="https://www.youtube.com/watch?v=PGlbQq1M-n8"><img src="http://img.youtube.com/vi/PGlbQq1M-n8/0.jpg" alt="" style="max-width: 100%;"></a></p>
|
|
@@ -170,6 +172,8 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
|
|
|
170
172
|
- [ ] optimize static resource (allow manually config url)
|
|
171
173
|
- [ ] improve search dialog
|
|
172
174
|
- [ ] add route/tag list
|
|
175
|
+
- [ ] type alias should not be kept as node instead of compiling to original type
|
|
176
|
+
- [ ] how to correctly handle the generic type ?
|
|
173
177
|
|
|
174
178
|
### in analysis
|
|
175
179
|
- [ ] click field to highlight links
|
|
@@ -240,6 +244,11 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
|
|
|
240
244
|
- [x] fix focus in brief-mode
|
|
241
245
|
- [x] ui: adjust focus position
|
|
242
246
|
- [x] refactor naming
|
|
247
|
+
- 0.10.4
|
|
248
|
+
- [x] fix: when focus is on, should ensure changes from other params not broken.
|
|
249
|
+
- 0.10.5
|
|
250
|
+
- [x] double click to show details, and highlight as tomato
|
|
251
|
+
|
|
243
252
|
|
|
244
253
|
#### 0.11
|
|
245
254
|
- [ ] enable/disable module cluster (to save space)
|
|
@@ -248,6 +257,11 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
|
|
|
248
257
|
- [ ] support opening route in swagger
|
|
249
258
|
- config docs path
|
|
250
259
|
- [ ] add tests
|
|
260
|
+
- [ ] fix: focus should reset zoom
|
|
261
|
+
- [ ] sort field name
|
|
262
|
+
- [ ] set max limit for fields
|
|
263
|
+
- [ ] add info icon alone with schema node
|
|
264
|
+
- [ ] add loading for field detail panel
|
|
251
265
|
|
|
252
266
|
#### 0.12
|
|
253
267
|
- [ ] integration with pydantic-resolve
|
|
@@ -2,23 +2,23 @@ fastapi_voyager/__init__.py,sha256=tZy0Nkj8kTaMgbvHy-mGxVcFGVX0Km-36dnzsAIG2uk,2
|
|
|
2
2
|
fastapi_voyager/cli.py,sha256=kQb4g6JEGZR99e5r8LyFFEeb_-uT-n_gp_sDoYG3R7k,11118
|
|
3
3
|
fastapi_voyager/filter.py,sha256=C718iwMjnnFXtqZISe9tzDRLAaY2FjbcE2LgkauEwnw,8095
|
|
4
4
|
fastapi_voyager/module.py,sha256=Z2QHNmiLk6ZAJlm2nSmO875Q33TweSg8UxZSzIpU9zY,3499
|
|
5
|
-
fastapi_voyager/render.py,sha256=
|
|
5
|
+
fastapi_voyager/render.py,sha256=vvJja8iNdmTA2Rpjo27a2efNtXmDy0M5sxXArMc3huY,7801
|
|
6
6
|
fastapi_voyager/server.py,sha256=6kCj906N4PVpKbUI8eq7bJ4RoET1kIQgUQUf-oMFdSY,6326
|
|
7
7
|
fastapi_voyager/type.py,sha256=pWYKmgb9e0W_JeD7k54Mr2lxUZV_Ir9TNpewGRwHyHQ,1629
|
|
8
8
|
fastapi_voyager/type_helper.py,sha256=hjBC4E0tgBpQDlYxGg74uK07SXjsrAgictEETJfIpYM,9231
|
|
9
|
-
fastapi_voyager/version.py,sha256=
|
|
9
|
+
fastapi_voyager/version.py,sha256=wULyXwCchfYy1WR_Ks9GdSJBTrJSOiEpDh_5kS02PC8,49
|
|
10
10
|
fastapi_voyager/voyager.py,sha256=r-_V0EPWwBM7N4hMlo-Si48mHVDc3zc9oGgTPCoEW_8,12377
|
|
11
|
-
fastapi_voyager/web/graph-ui.js,sha256=
|
|
11
|
+
fastapi_voyager/web/graph-ui.js,sha256=DTedkpZNbtufexONVkJ8mOwF_-VnvxoReYHtox6IKR4,5842
|
|
12
12
|
fastapi_voyager/web/graphviz.svg.css,sha256=zDCjjpT0Idufu5YOiZI76PL70-avP3vTyzGPh9M85Do,1563
|
|
13
13
|
fastapi_voyager/web/graphviz.svg.js,sha256=lvAdbjHc-lMSk4GQp-iqYA2PCFX4RKnW7dFaoe0LUHs,16005
|
|
14
|
-
fastapi_voyager/web/index.html,sha256=
|
|
14
|
+
fastapi_voyager/web/index.html,sha256=1W0QJUrQ1d-q9qdSD9Qax9uX6EJDNPUDGZsoO8T5I7g,16807
|
|
15
15
|
fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
|
|
16
16
|
fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
|
|
17
|
-
fastapi_voyager/web/vue-main.js,sha256=
|
|
17
|
+
fastapi_voyager/web/vue-main.js,sha256=zVE2vJJTe6BQ0rK2POiawu55MNIxnkEWQ4EYK1bBYlQ,10434
|
|
18
18
|
fastapi_voyager/web/component/render-graph.js,sha256=e8Xgh2Kl-nYU0P1gstEmAepCgFnk2J6UdxW8TlMafGs,2322
|
|
19
19
|
fastapi_voyager/web/component/route-code-display.js,sha256=8NJPPjNRUC21gjpY8XYEQs4RBbhX1pCiqEhJp39ku6k,3678
|
|
20
20
|
fastapi_voyager/web/component/schema-code-display.js,sha256=UgFotzvqSuhnPXNOr6w_r1fV2_savRiCdokEvferutE,6244
|
|
21
|
-
fastapi_voyager/web/component/schema-field-filter.js,sha256=
|
|
21
|
+
fastapi_voyager/web/component/schema-field-filter.js,sha256=c--XiXJrhIS7sYo1x8ZwMoqak0k9xLkNYTWoli-zd38,6253
|
|
22
22
|
fastapi_voyager/web/icon/android-chrome-192x192.png,sha256=35sBy6jmUFJCcquStaafHH1qClZIbd-X3PIKSeLkrNo,37285
|
|
23
23
|
fastapi_voyager/web/icon/android-chrome-512x512.png,sha256=eb2eDjCwIruc05029_0L9hcrkVkv8KceLn1DJMYU0zY,210789
|
|
24
24
|
fastapi_voyager/web/icon/apple-touch-icon.png,sha256=gnWK46tPnvSw1-oYZjgI02wpoO4OrIzsVzGHC5oKWO0,33187
|
|
@@ -26,8 +26,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
|
|
|
26
26
|
fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
|
|
27
27
|
fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
|
|
28
28
|
fastapi_voyager/web/icon/site.webmanifest,sha256=ep4Hzh9zhmiZF2At3Fp1dQrYQuYF_3ZPZxc1KcGBvwQ,263
|
|
29
|
-
fastapi_voyager-0.10.
|
|
30
|
-
fastapi_voyager-0.10.
|
|
31
|
-
fastapi_voyager-0.10.
|
|
32
|
-
fastapi_voyager-0.10.
|
|
33
|
-
fastapi_voyager-0.10.
|
|
29
|
+
fastapi_voyager-0.10.5.dist-info/METADATA,sha256=V7jML-nsztkhELLUDX6RNxGw6tjcovVKprCa1aMetXw,9659
|
|
30
|
+
fastapi_voyager-0.10.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
31
|
+
fastapi_voyager-0.10.5.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
|
|
32
|
+
fastapi_voyager-0.10.5.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
|
|
33
|
+
fastapi_voyager-0.10.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|