fastapi-voyager 0.9.2__py3-none-any.whl → 0.9.3__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.
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.9.2"
2
+ __version__ = "0.9.3"
@@ -3,12 +3,10 @@ const { defineComponent, ref, watch, onMounted } = window.Vue;
3
3
  // Component: RouteCodeDisplay
4
4
  // Props:
5
5
  // routeId: route id key in routeItems
6
- // modelValue: dialog visibility
7
6
  export default defineComponent({
8
7
  name: "RouteCodeDisplay",
9
8
  props: {
10
9
  routeId: { type: String, required: true },
11
- modelValue: { type: Boolean, default: false },
12
10
  },
13
11
  emits: ["close"],
14
12
  setup(props, { emit }) {
@@ -99,32 +97,26 @@ export default defineComponent({
99
97
  }
100
98
  }
101
99
 
102
- watch(
103
- () => props.modelValue,
104
- (v) => {
105
- if (v) load();
106
- }
107
- );
108
100
  watch(
109
101
  () => props.routeId,
110
102
  () => {
111
- if (props.modelValue) load();
103
+ load();
112
104
  }
113
105
  );
114
106
 
115
107
  onMounted(() => {
116
- if (props.modelValue) load();
108
+ load();
117
109
  });
118
110
 
119
111
  return { loading, code, error, close, link };
120
112
  },
121
113
  template: `
122
- <div class="frv-route-code-display" style="border:1px solid #ccc; position:relative; width:50vw; max-width:50vw; height:100%; background:#fff;">
114
+ <div class="frv-route-code-display" style="border:1px solid #ccc; position:relative; background:#fff;">
123
115
  <q-btn dense flat round icon="close" @click="close" aria-label="Close" style="position:absolute; top:6px; right:6px; z-index:10; background:rgba(255,255,255,0.85)" />
124
116
  <div v-if="link" class="q-ml-md q-mt-md" style="padding-top:4px;">
125
117
  <a :href="link" target="_blank" rel="noopener" style="font-size:12px; color:#3b82f6;">Open in VSCode</a>
126
118
  </div>
127
- <div style="padding:40px 16px 16px 16px; height:100%; box-sizing:border-box; overflow:auto;">
119
+ <div style="padding:40px 16px 16px 16px; box-sizing:border-box; overflow:auto;">
128
120
  <div v-if="loading" style="font-family:Menlo, monospace; font-size:12px;">Loading source...</div>
129
121
  <div v-else-if="error" style="color:#c10015; font-family:Menlo, monospace; font-size:12px;">{{ error }}</div>
130
122
  <pre v-else style="margin:0;"><code class="language-python">{{ code }}</code></pre>
@@ -13,23 +13,17 @@ export default defineComponent({
13
13
  name: "SchemaCodeDisplay",
14
14
  props: {
15
15
  schemaName: { type: String, required: true },
16
- modelValue: { type: Boolean, default: false },
17
16
  schemas: { type: Object, default: () => ({}) },
18
17
  },
19
- emits: ["close"],
20
18
  setup(props, { emit }) {
21
- const loading = ref(false);
22
19
  const code = ref("");
23
20
  const link = ref("");
24
21
  const error = ref("");
25
22
  const fields = ref([]); // schema fields list
26
23
  const tab = ref("source");
27
24
 
28
- function close() {
29
- emit("close");
30
- }
31
25
 
32
- function highlightLater() {
26
+ async function highlightLater() {
33
27
  // wait a tick for DOM update
34
28
  requestAnimationFrame(() => {
35
29
  try {
@@ -38,6 +32,10 @@ export default defineComponent({
38
32
  ".frv-code-display pre code.language-python"
39
33
  );
40
34
  if (block) {
35
+ // If already highlighted by highlight.js, remove the flag so it can be highlighted again
36
+ if (block.dataset && block.dataset.highlighted) {
37
+ block.removeAttribute("data-highlighted");
38
+ }
41
39
  window.hljs.highlightElement(block);
42
40
  }
43
41
  }
@@ -50,7 +48,6 @@ export default defineComponent({
50
48
  async function loadSource() {
51
49
  if (!props.schemaName) return;
52
50
 
53
- loading.value = true;
54
51
  error.value = null;
55
52
  code.value = "";
56
53
  link.value = "";
@@ -77,7 +74,6 @@ export default defineComponent({
77
74
  } catch (e) {
78
75
  error.value = "Failed to load source";
79
76
  } finally {
80
- loading.value = false;
81
77
  }
82
78
 
83
79
  try {
@@ -99,12 +95,12 @@ export default defineComponent({
99
95
  } catch (e) {
100
96
  error.value = "Failed to load source";
101
97
  } finally {
102
- loading.value = false;
103
98
  }
104
99
 
105
- fields.value = props.schemas[props.schemaName].fields || []
100
+ const schema = props.schemas && props.schemas[props.schemaName];
101
+ fields.value = Array.isArray(schema?.fields) ? schema.fields : [];
106
102
 
107
- if (!error.value && tab.value === "source") {
103
+ if (tab.value === "source") {
108
104
  highlightLater();
109
105
  }
110
106
  }
@@ -120,25 +116,21 @@ export default defineComponent({
120
116
  );
121
117
 
122
118
  watch(
123
- () => props.modelValue,
124
- (val) => {
125
- if (val) {
126
- loadSource();
127
- }
128
- }
119
+ () => props.schemaName,
120
+ () => {
121
+ loadSource();
122
+ },
129
123
  );
130
124
 
131
125
  onMounted(() => {
132
- if (props.modelValue) loadSource();
126
+ loadSource();
133
127
  });
134
128
 
135
- return { loading, link, code, error, close, fields, tab };
129
+ return { link, code, error, fields, tab };
136
130
  },
137
131
  template: `
138
- <div class="frv-code-display" style="border: 1px solid #ccc; border-left: none; position:relative; width:40vw; max-width:40vw; height:100%; background:#fff;">
139
- <q-btn dense flat round icon="close" @click="close" aria-label="Close"
140
- style="position:absolute; top:6px; right:6px; z-index:10; background:rgba(255,255,255,0.85)" />
141
- <div v-if="link" class="q-ml-md q-mt-md">
132
+ <div class="frv-code-display" style="border: 1px solid #ccc; border-left: none; position:relative; height:100%; background:#fff;">
133
+ <div class="q-ml-lg q-mt-md">
142
134
  <a :href="link" target="_blank" rel="noopener" style="font-size:12px; color:#3b82f6;">
143
135
  Open in VSCode
144
136
  </a>
@@ -152,8 +144,7 @@ export default defineComponent({
152
144
  </div>
153
145
  <q-separator />
154
146
  <div style="padding:8px 16px 16px 16px; height:75%; box-sizing:border-box; overflow:auto;">
155
- <div v-if="loading" style="font-family:Menlo, monospace; font-size:12px;">Loading source...</div>
156
- <div v-else-if="error" style="color:#c10015; font-family:Menlo, monospace; font-size:12px;">{{ error }}</div>
147
+ <div v-if="error" style="color:#c10015; font-family:Menlo, monospace; font-size:12px;">{{ error }}</div>
157
148
  <template v-else>
158
149
  <div v-show="tab === 'source'">
159
150
  <pre style="margin:0;"><code class="language-python">{{ code }}</code></pre>
@@ -69,23 +69,27 @@ export class GraphUI {
69
69
  const set = $();
70
70
  set.push(this);
71
71
  const obj = { set, direction: "bidirectional" };
72
- // Shift+Click to trigger schema detail callback (if provided)
72
+
73
+ const schemaName = event.currentTarget.dataset.name;
73
74
  if (event.shiftKey && self.options.onSchemaClick) {
74
75
  // try data-name or title text
75
- const schemaName = event.currentTarget.dataset.name;
76
76
  if (schemaName) {
77
77
  try {
78
- self.options.onSchemaClick(schemaName);
78
+ self.options.onSchemaShiftClick(schemaName);
79
79
  } catch (e) {
80
- console.warn("onSchemaClick callback failed", e);
80
+ console.warn("onSchemaShiftClick callback failed", e);
81
81
  }
82
82
  }
83
- } else if (event.altKey && self.options.onSchemaAltClick) {
84
- const schemaName = event.currentTarget.dataset.name;
85
- self.options.onSchemaAltClick(schemaName);
86
83
  } else {
87
84
  self.currentSelection = [obj];
88
85
  self._highlight();
86
+ if (schemaName) {
87
+ try {
88
+ self.options.onSchemaClick(schemaName);
89
+ } catch (e) {
90
+ console.warn("onSchemaClick callback failed", e);
91
+ }
92
+ }
89
93
  }
90
94
  });
91
95
 
@@ -55,51 +55,26 @@
55
55
  flex: 1 1 auto;
56
56
  overflow: auto;
57
57
  }
58
+
59
+ .adjust-fit {
60
+ height: calc(100% - 54px);
61
+ }
58
62
  </style>
59
63
  <body>
60
- <div id="q-app" class="column" style="height: 100%">
61
- <div
62
- v-if="state.initializing"
63
- style="
64
- position: fixed;
65
- inset: 0;
66
- display: flex;
67
- align-items: center;
68
- justify-content: center;
69
- z-index: 2000;
70
- background: rgba(255, 255, 255, 0.85);
71
- font-size: 18px;
72
- font-family: Roboto, sans-serif;
73
- color: #444;
74
- "
75
- >
76
- <div style="text-align: center">
77
- <div class="q-mb-sm">Initializing...</div>
78
- <q-spinner color="primary" size="32px" />
79
- </div>
80
- </div>
81
- <div
82
- style="
83
- padding: 8px;
84
- background-color: #fff;
85
- border-bottom: 1px solid #ccc;
86
- color: #211d1d;
87
- flex: 0 0 auto;
88
- "
89
- >
90
- <div class="row items-center q-col-gutter-md">
91
- <div class="col-auto">
64
+ <div id="q-app">
65
+ <q-layout view="hHh lpR fff">
66
+ <q-header bordered class="bg-primary text-white">
67
+ <q-toolbar class="row text-grey-9 bg-white" style="width: 100%">
92
68
  <div
93
- style="width: 282px; margin-left: 8px"
94
- class="text-h6 text-primary"
69
+ class="col-auto text-primary"
70
+ style="font-size: 16px; font-weight: bold"
95
71
  >
96
72
  <q-icon class="q-mr-sm" name="satellite_alt"></q-icon>
97
73
  <span> FastAPI Voyager </span>
98
74
  </div>
99
- </div>
100
- <div class="col-auto">
101
- <div class="column">
75
+ <div class="col-auto" style="font-size: 16px">
102
76
  <q-option-group
77
+ style="margin-left: 140px"
103
78
  v-model="state.showFields"
104
79
  :options="state.fieldOptions"
105
80
  @update:model-value="(val) => toggleShowField(val)"
@@ -109,170 +84,189 @@
109
84
  dense
110
85
  />
111
86
  </div>
112
- </div>
113
-
114
- <!-- <div class="col-auto">
115
- <q-btn-dropdown
116
- class="q-ml-md"
117
- split
118
- :loading="state.generating"
119
- @click="onGenerate"
120
- label="Generate"
121
- outline
122
- >
123
- <q-list>
124
- <q-item clickable v-close-popup @click="onDumpData">
125
- <q-item-section>Dump data</q-item-section>
126
- </q-item>
127
- <q-item clickable v-close-popup @click="openImportDialog">
128
- <q-item-section>Import data</q-item-section>
129
- </q-item>
130
- </q-list>
131
- </q-btn-dropdown>
132
- </div> -->
87
+ <div class="col-auto q-ml-auto">
88
+ <q-toggle
89
+ class="q-mr-md"
90
+ v-model="state.brief"
91
+ label="Brief Mode"
92
+ @update:model-value="(val) => toggleBrief(val)"
93
+ title="skip middle classes, config module_prefix to enable it"
94
+ dense
95
+ />
96
+ </div>
97
+ <div class="col-auto">
98
+ <q-toggle
99
+ v-model="state.hidePrimitiveRoute"
100
+ @update:model-value="(val) => toggleHidePrimitiveRoute(val)"
101
+ label="Hide Primitive"
102
+ title="hide routes return primitive"
103
+ class="q-mr-md"
104
+ dense
105
+ />
106
+ </div>
107
+ <div class="col-auto">
108
+ <q-btn
109
+ outline
110
+ @click="onReset"
111
+ title="may be very slow"
112
+ class="q-mr-md"
113
+ label="Show All"
114
+ />
115
+ </div>
116
+ <div class="col-auto">
117
+ <q-btn
118
+ outline
119
+ icon="search"
120
+ label="Search"
121
+ class="q-mr-md"
122
+ @click="showDialog()"
123
+ />
124
+ </div>
125
+ <div class="col-auto">
126
+ <q-btn
127
+ dense
128
+ round
129
+ flat
130
+ icon="help_outline"
131
+ aria-label="Help"
132
+ class="q-mr-sm"
133
+ >
134
+ <q-tooltip
135
+ anchor="bottom middle"
136
+ self="top middle"
137
+ :offset="[0,8]"
138
+ >
139
+ <div
140
+ class="column items-start text-left"
141
+ style="line-height: 1.4; font-size: 12px"
142
+ >
143
+ <ul>
144
+ <li>scroll to zoom in/out</li>
145
+ <li>
146
+ click node to check highlight related nodes on the
147
+ chart, esc to unselect
148
+ </li>
149
+ <li>
150
+ shift + click to see schema's dependencies without
151
+ unrelated nodes
152
+ </li>
153
+ <li>alt + click to see schema details</li>
154
+ </ul>
155
+ </div>
156
+ </q-tooltip>
157
+ </q-btn>
158
+ </div>
159
+ <!-- <q-toolbar-title class="text-primary row">
160
+ </q-toolbar-title> -->
161
+ </q-toolbar>
162
+ </q-header>
133
163
 
134
- <div class="col-auto q-ml-auto">
135
- <q-toggle
136
- class="q-ml-md"
137
- v-model="state.brief"
138
- label="Brief Mode"
139
- @update:model-value="(val) => toggleBrief(val)"
140
- title="skip middle classes, config module_prefix to enable it"
141
- dense
142
- />
143
- </div>
144
- <div class="col-auto">
145
- <q-toggle
146
- v-model="state.hidePrimitiveRoute"
147
- @update:model-value="(val) => toggleHidePrimitiveRoute(val)"
148
- label="Hide Primitive"
149
- title="hide routes return primitive"
150
- dense
151
- />
152
- </div>
153
- <div class="col-auto">
154
- <q-btn
155
- outline
156
- @click="onReset"
157
- title="may be very slow"
158
- label="Show All"
159
- />
160
- </div>
161
- <div class="col-auto">
162
- <q-btn outline icon="search" label="Search" @click="showDialog()" />
163
- </div>
164
- <div class="col-auto">
164
+ <q-drawer
165
+ v-model="state.detailDrawer"
166
+ width="400"
167
+ side="right"
168
+ overlay
169
+ bordered
170
+ >
171
+ <div style="z-index: 1; position: absolute; left: -17px; top: 9px">
165
172
  <q-btn
166
- dense
173
+ @click="state.detailDrawer = !state.detailDrawer"
167
174
  round
168
- flat
169
- icon="help_outline"
170
- aria-label="Help"
171
- class="q-mr-md"
172
- >
173
- <q-tooltip
174
- anchor="bottom middle"
175
- self="top middle"
176
- :offset="[0,8]"
177
- >
178
- <div
179
- class="column items-start text-left"
180
- style="line-height: 1.4; font-size: 12px"
181
- >
182
- <ul>
183
- <li>scroll to zoom in/out</li>
184
- <li>
185
- click node to check highlight related nodes on the chart,
186
- esc to unselect
187
- </li>
188
- <li>
189
- shift + click to see schema's dependencies without
190
- unrelated nodes
191
- </li>
192
- <li>alt + click to see schema details</li>
193
- </ul>
194
- </div>
195
- </q-tooltip>
196
- </q-btn>
175
+ unelevated
176
+ color="primary"
177
+ dense
178
+ icon="chevron_right"
179
+ />
197
180
  </div>
198
- </div>
199
- </div>
200
- <div style="flex: 1 1 auto; min-height: 10px;">
201
- <q-splitter
202
- v-model="state.splitter"
203
- unit="px"
204
- :limits="[200, 800]"
205
- class="fit"
206
- >
207
- <template #before>
208
- <div
209
- id="tag-navigator"
210
- class="column no-wrap"
211
- :style="{
181
+ <!-- move to bottom -->
182
+ <schema-code-display
183
+ :schema-name="schemaCodeName"
184
+ :schemas="state.rawSchemasFull"
185
+ />
186
+ </q-drawer>
187
+
188
+ <q-page-container>
189
+ <q-splitter
190
+ v-model="state.splitter"
191
+ unit="px"
192
+ :limits="[200, 800]"
193
+ class="adjust-fit"
194
+ >
195
+ <template #before>
196
+ <div
197
+ id="tag-navigator"
198
+ class="column no-wrap"
199
+ :style="{
212
200
  borderRight: '1px solid #e0e0e0',
213
201
  backgroundColor: '#fff',
214
202
  minHeight: 0,
215
203
  height: '100%'
216
204
  }"
217
- >
218
- <q-scroll-area class="fit">
219
- <q-list dense separator>
220
- <q-expansion-item
221
- v-for="tag in state.rawTags"
222
- :key="tag.name"
223
- expand-separator
224
- :model-value="state.tag === tag.name"
225
- @update:model-value="(val) => toggleTag(tag.name, val)"
226
- :header-class="state.tag === tag.name ? 'text-primary text-bold' : ''"
227
- content-class="q-pa-none"
228
- >
229
- <template #header>
230
- <div class="row items-center" style="width: 100%">
231
- <div class="row items-end">
232
- <q-icon
233
- class="q-mr-sm"
234
- :name="state.tag == tag.name ? 'folder' : 'folder_open'"
235
- ></q-icon>
236
- <span>{{ tag.name }}</span>
205
+ >
206
+ <q-scroll-area class="fit">
207
+ <q-list dense separator>
208
+ <q-expansion-item
209
+ v-for="tag in state.rawTags"
210
+ :key="tag.name"
211
+ expand-separator
212
+ :model-value="state.tag === tag.name"
213
+ @update:model-value="(val) => toggleTag(tag.name, val)"
214
+ :header-class="state.tag === tag.name ? 'text-primary text-bold' : ''"
215
+ content-class="q-pa-none"
216
+ >
217
+ <template #header>
218
+ <div class="row items-center" style="width: 100%">
219
+ <div class="row items-end">
220
+ <q-icon
221
+ class="q-mr-sm"
222
+ :name="state.tag == tag.name ? 'folder' : 'folder_open'"
223
+ ></q-icon>
224
+ <span>{{ tag.name }}</span>
225
+ </div>
237
226
  </div>
238
- </div>
239
- </template>
227
+ </template>
240
228
 
241
- <q-list separator>
242
- <q-item
243
- v-for="route in (state.hidePrimitiveRoute ? tag.routes.filter(r => !r.is_primitive) :tag.routes || [])"
244
- :key="route.id"
245
- clickable
246
- v-ripple
247
- :active="state.routeId === route.id"
248
- active-class=""
249
- @click="selectRoute(route.id)"
250
- >
251
- <q-item-section>
252
- <span class="q-ml-lg" style="white-space: nowrap">
253
- <q-icon class="q-mr-sm" name="data_object"></q-icon>
254
- {{ route.name }}
255
- </span>
256
- </q-item-section>
257
- </q-item>
258
- <q-item v-if="!tag.routes || tag.routes.length === 0" dense>
259
- <q-item-section class="text-grey-6"
260
- >No routes</q-item-section
229
+ <q-list separator>
230
+ <q-item
231
+ v-for="route in (state.hidePrimitiveRoute ? tag.routes.filter(r => !r.is_primitive) :tag.routes || [])"
232
+ :key="route.id"
233
+ clickable
234
+ v-ripple
235
+ :active="state.routeId === route.id"
236
+ active-class=""
237
+ @click="selectRoute(route.id)"
261
238
  >
262
- </q-item>
263
- </q-list>
264
- </q-expansion-item>
265
- </q-list>
266
- </q-scroll-area>
267
- </div>
268
- </template>
269
-
270
- <template #after>
271
- <div id="graph" class="fit"></div>
272
- </template>
273
- </q-splitter>
274
- </div>
239
+ <q-item-section>
240
+ <span class="q-ml-lg" style="white-space: nowrap">
241
+ <q-icon
242
+ class="q-mr-sm"
243
+ name="data_object"
244
+ ></q-icon>
245
+ {{ route.name }}
246
+ </span>
247
+ </q-item-section>
248
+ </q-item>
249
+ <q-item
250
+ v-if="!tag.routes || tag.routes.length === 0"
251
+ dense
252
+ >
253
+ <q-item-section class="text-grey-6"
254
+ >No routes</q-item-section
255
+ >
256
+ </q-item>
257
+ </q-list>
258
+ </q-expansion-item>
259
+ </q-list>
260
+ </q-scroll-area>
261
+ </div>
262
+ </template>
275
263
 
264
+ <template #after>
265
+ <div id="graph" class="fit"></div>
266
+ </template>
267
+ </q-splitter>
268
+ </q-page-container>
269
+ </q-layout>
276
270
  <!-- Detail Dialog -->
277
271
  <q-dialog v-model="showDetail" :persistent="true" :maximized="true">
278
272
  <detail-dialog
@@ -296,35 +290,10 @@
296
290
  />
297
291
  </q-dialog>
298
292
 
299
- <!-- Schema Source Code Dialog (Ctrl + Click) -->
300
- <q-dialog
301
- v-model="showSchemaCode"
302
- :maximized="true"
303
- :persistent="false"
304
- position="left"
305
- :seamless="false"
306
- >
307
- <schema-code-display
308
- :schema-name="schemaCodeName"
309
- :model-value="showSchemaCode"
310
- :schemas="state.rawSchemasFull"
311
- @close="showSchemaCode = false"
312
- />
313
- </q-dialog>
314
-
315
- <!-- Route Source Code Dialog (Alt + Click on route) -->
316
- <q-dialog
317
- v-model="showRouteCode"
318
- :maximized="true"
319
- :persistent="false"
320
- position="right"
321
- :seamless="false"
322
- >
323
- <route-code-display
324
- :route-id="routeCodeId"
325
- :model-value="showRouteCode"
326
- @close="showRouteCode = false"
327
- />
293
+ <q-dialog v-model="showRouteDetail" position="bottom">
294
+ <q-card style="width: 1100px; max-width: 1100px">
295
+ <route-code-display :route-id="routeCodeId" @close="showRouteDetail=false" />
296
+ </q-card>
328
297
  </q-dialog>
329
298
 
330
299
  <!-- Dump Core Data Dialog -->
@@ -14,7 +14,7 @@ const app = createApp({
14
14
  schemaId: null, // picked schema
15
15
  showFields: "object",
16
16
  fieldOptions: [
17
- { label: "No fields", value: "single" },
17
+ { label: "No field", value: "single" },
18
18
  { label: "Object fields", value: "object" },
19
19
  { label: "All fields", value: "all" },
20
20
  ],
@@ -27,12 +27,11 @@ const app = createApp({
27
27
  initializing: true,
28
28
  // Splitter size (left panel width in px)
29
29
  splitter: 300,
30
+ detailDrawer: false
30
31
  });
31
32
 
32
33
  const showDetail = ref(false);
33
34
  const showSchemaFieldFilter = ref(false);
34
- const showSchemaCode = ref(false);
35
- const showRouteCode = ref(false);
36
35
  const showDumpDialog = ref(false);
37
36
  const dumpJson = ref("");
38
37
  const showImportDialog = ref(false);
@@ -43,6 +42,7 @@ const app = createApp({
43
42
  const schemaFieldFilterSchema = ref(null); // external schemaName for schema-field-filter
44
43
  const schemaCodeName = ref("");
45
44
  const routeCodeId = ref("");
45
+ const showRouteDetail = ref(false)
46
46
 
47
47
  function openDetail() {
48
48
  showDetail.value = true;
@@ -100,22 +100,20 @@ const app = createApp({
100
100
 
101
101
  // create graph instance once
102
102
  const graphUI = new GraphUI("#graph", {
103
- onSchemaClick: (id) => {
103
+ onSchemaShiftClick: (id) => {
104
104
  if (state.rawSchemas.has(id)) {
105
105
  schemaFieldFilterSchema.value = id;
106
106
  showSchemaFieldFilter.value = true;
107
107
  }
108
108
  },
109
- onSchemaAltClick: (id) => {
109
+ onSchemaClick: (id) => {
110
110
  if (state.rawSchemas.has(id)) {
111
111
  schemaCodeName.value = id;
112
- showSchemaCode.value = true;
113
- return;
112
+ state.detailDrawer = true
114
113
  }
115
114
  if (id in state.routeItems) {
116
115
  routeCodeId.value = id;
117
- showRouteCode.value = true;
118
- return;
116
+ showRouteDetail.value = true
119
117
  }
120
118
  },
121
119
  });
@@ -245,14 +243,13 @@ const app = createApp({
245
243
  onGenerate,
246
244
  onReset,
247
245
  showDetail,
246
+ showRouteDetail,
248
247
  openDetail,
249
248
  closeDetail,
250
249
  schemaName,
251
250
  showSchemaFieldFilter,
252
251
  schemaFieldFilterSchema,
253
252
  showDialog,
254
- showSchemaCode,
255
- showRouteCode,
256
253
  schemaCodeName,
257
254
  routeCodeId,
258
255
  // dump/import
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.9.2
3
+ Version: 0.9.3
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
@@ -27,6 +27,8 @@ Description-Content-Type: text/markdown
27
27
 
28
28
  [![pypi](https://img.shields.io/pypi/v/fastapi-voyager.svg)](https://pypi.python.org/pypi/fastapi-voyager)
29
29
  ![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-voyager)
30
+ [![PyPI Downloads](https://static.pepy.tech/badge/fastapi-voyager/month)](https://pepy.tech/projects/fastapi-voyager)
31
+
30
32
 
31
33
  > This repo is still in early stage, it supports pydantic v2 only
32
34
 
@@ -163,7 +165,6 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
163
165
  - [ ] user can generate nodes/edges manually and connect to generated ones
164
166
  - [ ] add owner
165
167
  - [ ] add extra info for schema
166
- - [ ] fixed left/right bar show field information
167
168
  - [ ] display standard ER diagram `hard`
168
169
  - [ ] display potential invalid links
169
170
  - [ ] support dataclass (pending)
@@ -211,6 +212,9 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
211
212
  - [x] improve initialization time cost
212
213
  - [x] query route / schema info through realtime api
213
214
  - [x] adjust fe
215
+ - [x] adjust layout (0.9.3)
216
+ - [x] show field detail in right panel
217
+ - [x] show route info in bottom
214
218
 
215
219
  #### 0.10
216
220
  - [ ] support opening route in swagger
@@ -235,6 +239,9 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
235
239
  - [ ] show hint for resolve, post fields
236
240
  - [ ] display loader as edges
237
241
 
242
+ #### 0.13
243
+ - [ ] config release pipeline
244
+ - [ ]
238
245
 
239
246
  ## Using with pydantic-resolve
240
247
 
@@ -260,6 +267,8 @@ pydantic-resolve's @ensure_subset decorator is helpful to pick fields from `sour
260
267
  ## Changelog
261
268
 
262
269
  - 0.9:
270
+ - 0.9.3:
271
+ - enhancement: better UI
263
272
  - 0.9.2:
264
273
  - fix: missing fields in schema detail panel
265
274
  - optimization: clean up fe codes.
@@ -6,18 +6,18 @@ fastapi_voyager/render.py,sha256=qy3g1Rz1s8XkuR_6n1Q1YPwy_oMOjWjNswTHQjdz4N0,776
6
6
  fastapi_voyager/server.py,sha256=pg-LHDj4yU0usDA1b2X2Kt2_OCrexFA2G9ifGxb52Uc,6196
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=Su4VudgwOkDWEBzNahJ3LX1SbIA7uezku9g1zsUddHU,48
9
+ fastapi_voyager/version.py,sha256=Lt2a1ZjlXG3QcL31iJHgzvRFDSTSsCXmwjQNWNdNUMY,48
10
10
  fastapi_voyager/voyager.py,sha256=pXvA3ye5Jq6aJ6YrZFbTHjJ9MzdydqWllIgY8RFK_4A,10793
11
- fastapi_voyager/web/graph-ui.js,sha256=0hqMCzsPJfhgWDuwiXVXaGQL-_7urT_zryo4sXMN8jQ,4209
11
+ fastapi_voyager/web/graph-ui.js,sha256=QYJXHOH4EWF2jbcX3usTKv4tNody0RjpnVz-eh0UKkU,4185
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=pmctp4OizRd8ETKEI0vl0Seu9nIQklfnbFDDyztFoy4,14264
14
+ fastapi_voyager/web/index.html,sha256=YtVoDRrgz64E7IHpcPJBzUb1DI1H5P7a-3ziTx5BHYA,13735
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=ZRJQBV54YqoKkLI2a8WHF6uYeFUpqwBl-lykkaYxCXI,8182
17
+ fastapi_voyager/web/vue-main.js,sha256=kQJpcQ2ENzA90v1XJ1P2bNGfeFC4drTGoG5dNhQKQqc,8105
18
18
  fastapi_voyager/web/component/render-graph.js,sha256=e8Xgh2Kl-nYU0P1gstEmAepCgFnk2J6UdxW8TlMafGs,2322
19
- fastapi_voyager/web/component/route-code-display.js,sha256=Pdg8JX_yHhoUUGSqgRs_zTciIfw5wYzG6-kQfHtdWFU,3956
20
- fastapi_voyager/web/component/schema-code-display.js,sha256=Aa_mXxmNgIbImoT1_zuzsPgbPq8QaakUAzNWTxHxM58,6584
19
+ fastapi_voyager/web/component/route-code-display.js,sha256=8NJPPjNRUC21gjpY8XYEQs4RBbhX1pCiqEhJp39ku6k,3678
20
+ fastapi_voyager/web/component/schema-code-display.js,sha256=B-NOAKQIDORvFlKrsWNFAMGweXYBXrpg6AjKt4TFQFI,6256
21
21
  fastapi_voyager/web/component/schema-field-filter.js,sha256=PR8d2_u1UiSLrS5zqAvY2UR8LbvjBqiUDt71tm1DJTs,6345
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
@@ -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.9.2.dist-info/METADATA,sha256=k_l0KTvYeGwMhRPdulVlob3_q-uZ9UTEHo_KLeXTHsQ,9221
30
- fastapi_voyager-0.9.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- fastapi_voyager-0.9.2.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
32
- fastapi_voyager-0.9.2.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
33
- fastapi_voyager-0.9.2.dist-info/RECORD,,
29
+ fastapi_voyager-0.9.3.dist-info/METADATA,sha256=m7vs-SegP6z60WrAwoMBV-fqyrUwlg08_EktecMzcSM,9490
30
+ fastapi_voyager-0.9.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
+ fastapi_voyager-0.9.3.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
32
+ fastapi_voyager-0.9.3.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
33
+ fastapi_voyager-0.9.3.dist-info/RECORD,,