Skip to content

app

plantdb.client.sync_app.app Link

Dash UI for FSDBSync - PlantDB Database Synchronization Tool

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 exampleLink

Local Path to Local PathLink
>>> 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 APILink
>>> 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 Link

create_database_config_card(title, db_side)

Create a card for database configuration

Source code in plantdb/client/sync_app/app.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 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
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 Link

create_http_inputs(db_side)

Create inputs for HTTP database configuration

Source code in plantdb/client/sync_app/app.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
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 Link

create_local_inputs(db_side)

Create inputs for local database configuration

Source code in plantdb/client/sync_app/app.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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 Link

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
217
218
219
220
221
222
223
224
225
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
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 Link

create_ssh_inputs(db_side)

Create inputs for SSH database configuration

Source code in plantdb/client/sync_app/app.py
146
147
148
149
150
151
152
153
154
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
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 Link

get_scans_for_db(config)

Get list of scans for a database configuration

Source code in plantdb/client/sync_app/app.py
559
560
561
562
563
564
565
566
567
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
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()
            return db.list_scans(owner_only=False)
        elif config["type"] == "http":
            from plantdb.client.rest_api import refresh_url
            from plantdb.client.rest_api 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 list_scan_names(**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 []