Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ on:
- deploy/staging
- main
paths:
- .github/workflows/docs.yaml
- docs/*
- .github/workflows/docs.yml
- docs/**
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ start-with-step: deps-node env.json
export AWS_DEFAULT_REGION=us-east-1 ;\
sam local start-lambda --warm-containers=LAZY -t av-download/template.yaml --host 0.0.0.0 --port 3005 --env-vars $$PWD/env.json --log-file lambda.log & \
echo $$! > .sam-pids ;\
sg open all 3005 ;\
sgport open all 3005 ;\
sam local start-api --warm-containers=LAZY -t api/template.yaml --env-vars $$PWD/env.json --host 0.0.0.0 --port 3002 --log-file dc-api.log \
--ssl-cert-file $$HOME/.dev_cert/dev.rdc.cert.pem --ssl-key-file $$HOME/.dev_cert/dev.rdc.key.pem & \
echo $$! >> .sam-pids ;\
docker run --rm -p 8083:8083 -e LAMBDA_ENDPOINT=http://172.17.0.1:3005/ amazon/aws-stepfunctions-local ;\
echo -n "Shutting down..." ;\
sg close all 3005 ;\
sgport close all 3005 ;\
kill $$(cat .sam-pids) ;\
rm -f .sam-pids ;\
echo ""
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Develop against changes to the API.
2. Open the port so it can be accessed in the browser.

```
sg open all 3003
sgport open all 3003
```

3. Point to the proxy URL and start DC app (in your `/environment/dc-nextjs` shell)
Expand Down Expand Up @@ -142,7 +142,7 @@ In a nutshell:
2. Edit the Markdown files in the `docs/docs` directory.
3. To run `mkdocs` locally and preview your work:
```shell
sg open all 8000
sgport open all 8000
make serve-docs
```
Docs will be accessible at http://USER_PREFIX.dev.rdc.library.northwestern.edu:8000/
Expand All @@ -151,7 +151,7 @@ In a nutshell:

We also maintain an OpenAPI Specification under the docs directory in [`spec/openapi.yaml`](docs/docs/spec/openapi.yaml). When `mkdocs` is running, the Swagger UI can be found at http://USER_PREFIX.dev.rdc.library.northwestern.edu:8000/spec/openapi.html. Like the rest of the documentation, changes to the YAML will be immediately visible in the browser.

The existing spec files ([`openapi.yaml`](docs/docs/spec/openapi.yaml) and [`types.yaml`](docs/docs/spec/types.yaml)) are the best reference for understanding and updating the spec. It's especially important to understand how `openapi.yaml` uses the [`$ref` keyword](https://swagger.io/docs/specification/using-ref/) to refer to reusable elements defined in `types.yaml`.
The existing spec files ([`openapi.yaml`](docs/docs/spec/openapi.yaml), [`types.yaml`](docs/docs/spec/types.yaml), and [`data-types.yaml`](docs/docs/spec/data-types.yaml)) are the best reference for understanding and updating the spec. It's especially important to understand how `openapi.yaml` uses the [`$ref` keyword](https://swagger.io/docs/specification/using-ref/) to refer to reusable elements defined in `types.yaml`, and how `types.yaml` pulls model schemas from `data-types.yaml`.

For an in-depth look, or to learn how to define things for which there aren't good examples in our spec, refer to the [full OpenAPI documentation](https://swagger.io/docs/specification/).

Expand All @@ -178,4 +178,4 @@ The current API version is maintained in several different project files. To inc
```
make version BUMP=<major|minor|patch>
```
If you don't specify a `BUMP` value, the command will simply print the current version.
If you don't specify a `BUMP` value, the command will simply print the current version.
4 changes: 2 additions & 2 deletions api/dependencies/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/dependencies/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dc-api-dependencies",
"version": "2.9.1",
"version": "2.9.2",
"description": "NUL Digital Collections API Dependencies",
"repository": "https://github.com/nulib/dc-api-v2",
"author": "nulib",
Expand Down
7 changes: 7 additions & 0 deletions api/openapitools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "7.14.0"
}
}
4 changes: 2 additions & 2 deletions api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dc-api-build",
"version": "2.9.1",
"version": "2.9.2",
"description": "NUL Digital Collections API Build Environment",
"repository": "https://github.com/nulib/dc-api-v2",
"author": "nulib",
Expand Down
12 changes: 12 additions & 0 deletions api/src/api/opensearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ async function getWorkFileSets(workId, opts = {}) {
allowUnpublished = false,
role = null,
source = null,
sortBy = null,
sortOrder = "asc",
} = opts;

const visibilityFilters = [];
Expand Down Expand Up @@ -61,6 +63,16 @@ async function getWorkFileSets(workId, opts = {}) {
},
};

if (sortBy) {
searchBody.sort = [
{
[sortBy]: {
order: sortOrder,
},
},
];
}

if (source) {
searchBody._source = source;
}
Expand Down
69 changes: 69 additions & 0 deletions api/src/api/response/iiif/annotations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const { dcApiEndpoint } = require("../../../environment");
const { getWorkFileSets } = require("../../opensearch");

async function transform(response, options = {}) {
const body = JSON.parse(response.body);
const fileSet = body._source;
const annotations = fileSet?.annotations ?? [];

const workId = fileSet.work_id;
const fileSetId = body._id;
const fileSetIndex = await getFileSetIndex(workId, fileSetId, options);

const canvasId = `${dcApiEndpoint()}/works/${workId}?as=iiif/canvas/${fileSetIndex}`;
const annotationPageId = `${dcApiEndpoint()}/file-sets/${
fileSet.id
}/annotations?as=iiif`;

// Build annotation items - filter for transcriptions only
// We currently will only have one annotation and it's a transcription
const items = annotations
.filter((annotation) => annotation.type === "transcription")
.map((annotation, idx) => {
const annotationId = `${annotationPageId}/a${idx}`;
return {
id: annotationId,
type: "Annotation",
motivation: "commenting",
body: {
type: "TextualBody",
value: annotation.content,
format: "text/plain",
language: annotation.language || "en",
},
target: canvasId,
};
});

const annotationPage = {
"@context": "http://iiif.io/api/presentation/3/context.json",
id: annotationPageId,
type: "AnnotationPage",
items: items,
};

return {
statusCode: 200,
headers: {
"content-type": "application/json",
},
body: JSON.stringify(annotationPage),
};
}

async function getFileSetIndex(workId, fileSetId, options) {
const fileSetsResponse = await getWorkFileSets(workId, {
allowPrivate: options.allowPrivate,
allowUnpublished: options.allowUnpublished,
role: "Access",
sortBy: "rank",
});

const fileSetBody = JSON.parse(fileSetsResponse.body);
const hits = fileSetBody?.hits?.hits || [];

const index = hits.findIndex((hit) => hit._source.id === fileSetId);

return index;
}
module.exports = { transform };
59 changes: 59 additions & 0 deletions api/src/api/response/iiif/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ async function buildCollection(responseBody, pageInfo) {
];
}

const navPlace = buildCollectionNavPlace(responseBody?.hits?.hits);
if (navPlace) {
result.navPlace = navPlace;
}

return result;
}

Expand Down Expand Up @@ -236,4 +241,58 @@ function loadItem(item, itemType, size) {
}
}

function buildCollectionNavPlace(hits = []) {
if (!hits || hits.length === 0) return null;

const allFeatures = [];

hits.forEach((hit) => {
const source = hit._source;
if (!source) return;

const navPlace = source.navPlace || source.nav_place;
if (!Array.isArray(navPlace)) return;

const pointFeatures = navPlace
.filter(
(place) =>
place?.coordinates &&
Array.isArray(place.coordinates) &&
place.coordinates.length >= 2 &&
place.label
)
.map((place) => {
const feature = {
type: "Feature",
geometry: {
type: "Point",
coordinates: place.coordinates,
},
properties: {
label: { en: [place.label] },
},
};

if (place.id) {
feature.id = place.id;
}

if (place.summary) {
feature.properties.summary = { en: [place.summary] };
}

return feature;
});

allFeatures.push(...pointFeatures);
});

if (!allFeatures.length) return null;

return {
type: "FeatureCollection",
features: allFeatures,
};
}

module.exports = { transform };
Loading
Loading