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

show loading indicator for keymap

Yuki Takei 8 лет назад
Родитель
Сommit
bf4dd590ac
2 измененных файлов с 85 добавлено и 49 удалено
  1. 44 15
      resource/js/components/PageEditor/Editor.js
  2. 41 34
      resource/styles/scss/_on-edit.scss

+ 44 - 15
resource/js/components/PageEditor/Editor.js

@@ -54,6 +54,7 @@ export default class Editor extends React.Component {
       value: this.props.value,
       dropzoneActive: false,
       isUploading: false,
+      isLoadingKeymap: false,
     };
 
     this.loadedThemeSet = new Set(['eclipse', 'elegant']);   // themes imported in _vendor.scss
@@ -78,7 +79,9 @@ export default class Editor extends React.Component {
 
     this.getDropzoneAccept = this.getDropzoneAccept.bind(this);
     this.getDropzoneClassName = this.getDropzoneClassName.bind(this);
-    this.renderOverlay = this.renderOverlay.bind(this);
+    this.renderDropzoneOverlay = this.renderDropzoneOverlay.bind(this);
+
+    this.renderLoadingKeymapOverlay = this.renderLoadingKeymapOverlay.bind(this);
   }
 
 
@@ -194,7 +197,13 @@ export default class Editor extends React.Component {
       this.loadedKeymapSet.add(keymapMode);
     }
 
-    return Promise.all(scriptList.concat(cssList));
+    // set loading state
+    this.setState({ isLoadingKeymap: true });
+
+    return Promise.all(scriptList.concat(cssList))
+      .then(() => {
+        this.setState({ isLoadingKeymap: false });
+      })
   }
 
   /**
@@ -211,9 +220,9 @@ export default class Editor extends React.Component {
     }
 
     this.loadKeymapMode(keymapMode)
-    .then(() => {
-      this.getCodeMirror().setOption('keyMap', keymapMode);
-    });
+      .then(() => {
+        this.getCodeMirror().setOption('keyMap', keymapMode);
+      });
   }
 
   /**
@@ -376,8 +385,8 @@ export default class Editor extends React.Component {
     return className;
   }
 
-  renderOverlay() {
-    const overlayStyle = {
+  getOverlayStyle() {
+    return {
       position: 'absolute',
       zIndex: 4,  // forward than .CodeMirror-gutters
       top: 0,
@@ -385,20 +394,36 @@ export default class Editor extends React.Component {
       bottom: 0,
       left: 0,
     };
+  }
+
+  renderDropzoneOverlay() {
+    const overlayStyle = this.getOverlayStyle();
 
     return (
-      <div style={overlayStyle} className="dropzone-overlay">
+      <div style={overlayStyle} className="overlay">
         {this.state.isUploading &&
-          <span className="dropzone-overlay-content">
-            <i className="fa fa-spinner fa-pulse fa-fw"></i>
+          <span className="overlay-content">
+            <div className="speeding-wheel d-inline-block"></div>
             <span className="sr-only">Uploading...</span>
           </span>
         }
-        {!this.state.isUploading && <span className="dropzone-overlay-content"></span>}
+        {!this.state.isUploading && <span className="overlay-content"></span>}
       </div>
     );
   }
 
+  renderLoadingKeymapOverlay() {
+    const overlayStyle = this.getOverlayStyle();
+
+    return this.state.isLoadingKeymap
+      ? <div style={overlayStyle} className="loading-keymap overlay">
+          <span className="overlay-content">
+            <div className="speeding-wheel d-inline-block"></div> Loading Keymap ...
+          </span>
+        </div>
+      : '';
+  }
+
   render() {
     const flexContainer = {
       height: '100%',
@@ -408,7 +433,7 @@ export default class Editor extends React.Component {
 
     const theme = this.props.editorOptions.theme || 'elegant';
     const styleActiveLine = this.props.editorOptions.styleActiveLine || undefined;
-    return (
+    return <React.Fragment>
       <div style={flexContainer}>
         <Dropzone
           ref="dropzone"
@@ -422,7 +447,7 @@ export default class Editor extends React.Component {
           onDragLeave={this.onDragLeave}
           onDrop={this.onDrop}
         >
-          { this.state.dropzoneActive && this.renderOverlay() }
+          { this.state.dropzoneActive && this.renderDropzoneOverlay() }
 
           <ReactCodeMirror
             ref="cm"
@@ -480,15 +505,19 @@ export default class Editor extends React.Component {
         </Dropzone>
 
         <button type="button" className="btn btn-default btn-block btn-open-dropzone"
-            onClick={() => {this.refs.dropzone.open()}}>
+          onClick={() => {this.refs.dropzone.open()}}>
 
           <i className="icon-paper-clip" aria-hidden="true"></i>&nbsp;
           Attach files by dragging &amp; dropping,&nbsp;
           <span className="btn-link">selecting them</span>,&nbsp;
           or pasting from the clipboard.
         </button>
+
+        { this.renderLoadingKeymapOverlay() }
+
       </div>
-    );
+
+    </React.Fragment>;
   }
 
 }

+ 41 - 34
resource/styles/scss/_on-edit.scss

@@ -184,9 +184,33 @@ body.on-edit {
       }
     }
 
+    .overlay {
+      // layout
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      // style
+      margin: 0 15px;
+    }
+    .overlay-content {
+      font-size: 2.5em;
+      padding: 0.5em;
+    }
+
+    @mixin overlay-processing-style() {
+      .overlay {
+        background: rgba(255,255,255,0.5);
+      }
+      .overlay-content {
+        padding: 0.3em;
+        background: rgba(200,200,200,0.5);
+        color: #444;
+      }
+    }
+
     // for Dropzone
     .dropzone {
-      @mixin insertFontAwesome($code) {
+      @mixin insertSimpleLineIcons($code) {
         &:before {
           margin-right: 0.2em;
           font-family: 'simple-line-icons';
@@ -194,46 +218,25 @@ body.on-edit {
         }
       }
 
-      // default layout and style
-      .dropzone-overlay {
-        // layout
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        // style
-        margin: 0 15px;
-      }
-      .dropzone-overlay-content {
-        font-size: 2.5em;
-        padding: 0.5em;
-      }
-
       // unuploadable or rejected
       &.dropzone-unuploadable, &.dropzone-rejected {
-        .dropzone-overlay {
+        .overlay {
           background: rgba(200,200,200,0.8);
         }
-        .dropzone-overlay-content {
+        .overlay-content {
           color: #444;
         }
       }
       // uploading
       &.dropzone-uploading {
-        .dropzone-overlay {
-          background: rgba(255,255,255,0.5);
-        }
-        .dropzone-overlay-content {
-          padding: 0.3em;
-          background: rgba(200,200,200,0.5);
-          color: #444;
-        }
+        @include overlay-processing-style();
       }
 
       // unuploadable
       &.dropzone-unuploadable {
-        .dropzone-overlay-content {
+        .overlay-content {
           // insert content
-          @include insertFontAwesome("\e617");  // icon-exclamation
+          @include insertSimpleLineIcons("\e617");  // icon-exclamation
           &:after {
             content: "File uploading is disabled";
           }
@@ -243,12 +246,12 @@ body.on-edit {
       &.dropzone-uploadable {
         // accepted
         &.dropzone-accepted:not(.dropzone-rejected) {
-          .dropzone-overlay {
+          .overlay {
             border: 4px dashed #ccc;
           }
-          .dropzone-overlay-content {
+          .overlay-content {
             // insert content
-            @include insertFontAwesome("\e084");  // icon-cloud-upload
+            @include insertSimpleLineIcons("\e084");  // icon-cloud-upload
             &:after {
               content: "Drop here to upload";
             }
@@ -258,17 +261,17 @@ body.on-edit {
           }
         }
         // file type mismatch
-        &.dropzone-rejected:not(.dropzone-uploadablefile) .dropzone-overlay-content {
+        &.dropzone-rejected:not(.dropzone-uploadablefile) .overlay-content {
           // insert content
-          @include insertFontAwesome("\e032");  // icon-picture
+          @include insertSimpleLineIcons("\e032");  // icon-picture
           &:after {
             content: "Only an image file is allowed";
           }
         }
         // multiple files
-        &.dropzone-accepted.dropzone-rejected .dropzone-overlay-content {
+        &.dropzone-accepted.dropzone-rejected .overlay-content {
           // insert content
-          @include insertFontAwesome("\e617");  // icon-exclamation
+          @include insertSimpleLineIcons("\e617");  // icon-exclamation
           &:after {
             content: "Only 1 file is allowed";
           }
@@ -276,6 +279,10 @@ body.on-edit {
       }
     } // end of.dropzone
 
+    .loading-keymap {
+      @include overlay-processing-style();
+    }
+
     .btn-open-dropzone {
       z-index: 2;
       font-size: small;