Skip to content

Commit

Permalink
[3823] Add support for table widget in form
Browse files Browse the repository at this point in the history
Bug: #3823
Signed-off-by: Laurent Fasani <[email protected]>
  • Loading branch information
lfasani authored and sbegaudeau committed Oct 11, 2024
1 parent 157c9e8 commit 8c44758
Show file tree
Hide file tree
Showing 197 changed files with 13,278 additions and 3,664 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ jobs:
npx yalc add @eclipse-sirius/sirius-components-portals
npx yalc add @eclipse-sirius/sirius-components-widget-reference
npx yalc add @eclipse-sirius/sirius-components-selection
npx yalc add @eclipse-sirius/sirius-components-tables
npx yalc add @eclipse-sirius/sirius-components-trees
npx yalc add @eclipse-sirius/sirius-components-validation
npx yalc add @eclipse-sirius/sirius-web-application
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ This allows an error to be displayed when there is a problem during uploading
- https://github.com/eclipse-sirius/sirius-web/issues/3846[#3846] [core] Migrate the frontend to `react 18.3.1`, `react-dom 18.3.1`, `react-router-dom 6.26.0`, `@xstate/react: 3.0.0` and `@ObeoNetwork/gantt-task-react 0.6.0`
- https://github.com/eclipse-sirius/sirius-web/issues/3840[#3840] [diagram] Migrate to ReactFlow 12
- [releng] Switch to the final release version of AQL 8.0.2
- https://github.com/eclipse-sirius/sirius-web/issues/3823[#3823] [table] Add a dependency to `material-react-table "2.13.3"` and `export-to-csv "1.3.0"`


=== Bug fixes
Expand Down Expand Up @@ -78,6 +79,8 @@ description (optional).
** updateProject (`PUT /projects/{projectId}`): Update the project with the given id (projectId).
- https://github.com/eclipse-sirius/sirius-web/issues/3873[#3873] [diagram] Make the Selection Dialog available for the EdgeTool
- https://github.com/eclipse-sirius/sirius-web/issues/3950[#3950] [diagram] Have the multiple selection on the Selection Dialog
- https://github.com/eclipse-sirius/sirius-web/issues/3823[#3823] [form][table] Add table widget in form.


=== Improvements

Expand Down
4,844 changes: 1,237 additions & 3,607 deletions package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
<artifactId>sirius-components-collaborative-charts</artifactId>
<version>2024.9.8</version>
</dependency>
<dependency>
<groupId>org.eclipse.sirius</groupId>
<artifactId>sirius-components-collaborative-tables</artifactId>
<version>2024.9.8</version>
</dependency>
<dependency>
<groupId>org.eclipse.sirius</groupId>
<artifactId>sirius-components-tests</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,36 @@
import org.eclipse.sirius.components.collaborative.api.IRepresentationRefreshPolicyRegistry;
import org.eclipse.sirius.components.collaborative.api.IRepresentationSearchService;
import org.eclipse.sirius.components.collaborative.api.ISubscriptionManager;
import org.eclipse.sirius.components.collaborative.dto.RenameRepresentationInput;
import org.eclipse.sirius.components.collaborative.forms.api.FormCreationParameters;
import org.eclipse.sirius.components.collaborative.forms.api.IFormEventHandler;
import org.eclipse.sirius.components.collaborative.forms.api.IFormEventProcessor;
import org.eclipse.sirius.components.collaborative.forms.api.IFormInput;
import org.eclipse.sirius.components.collaborative.forms.api.IFormPostProcessor;
import org.eclipse.sirius.components.collaborative.forms.configuration.FormEventProcessorConfiguration;
import org.eclipse.sirius.components.collaborative.forms.dto.FormRefreshedEventPayload;
import org.eclipse.sirius.components.collaborative.forms.dto.RenameFormInput;
import org.eclipse.sirius.components.collaborative.forms.variables.FormVariableProvider;
import org.eclipse.sirius.components.collaborative.tables.api.ITableEventHandler;
import org.eclipse.sirius.components.collaborative.tables.api.ITableInput;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IInput;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
import org.eclipse.sirius.components.core.api.IRepresentationInput;
import org.eclipse.sirius.components.forms.Form;
import org.eclipse.sirius.components.forms.TableWidget;
import org.eclipse.sirius.components.forms.components.FormComponent;
import org.eclipse.sirius.components.forms.components.FormComponentProps;
import org.eclipse.sirius.components.forms.description.FormDescription;
import org.eclipse.sirius.components.forms.description.TableWidgetDescription;
import org.eclipse.sirius.components.forms.renderer.FormRenderer;
import org.eclipse.sirius.components.forms.renderer.IWidgetDescriptor;
import org.eclipse.sirius.components.representations.Element;
import org.eclipse.sirius.components.representations.GetOrCreateRandomIdProvider;
import org.eclipse.sirius.components.representations.IRepresentation;
import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.components.tables.Table;
import org.eclipse.sirius.components.tables.descriptions.TableDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -78,10 +83,14 @@ public class FormEventProcessor implements IFormEventProcessor {

private final List<IFormEventHandler> formEventHandlers;

private final List<ITableEventHandler> tableEventHandlers;

private final ISubscriptionManager subscriptionManager;

private final IRepresentationSearchService representationSearchService;

private final IRepresentationDescriptionSearchService representationDescriptionSearchService;

private final IRepresentationRefreshPolicyRegistry representationRefreshPolicyRegistry;

private final Many<IPayload> sink = Sinks.many().multicast().directBestEffort();
Expand All @@ -95,6 +104,7 @@ public class FormEventProcessor implements IFormEventProcessor {
public FormEventProcessor(FormEventProcessorConfiguration configuration,
ISubscriptionManager subscriptionManager,
IRepresentationSearchService representationSearchService,
IRepresentationDescriptionSearchService representationDescriptionSearchService,
IRepresentationRefreshPolicyRegistry representationRefreshPolicyRegistry, IFormPostProcessor formPostProcessor) {
this.logger.trace("Creating the form event processor {}", configuration.formCreationParameters().getId());
this.editingContext = Objects.requireNonNull(configuration.editingContext());
Expand All @@ -103,9 +113,11 @@ public FormEventProcessor(FormEventProcessorConfiguration configuration,
this.widgetDescriptors = Objects.requireNonNull(configuration.widgetDescriptors());
this.formEventHandlers = Objects.requireNonNull(configuration.formEventHandlers());
this.representationSearchService = Objects.requireNonNull(representationSearchService);
this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService);
this.subscriptionManager = Objects.requireNonNull(subscriptionManager);
this.representationRefreshPolicyRegistry = Objects.requireNonNull(representationRefreshPolicyRegistry);
this.formPostProcessor = Objects.requireNonNull(formPostProcessor);
this.tableEventHandlers = Objects.requireNonNull(configuration.tableEventHandlers());

this.variableManager = this.initializeVariableManager(this.formCreationParameters);

Expand Down Expand Up @@ -145,12 +157,7 @@ public ISubscriptionManager getSubscriptionManager() {

@Override
public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDescriptionSink, IRepresentationInput representationInput) {
IRepresentationInput effectiveInput = representationInput;
if (representationInput instanceof RenameRepresentationInput renameRepresentationInput) {
effectiveInput = new RenameFormInput(renameRepresentationInput.id(), renameRepresentationInput.editingContextId(), renameRepresentationInput.representationId(),
renameRepresentationInput.newLabel());
}
if (effectiveInput instanceof IFormInput formInput) {
if (representationInput instanceof IFormInput formInput) {

Optional<IFormEventHandler> optionalFormEventHandler = this.formEventHandlers.stream().filter(handler -> handler.canHandle(formInput)).findFirst();

Expand All @@ -160,9 +167,63 @@ public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDesc
} else {
this.logger.warn("No handler found for event: {}", formInput);
}
} else if (representationInput instanceof ITableInput tableInput) {

Optional<ITableEventHandler> optionalTableEventHandler = this.tableEventHandlers.stream().filter(handler -> handler.canHandle(tableInput)).findFirst();

if (optionalTableEventHandler.isPresent()) {
ITableEventHandler tableEventHandler = optionalTableEventHandler.get();
Optional<Table> tableOptional = getTable(currentForm.get(), tableInput.getTableId());
if (tableOptional.isPresent()) {
Optional<TableDescription> tableDescriptionOptional = getTableDescription(currentForm.get().getDescriptionId(), tableOptional.get().getDescriptionId());
if (tableDescriptionOptional.isPresent()) {
tableEventHandler.handle(payloadSink, changeDescriptionSink, this.editingContext, tableOptional.get(), tableDescriptionOptional.get(), tableInput);
} else {
this.logger.warn("No table description found for event: {}", tableInput);
}
} else {
this.logger.warn("No table found for event: {}", tableInput);
}
} else {
this.logger.warn("No handler found for event: {}", tableInput);
}
}
}

private Optional<Table> getTable(Form form, String tableId) {
return form.getPages().stream()
.flatMap(page -> page.getGroups().stream())
.flatMap(group -> group.getWidgets().stream())
.filter(TableWidget.class::isInstance)
.map(TableWidget.class::cast)
.map(TableWidget::getTable)
.filter(table -> tableId.equals(table.getId()))
.findFirst();
}

private Optional<TableDescription> getTableDescription(String formDescriptionId, String tableDescriptionId) {
return this.representationDescriptionSearchService
.findById(editingContext, formDescriptionId)
.filter(FormDescription.class::isInstance)
.map(FormDescription.class::cast)
.stream()
.flatMap(form -> form.getPageDescriptions().stream())
.flatMap(page -> page.getGroupDescriptions().stream())
.flatMap(group -> group.getControlDescriptions().stream())
.filter(TableWidgetDescription.class::isInstance)
.map(TableWidgetDescription.class::cast)
.map(TableWidgetDescription::getTableDescription)
.filter(tableDescription -> tableDescriptionId.equals(tableDescription.getId()))
.findFirst();
}

private Optional<FormDescription> findFormDescription(String formDescriptionId) {
return this.representationDescriptionSearchService
.findById(editingContext, formDescriptionId)
.filter(FormDescription.class::isInstance)
.map(FormDescription.class::cast);
}

@Override
public void refresh(ChangeDescription changeDescription) {
if (this.shouldReload(changeDescription)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.sirius.components.collaborative.forms.api.IFormPostProcessor;
import org.eclipse.sirius.components.collaborative.forms.configuration.FormEventProcessorConfiguration;
import org.eclipse.sirius.components.collaborative.forms.configuration.FormEventProcessorFactoryConfiguration;
import org.eclipse.sirius.components.collaborative.tables.api.ITableEventHandler;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
Expand Down Expand Up @@ -54,6 +55,8 @@ public class FormEventProcessorFactory implements IRepresentationEventProcessorF

private final List<IFormEventHandler> formEventHandlers;

private final List<ITableEventHandler> tableEventHandlers;

private final ISubscriptionManagerFactory subscriptionManagerFactory;

private final IRepresentationRefreshPolicyRegistry representationRefreshPolicyRegistry;
Expand All @@ -67,6 +70,7 @@ public FormEventProcessorFactory(RepresentationEventProcessorFactoryConfiguratio
this.objectService = Objects.requireNonNull(formConfiguration.getObjectService());
this.widgetDescriptors = Objects.requireNonNull(widgetDescriptors);
this.formEventHandlers = Objects.requireNonNull(formConfiguration.getFormEventHandlers());
this.tableEventHandlers = Objects.requireNonNull(formConfiguration.getTableEventHandlers());
this.representationRefreshPolicyRegistry = Objects.requireNonNull(configuration.getRepresentationRefreshPolicyRegistry());
this.formPostProcessor = Objects.requireNonNull(formConfiguration.getFormPostProcessor());
}
Expand Down Expand Up @@ -98,9 +102,10 @@ public Optional<IRepresentationEventProcessor> createRepresentationEventProcesso
.build();

IRepresentationEventProcessor formEventProcessor = new FormEventProcessor(
new FormEventProcessorConfiguration(editingContext, this.objectService, formCreationParameters, this.widgetDescriptors, this.formEventHandlers),
new FormEventProcessorConfiguration(editingContext, this.objectService, formCreationParameters, this.widgetDescriptors, this.formEventHandlers, this.tableEventHandlers),
this.subscriptionManagerFactory.create(),
this.representationSearchService,
this.representationDescriptionSearchService,
this.representationRefreshPolicyRegistry,
this.formPostProcessor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
import org.eclipse.sirius.components.collaborative.forms.api.FormCreationParameters;
import org.eclipse.sirius.components.collaborative.forms.api.IFormEventHandler;
import org.eclipse.sirius.components.collaborative.forms.api.IFormEventProcessor;
import org.eclipse.sirius.components.collaborative.tables.api.ITableEventHandler;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.forms.renderer.IWidgetDescriptor;

/**
* Bundles the common dependencies that {@link IFormEventProcessor} implementations need
* into a single object for convenience.
* Bundles the common dependencies that {@link IFormEventProcessor} implementations need into a single object for convenience.
*
* @author frouene
*/
public record FormEventProcessorConfiguration(IEditingContext editingContext, IObjectService objectService, FormCreationParameters formCreationParameters,
List<IWidgetDescriptor> widgetDescriptors, List<IFormEventHandler> formEventHandlers) {
public record FormEventProcessorConfiguration(IEditingContext editingContext, IObjectService objectService, FormCreationParameters formCreationParameters, List<IWidgetDescriptor> widgetDescriptors,
List<IFormEventHandler> formEventHandlers, List<ITableEventHandler> tableEventHandlers) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.eclipse.sirius.components.collaborative.api.IRepresentationEventProcessorFactory;
import org.eclipse.sirius.components.collaborative.forms.api.IFormEventHandler;
import org.eclipse.sirius.components.collaborative.forms.api.IFormPostProcessor;
import org.eclipse.sirius.components.collaborative.tables.api.ITableEventHandler;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.springframework.context.annotation.Configuration;

Expand All @@ -35,11 +36,14 @@ public class FormEventProcessorFactoryConfiguration {

private final List<IFormEventHandler> formEventHandlers;

private final List<ITableEventHandler> tableEventHandlers;

private final Optional<IFormPostProcessor> optionalFormProcessor;

public FormEventProcessorFactoryConfiguration(IObjectService objectService, List<IFormEventHandler> formEventHandlers, Optional<IFormPostProcessor> optionalFormProcessor) {
public FormEventProcessorFactoryConfiguration(IObjectService objectService, List<IFormEventHandler> formEventHandlers, List<ITableEventHandler> tableEventHandlers, Optional<IFormPostProcessor> optionalFormProcessor) {
this.objectService = Objects.requireNonNull(objectService);
this.formEventHandlers = Objects.requireNonNull(formEventHandlers);
this.tableEventHandlers = Objects.requireNonNull(tableEventHandlers);
this.optionalFormProcessor = Objects.requireNonNull(optionalFormProcessor);
}

Expand All @@ -54,4 +58,8 @@ public List<IFormEventHandler> getFormEventHandlers() {
public IFormPostProcessor getFormPostProcessor() {
return this.optionalFormProcessor.orElse(new IFormPostProcessor.NoOp());
}

public List<ITableEventHandler> getTableEventHandlers() {
return tableEventHandlers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,16 @@ type DateTimeStyle {
bold: Boolean
}

type TableWidget implements Widget {
id: ID!
label: String!
iconURL: [String!]!
diagnostics: [Diagnostic!]!
hasHelpText: Boolean!
readOnly: Boolean!
table: Table
}

type FormDescription implements RepresentationDescription {
id: ID!
label: String!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
import org.eclipse.sirius.components.core.api.IInput;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
import org.eclipse.sirius.components.forms.description.FormDescription;
import org.junit.jupiter.api.Test;

import reactor.test.StepVerifier;

import org.junit.jupiter.api.Test;

/**
* Unit tests of the form event processor.
*
Expand Down Expand Up @@ -116,9 +116,10 @@ private FormEventProcessor createFormEventProcessor() {
.build();

FormEventProcessor formEventProcessor = new FormEventProcessor(
new FormEventProcessorConfiguration(editingContext, new IObjectService.NoOp(), formCreationParameters, List.of(), List.of()),
new FormEventProcessorConfiguration(editingContext, new IObjectService.NoOp(), formCreationParameters, List.of(), List.of(), List.of()),
new SubscriptionManager(),
new IRepresentationSearchService.NoOp(),
new IRepresentationDescriptionSearchService.NoOp(),
new RepresentationRefreshPolicyRegistry(List.of()),
new IFormPostProcessor.NoOp());
return formEventProcessor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class WidgetHasHelpTextDataFetcher implements IDataFetcherWithFieldCoord
"Select",
"Slider",
"SplitButton",
"TableWidget",
"Textarea",
"Textfield",
"ToolbarAction",
Expand Down
5 changes: 5 additions & 0 deletions packages/forms/backend/sirius-components-forms/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
<artifactId>sirius-components-charts</artifactId>
<version>2024.9.8</version>
</dependency>
<dependency>
<groupId>org.eclipse.sirius</groupId>
<artifactId>sirius-components-tables</artifactId>
<version>2024.9.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
Loading

0 comments on commit 8c44758

Please sign in to comment.