diff --git a/package-lock.json b/package-lock.json
index 9344eda..b6a4e5a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,6 +5,7 @@
"packages": {
"": {
"dependencies": {
+ "@marcoschulte/vue3-progress": "^0.0.7",
"@tinymce/tinymce-vue": "^4.0.7",
"@vitejs/plugin-vue": "^4.0.0",
"@vuepic/vue-datepicker": "^3.6.4",
@@ -518,6 +519,11 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
+ "node_modules/@marcoschulte/vue3-progress": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/@marcoschulte/vue3-progress/-/vue3-progress-0.0.7.tgz",
+ "integrity": "sha512-gcvZW9gJ/isTD0sjorgvLOuoS2U5r5djMoLOwuN4YvhOvgOyYGWoQF1hubhouE/dVDPvWHmZsD0gvf6YD0x7fg=="
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
diff --git a/package.json b/package.json
index 7372449..930308b 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"vitest": "^0.28.5"
},
"dependencies": {
+ "@marcoschulte/vue3-progress": "^0.0.7",
"@tinymce/tinymce-vue": "^4.0.7",
"@vitejs/plugin-vue": "^4.0.0",
"@vuepic/vue-datepicker": "^3.6.4",
diff --git a/resources/css/app.scss b/resources/css/app.scss
index 92d8e56..a5d276b 100644
--- a/resources/css/app.scss
+++ b/resources/css/app.scss
@@ -3,6 +3,7 @@
@import "data-table.scss";
@import "tinymce.scss";
@import "prism.css";
+@import "progressbar.scss";
* {
box-sizing: border-box;
diff --git a/resources/css/progressbar.scss b/resources/css/progressbar.scss
new file mode 100644
index 0000000..b8c2bed
--- /dev/null
+++ b/resources/css/progressbar.scss
@@ -0,0 +1,28 @@
+$vue3-progress-bar-container-z-index: 999999 !default;
+$vue3-progress-bar-container-transition: all 500ms ease !default;
+
+$vue3-progress-bar-color: $primary-color-dark !default;
+$vue3-progress-bar-height: 4px !default;
+$vue3-progress-bar-transition: all 200ms ease !default;
+
+.vue3-progress-bar-container {
+ position: fixed;
+ z-index: $vue3-progress-bar-container-z-index;
+ top: 0;
+ left: 0;
+ width: 100%;
+ opacity: 0;
+ background-color: #eee;
+ transition: $vue3-progress-bar-container-transition;
+ &[active="true"] {
+ opacity: 1;
+ transition: none;
+ }
+ .vue3-progress-bar {
+ width: 100%;
+ height: $vue3-progress-bar-height;
+ transform: translate3d(-100%, 0, 0);
+ background-color: $vue3-progress-bar-color;
+ transition: $vue3-progress-bar-transition;
+ }
+}
diff --git a/resources/js/components/SMLoader.vue b/resources/js/components/SMLoader.vue
index 449862f..1201f4f 100644
--- a/resources/js/components/SMLoader.vue
+++ b/resources/js/components/SMLoader.vue
@@ -2,8 +2,7 @@
-
-
+
@@ -11,8 +10,7 @@
diff --git a/resources/js/components/SMLoadingIconToolbox.vue b/resources/js/components/SMLoadingIconToolbox.vue
deleted file mode 100644
index 28a2252..0000000
--- a/resources/js/components/SMLoadingIconToolbox.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
diff --git a/resources/js/helpers/api.ts b/resources/js/helpers/api.ts
index 47b7ec2..47c9a4a 100644
--- a/resources/js/helpers/api.ts
+++ b/resources/js/helpers/api.ts
@@ -1,7 +1,7 @@
-/* https://blog.logrocket.com/axios-vs-fetch-best-http-requests/ */
-
import { useUserStore } from "../store/UserStore";
+import { ProgressFinisher, useProgress } from "@marcoschulte/vue3-progress";
+const progresses = [] as ProgressFinisher[];
interface ApiProgressData {
loaded: number;
total: number;
@@ -82,6 +82,8 @@ export const api = {
let receivedData = false;
+ progresses.push(useProgress().start());
+
fetch(url, fetchOptions)
.then((response) => {
receivedData = true;
@@ -173,6 +175,9 @@ export const api = {
...rest,
response: response && response.json(),
});
+ })
+ .finally(() => {
+ progresses.pop()?.finish();
});
});
},
diff --git a/resources/js/main.js b/resources/js/main.js
index bc8d48e..e3b9106 100644
--- a/resources/js/main.js
+++ b/resources/js/main.js
@@ -12,6 +12,7 @@ import SMColumn from "./components/SMColumn.vue";
import { PromiseDialog } from "vue3-promise-dialog";
import { VueReCaptcha } from "vue-recaptcha-v3";
import "./lib/prism";
+import { Vue3ProgressPlugin } from "@marcoschulte/vue3-progress";
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
@@ -27,6 +28,7 @@ createApp(App)
autoHideBadge: true,
},
})
+ .use(Vue3ProgressPlugin)
.component("SMContainer", SMContainer)
.component("SMRow", SMRow)
.component("SMColumn", SMColumn)
diff --git a/resources/js/router/index.js b/resources/js/router/index.js
index 1b01eab..ef79495 100644
--- a/resources/js/router/index.js
+++ b/resources/js/router/index.js
@@ -2,6 +2,9 @@ import { createWebHistory, createRouter } from "vue-router";
import { useUserStore } from "@/store/UserStore";
import { useApplicationStore } from "../store/ApplicationStore";
import { api } from "../helpers/api";
+import { useProgress } from "@marcoschulte/vue3-progress";
+
+const progresses = [];
export const routes = [
{
@@ -371,22 +374,11 @@ const router = createRouter({
// export let activeRoutes = [];
-let routerLoadingTimeout = null;
-
router.beforeEach(async (to, from, next) => {
const userStore = useUserStore();
const applicationStore = useApplicationStore();
- if (routerLoadingTimeout != null) {
- clearTimeout(routerLoadingTimeout);
- routerLoadingTimeout = null;
- }
-
- routerLoadingTimeout = window.setTimeout(() => {
- routerLoadingTimeout = null;
- applicationStore.setRouterLoading(true);
- }, 1000);
-
+ progresses.push(useProgress().start());
applicationStore.clearDynamicTitle();
// Check Token
@@ -470,13 +462,7 @@ router.beforeEach(async (to, from, next) => {
});
router.afterEach((to, from) => {
- if (routerLoadingTimeout != null) {
- clearTimeout(routerLoadingTimeout);
- routerLoadingTimeout = null;
- }
-
- const applicationStore = useApplicationStore();
- applicationStore.setRouterLoading(false);
+ progresses.pop()?.finish();
});
export default router;
diff --git a/resources/js/store/ApplicationStore.ts b/resources/js/store/ApplicationStore.ts
index f34114b..5b16563 100644
--- a/resources/js/store/ApplicationStore.ts
+++ b/resources/js/store/ApplicationStore.ts
@@ -2,14 +2,12 @@ import { defineStore } from "pinia";
export interface ApplicationStore {
dynamicTitle: string;
- routerLoading: boolean;
}
export const useApplicationStore = defineStore({
id: "application",
state: (): ApplicationStore => ({
dynamicTitle: "",
- routerLoading: false,
}),
actions: {
diff --git a/resources/js/views/App.vue b/resources/js/views/App.vue
index 5675b65..9446e81 100644
--- a/resources/js/views/App.vue
+++ b/resources/js/views/App.vue
@@ -8,18 +8,14 @@
-
+