From 758f690412609b726380c4b55f8f5ebcc6c4992d Mon Sep 17 00:00:00 2001 From: Chris Colvard Date: Tue, 11 Jun 2024 16:47:55 -0400 Subject: [PATCH] showNotes Transcript prop for displaying NOTE comments (default: false) --- src/components/Transcript/Transcript.js | 13 +++- src/components/Transcript/Transcript.md | 5 ++ src/components/Transcript/Transcript.test.js | 79 +++++++++++++++++++- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/components/Transcript/Transcript.js b/src/components/Transcript/Transcript.js index cf337097..399e83d7 100644 --- a/src/components/Transcript/Transcript.js +++ b/src/components/Transcript/Transcript.js @@ -44,7 +44,8 @@ const TranscriptLine = ({ isActive, focusedMatchId, setFocusedMatchId, - autoScrollEnabled + autoScrollEnabled, + showNotes }) => { const itemRef = React.useRef(null); const isFocused = item.id === focusedMatchId; @@ -83,7 +84,7 @@ const TranscriptLine = ({ goToItem(item); }; - if (item.tag === TRANSCRIPT_CUE_TYPES.note) { + if (item.tag === TRANSCRIPT_CUE_TYPES.note && showNotes) { return ( { const [manuallyActivatedItemId, setManuallyActivatedItem] = React.useState(null); const goToItem = React.useCallback((item) => { @@ -191,6 +193,7 @@ const TranscriptList = ({ item={searchResults.results[itemId]} autoScrollEnabled={autoScrollEnabled} setFocusedMatchId={setFocusedMatchId} + showNotes={showNotes} /> )); } @@ -217,7 +220,7 @@ const TranscriptList = ({ * @param {Object} param2 transcripts resource * @returns */ -const Transcript = ({ playerID, manifestUrl, search = {}, transcripts = [] }) => { +const Transcript = ({ playerID, manifestUrl, showNotes = false, search = {}, transcripts = [] }) => { const [transcriptsList, setTranscriptsList] = React.useState([]); const [canvasTranscripts, setCanvasTranscripts] = React.useState([]); const [transcript, setTranscript] = React.useState([]); @@ -494,6 +497,7 @@ const Transcript = ({ playerID, manifestUrl, search = {}, transcripts = [] }) => transcriptInfo={transcriptInfo} setFocusedMatchId={setFocusedMatchId} autoScrollEnabled={autoScrollEnabledRef.current && searchQuery === null} + showNotes={showNotes} /> @@ -511,6 +515,7 @@ Transcript.propTypes = { /** URL of the manifest */ manifestUrl: PropTypes.string, showSearch: PropTypes.bool, + showNotes: PropTypes.bool, search: PropTypes.oneOf([PropTypes.bool, PropTypes.shape({ initialSearchQuery: PropTypes.string, showMarkers: PropTypes.bool, diff --git a/src/components/Transcript/Transcript.md b/src/components/Transcript/Transcript.md index 575dbcc1..fcd60491 100644 --- a/src/components/Transcript/Transcript.md +++ b/src/components/Transcript/Transcript.md @@ -23,6 +23,10 @@ Transcript component displays any available transcript data in a given IIIF mani **_Identifying machine generated transcripts_**: To identify machine generated transcripts the Transcript component checks for `(Machine generated/machine-generated)` text disregarding case-sensitivity in the given title in the props or in the label in the `annotations`. +`Transcript` component allows the following optional props: + +- `showNotes`: display NOTE comments in SRT/VTT timed-text files (default: false) + __Either `manifestUrl` or `transcripts` is REQUIRED. If both props are given then `transcripts` takes *precedence* over `manifestUrl`__ To import this component from the library; @@ -35,6 +39,7 @@ import config from '../../../env.js'; { expect(parseTranscriptMock).toHaveBeenCalled(); expect(screen.queryByTestId('transcript_content_1')).toBeInTheDocument(); expect(screen.queryAllByTestId('transcript_time')).toHaveLength(3); - // One more than timestamps for displaying the comment - expect(screen.queryAllByTestId('transcript_text')).toHaveLength(4); + expect(screen.queryAllByTestId('transcript_text')).toHaveLength(3); }); }); - test('renders comment in the header block', async () => { + test('does not render comment in the header block', async () => { await waitFor(() => { - expect(screen.queryAllByTestId('transcript_text')[0]).toHaveTextContent( + expect(screen.queryAllByTestId('transcript_text')[0]).not.toHaveTextContent( 'NOTEThis is a multi-line comment.Following is a list of cues.' ); }); @@ -196,6 +195,78 @@ describe('Transcript component', () => { }); }); + describe('with WebVTT with NOTE comment', () => { + let parseTranscriptMock; + beforeEach(async () => { + const parsedData = { + tData: [ + { + begin: 0, + end: 0, + text: 'NOTE
This is a multi-line comment.
Following is a list of cues.', + tag: 'NOTE' + }, + { + begin: 1.2, + end: 21, + text: '[music]', + tag: 'TIMED_CUE' + }, + { + begin: 22.2, + end: 26.6, + text: 'transcript text 1', + tag: 'TIMED_CUE' + }, + { + begin: 27.3, + end: 31, + text: 'transcript text 2', + tag: 'TIMED_CUE' + }, + ], + tUrl: 'http://example.com/transcript.vtt', + tType: transcriptParser.TRANSCRIPT_TYPES.timedText, + tFileExt: 'vtt', + }; + parseTranscriptMock = jest + .spyOn(transcriptParser, 'parseTranscriptData') + .mockReturnValue(parsedData); + + const TranscriptWithState = withManifestAndPlayerProvider(Transcript, { + initialManifestState: { manifest: lunchroomManners, canvasIndex: 0 }, + initialPlayerState: {}, + ...props, + showNotes: true, + }); + + render( + + + ); + + await act(() => Promise.resolve()); + }); + test('renders successfully', async () => { + await waitFor(() => { + expect(parseTranscriptMock).toHaveBeenCalled(); + expect(screen.queryByTestId('transcript_content_1')).toBeInTheDocument(); + expect(screen.queryAllByTestId('transcript_time')).toHaveLength(3); + expect(screen.queryAllByTestId('transcript_text')).toHaveLength(4); + }); + }); + + test('renders comment in the header block', async () => { + await waitFor(() => { + expect(screen.queryAllByTestId('transcript_text')[0]).toHaveTextContent( + 'NOTEThis is a multi-line comment.Following is a list of cues.' + ); + }); + }); + }); + describe('with transcript as an annotation list', () => { let parseTranscriptMock; beforeEach(async () => {