From 550c81a617fbb5f83404aba5651d01b451cc60f2 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Mon, 24 Jun 2019 18:53:55 +0100 Subject: [PATCH 01/55] fix: client was not receiving data from server in local dev fixed by adding this.projectsUrl inside constructor of APIWrapper class --- src/ApiWrapper/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ApiWrapper/index.js b/src/ApiWrapper/index.js index 4d4341a5..474a9676 100644 --- a/src/ApiWrapper/index.js +++ b/src/ApiWrapper/index.js @@ -4,11 +4,10 @@ import corsFetch from './cors_wrapper.js'; class ApiWrapper { constructor() { this.baseUrl = window.env.API_URL; - window.env.API_URL = null; - } - projectsUrl = `${ this.baseUrl }/api/projects`; + this.projectsUrl = `${ this.baseUrl }/api/projects`; + } projectsIdUrl = (projectId) => `${ this.projectsUrl }/${ projectId }`; transcriptsUrl = (projectId) => `${ this.projectsIdUrl(projectId) }/transcripts`; @@ -33,8 +32,10 @@ class ApiWrapper { * Projects */ async getAllProjects() { + console.log(this.projectsUrl); const res = await corsFetch(this.projectsUrl); const json = await res.json(); + console.log('getAllProjects::', json); return json.projects; } From b5f02d29f815eb295e7264735bc0a8caf6a6a462 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Tue, 25 Jun 2019 11:09:56 +0200 Subject: [PATCH 02/55] improved programme script btn options --- .env | 2 +- .../PaperEdit/ProgramScript/ToolBar.js | 24 +++++-- .../PaperEdit/ProgramScript/index.js | 71 ++++++++++++++----- 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/.env b/.env index f4a3c553..fcf8f601 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ # App name used in browser title and navbar -REACT_APP_NAME="Digital Paper Edit" +REACT_APP_NAME="" REACT_APP_NODE_ENV="development" REACT_APP_SERVER_URL="http://localhost:8080" diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js index d4835d18..0735ef0a 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js @@ -3,7 +3,12 @@ import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import Button from 'react-bootstrap/Button'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faMicrophoneAlt, faStickyNote, faHeading } from '@fortawesome/free-solid-svg-icons'; +import { + faMicrophoneAlt, + faStickyNote, + faHeading, + faPlus +} from '@fortawesome/free-solid-svg-icons'; class ToolBar extends Component { constructor(props) { @@ -13,20 +18,31 @@ class ToolBar extends Component { }; } + // eslint-disable-next-line class-methods-use-this render() { return ( - + + + + - + - + diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 9641d5f6..31323576 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -1,10 +1,19 @@ import React, { Component } from 'react'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; import cuid from 'cuid'; import Tab from 'react-bootstrap/Tab'; import PreviewCanvas from './PreviewCanvas/index.js'; import Button from 'react-bootstrap/Button'; import EDL from 'edl_composer'; import downloadjs from 'downloadjs'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { + faFileExport, + faRecycle, + faPlus +} from '@fortawesome/free-solid-svg-icons'; + import ToolBar from './ToolBar'; import ProgrammeScript from './ProgrammeScript.js'; import getDataFromUserWordsSelection from './get-data-from-user-selection.js'; @@ -164,24 +173,52 @@ class ProgramScript extends Component { : null }
- - - - + + + + + + + + + + + + + + +
- +
From 846e978c72643957197276bc8ba85079eba76466 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Wed, 3 Jul 2019 21:48:01 +0200 Subject: [PATCH 03/55] Refactor programme script btns added ADL, EDL, FCPX export + rearranged btns layour in programme script --- package-lock.json | 14 ++ package.json | 2 + .../PaperEdit/ProgramScript/ToolBar.js | 55 ------ .../PaperEdit/ProgramScript/index.js | 163 ++++++++++++++---- 4 files changed, 142 insertions(+), 92 deletions(-) delete mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js diff --git a/package-lock.json b/package-lock.json index 3fd9b10d..1759710b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -878,6 +878,20 @@ "to-fast-properties": "^2.0.0" } }, + "@bbc/aes31-adl-composer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@bbc/aes31-adl-composer/-/aes31-adl-composer-1.0.0.tgz", + "integrity": "sha512-LMSMJBLuBuZiHqWOkJXfLOLqBO0zX82Zupg89LDFmkQoaseU8xpMmInlTdKhCaXIHG44qyKlPmI1DtwqOscO9Q==", + "requires": { + "node-timecodes": "^2.5.0", + "uuid": "^3.3.2" + } + }, + "@bbc/fcpx-xml-composer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@bbc/fcpx-xml-composer/-/fcpx-xml-composer-1.0.0.tgz", + "integrity": "sha512-fL7UWi/YvTOCM2HLmVbdgQrKt/WN9zqQKi7Zn61dvZWbZE77fLfpeftaJc6O/k8QUVhS7qPYpNIsBBM8V3NupQ==" + }, "@bbc/react-transcript-editor": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@bbc/react-transcript-editor/-/react-transcript-editor-1.0.4.tgz", diff --git a/package.json b/package.json index 57efedbc..348f2d6f 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "description": "Digital paper edit application, using transcriptions from automated STT, to do text based video editing on audio and video interviews. Modular architecture with - React - Express - Electron - Adobe CEP", "main": "index.js", "dependencies": { + "@bbc/aes31-adl-composer": "^1.0.0", + "@bbc/fcpx-xml-composer": "^1.0.0", "@bbc/react-transcript-editor": "^1.0.4", "@fortawesome/fontawesome-svg-core": "^1.2.15", "@fortawesome/free-solid-svg-icons": "^5.7.2", diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js deleted file mode 100644 index 0735ef0a..00000000 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/ToolBar.js +++ /dev/null @@ -1,55 +0,0 @@ -import React, { Component } from 'react'; -import Col from 'react-bootstrap/Col'; -import Row from 'react-bootstrap/Row'; -import Button from 'react-bootstrap/Button'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { - faMicrophoneAlt, - faStickyNote, - faHeading, - faPlus -} from '@fortawesome/free-solid-svg-icons'; - -class ToolBar extends Component { - constructor(props) { - super(props); - this.state = { - - }; - } - - // eslint-disable-next-line class-methods-use-this - render() { - return ( - - - - - - - - - - - - - - - ); - } -} - -export default ToolBar; diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 31323576..9807ab63 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -5,16 +5,22 @@ import cuid from 'cuid'; import Tab from 'react-bootstrap/Tab'; import PreviewCanvas from './PreviewCanvas/index.js'; import Button from 'react-bootstrap/Button'; +import Dropdown from 'react-bootstrap/Dropdown'; import EDL from 'edl_composer'; +import generateADL from '@bbc/aes31-adl-composer'; +import jsonToFCPX from '@bbc/fcpx-xml-composer'; import downloadjs from 'downloadjs'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faFileExport, - faRecycle, - faPlus + faMicrophoneAlt, + faStickyNote, + faHeading, + faPlus, + faSync, + faInfoCircle } from '@fortawesome/free-solid-svg-icons'; -import ToolBar from './ToolBar'; import ProgrammeScript from './ProgrammeScript.js'; import getDataFromUserWordsSelection from './get-data-from-user-selection.js'; import ApiWrapper from '../../../../ApiWrapper/index.js'; @@ -77,9 +83,10 @@ class ProgramScript extends Component { } } - // https://www.npmjs.com/package/downloadjs - // https://www.npmjs.com/package/edl_composer - handleExportEDL = () => { + /** + * Helper function to create json EDL for other EDL/ADL/FPCX export + */ + getSequenceJsonEDL = () => { const edlSq = { 'title': this.state.programmeScript.title, 'events': [ ] @@ -112,11 +119,57 @@ class ProgramScript extends Component { return el; }); edlSq.events.push(...programmeScriptPaperCutsWithId); + + return edlSq; + } + + // https://www.npmjs.com/package/downloadjs + // https://www.npmjs.com/package/edl_composer + handleExportEDL = () => { + const edlSq = this.getSequenceJsonEDL(); const edl = new EDL(edlSq); console.log(edl.compose()); downloadjs(edl.compose(), `${ this.state.programmeScript.title }.edl`, 'text/plain'); } + handleExportADL = () => { + // alert('this function has not been implemented yet'); + const edlSq = this.getSequenceJsonEDL(); + // const result = generateADL(edlSq); + const result = generateADL({ + projectOriginator: 'Digital Paper Edit', + // TODO: it be good to change sequence for the ADL to be same schema + // as the one for EDL and FCPX - for now just adjusting + edits: edlSq.events.map((event) => { + return { + start: event.startTime, + end: event.endTime, + clipName: event.clipName, + // TODO: could add a label if present + label: '' + }; + }), + // TODO: sampleRate should be pulled from the sequence + sampleRate: '44100', + // TODO: frameRate should be pulled from the sequence + frameRate: 25, + projectName: edlSq.title + }); + downloadjs(result, `${ this.state.programmeScript.title }.adl`, 'text/plain'); + } + + handleExportFCPX = () => { + // alert('this function has not been implemented yet'); + const edlSq = this.getSequenceJsonEDL(); + + const result = jsonToFCPX(edlSq); + downloadjs(result, `${ this.state.programmeScript.title }.fcpxml`, 'text/plain'); + } + + handleExportTxt = () => { + alert('this function has not been implemented yet'); + } + handleUpdatePreview = () => { let timelineStartTime = 0; // const { playlist } = this.state; @@ -174,51 +227,87 @@ class ProgramScript extends Component { : null }
- + - - - - - + + + + + + + Heading + + + Voice Over + + + Note + + + + + + + Export + + + + + EDL - Video + + + {/* */} + ADL - Audio + + + FCPX + + + Text + + + + -
-
From e3a96684ec270cbdb69c61ede772bf1b34b2b835 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Wed, 3 Jul 2019 22:22:12 +0200 Subject: [PATCH 04/55] adjusted size of play/stop btn for videoContext preview component --- .../PreviewCanvas/VideoContextControls.js | 18 ++++++++++++++---- .../ProgramScript/PreviewCanvas/index.js | 10 +++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/PreviewCanvas/VideoContextControls.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/PreviewCanvas/VideoContextControls.js index 3c9188a2..448c7eca 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/PreviewCanvas/VideoContextControls.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/PreviewCanvas/VideoContextControls.js @@ -39,16 +39,26 @@ class Controls extends React.PureComponent { return ( <> - - From 79e4efcea955c982861c708dc91058088d7d020e Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Thu, 4 Jul 2019 23:05:05 +0200 Subject: [PATCH 14/55] Added support for programme script elements voice over, notes, heading/title --- .../PaperEdit/ProgramScript/index.js | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 444ffe5f..0005c07f 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -83,13 +83,41 @@ class ProgramScript extends Component { ); } + handleAddTranscriptElementToProgrammeScript = (elementType) => { + const { programmeScript } = this.state; + const elements = this.state.programmeScript.elements; + // TODO: refactor - with helper functions + if (elementType === 'title' + || elementType === 'note' + || elementType === 'voice-over') { + const text = prompt('Add some text for a section title', 'Section Two'); + console.log(text); + + elements.push({ + id: cuid(), + index: elements.length, + type: elementType, + text: text + }); + programmeScript.elements = elements; + // TODO: save to server + this.setState({ + programmeScript: programmeScript + }); + } + } + // TODO: save to server // TODO: needs to handle when selection spans across multiple paragraphs handleAddTranscriptSelectionToProgrammeScript = () => { const result = getDataFromUserWordsSelection(); console.log('getDataFromUserWordsSelection::', result); if (result) { - console.log(result); + console.log(JSON.stringify(result, null, 2)); + // result.words + // TODO: if there's just one speaker in selection do following + // if it's multiple split list of words into multiple groups + // and add a papercut for each to the programme script const { programmeScript } = this.state; const elements = this.state.programmeScript.elements; // papercut could be abstracted as helper function @@ -268,7 +296,7 @@ class ProgramScript extends Component { result += `[ ${ event.text }]\n\n`; } else if (event.type === 'paper-cut') { - result += `${ timecodes.fromSeconds(event.startTime) }\t${ timecodes.fromSeconds(event.endTime) }\t${ event.speaker }\t - ${ event.clipName }\n${ event.words.map((word) => {return `${ word.text } `;}) }\n\n`; + result += `${ timecodes.fromSeconds(event.startTime) }\t${ timecodes.fromSeconds(event.endTime) }\t${ event.speaker }\t-\t${ event.clipName }\n${ event.words.map((word) => {return word.text;}).join(' ') }\n\n`; } }); @@ -278,7 +306,7 @@ class ProgramScript extends Component { handleExportJson = () => { const programmeScriptJson = this.getProgrammeScriptJson(); const programmeScriptText = JSON.stringify(programmeScriptJson, null, 2); - downloadjs(programmeScriptText, `${ this.state.programmeScript.title }.txt`, 'text/plain'); + downloadjs(programmeScriptText, `${ this.state.programmeScript.title }.json`, 'text/plain'); } handleExportTxt = () => { @@ -362,17 +390,20 @@ class ProgramScript extends Component { {this.handleAddTranscriptElementToProgrammeScript('title');} } + title="Add a title header element to the programme script" > Heading {this.handleAddTranscriptElementToProgrammeScript('voice-over');} } + title="Add a title voice over element to the programme script" > Voice Over {this.handleAddTranscriptElementToProgrammeScript('note');} } + title="Add a note element to the programme script" > Note From cd1af435a82fc744a81b3e0ad47181fe88e3485a Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Thu, 4 Jul 2019 23:17:28 +0100 Subject: [PATCH 15/55] added possibility to edit programme script elements voice over, notes, titles, but not paper-cuts --- .../ProgramScript/ProgrammeScript.js | 22 +++++++++----- .../PaperEdit/ProgramScript/index.js | 30 +++++++++++++++++-- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js index cbb57970..87abe04a 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js @@ -15,21 +15,27 @@ import Note from './Note'; import { faGripLines, faGripHorizontal, + faPen, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const DragHandle = sortableHandle(() => ); -const SortableItem = sortableElement(({ value, index, handleDelete }) => { +const SortableItem = sortableElement(({ value, index, type, handleDelete, handleEdit }) => { return (
  • - + {value} + + {/* TODO: if paper-cut then don't show edit/pen icon */} + {type !== 'paper-cut' ? { handleEdit(index); } } /> : null} + + {/* TODO: pass a prop to remove element from list */} {handleDelete(index);} } /> @@ -68,13 +74,13 @@ class ProgrammeScript extends Component { programme = this.props.programmeScriptElements.map((el) => { switch (el.type) { case 'title': - return ; + return { el:, type: el.type }; case 'voice-over': - return ; + return { el:, type: el.type }; case 'paper-cut': - return ; + return { el: , type: el.type }; case 'note': - return ; + return { el: , type: el.type }; default: console.error('invalid programme element type'); @@ -89,8 +95,10 @@ class ProgrammeScript extends Component { ))} ; diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 0005c07f..851a0a6a 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -68,7 +68,8 @@ class ProgramScript extends Component { // TODO: save to server handleDeleteProgrammeScriptElement = (i) => { - alert('handle delete'); + // TODO: add a prompt, like are you shure you want to delete, confirm etc..? + // alert('handle delete'); console.log(i); this.setState(({ programmeScript }) => { const index = i; @@ -83,6 +84,30 @@ class ProgramScript extends Component { ); } + handleEditProgrammeScriptElement = (i) => { + console.log(i); + const { programmeScript } = this.state; + const elements = programmeScript.elements; + const currentElement = elements[i]; + const newText = prompt('Edit', currentElement.text); + console.log(newText); + if (newText) { + currentElement.text = newText; + elements[i] = currentElement; + programmeScript.elements = elements; + // TODO: save to server + this.setState({ + programmeScript: programmeScript + }); + // TODO: consider using set state function to avoid race condition? if needed? + // this.setState(({ programmeScript }) => { + // return { + // programmeScript: programmeScript + // }; + // }); + } + } + handleAddTranscriptElementToProgrammeScript = (elementType) => { const { programmeScript } = this.state; const elements = this.state.programmeScript.elements; @@ -90,7 +115,7 @@ class ProgramScript extends Component { if (elementType === 'title' || elementType === 'note' || elementType === 'voice-over') { - const text = prompt('Add some text for a section title', 'Section Two'); + const text = prompt('Add some text for a section title', 'Some place holder text'); console.log(text); elements.push({ @@ -475,6 +500,7 @@ class ProgramScript extends Component { programmeScriptElements={ this.state.programmeScript.elements } handleProgrammeScriptOrderChange={ this.handleProgrammeScriptOrderChange } handleDeleteProgrammeScriptElement={ this.handleDeleteProgrammeScriptElement } + handleEditProgrammeScriptElement={ this.handleEditProgrammeScriptElement } /> : null }
  • From af6cce01b14f5a8f73b5881d2d9d880ab52c9910 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Thu, 4 Jul 2019 23:50:20 +0100 Subject: [PATCH 16/55] can now add items at a specific insert point --- .../PaperEdit/ProgramScript/PaperCut.js | 9 +++- .../ProgramScript/ProgrammeScript.js | 20 ++++++--- .../PaperEdit/ProgramScript/index.js | 44 ++++++++++++++++--- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js index 3cb278d6..dfd8854c 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js @@ -17,7 +17,14 @@ class PaperCut extends Component { if (this.props.words) { // TODO could wrap words in span and add timecodes // to make it cliccable on programme script - words = this.props.words.map((w) => {return w.text + ' ';}); + words = this.props.words.map((w) => {return ( + // eslint-disable-next-line react/jsx-key + {w.text} );}); } return ( diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js index 87abe04a..73de762b 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js @@ -16,29 +16,33 @@ import { faGripLines, faGripHorizontal, faPen, - faTrash + faTrash, + faArrowAltCircleLeft, + faArrowAltCircleRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +const InsertPoint = (({ text }) => {text} ); + const DragHandle = sortableHandle(() => ); const SortableItem = sortableElement(({ value, index, type, handleDelete, handleEdit }) => { return (
  • - + - + {value} - + {/* TODO: if paper-cut then don't show edit/pen icon */} - {type !== 'paper-cut' ? { handleEdit(index); } } /> : null} + {type !== 'paper-cut' && type !== 'insert-point' ? { handleEdit(index); } } /> : null} - + {/* TODO: pass a prop to remove element from list */} - {handleDelete(index);} } /> + {type !== 'insert-point' ? {handleDelete(index);} } /> : null}
  • ); }); @@ -81,6 +85,8 @@ class ProgrammeScript extends Component { return { el: , type: el.type }; case 'note': return { el: , type: el.type }; + case 'insert-point': + return { el: , type: el.type }; default: console.error('invalid programme element type'); diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 851a0a6a..198a1921 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -47,8 +47,11 @@ class ProgramScript extends Component { ApiWrapper.getPaperEdit(this.props.projectId, this.props.papereditId) .then((json) => { console.log('get_ProgrammeScriptAndTranscripts--', json); + const programmeScript = json.programmeScript; + // Adding an insert point at the end of the list + programmeScript.elements.push({ type: 'insert-point', text: 'Insert Point to add selection' }); this.setState({ - programmeScript: json.programmeScript + programmeScript: programmeScript }); }); } @@ -145,8 +148,18 @@ class ProgramScript extends Component { // and add a papercut for each to the programme script const { programmeScript } = this.state; const elements = this.state.programmeScript.elements; - // papercut could be abstracted as helper function - elements.push({ + // TODO: insert at insert point + + // find insert point in list, + const insertPointElement = elements.find((el) => { + return el.type === 'insert-point'; + }); + console.log(insertPointElement); + // get insertpoint index + const indexOfInsertPoint = elements.indexOf(insertPointElement); + console.log(indexOfInsertPoint); + // create new element + const newElement = { id: cuid(), index: elements.length, type: 'paper-cut', @@ -156,7 +169,13 @@ class ProgramScript extends Component { words: result.words, transcriptId: result.transcriptId, labelId: [] - }); + }; + // add just above of insert point + // TODO: + // elements[indexOfInsertPoint] = + // papercut could be abstracted as helper function + elements.splice(indexOfInsertPoint, 0, newElement); + // elements.push(newElement); programmeScript.elements = elements; // TODO: save to server this.setState({ @@ -385,6 +404,17 @@ class ProgramScript extends Component { }); } + handleDoubleClickOnProgrammeScript = (e) => { + + if (e.target.className === 'words') { + const wordCurrentTime = e.target.dataset.start; + // TODO: set current time in preview canvas + // Video context probably needs more info like, which clip/track in the sequence? + // investigate how to set currentTime in video context + console.log('wordCurrentTime::', wordCurrentTime); + } + } + render() { return ( @@ -495,12 +525,16 @@ class ProgramScript extends Component {

    -
    +
    { this.state.programmeScript ? : null }
    From 9f08634c8cdee2dcfcc78514c17bc8cb2ddbe540 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Thu, 4 Jul 2019 23:55:04 +0100 Subject: [PATCH 17/55] can use insert point for other programme script elements voice over, notes, titles --- .../PaperEdit/ProgramScript/index.js | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 198a1921..aecc64bb 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -121,12 +121,14 @@ class ProgramScript extends Component { const text = prompt('Add some text for a section title', 'Some place holder text'); console.log(text); - elements.push({ + const indexOfInsertPoint = this.getIndexPositionOfInsertPoint(); + const newElement = { id: cuid(), index: elements.length, type: elementType, text: text - }); + }; + elements.splice(indexOfInsertPoint, 0, newElement); programmeScript.elements = elements; // TODO: save to server this.setState({ @@ -135,6 +137,19 @@ class ProgramScript extends Component { } } + getIndexPositionOfInsertPoint = () => { + const { programmeScript } = this.state; + const elements = programmeScript.elements; + // find insert point in list, + const insertPointElement = elements.find((el) => { + return el.type === 'insert-point'; + }); + // get insertpoint index + const indexOfInsertPoint = elements.indexOf(insertPointElement); + + return indexOfInsertPoint; + } + // TODO: save to server // TODO: needs to handle when selection spans across multiple paragraphs handleAddTranscriptSelectionToProgrammeScript = () => { @@ -147,17 +162,10 @@ class ProgramScript extends Component { // if it's multiple split list of words into multiple groups // and add a papercut for each to the programme script const { programmeScript } = this.state; - const elements = this.state.programmeScript.elements; + const elements = programmeScript.elements; // TODO: insert at insert point - // find insert point in list, - const insertPointElement = elements.find((el) => { - return el.type === 'insert-point'; - }); - console.log(insertPointElement); - // get insertpoint index - const indexOfInsertPoint = elements.indexOf(insertPointElement); - console.log(indexOfInsertPoint); + const indexOfInsertPoint = this.getIndexPositionOfInsertPoint(); // create new element const newElement = { id: cuid(), @@ -170,12 +178,8 @@ class ProgramScript extends Component { transcriptId: result.transcriptId, labelId: [] }; - // add just above of insert point - // TODO: - // elements[indexOfInsertPoint] = - // papercut could be abstracted as helper function + // add element just above of insert point elements.splice(indexOfInsertPoint, 0, newElement); - // elements.push(newElement); programmeScript.elements = elements; // TODO: save to server this.setState({ From e32ef1dec2535ee35850c3343c959e734dc2a74f Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Sat, 6 Jul 2019 17:05:01 +0100 Subject: [PATCH 18/55] can now select mutiple paragraphs to add to programme script added some unit tests for it, updated video context to patch audio glitch --- package-lock.json | 6 +- package.json | 2 +- src/App.test.js | 5 +- .../PaperEdit/ProgramScript/PaperCut.js | 4 +- .../ProgramScript/ProgrammeScript.js | 4 +- .../index.js | 53 +++ .../index.test.js | 56 +++ .../mock-expected.sample.json | 337 +++++++++++++++++ .../mock.sample.json | 351 ++++++++++++++++++ ...last_word_in_a_paragraph_alone.sample.json | 351 ++++++++++++++++++ .../mock_one_paragraph.sample.json | 169 +++++++++ .../get-data-from-user-selection.js | 8 +- .../PaperEdit/ProgramScript/index.js | 69 +++- 13 files changed, 1385 insertions(+), 30 deletions(-) create mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.js create mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.test.js create mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock-expected.sample.json create mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock.sample.json create mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_a_last_word_in_a_paragraph_alone.sample.json create mode 100644 src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_one_paragraph.sample.json diff --git a/package-lock.json b/package-lock.json index a093acaf..208ebbec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13223,9 +13223,9 @@ } }, "videocontext": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/videocontext/-/videocontext-0.53.0.tgz", - "integrity": "sha512-N6BBRdJ5wq7Xqq/xWkWLNEk8PEmJXbyeaahz9Apy3970y9uBoaLeEvpi4RGUCGxHHt9IEHAnGvli4bT9LLGlHw==", + "version": "0.53.1", + "resolved": "https://registry.npmjs.org/videocontext/-/videocontext-0.53.1.tgz", + "integrity": "sha512-G9TRc+MZoqsuNAedXYEKZnkAFR6jHFlS0+HxayXrS9ZeYDkX4H4sd2M2SGDQ4Khv4hlBJJgFoxRsYhxLSsBPSw==", "requires": { "regenerator-runtime": "^0.11.1" }, diff --git a/package.json b/package.json index cc250720..6bd2ae36 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "react-scripts": "3.0.1", "react-select": "^2.4.3", "react-sortable-hoc": "^1.9.1", - "videocontext": "^0.53.0" + "videocontext": "^0.53.1" }, "author": "Pietro Passarelli CC0 BBC 2019", "contributors": [ diff --git a/src/App.test.js b/src/App.test.js index f3fe19ab..b5999c39 100755 --- a/src/App.test.js +++ b/src/App.test.js @@ -1,8 +1,9 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import App from './App'; +// window.env.API_URL = 'test'; +// import App from './App'; // TypeError: Cannot read property 'API_URL' of undefined - in ApiWrapper -xit('renders without crashing', () => { +test.skip('renders without crashing', () => { const div = document.createElement('div'); ReactDOM.render(, div); ReactDOM.unmountComponentAtNode(div); diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js index dfd8854c..d288ebd7 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js @@ -30,8 +30,8 @@ class PaperCut extends Component { return ( <> - - {this.props.speaker} + + {this.props.speaker.toUpperCase()} {/*
    */} {/* 00:01:20 */} {/*
    */} diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js index 73de762b..e3c809fb 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js @@ -14,7 +14,6 @@ import Note from './Note'; import { faGripLines, - faGripHorizontal, faPen, faTrash, faArrowAltCircleLeft, @@ -22,7 +21,7 @@ import { } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -const InsertPoint = (({ text }) => {text} ); +const InsertPoint = (({ text }) => {text} ); const DragHandle = sortableHandle(() => ); @@ -43,6 +42,7 @@ const SortableItem = sortableElement(({ value, index, type, handleDelete, handle {/* TODO: pass a prop to remove element from list */} {type !== 'insert-point' ? {handleDelete(index);} } /> : null} + {type === 'insert-point' ? : null}
    ); }); diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.js new file mode 100644 index 00000000..a392792c --- /dev/null +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.js @@ -0,0 +1,53 @@ +// if the speaker of all the words is the same we can assume is one paragraph +const isOneParagraph = words => { + const firstword = words[0]; + + const result = words.filter(word => { + return word.speaker !== firstword.speaker; + }); + + return result.length === 0; +}; + +/** + * helper function to determine if an element is last one in a list + * based on the index + */ +const isLastElement = (elementIndex, list) => { + return elementIndex === (list.length - 1); +}; +const divideWordsSelectionsIntoParagraphs = words => { + if (isOneParagraph(words)) { + return words; + } + // initialising previous word speaker with speaker of first word + let previousWordSpeaker = words[0].speaker; + let currentParagraph = []; + const paragraphsResult = []; + + words.forEach((word, index) => { + if (word.speaker === previousWordSpeaker) { + currentParagraph.push(word); + } else { + paragraphsResult.push(currentParagraph); + currentParagraph = []; + // if (isLastElement(index, words)) { + currentParagraph.push(word); + // } + + previousWordSpeaker = word.speaker; + } + + // Handling last paragraph + if (isLastElement(index, words)) { + // currentParagraph.push(word); + paragraphsResult.push(currentParagraph); + } + }); + + return paragraphsResult; + // return paragraphsResult.reverse(); +}; + +// divideWordsSelectionsIntoParagraphs(result.words); +export { divideWordsSelectionsIntoParagraphs, isOneParagraph }; diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.test.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.test.js new file mode 100644 index 00000000..5c8fde94 --- /dev/null +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/index.test.js @@ -0,0 +1,56 @@ +import { + divideWordsSelectionsIntoParagraphs, + isOneParagraph +} from './index.js'; +import mockData from './mock.sample.json'; +import mockDataOneParagraph from './mock_one_paragraph.sample.json'; +import mockDataALastWordInAParagraphAlone from './mock_a_last_word_in_a_paragraph_alone.sample.json'; + +describe("detect if it's one paragraph or not", () => { + test('recognise when is one paragraph', () => { + const result = isOneParagraph(mockDataOneParagraph.words); + expect(result).toBe(true); + }); + + test('recognise when is not one paragraph', () => { + const result = isOneParagraph(mockData.words); + expect(result).toBe(false); + }); +}); + +describe('split into pragraphs', () => { + test('split into correct number of pragraph', () => { + const result = divideWordsSelectionsIntoParagraphs(mockData.words); + expect(result.length).toBe(3); + }); + +}); + +describe('detect if it\'s one paragraph or not', () => { + + test('retains the initial number of words after the split into paragraphs', () => { + const initialNumberOfWords = mockData.words.length; + const result = divideWordsSelectionsIntoParagraphs(mockData.words); + // https://stackoverflow.com/questions/16468124/count-values-of-the-inner-two-dimensional-array-javascript + const numberOfWordsAfterDivide = result.reduce( + (count, row) => count + row.length, + 0 + ); + expect(numberOfWordsAfterDivide).toBe(initialNumberOfWords); + }); + + test("retains the initial number of words after the split into paragraphs - even when there's a last paragraph with just one word at the end", () => { + const initialNumberOfWords = mockDataALastWordInAParagraphAlone.words.length; + const result = divideWordsSelectionsIntoParagraphs( + mockDataALastWordInAParagraphAlone.words + ); + // https://stackoverflow.com/questions/16468124/count-values-of-the-inner-two-dimensional-array-javascript + const numberOfWordsAfterDivide = result.reduce((count, row) => count + row.length, 0); + expect(numberOfWordsAfterDivide).toBe(initialNumberOfWords); + }); +}); + +test.skip('split - TBC', () => { + const result = divideWordsSelectionsIntoParagraphs(mockData.words); + expect(result.length).toBe(3); +}); diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock-expected.sample.json b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock-expected.sample.json new file mode 100644 index 00000000..a40fa725 --- /dev/null +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock-expected.sample.json @@ -0,0 +1,337 @@ +[ + [ + { + "start": "34.51", + "end": "34.7", + "text": "had", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.7", + "end": "34.81", + "text": "an", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.81", + "end": "34.97", + "text": "infra", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.97", + "end": "35.32", + "text": "red", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "35.31", + "end": "35.97", + "text": "camera", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.45", + "end": "36.61", + "text": "and", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.64", + "end": "36.79", + "text": "one", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.79", + "end": "36.87", + "text": "of", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.87", + "end": "36.98", + "text": "the", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.98", + "end": "37.22", + "text": "things", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.22", + "end": "37.33", + "text": "that", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.33", + "end": "37.53", + "text": "had", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.53", + "end": "37.69", + "text": "was", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.69", + "end": "37.83", + "text": "a", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.95", + "end": "38.39", + "text": "tilt", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "38.39", + "end": "39.01", + "text": "sensor", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "39.24", + "end": "39.51", + "text": "so", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "39.51", + "end": "39.61", + "text": "it", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + } + ], + [ + { + "start": "31.93", + "end": "32.12", + "text": "had", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.12", + "end": "32.45", + "text": "more", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.45", + "end": "32.76", + "text": "orders", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.76", + "end": "32.92", + "text": "and", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.92", + "end": "33.18", + "text": "touch", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "33.18", + "end": "33.88", + "text": "sensors", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + } + ], + [ + { + "start": "23.45", + "end": "23.82", + "text": "all", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.2", + "end": "24.6", + "text": "that", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.65", + "end": "24.84", + "text": "he'd", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.86", + "end": "25.3", + "text": "ordered", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.3", + "end": "25.42", + "text": "and", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.42", + "end": "25.49", + "text": "i", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.49", + "end": "25.66", + "text": "was", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.66", + "end": "25.88", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.88", + "end": "26.49", + "text": "excited", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.49", + "end": "26.82", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.82", + "end": "27.04", + "text": "it", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "27.04", + "end": "27.77", + "text": "because", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.35", + "end": "28.47", + "text": "i've", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.59", + "end": "28.79", + "text": "always", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.79", + "end": "29.03", + "text": "loved", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.09", + "end": "29.6", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.8", + "end": "30.04", + "text": "this", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.04", + "end": "30.2", + "text": "one", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.2", + "end": "30.46", + "text": "has", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.46", + "end": "30.76", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.76", + "end": "30.96", + "text": "caught", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.96", + "end": "31.34", + "text": "technical", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.34", + "end": "31.8", + "text": "features", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + } + ] + ] \ No newline at end of file diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock.sample.json b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock.sample.json new file mode 100644 index 00000000..0ae41c04 --- /dev/null +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock.sample.json @@ -0,0 +1,351 @@ +{ + "start": 23.03, + "end": 39.61, + "transcriptId": "19cjw29xii80000ird74yb19swa", + "speaker": "TBC 2", + "words": [ + { + "start": "23.45", + "end": "23.82", + "text": "all", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.2", + "end": "24.6", + "text": "that", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.65", + "end": "24.84", + "text": "he'd", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.86", + "end": "25.3", + "text": "ordered", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.3", + "end": "25.42", + "text": "and", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.42", + "end": "25.49", + "text": "i", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.49", + "end": "25.66", + "text": "was", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.66", + "end": "25.88", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.88", + "end": "26.49", + "text": "excited", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.49", + "end": "26.82", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.82", + "end": "27.04", + "text": "it", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "27.04", + "end": "27.77", + "text": "because", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.35", + "end": "28.47", + "text": "i've", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.59", + "end": "28.79", + "text": "always", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.79", + "end": "29.03", + "text": "loved", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.09", + "end": "29.6", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.8", + "end": "30.04", + "text": "this", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.04", + "end": "30.2", + "text": "one", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.2", + "end": "30.46", + "text": "has", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.46", + "end": "30.76", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.76", + "end": "30.96", + "text": "caught", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.96", + "end": "31.34", + "text": "technical", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.34", + "end": "31.8", + "text": "features", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.8", + "end": "31.93", + "text": "it", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.93", + "end": "32.12", + "text": "had", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.12", + "end": "32.45", + "text": "more", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.45", + "end": "32.76", + "text": "orders", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.76", + "end": "32.92", + "text": "and", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.92", + "end": "33.18", + "text": "touch", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "33.18", + "end": "33.88", + "text": "sensors", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.27", + "end": "34.51", + "text": "it", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.51", + "end": "34.7", + "text": "had", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.7", + "end": "34.81", + "text": "an", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.81", + "end": "34.97", + "text": "infra", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.97", + "end": "35.32", + "text": "red", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "35.31", + "end": "35.97", + "text": "camera", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.45", + "end": "36.61", + "text": "and", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.64", + "end": "36.79", + "text": "one", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.79", + "end": "36.87", + "text": "of", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.87", + "end": "36.98", + "text": "the", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.98", + "end": "37.22", + "text": "things", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.22", + "end": "37.33", + "text": "that", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.33", + "end": "37.53", + "text": "had", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.53", + "end": "37.69", + "text": "was", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.69", + "end": "37.83", + "text": "a", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.95", + "end": "38.39", + "text": "tilt", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "38.39", + "end": "39.01", + "text": "sensor", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "39.24", + "end": "39.51", + "text": "so", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "39.51", + "end": "39.61", + "text": "it", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + } + ] +} \ No newline at end of file diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_a_last_word_in_a_paragraph_alone.sample.json b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_a_last_word_in_a_paragraph_alone.sample.json new file mode 100644 index 00000000..0193a2b7 --- /dev/null +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_a_last_word_in_a_paragraph_alone.sample.json @@ -0,0 +1,351 @@ +{ + "start": 23.03, + "end": 39.61, + "transcriptId": "19cjw29xii80000ird74yb19swa", + "speaker": "TBC 2", + "words": [ + { + "start": "23.45", + "end": "23.82", + "text": "all", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.2", + "end": "24.6", + "text": "that", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.65", + "end": "24.84", + "text": "he'd", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.86", + "end": "25.3", + "text": "ordered", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.3", + "end": "25.42", + "text": "and", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.42", + "end": "25.49", + "text": "i", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.49", + "end": "25.66", + "text": "was", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.66", + "end": "25.88", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.88", + "end": "26.49", + "text": "excited", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.49", + "end": "26.82", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.82", + "end": "27.04", + "text": "it", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "27.04", + "end": "27.77", + "text": "because", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.35", + "end": "28.47", + "text": "i've", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.59", + "end": "28.79", + "text": "always", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.79", + "end": "29.03", + "text": "loved", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.09", + "end": "29.6", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.8", + "end": "30.04", + "text": "this", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.04", + "end": "30.2", + "text": "one", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.2", + "end": "30.46", + "text": "has", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.46", + "end": "30.76", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.76", + "end": "30.96", + "text": "caught", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.96", + "end": "31.34", + "text": "technical", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.34", + "end": "31.8", + "text": "features", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.8", + "end": "31.93", + "text": "it", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.93", + "end": "32.12", + "text": "had", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.12", + "end": "32.45", + "text": "more", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.45", + "end": "32.76", + "text": "orders", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.76", + "end": "32.92", + "text": "and", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "32.92", + "end": "33.18", + "text": "touch", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "33.18", + "end": "33.88", + "text": "sensors", + "speaker": "TBC 4", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.27", + "end": "34.51", + "text": "it", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.51", + "end": "34.7", + "text": "had", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.7", + "end": "34.81", + "text": "an", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.81", + "end": "34.97", + "text": "infra", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "34.97", + "end": "35.32", + "text": "red", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "35.31", + "end": "35.97", + "text": "camera", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.45", + "end": "36.61", + "text": "and", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.64", + "end": "36.79", + "text": "one", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.79", + "end": "36.87", + "text": "of", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.87", + "end": "36.98", + "text": "the", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "36.98", + "end": "37.22", + "text": "things", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.22", + "end": "37.33", + "text": "that", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.33", + "end": "37.53", + "text": "had", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.53", + "end": "37.69", + "text": "was", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.69", + "end": "37.83", + "text": "a", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "37.95", + "end": "38.39", + "text": "tilt", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "38.39", + "end": "39.01", + "text": "sensor", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "39.24", + "end": "39.51", + "text": "so", + "speaker": "TBC 5", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "39.51", + "end": "39.61", + "text": "it", + "speaker": "TBC 6", + "transcriptId": "19cjw29xii80000ird74yb19swa" + } + ] + } \ No newline at end of file diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_one_paragraph.sample.json b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_one_paragraph.sample.json new file mode 100644 index 00000000..83f7a40d --- /dev/null +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/divide-words-selections-into-paragraphs/mock_one_paragraph.sample.json @@ -0,0 +1,169 @@ +{ + "start": 23.03, + "end": 39.61, + "transcriptId": "19cjw29xii80000ird74yb19swa", + "speaker": "TBC 2", + "words": [ + { + "start": "23.45", + "end": "23.82", + "text": "all", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.2", + "end": "24.6", + "text": "that", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.65", + "end": "24.84", + "text": "he'd", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "24.86", + "end": "25.3", + "text": "ordered", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.3", + "end": "25.42", + "text": "and", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.42", + "end": "25.49", + "text": "i", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.49", + "end": "25.66", + "text": "was", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.66", + "end": "25.88", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "25.88", + "end": "26.49", + "text": "excited", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.49", + "end": "26.82", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "26.82", + "end": "27.04", + "text": "it", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "27.04", + "end": "27.77", + "text": "because", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.35", + "end": "28.47", + "text": "i've", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.59", + "end": "28.79", + "text": "always", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "28.79", + "end": "29.03", + "text": "loved", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.09", + "end": "29.6", + "text": "about", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "29.8", + "end": "30.04", + "text": "this", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.04", + "end": "30.2", + "text": "one", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.2", + "end": "30.46", + "text": "has", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.46", + "end": "30.76", + "text": "really", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.76", + "end": "30.96", + "text": "caught", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "30.96", + "end": "31.34", + "text": "technical", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + }, + { + "start": "31.34", + "end": "31.8", + "text": "features", + "speaker": "test", + "transcriptId": "19cjw29xii80000ird74yb19swa" + } + ] +} \ No newline at end of file diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/get-data-from-user-selection.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/get-data-from-user-selection.js index 02fe8d0f..3b530277 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/get-data-from-user-selection.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/get-data-from-user-selection.js @@ -10,7 +10,11 @@ function parseWordElDataset(wordEl) { return { start: wordEl.dataset.start, end: wordEl.dataset.end, - text: wordEl.dataset.text, + // you could also get the word from wordEl.dataset.text + // but the word there is lowercase and without punctuation coz is used + // for the search functionality so using innerText + // to preserve punctuation and capitalization + text: wordEl.innerText, speaker: wordEl.dataset.speaker, transcriptId: wordEl.dataset.transcriptId }; @@ -30,7 +34,9 @@ function getDataFromUserWordsSelection(e) { // Seems like this work no matter if the selection is made left to right // or right to left form the user const words = selectedRange.querySelectorAll('.words'); + if (words.length !== 0) { + // TODO: remove window.words, it's for troubleshooting window.words = words; return { diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index aecc64bb..1ac90f51 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -23,6 +23,7 @@ import { import timecodes from 'node-timecodes'; import ProgrammeScript from './ProgrammeScript.js'; import getDataFromUserWordsSelection from './get-data-from-user-selection.js'; +import { divideWordsSelectionsIntoParagraphs, isOneParagraph } from './divide-words-selections-into-paragraphs/index.js'; import ApiWrapper from '../../../../ApiWrapper/index.js'; class ProgramScript extends Component { @@ -36,9 +37,9 @@ class ProgramScript extends Component { // start - is relative to timeline // duration - of clip in playlist // sourceStart - time from start of clip in playlist - { type:'video', start:0, sourceStart: 30, duration:10, src:'https://download.ted.com/talks/MorganVague_2018X.mp4' }, - { type:'video', start:10, sourceStart: 40, duration:10, src:'https://download.ted.com/talks/IvanPoupyrev_2019.mp4' }, - { type:'video', start:20, sourceStart: 50, duration:10, src:'https://download.ted.com/talks/KateDarling_2018S-950k.mp4' }, + // { type:'video', start:0, sourceStart: 30, duration:10, src:'https://download.ted.com/talks/MorganVague_2018X.mp4' }, + // { type:'video', start:10, sourceStart: 40, duration:10, src:'https://download.ted.com/talks/IvanPoupyrev_2019.mp4' }, + // { type:'video', start:20, sourceStart: 50, duration:10, src:'https://download.ted.com/talks/KateDarling_2018S-950k.mp4' }, ] }; } @@ -52,8 +53,14 @@ class ProgramScript extends Component { programmeScript.elements.push({ type: 'insert-point', text: 'Insert Point to add selection' }); this.setState({ programmeScript: programmeScript - }); + } + // TODO: figure out how to update preview + // , () => { + // this.handleUpdatePreview(); + // } + ); }); + } // TODO: save to server @@ -157,6 +164,7 @@ class ProgramScript extends Component { console.log('getDataFromUserWordsSelection::', result); if (result) { console.log(JSON.stringify(result, null, 2)); + // result.words // TODO: if there's just one speaker in selection do following // if it's multiple split list of words into multiple groups @@ -166,21 +174,44 @@ class ProgramScript extends Component { // TODO: insert at insert point const indexOfInsertPoint = this.getIndexPositionOfInsertPoint(); - // create new element - const newElement = { - id: cuid(), - index: elements.length, - type: 'paper-cut', - start:result.start, - end: result.end, - speaker: result.speaker, - words: result.words, - transcriptId: result.transcriptId, - labelId: [] - }; - // add element just above of insert point - elements.splice(indexOfInsertPoint, 0, newElement); - programmeScript.elements = elements; + if (isOneParagraph(result.words)) { + // create new element + // TODO: Create new element could be refactored into helper function + const newElement = { + id: cuid(), + index: elements.length, + type: 'paper-cut', + start:result.start, + end: result.end, + speaker: result.speaker, + words: result.words, + transcriptId: result.transcriptId, + labelId: [] + }; + // add element just above of insert point + elements.splice(indexOfInsertPoint, 0, newElement); + programmeScript.elements = elements; + } + else { + const paragraphs = divideWordsSelectionsIntoParagraphs(result.words); + paragraphs.reverse().forEach((paragraph) => { + const newElement = { + id: cuid(), + index: elements.length, + type: 'paper-cut', + start:paragraph[0].start, + end: paragraph[paragraph.length - 1].end, + speaker: paragraph[0].speaker, + words: paragraph, + transcriptId: paragraph[0].transcriptId, + // TODO: ignoring labels for now + labelId: [] + }; + // add element just above of insert point + elements.splice(indexOfInsertPoint, 0, newElement); + programmeScript.elements = elements; + }); + } // TODO: save to server this.setState({ programmeScript: programmeScript From c0ae32d49812d5c577876ac41c0cf558c6bb8612 Mon Sep 17 00:00:00 2001 From: Pietro Passarelli - News Labs Date: Sat, 6 Jul 2019 22:02:48 +0100 Subject: [PATCH 19/55] adjusted layout + ui tweaked layout proportion for transcript - programme script view on/off added timecode info in speaker on hover, and removed from transcript, can now click on speaker to jump to corresponding point in media, in transcript --- .../PaperEdit/ProgramScript/PaperCut.js | 7 ++++++- .../ProgramScript/ProgrammeScript.js | 16 ++++++++------- .../PaperEdit/ProgramScript/index.js | 11 +++++++--- .../PaperEdit/Transcripts/Transcript.js | 8 +++++--- .../PaperEdits/PaperEdit/Transcripts/index.js | 9 +++++++-- src/Components/PaperEdits/PaperEdit/index.js | 18 ++++++++--------- .../generate-paragraphs/Paragraph.js | 20 ++++++++++++------- .../Transcripts/TranscriptAnnotate/index.js | 2 +- 8 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js index d288ebd7..35c31132 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/PaperCut.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; +import { shortTimecode } from '@bbc/react-transcript-editor/timecodeConverter'; // import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; // import { faTag } from '@fortawesome/free-solid-svg-icons'; @@ -30,7 +31,11 @@ class PaperCut extends Component { return ( <> - + {this.props.speaker.toUpperCase()} {/*
    */} {/* 00:01:20 */} diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js index e3c809fb..d700319a 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/ProgrammeScript.js @@ -28,27 +28,29 @@ const DragHandle = sortableHandle(() => { return (
  • - + - + {value} - + {/* TODO: if paper-cut then don't show edit/pen icon */} {type !== 'paper-cut' && type !== 'insert-point' ? { handleEdit(index); } } /> : null} - + {/* TODO: pass a prop to remove element from list */} {type !== 'insert-point' ? {handleDelete(index);} } /> : null} {type === 'insert-point' ? : null} -
  • ); +
    + ); }); const SortableContainer = sortableContainer(({ children }) => { - return
      {children}
    ; + + return
      {children}
    ; }); class ProgrammeScript extends Component { @@ -82,7 +84,7 @@ class ProgrammeScript extends Component { case 'voice-over': return { el:, type: el.type }; case 'paper-cut': - return { el: , type: el.type }; + return { el: , type: el.type }; case 'note': return { el: , type: el.type }; case 'insert-point': diff --git a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js index 1ac90f51..a24b9051 100644 --- a/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js +++ b/src/Components/PaperEdits/PaperEdit/ProgramScript/index.js @@ -375,7 +375,7 @@ class ProgramScript extends Component { result += `[ ${ event.text }]\n\n`; } else if (event.type === 'paper-cut') { - result += `${ timecodes.fromSeconds(event.startTime) }\t${ timecodes.fromSeconds(event.endTime) }\t${ event.speaker }\t-\t${ event.clipName }\n${ event.words.map((word) => {return word.text;}).join(' ') }\n\n`; + result += `${ timecodes.fromSeconds(event.startTime) }\t${ timecodes.fromSeconds(event.endTime) }\t${ event.speaker }\t-\t${ event.clipName } \n${ event.words.map((word) => {return word.text;}).join(' ') }\n\n`; } }); @@ -453,9 +453,14 @@ class ProgramScript extends Component { render() { return ( -

    Programme: +

    + {/* Programme: */} + {/* */} {this.state.programmeScript ? this.state.programmeScript.title : ''} -

    + {/*
    */} +

    {/*
    */} { !this.state.resetPreview ? diff --git a/src/Components/PaperEdits/PaperEdit/Transcripts/Transcript.js b/src/Components/PaperEdits/PaperEdit/Transcripts/Transcript.js index 1617687b..2f99007b 100644 --- a/src/Components/PaperEdits/PaperEdit/Transcripts/Transcript.js +++ b/src/Components/PaperEdits/PaperEdit/Transcripts/Transcript.js @@ -57,9 +57,8 @@ class Transcript extends Component { // functions repeadrted from TranscriptAnnotate/index.js handleTimecodeClick= e => { - if ( e.target.className === 'timecode') { + if (e.target.classList.contains('timecode')) { const wordEl = e.target; - console.log('handleTimecodeClick', wordEl.dataset.start); this.videoRef.current.currentTime = wordEl.dataset.start; this.videoRef.current.play(); } @@ -189,7 +188,10 @@ class Transcript extends Component { {`${ this.state.sentenceToSearchCSS } { background-color: ${ 'yellow' }; text-shadow: 0 0 0.01px black }`} {`${ this.state.sentenceToSearchCSSInHighlights } { background-color: ${ 'yellow' }; text-shadow: 0 0 0.01px black }`} -

    +

    {/* */} {this.props.title}

    diff --git a/src/Components/PaperEdits/PaperEdit/Transcripts/index.js b/src/Components/PaperEdits/PaperEdit/Transcripts/index.js index aa985b7d..118a6cef 100644 --- a/src/Components/PaperEdits/PaperEdit/Transcripts/index.js +++ b/src/Components/PaperEdits/PaperEdit/Transcripts/index.js @@ -19,11 +19,11 @@ class Transcripts extends Component { const transcriptsElNav = this.props.transcripts.map((transcript, index) => { return ( - { transcript.status === 'in-progress' ? : '' } { transcript.status === 'error' ? : '' } @@ -54,7 +54,12 @@ class Transcripts extends Component { > -

    Transcripts

    +

    + Transcripts