Skip to content

Commit

Permalink
SCKAN-300 feat: Remove graph state on path changes
Browse files Browse the repository at this point in the history
  • Loading branch information
afonsobspinto committed Nov 11, 2024
1 parent 65e92a2 commit 1d269b9
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 20 deletions.
19 changes: 16 additions & 3 deletions backend/composer/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,12 @@ def assign_owner(self, request, pk=None):
instance.assign_owner(request)
serializer = self.get_serializer(instance)
return Response(serializer.data)

def retrieve(self, request, *args, **kwargs):
self.get_object().auto_assign_owner(request)
return super().retrieve(request, *args, **kwargs)



class TagMixin(viewsets.GenericViewSet):
@extend_schema(
parameters=[
Expand Down Expand Up @@ -321,7 +320,7 @@ class NoteViewSet(viewsets.ModelViewSet):
queryset = Note.objects.all()
serializer_class = NoteSerializer
permission_classes = [
permissions.IsAuthenticatedOrReadOnly,
permissions.IsAuthenticatedOrReadOnly,
]
filterset_class = NoteFilter

Expand Down Expand Up @@ -392,16 +391,23 @@ def update(self, request, *args, **kwargs):
origin_ids = request.data.pop("origins", None)
graph_rendering_state_data = request.data.pop("graph_rendering_state", None)

# Call the UpdateModelMixin's update
response = super().update(request, *args, **kwargs)

if response.status_code == status.HTTP_200_OK:
instance = self.get_object()

# Handle custom updates
self.handle_graph_rendering_state(
instance, graph_rendering_state_data, request.user
)
if origin_ids is not None:
instance.set_origins(origin_ids)

# Re-serialize the instance with all modifications
serializer = self.get_serializer(instance)
return Response(serializer.data, status=status.HTTP_200_OK)

return response

@extend_schema(
Expand All @@ -412,14 +418,21 @@ def update(self, request, *args, **kwargs):
def partial_update(self, request, *args, **kwargs):
graph_rendering_state_data = request.data.pop("graph_rendering_state", None)

# Call the UpdateModelMixin's partial_update
response = super().partial_update(request, *args, **kwargs)

if response.status_code == status.HTTP_200_OK:
instance = self.get_object()

# Handle custom updates
self.handle_graph_rendering_state(
instance, graph_rendering_state_data, request.user
)

# Re-serialize the instance with all modifications
serializer = self.get_serializer(instance)
return Response(serializer.data, status=status.HTTP_200_OK)

return response


Expand Down
102 changes: 98 additions & 4 deletions backend/composer/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@
from django_fsm.signals import post_transition

from .enums import CSState, NoteType
from .models import ConnectivityStatement, ExportBatch, Note, Sentence, \
AnatomicalEntity, Layer, Region
from .models import (
ConnectivityStatement,
Destination,
ExportBatch,
GraphRenderingState,
Note,
Sentence,
AnatomicalEntity,
Layer,
Region,
Via,
)
from .services.export_services import compute_metrics, ConnectivityStatementStateService


Expand Down Expand Up @@ -42,8 +52,8 @@ def post_transition_callback(sender, instance, name, source, target, **kwargs):
def post_transition_cs(sender, instance, name, source, target, **kwargs):
if issubclass(sender, ConnectivityStatement):
if target == CSState.COMPOSE_NOW and source in (
CSState.NPO_APPROVED,
CSState.EXPORTED,
CSState.NPO_APPROVED,
CSState.EXPORTED,
):
# add important tag to CS when transition to COMPOSE_NOW from NPO Approved or Exported
instance = ConnectivityStatementStateService.add_important_tag(instance)
Expand All @@ -70,3 +80,87 @@ def delete_associated_entities(sender, instance, **kwargs):
# Delete the associated region_layer if it exists
if instance.region_layer:
instance.region_layer.delete()


# Signals for ConnectivityStatement origins
@receiver(m2m_changed, sender=ConnectivityStatement.origins.through)
def connectivity_statement_origins_changed(sender, instance, action, **kwargs):
if action in ["post_add", "post_remove", "post_clear"]:
try:
instance.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass


# Signals for Via anatomical_entities
@receiver(m2m_changed, sender=Via.anatomical_entities.through)
def via_anatomical_entities_changed(sender, instance, action, **kwargs):
if action in ["post_add", "post_remove", "post_clear"]:
try:
instance.connectivity_statement.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass


# Signals for Via from_entities
@receiver(m2m_changed, sender=Via.from_entities.through)
def via_from_entities_changed(sender, instance, action, **kwargs):
if action in ["post_add", "post_remove", "post_clear"]:
try:
instance.connectivity_statement.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass


# Signals for Destination anatomical_entities
@receiver(m2m_changed, sender=Destination.anatomical_entities.through)
def destination_anatomical_entities_changed(sender, instance, action, **kwargs):
if action in ["post_add", "post_remove", "post_clear"]:
try:
instance.connectivity_statement.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass


# Signals for Destination from_entities
@receiver(m2m_changed, sender=Destination.from_entities.through)
def destination_from_entities_changed(sender, instance, action, **kwargs):
if action in ["post_add", "post_remove", "post_clear"]:
try:
instance.connectivity_statement.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass


# Signals for Via model changes
@receiver(post_save, sender=Via)
@receiver(post_delete, sender=Via)
def via_changed(sender, instance, **kwargs):
try:
instance.connectivity_statement.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass


# Signals for Destination model changes
@receiver(post_save, sender=Destination)
@receiver(post_delete, sender=Destination)
def destination_changed(sender, instance, **kwargs):
try:
instance.connectivity_statement.graph_rendering_state.delete()
except GraphRenderingState.DoesNotExist:
pass
except ValueError:
pass
4 changes: 4 additions & 0 deletions frontend/src/components/Forms/StatementForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ const StatementForm = (props: any) => {
entityId: getConnectionId(formId, statement.vias),
entityType: "via",
propertyToUpdate: "anatomical_entities",
refreshStatement
});
},
errors: "",
Expand Down Expand Up @@ -354,6 +355,7 @@ const StatementForm = (props: any) => {
entityId: getConnectionId(formId, statement.vias),
entityType: "via",
propertyToUpdate: "from_entities",
refreshStatement
});
},
areConnectionsExplicit: (formId: any) => {
Expand Down Expand Up @@ -489,6 +491,7 @@ const StatementForm = (props: any) => {
entityId: getConnectionId(formId, statement?.destinations),
entityType: "destination",
propertyToUpdate: "anatomical_entities",
refreshStatement
});
},
errors: "",
Expand Down Expand Up @@ -534,6 +537,7 @@ const StatementForm = (props: any) => {
entityId: getConnectionId(formId, statement?.destinations),
entityType: "destination",
propertyToUpdate: "from_entities",
refreshStatement
});
},
areConnectionsExplicit: (formId: any) => {
Expand Down
31 changes: 18 additions & 13 deletions frontend/src/services/CustomDropdownService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Option } from "../types";
import { composerApi as api } from "./apis";
import {autocompleteRows, ChangeRequestStatus} from "../helpers/settings";
import { autocompleteRows, ChangeRequestStatus } from "../helpers/settings";
import {
convertToConnectivityStatementUpdate,
getViasGroupLabel,
Expand All @@ -18,10 +18,10 @@ import {
PatchedVia,
ViaSerializerDetails,
} from "../apiclient/backend";
import {searchAnatomicalEntities} from "../helpers/helpers";
import { searchAnatomicalEntities } from "../helpers/helpers";
import connectivityStatementService from "./StatementService";
import statementService from "./StatementService";
import {checkOwnership, getOwnershipAlertMessage} from "../helpers/ownershipAlert";
import { checkOwnership, getOwnershipAlertMessage } from "../helpers/ownershipAlert";

export async function getAnatomicalEntities(
searchValue: string,
Expand Down Expand Up @@ -53,7 +53,9 @@ export async function updateOrigins(
};

try {
return await statementService.partialUpdate(statementId, patchedStatement);
const response = await statementService.partialUpdate(statementId, patchedStatement);
setStatement(response);
return response;
} catch (error) {
alert(`Error updating origins: ${error}`);
}
Expand All @@ -65,6 +67,7 @@ export type UpdateEntityParams = {
entityId: number | null;
entityType: "via" | "destination";
propertyToUpdate: "anatomical_entities" | "from_entities";
refreshStatement: () => void;
};

const apiFunctionMap = {
Expand All @@ -80,6 +83,7 @@ export async function updateEntity({
entityId,
entityType,
propertyToUpdate,
refreshStatement,
}: UpdateEntityParams) {
if (entityId == null) {
alert(`Error updating ${entityType}`);
Expand All @@ -96,6 +100,7 @@ export async function updateEntity({
try {
if (entityId != null) {
await updateFunction(entityId, patchObject);
refreshStatement()
}
} catch (error) {
// Ownership error occurred, trigger ownership check
Expand Down Expand Up @@ -231,9 +236,9 @@ export async function searchForwardConnection(

try {
const forwardConnectionOrigins = statement.destinations?.flatMap(
(destination) =>
destination.anatomical_entities?.map((entity) => entity.id) ?? [],
) ?? [];
(destination) =>
destination.anatomical_entities?.map((entity) => entity.id) ?? [],
) ?? [];
if (forwardConnectionOrigins.length === 0) {
return []
}
Expand Down Expand Up @@ -262,16 +267,16 @@ export async function searchForwardConnection(

const sameSentenceOptions = sameRes.results
? mapConnectivityStatementsToOptions(
sameRes.results.filter((res) => res.id !== statement.id),
forwardConnectionGroups.sameSentence,
)
sameRes.results.filter((res) => res.id !== statement.id),
forwardConnectionGroups.sameSentence,
)
: [];

const differentSentenceOptions = diffRes.results
? mapConnectivityStatementsToOptions(
diffRes.results,
forwardConnectionGroups.otherSentence,
)
diffRes.results,
forwardConnectionGroups.otherSentence,
)
: [];

return [...sameSentenceOptions, ...differentSentenceOptions];
Expand Down

0 comments on commit 1d269b9

Please sign in to comment.