Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.gridsuite.studyconfig.server.StudyConfigApi;
import org.gridsuite.studyconfig.server.dto.ColumnInfos;
import org.gridsuite.studyconfig.server.dto.GlobalFilterInfos;
import org.gridsuite.studyconfig.server.dto.MetadataInfos;
import org.gridsuite.studyconfig.server.dto.SpreadsheetConfigInfos;
import org.gridsuite.studyconfig.server.dto.*;
import org.gridsuite.studyconfig.server.service.SpreadsheetConfigService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -179,6 +176,20 @@ public ResponseEntity<Void> reorderColumns(
return ResponseEntity.noContent().build();
}

@PutMapping("/{id}/columns/states")
@Operation(summary = "Update column states",
description = "Updates the visibility and order of columns in a spreadsheet configuration")
@ApiResponse(responseCode = "204", description = "Column states updated successfully")
@ApiResponse(responseCode = "404", description = "Spreadsheet configuration not found")
@ApiResponse(responseCode = "400", description = "Invalid column state data")
public ResponseEntity<Void> updateColumnStates(
@Parameter(description = "ID of the spreadsheet config") @PathVariable UUID id,
@Parameter(description = "List of column state updates")
@Valid @RequestBody List<ColumnStateUpdateInfos> columnStates) {
spreadsheetConfigService.updateColumnStates(id, columnStates);
return ResponseEntity.noContent().build();
}

@PostMapping("/{id}/global-filters")
@Operation(summary = "Set global filters",
description = "Replaces all existing global filters with the provided list for a spreadsheet configuration")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,8 @@ public record ColumnInfos(
String filterValue,

@Schema(description = "Filter tolerance for numeric comparisons")
Double filterTolerance
Double filterTolerance,

@Schema(description = "Column visibility", defaultValue = "true")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaultValue without nullable=true?

Suggested change
@Schema(description = "Column visibility", defaultValue = "true")
@Schema(description = "Column visibility", nullable=true, defaultValue = "true")

boolean visible
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attention: if you do that, you must also set the default value in Java because primitive types have 0/false as implicit value when their container object is initialized!

Suggested change
boolean visible
boolean visible = true

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cannot assign default values directly in record parameter declarations

) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* 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/.
*/
package org.gridsuite.studyconfig.server.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;

import java.util.UUID;

/**
* DTO for updating column state (visibility and order)
* @author Achour BERRAHMA <achour.berrahma at rte-france.com>
*/
@Schema(name = "ColumnStateUpdateDto", description = "Column state update information")
public record ColumnStateUpdateInfos(

@NotNull(message = "Column UUID is mandatory")
@Schema(description = "Column UUID")
UUID columnId,

@NotNull(message = "Visible state is mandatory")
@Schema(description = "Column visibility state")
Boolean visible,

@NotNull(message = "Order is mandatory")
@Schema(description = "New position in the column order (0-based index)")
Integer order

) { }
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ public class ColumnEntity {
@Column(name = "filter_tolerance")
private Double filterTolerance;

@Column(name = "visible", nullable = false)
@Builder.Default
private boolean visible = true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ public static ColumnInfos toColumnDto(ColumnEntity entity) {
entity.getFilterDataType(),
entity.getFilterType(),
entity.getFilterValue(),
entity.getFilterTolerance()
entity.getFilterTolerance(),
entity.isVisible()
);
}

Expand All @@ -89,6 +90,7 @@ public static ColumnEntity toColumnEntity(ColumnInfos dto) {
.filterType(dto.filterType())
.filterValue(dto.filterValue())
.filterTolerance(dto.filterTolerance())
.visible(dto.visible())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ public void updateColumn(UUID id, UUID columnId, ColumnInfos dto) {
columnEntity.setFilterType(dto.filterType());
columnEntity.setFilterValue(dto.filterValue());
columnEntity.setFilterTolerance(dto.filterTolerance());
columnEntity.setVisible(dto.visible());

spreadsheetConfigRepository.save(entity);
}
Expand All @@ -352,13 +353,43 @@ public void reorderColumns(UUID id, List<UUID> columnOrder) {
SpreadsheetConfigEntity entity = findEntityById(id);
List<ColumnEntity> columns = entity.getColumns();

reorderColumns(columnOrder, columns);
}

private static void reorderColumns(List<UUID> columnOrder, List<ColumnEntity> columns) {
columns.sort((c1, c2) -> {
int idx1 = columnOrder.indexOf(c1.getUuid());
int idx2 = columnOrder.indexOf(c2.getUuid());
return Integer.compare(idx1, idx2);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IntelliJ simplify as

Suggested change
private static void reorderColumns(List<UUID> columnOrder, List<ColumnEntity> columns) {
columns.sort((c1, c2) -> {
int idx1 = columnOrder.indexOf(c1.getUuid());
int idx2 = columnOrder.indexOf(c2.getUuid());
return Integer.compare(idx1, idx2);
});
}
private static void reorderColumns(List<UUID> columnOrder, List<ColumnEntity> columns) {
columns.sort(Comparator.comparingInt(c -> columnOrder.indexOf(c.getUuid())));
}


@Transactional
public void updateColumnStates(UUID id, List<ColumnStateUpdateInfos> columnStates) {
SpreadsheetConfigEntity entity = findEntityById(id);
List<ColumnEntity> columns = entity.getColumns();

Map<UUID, ColumnEntity> columnMap = columns.stream()
.collect(Collectors.toMap(ColumnEntity::getUuid, column -> column));

for (ColumnStateUpdateInfos state : columnStates) {
ColumnEntity column = columnMap.get(state.columnId());
if (column == null) {
throw new EntityNotFoundException(COLUMN_NOT_FOUND + state.columnId());
}
column.setVisible(state.visible());
}

// Reorder columns based on the provided states
columns.sort(Comparator.comparing(column ->
columnStates.stream()
.filter(state -> state.columnId().equals(column.getUuid()))
.findFirst()
.map(ColumnStateUpdateInfos::order)
.orElse(Integer.MAX_VALUE)
));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My previous review was wrong, I was thinking you could reuse the columnMap, but that isn't the case. You're previous version was good.

}

private SpreadsheetConfigCollectionInfos readDefaultSpreadsheetConfigCollection() throws IOException {
try (InputStream inputStream = defaultSpreadsheetConfigCollectionResource.getInputStream()) {
return objectMapper.readValue(inputStream, SpreadsheetConfigCollectionInfos.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<changeSet author="berrahmaach (generated)" id="1749213150568-4">
<addColumn tableName="spreadsheet_column">
<column name="visible" type="boolean" defaultValueBoolean="true" valueBoolean="true">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
3 changes: 3 additions & 0 deletions src/main/resources/db/changelog/db.changelog-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ databaseChangeLog:
- include:
file: changesets/changelog_20250612T140000Z.xml
relativeToChangelogFile: true
- include:
file: changesets/changelog_20250606T123216Z.xml
relativeToChangelogFile: true
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ void testConversionToDtoOfSpreadsheetConfig() {
.sheetType(SheetType.BATTERY)
.columns(Arrays.asList(
ColumnEntity.builder()
.name("Column1")
.formula("A+B")
.id("id1")
.filterDataType("text")
.filterType("contains")
.filterValue("test")
.build(),
.name("Column1")
.formula("A+B")
.id("id1")
.filterDataType("text")
.filterType("contains")
.filterValue("test")
.visible(false)
.build(),
ColumnEntity.builder().name("Column2").formula("C*D").id("id2").build()
))
.globalFilters(Arrays.asList(
Expand Down Expand Up @@ -75,13 +76,16 @@ void testConversionToDtoOfSpreadsheetConfig() {
assertThat(d.columns().get(0).filterDataType()).isEqualTo("text");
assertThat(d.columns().get(0).filterType()).isEqualTo("contains");
assertThat(d.columns().get(0).filterValue()).isEqualTo("test");
assertThat(d.columns().get(0).visible()).isFalse();

assertThat(d.columns().get(1).name()).isEqualTo("Column2");
assertThat(d.columns().get(1).formula()).isEqualTo("C*D");
assertThat(d.columns().get(1).id()).isEqualTo("id2");
assertThat(d.columns().get(1).filterDataType()).isNull();
assertThat(d.columns().get(1).filterType()).isNull();
assertThat(d.columns().get(1).filterValue()).isNull();
assertThat(d.columns().get(1).visible()).isTrue();

// Global filters assertions
assertThat(d.globalFilters()).hasSize(2);
assertThat(d.globalFilters().get(0).label()).isEqualTo("GlobalFilter1");
Expand All @@ -99,9 +103,9 @@ void testConversionToEntityOfSpreadsheetConfig() {
SheetType.BUS,
Arrays.asList(
new ColumnInfos(null, "Column1", ColumnType.NUMBER, 1, "X+Y", "[\"col1\", \"col2\"]", "id1",
"number", "greaterThan", "100", 0.5),
"number", "greaterThan", "100", 0.5, true),
new ColumnInfos(null, "Column2", ColumnType.NUMBER, 2, "Z*W", "[\"col1\"]", "id2",
null, null, null, null)
null, null, null, null, true)
),
List.of(
GlobalFilterInfos.builder().uuid(filterId).filterType("country").label("GlobalFilter1").recent(false).build()
Expand All @@ -126,6 +130,7 @@ void testConversionToEntityOfSpreadsheetConfig() {
assertThat(e.getColumns().get(0).getFilterType()).isEqualTo("greaterThan");
assertThat(e.getColumns().get(0).getFilterValue()).isEqualTo("100");
assertThat(e.getColumns().get(0).getFilterTolerance()).isEqualTo(0.5);
assertThat(e.getColumns().get(0).isVisible()).isTrue();

assertThat(e.getColumns().get(1).getName()).isEqualTo("Column2");
assertThat(e.getColumns().get(1).getFormula()).isEqualTo("Z*W");
Expand All @@ -135,6 +140,7 @@ void testConversionToEntityOfSpreadsheetConfig() {
assertThat(e.getColumns().get(1).getFilterType()).isNull();
assertThat(e.getColumns().get(1).getFilterValue()).isNull();
assertThat(e.getColumns().get(1).getFilterTolerance()).isNull();
assertThat(e.getColumns().get(1).isVisible()).isTrue();

// Global filter assertions
assertThat(e.getGlobalFilters()).hasSize(1);
Expand Down Expand Up @@ -170,6 +176,7 @@ void testConversionToDtoOfColumnWithFilter() {
assertThat(d.filterType()).isEqualTo("startsWith");
assertThat(d.filterValue()).isEqualTo("prefix");
assertThat(d.filterTolerance()).isNull();
assertThat(d.visible()).isTrue();
});
}

Expand All @@ -186,7 +193,8 @@ void testConversionToEntityOfColumnWithFilter() {
"number",
"lessThan",
"50.5",
0.1);
0.1,
true);

ColumnEntity column = SpreadsheetConfigMapper.toColumnEntity(dto);

Expand All @@ -201,6 +209,7 @@ void testConversionToEntityOfColumnWithFilter() {
assertThat(e.getFilterType()).isEqualTo("lessThan");
assertThat(e.getFilterValue()).isEqualTo("50.5");
assertThat(e.getFilterTolerance()).isEqualTo(0.1);
assertThat(e.isVisible()).isTrue();
});
}

Expand All @@ -217,7 +226,8 @@ void testConversionOfColumnWithoutFilter() {
null,
null,
null,
null);
null,
true);

ColumnEntity entity = SpreadsheetConfigMapper.toColumnEntity(dto);
ColumnInfos convertedDto = SpreadsheetConfigMapper.toColumnDto(entity);
Expand Down
Loading