mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 00:09:35 +00:00
### **PR Type**
Enhancement
___
### **Description**
- Upgrade Tailwind CSS from v3.4.4 to v4.1.18
- Bump rudder-sdk-js from 2.48.43 to 2.52.7
___
<details> <summary><h3> File Walkthrough</h3></summary>
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Dependencies</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>package.json</strong><dd><code>Bump dependency versions
in package.json</code>
</dd></summary>
<hr>
web/package.json
<ul><li>Updated <code>tailwindcss</code> version to ^4.1.18<br> <li>
Updated <code>rudder-sdk-js</code> version to ^2.52.7</ul>
</details>
</td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9773/files#diff-b861012a5dd72b8a9f3281b7cf09f5a779c98569d040b1bbc1db50f1b15e7cce">+2/-2</a>
</td>
</tr>
</table></td></tr></tr></tbody></table>
</details>
___
168 lines
4.2 KiB
Vue
168 lines
4.2 KiB
Vue
<template>
|
|
<div
|
|
class="tw:absolute tw:top-0 tw:left-0 tw:w-full tw:z-[999] tw:transition-opacity tw:duration-500 tw:ease-out"
|
|
:class="{
|
|
'tw:opacity-0': !loading && !isFadingOut,
|
|
'tw:opacity-100': loading || isFadingOut,
|
|
}"
|
|
>
|
|
<div
|
|
class="tw:w-full tw:h-[2px] tw:relative tw:overflow-x-hidden"
|
|
:class="
|
|
store.state.theme === 'dark' ? 'tw:bg-gray-700' : 'tw:bg-gray-200'
|
|
"
|
|
>
|
|
<div
|
|
class="tw:h-full tw:relative tw:overflow-hidden"
|
|
:class="
|
|
store.state.theme === 'dark' ? 'tw:bg-[#5960B2]' : 'tw:bg-[#5960B2]'
|
|
"
|
|
:style="{
|
|
width: `${displayPercentage}%`,
|
|
transition: shouldAnimate
|
|
? 'width 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
|
|
: 'none',
|
|
}"
|
|
>
|
|
<div
|
|
class="tw:absolute tw:inset-0 tw:bg-gradient-to-r tw:from-transparent tw:to-transparent "
|
|
:class="
|
|
store.state.theme === 'dark'
|
|
? 'tw:via-gray-300/40'
|
|
: 'tw:via-white/40'
|
|
"
|
|
:style="{
|
|
animation: 'shimmer 1.5s infinite linear',
|
|
width: '200%',
|
|
left: '-200%',
|
|
}"
|
|
></div>
|
|
</div>
|
|
<!-- Moving circle indicator -->
|
|
<div
|
|
class="tw:absolute tw:top-0 tw:w-[3px] tw:h-[2px] tw:rounded-full tw:shadow-[0_0_10px_2px_rgba(89,96,178,0.5)] tw:transform tw:translate-x-[-50%]"
|
|
:class="
|
|
store.state.theme === 'dark' ? 'tw:bg-[#5960B2]' : 'tw:bg-[#5960B2]'
|
|
"
|
|
:style="{
|
|
left: `${displayPercentage}%`,
|
|
transition: shouldAnimate
|
|
? 'left 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
|
|
: 'none',
|
|
}"
|
|
>
|
|
<div
|
|
class="tw:absolute tw:inset-0 tw:rounded-full tw:animate-pulse"
|
|
:class="
|
|
store.state.theme === 'dark'
|
|
? 'tw:bg-gray-300/20'
|
|
: 'tw:bg-white/20'
|
|
"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, computed, ref, watch, onUnmounted } from "vue";
|
|
import { useStore } from "vuex";
|
|
|
|
export default defineComponent({
|
|
name: "LoadingProgress",
|
|
props: {
|
|
loading: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
loadingProgressPercentage: {
|
|
type: Number,
|
|
required: true,
|
|
validator: (value: number) => {
|
|
return value >= 0 && value <= 100;
|
|
},
|
|
},
|
|
},
|
|
|
|
setup(props) {
|
|
const store = useStore();
|
|
const lastLoadingState = ref(props.loading);
|
|
const internalPercentage = ref(props.loadingProgressPercentage);
|
|
const isFadingOut = ref(false);
|
|
let fadeOutTimeout: number;
|
|
|
|
watch(
|
|
() => props.loading,
|
|
(newValue, oldValue) => {
|
|
if (oldValue && !newValue) {
|
|
// When loading becomes false, quickly complete to 100% and start fade out
|
|
internalPercentage.value = 100;
|
|
isFadingOut.value = true;
|
|
|
|
clearTimeout(fadeOutTimeout);
|
|
fadeOutTimeout = window.setTimeout(() => {
|
|
isFadingOut.value = false;
|
|
internalPercentage.value = 0;
|
|
}, 500); // Match the fade-out duration
|
|
}
|
|
},
|
|
);
|
|
|
|
onUnmounted(() => {
|
|
clearTimeout(fadeOutTimeout);
|
|
});
|
|
|
|
const shouldAnimate = computed(() => {
|
|
const wasLoading = lastLoadingState.value;
|
|
lastLoadingState.value = props.loading;
|
|
return props.loading || wasLoading || isFadingOut.value;
|
|
});
|
|
|
|
const displayPercentage = computed(() => {
|
|
if (isFadingOut.value) {
|
|
return 100; // Keep at 100% while fading out
|
|
}
|
|
if (!props.loading) {
|
|
return internalPercentage.value;
|
|
}
|
|
if (props.loadingProgressPercentage < 5) {
|
|
return 5;
|
|
}
|
|
return props.loadingProgressPercentage;
|
|
});
|
|
|
|
return {
|
|
store,
|
|
displayPercentage,
|
|
shouldAnimate,
|
|
isFadingOut,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
@keyframes shimmer {
|
|
0% {
|
|
transform: translateX(-200%);
|
|
}
|
|
100% {
|
|
transform: translateX(200%);
|
|
}
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%,
|
|
100% {
|
|
opacity: 0.2;
|
|
}
|
|
50% {
|
|
opacity: 0.4;
|
|
}
|
|
}
|
|
|
|
.tw:animate-pulse {
|
|
animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
}
|
|
</style>
|