Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hawc 2023-Q1 + hawc-client 2023.2 #803

Merged
merged 26 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
recursive-include hawc *css *.js *.json *.html *.py *.txt
recursive-include hawc *css *.js *.json *.jsonl *.html *.py *.txt
recursive-include hawc/refml/nltk_data *
recursive-include hawc/static *
recursive-include hawc/templates *
Expand Down
1 change: 0 additions & 1 deletion compose/app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ COPY ./compose/app/sync.sh /app/bin/sync.sh
COPY ./compose/app/web.sh /app/bin/web.sh
COPY ./compose/app/workers.sh /app/bin/workers.sh
COPY ./compose/app/cron.sh /app/bin/cron.sh
COPY ./vendor/bmds-0.11.0.tar.gz /app/build/vendor/bmds-0.11.0.tar.gz

# used in some dev/staging environments
COPY ./tests/data/fixtures/db.yaml /app/test-db-fixture.yaml
Expand Down
10 changes: 5 additions & 5 deletions docs/docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ Client tutorials for common operations are below:

### Changelog

#### [2023-2](https://pypi.org/project/hawc-client/2023.2/) (January 2023)
#### [2023-2](https://pypi.org/project/hawc-client/2023.2/) (April 2023)

* Add new parameter to `set_authentication_token`, login, and returns boolean instead of a dict.
- If False (default), a token based API session is created. This is consistent with previous behavior.
- If True, a django cookie-based session is set instead of a token-based API session. This may be used if
using the client to browse the website, however CSRF tokens would be required for form-based requests.
* Add new `login` parameter to `client.set_authentication_token`, and returns boolean instead of a dict.
- If `login` is False (default), a token based API session is created. This is consistent with previous behavior.
- If `login` is True, a django cookie-based session is set instead of a token-based API session. This may be used if using the client to browse the website, however CSRF tokens will be required for API and form requests.
* Added ``client.lit.reference_user_tags`` - retrieves all user tag for all references for an assessment.

#### [2023-1](https://pypi.org/project/hawc-client/2023.1/) (January 2023)

Expand Down
9 changes: 4 additions & 5 deletions frontend/animal/Endpoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,6 @@ class Endpoint extends Observee {
.then(data => cb(new Endpoint(data)));
}

static getTagURL(assessment, slug) {
return `/ani/assessment/${assessment}/endpoints/tags/${slug}/`;
}

static displayAsModal(id, opts) {
Endpoint.get_object(id, d => d.displayAsModal(opts));
}
Expand Down Expand Up @@ -271,7 +267,10 @@ class Endpoint extends Observee {
var div = $("<div>");
div.append(
tags.map(v => {
const url = Endpoint.getTagURL(assessment_id, v.slug);
const url = h.getUrlWithParameters(
`/ani/assessment/${assessment_id}/endpoints/`,
{tags: v.name}
);
return `<a class="btn btn-light" href="${url}">${v.name}</a>`;
})
);
Expand Down
3 changes: 3 additions & 0 deletions frontend/shared/utils/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ const helpers = {
getBulkUrl(host, base, ids = null) {
return `${host}${base}&ids=${ids}`;
},
getUrlWithParameters(path, params) {
return `${path}?${new URLSearchParams(params).toString()}`;
},
datetimeFormat(dt) {
return moment(dt).format("MMMM Do YYYY, h:mm:ss a");
},
Expand Down
2 changes: 1 addition & 1 deletion frontend/study/Study.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class Study {
);
if (this.data.full_text_url)
tbl.add_tbody_tr(
"Full-text link",
"Full text URL",
`<a href=${this.data.full_text_url}>${this.data.full_text_url}</a>`
);
tbl.add_tbody_tr("COI reported", this.data.coi_reported);
Expand Down
2 changes: 1 addition & 1 deletion hawc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import sys

__version__ = "0.1"
__version__ = "2023.1"


def manage():
Expand Down
17 changes: 0 additions & 17 deletions hawc/apps/animal/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,6 @@ def get_queryset(self):
def published(self, assessment_id=None):
return self.get_qs(assessment_id).filter(animal_group__experiment__study__published=True)

def tag_qs(self, assessment_id, tag_slug=None):
AnimalGroup = apps.get_model("animal", "AnimalGroup")
Experiment = apps.get_model("animal", "Experiment")
Study = apps.get_model("study", "Study")
return (
self.filter(effects__slug=tag_slug)
.select_related("animal_group", "animal_group__dosing_regime")
.prefetch_related("animal_group__dosing_regime__doses")
.filter(
animal_group__in=AnimalGroup.objects.filter(
experiment__in=Experiment.objects.filter(
study__in=Study.objects.get_qs(assessment_id)
)
)
)
)

def optimized_qs(self, **filters):
return (
self.filter(**filters)
Expand Down
5 changes: 0 additions & 5 deletions hawc/apps/animal/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,6 @@
views.EndpointListV2.as_view(),
name="endpoint_list_v2",
),
path(
"assessment/<int:pk>/endpoints/tags/<slug:tag_slug>/",
views.EndpointTags.as_view(),
name="assessment_endpoint_taglist",
),
path(
"animal-group/<int:pk>/endpoint/create/",
views.EndpointCreate.as_view(),
Expand Down
7 changes: 0 additions & 7 deletions hawc/apps/animal/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,13 +437,6 @@ def get_app_config(self, context) -> WebappConfig:
)


class EndpointTags(EndpointFilterList):
# List of Endpoints associated with an assessment and tag

def get_queryset(self):
return super().get_queryset().tag_qs(self.assessment.pk, self.kwargs["tag_slug"])


class EndpointRead(BaseDetail):
queryset = models.Endpoint.objects.select_related(
"animal_group",
Expand Down
9 changes: 6 additions & 3 deletions hawc/apps/assessment/api/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from rest_framework import status
from rest_framework.exceptions import APIException
from rest_framework.request import Request

from ...common.helper import tryParseInt
from .. import models
Expand All @@ -17,17 +18,19 @@ class InvalidAssessmentID(APIException):
default_detail = "Assessment does not exist for given `assessment_id`."


def get_assessment_id_param(request) -> int:
def get_assessment_id_param(request: Request) -> int:
"""
If request doesn't contain an integer-based `assessment_id`, an exception is raised.
"""
assessment_id = tryParseInt(request.GET.get("assessment_id"))
assessment_id = tryParseInt(
request.query_params.get("assessment_id") or request.data.get("assessment_id")
)
if assessment_id is None:
raise RequiresAssessmentID()
return assessment_id


def get_assessment_from_query(request) -> Optional[models.Assessment]:
def get_assessment_from_query(request: Request) -> Optional[models.Assessment]:
"""Returns assessment or raises exception if does not exist."""
assessment_id = get_assessment_id_param(request)
try:
Expand Down
1 change: 0 additions & 1 deletion hawc/apps/assessment/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ class AssessmentEditViewset(viewsets.ModelViewSet):
assessment_filter_args = ""
permission_classes = (AssessmentLevelPermissions,)
action_perms = {}
parent_model = models.Assessment
filter_backends = (InAssessmentFilter,)
lookup_value_regex = re_digits

Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/assessment/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def helper(self):
class AssessmentFilterForm(forms.Form):
search = forms.CharField(required=False)

DEFAULT_ORDER_BY = "-last_updated"
DEFAULT_ORDER_BY = "-year"
ORDER_BY_CHOICES = [
("name", "Name"),
("year", "Year, ascending"),
Expand Down
4 changes: 2 additions & 2 deletions hawc/apps/assessment/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ def get_df(self) -> pd.DataFrame:
"system": "system",
"value_type": "value_type",
"value": "value",
"value_unit__name": "value_unit",
"value_unit": "value_unit",
"basis": "basis",
"pod_value": "pod_value",
"pod_unit__name": "pod_unit",
"pod_unit": "pod_unit",
"species_studied": "species_studied",
"duration": "duration",
"study_id": "study_id",
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/assessment/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def _has_data(self, app: str, model: str, filter: str = "study__assessment") ->

@property
def has_lit_data(self) -> bool:
return self._has_data("lit", "Reference")
return self._has_data("lit", "Reference", filter="assessment")

@property
def has_rob_data(self) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ <h3>Assessment details for team members*</h3>
{% block extrajs %}
{% if crud == "Read" and object.dtxsids.first %}
<script type="text/javascript">
$(document).on('ready', function () {
window.addEventListener("DOMContentLoaded", function () {
const dtxsids = {{dtxsids|safe}},
el = document.getElementById('dtxsid-app');
window.app.startup("assessmentStartup", function(app){
Expand Down
12 changes: 12 additions & 0 deletions hawc/apps/common/autocomplete/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ def update_filters(self, filters: dict):
self.filters.update(filters)
self.url = self.autocomplete_class.url(**self.filters)

def filter_choices_to_render(self, selected_choices):
"""Filter out un-selected choices if choices is a QuerySet.

patched - see https://github.com/yourlabs/django-autocomplete-light/pull/1321
"""
try:
qs = self.choices.queryset.filter(pk__in=[c for c in selected_choices if c])
except ValueError:
# set queryset to empty set if filters are invalid
qs = self.choices.queryset.none()
self.choices.queryset = qs


class AutocompleteSelectWidget(AutocompleteWidgetMixin, autocomplete.ModelSelect2):
pass
Expand Down
10 changes: 5 additions & 5 deletions hawc/apps/common/flavors/help_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
StudyPopulation=dict(
design=(
"Choose the most specific description of study design. See “Epidemiology Terms Appendix“ for additional guidance: "
"<a target='_new' href='https://hawcprd.epa.gov/assessment/100000039/'>https://hawcprd.epa.gov/assessment/100000039/</a>. "
"<a target='_new' href='https://hawc.epa.gov/assessment/100000039/'>https://hawc.epa.gov/assessment/100000039/</a>. "
"<span class='important-note'>This field is commonly used in HAWC visualizations</span>"
),
),
Outcome=dict(
name=(
"Follow “Recommended Terminology for Outcomes/Endpoints“: <a target='_new' href='https://hawcprd.epa.gov/assessment/100000039/'>https://hawcprd.epa.gov/assessment/100000039/</a>. "
"Follow “Recommended Terminology for Outcomes/Endpoints“: <a target='_new' href='https://hawc.epa.gov/assessment/100000039/'>https://hawc.epa.gov/assessment/100000039/</a>. "
"Use title style (capitalize all words). Ex. Hyperthyroidism <span class='important-note'>This field is commonly used in HAWC visualizations</span>"
),
effects=(
Expand All @@ -28,17 +28,17 @@
),
system=(
"Enter biological system affected, following “Recommended Terminology for Outcomes/Endpoints“: "
"<a target='_new' href='https://hawcprd.epa.gov/assessment/100000039/'>https://hawcprd.epa.gov/assessment/100000039/</a>. "
"<a target='_new' href='https://hawc.epa.gov/assessment/100000039/'>https://hawc.epa.gov/assessment/100000039/</a>. "
"Use title style (capitalize all words). Ex. Endocrine"
),
effect=(
"Enter effect, following “Recommended Terminology for Outcomes/Endpoints“: "
"<a target='_new' href='https://hawcprd.epa.gov/assessment/100000039/'>https://hawcprd.epa.gov/assessment/100000039/</a>. "
"<a target='_new' href='https://hawc.epa.gov/assessment/100000039/'>https://hawc.epa.gov/assessment/100000039/</a>. "
"Use title style (capitalize all words). Ex. Thyroid Hormones "
),
effect_subtype=(
"Enter effect subtype, following “Recommended Terminology for Outcomes/Endpoints“: "
"<a target='_new' href='https://hawcprd.epa.gov/assessment/100000039/'>https://hawcprd.epa.gov/assessment/100000039/</a>."
"<a target='_new' href='https://hawc.epa.gov/assessment/100000039/'>https://hawc.epa.gov/assessment/100000039/</a>."
"Use title style (capitalize all words). Ex. Absolute "
"<i>This field is not mandatory; often no effect subtype is necessary</i>"
),
Expand Down
4 changes: 0 additions & 4 deletions hawc/apps/common/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ def strip_entities(value):
return re.sub(r"&(?:\w+|#\d+);", "", force_str(value))


def listToUl(list_):
return f"<ul>{''.join(['<li>{0}</li>'.format(d) for d in list_])}</ul>"


def tryParseInt(
value: Any, default: int = None, min_value: int = -inf, max_value: int = inf
) -> Optional[int]:
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/common/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def create(self, validated_data, *args, **kwargs):
class FlexibleFieldsMixin:
"""
Allows manipulation of fields on serializer instances.
This mixin is primarily meant for serailization and not deserialization.
This mixin is primarily meant for serialization and not deserialization.

Constructor kwargs:
fields (list[str]): allowlist of field names to include in serializer
Expand Down
12 changes: 8 additions & 4 deletions hawc/apps/epi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,21 +512,25 @@ def perform_update(self, serializer):

class ComparisonSet(EditPermissionsCheckMixin, AssessmentEditViewset):
edit_check_keys = ["study_population", "outcome"]
assessment_filter_args = "assessment" # todo: fix
assessment_filter_args = "study_population__study__assessment"
model = models.ComparisonSet
serializer_class = serializers.ComparisonSetSerializer

def get_serializer_class(self):
if self.action in ["list"]:
return serializers.ComparisonSetLinkSerializer
return serializers.ComparisonSetSerializer


class GroupNumericalDescriptions(EditPermissionsCheckMixin, AssessmentEditViewset):
edit_check_keys = ["group"]
# assessment_filter_args = "group__assessment"
assessment_filter_args = "group__comparison_set__study_population__study__assessment"
model = models.GroupNumericalDescriptions
serializer_class = serializers.GroupNumericalDescriptionsSerializer


class Group(EditPermissionsCheckMixin, AssessmentEditViewset):
edit_check_keys = ["comparison_set"]
assessment_filter_args = "assessment" # todo: fix
assessment_filter_args = "comparison_set__study_population__study__assessment"
model = models.Group
serializer_class = serializers.GroupSerializer

Expand Down
3 changes: 3 additions & 0 deletions hawc/apps/epi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,9 @@ def __str__(self):
def get_assessment(self):
return self.group.get_assessment()

def get_absolute_url(self):
return self.group.get_absolute_url()


class ResultMetric(models.Model):
objects = managers.ResultMetricManager()
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/epi/templates/epi/comparisonset_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

{% block extrajs %}
<script type="text/javascript">
$(document).on('ready', function(){
window.addEventListener("DOMContentLoaded", function(){
new window.app.DynamicFormset($('#gFormset'), 'form', {oneFormRequired: true});
$('#gFormset').insertBefore($('#gcForm .form-actions'));
});
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/epi/templates/epi/exposure_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

{% block extrajs %}
<script type="text/javascript">
$(document).on('ready', function () {
window.addEventListener("DOMContentLoaded", function () {
new window.app.DynamicFormset($('#ctFormset'), 'form', { oneFormRequired: true });
$('#ctFormset').insertBefore($('.form-actions'));
});
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/epi/templates/epi/group_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

{% block extrajs %}
<script type="text/javascript">
$(document).on('ready', function(){
window.addEventListener("DOMContentLoaded", function(){
new window.app.DynamicFormset($('#gnFormset'), 'form', {oneFormRequired: true});
$('#gnFormset').insertBefore($('#gForm .form-actions'));
});
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/epi/templates/epi/result_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

{% block extrajs %}
<script type="text/javascript">
$(document).on('ready', function(){
window.addEventListener("DOMContentLoaded", function(){

var printf = window.app.HAWCUtils.printf,
elFormset = $("#rFormset").insertBefore($('#rForm .form-actions')),
Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/hawc_admin/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ReportsViewset(viewsets.ViewSet):

@action(detail=False, renderer_classes=PandasRenderers)
def values(self, request):
"""Gets all value data accross all assessments."""
"""Gets all value data across all assessments."""
export = ValuesListExport(
queryset=AssessmentValue.objects.all(), filename="hawc-assessment-values"
).build_export()
Expand Down
4 changes: 2 additions & 2 deletions hawc/apps/invitro/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ def full_export(self, request, pk):


class IVChemical(AssessmentViewset):
assessment_filter_args = "assessment"
assessment_filter_args = "study__assessment"
model = models.IVChemical
serializer_class = serializers.IVChemicalSerializer


class IVCellType(AssessmentViewset):
assessment_filter_args = "assessment"
assessment_filter_args = "study__assessment"
model = models.IVCellType
serializer_class = serializers.IVCellTypeSerializer

Expand Down
2 changes: 1 addition & 1 deletion hawc/apps/invitro/templates/invitro/ivendpoint_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
},
};

$(document).on('ready', function(){
window.addEventListener("DOMContentLoaded", function(){
new window.app.DynamicFormset($('#egFormset'), 'form', {oneFormRequired: false});
$('#egFormset').insertBefore($('#eForm .form-actions'));
$('#egBenchmarkFormset').insertBefore($('#eForm .form-actions'));
Expand Down
Loading