From f2bd5a0af07d9a52248f33d09033360bfe32a60d Mon Sep 17 00:00:00 2001 From: AvinashAgarwal14 Date: Thu, 1 Aug 2019 03:38:23 +0530 Subject: [PATCH 1/8] pico-modal replaced by react-modal --- package.json | 1 + src/components/ImageEditor.js | 35 ++++++ src/components/WithMultimedia.js | 119 ++++++++++++------ src/containers/Builders/CLOZEForm.js | 3 +- src/containers/Builders/FreeTextInputForm.js | 3 +- .../Builders/GroupAssignmentForm.js | 3 +- src/containers/Builders/MCQForm.js | 3 +- src/containers/Builders/MatchingForm.js | 3 +- src/containers/Builders/REORDERForm.js | 3 +- src/containers/Players/CLOZEPlayer.js | 3 +- src/containers/Players/FreeTextInputPlayer.js | 3 +- .../Players/GroupAssignmentPlayer.js | 3 +- src/containers/Players/MCQPlayer.js | 3 +- src/containers/Players/MatchingPlayer.js | 3 +- src/containers/Players/REORDERPlayer.js | 3 +- src/css/ImageEditor.css | 38 ++++++ src/index.js | 2 + 17 files changed, 181 insertions(+), 50 deletions(-) create mode 100644 src/components/ImageEditor.js create mode 100644 src/css/ImageEditor.css diff --git a/package.json b/package.json index 38c61dea..52a6100e 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react-chartjs-2": "^2.7.2", "react-dom": "^16.4.0", "react-intl": "^2.4.0", + "react-modal": "^3.9.1", "react-redux": "^5.0.7", "react-router-dom": "^4.3.1", "react-scripts": "1.1.4", diff --git a/src/components/ImageEditor.js b/src/components/ImageEditor.js new file mode 100644 index 00000000..9e514cb3 --- /dev/null +++ b/src/components/ImageEditor.js @@ -0,0 +1,35 @@ +import React, {Component} from 'react'; +import '../css/ImageEditor.css'; + +class ImageEditor extends Component { + constructor(props) { + super(props); + this.state = { + mediaSource: '' + } + } + + componentDidMount () { + const {mediaSource} = this.props; + this.setState({ + mediaSource: mediaSource + }) + } + + render () { + return ( +
+ editable-img + + +
+ ) + } +} + +export default ImageEditor; \ No newline at end of file diff --git a/src/components/WithMultimedia.js b/src/components/WithMultimedia.js index 2eb22f81..dc34aa17 100644 --- a/src/components/WithMultimedia.js +++ b/src/components/WithMultimedia.js @@ -2,8 +2,23 @@ import React from 'react'; import datastore from 'lib/sugar-web/datastore'; import chooser from 'lib/sugar-web/graphics/journalchooser'; import env from 'lib/sugar-web/env'; -import picoModal from 'picomodal'; import meSpeak from 'mespeak'; +import Modal from 'react-modal'; +import ImageEditor from '../components/ImageEditor'; +import '../css/ImageEditor.css'; + +const modalStyle = { + content : { + top : '55%', + left : '50%', + right : 'auto', + bottom : 'auto', + marginRight : '-50%', + transform : 'translate(-50%, -50%)', + height : '85%', + width : '80%' + } +}; const withMultimedia = (defaultThumbnail) => (Component) => { class MultimediaHoc extends React.Component { @@ -12,7 +27,10 @@ const withMultimedia = (defaultThumbnail) => (Component) => { super(props); this.state = { thumbnail: '', - userLanguage: '' + userLanguage: '', + modalSource: '', + modalMediaType: '', + modalIsOpen: false, } } @@ -79,46 +97,69 @@ const withMultimedia = (defaultThumbnail) => (Component) => { } }); }; + + closeModal = () => { + this.setState({ + ...this.state, + modalIsOpen: false + }); + } showMedia = (imageSource, mediaType = 'img') => { - picoModal({ - content: ( - `<${mediaType} src = ${imageSource} \ - controls \ - style='max-height: 100%;\ - max-width: 100%;\ - margin: auto;\ - left: 0;\ - right: 0;\ - top: 0;\ - bottom: 0;\ - position: absolute;'>\ - \ - `), - closeButton: false, - modalStyles: { - backgroundColor: "#e5e5e5", - height: "400px", - width: "600px", - maxWidth: "90%" - } + this.setState({ + ...this.state, + modalSource: imageSource, + modalMediaType: mediaType, + modalIsOpen: true }) - .afterShow(function(modal) { - let closeButton = document.getElementById('close-button'); - closeButton.addEventListener('click', function() { - modal.close(); - }); - }) - .afterClose((modal) => { - modal.destroy(); - }) - .show(); - }; + } + + showModalWindow = () => { + return ( + + {this.state.modalMediaType === 'img' && + non-editable img + } + {this.state.modalMediaType === 'video' && + } + + + ); + } + showEditableModalWindow = () => { + return ( + + {this.state.modalMediaType === 'img' && + + } + {this.state.modalMediaType === 'video' && + } + + + ); + } + deleteThumbnail = () => { this.setState({ ...this.state, @@ -161,6 +202,8 @@ const withMultimedia = (defaultThumbnail) => (Component) => { thumbnail={thumbnail} insertThumbnail={this.insertThumbnail} showMedia={this.showMedia} + ShowModalWindow = {this.showModalWindow} + ShowEditableModalWindow = {this.showEditableModalWindow} /> ); } diff --git a/src/containers/Builders/CLOZEForm.js b/src/containers/Builders/CLOZEForm.js index e5c44154..458880c7 100644 --- a/src/containers/Builders/CLOZEForm.js +++ b/src/containers/Builders/CLOZEForm.js @@ -424,7 +424,7 @@ class CLOZEForm extends Component { render() { const {errors, answers} = this.state; - const { thumbnail, insertThumbnail, showMedia} = this.props; + const { thumbnail, insertThumbnail, showMedia, ShowEditableModalWindow} = this.props; let questionType = this.state.question.type; let inputs = answers.map((ans, i) => { @@ -630,6 +630,7 @@ class CLOZEForm extends Component { + ) } diff --git a/src/containers/Builders/FreeTextInputForm.js b/src/containers/Builders/FreeTextInputForm.js index 48adf584..b2b9fd87 100644 --- a/src/containers/Builders/FreeTextInputForm.js +++ b/src/containers/Builders/FreeTextInputForm.js @@ -387,7 +387,7 @@ class FreeTextInputForm extends Component { render() { const {currentQuestion, errors} = this.state; - const {thumbnail, insertThumbnail, showMedia} = this.props; + const {thumbnail, insertThumbnail, showMedia, ShowEditableModalWindow} = this.props; const {id} = currentQuestion; let questionType = currentQuestion.question.type; let placeholder_string = ENTER_ANSWER; @@ -515,6 +515,7 @@ class FreeTextInputForm extends Component { + ) } diff --git a/src/containers/Builders/GroupAssignmentForm.js b/src/containers/Builders/GroupAssignmentForm.js index 9002cd42..01ce6cad 100644 --- a/src/containers/Builders/GroupAssignmentForm.js +++ b/src/containers/Builders/GroupAssignmentForm.js @@ -555,7 +555,7 @@ class GroupAssignmentForm extends Component { render() { const {currentQuestion, errors, groups} = this.state; const {id} = currentQuestion; - const {thumbnail, insertThumbnail, showMedia} = this.props; + const {thumbnail, insertThumbnail, showMedia, ShowEditableModalWindow} = this.props; let questionType = currentQuestion.question.type; let groupOptions = groups.map((group, i) => { @@ -774,6 +774,7 @@ class GroupAssignmentForm extends Component { + ) } diff --git a/src/containers/Builders/MCQForm.js b/src/containers/Builders/MCQForm.js index bfc96710..bf7d2228 100644 --- a/src/containers/Builders/MCQForm.js +++ b/src/containers/Builders/MCQForm.js @@ -492,7 +492,7 @@ class MCQForm extends Component { render() { const {currentQuestion, errors} = this.state; const {id, options} = currentQuestion; - const {thumbnail, insertThumbnail, showMedia} = this.props; + const {thumbnail, insertThumbnail, showMedia, ShowEditableModalWindow} = this.props; let questionType = currentQuestion.question.type; let title_error = ''; @@ -628,6 +628,7 @@ class MCQForm extends Component { + ) } diff --git a/src/containers/Builders/MatchingForm.js b/src/containers/Builders/MatchingForm.js index bcde9ac2..2c648fab 100644 --- a/src/containers/Builders/MatchingForm.js +++ b/src/containers/Builders/MatchingForm.js @@ -435,7 +435,7 @@ class MATCHING_PAIRForm extends Component { render() { const {currentPair, errors} = this.state; - const {thumbnail, insertThumbnail, showMedia} = this.props + const {thumbnail, insertThumbnail, showMedia, ShowEditableModalWindow} = this.props let questionType = this.state.currentPair.question.type; let answerType = this.state.currentPair.answer.type; @@ -568,6 +568,7 @@ class MATCHING_PAIRForm extends Component { + ) } diff --git a/src/containers/Builders/REORDERForm.js b/src/containers/Builders/REORDERForm.js index 7ae62ca7..b0f42cd9 100644 --- a/src/containers/Builders/REORDERForm.js +++ b/src/containers/Builders/REORDERForm.js @@ -325,7 +325,7 @@ class REORDERForm extends Component { render() { const {errors, list} = this.state; - const {thumbnail, insertThumbnail, showMedia} = this.props; + const {thumbnail, insertThumbnail, showMedia, ShowEditableModalWindow} = this.props; let questionType = this.state.question.type; let title_error = ''; @@ -448,6 +448,7 @@ class REORDERForm extends Component { + ) } diff --git a/src/containers/Players/CLOZEPlayer.js b/src/containers/Players/CLOZEPlayer.js index 2a61de10..7187b78a 100644 --- a/src/containers/Players/CLOZEPlayer.js +++ b/src/containers/Players/CLOZEPlayer.js @@ -221,7 +221,7 @@ class CLOZEPlayer extends Component { } render() { - const {showMedia} = this.props; + const {showMedia, ShowModalWindow} = this.props; const questionType = this.state.question.type; const questionData = this.state.question.data; @@ -320,6 +320,7 @@ class CLOZEPlayer extends Component { + ) } diff --git a/src/containers/Players/FreeTextInputPlayer.js b/src/containers/Players/FreeTextInputPlayer.js index 4b696d95..874a8563 100644 --- a/src/containers/Players/FreeTextInputPlayer.js +++ b/src/containers/Players/FreeTextInputPlayer.js @@ -158,7 +158,7 @@ class FreeTextInputPlayer extends Component { render() { const {questions} = this.state; - const {showMedia} = this.props; + const {showMedia, ShowModalWindow} = this.props; let buttonText = ; if (this.state.submitted) buttonText = @@ -241,6 +241,7 @@ class FreeTextInputPlayer extends Component { + ); } diff --git a/src/containers/Players/GroupAssignmentPlayer.js b/src/containers/Players/GroupAssignmentPlayer.js index 67769528..d2ce7c13 100644 --- a/src/containers/Players/GroupAssignmentPlayer.js +++ b/src/containers/Players/GroupAssignmentPlayer.js @@ -251,7 +251,7 @@ class GroupAssignmentPlayer extends Component { render() { const {currentQuestion, groups, selectedAns} = this.state; - const {showMedia} = this.props; + const {showMedia, ShowModalWindow} = this.props; const {id, answer} = currentQuestion; const questionType = currentQuestion.question.type; const questionData = currentQuestion.question.data; @@ -361,6 +361,7 @@ class GroupAssignmentPlayer extends Component { + ) } diff --git a/src/containers/Players/MCQPlayer.js b/src/containers/Players/MCQPlayer.js index d1a0ec58..736be63d 100644 --- a/src/containers/Players/MCQPlayer.js +++ b/src/containers/Players/MCQPlayer.js @@ -205,7 +205,7 @@ class MCQPlayer extends Component { render() { const {currentQuestion} = this.state; - const {showMedia} = this.props; + const {showMedia, ShowModalWindow} = this.props; const {id} = currentQuestion; const questionType = currentQuestion.question.type; const questionData = currentQuestion.question.data; @@ -325,6 +325,7 @@ class MCQPlayer extends Component { + ) } diff --git a/src/containers/Players/MatchingPlayer.js b/src/containers/Players/MatchingPlayer.js index 1a880a35..966d8a31 100644 --- a/src/containers/Players/MatchingPlayer.js +++ b/src/containers/Players/MatchingPlayer.js @@ -268,7 +268,7 @@ class MATCHING_PAIRPLAYER extends Component { render() { const {questions} = this.state; - const {showMedia} = this.props; + const {showMedia, ShowModalWindow} = this.props; let matchingTemplate = questions.map((ques, index) => { let questionType = ques.type; @@ -347,6 +347,7 @@ class MATCHING_PAIRPLAYER extends Component { + ) } diff --git a/src/containers/Players/REORDERPlayer.js b/src/containers/Players/REORDERPlayer.js index b184a510..b9f55f62 100644 --- a/src/containers/Players/REORDERPlayer.js +++ b/src/containers/Players/REORDERPlayer.js @@ -170,7 +170,7 @@ class REORDERPlayer extends Component { render() { - const {showMedia} = this.props; + const {showMedia, ShowModalWindow} = this.props; const {checkAns, userAns} = this.state; const questionType = this.state.question.type; const questionData = this.state.question.data; @@ -266,6 +266,7 @@ class REORDERPlayer extends Component { + ) } diff --git a/src/css/ImageEditor.css b/src/css/ImageEditor.css new file mode 100644 index 00000000..4d64d6c0 --- /dev/null +++ b/src/css/ImageEditor.css @@ -0,0 +1,38 @@ +.center-element { + max-height: 100%; + max-width: 100%; + margin: auto; + left: 0; + right: 0; + top: 0; + bottom: 0; + position: absolute; +} + +.modal-close-button { + background-image: url('../icons/exercise/delete.svg'); + position: absolute; + right: 0px; + width: 50px; + height: 50px; + margin-top: 10px; + top: 0px; + border-radius: 25px; + background-position: center; + background-size: contain; + background-repeat: no-repeat; +} + +.modal-edit-button { + background-image: url('../icons/exercise/edit.svg'); + position: absolute; + right: 60px; + width: 50px; + height: 50px; + margin-top: 10px; + top: 0px; + border-radius: 25px; + background-position: center; + background-size: contain; + background-repeat: no-repeat; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index ca59629a..a7ec714c 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,8 @@ import './css/index.css'; import App from './containers/App'; import registerServiceWorker from './registerServiceWorker'; import 'bootstrap/dist/css/bootstrap.min.css'; +import Modal from 'react-modal'; +Modal.setAppElement('#root'); ReactDOM.render(, document.getElementById('root')); registerServiceWorker(); From 65db25f04706109bcd8519c6329ecc2c4c570cae Mon Sep 17 00:00:00 2001 From: AvinashAgarwal14 Date: Sat, 3 Aug 2019 21:29:02 +0530 Subject: [PATCH 2/8] Image Editor added for all forms --- package.json | 2 + src/components/ImageEditor.js | 222 +++++++++++++++++- src/components/MultimediaJSX.js | 8 +- src/components/WithMultimedia.js | 20 +- src/containers/Builders/CLOZEForm.js | 11 + src/containers/Builders/FreeTextInputForm.js | 14 ++ .../Builders/GroupAssignmentForm.js | 34 ++- src/containers/Builders/MCQForm.js | 30 ++- src/containers/Builders/MatchingForm.js | 28 +++ src/containers/Builders/REORDERForm.js | 26 +- src/css/GroupAssignmentPlayer.css | 1 - src/css/ImageEditor.css | 31 +++ src/css/MatchingPlayer.css | 1 - 13 files changed, 396 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 52a6100e..d3192995 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "bootstrap": "^4.1.1", "chart.js": "^2.7.2", "copy-webpack-plugin": "^5.0.3", + "cropper": "^4.0.0", + "font-awesome": "^4.7.0", "interactjs": "^1.4.0-rc.13", "jquery": "^1.9.1", "jsplumb": "^2.10.1", diff --git a/src/components/ImageEditor.js b/src/components/ImageEditor.js index 9e514cb3..f69ac5e2 100644 --- a/src/components/ImageEditor.js +++ b/src/components/ImageEditor.js @@ -1,33 +1,231 @@ import React, {Component} from 'react'; +import Cropper from 'cropperjs'; +import 'font-awesome/css/font-awesome.min.css'; +import 'cropperjs/dist/cropper.css'; import '../css/ImageEditor.css'; class ImageEditor extends Component { + constructor(props) { super(props); + this.state = { - mediaSource: '' - } + cropped: false, + cropping: false, + name: '', + previousUrl: '', + type: '', + url: '', + enableEditor: false + } ; + + this.canvasData = null; + this.cropBoxData = null; + this.croppedData = null; + this.cropper = null; } componentDidMount () { const {mediaSource} = this.props; this.setState({ - mediaSource: mediaSource + ...this.state, + url: mediaSource }) } + cropperSetup=()=>{ + + const image = document.getElementsByClassName('image')[0]; + this.cropper = new Cropper(image, { + autoCrop: false, + dragMode: 'move', + background: false, + + ready: () => { + if (this.croppedData) { + this.cropper + .crop() + .setData(this.croppedData) + .setCanvasData(this.canvasData) + .setCropBoxData(this.cropBoxData); + + this.croppedData = null; + this.canvasData = null; + this.cropBoxData = null; + } + }, + + crop: ({ detail }) => { + if (detail.width > 0 && detail.height > 0 && !this.state.cropping) { + this.update({ + cropping: true, + }); + } + }, + }); + } + + stop() { + if (this.cropper) { + this.cropper.destroy(); + this.canvasData = null; + this.cropBoxData = null; + this.croppedData = null; + this.cropper = null; + } + } + + crop = () => { + const { cropper} = this; + const { cropping, url, type } = this.state; + + if (cropping) { + this.croppedData = cropper.getData(); + this.canvasData = cropper.getCanvasData(); + this.cropBoxData = cropper.getCropBoxData(); + this.update({ + cropped: true, + cropping: false, + previousUrl: url, + url: cropper.getCroppedCanvas(type === 'image/png' ? {} : { + fillColor: '#fff', + }).toDataURL(type), + }); + cropper.clear(); + } + } + + clear = () => { + const { cropping } = this.state; + if (cropping) { + this.cropper.clear(); + this.update({ + cropping: false, + }); + } + } + + restore = () => { + const { cropped } = this.state; + if (cropped) { + this.setState({ + ...this.state, + cropped: false, + previousUrl: '', + url: this.state.previousUrl + }, () => { + this.cropper.destroy(); + this.cropper = null; + this.cropperSetup(); + } + ); + } + } + + update = (updatedData) => { + this.setState({ + ...this.state, + ...updatedData + }, () => { + if(this.state.cropped) { + this.cropper.destroy(); + this.cropper = null; + this.cropperSetup(); + } + }); + } + + updateCropper = () => { + if(this.cropper) + this.cropper.destroy(); + this.canvasData = null; + this.cropBoxData = null; + this.croppedData = null; + this.cropper = null; + this.cropperSetup(); + } + + editAction = (e) => { + if(this.state.url!=='') { + const { cropper } = this; + let action = e.currentTarget.dataset.action; + switch (action) { + case 'move': + break; + + case 'crop': + cropper.setDragMode(action); + break; + + case 'zoom-in': + cropper.zoom(0.1); + break; + + case 'zoom-out': + cropper.zoom(-0.1); + break; + + case 'rotate-left': + cropper.rotate(-90); + break; + + case 'rotate-right': + cropper.rotate(90); + break; + + case 'flip-horizontal': + cropper.scaleX(-cropper.getData().scaleX || -1); + break; + + case 'flip-vertical': + cropper.scaleY(-cropper.getData().scaleY || -1); + break; + + default: + } + } + } + + enableEditor = () => { + this.setState({ + ...this.state, + enableEditor: true + }); + this.cropperSetup(); + } + render () { return (
- editable-img - - -
+
+ editable-img + +
+ {!this.state.enableEditor && + } + {this.state.enableEditor && +
+ + + + + + + + + + + + +
+ } + ) } } diff --git a/src/components/MultimediaJSX.js b/src/components/MultimediaJSX.js index 18791c9d..49fa7222 100644 --- a/src/components/MultimediaJSX.js +++ b/src/components/MultimediaJSX.js @@ -40,7 +40,7 @@ export function QuestionOptionsJSX(props){ export function QuestionJSX(props){ let question; - let {questionType, questionData, handleChangeQues, showMedia, speak} = props; + let {questionType, questionData, handleChangeQues, showMedia, speak, setImageEditorSource} = props; if( questionType === MULTIMEDIA.text) question = ( {showMedia(questionData)}} + onClick = {()=>{showMedia(questionData, 'img', setImageEditorSource)}} alt="Question"/> ); @@ -93,7 +93,7 @@ export function QuestionJSX(props){ export function AnswerOptionsJSX(props){ - const {selectOptionType, resetOption, showMedia, speak, options, changeOrder, handleChangeOption, templateType} = props; + const {selectOptionType, resetOption, showMedia, speak, options, changeOrder, handleChangeOption, templateType, setImageEditorSource} = props; // Answer-Options let answerOptions = options.map((option, i) => { if(!option.type) @@ -165,7 +165,7 @@ export function AnswerOptionsJSX(props){
{showMedia(option.data)}} + onClick = {()=>{showMedia(option.data, 'img', setImageEditorSource(i))}} alt="Option"/>
, } - {this.state.enableEditor && + {this.state.enableEditor &&
@@ -222,7 +241,9 @@ class ImageEditor extends Component { - +
} @@ -230,4 +251,4 @@ class ImageEditor extends Component { } } -export default ImageEditor; \ No newline at end of file +export default ImageEditor; From 12d34b8aa8eee94b39cfa8c9fa7585f38beb564c Mon Sep 17 00:00:00 2001 From: AvinashAgarwal14 Date: Sat, 10 Aug 2019 00:39:26 +0530 Subject: [PATCH 6/8] image editor save for all operations --- src/components/ImageEditor.js | 98 +++++++++++++++++++------------- src/components/WithMultimedia.js | 69 ++++++++++++---------- src/css/ImageEditor.css | 22 +++++-- src/icons/exercise/dialog-ok.svg | 6 ++ 4 files changed, 119 insertions(+), 76 deletions(-) create mode 100644 src/icons/exercise/dialog-ok.svg diff --git a/src/components/ImageEditor.js b/src/components/ImageEditor.js index f87af5d3..0bee9540 100644 --- a/src/components/ImageEditor.js +++ b/src/components/ImageEditor.js @@ -12,7 +12,6 @@ class ImageEditor extends Component { this.state = { cropped: false, cropping: false, - name: '', previousUrl: '', type: '', url: '', @@ -65,16 +64,6 @@ class ImageEditor extends Component { }); } - stop() { - if (this.cropper) { - this.cropper.destroy(); - this.canvasData = null; - this.cropBoxData = null; - this.croppedData = null; - this.cropper = null; - } - } - crop = () => { const { cropper} = this; const { cropping, url, type } = this.state; @@ -97,20 +86,23 @@ class ImageEditor extends Component { save = () => { const { cropper} = this; - const { cropping, url, type } = this.state; - - this.croppedData = cropper.getData(); - this.canvasData = cropper.getCanvasData(); - this.cropBoxData = cropper.getCropBoxData(); - this.update({ - cropped: true, - cropping: false, - previousUrl: url, - url: cropper.getCroppedCanvas(type === 'image/png' ? {} : { - fillColor: '#fff', - }).toDataURL(type), - }); - cropper.clear(); + const {url, type } = this.state; + + if(cropper) { + this.croppedData = cropper.getData(); + this.canvasData = cropper.getCanvasData(); + this.cropBoxData = cropper.getCropBoxData(); + this.update({ + previousUrl: url, + url: cropper.getCroppedCanvas(type === 'image/png' ? {} : { + fillColor: '#fff', + }).toDataURL(type), + }); + cropper.clear(); + this.canvasData = null; + this.cropBoxData = null; + this.croppedData = null; + } } clear = () => { @@ -124,17 +116,16 @@ class ImageEditor extends Component { } restore = () => { - const { cropped } = this.state; - if (cropped) { + const { previousUrl } = this.state; + if (previousUrl) { this.setState({ ...this.state, - cropped: false, + cropper: false, + cropping: false, previousUrl: '', url: this.state.previousUrl }, () => { - this.cropper.destroy(); - this.cropper = null; - this.cropperSetup(); + this.updateCropper(); } ); } @@ -146,9 +137,12 @@ class ImageEditor extends Component { ...updatedData }, () => { if(this.state.cropped) { - this.cropper.destroy(); - this.cropper = null; - this.cropperSetup(); + this.updateCropper(); + this.setState({ + ...this.state, + cropped: false, + cropping: false + }) } }); } @@ -190,14 +184,17 @@ class ImageEditor extends Component { case 'rotate-right': cropper.rotate(90); + this.save(); break; case 'flip-horizontal': cropper.scaleX(-cropper.getData().scaleX || -1); + this.save(); break; case 'flip-vertical': cropper.scaleY(-cropper.getData().scaleY || -1); + this.save(); break; default: @@ -223,10 +220,32 @@ class ImageEditor extends Component { > - {!this.state.enableEditor && + {!this.state.enableEditor && +
+ , + +
+ } + {this.state.enableEditor && +
+ + +
} {this.state.enableEditor &&
@@ -241,9 +260,6 @@ class ImageEditor extends Component { -
} diff --git a/src/components/WithMultimedia.js b/src/components/WithMultimedia.js index 2bed84da..b94820c8 100644 --- a/src/components/WithMultimedia.js +++ b/src/components/WithMultimedia.js @@ -23,9 +23,9 @@ const modalStyle = { const withMultimedia = (defaultThumbnail) => (Component) => { class MultimediaHoc extends React.Component { - + constructor(props) { - super(props); + super(props); this.state = { thumbnail: '', userLanguage: '', @@ -38,12 +38,12 @@ const withMultimedia = (defaultThumbnail) => (Component) => { componentDidMount() { if (this.props.location.state) { const { thumbnail, userLanguage } = this.props.location.state.exercise; - let newThumbnail = thumbnail; - + let newThumbnail = thumbnail; + // For default exercises if(thumbnail && !thumbnail.startsWith('data:image') && !thumbnail.includes('/static/')) newThumbnail = require(`../images/defaultExerciseThumbnail/${thumbnail}`); - + this.setState({ ...this.state, thumbnail: newThumbnail, @@ -92,13 +92,13 @@ const withMultimedia = (defaultThumbnail) => (Component) => { this.setState({ ...this.state, thumbnail: text - }); + }); }); }, {mimetype: 'image/png'}, {mimetype: 'image/jpeg'}); } }); }; - + closeModal = () => { this.setState({ ...this.state, @@ -123,17 +123,17 @@ const withMultimedia = (defaultThumbnail) => (Component) => { onRequestClose={this.closeModal} style={modalStyle} > - {this.state.modalMediaType === 'img' && + {this.state.modalMediaType === 'img' && non-editable img } - {this.state.modalMediaType === 'video' && + {this.state.modalMediaType === 'video' && } - @@ -147,23 +147,27 @@ const withMultimedia = (defaultThumbnail) => (Component) => { onRequestClose={this.closeModal} style={modalStyle} > - {this.state.modalMediaType === 'img' && + {this.state.modalMediaType === 'img' && } - {this.state.modalMediaType === 'video' && - } - + {this.state.modalMediaType === 'video' && +
+ + +
+ } ); } - + deleteThumbnail = () => { this.setState({ ...this.state, @@ -171,6 +175,13 @@ const withMultimedia = (defaultThumbnail) => (Component) => { }); } + setThumbnail = (url) => { + this.setState({ + ...this.state, + thumbnail: url + }); + } + render() { // Thumbnail @@ -180,9 +191,7 @@ const withMultimedia = (defaultThumbnail) => (Component) => {
{this.showMedia(defaultThumbnail, 'img', (url)=>{ - this.setState({...this.state, thumbnail: url}) - })}} + onClick = {() => {this.showMedia(defaultThumbnail, 'img', this.setThumbnail)}} alt="Thumbnail"/>
); @@ -191,11 +200,9 @@ const withMultimedia = (defaultThumbnail) => (Component) => {
{this.showMedia(this.state.thumbnail, 'img', (url)=>{ - this.setState({...this.state, thumbnail: url}) - })}} + onClick = {() => {this.showMedia(this.state.thumbnail, 'img', this.setThumbnail)}} alt="Thumbnail"/> -
@@ -207,8 +214,8 @@ const withMultimedia = (defaultThumbnail) => (Component) => { {...this.props} srcThumbnail={this.state.thumbnail} userLanguage={this.state.userLanguage} - thumbnail={thumbnail} - insertThumbnail={this.insertThumbnail} + thumbnail={thumbnail} + insertThumbnail={this.insertThumbnail} showMedia={this.showMedia} ShowModalWindow = {this.showModalWindow} ShowEditableModalWindow = {this.showEditableModalWindow} @@ -220,4 +227,4 @@ const withMultimedia = (defaultThumbnail) => (Component) => { return MultimediaHoc; } -export default withMultimedia \ No newline at end of file +export default withMultimedia diff --git a/src/css/ImageEditor.css b/src/css/ImageEditor.css index a89d9e91..7948e0ca 100644 --- a/src/css/ImageEditor.css +++ b/src/css/ImageEditor.css @@ -10,7 +10,7 @@ } .modal-close-button { - background-image: url('../icons/exercise/delete.svg'); + background-image: url('../icons/exercise/dialog-cancel.svg'); position: absolute; right: 0px; width: 50px; @@ -23,6 +23,20 @@ background-repeat: no-repeat; } +.modal-save-button { + background-image: url('../icons/exercise/dialog-ok.svg'); + position: absolute; + right: 60px; + width: 50px; + height: 50px; + margin-top: 10px; + top: 0px; + border-radius: 25px; + background-position: center; + background-size: contain; + background-repeat: no-repeat; +} + .modal-edit-button { background-image: url('../icons/exercise/edit.svg'); position: absolute; @@ -58,9 +72,9 @@ color: #fff; height: 2rem; left: 50%; - margin-left: -22em; + margin-left: -20em; position: absolute; - width: 44rem; + width: 40rem; } .toolbar__button { @@ -74,4 +88,4 @@ height: 2rem; text-align: center; width: 3rem; -} \ No newline at end of file +} diff --git a/src/icons/exercise/dialog-ok.svg b/src/icons/exercise/dialog-ok.svg new file mode 100644 index 00000000..69e5a2a1 --- /dev/null +++ b/src/icons/exercise/dialog-ok.svg @@ -0,0 +1,6 @@ + + +]> + + \ No newline at end of file From a4884da561a320386f35f20235d59976359b3428 Mon Sep 17 00:00:00 2001 From: AvinashAgarwal14 Date: Sun, 11 Aug 2019 02:15:51 +0530 Subject: [PATCH 7/8] editor changes --- src/components/ImageEditor.js | 14 +++++++++----- src/css/ImageEditor.css | 8 ++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/components/ImageEditor.js b/src/components/ImageEditor.js index 0bee9540..53d369f3 100644 --- a/src/components/ImageEditor.js +++ b/src/components/ImageEditor.js @@ -171,10 +171,12 @@ class ImageEditor extends Component { case 'zoom-in': cropper.zoom(0.1); + this.save(); break; case 'zoom-out': cropper.zoom(-0.1); + this.save(); break; case 'rotate-left': @@ -227,21 +229,25 @@ class ImageEditor extends Component { className = "modal-edit-button"> , } {this.state.enableEditor &&
- @@ -258,8 +264,6 @@ class ImageEditor extends Component { - -
} diff --git a/src/css/ImageEditor.css b/src/css/ImageEditor.css index 7948e0ca..6a8b7284 100644 --- a/src/css/ImageEditor.css +++ b/src/css/ImageEditor.css @@ -12,7 +12,7 @@ .modal-close-button { background-image: url('../icons/exercise/dialog-cancel.svg'); position: absolute; - right: 0px; + right: 60px; width: 50px; height: 50px; margin-top: 10px; @@ -26,7 +26,7 @@ .modal-save-button { background-image: url('../icons/exercise/dialog-ok.svg'); position: absolute; - right: 60px; + right: 0px; width: 50px; height: 50px; margin-top: 10px; @@ -72,9 +72,9 @@ color: #fff; height: 2rem; left: 50%; - margin-left: -20em; + margin-left: -16.5em; position: absolute; - width: 40rem; + width: 33rem; } .toolbar__button { From 11e30c599f0c0c6c9deb86722e3a85bd4995ef53 Mon Sep 17 00:00:00 2001 From: AvinashAgarwal14 Date: Mon, 12 Aug 2019 01:36:01 +0530 Subject: [PATCH 8/8] crop issue fixed --- src/components/ImageEditor.js | 39 +++++------------------------------ 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/src/components/ImageEditor.js b/src/components/ImageEditor.js index 53d369f3..ccd4e226 100644 --- a/src/components/ImageEditor.js +++ b/src/components/ImageEditor.js @@ -18,9 +18,6 @@ class ImageEditor extends Component { enableEditor: false } ; - this.canvasData = null; - this.cropBoxData = null; - this.croppedData = null; this.cropper = null; } @@ -40,20 +37,6 @@ class ImageEditor extends Component { dragMode: 'move', background: false, - ready: () => { - if (this.croppedData) { - this.cropper - .crop() - .setData(this.croppedData) - .setCanvasData(this.canvasData) - .setCropBoxData(this.cropBoxData); - - this.croppedData = null; - this.canvasData = null; - this.cropBoxData = null; - } - }, - crop: ({ detail }) => { if (detail.width > 0 && detail.height > 0 && !this.state.cropping) { this.update({ @@ -69,9 +52,6 @@ class ImageEditor extends Component { const { cropping, url, type } = this.state; if (cropping) { - this.croppedData = cropper.getData(); - this.canvasData = cropper.getCanvasData(); - this.cropBoxData = cropper.getCropBoxData(); this.update({ cropped: true, cropping: false, @@ -89,9 +69,6 @@ class ImageEditor extends Component { const {url, type } = this.state; if(cropper) { - this.croppedData = cropper.getData(); - this.canvasData = cropper.getCanvasData(); - this.cropBoxData = cropper.getCropBoxData(); this.update({ previousUrl: url, url: cropper.getCroppedCanvas(type === 'image/png' ? {} : { @@ -99,9 +76,6 @@ class ImageEditor extends Component { }).toDataURL(type), }); cropper.clear(); - this.canvasData = null; - this.cropBoxData = null; - this.croppedData = null; } } @@ -138,11 +112,8 @@ class ImageEditor extends Component { }, () => { if(this.state.cropped) { this.updateCropper(); - this.setState({ - ...this.state, - cropped: false, - cropping: false - }) + this.props.setMediaSource(this.state.url); + this.props.onClose(); } }); } @@ -150,9 +121,6 @@ class ImageEditor extends Component { updateCropper = () => { if(this.cropper) this.cropper.destroy(); - this.canvasData = null; - this.cropBoxData = null; - this.croppedData = null; this.cropper = null; this.cropperSetup(); } @@ -237,9 +205,12 @@ class ImageEditor extends Component { {this.state.enableEditor &&