bfabric-web-apps 0.1.1__py3-none-any.whl → 0.1.2__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.
- bfabric_web_apps/__init__.py +69 -8
- bfabric_web_apps/layouts/layouts.py +76 -22
- bfabric_web_apps/objects/BfabricInterface.py +85 -22
- bfabric_web_apps/objects/Logger.py +3 -3
- bfabric_web_apps/utils/callbacks.py +44 -26
- bfabric_web_apps/utils/create_app_in_bfabric.py +86 -0
- bfabric_web_apps/utils/defaults.py +11 -0
- bfabric_web_apps/utils/get_logger.py +1 -1
- bfabric_web_apps/utils/get_power_user_wrapper.py +3 -5
- {bfabric_web_apps-0.1.1.dist-info → bfabric_web_apps-0.1.2.dist-info}/METADATA +1 -1
- bfabric_web_apps-0.1.2.dist-info/RECORD +15 -0
- bfabric_web_apps/utils/app_config.py +0 -27
- bfabric_web_apps-0.1.1.dist-info/RECORD +0 -14
- {bfabric_web_apps-0.1.1.dist-info → bfabric_web_apps-0.1.2.dist-info}/LICENSE +0 -0
- {bfabric_web_apps-0.1.1.dist-info → bfabric_web_apps-0.1.2.dist-info}/WHEEL +0 -0
bfabric_web_apps/__init__.py
CHANGED
@@ -1,25 +1,33 @@
|
|
1
|
+
import os
|
2
|
+
|
1
3
|
# Export objects and classes
|
2
4
|
from bfabric_web_apps.objects import BfabricInterface, Logger
|
3
5
|
|
4
6
|
# Export components
|
5
|
-
from .utils
|
7
|
+
from .utils import components
|
6
8
|
|
7
9
|
# Export layouts
|
8
10
|
from .layouts.layouts import get_static_layout
|
9
11
|
|
10
12
|
# Export app initialization utilities
|
11
13
|
from .utils.app_init import create_app
|
12
|
-
from .utils.app_config import load_config
|
13
14
|
from .utils.get_logger import get_logger
|
14
15
|
from .utils.get_power_user_wrapper import get_power_user_wrapper
|
16
|
+
from .utils.create_app_in_bfabric import create_app_in_bfabric
|
15
17
|
|
16
18
|
# Export callbacks
|
17
19
|
from .utils.callbacks import process_url_and_token, submit_bug_report
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
from .utils import defaults
|
22
|
+
|
23
|
+
HOST = os.getenv("HOST", defaults.HOST)
|
24
|
+
PORT = int(os.getenv("PORT", defaults.PORT)) # Convert to int since env variables are strings
|
25
|
+
DEV = os.getenv("DEV", str(defaults.DEV)).lower() in ["true", "1", "yes"] # Convert to bool
|
26
|
+
CONFIG_FILE_PATH = os.getenv("CONFIG_FILE_PATH", defaults.CONFIG_FILE_PATH)
|
27
|
+
|
28
|
+
DEVELOPER_EMAIL_ADDRESS = os.getenv("DEVELOPER_EMAIL_ADDRESS", defaults.DEVELOPER_EMAIL_ADDRESS)
|
29
|
+
BUG_REPORT_EMAIL_ADDRESS = os.getenv("BUG_REPORT_EMAIL_ADDRESS", defaults.BUG_REPORT_EMAIL_ADDRESS)
|
30
|
+
|
23
31
|
|
24
32
|
# Define __all__ for controlled imports
|
25
33
|
__all__ = [
|
@@ -28,9 +36,62 @@ __all__ = [
|
|
28
36
|
"components",
|
29
37
|
"get_static_layout",
|
30
38
|
"create_app",
|
31
|
-
"load_config",
|
32
39
|
"process_url_and_token",
|
33
40
|
"submit_bug_report",
|
34
41
|
'get_logger',
|
35
|
-
'get_power_user_wrapper'
|
42
|
+
'get_power_user_wrapper',
|
43
|
+
'HOST',
|
44
|
+
'PORT',
|
45
|
+
'DEV',
|
46
|
+
'CONFIG_FILE_PATH',
|
47
|
+
'DEVELOPER_EMAIL_ADDRESS',
|
48
|
+
'BUG_REPORT_EMAIL_ADDRESS',
|
49
|
+
'create_app_in_bfabric'
|
36
50
|
]
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
'''
|
55
|
+
import os
|
56
|
+
from .utils import defaults
|
57
|
+
|
58
|
+
# Private variable for CONFIG_FILE_PATH
|
59
|
+
_CONFIG_FILE_PATH = os.getenv("CONFIG_FILE_PATH", defaults.CONFIG_FILE_PATH)
|
60
|
+
|
61
|
+
def set_config_file_path(path):
|
62
|
+
"""
|
63
|
+
Setter for the CONFIG_FILE_PATH variable.
|
64
|
+
"""
|
65
|
+
global _CONFIG_FILE_PATH
|
66
|
+
if not isinstance(path, str):
|
67
|
+
raise ValueError("CONFIG_FILE_PATH must be a string.")
|
68
|
+
_CONFIG_FILE_PATH = path
|
69
|
+
|
70
|
+
def get_config_file_path():
|
71
|
+
"""
|
72
|
+
Getter for the CONFIG_FILE_PATH variable.
|
73
|
+
"""
|
74
|
+
return _CONFIG_FILE_PATH
|
75
|
+
|
76
|
+
# Expose CONFIG_FILE_PATH as a read-only property
|
77
|
+
class Config:
|
78
|
+
@property
|
79
|
+
def CONFIG_FILE_PATH(self):
|
80
|
+
return get_config_file_path()
|
81
|
+
|
82
|
+
config = Config()
|
83
|
+
|
84
|
+
'''
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
'''
|
89
|
+
from bfabric import config
|
90
|
+
|
91
|
+
config.CONFIG_FILE_PATH
|
92
|
+
'''
|
93
|
+
|
94
|
+
'''
|
95
|
+
from bfabric import set_config_file_path
|
96
|
+
set_config_file_path("new/path/to/config.json")
|
97
|
+
'''
|
@@ -1,25 +1,38 @@
|
|
1
1
|
from dash import html, dcc
|
2
2
|
import dash_bootstrap_components as dbc
|
3
|
+
import bfabric_web_apps
|
3
4
|
|
4
|
-
def get_static_layout(base_title
|
5
|
+
def get_static_layout(base_title=None, main_content=None, documentation_content=None):
|
5
6
|
"""
|
6
7
|
Returns a layout with static tabs for Main, Documentation, and Report a Bug.
|
7
8
|
The main content is customizable, while the other tabs are generic.
|
9
|
+
|
10
|
+
Args:
|
11
|
+
base_title (str): The main title to be displayed in the banner.
|
12
|
+
main_content (html.Div): Content to be displayed in the "Main" tab.
|
13
|
+
documentation_content (html.Div): Content for the "Documentation" tab.
|
14
|
+
|
15
|
+
Returns:
|
16
|
+
html.Div: The complete static layout of the web app.
|
8
17
|
"""
|
9
18
|
return html.Div(
|
10
19
|
children=[
|
11
20
|
dcc.Location(id='url', refresh=False),
|
12
21
|
dcc.Store(id='token', storage_type='session'),
|
13
22
|
dcc.Store(id='entity', storage_type='session'),
|
23
|
+
dcc.Store(id='app_data', storage_type='session'),
|
14
24
|
dcc.Store(id='token_data', storage_type='session'),
|
25
|
+
dcc.Store(id='dynamic-link-store', storage_type='session'), # Store for dynamic job link
|
26
|
+
|
15
27
|
dbc.Container(
|
16
28
|
children=[
|
17
|
-
# Banner
|
29
|
+
# Banner Section
|
18
30
|
dbc.Row(
|
19
31
|
dbc.Col(
|
20
32
|
html.Div(
|
21
33
|
className="banner",
|
22
34
|
children=[
|
35
|
+
# Title
|
23
36
|
html.Div(
|
24
37
|
children=[
|
25
38
|
html.P(
|
@@ -35,30 +48,70 @@ def get_static_layout(base_title = None, main_content = None, documentation_cont
|
|
35
48
|
)
|
36
49
|
],
|
37
50
|
style={"background-color": "#000000", "border-radius": "10px"}
|
38
|
-
)
|
51
|
+
),
|
52
|
+
],
|
53
|
+
style={"position": "relative", "padding": "10px"}
|
54
|
+
),
|
55
|
+
),
|
56
|
+
),
|
57
|
+
|
58
|
+
# Page Title Section + View Logs Button (Aligned Right)
|
59
|
+
dbc.Row(
|
60
|
+
dbc.Col(
|
61
|
+
html.Div(
|
62
|
+
children=[
|
63
|
+
# Page Title (Aligned Left)
|
64
|
+
html.P(
|
65
|
+
id="page-title",
|
66
|
+
children=[str(" ")],
|
67
|
+
style={"font-size": "40px", "margin-left": "20px", "margin-top": "10px"}
|
68
|
+
),
|
69
|
+
|
70
|
+
# View Logs Button (Aligned Right)
|
71
|
+
html.Div(
|
72
|
+
children=[
|
73
|
+
html.A(
|
74
|
+
dbc.Button(
|
75
|
+
"View Logs",
|
76
|
+
id="dynamic-link-button",
|
77
|
+
color="secondary", # Greyish color
|
78
|
+
style={
|
79
|
+
"font-size": "18px",
|
80
|
+
"padding": "10px 20px",
|
81
|
+
"border-radius": "8px"
|
82
|
+
}
|
83
|
+
),
|
84
|
+
id="dynamic-link",
|
85
|
+
href="#", # Will be dynamically set in the callback
|
86
|
+
target="_blank"
|
87
|
+
)
|
88
|
+
],
|
89
|
+
style={
|
90
|
+
"position": "absolute",
|
91
|
+
"right": "20px",
|
92
|
+
"top": "10px", # Aligns with title
|
93
|
+
}
|
94
|
+
),
|
39
95
|
],
|
96
|
+
style={
|
97
|
+
"position": "relative", # Ensures absolute positioning works
|
98
|
+
"margin-top": "0px",
|
99
|
+
"min-height": "80px",
|
100
|
+
"height": "6vh",
|
101
|
+
"border-bottom": "2px solid #d4d7d9",
|
102
|
+
"display": "flex",
|
103
|
+
"align-items": "center",
|
104
|
+
"justify-content": "space-between", # Title left, button right
|
105
|
+
"padding-right": "20px" # Space between button & right edge
|
106
|
+
}
|
40
107
|
),
|
41
108
|
),
|
42
109
|
),
|
43
|
-
|
110
|
+
|
111
|
+
# Bug Report Alerts (Restored)
|
44
112
|
dbc.Row(
|
45
113
|
dbc.Col(
|
46
114
|
[
|
47
|
-
html.Div(
|
48
|
-
children=[
|
49
|
-
html.P(
|
50
|
-
id="page-title",
|
51
|
-
children=[str(" ")],
|
52
|
-
style={"font-size": "40px", "margin-left": "20px", "margin-top": "10px"}
|
53
|
-
)
|
54
|
-
],
|
55
|
-
style={
|
56
|
-
"margin-top": "0px",
|
57
|
-
"min-height": "80px",
|
58
|
-
"height": "6vh",
|
59
|
-
"border-bottom": "2px solid #d4d7d9"
|
60
|
-
}
|
61
|
-
),
|
62
115
|
dbc.Alert(
|
63
116
|
"Your bug report has been submitted. Thanks for helping us improve!",
|
64
117
|
id="alert-fade-bug-success",
|
@@ -86,7 +139,8 @@ def get_static_layout(base_title = None, main_content = None, documentation_cont
|
|
86
139
|
]
|
87
140
|
)
|
88
141
|
),
|
89
|
-
|
142
|
+
|
143
|
+
# Tabs Section
|
90
144
|
dbc.Tabs(
|
91
145
|
[
|
92
146
|
dbc.Tab(main_content, label="Main", tab_id="main"),
|
@@ -167,8 +221,8 @@ def get_report_bug_tab():
|
|
167
221
|
[
|
168
222
|
"Please use the form below to report a bug. If you have any questions, please email the developer at ",
|
169
223
|
html.A(
|
170
|
-
|
171
|
-
href="mailto:
|
224
|
+
bfabric_web_apps.DEVELOPER_EMAIL_ADDRESS,
|
225
|
+
href=f"mailto:{bfabric_web_apps.DEVELOPER_EMAIL_ADDRESS}",
|
172
226
|
),
|
173
227
|
]
|
174
228
|
),
|
@@ -5,10 +5,10 @@ import datetime
|
|
5
5
|
import bfabric
|
6
6
|
from bfabric import BfabricAuth
|
7
7
|
from bfabric import BfabricClientConfig
|
8
|
-
from
|
9
|
-
import dash_bootstrap_components as dbc
|
10
|
-
from bfabric_web_apps.objects.Logger import Logger
|
8
|
+
from bfabric_web_apps.utils.get_logger import get_logger
|
11
9
|
import os
|
10
|
+
import bfabric_web_apps
|
11
|
+
|
12
12
|
|
13
13
|
|
14
14
|
VALIDATION_URL = "https://fgcz-bfabric.uzh.ch/bfabric/rest/token/validate?token="
|
@@ -110,7 +110,6 @@ class BfabricInterface( Bfabric ):
|
|
110
110
|
|
111
111
|
|
112
112
|
def entity_data(self, token_data: dict) -> str:
|
113
|
-
|
114
113
|
"""
|
115
114
|
Retrieves entity data associated with the provided token.
|
116
115
|
|
@@ -119,7 +118,7 @@ class BfabricInterface( Bfabric ):
|
|
119
118
|
|
120
119
|
Returns:
|
121
120
|
str: A JSON string containing entity data.
|
122
|
-
|
121
|
+
{}: If the retrieval fails or token_data is invalid.
|
123
122
|
"""
|
124
123
|
|
125
124
|
entity_class_map = {
|
@@ -132,24 +131,18 @@ class BfabricInterface( Bfabric ):
|
|
132
131
|
}
|
133
132
|
|
134
133
|
if not token_data:
|
135
|
-
return
|
136
|
-
|
134
|
+
return json.dumps({})
|
135
|
+
|
137
136
|
wrapper = self.token_response_to_bfabric(token_data)
|
138
137
|
entity_class = token_data.get('entityClass_data', None)
|
139
138
|
endpoint = entity_class_map.get(entity_class, None)
|
140
139
|
entity_id = token_data.get('entity_id_data', None)
|
141
140
|
jobId = token_data.get('jobId', None)
|
142
141
|
username = token_data.get("user_data", "None")
|
143
|
-
environment= token_data.get("environment", "None")
|
144
|
-
|
142
|
+
environment = token_data.get("environment", "None")
|
145
143
|
|
146
144
|
if wrapper and entity_class and endpoint and entity_id and jobId:
|
147
|
-
|
148
|
-
L = Logger(
|
149
|
-
jobid = jobId,
|
150
|
-
username= username,
|
151
|
-
environment= environment
|
152
|
-
)
|
145
|
+
L = get_logger(token_data)
|
153
146
|
|
154
147
|
# Log the read operation directly using Logger L
|
155
148
|
entity_data_dict = L.logthis(
|
@@ -157,9 +150,10 @@ class BfabricInterface( Bfabric ):
|
|
157
150
|
endpoint=endpoint,
|
158
151
|
obj={"id": entity_id},
|
159
152
|
max_results=None,
|
160
|
-
params
|
161
|
-
flush_logs
|
153
|
+
params=None,
|
154
|
+
flush_logs=True
|
162
155
|
)[0]
|
156
|
+
|
163
157
|
|
164
158
|
if entity_data_dict:
|
165
159
|
json_data = json.dumps({
|
@@ -171,18 +165,84 @@ class BfabricInterface( Bfabric ):
|
|
171
165
|
return json_data
|
172
166
|
else:
|
173
167
|
L.log_operation(
|
174
|
-
operation=
|
175
|
-
message=
|
168
|
+
operation="entity_data",
|
169
|
+
message="Entity data retrieval failed or returned None.",
|
176
170
|
params=None,
|
177
171
|
flush_logs=True
|
178
172
|
)
|
179
173
|
print("entity_data_dict is empty or None")
|
180
|
-
return
|
174
|
+
return json.dumps({})
|
181
175
|
|
182
176
|
else:
|
183
177
|
print("Invalid input or entity information")
|
184
|
-
return
|
178
|
+
return json.dumps({})
|
185
179
|
|
180
|
+
|
181
|
+
def app_data(self, token_data: dict) -> str:
|
182
|
+
"""
|
183
|
+
Retrieves application data (App Name and Description) associated with the provided token.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
token_data (dict): The token data.
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
str: A JSON string containing application data.
|
190
|
+
{}: If retrieval fails or token_data is invalid.
|
191
|
+
"""
|
192
|
+
|
193
|
+
if not token_data:
|
194
|
+
return json.dumps({}) # Return empty JSON if no token data
|
195
|
+
|
196
|
+
# Extract App ID from token
|
197
|
+
app_data_raw = token_data.get("application_data", None)
|
198
|
+
|
199
|
+
try:
|
200
|
+
app_id = int(app_data_raw)
|
201
|
+
except:
|
202
|
+
print("Invalid application_data format in token_data")
|
203
|
+
return json.dumps({}) # Return empty JSON if app_id is invalid
|
204
|
+
|
205
|
+
# Define API endpoint
|
206
|
+
endpoint = "application"
|
207
|
+
|
208
|
+
# Initialize Logger
|
209
|
+
L = get_logger(token_data)
|
210
|
+
|
211
|
+
# Get API wrapper
|
212
|
+
wrapper = self.token_response_to_bfabric(token_data) # Same as entity_data
|
213
|
+
if not wrapper:
|
214
|
+
print("Failed to get Bfabric API wrapper")
|
215
|
+
return json.dumps({})
|
216
|
+
|
217
|
+
# Make API Call
|
218
|
+
app_data_dict = L.logthis(
|
219
|
+
api_call=wrapper.read,
|
220
|
+
endpoint=endpoint,
|
221
|
+
obj={"id": app_id}, # Query using the App ID
|
222
|
+
max_results=None,
|
223
|
+
params=None,
|
224
|
+
flush_logs=True
|
225
|
+
)
|
226
|
+
|
227
|
+
# If API call fails, return empty JSON
|
228
|
+
if not app_data_dict or len(app_data_dict) == 0:
|
229
|
+
L.log_operation(
|
230
|
+
operation="app_data",
|
231
|
+
message=f"Failed to retrieve application data for App ID {app_id}",
|
232
|
+
params=None,
|
233
|
+
flush_logs=True
|
234
|
+
)
|
235
|
+
return json.dumps({})
|
236
|
+
|
237
|
+
# Extract Name and Description
|
238
|
+
app_info = app_data_dict[0] # First (and only) result
|
239
|
+
json_data = json.dumps({
|
240
|
+
"name": app_info.get("name", "Unknown"),
|
241
|
+
"description": app_info.get("description", "No description available")
|
242
|
+
})
|
243
|
+
|
244
|
+
return json_data
|
245
|
+
|
186
246
|
|
187
247
|
def send_bug_report(self, token_data = None, entity_data = None, description = None):
|
188
248
|
"""
|
@@ -207,7 +267,7 @@ class BfabricInterface( Bfabric ):
|
|
207
267
|
"""
|
208
268
|
|
209
269
|
mail = f"""
|
210
|
-
echo "{mail_string}" | mail -s "Bug Report"
|
270
|
+
echo "{mail_string}" | mail -s "Bug Report" {bfabric_web_apps.BUG_REPORT_EMAIL_ADDRESS}
|
211
271
|
"""
|
212
272
|
|
213
273
|
print("MAIL STRING:")
|
@@ -220,3 +280,6 @@ class BfabricInterface( Bfabric ):
|
|
220
280
|
|
221
281
|
return True
|
222
282
|
|
283
|
+
|
284
|
+
|
285
|
+
|
@@ -4,9 +4,8 @@ from typing import List
|
|
4
4
|
from bfabric import Bfabric
|
5
5
|
from datetime import datetime as dt
|
6
6
|
import base64
|
7
|
-
|
7
|
+
import bfabric_web_apps
|
8
8
|
|
9
|
-
CONFIG_FILE_PATH = load_config()["CONFIG_FILE_PATH"]
|
10
9
|
|
11
10
|
class Logger:
|
12
11
|
"""
|
@@ -23,6 +22,7 @@ class Logger:
|
|
23
22
|
"""
|
24
23
|
self.jobid = jobid
|
25
24
|
self.username = username
|
25
|
+
self.config_file_path = bfabric_web_apps.CONFIG_FILE_PATH
|
26
26
|
self.power_user_wrapper = self._get_power_user_wrapper(environment)
|
27
27
|
self.logs = []
|
28
28
|
|
@@ -37,7 +37,7 @@ class Logger:
|
|
37
37
|
Bfabric: An authenticated Bfabric instance.
|
38
38
|
"""
|
39
39
|
power_user_wrapper = Bfabric.from_config(
|
40
|
-
config_path = os.path.expanduser(
|
40
|
+
config_path = os.path.expanduser(self.config_file_path),
|
41
41
|
config_env = environment.upper()
|
42
42
|
)
|
43
43
|
return power_user_wrapper
|
@@ -2,25 +2,30 @@ from dash import Input, Output, State, html, dcc
|
|
2
2
|
from bfabric_web_apps.objects.BfabricInterface import BfabricInterface
|
3
3
|
import json
|
4
4
|
import dash_bootstrap_components as dbc
|
5
|
-
from bfabric_web_apps.objects.Logger import Logger
|
6
5
|
from datetime import datetime as dt
|
6
|
+
from bfabric_web_apps.utils.get_logger import get_logger
|
7
7
|
|
8
8
|
def process_url_and_token(url_params):
|
9
9
|
"""
|
10
10
|
Processes URL parameters to extract the token, validates it, and retrieves the corresponding data.
|
11
|
+
Additionally, it constructs a dynamic job link based on the environment and job ID.
|
11
12
|
|
12
13
|
Args:
|
13
14
|
url_params (str): The URL parameters containing the token.
|
14
|
-
base_title (str): The base title of the page.
|
15
15
|
|
16
16
|
Returns:
|
17
|
-
tuple: A tuple containing
|
18
|
-
|
17
|
+
tuple: A tuple containing:
|
18
|
+
- token (str): Authentication token.
|
19
|
+
- token_data (dict): Token metadata.
|
20
|
+
- entity_data (dict): Retrieved entity information.
|
21
|
+
- page_title (str): Title for the page header.
|
22
|
+
- session_details (list): HTML-formatted session details.
|
23
|
+
- job_link (str): Dynamically generated link to the job page.
|
19
24
|
"""
|
20
25
|
base_title = " "
|
21
26
|
|
22
27
|
if not url_params:
|
23
|
-
return None, None, None, base_title, None
|
28
|
+
return None, None, None, None, base_title, None, None
|
24
29
|
|
25
30
|
token = "".join(url_params.split('token=')[1:])
|
26
31
|
bfabric_interface = BfabricInterface()
|
@@ -28,43 +33,60 @@ def process_url_and_token(url_params):
|
|
28
33
|
|
29
34
|
if tdata_raw:
|
30
35
|
if tdata_raw == "EXPIRED":
|
31
|
-
return None, None, None, base_title, None
|
36
|
+
return None, None, None, None, base_title, None, None
|
32
37
|
else:
|
33
38
|
tdata = json.loads(tdata_raw)
|
34
39
|
else:
|
35
|
-
return None, None, None, base_title, None
|
40
|
+
return None, None, None, None, base_title, None, None
|
36
41
|
|
37
42
|
if tdata:
|
38
43
|
entity_data_json = bfabric_interface.entity_data(tdata)
|
44
|
+
app_data_json = bfabric_interface.app_data(tdata)
|
39
45
|
entity_data = json.loads(entity_data_json)
|
46
|
+
app_data = json.loads(app_data_json)
|
40
47
|
page_title = (
|
41
|
-
f"{tdata
|
42
|
-
f"({tdata
|
48
|
+
f"{tdata.get('entityClass_data', 'Unknown')} - {entity_data.get('name', 'Unknown')} "
|
49
|
+
f"({tdata.get('environment', 'Unknown')} System)"
|
43
50
|
) if tdata else "Bfabric App Interface"
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
environment = tdata.get("environment", "").strip().lower() # 'test' or 'prod'
|
53
|
+
job_id = tdata.get("jobId", None) # Extract job ID
|
54
|
+
|
55
|
+
job_link = None
|
56
|
+
if job_id:
|
57
|
+
if "test" in environment:
|
58
|
+
job_link = f"https://fgcz-bfabric-test.uzh.ch/bfabric/job/show.html?id={job_id}&tab=details"
|
59
|
+
else:
|
60
|
+
job_link = f"https://fgcz-bfabric.uzh.ch/bfabric/job/show.html?id={job_id}&tab=details"
|
61
|
+
|
62
|
+
session_details = [
|
49
63
|
html.P([
|
50
|
-
html.B("Entity Name: "), entity_data
|
64
|
+
html.B("Entity Name: "), entity_data.get('name', 'Unknown'),
|
65
|
+
html.Br(),
|
66
|
+
html.B("Entity Class: "), tdata.get('entityClass_data', 'Unknown'),
|
51
67
|
html.Br(),
|
52
|
-
html.B("
|
68
|
+
html.B("Environment: "), tdata.get('environment', 'Unknown'),
|
53
69
|
html.Br(),
|
54
|
-
html.B("
|
70
|
+
html.B("Entity ID: "), tdata.get('entity_id_data', 'Unknown'),
|
55
71
|
html.Br(),
|
56
|
-
html.B("
|
72
|
+
html.B("Job ID: "), job_id if job_id else "Unknown",
|
57
73
|
html.Br(),
|
58
|
-
html.B("User Name: "), tdata
|
74
|
+
html.B("User Name: "), tdata.get('user_data', 'Unknown'),
|
59
75
|
html.Br(),
|
60
|
-
html.B("Session Expires: "), tdata
|
76
|
+
html.B("Session Expires: "), tdata.get('token_expires', 'Unknown'),
|
77
|
+
html.Br(),
|
78
|
+
html.B("App Name: "), app_data.get("name", "Unknown"),
|
79
|
+
html.Br(),
|
80
|
+
html.B("App Description: "), app_data.get("description", "No description available"),
|
61
81
|
html.Br(),
|
62
82
|
html.B("Current Time: "), str(dt.now().strftime("%Y-%m-%d %H:%M:%S"))
|
63
83
|
])
|
64
84
|
]
|
65
|
-
|
85
|
+
|
86
|
+
return token, tdata, entity_data, app_data, page_title, session_details, job_link
|
66
87
|
else:
|
67
|
-
return None, None, None, base_title, None
|
88
|
+
return None, None, None, None, base_title, None, None
|
89
|
+
|
68
90
|
|
69
91
|
|
70
92
|
def submit_bug_report(n_clicks, bug_description, token, entity_data):
|
@@ -100,11 +122,7 @@ def submit_bug_report(n_clicks, bug_description, token, entity_data):
|
|
100
122
|
# Initialize the logger only if token_data is available
|
101
123
|
L = None
|
102
124
|
if token_data:
|
103
|
-
L =
|
104
|
-
jobid=jobId,
|
105
|
-
username=username,
|
106
|
-
environment=environment
|
107
|
-
)
|
125
|
+
L = get_logger(token_data)
|
108
126
|
|
109
127
|
if n_clicks:
|
110
128
|
# Log the operation only if the logger is initialized
|
@@ -0,0 +1,86 @@
|
|
1
|
+
from bfabric import Bfabric
|
2
|
+
|
3
|
+
def get_user_input():
|
4
|
+
"""Prompt user for necessary inputs."""
|
5
|
+
|
6
|
+
systems = {"TEST": "TEST", "PROD": "PRODUCTION"}
|
7
|
+
|
8
|
+
technologies = {
|
9
|
+
"TEST": {
|
10
|
+
"1": "Genomics / Transcriptomics",
|
11
|
+
"2": "Proteomics",
|
12
|
+
"4": "Metabolomics / Biophysics",
|
13
|
+
"6": "General",
|
14
|
+
"10": "New Tech"
|
15
|
+
},
|
16
|
+
"PRODUCTION": {
|
17
|
+
"1": "Genomics / Transcriptomics",
|
18
|
+
"2": "Proteomics",
|
19
|
+
"4": "Metabolomics / Biophysics",
|
20
|
+
"6": "General",
|
21
|
+
"10": "Bioinformatics"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
# Get system input
|
26
|
+
system = input("In which system do you want to create the app? (Type 'TEST' for the test system or 'PROD' for the production system): ").strip().upper()
|
27
|
+
|
28
|
+
while system not in systems:
|
29
|
+
print("Invalid input! Please enter 'TEST' or 'PROD'.")
|
30
|
+
system = input("Enter system (TEST/PROD): ").strip().upper()
|
31
|
+
|
32
|
+
selected_system = systems[system] # Map input to full system name
|
33
|
+
|
34
|
+
# Display technology options based on selected system
|
35
|
+
print("\nAvailable Technologies:")
|
36
|
+
for key, value in technologies[selected_system].items():
|
37
|
+
print(f"{key}: {value}")
|
38
|
+
|
39
|
+
# Get technology ID from user
|
40
|
+
technologyid = input("\nEnter the number corresponding to your chosen application type: ").strip()
|
41
|
+
|
42
|
+
while technologyid not in technologies[selected_system]:
|
43
|
+
print("Invalid technology ID! Please select a valid number from the list.")
|
44
|
+
technologyid = input("Enter a valid technology ID: ").strip()
|
45
|
+
|
46
|
+
# Get remaining inputs
|
47
|
+
name = input("Enter app name: ")
|
48
|
+
weburl = input("Enter web URL: ")
|
49
|
+
description = input("Enter description: ")
|
50
|
+
|
51
|
+
return {
|
52
|
+
"system": selected_system,
|
53
|
+
"name": name,
|
54
|
+
"weburl": weburl,
|
55
|
+
"type": "WebApp",
|
56
|
+
"technologyid": technologyid,
|
57
|
+
"supervisorid": "2446",
|
58
|
+
"enabled": True,
|
59
|
+
"valid": True,
|
60
|
+
"hidden": False,
|
61
|
+
"description": description
|
62
|
+
}
|
63
|
+
|
64
|
+
def create_app_in_bfabric():
|
65
|
+
"""Create an app in B-Fabric using user inputs."""
|
66
|
+
# Get user input for parameters
|
67
|
+
user_input = get_user_input()
|
68
|
+
|
69
|
+
# Determine configuration environment based on user input
|
70
|
+
config_env = user_input.pop("system")
|
71
|
+
|
72
|
+
# Initialize Bfabric instance
|
73
|
+
bfabric = Bfabric.from_config(config_env=config_env)
|
74
|
+
|
75
|
+
# Set endpoint for app creation
|
76
|
+
endpoint = "application"
|
77
|
+
|
78
|
+
# Make API call to save the app
|
79
|
+
try:
|
80
|
+
result = bfabric.save(endpoint=endpoint, obj=user_input)
|
81
|
+
print("App created successfully:", result)
|
82
|
+
except Exception as e:
|
83
|
+
print("Failed to create app:", str(e))
|
84
|
+
|
85
|
+
if __name__ == "__main__":
|
86
|
+
create_app_in_bfabric()
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# defaults.py
|
2
|
+
CONFIG_FILE_PATH = "~/.bfabricpy.yml"
|
3
|
+
|
4
|
+
# Default values for application settings
|
5
|
+
HOST = "0.0.0.0"
|
6
|
+
PORT = 8050
|
7
|
+
DEV = False
|
8
|
+
|
9
|
+
# Developer and bug report email addresses
|
10
|
+
DEVELOPER_EMAIL_ADDRESS = "griffin@gwcustom.com"
|
11
|
+
BUG_REPORT_EMAIL_ADDRESS = "gwtools@fgcz.system"
|
@@ -1,8 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
from bfabric import Bfabric
|
3
|
-
|
4
|
-
|
5
|
-
CONFIG_FILE_PATH = load_config()["CONFIG_FILE_PATH"]
|
3
|
+
import bfabric_web_apps
|
6
4
|
|
7
5
|
def get_power_user_wrapper(token_data):
|
8
6
|
"""
|
@@ -13,7 +11,7 @@ def get_power_user_wrapper(token_data):
|
|
13
11
|
determined by the `CONFIG_FILE_PATH` from the application's configuration.
|
14
12
|
|
15
13
|
Args:
|
16
|
-
token_data (dict): A dictionary containing token information
|
14
|
+
token_data (dict): A dictionary containing token information
|
17
15
|
The key "environment" is used to determine the environment
|
18
16
|
(default is "None" if not specified).
|
19
17
|
|
@@ -24,6 +22,6 @@ def get_power_user_wrapper(token_data):
|
|
24
22
|
environment = token_data.get("environment", "None")
|
25
23
|
|
26
24
|
return Bfabric.from_config(
|
27
|
-
config_path = os.path.expanduser(CONFIG_FILE_PATH),
|
25
|
+
config_path = os.path.expanduser(bfabric_web_apps.CONFIG_FILE_PATH),
|
28
26
|
config_env = environment.upper()
|
29
27
|
)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
bfabric_web_apps/__init__.py,sha256=zZvM0CQPkiu0y9xOZos-d2hK-h6erc8K_nov7vD1bdE,2362
|
2
|
+
bfabric_web_apps/layouts/layouts.py,sha256=XoSLcQPcgMBhQz2VfxkUzNL23FLBXFRFvbCL2mNLfnk,11636
|
3
|
+
bfabric_web_apps/objects/BfabricInterface.py,sha256=nRdU_cYLW2_xp2x1cvP9b30gQ5blavbOz66B-Hi6UZQ,8980
|
4
|
+
bfabric_web_apps/objects/Logger.py,sha256=62LC94xhm7YG5LUw3yH46NqvJQsAX7wnc9D4zbY16rA,5224
|
5
|
+
bfabric_web_apps/utils/app_init.py,sha256=RCdpCXp19cF74bouYJLPe-KSETZ0Vwqtd02Ta2VXEF8,428
|
6
|
+
bfabric_web_apps/utils/callbacks.py,sha256=PiP1ZJ-QxdrOAZ-Mt-MN-g9wJLSOoLkWkXwPq_TLqDI,6472
|
7
|
+
bfabric_web_apps/utils/components.py,sha256=V7ECGmF2XYy5O9ciDJVH1nofJYP2a_ELQF3z3X_ADbo,844
|
8
|
+
bfabric_web_apps/utils/create_app_in_bfabric.py,sha256=eVk3cQDXxW-yo9b9n_zzGO6kLg_SLxYbIDECyvEPJXU,2752
|
9
|
+
bfabric_web_apps/utils/defaults.py,sha256=B82j3JEbysLEU9JDZgoDBTX7WGvW3Hn5YMZaWAcjZew,278
|
10
|
+
bfabric_web_apps/utils/get_logger.py,sha256=0Y3SrXW93--eglS0_ZOc34NOriAt6buFPik5n0ltzRA,434
|
11
|
+
bfabric_web_apps/utils/get_power_user_wrapper.py,sha256=T33z64XjmJ0KSlmfEmrEP8eYpbpINCVD6Xld_V7PR2g,1027
|
12
|
+
bfabric_web_apps-0.1.2.dist-info/LICENSE,sha256=k0O_i2k13i9e35aO-j7FerJafAqzzu8x0kkBs0OWF3c,1065
|
13
|
+
bfabric_web_apps-0.1.2.dist-info/METADATA,sha256=tvvoNH4-tMyPbWJdoe_pVgC_cDzQpDzdGtqd49vt9QI,480
|
14
|
+
bfabric_web_apps-0.1.2.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
15
|
+
bfabric_web_apps-0.1.2.dist-info/RECORD,,
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import importlib.util
|
3
|
-
|
4
|
-
def load_config(params_path="./PARAMS.py"):
|
5
|
-
"""Load configuration for the Dash app."""
|
6
|
-
if os.path.exists(params_path):
|
7
|
-
try:
|
8
|
-
# Dynamically import the PARAMS module
|
9
|
-
spec = importlib.util.spec_from_file_location("PARAMS", params_path)
|
10
|
-
params_module = importlib.util.module_from_spec(spec)
|
11
|
-
spec.loader.exec_module(params_module)
|
12
|
-
|
13
|
-
# Retrieve values with defaults
|
14
|
-
PORT = getattr(params_module, "PORT", 8050)
|
15
|
-
HOST = getattr(params_module, "HOST", "localhost")
|
16
|
-
DEV = getattr(params_module, "DEV", True)
|
17
|
-
CONFIG_FILE_PATH = getattr(params_module, "CONFIG_FILE_PATH", "~/.bfabricpy.yml")
|
18
|
-
except ImportError:
|
19
|
-
# Fallback to default values in case of import errors
|
20
|
-
PORT, HOST, DEV = 8050, 'localhost', True
|
21
|
-
CONFIG_FILE_PATH = "~/.bfabricpy.yml"
|
22
|
-
else:
|
23
|
-
# Fallback to default values if PARAMS.py is not found
|
24
|
-
PORT, HOST, DEV = 8050, 'localhost', True
|
25
|
-
CONFIG_FILE_PATH = "~/.bfabricpy.yml"
|
26
|
-
|
27
|
-
return {"PORT": PORT, "HOST": HOST, "DEV": DEV, "CONFIG_FILE_PATH": CONFIG_FILE_PATH}
|
@@ -1,14 +0,0 @@
|
|
1
|
-
bfabric_web_apps/__init__.py,sha256=XDzAg0boEE3nj3RXGB85YbVc0KgEeRNOcQfrSkJoV-0,880
|
2
|
-
bfabric_web_apps/layouts/layouts.py,sha256=oQHfT65PdoFU5js8JkEJqFhxfgNjwU0GRvD1xbkfYD4,8758
|
3
|
-
bfabric_web_apps/objects/BfabricInterface.py,sha256=pHse1UgC_XFD-PsYqOs0Ho3xTRMDRCvtRgsILVYy-0k,6919
|
4
|
-
bfabric_web_apps/objects/Logger.py,sha256=ikMJJZYDPhJZEmgCY63_htGmPvXv1ItSmfb_xiFFZMQ,5225
|
5
|
-
bfabric_web_apps/utils/app_config.py,sha256=u7lz8sonf9CSkJsVK0nhTzIls227FksGCOb_SzYE_fE,1204
|
6
|
-
bfabric_web_apps/utils/app_init.py,sha256=RCdpCXp19cF74bouYJLPe-KSETZ0Vwqtd02Ta2VXEF8,428
|
7
|
-
bfabric_web_apps/utils/callbacks.py,sha256=OlNelwAJUKsEtnaJ4OuTdrgyu9PhEgm4uqCde4NNKHA,5270
|
8
|
-
bfabric_web_apps/utils/components.py,sha256=V7ECGmF2XYy5O9ciDJVH1nofJYP2a_ELQF3z3X_ADbo,844
|
9
|
-
bfabric_web_apps/utils/get_logger.py,sha256=_cn0en-itaGEeeCDtws-nw2ubd36w2xc6VfDNoBMFu4,433
|
10
|
-
bfabric_web_apps/utils/get_power_user_wrapper.py,sha256=ZUrv-xNLEXtMVeFEpAwmPbPFUmcAxu3hITIuPY2dhF8,1078
|
11
|
-
bfabric_web_apps-0.1.1.dist-info/LICENSE,sha256=k0O_i2k13i9e35aO-j7FerJafAqzzu8x0kkBs0OWF3c,1065
|
12
|
-
bfabric_web_apps-0.1.1.dist-info/METADATA,sha256=R1zgL1bVK18CV4uPQc1vUABgBnOn6us0YBbcC6yqy0g,480
|
13
|
-
bfabric_web_apps-0.1.1.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
14
|
-
bfabric_web_apps-0.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|