diff --git a/__test__/fixtures/bibFixtures.ts b/__test__/fixtures/bibFixtures.ts index 294842e95..65c4afebd 100644 --- a/__test__/fixtures/bibFixtures.ts +++ b/__test__/fixtures/bibFixtures.ts @@ -1,3 +1,1468 @@ +export const bibWithElectronicResourcesAndFindingAid = { + "@context": + "http://discovery-api-production.nypl.org/api/v0.1/discovery/context_all.jsonld", + "@type": ["nypl:Item", "nypl:Resource"], + "@id": "res:b15893398", + buildingLocationIds: ["ma", "rc"], + carrierType: [ + { + "@id": "carriertypes:nc", + prefLabel: "volume", + }, + ], + contributorLiteral: [ + "Ainger, Alfred, 1837-1904.", + "Barham, R. H. Dalton (Richard Harris Dalton), 1815-1886.", + "Bentley, George, 1828-1895.", + "Bentley, Richard, 1794-1871.", + "Brookfield, William Henry, 1809-1874.", + "Browne, Hablot Knight, 1815-1882.", + "Browning, Robert, 1812-1889.", + "Cattermole, George, 1800-1868.", + "Cerjat, William F. De.", + "Collins, Wilkie, 1824-1889.", + "Cruikshank, George, 1792-1878.", + "Cunningham, Peter, 1816-1869.", + "Dickens, Charles, 1837-1896.", + "Dickens, Frederick William, 1820-1868.", + "Dickens, Henry F. (Henry Fielding), Sir, 1849-1933.", + "Dolby, George, -1900.", + "Felton, C. C. (Cornelius Conway), 1807-1862.", + "Fields, James Thomas, 1817-1881.", + "Gaskell, Elizabeth Cleghorn, 1810-1865.", + "Hogarth, Georgina, 1827-1917.", + "Hunt, Leigh, 1784-1859.", + "Irving, Washington, 1783-1859.", + "Kelly, Frances Maria, 1790-1882.", + "Kitton, Frederic George, 1856-1904.", + "Landor, Walter Savage, 1775-1864.", + "La Rue, Emile de.", + "Leech, John, 1817-1864.", + "Lemon, Mark, 1809-1870.", + "Lewes, George Henry, 1817-1878.", + "Mackay, Charles, 1814-1889.", + "Maclise, Daniel, 1806-1870.", + "Macmillan, Alexander, 1818-1896.", + "Mitton, Thomas.", + "Morgan, E. S.", + "Nabokov, Vladimir Vladimirovich, 1899-1977.", + "Pailthorpe, F. W. (Frederic W.)", + "Poe, Edgar Allan, 1809-1849.", + "Roberts, David, 1896-1864.", + "Rossetti, William Michael, 1829-1919.", + "Stanfield, Clarkson, 1793-1867.", + "Talfourd, Thomas Noon, 1795-1854.", + "Tennent, James Emerson, Sir, 1804-1869.", + "Thackeray, William Makepeace, 1811-1863.", + "Trollope, Frances Milton, 1780-1863.", + "Trollope, Thomas Adolphus, 1810-1892.", + "Wills, W. Henry (William Henry), 1810-1880.", + "A. P. Watt and Son.", + "Chapman and Hall.", + ], + createdString: ["1833"], + createdYear: 1833, + creatorLiteral: ["Dickens, Charles, 1812-1870."], + dateEndString: ["1975"], + dateEndYear: 1975, + dateStartYear: 1833, + dateString: ["1833"], + description: [ + "This is a synthetic collection consisting of manuscripts, typescripts, correspondence, diaires for 1867 and 1868, notebooks for 1843 through 1870, financial and legal documents, portraits and pictorial works.", + ], + electronicResources: [ + { + url: "https://digitalcollections.nypl.org/search/index?keywords=b15893398", + prefLabel: "NYPL Digital Collections", + }, + ], + extent: ["1,179 items."], + genreForm: ["Correspondence.", "Diaries.", "Notebooks."], + idOclc: ["NYPW04-A49"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "Berg Coll MSS Dickens", + }, + { + "@type": "nypl:Bnumber", + "@value": "15893398", + }, + { + "@type": "nypl:Oclc", + "@value": "NYPW04-A49", + }, + { + "@type": "bf:Identifier", + "@value": "(WaOLN)W110000007", + }, + ], + issuance: [ + { + "@id": "urn:biblevel:d", + prefLabel: "subunit", + }, + ], + itemAggregations: [ + { + "@type": "nypl:Aggregation", + "@id": "res:location", + id: "location", + field: "location", + values: [ + { + value: "loc:rcmi2", + count: 18, + label: "Offsite", + }, + { + value: "loc:maee2", + count: 1, + label: "Schwarzman Building - Berg Collection Room 320", + }, + ], + }, + { + "@type": "nypl:Aggregation", + "@id": "res:format", + id: "format", + field: "format", + values: [ + { + value: "Mixed material", + count: 19, + label: "Mixed material", + }, + ], + }, + { + "@type": "nypl:Aggregation", + "@id": "res:status", + id: "status", + field: "status", + values: [ + { + value: "status:a", + count: 70, + label: "Available", + }, + ], + }, + ], + items: [ + { + "@id": "res:i14675897", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:p", + prefLabel: "Permit needed", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:20", + prefLabel: "manuscript", + }, + ], + eddRequestable: false, + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:maee2", + prefLabel: "Schwarzman Building - Berg Collection Room 320", + }, + ], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "Berg Coll MSS Dickens [Text]", + }, + ], + owner: [ + { + "@id": "orgs:1104", + prefLabel: + "Henry W. and Albert A. Berg Collection of English and American Literature", + }, + ], + physRequestable: false, + physicalLocation: ["Berg Coll MSS Dickens [Text]"], + requestable: [false], + shelfMark: ["Berg Coll MSS Dickens [Text]"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i14675897", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "14675897", + }, + }, + { + "@id": "res:i24178092", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 18"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111835"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 18", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111835", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 18"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178092", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178092", + }, + }, + { + "@id": "res:i24178091", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 17"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111843"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 17", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111843", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 17"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178091", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178091", + }, + }, + { + "@id": "res:i24178088", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 16"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111850"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 16", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111850", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 16"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178088", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178088", + }, + }, + { + "@id": "res:i24178087", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 15"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111876"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 15", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111876", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 15"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178087", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178087", + }, + }, + { + "@id": "res:i24178086", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 14"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111868"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 14", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111868", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 14"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178086", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178086", + }, + }, + { + "@id": "res:i24178082", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 13"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111884"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 13", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111884", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 13"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178082", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178082", + }, + }, + { + "@id": "res:i24178081", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 12"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111892"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 12", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111892", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 12"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178081", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178081", + }, + }, + { + "@id": "res:i24178080", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 11"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111900"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 11", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111900", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 11"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178080", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178080", + }, + }, + { + "@id": "res:i24178079", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 10"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111918"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 10", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111918", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 10"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178079", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178079", + }, + }, + { + "@id": "res:i24178076", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 9"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111926"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 9", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111926", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 9"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178076", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178076", + }, + }, + { + "@id": "res:i24178075", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 8"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111934"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 8", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111934", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 8"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178075", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178075", + }, + }, + { + "@id": "res:i24178074", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 7"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111942"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 7", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111942", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 7"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178074", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178074", + }, + }, + { + "@id": "res:i24178073", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 6"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111959"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 6", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111959", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 6"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178073", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178073", + }, + }, + { + "@id": "res:i24178072", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 5"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111967"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 5", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111967", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 5"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178072", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178072", + }, + }, + { + "@id": "res:i24178071", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 4"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111975"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 4", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111975", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 4"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178071", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178071", + }, + }, + { + "@id": "res:i24178069", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 3"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111983"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 3", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111983", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 3"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178069", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178069", + }, + }, + { + "@id": "res:i24178068", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 2"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075111991"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 2", + }, + { + "@type": "bf:Barcode", + "@value": "33433075111991", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 2"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178068", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178068", + }, + }, + { + "@id": "res:i24178066", + "@type": ["bf:Item"], + accessMessage: [ + { + "@id": "accessMessage:2", + prefLabel: "Request in advance", + }, + ], + catalogItemType: [ + { + "@id": "catalogItemType:6", + prefLabel: "microfilm service copy", + }, + ], + eddFulfillment: { + "@id": "fulfillment:recap-edd", + }, + eddRequestable: true, + enumerationChronology: ["Box 1"], + formatLiteral: ["Mixed material"], + holdingLocation: [ + { + "@id": "loc:rcmi2", + prefLabel: "Offsite", + }, + ], + idBarcode: ["33433075112007"], + identifier: [ + { + "@type": "bf:ShelfMark", + "@value": "*Z-10344 Box 1", + }, + { + "@type": "bf:Barcode", + "@value": "33433075112007", + }, + ], + owner: [ + { + "@id": "orgs:1000", + prefLabel: "Stephen A. Schwarzman Building", + }, + ], + physFulfillment: { + "@id": "fulfillment:recap-offsite", + }, + physRequestable: true, + physicalLocation: ["*Z-10344"], + recapCustomerCode: ["NA"], + requestable: [true], + shelfMark: ["*Z-10344 Box 1"], + specRequestable: false, + status: [ + { + "@id": "status:a", + prefLabel: "Available", + }, + ], + uri: "i24178066", + idNyplSourceId: { + "@type": "SierraNypl", + "@value": "24178066", + }, + }, + ], + language: [ + { + "@id": "lang:eng", + prefLabel: "English", + }, + ], + materialType: [ + { + "@id": "resourcetypes:mix", + prefLabel: "Mixed material", + }, + ], + mediaType: [ + { + "@id": "mediatypes:n", + prefLabel: "unmediated", + }, + ], + note: [ + { + noteType: "Access", + "@type": "bf:Note", + prefLabel: "Restricted access;", + }, + { + noteType: "Biography", + "@type": "bf:Note", + prefLabel: + "Charles Dickens was a British novelist, short story writer, essayist and journalist.", + }, + { + noteType: "Indexes/Finding Aids", + "@type": "bf:Note", + prefLabel: "Inventory list and card catalog available in repository.", + }, + { + noteType: "Provenance", + "@type": "bf:Note", + prefLabel: + "This is a synthetic collection, created from materials acquired through gift and purchase from various sources. The bulk of the materials is from Henry W. and Albert A. Berg, W. T. H. Howe, and Owen D. Young. Much of this and other materials were previously owned by Jerome Kern, B. W. Matz, Frederick William Cosens, Harry Glemby, Herschel V. Jones, M. C. D. Borden, George Barr McCutcheon, and Roderick Terry, Esther Leech, C. R. Leslie, Miss M. A. Browne, Eve Clendenin, Richard Henry Stoddard-Howe, Mrs. Rebecca Ball Wilson, Thomas Hatton, Hobart F. Cole, and William H. MacAfee. R. H. Barham's holograph notebook and commonplace book was a gift of Mr. & Mrs. Donald F. Hyde in honor of Dr. Albert A. Berg.", + }, + { + noteType: "Processing Action", + "@type": "bf:Note", + prefLabel: "Cataloged", + }, + { + noteType: "Processing Action", + "@type": "bf:Note", + prefLabel: "Will microfilm;", + }, + ], + numCheckinCardItems: 0, + numElectronicResources: 1, + numItemDatesParsed: 0, + numItemVolumesParsed: 0, + numItemsMatched: 19, + numItemsTotal: 19, + nyplSource: ["sierra-nypl"], + shelfMark: ["Berg Coll MSS Dickens"], + subjectLiteral: [ + "Dickens, Charles, 1812-1870.", + "Dickens, Charles, 1812-1870 -- Portraits.", + "Dickens, Charles, 1812-1870. -- Illustrations.", + "Dickens, Charles, 1812-1870. -- Illustations.", + ], + supplementaryContent: [ + { + "@type": "nypl:SupplementaryContent", + label: "Finding Aid", + url: "http://www.nypl.org/archives/443", + }, + ], + title: ["Charles Dickens collection of papers"], + titleDisplay: [ + "Charles Dickens collection of papers, [1833]-[1975] bulk ([1833]-1909).", + ], + type: ["nypl:Item"], + updatedAt: 1711076115882, + uri: "b15893398", + updatedAtDate: "2024-03-22T02:55:15.882Z", + hasItemVolumes: false, + hasItemDates: false, + recordType: { + "@id": "p", + prefLabel: "Archival Mix", + }, +} + export const bibWithItems = { resource: { "@context": diff --git a/__test__/fixtures/itemFixtures.ts b/__test__/fixtures/itemFixtures.ts index 44174b90f..6a5dc86a6 100644 --- a/__test__/fixtures/itemFixtures.ts +++ b/__test__/fixtures/itemFixtures.ts @@ -7,6 +7,7 @@ export const itemPhysicallyRequestable = { prefLabel: "Use in library", }, ], + specialCollections: true, aeonUrl: [ "https://specialcollections.nypl.org/aeon/Aeon.dll?Action=10&Form=30&Title=Spaghetti+westerns.&Site=LPAMRAMI&CallNumber=*LDC+14245&ItemPlace=[New+York?]+:&ItemPublisher=DRG+Records+Inc.,&Date=p1995.&ItemInfo3=https://catalog.nypl.org/record=b19028235&ReferenceNumber=b190282356&ItemInfo1=USE+IN+LIBRARY&ItemNumber=33433085319782&ItemISxN=i265238791&Genre=Music+CD&Location=Performing+Arts+Music+Division", ], diff --git a/src/components/ItemTable/ItemAvailability.test.tsx b/src/components/ItemTable/ItemAvailability.test.tsx index 938318cfb..e2dd007c8 100644 --- a/src/components/ItemTable/ItemAvailability.test.tsx +++ b/src/components/ItemTable/ItemAvailability.test.tsx @@ -2,6 +2,8 @@ import React from "react" import { render, screen } from "../../utils/testUtils" import userEvent from "@testing-library/user-event" +import ItemAvailabilityModel from "../../models/ItemAvailability" + import ItemAvailability from "./ItemAvailability" import Item from "../../models/Item" import SearchResultsBib from "../../models/SearchResultsBib" @@ -13,10 +15,151 @@ import { itemUnavailable, } from "../../../__test__/fixtures/itemFixtures" import { searchResultPhysicalItems } from "../../../__test__/fixtures/searchResultPhysicalItems" +import { notDeepEqual } from "assert" const parentBib = new SearchResultsBib(searchResultPhysicalItems) describe("ItemAvailability", () => { + describe("special collections", () => { + it("onsite aeon finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: false, + aeonUrl: "spaghetti.com", + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment")).toBeInTheDocument() + expect(screen.getByRole("link")).toHaveTextContent( + "Schwarzman Building - Main Reading Room 315" + ) + }) + it("recap aeon finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: true, + aeonUrl: "spaghetti.com", + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment.")).toBeInTheDocument() + expect(screen.queryByRole("link")).not.toBeInTheDocument() + expect( + screen.queryByText("Schwarzman Building - Main Reading Room 315") + ).not.toBeInTheDocument() + }) + it("recap aeon", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: true, + aeonUrl: "spaghetti.com", + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment.")).toBeInTheDocument() + expect(screen.queryByRole("link")).not.toBeInTheDocument() + expect( + screen.queryByText("Schwarzman Building - Main Reading Room 315") + ).not.toBeInTheDocument() + }) + it("onsite aeon NO finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: false, + aeonUrl: "spaghetti.com", + findingAid: null, + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment")).toBeInTheDocument() + expect(screen.queryByRole("link")).not.toBeInTheDocument() + expect( + screen.getByText("at Schwarzman Building - Main Reading Room 315.") + ).toBeInTheDocument() + }) + it("onsite NO aeon YES finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: false, + aeonUrl: null, + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment")).toBeInTheDocument() + expect(screen.queryByRole("link")).toHaveTextContent("finding aid") + expect( + screen.getByText( + "at Schwarzman Building - Main Reading Room 315. See the ", + { exact: false } + ) + ).toBeInTheDocument() + }) + it("recap NO aeon YES finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: true, + aeonUrl: null, + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment.")).toBeInTheDocument() + expect(screen.queryByRole("link")).toHaveTextContent("finding aid") + expect( + screen.queryByText("Schwarzman Building - Main Reading Room 315", { + exact: false, + }) + ).not.toBeInTheDocument() + }) + it("recap NO aeon NO finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: true, + aeonUrl: null, + findingAid: null, + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment.")).toBeInTheDocument() + expect(screen.queryByRole("link")).not.toBeInTheDocument() + expect( + screen.queryByText("Schwarzman Building - Main Reading Room 315", { + exact: false, + }) + ).not.toBeInTheDocument() + expect(screen.getByText("contact a librarian")).toBeInTheDocument() + }) + it("onsite NO aeon NO finding aid", () => { + const item = new Item(itemPhysicallyRequestable, parentBib) + item.availability = new ItemAvailabilityModel({ + isAvailable: true, + isReCAP: false, + aeonUrl: null, + findingAid: null, + isSpecRequestable: true, + }) + render() + expect(screen.getByText("Available by appointment")).toBeInTheDocument() + expect(screen.queryByRole("link")).not.toBeInTheDocument() + expect( + screen.queryByText("Schwarzman Building - Main Reading Room 315.", { + exact: false, + }) + ).toBeInTheDocument() + expect(screen.getByText("contact a librarian")).toBeInTheDocument() + }) + }) it("renders the correct link when item is available, is reCAP, and does not have an aeon url", async () => { const item = new Item(itemNYPLReCAP, parentBib) render() @@ -27,14 +170,6 @@ describe("ItemAvailability", () => { "https://www.nypl.org/help/request-research-materials" ) }) - 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() - expect(screen.getByText("Available by appointment")).toBeInTheDocument() - expect( - screen.getByText("Schwarzman Building - Main Reading Room 315") - ).toHaveAttribute("href", "https://www.nypl.org/locations/schwarzman") - }) it("renders the correct text for an available onsite item", async () => { const item = new Item(itemAvailableOnsite, parentBib) render() diff --git a/src/components/ItemTable/ItemAvailability.tsx b/src/components/ItemTable/ItemAvailability.tsx index 646ba63c7..2d653b0be 100644 --- a/src/components/ItemTable/ItemAvailability.tsx +++ b/src/components/ItemTable/ItemAvailability.tsx @@ -1,129 +1,139 @@ -import { useContext } from "react" -import { Text, Button, Box } from "@nypl/design-system-react-components" +import { Text } 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 { availabilityKeys } from "../../config/constants" +import { + AvailableByAppointment, + AvailableAt, + AvailableAtLink, +} from "./ItemAvailability/AvailableByAppointment" +import AvailableOnsite from "./ItemAvailability/AvailableOnsite" +import NotAvailable from "./ItemAvailability/NotAvailable" +import FindingAid from "./ItemAvailability/FindingAid" +import ContactALibrarian from "./ItemAvailability/ContactALibrarian" interface ItemAvailabilityProps { item: Item } +const { + EDGE_CASE, + RECAP_GENERAL_COLLECTIONS, + ONSITE_GENERAL_COLLECTIONS, + NOT_AVAILABLE, + // special collections availability keys + RECAP_AEON, + ONSITE_AEON, + ONSITE_AEON_FINDING_AID, + RECAP_AEON_FINDING_AID, + ONSITE_FINDING_AID, + RECAP_FINDING_AID, + ONSITE_NO_FINDING_AID_NO_AEON, + RECAP_NO_FINDING_AID_NO_AEON, +} = availabilityKeys + /** * The ItemAvailability component appears below the Item table and displays * info about an item's availability. * 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() + let message + const itemMetadata = { + id: item.id, + barcode: item.barcode, + callNumber: item.callNumber, + bibId: item.bibId, } - - // 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 + switch (item.availability.key) { + case RECAP_GENERAL_COLLECTIONS: return ( How do I pick up this item and when will it be ready? ) - } else if (item.aeonUrl && item.location?.endpoint) { - return ( - - - Available by appointment - - {!item.isReCAP ? ( - <> - {" at "} - - {item.location.prefLabel} - - - ) : null} - + case EDGE_CASE: + message = + break + case RECAP_AEON: + case RECAP_AEON_FINDING_AID: + message = ( + <> + + ) - } else { - // Available Onsite item - const locationShort = item.location.prefLabel.split("-")[0] - return ( - - - Available - - {" - Can be used on site. Please visit "} - - {`New York Public Library - ${locationShort}`} - - {" to submit a request in person."} - + break + case ONSITE_AEON_FINDING_AID: + message = ( + <> + + + + ) + break + case ONSITE_AEON: + message = ( + <> + + + ) - } - } else { - // Not available - return ( - - - Not available - - {item.dueDate && ` - In use until ${item.dueDate}`} - {" - Please "} - - {" for assistance."} - - ) + break + case ONSITE_FINDING_AID: + message = ( + <> + + + + + ) + break + case RECAP_FINDING_AID: + message = ( + <> + + + + ) + break + case RECAP_NO_FINDING_AID_NO_AEON: + message = ( + <> + + + + ) + break + case ONSITE_NO_FINDING_AID_NO_AEON: + message = ( + <> + + + + + ) + break + case ONSITE_GENERAL_COLLECTIONS: + message = + break + case NOT_AVAILABLE: + message = + break } + + return ( + + {message} + + ) } export default ItemAvailability diff --git a/src/components/ItemTable/ItemAvailability/AvailableByAppointment.tsx b/src/components/ItemTable/ItemAvailability/AvailableByAppointment.tsx new file mode 100644 index 000000000..7e7ce0c2b --- /dev/null +++ b/src/components/ItemTable/ItemAvailability/AvailableByAppointment.tsx @@ -0,0 +1,32 @@ +import { Box, Text } from "@nypl/design-system-react-components" +import { appConfig } from "../../../config/config" +import ExternalLink from "../../Links/ExternalLink/ExternalLink" + +const AvailableByAppointment = ({ displayPeriod = false }) => { + return ( + <> + + {`Available by appointment${displayPeriod ? ". " : ""}`} + + + ) +} + +const AvailableAtLink = ({ location }) => { + if (!location?.endpoint) return null + return ( + <> + {" at "} + + {location.prefLabel + "."} + + + ) +} + +const AvailableAt = ({ location }) => { + if (!location?.endpoint) return null + else return <> {` at ${location.prefLabel}. `} +} + +export { AvailableByAppointment, AvailableAtLink, AvailableAt } diff --git a/src/components/ItemTable/ItemAvailability/AvailableOnsite.tsx b/src/components/ItemTable/ItemAvailability/AvailableOnsite.tsx new file mode 100644 index 000000000..87a15dde0 --- /dev/null +++ b/src/components/ItemTable/ItemAvailability/AvailableOnsite.tsx @@ -0,0 +1,21 @@ +import { Box } from "@nypl/design-system-react-components" +import { appConfig } from "../../../config/config" +import ExternalLink from "../../Links/ExternalLink/ExternalLink" + +const AvailableOnsite = ({ location }) => { + const locationShort = location.prefLabel.split("-")[0] + return ( + <> + + Available + + {" - Can be used on site. Please visit "} + + {`New York Public Library - ${locationShort}`} + + {" to submit a request in person."} + + ) +} + +export default AvailableOnsite diff --git a/src/components/ItemTable/ItemAvailability/ContactALibrarian.tsx b/src/components/ItemTable/ItemAvailability/ContactALibrarian.tsx new file mode 100644 index 000000000..6e2714002 --- /dev/null +++ b/src/components/ItemTable/ItemAvailability/ContactALibrarian.tsx @@ -0,0 +1,53 @@ +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: { + id: string + barcode: string + callNumber: string + bibId: string + } +}) => { + const { onOpen, setItemMetadata } = useContext(FeedbackContext) + const onContact = (metadata: ItemMetadata) => { + setItemMetadata(metadata) + onOpen() + } + return ( + <> + {" Please "} + + {" for assistance."} + + ) +} + +export default ContactALibrarian diff --git a/src/components/ItemTable/ItemAvailability/FindingAid.tsx b/src/components/ItemTable/ItemAvailability/FindingAid.tsx new file mode 100644 index 000000000..b2c8168be --- /dev/null +++ b/src/components/ItemTable/ItemAvailability/FindingAid.tsx @@ -0,0 +1,13 @@ +import ExternalLink from "../../Links/ExternalLink/ExternalLink" + +const FindingAid = ({ url }: { url: string }) => { + return ( + <> + {" See the "} + {"finding aid"} + {" for details."} + + ) +} + +export default FindingAid diff --git a/src/components/ItemTable/ItemAvailability/NotAvailable.tsx b/src/components/ItemTable/ItemAvailability/NotAvailable.tsx new file mode 100644 index 000000000..9bec21921 --- /dev/null +++ b/src/components/ItemTable/ItemAvailability/NotAvailable.tsx @@ -0,0 +1,35 @@ +import { Box } from "@nypl/design-system-react-components" +import ContactALibrarian from "./ContactALibrarian" +import type Item from "../../../models/Item" + +const NotAvailable = ({ + item, + dueDate, +}: { + dueDate: string + item: { + id: string + barcode: string + callNumber: string + bibId: string + } +}) => { + const itemMetadata = { + id: item.id, + barcode: item.barcode, + callNumber: item.callNumber, + bibId: item.bibId, + } + return ( + <> + + Not available + + {" -"} + {dueDate && ` - In use until ${dueDate} -`} + + + ) +} + +export default NotAvailable diff --git a/src/components/ItemTable/RequestButtons.tsx b/src/components/ItemTable/RequestButtons.tsx index 164c7b0bd..06f81d36d 100644 --- a/src/components/ItemTable/RequestButtons.tsx +++ b/src/components/ItemTable/RequestButtons.tsx @@ -16,7 +16,7 @@ const RequestButtons = ({ item }: RequestButtonsProps) => { if (item.allLocationsClosed) return null return ( - {item.aeonUrl ? ( + {item.aeonUrl && ( { > Request appointment - ) : ( - <> - {item.isPhysicallyRequestable && ( - - Request for on-site use - - )} - {item.isEDDRequestable && ( - - Request scan - - )} - + )} + + {item.isPhysicallyRequestable && ( + + Request for on-site use + + )} + {item.isEDDRequestable && ( + + Request scan + )} ) diff --git a/src/components/SearchResults/ElectronicResourcesLink.tsx b/src/components/SearchResults/ElectronicResourcesLink.tsx index 2e9f508b6..c1f33ae31 100644 --- a/src/components/SearchResults/ElectronicResourcesLink.tsx +++ b/src/components/SearchResults/ElectronicResourcesLink.tsx @@ -17,9 +17,9 @@ const ElectronicResourcesLink = ({ electronicResources, }: ElectronicResourcesLinkProps) => { return ( - + diff --git a/src/components/SearchResults/FindingAid.tsx b/src/components/SearchResults/FindingAid.tsx new file mode 100644 index 000000000..f7fec1b06 --- /dev/null +++ b/src/components/SearchResults/FindingAid.tsx @@ -0,0 +1,46 @@ +import { Box, Icon, Text } from "@nypl/design-system-react-components" +import ExternalLink from "../Links/ExternalLink/ExternalLink" +import { appConfig } from "../../config/config" +import styles from "../../../styles/components/Search.module.scss" + +const FindingAid = ({ url }) => { + return ( + + + Collection information + + + Finding aid + + + + + The finding aid is a document containing details about the + organization and contents of this archival collection.
+ Archival collections{" "} + + require an appointment + {" "} + to view and use on-site. +
+
+
+ ) +} + +export default FindingAid diff --git a/src/components/SearchResults/SearchResult.test.tsx b/src/components/SearchResults/SearchResult.test.tsx index 0841379c2..b5eaac6c1 100644 --- a/src/components/SearchResults/SearchResult.test.tsx +++ b/src/components/SearchResults/SearchResult.test.tsx @@ -5,6 +5,10 @@ import SearchResultsBib from "../../models/SearchResultsBib" import { searchResultPhysicalItems } from "../../../__test__/fixtures/searchResultPhysicalItems" import { searchResultManyPhysicalItems } from "../../../__test__/fixtures/searchResultManyPhysicalItems" import { searchResultElectronicResources } from "../../../__test__/fixtures/searchResultElectronicResources" +import { + bibWithElectronicResourcesAndFindingAid, + bibWithItems, +} from "../../../__test__/fixtures/bibFixtures" import type { DiscoveryBibResult } from "../../types/bibTypes" describe("SearchResult with Physical Items", () => { @@ -51,9 +55,38 @@ describe("SearchResult with Many Physical Items", () => { }) describe("SearchResult with Electronic Resources", () => { - it("renders the correct item message for bib with electronic resources", async () => { + it("renders the correct item message for bib with electronic resources", () => { const bib = new SearchResultsBib(searchResultElectronicResources) render() screen.getByText("1 resource") }) + it("renders a finding aid message and electronic resource information", () => { + const bib = new SearchResultsBib(bibWithElectronicResourcesAndFindingAid) + render() + expect(screen.getByText("Collection information")).toBeInTheDocument() + expect(screen.getByText("Available online")).toBeInTheDocument() + }) + it("renders only a finding aid message and no electronic resource information", () => { + const bib = new SearchResultsBib({ + ...bibWithElectronicResourcesAndFindingAid, + electronicResources: [], + }) + render() + expect(screen.getByText("Collection information")).toBeInTheDocument() + expect(screen.queryByText("Available online")).not.toBeInTheDocument() + }) + it("renders no finding aid message and only electronic resource information", () => { + const bib = new SearchResultsBib({ + ...bibWithElectronicResourcesAndFindingAid, + supplementaryContent: [], + }) + render() + expect(screen.getByText("Available online")).toBeInTheDocument() + expect(screen.queryByText("Collection information")).not.toBeInTheDocument() + }) + it("renders finding aid status badge", () => { + const bib = new SearchResultsBib(bibWithElectronicResourcesAndFindingAid) + render() + expect(screen.getByText("FINDING AID AVAILABLE")).toBeInTheDocument() + }) }) diff --git a/src/components/SearchResults/SearchResult.tsx b/src/components/SearchResults/SearchResult.tsx index c54139ff3..3f179b7b7 100644 --- a/src/components/SearchResults/SearchResult.tsx +++ b/src/components/SearchResults/SearchResult.tsx @@ -6,6 +6,7 @@ import { Text, CardActions, SimpleGrid, + StatusBadge, } from "@nypl/design-system-react-components" import RCLink from "../Links/RCLink/RCLink" @@ -13,6 +14,7 @@ import ElectronicResourcesLink from "./ElectronicResourcesLink" import ItemTable from "../ItemTable/ItemTable" import type SearchResultsBib from "../../models/SearchResultsBib" import { PATHS } from "../../config/constants" +import FindingAid from "./FindingAid" interface SearchResultProps { bib: SearchResultsBib @@ -25,6 +27,7 @@ const SearchResult = ({ bib }: SearchResultProps) => { return ( { size="heading5" sx={{ a: { textDecoration: "none" } }} > - {bib.titleDisplay} + {bib.findingAid && ( + + FINDING AID AVAILABLE + + )} + + {bib.titleDisplay} + { {bib.getNumItemsMessage()} + {bib.findingAid && } {bib.hasElectronicResources && ( el.label.toLocaleLowerCase() === "finding aid" + )?.url || null + this.items = this.getItemsFromResult(result) } get url() { diff --git a/src/models/Item.ts b/src/models/Item.ts index 436ee500a..209605e2a 100644 --- a/src/models/Item.ts +++ b/src/models/Item.ts @@ -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 @@ -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 || "" @@ -57,6 +59,13 @@ export default class Item { this.isPhysicallyRequestable = item.physRequestable this.isEDDRequestable = item.eddRequestable this.bibTitle = bib.titleDisplay + this.availability = new ItemAvailability({ + isSpecRequestable: item.specRequestable, + isAvailable: this.isAvailable, + isReCAP: this.isReCAP, + aeonUrl: this.aeonUrl, + findingAid: bib.findingAid, + }) } // Item availability is determined by the existence of status id in the availability ids list diff --git a/src/models/ItemAvailability.ts b/src/models/ItemAvailability.ts new file mode 100644 index 000000000..6c72f8ff4 --- /dev/null +++ b/src/models/ItemAvailability.ts @@ -0,0 +1,93 @@ +import { availabilityKeys } from "../config/constants" + +const { + EDGE_CASE, + RECAP_GENERAL_COLLECTIONS, + ONSITE_GENERAL_COLLECTIONS, + NOT_AVAILABLE, + // special collections availability keys + RECAP_AEON, + ONSITE_AEON, + ONSITE_AEON_FINDING_AID, + RECAP_AEON_FINDING_AID, + ONSITE_FINDING_AID, + RECAP_FINDING_AID, + ONSITE_NO_FINDING_AID_NO_AEON, + RECAP_NO_FINDING_AID_NO_AEON, +} = availabilityKeys + +class ItemAvailability { + key: string + isAvailable: boolean + isReCAP: boolean + aeonUrl: string + findingAid: string + isSpecRequestable?: boolean + isOnsite: boolean + + constructor({ + isAvailable, + isReCAP, + aeonUrl, + findingAid, + isSpecRequestable, + }) { + this.findingAid = findingAid + this.isReCAP = isReCAP + this.isAvailable = isAvailable + this.aeonUrl = aeonUrl + this.isOnsite = !this.isReCAP + this.isSpecRequestable = isSpecRequestable + this.key = this.buildKey() + } + buildKey() { + // All unavailable records have the same messaging. + // general collections messages + if (!this.isAvailable) { + return NOT_AVAILABLE + } + if (this.isReCAP && !this.isSpecRequestable) { + return RECAP_GENERAL_COLLECTIONS + } + if (this.isOnsite && !this.isSpecRequestable) { + return ONSITE_GENERAL_COLLECTIONS + } + // special collections messaging + if (this.aeonUrl && this.isReCAP && !this.findingAid) { + return RECAP_AEON + } + if (this.aeonUrl && this.isReCAP && this.findingAid) { + return RECAP_AEON_FINDING_AID + } + if (this.aeonUrl && this.isOnsite && !this.findingAid) { + return ONSITE_AEON + } + if (this.isOnsite && this.aeonUrl && this.findingAid) { + return ONSITE_AEON_FINDING_AID + } + if (this.isOnsite && this.findingAid && !this.aeonUrl) { + return ONSITE_FINDING_AID + } + if (this.isReCAP && this.findingAid && !this.aeonUrl) { + return RECAP_FINDING_AID + } + if ( + this.isOnsite && + !this.findingAid && + !this.aeonUrl && + this.isSpecRequestable + ) { + return ONSITE_NO_FINDING_AID_NO_AEON + } + if ( + this.isReCAP && + !this.findingAid && + !this.aeonUrl && + this.isSpecRequestable + ) { + return RECAP_NO_FINDING_AID_NO_AEON + } else return EDGE_CASE + } +} + +export default ItemAvailability diff --git a/src/models/modelTests/Bib.test.ts b/src/models/modelTests/Bib.test.ts index 592572f40..22a752424 100644 --- a/src/models/modelTests/Bib.test.ts +++ b/src/models/modelTests/Bib.test.ts @@ -1,4 +1,7 @@ -import { bibWithItems } from "../../../__test__/fixtures/bibFixtures" +import { + bibWithItems, + bibWithSupplementaryContent, +} from "../../../__test__/fixtures/bibFixtures" import Bib from "../Bib" import Item from "../Item" @@ -10,6 +13,37 @@ describe("Bib model", () => { }) describe("constructor", () => { + describe("findingAid", () => { + const findingAidBib = new Bib({ + ...bibWithItems.resource, + supplementaryContent: [ + { + "@type": "nypl:SupplementaryContent", + label: "Finding aid", + url: "http://archives.nypl.org/scm/29990", + }, + ], + }) + it("initializes the finding aid when present", () => { + expect(findingAidBib.findingAid).toBe( + "http://archives.nypl.org/scm/29990" + ) + }) + it("does not initialize finding aid when no aid but supp content", () => { + const bibWithSupplementaryContentModel = new Bib( + bibWithSupplementaryContent.resource + ) + expect(bibWithSupplementaryContentModel.findingAid).toBe(null) + }) + it("can handle no supplementary content", () => { + expect(bib.findingAid).toBe(null) + }) + it("initializes finding aid in time to populate finding aid on item availability", () => { + expect( + findingAidBib.items.every((item) => item.availability.findingAid) + ).toBe(true) + }) + }) it("initializes the Bib ID with the with the Bib's @id field", () => { expect(bib.id).toBe("b15080796") }) diff --git a/src/models/modelTests/ItemAvailability.test.ts b/src/models/modelTests/ItemAvailability.test.ts new file mode 100644 index 000000000..c0883062e --- /dev/null +++ b/src/models/modelTests/ItemAvailability.test.ts @@ -0,0 +1,107 @@ +import { availabilityKeys } from "../../config/constants" +import ItemAvailability from "../ItemAvailability" + +describe("ItemAvailabilityFactory", () => { + it("not available", () => { + const availability = new ItemAvailability({ + isAvailable: false, + isReCAP: false, + aeonUrl: null, + findingAid: null, + isSpecRequestable: false, + }) + expect(availability.key).toBe(availabilityKeys.NOT_AVAILABLE) + }) + it("recap not special collections", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: true, + aeonUrl: null, + findingAid: null, + isSpecRequestable: false, + }) + expect(availability.key).toBe(availabilityKeys.RECAP_GENERAL_COLLECTIONS) + }) + it("recap aeon", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: true, + aeonUrl: "spaghetti.com", + findingAid: null, + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.RECAP_AEON) + }) + it("recap aeon finding aid", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: true, + aeonUrl: "spaghetti.com", + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.RECAP_AEON_FINDING_AID) + }) + it("onsite aeon", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: false, + aeonUrl: "spaghetti.com", + findingAid: false, + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.ONSITE_AEON) + }) + it("onsite aeon finding aid", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: false, + aeonUrl: "spaghetti.com", + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.ONSITE_AEON_FINDING_AID) + }) + it("onsite finding aid - no aeon", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: false, + aeonUrl: false, + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.ONSITE_FINDING_AID) + }) + it("recap finding aid - no aeon", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: true, + aeonUrl: false, + findingAid: "meatballs.com", + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.RECAP_FINDING_AID) + }) + it("recap no finding aid no aeon", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: true, + aeonUrl: false, + findingAid: false, + isSpecRequestable: true, + }) + expect(availability.key).toBe(availabilityKeys.RECAP_NO_FINDING_AID_NO_AEON) + }) + it("recap no finding aid no aeon", () => { + const availability = new ItemAvailability({ + isAvailable: true, + isReCAP: false, + aeonUrl: false, + findingAid: false, + isSpecRequestable: true, + }) + expect(availability.key).toBe( + availabilityKeys.ONSITE_NO_FINDING_AID_NO_AEON + ) + }) +}) diff --git a/src/types/appTypes.ts b/src/types/appTypes.ts index 318c851bf..5a312603b 100644 --- a/src/types/appTypes.ts +++ b/src/types/appTypes.ts @@ -9,6 +9,7 @@ export interface AppConfig { features: Record sourceEmail: string libAnswersEmail: string + requireAnAppointmentUrl: string } export interface APIEndpoints { development: string