Skip to content

Commit 6a7219f

Browse files
committed
Support local IDs for overlay of MARC records.
refs #3555
1 parent e38de3d commit 6a7219f

File tree

7 files changed

+178
-32
lines changed

7 files changed

+178
-32
lines changed

__tests__/actionCreators/transfer.test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ describe("transfer", () => {
1616
sinopiaApi.postTransfer = jest.fn().mockResolvedValue()
1717
const store = mockStore(createState())
1818
await store.dispatch(
19-
transfer(resourceUri, "stanford", "ils", "testerrorkey")
19+
transfer(resourceUri, "stanford", "ils", "abc123", "testerrorkey")
2020
)
2121

2222
expect(store.getActions()).toHaveLength(0)
2323
expect(sinopiaApi.postTransfer).toHaveBeenCalledWith(
2424
resourceUri,
2525
"stanford",
26-
"ils"
26+
"ils",
27+
"abc123"
2728
)
2829
})
2930
})
@@ -32,7 +33,7 @@ describe("transfer", () => {
3233
sinopiaApi.postTransfer = jest.fn().mockRejectedValue("Ooops!")
3334
const store = mockStore(createState())
3435
await store.dispatch(
35-
transfer(resourceUri, "stanford", "ils", "testerrorkey")
36+
transfer(resourceUri, "stanford", "ils", "abc123", "testerrorkey")
3637
)
3738

3839
expect(store.getActions()).toHaveAction("ADD_ERROR", {

__tests__/feature/editing/transfer.test.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jest.spyOn(Config, "transferConfig", "get").mockReturnValue({
2020
},
2121
})
2222

23-
describe("transfer saved bf:Instance when user belongs to a transfer group", () => {
23+
describe("transfer saved bf:Instance when user belongs to a transfer group and no local ID", () => {
2424
it("allows transfer", async () => {
2525
const state = createState()
2626
const store = createStore(state)
@@ -42,6 +42,37 @@ describe("transfer saved bf:Instance when user belongs to a transfer group", ()
4242

4343
const transferBtn = screen.getByText("Export to Catalog")
4444
fireEvent.click(transferBtn)
45+
fireEvent.click(await screen.findByText("Create a new record in catalog."))
46+
await screen.findByText("Requesting")
47+
}, 15000)
48+
})
49+
50+
describe("transfer saved bf:Instance when user belongs to a transfer group and provided local ID", () => {
51+
it("allows transfer", async () => {
52+
const state = createState()
53+
const store = createStore(state)
54+
renderApp(store)
55+
56+
fireEvent.click(screen.getByText("Linked Data Editor", { selector: "a" }))
57+
58+
fireEvent.change(screen.getByLabelText("Search"), {
59+
target: { value: bfUri },
60+
})
61+
fireEvent.click(screen.getByTestId("Submit search"))
62+
63+
await screen.findByText(bfUri)
64+
fireEvent.click(screen.getByRole("button", { name: `Edit ${bfUri}` }))
65+
66+
await screen.findByText("The Practitioner's Guide to Graph Data", {
67+
selector: resourceHeaderSelector,
68+
})
69+
70+
const transferBtn = screen.getByText("Export to Catalog")
71+
fireEvent.click(transferBtn)
72+
fireEvent.change(await screen.findByLabelText("Enter local system id"), {
73+
target: { value: "abc123" },
74+
})
75+
fireEvent.click(await screen.findByText("Go"))
4576
await screen.findByText("Requesting")
4677
}, 15000)
4778
})

__tests__/sinopiaApi.test.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,13 +431,13 @@ describe("putUserHistory", () => {
431431
})
432432

433433
describe("postTransfer", () => {
434-
describe("success", () => {
434+
describe("success without localId", () => {
435435
it("returns", async () => {
436436
global.fetch = jest.fn().mockResolvedValue({
437437
ok: true,
438438
})
439439

440-
await postTransfer(resourceUri, "stanford", "ils")
440+
await postTransfer(resourceUri, "stanford", "ils", null)
441441

442442
expect(global.fetch).toHaveBeenCalledWith(
443443
"https://api.development.sinopia.io/transfer/7b4c275d-b0c7-40a4-80b3-e95a0d9d987c/stanford/ils",
@@ -450,6 +450,25 @@ describe("postTransfer", () => {
450450
)
451451
})
452452
})
453+
describe("success with localId", () => {
454+
it("returns", async () => {
455+
global.fetch = jest.fn().mockResolvedValue({
456+
ok: true,
457+
})
458+
459+
await postTransfer(resourceUri, "stanford", "ils", "abc123")
460+
461+
expect(global.fetch).toHaveBeenCalledWith(
462+
"https://api.development.sinopia.io/transfer/7b4c275d-b0c7-40a4-80b3-e95a0d9d987c/stanford/ils/abc123",
463+
{
464+
method: "POST",
465+
headers: {
466+
Authorization: "Bearer Secret-Token",
467+
},
468+
}
469+
)
470+
})
471+
})
453472
})
454473

455474
describe("fetchResourceRelationships", () => {

src/actionCreators/transfer.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import { postTransfer } from "../sinopiaApi"
22
import { addError } from "actions/errors"
33

44
export const transfer =
5-
(resourceUri, group, target, errorKey) => (dispatch) => {
6-
postTransfer(resourceUri, group, target).catch((err) => {
5+
(resourceUri, group, target, localId, errorKey) => (dispatch) =>
6+
postTransfer(resourceUri, group, target, localId).catch((err) => {
77
dispatch(
88
addError(errorKey, `Error requesting transfer: ${err.message || err}`)
99
)
1010
})
11-
}
1211

1312
export const noop = () => {}
Lines changed: 109 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React, { useState, useEffect, useRef } from "react"
22
import PropTypes from "prop-types"
3+
import _ from "lodash"
34

4-
const TransferButton = ({ label, handleClick }) => {
5-
const [btnText, setBtnText] = useState(label)
5+
const TransferButton = ({ label, localId, group, target, handleTransfer }) => {
6+
const [requesting, setRequesting] = useState(false)
7+
const [providedLocalId, setProvidedLocalId] = useState("")
68
const timerRef = useRef(null)
79

810
useEffect(
@@ -12,27 +14,120 @@ const TransferButton = ({ label, handleClick }) => {
1214
[]
1315
)
1416

15-
const handleBtnClick = (event) => {
16-
setBtnText(<em>Requesting</em>)
17-
timerRef.current = setTimeout(() => setBtnText(label), 3000)
18-
handleClick(event)
17+
const handleExistingLocalIdClick = (event) => {
18+
handleTransfer(localId)
19+
notify()
1920
event.preventDefault()
2021
}
2122

23+
const handleProvidedLocalIdClick = (event) => {
24+
handleTransfer(providedLocalId)
25+
notify()
26+
event.preventDefault()
27+
}
28+
29+
const handleNoLocalIdClick = (event) => {
30+
handleTransfer(null)
31+
notify()
32+
event.preventDefault()
33+
}
34+
35+
const notify = () => {
36+
setRequesting(true)
37+
timerRef.current = setTimeout(() => setRequesting(false), 3000)
38+
}
39+
40+
const handleChangeProvidedLocalId = (event) => {
41+
setProvidedLocalId(event.target.value)
42+
event.preventDefault()
43+
}
44+
45+
if (requesting) {
46+
return (
47+
<button type="button" className="btn btn-secondary btn-no-outline">
48+
<em>Requesting</em>
49+
</button>
50+
)
51+
}
52+
53+
const btnId = `transferBtn-${group}-${target}`
54+
const btnClasses = ["btn", "dropdown-toggle", "btn-no-outline"]
55+
const dropDownItemBtnClasses = ["btn", "btn-secondary", "dropdown-item"]
56+
2257
return (
23-
<button
24-
type="button"
25-
className="btn btn-secondary btn-no-outline"
26-
onClick={handleBtnClick}
27-
>
28-
{btnText}
29-
</button>
58+
<div className="btn-group dropdown">
59+
<button
60+
type="button"
61+
id={btnId}
62+
className={btnClasses.join(" ")}
63+
aria-label="Transfer to catalog"
64+
title="Transfer to catalog"
65+
data-bs-toggle="dropdown"
66+
aria-expanded="false"
67+
>
68+
{label}
69+
</button>
70+
<div className="dropdown-menu dropdown-menu-end" aria-labelledby={btnId}>
71+
{localId ? (
72+
<React.Fragment>
73+
<button
74+
className={dropDownItemBtnClasses.join(" ")}
75+
onClick={handleExistingLocalIdClick}
76+
>
77+
Export with local system ID: {localId}
78+
</button>
79+
</React.Fragment>
80+
) : (
81+
<React.Fragment>
82+
<div className="dropdown-item">
83+
Overlay record with local system ID:
84+
<div className="input-group mb-3">
85+
<input
86+
type="text"
87+
className="form-control"
88+
aria-label="Enter local system id"
89+
onChange={handleChangeProvidedLocalId}
90+
value={providedLocalId}
91+
/>
92+
<button
93+
className="btn btn-primary"
94+
type="button"
95+
disabled={_.isEmpty(providedLocalId)}
96+
onClick={handleProvidedLocalIdClick}
97+
>
98+
Go
99+
</button>
100+
</div>
101+
</div>
102+
<button
103+
className={dropDownItemBtnClasses.join(" ")}
104+
onClick={handleNoLocalIdClick}
105+
>
106+
Create a new record in catalog.
107+
</button>
108+
</React.Fragment>
109+
)}
110+
</div>
111+
</div>
30112
)
113+
114+
// return (
115+
// <button
116+
// type="button"
117+
// className="btn btn-secondary btn-no-outline"
118+
// onClick={handleBtnClick}
119+
// >
120+
// {label}
121+
// </button>
122+
// )
31123
}
32124

33125
TransferButton.propTypes = {
34126
label: PropTypes.string.isRequired,
35-
handleClick: PropTypes.func.isRequired,
127+
group: PropTypes.string.isRequired,
128+
target: PropTypes.string.isRequired,
129+
localId: PropTypes.string,
130+
handleTransfer: PropTypes.func.isRequired,
36131
}
37132

38133
export default TransferButton

src/components/editor/actions/TransferButtons.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,17 @@ const TransferButtons = ({ resourceKey }) => {
3535
// Must be targets
3636
if (_.isEmpty(transferTargets)) return null
3737

38-
const handleClick = (event, group, target) => {
39-
dispatch(transfer(resource.uri, group, target, errorKey))
40-
event.preventDefault()
38+
const handleTransfer = (group, target, localId) => {
39+
dispatch(transfer(resource.uri, group, target, localId, errorKey))
4140
}
4241

4342
const buttons = transferTargets.map(([target, group, label]) => (
4443
<TransferButton
4544
key={`${group}-${target}`}
45+
group={group}
46+
target={target}
4647
label={`Export to ${label}`}
47-
handleClick={(event) => handleClick(event, group, target)}
48+
handleTransfer={(localId) => handleTransfer(group, target, localId)}
4849
/>
4950
))
5051

src/sinopiaApi.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,11 @@ export const putUserHistory = (
212212
)
213213
}
214214

215-
export const postTransfer = (resourceUri, group, target) => {
216-
const url = `${resourceUri.replace(
217-
"resource",
218-
"transfer"
219-
)}/${group}/${target}`
215+
export const postTransfer = (resourceUri, group, target, localId) => {
216+
let url = `${resourceUri.replace("resource", "transfer")}/${group}/${target}`
217+
if (localId) {
218+
url += `/${localId}`
219+
}
220220
return getJwt()
221221
.then((jwt) =>
222222
fetch(url, {

0 commit comments

Comments
 (0)