From a93fea8ed6daf3c9622e3ddcde70a0f58d143ac0 Mon Sep 17 00:00:00 2001 From: Cornelius Roemer Date: Tue, 17 Sep 2024 18:33:08 +0200 Subject: [PATCH 1/2] refactor(website): rename `siloVersionStatus` to `versionStatus` Also some slight tweaks to function names in organism statistics, follow up to #2814 --- .../components/IndexPage/getOrganismStatistics.ts | 13 +++++++------ .../DownloadDialog/generateDownloadUrl.ts | 4 ++-- .../SequenceDetailsPage/SequencesBanner.astro | 6 +++--- website/src/pages/[organism]/search/index.astro | 4 ++-- .../[organism]/submission/[groupId]/released.astro | 4 ++-- website/src/services/lapisClient.ts | 4 ++-- website/src/types/lapis.ts | 14 +++++++------- website/src/utils/getVersionStatusColor.ts | 6 +++--- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/website/src/components/IndexPage/getOrganismStatistics.ts b/website/src/components/IndexPage/getOrganismStatistics.ts index 02623134c..c2aa70aee 100644 --- a/website/src/components/IndexPage/getOrganismStatistics.ts +++ b/website/src/components/IndexPage/getOrganismStatistics.ts @@ -2,8 +2,9 @@ import { DateTime, FixedOffsetZone } from 'luxon'; import { LapisClient } from '../../services/lapisClient.ts'; import { RELEASED_AT_FIELD, VERSION_STATUS_FIELD, IS_REVOCATION_FIELD } from '../../settings.ts'; -import { siloVersionStatuses } from '../../types/lapis'; +import { versionStatuses } from '../../types/lapis'; +// Excluding sequences whose latest version is revoked export type OrganismStatistics = { totalSequences: number; recentSequences: number; @@ -50,7 +51,7 @@ const getTotalAndLastUpdatedAt = async ( const client = LapisClient.createForOrganism(organism); return ( await client.call('aggregated', { - [VERSION_STATUS_FIELD]: siloVersionStatuses.latestVersion, + [VERSION_STATUS_FIELD]: versionStatuses.latestVersion, [IS_REVOCATION_FIELD]: 'false', }) ) @@ -69,7 +70,7 @@ const getTotalAndLastUpdatedAt = async ( const getRecent = async (organism: string, numberDaysAgo: number): Promise => { const recentTimestamp = Math.floor(Date.now() / 1000 - numberDaysAgo * 24 * 60 * 60); const client = LapisClient.createForOrganism(organism); - const recentTotal = ( + const recentTotalIncludingRevoked = ( await client.call('aggregated', { [`${RELEASED_AT_FIELD}From`]: recentTimestamp, version: 1, @@ -77,14 +78,14 @@ const getRecent = async (organism: string, numberDaysAgo: number): Promise x.data[0].count) .unwrapOr(0); - const recentRevoked = ( + const recentTotalRevoked = ( await client.call('aggregated', { [`${RELEASED_AT_FIELD}From`]: recentTimestamp, version: 1, - [VERSION_STATUS_FIELD]: siloVersionStatuses.revoked, + [VERSION_STATUS_FIELD]: versionStatuses.revoked, }) ) .map((x) => x.data[0].count) .unwrapOr(0); - return recentTotal - recentRevoked; + return recentTotalIncludingRevoked - recentTotalRevoked; }; diff --git a/website/src/components/SearchPage/DownloadDialog/generateDownloadUrl.ts b/website/src/components/SearchPage/DownloadDialog/generateDownloadUrl.ts index 323859fe4..8a49d9cc9 100644 --- a/website/src/components/SearchPage/DownloadDialog/generateDownloadUrl.ts +++ b/website/src/components/SearchPage/DownloadDialog/generateDownloadUrl.ts @@ -1,5 +1,5 @@ import { IS_REVOCATION_FIELD, metadataDefaultDownloadDataFormat, VERSION_STATUS_FIELD } from '../../../settings.ts'; -import { siloVersionStatuses } from '../../../types/lapis.ts'; +import { versionStatuses } from '../../../types/lapis.ts'; export type DownloadDataType = | { type: 'metadata' } @@ -26,7 +26,7 @@ export const generateDownloadUrl = ( params.set('downloadAsFile', 'true'); if (!option.includeOldData) { - params.set(VERSION_STATUS_FIELD, siloVersionStatuses.latestVersion); + params.set(VERSION_STATUS_FIELD, versionStatuses.latestVersion); params.set(IS_REVOCATION_FIELD, 'false'); } if (!option.includeRestricted) { diff --git a/website/src/components/SequenceDetailsPage/SequencesBanner.astro b/website/src/components/SequenceDetailsPage/SequencesBanner.astro index 07379529b..59bbad0a7 100644 --- a/website/src/components/SequenceDetailsPage/SequencesBanner.astro +++ b/website/src/components/SequenceDetailsPage/SequencesBanner.astro @@ -1,7 +1,7 @@ --- import { getLatestAccessionVersion } from './getTableData'; import { routes } from '../../routes/routes.ts'; -import { type SequenceEntryHistory, siloVersionStatuses } from '../../types/lapis'; +import { type SequenceEntryHistory, versionStatuses } from '../../types/lapis'; import { getAccessionVersionString } from '../../utils/extractAccessionVersion'; interface Props { @@ -16,8 +16,8 @@ const ownHistoryEntry = sequenceEntryHistory.find((entry) => entry.accessionVers const latestAccessionVersion = getLatestAccessionVersion(sequenceEntryHistory); const revoked = - ownHistoryEntry?.versionStatus === siloVersionStatuses.revoked && latestAccessionVersion?.isRevocation === true; -const isLatestVersion = ownHistoryEntry?.versionStatus === siloVersionStatuses.latestVersion; + ownHistoryEntry?.versionStatus === versionStatuses.revoked && latestAccessionVersion?.isRevocation === true; +const isLatestVersion = ownHistoryEntry?.versionStatus === versionStatuses.latestVersion; ---
diff --git a/website/src/pages/[organism]/search/index.astro b/website/src/pages/[organism]/search/index.astro index f78ef48a3..2f3b4dccd 100644 --- a/website/src/pages/[organism]/search/index.astro +++ b/website/src/pages/[organism]/search/index.astro @@ -4,14 +4,14 @@ import { SearchFullUI } from '../../../components/SearchPage/SearchFullUI'; import { getRuntimeConfig, getSchema } from '../../../config'; import BaseLayout from '../../../layouts/BaseLayout.astro'; import { VERSION_STATUS_FIELD, IS_REVOCATION_FIELD } from '../../../settings'; -import { siloVersionStatuses } from '../../../types/lapis'; +import { versionStatuses } from '../../../types/lapis'; import { getAccessToken } from '../../../utils/getAccessToken'; import { getMyGroups } from '../../../utils/getMyGroups'; import { getReferenceGenomesSequenceNames } from '../../../utils/search'; import { performLapisSearchQueries } from '../../../utils/serversideSearch'; const hiddenFieldValues = { - [VERSION_STATUS_FIELD]: siloVersionStatuses.latestVersion, + [VERSION_STATUS_FIELD]: versionStatuses.latestVersion, [IS_REVOCATION_FIELD]: 'false', }; diff --git a/website/src/pages/[organism]/submission/[groupId]/released.astro b/website/src/pages/[organism]/submission/[groupId]/released.astro index e3da3dafe..1281bc555 100644 --- a/website/src/pages/[organism]/submission/[groupId]/released.astro +++ b/website/src/pages/[organism]/submission/[groupId]/released.astro @@ -4,7 +4,7 @@ import { SearchFullUI } from '../../../../components/SearchPage/SearchFullUI'; import SubmissionPageWrapper from '../../../../components/Submission/SubmissionPageWrapper.astro'; import { getRuntimeConfig, getSchema } from '../../../../config'; import { GROUP_ID_FIELD, VERSION_STATUS_FIELD } from '../../../../settings'; -import { siloVersionStatuses } from '../../../../types/lapis'; +import { versionStatuses } from '../../../../types/lapis'; import { getAccessToken } from '../../../../utils/getAccessToken'; import { getReferenceGenomesSequenceNames } from '../../../../utils/search'; import { performLapisSearchQueries } from '../../../../utils/serversideSearch'; @@ -33,7 +33,7 @@ const accessToken = getAccessToken(Astro.locals.session); const referenceGenomeSequenceNames = getReferenceGenomesSequenceNames(cleanedOrganism.key); const hiddenFieldValues = { - [VERSION_STATUS_FIELD]: siloVersionStatuses.latestVersion, + [VERSION_STATUS_FIELD]: versionStatuses.latestVersion, [GROUP_ID_FIELD]: group.groupId, }; diff --git a/website/src/services/lapisClient.ts b/website/src/services/lapisClient.ts index 096e59cb2..30cea57b6 100644 --- a/website/src/services/lapisClient.ts +++ b/website/src/services/lapisClient.ts @@ -19,7 +19,7 @@ import { type LapisBaseRequest, sequenceEntryHistory, type SequenceEntryHistory, - siloVersionStatuses, + versionStatuses, } from '../types/lapis.ts'; import type { BaseType } from '../utils/sequenceTypeHelpers.ts'; @@ -56,7 +56,7 @@ export class LapisClient extends ZodiosWrapperClient { public async getLatestAccessionVersion(accession: string): Promise> { const result = await this.call('details', { accession, - versionStatus: siloVersionStatuses.latestVersion, + versionStatus: versionStatuses.latestVersion, fields: [ACCESSION_FIELD, VERSION_FIELD], }); diff --git a/website/src/types/lapis.ts b/website/src/types/lapis.ts index 5c127d4c3..8984df2dc 100644 --- a/website/src/types/lapis.ts +++ b/website/src/types/lapis.ts @@ -74,25 +74,25 @@ export type LapisError = { error: ProblemDetail; }; -export const siloVersionStatuses = { +export const versionStatuses = { revoked: 'REVOKED', revised: 'REVISED', latestVersion: 'LATEST_VERSION', } as const; -export const siloVersionStatusSchema = z.enum([ - siloVersionStatuses.revoked, - siloVersionStatuses.revised, - siloVersionStatuses.latestVersion, +export const versionStatusSchema = z.enum([ + versionStatuses.revoked, + versionStatuses.revised, + versionStatuses.latestVersion, ]); -export type SiloVersionStatus = z.infer; +export type VersionStatus = z.infer; export const sequenceEntryHistoryEntry = accessionVersion .merge( z.object({ accessionVersion: z.string(), - versionStatus: siloVersionStatusSchema, + versionStatus: versionStatusSchema, isRevocation: z.boolean(), submittedAtTimestamp: z.number(), }), diff --git a/website/src/utils/getVersionStatusColor.ts b/website/src/utils/getVersionStatusColor.ts index 05dc33b2a..e93b77b05 100644 --- a/website/src/utils/getVersionStatusColor.ts +++ b/website/src/utils/getVersionStatusColor.ts @@ -1,8 +1,8 @@ -import { type SiloVersionStatus, siloVersionStatuses } from '../types/lapis.ts'; +import { type VersionStatus, versionStatuses } from '../types/lapis.ts'; -export const getVersionStatusColor = (versionStatus: SiloVersionStatus) => { +export const getVersionStatusColor = (versionStatus: VersionStatus) => { switch (versionStatus) { - case siloVersionStatuses.latestVersion: + case versionStatuses.latestVersion: return 'text-green-500'; default: return 'text-red-500'; From bfba0b76d542437a9cbae13d2afce40aecf6a1db Mon Sep 17 00:00:00 2001 From: Cornelius Roemer Date: Tue, 17 Sep 2024 19:35:33 +0200 Subject: [PATCH 2/2] Fix incorrect comment, explain edge case in getRecent --- .../components/IndexPage/getOrganismStatistics.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/website/src/components/IndexPage/getOrganismStatistics.ts b/website/src/components/IndexPage/getOrganismStatistics.ts index c2aa70aee..efbf3af49 100644 --- a/website/src/components/IndexPage/getOrganismStatistics.ts +++ b/website/src/components/IndexPage/getOrganismStatistics.ts @@ -4,7 +4,6 @@ import { LapisClient } from '../../services/lapisClient.ts'; import { RELEASED_AT_FIELD, VERSION_STATUS_FIELD, IS_REVOCATION_FIELD } from '../../settings.ts'; import { versionStatuses } from '../../types/lapis'; -// Excluding sequences whose latest version is revoked export type OrganismStatistics = { totalSequences: number; recentSequences: number; @@ -67,10 +66,16 @@ const getTotalAndLastUpdatedAt = async ( }); }; +/** + * Note: This method undercounts in cases where recently released sequences + * are later revoked and then unrevoked (revised), all within the "recency window". + * This trade-off allows for a simpler, more efficient query + * without needing to fetch individual accession lists. + */ const getRecent = async (organism: string, numberDaysAgo: number): Promise => { const recentTimestamp = Math.floor(Date.now() / 1000 - numberDaysAgo * 24 * 60 * 60); const client = LapisClient.createForOrganism(organism); - const recentTotalIncludingRevoked = ( + const recentlyReleasedTotal = ( await client.call('aggregated', { [`${RELEASED_AT_FIELD}From`]: recentTimestamp, version: 1, @@ -78,7 +83,7 @@ const getRecent = async (organism: string, numberDaysAgo: number): Promise x.data[0].count) .unwrapOr(0); - const recentTotalRevoked = ( + const recentlyReleasedThenRevokedTotal = ( await client.call('aggregated', { [`${RELEASED_AT_FIELD}From`]: recentTimestamp, version: 1, @@ -87,5 +92,5 @@ const getRecent = async (organism: string, numberDaysAgo: number): Promise x.data[0].count) .unwrapOr(0); - return recentTotalIncludingRevoked - recentTotalRevoked; + return recentlyReleasedTotal - recentlyReleasedThenRevokedTotal; };