add canvas media package

fixes COMMS-2290
flag Assignments 2

Test Plan:
- create a media upload assignment
- in a2 as a sutdent go submit an assignment
- notice a video upload button
- click button
- notice the modal is shown and you can drag and drop video files
  or record yourself
- close modal
- notice no console errors or crashes

Change-Id: I9a6184efb99aa05d0d634d2744cca00abf5ae26e
Reviewed-on: https://gerrit.instructure.com/204375
Tested-by: Jenkins
QA-Review: Steven Burnett <sburnett@instructure.com>
Product-Review: Steven Burnett <sburnett@instructure.com>
Reviewed-by: Landon Gilbert-Bland <lbland@instructure.com>
This commit is contained in:
Steven Burnett 2019-08-08 09:09:48 -06:00
parent 0b4362749f
commit 1f7bf02c4d
13 changed files with 757 additions and 2 deletions

1
.gitignore vendored
View File

@ -62,6 +62,7 @@ docker-compose.local.*
# sub-packages
/packages/*/node_modules
/packages/*/es
/packages/*/lib
/packages/*/coverage/
/packages/canvas-planner/.babel-cache

View File

@ -28,6 +28,7 @@ import React, {Component} from 'react'
import {STUDENT_VIEW_QUERY, SUBMISSION_HISTORIES_QUERY} from '../graphqlData/Queries'
import {Submission} from '../graphqlData/Submission'
import TextEntry from './TextEntry'
import MediaAttempt from './AttemptType/MediaAttempt'
export default class AttemptTab extends Component {
static propTypes = {
@ -164,9 +165,21 @@ export default class AttemptTab extends Component {
)
}
renderMediaAttempt = createSubmissionDraft => {
return (
<MediaAttempt
createSubmissionDraft={createSubmissionDraft}
submission={this.props.submission}
updateUploadState={this.updateUploadState}
/>
)
}
renderSubmissionByType = (createSubmission, createSubmissionDraft) => {
// TODO: we need to ensure we handle multiple submission types eventually
switch (this.props.assignment.submissionTypes[0]) {
case 'media_recording':
return this.renderMediaAttempt(createSubmission, createSubmissionDraft)
case 'online_text_entry':
return this.renderTextAttempt(createSubmissionDraft)
case 'online_upload':

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Billboard from '@instructure/ui-billboard/lib/components/Billboard'
import Button from '@instructure/ui-buttons/lib/components/Button'
import I18n from 'i18n!assignments_2_text_entry'
import {IconAttachMediaLine} from '@instructure/ui-icons'
import React, {useState} from 'react'
import UploadMedia from '@instructure/canvas-media'
import View from '@instructure/ui-layout/lib/components/View'
export default function MediaAttempt() {
const [mediaModalOpen, setMediaModalOpen] = useState(false)
return (
<View as="div" borderWidth="small">
<UploadMedia onDismiss={() => setMediaModalOpen(false)} open={mediaModalOpen} />
<Billboard
heading={I18n.t('Add Media')}
hero={<IconAttachMediaLine color="brand" />}
message={
<Button size="small" variant="primary" onClick={() => setMediaModalOpen(true)}>
{I18n.t('Record/Upload')}
</Button>
}
/>
</View>
)
}

View File

@ -0,0 +1,49 @@
{
"name": "@instructure/canvas-media",
"version": "1.0.0",
"description": "A component that will handle upload/record and displaying of media",
"author": "Instructure, Inc.",
"main": "lib/index.js",
"module": "es/index.js",
"sideEffects": false,
"scripts": {
"test": "echo 'no tests yet...'",
"build:canvas": "babel --root-mode upward src -d es & JEST_WORKER_ID=true babel --root-mode upward src -d lib"
},
"repository": {
"type": "git",
"url": "git+https://github.com/instructure/canvas-lms.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/instructure/canvas-lms/issues"
},
"homepage": "https://github.com/instructure/canvas-lms#readme",
"dependencies": {
"@instructure/canvas-theme": "^6.8.1",
"@instructure/media-capture": "^5",
"@instructure/ui-a11y": "^6.8.1",
"@instructure/ui-alerts": "^6.8.1",
"@instructure/ui-billboard": "^6.8.1",
"@instructure/ui-buttons": "^6.8.1",
"@instructure/ui-color-utils": "^6.8.1",
"@instructure/ui-elements": "^6.8.1",
"@instructure/ui-forms": "^6.8.1",
"@instructure/ui-icons": "^6.8.1",
"@instructure/ui-layout": "^6.8.1",
"@instructure/ui-media-player": "^5",
"@instructure/ui-overlays": "^6.8.1",
"@instructure/ui-pagination": "^6.8.1",
"@instructure/ui-react-utils": "^6.8.1",
"@instructure/ui-svg-images": "^6.8.1",
"@instructure/ui-tabs": "^6.8.1",
"@instructure/ui-text-input": "^6.8.1",
"@instructure/ui-themeable": "^6.8.1",
"@instructure/ui-themes": "^6.8.1",
"@instructure/ui-toggle-details": "^6.8.1",
"@instructure/uid": "^6.8.1",
"prop-types": "^15",
"react": "^16",
"react-dom": "^16"
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, {useState} from 'react'
import {arrayOf, bool, func, instanceOf, oneOfType, string} from 'prop-types'
import {Billboard} from '@instructure/ui-billboard'
import {Button} from '@instructure/ui-buttons'
import {FileDrop} from '@instructure/ui-forms'
import {Flex, View} from '@instructure/ui-layout'
import {IconTrashLine} from '@instructure/ui-icons'
import {PresentationContent, ScreenReaderContent} from '@instructure/ui-a11y'
import {Text} from '@instructure/ui-elements'
import {VideoPlayer} from '@instructure/ui-media-player'
import RocketSVG from './RocketSVG'
export default function ComputerPanel({
theFile,
setFile,
hasUploadedFile,
setHasUploadedFile,
accept,
label
}) {
const [messages, setMessages] = useState([])
if (hasUploadedFile) {
const sources = [{label: theFile.name, src: URL.createObjectURL(theFile)}]
return (
<>
<Flex direction="row-reverse" margin="none none medium">
<Flex.Item>
<Button
onClick={() => {
setFile(null)
setHasUploadedFile(false)
}}
icon={IconTrashLine}
>
<ScreenReaderContent>Clear selected file</ScreenReaderContent>
</Button>
</Flex.Item>
<Flex.Item grow shrink>
<PresentationContent>
<Text>{theFile.name}</Text>
</PresentationContent>
</Flex.Item>
</Flex>
<View as="div" height="100%" width="100%" textAlign="center">
<VideoPlayer sources={sources} />
</View>
</>
)
}
return (
<div>
<FileDrop
accept={accept}
onDropAccepted={([file]) => {
if (messages.length) {
setMessages([])
}
setFile(file)
setHasUploadedFile(true)
}}
onDropRejected={() => {
setMessages((msgs) =>
msgs.concat({
text:'Invalid file type',
type: 'error'
})
)
}}
messages={messages}
label={
<Billboard
heading={label}
hero={<RocketSVG width="3em" height="3em" />}
message='Drag and drop, or click to browse your computer'
/>
}
/>
</div>
)
}
ComputerPanel.propTypes = {
theFile: instanceOf(File),
setFile: func.isRequired,
hasUploadedFile: bool,
setHasUploadedFile: func.isRequired,
accept: oneOfType([string, arrayOf(string)]),
label: string.isRequired
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react'
import { string, func } from 'prop-types'
import { TextArea } from '@instructure/ui-forms'
export default function EmbedPanel ({embedCode, setEmbedCode}) {
return (
<TextArea
maxHeight="10rem"
label='Embed Video Code'
value={embedCode}
onChange={(e) =>{
setEmbedCode(e.target.value)}
}
/>
)
}
EmbedPanel.propTypes = {
embedCode: string.isRequired,
setEmbedCode: func.isRequired
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const formatMessage = (string) => string
const MediaCaptureStrings = {
ARIA_VIDEO_LABEL: formatMessage('Video Player'),
ARIA_VOLUME: formatMessage('Current Volume Level'),
ARIA_RECORDING: formatMessage('Recording'),
DEFAULT_ERROR: formatMessage('Something went wrong accessing your mic or webcam.'),
DEVICE_AUDIO: formatMessage('Mic'),
DEVICE_VIDEO: formatMessage('Webcam'),
FILE_PLACEHOLDER: formatMessage('Untitled'),
FINISH: formatMessage('Finish'),
NO_WEBCAM: formatMessage('No Video'),
NOT_ALLOWED_ERROR: formatMessage('Please allow Canvas to access your microphone and webcam.'),
NOT_READABLE_ERROR: formatMessage('Your webcam may already be in use.'),
PLAYBACK_PAUSE: formatMessage('Pause'),
PLAYBACK_PLAY: formatMessage('Play'),
PREVIEW: formatMessage('PREVIEW'),
SAVE: formatMessage('Save'),
SR_FILE_INPUT: formatMessage('File name'),
START: formatMessage('Start Recording'),
START_OVER: formatMessage('Start Over')
}
export {MediaCaptureStrings}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {Alert} from '@instructure/ui-alerts'
import {canUseMediaCapture, MediaCapture} from '@instructure/media-capture'
// import {object, func} from 'prop-types'
import React from 'react'
import {MediaCaptureStrings} from './MediaCaptureStrings'
export default class MediaRecorder extends React.Component {
// saveFile = (file) => {
// this.props.contentProps.saveMediaRecording(file, this.props.editor, this.props.dismiss)
// }
render() {
return (
<div>
{canUseMediaCapture() ? (
<MediaCapture
translations={MediaCaptureStrings}
onCompleted={this.saveFile}
/>
) :
(<Alert
variant="error"
margin="small"
>
{'Error uploading video/audio recording'}
</Alert>)
}
</div>
)
}
}
// MediaRecorder.propTypes = {
// dismiss: func.isRequired,
// }

View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react'
const RocketSVG = props => (
<svg id="filedrop-rocket_svg__Layer_1" data-name="Layer 1" viewBox="0 0 182 182" {...props}>
<defs>
<style>
{
'.filedrop-rocket_svg__cls-1{fill:#243038}.filedrop-rocket_svg__cls-2{fill:#c0c6cb}.filedrop-rocket_svg__cls-3{fill:#e5e7e9}.filedrop-rocket_svg__cls-4{fill:#d0d4d8}'
}
</style>
</defs>
<path className="filedrop-rocket_svg__cls-1" d="M152.21 138.46h-32v-93h32zm-30-2h28v-89h-28z" />
<path
className="filedrop-rocket_svg__cls-1"
transform="rotate(-45 136.317 61.556)"
d="M135.32 40.2h2v42.73h-2z"
/>
<path
className="filedrop-rocket_svg__cls-1"
transform="rotate(-45 136.317 61.556)"
d="M114.95 60.56h42.73v2h-42.73z"
/>
<path
className="filedrop-rocket_svg__cls-1"
transform="rotate(-45 136.314 92.667)"
d="M135.32 71.3h2v42.73h-2z"
/>
<path
className="filedrop-rocket_svg__cls-1"
transform="rotate(-45 136.314 92.667)"
d="M114.95 91.66h42.73v2h-42.73z"
/>
<path
className="filedrop-rocket_svg__cls-1"
transform="rotate(-45 136.317 122.056)"
d="M135.32 100.7h2v42.73h-2z"
/>
<path
className="filedrop-rocket_svg__cls-1"
transform="rotate(-45 136.317 122.056)"
d="M114.95 121.06h42.73v2h-42.73z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M121.21 76.56h30v2h-30zM121.21 106.56h30v2h-30zM87.39 50.56h33.82v2H87.39zM88.11 55.46h33.1v2h-33.1z"
/>
<path
className="filedrop-rocket_svg__cls-2"
d="M45.36 97.31a27 27 0 0 0-26.3 20.87 5 5 0 0 0 4.88 6.13h42.84a5 5 0 0 0 4.88-6.13 27 27 0 0 0-26.3-20.87z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M66.78 125.31H23.94a6 6 0 0 1-5.85-7.31 28 28 0 0 1 54.55 0 6 6 0 0 1-5.86 7.36zm-21.42-27A25.87 25.87 0 0 0 20 118.4a4 4 0 0 0 3.91 4.91h42.87a4 4 0 0 0 3.14-1.52 4 4 0 0 0 .77-3.39 25.87 25.87 0 0 0-25.33-20.09z"
/>
<path
className="filedrop-rocket_svg__cls-2"
d="M78.36 97.31a27 27 0 0 0-26.3 20.87 5 5 0 0 0 4.88 6.13h42.84a5 5 0 0 0 4.88-6.13 27 27 0 0 0-26.3-20.87z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M99.78 125.31H56.94a6 6 0 0 1-5.85-7.31 28 28 0 0 1 54.55 0 6 6 0 0 1-5.86 7.36zm-21.42-27A25.87 25.87 0 0 0 53 118.4a4 4 0 0 0 3.91 4.91h42.87a4 4 0 0 0 3.14-1.52 4 4 0 0 0 .77-3.39 25.87 25.87 0 0 0-25.33-20.09z"
/>
<path
className="filedrop-rocket_svg__cls-3"
d="M84.37 124.31c3.32-12.17 5.29-27.18 5.29-43.43 0-40.55-12.22-73.42-27.29-73.42s-27.3 32.87-27.3 73.42c0 16.25 2 31.26 5.29 43.43z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M85.13 125.31H39.6l-.2-.74c-3.49-12.75-5.33-27.86-5.33-43.69 0-41.73 12.43-74.42 28.3-74.42s28.29 32.69 28.29 74.42c0 15.83-1.84 30.94-5.32 43.69zm-44-2h42.48a168.39 168.39 0 0 0 5-42.43C88.66 41 76.86 8.46 62.37 8.46S36.07 41 36.07 80.88a167.91 167.91 0 0 0 5.06 42.43z"
/>
<path className="filedrop-rocket_svg__cls-4" d="M75.37 136.87H49.36l-4-12.56h34.01l-4 12.56z" />
<path
className="filedrop-rocket_svg__cls-1"
d="M76.1 137.87H48.63L44 123.31h36.74zm-26-2h24.54L78 125.31H46.73z"
/>
<circle className="filedrop-rocket_svg__cls-2" cx={62.37} cy={78.88} r={15.75} />
<path
className="filedrop-rocket_svg__cls-1"
d="M62.37 95.63a16.75 16.75 0 1 1 16.75-16.75 16.76 16.76 0 0 1-16.75 16.75zm0-31.5a14.75 14.75 0 1 0 14.75 14.75 14.76 14.76 0 0 0-14.75-14.75z"
/>
<circle cx={62.37} cy={78.88} r={11} fill="#9ad6f5" />
<path
className="filedrop-rocket_svg__cls-1"
d="M62.37 90.88a12 12 0 1 1 12-12 12 12 0 0 1-12 12zm0-22a10 10 0 1 0 10 10 10 10 0 0 0-10-10zM40.09 37.44h44.55v2H40.09z"
/>
<path
className="filedrop-rocket_svg__cls-4"
d="M171.21 147.46h-160l3.79-9.38a1 1 0 0 1 .93-.62h150.6a1 1 0 0 1 .93.62z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M172.69 148.46H9.73L14 137.71a2 2 0 0 1 1.86-1.25h150.67a2 2 0 0 1 1.86 1.25zm-160-2h157l-3.2-8H15.89z"
/>
<path className="filedrop-rocket_svg__cls-3" d="M11.21 147.46h160v11h-160z" />
<path
className="filedrop-rocket_svg__cls-1"
d="M172.21 159.46h-162v-13h162zm-160-2h158v-9h-158z"
/>
<path
className="filedrop-rocket_svg__cls-2"
d="M15.21 177.46H3.79a1 1 0 0 1-.9-1.43l8.32-17.57h30z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M15.54 178.46H3.79A2 2 0 0 1 2 175.6l8.6-18.14h33.67zm-3.7-19l-8 17h11.04l23.27-17z"
/>
<path
className="filedrop-rocket_svg__cls-2"
d="M166.79 177.46h11.42a1 1 0 0 0 .9-1.43l-8.32-17.57h-30z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M178.21 178.46h-11.75l-28.73-21h33.69L180 175.6a2 2 0 0 1-1.81 2.86zm-11.09-2h11.09l-8.05-17h-26.31z"
/>
<path
className="filedrop-rocket_svg__cls-2"
d="M85.49 177.05a1 1 0 0 0 .8.41h10.92c.73 0 15.58-19 15.58-19h-41z"
/>
<path
className="filedrop-rocket_svg__cls-1"
d="M97.21 178.46H86.29a2 2 0 0 1-1.6-.82l-14.88-20.18h45l-1.26 1.61c-15.12 19.39-15.74 19.39-16.34 19.39zm-10.92-2l-.8.59.8-.59zm0 0h10.6c1.47-1.4 8.71-10.46 13.85-17h-37z"
/>
</svg>
)
export default RocketSVG

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const ACCEPTED_FILE_TYPES = [
"3gp",
"aac",
"amr",
"asf",
"avi",
"flac",
"flv",
"m4a",
"m4v",
"mkv",
"mov",
"mp3",
"mp4",
"mpeg",
"mpg",
"ogg",
"qt",
"wav",
"wma",
"wmv"
]

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {
IconDocumentLine,
IconMsExcelLine,
IconMsPptLine,
IconMsWordLine,
IconPdfLine
} from '@instructure/ui-icons'
export function getIconFromType(type) {
switch(type) {
case 'application/msword':
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
return IconMsWordLine
case 'application/vnd.ms-powerpoint':
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
return IconMsPptLine
case 'application/pdf':
return IconPdfLine
case 'application/vnd.ms-excel':
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
return IconMsExcelLine
default:
return IconDocumentLine
}
}
export function isImage(type) {
return /^image/.test(type)
}
export function isAudioOrVideo(type) {
return isVideo(type) || isAudio(type)
}
export function isVideo(type) {
return /^video/.test(type)
}
export function isAudio(type) {
return /^audio/.test(type)
}
export function isText(type) {
return /^text/.test(type)
}

View File

@ -0,0 +1,156 @@
/*
* Copyright (C) 2019 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {bool, func} from 'prop-types'
import {Button, CloseButton} from '@instructure/ui-buttons'
import {Heading, Spinner} from '@instructure/ui-elements'
import {Modal} from '@instructure/ui-overlays'
import React, {Suspense} from 'react'
import {Tabs} from '@instructure/ui-tabs'
import {View} from '@instructure/ui-layout'
import {ACCEPTED_FILE_TYPES} from './acceptedMediaFileTypes'
const ComputerPanel = React.lazy(() => import('./ComputerPanel'))
const EmbedPanel = React.lazy(() => import('./EmbedPanel'))
const MediaRecorder = React.lazy(() => import('./MediaRecorder'))
export const PANELS = {
COMPUTER: 0,
RECORD: 1,
EMBED: 2
}
export const handleSubmit = (editor, selectedPanel, uploadData, saveMediaRecording, onDismiss) => {
switch (selectedPanel) {
case PANELS.COMPUTER: {
const {theFile} = uploadData
saveMediaRecording(theFile, editor, onDismiss)
break;
}
case PANELS.EMBED: {
const {embedCode} = uploadData
editor.insertContent(embedCode)
onDismiss()
break
}
default:
throw new Error('Selected Panel is invalid') // Should never get here
}
}
export default class UploadMedia extends React.Component {
static propTypes = {
onDismiss: func,
open: bool
}
state = {
theFile: null,
hasUploadedFile: false,
selectedPanel: 0,
embedCode: ''
}
renderModalBody = () => {
return (
<Tabs shouldFocusOnRender maxWidth="large" onRequestTabChange={(_, { index }) => this.setState({selectedPanel: index})}>
<Tabs.Panel isSelected={this.state.selectedPanel === PANELS.COMPUTER} renderTitle={() => 'Computer'}>
<Suspense fallback={
<View as="div" height="100%" width="100%" textAlign="center">
<Spinner renderTitle={() => "Loading Media"} size="large" margin="0 0 0 medium" />
</View>
} size="large">
<ComputerPanel
theFile={this.state.theFile}
setFile={(file) => this.setState({theFile: file})}
hasUploadedFile={this.state.hasUploadedFile}
setHasUploadedFile={(uploadFileState) => this.setState({hasUploadedFile: uploadFileState})}
label='Drag a File Here'
accept={ACCEPTED_FILE_TYPES}
/>
</Suspense>
</Tabs.Panel>
<Tabs.Panel isSelected={this.state.selectedPanel === PANELS.RECORD} renderTitle={() => 'Record'}>
<Suspense fallback={
<View as="div" height="100%" width="100%" textAlign="center">
<Spinner renderTitle={() => "Loading Media"} size="large" margin="0 0 0 medium" />
</View>
}>
<MediaRecorder dismiss={this.props.onDismiss}/>
</Suspense>
</Tabs.Panel>
<Tabs.Panel isSelected={this.state.selectedPanel === PANELS.EMBED} renderTitle={() => 'Embed'}>
<Suspense fallback={
<View as="div" height="100%" width="100%" textAlign="center">
<Spinner renderTitle={() => "Loading Media"} size="large" margin="0 0 0 medium" />
</View>
}>
<EmbedPanel embedCode={this.state.embedCode} setEmbedCode={(embedCode) => this.setState({embedCode})} />
</Suspense>
</Tabs.Panel>
</Tabs>
)
}
renderModalFooter = () => {
if (this.state.selectedPanel !== PANELS.RECORD) {
return (
<Modal.Footer>
<Button onClick={this.props.onDismiss}>Close</Button>&nbsp;
<Button
onClick={e => {
e.preventDefault()
handleSubmit()
}}
variant="primary"
type="submit"
>
Submit
</Button>
</Modal.Footer>
)
}
return null
}
render() {
return (
<Modal
label='Upload Media'
size="medium"
onDismiss={this.props.onDismiss}
open={this.props.open}
shouldCloseOnDocumentClick={false}
>
<Modal.Header>
<CloseButton onClick={this.props.onDismiss} offset="medium" placement="end">
Close
</CloseButton>
<Heading>Upload Media</Heading>
</Modal.Header>
<Modal.Body>
{this.renderModalBody()}
</Modal.Body>
{this.renderModalFooter()}
</Modal>
)
}
}

View File

@ -16242,7 +16242,7 @@ react-dnd@^2.5.2:
lodash "^4.2.0"
prop-types "^15.5.10"
"react-dom@^0.14.7 || ^15 || 16", "react-dom@^0.14.8 || ^15.0.0 || ^16", react-dom@^16.6.0:
"react-dom@^0.14.7 || ^15 || 16", "react-dom@^0.14.8 || ^15.0.0 || ^16", react-dom@^16, react-dom@^16.6.0:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==
@ -16383,7 +16383,7 @@ react@0.14.9:
envify "^3.0.0"
fbjs "^0.6.1"
"react@^0.14.7 || ^15 || 16", "react@^0.14.8 || ^15.0.0 || ^16", "react@^0.14.9 || ^15 || ^16", "react@^15 || ^16", react@^16.8.0:
"react@^0.14.7 || ^15 || 16", "react@^0.14.8 || ^15.0.0 || ^16", "react@^0.14.9 || ^15 || ^16", "react@^15 || ^16", react@^16, react@^16.8.0:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==