diff --git a/package-lock.json b/package-lock.json index 25b56af..eea852a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2861,6 +2861,11 @@ "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", "dev": true }, + "array-move": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-move/-/array-move-2.1.0.tgz", + "integrity": "sha512-BXEIud+F7/ech2HcSfo+6bpgSCRlNnVTqQhGKdMov9iJkHq+vu9IP9qRXDpZvQpc1WWpDLiEfjs6Lfvvac+fDA==" + }, "array-reduce": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", @@ -12285,6 +12290,16 @@ "throttle-debounce": "^2.1.0" } }, + "react-sortable-hoc": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.10.1.tgz", + "integrity": "sha512-eVyv5rrK6qY9bG60bboRY78In7OpdRRg+hxp4QMLIjC/UJaFSU7exTYd0764GtXvBqh+b+faYGzren5/ffRYKw==", + "requires": { + "@babel/runtime": "^7.2.0", + "invariant": "^2.2.4", + "prop-types": "^15.5.7" + } + }, "react-syntax-highlighter": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-8.1.0.tgz", diff --git a/package.json b/package.json index 7ee9ebc..6411016 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@fortawesome/free-brands-svg-icons": "^5.8.2", "@fortawesome/free-solid-svg-icons": "^5.10.1", "@fortawesome/react-fontawesome": "^0.1.4", + "array-move": "^2.1.0", "bootstrap": "^4.3.1", "bootstrap-css-only": "^4.3.1", "chroma-js": "^2.0.3", @@ -47,6 +48,7 @@ "react-router-bootstrap": "^0.25.0", "react-router-dom": "^5.0.1", "react-select": "^2.4.3", + "react-sortable-hoc": "^1.10.1", "sass-loader": "^7.1.0", "save": "^2.4.0", "style-loader": "^0.23.1", diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/Note.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/Note.js new file mode 100644 index 0000000..a20152f --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/Note.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faStickyNote } from '@fortawesome/free-solid-svg-icons'; +import PropTypes from 'prop-types'; + +const Note = (props) => ( +

+ { props.text } +

+); + +Note.propTypes = { + text: PropTypes.any +}; + +export default Note; diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/PaperCut.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/PaperCut.js new file mode 100644 index 0000000..dc0d551 --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/PaperCut.js @@ -0,0 +1,52 @@ +import React from 'react'; +import cuid from 'cuid'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import PropTypes from 'prop-types'; + +const PaperCut = (props) => { + let words; + if (props.words) { + // TODO could wrap words in span and add timecodes + // to make it cliccable on programme script + words = props.words.map((w) => { + return ( + + {w.text} + + ); + }); + } + + return ( + + + {props.speaker.toUpperCase()} + {/*
*/} + {/* 00:01:20 */} + {/*
*/} + {/* TagExample */} + + + { words } + +
+ ); +}; + +PaperCut.propTypes = { + speaker: PropTypes.any, + words: PropTypes.any +}; + +export default PaperCut; diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/SortableHandle.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/SortableHandle.js new file mode 100644 index 0000000..3c0ce91 --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/SortableHandle.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { + sortableHandle +} from 'react-sortable-hoc'; + +import { + faGripLines, +} from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +const SortableHandle = sortableHandle(() => ( + + + ) +); + +export default SortableHandle; \ No newline at end of file diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/SortableItem.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/SortableItem.js new file mode 100644 index 0000000..dc7b76b --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/SortableItem.js @@ -0,0 +1,60 @@ +import React from 'react'; +import { SortableElement } from 'react-sortable-hoc'; + +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; + +import { + faPen, + faTrash, +} from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +import SortableHandle from './SortableHandle'; + +const SortableItem = SortableElement(({ value, handleFns, colourOpts }) => { + + const EditIcon = ( + + + ); + + const DeleteIcon = ( + + + ); + + return ( +
  • + + + + + + + {value} + + + + {handleFns.edit ? EditIcon : null} + + + {handleFns.delete ? DeleteIcon : null} + + +
  • + ); +}); + +SortableItem.defaultProps = { + colourOpts: {}, + handleFns: {} +}; + +export default SortableItem; diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/TitleHeading.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/TitleHeading.js new file mode 100644 index 0000000..c2e0701 --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/TitleHeading.js @@ -0,0 +1,5 @@ +import React from 'react'; + +const TitleHeading = ({ text }) =>

    {text}

    ; + +export default TitleHeading; diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/VoiceOver.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/VoiceOver.js new file mode 100644 index 0000000..87d42af --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/VoiceOver.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faMicrophoneAlt } from '@fortawesome/free-solid-svg-icons'; + +const VoiceOver = ({ text }) => +

    + + { text } +

    ; + +export default VoiceOver; diff --git a/packages/components/ProgrammeScriptContainer/ProgrammeElements/index.js b/packages/components/ProgrammeScriptContainer/ProgrammeElements/index.js new file mode 100644 index 0000000..bb9c6d3 --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/ProgrammeElements/index.js @@ -0,0 +1,83 @@ +import React from 'react'; +import cuid from 'cuid'; + +import VoiceOver from './VoiceOver'; +import PaperCut from './PaperCut'; +import TitleHeading from './TitleHeading'; +import Note from './Note'; + +import SortableItem from './SortableItem'; + +const adaptAddedElement = (type, text) => { + switch (type) { + case 'title': + return ; + case 'voice-over': + return ; + case 'note': + return ; + default: + console.error('invalid added element type: ', type, text); + + return null; + } +}; + +const ProgrammeElements = (elements, handleEdit, handleDelete) => { + + return elements.map((el, index) => { + const key = cuid(); + const type = el.type; + const text = el.text; + + const handleFns = { + edit: () => { handleEdit(index);}, + delete: () => { handleDelete(index);} + }; + + if (type === 'insert') { + const colourOpts = { + background: 'orange', + text: 'white' + }; + + return ( + + ); + + } + + if (type === 'paper-cut') { + handleFns.edit = null; + + return ( + + } + handleFns={ handleFns } + />); + } + + return ( + + ); + }); +}; + +export default ProgrammeElements; diff --git a/packages/components/ProgrammeScriptContainer/index.js b/packages/components/ProgrammeScriptContainer/index.js new file mode 100644 index 0000000..9f48a92 --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/index.js @@ -0,0 +1,38 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import arrayMove from 'array-move'; +import { SortableContainer, } from 'react-sortable-hoc'; +import ProgrammeElements from './ProgrammeElements'; + +const ProgrammeScriptContainer = (props) => { + const programmeElements = ProgrammeElements(props.items, props.handleEdit, props.handleDelete); + const [ elements, setElements ] = useState(programmeElements); + + const onSortEnd = ({ oldIndex, newIndex }) => { + const result = arrayMove(elements, oldIndex, newIndex); + props.handleReorder(result); + setElements(result); + }; + + const SortableList = SortableContainer(({ children }) => +
      + {children} +
    + ); + + return ( + + {elements} + + ); + +}; + +ProgrammeScriptContainer.propTypes = { + items: PropTypes.any, + handleDelete: PropTypes.func, + handleEdit: PropTypes.func, + handleReorder: PropTypes.func +}; + +export default ProgrammeScriptContainer; diff --git a/packages/components/ProgrammeScriptContainer/stories/index.stories.js b/packages/components/ProgrammeScriptContainer/stories/index.stories.js new file mode 100644 index 0000000..482d992 --- /dev/null +++ b/packages/components/ProgrammeScriptContainer/stories/index.stories.js @@ -0,0 +1,50 @@ +import React from 'react'; + +import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import ProgrammeScriptContainer from '../index.js'; + +export const handleReorderActions = action('Handle reorder'); +export const handleDeleteActions = action('Handle delete'); +export const handleEditActions = action('Handle edit'); + +const items = [ + { + type: 'title', + text: 'An immense Achievement' + }, + { + type: 'paper-cut', + id: 1, + speaker: 'Mr Loud', + words: [ { text:'Greatest day of my life was when I wrote this text.', start: 0, end: 1 } ] + }, + { + type: 'note', + text: 'Maybe a little bit obnoxious' + }, + { + type: 'insert', + text: 'Insert New Selection here' + }, + { + type: 'paper-cut', + id: 2, + speaker: 'Mrs Loud', + words: [ { text:'Greatest day of my life was when I spoke this text.', start: 0, end: 1 } ] + }, + { + type: 'voice-over', + text: 'link: wonderful times of the Loud family' + }, +]; + +storiesOf('ProgrammeScript', module) + .add('Default', () => + + ); diff --git a/packages/components/SimpleCard/index.js b/packages/components/SimpleCard/index.js index 9a52354..536f9dc 100644 --- a/packages/components/SimpleCard/index.js +++ b/packages/components/SimpleCard/index.js @@ -17,9 +17,13 @@ const SimpleCard = (props) => { const confirmDeleteText = "Click OK if you wish to delete or cancel if you don't"; const cancelDeleteText = 'All is good, it was not deleted'; const confirmationPrompt = window.confirm(confirmDeleteText); - + if (confirmationPrompt) { - props.handleDelete ? props.handleDelete(props.id) : alert(cancelDeleteText); + if (props.handleDelete) { + props.handleDelete(props.id); + } else { + alert(cancelDeleteText); + } } };