Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0b1ba94
change colours and padding
Heather0K Dec 16, 2025
338111b
Merge pull request #849 from digirati-co-uk/improvment/MAD-1055/slot-…
Heather0K Dec 17, 2025
ab3830c
add manifes and canvas uri to cvs export
Heather0K Dec 18, 2025
b01db13
show not found component for unpublished manifest
funkydunc Dec 19, 2025
add81fc
sql filenames
funkydunc Dec 19, 2025
a91c700
add vscode folder to gitignore
funkydunc Dec 19, 2025
ec88733
remove vscode settings
funkydunc Dec 19, 2025
a055eb3
Merge pull request #852 from digirati-co-uk/feat/MAD-1504-unpublished…
funkydunc Dec 19, 2025
1a0c814
WIP Export CVS NLW
Heather0K Dec 22, 2025
8fe9f9d
fix instances of styles in wrong states
Heather0K Dec 22, 2025
c02d4ac
install tanstacktable and replace global user table, add in filerting…
Heather0K Dec 23, 2025
3863bff
MAD-1427 fix typo
Heather0K Dec 23, 2025
3788017
update changelog
Heather0K Dec 23, 2025
44018eb
throw 404 if manifest not published
funkydunc Dec 23, 2025
29628d2
update lists to match
Heather0K Dec 23, 2025
c1e2a83
Merge pull request #854 from digirati-co-uk/MAD-995/replace-tables-ta…
Heather0K Dec 23, 2025
d54f8a2
Merge pull request #850 from digirati-co-uk/improvment/MAD-1530/expor…
Heather0K Dec 23, 2025
98b9c76
Merge pull request #853 from digirati-co-uk/MAD-1055/slot-editor-css-…
Heather0K Dec 23, 2025
1d2bd54
update Site admin dash and style
Heather0K Dec 23, 2025
33cd8a1
allow admin to see unpublished manifests
funkydunc Dec 23, 2025
49c7f08
Merge pull request #855 from digirati-co-uk/feat/MAD-1054-unpublished…
funkydunc Jan 5, 2026
86ba3c6
add status filters to review table
Heather0K Jan 6, 2026
f9c6a52
MAD-1321 column width resize
Heather0K Jan 6, 2026
367385e
Merge pull request #856 from digirati-co-uk/MAD-1320/filter-status-re…
Heather0K Jan 7, 2026
113a297
NS-75 add contribution export impromvents
Heather0K Jan 8, 2026
de5a58d
fix transcriber filter, fix filter styles and add reset button
Heather0K Jan 8, 2026
5a59b78
replace fixed width with vw %
Heather0K Jan 8, 2026
b5254fd
remove console.log
Heather0K Jan 9, 2026
acdb249
fix sort by asignee on review table
Heather0K Jan 9, 2026
268d029
MAD-995 added server filtering
stephenwf Jan 9, 2026
4c7bced
New useLocationState hook
stephenwf Jan 9, 2026
3da7ae6
Update site-user-repository.ts
stephenwf Jan 9, 2026
7ac1fd3
MAD-995 - Attempt to hook up the existing filters to the server
stephenwf Jan 9, 2026
ec80cdd
MAD-995 refactored out the sort code
stephenwf Jan 9, 2026
aaf66e5
MAD-995 split out reusable sortable toggle
stephenwf Jan 9, 2026
68c011f
MAD-1054 - Fixed unpublished manifest permissions
stephenwf Jan 12, 2026
53961ee
MAD-995 Fixed PR feedback
stephenwf Jan 12, 2026
740b09f
MAD-955 Added text search
stephenwf Jan 12, 2026
20f817b
Merge pull request #859 from digirati-co-uk/feature/MAD-995-server-fi…
stephenwf Jan 12, 2026
6df8958
Added open in Theseus link to Manifests
stephenwf Jan 12, 2026
96ee4d9
Fixed changelog
stephenwf Jan 12, 2026
9c445d2
Merge pull request #860 from digirati-co-uk/feature/open-in-theseus
stephenwf Jan 12, 2026
4531b3d
api key table;
Heather0K Jan 12, 2026
aabcb9c
site permissions
Heather0K Jan 12, 2026
260bd39
update canvas and manifest origonal id
Heather0K Jan 13, 2026
d93a03b
Update services/madoc-ts/src/frontend/admin/pages/sites/site-permissi…
Heather0K Jan 13, 2026
0970d4f
Merge pull request #858 from digirati-co-uk/improvment/MAD-1530/expor…
Heather0K Jan 13, 2026
fa9b7e3
Merge pull request #861 from digirati-co-uk/admin-tables-tanstack
Heather0K Jan 13, 2026
ac45d4a
Updated count to use filter for accurate pagination
stephenwf Jan 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ e2e/test-fixtures/postgres/default/default.sql
services/madoc-next
scripts
notes
.vscode/*
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

-->

## Unreleased

### Changed

- Improved edit mode slot & block styles (MAD-1055)
- CSV exports to include original Manifest/Canvas URI (MAD-1530)
- Replaced Global -> All Users table with Tanstack table and added sorting & filtering (MAD-955)
- Admin interface: Content labelling and content readability improvements (MAD-1466)

### Fixed

- Typo in review dashboard 'changed' to 'change' (MAD-1472)
- Fixed unpublished manifests can still be reached using Google/Bing/etc (MAD-1054)
- Fixed CORS for annotation pages

### Added

- Added "Open in Theseus" link to Manifests

## [v2.2.10](https://github.com/digirati-co-uk/madoc-platform/compare/v2.2.9...v2.2.10)

### Added

- Added button to exclude all manifests from preview collection
- Added button to delete all contributions on a Manifest to hard-reset it (NS-67)
- Added filter by status option to review list table (MAD-1320)
- Added column resizing on review list table (MAD-1321)

### Changed

Expand Down
1 change: 1 addition & 0 deletions services/madoc-ts/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"manifestPageOptions": {
"hideStartContributing": false,
"hideOpenInMirador": false,
"hideOpenInTheseus": false,
"hideSearchButton": false,
"hideRandomCanvas": false,
"hideFilterImages": false,
Expand Down
1 change: 1 addition & 0 deletions services/madoc-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"@manifest-editor/iiif-browser-bundle": "https://pkg.csb.dev/digirati-co-uk/iiif-manifest-editor/commit/cc804fcf/@manifest-editor/iiif-browser-bundle",
"@slonik/migrator": "^0.2.0",
"@styled-icons/entypo": "^10.34.0",
"@tanstack/react-table": "^8.21.3",
"adm-zip": "^0.5.10",
"ajv": "^6.12.3",
"bcrypt": "^5.0.1",
Expand Down
5 changes: 4 additions & 1 deletion services/madoc-ts/schemas/ProjectConfiguration.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@
"hideOpenInMirador": {
"type": "boolean"
},
"hideOpenInTheseus": {
"type": "boolean"
},
"hideSearchButton": {
"type": "boolean"
},
Expand Down Expand Up @@ -426,4 +429,4 @@
"revisionApprovalsRequired"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
}
5 changes: 4 additions & 1 deletion services/madoc-ts/schemas/ProjectConfigurationNEW.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@
"hideOpenInMirador": {
"type": "boolean"
},
"hideOpenInTheseus": {
"type": "boolean"
},
"hideSearchButton": {
"type": "boolean"
},
Expand Down Expand Up @@ -446,4 +449,4 @@
"revisionApprovalsRequired"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
}
3 changes: 3 additions & 0 deletions services/madoc-ts/schemas/ProjectFull.json
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@
"hideOpenInMirador": {
"type": "boolean"
},
"hideOpenInTheseus": {
"type": "boolean"
},
"hideSearchButton": {
"type": "boolean"
},
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ export class CrowdsourcingApi implements BaseExtension {
await this.api.updateRevisionTask(userTaskId, {
// Mark the task as needing changes
status: 4,
status_text: statusText || 'changed requested',
status_text: statusText || 'change requested',
// Add the message to the task
state: {
changesRequested: message,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,124 @@
import { parseModelTarget } from '../../../../utility/parse-model-target';
import { ExportFile } from '../../server-export';
import { ExportConfig, ExportDataOptions, ExportFileDefinition, SupportedExportResource } from '../../types';
import type { ExportConfig, ExportDataOptions, ExportFileDefinition, SupportedExportResource } from '../../types';
import { getValue } from '@iiif/helpers/i18n';

const labelCache: { manifestLabels: Record<string, string>; canvasLabels: Record<string, string> } = {
const labelCache: {
manifestLabels: Record<string, { label?: string; uri?: string }>;
canvasLabels: Record<string, { label?: string; uri?: string }>;
} = {
manifestLabels: {},
canvasLabels: {},
};

const missingUriLogged = {
manifest: new Set<string>(),
canvas: new Set<string>(),
};

async function fetchLabels(api: any, manifestIds: number[], canvasIds: number[]) {
const newManifestIds = manifestIds.filter(id => id !== undefined && !labelCache.manifestLabels[id.toString()]);
const newCanvasIds = canvasIds.filter(id => id !== undefined && !labelCache.canvasLabels[id.toString()]);
const uniqueManifestIds = Array.from(new Set(manifestIds.filter(id => id !== undefined)));
const uniqueCanvasIds = Array.from(new Set(canvasIds.filter(id => id !== undefined)));

const newManifestIds = uniqueManifestIds.filter(id => !labelCache.manifestLabels[id.toString()]);
const newCanvasIds = uniqueCanvasIds.filter(id => !labelCache.canvasLabels[id.toString()]);

function extractOriginalUri(resource: any): string | undefined {
if (!resource) return undefined;

const preferredKeys = [
'id',
'@id',
'source',
'originalId',
'original_id',
'iiifId',
'iiif_id',
'iiifUri',
'iiif_uri',
'uri',
'url',
'sourceId',
'source_id',
];

const isLikelyUri = (v: any) =>
typeof v === 'string' &&
v.length > 3 &&
(v.startsWith('http://') || v.startsWith('https://') || v.startsWith('urn:'));

const visited = new Set<any>();

const scan = (obj: any, depth: number): string | undefined => {
if (!obj || depth < 0) return undefined;
if (typeof obj !== 'object') return undefined;
if (visited.has(obj)) return undefined;
visited.add(obj);

for (const key of preferredKeys) {
const value = (obj as any)[key];
if (isLikelyUri(value)) return value;
}
if (typeof (obj as any).id === 'string' && (obj as any).id.length > 3) {
return (obj as any).id;
}
if (typeof (obj as any)['@id'] === 'string' && (obj as any)['@id'].length > 3) {
return (obj as any)['@id'];
}

for (const value of Object.values(obj)) {
if (value && typeof value === 'object') {
const found = scan(value, depth - 1);
if (found) return found;
}
}

return undefined;
};

return scan(resource, 3);
}

if (newManifestIds.length > 0) {
const manifests = await Promise.all(newManifestIds.map(id => api.getManifestById(id)));
manifests.forEach(response => {
const manifests = await Promise.all(
newManifestIds.map(async id => ({ id, response: await api.getManifestById(id) }))
);

manifests.forEach(({ id, response }) => {
const manifest = response.manifest;
if (manifest && manifest.id !== undefined) {
labelCache.manifestLabels[manifest.id.toString()] = getValue(manifest.label);
if (manifest) {
const uri = extractOriginalUri(manifest);

labelCache.manifestLabels[id.toString()] = {
label: getValue(manifest.label),
uri,
};

if (!uri && !missingUriLogged.manifest.has(id.toString())) {
missingUriLogged.manifest.add(id.toString());
console.warn('CSV export: missing manifest URI', { id, keys: Object.keys(manifest) });
}
} else {
console.warn('CSV export: missing manifest (no response.manifest)', { id });
}
});
}

if (newCanvasIds.length > 0) {
const canvases = await Promise.all(newCanvasIds.map(id => api.getCanvasById(id)));
canvases.forEach(response => {
const canvases = await Promise.all(newCanvasIds.map(async id => ({ id, response: await api.getCanvasById(id) })));

canvases.forEach(({ id, response }) => {
const canvas = response.canvas;
if (canvas && canvas.id !== undefined) {
labelCache.canvasLabels[canvas.id.toString()] = getValue(canvas.label);
if (canvas) {
const uri = extractOriginalUri(canvas) || extractOriginalUri(response);
labelCache.canvasLabels[id.toString()] = {
label: getValue(canvas.label),
uri,
};
if (!uri && !missingUriLogged.canvas.has(id.toString())) {
missingUriLogged.canvas.add(id.toString());
console.warn('CSV export: missing canvas URI', { id, keys: Object.keys(canvas) });
}
}
});
}
Expand Down Expand Up @@ -117,12 +208,11 @@ export const projectCsvSimpleExport: ExportConfig = {

function findBest(fields: any[]) {
const revises = fields.map(r => r.revises);
console.log('FINDING BEST', fields);
return fields.filter(r => !revises.includes(r.id)).pop() || fields[0];
}

const mappedList = Object.entries(rowRecord)
.map(([key, record]) => {
.map(([, record]) => {
const newRecord: any = {
model_id: record.model_id,
doc_id: record.doc_id,
Expand All @@ -135,12 +225,16 @@ export const projectCsvSimpleExport: ExportConfig = {

const target = parseModelTarget(record.target);
if (target.manifest && target.manifest.id !== undefined) {
const manifest = manifestLabels[target.manifest.id.toString()];
newRecord.manifest = target.manifest.id;
newRecord.manifest_label = manifestLabels[target.manifest.id.toString()];
newRecord.manifest_uri = manifest?.uri;
newRecord.manifest_label = manifest?.label;
}
if (target.canvas && target.canvas.id !== undefined) {
const canvas = canvasLabels[target.canvas.id.toString()];
newRecord.canvas = target.canvas.id;
newRecord.canvas_label = canvasLabels[target.canvas.id.toString()];
newRecord.canvas_uri = canvas?.uri;
newRecord.canvas_label = canvas?.label;
}
return newRecord;
}
Expand Down
Loading
Loading