[MGNLUI-8033] RichTextField should support "linkable apps" Created: 02/May/23  Updated: 12/Sep/23

Status: Open
Project: Magnolia UI
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Neutral
Reporter: Thomas Duffey Assignee: Dominik Maslanka
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Date of First Response:
Team: Nucleus

 Description   

The light rich text field includes a "linkable apps" attribute that allows content authors to quickly create links between content items in different content apps. The standard rich text field should also support this.

Note this is being added via customization for Sanofi thanks to @Roman's provided Java code update for the rich text field.



 Comments   
Comment by Thomas Duffey [ 02/May/23 ]
/**
 * This file Copyright (c) 2023 Magnolia International
 * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
 *
 *
 * This program and the accompanying materials are made
 * available under the terms of the Magnolia Network Agreement
 * which accompanies this distribution, and is available at
 * http://www.magnolia-cms.com/mna.html
 *
 * Any modifications to this file must keep this entire header
 * intact.
 *
 */
package info.magnolia.editor.field.factory;

import static info.magnolia.ui.vaadin.ckeditor.MagnoliaCKEditorTextFieldEvents.EVENT_CANCEL_LINK;

import info.magnolia.dam.jcr.DamConstants;
import info.magnolia.editor.v2.body.LinkChooser;
import info.magnolia.i18nsystem.I18nizer;
import info.magnolia.i18nsystem.SimpleTranslator;
import info.magnolia.ui.dialog.DialogDefinitionRegistry;
import info.magnolia.ui.field.RichTextFieldDefinition;
import info.magnolia.ui.field.factory.RichTextFieldFactory;
import info.magnolia.ui.framework.ioc.UiComponentProvider;
import info.magnolia.ui.framework.overlay.ChooserController;
import info.magnolia.ui.vaadin.ckeditor.MagnoliaCKEditorTextField;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

import javax.inject.Inject;

import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;

/**
 * Linkable RichTextFieldFactory.
 */
public class LinkableRichTextFieldFactory extends RichTextFieldFactory {

    private final LinkChooser linkChooser;

    @Inject
    public LinkableRichTextFieldFactory(Definition definition, UiComponentProvider componentProvider, SimpleTranslator i18n, ChooserController chooserController, DialogDefinitionRegistry dialogDefinitionRegistry, I18nizer i18nizer, LinkChooser linkChooser) {
        super(definition, componentProvider, i18n, dialogDefinitionRegistry, i18nizer);
        this.linkChooser = linkChooser;
    }

    @Override
    protected void openLinkDialog(MagnoliaCKEditorTextField richTextEditor, PluginData pluginData, Consumer<Object> consumer) {
        if (DamConstants.WORKSPACE.equals(pluginData.workspace)) {
            super.openLinkDialog(richTextEditor, pluginData, consumer);
            return;
        }
        Set<String> linkableApps = getDefinition().getLinkableApps();
        CompletableFuture<?> future = linkChooser.start(linkableApps);
        future.thenAccept(consumer::accept)
                .exceptionally(throwable -> {
                    richTextEditor.firePluginEvent(EVENT_CANCEL_LINK);
                    return null;
                });
    }

    @Override
    protected MagnoliaLink createMagnoliaLink(Object object) {
        if (object.getClass().getName().startsWith(LinkChooser.class.getName())) {
            MagnoliaLink mlink = new MagnoliaLink();
            mlink.repository = getString(object, "repository");
            mlink.path = getString(object, "path");
            mlink.identifier = getString(object, "identifier");
            mlink.caption = getString(object, "caption");
            return mlink;
        } else {
            return super.createMagnoliaLink(object);
        }
    }

    @Override
    protected Definition getDefinition() {
        return (Definition) super.getDefinition();
    }

    @SneakyThrows(ReflectiveOperationException.class)
    private static String getString(Object object, String repository) {
        return (String) object.getClass().getDeclaredField(repository).get(object);
    }

    @Setter
    @Getter
    public static class Definition extends RichTextFieldDefinition {

        private Set<String> linkableApps = Collections.singleton("pages-app");

        public Definition() {
            setFactoryClass(LinkableRichTextFieldFactory.class);
        }
    }
} 
Comment by Thomas Duffey [ 08/May/23 ]

We ended up having to also duplicate/copy/paste the following from the light rich text field due to errors when clicking the "cancel" button:

  • added overrides for LinkChooser to modify private method complete inside start method
  • recreated the whole ListDialogHelper since it has private constructor and method
  • added null handler in complete method
Comment by Roman Kovařík [ 15/May/23 ]

If this would become a part of the framework (not an extension), I'd expect to be it much more simple like e.g. the switcher in JCR browser with configurable list of workspaces. But up to the Nucleus team, cc dmaslanka.

Generated at Mon Feb 12 09:51:31 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.