Skip to content

Commit

Permalink
A LOT wrapped up. all search approaches are now standardized and temp…
Browse files Browse the repository at this point in the history
…lated. files and file sets look good. admin WYSIWYG config editor works, as does improved detail view property editor. general style tidying. some performance improvements. code housekeeping. Basically, this is ready to roll. remaining big nice todos: automate pulling in xcures files, play with superset integration. One real to-do is a proper larger instance stress test with 100s of k of database records at the least (large file slogging harder and costly to test). I'm pleased
  • Loading branch information
John Major committed Aug 7, 2024
1 parent c083ac6 commit 39358c1
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 94 deletions.
2 changes: 1 addition & 1 deletion bloom_lims/config/file/file_set.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{"property_key":"tag","form_label":"Tag", "required": false, "value_type":"uid-interactive"},
{"property_key":"tags","form_label":"Tags", "required": false, "value_type":"list"},
{"property_key": "creating_user", "form_label":"Creating User", "required":false, "value_type":"uid-static"},
{"property_key": "ref_type", "form_label":"Ref Type", "required":false, "value_type":"query-only-uid-statuc"},
{"property_key": "ref_type", "form_label":"Ref Type", "required":false, "value_type":"uid-static"},
{"property_key": "comments", "form_label": "Comments", "required": false, "value_type": "string"}
],
"controlled_properties": { },
Expand Down
138 changes: 62 additions & 76 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2298,73 +2298,34 @@ async def search_files(
created_datetime_end: str = Form(None),
creating_user: List[str] = Form(None),
):
search_criteria = {}

if euid:
search_criteria["euid"] = euid

if patient_id:
if len(patient_id) == 1 and patient_id[0] == ".na":
patient_id = ""

if len(patient_id) == 1 and patient_id[0] == "":
pass
else:
search_criteria["patient_id"] = patient_id

if clinician_id:
if len(clinician_id) == 1 and clinician_id[0] == ".na":
clinician_id = ""
if len(clinician_id) == 1 and clinician_id[0] == "":
pass
else:
search_criteria["clinician_id"] = clinician_id

form_data = {
"euid": euid,
"patient_id": patient_id,
"clinician_id": clinician_id,
"lab_code": lab_code,
"purpose": purpose,
"purpose_subtype": purpose_subtype,
"category": category,
"sub_category": sub_category,
"sub_category_2": sub_category_2,
"study_id": study_id,
"comments": comments,
"creating_user": creating_user,
}

search_fields = [
"euid", "patient_id", "clinician_id", "lab_code", "purpose", "purpose_subtype",
"category", "sub_category", "sub_category_2", "study_id", "comments", "creating_user"
]

search_criteria = create_search_criteria(form_data, search_fields)

if relevant_datetime_start or relevant_datetime_end:
search_criteria["relevant_datetime"] = {
"start": relevant_datetime_start,
"end": relevant_datetime_end
}

if lab_code:
if len(lab_code) == 1 and lab_code[0] == ".na":
lab_code = ""

if len(lab_code) == 1 and lab_code[0] == "":
pass
else:
search_criteria["lab_code"] = lab_code

if purpose:
search_criteria["purpose"] = purpose
if purpose_subtype:
search_criteria["purpose_subtype"] = purpose_subtype
if category:
search_criteria["category"] = category
if sub_category:
search_criteria["sub_category"] = sub_category
if sub_category_2:
search_criteria["sub_category_2"] = sub_category_2
if study_id:
if len(study_id) == 1 and study_id[0] == ".na":
study_id = ""

if len(study_id) == 1 and study_id[0] == "":
pass
else:
search_criteria["study_id"] = study_id

if comments:
search_criteria["comments"] = comments

if creating_user:
if len(creating_user) == 1 and creating_user[0] == ".na":
creating_user = ""

if len(creating_user) == 1 and creating_user[0] == "":
pass
else:
search_criteria["creating_user"] = creating_user

greedy = is_greedy == "yes"

Expand Down Expand Up @@ -2511,7 +2472,8 @@ async def create_file_set(
"comments": comments,
"ref_type": ref_type,
"duration": duration,
"rclone_config": rclone_config
"rclone_config": rclone_config,
"creating_user": request.session["user_data"]["email"],
}

# Create the file set
Expand Down Expand Up @@ -2545,38 +2507,61 @@ async def create_file_set(

except Exception as e:
raise (e)


def create_search_criteria(form_data, fields):
search_criteria = {}
for field in fields:
field_value = form_data.get(field)
if field_value:
if isinstance(field_value, list):
if len(field_value) == 1 and field_value[0] in [".na"]:
field_value = ""
if len(field_value) == 1 and field_value[0] in [""]:
continue
search_criteria[field] = field_value
else:
if field_value in [".na"]:
field_value = ""
if field_value in [""]:
continue
search_criteria[field] = field_value
return search_criteria


# The following is very redundant to the file_search and <s>probably</s> should be refactored
@app.post("/search_file_sets", response_class=HTMLResponse)
async def search_file_sets(
request: Request,
name: str = Form(None),
description: str = Form(None),
tag: str = Form(None),
tag: List[str] = Form(None),
comments: str = Form(None),
file_euids: str = Form(None),
is_greedy: str = Form("yes"),
ref_type: str = Form(None),
ref_type: List[str] = Form(None),
creating_user: List[str] = Form(None),
):
search_criteria = {}

if name:
search_criteria["name"] = name
if description:
search_criteria["description"] = description
if tag:
search_criteria["tag"] = tag
if comments:
search_criteria["comments"] = comments
form_data = {
"name": name,
"description": description,
"tag": tag,
"comments": comments,
"file_euids": file_euids,
"ref_type": ref_type,
"creating_user": creating_user,
}

q_ds = {"properties": search_criteria}
search_fields = ["name", "description", "tag", "comments", "ref_type", "creating_user"]
search_criteria = create_search_criteria(form_data, search_fields)

greedy = is_greedy == "yes"

try:
bfs = BloomFileSet(BLOOMdb3(app_username=request.session["user_data"]["email"]))
file_sets = bfs.search_objs_by_addl_metadata(
q_ds, greedy, "file_set", super_type="file"
{'properties':search_criteria}, greedy, "file_set", super_type="file"
)

# Fetch details for each EUID
Expand Down Expand Up @@ -2609,12 +2594,14 @@ async def search_file_sets(
user_data = request.session.get("user_data", {})
style = {"skin_css": user_data.get("style_css", "static/skins/bloom.css")}

num_results = len(table_data)
content = templates.get_template("file_set_search_results.html").render(
request=request,
table_data=table_data,
columns=columns,
style=style,
udat=user_data,
num_results=num_results,
)
return HTMLResponse(content=content)

Expand Down Expand Up @@ -2798,7 +2785,6 @@ def generate_ui_form_fields(ui_form_properties: List[Dict], controlled_propertie
required=required
))
else:
#from IPython import embed; embed()
unique_values = sorted(bobject.get_unique_property_values(property_key, super_type=super_type, btype=btype, b_sub_type=b_sub_type, version=version))
if '' not in unique_values:
unique_values.insert(0, '')
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="bloom_lims",
version="0.10.4",
version="0.10.5",
packages=find_packages(),
install_requires=[
# Add dependencies here,
Expand Down
22 changes: 22 additions & 0 deletions static/skins/bloom.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,26 @@
}


input[type="date" i] {
font-family: inherit;
padding-inline-start: 1px;
cursor: default;
padding: inherit;
border: inherit;
overflow: hidden;
}

input[type="file" i] {
font-family: inherit;
appearance: none;
background-color: inherit;
cursor: default;
align-items: baseline;
color: inherit;
text-overflow: ellipsis;
text-align: start !important;
padding: initial;
border: inherit;
white-space: pre;
overflow: hidden !important;
}
14 changes: 14 additions & 0 deletions templates/dewey.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@
color: var(--text-color);
border-color: var(--button-border-color);
}

.div.selectize-input {
padding: inherit;
border: inherit;
margin: inherit;
position: inherit;
}
.selectize-input {
padding: inherit;
border: inherit;
margin: inherit;
position: inherit;
background-color: var(--form-in-bg-color);
}
</style>
<script>
const controlledProperties = {{ controlled_properties | tojson | safe }};
Expand Down
4 changes: 2 additions & 2 deletions templates/file_search.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<ul>
<h3>Search Files</h3>
<table>
<tr>
<td style="align:top;">
<tr style="vertical-align: top;">
<td style="align:top; width:22%;">
<!-- New form for querying by EUIDs -->
<form id="queryByEuidsForm" action="query_by_euids" method="post" enctype="multipart/form-data">
<label for="file_euids">File EUIDs (one per line):</label>
Expand Down
4 changes: 3 additions & 1 deletion templates/file_set_search_results.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<body>
{% include 'bloom_header.html' %}

<h1>Search Results</h1>
<h1>{{ num_results }} Results</h1>

<table id="results-table" border="1">
<thead>
Expand All @@ -27,7 +27,9 @@ <h1>Search Results</h1>
{% for row in table_data %}
<tr>
<td>
{% if row['ref_type'] == 'presigned_url' %}
<a href="/file_set_urls?fs_euid={{ row['EUID'] }}" target="_blank">View Presigned URLSs</a>
{% endif %}
</td> <!-- New cell with the link -->
{% for column in columns %}
<td>
Expand Down
47 changes: 37 additions & 10 deletions templates/search_file_sets.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,47 @@
<ul>
<h3>Search File Sets By</h3>
<form id="searchFileSetForm" action="search_file_sets" method="post" enctype="multipart/form-data">
<label for="file_set_name">Name: </label>
<input type="text" id="file_set_name" name="file_set_name" value=""><br><br>

<label for="file_set_description">Description: </label>
<input type="text" id="file_set_description" name="file_set_description" value=""><br><br>

<label for="file_set_tag">Tag: </label>
<input type="text" id="file_set_tag" name="file_set_tag" value=""><br><br>

<label for="comments">Comments: </label>
<input type="text" id="comments" name="comments" value=""><br><br>
{% for field in ui_search_fields_fset %}
<div>
{% if field.name in ["tags", "xxx"] %}

{% else %}

{% if field.type == "select" and field.multiple %}

<label for="{{ field.name }}">{{ field.label }}</label>
<div class="option-buttons" data-select-id="{{ field.name }}">
<select class="no-selectize" name="{{ field.name }}" id="{{ field.name }}" multiple style="display: none;">
<option value="" selected></option> <!-- Placeholder for blank state -->
<option value=".na">isnull</option>
{% for option in field.options %}
<option value="{{ option }}">{{ option }}</option>
{% endfor %}
</select>
</div>
{% elif field.type == "select" %}
<label for="{{ field.name }}">{{ field.label }}</label>
<select class="no-selectize" name="{{ field.name }}" id="{{ field.name }}">
<option value="" selected></option> <!-- Placeholder for blank state -->
<option value=".na">isnull</option>
{% for option in field.options %}
<option value="{{ option }}">{{ option }}</option>
{% endfor %}
</select>
{% else %}
{% if not field.name.endswith('_datetime') %}
<label for="{{ field.name }}">{{ field.label }}</label>
<input type="{{ field.type }}" name="{{ field.name }}" id="{{ field.name }}" />
{% endif %}
{% endif %}
{% endif %}
</div>

{% endfor %}

<label for="file_euids">File EUIDs (not working presently): </label>
<input type="text" id="file_euids" name="file_euids" value=""><br><br>

<label for="is_greedy">Greedy Search: </label>
<select name="is_greedy">
Expand Down
Loading

0 comments on commit 39358c1

Please sign in to comment.