add loading indicator to import (ST-149), change card divider color

This commit is contained in:
Gregor Vostrak
2024-06-07 14:18:27 +02:00
parent f40ae91444
commit 8857befc6c
5 changed files with 69 additions and 39 deletions

View File

@@ -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);

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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