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

Enable conditional inserts of blocks in the toolbar or implement schemas #768

Open
nynevi opened this issue May 14, 2019 · 1 comment
Open

Comments

@nynevi
Copy link

nynevi commented May 14, 2019

Hi,

First of all, thank you for your efforts. We like the project and if it turns out that we can work with it, hopefully we contribute to it in the future.

We have a situation where some part of the document needs to be paid for in order to read. So we have thought of several solutions for this (considering the best UX):

  1. have a custom block and nest pay-to-read stuff inside this block but as editorjs does not support nested blocks, we have gave up on this idea (I've read it in reddit where someone was asking whether editorjs supported nested structures and the answer from you was 'you can do complex plugins for nested structures' but the fact that the structure inside the plugin should be dynamic does not allow this idea I think)
  2. have a custom divider block (like the delimiter plugin) that when you insert it, stuff below becomes pay-to-read (on the backend we simply split the array by the index of this custom block). there is one condition, there has to be only one pay section divider (if there was a nested structure, we could have several pay to read sections in one article but that would be an edge case because most people just have one section in their articles so this single divider idea is valid)
  3. have several editor instances, one for the free stuff, one for the paid stuff with no delimiter/divider (not good UX)
  4. set the paid section just before publishing/saving. but we want the UX to be as close to editorjs's UX flow where writing feels natural. this approach adds another step to publish the article so we also scrapped this idea but we'll do it if we have to. here is an example: https://media.giphy.com/media/MePJiKgmk9jLaF1zN2/giphy.gif
  5. loop through blocks and warn user just before publish/save that he cannot have more than one divider and ask him to remove it or we take the first divider block and remove the latter from the blocks array then submit (also bad UX and kind of opinionated)
  6. use the mouse selection rectangle to select the blocks then use a tool to mark the blocks (I believe the current InlineTool can only work with text inside a single block so something needs to be developed for this in editorjs). so at the moment the mouse selection exists only to select and hit delete to remove the blocks because when you select them you cannot move them up/down with the arrows as a whole set of blocks; when you click the ... in the corner it just selects the topmost block and deselects the rest. Given that this would work, we also have concerns for the mobile usage of the editor causing problems with block selection (it would probably select just the text in mobile).

The second approach seemed feasible but there are some limitations towards this implementation:

  • you cannot check programmatically the click event on block icon in the + toolbar to see whether it should be inserted into the document or else (alert, notify, console.log etc). we probably can tap into it but it will again be monkey-patching and the result would not be any different than the error we receive below.
  • you have to check in block plugin whether there is already a paid section divider and conditionally return the element

so we have the exact same structure of the delimiter plugin where we do monkey-patching for this but in the end we cheat the editor which we don't really want and also we don't know of the consequences of the error we get from this:

    const blockCount = this.api.blocks.getBlocksCount();
    for (var index = 0; index < blockCount; index++) {
      const block = this.api.blocks.getBlockByIndex(index);
      const hasPaywall = block.innerHTML.includes('ce-paywall');
      if (hasPaywall) {
        this.existing = true;
        break;
      }
    }

and then on the render method:

  render() {
    if (!this.existing) {
      return this._element;
    }
  }

so when we don't return an element from render function the following error pops in console:
ERROR TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

some solutions:

  1. so a general approach to this problem would be to introduce schemas for the document but then it would take some time to develop this, even the planning for this, taking into account several different editor schema implementations would take some time...
  2. another approach would be to accept render function returning void (or null) and make the appendChild void-proof (or null-proof)
  3. have a validate function in the EditorConfig tools object where it returns a boolean whether the click should go through and do the action
  4. have the toolbar icon button disabled if there is already one of that block but again this needs kind of a validate function and the checks need to be done at each toolbar.open. this would kind of indicate the intention but it also requires a kind of a tooltip to show the intention message explicitly on hover or some other area to show the error. 'the double click to remove a block' functionality might be used so that the icon would change to grey 'prohibited' icon with disabled status but again it would lack the message for the intention.
    link: {
      class: Link,
      validate: (api) => {},
      ...
    },

Is there a refined way of doing this that I could not think of? How and what needs to be implemented to have this work?

@taurenshaman
Copy link

I love the 4th solution, which separates the business logic and content editor.
I think one document/article should contains several sections/chapters (in ordered list). So you can make every section/chapter free or not free.
After the editor initialized, get sections list by URIs (e.g. https://a.com/article/1234/section/{1~99}.
The server check what content to return (section data or PayBlock data).

I created a Cytoscape block, get data by URI and then render it: https://taurenshaman.github.io/editor@codexteam+jsoneditor.html
You can switch graph layout through a html select element. Also you can add a BUY button.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants