Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scc 4142/spec coll messaging #421

Closed
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
fcc1c3a
add build avail key and use switch statment
charmingduchess Dec 17, 2024
c9e8075
extract contact a librarian
charmingduchess Dec 17, 2024
dba9aa8
extract all availability messaging
charmingduchess Dec 17, 2024
879ef5b
move availability componetns to model
charmingduchess Dec 17, 2024
9d67c2e
use constants for avail keys
charmingduchess Dec 17, 2024
287ba38
use consttants for keys
charmingduchess Dec 17, 2024
d2415ef
add finding aid to bib model;
charmingduchess Dec 17, 2024
c59596f
add finding aid to item and availability models
charmingduchess Dec 17, 2024
383a6f9
start to split aeon statuses
charmingduchess Dec 17, 2024
03cb92f
actual refactor
charmingduchess Dec 17, 2024
d4d0cf6
clean up;
charmingduchess Dec 17, 2024
ca84fb8
move message render to component
charmingduchess Dec 17, 2024
39f8c10
start availability model tests
charmingduchess Dec 17, 2024
bc233b0
more tests for item availability
charmingduchess Dec 17, 2024
b71027e
create all cases in model
charmingduchess Dec 18, 2024
790e7bb
start speccoll tests
charmingduchess Dec 18, 2024
13a0c72
rm non avail details from itemavailability
charmingduchess Dec 18, 2024
2c591bd
more tests
charmingduchess Dec 18, 2024
3ac3d6f
build out rendering cases and tests
charmingduchess Dec 18, 2024
4b5730b
add provisional special collections designation
charmingduchess Dec 18, 2024
caf8731
fix bib/item instantiation bug
charmingduchess Dec 19, 2024
17628f4
add test for bibs and finding aid
charmingduchess Dec 19, 2024
a923226
update to specRequestable and variable casing of finding aid
charmingduchess Dec 19, 2024
a4cf18d
fix recap aeon only case
charmingduchess Dec 19, 2024
115ec56
update request buttons to remove ternary
charmingduchess Dec 19, 2024
57beae1
formatting periods
charmingduchess Dec 19, 2024
74b8e76
fix periods in tests
charmingduchess Dec 20, 2024
a04fe17
return recap general collections message from switch
charmingduchess Dec 20, 2024
5fb0ea1
fix types
charmingduchess Dec 20, 2024
a4be195
return component instead of string
charmingduchess Dec 20, 2024
e997956
replace platform urls
charmingduchess Dec 20, 2024
70f97b1
fix string return
charmingduchess Dec 20, 2024
132661f
rm link from onsite no finding aid no aeon
charmingduchess Dec 23, 2024
eb13be4
rm dash from contactALibrarian component
charmingduchess Dec 23, 2024
de6c2ec
add dash to not available
charmingduchess Dec 23, 2024
7d13a04
move dash
charmingduchess Dec 23, 2024
8c8cddc
add finding aid status badge
charmingduchess Dec 23, 2024
be7bafa
move statusbadge above bib title
charmingduchess Dec 23, 2024
d757054
rm finding aid from electronic resources
charmingduchess Dec 23, 2024
68060ac
add finding aid card to search result
charmingduchess Dec 23, 2024
e7b4ec2
add finding aid information panel
charmingduchess Dec 23, 2024
9fb9fde
fix spacing on finding aid and electronic resources cards
charmingduchess Dec 23, 2024
d9e14eb
update tests for finding aid additions
charmingduchess Dec 23, 2024
81b9cf8
fix spacing
charmingduchess Dec 23, 2024
35d8fc3
move finding aid out of grid
charmingduchess Dec 24, 2024
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 src/components/ItemTable/ItemAvailability.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe("ItemAvailability", () => {
})
it("renders the correct text when item is available, has an aeon url, and has a location endpoint", async () => {
const item = new Item(itemPhysicallyRequestable, parentBib)

render(<ItemAvailability item={item} />)
expect(screen.getByText("Available by appointment")).toBeInTheDocument()
expect(
Expand Down
128 changes: 20 additions & 108 deletions src/components/ItemTable/ItemAvailability.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useContext } from "react"
import { Text, Button, Box } from "@nypl/design-system-react-components"
import { Text, Box } from "@nypl/design-system-react-components"

import ExternalLink from "../Links/ExternalLink/ExternalLink"
import { appConfig } from "../../config/config"
import type Item from "../../models/Item"
import { FeedbackContext } from "../../context/FeedbackContext"
import type { ItemMetadata } from "../../types/itemTypes"
import AvailableByAppointment from "./ItemAvailabilityComponents/AvailableByAppointment"
import NotAvailable from "./ItemAvailabilityComponents/NotAvailable"
import AvailableOnsite from "./ItemAvailabilityComponents/AvailableOnsite"

interface ItemAvailabilityProps {
item: Item
Expand All @@ -17,113 +17,25 @@ interface ItemAvailabilityProps {
* TODO: Add Feedback box, Due date, Available font styles
*/
const ItemAvailability = ({ item }: ItemAvailabilityProps) => {
const { onOpen, setItemMetadata } = useContext(FeedbackContext)

const onContact = (metadata: ItemMetadata) => {
setItemMetadata(metadata)
onOpen()
}

// TODO: Move this logic into a getter function in the Item class that returns an availability status key
// and replace this nested If with a simple switch statement
if (item.isAvailable) {
if (item.isReCAP && !item.aeonUrl) {
// Available ReCAP item
return (
<ExternalLink href={appConfig.urls.researchMaterialsHelp} fontSize="sm">
How do I pick up this item and when will it be ready?
</ExternalLink>
)
} else if (item.aeonUrl && item.location?.endpoint) {
return (
<Text
mb="0"
fontSize={{
base: "mobile.body.body2",
md: "desktop.body.body2",
}}
>
<Box as="span" color="ui.success.primary">
Available by appointment
</Box>
{!item.isReCAP ? (
<>
{" at "}
<ExternalLink
href={`${appConfig.urls.locations}${item.location.endpoint}`}
>
{item.location.prefLabel}
</ExternalLink>
</>
) : null}
</Text>
)
} else {
// Available Onsite item
const locationShort = item.location.prefLabel.split("-")[0]
return (
<Text
mb="0"
fontSize={{
base: "mobile.body.body2",
md: "desktop.body.body2",
}}
>
<Box as="span" color="ui.success.primary">
Available
</Box>
{" - Can be used on site. Please visit "}
<ExternalLink
href={`${appConfig.urls.locations}${item.location.endpoint}`}
>
{`New York Public Library - ${locationShort}`}
</ExternalLink>
{" to submit a request in person."}
</Text>
)
}
} else {
// Not available
if (item.availability.key === "availableRecap") {
return (
<Text
mb="0"
fontSize={{
base: "mobile.body.body2",
md: "desktop.body.body2",
}}
>
<Box as="span" color="ui.warning.tertiary">
Not available
</Box>
{item.dueDate && ` - In use until ${item.dueDate}`}
{" - Please "}
<Button
id="contact-librarian"
buttonType="link"
sx={{
display: "inline",
fontWeight: "inherit",
fontSize: "inherit",
p: 0,
height: "auto",
textAlign: "left",
minHeight: "auto",
}}
onClick={() =>
onContact({
id: item.id,
barcode: item.barcode,
callNumber: item.callNumber,
bibId: item.bibId,
})
}
>
contact a librarian
</Button>
{" for assistance."}
</Text>
<ExternalLink href={appConfig.urls.researchMaterialsHelp} fontSize="sm">
How do I pick up this item and when will it be ready?
</ExternalLink>
)
}

return (
<Text
mb="0"
fontSize={{
base: "mobile.body.body2",
md: "desktop.body.body2",
}}
>
{item.availability.message()}
</Text>
)
}

export default ItemAvailability
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Box } from "@nypl/design-system-react-components"
import { appConfig } from "../../../config/config"
import ExternalLink from "../../Links/ExternalLink/ExternalLink"

const AvailableByAppointment = ({ item }) => {
return (
<>
<Box as="span" color="ui.success.primary">
Available by appointment
</Box>
{!item.isReCAP && (
<>
{" at "}
<ExternalLink
href={`${appConfig.urls.locations}${item.location.endpoint}`}
>
{item.location.prefLabel}
</ExternalLink>
</>
)}
</>
)
}

export default AvailableByAppointment
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Box } from "@nypl/design-system-react-components"
import { appConfig } from "../../../config/config"
import type Item from "../../../models/Item"
import ExternalLink from "../../Links/ExternalLink/ExternalLink"

const AvailableOnsite = ({ item }: { item: Item }) => {
const locationShort = item.location.prefLabel.split("-")[0]
return (
<>
<Box as="span" color="ui.success.primary">
Available
</Box>
{" - Can be used on site. Please visit "}
<ExternalLink
href={`${appConfig.urls.locations}${item.location.endpoint}`}
>
{`New York Public Library - ${locationShort}`}
</ExternalLink>
{" to submit a request in person."}
</>
)
}

export default AvailableOnsite
charmingduchess marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Button } from "@nypl/design-system-react-components"
import { useContext } from "react"
import { FeedbackContext } from "../../../context/FeedbackContext"
import type { ItemMetadata } from "../../../types/itemTypes"
import type Item from "../../../models/Item"

const ContactALibrarian = ({ item }: { item: Item }) => {
const { onOpen, setItemMetadata } = useContext(FeedbackContext)
const onContact = (metadata: ItemMetadata) => {
setItemMetadata(metadata)
onOpen()
}
return (
<>
{" - Please "}
<Button
id="contact-librarian"
buttonType="link"
charmingduchess marked this conversation as resolved.
Show resolved Hide resolved
sx={{
display: "inline",
fontWeight: "inherit",
fontSize: "inherit",
p: 0,
height: "auto",
textAlign: "left",
minHeight: "auto",
}}
onClick={() =>
onContact({
id: item.id,
barcode: item.barcode,
callNumber: item.callNumber,
bibId: item.bibId,
})
}
>
contact a librarian
</Button>
{" for assistance."}
</>
)
}

export default ContactALibrarian
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Box } from "@nypl/design-system-react-components"
import type Item from "../../../models/Item"
import ContactALibrarian from "./ContactALibrarian"

const NotAvailable = ({ item }: { item: Item }) => {
return (
<>
<Box as="span" color="ui.warning.tertiary">
Not available
</Box>
{item.dueDate && ` - In use until ${item.dueDate}`}
<ContactALibrarian item={item} />
</>
)
}

export default NotAvailable
3 changes: 3 additions & 0 deletions src/models/Item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
locationEndpointsMap,
} from "../utils/itemUtils"
import { appConfig } from "../config/config"
import ItemAvailability from "./ItemAvailability"

/**
* The Item class contains the data and getter functions
Expand All @@ -34,6 +35,7 @@ export default class Item {
isPhysicallyRequestable: boolean
isEDDRequestable: boolean
bibTitle: string
availability: ItemAvailability

constructor(item: DiscoveryItemResult, bib: Bib) {
this.id = item.uri || ""
Expand All @@ -57,6 +59,7 @@ export default class Item {
this.isPhysicallyRequestable = item.physRequestable
this.isEDDRequestable = item.eddRequestable
this.bibTitle = bib.titleDisplay
this.availability = new ItemAvailability(this)
}

// Item availability is determined by the existence of status id in the availability ids list
Expand Down
44 changes: 44 additions & 0 deletions src/models/ItemAvailability.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this functionality needs its own class? I feel like the key building could be added to the item model with a component handling the presentation logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's so focused on a specific cluster of data that I think it justifies its own class. I am going to move the presentation logic to the component.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { JsxElement } from "typescript"
import type Item from "./Item"
import AvailableByAppointment from "../components/ItemTable/ItemAvailabilityComponents/AvailableByAppointment"
import AvailableOnsite from "../components/ItemTable/ItemAvailabilityComponents/AvailableOnsite"
import NotAvailable from "../components/ItemTable/ItemAvailabilityComponents/NotAvailable"

class ItemAvailability {
item: Item
key: string
constructor(item: Item) {
this.item = item
this.key = this.buildKey()
}
buildKey() {
if (this.item.isAvailable && this.item.isReCAP && !this.item.aeonUrl) {
return "availableRecap"
}
if (
this.item.isAvailable &&
this.item.aeonUrl &&
this.item.location?.endpoint
) {
return "availableAeon"
}
if (this.item.isAvailable && !this.item.isReCAP) {
return "availableOnsite"
}
if (!this.item.isAvailable) {
return "notAvailable"
}
}
message() {
switch (this.key) {
case "availableAeon":
return <AvailableByAppointment item={this.item} />
case "availableOnsite":
return <AvailableOnsite item={this.item} />
case "notAvailable":
return <NotAvailable item={this.item} />
}
}
}

export default ItemAvailability
Loading