Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: CKE5 placeholder insert plugin #46

Merged
merged 2 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 8 additions & 1 deletion Configuration/NodeTypes.Finishers.Confirmation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@
group: 'finisher'
editor: 'Neos.Neos/Inspector/Editors/CodeEditor'
editorOptions:
buttonLabel: i18n
buttonLabel: i18n
# Alternatively enable a rich text editor:
# editor: 'Neos.Neos/Inspector/Editors/RichTextEditor'
# editorOptions:
# formatting:
# placeholderInsert: true
# strong: true
# em: true
9 changes: 8 additions & 1 deletion Configuration/NodeTypes.Finishers.Email.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
editor: 'Neos.Neos/Inspector/Editors/CodeEditor'
editorOptions:
buttonLabel: i18n
# Alternatively enable a rich text editor:
# editor: 'Neos.Neos/Inspector/Editors/RichTextEditor'
# editorOptions:
# formatting:
# placeholderInsert: true
# strong: true
# em: true
'recipientAddress':
type: string
ui:
Expand Down Expand Up @@ -102,4 +109,4 @@
ui:
label: i18n
inspector:
group: 'finisher-attachments'
group: 'finisher-attachments'
6 changes: 6 additions & 0 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,9 @@ Neos:
'form.selectOptions':
label: 'Select options'
collapsed: false

Ui:
resources:
javascript:
"Neos.Form.Builder:PlaceholderInsert":
resource: '${"resource://Neos.Form.Builder/Public/JavaScript/PlaceholderInsert/Plugin.js"}'
1 change: 1 addition & 0 deletions Resources/Private/PlaceholderInsert/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
15 changes: 15 additions & 0 deletions Resources/Private/PlaceholderInsert/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"description": "PlaceholderInsert",
"license": "MIT",
"private": true,
"scripts": {
"build": "neos-react-scripts build",
"watch": "neos-react-scripts watch"
},
"devDependencies": {
"@neos-project/neos-ui-extensibility": "^1.3"
Copy link
Member

Choose a reason for hiding this comment

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

really version 1.3?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't matter really, it would compile with any version of the extensibility package. Will change to wildcard to avoid confusion.

},
"neos": {
"buildTargetDirectory": "../../Public/JavaScript/PlaceholderInsert"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { connect } from "react-redux";
import { SelectBox } from "@neos-project/react-ui-components";
import React, { PureComponent } from "react";
import { neos } from "@neos-project/neos-ui-decorators";
import { $transform } from "plow-js";
import { selectors } from "@neos-project/neos-ui-redux-store";

export const parentNodeContextPath = contextPath => {
if (typeof contextPath !== "string") {
console.error("`contextPath` must be a string!"); // tslint:disable-line
return null;
}
const [path, context] = contextPath.split("@");

if (path.length === 0) {
// We are at top level; so there is no parent anymore!
return null;
}

return `${path.substr(0, path.lastIndexOf("/"))}@${context}`;
};

@connect(
$transform({
nodesByContextPath: selectors.CR.Nodes.nodesByContextPathSelector,
focusedNode: selectors.CR.Nodes.focusedSelector
})
)
@neos(globalRegistry => ({
i18nRegistry: globalRegistry.get("i18n"),
nodeTypeRegistry: globalRegistry.get(
"@neos-project/neos-ui-contentrepository"
)
}))
export default class PlaceholderInsertDropdown extends PureComponent {
handleOnSelect = value => {
this.props.executeCommand("placeholderInsert", value);
};

render() {
const [formPath, workspace] = parentNodeContextPath(
parentNodeContextPath(this.props.focusedNode.contextPath)
).split("@");

const elementsPath = `${formPath}/elements@${workspace}`;

const elementsNode = this.props.nodesByContextPath[elementsPath];
if (!elementsNode) {
return null;
}
const options = elementsNode.children
.map(node => this.props.nodesByContextPath[node.contextPath])
.map(node => ({
value: node.properties.identifier || node.identifier,

Choose a reason for hiding this comment

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

Would it be possible to have this in Settings? While thinking of it, I see that different use-cases are possible; sometimes you want to use speaking identifiers, sometimes not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you describe your idea in more details: setting name, setting format, what exactly it does etc?

Choose a reason for hiding this comment

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

After thinking again, let's not over-complicate things for the moment and go with it as it is.

label:
node.properties.label || node.properties.identifier || node.identifier
}));

if (options.length === 0) {
return null;
}

const placeholderLabel = this.props.i18nRegistry.translate(
"Neos.Form.Builder:Main:placeholder",
"Insert placeholder"

Choose a reason for hiding this comment

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

This should be localized.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is, once the translations will be in place, it would show up, this is just a fallback

);

return (
<SelectBox
placeholder={placeholderLabel}
options={options}
onValueChange={this.handleOnSelect}
value={null}
/>
);
}
}
1 change: 1 addition & 0 deletions Resources/Private/PlaceholderInsert/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("./manifest");
28 changes: 28 additions & 0 deletions Resources/Private/PlaceholderInsert/src/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import manifest from "@neos-project/neos-ui-extensibility";
import PlaceholderInsertDropdown from "./PlaceholderInsertDropdown";
import placeholderInsertPlugin from "./placeholderInsertPlugin";
import { $add, $get } from "plow-js";

const addPlugin = (Plugin, isEnabled) => (ckEditorConfiguration, options) => {
if (!isEnabled || isEnabled(options.editorOptions, options)) {
ckEditorConfiguration.plugins = ckEditorConfiguration.plugins || [];
return $add("plugins", Plugin, ckEditorConfiguration);
}
return ckEditorConfiguration;
};

manifest("Neos.Form.Builder:PlaceholderInsert", {}, globalRegistry => {
const richtextToolbar = globalRegistry
.get("ckEditor5")
.get("richtextToolbar");
richtextToolbar.set("placeholderInsertt", {
component: PlaceholderInsertDropdown,
isVisible: $get("formatting.placeholderInsert")
});

const config = globalRegistry.get("ckEditor5").get("config");
config.set(
"placeholderInsert",
addPlugin(placeholderInsertPlugin, $get("formatting.placeholderInsert"))
);
});
25 changes: 25 additions & 0 deletions Resources/Private/PlaceholderInsert/src/placeholderInsertPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ModelText, Command, Plugin } from "ckeditor5-exports";

class PlaceholderInsertCommand extends Command {
execute(value) {
const model = this.editor.model;
const doc = model.document;
const selection = doc.selection;
const placeholder = new ModelText("{" + value + "}");
model.insertContent(placeholder, selection);
}
}

export default class PlaceholderInsertPlugin extends Plugin {
static get pluginName() {
return "PlaceholderInsert";
}
init() {
const editor = this.editor;

editor.commands.add(
"placeholderInsert",
new PlaceholderInsertCommand(this.editor)
);
}
}
Loading