@harvard-lts/mirador-eda-plugin 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/es/index.js +2 -2
  2. package/package.json +5 -4
  3. package/.github/pull_request_template.md +0 -31
  4. package/.github/workflows/publish-package.yml +0 -34
  5. package/.nvmrc +0 -1
  6. package/.parcelrc +0 -9
  7. package/.travis.yml +0 -16
  8. package/CONTRIBUTING.md +0 -20
  9. package/__mocks__/fileMock.js +0 -1
  10. package/babel.config.json +0 -11
  11. package/demo/data/manifest-3037.json +0 -524
  12. package/demo/data/manifest-5f3b.json +0 -315
  13. package/demo/data/manifest-609.json +0 -500
  14. package/demo/data/ms_am_1118_3_142_0001.jpg +0 -0
  15. package/demo/data/ms_am_1118_3_142_0002.jpg +0 -0
  16. package/demo/data/ms_am_1118_3_142_0003.jpg +0 -0
  17. package/demo/demoEntry.js +0 -21
  18. package/demo/index.html +0 -23
  19. package/jest.config.js +0 -23
  20. package/nwb.config.js +0 -20
  21. package/rollup.config.mjs +0 -12
  22. package/setupTests.js +0 -1
  23. package/src/index.js +0 -10
  24. package/src/plugins/EdaSideBarButtonsWrapper.js +0 -51
  25. package/src/plugins/EdaTranscriptionButton.js +0 -19
  26. package/src/plugins/EdaTranscriptionPanel.js +0 -245
  27. package/src/plugins/__tests__/EdaSideBarButtonsWrapper.spec.js +0 -183
  28. package/src/plugins/__tests__/EdaTranscriptionButton.spec.js +0 -17
  29. package/src/plugins/__tests__/EdaTranscriptionPanel.spec.js +0 -188
  30. package/src/plugins/__tests__/edaManifest.spec.js +0 -110
  31. package/src/plugins/__tests__/nonEdaManifest.spec.js +0 -64
  32. package/src/plugins/__tests__/transcriptionUtils.spec.js +0 -430
  33. package/src/plugins/testFixtures/combinedEditionsTranscriptions.js +0 -62
  34. package/src/plugins/testFixtures/franklinVariorum1998Transcription.js +0 -85
  35. package/src/plugins/testFixtures/johnsonPoems1955Transcription.js +0 -88
  36. package/src/plugins/transcriptionUtils.js +0 -114
  37. package/src/plugins/utils/suppressWarnings.js +0 -41
  38. package/webpack.config.cjs +0 -56
@@ -1,51 +0,0 @@
1
- import React, { useMemo } from "react"
2
- import { useSelector, shallowEqual } from "react-redux"
3
- import { getEdaTranscription } from "./transcriptionUtils"
4
- import EdaTranscriptionButton from "./EdaTranscriptionButton"
5
-
6
- // /**
7
- // * Wrapper for the WindowSideBarButtons component
8
- // * Sets "EDA Transcriptions" for the tooltip text translations for EDA Transcriptions button
9
- // * Hides the Annotation button when EDA transcriptions are available
10
- // * @param {Object} props - Component props
11
- // * @param {React.Component} props.TargetComponent - The component to wrap
12
- // * @param {Object} props.targetProps - Other props passed to the component
13
- // */
14
-
15
- const EdaSideBarButtonsWrapper = ({ TargetComponent, ...targetProps }) => {
16
- // shallowEqual prevents re-renders unless transcriptions actually change
17
- const transcriptions = useSelector(getEdaTranscription, shallowEqual)
18
- const hasTranscriptions = Boolean(transcriptions && transcriptions.length > 0)
19
-
20
- // sets the translation for the EDA Transcriptions button tooltip
21
- const customTranslation = (key, opts) => {
22
- if (key === "openCompanionWindow" &&
23
- opts &&
24
- opts.context === "edaTranscription") {
25
- return "EDA Transcriptions"
26
- }
27
-
28
- const originalTranslation = targetProps.t || (key => key)
29
- return originalTranslation(key, opts)
30
- }
31
-
32
- // if transcriptions exist, add EDA Transcriptions button and hide Annotations button
33
- const plugin = hasTranscriptions
34
- ? [...(targetProps.PluginComponents || []), EdaTranscriptionButton]
35
- : targetProps.PluginComponents
36
-
37
- return (
38
- <TargetComponent
39
- {...targetProps}
40
- t={customTranslation}
41
- panels={{ ...targetProps.panels, annotations: !hasTranscriptions }}
42
- PluginComponents={plugin}
43
- />
44
- )
45
- }
46
-
47
- export default {
48
- target: "WindowSideBarButtons",
49
- mode: "wrap",
50
- component: EdaSideBarButtonsWrapper
51
- }
@@ -1,19 +0,0 @@
1
- import React from "react"
2
- import TitleIcon from "@material-ui/icons/Title"
3
-
4
- /**
5
- * A button component that displays a T icon
6
- * The button triggers the opening of the EDA Transcriptions companion window
7
- */
8
-
9
- const EdaTranscriptionButton = () => {
10
- return (
11
- <TitleIcon data-testid="eda-transcription-icon" />
12
- )
13
- }
14
-
15
- // this needs to match the companionWindowKey in EdaTranscriptionPanel.js
16
- EdaTranscriptionButton.value = "edaTranscription"
17
-
18
- export default EdaTranscriptionButton
19
-
@@ -1,245 +0,0 @@
1
- import React, { useState, createRef } from "react"
2
- import CompanionWindow from "mirador/dist/es/src/containers/CompanionWindow"
3
- import { compose } from "redux"
4
- import { connect } from "react-redux"
5
- import { getEdaTranscription } from "./transcriptionUtils"
6
- import { withStyles } from "@material-ui/core/styles"
7
- import {
8
- FormControl,
9
- Select,
10
- MenuItem,
11
- FormControlLabel,
12
- Checkbox,
13
- Typography,
14
- } from "@material-ui/core"
15
-
16
- /**
17
- * EDA Transcription Panel Component
18
- * Displays transcription options and the transcription content
19
- * Manages state for selected edition, editorial marks, and line breaks
20
- * @param {Object} props.classes - JSS classes for styling
21
- * @param {array} props.transcriptions - Array of transcription HTML strings
22
- * @param {string} props.windowId - ID of the current window
23
- * @param {string} props.id - ID for the companion window
24
- */
25
-
26
- const EdaTranscriptionPanel = ({ classes, transcriptions, windowId, id }) => {
27
- const [selectedEdition, setSelectedEdition] = useState(0)
28
- const [showPhysicalLinebreaks, setShowPhysicalLinebreaks] = useState(true)
29
- const [hideEdits, setHideEdits] = useState(false)
30
- const currentTranscription = transcriptions[selectedEdition] || ""
31
- const contentRef = createRef()
32
-
33
- const getEditionLabel = (html) => {
34
- const parser = new DOMParser()
35
- const doc = parser.parseFromString(html, "text/html")
36
- const workBody = doc.querySelector(".work-body")
37
- return workBody?.dataset?.edition || "Unknown Edition"
38
- }
39
-
40
- const handleEditionChange = (event) => {
41
- setSelectedEdition(event.target.value)
42
- }
43
-
44
- const handleLinebreaksChange = (event) => {
45
- setShowPhysicalLinebreaks(event.target.checked)
46
- }
47
-
48
- const handleEditsChange = (event) => {
49
- setHideEdits(event.target.checked)
50
- }
51
-
52
- const sectionClasses = [
53
- classes.section,
54
- showPhysicalLinebreaks ? "show-linebreaks" : "",
55
- hideEdits ? "hide-edits" : "",
56
- ].filter(Boolean).join(" ")
57
-
58
- // CompanionWindow pulls the resizing functionality from Mirador
59
- // the paperClassName prop allows styles to the underlying container
60
- return (
61
- <CompanionWindow
62
- title="EDA Transcription"
63
- windowId={windowId}
64
- id={id}
65
- paperClassName={classes.paper}
66
- >
67
- {/* handle the case when the panel is opened but no transcriptions exist */}
68
- {(!transcriptions || transcriptions.length === 0) && (
69
- <div className={classes.root}>
70
- <div className={classes.section}>
71
- <Typography variant="body1" className={classes.noTranscriptionsMessage1}>
72
- No Emily Dickinson Archive transcriptions are available for this manifest.
73
- </Typography>
74
- <Typography variant="body2" className={classes.noTranscriptionsMessage2}>
75
- This feature is only available for items from the Emily Dickinson Archive.
76
- </Typography>
77
- </div>
78
- </div>
79
- )}
80
-
81
- <div className={classes.root}>
82
- <div className={classes.controls}>
83
- {transcriptions.length > 0 && (
84
- <FormControl className={classes.formControl}>
85
- <Typography variant="body2" className={classes.editionLabel}>
86
- Edition
87
- </Typography>
88
- <Select
89
- value={selectedEdition}
90
- onChange={handleEditionChange}
91
- variant="outlined"
92
- margin="dense"
93
- className={classes.selectInput}
94
- disabled={transcriptions.length === 1}
95
- >
96
- {transcriptions.map((transcription, index) => (
97
- <MenuItem key={index} value={index}>
98
- {getEditionLabel(transcription)}
99
- </MenuItem>
100
- ))}
101
- </Select>
102
- </FormControl>
103
- )}
104
-
105
- <FormControlLabel
106
- control={
107
- <Checkbox
108
- checked={hideEdits}
109
- onChange={handleEditsChange}
110
- name="edits"
111
- color="primary"
112
- />
113
- }
114
- label="Hide Edits"
115
- />
116
-
117
- <FormControlLabel
118
- control={
119
- <Checkbox
120
- checked={showPhysicalLinebreaks}
121
- onChange={handleLinebreaksChange}
122
- name="linebreaks"
123
- color="primary"
124
- />
125
- }
126
- label="Physical Line Breaks"
127
- />
128
- </div>
129
-
130
- <div
131
- ref={contentRef}
132
- className={sectionClasses}
133
- dangerouslySetInnerHTML={{ __html: currentTranscription }}
134
- />
135
- </div>
136
- </CompanionWindow>
137
- )
138
- }
139
-
140
- const styles = (theme) => ({
141
- "@global": {
142
- ".react-draggable": {
143
- minWidth: "350px !important", // this must match the paper minWidth
144
- }
145
- },
146
- root: {
147
- height: "100%",
148
- overflow: "auto",
149
- display: "flex",
150
- flexDirection: "column",
151
- },
152
- paper: {
153
- minWidth: "350px", // this must match the companion window minWidth
154
- },
155
- controls: {
156
- padding: theme.spacing(2),
157
- borderBottom: `1px solid ${theme.palette.divider}`,
158
- backgroundColor: theme.palette.background.paper,
159
- },
160
- formControl: {
161
- marginBottom: theme.spacing(1),
162
- width: "100%",
163
- },
164
- editionLabel: {
165
- fontWeight: "bold",
166
- marginBottom: theme.spacing(0.5),
167
- fontSize: "0.875rem",
168
- },
169
- selectInput: {
170
- width: 300
171
- },
172
- section: {
173
- flex: 1,
174
- fontSize: ".875em",
175
- lineHeight: theme.typography.body2.lineHeight,
176
- fontFamily: theme.typography.fontFamily,
177
- backgroundColor: theme.palette.background.paper,
178
- borderRight: `0.5px solid ${theme.palette.divider}`,
179
- overflow: "auto",
180
- color: theme.palette.text.primary,
181
- padding: theme.spacing(2),
182
- "& .line": {
183
- display: "block",
184
- },
185
- "& ins:before": {
186
- content: '"["',
187
- fontWeight: theme.typography.fontWeightBold,
188
- },
189
- "& ins:after": {
190
- content: '"]"',
191
- fontWeight: theme.typography.fontWeightBold,
192
- },
193
- "& rt": {
194
- fontSize: "0.833em",
195
- },
196
- "& .work-body": {
197
- whiteSpace: "nowrap",
198
- "& h3, & h4": {
199
- fontWeight: theme.typography.fontWeightBold,
200
- whiteSpace: "normal",
201
- },
202
- "& br": {
203
- display: "none",
204
- },
205
- },
206
- "&.show-linebreaks .work-body br": {
207
- display: "block",
208
- },
209
- "&.hide-edits ins": {
210
- display: "none",
211
- },
212
- "&.hide-edits rt": {
213
- display: "none",
214
- },
215
- "& .stanza": {
216
- marginBottom: theme.spacing(1.875)
217
- },
218
- "& .page-break": {
219
- borderWidth: "1px 0 0 0",
220
- borderStyle: "dotted",
221
- display: "block !important",
222
- },
223
- },
224
- noTranscriptionsMessage1: {
225
- padding: "16px"
226
- },
227
- noTranscriptionsMessage2: {
228
- padding: "0 16px 16px"
229
- },
230
- })
231
-
232
- const mapStateToProps = (state, { windowId }) => ({
233
- transcriptions: getEdaTranscription(state, windowId),
234
- })
235
-
236
- const enhance = compose(
237
- withStyles(styles),
238
- connect(mapStateToProps)
239
- )
240
-
241
- export default {
242
- component: enhance(EdaTranscriptionPanel),
243
- companionWindowKey: "edaTranscription"
244
- }
245
-
@@ -1,183 +0,0 @@
1
- /** @jest-environment jsdom */
2
- import React from "react"
3
- import { render, screen } from "@testing-library/react"
4
- import { Provider } from "react-redux"
5
- import EdaSideBarButtonsWrapper from "../EdaSideBarButtonsWrapper"
6
- import { getEdaTranscription } from "../transcriptionUtils"
7
-
8
- // Mock transcriptionUtils
9
- jest.mock("../transcriptionUtils", () => ({
10
- getEdaTranscription: jest.fn()
11
- }))
12
-
13
- // Mock base components that would be provided by Mirador
14
- const MockButton = ({ value, onClick }) => (
15
- <button onClick={onClick} data-value={value}>
16
- {value}
17
- </button>
18
- )
19
-
20
- const MockSidebarButtons = ({
21
- PluginComponents = [],
22
- panels = {},
23
- t = (key) => key
24
- }) => {
25
- return (
26
- <div>
27
- {/* Info button - always visible */}
28
- <MockButton value="information" onClick={() => { }} />
29
-
30
- {/* Rights button - always visible */}
31
- <MockButton value="rights" onClick={() => { }} />
32
-
33
- {/* Index button - always visible */}
34
- <MockButton value="index" onClick={() => { }} />
35
-
36
- {/* Annotations button - conditionally visible */}
37
- {panels.annotations !== false && (
38
- <MockButton value="annotations" onClick={() => { }} />
39
- )}
40
-
41
- {/* Plugin buttons */}
42
- {PluginComponents.map((Component, index) => (
43
- <Component key={index} />
44
- ))}
45
- </div>
46
- )
47
- }
48
-
49
- describe("EdaSideBarButtonsWrapper", () => {
50
- const createWrapper = (hasTranscriptions = false) => {
51
- // Mock the transcription selector
52
- getEdaTranscription.mockReturnValue(
53
- hasTranscriptions ? ["some transcription"] : []
54
- )
55
-
56
- // Mock store
57
- const store = {
58
- getState: () => ({}),
59
- subscribe: jest.fn(),
60
- dispatch: jest.fn()
61
- }
62
-
63
- // Get the wrapped component from the plugin config
64
- const { component: WrappedComponent } = EdaSideBarButtonsWrapper
65
-
66
- return render(
67
- <Provider store={store}>
68
- <WrappedComponent
69
- TargetComponent={MockSidebarButtons}
70
- panels={{}}
71
- t={(key, opts) => key}
72
- />
73
- </Provider>
74
- )
75
- }
76
-
77
- describe("when translations are false (no transcriptions)", () => {
78
- beforeEach(() => {
79
- createWrapper(false)
80
- })
81
-
82
- it("should display the information button", () => {
83
- const button = screen.getByText("information")
84
- expect(button).toBeInTheDocument()
85
- })
86
-
87
- it("should display the rights button", () => {
88
- const button = screen.getByText("rights")
89
- expect(button).toBeInTheDocument()
90
- })
91
-
92
- it("should display the index button", () => {
93
- const button = screen.getByText("index")
94
- expect(button).toBeInTheDocument()
95
- })
96
-
97
- it("should display the annotations button", () => {
98
- const button = screen.getByText("annotations")
99
- expect(button).toBeInTheDocument()
100
- })
101
-
102
- it("should not render the EDA button", () => {
103
- const button = screen.queryByAltText("EDA Transcriptions")
104
- expect(button).not.toBeInTheDocument()
105
- })
106
- })
107
-
108
- describe("when translations are true (has transcriptions)", () => {
109
- beforeEach(() => {
110
- createWrapper(true)
111
- })
112
-
113
- it("should display the information button", () => {
114
- const button = screen.getByText("information")
115
- expect(button).toBeInTheDocument()
116
- })
117
-
118
- it("should display the rights button", () => {
119
- const button = screen.getByText("rights")
120
- expect(button).toBeInTheDocument()
121
- })
122
-
123
- it("should display the index button", () => {
124
- const button = screen.getByText("index")
125
- expect(button).toBeInTheDocument()
126
- })
127
-
128
- it("should not display the annotations button", () => {
129
- const button = screen.queryByText("annotations")
130
- expect(button).not.toBeInTheDocument()
131
- })
132
-
133
- it("should display the EDA button", () => {
134
- createWrapper(true)
135
- const icons = screen.queryAllByTestId("eda-transcription-icon")
136
- expect(icons.length).toBeGreaterThan(0)
137
- })
138
- })
139
-
140
- describe("translations", () => {
141
- it("should provide custom translation for EDA button tooltip", () => {
142
- let capturedTranslation
143
- const MockComponent = (props) => {
144
- // Capture the translation for testing
145
- capturedTranslation = props.t("openCompanionWindow", { context: "edaTranscription" })
146
- return null
147
- }
148
-
149
- const { component: Wrapped } = EdaSideBarButtonsWrapper
150
- render(
151
- <Provider store={{ getState: () => ({}), subscribe: jest.fn(), dispatch: jest.fn() }}>
152
- <Wrapped
153
- TargetComponent={MockComponent}
154
- t={(key) => key}
155
- />
156
- </Provider>
157
- )
158
-
159
- expect(capturedTranslation).toBe("EDA Transcriptions")
160
- })
161
-
162
- it("should pass through other translations", () => {
163
- let capturedTranslation
164
- const MockComponent = (props) => {
165
- // Capture the translation for testing
166
- capturedTranslation = props.t("someOtherKey", { context: "other" })
167
- return null
168
- }
169
-
170
- const { component: Wrapped } = EdaSideBarButtonsWrapper
171
- render(
172
- <Provider store={{ getState: () => ({}), subscribe: jest.fn(), dispatch: jest.fn() }}>
173
- <Wrapped
174
- TargetComponent={MockComponent}
175
- t={(key) => key}
176
- />
177
- </Provider>
178
- )
179
-
180
- expect(capturedTranslation).toBe("someOtherKey")
181
- })
182
- })
183
- })
@@ -1,17 +0,0 @@
1
- /** @jest-environment jsdom */
2
- import React from "react"
3
- import { render, screen } from "@testing-library/react"
4
- import EdaTranscriptionButton from "../EdaTranscriptionButton"
5
-
6
- describe("EdaTranscriptionButton", () => {
7
- it("should render with a TitleIcon", () => {
8
- render(<EdaTranscriptionButton />)
9
- const icon = screen.getByTestId("eda-transcription-icon")
10
- expect(icon).toBeInTheDocument()
11
- })
12
-
13
- it("should have the correct value property", () => {
14
- expect(EdaTranscriptionButton.value).toBe("edaTranscription")
15
- })
16
- })
17
-