endoreg-db 0.6.2__py3-none-any.whl → 0.6.4__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.

Potentially problematic release.


This version of endoreg-db might be problematic. Click here for more details.

Files changed (97) hide show
  1. endoreg_db/data/__init__.py +14 -0
  2. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +2 -2
  3. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +6 -6
  4. endoreg_db/data/distribution/numeric/data.yaml +1 -1
  5. endoreg_db/data/examination/examinations/data.yaml +22 -21
  6. endoreg_db/data/examination/type/data.yaml +12 -0
  7. endoreg_db/data/examination_indication/endoscopy.yaml +417 -1
  8. endoreg_db/data/examination_indication_classification/endoscopy.yaml +157 -5
  9. endoreg_db/data/finding/data.yaml +18 -11
  10. endoreg_db/data/finding_intervention/endoscopy.yaml +26 -121
  11. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +163 -0
  12. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
  13. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
  14. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
  15. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
  16. endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
  17. endoreg_db/data/medication_indication/anticoagulation.yaml +4 -4
  18. endoreg_db/data/pdf_type/data.yaml +9 -16
  19. endoreg_db/data/requirement/colonoscopy_indications.yaml +56 -0
  20. endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
  21. endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +38 -0
  22. endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
  23. endoreg_db/data/requirement/disease_misc.yaml +12 -0
  24. endoreg_db/data/requirement/disease_renal.yaml +80 -0
  25. endoreg_db/data/requirement/event_cardiology.yaml +251 -0
  26. endoreg_db/data/requirement/lab_value.yaml +120 -0
  27. endoreg_db/data/requirement_operator/lab_operators.yaml +128 -0
  28. endoreg_db/data/requirement_operator/model_operators.yaml +90 -0
  29. endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +12 -0
  30. endoreg_db/data/requirement_set_type/data.yaml +20 -0
  31. endoreg_db/data/requirement_type/requirement_types.yaml +83 -0
  32. endoreg_db/data/risk/bleeding.yaml +26 -0
  33. endoreg_db/data/risk/thrombosis.yaml +37 -0
  34. endoreg_db/data/risk_type/data.yaml +27 -0
  35. endoreg_db/data/unit/time.yaml +36 -1
  36. endoreg_db/management/commands/load_base_db_data.py +14 -1
  37. endoreg_db/management/commands/load_center_data.py +46 -21
  38. endoreg_db/management/commands/load_examination_indication_data.py +49 -27
  39. endoreg_db/management/commands/load_requirement_data.py +156 -0
  40. endoreg_db/management/commands/load_risk_data.py +56 -0
  41. endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
  42. endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
  43. endoreg_db/mermaid/binary_classification_annotation.md +50 -0
  44. endoreg_db/mermaid/classification.md +8 -0
  45. endoreg_db/mermaid/examination.md +8 -0
  46. endoreg_db/mermaid/findings.md +7 -0
  47. endoreg_db/mermaid/image_classification.md +28 -0
  48. endoreg_db/mermaid/interventions.md +8 -0
  49. endoreg_db/mermaid/morphology.md +8 -0
  50. endoreg_db/mermaid/patient_creation.md +14 -0
  51. endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
  52. endoreg_db/migrations/0009_requirementoperator_requirementsettype_and_more.py +154 -0
  53. endoreg_db/models/__init__.py +20 -0
  54. endoreg_db/models/ai_model/ai_model.py +0 -13
  55. endoreg_db/models/ai_model/model_meta.py +2 -12
  56. endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -2
  57. endoreg_db/models/data_file/base_classes/abstract_pdf.py +0 -9
  58. endoreg_db/models/data_file/base_classes/abstract_video.py +7 -8
  59. endoreg_db/models/data_file/base_classes/utils.py +0 -22
  60. endoreg_db/models/data_file/frame.py +1 -1
  61. endoreg_db/models/data_file/import_classes/raw_pdf.py +5 -11
  62. endoreg_db/models/data_file/import_classes/raw_video.py +6 -4
  63. endoreg_db/models/data_file/video/video.py +3 -3
  64. endoreg_db/models/disease.py +88 -19
  65. endoreg_db/models/event.py +108 -21
  66. endoreg_db/models/examination/examination_indication.py +108 -29
  67. endoreg_db/models/examination/examination_type.py +20 -6
  68. endoreg_db/models/information_source.py +37 -1
  69. endoreg_db/models/laboratory/lab_value.py +83 -32
  70. endoreg_db/models/requirement/__init__.py +11 -0
  71. endoreg_db/models/requirement/requirement.py +325 -0
  72. endoreg_db/models/requirement/requirement_evaluation/__init__.py +134 -0
  73. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +102 -0
  74. endoreg_db/models/requirement/requirement_operator.py +58 -0
  75. endoreg_db/models/requirement/requirement_set.py +127 -0
  76. endoreg_db/models/risk/__init__.py +7 -0
  77. endoreg_db/models/risk/risk.py +72 -0
  78. endoreg_db/models/risk/risk_type.py +55 -0
  79. endoreg_db/serializers/raw_pdf_anony_text_validation.py +137 -0
  80. endoreg_db/serializers/raw_pdf_meta_validation.py +223 -0
  81. endoreg_db/serializers/raw_video_meta_validation.py +163 -1
  82. endoreg_db/serializers/video_segmentation.py +208 -126
  83. endoreg_db/urls.py +127 -14
  84. endoreg_db/utils/__init__.py +43 -0
  85. endoreg_db/utils/dataloader.py +38 -19
  86. endoreg_db/utils/hashs.py +1 -0
  87. endoreg_db/utils/paths.py +86 -0
  88. endoreg_db/views/raw_pdf_anony_text_validation_views.py +95 -0
  89. endoreg_db/views/raw_pdf_meta_validation_views.py +111 -0
  90. endoreg_db/views/raw_video_meta_validation_views.py +128 -18
  91. endoreg_db/views/video_segmentation_views.py +28 -11
  92. endoreg_db/views/views.py +107 -0
  93. {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/METADATA +1 -1
  94. {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/RECORD +96 -46
  95. endoreg_db/management/commands/load_name_data.py +0 -37
  96. {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/WHEEL +0 -0
  97. {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,102 @@
1
+ # Currently those strings MUST match the ones
2
+ # in the requirement_type data definitions
3
+ from collections import namedtuple
4
+ from endoreg_db.models import (
5
+ Requirement,
6
+ RequirementType,
7
+ PatientExamination,
8
+ PatientFindingIntervention,
9
+ Examination,
10
+ ExaminationIndication,
11
+ Disease,
12
+ DiseaseClassificationChoice,
13
+ PatientEvent,
14
+ PatientFinding,
15
+ PatientFindingMorphology,
16
+ )
17
+ from typing import List
18
+ from icecream import ic
19
+ # Requirement has RequirementTypes
20
+ # Requirement has RequirementOperators
21
+ # For each Operator/Type pair, there must be a custom function
22
+ # for evaluation
23
+
24
+ OperatorTypeTuple = namedtuple("OperatorTypeTuple", ["operator", "requirement_type"])
25
+
26
+
27
+ data_model_dict = {
28
+ "patient_examination": PatientExamination,
29
+ "finding_intervention": PatientFindingIntervention,
30
+ "finding_interventions": List[PatientFindingIntervention],
31
+ "examination": Examination,
32
+ "examination_indication": ExaminationIndication,
33
+ "disease": Disease,
34
+ "disease_classification_choice": DiseaseClassificationChoice,
35
+ "event": PatientEvent,
36
+ "finding": PatientFinding,
37
+ "finding_morphology": PatientFindingMorphology,
38
+ # Add more mappings as needed
39
+ }
40
+
41
+
42
+ def evaluate_operator_type_tuple(
43
+ operator_type_tuple: OperatorTypeTuple, data: object, **kwargs
44
+ ):
45
+ """
46
+ Evaluates the requirement type and operator tuple against the provided data.
47
+
48
+ Args:
49
+ operator_type_tuple (OperatorTypeTuple): Tuple containing requirement type and operator.
50
+ data (object): The data to evaluate.
51
+ **kwargs: Additional keyword arguments.
52
+
53
+ Returns:
54
+ bool: True if the evaluation is successful, False otherwise.
55
+ """
56
+ # data = kwargs.get(name, None)
57
+
58
+ # # make sure data type matches the model for the req_type name
59
+ # if data is None:
60
+ # raise ValueError(f"No data found for requirement type: {name}")
61
+ # if name not in data_model_dict:
62
+ # raise ValueError(f"Unknown requirement type: {name}")
63
+
64
+ # model = data_model_dict[name]
65
+ # if not isinstance(data, model):
66
+ # raise TypeError(
67
+ # f"Data type mismatch for {name}: expected {model}, got {type(data)}"
68
+ # )
69
+
70
+ requirement_type = operator_type_tuple.requirement_type
71
+ operator = operator_type_tuple.operator
72
+
73
+ # Call the appropriate function based on the requirement type and operator
74
+ # This is a placeholder; actual implementation will depend on your logic
75
+ return True # Replace with actual evaluation logic
76
+
77
+
78
+ def evaluate_requirement(requirement: Requirement, **kwargs):
79
+ requirement_types = requirement.requirement_types.all()
80
+ requirement_operators = requirement.operators.all()
81
+ operator_return_values = {}
82
+ operator_evaluation_results = {}
83
+
84
+ for requirement_operator in requirement_operators:
85
+ # Create tuples
86
+ requirement_type_operator_tuples = [
87
+ OperatorTypeTuple(requirement_operator, rt) for ro in requirement_types
88
+ ]
89
+
90
+ eval_result = [
91
+ evaluate_operator_type_tuple(t, **kwargs)
92
+ for t in requirement_type_operator_tuples
93
+ ]
94
+
95
+ operator_evaluation_results[requirement_operator.name] = eval_result
96
+
97
+ # TODO FIX
98
+ operator_return_values[requirement_operator.name] = (
99
+ requirement_operator.evaluate_return_values()
100
+ )
101
+
102
+ return operator_evaluation_results, operator_return_values
@@ -0,0 +1,58 @@
1
+ from django.db import models
2
+ from typing import TYPE_CHECKING
3
+
4
+
5
+ class RequirementOperatorManager(models.Manager):
6
+ def get_by_natural_key(self, name):
7
+ """
8
+ Retrieve a RequirementOperator instance by its natural key.
9
+
10
+ Args:
11
+ name (str): The unique name representing the natural key.
12
+
13
+ Returns:
14
+ RequirementOperator: The model instance matching the provided name.
15
+ """
16
+ return self.get(name=name)
17
+
18
+
19
+ class RequirementOperator(models.Model):
20
+ """
21
+ A class representing a requirement operator.
22
+
23
+ Attributes:
24
+ name (str): The name of the requirement operator.
25
+ name_de (str): The German name of the requirement operator.
26
+ name_en (str): The English name of the requirement operator.
27
+ description (str): A description of the requirement operator.
28
+ """
29
+
30
+ name = models.CharField(max_length=100, unique=True)
31
+ name_de = models.CharField(max_length=100, blank=True, null=True)
32
+ name_en = models.CharField(max_length=100, blank=True, null=True)
33
+ description = models.TextField(blank=True, null=True)
34
+
35
+ objects = RequirementOperatorManager()
36
+
37
+ if TYPE_CHECKING:
38
+ from endoreg_db.models.requirement.requirement import Requirement
39
+
40
+ requirements: models.QuerySet[Requirement]
41
+
42
+ def natural_key(self):
43
+ """
44
+ Return the natural key for the requirement operator.
45
+
46
+ This method returns a tuple containing the operator's name, which serves as its
47
+ natural key for serialization and unique identification within the system.
48
+ """
49
+ return (self.name,)
50
+
51
+ def __str__(self):
52
+ """
53
+ Return the string representation of the requirement operator.
54
+
55
+ Returns:
56
+ str: The name attribute of the operator.
57
+ """
58
+ return str(self.name)
@@ -0,0 +1,127 @@
1
+ from django.db import models
2
+ from typing import TYPE_CHECKING
3
+
4
+
5
+ class RequirementSetTypeManager(models.Manager):
6
+ """
7
+ Manager for RequirementSetType with custom query methods.
8
+ """
9
+
10
+ def get_by_natural_key(self, name: str) -> "RequirementSetType":
11
+ """
12
+ Retrieves a RequirementSetType instance using its natural key.
13
+
14
+ Args:
15
+ name (str): The unique name that serves as the natural key.
16
+
17
+ Returns:
18
+ RequirementSetType: The matching RequirementSetType instance.
19
+ """
20
+ return self.get(name=name)
21
+
22
+
23
+ class RequirementSetType(models.Model):
24
+ """
25
+ A class representing a type of requirement set.
26
+
27
+ Attributes:
28
+ name (str): The name of the requirement set type.
29
+ name_de (str): The German name of the requirement set type.
30
+ name_en (str): The English name of the requirement set type.
31
+ """
32
+
33
+ name = models.CharField(max_length=100, unique=True)
34
+ name_de = models.CharField(max_length=100, blank=True, null=True)
35
+ name_en = models.CharField(max_length=100, blank=True, null=True)
36
+ description = models.TextField(blank=True, null=True)
37
+
38
+ objects = RequirementSetTypeManager()
39
+
40
+ if TYPE_CHECKING:
41
+ from endoreg_db.models.requirement import RequirementType
42
+
43
+ requirement_types: models.QuerySet[RequirementType]
44
+
45
+ def natural_key(self):
46
+ """
47
+ Return the natural key tuple for the instance.
48
+
49
+ Returns:
50
+ tuple: A one-element tuple containing the instance's name, used as its natural key.
51
+ """
52
+ return (self.name,)
53
+
54
+
55
+ class RequirementSetManager(models.Manager):
56
+ def get_by_natural_key(self, name):
57
+ """
58
+ Retrieves a model instance by its natural key.
59
+
60
+ Args:
61
+ name: The natural key value, typically corresponding to the model's unique name.
62
+
63
+ Returns:
64
+ The model instance whose name matches the provided natural key.
65
+ """
66
+ return self.get(name=name)
67
+
68
+
69
+ class RequirementSet(models.Model):
70
+ """
71
+ A class representing a set of requirements.
72
+
73
+ Attributes:
74
+ name (str): The name of the requirement set.
75
+ name_de (str): The German name of the requirement set.
76
+ name_en (str): The English name of the requirement set.
77
+ description (str): A description of the requirement set.
78
+ """
79
+
80
+ name = models.CharField(max_length=100, unique=True)
81
+ name_de = models.CharField(max_length=100, blank=True, null=True)
82
+ name_en = models.CharField(max_length=100, blank=True, null=True)
83
+ description = models.TextField(blank=True, null=True)
84
+ requirements = models.ManyToManyField(
85
+ "Requirement",
86
+ blank=True,
87
+ related_name="requirement_sets",
88
+ )
89
+ links_to_sets = models.ManyToManyField(
90
+ "RequirementSet",
91
+ blank=True,
92
+ related_name="links_from_sets",
93
+ )
94
+ requirement_set_type = models.ForeignKey(
95
+ "RequirementSetType",
96
+ on_delete=models.CASCADE,
97
+ related_name="requirement_sets",
98
+ blank=True,
99
+ null=True,
100
+ )
101
+ information_sources = models.ManyToManyField(
102
+ "InformationSource",
103
+ related_name="requirement_sets",
104
+ blank=True,
105
+ )
106
+ objects = RequirementSetManager()
107
+
108
+ if TYPE_CHECKING:
109
+ from endoreg_db.models import Requirement, InformationSource
110
+
111
+ requirements: models.QuerySet[Requirement]
112
+ information_source: InformationSource
113
+ requirement_set_type: RequirementSetType
114
+ linked_sets: models.QuerySet["RequirementSet"]
115
+
116
+ def natural_key(self):
117
+ """Return the natural key as a tuple containing the instance's name."""
118
+ return (self.name,)
119
+
120
+ def __str__(self):
121
+ """
122
+ Return the string representation of the requirement set.
123
+
124
+ Returns:
125
+ str: The name of the requirement set.
126
+ """
127
+ return str(self.name)
@@ -0,0 +1,7 @@
1
+ from .risk import Risk
2
+ from .risk_type import RiskType
3
+
4
+ __all__ = [
5
+ "Risk",
6
+ "RiskType",
7
+ ]
@@ -0,0 +1,72 @@
1
+ from django.db import models
2
+ from typing import List, TYPE_CHECKING
3
+
4
+
5
+ class RiskManager(models.Manager):
6
+ def get_by_natural_key(self, name):
7
+ """
8
+ Retrieve a risk instance using its natural key.
9
+
10
+ Args:
11
+ name: The unique name identifying the risk instance.
12
+
13
+ Returns:
14
+ The risk instance with the matching name.
15
+ """
16
+ return self.get(name=name)
17
+
18
+
19
+ class Risk(models.Model):
20
+ """
21
+ A class representing a risk.
22
+
23
+ Attributes:
24
+ name (str): The name of the risk.
25
+ name_de (str): The German name of the risk.
26
+ name_en (str): The English name of the risk.
27
+ description (str): A description of the risk.
28
+ """
29
+
30
+ name = models.CharField(max_length=100, unique=True)
31
+ name_de = models.CharField(max_length=100, blank=True, null=True)
32
+ name_en = models.CharField(max_length=100, blank=True, null=True)
33
+ description = models.TextField(blank=True, null=True)
34
+
35
+ risk_value = models.FloatField(
36
+ blank=True,
37
+ null=True,
38
+ help_text="Risk value for the risk. If not set, the risk is not used in calculations.",
39
+ )
40
+
41
+ risk_type = models.ForeignKey(
42
+ "RiskType",
43
+ on_delete=models.CASCADE,
44
+ related_name="risks",
45
+ blank=True,
46
+ null=True,
47
+ )
48
+
49
+ objects = RiskManager()
50
+
51
+ if TYPE_CHECKING:
52
+ from endoreg_db.models.risk.risk_type import RiskType
53
+
54
+ risk_types: RiskType
55
+
56
+ def natural_key(self):
57
+ """
58
+ Return a tuple containing the natural key of the risk instance.
59
+
60
+ The tuple consists of the unique 'name' attribute, which enables natural key lookups
61
+ and serialization within Django.
62
+ """
63
+ return (self.name,)
64
+
65
+ def __str__(self):
66
+ """
67
+ Return the string representation of the risk.
68
+
69
+ Returns:
70
+ str: The risk's name.
71
+ """
72
+ return str(self.name)
@@ -0,0 +1,55 @@
1
+ from django.db import models
2
+ from typing import TYPE_CHECKING
3
+
4
+
5
+ class RiskTypeManager(models.Manager):
6
+ def get_by_natural_key(self, name):
7
+ """
8
+ Retrieves a RiskType instance using its natural key.
9
+
10
+ Args:
11
+ name (str): The unique name identifying the RiskType instance.
12
+
13
+ Returns:
14
+ RiskType: The matching instance with the provided name.
15
+ """
16
+ return self.get(name=name)
17
+
18
+
19
+ class RiskType(models.Model):
20
+ """
21
+ A class representing a risk type.
22
+
23
+ Attributes:
24
+ name (str): The name of the risk type.
25
+ name_de (str): The German name of the risk type.
26
+ name_en (str): The English name of the risk type.
27
+ description (str): A description of the risk type.
28
+ """
29
+
30
+ name = models.CharField(max_length=100, unique=True)
31
+ name_de = models.CharField(max_length=100, blank=True, null=True)
32
+ name_en = models.CharField(max_length=100, blank=True, null=True)
33
+ description = models.TextField(blank=True, null=True)
34
+
35
+ objects = RiskTypeManager()
36
+
37
+ if TYPE_CHECKING:
38
+ from endoreg_db.models.risk.risk import Risk
39
+
40
+ risks: models.QuerySet[Risk]
41
+
42
+ def natural_key(self):
43
+ """
44
+ Return the natural key for this risk type.
45
+
46
+ This method returns a tuple containing only the risk type's unique name, which is used
47
+ to identify the instance naturally.
48
+ """
49
+ return (self.name,)
50
+
51
+ def __str__(self):
52
+ """
53
+ Return the risk type's name as its string representation.
54
+ """
55
+ return str(self.name)
@@ -0,0 +1,137 @@
1
+ from pathlib import Path
2
+ from rest_framework import serializers
3
+ from django.conf import settings
4
+ from ..models import RawPdfFile
5
+
6
+ class RawPdfAnonyTextSerializer(serializers.ModelSerializer):
7
+ """
8
+ Serializer to fetch PDF metadata along with `anonymized_text` from `RawPdfFile`.
9
+ Ensures Vue.js can process JSON efficiently.
10
+ """
11
+
12
+ pdf_url = serializers.SerializerMethodField()
13
+ full_pdf_path = serializers.SerializerMethodField()
14
+ file = serializers.SerializerMethodField()
15
+
16
+ class Meta:
17
+ model = RawPdfFile
18
+ fields = ['id', 'file', 'pdf_url', 'full_pdf_path',
19
+ 'sensitive_meta_id', 'anonymized_text']
20
+
21
+ @staticmethod
22
+ def get_next_pdf(last_id=None):
23
+ """
24
+ Retrieves the first available PDF if `last_id` is NOT provided.
25
+ Otherwise, fetches the next available PDF where `id > last_id`.
26
+ """
27
+ query_filter = {} if last_id is None else {"id__gt": int(last_id)}
28
+ pdf_entry = RawPdfFile.objects.filter(**query_filter).order_by('id').first()
29
+ return pdf_entry
30
+
31
+ def get_pdf_url(self, obj):
32
+ """
33
+ Generates the full URL where Vue.js can fetch and display the PDF.
34
+ """
35
+ request = self.context.get('request')
36
+ return request.build_absolute_uri(f"/api/pdf/anony_text/?id={obj.id}") if request and obj.file else None
37
+
38
+ def get_file(self, obj):
39
+ """
40
+ Returns the relative file path stored in the database.
41
+ """
42
+ return str(obj.file.name).strip() if obj.file else None
43
+
44
+ def get_full_pdf_path(self, obj):
45
+ """
46
+ Constructs the full absolute file path using `settings.MEDIA_ROOT`.
47
+ """
48
+ if not obj.file:
49
+ return None
50
+ pdf_relative_path = str(obj.file.name)
51
+ full_path = Path(settings.MEDIA_ROOT) / pdf_relative_path
52
+ return str(full_path) if full_path.exists() else None
53
+
54
+ def validate_anonymized_text(self, value):
55
+ """
56
+ Ensures the anonymized_text is not empty or too long.
57
+ """
58
+ if not value.strip():
59
+ raise serializers.ValidationError("Anonymized text cannot be empty.")
60
+ if len(value) > 5000: # Arbitrary limit to prevent excessively long text
61
+ raise serializers.ValidationError("Anonymized text exceeds the maximum length of 5000 characters.")
62
+ return value
63
+
64
+ def update(self, instance, validated_data):
65
+ """
66
+ Updates only `anonymized_text` without modifying other fields.
67
+ """
68
+ instance.anonymized_text = validated_data.get('anonymized_text', instance.anonymized_text)
69
+ instance.save()
70
+ return instance
71
+
72
+
73
+
74
+ """
75
+ await import('https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js');
76
+
77
+ const fetchPdfWithAnonymizedText = async (lastId = null) => {
78
+ const url = lastId
79
+ ? `http://localhost:8000/api/pdf/anony_text/?last_id=${lastId}`
80
+ : "http://localhost:8000/api/pdf/anony_text/";
81
+
82
+ try {
83
+ const response = await axios.get(url, { headers: { "Accept": "application/json" } });
84
+ console.log("PDF Data:", response.data);
85
+ } catch (error) {
86
+ console.error("Error fetching PDF:", error.response?.data || error);
87
+ }
88
+ };
89
+
90
+ fetchPdfWithAnonymizedText();
91
+
92
+ """
93
+
94
+ """
95
+ await import('https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js');
96
+
97
+ const updateAnonymizedText = async (pdfId, newText) => {
98
+ try {
99
+ const response = await axios.patch("http://localhost:8000/api/pdf/update_anony_text/", {
100
+ id: pdfId,
101
+ anonymized_text: newText
102
+ }, { headers: { "Content-Type": "application/json" } });
103
+
104
+ console.log("Update Success:", response.data);
105
+ } catch (error) {
106
+ console.error("Update Error:", error.response?.data || error);
107
+ }
108
+ };
109
+
110
+ updateAnonymizedText(1, "Updated anonymized text.");
111
+
112
+ """
113
+
114
+ """
115
+ await import('https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js');
116
+
117
+ const updateAnonymizedText = async () => {
118
+ const updatedData = {
119
+ id: 1,
120
+ anonymized_text: "This is the updated anonymized text."
121
+ };
122
+
123
+ try {
124
+ const response = await axios.patch("http://localhost:8000/api/pdf/update_anony_text/", updatedData, {
125
+ headers: { "Content-Type": "application/json" }
126
+ });
127
+
128
+ console.log("Update Success:", response.data);
129
+ alert("Anonymized text updated successfully!");
130
+ } catch (error) {
131
+ console.error("Update Error:", error.response?.data || error);
132
+ alert("Failed to update anonymized text.");
133
+ }
134
+ };
135
+
136
+ updateAnonymizedText();
137
+ """