mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Migrate export generation flow from plain JS to Vue
Replaced the old JavaScript-based export generation logic with a Vue.js implementation to improve maintainability and modularity. Introduced a new API endpoint to fetch export status, updated the Webpack config, and integrated translations and Twig templates for the new flow. The Vue-based solution enhances user feedback and error handling during the export process.
This commit is contained in:
parent
80ce7f0bf1
commit
bd61eedfbb
@ -1,14 +0,0 @@
|
||||
import { download_report } from "../../lib/download-report/download-report";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", function (e) {
|
||||
const export_generate_url = window.export_generate_url;
|
||||
|
||||
if (typeof export_generate_url === "undefined") {
|
||||
console.error("Alias not found!");
|
||||
throw new Error("Alias not found!");
|
||||
}
|
||||
|
||||
const query = window.location.search,
|
||||
container = document.querySelector("#download_container");
|
||||
download_report(export_generate_url + query.toString(), container);
|
||||
});
|
@ -0,0 +1,129 @@
|
||||
<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/vuejs/DownloadExport/api";
|
||||
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
|
||||
|
||||
interface AppProps {
|
||||
exportGenerationId: string;
|
||||
}
|
||||
|
||||
const props = defineProps<AppProps>();
|
||||
|
||||
const status = ref<StoredObjectStatus>("pending");
|
||||
const storedObject = ref<null | StoredObject>(null);
|
||||
|
||||
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");
|
||||
|
||||
/**
|
||||
* 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> {
|
||||
let status_response = await fetchExportGenerationStatus(
|
||||
props.exportGenerationId,
|
||||
);
|
||||
|
||||
if (status_response.status === "pending") {
|
||||
checkForReady();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
status.value = status_response.status;
|
||||
storedObject.value = status_response.stored_object;
|
||||
|
||||
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"
|
||||
></document-action-buttons-group>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#waiting-screen {
|
||||
> .alert {
|
||||
min-height: 350px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,14 @@
|
||||
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
|
||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||
|
||||
export const fetchExportGenerationStatus = async (
|
||||
exportGenerationId: string,
|
||||
): Promise<
|
||||
| { status: "pending" }
|
||||
| { status: StoredObjectStatus; stored_object: StoredObject }
|
||||
> => {
|
||||
return makeFetch(
|
||||
"GET",
|
||||
`/api/1.0/main/export-generation/${exportGenerationId}/object`,
|
||||
);
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
|
||||
const el = document.getElementById("app");
|
||||
|
||||
if (null === el) {
|
||||
console.error("div element app was not found");
|
||||
throw new Error("div element app was not found");
|
||||
}
|
||||
|
||||
const exportGenerationId = el?.dataset.exportGenerationId as string;
|
||||
createApp(App, { exportGenerationId }).mount(el);
|
@ -0,0 +1,23 @@
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_script_tags('page_download_exports') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('page_download_exports') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="app" data-export-generation-id="{{ exportGeneration.id | escape('html_attr') }}"></div>
|
||||
|
||||
<ul class="sticky-form-buttons record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ chill_return_path_or('chill_main_export_index') }}" class="btn btn-cancel">
|
||||
{{ 'export.generation.Come back later'|trans|chill_return_path_label }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock content %}
|
@ -1101,3 +1101,25 @@ paths:
|
||||
204:
|
||||
description: "resource was deleted successfully"
|
||||
|
||||
/1.0/main/export-generation/{id}/object:
|
||||
get:
|
||||
tags:
|
||||
- export
|
||||
summary: get the object status and details of an export-generation
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The entity export generation id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
403:
|
||||
description: Access denied
|
||||
200:
|
||||
description: "ok"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
|
@ -34,7 +34,7 @@ module.exports = function (encore, entries) {
|
||||
);
|
||||
encore.addEntry(
|
||||
"page_download_exports",
|
||||
__dirname + "/Resources/public/page/export/download-export.js",
|
||||
__dirname + "/Resources/public/vuejs/DownloadExport/index.ts",
|
||||
);
|
||||
|
||||
// Modules entrypoints
|
||||
@ -120,4 +120,5 @@ module.exports = function (encore, entries) {
|
||||
"vue_onthefly",
|
||||
__dirname + "/Resources/public/vuejs/OnTheFly/index.js",
|
||||
);
|
||||
|
||||
};
|
||||
|
@ -716,6 +716,12 @@ notification:
|
||||
|
||||
|
||||
export:
|
||||
generation:
|
||||
Export generation is pending: La génération de l'export est en cours
|
||||
Come back later: Retour à l'index
|
||||
Too many retries: Le nombre de vérification de la disponibilité de l'export a échoué. Essayez de recharger la page.
|
||||
Error while generating export: Erreur interne lors de la génération de l'export
|
||||
Export ready: L'export est prêt à être téléchargé
|
||||
address_helper:
|
||||
id: Identifiant de l'adresse
|
||||
street: Voie
|
||||
|
Loading…
x
Reference in New Issue
Block a user