Files
chill-bundles/src/Bundle/ChillMainBundle/Resources/public/vuejs/DownloadExport/App.vue
2025-07-09 17:46:36 +02:00

139 lines
3.6 KiB
Vue

<script setup lang="ts">
import {
trans,
EXPORT_GENERATION_EXPORT_GENERATION_IS_PENDING,
EXPORT_GENERATION_TOO_MANY_RETRIES,
EXPORT_GENERATION_ERROR_WHILE_GENERATING_EXPORT,
EXPORT_GENERATION_EXPORT_READY,
} from "translator";
import { computed, onMounted, ref } from "vue";
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
import { fetchExportGenerationStatus } from "ChillMainAssets/lib/api/export";
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
import { ExportGeneration } from "ChillMainAssets/types";
interface AppProps {
exportGenerationId: string;
title: string;
createdDate: string;
}
const props = defineProps<AppProps>();
const exportGeneration = ref<ExportGeneration | null>(null);
const status = computed<StoredObjectStatus>(
() => exportGeneration.value?.status ?? "pending",
);
const storedObject = computed<null | StoredObject>(() => {
if (exportGeneration.value === null) {
return null;
}
return exportGeneration.value?.storedObject;
});
const isPending = computed<boolean>(() => status.value === "pending");
const isFetching = computed<boolean>(
() => tryiesForReady.value < maxTryiesForReady,
);
const isReady = computed<boolean>(() => status.value === "ready");
const isFailure = computed<boolean>(() => status.value === "failure");
const filename = computed<string>(() => `${props.title}-${props.createdDate}`);
/**
* counter for the number of times that we check for a new status
*/
let tryiesForReady = ref<number>(0);
/**
* how many times we may check for a new status, once loaded
*/
const maxTryiesForReady = 120;
const checkForReady = function (): void {
if (
"ready" === status.value ||
"empty" === status.value ||
"failure" === status.value ||
// stop reloading if the page stays opened for a long time
tryiesForReady.value > maxTryiesForReady
) {
return;
}
tryiesForReady.value = tryiesForReady.value + 1;
setTimeout(onObjectNewStatusCallback, 5000);
};
const onObjectNewStatusCallback = async function (): Promise<void> {
exportGeneration.value = await fetchExportGenerationStatus(
props.exportGenerationId,
);
if (isPending.value) {
checkForReady();
return Promise.resolve();
}
return Promise.resolve();
};
onMounted(() => {
onObjectNewStatusCallback();
});
</script>
<template>
<div id="waiting-screen">
<div v-if="isPending && isFetching" class="alert alert-danger text-center">
<div>
<p>
{{ trans(EXPORT_GENERATION_EXPORT_GENERATION_IS_PENDING) }}
</p>
</div>
<div>
<i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
<span class="sr-only">Loading...</span>
</div>
</div>
<div v-if="isPending && !isFetching" class="alert alert-info">
<div>
<p>
{{ trans(EXPORT_GENERATION_TOO_MANY_RETRIES) }}
</p>
</div>
</div>
<div v-if="isFailure" class="alert alert-danger text-center">
<div>
<p>
{{ trans(EXPORT_GENERATION_ERROR_WHILE_GENERATING_EXPORT) }}
</p>
</div>
</div>
<div v-if="isReady" class="alert alert-success text-center">
<div>
<p>
{{ trans(EXPORT_GENERATION_EXPORT_READY) }}
</p>
<p v-if="storedObject !== null">
<document-action-buttons-group
:stored-object="storedObject"
:filename="filename"
></document-action-buttons-group>
</p>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
#waiting-screen {
> .alert {
min-height: 350px;
}
}
</style>