Просмотр исходного кода

WIP: replace inline-attachment with Dropzone.js

control accept and reject styles
Yuki Takei 8 лет назад
Родитель
Сommit
dcba7463f8
3 измененных файлов с 96 добавлено и 51 удалено
  1. 54 11
      resource/css/_form.scss
  2. 4 0
      resource/js/components/PageEditor.js
  3. 38 40
      resource/js/components/PageEditor/Editor.js

+ 54 - 11
resource/css/_form.scss

@@ -79,6 +79,7 @@
       }
       }
     }
     }
 
 
+    // for Dropzone
     .dropzone-overlay {
     .dropzone-overlay {
       // layout
       // layout
       display: flex;
       display: flex;
@@ -88,18 +89,60 @@
       font-size: 2em;
       font-size: 2em;
       margin: 0 15px;
       margin: 0 15px;
 
 
-      > * {
-        pointer-events: none;
-      }
-    }
-    .dropzone-overlay-activated {
-      color: #ccc;
-      border: 4px dashed #999;
-    }
-    .dropzone-overlay-disabled {
-      background: rgba(0,0,0,0.5);
-      color: #333;
+      // > * {
+      //   pointer-events: none;
+      // }
     }
     }
+    .dropzone {
+      // unuploadable or rejected
+      &.dropzone-unuploadable, &.dropzone-rejected {
+        .dropzone-overlay {
+          background: rgba(0,0,0,0.5);
+          color: #333;
+        }
+      }
+      // uploadable
+      &.dropzone-uploadable {
+        &.dropzone-accepted .dropzone-overlay {
+          color: #ccc;
+          border: 4px dashed #ccc;
+          // insert content
+          &:before {
+            content: "\f093";   // fa-upload
+            font-family: FontAwesome;
+            margin-right: 0.5em;
+          }
+          &:after {
+            content: "Drop here to upload";
+          }
+        }
+        // file type mismatch
+        &.dropzone-rejected:not(.dropzone-uploadablefile) .dropzone-overlay {
+          // insert content
+          &:before {
+            content: "\f03e";   // fa-upload
+            font-family: FontAwesome;
+            margin-right: 0.5em;
+          }
+          &:after {
+            content: "Only Image files are allowed";
+          }
+        }
+        // multiple files
+        &.dropzone-rejected.dropzone-uploadablefile .dropzone-overlay {
+          // insert content
+          &:before {
+            content: "\f071";   // fa-upload
+            font-family: FontAwesome;
+            margin-right: 0.5em;
+          }
+          &:after {
+            content: "Only 1 file allowed";
+          }
+        }
+      }
+    } // end of.dropzone
+
   }
   }
   .page-editor-preview-container {
   .page-editor-preview-container {
   }
   }

+ 4 - 0
resource/js/components/PageEditor.js

@@ -14,10 +14,13 @@ export default class PageEditor extends React.Component {
 
 
     const config = this.props.crowi.getConfig();
     const config = this.props.crowi.getConfig();
     const isUploadable = config.upload.image || config.upload.file;
     const isUploadable = config.upload.image || config.upload.file;
+    const isUploadableFile = config.upload.file;
+
     this.state = {
     this.state = {
       revisionId: this.props.revisionId,
       revisionId: this.props.revisionId,
       markdown: this.props.markdown,
       markdown: this.props.markdown,
       isUploadable,
       isUploadable,
+      isUploadableFile,
     };
     };
 
 
     this.setCaretLine = this.setCaretLine.bind(this);
     this.setCaretLine = this.setCaretLine.bind(this);
@@ -271,6 +274,7 @@ export default class PageEditor extends React.Component {
         <div className="col-md-6 col-sm-12 page-editor-editor-container">
         <div className="col-md-6 col-sm-12 page-editor-editor-container">
           <Editor ref="editor" value={this.state.markdown}
           <Editor ref="editor" value={this.state.markdown}
               isUploadable={this.state.isUploadable}
               isUploadable={this.state.isUploadable}
+              isUploadableFile={this.state.isUploadableFile}
               onScroll={this.onEditorScroll}
               onScroll={this.onEditorScroll}
               onChange={this.onMarkdownChanged}
               onChange={this.onMarkdownChanged}
               onSave={this.onSave}
               onSave={this.onSave}

+ 38 - 40
resource/js/components/PageEditor/Editor.js

@@ -34,7 +34,6 @@ export default class Editor extends React.Component {
 
 
     this.state = {
     this.state = {
       value: this.props.value,
       value: this.props.value,
-      dropzoneAccept: '',
       dropzoneActive: false,
       dropzoneActive: false,
     };
     };
 
 
@@ -43,7 +42,7 @@ export default class Editor extends React.Component {
     this.forceToFocus = this.forceToFocus.bind(this);
     this.forceToFocus = this.forceToFocus.bind(this);
     this.dispatchSave = this.dispatchSave.bind(this);
     this.dispatchSave = this.dispatchSave.bind(this);
 
 
-    this.onDragEnter = this.onDragEnter.bind(this);
+    this.onDragEnterForCM = this.onDragEnterForCM.bind(this);
     this.onDragLeave = this.onDragLeave.bind(this);
     this.onDragLeave = this.onDragLeave.bind(this);
     this.onDrop = this.onDrop.bind(this);
     this.onDrop = this.onDrop.bind(this);
 
 
@@ -108,8 +107,13 @@ export default class Editor extends React.Component {
     }
     }
   }
   }
 
 
-  onDragEnter(event) {
-    console.log('dragenter', event);
+  onDragEnterForCM(editor, event) {
+    const dataTransfer = event.dataTransfer;
+
+    // do nothing if contents is not files
+    if (!dataTransfer.types.includes('Files')) {
+      return;
+    }
 
 
     this.setState({
     this.setState({
       dropzoneActive: true
       dropzoneActive: true
@@ -122,18 +126,18 @@ export default class Editor extends React.Component {
     });
     });
   }
   }
 
 
-  onDrop(files) {
-    if (!this.props.isUploadable) {
-      return;
-    }
+  onDrop(accepted, rejected) {
+    // if (!this.props.isUploadable) {
+    //   return;
+    // }
 
 
-    this.setState({
-      dropzoneActive: false
-    });
+    // this.setState({
+    //   dropzoneActive: false
+    // });
 
 
-    // TODO abort multi files
+    // // TODO abort multi files
 
 
-    this.dispatchUpload(files[0]);
+    // this.dispatchUpload(files[0]);
   }
   }
 
 
   renderOverlayMessage() {
   renderOverlayMessage() {
@@ -146,31 +150,8 @@ export default class Editor extends React.Component {
       left: 0,
       left: 0,
     };
     };
 
 
-    let overlayClassName;
-    let message;
-    if (this.props.isUploadable) {
-      overlayClassName = 'dropzone-overlay dropzone-overlay-activated';
-      message = (
-        <span>
-          <i className="fa fa-fw fa-upload" aria-hidden="true"></i>
-          Upload to drop here
-        </span>
-      );
-    }
-    else {
-      overlayClassName = 'dropzone-overlay dropzone-overlay-disabled';
-      message = (
-        <span>
-          <i className="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
-          Uploading is disabled
-        </span>
-      );
-    }
-
     return (
     return (
-      <div style={overlayStyle} className={overlayClassName}>
-        {message}
-      </div>
+      <div style={overlayStyle} className="dropzone-overlay"></div>
     );
     );
   }
   }
 
 
@@ -179,12 +160,28 @@ export default class Editor extends React.Component {
       height: '100%'
       height: '100%'
     }
     }
 
 
+    let accept = null;
+    let className = 'dropzone';
+    if (this.props.isUploadable) {
+      accept = 'image/*'
+      className += ' dropzone-uploadable';
+
+      if (this.props.isUploadableFile) {
+        className += ' dropzone-uploadablefile';
+        accept = '';
+      }
+    }
+
     return (
     return (
       <Dropzone
       <Dropzone
         disableClick
         disableClick
+        disablePreview={true}
         style={dropzoneStyle}
         style={dropzoneStyle}
-        accept={this.state.accept}
-        onDragEnter={this.onDragEnter}
+        accept={accept}
+        className={className}
+        acceptClassName="dropzone-accepted"
+        rejectClassName="dropzone-rejected"
+        multiple={false}
         onDragLeave={this.onDragLeave}
         onDragLeave={this.onDragLeave}
         onDrop={this.onDrop}
         onDrop={this.onDrop}
       >
       >
@@ -232,7 +229,7 @@ export default class Editor extends React.Component {
             // Emoji AutoComplete
             // Emoji AutoComplete
             emojiAutoCompleteHelper.showHint(editor);
             emojiAutoCompleteHelper.showHint(editor);
           }}
           }}
-          // onDragEnter={this.onDragEnter}
+          onDragEnter={this.onDragEnterForCM}
         />
         />
       </Dropzone>
       </Dropzone>
     )
     )
@@ -243,6 +240,7 @@ export default class Editor extends React.Component {
 Editor.propTypes = {
 Editor.propTypes = {
   value: PropTypes.string,
   value: PropTypes.string,
   isUploadable: PropTypes.bool,
   isUploadable: PropTypes.bool,
+  isUploadableFile: PropTypes.bool,
   onChange: PropTypes.func,
   onChange: PropTypes.func,
   onScroll: PropTypes.func,
   onScroll: PropTypes.func,
   onSave: PropTypes.func,
   onSave: PropTypes.func,