diff --git a/backend/core/migrations/0042_asset_filtering_labels.py b/backend/core/migrations/0042_asset_filtering_labels.py new file mode 100644 index 000000000..becd9fca4 --- /dev/null +++ b/backend/core/migrations/0042_asset_filtering_labels.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.1 on 2024-11-28 10:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0041_add_ref_id_to_project_appliedcontrol_assessment"), + ] + + operations = [ + migrations.AddField( + model_name="asset", + name="filtering_labels", + field=models.ManyToManyField( + blank=True, to="core.filteringlabel", verbose_name="Labels" + ), + ), + ] diff --git a/backend/core/models.py b/backend/core/models.py index 718f8c0d6..474c5f4db 100644 --- a/backend/core/models.py +++ b/backend/core/models.py @@ -1206,7 +1206,9 @@ def __str__(self): return self.folder.name + "/" + self.name -class Asset(NameDescriptionMixin, FolderMixin, PublishInRootFolderMixin): +class Asset( + NameDescriptionMixin, FolderMixin, PublishInRootFolderMixin, FilteringLabelMixin +): class Type(models.TextChoices): """ The type of the asset. diff --git a/backend/core/serializers.py b/backend/core/serializers.py index ae341bda7..e42d8c9e2 100644 --- a/backend/core/serializers.py +++ b/backend/core/serializers.py @@ -230,7 +230,7 @@ class AssetReadSerializer(AssetWriteSerializer): disaster_recovery_objectives = serializers.JSONField( source="get_disaster_recovery_objectives_display" ) - + filtering_labels = FieldsRelatedField(["folder"], many=True) type = serializers.CharField(source="get_type_display") diff --git a/backend/core/views.py b/backend/core/views.py index b1b009c3e..2eb4fcb0c 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -151,12 +151,36 @@ def _process_request_data(self, request: Request) -> None: elif not request.data[field][0]: request.data[field] = [] + def _process_labels(self, labels): + """ + Creates a FilteringLabel and replaces the value with the ID of the newly created label. + """ + new_labels = [] + for label in labels: + try: + uuid.UUID(label, version=4) + new_labels.append(label) + except ValueError: + new_label = FilteringLabel(label=label) + new_label.full_clean() + new_label.save() + new_labels.append(str(new_label.id)) + return new_labels + def create(self, request: Request, *args, **kwargs) -> Response: self._process_request_data(request) + if request.data.get("filtering_labels"): + request.data["filtering_labels"] = self._process_labels( + request.data["filtering_labels"] + ) return super().create(request, *args, **kwargs) def update(self, request: Request, *args, **kwargs) -> Response: self._process_request_data(request) + if request.data.get("filtering_labels"): + request.data["filtering_labels"] = self._process_labels( + request.data["filtering_labels"] + ) return super().update(request, *args, **kwargs) def partial_update(self, request: Request, *args, **kwargs) -> Response: @@ -448,34 +472,6 @@ class VulnerabilityViewSet(BaseModelViewSet): def status(self, request): return Response(dict(Vulnerability.Status.choices)) - def _process_labels(self, labels): - """ - Creates a FilteringLabel and replaces the value with the ID of the newly created label. - """ - new_labels = [] - for label in labels: - try: - uuid.UUID(label, version=4) - new_labels.append(label) - except ValueError: - new_label = FilteringLabel(label=label) - new_label.full_clean() - new_label.save() - new_labels.append(str(new_label.id)) - return new_labels - - def update(self, request: Request, *args, **kwargs) -> Response: - request.data["filtering_labels"] = self._process_labels( - request.data["filtering_labels"] - ) - return super().update(request, *args, **kwargs) - - def create(self, request: Request, *args, **kwargs) -> Response: - request.data["filtering_labels"] = self._process_labels( - request.data["filtering_labels"] - ) - return super().create(request, *args, **kwargs) - class FilteringLabelViewSet(BaseModelViewSet): """ diff --git a/frontend/src/lib/components/Forms/AutocompleteSelect.svelte b/frontend/src/lib/components/Forms/AutocompleteSelect.svelte index 55b5d1727..8e71e96f4 100644 --- a/frontend/src/lib/components/Forms/AutocompleteSelect.svelte +++ b/frontend/src/lib/components/Forms/AutocompleteSelect.svelte @@ -59,7 +59,7 @@ let selectedValues: (string | undefined)[] = []; - $: selectedValues = selected.map((item) => item.value); + $: selectedValues = selected.map((item) => item.value || item.label || item); const default_value = nullable ? null : selectedValues[0]; @@ -85,17 +85,6 @@ dispatch('change', $value); dispatch('cache', selected); } - - $: { - selected = selected.map((option) => { - const newOption = { - label: option.label, - value: option.value || option.label - }; - selected = [...selected, newOption]; - return newOption; - }); - }