flowy icon indicating copy to clipboard operation
flowy copied to clipboard

Zoom in/out

Open taf2 opened this issue 5 years ago • 30 comments

It would be great and very useful if for larger diagrams we could zoom in/out. This would make it easier to visualize larger flows.

taf2 avatar Dec 16 '19 02:12 taf2

That could definitely be a good idea, I'll look into it.

alyssaxuu avatar Dec 16 '19 09:12 alyssaxuu

In addition to zooming in and out, perhaps this is more useful: module. I find this concept really useful on Botstar.com which has a comprehensive UI to build bot flows. The module allow you to group multiple steps and hide them by default. image

yellow1912 avatar Apr 16 '20 15:04 yellow1912

NVM, I found https://github.com/alyssaxuu/flowy/issues/29 which proposes the idea of a wrapper outside of flowy to keep things simple. I think that's quite amazing to be honest. It would be nice if we do have the api to addBlock and removeBlock exposed, that would help alot.

yellow1912 avatar Apr 16 '20 15:04 yellow1912

NVM, I found #29 which proposes the idea of a wrapper outside of flowy to keep things simple. I think that's quite amazing to be honest. It would be nice if we do have the api to addBlock and removeBlock exposed, that would help alot.

What would "addBlock" being exposed look like? There is currently onSnap which gets triggered when a block is able to be attached to another block, which lets you to either prevent or allow the attachment. Just added a method for the block removal.

alyssaxuu avatar Apr 16 '20 15:04 alyssaxuu

I think right now all the "actions" require interaction from the user (drag and drop). There is an import method but it would affect the whole tree. Perhaps we could extend the import and allow specifying the root of the import, would that work?

yellow1912 avatar Apr 17 '20 00:04 yellow1912

I think right now all the "actions" require interaction from the user (drag and drop). There is an import method but it would affect the whole tree. Perhaps we could extend the import and allow specifying the root of the import, would that work?

I see, so you suggest a way to import blocks under a certain parent? I can definitely make it so that blocks can be added programmatically (and not just individual blocks, also trees), but the problem is, how would that work? Blocks can be 100% custom - so would it be a method that accepts some HTML, an array of blocks, and the ID of the desired parent? Not sure what would be the most intuitive here.

alyssaxuu avatar Apr 17 '20 01:04 alyssaxuu

I see what you mean, can it work the same way with the import to make things consistent?

{
	"html": "",
	"blockarr": [],
	"blocks": [
		{
			"id": 1,
			"parent": 0,
			"data": [
				{
				"name": "blockid",
				"value": "1"
				}
			],
			"attr": [
				{
				"id": "block-id",
				"class": "block-class"
				}
			]
		}
	]
}

Regarding the HTML, I think we should avoid touching any HTML if possible and only deal with json data. There could be a render callback that accept a block data then return a rendered HTML string perhaps?

yellow1912 avatar Apr 17 '20 05:04 yellow1912

Hello, I was thinking about implementing this feature as well, Do you think using the scale property on all dom element on the canvas, and updating the blocks array would be enough? I mean scaling with the same ratio the blocks? As it did not succeed so far. If you have a direction, that would be great ;)

pilootchoum avatar Apr 22 '20 17:04 pilootchoum

Hello, I was thinking about implementing this feature as well, Do you think using the scale property on all dom element on the canvas, and updating the blocks array would be enough? I mean scaling with the same ratio the blocks? As it did not succeed so far. If you have a direction, that would be great ;)

I assume you mean using transform: scale()? It's certainly possible, I would just need to make sure this doesn't cause any conflicts with the block positioning/dimensions.

I haven't been prioritizing this feature simply because I see a potential problem - if the canvas area is scaled up/down, how would it look/feel like dragging and dropping a differently sized block there (e.g. in the demo, from the left panel)? I'm just not sure if it would feel smooth or intuitive.

Screen Shot 2020-04-24 at 8 22 19 AM

Here's an image of what I mean. It might just feel weird, but I'm open to hearing your thoughts.

alyssaxuu avatar Apr 24 '20 15:04 alyssaxuu

Sure I thought about this too, maybe, I would have forced the user then to reset the zoom before dropping a new element on the canvas, but that would be out of Flowy charge I mean.

Its just that after adding a few blocks, it seems to me that it becomes quite hard to see properly the canvas and maybe rearrange the blocks if needed.

But one can also just use the browser zoom feature if needed. Anyway that feature would be awesome I think ;)

pilootchoum avatar Apr 24 '20 15:04 pilootchoum

Sure I thought about this too, maybe, I would have forced the user then to reset the zoom before dropping a new element on the canvas, but that would be out of Flowy charge I mean.

Its just that after adding a few blocks, it seems to me that it becomes quite hard to see properly the canvas and maybe rearrange the blocks if needed.

But one can also just use the browser zoom feature if needed. Anyway that feature would be awesome I think ;)

Hmm in that case the developer could simply use transform: scale() on the canvas themselves, since either way the block snapping / dragging functionality would be off when resizing. So I don't see it being useful as a method, in that sense. Like I said, unless someone thinks of a better way to go about it - maybe it could work when resized, just that when the block is dropped into the flowchart it would resize to match automatically?

alyssaxuu avatar Apr 24 '20 15:04 alyssaxuu

Yes that would be the best I think, Once dropped the block should resize automaticlly to the new scale.

pilootchoum avatar Apr 24 '20 15:04 pilootchoum

Hello @alyssaxuu,

I tried to implement it myself doing the following :

on zoom in I am changing the scale of every childNode of the canvas except the arrows : document.getElementById("canvas").childNodes.forEach((node) => { if (node.className.indexOf("arrowblock") < 0) { node.style.transform = "scale(" + this.currentScale + ")"; } });

Then in flowy, I am updating the height and witdth of every block :

flowy.scale = function (scale) { blocks.forEach(function (block) { block.width = block.width * scale; block.height = block.height * scale; }); if (blocks.length > 1) { rearrangeMe(); } };

I thought that the rearrangeMe function would update then the childWidth properties, and redraw the arrows to fit the new size of the element, however it does not seem to work properly.

Do you have any hint on how to do that in a better way?

pilootchoum avatar May 05 '20 07:05 pilootchoum

Hello @alyssaxuu,

I tried to implement it myself doing the following :

on zoom in I am changing the scale of every childNode of the canvas except the arrows : document.getElementById("canvas").childNodes.forEach((node) => { if (node.className.indexOf("arrowblock") < 0) { node.style.transform = "scale(" + this.currentScale + ")"; } });

Then in flowy, I am updating the height and witdth of every block :

flowy.scale = function (scale) { blocks.forEach(function (block) { block.width = block.width * scale; block.height = block.height * scale; }); if (blocks.length > 1) { rearrangeMe(); } };

I thought that the rearrangeMe function would update then the childWidth properties, and redraw the arrows to fit the new size of the element, however it does not seem to work properly.

Do you have any hint on how to do that in a better way?

I believe the best way to go about it would be to use transform scale to resize the canvas' contents, and then immediately after replace all the array properties of the blocks (I see you updated height and width, but there's also the X and Y properties that are important which you're missing. Childwidth is used to store how much space all the children elements one next to the other (including spacing in between) takes in order to then calculate how much offset a new block being dragged in should have. I suppose if you changed all those properties and ran the rearrangeMe function it should work (haven't tested it though).

alyssaxuu avatar May 29 '20 11:05 alyssaxuu

Someone have a solution ? screencast-crm-preprod fboard app-2020 10 19-10_20_38

One solution works but arrows are !@{"#

        let _this = this;
        let ratio = this.scale / this.previousScale;
        let canvas = document.getElementById("canvas");
        //console.log(ratio);

        canvas.childNodes.forEach(function(node){

            let nodeX = parseFloat(window.getComputedStyle(node).left);
            let nodeY = parseFloat(window.getComputedStyle(node).top);

            let style = window.getComputedStyle(node);
            let matrix = new WebKitCSSMatrix(style.transform);

            let previousTx = (- matrix.m41 * _this.previousScale);
            let previousTy = (- matrix.m42 * _this.previousScale);

            let previousDx = (nodeX * _this.previousScale);
            let previousDy = (nodeY * _this.previousScale);

            let newTx = ((previousTx * ratio + previousDx * (ratio - 1)) / _this.scale);
            let newTy = ((previousTy * ratio + previousDy * (ratio - 1)) / _this.scale);

            let newX = nodeX - newTx;
            let newY = nodeY - newTy;

            //node.style.transform = "scale(" + _this.scale + ")";

            //node.style.transform = "scale(" + _this.scale + ") translate(" + newTx + "px, " + newTy + "px)";
            //node.style.transformOrigin = "0 0";


            if (node.className.indexOf("arrowblock") < 0) {
                let blockProperties = {
                    id: parseInt(node.querySelector(".blockid").value),
                    x: ((node.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(node).width) / 2) + canvas.scrollLeft) * _this.scale,
                    y: ((node.getBoundingClientRect().top + window.scrollY) + (parseInt(window.getComputedStyle(node).height) / 2) + canvas.scrollTop) * _this.scale,
                    width: (parseInt(window.getComputedStyle(node).width)) * _this.scale,
                    height: (parseInt(window.getComputedStyle(node).height)) * _this.scale
                }
                let blocStyles = {
                    top : ((node.getBoundingClientRect().top + window.scrollY) - (canvas.getBoundingClientRect().top + window.scrollY) + canvas.scrollTop) * _this.scale,
                    left : ((node.getBoundingClientRect().left + window.scrollX) - (canvas.getBoundingClientRect().left + window.scrollX) + canvas.scrollLeft) * _this.scale
                }
                console.log(blockProperties, blocStyles);
                node.style.left = blocStyles.left + 'px';
                node.style.top = blocStyles.top + 'px';
                //node.style.transform = "scale(" + _this.scale + ")";
                node.style.transform = "scale(" + _this.scale + ") translate(" + newTx + "px, " + newTy + "px)";
                //node.style.transformOrigin = "0 0";
                //node.style.left = newX + 'px';
                //node.style.top = newY + 'px';
                flowy.transformBlocks(blockProperties.id, 'x', blockProperties.x);
                flowy.transformBlocks(blockProperties.id, 'y', blockProperties.y);
                flowy.transformBlocks(blockProperties.id, 'width', blockProperties.width);
                flowy.transformBlocks(blockProperties.id, 'height', blockProperties.height);

            }else{
                node.style.transform = "scale(" + _this.scale + ")";
            }

            /*console.log(nodeX, nodeY);
            console.log(previousTx, previousTy);
            console.log(previousDx, previousDy);
            console.log(newTx, newTy);
            console.log(newX, newY);*/

        });
        //flowy.scale(this.scale);
        console.log(flowy.output());

I tried a CSS trick and it works but now have to changes the x,y,width,height,childwitdh and the code above don't work

        canvas.style.transform = "scale(" + this.scale + ")";
        canvas.style.width = "calc(" + 100 / this.scale  + "% - 0px)"
        canvas.style.height = "calc(" + 100 / this.scale  + "% - 0px)"
        canvas.style.top = (100 - (100 / this.scale)) / 2 + "%"
        canvas.style.left = (100 - (100 / this.scale)) / 2 + "%"

cdebattista avatar Oct 19 '20 08:10 cdebattista

Finally got it ! next step panning. screencast-crm-preprod fboard app-2020 10 19-15_36_04

var zoom = 1;
...
...
flowy.zoom = function(value = 0, restore = false){
	zoom += value;
	if(zoom > 1 || zoom < 0.1 || restore){
		zoom = 1;
	}
	canvas_div.style.zoom = zoom;
	canvas_div.childNodes.forEach(function(node){
		if (node.className.indexOf("arrowblock") < 0) {
			let id = parseInt(node.querySelector(".blockid").value);
			let block = blocks.filter(a => a.id == id)[0];
			block.x = ((node.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(node).width) / 2) + canvas.scrollLeft);
			block.y = ((node.getBoundingClientRect().top + window.scrollY) + (parseInt(window.getComputedStyle(node).height) / 2) + canvas.scrollTop);
		}
	});
}
...
...
var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2) + canvas_div.scrollLeft) / zoom;
var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / zoom
zoom: function(){

        document.querySelector('.zoom-in').addEventListener('click', () => {
            flowy.zoom(+0.1);
        });
        document.querySelector('.zoom-out').addEventListener('click', () => {
            flowy.zoom(-0.1);
        });
        document.querySelector('.zoom-restore').addEventListener('click', () => {
            flowy.zoom(null, true);
        });
    },

cdebattista avatar Oct 19 '20 13:10 cdebattista

@cdebattista in the approach you mentioned, when the tree becomes big and wide the indicator will not attach to the target node and will distance far away from the node you want. As zoom increases the distance will be increased more. Do you have any idea about that?

In my opinion, the indicator's left property should be tied to the canvas left property as well as so.

ebihimself avatar Jan 15 '21 10:01 ebihimself

So I had planned to implement this as well, we came almost to the same implementation. My UX is a little different. I've also been going through and refactoring the code into more functions.

Still a few issues with scroll position for large workflows.

image

image

robhoward avatar Mar 22 '21 19:03 robhoward

Hi Rob Howard

I am using flowy.js script and at the moment I failed to implement the ZOOM IN & OUT feature.

I really don't have idea how to implement. I gone through the Git comments but it does help me out any luck.

Can any one please share the piece of logic with.

Thank you so much in advance.

ravikoppula avatar Apr 02 '21 07:04 ravikoppula

Sure:

  1. I have a global var: var zoom = 100;

  2. Some Zoom functions:

     // ┌────────────────────────────────────────────────────────────────────
     // │ Zooms the display out making the blocks smaller
     // └────────────────────────────────────────────────────────────────────
     flowy.zoomOut = function () {
         let scale_factor = 5;
         zoom = zoom - scale_factor;
    
         flowy.setZoom();
         flowy.draw();
     }
    
     // ┌────────────────────────────────────────────────────────────────────
     // │ Zooms the display in making the blocks larger
     // └────────────────────────────────────────────────────────────────────
     flowy.zoomIn = function () {
         let scale_factor = 5;
         zoom = zoom + scale_factor;
    
         flowy.setZoom();
         flowy.draw();
     }
    
     // ┌────────────────────────────────────────────────────────────────────
     // │ Sets the current zoom
     // └────────────────────────────────────────────────────────────────────
     flowy.setZoom = function () {
         flowy.getZoom();
         canvas_div.style.zoom = `${zoom}%`;
     }
    
     // ┌────────────────────────────────────────────────────────────────────
     // │ Gets the current zoom
     // └────────────────────────────────────────────────────────────────────
     flowy.getZoom = function () {
    
         if (zoom > 100) {
             zoom = 100;
         }
    
         if (zoom < 40) {
             zoom = 40;
         }
    
         return zoom;
     }
    
  3. In flowy.moveBlock I recalculate the mouse position:

         if (zoom < 1) {
             mouse_x = mouse_x * (zoom / 100);
             mouse_y = mouse_y * (zoom / 100);
         }
    

Also in moveBlock (but refactored into another function:

        let z = zoom / 100;

        // Get the center point position of the dragged block and offset with zoom
        var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2) + canvas_div.scrollLeft) / z;
        var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / z;

Then in my UX I have this wired up with the plus/minus keys and the UX in screen shot above. Hope that helps!

robhoward avatar Apr 02 '21 14:04 robhoward

You might want to instead look at #105. Scroll to the bottom and @cdebattista posted a solid update. I found it this morning and have been converting my zoom behavior to use his.

robhoward avatar Apr 02 '21 16:04 robhoward

Hi Rob Howard

Thank you so much for the response.

Can you please assist me how can I use the user interface part +/- as shown in the above image.

Do you attached the code? I cant see any out come after I apply the code you had attached.

Please assist me.

ravikoppula avatar Apr 05 '21 08:04 ravikoppula

Hi Ravi,

You need to add the UX to handle this. For example:

Zoom 100% |

Along with the appropriate event handlers:

        //

┌──────────────────────────────────────────────────────────────────── // │ Updates the percentage of zoom we're at // └──────────────────────────────────────────────────────────────────── function updateZoomDisplay() { let zoom = flowy.getZoom();

            document.querySelector("#zoom span").innerText = zoom;
        }

        //

┌──────────────────────────────────────────────────────────────────── // │ Zoom out // └──────────────────────────────────────────────────────────────────── document.getElementById("zoom_out").addEventListener("click", function (e) { flowy.zoomOut(); updateZoomDisplay(); });

        //

┌──────────────────────────────────────────────────────────────────── // │ Zoom in // └──────────────────────────────────────────────────────────────────── document.getElementById("zoom_in").addEventListener("click", function (e) { flowy.zoomIn(); updateZoomDisplay(); });

On Mon, Apr 5, 2021 at 3:30 AM Ravi Koppula @.***> wrote:

Hi Rob Howard

Thank you so much for the response.

Can you please assist me how can I use the user interface part +/- as shown in the above image.

Do you attached the code? I cant see any out come after I apply the code you had attached.

Please assist me.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/alyssaxuu/flowy/issues/22#issuecomment-813272944, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHHFGC7Q7Q5ZNSGB32KURTTHFYJLANCNFSM4J3DNMRA .

robhoward avatar Apr 05 '21 13:04 robhoward

Thank you for the response.

Let me explain to you the way I added your code in my project.

step 1. Downloaded the code from the Git repo https://github.com/alyssaxuu/flowy step 2: In the flowy.min.js file I had added the below strip var zoom = 100; Global variable. // ┌──────────────────────────────────────────────────────────────────── // │ Zooms the display out making the blocks smaller // └──────────────────────────────────────────────────────────────────── flowy.zoomOut = function () { let scale_factor = 5; zoom = zoom - scale_factor;

               flowy.setZoom();
               flowy.draw();
           }
          
           // ┌────────────────────────────────────────────────────────────────────
           // │ Zooms the display in making the blocks larger
           // └────────────────────────────────────────────────────────────────────
           flowy.zoomIn = function () {
               let scale_factor = 5;
               zoom = zoom + scale_factor;
          
               flowy.setZoom();
               flowy.draw();
           }
          
           // ┌────────────────────────────────────────────────────────────────────
           // │ Sets the current zoom
           // └────────────────────────────────────────────────────────────────────
           flowy.setZoom = function () {
               flowy.getZoom();
               canvas_div.style.zoom = `${zoom}%`;
           }
          
           // ┌────────────────────────────────────────────────────────────────────
           // │ Gets the current zoom
           // └────────────────────────────────────────────────────────────────────
           flowy.getZoom = function () {
          
               if (zoom > 100) {
                   zoom = 100;
               }
          
               if (zoom < 40) {
                   zoom = 40;
               }
          
               return zoom;
           }

  In the **flowy.moveBlock** 
  
       if (zoom < 1) {
           mouse_x = mouse_x * (zoom / 100);
           mouse_y = mouse_y * (zoom / 100);
       }

@NOTE: I have No Idea about the below code ( getBoundingClientRect() is returning an error method name not found ) but I have used the same method name many times in the flowy.min.js file. Indeed I added this code in the flowy.moveBlock let z = zoom / 100; // Get the center point position of the dragged block and offset with zoom var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2)

  • canvas_div.scrollLeft) / z; var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / z;

Step 3: In the index.html page inside the canvas div, I added the below code.

Zoom 100% |

Step4: Based on Id triggered the Zoom IN/ Out functions from the main.js.

These are the steps I followed to implement but still not working.

Can you please advice on this. I really want to implement this feature and release in the production.

If possible can you please hang-up on the skype call or any alternative channel for this fix to be done.

I really apricated your time for replying me back.

Have a great day :)

ravikoppula avatar Apr 06 '21 02:04 ravikoppula

Hi Ravi,

Sorry, I'm not sure what to tell you. You've got all the pieces, but it's not trivial. Most of what I've done (as well as others) isn't really tied in with the flowy library any longer. They are additions. I can only provide you the pieces I used.

Rob

On Mon, Apr 5, 2021 at 9:54 PM Ravi Koppula @.***> wrote:

Thank you for the response.

Let me explain to you the way I added your code in my project.

step 1. Downloaded the code from the Git repo https://github.com/alyssaxuu/flowy https://github.com/alyssaxuu/flowy step 2: In the flowy.min.js file I had added the below strip var zoom = 100; Global variable. // ┌──────────────────────────────────────────────────────────────────── // │ Zooms the display out making the blocks smaller // └──────────────────────────────────────────────────────────────────── flowy.zoomOut = function () { let scale_factor = 5; zoom = zoom - scale_factor;

           flowy.setZoom();
           flowy.draw();
       }

       // ┌────────────────────────────────────────────────────────────────────
       // │ Zooms the display in making the blocks larger
       // └────────────────────────────────────────────────────────────────────
       flowy.zoomIn = function () {
           let scale_factor = 5;
           zoom = zoom + scale_factor;

           flowy.setZoom();
           flowy.draw();
       }

       // ┌────────────────────────────────────────────────────────────────────
       // │ Sets the current zoom
       // └────────────────────────────────────────────────────────────────────
       flowy.setZoom = function () {
           flowy.getZoom();
           canvas_div.style.zoom = `${zoom}%`;
       }

       // ┌────────────────────────────────────────────────────────────────────
       // │ Gets the current zoom
       // └────────────────────────────────────────────────────────────────────
       flowy.getZoom = function () {

           if (zoom > 100) {
               zoom = 100;
           }

           if (zoom < 40) {
               zoom = 40;
           }

           return zoom;
       }

In the flowy.moveBlock

   if (zoom < 1) {
       mouse_x = mouse_x * (zoom / 100);
       mouse_y = mouse_y * (zoom / 100);
   }

@NOTE: I have No Idea about the below code ( getBoundingClientRect() is returning an error method name not found ) but I have used the same method name many times in the flowy.min.js file. Indeed I added this code in the flowy.moveBlock let z = zoom / 100; // Get the center point position of the dragged block and offset with zoom var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2)

  • canvas_div.scrollLeft) / z; var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / z;

Step 3: In the index.html page inside the canvas div, I added the below code. Zoom 100% <#m_1333813811625634984_> | <#m_1333813811625634984_>

Step4: Based on Id triggered the Zoom IN/ Out functions from the main.js.

These are the steps I followed to implement but still not working.

Can you please advice on this. I really want to implement this feature and release in the production.

If possible can you please hang-up on the skype call or any alternative channel for this fix to be done.

I really apricated your time for replying me back.

Have a great day :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/alyssaxuu/flowy/issues/22#issuecomment-813784685, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHHFGG5V4L46PABHP2EW5LTHJZVZANCNFSM4J3DNMRA .

robhoward avatar Apr 06 '21 13:04 robhoward

Rob has its own flowy.draw() function so you'd have to build an equivalent to make it work.

You should be able to make cdebattista's code work fairly easily though.

sabatale avatar Dec 14 '21 14:12 sabatale

Yes, that's correct. I ended up doing a massive merge over the last few months of my changes with @cdebattista's code. I just finished it last month.

robhoward avatar Dec 14 '21 14:12 robhoward

@robhoward I know it's a year later, but if you have it working could you link an example repo or fork? I would love to use this and it seems non-trivial from above!

DrewWeth avatar Feb 28 '23 20:02 DrewWeth

Hey Drew we’ve since modified it to the point that it’s super customized to our use case. I can probably provide some snippets that show what we’re doing but it’s gotten crazy complicated.

On Tue, Feb 28, 2023 at 12:09 PM Drew Wetherington @.***> wrote:

@robhoward https://github.com/robhoward I know it's a year later, but if you have it working could you link an example repo or fork? I would love to use this and it seems non-trivial from above!

— Reply to this email directly, view it on GitHub https://github.com/alyssaxuu/flowy/issues/22#issuecomment-1448816646, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHHFGCIYGM3WNFDV4HZF4LWZZLRNANCNFSM4J3DNMRA . You are receiving this because you were mentioned.Message ID: @.***>

--

Founder *DailyStory Marketing Automation | Superhero powers for your marketing team learn more at dailystory.com http://dailystory.com | +1-833-914-1105

  • cape not included

robhoward avatar Mar 13 '23 16:03 robhoward

Would be nice to see a PR of a zoom done tbh

belthaZornv avatar Jul 19 '23 08:07 belthaZornv