mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-06-15 13:32:43 +01:00
add loading indicator to import (ST-149), change card divider color
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
--theme-color-icon-active: rgb(var(--color-text-tertiary));
|
||||
--theme-color-card-background: var(--color-bg-secondary);
|
||||
--theme-color-card-background-active: var(--color-bg-tertiary);
|
||||
--theme-color-card-background-separator: var(--color-border-quaternary);
|
||||
--theme-color-card-background-separator: var(--color-border-tertiary);
|
||||
--theme-color-card-border: var(--color-border-secondary);
|
||||
--theme-color-card-border-active: var(--color-border-tertiary);
|
||||
--theme-color-default-background-separator: var(--color-border-primary);
|
||||
|
||||
31
resources/js/Components/LoadingSpinner.vue
Normal file
31
resources/js/Components/LoadingSpinner.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
const props = defineProps<{
|
||||
class?: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<svg
|
||||
:class="
|
||||
twMerge('animate-spin -ml-1 mr-3 h-5 w-5 text-white', props.class)
|
||||
"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
stroke-width="4"></circle>
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,12 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type { HtmlButtonType } from '@/types/dom';
|
||||
import LoadingSpinner from '@/Components/LoadingSpinner.vue';
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
type: HtmlButtonType;
|
||||
loading: boolean;
|
||||
}>(),
|
||||
{
|
||||
type: 'submit',
|
||||
loading: false,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
@@ -14,7 +17,9 @@ withDefaults(
|
||||
<template>
|
||||
<button
|
||||
:type="type"
|
||||
:disabled="loading"
|
||||
class="inline-flex items-center px-2 sm:px-3 py-1 sm:py-2 bg-accent-300/10 border border-accent-300/20 rounded-md font-medium text-xs sm:text-sm text-white hover:bg-accent-300/20 active:bg-accent-300/20 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150">
|
||||
<LoadingSpinner v-if="loading"></LoadingSpinner>
|
||||
<slot />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -11,10 +11,13 @@ import type { ImportReport, ImportType } from '@/utils/api';
|
||||
import DialogModal from '@/Components/DialogModal.vue';
|
||||
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
||||
import { initializeStores } from '@/utils/init';
|
||||
|
||||
const importTypeOptions = ref<ImportType[]>([]);
|
||||
|
||||
const { addNotification } = useNotificationsStore();
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
onMounted(async () => {
|
||||
const organizationId = getCurrentOrganizationId();
|
||||
if (organizationId) {
|
||||
@@ -50,28 +53,32 @@ async function importData() {
|
||||
const organizationId = getCurrentOrganizationId();
|
||||
if (organizationId !== null) {
|
||||
const { handleApiRequestNotifications } = useNotificationsStore();
|
||||
|
||||
reportResult.value = await handleApiRequestNotifications(() => {
|
||||
if (importType.value) {
|
||||
return api.importData(
|
||||
{
|
||||
type: importType.value.key,
|
||||
data: base64String,
|
||||
},
|
||||
{
|
||||
params: {
|
||||
organization: organizationId,
|
||||
loading.value = true;
|
||||
try {
|
||||
reportResult.value = await handleApiRequestNotifications(() => {
|
||||
if (importType.value) {
|
||||
return api.importData(
|
||||
{
|
||||
type: importType.value.key,
|
||||
data: base64String,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
reject('Import type is null');
|
||||
{
|
||||
params: {
|
||||
organization: organizationId,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
reject('Import type is null');
|
||||
});
|
||||
});
|
||||
});
|
||||
initializeStores();
|
||||
if (reportResult.value) {
|
||||
showResultModal.value = true;
|
||||
initializeStores();
|
||||
if (reportResult.value) {
|
||||
showResultModal.value = true;
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,7 +232,9 @@ const showResultModal = ref(false);
|
||||
</div>
|
||||
</template>
|
||||
<template #actions>
|
||||
<PrimaryButton @click="importData">Import Data</PrimaryButton>
|
||||
<PrimaryButton :loading @click="importData"
|
||||
>Import Data</PrimaryButton
|
||||
>
|
||||
</template>
|
||||
</FormSection>
|
||||
</template>
|
||||
|
||||
@@ -18,6 +18,7 @@ import SecondaryButton from '@/Components/SecondaryButton.vue';
|
||||
import { PlusIcon } from '@heroicons/vue/16/solid';
|
||||
import TimeEntryCreateModal from '@/Components/Common/TimeEntry/TimeEntryCreateModal.vue';
|
||||
import TimeEntryAggregateRow from '@/Components/Common/TimeEntry/TimeEntryAggregateRow.vue';
|
||||
import LoadingSpinner from '@/Components/LoadingSpinner.vue';
|
||||
|
||||
const timeEntriesStore = useTimeEntriesStore();
|
||||
const { timeEntries, allTimeEntriesLoaded } = storeToRefs(timeEntriesStore);
|
||||
@@ -148,23 +149,7 @@ const showManualTimeEntryModal = ref(false);
|
||||
<div
|
||||
v-if="loading && !allTimeEntriesLoaded"
|
||||
class="flex justify-center items-center py-5 text-white font-medium">
|
||||
<svg
|
||||
class="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
stroke-width="4"></circle>
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<LoadingSpinner></LoadingSpinner>
|
||||
<span> Loading more time entries... </span>
|
||||
</div>
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user