dsa-helpers 0.3__tar.gz → 0.3.dev0__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.
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/.gitignore +1 -3
- {dsa_helpers-0.3/dsa_helpers.egg-info → dsa_helpers-0.3.dev0}/PKG-INFO +6 -12
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers/__init__.py +2 -3
- dsa_helpers-0.3.dev0/dsa_helpers/girder_utils.py +116 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers/login.py +1 -3
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0/dsa_helpers.egg-info}/PKG-INFO +6 -12
- dsa_helpers-0.3.dev0/dsa_helpers.egg-info/SOURCES.txt +16 -0
- dsa_helpers-0.3.dev0/dsa_helpers.egg-info/requires.txt +5 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/pyproject.toml +6 -12
- dsa_helpers-0.3.dev0/requirements.txt +5 -0
- dsa_helpers-0.3/app.py +0 -14
- dsa_helpers-0.3/dsa_helpers/dash/__init__.py +0 -1
- dsa_helpers-0.3/dsa_helpers/dash/header.py +0 -141
- dsa_helpers-0.3/dsa_helpers/dash/header_callbacks.py +0 -98
- dsa_helpers-0.3/dsa_helpers/girder_utils.py +0 -321
- dsa_helpers-0.3/dsa_helpers/ml/__init__.py +0 -2
- dsa_helpers-0.3/dsa_helpers/ml/object_detection/__init__.py +0 -5
- dsa_helpers-0.3/dsa_helpers/ml/object_detection/get_pearce_roi_images.py +0 -136
- dsa_helpers-0.3/dsa_helpers/ml/object_detection/tile_image.py +0 -137
- dsa_helpers-0.3/dsa_helpers/ml/object_detection/utils.py +0 -104
- dsa_helpers-0.3/dsa_helpers/mongo_utils.py +0 -147
- dsa_helpers-0.3/dsa_helpers.egg-info/SOURCES.txt +0 -28
- dsa_helpers-0.3/dsa_helpers.egg-info/requires.txt +0 -11
- dsa_helpers-0.3/readthedocs.yaml +0 -27
- dsa_helpers-0.3/requirements.txt +0 -11
- dsa_helpers-0.3/test.ipynb +0 -268
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/LICENSE +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/README.md +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers/image_utils.py +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers/imread.py +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers/imwrite.py +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers.egg-info/dependency_links.txt +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/dsa_helpers.egg-info/top_level.txt +0 -0
- {dsa_helpers-0.3 → dsa_helpers-0.3.dev0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dsa_helpers
|
|
3
|
-
Version: 0.3
|
|
3
|
+
Version: 0.3.dev0
|
|
4
4
|
Summary: Utility functions for working with the DSA girder client.
|
|
5
5
|
Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
|
|
6
6
|
Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
|
|
@@ -11,17 +11,11 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
11
11
|
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: girder-client
|
|
15
|
-
Requires-Dist: numpy
|
|
16
|
-
Requires-Dist: setuptools
|
|
17
|
-
Requires-Dist: opencv-python
|
|
18
|
-
Requires-Dist: pandas
|
|
19
|
-
Requires-Dist: pymongo
|
|
20
|
-
Requires-Dist: pillow
|
|
21
|
-
Requires-Dist: dash
|
|
22
|
-
Requires-Dist: dash_bootstrap_components
|
|
23
|
-
Requires-Dist: shapely
|
|
24
|
-
Requires-Dist: geopandas
|
|
14
|
+
Requires-Dist: girder-client==3.2.3
|
|
15
|
+
Requires-Dist: numpy==2.0.0
|
|
16
|
+
Requires-Dist: setuptools==71.0.3
|
|
17
|
+
Requires-Dist: opencv-python==4.10.0.84
|
|
18
|
+
Requires-Dist: pandas==2.2.2
|
|
25
19
|
|
|
26
20
|
# Digital Slide Archive (DSA) Helpers
|
|
27
21
|
Digital Slide Archive Python utility library.
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Shadow imports.
|
|
2
|
+
from .login import login
|
|
2
3
|
from .imread import imread
|
|
3
4
|
from .imwrite import imwrite
|
|
4
5
|
|
|
5
6
|
# Modules that should be available.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__all__ = ["girder_utils", "image_utils", "dash"]
|
|
7
|
+
from . import girder_utils, image_utils
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Functions using the girder client.
|
|
2
|
+
from girder_client import GirderClient
|
|
3
|
+
import pickle
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_item_large_image_metadata(gc: GirderClient, item_id: str) -> dict:
|
|
8
|
+
"""Get large image metadata for an item.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
gc (girder_client.GirderClient): The authenticated girder client.
|
|
12
|
+
item_id (str): The item id.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
dict: The metadata of the large image item.
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
return gc.get(f"item/{item_id}/tiles")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_thumbnail(
|
|
22
|
+
gc: GirderClient,
|
|
23
|
+
item_id: str,
|
|
24
|
+
mag: float | None = None,
|
|
25
|
+
width: int | None = None,
|
|
26
|
+
height: int | None = None,
|
|
27
|
+
fill: int | tuple = (255, 255, 255),
|
|
28
|
+
) -> np.ndarray:
|
|
29
|
+
"""Get the thumbnail image by a specific magnification or shape. If mag is
|
|
30
|
+
not None, then width and height are ignored. Fill is only used when both
|
|
31
|
+
width and height are provided, to return the thumbnail at the exact shape.
|
|
32
|
+
DSA convention will fill the height of the image, centering the image and
|
|
33
|
+
filling the top and bottom of the image equally.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
gc (girder_client.GirderClient): The authenticated girder client.
|
|
37
|
+
item_id (str): The item id.
|
|
38
|
+
mag (float, optional): The magnification. Defaults to None.
|
|
39
|
+
width (int, optional): The width of the thumbnail. Defaults to None.
|
|
40
|
+
height (int, optional): The height of the thumbnail. Defaults to None.
|
|
41
|
+
fill (int | tuple, optional): The fill color. Defaults to (255, 255, 255).
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
np.ndarray: The thumbnail image.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
get_url = f"item/{item_id}/tiles/"
|
|
48
|
+
|
|
49
|
+
if mag is not None:
|
|
50
|
+
get_url += f"region?magnification={mag}&encoding=pickle"
|
|
51
|
+
else:
|
|
52
|
+
# Instead use width and height.
|
|
53
|
+
params = ["encoding=pickle"]
|
|
54
|
+
|
|
55
|
+
if width is not None and height is not None:
|
|
56
|
+
if isinstance(fill, (tuple, list)):
|
|
57
|
+
if len(fill) == 3:
|
|
58
|
+
fill = f"rgb({fill[0]},{fill[1]},{fill[2]})"
|
|
59
|
+
elif len(fill) == 4:
|
|
60
|
+
fill = f"rgba({fill[0]},{fill[1]},{fill[2]},{fill[3]})"
|
|
61
|
+
|
|
62
|
+
params.extend([f"width={width}", f"height={height}", f"fill={fill}"])
|
|
63
|
+
elif width is not None:
|
|
64
|
+
params.append(f"width={width}")
|
|
65
|
+
elif height is not None:
|
|
66
|
+
params.append(f"height={height}")
|
|
67
|
+
|
|
68
|
+
get_url += "thumbnail?" + "&".join(params)
|
|
69
|
+
|
|
70
|
+
response = gc.get(get_url, jsonResp=False)
|
|
71
|
+
|
|
72
|
+
return pickle.loads(response.content)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_region(
|
|
76
|
+
gc: GirderClient,
|
|
77
|
+
item_id: str,
|
|
78
|
+
left: int,
|
|
79
|
+
top: int,
|
|
80
|
+
width: int,
|
|
81
|
+
height: int,
|
|
82
|
+
mag: float | None = None,
|
|
83
|
+
) -> np.ndarray:
|
|
84
|
+
"""Get a region of the image for an item. Note that the output image might
|
|
85
|
+
not be in the shape (width, height) if left + width or top + height exceeds
|
|
86
|
+
the image size. The output image will be the maximum size possible.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
gc (girder_client.GirderClient): The authenticated girder client.
|
|
90
|
+
item_id (str): The item id.
|
|
91
|
+
left (int): The left coordinate.
|
|
92
|
+
top (int): The top coordinate.
|
|
93
|
+
width (int): The width of the region.
|
|
94
|
+
height (int): The height of the region.
|
|
95
|
+
mag (float, optional): The magnification. Defaults to None which returns
|
|
96
|
+
the image at scan magnification. Using a mag lower than the scan
|
|
97
|
+
magnification will result in an ouptut image smaller than the
|
|
98
|
+
width and height. Similarly, using a mag higher than the scan
|
|
99
|
+
magnification will result in an output image larger than the width
|
|
100
|
+
and height.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
np.ndarray: The region of the image.
|
|
104
|
+
|
|
105
|
+
"""
|
|
106
|
+
get_url = (
|
|
107
|
+
f"item/{item_id}/tiles/region?left={left}&top={top}®ionWidth="
|
|
108
|
+
f"{width}®ionHeight={height}&encoding=pickle"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if mag is not None:
|
|
112
|
+
get_url += f"&magnification={mag}"
|
|
113
|
+
|
|
114
|
+
response = gc.get(get_url, jsonResp=False)
|
|
115
|
+
|
|
116
|
+
return pickle.loads(response.content)
|
|
@@ -24,9 +24,7 @@ def login(
|
|
|
24
24
|
gc = GirderClient(apiUrl=api_url)
|
|
25
25
|
|
|
26
26
|
if api_key is None:
|
|
27
|
-
if
|
|
28
|
-
_ = gc.authenticate(interactive=True)
|
|
29
|
-
elif password is None:
|
|
27
|
+
if password is None:
|
|
30
28
|
_ = gc.authenticate(username=login_or_email, interactive=True)
|
|
31
29
|
else:
|
|
32
30
|
_ = gc.authenticate(username=login_or_email, password=password)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dsa_helpers
|
|
3
|
-
Version: 0.3
|
|
3
|
+
Version: 0.3.dev0
|
|
4
4
|
Summary: Utility functions for working with the DSA girder client.
|
|
5
5
|
Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
|
|
6
6
|
Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
|
|
@@ -11,17 +11,11 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
11
11
|
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: girder-client
|
|
15
|
-
Requires-Dist: numpy
|
|
16
|
-
Requires-Dist: setuptools
|
|
17
|
-
Requires-Dist: opencv-python
|
|
18
|
-
Requires-Dist: pandas
|
|
19
|
-
Requires-Dist: pymongo
|
|
20
|
-
Requires-Dist: pillow
|
|
21
|
-
Requires-Dist: dash
|
|
22
|
-
Requires-Dist: dash_bootstrap_components
|
|
23
|
-
Requires-Dist: shapely
|
|
24
|
-
Requires-Dist: geopandas
|
|
14
|
+
Requires-Dist: girder-client==3.2.3
|
|
15
|
+
Requires-Dist: numpy==2.0.0
|
|
16
|
+
Requires-Dist: setuptools==71.0.3
|
|
17
|
+
Requires-Dist: opencv-python==4.10.0.84
|
|
18
|
+
Requires-Dist: pandas==2.2.2
|
|
25
19
|
|
|
26
20
|
# Digital Slide Archive (DSA) Helpers
|
|
27
21
|
Digital Slide Archive Python utility library.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.gitignore
|
|
2
|
+
LICENSE
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
requirements.txt
|
|
6
|
+
dsa_helpers/__init__.py
|
|
7
|
+
dsa_helpers/girder_utils.py
|
|
8
|
+
dsa_helpers/image_utils.py
|
|
9
|
+
dsa_helpers/imread.py
|
|
10
|
+
dsa_helpers/imwrite.py
|
|
11
|
+
dsa_helpers/login.py
|
|
12
|
+
dsa_helpers.egg-info/PKG-INFO
|
|
13
|
+
dsa_helpers.egg-info/SOURCES.txt
|
|
14
|
+
dsa_helpers.egg-info/dependency_links.txt
|
|
15
|
+
dsa_helpers.egg-info/requires.txt
|
|
16
|
+
dsa_helpers.egg-info/top_level.txt
|
|
@@ -4,17 +4,11 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
dependencies = [
|
|
7
|
-
'girder-client',
|
|
8
|
-
'numpy',
|
|
9
|
-
'setuptools',
|
|
10
|
-
'opencv-python',
|
|
11
|
-
'pandas'
|
|
12
|
-
'pymongo',
|
|
13
|
-
'pillow',
|
|
14
|
-
'dash',
|
|
15
|
-
'dash_bootstrap_components',
|
|
16
|
-
'shapely',
|
|
17
|
-
'geopandas'
|
|
7
|
+
'girder-client==3.2.3',
|
|
8
|
+
'numpy==2.0.0',
|
|
9
|
+
'setuptools==71.0.3',
|
|
10
|
+
'opencv-python==4.10.0.84',
|
|
11
|
+
'pandas==2.2.2'
|
|
18
12
|
]
|
|
19
13
|
name = "dsa_helpers"
|
|
20
14
|
authors = [
|
|
@@ -31,7 +25,7 @@ classifiers = [
|
|
|
31
25
|
"License :: OSI Approved :: MIT License",
|
|
32
26
|
]
|
|
33
27
|
keywords = ["dsa", "girder", "girder_client"]
|
|
34
|
-
version = "v0.
|
|
28
|
+
version = "v0.3dev"
|
|
35
29
|
|
|
36
30
|
[project.urls]
|
|
37
31
|
Repository = "https://github.com/Gutman-Lab/dsa-python-utils"
|
dsa_helpers-0.3/app.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# A test application.
|
|
2
|
-
from dash import Dash, html
|
|
3
|
-
import dash_bootstrap_components as dbc
|
|
4
|
-
from dsa_helpers.dash.header import get_header
|
|
5
|
-
import os
|
|
6
|
-
|
|
7
|
-
os.environ["DSA_API_URL"] = "https://megabrain.neurology.emory.edu/api/v1"
|
|
8
|
-
|
|
9
|
-
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
|
10
|
-
|
|
11
|
-
app.layout = html.Div([get_header("Test")])
|
|
12
|
-
|
|
13
|
-
if __name__ == "__main__":
|
|
14
|
-
app.run_server(debug=True)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from . import header
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
from dash import html, dcc
|
|
2
|
-
import dash_bootstrap_components as dbc
|
|
3
|
-
from . import header_callbacks
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
7
|
-
"""Get the Dash html component that contains the header of the application
|
|
8
|
-
with login capabilities.
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
title (str): The title of the application.
|
|
12
|
-
config (dict): The configuration of the component.
|
|
13
|
-
|
|
14
|
-
backgroundColor
|
|
15
|
-
titleColor
|
|
16
|
-
fontColor
|
|
17
|
-
|
|
18
|
-
Returns:
|
|
19
|
-
html.Div: The header component.
|
|
20
|
-
|
|
21
|
-
"""
|
|
22
|
-
login_modal = dbc.Modal(
|
|
23
|
-
[
|
|
24
|
-
dbc.ModalHeader("Log in"),
|
|
25
|
-
dbc.ModalBody(
|
|
26
|
-
[
|
|
27
|
-
html.Div(
|
|
28
|
-
"Login or email", style={"margin": 5, "fontWeight": "bold"}
|
|
29
|
-
),
|
|
30
|
-
dbc.Input(
|
|
31
|
-
id="login",
|
|
32
|
-
type="text",
|
|
33
|
-
placeholder="Enter login",
|
|
34
|
-
style={"margin": 5},
|
|
35
|
-
),
|
|
36
|
-
html.Div(
|
|
37
|
-
"Password",
|
|
38
|
-
style={"margin": 5, "marginTop": 15, "fontWeight": "bold"},
|
|
39
|
-
),
|
|
40
|
-
dbc.Input(
|
|
41
|
-
id="password",
|
|
42
|
-
type="password",
|
|
43
|
-
placeholder="Enter password",
|
|
44
|
-
style={"margin": 5},
|
|
45
|
-
),
|
|
46
|
-
html.Div(
|
|
47
|
-
"Login failed.",
|
|
48
|
-
hidden=True,
|
|
49
|
-
id="login-failed",
|
|
50
|
-
style={"color": "red", "fontWeight": "bold", "margin": 10},
|
|
51
|
-
),
|
|
52
|
-
],
|
|
53
|
-
),
|
|
54
|
-
dbc.ModalFooter(
|
|
55
|
-
dbc.Row(
|
|
56
|
-
[
|
|
57
|
-
dbc.Col(
|
|
58
|
-
dbc.Button(
|
|
59
|
-
"Close",
|
|
60
|
-
id="close-login-modal",
|
|
61
|
-
className="me-1",
|
|
62
|
-
color="light",
|
|
63
|
-
)
|
|
64
|
-
),
|
|
65
|
-
dbc.Col(
|
|
66
|
-
dbc.Button(
|
|
67
|
-
"Login",
|
|
68
|
-
id="log-in-btn",
|
|
69
|
-
className="me-1",
|
|
70
|
-
color="primary",
|
|
71
|
-
)
|
|
72
|
-
),
|
|
73
|
-
],
|
|
74
|
-
)
|
|
75
|
-
),
|
|
76
|
-
],
|
|
77
|
-
is_open=False,
|
|
78
|
-
id="login-modal",
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
logout_modal = dbc.Modal(
|
|
82
|
-
[
|
|
83
|
-
dbc.ModalFooter(
|
|
84
|
-
[
|
|
85
|
-
dbc.Button(
|
|
86
|
-
"Log out",
|
|
87
|
-
id="logout-btn",
|
|
88
|
-
color="danger",
|
|
89
|
-
className="me-1",
|
|
90
|
-
),
|
|
91
|
-
]
|
|
92
|
-
)
|
|
93
|
-
],
|
|
94
|
-
is_open=False,
|
|
95
|
-
id="logout-modal",
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
if config is None:
|
|
99
|
-
config = {}
|
|
100
|
-
|
|
101
|
-
return html.Div(
|
|
102
|
-
[
|
|
103
|
-
dbc.Row(
|
|
104
|
-
[
|
|
105
|
-
dbc.Col(
|
|
106
|
-
html.H1(
|
|
107
|
-
title,
|
|
108
|
-
style={
|
|
109
|
-
"fontWeight": "bold",
|
|
110
|
-
"color": config.get("titleColor", "#d9d9d6"),
|
|
111
|
-
"marginLeft": 5,
|
|
112
|
-
},
|
|
113
|
-
),
|
|
114
|
-
width="auto",
|
|
115
|
-
),
|
|
116
|
-
dbc.Col(
|
|
117
|
-
dbc.Button(
|
|
118
|
-
"Log in",
|
|
119
|
-
id="login-btn",
|
|
120
|
-
color=config.get("backgroundColor", "#012169"),
|
|
121
|
-
style={
|
|
122
|
-
"color": config.get("fontColor", "#f2a900"),
|
|
123
|
-
"fontSize": "1.2rem",
|
|
124
|
-
},
|
|
125
|
-
className="me-1",
|
|
126
|
-
),
|
|
127
|
-
width="auto",
|
|
128
|
-
),
|
|
129
|
-
],
|
|
130
|
-
justify="between",
|
|
131
|
-
align="center",
|
|
132
|
-
),
|
|
133
|
-
login_modal,
|
|
134
|
-
logout_modal,
|
|
135
|
-
dcc.Store(id="user-store", storage_type="local", data={}),
|
|
136
|
-
],
|
|
137
|
-
style={
|
|
138
|
-
"backgroundColor": config.get("backgroundColor", "#012169"),
|
|
139
|
-
"padding": 5,
|
|
140
|
-
},
|
|
141
|
-
)
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# Callbacks for the header component.
|
|
2
|
-
from dash import callback, Output, Input, State, no_update
|
|
3
|
-
from girder_client import GirderClient
|
|
4
|
-
from os import getenv
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@callback(Output("login-btn", "children"), Input("user-store", "data"))
|
|
8
|
-
def check_user_store(data):
|
|
9
|
-
# Check if the user store has user info or if no one is logged in.
|
|
10
|
-
return data["user"] if len(data) else "Log in"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@callback(
|
|
14
|
-
[
|
|
15
|
-
Output("login-modal", "is_open", allow_duplicate=True),
|
|
16
|
-
Output("logout-modal", "is_open", allow_duplicate=True),
|
|
17
|
-
],
|
|
18
|
-
[Input("login-btn", "n_clicks"), State("login-btn", "children")],
|
|
19
|
-
prevent_initial_call=True,
|
|
20
|
-
)
|
|
21
|
-
def open_login_modal(n_clicks, children):
|
|
22
|
-
# Open login / logout modal.
|
|
23
|
-
if n_clicks:
|
|
24
|
-
if children == "Log in":
|
|
25
|
-
return True, False
|
|
26
|
-
else:
|
|
27
|
-
return False, True
|
|
28
|
-
|
|
29
|
-
return False, False
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@callback(
|
|
33
|
-
[
|
|
34
|
-
Output("user-store", "data"),
|
|
35
|
-
Output("login-failed", "hidden", allow_duplicate=True),
|
|
36
|
-
Output("login-modal", "is_open", allow_duplicate=True),
|
|
37
|
-
Output("login", "value", allow_duplicate=True),
|
|
38
|
-
Output("password", "value", allow_duplicate=True),
|
|
39
|
-
],
|
|
40
|
-
[
|
|
41
|
-
Input("log-in-btn", "n_clicks"),
|
|
42
|
-
State("login", "value"),
|
|
43
|
-
State("password", "value"),
|
|
44
|
-
],
|
|
45
|
-
prevent_initial_call=True,
|
|
46
|
-
)
|
|
47
|
-
def login(n_clicks, login, password):
|
|
48
|
-
# Try to login.
|
|
49
|
-
gc = GirderClient(apiUrl=getenv("DSA_API_URL"))
|
|
50
|
-
|
|
51
|
-
try:
|
|
52
|
-
_ = gc.authenticate(username=login, password=password)
|
|
53
|
-
|
|
54
|
-
response = gc.get("token/session")
|
|
55
|
-
|
|
56
|
-
user = gc.get("user/me")["login"]
|
|
57
|
-
|
|
58
|
-
return {"user": user, "token": response["token"]}, True, False, "", ""
|
|
59
|
-
except:
|
|
60
|
-
return (
|
|
61
|
-
{},
|
|
62
|
-
False,
|
|
63
|
-
True,
|
|
64
|
-
no_update,
|
|
65
|
-
no_update,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
@callback(
|
|
70
|
-
[
|
|
71
|
-
Output("login-modal", "is_open", allow_duplicate=True),
|
|
72
|
-
Output("login", "value", allow_duplicate=True),
|
|
73
|
-
Output("password", "value", allow_duplicate=True),
|
|
74
|
-
Output("login-failed", "hidden", allow_duplicate=True),
|
|
75
|
-
],
|
|
76
|
-
Input("close-login-modal", "n_clicks"),
|
|
77
|
-
prevent_initial_call=True,
|
|
78
|
-
)
|
|
79
|
-
def close_login_modal(n_clicks):
|
|
80
|
-
if n_clicks:
|
|
81
|
-
return False, "", "", True
|
|
82
|
-
|
|
83
|
-
return False, "", "", True
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@callback(
|
|
87
|
-
[
|
|
88
|
-
Output("user-store", "data", allow_duplicate=True),
|
|
89
|
-
Output("logout-modal", "is_open", allow_duplicate=True),
|
|
90
|
-
],
|
|
91
|
-
Input("logout-btn", "n_clicks"),
|
|
92
|
-
prevent_initial_call=True,
|
|
93
|
-
)
|
|
94
|
-
def logout(n_clicks):
|
|
95
|
-
if n_clicks:
|
|
96
|
-
return {}, False
|
|
97
|
-
|
|
98
|
-
return no_update, False
|