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

Upload feature #80

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ccb2f87
copy upload files into branch
lmdulz Aug 28, 2024
ffd15d1
deleted a comment
lmdulz Aug 28, 2024
09b86eb
delete package-lock.json and package.json files
lmdulz Aug 28, 2024
e27f800
parse seed env variable for Anonymizer to Javascript
lmdulz Aug 29, 2024
c257f0c
cleanup for CI
lmdulz Sep 2, 2024
ef10a09
Merge remote-tracking branch 'origin/main' into upload_dev
lmdulz Sep 2, 2024
d884d2a
Use model pk instead of id and adapt to upgraded packages
lmdulz Sep 2, 2024
34b4174
adapt tests to package updates
lmdulz Sep 2, 2024
eddce09
adjust upload tests for CI
lmdulz Sep 4, 2024
3dc574a
integrate UploadPermissionSupport into existing UploadSettings
lmdulz Oct 10, 2024
49eb7fc
update adit_radis_shared
lmdulz Oct 10, 2024
9d25903
update dicom-wab-anonymizer
lmdulz Oct 10, 2024
7d2eeb5
package-lock.json
lmdulz Oct 10, 2024
70791be
add type assertions, adaption to updated Anonymizer, adapt series dic…
lmdulz Oct 10, 2024
cb3326b
upgrade adit-radis-shared
lmdulz Oct 10, 2024
2ecaadd
Merge branch 'main' into upload_dev
lmdulz Oct 19, 2024
0249f23
create initial migration fopr upload app
lmdulz Oct 19, 2024
f119d70
delete update task bc of renovate usage
lmdulz Oct 23, 2024
f77f744
Merge branch 'main' into upload_dev
medihack Dec 20, 2024
38d9471
Exclude async views from test
medihack Dec 24, 2024
2dfe48e
Improve integration upload tests
medihack Dec 25, 2024
ed071a3
Merge branch 'main' into upload_dev
medihack Dec 25, 2024
a1c062b
Move fixtures to helpers
medihack Dec 25, 2024
0e63308
Use correct type hint
medihack Dec 25, 2024
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
3 changes: 3 additions & 0 deletions adit/core/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ def create_option(self, name, value, label, selected, index, subindex=None, attr
dicom_node = value.instance
if dicom_node.node_type == DicomNode.NodeType.SERVER:
option["attrs"]["data-node_type"] = "server"
option["attrs"]["data-node_id"] = dicom_node.id
elif dicom_node.node_type == DicomNode.NodeType.FOLDER:
option["attrs"]["data-node_type"] = "folder"
option["attrs"]["data-node_id"] = dicom_node.id

return option

4 changes: 4 additions & 0 deletions adit/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"adit.batch_transfer.apps.BatchTransferConfig",
"adit.dicom_explorer.apps.DicomExplorerConfig",
"adit.dicom_web.apps.DicomWebConfig",
"adit.upload.apps.UploadConfig",
"channels",
]

Expand Down Expand Up @@ -434,3 +435,6 @@
"StudyDate",
"StudyTime",
]

# Secret seed for Patient data anonymization
ANONYMIZATION_SEED = env.str("ANONYMIZATION_SEED", default="") # type: ignore
Empty file added adit/upload/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions adit/upload/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.contrib import admin

# Register your models here.
from .models import UploadSettings

admin.site.register(UploadSettings, admin.ModelAdmin)
29 changes: 29 additions & 0 deletions adit/upload/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from django.apps import AppConfig

SECTION_NAME = "DICOM Upload"


class UploadConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "adit.upload"

def ready(self):
register_app()


def register_app():
from adit_radis_shared.common.site import MainMenuItem, register_main_menu_item

register_main_menu_item(
MainMenuItem(
url_name="upload_create",
label=SECTION_NAME,
)
)


def create_app_settings():
from .models import UploadSettings

if not UploadSettings.objects.exists():
UploadSettings.objects.create()
90 changes: 90 additions & 0 deletions adit/upload/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Column, Div, Field, Layout, Row
from django import forms

from adit.core.fields import DicomNodeChoiceField
from adit.core.validators import no_backslash_char_validator, no_control_chars_validator


class MultipleFileInput(forms.widgets.FileInput):
def __init__(self, attrs=None):
attrs = attrs or {}
attrs["onchange"] = "chooseFolder(event)"
attrs["webkitdirectory"] = True
attrs["directory"] = True
attrs["multiple"] = True
super().__init__(attrs)


class UploadForm(forms.Form):
pseudonym = forms.CharField(
required=True,
max_length=64,
validators=[no_backslash_char_validator, no_control_chars_validator],
label="Patient Pseudonym",
)

def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user")
self.action = kwargs.pop("action")

super().__init__(*args, **kwargs)

self.fields["destination"] = DicomNodeChoiceField("destination", self.user)
self.fields["pseudonym"].required = True
self.fields["destination"].required = True
self.helper = FormHelper(self)
form_fields_layout = self.build_query_form_layout()

# We swap the form using the htmx alpine-morph extension to retain the focus on the input
self.helper.layout = Layout(
Div(
form_fields_layout,
css_id="form_fields",
),
)
self.helper.form_action = ""
self.helper.attrs = {
"x-init": "initUploadForm($el)",
"id": "myForm",
"hx-ext": "alpine-morph",
"hx-post": "",
"method": "post",
"hx-trigger": "submit",
"hx-swap-oob": "true",
"action": "",
"novalidate": "",
"enctype": "multipart/form-data",
}

def build_query_form_layout(self):
query_form_layout = Layout(
Div(
Row(
Column(
self.build_option_field(
"pseudonym",
)
),
Column(
Field(
"destination",
**{
"x-init": "initDestination($el)",
"@change": "onDestinationChange($event)",
},
)
),
),
css_id="form_partial",
)
)

return query_form_layout

def build_option_field(self, field_name, additional_attrs=None):
attrs = {"@keydown.enter.prevent": ""}
if additional_attrs:
attrs = {**additional_attrs, **attrs}

return Column(Field(field_name, **attrs))
36 changes: 36 additions & 0 deletions adit/upload/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 5.0.7 on 2024-08-28 14:46

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='UploadPermissionSupport',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
options={
'permissions': [('can_upload_data', 'Can upload data')],
'managed': False,
'default_permissions': (),
},
),
migrations.CreateModel(
name='UploadSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('locked', models.BooleanField(default=False)),
('suspended', models.BooleanField(default=False)),
],
options={
'verbose_name_plural': 'Upload settings',
},
),
]
Empty file.
20 changes: 20 additions & 0 deletions adit/upload/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.db import models

from adit.core.models import DicomAppSettings


class UploadSettings(DicomAppSettings):
class Meta:
verbose_name_plural = "Upload settings"


class UploadPermissionSupport(models.Model):
class Meta:
managed = False
default_permissions = ()
permissions = [
("can_upload_data", "Can upload data"),
lmdulz marked this conversation as resolved.
Show resolved Hide resolved
]

def __str__(self) -> str:
return f"{self.__class__.__name__} [{self.pk}]"
Loading
Loading