Skip to content

Commit

Permalink
[4443] Add missing edit handler for table cells in view
Browse files Browse the repository at this point in the history
Bug: #4443
Signed-off-by: Jerome Gout <[email protected]>
  • Loading branch information
jerome-obeo authored and sbegaudeau committed Mar 4, 2025
1 parent 926c119 commit 5b57f24
Show file tree
Hide file tree
Showing 31 changed files with 749 additions and 124 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ You have to add `tableWidgetDocumentTransform` to your extensionRegistry to use
Given that it is an application service, it comes with some constraints with regard to transactions, for that a new reusable service named `IProjectEditingContextService` has now been added to manipulate the `projectId` and `editingContextId` instead.
`IProjectEditingContextApplicationService` has thus been modified to be more focused on its original goal as the behavior of the `Project#currentEditingContext` datafetcher.

- https://github.com/eclipse-sirius/sirius-web/issues/4443[#4443] [table] `ICell` has a new method `getDescriptionId` that all implementors should provide.

=== Dependency update

Expand All @@ -42,6 +43,7 @@ Given that it is an application service, it comes with some constraints with reg
- https://github.com/eclipse-sirius/sirius-web/issues/4257[#4257] [diagram] Prevent the width of list parent nodes from increasing on each layout.
- https://github.com/eclipse-sirius/sirius-web/issues/4534[#4534] [table] Fix an issue that prevent row action to be trigger on row in the next paginated data
- https://github.com/eclipse-sirius/sirius-web/issues/4535[#4535] [table] Prevent page size from being reset after global search has been cleared
- https://github.com/eclipse-sirius/sirius-web/issues/4443[#4443] [table] Add missing edit handler for table cells in view


=== New Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "sirius.web.test.enabled=studio" })
public class PapayaTableCellControllerIntegrationTests extends AbstractIntegrationTests {

private static final String MISSING_TABLE = "Missing table";

@Autowired
private IGivenInitialServerState givenInitialServerState;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2025 CEA LIST.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.web.application.controllers.tables;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

import com.jayway.jsonpath.JsonPath;

import java.time.Duration;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;

import org.eclipse.sirius.components.collaborative.dto.CreateRepresentationInput;
import org.eclipse.sirius.components.collaborative.tables.TableRefreshedEventPayload;
import org.eclipse.sirius.components.collaborative.tables.dto.EditTextfieldCellInput;
import org.eclipse.sirius.components.core.api.SuccessPayload;
import org.eclipse.sirius.components.tables.Table;
import org.eclipse.sirius.components.tables.TextfieldCell;
import org.eclipse.sirius.components.tables.tests.graphql.EditTextfieldCellMutationRunner;
import org.eclipse.sirius.web.AbstractIntegrationTests;
import org.eclipse.sirius.web.data.PapayaIdentifiers;
import org.eclipse.sirius.web.services.tables.ViewTableDescriptionProvider;
import org.eclipse.sirius.web.tests.data.GivenSiriusWebServer;
import org.eclipse.sirius.web.tests.services.api.IGivenCreatedDiagramSubscription;
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;

/**
* Integration tests of the view table cell description.
*
* @author Jerome Gout
*/
@Transactional
@SuppressWarnings("checkstyle:MultipleStringLiterals")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "sirius.web.test.enabled=studio" })
public class PapayaViewCellControllerIntegrationTests extends AbstractIntegrationTests {

@Autowired
private IGivenInitialServerState givenInitialServerState;

@Autowired
private IGivenCreatedDiagramSubscription givenCreatedDiagramSubscription;

@Autowired
private ViewTableDescriptionProvider viewTableDescriptionProvider;

@Autowired
private EditTextfieldCellMutationRunner editTextfieldCellMutationRunner;

@BeforeEach
public void beforeEach() {
this.givenInitialServerState.initialize();
}

private Flux<Object> givenSubscriptionToViewTableRepresentation() {
var input = new CreateRepresentationInput(
UUID.randomUUID(),
PapayaIdentifiers.PAPAYA_EDITING_CONTEXT_ID.toString(),
this.viewTableDescriptionProvider.getRepresentationDescriptionId(),
PapayaIdentifiers.SIRIUS_WEB_DOMAIN_PACKAGE.toString(),
"ViewTableDescription"
);
return this.givenCreatedDiagramSubscription.createAndSubscribe(input);
}

@Test
@GivenSiriusWebServer
@DisplayName("Given a table, when an cell edit mutation is triggered, then the representation is refreshed with the new cell value")
public void givenTableWhenCellEditMutationTriggeredThenTheRepresentationIsRefreshedWithNewCellValue() {
var flux = this.givenSubscriptionToViewTableRepresentation();

var cellId = new AtomicReference<UUID>();
var tableId = new AtomicReference<String>();

Consumer<Object> initialTableContentConsumer = this.getTableSubscriptionConsumer(table -> {
tableId.set(table.getId());
assertThat(table).isNotNull();
assertThat(table.getLines()).hasSize(2);
assertThat(table.getLines().get(0).getCells()).hasSize(2);
assertThat(table.getLines().get(0).getCells().get(0)).isInstanceOf(TextfieldCell.class);
assertThat(((TextfieldCell) table.getLines().get(0).getCells().get(0)).getValue()).isEqualTo("Success");
cellId.set(table.getLines().get(0).getCells().get(0).getId());
});

Runnable editName = () -> {
var input = new EditTextfieldCellInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_EDITING_CONTEXT_ID.toString(), tableId.get(), tableId.get(), cellId.get(), "newName");
var result = this.editTextfieldCellMutationRunner.run(input);

String typename = JsonPath.read(result, "$.data.editTextfieldCell.__typename");
assertThat(typename).isEqualTo(SuccessPayload.class.getSimpleName());
};

Consumer<Object> updatedTableContentConsumer = this.getTableSubscriptionConsumer(table -> {
assertThat(table).isNotNull();
assertThat(table.getLines()).hasSize(2);
assertThat(((TextfieldCell) table.getLines().get(0).getCells().get(0)).getValue()).isEqualTo("newName");
});

StepVerifier.create(flux)
.consumeNextWith(initialTableContentConsumer)
.then(editName)
.consumeNextWith(updatedTableContentConsumer)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

private Consumer<Object> getTableSubscriptionConsumer(Consumer<Table> tableConsumer) {
return payload -> Optional.of(payload)
.filter(TableRefreshedEventPayload.class::isInstance)
.map(TableRefreshedEventPayload.class::cast)
.map(TableRefreshedEventPayload::table)
.ifPresentOrElse(tableConsumer, () -> fail("Missing table"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,16 @@ private TableDescription createTableDescription() {
.contextMenuEntries(contextMenuEntry)
.build();

var setNameOperation = new ViewBuilders().newSetValue()
.featureName("name")
.valueExpression("aql:newValue");

var nameCellDescription = new TableBuilders().newCellDescription()
.preconditionExpression("aql:columnTargetObject.equals('Name')")
.valueExpression("aql:self.name")
.cellWidgetDescription(new TableBuilders().newCellTextfieldWidgetDescription().build())
.cellWidgetDescription(new TableBuilders().newCellTextfieldWidgetDescription()
.body(setNameOperation.build())
.build())
.selectedTargetObjectExpression("aql:self.eContainer()")
.build();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -30,6 +30,8 @@ public final class CheckboxCell implements ICell {

private UUID id;

private String descriptionId;

private String targetObjectId;

private String targetObjectKind;
Expand All @@ -42,23 +44,14 @@ private CheckboxCell() {
// Prevent instantiation
}

public boolean isValue() {
return this.value;
}

public static Builder newCheckboxCell(UUID id) {
return new Builder(id);
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, columnId: {2}, value: {3}'}'";
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.columnId, this.value);
public UUID getId() {
return this.id;
}

@Override
public UUID getId() {
return this.id;
public String getDescriptionId() {
return this.descriptionId;
}

@Override
Expand All @@ -81,6 +74,20 @@ public UUID getColumnId() {
return this.columnId;
}

public boolean isValue() {
return this.value;
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, columnId: {2}, value: {3}'}'";
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.columnId, this.value);
}

public static Builder newCheckboxCell(UUID id) {
return new Builder(id);
}

/**
* The builder used to create a cell.
*
Expand All @@ -91,6 +98,8 @@ public static final class Builder {

private final UUID id;

private String descriptionId;

private String targetObjectId;

private String targetObjectKind;
Expand All @@ -103,6 +112,11 @@ private Builder(UUID id) {
this.id = Objects.requireNonNull(id);
}

public Builder descriptionId(String descriptionId) {
this.descriptionId = Objects.requireNonNull(descriptionId);
return this;
}

public Builder targetObjectId(String targetObjectId) {
this.targetObjectId = Objects.requireNonNull(targetObjectId);
return this;
Expand All @@ -126,6 +140,7 @@ public Builder value(boolean value) {
public CheckboxCell build() {
CheckboxCell cell = new CheckboxCell();
cell.id = Objects.requireNonNull(this.id);
cell.descriptionId = Objects.requireNonNull(this.descriptionId);
cell.targetObjectId = Objects.requireNonNull(this.targetObjectId);
cell.targetObjectKind = Objects.requireNonNull(this.targetObjectKind);
cell.columnId = Objects.requireNonNull(this.columnId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -24,6 +24,8 @@ public interface ICell {

UUID getId();

String getDescriptionId();

String getType();

String getTargetObjectId();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 CEA LIST.
* Copyright (c) 2024, 2025 CEA LIST.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -31,6 +31,8 @@ public final class IconLabelCell implements ICell {

private UUID id;

private String descriptionId;

private String targetObjectId;

private String targetObjectKind;
Expand All @@ -45,27 +47,14 @@ private IconLabelCell() {
// Prevent instantiation
}

public String getValue() {
return this.value;
}

public List<String> getIconURLs() {
return this.iconURLs;
}

public static Builder newIconLabelCell(UUID id) {
return new Builder(id);
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, columnId: {2}, value: {3}'}'";
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.getId(), this.columnId, this.value);
public UUID getId() {
return this.id;
}

@Override
public UUID getId() {
return this.id;
public String getDescriptionId() {
return this.descriptionId;
}

@Override
Expand All @@ -88,6 +77,24 @@ public UUID getColumnId() {
return this.columnId;
}

public String getValue() {
return this.value;
}

public List<String> getIconURLs() {
return this.iconURLs;
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, columnId: {2}, value: {3}'}'";
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.getId(), this.columnId, this.value);
}

public static Builder newIconLabelCell(UUID id) {
return new Builder(id);
}

/**
* The builder used to create a cell.
*
Expand All @@ -98,6 +105,8 @@ public static final class Builder {

private final UUID id;

private String descriptionId;

private String targetObjectId;

private String targetObjectKind;
Expand All @@ -112,6 +121,11 @@ private Builder(UUID id) {
this.id = Objects.requireNonNull(id);
}

public Builder descriptionId(String descriptionId) {
this.descriptionId = Objects.requireNonNull(descriptionId);
return this;
}

public Builder targetObjectId(String targetObjectId) {
this.targetObjectId = Objects.requireNonNull(targetObjectId);
return this;
Expand Down Expand Up @@ -140,6 +154,7 @@ public Builder iconURLs(List<String> iconURLs) {
public IconLabelCell build() {
IconLabelCell cell = new IconLabelCell();
cell.id = Objects.requireNonNull(this.id);
cell.descriptionId = Objects.requireNonNull(this.descriptionId);
cell.targetObjectId = Objects.requireNonNull(this.targetObjectId);
cell.targetObjectKind = Objects.requireNonNull(this.targetObjectKind);
cell.columnId = Objects.requireNonNull(this.columnId);
Expand Down
Loading

0 comments on commit 5b57f24

Please sign in to comment.