Skip to content

Commit

Permalink
[1346] Add support for rich text widget in forms
Browse files Browse the repository at this point in the history
Bug: #1346
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
  • Loading branch information
pcdavid committed Sep 30, 2022
1 parent 0e9c992 commit 46779e7
Show file tree
Hide file tree
Showing 26 changed files with 2,507 additions and 1 deletion.
548 changes: 548 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

@@ -0,0 +1,76 @@
/*******************************************************************************
* Copyright (c) 2022 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.collaborative.forms.dto;

import java.text.MessageFormat;
import java.util.Objects;
import java.util.UUID;

import org.eclipse.sirius.components.collaborative.forms.api.IFormInput;

/**
* The input object for the rich text edition mutation.
*
* @author pcdavid
*/
public final class EditRichTextInput implements IFormInput {
private UUID id;

private String editingContextId;

private String representationId;

private String richTextId;

private String newValue;

public EditRichTextInput() {
// Used by Jackson
}

public EditRichTextInput(UUID id, String editingContextId, String representationId, String richTextId, String newValue) {
this.id = Objects.requireNonNull(id);
this.editingContextId = Objects.requireNonNull(editingContextId);
this.representationId = Objects.requireNonNull(representationId);
this.richTextId = Objects.requireNonNull(richTextId);
this.newValue = Objects.requireNonNull(newValue);
}

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

public String getEditingContextId() {
return this.editingContextId;
}

@Override
public String getRepresentationId() {
return this.representationId;
}

public String getRichTextId() {
return this.richTextId;
}

public String getNewValue() {
return this.newValue;
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, editingContextId: {2}, representationId: {3}, richTextId: {4}, newValue: {5}'}'"; //$NON-NLS-1$
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.editingContextId, this.representationId, this.richTextId, this.newValue);
}
}
@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2022 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.collaborative.forms.dto;

import java.text.MessageFormat;
import java.util.Objects;
import java.util.UUID;

import org.eclipse.sirius.components.core.api.IPayload;

/**
* The payload for the rich text edition mutation.
*
* @author pcdavid
*/
public final class EditRichTextSuccessPayload implements IPayload {
private final UUID id;

public EditRichTextSuccessPayload(UUID id) {
this.id = Objects.requireNonNull(id);
}

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

@Override
public String toString() {
String pattern = "{0} '{'id: {1}'}'"; //$NON-NLS-1$
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id);
}
}
@@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (c) 2022 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.collaborative.forms.handlers;

import java.util.Objects;
import java.util.function.Function;

import org.eclipse.sirius.components.collaborative.api.ChangeDescription;
import org.eclipse.sirius.components.collaborative.api.ChangeKind;
import org.eclipse.sirius.components.collaborative.api.Monitoring;
import org.eclipse.sirius.components.collaborative.forms.api.IFormEventHandler;
import org.eclipse.sirius.components.collaborative.forms.api.IFormInput;
import org.eclipse.sirius.components.collaborative.forms.api.IFormQueryService;
import org.eclipse.sirius.components.collaborative.forms.dto.EditRichTextInput;
import org.eclipse.sirius.components.collaborative.forms.dto.EditRichTextSuccessPayload;
import org.eclipse.sirius.components.collaborative.forms.messages.ICollaborativeFormMessageService;
import org.eclipse.sirius.components.core.api.ErrorPayload;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.forms.Form;
import org.eclipse.sirius.components.forms.RichText;
import org.eclipse.sirius.components.representations.Failure;
import org.eclipse.sirius.components.representations.IStatus;
import org.eclipse.sirius.components.representations.Success;
import org.springframework.stereotype.Service;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import reactor.core.publisher.Sinks.Many;
import reactor.core.publisher.Sinks.One;

/**
* The handler of the edit rich text event.
*
* @author pcdavid
*/
@Service
public class EditRichTextEventHandler implements IFormEventHandler {

private final IFormQueryService formQueryService;

private final ICollaborativeFormMessageService messageService;

private final Counter counter;

public EditRichTextEventHandler(IFormQueryService formQueryService, ICollaborativeFormMessageService messageService, MeterRegistry meterRegistry) {
this.formQueryService = Objects.requireNonNull(formQueryService);
this.messageService = Objects.requireNonNull(messageService);

// @formatter:off
this.counter = Counter.builder(Monitoring.EVENT_HANDLER)
.tag(Monitoring.NAME, this.getClass().getSimpleName())
.register(meterRegistry);
// @formatter:on
}

@Override
public boolean canHandle(IFormInput formInput) {
return formInput instanceof EditRichTextInput;
}

@Override
public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDescriptionSink, IEditingContext editingContext, Form form, IFormInput formInput) {
this.counter.increment();
String message = this.messageService.invalidInput(formInput.getClass().getSimpleName(), EditRichTextInput.class.getSimpleName());
IPayload payload = new ErrorPayload(formInput.getId(), message);
ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, formInput.getRepresentationId(), formInput);

if (formInput instanceof EditRichTextInput) {
EditRichTextInput input = (EditRichTextInput) formInput;

// @formatter:off
IStatus status = this.formQueryService.findWidget(form, input.getRichTextId())
.map(widget -> {
Function<String, IStatus> handlerFunction = null;
if (widget instanceof RichText) {
handlerFunction = ((RichText) widget).getNewValueHandler();
}
return handlerFunction;
})
.map(handler -> handler.apply(input.getNewValue()))
.orElse(new Failure("")); //$NON-NLS-1$
// @formatter:on

if (status instanceof Success) {
payload = new EditRichTextSuccessPayload(formInput.getId());
changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, formInput.getRepresentationId(), formInput);
} else if (status instanceof Failure) {
payload = new ErrorPayload(formInput.getId(), ((Failure) status).getMessage());
}
}

changeDescriptionSink.tryEmitNext(changeDescription);
payloadSink.tryEmitValue(payload);
}
}
Expand Up @@ -316,6 +316,14 @@ type TreeNode {
selectable: Boolean!
}

type RichText implements Widget {
id: ID!
diagnostics: [Diagnostic!]!
label: String!
iconURL: String
value: String!
}

type FormDescription implements RepresentationDescription {
id: ID!
label: String!
Expand All @@ -327,6 +335,7 @@ extend type Mutation {
editRadio(input: EditRadioInput!): EditRadioPayload!
editSelect(input: EditSelectInput!): EditSelectPayload!
editTextfield(input: EditTextfieldInput!): EditTextfieldPayload!
editRichText(input: EditRichTextInput!): EditRichTextPayload!
updateWidgetFocus(input: UpdateWidgetFocusInput!): UpdateWidgetFocusPayload!
clickListItem(input: ClickListItemInput!): ClickListItemPayload!
deleteListItem(input: DeleteListItemInput!): DeleteListItemPayload!
Expand Down Expand Up @@ -403,6 +412,21 @@ type EditTextfieldSuccessPayload {
id: ID!
}

input EditRichTextInput {
id: ID!
editingContextId: ID!
representationId: ID!
richTextId: ID!
newValue: String!
}

union EditRichTextPayload = ErrorPayload | EditRichTextSuccessPayload

type EditRichTextSuccessPayload {
id: ID!
}


input UpdateWidgetFocusInput {
id: ID!
editingContextId: ID!
Expand Down
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2022 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.forms.graphql.datafetchers.mutation;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher;
import org.eclipse.sirius.components.collaborative.forms.dto.EditRichTextInput;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher;
import org.eclipse.sirius.components.graphql.api.IExceptionWrapper;

import graphql.schema.DataFetchingEnvironment;

/**
* The data fetcher used to edit a rich text.
*
* @author pcdavid
*/
@MutationDataFetcher(type = "Mutation", field = "editRichText")
public class MutationEditRichTextDataFetcher implements IDataFetcherWithFieldCoordinates<CompletableFuture<IPayload>> {

private static final String INPUT_ARGUMENT = "input"; //$NON-NLS-1$

private final ObjectMapper objectMapper;

private final IExceptionWrapper exceptionWrapper;

private final IEditingContextDispatcher editingContextDispatcher;

public MutationEditRichTextDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) {
this.objectMapper = Objects.requireNonNull(objectMapper);
this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper);
this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher);
}

@Override
public CompletableFuture<IPayload> get(DataFetchingEnvironment environment) throws Exception {
Object argument = environment.getArgument(INPUT_ARGUMENT);
var input = this.objectMapper.convertValue(argument, EditRichTextInput.class);

return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.getEditingContextId(), input), input).toFuture();
}
}

0 comments on commit 46779e7

Please sign in to comment.