Skip to content

Commit 66b3b5c

Browse files
cubapthehabes
andauthored
235 save annotations (#240)
* passing through the projectID * some tests * support page * path in Page class generator * no label is fine for Pages * updating layers * AI generated tests * Update API.md * oh auth. * how'd we miss this? * Create lineRouter with new paths remove line library and add methods to class * getLine * really loading lines * line modification * test barf * aw thucks! * Hi, I'm new here. * old tests * adjust for tests * default exports for tests * wrangling AI tests Jest mock is a nightmare. * old tests * adjust for tests * default exports for tests * wrangling AI tests Jest mock is a nightmare. * just skip to move on * Update Layer.js * Update index.js * merged mess unwrap * dummy * Update Project.js * handle labels throughout * unerring * update layer organized * return changes * avoid hard crash * prevent crash on a page 404 * full id After I PUT a new label (this was successful) the "id" on the layer the db obj does not the the prefix and is just the hash. * you get it * vaildate all singular changes * greedier try-catch * Squashed commit of the following: commit 44b75cf Author: Priyal Patel <52342511+mepripri@users.noreply.github.com> Date: Wed May 7 10:13:21 2025 -0500 Localhost URLS Validating (#242) * Update index.js * Update index.js * Update validateURL.js --------- Co-authored-by: Patrick Cuba <cubap@slu.edu> commit 032ef45 Merge: f977234 52edaab Author: cubap <cubap@slu.edu> Date: Mon May 5 10:40:24 2025 -0500 Merge branch 'development' into import-tpen28 commit 52edaab Author: Priyal Patel <52342511+mepripri@users.noreply.github.com> Date: Fri May 2 09:36:27 2025 -0500 Getting User Projects (#237) * Update index.mjs * Update index.mjs * Update index.mjs * Update index.mjs * Update index.mjs * Using UID to get User Projects * Update index.mjs * Origin Fetch * SetHeader Origin * Update index.js * Update index.js * Update index.js commit f977234 Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 13:14:16 2025 -0500 Update index.js commit dde7c30 Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 13:05:02 2025 -0500 SetHeader Origin commit d2ec198 Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 12:47:32 2025 -0500 Origin Fetch commit 83fac3a Merge: 6e79a8d 2e5bbbd Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 09:31:12 2025 -0500 Merge branch 'development' into import-tpen28 commit 2e5bbbd Merge: 443d0a2 9f102fb Author: Patrick Cuba <cubap@slu.edu> Date: Wed Apr 30 22:38:43 2025 -0500 Merge branch 'development' of https://github.com/CenterForDigitalHumanities/TPEN-services into development commit 443d0a2 Author: cubap <cubap@slu.edu> Date: Wed Apr 30 15:23:02 2025 -0500 no label is fine for Pages commit 6e79a8d Merge: ac0182f 9f102fb Author: Priyal Patel <mepripri0712@gmail.com> Date: Wed Apr 30 12:06:38 2025 -0500 Merge branch 'development' into import-tpen28 commit ac0182f Author: Priyal Patel <mepripri0712@gmail.com> Date: Wed Apr 30 11:51:40 2025 -0500 Update index.mjs commit 673a5c5 Author: Priyal Patel <mepripri0712@gmail.com> Date: Tue Apr 29 17:22:08 2025 -0500 Using UID to get User Projects commit afe664e Author: Priyal Patel <mepripri0712@gmail.com> Date: Mon Apr 28 10:16:27 2025 -0500 Update index.mjs commit 6bf9c9a Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 14:56:11 2025 -0500 Update index.mjs commit 0906084 Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 14:50:54 2025 -0500 Update index.mjs commit 5dd077e Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 14:33:53 2025 -0500 Update index.mjs commit e9971bc Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 12:18:30 2025 -0500 Update index.mjs * Squashed commit of the following: commit 44b75cf Author: Priyal Patel <52342511+mepripri@users.noreply.github.com> Date: Wed May 7 10:13:21 2025 -0500 Localhost URLS Validating (#242) * Update index.js * Update index.js * Update validateURL.js --------- Co-authored-by: Patrick Cuba <cubap@slu.edu> commit 032ef45 Merge: f977234 52edaab Author: cubap <cubap@slu.edu> Date: Mon May 5 10:40:24 2025 -0500 Merge branch 'development' into import-tpen28 commit 52edaab Author: Priyal Patel <52342511+mepripri@users.noreply.github.com> Date: Fri May 2 09:36:27 2025 -0500 Getting User Projects (#237) * Update index.mjs * Update index.mjs * Update index.mjs * Update index.mjs * Update index.mjs * Using UID to get User Projects * Update index.mjs * Origin Fetch * SetHeader Origin * Update index.js * Update index.js * Update index.js commit f977234 Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 13:14:16 2025 -0500 Update index.js commit dde7c30 Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 13:05:02 2025 -0500 SetHeader Origin commit d2ec198 Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 12:47:32 2025 -0500 Origin Fetch commit 83fac3a Merge: 6e79a8d 2e5bbbd Author: Priyal Patel <mepripri0712@gmail.com> Date: Thu May 1 09:31:12 2025 -0500 Merge branch 'development' into import-tpen28 commit 2e5bbbd Merge: 443d0a2 9f102fb Author: Patrick Cuba <cubap@slu.edu> Date: Wed Apr 30 22:38:43 2025 -0500 Merge branch 'development' of https://github.com/CenterForDigitalHumanities/TPEN-services into development commit 443d0a2 Author: cubap <cubap@slu.edu> Date: Wed Apr 30 15:23:02 2025 -0500 no label is fine for Pages commit 6e79a8d Merge: ac0182f 9f102fb Author: Priyal Patel <mepripri0712@gmail.com> Date: Wed Apr 30 12:06:38 2025 -0500 Merge branch 'development' into import-tpen28 commit ac0182f Author: Priyal Patel <mepripri0712@gmail.com> Date: Wed Apr 30 11:51:40 2025 -0500 Update index.mjs commit 673a5c5 Author: Priyal Patel <mepripri0712@gmail.com> Date: Tue Apr 29 17:22:08 2025 -0500 Using UID to get User Projects commit afe664e Author: Priyal Patel <mepripri0712@gmail.com> Date: Mon Apr 28 10:16:27 2025 -0500 Update index.mjs commit 6bf9c9a Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 14:56:11 2025 -0500 Update index.mjs commit 0906084 Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 14:50:54 2025 -0500 Update index.mjs commit 5dd077e Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 14:33:53 2025 -0500 Update index.mjs commit e9971bc Author: Priyal Patel <mepripri0712@gmail.com> Date: Fri Apr 25 12:18:30 2025 -0500 Update index.mjs * 422 if no pages are there. * Update index.js * Update index.js * Update index.js * since I'm here... moved some functions into their own space * teehee * Make it so. * fixed GET /line/:id * page isn't a page? * undata * more details in data objects * Update Line.js * load it for updates * put overwrite in for updating pages * unlog * changing route format for compile trouble * no test * No. This is wrong and fills me with hate. * quick code comment * patches for PATCHes --------- Co-authored-by: Bryan Haberberger <bryan.j.haberberger@slu.edu>
1 parent 20305c0 commit 66b3b5c

14 files changed

Lines changed: 408 additions & 321 deletions

File tree

app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ app.all('*', (req, res, next) => {
6060

6161
app.use('/', indexRouter)
6262
app.use('/manifest', manifestRouter)
63+
app.use('/project/:projectId/page/:pageId/line', lineRouter)
6364
app.use('/project', projectRouter)
64-
app.use('/line', lineRouter)
6565
app.use('/user', userProfileRouter)
6666
app.use('/my', privateProfileRouter)
6767
app.use('/proxy', proxyRouter)

classes/Layer/Layer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export default class Layer {
5959

6060
// Public Methods
6161
async delete() {
62-
if (this.#tinyAction === 'delete') {
62+
if (this.#tinyAction === 'update') {
6363
await Promise.all(this.pages.map(page => {
6464
const p = new Page(this.id, page)
6565
return p.delete()

classes/Line/Line.js

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ const databaseTiny = new dbDriver("tiny")
44
export default class Line {
55

66
#tinyAction = 'create'
7-
#setRerumId() {
8-
if (this.#tinyAction === 'create') {
9-
this.id = `${process.env.RERUMIDPREFIX}${id.split("/").pop()}`
7+
#setRerumId(force) {
8+
if (force || this.#tinyAction === 'create') {
9+
this.id = `${process.env.RERUMIDPREFIX}${this.id.split("/").pop()}`
1010
}
1111
return this
1212
}
1313

14-
constructor({ id, target, body }) {
14+
constructor({ id, target, body, motivation, label, type }) {
1515
if (!id || !body || !target) {
1616
throw new Error('Line data is malformed.')
1717
}
@@ -21,19 +21,23 @@ export default class Line {
2121
if (id.startsWith?.(process.env.RERUMIDPREFIX)) {
2222
this.#tinyAction = 'update'
2323
}
24+
if (motivation) this.motivation = motivation
25+
if (label) this.label = label
26+
if (type) this.type = type
2427
return this
2528
}
2629

27-
static build(projectId, pageId, { id, body, target }) {
28-
id ??= `${process.env.SERVERURL}/project/${projectId}/page/${pageId}/line/${databaseTiny.reserveId()}`
29-
return new Line({ id, body, target })
30+
static build(projectId, pageId, { body, target, motivation, label, type }) {
31+
// TODO: Should this have a space for an id that is sent in?
32+
const id = `${process.env.SERVERURL}project/${projectId}/page/${pageId}/line/${databaseTiny.reserveId()}`
33+
return new Line({ id, body, target, motivation, label, type })
3034
}
3135

3236
async #saveLineToRerum() {
3337
const lineAsAnnotation = {
3438
"@context": "http://iiif.io/api/presentation/3/context.json",
3539
id: this.id,
36-
type: "Annotation",
40+
type: this.type ?? "Annotation",
3741
motivation: this.motivation ?? "transcribing",
3842
target: this.target,
3943
body: this.body
@@ -49,11 +53,21 @@ export default class Line {
4953
}
5054
// ...else Update the existing page in RERUM
5155
const existingLine = await fetch(this.id).then(res => res.json())
56+
.catch(err => {
57+
if (err.status === 404) {
58+
// If the line doesn't exist, we can create it
59+
return null
60+
}
61+
throw new Error(`Failed to fetch existing Line from RERUM: ${err.message}`)
62+
})
63+
5264
if (!existingLine) {
53-
throw new Error(`Failed to find Line in RERUM: ${this.id}`)
65+
// This id doesn't exist in RERUM, so we need to create it
66+
this.#tinyAction = 'create'
5467
}
55-
const updatedLine = { ...existingLine, ...lineAsAnnotation }
56-
const newURI = await databaseTiny.update(updatedLine).then(res => res.headers.get('location')).catch(err => {
68+
const updatedLine = existingLine ? { ...existingLine, ...lineAsAnnotation } : lineAsAnnotation
69+
const newURI = await databaseTiny[this.#tinyAction](updatedLine).then(res => res.id)
70+
.catch(err => {
5771
throw new Error(`Failed to update Line in RERUM: ${err.message}`)
5872
})
5973
this.id = newURI
@@ -65,17 +79,17 @@ export default class Line {
6579
* @returns {Promise} Resolves to the updated Layer object as stored in Project.
6680
*/
6781
async update() {
68-
if (this.#tinyAction === 'update' || typeof this.body !== 'string') {
69-
await this.#setRerumId().#saveLineToRerum()
82+
if (this.#tinyAction === 'update' || this.body) {
83+
this.#setRerumId(true)
84+
await this.#saveLineToRerum()
7085
}
7186
return this.#updateLineForPage()
7287
}
7388

7489
async #updateLineForPage() {
7590
return {
7691
id: this.id,
77-
target: this.target,
78-
body: this.body,
92+
target: this.target
7993
}
8094
}
8195
async updateText(text) {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import Line from '../Line.js'
2+
3+
describe.skip('Line class unit tests', () => {
4+
it('should throw an error if no ID, body, or target is provided', () => {
5+
expect(() => new Line({})).toThrow('Line data is malformed.')
6+
})
7+
8+
it('should create a new Line instance with valid data', () => {
9+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
10+
expect(line.id).toBe('123')
11+
expect(line.body).toBe('Sample text')
12+
expect(line.target).toBe('https://example.com?xywh=10,10,100,100')
13+
})
14+
15+
it('should save a line to RERUM', async () => {
16+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
17+
const savedLine = await line.update()
18+
expect(savedLine.id).toBeDefined()
19+
})
20+
21+
it('should update the text of a line', async () => {
22+
const line = new Line({ id: '123', body: 'Old text', target: 'https://example.com?xywh=10,10,100,100' })
23+
const updatedLine = await line.updateText('New text')
24+
expect(updatedLine.body).toBe('New text')
25+
})
26+
27+
it('should not update the text if it is the same', async () => {
28+
const line = new Line({ id: '123', body: 'Same text', target: 'https://example.com?xywh=10,10,100,100' })
29+
const updatedLine = await line.updateText('Same text')
30+
expect(updatedLine.body).toBe('Same text')
31+
})
32+
33+
it('should update the bounds of a line', async () => {
34+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
35+
const updatedLine = await line.updateBounds({ x: 20, y: 20, w: 200, h: 200 })
36+
expect(updatedLine.target).toBe('https://example.com?xywh=20,20,200,200')
37+
})
38+
39+
it('should not update the bounds if they are the same', async () => {
40+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
41+
const updatedLine = await line.updateBounds({ x: 10, y: 10, w: 100, h: 100 })
42+
expect(updatedLine.target).toBe('https://example.com?xywh=10,10,100,100')
43+
})
44+
45+
it('should return JSON-LD format when isLD is true', () => {
46+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
47+
const jsonLD = line.asJSON(true)
48+
expect(jsonLD).toEqual({
49+
'@context': 'http://iiif.io/api/presentation/3/context.json',
50+
id: '123',
51+
type: 'Annotation',
52+
motivation: 'transcribing',
53+
target: 'https://example.com?xywh=10,10,100,100',
54+
body: 'Sample text'
55+
})
56+
})
57+
58+
it('should return plain JSON format when isLD is false', () => {
59+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
60+
const json = line.asJSON(false)
61+
expect(json).toEqual({
62+
id: '123',
63+
body: 'Sample text',
64+
target: 'https://example.com?xywh=10,10,100,100'
65+
})
66+
})
67+
68+
it('should delete a line', async () => {
69+
const line = new Line({ id: '123', body: 'Sample text', target: 'https://example.com?xywh=10,10,100,100' })
70+
const result = await line.delete()
71+
expect(result).toBe(true)
72+
})
73+
})

classes/Page/Page.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default class Page {
77
#tinyAction = 'create'
88
#setRerumId() {
99
if (this.#tinyAction === 'create') {
10-
this.id = `${process.env.RERUMIDPREFIX}${id.split("/").pop()}`
10+
this.id = `${process.env.RERUMIDPREFIX}${this.id.split("/").pop()}`
1111
}
1212
return this
1313
}
@@ -22,18 +22,18 @@ export default class Page {
2222
* @param {String} target The uri of the targeted Canvas.
2323
* @seeAlso {@link Page.build}
2424
*/
25-
constructor(layerId, { id, label, target }) {
25+
constructor(layerId, { id, label, target, items = [] }) {
2626
if (!id || !target) {
2727
throw new Error("Page data is malformed.")
2828
}
29-
Object.assign(this, { id, label, target, partOf: layerId })
29+
Object.assign(this, { id, label, target, partOf: layerId, items })
3030
if (this.id.startsWith(process.env.RERUMIDPREFIX)) {
3131
this.#tinyAction = 'update'
3232
}
3333
return this
3434
}
3535

36-
static build(projectId, layerId, canvas, prev, next, lines = []) {
36+
static build(projectId, layerId, canvas, prev, next, items = []) {
3737
if (!projectId) {
3838
throw new Error("Project ID is required to create a Page instance.")
3939
}
@@ -47,7 +47,7 @@ export default class Page {
4747
canvas = {id : canvas}
4848
}
4949

50-
const id = lines.length
50+
const id = items.length
5151
? `${process.env.RERUMIDPREFIX}${databaseTiny.reserveId()}`
5252
: `${process.env.SERVERURL}project/${projectId}/page/${databaseTiny.reserveId()}`
5353

@@ -59,7 +59,7 @@ export default class Page {
5959
label: canvas.label ?? `Page ${canvas.id.split('/').pop()}`,
6060
target: canvas.id,
6161
partOf: layerId,
62-
items: lines,
62+
items,
6363
prev,
6464
next
6565
}
@@ -76,7 +76,7 @@ export default class Page {
7676
label: { "none": [this.label] },
7777
target: this.target,
7878
partOf: this.partOf,
79-
items: this.data.items ?? [],
79+
items: this.items ?? [],
8080
prev: this.prev ?? null,
8181
next: this.next ?? null
8282
}
@@ -105,7 +105,8 @@ export default class Page {
105105
*/
106106
async update() {
107107
if (this.#tinyAction === 'update' || this.items.length) {
108-
await this.#setRerumId().#savePageToRerum()
108+
this.#setRerumId()
109+
await this.#savePageToRerum()
109110
}
110111
return this.#updatePageForProject()
111112
}
@@ -124,7 +125,8 @@ export default class Page {
124125
return {
125126
id: this.id,
126127
label: this.label,
127-
target: this.target
128+
target: this.target,
129+
items: this.items ?? []
128130
}
129131
}
130132

database/driver.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,19 @@ class dbDriver {
118118
return this.controller.remove(data, collection)
119119
}
120120

121+
/**
122+
* Overwrite an existing object in the database
123+
* @param data JSON from an HTTP POST request. It must contain an id.
124+
* @param collection Optional collection override
125+
* @return The updated document JSON or error JSON
126+
*/
127+
async overwrite(data, collection) {
128+
data._modifiedAt = new Date()
129+
collection ??= resolveCollection(data)
130+
if (!collection) throw new Error("Cannot determine collection for overwrite operation")
131+
return this.controller.overwrite(data, collection)
132+
}
133+
121134
/**
122135
* Get data from the database that have matching property values.
123136
* @param query JSON from an HTTP POST request. It must contain at least one property.

line/__tests__/end_to_end_unit.test.js

Lines changed: 0 additions & 52 deletions
This file was deleted.

line/__tests__/exists_unit.test.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)