diff --git a/apps/analysis/models.py b/apps/analysis/models.py index 54edc7fb1d..90ada578a1 100644 --- a/apps/analysis/models.py +++ b/apps/analysis/models.py @@ -563,6 +563,19 @@ class AnalysisReport(UserResource): organizations = models.ManyToManyField(Organization, blank=True) configuration = models.JSONField(default=dict) + @staticmethod + def get_latest_snapshot(slug=None, report_id=None): + if slug is None or id is None: + return + queryset = AnalysisReportSnapshot.objects.filter( + report__is_public=True, + ) + if slug is not None: + queryset = queryset.filter(report__slug=slug) + if report_id is not None: + queryset = queryset.filter(report_id=report_id) + return queryset.order_by('-published_on').first() + class AnalysisReportUpload(models.Model): class Type(models.IntegerChoices): diff --git a/apps/analysis/public_schema.py b/apps/analysis/public_schema.py index 644bf7a554..eb395fcd4f 100644 --- a/apps/analysis/public_schema.py +++ b/apps/analysis/public_schema.py @@ -2,7 +2,7 @@ import graphene from .schema import AnalysisReportSnapshotType -from .models import AnalysisReportSnapshot +from .models import AnalysisReport, AnalysisReportSnapshot class Query: @@ -13,7 +13,4 @@ class Query: @staticmethod def resolve_analysis_report_snapshot(root, info, slug, **kwargs) -> typing.Optional[AnalysisReportSnapshot]: - return AnalysisReportSnapshot.objects.filter( - report__is_public=True, - report__slug=slug, - ).order_by('-published_on').first() + return AnalysisReport.get_latest_snapshot(slug=slug) diff --git a/apps/analysis/schema.py b/apps/analysis/schema.py index a4fe8adc81..f0926e72a4 100644 --- a/apps/analysis/schema.py +++ b/apps/analysis/schema.py @@ -22,6 +22,8 @@ from entry.filter_set import EntriesFilterDataType from user.schema import UserType from organization.schema import OrganizationType +from gallery.schema import GalleryFileType +from gallery.models import File as GalleryFile from .models import ( Analysis, @@ -622,7 +624,42 @@ def resolve_content_data(root, info, **_): return root.analysisreportcontainerdata_set.all() -class AnalysisReportType(DjangoObjectType): +class AnalysisReportSnapshotType(DjangoObjectType): + class Meta: + model = AnalysisReportSnapshot + only_fields = ( + 'id', + 'published_on', + ) + + report = graphene.ID(source='report_id', required=True) + published_by = graphene.Field(UserType, required=True) + report_data_file = graphene.Field(FileFieldType) + files = graphene.List(graphene.NonNull(GalleryFileType), required=True) + + @staticmethod + def get_custom_queryset(queryset, info, **_): + return get_analysis_report_snaphost_qs(info) + + @staticmethod + def resolve_published_by(root, info, **_): + return resolve_user_field(root, info, 'published_by') + + @staticmethod + def resolve_uploads(root, info, **_): + # TODO: Maybe filter this out? + # For now + # - organization logos + # - report uploads + # TODO: use queryset instead + related_file_id = [ + *list(root.report.analysisreportupload_set.values_list('file_id', flat=True)), + *list(root.report.organizations.values_list('logo_id', flat=True)), + ] + return GalleryFile.objects.filter(id__in=related_file_id).all() + + +class AnalysisReportType(UserResourceMixin, DjangoObjectType): class Meta: model = AnalysisReport only_fields = ( @@ -647,43 +684,31 @@ class Meta: ) organizations = graphene.List(graphene.NonNull(OrganizationType), required=True) uploads = graphene.List(graphene.NonNull(AnalysisReportUploadType), required=True) + latest_snapshot = graphene.Field(AnalysisReportSnapshotType, required=False) @staticmethod def get_custom_queryset(queryset, info, **_): return get_analysis_report_qs(info) + @staticmethod def resolve_organizations(root, info, **_): # TODO: Dataloader return root.organizations.all() + @staticmethod def resolve_uploads(root, info, **_): # TODO: Dataloader return root.analysisreportupload_set.all() + @staticmethod def resolve_containers(root, info, **_): # TODO: Dataloader return root.analysisreportcontainer_set.all() - -class AnalysisReportSnapshotType(DjangoObjectType): - class Meta: - model = AnalysisReportSnapshot - only_fields = ( - 'id', - 'published_on', - ) - - report = graphene.ID(source='report_id', required=True) - published_by = graphene.Field(UserType, required=True) - report_data_file = graphene.Field(FileFieldType) - - @staticmethod - def resolve_published_by(root, info, **_): - return resolve_user_field(root, info, 'published_by') - @staticmethod - def get_custom_queryset(queryset, info, **_): - return get_analysis_report_snaphost_qs(info) + def resolve_latest_snapshot(root, info, **_): + # TODO: Dataloader + return AnalysisReport.get_latest_snapshot(report_id=root.id) class AnalysisReportListType(CustomDjangoListObjectType): diff --git a/schema.graphql b/schema.graphql index 961ec334cc..42017cfadb 100644 --- a/schema.graphql +++ b/schema.graphql @@ -605,6 +605,7 @@ type AnalysisReportSnapshotType { report: ID! publishedBy: UserType! reportDataFile: FileFieldType + files: [GalleryFileType!]! } input AnalysisReportTextConfigurationInputType { @@ -654,11 +655,16 @@ type AnalysisReportType { slug: String! title: String! subTitle: String! + createdAt: DateTime! + modifiedAt: DateTime! + createdBy: UserType + modifiedBy: UserType analysis: ID! configuration: AnalysisReportConfigurationType containers: [AnalysisReportContainerType!]! organizations: [OrganizationType!]! uploads: [AnalysisReportUploadType!]! + latestSnapshot: AnalysisReportSnapshotType } input AnalysisReportUploadInputType {