From 06789be265099bc547f8c48feb67e9e5b734f905 Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 14 May 2024 15:18:45 +0100 Subject: [PATCH 1/3] Fixed manifest claim status when creating a canvas claim --- CHANGELOG.md | 5 ++ .../get-collection-autocomplete.ts | 2 +- .../manifests/get-manifest-autocomplete.ts | 2 +- .../routes/projects/create-resource-claim.ts | 78 +++++++++++++++---- 4 files changed, 69 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bfd2f7ad..b2c4200d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed --> +### Fixed +- Adding Manifests to projects with large amounts of content +- Fixed status of Manifest task after submission + + ## [v2.2.3](https://github.com/digirati-co-uk/madoc-platform/compare/v2.2.2...v2.2.3) - 13/05/2024 ### Added diff --git a/services/madoc-ts/src/routes/iiif/collections/get-collection-autocomplete.ts b/services/madoc-ts/src/routes/iiif/collections/get-collection-autocomplete.ts index b3877ba70..96daecc83 100644 --- a/services/madoc-ts/src/routes/iiif/collections/get-collection-autocomplete.ts +++ b/services/madoc-ts/src/routes/iiif/collections/get-collection-autocomplete.ts @@ -6,7 +6,7 @@ import { optionalUserWithScope } from '../../../utility/user-with-scope'; export const getCollectionAutocomplete: RouteMiddleware = async context => { const { siteId } = optionalUserWithScope(context, ['site.admin']); - const { q, project_id, blacklist_ids, page } = context.query; + const { q, project_id, blacklist_ids = '', page } = context.query; const { projectId, projectSlug } = parseProjectId(project_id); const blackListIds = (blacklist_ids || '') diff --git a/services/madoc-ts/src/routes/iiif/manifests/get-manifest-autocomplete.ts b/services/madoc-ts/src/routes/iiif/manifests/get-manifest-autocomplete.ts index 14a69687c..a42eab80f 100644 --- a/services/madoc-ts/src/routes/iiif/manifests/get-manifest-autocomplete.ts +++ b/services/madoc-ts/src/routes/iiif/manifests/get-manifest-autocomplete.ts @@ -6,7 +6,7 @@ import { userWithScope } from '../../../utility/user-with-scope'; export const getManifestAutocomplete: RouteMiddleware<{}, { blacklist_ids?: number[] }> = async context => { const { siteId } = userWithScope(context, ['site.admin']); - const { q, project_id, blacklist_ids = [], page } = context.query; + const { q, project_id, blacklist_ids = '', page } = context.query; const { projectId, projectSlug } = parseProjectId(project_id); const blackListIds = (blacklist_ids || '') diff --git a/services/madoc-ts/src/routes/projects/create-resource-claim.ts b/services/madoc-ts/src/routes/projects/create-resource-claim.ts index 09448fca8..ac04ec407 100644 --- a/services/madoc-ts/src/routes/projects/create-resource-claim.ts +++ b/services/madoc-ts/src/routes/projects/create-resource-claim.ts @@ -361,10 +361,10 @@ async function upsertCaptureModelForResource( const mainTarget = claim.canvasId ? { type: 'Canvas', id: `urn:madoc:canvas:${claim.canvasId}` } : claim.manifestId - ? { type: 'Manifest', id: `urn:madoc:manifest:${claim.manifestId}` } - : claim.collectionId - ? { type: 'Collection', id: `urn:madoc:collection:${claim.collectionId}` } - : undefined; + ? { type: 'Manifest', id: `urn:madoc:manifest:${claim.manifestId}` } + : claim.collectionId + ? { type: 'Collection', id: `urn:madoc:collection:${claim.collectionId}` } + : undefined; if (mainTarget && capture_model_id) { const existingModel = await userApi.getAllCaptureModels({ @@ -573,13 +573,10 @@ export const createResourceClaim: RouteMiddleware<{ id: string }, ResourceClaim> // Check for existing claim const [canvasClaim, manifestClaim] = await getTaskFromClaim({ userId: userId, parent, claim }); - - const resourceClaim = manifestOnly && !canvasClaim ? manifestClaim : canvasClaim; - - if (resourceClaim) { - if (!resourceClaim.state.revisionId && claim.revisionId) { + if (canvasClaim) { + if (!canvasClaim.state.revisionId && claim.revisionId) { context.response.body = { - claim: await userApi.updateTask(resourceClaim.id, { + claim: await userApi.updateTask(canvasClaim.id, { state: { revisionId: claim.revisionId, }, @@ -592,7 +589,7 @@ export const createResourceClaim: RouteMiddleware<{ id: string }, ResourceClaim> // @todo this should ALWAYS be false. const revisionDontMatch = - resourceClaim.state.revisionId && claim.revisionId && resourceClaim.state.revisionId !== claim.revisionId; + canvasClaim.state.revisionId && claim.revisionId && canvasClaim.state.revisionId !== claim.revisionId; const revisionExistsAndMatch = !revisionDontMatch; if (config.modelPageOptions?.preventMultipleUserSubmissionsPerResource && revisionDontMatch) { @@ -600,18 +597,18 @@ export const createResourceClaim: RouteMiddleware<{ id: string }, ResourceClaim> } if (revisionExistsAndMatch) { - if (typeof claim.status !== 'undefined' && claim.status !== resourceClaim.status) { + if (typeof claim.status !== 'undefined' && claim.status !== canvasClaim.status) { if ( config.modelPageOptions?.preventContributionAfterSubmission && - resourceClaim.status === 2 && + canvasClaim.status === 2 && (claim.status === 0 || claim.status === 1) && - resourceClaim.state.revisionId + canvasClaim.state.revisionId ) { throw new Error('Cannot update task in review'); } context.response.body = { - claim: await userApi.updateTask(resourceClaim.id, { + claim: await userApi.updateTask(canvasClaim.id, { status: claim.status, status_text: statusToClaimMap[claim.status as any] || 'in progress', }), @@ -620,7 +617,7 @@ export const createResourceClaim: RouteMiddleware<{ id: string }, ResourceClaim> } context.response.body = { - claim: await userApi.getTaskById(resourceClaim.id as string, true, 0, undefined, undefined, true), + claim: await userApi.getTaskById(canvasClaim.id as string, true, 0, undefined, undefined, true), }; return; } @@ -628,6 +625,55 @@ export const createResourceClaim: RouteMiddleware<{ id: string }, ResourceClaim> // Can't claim a canvas is you've already claimed the manifest. if (manifestClaim) { + if (manifestOnly) { + if (!manifestClaim.state.revisionId && claim.revisionId) { + context.response.body = { + claim: await userApi.updateTask(manifestClaim.id, { + state: { + revisionId: claim.revisionId, + }, + status: claim.status, + status_text: statusToClaimMap[claim.status as any] || 'in progress', + }), + }; + return; + } + + // @todo this should ALWAYS be false. + const revisionDontMatch = + manifestClaim.state.revisionId && claim.revisionId && manifestClaim.state.revisionId !== claim.revisionId; + const revisionExistsAndMatch = !revisionDontMatch; + + if (config.modelPageOptions?.preventMultipleUserSubmissionsPerResource && revisionDontMatch) { + throw new Error('Can only submit one revision per resource'); + } + + if (revisionExistsAndMatch) { + if (typeof claim.status !== 'undefined' && claim.status !== manifestClaim.status) { + if ( + config.modelPageOptions?.preventContributionAfterSubmission && + manifestClaim.status === 2 && + (claim.status === 0 || claim.status === 1) && + manifestClaim.state.revisionId + ) { + throw new Error('Cannot update task in review'); + } + + context.response.body = { + claim: await userApi.updateTask(manifestClaim.id, { + status: claim.status, + status_text: statusToClaimMap[claim.status as any] || 'in progress', + }), + }; + return; + } + + context.response.body = { + claim: await userApi.getTaskById(manifestClaim.id as string, true, 0, undefined, undefined, true), + }; + return; + } + } // The normal path. context.response.body = { claim: await userApi.getTaskById(manifestClaim.id as string, true, 0, undefined, undefined, true), From 757d93022b793f5e5b69c6546128b095f7fb2443 Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 14 May 2024 16:11:59 +0100 Subject: [PATCH 2/3] Fixed "hide completed" on large collections --- CHANGELOG.md | 1 + services/madoc-ts/src/gateway/api.ts | 12 ++++++++++ services/madoc-ts/src/router.ts | 7 +++--- .../routes/iiif/collections/get-collection.ts | 24 +++++++++++++------ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2c4200d1..689289aa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Adding Manifests to projects with large amounts of content - Fixed status of Manifest task after submission +- Fixed "Hide completed" on very large collections ## [v2.2.3](https://github.com/digirati-co-uk/madoc-platform/compare/v2.2.2...v2.2.3) - 13/05/2024 diff --git a/services/madoc-ts/src/gateway/api.ts b/services/madoc-ts/src/gateway/api.ts index 7faa7d205..b5b5f7614 100644 --- a/services/madoc-ts/src/gateway/api.ts +++ b/services/madoc-ts/src/gateway/api.ts @@ -1092,6 +1092,18 @@ export class ApiClient { } async getCollectionById(id: number, page = 0, type?: 'manifest' | 'collection', excluded?: number[]) { + if (excluded && excluded.length) { + return this.request( + `/api/madoc/iiif/collections-bulk/${id}${page || type ? `?${stringify({ type, page })}` : ''}`, + { + body: { + excluded, + }, + method: 'POST', + } + ); + } + return this.request( `/api/madoc/iiif/collections/${id}${page || type || excluded ? `?${stringify({ type, page, excluded })}` : ''}` ); diff --git a/services/madoc-ts/src/router.ts b/services/madoc-ts/src/router.ts index 3bfb7cd38..0174d28dc 100644 --- a/services/madoc-ts/src/router.ts +++ b/services/madoc-ts/src/router.ts @@ -31,7 +31,7 @@ import { getAutomatedUsers } from './routes/manage-site/get-automated-users'; import { createProjectExport } from './routes/projects/create-project-export'; import { getProjectFromTask } from './routes/projects/get-project-from-task'; import { getProjectRawData } from './routes/projects/get-project-raw-data'; -import { listProjectEmails } from "./routes/projects/list-project-emails"; +import { listProjectEmails } from './routes/projects/list-project-emails'; import { listProjectModelEntityAutocomplete } from './routes/projects/list-project-model-entity-autocomplete'; import { addProjectFeedback, listProjectFeedback, removeProjectFeedback } from './routes/projects/project-feedback'; import { @@ -49,7 +49,7 @@ import { } from './routes/projects/project-updates'; import { svgFromCrowdsourcingTask } from './routes/projects/svg-from-crowdsourcing-task'; import { updateProjectAnnotationStyle } from './routes/projects/update-project-annotation-style'; -import { updateProjectBanner } from "./routes/projects/update-project-banner"; +import { updateProjectBanner } from './routes/projects/update-project-banner'; import { updateProjectDuration } from './routes/projects/update-project-duration'; import { siteRoot } from './routes/root'; import { @@ -164,7 +164,7 @@ import { updateProjectStatus } from './routes/projects/update-project-status'; import { siteManifestTasks } from './routes/site/site-manifest-tasks'; import { getStaticPage, sitePages } from './routes/site/site-pages'; import { listProjectsAutocomplete } from './routes/projects/list-projects-autocomplete'; -import { siteProjectMembers } from "./routes/site/site-project-members"; +import { siteProjectMembers } from './routes/site/site-project-members'; import { siteProjectRecent } from './routes/site/site-project-recent'; import { siteProjectUpdates } from './routes/site/site-project-updates'; import { siteTaskMetadata } from './routes/site/site-task-metadata'; @@ -399,6 +399,7 @@ export const router = new TypedRouter({ // Collection API. 'list-collections': [TypedRouter.GET, '/api/madoc/iiif/collections', listCollections], 'get-collection': [TypedRouter.GET, '/api/madoc/iiif/collections/:id', getCollection], + 'get-collection-bulk': [TypedRouter.POST, '/api/madoc/iiif/collections-bulk/:id', getCollection], 'create-collection': [ TypedRouter.POST, '/api/madoc/iiif/collections', diff --git a/services/madoc-ts/src/routes/iiif/collections/get-collection.ts b/services/madoc-ts/src/routes/iiif/collections/get-collection.ts index d81774f89..2351bf8bd 100644 --- a/services/madoc-ts/src/routes/iiif/collections/get-collection.ts +++ b/services/madoc-ts/src/routes/iiif/collections/get-collection.ts @@ -14,11 +14,18 @@ export const getCollection: RouteMiddleware<{ id: number }> = async context => { const manifestsPerPage = 24; const excludeManifests = context.query.excluded; - const excluded = Array.isArray(excludeManifests) + let excluded = Array.isArray(excludeManifests) ? excludeManifests : excludeManifests - ? excludeManifests.split(',') - : undefined; + ? excludeManifests.split(',') + : undefined; + + if (context.requestBody && context.requestBody.excluded) { + excluded = Array.isArray(context.requestBody.excluded) + ? context.requestBody.excluded + : context.requestBody.excluded.split(','); + } + const { total = 0 } = (await context.connection.maybeOne(getResourceCount(collectionId, siteId))) || { total: 0 }; const adjustedTotal = excluded ? total - excluded.length : total; const totalPages = Math.ceil(adjustedTotal / manifestsPerPage) || 1; @@ -48,10 +55,13 @@ export const getCollection: RouteMiddleware<{ id: number }> = async context => { const totals = await context.connection.any(getResourceCount([collectionId], siteId)); - const totalsIdMap = totals.reduce((state, row) => { - state[row.resource_id] = row.total; - return state; - }, {} as { [id: string]: number }); + const totalsIdMap = totals.reduce( + (state, row) => { + state[row.resource_id] = row.total; + return state; + }, + {} as { [id: string]: number } + ); const returnCollections = []; const collection = table.collections[`${collectionId}`] || { From c07eb29e981c3b978d8008482f1075bfb81688fb Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 14 May 2024 16:12:06 +0100 Subject: [PATCH 3/3] Fixed warning in console --- services/madoc-ts/src/utility/gen-rsa.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/madoc-ts/src/utility/gen-rsa.ts b/services/madoc-ts/src/utility/gen-rsa.ts index d815df91f..965c225af 100644 --- a/services/madoc-ts/src/utility/gen-rsa.ts +++ b/services/madoc-ts/src/utility/gen-rsa.ts @@ -58,5 +58,5 @@ export async function genRSA(force = false) { // When this function is called dynamically, it's likely to cause some disruption. // And all users will be logged out. This is only temporary, the service will be // restarted (without downtime) - require('../gateway/api.server').api.invalidateJwt(); + (await import('../gateway/api.server')).api.invalidateJwt(); }