-
Notifications
You must be signed in to change notification settings - Fork 2
implement async convert #743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /** | ||
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
|
|
||
| import { useSnackMessage } from '@gridsuite/commons-ui'; | ||
| import { useCallback } from 'react'; | ||
| import { UUID } from 'node:crypto'; | ||
| import { triggerDownload } from '../components/utils/downloadUtils'; | ||
| import { fetchExportNetworkFile } from '../utils/rest-api'; | ||
|
|
||
| export function useExportDownload() { | ||
| const { snackError } = useSnackMessage(); | ||
|
|
||
| const downloadExportFile = useCallback( | ||
| (exportUuid: UUID) => { | ||
| fetchExportNetworkFile(exportUuid) | ||
| .then(async (response) => { | ||
| const contentDisposition = response.headers.get('Content-Disposition'); | ||
| let filename = 'export.zip'; | ||
| if (contentDisposition?.includes('filename=')) { | ||
| const regex = /filename="?([^"]+)"?/; | ||
| const [, extractedFilename] = regex.exec(contentDisposition) ?? []; | ||
| if (extractedFilename) { | ||
| filename = extractedFilename; | ||
| } | ||
| } | ||
|
|
||
| const blob = await response.blob(); | ||
| triggerDownload({ blob, filename }); | ||
| }) | ||
| .catch((error: Error) => { | ||
| snackError({ | ||
| messageTxt: error.message, | ||
| headerId: 'export.header.failed', | ||
| }); | ||
| }); | ||
| }, | ||
| [snackError] | ||
| ); | ||
| return { downloadExportFile }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /** | ||
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
| import { useIntl } from 'react-intl'; | ||
| import { NotificationsUrlKeys, useNotificationsListener, useSnackMessage } from '@gridsuite/commons-ui'; | ||
| import { useSelector } from 'react-redux'; | ||
| import { useCallback } from 'react'; | ||
| import { AppState } from '../redux/types'; | ||
| import { buildExportIdentifier, isExportSubscribed, unsetExportSubscription } from '../utils/case-export-utils'; | ||
| import { useExportDownload } from './use-export-download'; | ||
|
|
||
| export function useExportNotification() { | ||
| const intl = useIntl(); | ||
| const { snackError, snackInfo } = useSnackMessage(); | ||
| const { downloadExportFile } = useExportDownload(); | ||
| const userIdProfile = useSelector((state: AppState) => state.user?.profile.sub); | ||
| const handleExportNotification = useCallback( | ||
| (event: MessageEvent<string>) => { | ||
| const eventData = JSON.parse(event.data); | ||
| if (eventData?.headers?.notificationType === 'caseExportSucceeded') { | ||
| const { caseUuid, userId, exportUuid, error } = eventData.headers; | ||
| const exportIdentifierNotif = buildExportIdentifier({ | ||
| caseUuid, | ||
| exportUuid, | ||
| }); | ||
| const isSubscribed = isExportSubscribed(exportIdentifierNotif); | ||
| if (isSubscribed && userIdProfile === userId) { | ||
| unsetExportSubscription(exportIdentifierNotif); | ||
|
|
||
| if (error) { | ||
| snackError({ | ||
| messageTxt: error, | ||
| }); | ||
| } else { | ||
| downloadExportFile(exportUuid); | ||
| snackInfo({ | ||
| messageTxt: intl.formatMessage({ id: 'export.message.succeeded' }), | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| [userIdProfile, snackError, downloadExportFile, snackInfo, intl] | ||
| ); | ||
|
|
||
| useNotificationsListener(NotificationsUrlKeys.DIRECTORY, { listenerCallbackMessage: handleExportNotification }); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /** | ||
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
| import { APP_NAME } from '../utils/config-params'; | ||
|
|
||
| const SESSION_STORAGE_EXPORT_STATE_KEY_PREFIX = `${APP_NAME.toUpperCase()}_EXPORT_STATE_`; | ||
|
|
||
| export function getExportState() { | ||
| const objJson = sessionStorage.getItem(SESSION_STORAGE_EXPORT_STATE_KEY_PREFIX); | ||
| if (objJson) { | ||
| const array = JSON.parse(objJson) as string[]; | ||
| return new Set(array); | ||
| } | ||
| return undefined; | ||
| } | ||
|
|
||
| export function saveExportState(newExportState: Set<string>): void { | ||
| const array = Array.from(newExportState); | ||
| sessionStorage.setItem(SESSION_STORAGE_EXPORT_STATE_KEY_PREFIX, JSON.stringify(array)); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -201,5 +201,8 @@ | |||||||||
| "visualization": "Visualization", | ||||||||||
| "missingEquipmentsFromStudy": "Equipments missing from study", | ||||||||||
| "equipmentTypesByFilters": "Contingencies per equipment types in voltage levels & substations", | ||||||||||
| "reload": "Reload" | ||||||||||
| "reload": "Reload", | ||||||||||
| "export.message.started": "Export file started", | ||||||||||
| "export.message.succeeded": "Export file succeeded", | ||||||||||
|
Comment on lines
+205
to
+206
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| "export.header.failed": "export file failed" | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /** | ||
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
| import { UUID } from 'node:crypto'; | ||
| import { getExportState, saveExportState } from '../redux/export-network-state'; | ||
|
|
||
| export function buildExportIdentifier({ caseUuid, exportUuid }: { caseUuid: UUID; exportUuid: String }): string { | ||
| return `${caseUuid}|${exportUuid}`; | ||
| } | ||
|
|
||
| export function setExportSubscription(identifier: string): void { | ||
| const currentState = getExportState() || new Set<string>(); | ||
| currentState.add(identifier); | ||
| saveExportState(currentState); | ||
| } | ||
|
|
||
| export function unsetExportSubscription(identifier: string): void { | ||
| const currentState = getExportState(); | ||
| if (currentState) { | ||
| currentState.delete(identifier); | ||
| saveExportState(currentState); | ||
| } | ||
| } | ||
|
|
||
| export function isExportSubscribed(identifier: string): boolean { | ||
| const currentState = getExportState(); | ||
| return currentState ? currentState.has(identifier) : false; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -736,16 +736,21 @@ export const fetchConvertedCase = ( | |
| formatParameters: unknown, | ||
| abortController: AbortController | ||
| ) => | ||
| backendFetch( | ||
| backendFetchText( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. exportUuid return as string but when download you send UUID.. it is better to use all as UUID.. (also typing Notification as in study) |
||
| `${PREFIX_NETWORK_CONVERSION_SERVER_QUERIES}/v1/cases/${caseUuid}/convert/${format}?fileName=${fileName}`, | ||
| { | ||
| method: 'post', | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify(formatParameters), | ||
| signal: abortController.signal, | ||
| } | ||
| ); | ||
|
|
||
| export const fetchExportNetworkFile = (exportUuid: UUID) => | ||
| backendFetch(`${PREFIX_NETWORK_CONVERSION_SERVER_QUERIES}/v1/download-file/${exportUuid}`, { | ||
| method: 'get', | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| }); | ||
|
|
||
| export const downloadCase = (caseUuid: string) => | ||
| backendFetch(`${PREFIX_CASE_QUERIES}/v1/cases/${caseUuid}`, { | ||
| method: 'get', | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can not typing the notification as in study?