Skip to content

Commit b10c6fb

Browse files
authored
Add support for spreadsheet config collections (#578)
Signed-off-by: Ayoub LABIDI <[email protected]>
1 parent 2c14d7a commit b10c6fb

File tree

10 files changed

+85
-8
lines changed

10 files changed

+85
-8
lines changed

package-lock.json

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"dependencies": {
88
"@emotion/react": "^11.11.4",
99
"@emotion/styled": "^11.11.5",
10-
"@gridsuite/commons-ui": "0.74.0",
10+
"@gridsuite/commons-ui": "0.75.0",
1111
"@hookform/resolvers": "^3.3.4",
1212
"@mui/icons-material": "^5.15.14",
1313
"@mui/lab": "5.0.0-alpha.169",

src/components/directory-content-table.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const getClickableRowStyle = (cellData: RowClassParams<ElementAttributes>) => {
5050
ElementType.VOLTAGE_INIT_PARAMETERS,
5151
ElementType.SHORT_CIRCUIT_PARAMETERS,
5252
ElementType.SPREADSHEET_CONFIG,
53+
ElementType.SPREADSHEET_CONFIG_COLLECTION,
5354
].includes(cellData.data.type)
5455
) {
5556
style.cursor = 'pointer';

src/components/menus/content-contextual-menu.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
deleteElements,
3939
duplicateElement,
4040
duplicateSpreadsheetConfig,
41+
duplicateSpreadsheetConfigCollection,
4142
elementExists,
4243
moveElementsToDirectory,
4344
newScriptFromFilter,
@@ -169,6 +170,7 @@ export default function ContentContextualMenu(props: Readonly<ContentContextualM
169170
case ElementType.LOADFLOW_PARAMETERS:
170171
case ElementType.SHORT_CIRCUIT_PARAMETERS:
171172
case ElementType.SPREADSHEET_CONFIG:
173+
case ElementType.SPREADSHEET_CONFIG_COLLECTION:
172174
console.info(
173175
`${activeElement.type} with uuid ${activeElement.elementUuid} from directory ${selectedDirectory?.elementUuid} selected for copy`
174176
);
@@ -241,6 +243,11 @@ export default function ContentContextualMenu(props: Readonly<ContentContextualM
241243
handleDuplicateError(error.message);
242244
});
243245
break;
246+
case ElementType.SPREADSHEET_CONFIG_COLLECTION:
247+
duplicateSpreadsheetConfigCollection(activeElement.elementUuid).catch((error) => {
248+
handleDuplicateError(error.message);
249+
});
250+
break;
244251
default: {
245252
handleLastError(intl.formatMessage({ id: 'unsupportedItem' }));
246253
}
@@ -409,6 +416,7 @@ export default function ContentContextualMenu(props: Readonly<ContentContextualM
409416
ElementType.SHORT_CIRCUIT_PARAMETERS,
410417
ElementType.LOADFLOW_PARAMETERS,
411418
ElementType.SPREADSHEET_CONFIG,
419+
ElementType.SPREADSHEET_CONFIG_COLLECTION,
412420
];
413421

414422
const hasMetadata = selectedElements[0]?.hasMetadata;
@@ -453,7 +461,11 @@ export default function ContentContextualMenu(props: Readonly<ContentContextualM
453461
);
454462

455463
const allowsDownload = useCallback(() => {
456-
const allowedTypes = [ElementType.CASE, ElementType.SPREADSHEET_CONFIG];
464+
const allowedTypes = [
465+
ElementType.CASE,
466+
ElementType.SPREADSHEET_CONFIG,
467+
ElementType.SPREADSHEET_CONFIG_COLLECTION,
468+
];
457469
// if selectedElements contains at least one of the allowed types
458470
return selectedElements.some((element) => allowedTypes.includes(element.type)) && noCreationInProgress();
459471
}, [selectedElements, noCreationInProgress]);

src/components/menus/directory-tree-contextual-menu.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
deleteElement,
3535
duplicateElement,
3636
duplicateSpreadsheetConfig,
37+
duplicateSpreadsheetConfigCollection,
3738
elementExists,
3839
insertDirectory,
3940
insertRootDirectory,
@@ -172,6 +173,11 @@ export default function DirectoryTreeContextualMenu(props: Readonly<DirectoryTre
172173
handlePasteError(error)
173174
);
174175
break;
176+
case ElementType.SPREADSHEET_CONFIG_COLLECTION:
177+
duplicateSpreadsheetConfigCollection(selectionForPaste.sourceItemUuid, directoryUuid).catch(
178+
(error: any) => handlePasteError(error)
179+
);
180+
break;
175181
default:
176182
handleError(
177183
intl.formatMessage({

src/components/toolbars/content-toolbar.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ export default function ContentToolbar(props: Readonly<ContentToolbarProps>) {
120120
);
121121

122122
const allowsDownload = useMemo(() => {
123-
const allowedTypes = [ElementType.CASE, ElementType.SPREADSHEET_CONFIG];
123+
const allowedTypes = [
124+
ElementType.CASE,
125+
ElementType.SPREADSHEET_CONFIG,
126+
ElementType.SPREADSHEET_CONFIG_COLLECTION,
127+
];
124128
// if selectedElements contains at least one of the allowed types
125129
return selectedElements.some((element) => allowedTypes.includes(element.type)) && noCreationInProgress;
126130
}, [selectedElements, noCreationInProgress]);

src/components/utils/downloadUtils.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ import { useIntl } from 'react-intl';
99
import { ElementAttributes, ElementType, useSnackMessage } from '@gridsuite/commons-ui';
1010
import { useCallback, useState } from 'react';
1111
import { UUID } from 'crypto';
12-
import { downloadCase, downloadSpreadsheetConfig, fetchConvertedCase, getCaseOriginalName } from '../../utils/rest-api';
12+
import {
13+
downloadCase,
14+
downloadSpreadsheetConfig,
15+
downloadSpreadsheetConfigCollection,
16+
fetchConvertedCase,
17+
getCaseOriginalName,
18+
} from '../../utils/rest-api';
1319

1420
interface DownloadData {
1521
blob: Blob;
@@ -56,6 +62,23 @@ const downloadStrategies: { [key in ElementType]?: (element: ElementAttributes)
5662
return { blob: await result.blob(), filename };
5763
}
5864
},
65+
[ElementType.SPREADSHEET_CONFIG_COLLECTION]: async (element: ElementAttributes) => {
66+
const result = await downloadSpreadsheetConfigCollection(element.elementUuid);
67+
const filename = `${element.elementName}.json`;
68+
try {
69+
// Parse the JSON to ensure it's valid
70+
const jsonContent = await result.json();
71+
// Stringify with indentation for pretty formatting
72+
const prettyJson = JSON.stringify(jsonContent, null, 2);
73+
// Create a new Blob with the pretty-formatted JSON
74+
const blob = new Blob([prettyJson], { type: 'application/json' });
75+
return { blob, filename };
76+
} catch (error) {
77+
// If parsing fails, fall back to the original blob
78+
console.error('Error parsing JSON:', error);
79+
return { blob: await result.blob(), filename };
80+
}
81+
},
5982
};
6083

6184
export function useDownloadUtils() {

src/translations/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
"editFilter": "Edit filter",
7676
"STUDY": "Study",
7777
"SPREADSHEET_CONFIG": "Spreadsheet model",
78+
"SPREADSHEET_CONFIG_COLLECTION": "Spreadsheet model collection",
7879
"VOLTAGE_INIT_PARAMETERS": "Settings (Voltage profile initialization)",
7980
"SECURITY_ANALYSIS_PARAMETERS": "Settings (Security analysis)",
8081
"SENSITIVITY_PARAMETERS": "Settings (Sensitivity analysis)",

src/translations/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"editFilter": "Éditer le filtre",
7575
"STUDY": "Étude",
7676
"SPREADSHEET_CONFIG": "Modèle de tableur",
77+
"SPREADSHEET_CONFIG_COLLECTION": "Modèles de tableur",
7778
"VOLTAGE_INIT_PARAMETERS": "Paramètres (Initialisation du plan de tension)",
7879
"SECURITY_ANALYSIS_PARAMETERS": "Paramètres (Analyse de sécurité)",
7980
"SENSITIVITY_PARAMETERS": "Paramètres (Analyse de sensibilité)",

src/utils/rest-api.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,22 @@ export function duplicateSpreadsheetConfig(sourceCaseUuid: UUID, parentDirectory
432432
});
433433
}
434434

435+
export function duplicateSpreadsheetConfigCollection(sourceCaseUuid: UUID, parentDirectoryUuid?: UUID) {
436+
console.info('Duplicating a spreadsheet config collection...');
437+
const queryParams = new URLSearchParams();
438+
queryParams.append('duplicateFrom', sourceCaseUuid);
439+
if (parentDirectoryUuid) {
440+
queryParams.append('parentDirectoryUuid', parentDirectoryUuid);
441+
}
442+
const url = `${PREFIX_EXPLORE_SERVER_QUERIES}/v1/explore/spreadsheet-config-collections/duplicate?${queryParams.toString()}`;
443+
444+
console.debug(url);
445+
446+
return backendFetch(url, {
447+
method: 'post',
448+
});
449+
}
450+
435451
export function downloadSpreadsheetConfig(configId: string) {
436452
console.info(`Downloading spreadsheet config with id: ${configId}`);
437453
const fetchUrl = `${PREFIX_SPREADSHEET_CONFIG_QUERIES}/v1/spreadsheet-configs/${configId}`;
@@ -444,6 +460,18 @@ export function downloadSpreadsheetConfig(configId: string) {
444460
});
445461
}
446462

463+
export function downloadSpreadsheetConfigCollection(collectionId: string) {
464+
console.info(`Downloading spreadsheet config collection with id: ${collectionId}`);
465+
const fetchUrl = `${PREFIX_SPREADSHEET_CONFIG_QUERIES}/v1/spreadsheet-config-collections/${collectionId}`;
466+
467+
return backendFetch(fetchUrl, {
468+
method: 'GET',
469+
headers: {
470+
'Content-Type': 'application/json',
471+
},
472+
});
473+
}
474+
447475
export function elementExists(directoryUuid: UUID | null | undefined, elementName: string, type: string) {
448476
const elementNameEncoded = encodeURIComponent(elementName);
449477
const existsElementUrl = `${PREFIX_DIRECTORY_SERVER_QUERIES}/v1/directories/${directoryUuid}/elements/${elementNameEncoded}/types/${type}`;

0 commit comments

Comments
 (0)