Jelajahi Sumber

Merge pull request #3858 from mfilser/more_spinners_and_configureable_in_admin_panel

More spinners + configureable in admin panel
Lauri Ojansivu 4 tahun lalu
induk
melakukan
611ac0ab57
37 mengubah file dengan 557 tambahan dan 58 penghapusan
  1. 2 1
      .devcontainer/Dockerfile
  2. 2 1
      Dockerfile
  3. 3 7
      client/components/lists/listBody.jade
  4. 39 26
      client/components/lists/listBody.js
  5. 5 0
      client/components/main/spinner.jade
  6. 11 0
      client/components/main/spinner.js
  7. 0 6
      client/components/main/spinner.tpl.jade
  8. 11 0
      client/components/main/spinner_bounce.jade
  9. 44 0
      client/components/main/spinner_bounce.styl
  10. 8 0
      client/components/main/spinner_cube.jade
  11. 52 0
      client/components/main/spinner_cube.styl
  12. 14 0
      client/components/main/spinner_cube_grid.jade
  13. 64 0
      client/components/main/spinner_cube_grid.styl
  14. 7 0
      client/components/main/spinner_dot.jade
  15. 51 0
      client/components/main/spinner_dot.styl
  16. 7 0
      client/components/main/spinner_double_bounce.jade
  17. 44 0
      client/components/main/spinner_double_bounce.styl
  18. 6 0
      client/components/main/spinner_rotateplane.jade
  19. 38 0
      client/components/main/spinner_rotateplane.styl
  20. 6 0
      client/components/main/spinner_scaleout.jade
  21. 40 0
      client/components/main/spinner_scaleout.styl
  22. 15 0
      client/components/main/spinner_wave.jade
  23. 2 16
      client/components/main/spinner_wave.styl
  24. 11 0
      client/components/settings/settingBody.jade
  25. 14 0
      client/components/settings/settingBody.js
  26. 27 0
      client/lib/spinner.js
  27. 10 0
      config/const.js
  28. 3 0
      docker-compose.yml
  29. 2 1
      i18n/en.i18n.json
  30. 4 0
      models/settings.js
  31. 3 0
      releases/virtualbox/start-wekan.sh
  32. 1 0
      server/publications/settings.js
  33. 3 0
      server/spinner.js
  34. 0 0
      snap-src/bin/config
  35. 2 0
      start-wekan.bat
  36. 3 0
      start-wekan.sh
  37. 3 0
      torodb-postgresql/docker-compose.yml

+ 2 - 1
.devcontainer/Dockerfile

@@ -130,7 +130,8 @@ ENV \
     SAML_PUBLIC_CERTFILE="" \
     SAML_IDENTIFIER_FORMAT="" \
     SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
-    SAML_ATTRIBUTES=""
+    SAML_ATTRIBUTES="" \
+    DEFAULT_WAIT_SPINNER=""
 
 # Install OS
 RUN set -o xtrace \

+ 2 - 1
Dockerfile

@@ -137,7 +137,8 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
     SAML_IDENTIFIER_FORMAT="" \
     SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
     SAML_ATTRIBUTES="" \
-    ORACLE_OIM_ENABLED=false
+    ORACLE_OIM_ENABLED=false \
+    DEFAULT_WAIT_SPINNER=""
 
 # Copy the app to the image
 COPY ${SRC_PATH} /home/wekan/app

+ 3 - 7
client/components/lists/listBody.jade

@@ -23,14 +23,10 @@ template(name="listBody")
             i.fa.fa-plus
 
 template(name="spinnerList")
-  .sk-spinner.sk-spinner-wave.sk-spinner-list(
-    class=currentBoard.colorClass
+  .sk-spinner.sk-spinner-list(
+    class="{{currentBoard.colorClass}} {{getSkSpinnerName}}"
     id="showMoreResults")
-    .sk-rect1
-    .sk-rect2
-    .sk-rect3
-    .sk-rect4
-    .sk-rect5
+    +spinnerRaw
 
 template(name="addCardForm")
   .minicard.minicard-composer.js-composer

+ 39 - 26
client/components/lists/listBody.js

@@ -1,3 +1,5 @@
+import { Spinner } from '/client/lib/spinner';
+
 const subManager = new SubsManager();
 const InfiniteScrollIter = 10;
 
@@ -696,7 +698,7 @@ BlazeComponent.extendComponent({
   },
 }).register('searchElementPopup');
 
-BlazeComponent.extendComponent({
+(class extends Spinner {
   onCreated() {
     this.cardlimit = this.parentComponent().cardlimit;
 
@@ -724,7 +726,7 @@ BlazeComponent.extendComponent({
         .parentComponent()
         .data()._id;
     }
-  },
+  }
 
   onRendered() {
     this.spinner = this.find('.sk-spinner-list');
@@ -739,47 +741,58 @@ BlazeComponent.extendComponent({
     );
 
     this.updateList();
-  },
+  }
 
   onDestroyed() {
     $(this.container).off(`scroll.spinner_${this.swimlaneId}_${this.listId}`);
     $(window).off(`resize.spinner_${this.swimlaneId}_${this.listId}`);
-  },
+  }
+
+  checkIdleTime() {
+    return window.requestIdleCallback ||
+    function(handler) {
+      const startTime = Date.now();
+      return setTimeout(function() {
+        handler({
+          didTimeout: false,
+          timeRemaining() {
+            return Math.max(0, 50.0 - (Date.now() - startTime));
+          },
+        });
+      }, 1);
+    };
+  }
 
   updateList() {
     // Use fallback when requestIdleCallback is not available on iOS and Safari
     // https://www.afasterweb.com/2017/11/20/utilizing-idle-moments/
-    checkIdleTime =
-      window.requestIdleCallback ||
-      function(handler) {
-        const startTime = Date.now();
-        return setTimeout(function() {
-          handler({
-            didTimeout: false,
-            timeRemaining() {
-              return Math.max(0, 50.0 - (Date.now() - startTime));
-            },
-          });
-        }, 1);
-      };
 
     if (this.spinnerInView()) {
       this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
-      checkIdleTime(() => this.updateList());
+      this.checkIdleTime(() => this.updateList());
     }
-  },
+  }
 
   spinnerInView() {
+    // spinner deleted
+    if (!this.spinner.offsetTop) {
+      return false;
+    }
+
     const parentViewHeight = this.container.clientHeight;
     const bottomViewPosition = this.container.scrollTop + parentViewHeight;
 
-    const threshold = this.spinner.offsetTop;
+    let spinnerOffsetTop = this.spinner.offsetTop;
 
-    // spinner deleted
-    if (!this.spinner.offsetTop) {
-      return false;
+    const addCard = $(this.container).find("a.open-minicard-composer").first()[0];
+    if (addCard !== undefined) {
+      spinnerOffsetTop -= addCard.clientHeight;
     }
 
-    return bottomViewPosition > threshold;
-  },
-}).register('spinnerList');
+    return bottomViewPosition > spinnerOffsetTop;
+  }
+
+  getSkSpinnerName() {
+    return "sk-spinner-" + super.getSpinnerName().toLowerCase();
+  }
+}.register('spinnerList'));

+ 5 - 0
client/components/main/spinner.jade

@@ -0,0 +1,5 @@
+template(name="spinner")
+  +Template.dynamic(template=getSpinnerTemplate)
+
+template(name="spinnerRaw")
+  +Template.dynamic(template=getSpinnerTemplateRaw)

+ 11 - 0
client/components/main/spinner.js

@@ -0,0 +1,11 @@
+import { Spinner } from '/client/lib/spinner';
+
+(class extends Spinner {
+}.register('spinner'));
+
+(class extends Spinner {
+  getSpinnerTemplateRaw() {
+    let ret = super.getSpinnerTemplate() + 'Raw';
+    return ret;
+  }
+}.register('spinnerRaw'));

+ 0 - 6
client/components/main/spinner.tpl.jade

@@ -1,6 +0,0 @@
-.sk-spinner.sk-spinner-wave(class=currentBoard.colorClass)
-  .sk-rect1
-  .sk-rect2
-  .sk-rect3
-  .sk-rect4
-  .sk-rect5

+ 11 - 0
client/components/main/spinner_bounce.jade

@@ -0,0 +1,11 @@
+template(name="spinnerBounce")
+  .sk-spinner.sk-spinner-bounce(class=currentBoard.colorClass)
+    +spinnerBounceRaw
+
+template(name="spinnerBounceRaw")
+  .sk-bounce1
+  |  
+  .sk-bounce2
+  |  
+  .sk-bounce3
+  |  

+ 44 - 0
client/components/main/spinner_bounce.styl

@@ -0,0 +1,44 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-bounce {
+  margin: 100px auto 0;
+  width: 70px;
+  text-align: center;
+
+  div {
+    width: 18px;
+    height: 18px;
+    background-color: #333;
+
+    border-radius: 100%;
+    display: inline-block;
+    -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
+    animation: sk-bouncedelay 1.4s infinite ease-in-out both;
+  }
+
+  .sk-bounce1 {
+    -webkit-animation-delay: -0.32s;
+    animation-delay: -0.32s;
+  }
+
+  .sk-bounce2 {
+    -webkit-animation-delay: -0.16s;
+    animation-delay: -0.16s;
+  }
+}
+
+@-webkit-keyframes sk-bouncedelay {
+  0%, 80%, 100% { -webkit-transform: scale(0) }
+  40% { -webkit-transform: scale(1.0) }
+}
+
+@keyframes sk-bouncedelay {
+  0%, 80%, 100% {
+    -webkit-transform: scale(0);
+    transform: scale(0);
+  } 40% {
+    -webkit-transform: scale(1.0);
+    transform: scale(1.0);
+  }
+}

+ 8 - 0
client/components/main/spinner_cube.jade

@@ -0,0 +1,8 @@
+template(name="spinnerCube")
+  .sk-spinner.sk-spinner-cube(class=currentBoard.colorClass)
+    +spinnerCubeRaw
+
+template(name="spinnerCubeRaw")
+  .sk-cube1
+  .sk-cube2
+  .sk-cube3

+ 52 - 0
client/components/main/spinner_cube.styl

@@ -0,0 +1,52 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-cube {
+  margin: 100px auto;
+  width: 40px;
+  height: 40px;
+  position: relative;
+}
+
+.sk-cube1, .sk-cube2 {
+  background-color: #333;
+  width: 15px;
+  height: 15px;
+  position: absolute;
+  top: 0;
+  left: 0;
+
+  -webkit-animation: sk-cubemove 1.8s infinite ease-in-out;
+  animation: sk-cubemove 1.8s infinite ease-in-out;
+}
+
+.sk-cube2 {
+  -webkit-animation-delay: -0.9s;
+  animation-delay: -0.9s;
+}
+
+@-webkit-keyframes sk-cubemove {
+  25% { -webkit-transform: translateX(35px) rotate(-90deg) scale(0.5) }
+  50% { -webkit-transform: translateX(35px) translateY(35px) rotate(-180deg) }
+  75% { -webkit-transform: translateX(0px) translateY(35px) rotate(-270deg) scale(0.5) }
+  100% { -webkit-transform: rotate(-360deg) }
+}
+
+@keyframes sk-cubemove {
+  25% {
+    transform: translateX(35px) rotate(-90deg) scale(0.5);
+    -webkit-transform: translateX(35px) rotate(-90deg) scale(0.5);
+  } 50% {
+    transform: translateX(35px) translateY(35px) rotate(-179deg);
+    -webkit-transform: translateX(35px) translateY(35px) rotate(-179deg);
+  } 50.1% {
+    transform: translateX(35px) translateY(35px) rotate(-180deg);
+    -webkit-transform: translateX(35px) translateY(35px) rotate(-180deg);
+  } 75% {
+    transform: translateX(0px) translateY(35px) rotate(-270deg) scale(0.5);
+    -webkit-transform: translateX(0px) translateY(35px) rotate(-270deg) scale(0.5);
+  } 100% {
+    transform: rotate(-360deg);
+    -webkit-transform: rotate(-360deg);
+  }
+}

+ 14 - 0
client/components/main/spinner_cube_grid.jade

@@ -0,0 +1,14 @@
+template(name="spinnerCubeGrid")
+  .sk-spinner.sk-spinner-cube-grid(class=currentBoard.colorClass)
+    +spinnerCubeGridRaw
+
+template(name="spinnerCubeGridRaw")
+  .sk-cube-grid.sk-cube-grid1
+  .sk-cube-grid.sk-cube-grid2
+  .sk-cube-grid.sk-cube-grid3
+  .sk-cube-grid.sk-cube-grid4
+  .sk-cube-grid.sk-cube-grid5
+  .sk-cube-grid.sk-cube-grid6
+  .sk-cube-grid.sk-cube-grid7
+  .sk-cube-grid.sk-cube-grid8
+  .sk-cube-grid.sk-cube-grid9

+ 64 - 0
client/components/main/spinner_cube_grid.styl

@@ -0,0 +1,64 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-cube-grid {
+  width: 40px;
+  height: 40px;
+  margin: 100px auto;
+}
+
+.sk-spinner-cube-grid .sk-cube-grid {
+  width: 33%;
+  height: 33%;
+  background-color: #333;
+  float: left;
+  -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
+          animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
+}
+.sk-spinner-cube-grid .sk-cube-grid1 {
+  -webkit-animation-delay: 0.2s;
+          animation-delay: 0.2s; }
+.sk-spinner-cube-grid .sk-cube-grid2 {
+  -webkit-animation-delay: 0.3s;
+          animation-delay: 0.3s; }
+.sk-spinner-cube-grid .sk-cube-grid3 {
+  -webkit-animation-delay: 0.4s;
+          animation-delay: 0.4s; }
+.sk-spinner-cube-grid .sk-cube-grid4 {
+  -webkit-animation-delay: 0.1s;
+          animation-delay: 0.1s; }
+.sk-spinner-cube-grid .sk-cube-grid5 {
+  -webkit-animation-delay: 0.2s;
+          animation-delay: 0.2s; }
+.sk-spinner-cube-grid .sk-cube-grid6 {
+  -webkit-animation-delay: 0.3s;
+          animation-delay: 0.3s; }
+.sk-spinner-cube-grid .sk-cube-grid7 {
+  -webkit-animation-delay: 0s;
+          animation-delay: 0s; }
+.sk-spinner-cube-grid .sk-cube-grid8 {
+  -webkit-animation-delay: 0.1s;
+          animation-delay: 0.1s; }
+.sk-spinner-cube-grid .sk-cube-grid9 {
+  -webkit-animation-delay: 0.2s;
+          animation-delay: 0.2s; }
+
+@-webkit-keyframes sk-cubeGridScaleDelay {
+  0%, 70%, 100% {
+    -webkit-transform: scale3D(1, 1, 1);
+            transform: scale3D(1, 1, 1);
+  } 35% {
+    -webkit-transform: scale3D(0, 0, 1);
+            transform: scale3D(0, 0, 1);
+  }
+}
+
+@keyframes sk-cubeGridScaleDelay {
+  0%, 70%, 100% {
+    -webkit-transform: scale3D(1, 1, 1);
+            transform: scale3D(1, 1, 1);
+  } 35% {
+    -webkit-transform: scale3D(0, 0, 1);
+            transform: scale3D(0, 0, 1);
+  }
+}

+ 7 - 0
client/components/main/spinner_dot.jade

@@ -0,0 +1,7 @@
+template(name="spinnerDot")
+  .sk-spinner.sk-spinner-dot(class=currentBoard.colorClass)
+    +spinnerDotRaw
+
+template(name="spinnerDotRaw")
+  .sk-dot1
+  .sk-dot2

+ 51 - 0
client/components/main/spinner_dot.styl

@@ -0,0 +1,51 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-dot {
+  margin: 100px auto;
+  width: 40px;
+  height: 40px;
+  position: relative;
+  text-align: center;
+
+  -webkit-animation: sk-rotate 2.0s infinite linear;
+  animation: sk-rotate 2.0s infinite linear;
+}
+
+.sk-dot1, .sk-dot2 {
+  width: 40%;
+  height: 40%;
+  display: inline-block;
+  position: absolute;
+  top: 0;
+  background-color: #333;
+  border-radius: 100%;
+
+  -webkit-animation: sk-bounce 2.0s infinite ease-in-out;
+  animation: sk-bounce 2.0s infinite ease-in-out;
+}
+
+.sk-dot2 {
+  top: auto;
+  bottom: 0;
+  -webkit-animation-delay: -1.0s;
+  animation-delay: -1.0s;
+}
+
+@-webkit-keyframes sk-rotate { 100% { -webkit-transform: rotate(360deg) }}
+@keyframes sk-rotate { 100% { transform: rotate(360deg); -webkit-transform: rotate(360deg) }}
+
+@-webkit-keyframes sk-bounce {
+  0%, 100% { -webkit-transform: scale(0.0) }
+  50% { -webkit-transform: scale(1.0) }
+}
+
+@keyframes sk-bounce {
+  0%, 100% {
+    transform: scale(0.0);
+    -webkit-transform: scale(0.0);
+  } 50% {
+    transform: scale(1.0);
+    -webkit-transform: scale(1.0);
+  }
+}

+ 7 - 0
client/components/main/spinner_double_bounce.jade

@@ -0,0 +1,7 @@
+template(name="spinnerDoubleBounce")
+  .sk-spinner.sk-spinner-double-bounce(class=currentBoard.colorClass)
+    +spinnerDoubleBounceRaw
+
+template(name="spinnerDoubleBounceRaw")
+  .sk-double-bounce1
+  .sk-double-bounce2

+ 44 - 0
client/components/main/spinner_double_bounce.styl

@@ -0,0 +1,44 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-double-bounce {
+  width: 40px;
+  height: 40px;
+
+  position: relative;
+  margin: 100px auto;
+}
+
+.sk-double-bounce1, .sk-double-bounce2 {
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  background-color: #333;
+  opacity: 0.6;
+  position: absolute;
+  top: 0;
+  left: 0;
+
+  -webkit-animation: sk-bounce 2.0s infinite ease-in-out;
+  animation: sk-bounce 2.0s infinite ease-in-out;
+}
+
+.sk-double-bounce2 {
+  -webkit-animation-delay: -1.0s;
+  animation-delay: -1.0s;
+}
+
+@-webkit-keyframes sk-bounce {
+  0%, 100% { -webkit-transform: scale(0.0) }
+  50% { -webkit-transform: scale(1.0) }
+}
+
+@keyframes sk-bounce {
+  0%, 100% {
+    transform: scale(0.0);
+    -webkit-transform: scale(0.0);
+  } 50% {
+    transform: scale(1.0);
+    -webkit-transform: scale(1.0);
+  }
+}

+ 6 - 0
client/components/main/spinner_rotateplane.jade

@@ -0,0 +1,6 @@
+template(name="spinnerRotateplane")
+  .sk-spinner.sk-spinner-rotateplane(class=currentBoard.colorClass)
+    +spinnerRotateplaneRaw
+
+template(name="spinnerRotateplaneRaw")
+  .sk-rotateplane1

+ 38 - 0
client/components/main/spinner_rotateplane.styl

@@ -0,0 +1,38 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-rotateplane {
+  width: 40px;
+  height: 40px;
+  text-align: center;
+
+  margin: 100px auto;
+  -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
+  animation: sk-rotateplane 1.2s infinite ease-in-out;
+
+  div {
+    background-color: #333;
+    height: 100%;
+    width: 100%;
+    display: inline-block;
+  }
+}
+
+@-webkit-keyframes sk-rotateplane {
+  0% { -webkit-transform: perspective(120px) }
+  50% { -webkit-transform: perspective(120px) rotateY(180deg) }
+  100% { -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg) }
+}
+
+@keyframes sk-rotateplane {
+  0% {
+    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
+    -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
+  } 50% {
+    transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
+    -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
+  } 100% {
+    transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
+    -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
+  }
+}

+ 6 - 0
client/components/main/spinner_scaleout.jade

@@ -0,0 +1,6 @@
+template(name="spinnerScaleout")
+  .sk-spinner.sk-spinner-scaleout(class=currentBoard.colorClass)
+    +spinnerScaleoutRaw
+
+template(name="spinnerScaleoutRaw")
+  .sk-scaleout1

+ 40 - 0
client/components/main/spinner_scaleout.styl

@@ -0,0 +1,40 @@
+@import 'nib'
+
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-scaleout {
+  width: 40px;
+  height: 40px;
+  text-align: center;
+
+  margin: 100px auto;
+
+  border-radius: 100%;
+  -webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
+  animation: sk-scaleout 1.0s infinite ease-in-out;
+
+  div {
+    background-color: #333;
+    height: 100%;
+    width: 100%;
+    display: inline-block;
+  }
+}
+
+@-webkit-keyframes sk-scaleout {
+  0% { -webkit-transform: scale(0) }
+  100% {
+    -webkit-transform: scale(1.0);
+    opacity: 0;
+  }
+}
+
+@keyframes sk-scaleout {
+  0% {
+    -webkit-transform: scale(0);
+    transform: scale(0);
+  } 100% {
+    -webkit-transform: scale(1.0);
+    transform: scale(1.0);
+    opacity: 0;
+  }
+}

+ 15 - 0
client/components/main/spinner_wave.jade

@@ -0,0 +1,15 @@
+template(name="spinnerWave")
+  .sk-spinner.sk-spinner-wave(class=currentBoard.colorClass)
+    +spinnerWaveRaw
+
+template(name="spinnerWaveRaw")
+  .sk-rect1
+  |  
+  .sk-rect2
+  |  
+  .sk-rect3
+  |  
+  .sk-rect4
+  |  
+  .sk-rect5
+  |  

+ 2 - 16
client/components/main/spinner.styl → client/components/main/spinner_wave.styl

@@ -1,21 +1,7 @@
 @import 'nib'
 
-/*
- * From https://github.com/tobiasahlin/SpinKit
- *
- * Usage:
- *
- *    <div class="sk-spinner sk-spinner-wave">
- *      <div class="sk-rect1"></div>
- *      <div class="sk-rect2"></div>
- *      <div class="sk-rect3"></div>
- *      <div class="sk-rect4"></div>
- *      <div class="sk-rect5"></div>
- *    </div>
- *
- */
-
-.sk-spinner {
+// From https://github.com/tobiasahlin/SpinKit
+.sk-spinner-wave {
   width: 50px;
   height: 50px;
   margin: auto;

+ 11 - 0
client/components/settings/settingBody.jade

@@ -173,6 +173,9 @@ template(name='layoutSettings')
     li.layout-form
       .title {{_ 'default-authentication-method'}}
       +selectAuthenticationMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod)
+    li.layout-form
+      .title {{_ 'wait-spinner'}}
+      +selectSpinnerName(spinnerName=currentSetting.spinnerName)
     li.layout-form
       .title {{_ 'custom-product-name'}}
       .form-group
@@ -222,3 +225,11 @@ template(name='selectAuthenticationMethod')
         option(value="{{value}}" selected) {{_ value}}
       else
         option(value="{{value}}") {{_ value}}
+
+template(name='selectSpinnerName')
+  select#spinnerName
+    each spinner in spinners
+      if isSelected spinner
+        option(value="{{spinner}}" selected) {{spinner}}
+      else
+        option(value="{{spinner}}") {{spinner}}

+ 14 - 0
client/components/settings/settingBody.js

@@ -1,3 +1,5 @@
+import { ALLOWED_WAIT_SPINNERS } from '/config/const';
+
 BlazeComponent.extendComponent({
   onCreated() {
     this.error = new ReactiveVar('');
@@ -199,6 +201,8 @@ BlazeComponent.extendComponent({
       $('input[name=displayAuthenticationMethod]:checked').val() === 'true';
     const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val();
 
+    const spinnerName = $('#spinnerName').val();
+
     try {
       Settings.update(Settings.findOne()._id, {
         $set: {
@@ -213,6 +217,7 @@ BlazeComponent.extendComponent({
           displayAuthenticationMethod,
           defaultAuthenticationMethod,
           automaticLinkedUrlSchemes,
+          spinnerName,
         },
       });
     } catch (e) {
@@ -384,3 +389,12 @@ Template.selectAuthenticationMethod.helpers({
     return Template.instance().data.authenticationMethod === match;
   },
 });
+
+Template.selectSpinnerName.helpers({
+  spinners() {
+    return ALLOWED_WAIT_SPINNERS;
+  },
+  isSelected(match) {
+    return Template.instance().data.spinnerName === match;
+  },
+});

+ 27 - 0
client/lib/spinner.js

@@ -0,0 +1,27 @@
+Meteor.subscribe('setting');
+
+import { ALLOWED_WAIT_SPINNERS } from '/config/const';
+
+export class Spinner extends BlazeComponent {
+  currentSettings() {
+    return Settings.findOne();
+  }
+
+  getSpinnerName() {
+    let ret = 'Bounce';
+    let defaultWaitSpinner = Meteor.settings.public.DEFAULT_WAIT_SPINNER;
+    if (defaultWaitSpinner && ALLOWED_WAIT_SPINNERS.includes(defaultWaitSpinner)) {
+      ret = defaultWaitSpinner;
+    }
+    let settings = this.currentSettings();
+
+    if (settings && settings.spinnerName) {
+      ret = settings.spinnerName;
+    }
+    return ret;
+  }
+
+  getSpinnerTemplate() {
+    return 'spinner' + this.getSpinnerName().replace(/-/, '');
+  }
+}

+ 10 - 0
config/const.js

@@ -49,3 +49,13 @@ export const TYPE_LINKED_BOARD = 'cardType-linkedBoard';
 export const TYPE_LINKED_CARD = 'cardType-linkedCard';
 export const TYPE_TEMPLATE_BOARD = 'template-board';
 export const TYPE_TEMPLATE_CONTAINER = 'template-container';
+export const ALLOWED_WAIT_SPINNERS = [
+  'Bounce',
+  'Cube',
+  'Cube-Grid',
+  'Dot',
+  'Double-Bounce',
+  'Rotateplane',
+  'Scaleout',
+  'Wave'
+];

+ 3 - 0
docker-compose.yml

@@ -618,6 +618,9 @@ services:
       #- SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE=
       #- SAML_ATTRIBUTES=
       #---------------------------------------------------------------------
+      # Default wait spinner to use
+      # - DEFAULT_WAIT_SPINNER=Bounce
+      #---------------------------------------------------------------------
     depends_on:
       - wekandb
 

+ 2 - 1
i18n/en.i18n.json

@@ -1039,5 +1039,6 @@
   "rulesReportTitle": "Rules Report",
   "copy-swimlane": "Copy Swimlane",
   "copySwimlanePopup-title": "Copy Swimlane",
-  "display-card-creator": "Display Card Creator"
+  "display-card-creator": "Display Card Creator",
+  "wait-spinner": "Wait Spinner"
 }

+ 4 - 0
models/settings.js

@@ -46,6 +46,10 @@ Settings.attachSchema(
       type: String,
       optional: false,
     },
+    spinnerName: {
+      type: String,
+      optional: true,
+    },
     hideLogo: {
       type: Boolean,
       optional: true,

+ 3 - 0
releases/virtualbox/start-wekan.sh

@@ -382,6 +382,9 @@
       #export SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE=
       #export SAML_ATTRIBUTES=
       #---------------------------------------------------------------------
+      # Default wait spinner to use
+      #export DEFAULT_WAIT_SPINNER=Bounce
+      #---------------------------------------------------------------------
 
       node main.js & >> ~/repos/wekan.log
       cd ~/repos

+ 1 - 0
server/publications/settings.js

@@ -23,6 +23,7 @@ Meteor.publish('setting', () => {
         customHTMLbeforeBodyEnd: 1,
         displayAuthenticationMethod: 1,
         defaultAuthenticationMethod: 1,
+        spinnerName: 1,
       },
     },
   );

+ 3 - 0
server/spinner.js

@@ -0,0 +1,3 @@
+Meteor.startup(() => {
+  Meteor.settings.public.DEFAULT_WAIT_SPINNER = process.env.DEFAULT_WAIT_SPINNER;
+});

File diff ditekan karena terlalu besar
+ 0 - 0
snap-src/bin/config


+ 2 - 0
start-wekan.bat

@@ -418,4 +418,6 @@ REM SET SAML_IDENTIFIER_FORMAT=
 REM SET SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE=
 REM SET SAML_ATTRIBUTES=
 
+REM SET DEFAULT_WAIT_SPINNER=
+
 node main.js

+ 3 - 0
start-wekan.sh

@@ -388,6 +388,9 @@
       #export SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE=
       #export SAML_ATTRIBUTES=
       #---------------------------------------------------------------------
+      # Default wait spinner to use
+      #export DEFAULT_WAIT_SPINNER=Bounce
+      #---------------------------------------------------------------------
       node main.js
       # & >> ../../wekan.log
       cd ../..

+ 3 - 0
torodb-postgresql/docker-compose.yml

@@ -559,6 +559,9 @@ services:
       #- SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE=
       #- SAML_ATTRIBUTES=
       #---------------------------------------------------------------------
+      # Default wait spinner to use
+      # - DEFAULT_WAIT_SPINNER=Bounce
+      #---------------------------------------------------------------------
 
     depends_on:
       - mongodb

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini