fastapi-voyager 0.12.6__tar.gz → 0.12.7__tar.gz
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-0.12.6 → fastapi_voyager-0.12.7}/PKG-INFO +1 -1
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/docs/changelog.md +3 -1
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/server.py +32 -1
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/version.py +1 -1
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/voyager.py +16 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/index.html +48 -27
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/store.js +8 -4
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/vue-main.js +181 -64
- fastapi_voyager-0.12.6/src/fastapi_voyager/web/component/schema-field-filter.js +0 -190
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/.github/workflows/publish.yml +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/.gitignore +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/.python-version +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/CONTRIBUTING.md +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/LICENSE +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/README.md +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/docs/idea.md +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/pyproject.toml +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/release.md +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/__init__.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/cli.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/filter.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/module.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/render.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/type.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/type_helper.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/component/demo.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/component/render-graph.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/component/route-code-display.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/component/schema-code-display.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/graph-ui.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/graphviz.svg.css +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/graphviz.svg.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/android-chrome-192x192.png +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/android-chrome-512x512.png +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/apple-touch-icon.png +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/favicon-16x16.png +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/favicon-32x32.png +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/favicon.ico +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/site.webmanifest +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/quasar.min.css +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/quasar.min.js +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/__init__.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/demo.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/demo_anno.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/programatic.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/service/__init__.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/service/schema/__init__.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/service/schema/extra.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/service/schema/schema.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/test_analysis.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/test_filter.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/test_generic.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/test_import.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/test_module.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/tests/test_type_helper.py +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/uv.lock +0 -0
- {fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/voyager.jpg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-voyager
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.7
|
|
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
|
|
@@ -120,8 +120,10 @@
|
|
|
120
120
|
- [x] click link(edge) to highlight related nodes
|
|
121
121
|
- [x] on hover cursor effect
|
|
122
122
|
- 0.12.7
|
|
123
|
+
- [x] remove search component, integrated into main page
|
|
124
|
+
- 0.12.8
|
|
125
|
+
- [ ] refactor vue-main.js, move methods to store
|
|
123
126
|
- [ ] refactor render.py
|
|
124
|
-
- [ ] remove search component, integrated into main page
|
|
125
127
|
|
|
126
128
|
## 0.13
|
|
127
129
|
- 0.13.2
|
|
@@ -34,6 +34,8 @@ def _build_ga_snippet(ga_id: str | None) -> str:
|
|
|
34
34
|
|
|
35
35
|
INITIAL_PAGE_POLICY = Literal['first', 'full', 'empty']
|
|
36
36
|
|
|
37
|
+
# ---------- setup ----------
|
|
38
|
+
|
|
37
39
|
class OptionParam(BaseModel):
|
|
38
40
|
tags: list[Tag]
|
|
39
41
|
schemas: list[SchemaNode]
|
|
@@ -49,11 +51,21 @@ class Payload(BaseModel):
|
|
|
49
51
|
schema_field: str | None = None
|
|
50
52
|
route_name: str | None = None
|
|
51
53
|
show_fields: str = 'object'
|
|
52
|
-
show_meta: bool = False
|
|
53
54
|
brief: bool = False
|
|
54
55
|
hide_primitive_route: bool = False
|
|
55
56
|
show_module: bool = True
|
|
56
57
|
|
|
58
|
+
# ---------- search ----------
|
|
59
|
+
class SearchResultOptionParam(BaseModel):
|
|
60
|
+
tags: list[Tag]
|
|
61
|
+
|
|
62
|
+
class SchemaSearchPayload(BaseModel): # leave tag, route out
|
|
63
|
+
schema_name: str | None = None
|
|
64
|
+
schema_field: str | None = None
|
|
65
|
+
show_fields: str = 'object'
|
|
66
|
+
brief: bool = False
|
|
67
|
+
hide_primitive_route: bool = False
|
|
68
|
+
show_module: bool = True
|
|
57
69
|
|
|
58
70
|
def create_voyager(
|
|
59
71
|
target_app: FastAPI,
|
|
@@ -91,6 +103,25 @@ def create_voyager(
|
|
|
91
103
|
swagger_url=swagger_url,
|
|
92
104
|
initial_page_policy=initial_page_policy)
|
|
93
105
|
|
|
106
|
+
@router.post("/dot-search", response_model=SearchResultOptionParam)
|
|
107
|
+
def get_search_dot(payload: SchemaSearchPayload):
|
|
108
|
+
voyager = Voyager(
|
|
109
|
+
schema=payload.schema_name,
|
|
110
|
+
schema_field=payload.schema_field,
|
|
111
|
+
show_fields=payload.show_fields,
|
|
112
|
+
module_color=module_color,
|
|
113
|
+
hide_primitive_route=payload.hide_primitive_route,
|
|
114
|
+
show_module=payload.show_module,
|
|
115
|
+
)
|
|
116
|
+
voyager.analysis(target_app)
|
|
117
|
+
tags = voyager.calculate_filtered_tag_and_route()
|
|
118
|
+
|
|
119
|
+
for t in tags:
|
|
120
|
+
t.routes.sort(key=lambda r: r.name)
|
|
121
|
+
tags.sort(key=lambda t: t.name)
|
|
122
|
+
|
|
123
|
+
return SearchResultOptionParam(tags=tags)
|
|
124
|
+
|
|
94
125
|
@router.post("/dot", response_class=PlainTextResponse)
|
|
95
126
|
def get_filtered_dot(payload: Payload) -> str:
|
|
96
127
|
voyager = Voyager(
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "0.12.
|
|
2
|
+
__version__ = "0.12.7"
|
|
@@ -297,6 +297,22 @@ class Voyager:
|
|
|
297
297
|
else:
|
|
298
298
|
return tags, routes, links
|
|
299
299
|
|
|
300
|
+
def calculate_filtered_tag_and_route(self):
|
|
301
|
+
_tags, _routes, _, _ = filter_graph(
|
|
302
|
+
schema=self.schema,
|
|
303
|
+
schema_field=self.schema_field,
|
|
304
|
+
tags=self.tags,
|
|
305
|
+
routes=self.routes,
|
|
306
|
+
nodes=self.nodes,
|
|
307
|
+
links=self.links,
|
|
308
|
+
node_set=self.node_set,
|
|
309
|
+
)
|
|
310
|
+
# filter tag.routes based by _routes
|
|
311
|
+
route_ids = {r.id for r in _routes}
|
|
312
|
+
for t in _tags:
|
|
313
|
+
t.routes = [r for r in t.routes if r.id in route_ids]
|
|
314
|
+
return _tags
|
|
315
|
+
|
|
300
316
|
def render_dot(self):
|
|
301
317
|
_tags, _routes, _nodes, _links = filter_graph(
|
|
302
318
|
schema=self.schema,
|
|
@@ -120,24 +120,56 @@
|
|
|
120
120
|
/>
|
|
121
121
|
</div>
|
|
122
122
|
<div class="col-auto q-ml-auto">
|
|
123
|
+
</div>
|
|
124
|
+
<div class="col-auto row items-center q-gutter-sm">
|
|
125
|
+
<q-select
|
|
126
|
+
dense
|
|
127
|
+
outlined
|
|
128
|
+
use-input
|
|
129
|
+
fill-input
|
|
130
|
+
hide-selected
|
|
131
|
+
input-debounce="200"
|
|
132
|
+
v-model="store.state.search.schemaName"
|
|
133
|
+
:options="store.state.search.schemaOptions"
|
|
134
|
+
option-label="label"
|
|
135
|
+
option-value="value"
|
|
136
|
+
emit-value
|
|
137
|
+
map-options
|
|
138
|
+
style="min-width: 320px;"
|
|
139
|
+
clearable
|
|
140
|
+
label="Select schema"
|
|
141
|
+
@update:model-value="onSearchSchemaChange"
|
|
142
|
+
@filter="filterSearchSchemas"
|
|
143
|
+
@clear="resetSearch"
|
|
144
|
+
></q-select>
|
|
145
|
+
|
|
146
|
+
<q-select
|
|
147
|
+
dense
|
|
148
|
+
outlined
|
|
149
|
+
v-model="store.state.search.fieldName"
|
|
150
|
+
:disable="!store.state.search.schemaName || store.state.search.fieldOptions.length===0"
|
|
151
|
+
:options="store.state.search.fieldOptions"
|
|
152
|
+
style="min-width: 180px"
|
|
153
|
+
clearable
|
|
154
|
+
label="Select field (optional)"
|
|
155
|
+
></q-select>
|
|
123
156
|
<q-btn
|
|
124
157
|
outline
|
|
125
|
-
|
|
126
|
-
title="may be very slow"
|
|
127
|
-
icon="border_all"
|
|
158
|
+
icon="search"
|
|
128
159
|
flat
|
|
129
|
-
class="q-mr-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
160
|
+
class="q-mr-none"
|
|
161
|
+
:disable="!store.state.search.schemaName"
|
|
162
|
+
:loading="store.state.generating"
|
|
163
|
+
@click="onSearch"
|
|
164
|
+
></q-btn>
|
|
134
165
|
<q-btn
|
|
135
166
|
outline
|
|
136
|
-
|
|
167
|
+
@click="onReset"
|
|
168
|
+
dense
|
|
169
|
+
title="full graph"
|
|
170
|
+
icon="border_all"
|
|
137
171
|
flat
|
|
138
|
-
|
|
139
|
-
class="q-mr-md"
|
|
140
|
-
@click="showSearchDialog()"
|
|
172
|
+
class="q-mr-sm"
|
|
141
173
|
/>
|
|
142
174
|
</div>
|
|
143
175
|
<div class="col-auto">
|
|
@@ -164,7 +196,7 @@
|
|
|
164
196
|
double click node to view details.
|
|
165
197
|
</li>
|
|
166
198
|
<li>
|
|
167
|
-
shift + click to
|
|
199
|
+
shift + click to search the schema and highlight related nodes.
|
|
168
200
|
</li>
|
|
169
201
|
</ul>
|
|
170
202
|
</div>
|
|
@@ -183,7 +215,6 @@
|
|
|
183
215
|
bordered
|
|
184
216
|
overlay
|
|
185
217
|
>
|
|
186
|
-
<!-- 可拖拽的调整栏 -->
|
|
187
218
|
<div
|
|
188
219
|
@mousedown="startDragDrawer"
|
|
189
220
|
style="
|
|
@@ -239,7 +270,7 @@
|
|
|
239
270
|
v-for="tag in store.state.leftPanel.tags"
|
|
240
271
|
:key="tag.name"
|
|
241
272
|
expand-separator
|
|
242
|
-
:model-value="store.state.leftPanel._tag === tag.name"
|
|
273
|
+
:model-value="store.state.leftPanel._tag === tag.name || store.state.search.mode"
|
|
243
274
|
@update:model-value="(val) => toggleTag(tag.name, val)"
|
|
244
275
|
:header-class="store.state.leftPanel.tag === tag.name ? 'text-primary text-bold' : ''"
|
|
245
276
|
content-class="q-pa-none"
|
|
@@ -299,7 +330,7 @@
|
|
|
299
330
|
<div style="position: relative; width: 100%; height: 100%;">
|
|
300
331
|
<div id="graph" class="adjust-fit"></div>
|
|
301
332
|
<div style="position: absolute; left: 8px; top: 8px; z-index: 10; background: rgba(255,255,255,0.85); border-radius: 4px; padding: 2px 8px;">
|
|
302
|
-
<div class="q-mt-sm">
|
|
333
|
+
<div class="q-mt-sm" v-if="store.state.modeControl.briefModeEnabled && store.state.search.mode === false">
|
|
303
334
|
<q-toggle
|
|
304
335
|
v-if="store.state.modeControl.briefModeEnabled"
|
|
305
336
|
dense
|
|
@@ -309,7 +340,7 @@
|
|
|
309
340
|
title="skip middle classes, config module_prefix to enable it"
|
|
310
341
|
/>
|
|
311
342
|
</div>
|
|
312
|
-
<div class="q-mt-sm">
|
|
343
|
+
<div class="q-mt-sm" v-if="store.state.modeControl.briefModeEnabled && store.state.search.mode === false">
|
|
313
344
|
<q-toggle
|
|
314
345
|
v-model="store.state.filter.hidePrimitiveRoute"
|
|
315
346
|
@update:model-value="(val) => toggleHidePrimitiveRoute(val)"
|
|
@@ -327,16 +358,6 @@
|
|
|
327
358
|
title="show module cluster"
|
|
328
359
|
/>
|
|
329
360
|
</div>
|
|
330
|
-
<div class="q-mt-sm">
|
|
331
|
-
<q-toggle
|
|
332
|
-
v-model="store.state.modeControl.focus"
|
|
333
|
-
v-show="store.state.schemaDetail.schemaCodeName"
|
|
334
|
-
@update:model-value="val => onFocusChange(val)"
|
|
335
|
-
label="Focus"
|
|
336
|
-
dense
|
|
337
|
-
title="pick a schema and toggle focus on to display related nodes only"
|
|
338
|
-
/>
|
|
339
|
-
</div>
|
|
340
361
|
</div>
|
|
341
362
|
</template>
|
|
342
363
|
</q-splitter>
|
|
@@ -6,6 +6,9 @@ const state = reactive({
|
|
|
6
6
|
},
|
|
7
7
|
|
|
8
8
|
version: '',
|
|
9
|
+
config: {
|
|
10
|
+
initial_page_policy: 'first'
|
|
11
|
+
},
|
|
9
12
|
|
|
10
13
|
swagger: {
|
|
11
14
|
url: ''
|
|
@@ -38,13 +41,14 @@ const state = reactive({
|
|
|
38
41
|
routeItems: []
|
|
39
42
|
},
|
|
40
43
|
|
|
41
|
-
leftPanelFiltered: {
|
|
42
|
-
|
|
43
|
-
},
|
|
44
44
|
|
|
45
45
|
// schema options, schema, fields
|
|
46
46
|
search: {
|
|
47
|
-
|
|
47
|
+
mode: false,
|
|
48
|
+
schemaName: null,
|
|
49
|
+
fieldName: null,
|
|
50
|
+
schemaOptions: [],
|
|
51
|
+
fieldOptions: [],
|
|
48
52
|
},
|
|
49
53
|
|
|
50
54
|
|
|
@@ -1,16 +1,70 @@
|
|
|
1
|
-
import SchemaFieldFilter from "./component/schema-field-filter.js";
|
|
2
1
|
import SchemaCodeDisplay from "./component/schema-code-display.js";
|
|
3
2
|
import RouteCodeDisplay from "./component/route-code-display.js";
|
|
4
|
-
import Demo from
|
|
3
|
+
import Demo from "./component/demo.js";
|
|
5
4
|
import RenderGraph from "./component/render-graph.js";
|
|
6
5
|
import { GraphUI } from "./graph-ui.js";
|
|
7
|
-
import { store } from
|
|
6
|
+
import { store } from "./store.js";
|
|
8
7
|
|
|
9
|
-
const { createApp, onMounted, ref } = window.Vue;
|
|
8
|
+
const { createApp, onMounted, ref, watch } = window.Vue;
|
|
10
9
|
|
|
11
10
|
const app = createApp({
|
|
12
11
|
setup() {
|
|
13
12
|
let graphUI = null;
|
|
13
|
+
const allSchemaOptions = ref([]);
|
|
14
|
+
|
|
15
|
+
const NBSP = String.fromCharCode(160);
|
|
16
|
+
const formatSchemaLabel = (name, id) =>
|
|
17
|
+
`${name}${NBSP}${NBSP}${NBSP}-${NBSP}${NBSP}${NBSP}${id}`;
|
|
18
|
+
|
|
19
|
+
function rebuildSchemaOptions() {
|
|
20
|
+
const dict = store.state.graph.schemaMap || {};
|
|
21
|
+
const opts = Object.values(dict).map((s) => ({
|
|
22
|
+
label: formatSchemaLabel(s.name, s.id),
|
|
23
|
+
value: s.id,
|
|
24
|
+
}));
|
|
25
|
+
allSchemaOptions.value = opts;
|
|
26
|
+
store.state.search.schemaOptions = opts.slice();
|
|
27
|
+
populateFieldOptions(store.state.search.schemaName);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function populateFieldOptions(schemaId) {
|
|
31
|
+
if (!schemaId) {
|
|
32
|
+
store.state.search.fieldOptions = [];
|
|
33
|
+
store.state.search.fieldName = null;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const schema = store.state.graph.schemaMap?.[schemaId];
|
|
37
|
+
if (!schema) {
|
|
38
|
+
store.state.search.fieldOptions = [];
|
|
39
|
+
store.state.search.fieldName = null;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const fields = Array.isArray(schema.fields)
|
|
43
|
+
? schema.fields.map((f) => f.name)
|
|
44
|
+
: [];
|
|
45
|
+
store.state.search.fieldOptions = fields;
|
|
46
|
+
if (!fields.includes(store.state.search.fieldName)) {
|
|
47
|
+
store.state.search.fieldName = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function filterSearchSchemas(val, update) {
|
|
52
|
+
const needle = (val || "").toLowerCase();
|
|
53
|
+
update(() => {
|
|
54
|
+
if (!needle) {
|
|
55
|
+
store.state.search.schemaOptions = allSchemaOptions.value.slice();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
store.state.search.schemaOptions = allSchemaOptions.value.filter((option) =>
|
|
59
|
+
option.label.toLowerCase().includes(needle)
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function onSearchSchemaChange(val) {
|
|
65
|
+
store.state.search.schemaName = val;
|
|
66
|
+
store.state.search.mode = false;
|
|
67
|
+
}
|
|
14
68
|
|
|
15
69
|
function readQuerySelection() {
|
|
16
70
|
if (typeof window === "undefined") {
|
|
@@ -55,7 +109,10 @@ const app = createApp({
|
|
|
55
109
|
|
|
56
110
|
function applySelectionFromQuery(selection) {
|
|
57
111
|
let applied = false;
|
|
58
|
-
if (
|
|
112
|
+
if (
|
|
113
|
+
selection.tag &&
|
|
114
|
+
store.state.leftPanel.tags.some((tag) => tag.name === selection.tag)
|
|
115
|
+
) {
|
|
59
116
|
store.state.leftPanel.tag = selection.tag;
|
|
60
117
|
store.state.leftPanel._tag = selection.tag;
|
|
61
118
|
applied = true;
|
|
@@ -72,6 +129,48 @@ const app = createApp({
|
|
|
72
129
|
return applied;
|
|
73
130
|
}
|
|
74
131
|
|
|
132
|
+
async function resetSearch() {
|
|
133
|
+
store.state.search.mode = false;
|
|
134
|
+
store.state.leftPanel.tag = null;
|
|
135
|
+
store.state.leftPanel._tag = null;
|
|
136
|
+
store.state.leftPanel.routeId = null;
|
|
137
|
+
await loadSearchedTags();
|
|
138
|
+
renderBasedOnInitialPolicy()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function onSearch() {
|
|
142
|
+
store.state.search.mode = true;
|
|
143
|
+
store.state.leftPanel.tag = null;
|
|
144
|
+
store.state.leftPanel._tag = null;
|
|
145
|
+
store.state.leftPanel.routeId = null;
|
|
146
|
+
await loadSearchedTags();
|
|
147
|
+
await onGenerate();
|
|
148
|
+
}
|
|
149
|
+
async function loadSearchedTags() {
|
|
150
|
+
try {
|
|
151
|
+
const payload = {
|
|
152
|
+
schema_name: store.state.search.schemaName,
|
|
153
|
+
schema_field: store.state.search.fieldName || null,
|
|
154
|
+
show_fields: store.state.filter.showFields,
|
|
155
|
+
brief: store.state.filter.brief,
|
|
156
|
+
hide_primitive_route: store.state.filter.hidePrimitiveRoute,
|
|
157
|
+
show_module: store.state.filter.showModule,
|
|
158
|
+
};
|
|
159
|
+
const res = await fetch("dot-search", {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: { "Content-Type": "application/json" },
|
|
162
|
+
body: JSON.stringify(payload),
|
|
163
|
+
});
|
|
164
|
+
if (res.ok) {
|
|
165
|
+
const data = await res.json();
|
|
166
|
+
const tags = Array.isArray(data.tags) ? data.tags : [];
|
|
167
|
+
store.state.leftPanel.tags = tags;
|
|
168
|
+
}
|
|
169
|
+
} catch (err) {
|
|
170
|
+
console.error("dot-search failed", err);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
75
174
|
async function loadInitial() {
|
|
76
175
|
store.state.initializing = true;
|
|
77
176
|
try {
|
|
@@ -81,10 +180,8 @@ const app = createApp({
|
|
|
81
180
|
|
|
82
181
|
const schemasArr = Array.isArray(data.schemas) ? data.schemas : [];
|
|
83
182
|
// Build dict keyed by id for faster lookups and simpler prop passing
|
|
84
|
-
const schemaMap = Object.fromEntries(
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
store.state.graph.schemaMap = schemaMap
|
|
183
|
+
const schemaMap = Object.fromEntries(schemasArr.map((s) => [s.id, s]));
|
|
184
|
+
store.state.graph.schemaMap = schemaMap;
|
|
88
185
|
store.state.graph.schemaKeys = new Set(Object.keys(schemaMap));
|
|
89
186
|
store.state.graph.routeItems = data.tags
|
|
90
187
|
.map((t) => t.routes)
|
|
@@ -93,9 +190,12 @@ const app = createApp({
|
|
|
93
190
|
acc[r.id] = r;
|
|
94
191
|
return acc;
|
|
95
192
|
}, {});
|
|
96
|
-
store.state.modeControl.briefModeEnabled =
|
|
193
|
+
store.state.modeControl.briefModeEnabled =
|
|
194
|
+
data.enable_brief_mode || false;
|
|
97
195
|
store.state.version = data.version || "";
|
|
98
|
-
store.state.swagger.url = data.swagger_url || null
|
|
196
|
+
store.state.swagger.url = data.swagger_url || null;
|
|
197
|
+
|
|
198
|
+
rebuildSchemaOptions();
|
|
99
199
|
|
|
100
200
|
const querySelection = readQuerySelection();
|
|
101
201
|
const restoredFromQuery = applySelectionFromQuery(querySelection);
|
|
@@ -104,19 +204,8 @@ const app = createApp({
|
|
|
104
204
|
onGenerate();
|
|
105
205
|
return;
|
|
106
206
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
case "full":
|
|
110
|
-
onGenerate()
|
|
111
|
-
return
|
|
112
|
-
case "empty":
|
|
113
|
-
return
|
|
114
|
-
case "first":
|
|
115
|
-
store.state.leftPanel.tag = store.state.leftPanel.tags.length > 0 ? store.state.leftPanel.tags[0].name : null;
|
|
116
|
-
store.state.leftPanel._tag = store.state.leftPanel.tag;
|
|
117
|
-
onGenerate();
|
|
118
|
-
return
|
|
119
|
-
}
|
|
207
|
+
store.state.config.initial_page_policy = data.initial_page_policy
|
|
208
|
+
renderBasedOnInitialPolicy()
|
|
120
209
|
|
|
121
210
|
// default route options placeholder
|
|
122
211
|
} catch (e) {
|
|
@@ -126,28 +215,40 @@ const app = createApp({
|
|
|
126
215
|
}
|
|
127
216
|
}
|
|
128
217
|
|
|
129
|
-
async function
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
218
|
+
async function renderBasedOnInitialPolicy() {
|
|
219
|
+
switch (store.state.config.initial_page_policy) {
|
|
220
|
+
case "full":
|
|
221
|
+
onGenerate();
|
|
222
|
+
return;
|
|
223
|
+
case "empty":
|
|
224
|
+
return;
|
|
225
|
+
case "first":
|
|
226
|
+
store.state.leftPanel.tag =
|
|
227
|
+
store.state.leftPanel.tags.length > 0
|
|
228
|
+
? store.state.leftPanel.tags[0].name
|
|
229
|
+
: null;
|
|
230
|
+
store.state.leftPanel._tag = store.state.leftPanel.tag;
|
|
231
|
+
onGenerate();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
139
234
|
}
|
|
140
235
|
|
|
141
236
|
async function onGenerate(resetZoom = true) {
|
|
142
|
-
const
|
|
237
|
+
const activeSchema = store.state.search.mode
|
|
238
|
+
? store.state.search.schemaName
|
|
239
|
+
: null;
|
|
240
|
+
const activeField = store.state.search.mode
|
|
241
|
+
? store.state.search.fieldName
|
|
242
|
+
: null;
|
|
143
243
|
store.state.generating = true;
|
|
144
244
|
try {
|
|
145
245
|
const payload = {
|
|
146
246
|
tags: store.state.leftPanel.tag ? [store.state.leftPanel.tag] : null,
|
|
147
|
-
schema_name:
|
|
247
|
+
schema_name: activeSchema || null,
|
|
248
|
+
schema_field: activeField || null,
|
|
148
249
|
route_name: store.state.leftPanel.routeId || null,
|
|
149
250
|
show_fields: store.state.filter.showFields,
|
|
150
|
-
brief: store.state.
|
|
251
|
+
brief: store.state.filter.brief,
|
|
151
252
|
hide_primitive_route: store.state.filter.hidePrimitiveRoute,
|
|
152
253
|
show_module: store.state.filter.showModule,
|
|
153
254
|
};
|
|
@@ -163,9 +264,9 @@ const app = createApp({
|
|
|
163
264
|
graphUI = new GraphUI("#graph", {
|
|
164
265
|
onSchemaShiftClick: (id) => {
|
|
165
266
|
if (store.state.graph.schemaKeys.has(id)) {
|
|
166
|
-
|
|
167
|
-
store.state.
|
|
168
|
-
|
|
267
|
+
store.state.search.mode = true;
|
|
268
|
+
store.state.search.schemaName = id;
|
|
269
|
+
onSearch();
|
|
169
270
|
}
|
|
170
271
|
},
|
|
171
272
|
onSchemaClick: (id) => {
|
|
@@ -192,14 +293,9 @@ const app = createApp({
|
|
|
192
293
|
}
|
|
193
294
|
}
|
|
194
295
|
|
|
195
|
-
function showSearchDialog() {
|
|
196
|
-
store.state.searchDialog.show = true;
|
|
197
|
-
store.state.searchDialog.schema = null;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
296
|
function resetDetailPanels() {
|
|
201
297
|
store.state.rightDrawer.drawer = false;
|
|
202
|
-
store.state.routeDetail.show = false
|
|
298
|
+
store.state.routeDetail.show = false;
|
|
203
299
|
store.state.schemaDetail.schemaCodeName = "";
|
|
204
300
|
}
|
|
205
301
|
|
|
@@ -210,11 +306,14 @@ const app = createApp({
|
|
|
210
306
|
|
|
211
307
|
store.state.graph.schemaId = null;
|
|
212
308
|
|
|
213
|
-
|
|
214
|
-
store.state.
|
|
309
|
+
store.state.search.mode = false;
|
|
310
|
+
store.state.search.schemaName = null;
|
|
311
|
+
store.state.search.fieldName = null;
|
|
312
|
+
store.state.search.fieldOptions = [];
|
|
313
|
+
store.state.search.schemaOptions = allSchemaOptions.value.slice();
|
|
314
|
+
|
|
215
315
|
store.state.schemaDetail.schemaCodeName = "";
|
|
216
|
-
|
|
217
|
-
syncSelectionToUrl();
|
|
316
|
+
resetSearch()
|
|
218
317
|
}
|
|
219
318
|
|
|
220
319
|
function toggleTag(tagName, expanded = null) {
|
|
@@ -223,7 +322,6 @@ const app = createApp({
|
|
|
223
322
|
store.state.leftPanel.tag = tagName;
|
|
224
323
|
store.state.leftPanel.routeId = "";
|
|
225
324
|
|
|
226
|
-
store.state.modeControl.focus = false;
|
|
227
325
|
store.state.schemaDetail.schemaCodeName = "";
|
|
228
326
|
onGenerate();
|
|
229
327
|
} else {
|
|
@@ -231,7 +329,7 @@ const app = createApp({
|
|
|
231
329
|
}
|
|
232
330
|
|
|
233
331
|
store.state.rightDrawer.drawer = false;
|
|
234
|
-
store.state.routeDetail.show = false
|
|
332
|
+
store.state.routeDetail.show = false;
|
|
235
333
|
syncSelectionToUrl();
|
|
236
334
|
}
|
|
237
335
|
|
|
@@ -242,8 +340,7 @@ const app = createApp({
|
|
|
242
340
|
store.state.leftPanel.routeId = routeId;
|
|
243
341
|
}
|
|
244
342
|
store.state.rightDrawer.drawer = false;
|
|
245
|
-
store.state.routeDetail.show = false
|
|
246
|
-
store.state.modeControl.focus = false;
|
|
343
|
+
store.state.routeDetail.show = false;
|
|
247
344
|
store.state.schemaDetail.schemaCodeName = "";
|
|
248
345
|
onGenerate();
|
|
249
346
|
syncSelectionToUrl();
|
|
@@ -251,7 +348,7 @@ const app = createApp({
|
|
|
251
348
|
|
|
252
349
|
function toggleShowModule(val) {
|
|
253
350
|
store.state.filter.showModule = val;
|
|
254
|
-
onGenerate()
|
|
351
|
+
onGenerate();
|
|
255
352
|
}
|
|
256
353
|
|
|
257
354
|
function toggleShowField(field) {
|
|
@@ -260,7 +357,7 @@ const app = createApp({
|
|
|
260
357
|
}
|
|
261
358
|
|
|
262
359
|
function toggleBrief(val) {
|
|
263
|
-
store.state.
|
|
360
|
+
store.state.filter.brief = val;
|
|
264
361
|
onGenerate();
|
|
265
362
|
}
|
|
266
363
|
|
|
@@ -293,24 +390,45 @@ const app = createApp({
|
|
|
293
390
|
e.preventDefault();
|
|
294
391
|
}
|
|
295
392
|
|
|
393
|
+
watch(
|
|
394
|
+
() => store.state.graph.schemaMap,
|
|
395
|
+
() => {
|
|
396
|
+
rebuildSchemaOptions();
|
|
397
|
+
},
|
|
398
|
+
{ deep: false }
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
watch(
|
|
402
|
+
() => store.state.search.schemaName,
|
|
403
|
+
(schemaId) => {
|
|
404
|
+
store.state.search.schemaOptions = allSchemaOptions.value.slice();
|
|
405
|
+
populateFieldOptions(schemaId);
|
|
406
|
+
if (!schemaId) {
|
|
407
|
+
store.state.search.mode = false;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
);
|
|
411
|
+
|
|
296
412
|
onMounted(async () => {
|
|
297
|
-
document.body.classList.remove("app-loading")
|
|
413
|
+
document.body.classList.remove("app-loading");
|
|
298
414
|
await loadInitial();
|
|
299
415
|
// Reveal app content only after initial JS/data is ready
|
|
300
416
|
});
|
|
301
417
|
|
|
302
418
|
return {
|
|
303
419
|
store,
|
|
420
|
+
onSearch,
|
|
421
|
+
resetSearch,
|
|
422
|
+
filterSearchSchemas,
|
|
423
|
+
onSearchSchemaChange,
|
|
304
424
|
toggleTag,
|
|
305
425
|
toggleBrief,
|
|
306
426
|
toggleHidePrimitiveRoute,
|
|
307
427
|
selectRoute,
|
|
308
428
|
onGenerate,
|
|
309
429
|
onReset,
|
|
310
|
-
showSearchDialog,
|
|
311
430
|
toggleShowField,
|
|
312
431
|
startDragDrawer,
|
|
313
|
-
onFocusChange,
|
|
314
432
|
toggleShowModule,
|
|
315
433
|
};
|
|
316
434
|
},
|
|
@@ -323,10 +441,9 @@ if (window.Quasar && typeof window.Quasar.setCssVar === "function") {
|
|
|
323
441
|
window.Quasar.setCssVar("primary", "#009485");
|
|
324
442
|
}
|
|
325
443
|
|
|
326
|
-
app.component("schema-
|
|
327
|
-
app.component("
|
|
328
|
-
app.component("
|
|
329
|
-
app.component("
|
|
330
|
-
app.component('demo-component', Demo)
|
|
444
|
+
app.component("schema-code-display", SchemaCodeDisplay); // double click to see node details
|
|
445
|
+
app.component("route-code-display", RouteCodeDisplay); // double click to see route details
|
|
446
|
+
app.component("render-graph", RenderGraph); // for debug, render pasted dot content
|
|
447
|
+
app.component("demo-component", Demo);
|
|
331
448
|
|
|
332
449
|
app.mount("#q-app");
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { GraphUI } from "../graph-ui.js";
|
|
2
|
-
const { defineComponent, reactive, ref, onMounted, nextTick, watch } =
|
|
3
|
-
window.Vue;
|
|
4
|
-
|
|
5
|
-
// SchemaFieldFilter component
|
|
6
|
-
// Features:
|
|
7
|
-
// - Fetch initial schemas list (GET /dot) and build schema options
|
|
8
|
-
// - Second selector lists fields of the chosen schema
|
|
9
|
-
// - Query button disabled until a schema is selected
|
|
10
|
-
// - On query: POST /dot with schema_name + optional schema_field; render returned DOT in #graph-schema-field
|
|
11
|
-
// - Uses GraphUI once and re-renders
|
|
12
|
-
// - Emits 'queried' event after successful render (payload: { schemaName, fieldName })
|
|
13
|
-
export default defineComponent({
|
|
14
|
-
name: "SchemaFieldFilter",
|
|
15
|
-
props: {
|
|
16
|
-
schemaName: { type: String, default: null }, // external injection triggers auto-query
|
|
17
|
-
schemas: { type: Object, default: () => ({}) },
|
|
18
|
-
},
|
|
19
|
-
emits: ["queried", "close"],
|
|
20
|
-
setup(props, { emit }) {
|
|
21
|
-
const state = reactive({
|
|
22
|
-
loadingSchemas: false,
|
|
23
|
-
querying: false,
|
|
24
|
-
schemas: [], // [{ name, fullname, fields: [{name,...}] }]
|
|
25
|
-
schemaOptions: [], // [{ label, value }]
|
|
26
|
-
fieldOptions: [], // [ field.name ]
|
|
27
|
-
schemaFullname: null,
|
|
28
|
-
fieldName: null,
|
|
29
|
-
error: null,
|
|
30
|
-
showFields: "object",
|
|
31
|
-
showFieldOptions: [
|
|
32
|
-
{ label: "No fields", value: "single" },
|
|
33
|
-
{ label: "Object fields", value: "object" },
|
|
34
|
-
{ label: "All fields", value: "all" },
|
|
35
|
-
],
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
let graphInstance = null;
|
|
39
|
-
let lastAppliedExternal = null;
|
|
40
|
-
|
|
41
|
-
async function loadSchemas() {
|
|
42
|
-
// Use externally provided props.schemas dict directly; no network call.
|
|
43
|
-
state.error = null;
|
|
44
|
-
const dict =
|
|
45
|
-
props.schemas && typeof props.schemas === "object" ? props.schemas : {};
|
|
46
|
-
// Flatten to array for local operations
|
|
47
|
-
state.schemas = Object.values(dict);
|
|
48
|
-
state.schemaOptions = state.schemas.map((s) => ({
|
|
49
|
-
label: `${s.name} - ${s.id}`,
|
|
50
|
-
value: s.id,
|
|
51
|
-
}));
|
|
52
|
-
// Maintain compatibility: loadingSchemas flag toggled quickly (no async work)
|
|
53
|
-
state.loadingSchemas = false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function onFilterSchemas(val, update) {
|
|
57
|
-
const needle = (val || "").toLowerCase();
|
|
58
|
-
update(() => {
|
|
59
|
-
let opts = state.schemas.map((s) => ({
|
|
60
|
-
label: `${s.name} - ${s.id}`,
|
|
61
|
-
value: s.id,
|
|
62
|
-
}));
|
|
63
|
-
if (needle) {
|
|
64
|
-
opts = opts.filter((o) => o.label.toLowerCase().includes(needle));
|
|
65
|
-
}
|
|
66
|
-
state.schemaOptions = opts;
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function onSchemaChange(val) {
|
|
71
|
-
state.schemaFullname = val;
|
|
72
|
-
state.fieldName = null;
|
|
73
|
-
const schema = state.schemas.find((s) => s.id === val);
|
|
74
|
-
state.fieldOptions = schema ? schema.fields.map((f) => f.name) : [];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function onQuery() {
|
|
78
|
-
if (!state.schemaFullname) return;
|
|
79
|
-
state.querying = true;
|
|
80
|
-
state.error = null;
|
|
81
|
-
try {
|
|
82
|
-
const payload = {
|
|
83
|
-
schema_name: state.schemaFullname,
|
|
84
|
-
schema_field: state.fieldName || null,
|
|
85
|
-
show_fields: state.showFields,
|
|
86
|
-
};
|
|
87
|
-
const res = await fetch("dot", {
|
|
88
|
-
method: "POST",
|
|
89
|
-
headers: { "Content-Type": "application/json" },
|
|
90
|
-
body: JSON.stringify(payload),
|
|
91
|
-
});
|
|
92
|
-
const dotText = await res.text();
|
|
93
|
-
if (!graphInstance) {
|
|
94
|
-
graphInstance = new GraphUI("#graph-schema-field");
|
|
95
|
-
}
|
|
96
|
-
await graphInstance.render(dotText);
|
|
97
|
-
emit("queried", {
|
|
98
|
-
schemaName: state.schemaFullname,
|
|
99
|
-
fieldName: state.fieldName,
|
|
100
|
-
});
|
|
101
|
-
} catch (e) {
|
|
102
|
-
state.error = "Query failed";
|
|
103
|
-
console.error("SchemaFieldFilter query failed", e);
|
|
104
|
-
} finally {
|
|
105
|
-
state.querying = false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function applyExternalSchema(name) {
|
|
110
|
-
if (!name || !state.schemas.length) return;
|
|
111
|
-
if (lastAppliedExternal === name) return; // avoid duplicate
|
|
112
|
-
const schema = state.schemas.find((s) => s.id === name);
|
|
113
|
-
if (!schema) return;
|
|
114
|
-
state.schemaFullname = schema.id;
|
|
115
|
-
state.fieldOptions = schema.fields.map((f) => f.name);
|
|
116
|
-
state.fieldName = null; // reset field for external injection
|
|
117
|
-
lastAppliedExternal = name;
|
|
118
|
-
// auto query
|
|
119
|
-
onQuery();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
onMounted(async () => {
|
|
123
|
-
await nextTick();
|
|
124
|
-
await loadSchemas();
|
|
125
|
-
if (props.schemaName) {
|
|
126
|
-
applyExternalSchema(props.schemaName);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
function close() {
|
|
131
|
-
emit("close");
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return { state, onSchemaChange, onQuery, close, onFilterSchemas };
|
|
135
|
-
},
|
|
136
|
-
template: `
|
|
137
|
-
<div style="height:100%; position:relative; background:#fff;">
|
|
138
|
-
<div style="position:absolute; top:8px; left:8px; z-index:10; background:rgba(255,255,255,0.95); padding:8px 10px; border-radius:4px; box-shadow:0 1px 3px rgba(0,0,0,0.15);" class="q-gutter-sm row items-center">
|
|
139
|
-
<q-select
|
|
140
|
-
dense outlined use-input input-debounce="0"
|
|
141
|
-
v-model="state.schemaFullname"
|
|
142
|
-
:options="state.schemaOptions"
|
|
143
|
-
option-label="label"
|
|
144
|
-
option-value="value"
|
|
145
|
-
emit-value
|
|
146
|
-
map-options
|
|
147
|
-
:loading="state.loadingSchemas"
|
|
148
|
-
style="min-width:220px"
|
|
149
|
-
clearable
|
|
150
|
-
label="Select schema"
|
|
151
|
-
@update:model-value="onSchemaChange"
|
|
152
|
-
@filter="onFilterSchemas"
|
|
153
|
-
/>
|
|
154
|
-
<q-select
|
|
155
|
-
dense outlined
|
|
156
|
-
v-model="state.fieldName"
|
|
157
|
-
:disable="!state.schemaFullname || state.fieldOptions.length===0"
|
|
158
|
-
:options="state.fieldOptions"
|
|
159
|
-
style="min-width:180px"
|
|
160
|
-
clearable
|
|
161
|
-
label="Select field (optional)"
|
|
162
|
-
/>
|
|
163
|
-
<q-option-group
|
|
164
|
-
v-model="state.showFields"
|
|
165
|
-
:options="state.showFieldOptions"
|
|
166
|
-
type="radio"
|
|
167
|
-
inline
|
|
168
|
-
dense
|
|
169
|
-
color="primary"
|
|
170
|
-
style="min-width:260px"
|
|
171
|
-
/>
|
|
172
|
-
<q-btn
|
|
173
|
-
class="q-ml-md"
|
|
174
|
-
icon="search"
|
|
175
|
-
label="Search"
|
|
176
|
-
outline
|
|
177
|
-
:disable="!state.schemaFullname"
|
|
178
|
-
:loading="state.querying"
|
|
179
|
-
@click="onQuery" />
|
|
180
|
-
<q-btn
|
|
181
|
-
flat dense round icon="close"
|
|
182
|
-
aria-label="Close"
|
|
183
|
-
@click="close"
|
|
184
|
-
/>
|
|
185
|
-
</div>
|
|
186
|
-
<div v-if="state.error" style="position:absolute; top:52px; left:8px; z-index:10; color:#c10015; font-size:12px;">{{ state.error }}</div>
|
|
187
|
-
<div id="graph-schema-field" style="width:100%; height:100%; overflow:auto; background:#fafafa"></div>
|
|
188
|
-
</div>
|
|
189
|
-
`,
|
|
190
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/component/render-graph.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/apple-touch-icon.png
RENAMED
|
File without changes
|
{fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/favicon-16x16.png
RENAMED
|
File without changes
|
{fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/favicon-32x32.png
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_voyager-0.12.6 → fastapi_voyager-0.12.7}/src/fastapi_voyager/web/icon/site.webmanifest
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|