Giter VIP home page Giter VIP logo

Comments (23)

alyssaxuu avatar alyssaxuu commented on May 17, 2024 6

I am considering adding the functionality of creating "grouped blocks", for example, as shown by @robhoward in this image (which can be used for conditional blocks):

image

That way it could be dragged from the "panel" as a single unit, and have two outputs prebuilt.

I don't think I can come up with another way to implement conditional/logic blocks differently. Adding multiple arrows to the output of a block would be really tricky to implement with the current library, as it would cause issues with spacing and centering.

I'm going to explore the grouping functionalty for the next release (which will be bundled with new features and improvements), but it is not guaranteed yet.

from flowy.

johndkn avatar johndkn commented on May 17, 2024 4

Thanks for your reply :)

I gave it a lot of thought since yesterday, and maybe the best UX is to have instead "Filtering Blocks" in which we could implement conditional logic.

Example :
image

from flowy.

robhoward avatar robhoward commented on May 17, 2024 4

We solved this with a block controller that owns how parent/child relationships get setup, e.g. what children can snap to what parent and some parents are 'decision' types.

And, my vote would be to keep flowy simple per @fqure

image

from flowy.

cdebattista avatar cdebattista commented on May 17, 2024 4

Here is my way.

I have a "Class" who is loading modules window.Automation.
Each module has his own functions but have same requirements info.
All forms elements is linked with his hidden input.

window.ConditionSource = {
    init: function () {
        this.info = {
            class: 'ConditionSource',
            name: 'source',
            title: 'Source',
            blocks: {
                canvas: '...../block.html'
            },
            selects: [
                {name: 'ConditionSource_selectState', hidden: 'source_state'},
                {name: 'ConditionSource_selectSource', hidden: 'source_id', populate: true, function: 'selectSource'}
            ]
        }
    },
....
}

I have a test button to match with the first contact in DB.
Success = green, failed = red.
if success but his parent is false = red

WIP, have to make block allowParent, etc...

I didn't want a popup to enter settings. I wanted to do all in the canvas, to be faster.

check video
img

from flowy.

johndkn avatar johndkn commented on May 17, 2024 2

Woow! Thanks @robhoward for these details! This "wrapper" seems like an amazing solution to organize the blocks and the logic. Would love to see this in a pull request.

from flowy.

robhoward avatar robhoward commented on May 17, 2024 1

Sure, @johndkn - hopefully I can explain it in a way that makes sense :)

We created a "blockBase" that wraps flowly. For example, it manages an internal array of blocks and the loading/saving. It also handles all the logic of what block and snap to what block/etc. We started with the example @alyssaxuu put together and took it further. Then we added functions for getting blocks by id/etc.

Each block is a separate object. For example, below is the "Yes" block.

The blockBase then renders all the loaded blocks into the UI by blockType. It places them in the UI by group, e.g. Trigger, Condition, Action. It then calls methods on the the block when it is dragged, rendered, needs to show properties, check parents, etc.

We're so happy with how this turned out. We always had workflow in our system, but we couldn't find a solid, simple way to visualize it. So much so, we just updated our website with a screen shot highlighting it :)

https://www.dailystory.com/ (just scroll down slightly)

And we also made some updates to flowy itself. I'd like to try to get those submitted as pull requests soon.

// ┌────────────────────────────────────────────────────────────────────
// │ Decision block Yes
// └────────────────────────────────────────────────────────────────────
var blockYes = {

// ┌────────────────────────────────────────────────────────────────────
// │ Required - unique name of the block matches enum AutomationDecisionType.Yes
// └────────────────────────────────────────────────────────────────────
name: "Yes",

// ┌────────────────────────────────────────────────────────────────────
// │ Required - friendly name of the block, shown in messages
// └────────────────────────────────────────────────────────────────────
friendlyName: "Yes",

// ┌────────────────────────────────────────────────────────────────────
// │ Required - list of parents this block can snap to. Empty array means all
// └────────────────────────────────────────────────────────────────────
allowedParents: ['HasOpenedEmail', 'HasClickedEmail', 'HasRepliedToTextMessage', 'HasTextMessageReply','HasCustomRule'],

// ┌────────────────────────────────────────────────────────────────────
// │ Required - type of block
// └────────────────────────────────────────────────────────────────────
blockType: 'Condition',

// ┌────────────────────────────────────────────────────────────────────
// │ Required - does this block have properties
// └────────────────────────────────────────────────────────────────────
hasProperties: false,

// ┌────────────────────────────────────────────────────────────────────
// │ Required - validates the block, called on save
// └────────────────────────────────────────────────────────────────────
validate: function (props) {
    return { status: true };
},

// ┌────────────────────────────────────────────────────────────────────
// │ Required - renders HTML for block in toolbar
// └────────────────────────────────────────────────────────────────────
getToolbarBlock: function () {
    return `<div class="blockelem create-flowy noselect">
                    <input type="hidden" name="blockelemtype" class="blockelemtype" value="${this.name}">                            
                        <div class="blockin">
                            <div class="blockico"><span></span><i class="fad fa-thumbs-up"></i></div>
                            <div class="blocktext"><p class="blocktitle">${this.friendlyName}</p><p class="blockdesc">Used with a condition</p></div>
                        </div>
                </div>`;
},

// ┌────────────────────────────────────────────────────────────────────
// │ Required - renders HTML when block is placed in designer
// └────────────────────────────────────────────────────────────────────
renderDrag: function (elem, parent) {
    elem.innerHTML += `<div class='blockyinfo-basic'><p class='blockyname-basic'>${this.friendlyName}</p></div>`;
    elem.classList.add('decision-yes');
}

};
blockBase.register(blockYes);

from flowy.

fj-vega avatar fj-vega commented on May 17, 2024 1

Thanks for the contribution @robhoward .
Do you plan on creating a pull request? I want to use flowy but I really need the conditional blocks feature.

from flowy.

brijesh-k-bharattechlabs-com avatar brijesh-k-bharattechlabs-com commented on May 17, 2024 1

@alyssaxuu are you planning to implement conditional blocks anytime soon?

from flowy.

brijesh-k-bharattechlabs-com avatar brijesh-k-bharattechlabs-com commented on May 17, 2024 1

@robhoward have you implement conditional blocks and submit a pull request?

from flowy.

robhoward avatar robhoward commented on May 17, 2024 1

Hi @laura040796 unfortunately my version of flowy is pretty much completely re-written, so I'm not sure how much help the code would be. But I can tell you how it works:

During the snapping event a check is done to see if the block is allowed to snap to the parent:

            // check if can snap these blocks together
            if (!blockBase.allowedToSnapToParent(drag, parent, first))
                return false;

The allowedToSnapToParent method walks through the conditions to determine if snapping will return true/false. For example:

    // Is this parent in the child's allowed parents list
    if (isParentInChildAllowedList()) {
        allowed_to_snap = true;
    } else {
        DsUtility.statusMessage(`'${child_block.friendlyName}' cannot be used with '${parent_block.friendlyName}'`);
        allowed_to_snap = false;
    }

    // Is this child in the parent's allowed childs list
    if (isChildInParentAllowedList()) {
        allowed_to_snap = true;
    } else {
        DsUtility.statusMessage(`'${child_block.friendlyName}' cannot be used with '${parent_block.friendlyName}'`);
        allowed_to_snap = false;
    }

    // Does the parent allow children
    if (allowed_to_snap && parent_block && undefined !== parent_block.allowChildren && !parent_block.allowChildren) {
        DsUtility.statusMessage(`'${parent_block.friendlyName}' cannot have additional steps`);
        allowed_to_snap = false;
    }

    // Does this parent already have children?
    if (allowed_to_snap) {
        if (isChildAllowedInParent(parent, child_block)) {
            allowed_to_snap = true;
        } else {
            allowed_to_snap = true;
        }
    }

from flowy.

alyssaxuu avatar alyssaxuu commented on May 17, 2024

How would you see it best implemented w/ the current mechanics? Special blocks that instead of being able to have infinite children, have 2 children max, each for a different outcome? Doable for sure, just trying to think of the best UX for this sort of scenario (also because in this case the order of the "children blocks" is important, and you should be able to choose if you put it on the left or the right side, something that isn't possible w/ the current engine).

from flowy.

fqure avatar fqure commented on May 17, 2024

There are dozens of flowchart type scripts out there packed with numerous features and UI/UX artifacts. What's significant about Flowy is its very vanilla-like simplicity. If it's going to be a library encapsulated into other larger projects, it's important to keep simplicity in mind to keep options open for unforeseen behavior types.
Here's a possible litmus test to consider when adopting new behavior: Could these blocks and relationships be translated 1:1 into a textual format (ie. Markdown) for documentation?
The current "If ___ is from ___ then ___" or "When ___ days have pass" statements inside these blocks should be simple enough to create conditional prompts for developers to add time delays, pending tasks, logic dependencies, and from another issue groups without adding artifacts that could increase user complexity.

I guess we're at a fork.
Does Flowy build additional visual UI/UX artifacts to denote behavior or does it leave it as-is in its current textual state and leave it to the beholder to decide.

from flowy.

johndkn avatar johndkn commented on May 17, 2024

This is awesome @robhoward! Can you give us more details on how you achieved this?

from flowy.

yellow1912 avatar yellow1912 commented on May 17, 2024

Thank you @robhoward , I think it's an amazing idea. With this you can create "virtual" blocks that group things together. You can even decide to hide the children block if you dont want to show, amazing.

from flowy.

robhoward avatar robhoward commented on May 17, 2024

Just my $0.02 on this as we have this in production now:

An action, such as "text message replied to" can evaluate to true or false. We're finding that in some cases customers only care about one condition vs both.

So, as long as the group block could have the concept of removing one of the items in the group on the design surface.

from flowy.

alyssaxuu avatar alyssaxuu commented on May 17, 2024

Just my $0.02 on this as we have this in production now:

An action, such as "text message replied to" can evaluate to true or false. We're finding that in some cases customers only care about one condition vs both.

So, as long as the group block could have the concept of removing one of the items in the group on the design surface.

Interesting. I suppose that could be possible by adding an optional parameter when creating blocks that allows it to be broken apart by the user (or else locked together).

from flowy.

fqure avatar fqure commented on May 17, 2024

Possibly a new view to create a group block that is saved to the global block list to save space on the main view while keeping easy usability for those that don't need group blocks?

from flowy.

aadityak avatar aadityak commented on May 17, 2024

Are conditional blocks as described by @johndkn planned anytime soon?

from flowy.

papeventures avatar papeventures commented on May 17, 2024

HS does a good job with having the arrows pre-rendered for decision points. Labels on the arrows would be amazing!
https://blog.hubspot.com/customers/sales-management-pain-points-workflow-automation

from flowy.

jatinderbhola avatar jatinderbhola commented on May 17, 2024

Here is my way.

I have a "Class" who is loading modules window.Automation.
Each module has his own functions but have same requirements info.
All forms elements is linked with his hidden input.

window.ConditionSource = {
    init: function () {
        this.info = {
            class: 'ConditionSource',
            name: 'source',
            title: 'Source',
            blocks: {
                canvas: '...../block.html'
            },
            selects: [
                {name: 'ConditionSource_selectState', hidden: 'source_state'},
                {name: 'ConditionSource_selectSource', hidden: 'source_id', populate: true, function: 'selectSource'}
            ]
        }
    },
....
}

I have a test button to match with the first contact in DB.
Success = green, failed = red.
if success but his parent is false = red

WIP, have to make block allowParent, etc...

I didn't want a popup to enter settings. I wanted to do all in the canvas, to be faster.

check video
img

@cdebattista amazing work! Can you be kind enough to jump start toward the similar direction. I am trying to build similar application (user flow). Any help/ direction would be really appreciated.

from flowy.

loralll0 avatar loralll0 commented on May 17, 2024

@robhoward
I want to have only one child when you drop the block like you have in DailyStory, not like this one:
multipleParents
Can you help me with this? Thanks

from flowy.

jhaineymilevis avatar jhaineymilevis commented on May 17, 2024

@robhoward is possible see your version?

from flowy.

robhoward avatar robhoward commented on May 17, 2024

@jhaineymilevis unfortunately it's pretty much been re-written from the original flowy at this point. What are you trying to solve for?

from flowy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.