max improvement
This commit is contained in:
+10
-1
@@ -1495,12 +1495,21 @@ class CaseSeriesForm(forms.ModelForm):
|
|||||||
def __init__(self, *args, queryset, user=None, is_atlas_editor=False, **kwargs):
|
def __init__(self, *args, queryset, user=None, is_atlas_editor=False, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields["series"].queryset = queryset
|
self.fields["series"].queryset = queryset
|
||||||
self.fields["series"].label_from_instance = lambda obj: str(obj.pk)
|
self.fields["series"].label_from_instance = lambda obj: f"Series {obj.pk}: {obj.description or ''} ({obj.modality or ''})"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SeriesDetail # through model for Case.series
|
model = SeriesDetail # through model for Case.series
|
||||||
|
|
||||||
fields = ["series", "sort_order", "feedback"]
|
fields = ["series", "sort_order", "feedback"]
|
||||||
|
widgets = {
|
||||||
|
"series": autocomplete.ModelSelect2(
|
||||||
|
url="atlas:series-autocomplete",
|
||||||
|
attrs={
|
||||||
|
"data-placeholder": "Search by Series ID or description...",
|
||||||
|
"data-minimum-input-length": 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class CaseUpdateSeriesForm(forms.ModelForm):
|
class CaseUpdateSeriesForm(forms.ModelForm):
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
{% load static %}
|
||||||
|
{% load django_htmx %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
<html data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
<title>Create Resource</title>
|
||||||
|
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
||||||
|
<link href="{% static 'css/widgets.css' %}" type="text/css" media="all" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{% static 'css/bootstrap-icons.css' %}">
|
||||||
|
<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
|
||||||
|
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
|
||||||
|
{% block js %}
|
||||||
|
{% endblock %}
|
||||||
|
<link rel="stylesheet" href="{% static 'css/forms.css' %}">
|
||||||
|
</head>
|
||||||
|
<body class="p-3">
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<a href="{% url 'atlas:case_detail' case.pk %}" style="color: inherit; text-decoration: none;">View Case</a>
|
<a href="{% url 'atlas:case_detail' case.pk %}" style="color: inherit; text-decoration: none;">View Case</a>
|
||||||
</button>
|
</button>
|
||||||
<button class="edit-link-case btn btn-outline-warning btn-sm ms-2" style="display:none;">
|
<button class="edit-link-case btn btn-outline-warning btn-sm ms-2" style="display:none;">
|
||||||
<a href="{% url 'atlas:case_update' case.pk %}" style="color: inherit; text-decoration: none;">Edit Case</a>
|
<a href="{% url 'atlas:case_update' case.pk %}?next={{ request.get_full_path|urlencode }}" style="color: inherit; text-decoration: none;">Edit Case</a>
|
||||||
</button>
|
</button>
|
||||||
<br />
|
<br />
|
||||||
<div class="pre-whitespace multi-image-block">
|
<div class="pre-whitespace multi-image-block">
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<a href="{% url 'atlas:case_detail' case.pk %}" style="color: inherit; text-decoration: none;">View Case</a>
|
<a href="{% url 'atlas:case_detail' case.pk %}" style="color: inherit; text-decoration: none;">View Case</a>
|
||||||
</button>
|
</button>
|
||||||
<button class="edit-link-case btn btn-outline-warning btn-sm" style="display:none;">
|
<button class="edit-link-case btn btn-outline-warning btn-sm" style="display:none;">
|
||||||
<a href="{% url 'atlas:case_update' case.pk %}" style="color: inherit; text-decoration: none;">Edit Case</a>
|
<a href="{% url 'atlas:case_update' case.pk %}?next={{ request.get_full_path|urlencode }}" style="color: inherit; text-decoration: none;">Edit Case</a>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{% load crispy_forms_tags %}
|
||||||
|
<form hx-post="{% url 'atlas:case_create_resource_inline' pk=case.pk %}"
|
||||||
|
hx-encoding="multipart/form-data"
|
||||||
|
hx-target="#case-resources-list"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
class="bg-dark p-3 rounded border border-secondary text-white my-3">
|
||||||
|
{% csrf_token %}
|
||||||
|
<h5>Create New Resource</h5>
|
||||||
|
{{ form|crispy }}
|
||||||
|
<div class="form-check mb-3">
|
||||||
|
<input type="checkbox" name="pre_review" class="form-check-input" id="id_pre_review">
|
||||||
|
<label class="form-check-label" for="id_pre_review">Pre-review (show before case is taken)</label>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button type="submit" class="btn btn-sm btn-success">Save and Attach</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary"
|
||||||
|
hx-get="{% url 'atlas:resource_search_panel' %}?case_id={{ case.pk }}"
|
||||||
|
hx-target="#resource-search-panel-placeholder"
|
||||||
|
hx-swap="innerHTML">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -35,6 +35,14 @@
|
|||||||
<label class="form-check-label small" for="resource-open-access-{{ case.pk }}">Open</label>
|
<label class="form-check-label small" for="resource-open-access-{{ case.pk }}">Open</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-auto ms-auto">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-success"
|
||||||
|
hx-get="{% url 'atlas:case_create_resource_inline' pk=case.pk %}"
|
||||||
|
hx-target="#resource-search-panel"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
+ New Resource
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="resource-search-results" class="mt-2"></div>
|
<div id="resource-search-results" class="mt-2"></div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="btn-toolbar" role="toolbar" aria-label="Case actions">
|
<div class="btn-toolbar" role="toolbar" aria-label="Case actions">
|
||||||
<div class="btn-group me-2 mb-2" role="group" aria-label="Primary actions">
|
<div class="btn-group me-2 mb-2" role="group" aria-label="Primary actions">
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{% url 'atlas:case_detail' pk=case.pk %}" title="View the Case">View</a>
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'atlas:case_detail' pk=case.pk %}" title="View the Case">View</a>
|
||||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_update' pk=case.pk %}" title="Edit the Case">Edit</a>
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_update' pk=case.pk %}?next={{ request.get_full_path|urlencode }}" title="Edit the Case">Edit</a>
|
||||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_series_update' pk=case.pk %}" title="Edit the Cases Series">Series</a>
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_series_update' pk=case.pk %}" title="Edit the Cases Series">Series</a>
|
||||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_displaysets' pk=case.pk %}" title="View and edit case display sets">Display sets</a>
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_displaysets' pk=case.pk %}" title="View and edit case display sets">Display sets</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends "atlas/base.html" %}
|
{% extends base_template|default:"atlas/base.html" %}
|
||||||
<!-- {% load static from static %} -->
|
<!-- {% load static from static %} -->
|
||||||
|
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
<h2>Resources</h2>
|
<h2>Resources</h2>
|
||||||
|
|
||||||
|
<button class="btn btn-primary mb-3">
|
||||||
|
<a href="{% url 'atlas:resource_create' %}">Create New Resource</a>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{% comment %} <details>
|
||||||
|
<summary>Search Resources</summary>
|
||||||
|
{% include "atlas/partials/resource_search_panel.html" %}
|
||||||
|
</details>
|
||||||
|
{% endcomment %}
|
||||||
<form>
|
<form>
|
||||||
{% render_table table %}
|
{% render_table table %}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+7
-1
@@ -2,7 +2,7 @@ from django.urls import path, include
|
|||||||
from django.views.generic import RedirectView, TemplateView
|
from django.views.generic import RedirectView, TemplateView
|
||||||
|
|
||||||
|
|
||||||
from atlas.models import CaseCollection, Condition, Finding, Presentation, Structure, Subspecialty, Procedure
|
from atlas.models import CaseCollection, Condition, Finding, Presentation, Structure, Subspecialty, Procedure, Series
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
app_name = "atlas"
|
app_name = "atlas"
|
||||||
@@ -254,6 +254,7 @@ urlpatterns = [
|
|||||||
path("case/<int:pk>/attach-resource/", views.case_attach_resource, name="case_attach_resource"),
|
path("case/<int:pk>/attach-resource/", views.case_attach_resource, name="case_attach_resource"),
|
||||||
path("case/<int:pk>/detach-resource/", views.case_detach_resource, name="case_detach_resource"),
|
path("case/<int:pk>/detach-resource/", views.case_detach_resource, name="case_detach_resource"),
|
||||||
path("case/<int:pk>/toggle-resource-pre/", views.case_toggle_resource_pre, name="case_toggle_resource_pre"),
|
path("case/<int:pk>/toggle-resource-pre/", views.case_toggle_resource_pre, name="case_toggle_resource_pre"),
|
||||||
|
path("case/<int:pk>/create-resource-inline/", views.case_create_resource_inline, name="case_create_resource_inline"),
|
||||||
# Backwards-compatible redirect from legacy case_id-style URLs
|
# Backwards-compatible redirect from legacy case_id-style URLs
|
||||||
path(
|
path(
|
||||||
"collection/<int:exam_id>/case/id/<int:case_id>/details",
|
"collection/<int:exam_id>/case/id/<int:case_id>/details",
|
||||||
@@ -785,6 +786,11 @@ urlpatterns = [
|
|||||||
views.SubspecialtyAutocomplete.as_view(model=Subspecialty, create_field="name"),
|
views.SubspecialtyAutocomplete.as_view(model=Subspecialty, create_field="name"),
|
||||||
name="subspecialty-autocomplete",
|
name="subspecialty-autocomplete",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"series-autocomplete",
|
||||||
|
views.SeriesAutocomplete.as_view(model=Series),
|
||||||
|
name="series-autocomplete",
|
||||||
|
),
|
||||||
path("presentation/", views.PresentationView.as_view(), name="presentation_view"),
|
path("presentation/", views.PresentationView.as_view(), name="presentation_view"),
|
||||||
path(
|
path(
|
||||||
"presentation/<int:pk>", views.presentation_detail, name="presentation_detail"
|
"presentation/<int:pk>", views.presentation_detail, name="presentation_detail"
|
||||||
|
|||||||
+127
-29
@@ -4301,11 +4301,28 @@ class ResourceCreate(LoginRequiredMixin, CreateView):
|
|||||||
model = Resource
|
model = Resource
|
||||||
form_class = ResourceForm
|
form_class = ResourceForm
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
if self.request.GET.get("popup") == "1":
|
||||||
|
context["base_template"] = "atlas/base_popup.html"
|
||||||
|
else:
|
||||||
|
context["base_template"] = "atlas/base.html"
|
||||||
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
self.object = form.save(commit=False)
|
self.object = form.save(commit=False)
|
||||||
self.object.save()
|
self.object.save()
|
||||||
form.instance.author.add(self.request.user.id)
|
form.instance.author.add(self.request.user.id)
|
||||||
|
|
||||||
|
if self.request.GET.get("popup") == "1":
|
||||||
|
field_id = self.request.GET.get("field_id", "")
|
||||||
|
from django.utils.html import escapejs
|
||||||
|
return HttpResponse(
|
||||||
|
f'<script type="text/javascript">'
|
||||||
|
f'opener.closePopup(window, "{self.object.pk}", "{escapejs(str(self.object))}", "#{field_id}");'
|
||||||
|
f'</script>'
|
||||||
|
)
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
@@ -4637,14 +4654,15 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
|
|||||||
kwargs.update({"user": self.request.user})
|
kwargs.update({"user": self.request.user})
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
next_url = self.request.GET.get("next")
|
||||||
|
if next_url:
|
||||||
|
return next_url
|
||||||
|
return self.object.get_absolute_url()
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(AtlasCreateBase, self).get_context_data(**kwargs)
|
context = super(AtlasCreateBase, self).get_context_data(**kwargs)
|
||||||
if self.request.POST:
|
if self.request.POST:
|
||||||
# context["series_formset"] = SeriesFormSet(
|
|
||||||
# self.request.POST,
|
|
||||||
# self.request.FILES,
|
|
||||||
# form_kwargs={"user": self.request.user},
|
|
||||||
# )
|
|
||||||
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
||||||
self.request.POST, self.request.FILES
|
self.request.POST, self.request.FILES
|
||||||
)
|
)
|
||||||
@@ -4653,18 +4671,20 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
|
|||||||
self.request.FILES,
|
self.request.FILES,
|
||||||
form_kwargs={"user": self.request.user},
|
form_kwargs={"user": self.request.user},
|
||||||
)
|
)
|
||||||
# context["series_formset"].full_clean()
|
|
||||||
context["casedifferential_formset"].full_clean()
|
context["casedifferential_formset"].full_clean()
|
||||||
context["caseresource_formset"].full_clean()
|
context["caseresource_formset"].full_clean()
|
||||||
else:
|
else:
|
||||||
# context["series_formset"] = SeriesFormSet(instance=Case.objects.filter(author__id=self.request.user.id), queryset=Series.objects.filter(author__id=self.request.user.id))
|
|
||||||
# context["series_formset"] = SeriesFormSet(
|
|
||||||
# form_kwargs={"user": self.request.user}
|
|
||||||
# )
|
|
||||||
context["casedifferential_formset"] = CaseDifferentialFormSet()
|
context["casedifferential_formset"] = CaseDifferentialFormSet()
|
||||||
context["caseresource_formset"] = CaseResourceFormSet(
|
context["caseresource_formset"] = CaseResourceFormSet(
|
||||||
form_kwargs={"user": self.request.user}
|
form_kwargs={"user": self.request.user}
|
||||||
)
|
)
|
||||||
|
next_url = self.request.GET.get("next")
|
||||||
|
if not next_url:
|
||||||
|
if self.object and self.object.pk:
|
||||||
|
next_url = self.object.get_absolute_url()
|
||||||
|
else:
|
||||||
|
next_url = reverse("atlas:case_view")
|
||||||
|
context["next_url"] = next_url
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
@@ -4760,15 +4780,15 @@ class AtlasUpdate(
|
|||||||
kwargs.update({"user": self.request.user})
|
kwargs.update({"user": self.request.user})
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
next_url = self.request.GET.get("next")
|
||||||
|
if next_url:
|
||||||
|
return next_url
|
||||||
|
return self.object.get_absolute_url()
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(AtlasUpdate, self).get_context_data(**kwargs)
|
context = super(AtlasUpdate, self).get_context_data(**kwargs)
|
||||||
if self.request.POST:
|
if self.request.POST:
|
||||||
# context["series_formset"] = SeriesFormSet(
|
|
||||||
# self.request.POST,
|
|
||||||
# self.request.FILES,
|
|
||||||
# instance=self.object,
|
|
||||||
# form_kwargs={"user": self.request.user},
|
|
||||||
# )
|
|
||||||
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
||||||
self.request.POST, self.request.FILES, instance=self.object
|
self.request.POST, self.request.FILES, instance=self.object
|
||||||
)
|
)
|
||||||
@@ -4778,13 +4798,9 @@ class AtlasUpdate(
|
|||||||
instance=self.object,
|
instance=self.object,
|
||||||
form_kwargs={"user": self.request.user},
|
form_kwargs={"user": self.request.user},
|
||||||
)
|
)
|
||||||
# context["series_formset"].full_clean()
|
|
||||||
context["casedifferential_formset"].full_clean()
|
context["casedifferential_formset"].full_clean()
|
||||||
context["caseresource_formset"].full_clean()
|
context["caseresource_formset"].full_clean()
|
||||||
else:
|
else:
|
||||||
# context["series_formset"] = SeriesFormSet(
|
|
||||||
# instance=self.object, form_kwargs={"user": self.request.user}
|
|
||||||
# )
|
|
||||||
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
||||||
instance=self.object
|
instance=self.object
|
||||||
)
|
)
|
||||||
@@ -4792,6 +4808,13 @@ class AtlasUpdate(
|
|||||||
instance=self.object,
|
instance=self.object,
|
||||||
form_kwargs={"user": self.request.user},
|
form_kwargs={"user": self.request.user},
|
||||||
)
|
)
|
||||||
|
next_url = self.request.GET.get("next")
|
||||||
|
if not next_url:
|
||||||
|
if self.object and self.object.pk:
|
||||||
|
next_url = self.object.get_absolute_url()
|
||||||
|
else:
|
||||||
|
next_url = reverse("atlas:case_view")
|
||||||
|
context["next_url"] = next_url
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
@@ -4888,15 +4911,7 @@ class AtlasSeriesUpdate(
|
|||||||
queryset = Series.objects.filter(author__id=self.request.user.id)
|
queryset = Series.objects.filter(author__id=self.request.user.id)
|
||||||
else:
|
else:
|
||||||
queryset = Series.objects.all()
|
queryset = Series.objects.all()
|
||||||
queryset = queryset.select_related("modality").prefetch_related(
|
queryset = queryset.select_related("modality")
|
||||||
"examination",
|
|
||||||
"plane",
|
|
||||||
"contrast",
|
|
||||||
Prefetch(
|
|
||||||
"images",
|
|
||||||
queryset=SeriesImage.objects.filter(removed=False).order_by("position"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.request.POST:
|
if self.request.POST:
|
||||||
context["series_formset"] = SeriesFormSet(
|
context["series_formset"] = SeriesFormSet(
|
||||||
@@ -6216,6 +6231,32 @@ class SubspecialtyAutocomplete(autocomplete.Select2QuerySetView):
|
|||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
class SeriesAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
|
def get_queryset(self):
|
||||||
|
if not self.request.user.is_authenticated:
|
||||||
|
return Series.objects.none()
|
||||||
|
|
||||||
|
qs = Series.objects.all().select_related("modality")
|
||||||
|
|
||||||
|
is_atlas_editor = (
|
||||||
|
self.request.user.groups.filter(name="atlas_editor").exists()
|
||||||
|
or self.request.user.is_superuser
|
||||||
|
)
|
||||||
|
if not is_atlas_editor:
|
||||||
|
qs = qs.filter(author__id=self.request.user.id)
|
||||||
|
|
||||||
|
if self.q:
|
||||||
|
q_filter = Q(description__icontains=self.q) | Q(info__icontains=self.q)
|
||||||
|
if self.q.isdigit():
|
||||||
|
q_filter |= Q(pk=int(self.q))
|
||||||
|
qs = qs.filter(q_filter)
|
||||||
|
|
||||||
|
return qs
|
||||||
|
|
||||||
|
def get_result_label(self, result):
|
||||||
|
return f"Series {result.pk}: {result.description or ''} ({result.modality or ''})"
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @user_is_atlas_editor
|
# @user_is_atlas_editor
|
||||||
def categories_list(request):
|
def categories_list(request):
|
||||||
@@ -9871,6 +9912,63 @@ def case_toggle_resource_pre(request, pk):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def case_create_resource_inline(request, pk):
|
||||||
|
"""Create a new resource and attach it to the case (HTMX).
|
||||||
|
|
||||||
|
GET: Renders the inline form `ResourceForm`.
|
||||||
|
POST: Processes the form, saves new Resource, sets author, attaches to case,
|
||||||
|
and returns updated `atlas/partials/case_resources_list.html` partial.
|
||||||
|
"""
|
||||||
|
case = get_case_for_case_detail(pk)
|
||||||
|
if not case.check_user_can_edit(request.user):
|
||||||
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = ResourceForm(request.POST, request.FILES)
|
||||||
|
if form.is_valid():
|
||||||
|
resource = form.save(commit=False)
|
||||||
|
resource.save()
|
||||||
|
resource.author.add(request.user.id)
|
||||||
|
|
||||||
|
pre_review = request.POST.get("pre_review") == "on" or request.POST.get("pre_review") == "1"
|
||||||
|
CaseResource.objects.create(
|
||||||
|
case=case,
|
||||||
|
resource=resource,
|
||||||
|
pre_review=pre_review,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Refresh case from DB to render updated resources list
|
||||||
|
try:
|
||||||
|
case = Case.objects.get(pk=case.pk)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
html = render_to_string(
|
||||||
|
"atlas/partials/case_resources_list.html", {"case": case}, request=request
|
||||||
|
)
|
||||||
|
add_resource_button_html = (
|
||||||
|
f'<div id="resource-search-panel-placeholder" hx-swap-oob="true" class="d-inline-flex">'
|
||||||
|
f' <button class="btn btn-sm btn-outline-primary" '
|
||||||
|
f' hx-get="{reverse("atlas:resource_search_panel")}?case_id={case.pk}" '
|
||||||
|
f' hx-target="#resource-search-panel-placeholder" '
|
||||||
|
f' hx-swap="innerHTML"> '
|
||||||
|
f' Add Resource '
|
||||||
|
f' </button>'
|
||||||
|
f'</div>'
|
||||||
|
)
|
||||||
|
resp = HttpResponse(html + add_resource_button_html)
|
||||||
|
resp["HX-Trigger"] = json.dumps({"caseResourcesChanged": {"case_id": case.pk}})
|
||||||
|
return resp
|
||||||
|
else:
|
||||||
|
form = ResourceForm()
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"atlas/partials/case_create_resource_inline.html",
|
||||||
|
{"form": form, "case": case},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def series_dicom_json(request, pk):
|
def series_dicom_json(request, pk):
|
||||||
series = get_object_or_404(Series, pk=pk)
|
series = get_object_or_404(Series, pk=pk)
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ set -e
|
|||||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
cd "$REPO_ROOT"
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
docker compose -f docker/docker-compose.prod.yml -f docker/docker-compose.test.yml -f docker/docker-compose.dev.yml down --volumes --remove-orphans
|
docker compose -f docker/docker-compose.prod.yml -f docker/docker-compose.local.yml -f docker/docker-compose.test.yml -f docker/docker-compose.dev.yml down --volumes --remove-orphans
|
||||||
|
|||||||
@@ -123,6 +123,15 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Stop and clean up any running containers/networks to prevent conflicts (especially if local db/cache are running)
|
||||||
|
echo "Stopping any existing compose services to prevent network conflicts..."
|
||||||
|
COMPOSE_ENV=$COMPOSE_ENV docker compose \
|
||||||
|
-f docker/docker-compose.prod.yml \
|
||||||
|
-f docker/docker-compose.local.yml \
|
||||||
|
-f docker/docker-compose.test.yml \
|
||||||
|
-f docker/docker-compose.dev.yml \
|
||||||
|
down || true
|
||||||
|
|
||||||
if [ "$NO_BUILD" -eq 1 ]; then
|
if [ "$NO_BUILD" -eq 1 ]; then
|
||||||
COMPOSE_ENV=$COMPOSE_ENV docker compose -f docker/docker-compose.prod.yml -f docker/docker-compose.dev.yml up
|
COMPOSE_ENV=$COMPOSE_ENV docker compose -f docker/docker-compose.prod.yml -f docker/docker-compose.dev.yml up
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user