|
@@ -4,7 +4,7 @@ import './App.css';
|
|
|
import Select from 'react-select/async'
|
|
|
import {sortableContainer, sortableElement} from 'react-sortable-hoc';
|
|
|
import Dropzone from 'react-dropzone'
|
|
|
-import {buildAST, toReact} from 'mdast';
|
|
|
+import {buildAST, toReact, getTimeCodes, getTimeCodeFromSeconds} from 'mdast';
|
|
|
|
|
|
import { GraphQLClient } from 'graphql-request';
|
|
|
|
|
@@ -14,6 +14,12 @@ import AceEditor from 'react-ace';
|
|
|
import "ace-builds/src-noconflict/mode-markdown";
|
|
|
import "ace-builds/src-noconflict/theme-github";
|
|
|
|
|
|
+Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
|
|
|
+ get: function(){
|
|
|
+ return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2);
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
|
|
|
let gql;
|
|
|
|
|
@@ -386,22 +392,64 @@ const arrayMove = (arr, newIndex, oldIndex) => {
|
|
|
const withoutOld = arr.filter((item, i) => i !== oldIndex)
|
|
|
return [...withoutOld.slice(0, newIndex), arr[oldIndex], ...withoutOld.slice(newIndex)]
|
|
|
}
|
|
|
-const MDEdit = ({children, field, ...props}) =>
|
|
|
- <div style={{display: 'flex'}}>
|
|
|
+const MDEdit = ({children, field, onChange, ...props}) => {
|
|
|
+ const ref = useRef()
|
|
|
+ return (
|
|
|
+ <div style={{display: 'flex'}} ref={ref}>
|
|
|
<AceEditor
|
|
|
-
|
|
|
- mode="markdown"
|
|
|
- width='100%'
|
|
|
- height='400px'
|
|
|
- theme='github'
|
|
|
- fontFamily="TerminusTTF"
|
|
|
- fontSize={15}
|
|
|
- enableBasicAutocompletion={true}
|
|
|
- enableLiveAutocompletion={true}
|
|
|
- style={{maxWidth: '50%', height: '400px'}} placeholder={field.name} value={children} {...props}/>
|
|
|
+ mode="markdown"
|
|
|
+ width='100%'
|
|
|
+ height='400px'
|
|
|
+ theme='github'
|
|
|
+ fontFamily="TerminusTTF"
|
|
|
+ fontSize={15}
|
|
|
+ enableBasicAutocompletion={true}
|
|
|
+ enableLiveAutocompletion={true}
|
|
|
+ style={{maxWidth: '50%', height: '400px'}}
|
|
|
+ placeholder={field.name}
|
|
|
+ value={children}
|
|
|
+ onChange={onChange}
|
|
|
+ {...props}
|
|
|
+ />
|
|
|
<div style={{maxWidth: '50%', height: '400px', overflow: 'auto'}}>
|
|
|
+ <button onClick={()=>{
|
|
|
+ const videos = [...document.querySelectorAll('video')]
|
|
|
+ const playing = videos.find(v => v.playing)
|
|
|
+ if (playing){
|
|
|
+ const {currentTime} = playing
|
|
|
+ const ast = buildAST(children)
|
|
|
+ let timeCodes = getTimeCodes(ast)
|
|
|
+ console.log(currentTime, timeCodes)
|
|
|
+ let second, hash;
|
|
|
+ for ([second, hash] of Object.entries(timeCodes)){
|
|
|
+ if (second > currentTime){
|
|
|
+ console.log(hash)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else hash = ''
|
|
|
+ }
|
|
|
+ let newLine;
|
|
|
+ if (hash){
|
|
|
+ const line = children.match(new RegExp(`\\n(#{1,6}).*${hash}.*\\n`))
|
|
|
+ if (line){
|
|
|
+ newLine = `\n${line[1]} [#${getTimeCodeFromSeconds(currentTime)}]\n`
|
|
|
+ onChange(children.slice(0, line.index) + newLine + children.slice(line.index) )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ newLine = `\n# [#${getTimeCodeFromSeconds(currentTime)}]\n`
|
|
|
+ onChange(children + newLine)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }}>Timecode</button>
|
|
|
{toReact(buildAST(children), React)}
|
|
|
</div>
|
|
|
+ </div>)
|
|
|
+}
|
|
|
+
|
|
|
+const MD = ({children}) =>
|
|
|
+ <div >
|
|
|
+ {toReact(buildAST(children), React)}
|
|
|
</div>
|
|
|
|
|
|
|
|
@@ -410,7 +458,7 @@ const defaultAdminOptions =
|
|
|
view: {
|
|
|
formatters:{
|
|
|
ID: ({children}) => <b>{children && children.slice(-6).toUpperCase()}</b>,
|
|
|
- String: ({children}) => <>{children && children.length > 100 ? children.slice(0,100) + '...' : children}</>,
|
|
|
+ String: ({children}) => <MD>{children && children.length > 100 ? children.slice(0,100) + '...' : children}</MD>,
|
|
|
Object: ObjectShortView,
|
|
|
Array: ({children, ...props}) => <>{children.map((child,i) => <ObjectShortView key={child && (child._id || child.key || child.name) || i} children={child} {...props}/>)}</>
|
|
|
},
|