This module provides a web-based user interface for the FSDBSync class,
allowing users to easily configure and manage database synchronization
between different database types (local, SSH, HTTP).
Usage example
Local Path to Local Path
>>> from plantdb.commons.test_database import test_database
>>> # Create a test source database
>>> db_source = test_database()
>>> # Create a test target database
>>> db_target = test_database(dataset=None)
>>> # ---------------------------------------------------------------------
>>> # Synchronize the database using the WebUI
>>> # Use the path printed out during the test FSDB initialization
>>> # ---------------------------------------------------------------------
>>> db_source.disconnect() # Remove the test database
>>> db_target.disconnect() # Remove the test database
Local Path to HTTP REST API
>>> from plantdb.server.test_rest_api import TestRestApiServer
>>> from plantdb.commons.test_database import test_database
>>> # Create a test source database
>>> db_source = test_database("all")
>>> # Create a test target database
>>> db_target = TestRestApiServer(test=True, empty=True)
>>> db_target.start()
>>> # ---------------------------------------------------------------------
>>> # Synchronize the database using the WebUI
>>> # Use the path and URL printed out during the test FSDB initialization
>>> # ---------------------------------------------------------------------
>>> db_target.stop()
create_database_config_card
create_database_config_card(title, db_side)
Create a card for database configuration
Source code in plantdb/client/sync_app/app.py
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 | def create_database_config_card(title, db_side):
"""Create a card for database configuration"""
return dbc.Card([
dbc.CardHeader(html.H4([html.I(className="bi bi-database me-2"), title], className="mb-0")),
dbc.CardBody([
# Database type selection
dbc.Row([
dbc.Col([
dbc.Label([html.I(className="bi bi-hdd-network me-1"), "Database Type:"]),
dbc.Select(
id=f"{db_side}-type",
options=[
{"label": "Local Path", "value": "local"},
{"label": "SSH/SFTP", "value": "ssh"},
{"label": "HTTP REST API", "value": "http"}
],
value="local"
)
], width=12)
], className="mb-3"),
# Pre-register all possible input IDs as hidden components to avoid callback errors
html.Div([
# Source inputs
create_local_inputs(db_side),
create_ssh_inputs(db_side),
create_http_inputs(db_side),
]),
# Test connection button and status
dbc.Row([
dbc.Col([
dbc.Button([
html.I(className="bi bi-plug me-1"),
"Test Connection"
],
id=f"{db_side}-test-btn",
color="primary",
size="md",
disabled=True
),
html.Div(id=f"{db_side}-status", className="mt-2")
], width=12)
])
])
], className="mb-4")
|
create_http_inputs(db_side)
Create inputs for HTTP database configuration
Source code in plantdb/client/sync_app/app.py
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223 | def create_http_inputs(db_side): # db_side is "source" or "target"
"""Create inputs for HTTP database configuration"""
return dbc.Row([
dbc.Col([
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-link-45deg")),
dbc.Input(
id=f"{db_side}-url",
placeholder="http://api.example.com:5000",
type="text",
value=""
)
])
], width=12)
], id=f"{db_side}-http-inputs", className="mb-3", style={"display": "none"})
|
create_local_inputs(db_side)
Create inputs for local database configuration
Source code in plantdb/client/sync_app/app.py
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 | def create_local_inputs(db_side): # db_side is "source" or "target"
"""Create inputs for local database configuration"""
return dbc.Row([
dbc.Col([
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-folder2-open")),
dbc.Input(
id=f"{db_side}-path",
placeholder="/path/to/database",
type="text",
value=""
)
])
], width=12)
], id=f"{db_side}-local-inputs", className="mb-3", style={"display": "none"})
|
create_scan_list_card
create_scan_list_card(title, list_id, search_id=None)
Create a card for displaying scan lists
Source code in plantdb/client/sync_app/app.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 | def create_scan_list_card(title, list_id, search_id=None):
"""Create a card for displaying scan lists"""
search_component = []
if search_id:
search_component = [
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-search")),
dbc.Input(
id=search_id,
placeholder="Search scans...",
type="text"
),
dbc.Button([
html.I(className="bi bi-x-circle"),
" Clear"
],
id=f"{search_id}-clear",
color="secondary",
outline=True
)
], className="mb-3")
]
return dbc.Card([
dbc.CardHeader(html.H4([html.I(className="bi bi-card-list me-2"), title], className="mb-0")),
dbc.CardBody([
*search_component,
dbc.Checklist(
id=list_id,
options=[],
value=[],
inline=False,
switch=True
),
html.Div([
html.I(className="bi bi-info-circle me-1"),
html.Span(id=f"{list_id}-info")
], className="mt-2 text-muted small")
])
])
|
create_ssh_inputs(db_side)
Create inputs for SSH database configuration
Source code in plantdb/client/sync_app/app.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 | def create_ssh_inputs(db_side): # db_side is "source" or "target"
"""Create inputs for SSH database configuration"""
return html.Div([
dbc.Row([
dbc.Col([
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-globe")),
dbc.Input(
id=f"{db_side}-hostname",
placeholder="server.example.com",
type="text",
value=""
)
])
], width=6),
dbc.Col([
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-folder2")),
dbc.Input(
id=f"{db_side}-ssh-path",
placeholder="/path/to/database",
type="text",
value=""
)
])
], width=6)
], className="mb-3"),
dbc.Row([
dbc.Col([
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-person")),
dbc.Input(
id=f"{db_side}-username",
placeholder="username",
type="text",
value=""
)
])
], width=6),
dbc.Col([
dbc.InputGroup([
dbc.InputGroupText(html.I(className="bi bi-key")),
dbc.Input(
id=f"{db_side}-password",
placeholder="password",
type="password",
value=""
)
])
], width=6)
], className="mb-3")
], id=f"{db_side}-ssh-inputs", style={"display": "none"})
|
get_scans_for_db
Get list of scans for a database configuration
Source code in plantdb/client/sync_app/app.py
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608 | def get_scans_for_db(config):
"""Get list of scans for a database configuration"""
def _try_refresh(url):
try:
response = make_api_request(url)
except Exception as e:
refreshed = False
else:
refreshed = response.status_code == 200
return refreshed
try:
if config["type"] == "local":
path = Path(config["spec"])
db = FSDB(path)
db.connect()
try:
return db.list_scans(owner_only=False)
finally:
db.disconnect()
elif config["type"] == "http":
from plantdb.client.rest_api import refresh_url
from plantdb.client.rest_api.requests import make_api_request
url = refresh_url(**config)
refreshed = _try_refresh(url)
n_attempts = 0
while not refreshed:
if n_attempts >= 3:
break
n_attempts += 1
time.sleep(5)
refreshed = _try_refresh(url)
return request_scan_names_list(**config)
elif config["type"] == "ssh":
# For SSH, we'll need to use the sync instance's SSH methods
# This is a simplified version - in practice you'd use the FSDBSync methods
return []
return []
except Exception:
return []
|
main
Dash UI for FSDBSync - PlantDB Database Synchronization Tool
A web-based user interface for synchronizing databases between different types (local, SSH, HTTP).
Source code in plantdb/client/sync_app/app.py
874
875
876
877
878
879
880
881
882
883
884
885
886 | @click.command(context_settings=dict(help_option_names=["-h", "--help"]))
@click.option("--port", type=int, default=8050, help="Port to run the web application on")
@click.option("--debug", is_flag=True, help="Enable debug mode")
def main(port, debug):
"""Dash UI for FSDBSync - PlantDB Database Synchronization Tool
A web-based user interface for synchronizing databases between different types (local, SSH, HTTP).
"""
# Get the logger and change the level if needed:
logger = get_logger(os.environ.get('ROMI_APP_LOGGER', __name__))
logger.setLevel(DEFAULT_LOG_LEVEL) # Using default log level for web app
app.run(host="0.0.0.0", port=port, debug=debug)
|