Skip to content

Commit

Permalink
EES-5738 Data Catalogue page Geog lvl filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
mmyoungman committed Dec 13, 2024
1 parent aeca23b commit cc25b5f
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Azure.Data.Tables;
using GovUk.Education.ExploreEducationStatistics.Common.Extensions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class ListDataSetsTests : DataSetFilesControllerCachingTests
ThemeId: Guid.NewGuid(),
PublicationId: Guid.NewGuid(),
ReleaseId: Guid.NewGuid(),
GeographicLevel: GeographicLevel.Country.GetEnumValue(),
LatestOnly: true,
DataSetType: DataSetType.Api,
SearchTerm: "term",
Expand Down Expand Up @@ -116,6 +117,7 @@ public async Task NoCachedEntryExists_CreatesCache()
_query.ThemeId,
_query.PublicationId,
_query.ReleaseId,
_query.GeographicLevelEnum,
_query.LatestOnly,
_query.DataSetType,
_query.SearchTerm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using GovUk.Education.ExploreEducationStatistics.Common.Cache;
using GovUk.Education.ExploreEducationStatistics.Common.Extensions;
using GovUk.Education.ExploreEducationStatistics.Common.Model.Data;
using GovUk.Education.ExploreEducationStatistics.Common.ViewModels;
using GovUk.Education.ExploreEducationStatistics.Content.Api.Cache;
using GovUk.Education.ExploreEducationStatistics.Content.Requests;
Expand Down Expand Up @@ -39,6 +40,7 @@ public async Task<ActionResult<PaginatedListViewModel<DataSetFileSummaryViewMode
themeId: request.ThemeId,
publicationId: request.PublicationId,
releaseVersionId: request.ReleaseId,
geographicLevel: request.GeographicLevelEnum,
latestOnly: request.LatestOnly,
dataSetType: request.DataSetType,
searchTerm: request.SearchTerm,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using FluentValidation;
using GovUk.Education.ExploreEducationStatistics.Common.Model;
using GovUk.Education.ExploreEducationStatistics.Common.Model.Data;
using GovUk.Education.ExploreEducationStatistics.Common.Utils;
using GovUk.Education.ExploreEducationStatistics.Common.Validators;

namespace GovUk.Education.ExploreEducationStatistics.Content.Requests;

public record DataSetFileListRequest(
Guid? ThemeId = null,
Guid? PublicationId = null,
Guid? ReleaseId = null,
string? GeographicLevel = null,
bool? LatestOnly = null,
DataSetType? DataSetType = null,
string? SearchTerm = null,
Expand All @@ -15,6 +19,11 @@ public record DataSetFileListRequest(
int Page = 1,
int PageSize = 10)
{
public GeographicLevel? GeographicLevelEnum =>
GeographicLevel == null
? null
: EnumUtil.GetFromEnumValue<GeographicLevel>(GeographicLevel);

public class Validator : AbstractValidator<DataSetFileListRequest>
{
public Validator()
Expand All @@ -23,6 +32,9 @@ public Validator()
.MinimumLength(3);
RuleFor(request => request.ReleaseId).NotEmpty()
.When(request => request.Sort == DataSetsListRequestSortBy.Natural);
RuleFor(request => request.GeographicLevel)
.AllowedValue(EnumUtil.GetEnumValues<GeographicLevel>())
.When(request => request.GeographicLevel != null);
RuleFor(request => request.SearchTerm).NotEmpty()
.When(request => request.Sort == DataSetsListRequestSortBy.Relevance);
RuleFor(request => request.Page)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,25 @@
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using GovUk.Education.ExploreEducationStatistics.Common.Model.Data;
using static GovUk.Education.ExploreEducationStatistics.Common.Model.SortDirection;
using static GovUk.Education.ExploreEducationStatistics.Content.Requests.DataSetsListRequestSortBy;
using ReleaseVersion = GovUk.Education.ExploreEducationStatistics.Content.Model.ReleaseVersion;

namespace GovUk.Education.ExploreEducationStatistics.Content.Services;

public class DataSetFileService : IDataSetFileService
public class DataSetFileService(
ContentDbContext contentDbContext,
IReleaseVersionRepository releaseVersionRepository,
IPublicBlobStorageService publicBlobStorageService,
IFootnoteRepository footnoteRepository)
: IDataSetFileService
{
private readonly ContentDbContext _contentDbContext;
private readonly IReleaseVersionRepository _releaseVersionRepository;
private readonly IPublicBlobStorageService _publicBlobStorageService;
private readonly IFootnoteRepository _footnoteRepository;

public DataSetFileService(
ContentDbContext contentDbContext,
IReleaseVersionRepository releaseVersionRepository,
IPublicBlobStorageService publicBlobStorageService,
IFootnoteRepository footnoteRepository)
{
_contentDbContext = contentDbContext;
_releaseVersionRepository = releaseVersionRepository;
_publicBlobStorageService = publicBlobStorageService;
_footnoteRepository = footnoteRepository;
}

public async Task<Either<ActionResult, PaginatedListViewModel<DataSetFileSummaryViewModel>>> ListDataSetFiles(
Guid? themeId,
Guid? publicationId,
Guid? releaseVersionId,
GeographicLevel? geographicLevel,
bool? latestOnly,
DataSetType? dataSetType,
string? searchTerm,
Expand All @@ -73,18 +63,19 @@ public async Task<Either<ActionResult, PaginatedListViewModel<DataSetFileSummary
sortDirection ??= sort is Title or Natural ? Asc : Desc;

var latestPublishedReleaseVersions =
_contentDbContext.ReleaseVersions.LatestReleaseVersions(publicationId, publishedOnly: true);
contentDbContext.ReleaseVersions.LatestReleaseVersions(publicationId, publishedOnly: true);

var query = _contentDbContext.ReleaseFiles
var query = contentDbContext.ReleaseFiles
.AsNoTracking()
.OfFileType(FileType.Data)
.HavingNoDataReplacementInProgress()
.HavingThemeId(themeId)
.HavingPublicationIdOrNoSupersededPublication(publicationId)
.HavingReleaseVersionId(releaseVersionId)
.HavingGeographicLevel(geographicLevel)
.OfDataSetType(dataSetType.Value)
.HavingLatestPublishedReleaseVersions(latestPublishedReleaseVersions, latestOnly.Value)
.JoinFreeText(_contentDbContext.ReleaseFilesFreeTextTable, rf => rf.Id, searchTerm);
.JoinFreeText(contentDbContext.ReleaseFilesFreeTextTable, rf => rf.Id, searchTerm);

var results = await query
.OrderBy(sort.Value, sortDirection.Value)
Expand Down Expand Up @@ -144,10 +135,10 @@ private static Expression<Func<FreeTextValueResult<ReleaseFile>, DataSetFileSumm
public async Task<Either<ActionResult, List<DataSetSitemapItemViewModel>>> ListSitemapItems(
CancellationToken cancellationToken = default)
{
var latestReleaseVersions = _contentDbContext.ReleaseVersions
var latestReleaseVersions = contentDbContext.ReleaseVersions
.LatestReleaseVersions(publishedOnly: true);

var latestReleaseFiles = _contentDbContext.ReleaseFiles
var latestReleaseFiles = contentDbContext.ReleaseFiles
.AsNoTracking()
.OfFileType(FileType.Data)
.HavingNoDataReplacementInProgress()
Expand Down Expand Up @@ -176,7 +167,7 @@ private static async Task<List<DataSetFileSummaryViewModel>> ChangeSummaryHtmlTo

public async Task<Either<ActionResult, DataSetFileViewModel>> GetDataSetFile(Guid dataSetFileId)
{
var releaseFile = await _contentDbContext.ReleaseFiles
var releaseFile = await contentDbContext.ReleaseFiles
.Include(rf => rf.ReleaseVersion.Publication.Theme)
.Include(rf => rf.ReleaseVersion.Publication.SupersededBy)
.Include(rf => rf.File)
Expand All @@ -188,7 +179,7 @@ public async Task<Either<ActionResult, DataSetFileViewModel>> GetDataSetFile(Gui
.FirstOrDefaultAsync();

if (releaseFile == null
|| !await _releaseVersionRepository.IsLatestPublishedReleaseVersion(
|| !await releaseVersionRepository.IsLatestPublishedReleaseVersion(
releaseFile.ReleaseVersionId))
{
return new NotFoundResult();
Expand All @@ -198,7 +189,7 @@ public async Task<Either<ActionResult, DataSetFileViewModel>> GetDataSetFile(Gui

var variables = GetVariables(releaseFile.File.DataSetFileMeta!);

var footnotes = await _footnoteRepository.GetFootnotes(
var footnotes = await footnoteRepository.GetFootnotes(
releaseFile.ReleaseVersionId,
releaseFile.File.SubjectId);

Expand Down Expand Up @@ -249,7 +240,7 @@ public async Task<Either<ActionResult, DataSetFileViewModel>> GetDataSetFile(Gui
public async Task<ActionResult> DownloadDataSetFile(
Guid dataSetFileId)
{
var releaseFile = await _contentDbContext.ReleaseFiles
var releaseFile = await contentDbContext.ReleaseFiles
.Include(rf => rf.File)
.Where(rf =>
rf.File.DataSetFileId == dataSetFileId
Expand All @@ -259,13 +250,13 @@ public async Task<ActionResult> DownloadDataSetFile(
.FirstOrDefaultAsync();

if (releaseFile == null
|| !await _releaseVersionRepository.IsLatestPublishedReleaseVersion(
|| !await releaseVersionRepository.IsLatestPublishedReleaseVersion(
releaseFile.ReleaseVersionId))
{
return new NotFoundResult();
}

var stream = await _publicBlobStorageService.StreamBlob(
var stream = await publicBlobStorageService.StreamBlob(
containerName: BlobContainers.PublicReleaseFiles,
path: releaseFile.PublicPath());

Expand Down Expand Up @@ -306,7 +297,7 @@ private static DataSetFileMetaViewModel BuildDataSetFileMetaViewModel(

private async Task<DataSetFileCsvPreviewViewModel> GetDataCsvPreview(ReleaseFile releaseFile)
{
var datafileStreamProvider = () => _publicBlobStorageService.StreamBlob(
var datafileStreamProvider = () => publicBlobStorageService.StreamBlob(
containerName: BlobContainers.PublicReleaseFiles,
path: releaseFile.PublicPath());

Expand Down Expand Up @@ -491,6 +482,17 @@ internal static IQueryable<ReleaseFile> HavingReleaseVersionId(
return releaseVersionId.HasValue ? query.Where(rf => rf.ReleaseVersionId == releaseVersionId.Value) : query;
}

internal static IQueryable<ReleaseFile> HavingGeographicLevel( // @MarkFix write tests
this IQueryable<ReleaseFile> query,
GeographicLevel? geographicLevel)
{
return geographicLevel.HasValue
? query.Where(rf => rf.File.DataSetFileGeographicLevels!.Any( // @MarkFix null allowing
gl => gl.GeographicLevel == geographicLevel
&& rf.FileId == gl.DataSetFileVersionId))
: query;
}

internal static IQueryable<ReleaseFile> OfDataSetType(
this IQueryable<ReleaseFile> query,
DataSetType dataSetType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using GovUk.Education.ExploreEducationStatistics.Common.Model;
using GovUk.Education.ExploreEducationStatistics.Common.Model.Data;
using GovUk.Education.ExploreEducationStatistics.Common.ViewModels;
using GovUk.Education.ExploreEducationStatistics.Content.Requests;
using GovUk.Education.ExploreEducationStatistics.Content.ViewModels;
Expand All @@ -17,6 +18,7 @@ Task<Either<ActionResult, PaginatedListViewModel<DataSetFileSummaryViewModel>>>
Guid? themeId,
Guid? publicationId,
Guid? releaseVersionId,
GeographicLevel? geographicLevel,
bool? latestOnly,
DataSetType? dataSetType,
string? searchTerm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import omit from 'lodash/omit';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { ParsedUrlQuery } from 'querystring';
import { GeographicLevelCode } from '@common/utils/locationLevelsMap';

const defaultPageTitle = 'Data catalogue';

Expand All @@ -61,6 +62,7 @@ export interface DataCataloguePageQuery {
page?: number;
publicationId?: string;
releaseId?: string;
geographicLevel?: GeographicLevelCode;
searchTerm?: string;
sortBy?: DataSetFileSortOption;
sortDirection?: SortDirection;
Expand All @@ -85,6 +87,7 @@ const DataCataloguePage: NextPage<Props> = ({ showTypeFilter }) => {
sortBy,
publicationId,
releaseId,
geographicLevel,
searchTerm,
themeId,
} = getParamsFromQuery(router.query);
Expand Down Expand Up @@ -131,6 +134,7 @@ const DataCataloguePage: NextPage<Props> = ({ showTypeFilter }) => {
searchTerm,
selectedTheme?.title,
selectedPublication?.title,
geographicLevel,
]).join(', ');

const updateQueryParams = async (nextQuery: DataCataloguePageQuery) => {
Expand Down Expand Up @@ -327,6 +331,7 @@ const DataCataloguePage: NextPage<Props> = ({ showTypeFilter }) => {
publicationId={publicationId}
publications={publications}
releaseId={releaseId}
geographicLevel={geographicLevel}
releases={releases}
showResetFiltersButton={!isMobileMedia && isFiltered}
showTypeFilter={showTypeFilter}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import styles from '@frontend/modules/data-catalogue/components/Filters.module.s
import { DataSetFileFilter } from '@frontend/modules/data-catalogue/utils/dataSetFileFilters';
import React from 'react';
import classNames from 'classnames';
import locationLevelsMap, {
GeographicLevelCode,
} from '@common/utils/locationLevelsMap';
import typedKeys from '@common/utils/object/typedKeys';

const formId = 'filters-form';

Expand All @@ -23,6 +27,7 @@ interface Props {
publications?: PublicationTreeSummary[];
releaseId?: string;
releases?: ReleaseSummary[];
geographicLevel?: GeographicLevelCode;
showResetFiltersButton?: boolean;
showTypeFilter?: boolean;
themeId?: string;
Expand All @@ -44,6 +49,7 @@ export default function Filters({
publicationId,
releaseId,
releases = [],
geographicLevel,
showResetFiltersButton,
showTypeFilter,
themeId,
Expand Down Expand Up @@ -140,6 +146,36 @@ export default function Filters({
/>
</FormGroup>

<FormGroup>
<FormSelect
className="govuk-!-width-full"
id={`${formId}-geographic-level`}
label={
<>
<VisuallyHidden>Filter by </VisuallyHidden>Geographic level
</>
}
name="geographicLevel"
options={[
{ label: 'All', value: 'all' },
...typedKeys(locationLevelsMap).map(key => {
return {
label: locationLevelsMap[key].label,
value: locationLevelsMap[key].code,
};
}),
]}
value={geographicLevel}
order={[]}
onChange={e => {
onChange({
filterType: 'geographicLevel',
nextValue: e.target.value,
});
}}
/>
</FormGroup>

{showResetFiltersButton && (
<ButtonText
className={classNames({ 'govuk-!-margin-top-4': !showTypeFilter })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default function createDataSetFileListRequest(
sortBy,
publicationId,
releaseId,
geographicLevel,
searchTerm: searchParam,
themeId,
} = getParamsFromQuery(query);
Expand All @@ -43,6 +44,7 @@ export default function createDataSetFileListRequest(
page: parseNumber(query.page) ?? 1,
publicationId,
releaseId,
geographicLevel,
sort,
sortDirection,
searchTerm,
Expand Down Expand Up @@ -101,6 +103,7 @@ export function getParamsFromQuery(query: DataCataloguePageQuery) {
: 'newest',
publicationId: getFirst(query.publicationId),
releaseId: getFirst(query.releaseId),
geographicLevel: getFirst(query.geographicLevel),
searchTerm: getFirst(query.searchTerm),
themeId: getFirst(query.themeId),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const dataSetFileFilters = [
'latest',
'publicationId',
'releaseId',
'geographicLevel',
'searchTerm',
'themeId',
] as const;
Expand Down
Loading

0 comments on commit cc25b5f

Please sign in to comment.