[{"data":1,"prerenderedAt":472},["ShallowReactive",2],{"footer-primary":3,"footer-secondary":93,"footer-description":119,"request-review-flows-log":121,"request-review-flows-log-next":198,"sales-reps":220},{"items":4},[5,29,49,69],{"id":6,"title":7,"url":8,"page":8,"children":9},"522e608a-77b0-4333-820d-d4f44be2ade1","Solutions",null,[10,15,20,25],{"id":11,"title":12,"url":8,"page":13},"fcafe85a-a798-4710-9e7a-776fe413aae5","Headless CMS",{"permalink":14},"/solutions/headless-cms",{"id":16,"title":17,"url":8,"page":18},"79972923-93cf-4777-9e32-5c9b0315fc10","Backend-as-a-Service",{"permalink":19},"/solutions/backend-as-a-service",{"id":21,"title":22,"url":8,"page":23},"0fa8d0c1-7b64-4f6f-939d-d7fdb99fc407","Product Information",{"permalink":24},"/solutions/product-information-management",{"id":26,"title":27,"url":28,"page":8},"63946d54-6052-4780-8ff4-91f5a9931dcc","100+ Things to Build","https://directus.io/blog/100-tools-apps-and-platforms-you-can-build-with-directus",{"id":30,"title":31,"url":8,"page":8,"children":32},"8ab4f9b1-f3e2-44d6-919b-011d91fe072f","Resources",[33,37,41,45],{"id":34,"title":35,"url":36,"page":8},"f951fb84-8777-4b84-9e91-996fe9d25483","Documentation","https://docs.directus.io",{"id":38,"title":39,"url":40,"page":8},"366febc7-a538-4c08-a326-e6204957f1e3","Guides","https://docs.directus.io/guides/",{"id":42,"title":43,"url":44,"page":8},"aeb9128e-1c5f-417f-863c-2449416433cd","Community","https://directus.chat",{"id":46,"title":47,"url":48,"page":8},"da1c2ed8-0a77-49b0-a903-49c56cb07de5","Release Notes","https://github.com/directus/directus/releases",{"id":50,"title":51,"url":8,"page":8,"children":52},"d61fae8c-7502-494a-822f-19ecff3d0256","Support",[53,57,61,65],{"id":54,"title":55,"url":56,"page":8},"8c43c781-7ebd-475f-a931-747e293c0a88","Issue Tracker","https://github.com/directus/directus/issues",{"id":58,"title":59,"url":60,"page":8},"d77bb78e-cf7b-4e01-932a-514414ba49d3","Feature Requests","https://github.com/directus/directus/discussions?discussions_q=is:open+sort:top",{"id":62,"title":63,"url":64,"page":8},"4346be2b-2c53-476e-b53b-becacec626a6","Community Chat","https://discord.com/channels/725371605378924594/741317677397704757",{"id":66,"title":67,"url":68,"page":8},"26c115d2-49f7-4edc-935e-d37d427fb89d","Cloud Dashboard","https://directus.cloud",{"id":70,"title":71,"url":8,"page":8,"children":72},"49141403-4f20-44ac-8453-25ace1265812","Organization",[73,78,84,88],{"id":74,"title":75,"url":76,"page":77},"1f36ea92-8a5e-47c8-914c-9822a8b9538a","About","/about",{"permalink":76},{"id":79,"title":80,"url":81,"page":82},"b84bf525-5471-4b14-a93c-225f6c386005","Careers","#",{"permalink":83},"/careers",{"id":85,"title":86,"url":87,"page":8},"86aabc3a-433d-434b-9efa-ad1d34be0a34","Brand Assets","https://drive.google.com/drive/folders/1lBOTba4RaA5ikqOn8Ewo4RYzD0XcymG9?usp=sharing",{"id":89,"title":90,"url":8,"page":91},"8d2fa1e3-198e-4405-81e1-2ceb858bc237","Contact",{"permalink":92},"/contact",{"items":94},[95,101,107,113],{"id":96,"title":97,"url":8,"page":98,"children":100},"8a1b7bfa-429d-4ffc-a650-2a5fdcf356da","Cloud Policies",{"permalink":99},"/cloud-policies",[],{"id":102,"title":103,"url":81,"page":104,"children":106},"bea848ef-828f-4306-8017-6b00ec5d4a0c","License",{"permalink":105},"/bsl",[],{"id":108,"title":109,"url":81,"page":110,"children":112},"4e914f47-4bee-42b7-b445-3119ee4196ef","Terms",{"permalink":111},"/terms",[],{"id":114,"title":115,"url":81,"page":116,"children":118},"ea69eda6-d317-4981-8421-fcabb1826bfd","Privacy",{"permalink":117},"/privacy",[],{"description":120},"\u003Cp>A composable backend to build your Headless CMS, BaaS, and more.&nbsp;\u003C/p>",{"id":122,"slug":123,"vimeo_id":124,"description":125,"tile":126,"length":127,"resources":128,"people":132,"episode_number":142,"published":143,"title":144,"video_transcript_html":145,"video_transcript_text":146,"content":8,"status":147,"episode_people":148,"recommendations":177,"season":178,"seo":8},"0b5f4343-1494-455b-b41a-25811c151242","flows-log","912263898","In this recording of our live event on February 8 2024, Rijk, Jonathan, and Daniel discuss improvements to our no-code automation builder - Flows.","f89ae85c-4df4-4b9e-86db-8ca73f5980ba",55,[129],{"name":130,"url":131},"GitHub Discussion","https://github.com/directus/directus/discussions/15870",[133,136,139],{"name":134,"url":135},"Rijk van Zanten","https://directus.io/team/rijk-van-zanten",{"name":137,"url":138},"Jonathan Wagner","https://directus.io/team/jonathan-wagner",{"name":140,"url":141},"Daniel Biegler","https://directus.io/team/daniel-biegler",3,"2024-02-15","Improvements to Flows Debugging","\u003Cp>Speaker 0: Alright. Yeah. So, Jonathan, you already, briefly introduced that seeing all the hiccups, I don't know if we're gonna cut that. But just to restart it, we're gonna be talking about flows today. We're really gonna be starting with this 15 8 70 about improving the activity panel.\u003C/p>\u003Cp>But, realistically, as far as I'm concerned, it's sort of a smaller piece of a bigger discussion around upgrades to flows. Right? So for those out of the loop, we introduced that flow system as a way to do event based, actions and operations, kinda like you could with hooks, or custom endpoints, but doing it in a no code type of way. Right? So you configure when you want your flow to trigger and then step by step configure individual operations, individual nodes of sort of this this path, that you wanna execute.\u003C/p>\u003Cp>The original version of that was really much designed as a, start with the basics, see what people wanna use it for, see where what what the best improvements are gonna be. So we shipped it a little bit lightweight, you know, with a handful of operations and have been more and more over time. But it has been becoming increasingly obvious that there's, a lot of improvements that would be really nice to have, especially when it comes to debugging, sort of helping configuring some of these pieces. So with that being said\u003C/p>\u003Cp>Speaker 1: Yes.\u003C/p>\u003Cp>Speaker 0: Discussion. So for Daniel, who's flying blind here, we're looking at the one about the logs first. Right? So if you're currently running a flow, optionally if you have it enabled, it's enabled by default. It will keep track of the data that sort of went through the various operations, and then saves it to, a logs tab that you can see on the right hand side of the flow.\u003C/p>\u003Cp>This is basically the primary way at the moment where you can debug what is happening under the hood, because otherwise, you know, there it's it's the way where you can see what data came actually through the trigger and how you've modified the data points in between. So over the Jonathan, you're you're showing it out what that looks like now on your own instance. What are some of the points in this initial discussion that triggered this this conversation? You've got\u003C/p>\u003Cp>Speaker 2: a lot of the ease and access to that information, as well as the ability to control, like, durations. Some of the problems we run into with flows, especially if someone once they get them into production, if they still have the activity and logging turned on, you can fill up your activity revisions tables really quickly. And there's you know, the mechanisms for cleaning that up are, you know, another flow, or direct database access or other kinds of things where you've gotta manage your activity and revision logs and so forth. Common recommendation that I make is once you've done your testing and you've got your flows functioning is to disable the activity and logging. But there are cases where you may want that and logging just for audit trackability on actions and things that people are doing with flows.\u003C/p>\u003Cp>So, I think some of that is just the general trigger and management of that. Other things that, tend to cause struggle for people in flows is the way that you access this instead of being able to say, look at the data from the log directly in something that I'm working on. There's been a again, there's a number of ways that we can kind of shake and look at this. But the general thing is this kinda lives over here. I can't edit this while I'm looking at this, so the the interactions with logs and the work that you're doing is kind of a it's a bit of a hindrance when you're doing the development phase of flow development.\u003C/p>\u003Cp>So it's just a more a nuisance than anything else. But the the inability to say edit something here, I have to actually come here to check. So if I'm looking for variables or data or what are the things looking like in here, what's my payload? Now I've gotta remember this data structure or copy this data somewhere else because I wanna actually do something with it. I wanna interact with it.\u003C/p>\u003Cp>I wanna use those variables. So it's kind of a it's a weird transition kind of back and forth. Some of the systems that we we got in some inbound activity on some other tickets and feedback that we got from some clients on the enterprise side, was you know, they showed showed us some other systems that have similar no code kinds of flow capabilities. And logs, instead of living in, like, a side panel in a weird way, kind of live with the operations themselves. So there's just some general ideas and thoughts around how that interaction in the UX kind of works.\u003C/p>\u003Cp>Data wise, I don't think anybody's complaining about the information that shows up in here. That tends to be you know, it's fairly easy to work with and deal with. I think it's more the kind of user interactions with data.\u003C/p>\u003Cp>Speaker 1: Yeah. For me, personally, I've ran into this when I tried to set up a flow which triggers another flow, which then leads you to, you know, switching between those 2. And then you have to check that again, but then you forgot on the first flow, forgot something, and you have to switch back. And, you know, so people do run into this, and, I've experienced this myself. So, generally, if I if I experience this, the general user will probably also experience this.\u003C/p>\u003Cp>So this is a very valid point, in my opinion, and, we should we should improve this a little bit. You're muted, Jonathan. Sorry. You're muted.\u003C/p>\u003Cp>Speaker 0: You look very passionate, though. I'll give you that. But\u003C/p>\u003Cp>Speaker 2: Sorry. I'm not gonna mute. So so what that does is, you know and that's why we saw this very same thing as we started doing some internal research on just this ticket. We rapidly diverged into we've got 4 or 5 other kinds of spec, and that's why we it's kinda leading into this call today. We were talking about the fact that there's some general overall flows improvements that I think we'd like to see across the boards.\u003C/p>\u003Cp>But the logging and activity, you know, that's that kinda triggered this action was really about that the way that those logs interact and how you have to it's kind of a separation of what is a common function.\u003C/p>\u003Cp>Speaker 1: Yeah. Definitely. Totally agree. And, like the other comment on the chat said, switching is painful. Yes.\u003C/p>\u003Cp>An auto refresh for logs would go a very long way because I I do think that these two things are very, service the same niche, service the same pain. Because you you want to have up to date logs and see what is different, what do I have to work with, what can I work with, and not being able to have that on auto refresh, for example? Is the same thing as context switching back and forth, and you want to refresh and whatever. So I think these two pieces are very similar and and and try to work on the same pain, basically. So, good point from the chat.\u003C/p>\u003Cp>Thank you very much.\u003C/p>\u003Cp>Speaker 0: So there's a lot of lot of, I saw the word divergent on the screen. Just made me think there's a lot of divergent ideas happening at the same time. Right? We're talking about a lot of smaller optimizations like the auto refresh or some sort of way to make that context switching a little bit less painful. If we take a deeper look at this discussion, though, that sort of triggered everything, are there any particular pain points about the way we describe or show those logs that is currently sort of, something that should be improved?\u003C/p>\u003Cp>Speaker 2: I'm kinda skimming through this guy.\u003C/p>\u003Cp>Speaker 1: See some people typing in the chat. Please let us know if you have experience in using flows and would like to, contribute. We're here for you.\u003C/p>\u003Cp>Speaker 2: I think on the Trigger log\u003C/p>\u003Cp>Speaker 0: is the hardest to understand.\u003C/p>\u003Cp>Speaker 2: I'm still on. So on that log side, the other key thing that's being pointed out here is there are differences in the inbound payloads based on whether you're doing a create, update, or delete operation. You do have some variation in the trigger payload bodies. And, again, I don't know that it's a bad thing, but it is one of the things that's called out as a there's differences in the pathing, say, to the collection or the item, based on what type of event triggered the action. Yep.\u003C/p>\u003Cp>Speaker 0: Yeah. Very good one. That that makes a lot of sense, and it's it's it's explainable from a technical perspective, but also makes sense where it's where where the pain point's coming from. So earlier on, when we just did the hooks initially, the decision was made to differentiate between create a single thing and create multiple things, which in turn means that sometimes you get a single ID as a sort of, string or a number, and sometimes you get an array of ID strings or a number, which is basically just a bigger discussion around what does that hook payload look like. Right?\u003C/p>\u003Cp>Because everything is based on the same internal, event system. So, you know, a flow is triggered based on the same hook that you get from, a hook extension, for example. It's all the same thing. Then, the difference between, you know, trigger dot keys, trigger dot body dot keys, etcetera, sometimes it's payload, sometimes it's not, That really depends on the type of trigger, which, again, you know, doesn't necessarily make it make it better, but it is, you know, explainable where it's coming from, where. If you're having an endpoint, you know, with a a trigger request, now you're dealing with a sort of user payload that was submitted that could be anything.\u003C/p>\u003Cp>Right? If you're dealing with a hook, it's a pre pre known format for what our hooks fire. But, you know, it's there's a difference. There's gonna be a difference, and that is that's definitely tricky. Somebody said, if hooks supported loops, we probably wouldn't need the differentiation for 1 versus multiple.\u003C/p>\u003Cp>Hook supported loops. I'm not entirely sure what you mean by that because a hook is just a bit of JavaScript, so you could loop over whatever you want. Right? Oh, flows. Oh.\u003C/p>\u003Cp>Oh, I see. Gotcha. Gotcha. Gotcha. Gotcha.\u003C/p>\u003Cp>Yeah. So we're basically saying, you know, if you have a way to just say do this flow against every item in the triggered whatever trigger keys, then we can basically just drop the one hook and make everything an array all the time, sort of get rid of some of that confusion, which for the record Yeah. Makes a ton of sense to me. I mean, every every insert into the database could be 1 or multiple things. And if you do one thing, it's just an area of one thing.\u003C/p>\u003Cp>Right? It's basically it's it's easy to explain. So I I do agree with that sort of general sentiment. Even though for the record, that would be a quite a big breaking change and totally wreck everybody's existing flows and extensions. So TBD TBD.\u003C/p>\u003Cp>As mentioned, the extension shed will be very possible to create a repeat operation for all elements in an array extension with exposing a single function from the flows manager. Yeah. Yeah. No. Absolutely.\u003C/p>\u003Cp>Yeah. That's very true. Very true. Cool. There is one more, thing in the chat here from our very own Brian saying remembering the key names for operations is a pretty big headache for me.\u003C/p>\u003Cp>Why are the keys only showing on hover? Where can I not copy them? Which has been a thing all over the app. And just trying to remember what that key name is. That's a very good point.\u003C/p>\u003Cp>And I think, you know, overall in the app, we've sort of on the side of making things sort of, what's the right word? User friendly is such an empty thing, but, like, look pretty for nontechnical users. Right? So a lot of stuff gets, what we call title formatted. Family friendly.\u003C/p>\u003Cp>Yeah. Exactly. We we we title format a lot of that stuff, so it looks prettier in the UI. But totally. Yeah.\u003C/p>\u003Cp>For things like flow logs, you know, which is inherently a very technical thing, flows is only available for admin users, which are generally speaking, a little bit more of the on the technical side. Those should most likely just be the technical keys. Right? Render them in monospace and just lean into it. Because why why show them as a title formatted version and then have it only show on hover that you can then not copy paste because it's a tooltip.\u003C/p>\u003Cp>Right? It that that makes a ton of sense, and that is just a perfect sort of tiny little tiny little tweak that's a huge quality of life improvement. Jonathan, I hope that was in the notes somewhere now.\u003C/p>\u003Cp>Speaker 2: Yep. I'm taking some notes in in a separate section, over in the the actual internal notion doc that we've got running on this guy. So I'm trying to capture pretty much it.\u003C/p>\u003Cp>Speaker 0: Another good point here too is, like, why even have a pretty name if you just have the key? You know? Good point. Good point. I think having some sort of description is a nice, you know, nice to have where at least you can write, like, a mini description, but you wouldn't really use the name for that anyways necessarily.\u003C/p>\u003Cp>Cool. Okay. Just looking at the discussion, though, because I see we're sort of, what, 1 eighths of the way on the scroll on the page. So I'm kinda curious to see if there's any other points in this particular discussion that we haven't really touched on. That's easy to forget.\u003C/p>\u003Cp>So these ones we just looked at.\u003C/p>\u003Cp>Speaker 1: I think, the suggestion by our own\u003C/p>\u003Cp>Speaker 2: Oh, the the JSON object wrapping. Object wrapping was the other big thing. Again, having this in the side panel, data here, you can start to see if you get long things. It it actually goes off screen and ends up, you know, and you I don't even think it enables a scroll. I'm not sure you can even get to long data that's being displayed in the log there.\u003C/p>\u003Cp>So some form of wrap, at least, if we're gonna continue in this panel. I think, ultimately, I think we'd like to maybe move this out of the panel anyway. It'll end up somewhere else in the UX. But something for us to keep in mind is that JSON wrapping, and we have that captured as well in a I\u003C/p>\u003Cp>Speaker 0: was just gonna say that it's there it it's I can already also see there's no way to search or filter through logs. Right? That is another, you know, in. The only thing we show about the log is just a time stamp and then a rel as a time stamp. But I'd I'd say an obvious next step is to sort of move that out of the sidebar into just a proper, you know, layout like we do with other things all over the place.\u003C/p>\u003Cp>So you get the searching, you get the filtering, and we can have a proper detailed view, or draw our although a detail page is probably gonna be nicer for that. Save a little bit more space, for things like that overflowing scroll and just presenting it nicer. Although, then, you know, we create a new problem, which is now the logs live outside of the flow where you configure them. So at that point, you know, we also wanna make sure that we have some sort of way where you can render that maybe as a split view, maybe you can sort of 50 50 between the flow that you're creating and then seeing the logs of that flow with this layout. Because I do believe that keeping them in context or at least having some sort of link back and forth, from, you know, where you're configuring the the law, the flow and configuring the log is gonna be important.\u003C/p>\u003Cp>Speaker 1: From\u003C/p>\u003Cp>Speaker 0: the chat, having logs and operations might be helpful for that. Yes. Yes. Yes and no. It's it's I'm I'm, to me, the logs on operations is an addition, not a replacement.\u003C/p>\u003Cp>I think personally it's very valuable that you can see, you know, the full, execution path in a log. You can see, you know, at 2 pm today we started with this, we started with it, that one failed, and then we did this, and then here's the data that went through it and what we concluded with. I do think it's important to have that sort of consolidated together, but the the logs and operations, I do agree, would have really be a really nice addition to that where you can just look like, okay. In the last couple of runs, here's the day that it came in and went out of this particular box in your flow. Right?\u003C/p>\u003Cp>I don't know if that's gonna be a deep link or maybe just an info.\u003C/p>\u003Cp>Speaker 2: Almost feels like you could have, like, a split panel down here that had the normal, like, search layout capabilities of searching through the logs, could be an interesting use case for this where you'd Mhmm. Similar to Visual Studio and other kinds of console logs where when you're doing this kind of development, you've got logging information you can see down here. Because I also think some of the other nice things with flows would be able to have, like, step through. Right? Being able to step through and see data at certain points, what's going on as you're debugging and working on the flow itself.\u003C/p>\u003Cp>But then as you say, having an actual, you know, log panel or maybe there's a, like, in a sub ten under flows where you can go to the logs and just see logs full screen, be able to search. Because once my flow is operating, I think the the DERF, pointed out that they're they like logs turned on so when users report issues hours later, they can go back and search the logs. And in that case, I'm not looking at the flow. I'm looking at what's the data, what's the flow, what happened, what errors, what things do I see. So\u003C/p>\u003Cp>Speaker 1: cool.\u003C/p>\u003Cp>Speaker 0: Because the nice thing by putting the again, this for for those new to the stream, this is very much a session of divergently thinking. Right? We're just gonna go brainstorm a bunch, like, what will be the ideal state and then take it back towards the end to, like, okay. What is an actual realistic next step? So I can also imagine, you know, closing your eyes thinking about it, if we have a proper detail page, like a full full screen view for the logs for one particular run.\u003C/p>\u003Cp>Right? We could actually render sort of a smaller, graphical representation of your flow as you have configured it, in in here, and then just show you. You can sort of replay it, so to speak. So we can just show you step 1, and then that's the data that came in and out based on the logs that you're looking at. Right?\u003C/p>\u003Cp>So instead of just having a long list top to bottom, you could effectively just get a visual replay, of that particular flow operation. I think that could be an interesting one too. Because then you really get to visualize the the execution of that flow because you're effectively trying to follow a path through your flow with the log. But right now, the log is always gonna be a a sort of,\u003C/p>\u003Cp>Speaker 2: what's the\u003C/p>\u003Cp>Speaker 0: right word, a one dimensional list, top to bottom. Right? Chronological. But, you're thinking about your flow, potentially, in more of a graphical tree. Right?\u003C/p>\u003Cp>Where it's like you have option b, and then you branch off, etcetera, which is not really, represented in the logs in any sort of way right now. From the chat, somebody you could almost use the exact same UI as the flow editing page for that. Yeah. No. Yeah.\u003C/p>\u003Cp>Yeah. Exactly. Maybe a little bit smaller so you have the whole thing, you know, in view at the same time, and we just can highlight whichever box we're currently showing you. Yeah. I think that could be a very interesting visual representation.\u003C/p>\u003Cp>It becomes very interactive at that point. Right? Where it's almost like, you know, the logs will just be represented with some sort of timeline bar where it's like, okay. You read operation 1 out of 16 steps, and then you can just go to the next one. Then the visual representation up top just sort of, like, highlights which box we're on.\u003C/p>\u003Cp>Right? And then just go to the next one, go to the next one, go to the next one. I still think we would have to have some sort of way where it's just, like, show me the whole thing as a JSON blob. Don't make me go through this this pretty thing, but I'm pretty hopeful that that could help, really help debug what's going on here. Speaking of which, why is the flow edit page the default?\u003C/p>\u003Cp>The view page seems kinda pointless. Yeah. Agreed. Done. So easy it can be sometimes.\u003C/p>\u003Cp>I I think the the honest answer is that kinda came from flows being initially designed as using the exact same UI and UX and order of operations as dashboards, where that is, very different, obviously, where dashboard is definitely read read only by default, and then only if you wanna change something to your panels for the order of the dashboard or that kind of stuff that you really go edit it. But in this particular case, I agree because it's like, what is really the difference between read and editing it? The only difference for read is that you can't, you know, click a button, but there's nothing that's really, you know, different between the two states. Right? So just getting rid of that read only view, I mean, it it makes sense to me, honestly.\u003C/p>\u003Cp>Food for thought. It's not not something we're just gonna we'll have to double check if that all makes sense, but just you know?\u003C/p>\u003Cp>Speaker 1: Well, let's say let's play with that thought a little bit. So let's say we make a new page, detailed page, which features everything that we want. Would we like to then be more stringent on how it looks? So maybe take away the ability to point, to to place nodes wherever you want so we can, you know, for example, make it, smaller for the detail page because we probably don't have the same amount of space as of right now. Is that something that we would like to do?\u003C/p>\u003Cp>I don't know. Like, how important is that even?\u003C/p>\u003Cp>Speaker 0: I think for the flow detail page, for the if you're talking about the flow detail page, it's not important. It's it's really more of a visual aid. This is like if you're mentally, you know, visioning what your flow looked like when you created it, you can see it sort of, like, go through the go through the motion. So it's really more meant as a graphical element that is more for, it's kinda like a map. It's kinda what I see it like.\u003C/p>\u003Cp>Right? It's it's a nice to have, not really a requirement. What I was kinda thinking we could potentially get away with though is instead of rendering the full boxes with everything in it, which just be the name or just an empty box for that matter. What we could do, though, it's I don't know if you've ever ever played with this, but if you have a dashboard set up Jonathan, do you happen to have a dashboard in this this demo instance? Plenty.\u003C/p>\u003Cp>You gotta love it. Dashboards and sort of the underlying panels and the the viewport stuff. Yeah. Exactly. It has a button that just sort of zoom out the fit.\u003C/p>\u003Cp>And also a full screen button for those who don't. Pro tip for you. So you can full screen and make it fit on your your, fit on your screen. But we could use that exact same thing for doing just sort of a mini representation of, of your flow at the top of this flow's detail log page. Right?\u003C/p>\u003Cp>Because you don't need to see all the exact details. It's mostly just as a graphical map for going through your flow. This could be a very\u003C/p>\u003Cp>Speaker 2: interesting trick. Similar similar tools I've seen, you can actually zoom in or out. You can actually zoom your view so you can see more of your flow or all of your flow. And then when you double click or click on something, then you get back into the item view or the detailed view. So back in our flows example here.\u003C/p>\u003Cp>Right? You'd be able to, you know, have a zoom option or be able to scroll in or out and zoom your view similar to a map style the way we do with the geospatial kinds of things. So very similar to that would be fun.\u003C/p>\u003Cp>Speaker 1: I wish I could see the screen right now, but, I thought there's something\u003C/p>\u003Cp>Speaker 0: Oh, right. About exhibit. I forgot.\u003C/p>\u003Cp>Speaker 1: For example, yeah, if if we decide to, you know, like, restructure the visuals or want to provide a different type of view, for example, like, we don't have to have boxes. We could also have, like, circles, for example, which could be smaller, take out the space. Maybe they're horizontal or something. I'm not sure if you showed this, right now. I'm sorry for that.\u003C/p>\u003Cp>But\u003C/p>\u003Cp>Speaker 0: Oh, no. No. No. No. It's I just I just love the the very bit of a sidebar.\u003C/p>\u003Cp>I just absolutely love the the artistic way you brought that just now. Maybe instead of rectangles, they could be circles. Yes. But yeah. No.\u003C/p>\u003Cp>You're absolutely right. Because we the nice thing is we know the exact dimensions of each box. Right? So we could theoretically, for a graphical overview, render each box at a half height and offset all of the, x and y positions by, you know, the number of boxes high To sort of recreate the diagram in a more compact view.\u003C/p>\u003Cp>Speaker 1: For sure.\u003C/p>\u003Cp>Speaker 0: Yeah. Good point. So let's let's noodle on this idea for logs on the actual operation box. Right? So would that be a, sort of additional button, I guess?\u003C/p>\u003Cp>Because I'm also sort of operating under this. It's edit mode by default all the time. So I could imagine that maybe next to the edit button, there's just some sort of logs link.\u003C/p>\u003Cp>Speaker 2: And now\u003C/p>\u003Cp>Speaker 0: that I'm thinking about it even more.\u003C/p>\u003Cp>Speaker 2: Pre filter the logs to the particular one you're looking at, all that kind of fun stuff.\u003C/p>\u003Cp>Speaker 0: Yeah. Because now that I'm thinking about it, we save the logs as one row with a bunch of JSON in it for the whole flow execution. Right? That's the, that's the log item that we have. So there's no real way to just say, give me all of the logs for just the update data operation, because you're looking about all of the, you know, all of the, all of the data from the whole flow, and then we have to sort of filter it back down.\u003C/p>\u003Cp>But, you know, we could consider, although the amount of data is gonna get out of control real quick, but we could consider saving, you know, a log row in the database for each operation step instead of for the whole flow. But we gotta make sure that we have some sort of automated retention setting and and a bunch of indexes, indices for that, to not completely wreck your database. Because if we're now creating 5 new records per flow instead of 1, then you're talking about millions and millions of data points, which, you know, depending on your database might not matter.\u003C/p>\u003Cp>Speaker 1: This has been a point in the discussion. The person that started then was already interested in some type of way to for example, similar to the activities, issue that we had, recently where, you know, big or large instances have trouble with, I don't know, I don't know, 2,000,000 activity entries and some type of schedule that clears logs or, for example, you only want to retain those who are at most, I don't know, 30 days old, for example. Some type of rule maybe which could, lighten the load a little bit would be helpful, I think.\u003C/p>\u003Cp>Speaker 0: Oh, a 100%. Yeah. Yeah. The 100%. The the main reason we haven't had that before, I haven't done that yet, is because we didn't have support for this use yet.\u003C/p>\u003Cp>Right? And that's really a requirement. Because if you wanna delete with a filter on a timestamp and you don't have an index on that timestamp, now it might take your database, you know, minutes to just go through a table of that size. So that's that's also where that sort of sprint came through to, like, support indices and now collaborating with the the contributor there to to get that across the finish line. Because then once we have proper support for indices because because I do wanna make sure that, you know, whatever we do for the system stuff needs to be available to the end user.\u003C/p>\u003Cp>Right? So once we have support for indices, we can then enable indices for the system tables for, like, the timestamp in activity and and same for flow logs and stuff. And then the second piece of that is gonna be a setting that says, what do you want your, you know, low log retention to be? And it should be an environment variable, I guess, or maybe it's a per flow option. T b t b d on that.\u003C/p>\u003Cp>Right? Maybe there's an environment variable for the the maximum number you can set, and then in the app, there's a drop down, whatever. We'll have to figure it out. But, yeah, to your point, if you can configure, I only wanna keep 7 days worth of flow logs for this flow. I feel like that's a must have for any sort of upgrade that we're gonna be doing the flows, because it's so easy to just now accidentally end up with a couple of 100.\u003C/p>\u003Cp>Actually, that reminds me, I think, Kevin the other day did a fantastic little flow that he sent over where he was using it for, for beddlesnakes. But I also saw his flow logs in the sidebar already be in the 100, and I was like, how how long have you been running this right now? Right? You're gonna have 1,000 tens of 1,000 of those, so we need to have some sort of retention for that, which I could imagine, you know, if you have a flow that you know you're running a lot and you want it to be lowers, think it has to be per flow.\u003C/p>\u003Cp>Speaker 1: Food for thought. Food for thought for sure.\u003C/p>\u003Cp>Speaker 0: So then when we're thinking about, you know, one other thing I know about the debugging of, flow specifically is that right now to test anything, you have to trigger the actual thing that triggers this. Right? So, as of right now, if, Jonathan wanted to test this ready for review flow in any way, he would have to save this, quit, go to his articles collection, and then manually trigger it. Right? Oh, it's\u003C/p>\u003Cp>Speaker 2: so painful. It is so painful to debug these things, because you have to do just that. Right? I have to go I have to go save, then I have to go to our to my systems over here. I have to go to articles.\u003C/p>\u003Cp>I mean, at this point, normally, I've got an you're already kind of nabbed here, but now I've gotta open an article, and then I've gotta go through the actions of whatever I'm testing. So ready for review case. I have to push the button, then we go back, and then we're gonna go back to flows. We go back to ready for review. Now I have to go to logs, and now I can look at logs and see what's going on, test flow or not.\u003C/p>\u003Cp>So you're in here, you're traveling through, and you're looking at your payloads, and at your options wherever you are in the debug process, then you're closing out. Now you're going back to edit. So many mouse\u003C/p>\u003Cp>Speaker 0: It's a pain is what I'm hearing. It's a pain in the butt. Flow is\u003C/p>\u003Cp>Speaker 2: awesome, but it is it is painful to do the administration.\u003C/p>\u003Cp>Speaker 0: That's why we're here.\u003C/p>\u003Cp>Speaker 2: That's why we're here.\u003C/p>\u003Cp>Speaker 1: Yeah. So one thing I think just wanna add another point from from him. Yeah. Sorry.\u003C/p>\u003Cp>Speaker 0: Go. Go. Go. Go. No.\u003C/p>\u003Cp>Please. Please. Yeah. Yeah.\u003C/p>\u003Cp>Speaker 1: Because, this this then touches the issue of alright, so let's you you want to create a flow. You want to try it out. You have to try it out in order to actually make it work. But then comes the thing, alright, so let's say I have an existing flow, and it's running. It should continue on running, but I want to, I want to edit it without changing the actual running flow, which would technically be something like, alright.\u003C/p>\u003Cp>Let's duplicate this flow so I can play around with it. And then, after I'm done with my modification, then I switch them or, basically, disable the previous one and enable the next one. So some type of let's let's call it, like, very, very lightly versioning. Yes. Oh, the chat.\u003C/p>\u003Cp>The chat is exactly it.\u003C/p>\u003Cp>Speaker 0: Once they\u003C/p>\u003Cp>Speaker 1: have the\u003C/p>\u003Cp>Speaker 0: whole tag.\u003C/p>\u003Cp>Speaker 1: Right. So so if, yeah, if you have a couple of, like, important very important flows running in production systems, you don't want to, you know, edit them willy nilly. So that's the that's the another thing, which is can be can be painful because as of right now, there's technically no duplicate button, which is, not as nice as it could be.\u003C/p>\u003Cp>Speaker 0: And, it's it's a difficult one, isn't it? Because I'm also thinking about some of the triggers. Would that make sense? Because if you make a new version of a an endpoint, right, and an endpoint has a UUID to run it. But then if you create a duplicate, now the endpoint is different.\u003C/p>\u003Cp>So then if you wanna make that your production one, now you have a different endpoint. Right? So it's like the the duplicate and then kill the old one flow pun intended of updating flows might not work for every trigger. Also, if you create a new version of a flow that uses, like, an event hook for, like, an item save on articles or something, like, in this example. Yeah.\u003C/p>\u003Cp>It would have to be some sort of dedicated versioning because if you create a duplicate, then now you're firing both of your flows. Right?\u003C/p>\u003Cp>Speaker 1: You know, a very, like, naive solution to that event problem would be to have the duplicated flow immediately be set to disabled. So if you duplicate duplicate something, the duplicate one is disabled, so it doesn't fire. And then you can play around with it, change something, and then enable it yourself. Yeah.\u003C/p>\u003Cp>Speaker 0: Somebody in the chat that or somebody's plural in the chat, we're also saying, you know, you can obviously have a local dev instance or a dev copy where you could configure a new flow and then sort of import it at once so you don't, you know, mess anything up on production. Very true. Very true. Wanna make sure, you know, we keep we can Yeah. All the use ASM license.\u003C/p>\u003Cp>Speaker 1: This this then goes hand in hand with the next thing that I wanted to bring up with with the same thing. So let's say you have your dev instance, and then you want to sync your synchronize your flow to the production instance. Alright? There's no version control, basically. If you don't use, like, an actual extension, which you can put into your Git, version control, you would have to manually duplicate or use the API or something to to get the flow over or synchronize between your two instances.\u003C/p>\u003Cp>Mhmm.\u003C/p>\u003Cp>Speaker 0: Well, luckily, we talked about that particular problem 2 weeks ago in the last episode.\u003C/p>\u003Cp>Speaker 1: That's exactly right.\u003C/p>\u003Cp>Speaker 0: Like and subscribe. Exactly. The link right below the like button. Is that what they say?\u003C/p>\u003Cp>Speaker 1: Yeah. I'm gonna have the sidebar here.\u003C/p>\u003Cp>Speaker 0: Exactly. Circling back, though, because we we have, I think, 2 or 3 different, UX points with, like, a couple of different solutions. So one thing that I think is a must have for sort of this flows upgrade project that we're putting together here is that there needs to be a button on the trigger where you can manually trigger that trigger. The difficulty will be what data do we trigger it with, and how can we help you make that data realistic? Right?\u003C/p>\u003Cp>That is gonna be the difficulty there, which is kind of what we haven't done before. Because right now, with this manual trigger on an article, you know, the data format for that, like we talked about with the chat a little bit earlier, it's very specific to that particular article and that particular, data model for the article if it's like a filter hook or something. So if you have a manual play button, so to speak, we need to have some sort of way where you can sort of fake what that event looks like. We can pre pre generate a couple of ones based on your instance, I guess. Because, like, we know for the manual trigger that you get the primary key of an article.\u003C/p>\u003Cp>Right? That's what you would trigger with. So when you hit a play button, I imagine that we would have to show some sort of modal or a dialogue that allows you to put in a JSON object, I guess, with what that sort of, fake data looks like. And for some of the triggers, I think we can prepare that cause we can we can pre fill, you know, a fake article manual run cause we know the format, collection, keys, etcetera. For some of them, you don't need to do anything at all.\u003C/p>\u003Cp>Like a cron thing, you can just play because there's no real, you know, trigger data coming in, maybe a timestamp, but I'm not a 100% sure. For an endpoint, though, there there's no way for us to know what that looks like. Right? Because the payload is user edit, so we don't really know do with that.\u003C/p>\u003Cp>Speaker 2: So so some of the things I've seen with other tools, then this goes this even goes back 20 plus years ago using WebLogic's BEA workflow engines. You could actually take data from previous runs, so from the logs essentially. You could actually generate your payloads dynamically from that, or have say, I wanna capture this data, and I wanna actually reuse that as the test mechanism and essentially create your test data from an existing run. And then, ultimately, you could even edit at that point, you could edit the payload. So if you wanted to change some of the data attribution for subsequent runs, you could actually just quickly edit.\u003C/p>\u003Cp>So as part of the you know, that kind of play operation, you would actually get some dialogue capability and say, I wanna use either an existing or, in some way, create or save your payload and then fire that in. And in that way, you know, we don't have to be trying to generate it. We can just say, you can either run it normally, go and trigger the action. You know. Another way that I've done some of it is, like, have an incognito window with log you know, I I don't have to actually do what I just showed you, which is exit my flow.\u003C/p>\u003Cp>I can actually do the testing from another user. You can there there are some ways you can simplify or streamline that just a little bit. And you may be testing that permission set anyway. Then you may have permissions and restrictions, and you may be testing that as part of your application anyway. You'd have a test user with those permission.\u003C/p>\u003Cp>But being able to capture that information from an existing log or flow, run would be super cool and helpful. And that's some of what we've captured some of that already.\u003C/p>\u003Cp>Speaker 0: We have the logs. I mean, we have all of that data to your point.\u003C/p>\u003Cp>Speaker 2: Like,\u003C/p>\u003Cp>Speaker 0: if if there was a previous run, we'd know exactly, you know, what what information was there anyway. So we could definitely use that to to prefill it. Is this sort of manual trigger for well, manual trigger is a bad bad name because we already have a thing called manual trigger. But it's this sort of play button. Let's call it that.\u003C/p>\u003Cp>Is that something you'd wanna do for the whole flow, like, on the trigger level, or is that something you'd also wanna be able to do per operation itself? Because somebody before was like, you know, I used the run script operation a lot. I can also imagine that it would be really useful then to just just be able to say, okay. Just replay my run script a couple of times. But what I was just about to say showed up in the chat.\u003C/p>\u003Cp>Shout out to the Dev once more. Operations depend on a lot of context from what happened before. Right? Yep.\u003C/p>\u003Cp>Speaker 2: That would be more like that step through capability, right, where you you can step through and, you know, in debug mode, essentially pause. Right? The you know, you have your your break point. And at that point, you stop. You can actually analyze and look at the data.\u003C/p>\u003Cp>So, I mean, this does become very much ID style kind because that's what this really is. We're we're doing ID development. The idea is you would have these kinds of breakpoint capabilities to be able to stop, look at what data and parameters, be able to look back through the current context, what does it look like. Am I getting what I expect? Okay.\u003C/p>\u003Cp>Okay. Then step through debug. And it gets complex because we've got this mix of operations, and then you got run script that has, you know, code. Right? You know?\u003C/p>\u003Cp>Now do I have another debug capability with stop points and break points inside the job? You know?\u003C/p>\u003Cp>Speaker 0: Yeah.\u003C/p>\u003Cp>Speaker 2: Debugging that the TypeScript JavaScript in there directly. It gets very complex in that sense. But I think just the ability to be able to have a I wanna be able break point at the run script, be able to step to the next operation, then check the data and see I'll be able to multiple breakpoint options. We could get more creative down the line. I think if we can just put it at the operation level, that could it would be kinda cool if you could, you know, essentially step back, edit the data, or do something to the input, and then feed it back through, step back, step forward in in the operations themselves.\u003C/p>\u003Cp>Like, it's more complex\u003C/p>\u003Cp>Speaker 0: than And another thing with all of this, of course, is that, these operations may very well have side of on purpose because you might ping a different endpoint. You might save something's database, whatever. Right? So if you're manually playing, you know, with Flow or even individual operations for debugging purposes or whatever else, those side effects will still be in effect. Right?\u003C/p>\u003Cp>And if you're trying to debug a whole flow, you know, operation 2 might be dependent on a successful response from operation number 1. Like, number 1, save something to the database. Number 2, reads it, you know, now that it has been saved or something. I'm just trying to come up with an example. Because I was thinking, you know, it it be important to think through some sort of dry run as well where you can just like, okay.\u003C/p>\u003Cp>This would have now saved to the database. Right? And then, oh, this would have now made a request to the API, but we didn't actually do that. We didn't want to make a Stripe subscription as part of our little testing thing right now, right, to just test if everything works. So that'll be interest interesting.\u003C/p>\u003Cp>Some sort of dry running, thing behind it. I I do think it's important to think through at least because of the side effects. But to again, shout out to the derp. Can't really do a universal drive run because you never know what, you know, arbitrary stuff is being used.\u003C/p>\u003Cp>Speaker 2: Yeah. You'd almost have to have, like, a successful run or at least a set of data and payload options that you could edit up to say, you know, this is what I'm kind of expecting as I process through my input outputs.\u003C/p>\u003Cp>Speaker 1: Mhmm.\u003C/p>\u003Cp>Speaker 2: So So you'd have to have input output capabilities. What do you expect? And then as\u003C/p>\u003Cp>Speaker 0: you say,\u003C/p>\u003Cp>Speaker 2: dry run mode, not save, but often, you know, maybe the change that I'm making, I then getting that and then doing something. So I'm sending it to that I'm sending a webhook out data payload that comes back, you know, depending on how complex you make a flow. Mhmm. My general recommendation is if flows get that complex, go write a\u003C/p>\u003Cp>Speaker 0: hook. But it's Well\u003C/p>\u003Cp>Speaker 1: Well it\u003C/p>\u003Cp>Speaker 0: it there is gonna be a point.\u003C/p>\u003Cp>Speaker 2: It's a balancing act. Right? There there are I I like flows for admin kinds of functions where state management user control. When I get into really complex conditional lock, do doing this in these boxes so much faster to write TypeScript, be done with a hook on the backside. That's my Yeah.\u003C/p>\u003Cp>Speaker 1: The the similar to yeah. What I wanted to say is this sounds, like, very similar to some type of bash script or something. You know, some some type of scripting, where as soon as you need conditions or something, it's probably better to make it a program. Because, who likes to write bash? Basically, you know, it it gets it gets gnarly really quickly.\u003C/p>\u003Cp>So as soon as you need sophisticated stuff, some type of conditions that branch into something and do something with arrays or something, it's probably better to actually use a programming language. And,\u003C/p>\u003Cp>Speaker 0: I, yeah, I don't know. It really depends on a lot of things because one one is like, do you even know TypeScript or JavaScript in the first place? I think that's an important one. I think by, you know, doing it manually as as code, you also have a lot more opportunities to break it bad. You know, make it insecure, just make it an optimized break stuff tremendously hard.\u003C/p>\u003Cp>And also in, the chat somebody pointed out, you know, with flows, you do get the the logs and sort of the ability to explore the steps and what went wrong. So it's it's an interesting take, Jonathan, because what we're saying is, like, as as of today, you know, when it gets complicated, you wanna switch to code because the flows, UX, and UI just doesn't isn't good enough yet for complicated stuff. Right? So Right.\u003C/p>\u003Cp>Speaker 2: Yeah. Yeah. It is.\u003C/p>\u003Cp>Speaker 0: But I I'm hopeful.\u003C/p>\u003Cp>Speaker 2: If if we make this kind of what we're talking about, if we get to that point in these next few iterations on maybe it does become I don't actually need hooks as often. Right? I could be you know, hooks could just be when I need external library.\u003C/p>\u003Cp>Speaker 0: Yeah. Exactly.\u003C/p>\u003Cp>Speaker 2: Allow within flow at the moment.\u003C/p>\u003Cp>Speaker 0: I'm just I'm very I'm very hopeful that by by some of these seemingly small but very big changes, like adding the manual trigger so you can at least just try it out, I think we can actually get this to a point where\u003C/p>\u003Cp>Speaker 2: HOOX\u003C/p>\u003Cp>Speaker 0: is gonna be the more complicated one to do, you know, because it's like, yes, you have a black box and do whatever, but you don't get all of the debugging niceties and and all of the comments. Not that it's a battle. I mean, at the end of the day, it's just pick whatever you want, what's worked best for you. But I think that we can reverse that take, honestly, that flows could be I think that might be my personal challenge. Make flows the default for Jonathan.\u003C/p>\u003Cp>That's my measure of success.\u003C/p>\u003Cp>Speaker 2: Writes the worst TypeScript he's ever seen.\u003C/p>\u003Cp>Speaker 0: If he says I prefer flows over hooks, it means we did a good job.\u003C/p>\u003Cp>Speaker 2: Perfect. I love it.\u003C/p>\u003Cp>Speaker 0: Project Jonathan is what we call it. Cool. Okay.\u003C/p>\u003Cp>Speaker 2: If you can keep me from writing code, it's always a good.\u003C/p>\u003Cp>Speaker 0: It's always a good idea. So there's there's definitely a couple of unresolved You know, as per usual, I with the eye on the clock. As per usual, we're gonna be wrapping up. We've been taking a lot of notes during all of this, and it's, again, very divergently thinking. We're gonna be compiling all of these notes and ideas from everything that we just talked about and everything on the chat.\u003C/p>\u003Cp>Thank you for that. Into, you know, a proper RFC document and figure out what does this project upgrade flows, x y z, you know. What does that look like? What do we see as the must have? What can we get done in a sort of initial sprint?\u003C/p>\u003Cp>There have been, I think, like, 4 or 5 different discussions that are all sort of asking for the same thing, which is, like, improve Flows debugging. But they're all various sort of smaller bits and pieces of a, to me, bigger Flows 2 point o type of upgrade. So we're gonna be trying to compile those and sort of merge them into one sort of flows project, if that makes sense. Just as a quick summary, I think just the the upgrades to the logs that we talked about, you know, making them, like, explorable. I guess that's the right the right word.\u003C/p>\u003Cp>Giving them its own page, giving it more space, making it easier to step through, you know, the execution of a flow. Definitely a big must have. And the ability to trigger a flow from where you're editing it with some sort of, you know, preloaded payload from a previous run or something you can manually adjust so you can actually try out what the hell it is that you're building without having to go all over the app. I think it's gonna be a very, very important thing to have. Last question from from the chat here before we wrap up.\u003C/p>\u003Cp>Someone had said that many of these ideas could be implemented by the community in a custom module? No. Yes. Community can build whatever they want as a custom module at the end of the day. That is very true.\u003C/p>\u003Cp>And with the, you know, upcoming release of, for marketplace project, I'm also very curious to see, you know, what people will do with this type of stuff. Right? Somebody could, definitely, make a flow flows log module and just make it super custom or super proprietary or super flexible, whatever they want Whatever they want, really. Cool. Okay.\u003C/p>\u003Cp>There was one more that snuck in with an upvote. One final thing. Can we have access to the flow manager from the flows service so we can do more things with flows from extensions? May may may. No problems.\u003C/p>\u003Cp>So so It depends. It depends. Now I'll I'll, it's oddly tucked away compared to the extension manager, which should also similarly be tucked away, actually. Anyways, no. The the the reason for the hesitation is more around updates that I kinda wanna do to those services in the first place.\u003C/p>\u003Cp>Right? So I know I wanna do some sweeping upgrades to what those services look like and how they work in the first place. So I'm hesitant to to add new stuff onto the services service that we know might change already. Right? So I I don't wanna introduce something new that's gonna change then fast after, if that makes sense.\u003C/p>\u003Cp>That being said, yes, I do wanna make sure that extensions do have access to all of those types of internal things, which is also a reason why we've been moving a lot more stuff into individual libraries. Right? So I don't know. For for those who have been watching the repo like a hawk, we just moved sort of the environment variable extraction and handling different library with the same sort of idea, right, where an extension can just import the Directus ENV library and then use the same sort of ENV handling that, Directus does itself. We're we're basically doing that across the board, and the services is one of those things that I wanna do like that.\u003C/p>\u003Cp>And I can definitely imagine there being eventually being, you know, a Directus flows library that contains, you know, this flows manager state, so that extensions just can import it just like the direct as API would with TypeScript typing. I I heard you. Community, I heard you. With proper TypeScript typing and everything as well. So that's that's the only reason why I'm a little hesitant to promise anything better, as of right now.\u003C/p>\u003Cp>Any cool. That marks 11 sharp on the clock on my end. I think this was a very interesting session so far. This is a little bit more divergently rambling, than doing an existing discussion, but I think we've touched on a couple of very, very important points. Any any other closing thoughts?\u003C/p>\u003Cp>Speaker 2: If I could remember the dad joke from Bryant this morning, I would tell it, but I suck at remembering jokes. So\u003C/p>\u003Cp>Speaker 0: Well, tune in next time for for\u003C/p>\u003Cp>Speaker 2: John's phone dad joke.\u003C/p>\u003Cp>Speaker 0: With all that being said, thank you to the audience. Thank you for watching. If you're watching this on Directus TV, Directus dot a 0/tv, Hi. Be sure to watch the previous versions of this video down below. And we'll see you guys in 2 weeks, I think.\u003C/p>\u003Cp>Or are we skipping that one? Because it's sleep week, I think. Maybe oh, TBD. There will be one.\u003C/p>\u003Cp>Speaker 2: I think our next one's in March, because the I think or no. No. It's actually the other way around. We have one more month. We're skipping the first one in March.\u003C/p>\u003Cp>That was the\u003C/p>\u003Cp>Speaker 0: See you guys in 2 weeks then.\u003C/p>\u003Cp>Speaker 2: I remember now. My poor old brain catching up.\u003C/p>\u003Cp>Speaker 0: It's all in the event tab. Exactly. Keep your eye on it.\u003C/p>\u003Cp>Speaker 2: It's all in the event tab.\u003C/p>\u003Cp>Speaker 0: Thanks, everybody.\u003C/p>\u003Cp>Speaker 2: Kevin's keeping us honest. Cheers, everyone. Bye.\u003C/p>\u003Cp>Speaker 0: Bye bye.\u003C/p>","Alright. Yeah. So, Jonathan, you already, briefly introduced that seeing all the hiccups, I don't know if we're gonna cut that. But just to restart it, we're gonna be talking about flows today. We're really gonna be starting with this 15 8 70 about improving the activity panel. But, realistically, as far as I'm concerned, it's sort of a smaller piece of a bigger discussion around upgrades to flows. Right? So for those out of the loop, we introduced that flow system as a way to do event based, actions and operations, kinda like you could with hooks, or custom endpoints, but doing it in a no code type of way. Right? So you configure when you want your flow to trigger and then step by step configure individual operations, individual nodes of sort of this this path, that you wanna execute. The original version of that was really much designed as a, start with the basics, see what people wanna use it for, see where what what the best improvements are gonna be. So we shipped it a little bit lightweight, you know, with a handful of operations and have been more and more over time. But it has been becoming increasingly obvious that there's, a lot of improvements that would be really nice to have, especially when it comes to debugging, sort of helping configuring some of these pieces. So with that being said Yes. Discussion. So for Daniel, who's flying blind here, we're looking at the one about the logs first. Right? So if you're currently running a flow, optionally if you have it enabled, it's enabled by default. It will keep track of the data that sort of went through the various operations, and then saves it to, a logs tab that you can see on the right hand side of the flow. This is basically the primary way at the moment where you can debug what is happening under the hood, because otherwise, you know, there it's it's the way where you can see what data came actually through the trigger and how you've modified the data points in between. So over the Jonathan, you're you're showing it out what that looks like now on your own instance. What are some of the points in this initial discussion that triggered this this conversation? You've got a lot of the ease and access to that information, as well as the ability to control, like, durations. Some of the problems we run into with flows, especially if someone once they get them into production, if they still have the activity and logging turned on, you can fill up your activity revisions tables really quickly. And there's you know, the mechanisms for cleaning that up are, you know, another flow, or direct database access or other kinds of things where you've gotta manage your activity and revision logs and so forth. Common recommendation that I make is once you've done your testing and you've got your flows functioning is to disable the activity and logging. But there are cases where you may want that and logging just for audit trackability on actions and things that people are doing with flows. So, I think some of that is just the general trigger and management of that. Other things that, tend to cause struggle for people in flows is the way that you access this instead of being able to say, look at the data from the log directly in something that I'm working on. There's been a again, there's a number of ways that we can kind of shake and look at this. But the general thing is this kinda lives over here. I can't edit this while I'm looking at this, so the the interactions with logs and the work that you're doing is kind of a it's a bit of a hindrance when you're doing the development phase of flow development. So it's just a more a nuisance than anything else. But the the inability to say edit something here, I have to actually come here to check. So if I'm looking for variables or data or what are the things looking like in here, what's my payload? Now I've gotta remember this data structure or copy this data somewhere else because I wanna actually do something with it. I wanna interact with it. I wanna use those variables. So it's kind of a it's a weird transition kind of back and forth. Some of the systems that we we got in some inbound activity on some other tickets and feedback that we got from some clients on the enterprise side, was you know, they showed showed us some other systems that have similar no code kinds of flow capabilities. And logs, instead of living in, like, a side panel in a weird way, kind of live with the operations themselves. So there's just some general ideas and thoughts around how that interaction in the UX kind of works. Data wise, I don't think anybody's complaining about the information that shows up in here. That tends to be you know, it's fairly easy to work with and deal with. I think it's more the kind of user interactions with data. Yeah. For me, personally, I've ran into this when I tried to set up a flow which triggers another flow, which then leads you to, you know, switching between those 2. And then you have to check that again, but then you forgot on the first flow, forgot something, and you have to switch back. And, you know, so people do run into this, and, I've experienced this myself. So, generally, if I if I experience this, the general user will probably also experience this. So this is a very valid point, in my opinion, and, we should we should improve this a little bit. You're muted, Jonathan. Sorry. You're muted. You look very passionate, though. I'll give you that. But Sorry. I'm not gonna mute. So so what that does is, you know and that's why we saw this very same thing as we started doing some internal research on just this ticket. We rapidly diverged into we've got 4 or 5 other kinds of spec, and that's why we it's kinda leading into this call today. We were talking about the fact that there's some general overall flows improvements that I think we'd like to see across the boards. But the logging and activity, you know, that's that kinda triggered this action was really about that the way that those logs interact and how you have to it's kind of a separation of what is a common function. Yeah. Definitely. Totally agree. And, like the other comment on the chat said, switching is painful. Yes. An auto refresh for logs would go a very long way because I I do think that these two things are very, service the same niche, service the same pain. Because you you want to have up to date logs and see what is different, what do I have to work with, what can I work with, and not being able to have that on auto refresh, for example? Is the same thing as context switching back and forth, and you want to refresh and whatever. So I think these two pieces are very similar and and and try to work on the same pain, basically. So, good point from the chat. Thank you very much. So there's a lot of lot of, I saw the word divergent on the screen. Just made me think there's a lot of divergent ideas happening at the same time. Right? We're talking about a lot of smaller optimizations like the auto refresh or some sort of way to make that context switching a little bit less painful. If we take a deeper look at this discussion, though, that sort of triggered everything, are there any particular pain points about the way we describe or show those logs that is currently sort of, something that should be improved? I'm kinda skimming through this guy. See some people typing in the chat. Please let us know if you have experience in using flows and would like to, contribute. We're here for you. I think on the Trigger log is the hardest to understand. I'm still on. So on that log side, the other key thing that's being pointed out here is there are differences in the inbound payloads based on whether you're doing a create, update, or delete operation. You do have some variation in the trigger payload bodies. And, again, I don't know that it's a bad thing, but it is one of the things that's called out as a there's differences in the pathing, say, to the collection or the item, based on what type of event triggered the action. Yep. Yeah. Very good one. That that makes a lot of sense, and it's it's it's explainable from a technical perspective, but also makes sense where it's where where the pain point's coming from. So earlier on, when we just did the hooks initially, the decision was made to differentiate between create a single thing and create multiple things, which in turn means that sometimes you get a single ID as a sort of, string or a number, and sometimes you get an array of ID strings or a number, which is basically just a bigger discussion around what does that hook payload look like. Right? Because everything is based on the same internal, event system. So, you know, a flow is triggered based on the same hook that you get from, a hook extension, for example. It's all the same thing. Then, the difference between, you know, trigger dot keys, trigger dot body dot keys, etcetera, sometimes it's payload, sometimes it's not, That really depends on the type of trigger, which, again, you know, doesn't necessarily make it make it better, but it is, you know, explainable where it's coming from, where. If you're having an endpoint, you know, with a a trigger request, now you're dealing with a sort of user payload that was submitted that could be anything. Right? If you're dealing with a hook, it's a pre pre known format for what our hooks fire. But, you know, it's there's a difference. There's gonna be a difference, and that is that's definitely tricky. Somebody said, if hooks supported loops, we probably wouldn't need the differentiation for 1 versus multiple. Hook supported loops. I'm not entirely sure what you mean by that because a hook is just a bit of JavaScript, so you could loop over whatever you want. Right? Oh, flows. Oh. Oh, I see. Gotcha. Gotcha. Gotcha. Gotcha. Yeah. So we're basically saying, you know, if you have a way to just say do this flow against every item in the triggered whatever trigger keys, then we can basically just drop the one hook and make everything an array all the time, sort of get rid of some of that confusion, which for the record Yeah. Makes a ton of sense to me. I mean, every every insert into the database could be 1 or multiple things. And if you do one thing, it's just an area of one thing. Right? It's basically it's it's easy to explain. So I I do agree with that sort of general sentiment. Even though for the record, that would be a quite a big breaking change and totally wreck everybody's existing flows and extensions. So TBD TBD. As mentioned, the extension shed will be very possible to create a repeat operation for all elements in an array extension with exposing a single function from the flows manager. Yeah. Yeah. No. Absolutely. Yeah. That's very true. Very true. Cool. There is one more, thing in the chat here from our very own Brian saying remembering the key names for operations is a pretty big headache for me. Why are the keys only showing on hover? Where can I not copy them? Which has been a thing all over the app. And just trying to remember what that key name is. That's a very good point. And I think, you know, overall in the app, we've sort of on the side of making things sort of, what's the right word? User friendly is such an empty thing, but, like, look pretty for nontechnical users. Right? So a lot of stuff gets, what we call title formatted. Family friendly. Yeah. Exactly. We we we title format a lot of that stuff, so it looks prettier in the UI. But totally. Yeah. For things like flow logs, you know, which is inherently a very technical thing, flows is only available for admin users, which are generally speaking, a little bit more of the on the technical side. Those should most likely just be the technical keys. Right? Render them in monospace and just lean into it. Because why why show them as a title formatted version and then have it only show on hover that you can then not copy paste because it's a tooltip. Right? It that that makes a ton of sense, and that is just a perfect sort of tiny little tiny little tweak that's a huge quality of life improvement. Jonathan, I hope that was in the notes somewhere now. Yep. I'm taking some notes in in a separate section, over in the the actual internal notion doc that we've got running on this guy. So I'm trying to capture pretty much it. Another good point here too is, like, why even have a pretty name if you just have the key? You know? Good point. Good point. I think having some sort of description is a nice, you know, nice to have where at least you can write, like, a mini description, but you wouldn't really use the name for that anyways necessarily. Cool. Okay. Just looking at the discussion, though, because I see we're sort of, what, 1 eighths of the way on the scroll on the page. So I'm kinda curious to see if there's any other points in this particular discussion that we haven't really touched on. That's easy to forget. So these ones we just looked at. I think, the suggestion by our own Oh, the the JSON object wrapping. Object wrapping was the other big thing. Again, having this in the side panel, data here, you can start to see if you get long things. It it actually goes off screen and ends up, you know, and you I don't even think it enables a scroll. I'm not sure you can even get to long data that's being displayed in the log there. So some form of wrap, at least, if we're gonna continue in this panel. I think, ultimately, I think we'd like to maybe move this out of the panel anyway. It'll end up somewhere else in the UX. But something for us to keep in mind is that JSON wrapping, and we have that captured as well in a I was just gonna say that it's there it it's I can already also see there's no way to search or filter through logs. Right? That is another, you know, in. The only thing we show about the log is just a time stamp and then a rel as a time stamp. But I'd I'd say an obvious next step is to sort of move that out of the sidebar into just a proper, you know, layout like we do with other things all over the place. So you get the searching, you get the filtering, and we can have a proper detailed view, or draw our although a detail page is probably gonna be nicer for that. Save a little bit more space, for things like that overflowing scroll and just presenting it nicer. Although, then, you know, we create a new problem, which is now the logs live outside of the flow where you configure them. So at that point, you know, we also wanna make sure that we have some sort of way where you can render that maybe as a split view, maybe you can sort of 50 50 between the flow that you're creating and then seeing the logs of that flow with this layout. Because I do believe that keeping them in context or at least having some sort of link back and forth, from, you know, where you're configuring the the law, the flow and configuring the log is gonna be important. From the chat, having logs and operations might be helpful for that. Yes. Yes. Yes and no. It's it's I'm I'm, to me, the logs on operations is an addition, not a replacement. I think personally it's very valuable that you can see, you know, the full, execution path in a log. You can see, you know, at 2 pm today we started with this, we started with it, that one failed, and then we did this, and then here's the data that went through it and what we concluded with. I do think it's important to have that sort of consolidated together, but the the logs and operations, I do agree, would have really be a really nice addition to that where you can just look like, okay. In the last couple of runs, here's the day that it came in and went out of this particular box in your flow. Right? I don't know if that's gonna be a deep link or maybe just an info. Almost feels like you could have, like, a split panel down here that had the normal, like, search layout capabilities of searching through the logs, could be an interesting use case for this where you'd Mhmm. Similar to Visual Studio and other kinds of console logs where when you're doing this kind of development, you've got logging information you can see down here. Because I also think some of the other nice things with flows would be able to have, like, step through. Right? Being able to step through and see data at certain points, what's going on as you're debugging and working on the flow itself. But then as you say, having an actual, you know, log panel or maybe there's a, like, in a sub ten under flows where you can go to the logs and just see logs full screen, be able to search. Because once my flow is operating, I think the the DERF, pointed out that they're they like logs turned on so when users report issues hours later, they can go back and search the logs. And in that case, I'm not looking at the flow. I'm looking at what's the data, what's the flow, what happened, what errors, what things do I see. So cool. Because the nice thing by putting the again, this for for those new to the stream, this is very much a session of divergently thinking. Right? We're just gonna go brainstorm a bunch, like, what will be the ideal state and then take it back towards the end to, like, okay. What is an actual realistic next step? So I can also imagine, you know, closing your eyes thinking about it, if we have a proper detail page, like a full full screen view for the logs for one particular run. Right? We could actually render sort of a smaller, graphical representation of your flow as you have configured it, in in here, and then just show you. You can sort of replay it, so to speak. So we can just show you step 1, and then that's the data that came in and out based on the logs that you're looking at. Right? So instead of just having a long list top to bottom, you could effectively just get a visual replay, of that particular flow operation. I think that could be an interesting one too. Because then you really get to visualize the the execution of that flow because you're effectively trying to follow a path through your flow with the log. But right now, the log is always gonna be a a sort of, what's the right word, a one dimensional list, top to bottom. Right? Chronological. But, you're thinking about your flow, potentially, in more of a graphical tree. Right? Where it's like you have option b, and then you branch off, etcetera, which is not really, represented in the logs in any sort of way right now. From the chat, somebody you could almost use the exact same UI as the flow editing page for that. Yeah. No. Yeah. Yeah. Exactly. Maybe a little bit smaller so you have the whole thing, you know, in view at the same time, and we just can highlight whichever box we're currently showing you. Yeah. I think that could be a very interesting visual representation. It becomes very interactive at that point. Right? Where it's almost like, you know, the logs will just be represented with some sort of timeline bar where it's like, okay. You read operation 1 out of 16 steps, and then you can just go to the next one. Then the visual representation up top just sort of, like, highlights which box we're on. Right? And then just go to the next one, go to the next one, go to the next one. I still think we would have to have some sort of way where it's just, like, show me the whole thing as a JSON blob. Don't make me go through this this pretty thing, but I'm pretty hopeful that that could help, really help debug what's going on here. Speaking of which, why is the flow edit page the default? The view page seems kinda pointless. Yeah. Agreed. Done. So easy it can be sometimes. I I think the the honest answer is that kinda came from flows being initially designed as using the exact same UI and UX and order of operations as dashboards, where that is, very different, obviously, where dashboard is definitely read read only by default, and then only if you wanna change something to your panels for the order of the dashboard or that kind of stuff that you really go edit it. But in this particular case, I agree because it's like, what is really the difference between read and editing it? The only difference for read is that you can't, you know, click a button, but there's nothing that's really, you know, different between the two states. Right? So just getting rid of that read only view, I mean, it it makes sense to me, honestly. Food for thought. It's not not something we're just gonna we'll have to double check if that all makes sense, but just you know? Well, let's say let's play with that thought a little bit. So let's say we make a new page, detailed page, which features everything that we want. Would we like to then be more stringent on how it looks? So maybe take away the ability to point, to to place nodes wherever you want so we can, you know, for example, make it, smaller for the detail page because we probably don't have the same amount of space as of right now. Is that something that we would like to do? I don't know. Like, how important is that even? I think for the flow detail page, for the if you're talking about the flow detail page, it's not important. It's it's really more of a visual aid. This is like if you're mentally, you know, visioning what your flow looked like when you created it, you can see it sort of, like, go through the go through the motion. So it's really more meant as a graphical element that is more for, it's kinda like a map. It's kinda what I see it like. Right? It's it's a nice to have, not really a requirement. What I was kinda thinking we could potentially get away with though is instead of rendering the full boxes with everything in it, which just be the name or just an empty box for that matter. What we could do, though, it's I don't know if you've ever ever played with this, but if you have a dashboard set up Jonathan, do you happen to have a dashboard in this this demo instance? Plenty. You gotta love it. Dashboards and sort of the underlying panels and the the viewport stuff. Yeah. Exactly. It has a button that just sort of zoom out the fit. And also a full screen button for those who don't. Pro tip for you. So you can full screen and make it fit on your your, fit on your screen. But we could use that exact same thing for doing just sort of a mini representation of, of your flow at the top of this flow's detail log page. Right? Because you don't need to see all the exact details. It's mostly just as a graphical map for going through your flow. This could be a very interesting trick. Similar similar tools I've seen, you can actually zoom in or out. You can actually zoom your view so you can see more of your flow or all of your flow. And then when you double click or click on something, then you get back into the item view or the detailed view. So back in our flows example here. Right? You'd be able to, you know, have a zoom option or be able to scroll in or out and zoom your view similar to a map style the way we do with the geospatial kinds of things. So very similar to that would be fun. I wish I could see the screen right now, but, I thought there's something Oh, right. About exhibit. I forgot. For example, yeah, if if we decide to, you know, like, restructure the visuals or want to provide a different type of view, for example, like, we don't have to have boxes. We could also have, like, circles, for example, which could be smaller, take out the space. Maybe they're horizontal or something. I'm not sure if you showed this, right now. I'm sorry for that. But Oh, no. No. No. No. It's I just I just love the the very bit of a sidebar. I just absolutely love the the artistic way you brought that just now. Maybe instead of rectangles, they could be circles. Yes. But yeah. No. You're absolutely right. Because we the nice thing is we know the exact dimensions of each box. Right? So we could theoretically, for a graphical overview, render each box at a half height and offset all of the, x and y positions by, you know, the number of boxes high To sort of recreate the diagram in a more compact view. For sure. Yeah. Good point. So let's let's noodle on this idea for logs on the actual operation box. Right? So would that be a, sort of additional button, I guess? Because I'm also sort of operating under this. It's edit mode by default all the time. So I could imagine that maybe next to the edit button, there's just some sort of logs link. And now that I'm thinking about it even more. Pre filter the logs to the particular one you're looking at, all that kind of fun stuff. Yeah. Because now that I'm thinking about it, we save the logs as one row with a bunch of JSON in it for the whole flow execution. Right? That's the, that's the log item that we have. So there's no real way to just say, give me all of the logs for just the update data operation, because you're looking about all of the, you know, all of the, all of the data from the whole flow, and then we have to sort of filter it back down. But, you know, we could consider, although the amount of data is gonna get out of control real quick, but we could consider saving, you know, a log row in the database for each operation step instead of for the whole flow. But we gotta make sure that we have some sort of automated retention setting and and a bunch of indexes, indices for that, to not completely wreck your database. Because if we're now creating 5 new records per flow instead of 1, then you're talking about millions and millions of data points, which, you know, depending on your database might not matter. This has been a point in the discussion. The person that started then was already interested in some type of way to for example, similar to the activities, issue that we had, recently where, you know, big or large instances have trouble with, I don't know, I don't know, 2,000,000 activity entries and some type of schedule that clears logs or, for example, you only want to retain those who are at most, I don't know, 30 days old, for example. Some type of rule maybe which could, lighten the load a little bit would be helpful, I think. Oh, a 100%. Yeah. Yeah. The 100%. The the main reason we haven't had that before, I haven't done that yet, is because we didn't have support for this use yet. Right? And that's really a requirement. Because if you wanna delete with a filter on a timestamp and you don't have an index on that timestamp, now it might take your database, you know, minutes to just go through a table of that size. So that's that's also where that sort of sprint came through to, like, support indices and now collaborating with the the contributor there to to get that across the finish line. Because then once we have proper support for indices because because I do wanna make sure that, you know, whatever we do for the system stuff needs to be available to the end user. Right? So once we have support for indices, we can then enable indices for the system tables for, like, the timestamp in activity and and same for flow logs and stuff. And then the second piece of that is gonna be a setting that says, what do you want your, you know, low log retention to be? And it should be an environment variable, I guess, or maybe it's a per flow option. T b t b d on that. Right? Maybe there's an environment variable for the the maximum number you can set, and then in the app, there's a drop down, whatever. We'll have to figure it out. But, yeah, to your point, if you can configure, I only wanna keep 7 days worth of flow logs for this flow. I feel like that's a must have for any sort of upgrade that we're gonna be doing the flows, because it's so easy to just now accidentally end up with a couple of 100. Actually, that reminds me, I think, Kevin the other day did a fantastic little flow that he sent over where he was using it for, for beddlesnakes. But I also saw his flow logs in the sidebar already be in the 100, and I was like, how how long have you been running this right now? Right? You're gonna have 1,000 tens of 1,000 of those, so we need to have some sort of retention for that, which I could imagine, you know, if you have a flow that you know you're running a lot and you want it to be lowers, think it has to be per flow. Food for thought. Food for thought for sure. So then when we're thinking about, you know, one other thing I know about the debugging of, flow specifically is that right now to test anything, you have to trigger the actual thing that triggers this. Right? So, as of right now, if, Jonathan wanted to test this ready for review flow in any way, he would have to save this, quit, go to his articles collection, and then manually trigger it. Right? Oh, it's so painful. It is so painful to debug these things, because you have to do just that. Right? I have to go I have to go save, then I have to go to our to my systems over here. I have to go to articles. I mean, at this point, normally, I've got an you're already kind of nabbed here, but now I've gotta open an article, and then I've gotta go through the actions of whatever I'm testing. So ready for review case. I have to push the button, then we go back, and then we're gonna go back to flows. We go back to ready for review. Now I have to go to logs, and now I can look at logs and see what's going on, test flow or not. So you're in here, you're traveling through, and you're looking at your payloads, and at your options wherever you are in the debug process, then you're closing out. Now you're going back to edit. So many mouse It's a pain is what I'm hearing. It's a pain in the butt. Flow is awesome, but it is it is painful to do the administration. That's why we're here. That's why we're here. Yeah. So one thing I think just wanna add another point from from him. Yeah. Sorry. Go. Go. Go. Go. No. Please. Please. Yeah. Yeah. Because, this this then touches the issue of alright, so let's you you want to create a flow. You want to try it out. You have to try it out in order to actually make it work. But then comes the thing, alright, so let's say I have an existing flow, and it's running. It should continue on running, but I want to, I want to edit it without changing the actual running flow, which would technically be something like, alright. Let's duplicate this flow so I can play around with it. And then, after I'm done with my modification, then I switch them or, basically, disable the previous one and enable the next one. So some type of let's let's call it, like, very, very lightly versioning. Yes. Oh, the chat. The chat is exactly it. Once they have the whole tag. Right. So so if, yeah, if you have a couple of, like, important very important flows running in production systems, you don't want to, you know, edit them willy nilly. So that's the that's the another thing, which is can be can be painful because as of right now, there's technically no duplicate button, which is, not as nice as it could be. And, it's it's a difficult one, isn't it? Because I'm also thinking about some of the triggers. Would that make sense? Because if you make a new version of a an endpoint, right, and an endpoint has a UUID to run it. But then if you create a duplicate, now the endpoint is different. So then if you wanna make that your production one, now you have a different endpoint. Right? So it's like the the duplicate and then kill the old one flow pun intended of updating flows might not work for every trigger. Also, if you create a new version of a flow that uses, like, an event hook for, like, an item save on articles or something, like, in this example. Yeah. It would have to be some sort of dedicated versioning because if you create a duplicate, then now you're firing both of your flows. Right? You know, a very, like, naive solution to that event problem would be to have the duplicated flow immediately be set to disabled. So if you duplicate duplicate something, the duplicate one is disabled, so it doesn't fire. And then you can play around with it, change something, and then enable it yourself. Yeah. Somebody in the chat that or somebody's plural in the chat, we're also saying, you know, you can obviously have a local dev instance or a dev copy where you could configure a new flow and then sort of import it at once so you don't, you know, mess anything up on production. Very true. Very true. Wanna make sure, you know, we keep we can Yeah. All the use ASM license. This this then goes hand in hand with the next thing that I wanted to bring up with with the same thing. So let's say you have your dev instance, and then you want to sync your synchronize your flow to the production instance. Alright? There's no version control, basically. If you don't use, like, an actual extension, which you can put into your Git, version control, you would have to manually duplicate or use the API or something to to get the flow over or synchronize between your two instances. Mhmm. Well, luckily, we talked about that particular problem 2 weeks ago in the last episode. That's exactly right. Like and subscribe. Exactly. The link right below the like button. Is that what they say? Yeah. I'm gonna have the sidebar here. Exactly. Circling back, though, because we we have, I think, 2 or 3 different, UX points with, like, a couple of different solutions. So one thing that I think is a must have for sort of this flows upgrade project that we're putting together here is that there needs to be a button on the trigger where you can manually trigger that trigger. The difficulty will be what data do we trigger it with, and how can we help you make that data realistic? Right? That is gonna be the difficulty there, which is kind of what we haven't done before. Because right now, with this manual trigger on an article, you know, the data format for that, like we talked about with the chat a little bit earlier, it's very specific to that particular article and that particular, data model for the article if it's like a filter hook or something. So if you have a manual play button, so to speak, we need to have some sort of way where you can sort of fake what that event looks like. We can pre pre generate a couple of ones based on your instance, I guess. Because, like, we know for the manual trigger that you get the primary key of an article. Right? That's what you would trigger with. So when you hit a play button, I imagine that we would have to show some sort of modal or a dialogue that allows you to put in a JSON object, I guess, with what that sort of, fake data looks like. And for some of the triggers, I think we can prepare that cause we can we can pre fill, you know, a fake article manual run cause we know the format, collection, keys, etcetera. For some of them, you don't need to do anything at all. Like a cron thing, you can just play because there's no real, you know, trigger data coming in, maybe a timestamp, but I'm not a 100% sure. For an endpoint, though, there there's no way for us to know what that looks like. Right? Because the payload is user edit, so we don't really know do with that. So so some of the things I've seen with other tools, then this goes this even goes back 20 plus years ago using WebLogic's BEA workflow engines. You could actually take data from previous runs, so from the logs essentially. You could actually generate your payloads dynamically from that, or have say, I wanna capture this data, and I wanna actually reuse that as the test mechanism and essentially create your test data from an existing run. And then, ultimately, you could even edit at that point, you could edit the payload. So if you wanted to change some of the data attribution for subsequent runs, you could actually just quickly edit. So as part of the you know, that kind of play operation, you would actually get some dialogue capability and say, I wanna use either an existing or, in some way, create or save your payload and then fire that in. And in that way, you know, we don't have to be trying to generate it. We can just say, you can either run it normally, go and trigger the action. You know. Another way that I've done some of it is, like, have an incognito window with log you know, I I don't have to actually do what I just showed you, which is exit my flow. I can actually do the testing from another user. You can there there are some ways you can simplify or streamline that just a little bit. And you may be testing that permission set anyway. Then you may have permissions and restrictions, and you may be testing that as part of your application anyway. You'd have a test user with those permission. But being able to capture that information from an existing log or flow, run would be super cool and helpful. And that's some of what we've captured some of that already. We have the logs. I mean, we have all of that data to your point. Like, if if there was a previous run, we'd know exactly, you know, what what information was there anyway. So we could definitely use that to to prefill it. Is this sort of manual trigger for well, manual trigger is a bad bad name because we already have a thing called manual trigger. But it's this sort of play button. Let's call it that. Is that something you'd wanna do for the whole flow, like, on the trigger level, or is that something you'd also wanna be able to do per operation itself? Because somebody before was like, you know, I used the run script operation a lot. I can also imagine that it would be really useful then to just just be able to say, okay. Just replay my run script a couple of times. But what I was just about to say showed up in the chat. Shout out to the Dev once more. Operations depend on a lot of context from what happened before. Right? Yep. That would be more like that step through capability, right, where you you can step through and, you know, in debug mode, essentially pause. Right? The you know, you have your your break point. And at that point, you stop. You can actually analyze and look at the data. So, I mean, this does become very much ID style kind because that's what this really is. We're we're doing ID development. The idea is you would have these kinds of breakpoint capabilities to be able to stop, look at what data and parameters, be able to look back through the current context, what does it look like. Am I getting what I expect? Okay. Okay. Then step through debug. And it gets complex because we've got this mix of operations, and then you got run script that has, you know, code. Right? You know? Now do I have another debug capability with stop points and break points inside the job? You know? Yeah. Debugging that the TypeScript JavaScript in there directly. It gets very complex in that sense. But I think just the ability to be able to have a I wanna be able break point at the run script, be able to step to the next operation, then check the data and see I'll be able to multiple breakpoint options. We could get more creative down the line. I think if we can just put it at the operation level, that could it would be kinda cool if you could, you know, essentially step back, edit the data, or do something to the input, and then feed it back through, step back, step forward in in the operations themselves. Like, it's more complex than And another thing with all of this, of course, is that, these operations may very well have side of on purpose because you might ping a different endpoint. You might save something's database, whatever. Right? So if you're manually playing, you know, with Flow or even individual operations for debugging purposes or whatever else, those side effects will still be in effect. Right? And if you're trying to debug a whole flow, you know, operation 2 might be dependent on a successful response from operation number 1. Like, number 1, save something to the database. Number 2, reads it, you know, now that it has been saved or something. I'm just trying to come up with an example. Because I was thinking, you know, it it be important to think through some sort of dry run as well where you can just like, okay. This would have now saved to the database. Right? And then, oh, this would have now made a request to the API, but we didn't actually do that. We didn't want to make a Stripe subscription as part of our little testing thing right now, right, to just test if everything works. So that'll be interest interesting. Some sort of dry running, thing behind it. I I do think it's important to think through at least because of the side effects. But to again, shout out to the derp. Can't really do a universal drive run because you never know what, you know, arbitrary stuff is being used. Yeah. You'd almost have to have, like, a successful run or at least a set of data and payload options that you could edit up to say, you know, this is what I'm kind of expecting as I process through my input outputs. Mhmm. So So you'd have to have input output capabilities. What do you expect? And then as you say, dry run mode, not save, but often, you know, maybe the change that I'm making, I then getting that and then doing something. So I'm sending it to that I'm sending a webhook out data payload that comes back, you know, depending on how complex you make a flow. Mhmm. My general recommendation is if flows get that complex, go write a hook. But it's Well Well it it there is gonna be a point. It's a balancing act. Right? There there are I I like flows for admin kinds of functions where state management user control. When I get into really complex conditional lock, do doing this in these boxes so much faster to write TypeScript, be done with a hook on the backside. That's my Yeah. The the similar to yeah. What I wanted to say is this sounds, like, very similar to some type of bash script or something. You know, some some type of scripting, where as soon as you need conditions or something, it's probably better to make it a program. Because, who likes to write bash? Basically, you know, it it gets it gets gnarly really quickly. So as soon as you need sophisticated stuff, some type of conditions that branch into something and do something with arrays or something, it's probably better to actually use a programming language. And, I, yeah, I don't know. It really depends on a lot of things because one one is like, do you even know TypeScript or JavaScript in the first place? I think that's an important one. I think by, you know, doing it manually as as code, you also have a lot more opportunities to break it bad. You know, make it insecure, just make it an optimized break stuff tremendously hard. And also in, the chat somebody pointed out, you know, with flows, you do get the the logs and sort of the ability to explore the steps and what went wrong. So it's it's an interesting take, Jonathan, because what we're saying is, like, as as of today, you know, when it gets complicated, you wanna switch to code because the flows, UX, and UI just doesn't isn't good enough yet for complicated stuff. Right? So Right. Yeah. Yeah. It is. But I I'm hopeful. If if we make this kind of what we're talking about, if we get to that point in these next few iterations on maybe it does become I don't actually need hooks as often. Right? I could be you know, hooks could just be when I need external library. Yeah. Exactly. Allow within flow at the moment. I'm just I'm very I'm very hopeful that by by some of these seemingly small but very big changes, like adding the manual trigger so you can at least just try it out, I think we can actually get this to a point where HOOX is gonna be the more complicated one to do, you know, because it's like, yes, you have a black box and do whatever, but you don't get all of the debugging niceties and and all of the comments. Not that it's a battle. I mean, at the end of the day, it's just pick whatever you want, what's worked best for you. But I think that we can reverse that take, honestly, that flows could be I think that might be my personal challenge. Make flows the default for Jonathan. That's my measure of success. Writes the worst TypeScript he's ever seen. If he says I prefer flows over hooks, it means we did a good job. Perfect. I love it. Project Jonathan is what we call it. Cool. Okay. If you can keep me from writing code, it's always a good. It's always a good idea. So there's there's definitely a couple of unresolved You know, as per usual, I with the eye on the clock. As per usual, we're gonna be wrapping up. We've been taking a lot of notes during all of this, and it's, again, very divergently thinking. We're gonna be compiling all of these notes and ideas from everything that we just talked about and everything on the chat. Thank you for that. Into, you know, a proper RFC document and figure out what does this project upgrade flows, x y z, you know. What does that look like? What do we see as the must have? What can we get done in a sort of initial sprint? There have been, I think, like, 4 or 5 different discussions that are all sort of asking for the same thing, which is, like, improve Flows debugging. But they're all various sort of smaller bits and pieces of a, to me, bigger Flows 2 point o type of upgrade. So we're gonna be trying to compile those and sort of merge them into one sort of flows project, if that makes sense. Just as a quick summary, I think just the the upgrades to the logs that we talked about, you know, making them, like, explorable. I guess that's the right the right word. Giving them its own page, giving it more space, making it easier to step through, you know, the execution of a flow. Definitely a big must have. And the ability to trigger a flow from where you're editing it with some sort of, you know, preloaded payload from a previous run or something you can manually adjust so you can actually try out what the hell it is that you're building without having to go all over the app. I think it's gonna be a very, very important thing to have. Last question from from the chat here before we wrap up. Someone had said that many of these ideas could be implemented by the community in a custom module? No. Yes. Community can build whatever they want as a custom module at the end of the day. That is very true. And with the, you know, upcoming release of, for marketplace project, I'm also very curious to see, you know, what people will do with this type of stuff. Right? Somebody could, definitely, make a flow flows log module and just make it super custom or super proprietary or super flexible, whatever they want Whatever they want, really. Cool. Okay. There was one more that snuck in with an upvote. One final thing. Can we have access to the flow manager from the flows service so we can do more things with flows from extensions? May may may. No problems. So so It depends. It depends. Now I'll I'll, it's oddly tucked away compared to the extension manager, which should also similarly be tucked away, actually. Anyways, no. The the the reason for the hesitation is more around updates that I kinda wanna do to those services in the first place. Right? So I know I wanna do some sweeping upgrades to what those services look like and how they work in the first place. So I'm hesitant to to add new stuff onto the services service that we know might change already. Right? So I I don't wanna introduce something new that's gonna change then fast after, if that makes sense. That being said, yes, I do wanna make sure that extensions do have access to all of those types of internal things, which is also a reason why we've been moving a lot more stuff into individual libraries. Right? So I don't know. For for those who have been watching the repo like a hawk, we just moved sort of the environment variable extraction and handling different library with the same sort of idea, right, where an extension can just import the Directus ENV library and then use the same sort of ENV handling that, Directus does itself. We're we're basically doing that across the board, and the services is one of those things that I wanna do like that. And I can definitely imagine there being eventually being, you know, a Directus flows library that contains, you know, this flows manager state, so that extensions just can import it just like the direct as API would with TypeScript typing. I I heard you. Community, I heard you. With proper TypeScript typing and everything as well. So that's that's the only reason why I'm a little hesitant to promise anything better, as of right now. Any cool. That marks 11 sharp on the clock on my end. I think this was a very interesting session so far. This is a little bit more divergently rambling, than doing an existing discussion, but I think we've touched on a couple of very, very important points. Any any other closing thoughts? If I could remember the dad joke from Bryant this morning, I would tell it, but I suck at remembering jokes. So Well, tune in next time for for John's phone dad joke. With all that being said, thank you to the audience. Thank you for watching. If you're watching this on Directus TV, Directus dot a 0/tv, Hi. Be sure to watch the previous versions of this video down below. And we'll see you guys in 2 weeks, I think. Or are we skipping that one? Because it's sleep week, I think. Maybe oh, TBD. There will be one. I think our next one's in March, because the I think or no. No. It's actually the other way around. We have one more month. We're skipping the first one in March. That was the See you guys in 2 weeks then. I remember now. My poor old brain catching up. It's all in the event tab. Exactly. Keep your eye on it. It's all in the event tab. Thanks, everybody. Kevin's keeping us honest. Cheers, everyone. Bye. Bye bye.","published",[149,159,168],{"people_id":150},{"id":151,"first_name":152,"last_name":153,"avatar":154,"bio":155,"links":156},"23ebcf2c-4374-4f5c-8198-f8ad497fd856","Rijk","van Zanten","7ef9652f-3835-432c-a43a-c5fe13001f31","CTO of Directus",[157],{"url":135,"service":158},"website",{"people_id":160},{"id":161,"first_name":162,"last_name":163,"avatar":164,"bio":165,"links":166},"0d906492-75f0-45d9-abf7-ab779bf1ed08","Jonathan","Wagner","5062e4df-a198-4b40-af47-42362d3c0551","Sales Engineering Manager at Directus",[167],{"url":138,"service":158},{"people_id":169},{"id":170,"first_name":171,"last_name":172,"avatar":173,"bio":174,"links":175},"07ec688d-251d-4efe-bc17-73848402d43b","Daniel","Biegler","8897b70f-c524-460a-8990-58cc5c3be886","Engineer at Directus",[176],{"url":141,"service":158},[],{"id":179,"number":180,"year":181,"episodes":182,"show":195},"6aa046f1-bd53-4510-9af0-c0f3daaf4415",1,"2024",[183,184,122,185,186,187,188,189,190,191,192,193,194],"daed2c08-703a-43d6-ac97-aacac61be4c0","86fa152b-6a8b-477e-94b5-bd91e1202d21","b2b01569-d8c6-49a7-adaa-429fe84f204f","b63afbe1-6418-4e9e-b1da-4890979789f0","69ad81e8-5e1d-4b85-9fa9-3b767a3a3478","5c9c888c-f527-4608-a2f7-56f156d00980","243daa59-3772-4ebe-b212-c2a09a4a0b71","d66c1e46-cc57-49fe-a914-2e440bbc1576","12c8f72d-22fa-4ffa-a9d1-57047216fd1a","8896c934-aa2c-43b6-9342-8275682ab8b2","84c7b3ac-fd85-4539-8f39-3247118bcbf2","044b7c89-aaec-43b2-9d6d-6743a0fb5afd",{"title":196,"tile":197},"Request Review","73687d01-3734-4c28-aef7-e6fa8db4cf1e",{"id":185,"slug":199,"season":179,"vimeo_id":200,"description":201,"tile":202,"length":127,"resources":203,"people":206,"episode_number":210,"published":211,"title":212,"video_transcript_html":213,"video_transcript_text":214,"content":8,"seo":8,"status":147,"episode_people":215,"recommendations":219},"conditional-fields-nested-relations","916080169","In this recording of our live event on February 22 2024, Rijk, Jonathan, and Daniel discuss the support of nested relational values in conditional fields to build more flexible content editors","4764c83c-2464-4764-8ef3-9d310502315d",[204],{"name":130,"url":205},"https://github.com/directus/directus/issues/8228",[207,208,209],{"name":134,"url":135},{"name":137,"url":138},{"name":140,"url":141},4,"2024-02-29","Conditional Fields & Relational Values","\u003Cp>Speaker 0: Love it all.\u003C/p>\u003Cp>Speaker 1: Yeah. Hello. Welcome everybody once again. Thank you for joining us again in our biweekly, bi monthly. I always forget the difference between the 2, but they're also interchangeable.\u003C/p>\u003Cp>Our bimonthly, twice a month, session where we go over, you know, feature requests and try to go in deep, find all of the edge cases, think about everything that we possibly wanna support ever of the universe, and then bring it back down to number 42. Today, we're talking about supported nested relational values in conditional fields, which feels like a, oh, just support nested relational values. Easy. Until you start thinking about it for real, which is what we're gonna do today, and realize that it's probably not as easy as it sounds because that seems to be far from the course for these sessions.\u003C/p>\u003Cp>Speaker 0: As it always So\u003C/p>\u003Cp>Speaker 1: before we dive in on the every single time, before we get in too deep on the technical problems, you wanna, outline what what this is all about, Daniel?\u003C/p>\u003Cp>Speaker 0: Yes. So, just for anyone that has not used this feature before, it's pretty, I think it's pretty niche. I mean, I have not extensively used it in the past, but, a little bit here and there. And I think lots of people, share this experience. But, if if you use this feature, conditional fields, you will eventually run into this little problem.\u003C/p>\u003Cp>So it is about the ability to conditionally render, for example, or hide or show or change fields inside of your collection edit or your item edit page depending on other fields. So you open up an item and you have a couple of groups depending on how much information there is inside of your item. It might be useful for you as a user or for, you know, to make it easier for actual users of your directus instance to hide a couple of fields, for example, so lessen the, you know, initial information overload, for example. Or you could also make use of it to actually enhance the visual, the the user experience. There's lots of stuff that you can do.\u003C/p>\u003Cp>Also, you know, require different fields if a different field has a specific condition, if it meets a specific condition. So lots of interesting stuff that you can do and, like, really, really customize how your editing experience looks, how it feels, and improve it for your users. And, so this is just the overall, like, high level description of what this does. But this issue that has been opened for a little bit, a little tiny, tiny, tiny while. So, it is about this exact scenario.\u003C/p>\u003Cp>So where you want a field to have a new, let let's say you want to hide something depending on if this item has some type of property in in a relation. I don't think I, describe this very well. But, so you want the to apply these conditions depending on some nested property. And this currently is a little bit tricky, for us because this stems stems from an architecture standpoint, like, how our forms work as of right now. So this is not like, you know, we're just missing a little if statement maybe, and then we could enable this.\u003C/p>\u003Cp>It's a little bit more more involved, but we'll explore this a little bit. So, yeah, this is what this issue is about. You want to, you know, conditionally style or, you know, change your existing fields depending on the nested property. And it's currently a little problematic because if you open up a form or your item page, I mean, we currently do not load every single nested relation because, you know, that it could be bad. It could be good.\u003C/p>\u003Cp>It could be bad depending on how large your item is. So, technically, if you open up your item page, we do not have that type of information as of right now. So you can't actually apply conditions because we don't have that information inside of the form, which is the root of the problem. So how do we fix that? Good question.\u003C/p>\u003Cp>Speaker 1: Problem number 2 is we might not even have access to the info that you're trying to use, which makes this a heck of a lot more tricky to think.\u003C/p>\u003Cp>Speaker 2: Yeah. Tack tack on permissions, and suddenly this gets very, very complicate. I mean and how deep is this? Right? So in my case, right, where many to any, this can this, I've seen clients with anywhere from 5 to 18 levels deep in this relational model.\u003C/p>\u003Cp>How much data do you load up into the current view? Right? This can get very\u003C/p>\u003Cp>Speaker 1: first, Gary, you know, this\u003C/p>\u003Cp>Speaker 0: can get a little bit of hands in from the chat. You know? Let's involve the chat a little bit. So So just\u003C/p>\u003Cp>Speaker 1: to just to summarize this to, those three main Please,\u003C/p>\u003Cp>Speaker 0: let's\u003C/p>\u003Cp>Speaker 1: problems at first. Right? So right now, those conditional fields are just using the information that is visible on the form, right, with the edits applied because it needs to be reactive to what the user does. Then once you go relationally deep, we have a bit a problem because that information just doesn't exist in the context of that page at present time. Right?\u003C/p>\u003Cp>So that in and of itself could be easy enough by saying, okay. Let's just fetch all of the paths that are used within the conditional fields, and then at least we have that data. But we fetch it separately from the actual form content just for conditional fields purposes. That would solve part of this. Right?\u003C/p>\u003Cp>But then the second problem that makes that part a little tricky is that we have to merge it with the edits made by the user in the form. Right? So now we're dealing with differences in data types and how you configure them, which is one of the the sort of bigger the the second issue. Because theoretically speaking, you know, conditional fields check against the staged value of the form. So therefore, if you select, you know, a many to one item, you could check against the ID that you have selected.\u003C/p>\u003Cp>If you make a nested update, you could theoretically, through the rules, check for the nested value and and change it. The difficulty is, like, if you select an existing item, now the data that is staged is just a UUID. Right? It's not a nested object of values. So if your conditional field says, author names or nested name and author has to be reg, then it becomes tricky if you select the existing author because now you're checking the rule is nested field name has to be reg, but you're checking it against the u a d string.\u003C/p>\u003Cp>Right? Because that's the actual data that you're about to save. So that's that's another big big mismatch there. And that problem compounds the further down you go, obviously. Right?\u003C/p>\u003Cp>So the other thing is when you update, a one to many, we have that difference in syntax where you can provide an array of all the items or you can provide, you know, the create update, delete statements individually, which is what the app uses because it's still easier to manage for larger datasets. But that again also means that you now have to check against 2 data types and it works a little bit unlike you would expect. Right? That's kind of the the the TLDR for this. The 3rd major issue is permissions.\u003C/p>\u003Cp>Right? So as an administrator, you could set hide, a certain set of fields if a hidden field for this user, like, that's something they can't see is enabled or disabled, which for the end user is invisible and therefore the app can't actually run the check against it because it doesn't even know that the field exists. Right? So that needs a totally different solution where the check doesn't even happen on the app client side. The check happens on the server side.\u003C/p>\u003Cp>So it can check against data that the client user might not even have access to in the first place. Right? So those are the 3 major sort of problem spaces that we have with this particular feature. All of which need some sort of specialized solution for conditional fields. And hopefully, we can find some sort of direction that is 1, you know, one endpoint that rule them all, so to speak.\u003C/p>\u003Cp>Speaker 0: That's a top order. I guess. We we have some interactions. Yeah. Exactly.\u003C/p>\u003Cp>So we have a little bit of chat. How about having a field, that just show calculated data from other columns? So it's not a column in a database, a column just for showing some calculation.\u003C/p>\u003Cp>Speaker 1: So if I'm understanding correctly, to summarize that, what we're saying is instead of trying to use the nested values like an actual nest of the tree, why not have one alias field that just pulls up the relevant bit of data? So it's always just the string name, for example, from an author, and then you can conditional fields against that. Right? So instead of trying to dynamically do it against the whole tree, you're just pulling out the data that's relevant, and then the conditional fields check only runs on the top level.\u003C/p>\u003Cp>Speaker 0: Alright. But lots to think about. There we go. I've done it in. Fit this problem before, so what I do is to just create another extra foreign key.\u003C/p>\u003Cp>Speaker 1: It can\u003C/p>\u003Cp>Speaker 0: be used to filter the current items onto many drop down. Problem is that the user need to do another selection to enable this filtering.\u003C/p>\u003Cp>Speaker 1: That's kind of a similar idea. Right? Yeah. Where it's like instead of trying to nest it deeply, you just pull the value back up in some sort of way, either automatically or by having the user chip choose it, and then you operate against the static value of that field. Now the the interesting thing here is that one of the problems that we're seeing is that the way it works technically makes sense.\u003C/p>\u003Cp>Right? You you validate the conditions against whatever the third stage value is with the user's changes applied. Where it falls on its face is that the expectation is that it will do nested relational lookups and then dynamically apply the changes in that tree and then check against that. Right? So that could potentially solve for the first two.\u003C/p>\u003Cp>Right? Where we're saying, okay. We can make some sort of utility function that says, what is the conditional field rule? What data do we need for that? Then apply the current edits on top of that in a way that fits the model, right, the model for the conditional fields.\u003C/p>\u003Cp>So, therefore, if you selected an an ID for many to 1, we have to go fetch the nested data for that so not the permission. I saw it on the screen. It's in a different order now. So it's for the the app data context and then the nested relationships. For the permissions piece, though, we have an issue.\u003C/p>\u003Cp>Right? Because at the, like, the end of the day, we cannot run that in the app. That's that's basically the long story short. So those for for those who have been eyeing the GitHub repo like a hawk, there was actually a PR not too long ago with an issue, in a in a similar vein, but about the permission checks. Right?\u003C/p>\u003Cp>So some users were running into some issues where the application would allow you to change fields that you didn't have update permission to, for that exact reason because the update permissions were using a field that the app cannot read because you didn't have read permissions to those fields. So, therefore, the app couldn't know if you had access or not. So it would just default to, like, okay. You can do it. And then once you hit save, the API would just throw an error and be like, no.\u003C/p>\u003Cp>You cannot do it actually. Right? The way we solved for that is with a new endpoint in the API that basically say, hey. For the current user, am I able to update this particular item in this particular collection? Right?\u003C/p>\u003Cp>And it will return, like, these are the fields that you can edit, as far as I understand. I I'm a little hazing the execs, you know, IO, but that is effectively the gist of it. Right? And it feels like It feels like this feature will probably go in a very similar direction, where we need to have some sort of API endpoint where the app can say, okay. Here's the current about to be safe changes.\u003C/p>\u003Cp>For the for the current user, what should the conditional state be, I guess? Right? Because that's the only way. If the the app cannot read fields that are used in the conditions, it's kinda game over. Right?\u003C/p>\u003Cp>However\u003C/p>\u003Cp>Speaker 0: Interesting. How how would how would that endpoint look like? Like, what type of payload how would that translate all of the different requirements that we have? Interesting.\u003C/p>\u003Cp>Speaker 1: So I'd imagine I I know the requirements generally are, a, we need to fetch all of the data that is used in the, conditional fields rules. Right? So we just have to look up what are all the fields and what is the whole tree that is used within the conditional fields and fetch just those in the exact same structure so so we can run the checks against it. Right? Then we need to dynamically apply all of the staged changes from the user because one very important use case for conditional fields is things like, you know, you click a toggle and you show and hide fields conditionally.\u003C/p>\u003Cp>Right? That's kind of one of the major use cases for this. So it needs to be real time. And then the last thing right now, I'm pretty sure that's, it just returns. I I think what we do right now is we effectively just loop over and and then merge the field's configuration for the current item with the conditional field result, sort of smash them together.\u003C/p>\u003Cp>Right? So if, like, the default field is hidden in your conditional fields, you have field that's visible, then that takes precedence, and we merge them together by by field key. Right? So we dynamically update the area of fields that exist within the form based on that logic. So to translate that into an endpoint, you would most likely have to have an endpoint that takes what collection are we in, what item are we in, because that might affect, you know, the the IDs and all that kind of stuff.\u003C/p>\u003Cp>And then what is the changes that you've currently made so we can dynamically merge those and then do all of that logic on the server side and effectively return a new list of fields that should be visible in the app. Right? That's theoretically possible. Tricky thing, performance. Right?\u003C/p>\u003Cp>Speaker 0: It it is exactly. Like, I was already, like like, inhaling and just to, you know, finish your sentence so I can say that. Exactly. So, yeah, that that would probably then lead to, you know, some delay because, let's say, you type a name pretty quickly, you know, like, example, whatever. Now you made, like, I don't know, 6, 7, 8, whatever it is that you're typing.\u003C/p>\u003Cp>The key presses, alright, do we debounce those? Then, alright, we have another little delay. So we then have to contact the API, which gets the stuff back, and then we have another little delay. And then the whole experience might suffer depending on how exactly we do it. Because, like, even if we now if we now, start, like, debouncing, that could lead to other problems.\u003C/p>\u003Cp>You know? Like, if if we want something to change, if the the the the text field contains a specific substring or something. Yeah. Then then that won't trigger fast enough, basically, which, you know, is kinda not the point.\u003C/p>\u003Cp>Speaker 1: That is that's really hitting it on the head because this has to be you click a toggle, stuff shows up. That's that's the goal. Right? So it needs to be immediate and interactive. So if you debounce it for a second or something, to your point, the experience is gonna suck because you click a button and then Yeah.\u003C/p>\u003Cp>You're already looking somewhere else and then magically stuff shows up.\u003C/p>\u003Cp>Speaker 2: Right? This, it's instant. Right? Because the app has all the context and data and permissions and things that it needs, so this is instantaneous for this to show or hide. Mhmm.\u003C/p>\u003Cp>You know, make required, do whatever. The the toggle here, the app side is doing all that, and it's almost instantaneous where you go server side now if you're having to send back to server. I'm wondering, does WebSockets' real time kinds of capabilities help at all in this space if we work towards I mean, again, we've always wanted to make the app real time so that we can do, you know, multi multi user editing of records and things.\u003C/p>\u003Cp>Speaker 1: Yeah. I think, realistically, the main it it would reduce the network latency a little bit, but I think the main time spent on this is re fetching the existing item data and then merging on the changes. Right? Now\u003C/p>\u003Cp>Speaker 0: this is a\u003C/p>\u003Cp>Speaker 1: nice segue because I just read it in the chat. Does it have to be solved dynamically on the fly? Question mark. I think the answer is yes, unfortunately, because it's based on the current user changes, so it's always have to be dynamic. Is it possible to require users to save the query somewhere, save like a SQL stored procedure kind of thing?\u003C/p>\u003Cp>If so, would that make it easier to resolve? Yes and no. I mean, it's again, because it's based on the current sexual users changes, we can't really have that prepared because you don't know what those changes will be. That being said, you know, if the item that you've just read, we could cache that for a little while. Right?\u003C/p>\u003Cp>The tricky bit is just when do you invalidate that cache? That's been a bit of an issue before, right, where right now we have to sort of auto purge the whole thing and it's kind of inefficient, which is a very high on my personal wish list item, but let's not psych sidetrack too much on that in this one. So so the the problem is we can cache that particular call to the database and just be like, oh, in the last, you know, 10 minutes, we already fetched this. It's probably the same. But if some other user changed it in between, you know, it gets a little bit tricky.\u003C/p>\u003Cp>But we could cache the database call for sure for sure. If so, would that make it easier to resolve? Yeah. It would make it a little bit faster. We still have the network latency though.\u003C/p>\u003Cp>Right? Even if the API would just respond immediately from all the caches and skips all the execution, just by the nature of it having to go over the Internet, you know, you might have your the the API that you're talking to might be in a different region or something that might be, you know, a 100 200 milliseconds latency just from that. And then it's just the experience is gonna suffer a lot. Like, a lot. Right?\u003C/p>\u003Cp>Yeah. To a point where, oh, I see our own team here in the chat mentioning a similar thing where it's like, maybe conditions should just not support fields you don't have the permissions to. Because that way, you know, all the commissions, because then then you have this issue where it has to be on the API side. Right? So maybe one of the requirements that we're learning here now is that it kinda has to be on the app just to be able to keep that instant, feedback loop going.\u003C/p>\u003Cp>And then to mention for conditions not to support fields you don't have permissions to though, you have to configure it on a sort of per role basis what those conditions are because only on the role do you know what fields are available in the condition, Which is true, although that makes configuration hack a lot more annoying. Because if you just have you know, I wanna show an email field when you click, subscribe to newsletter or something. Then now you have to reconfigure that for every single role. Right? Yeah.\u003C/p>\u003Cp>Chicken. There's always plan c, which is just aggressively saying no relational fields and conditions. That's kind of what we've been doing so far. You know? It it sucks.\u003C/p>\u003Cp>Speaker 2: Does Paul is does the new policy system maybe allow us some better flexibility so that it's not on a per role? It's configured, but\u003C/p>\u003Cp>Speaker 1: Oh, don't get me started.\u003C/p>\u003Cp>Speaker 2: But, again,\u003C/p>\u003Cp>Speaker 1: it's a lot of and no.\u003C/p>\u003Cp>Speaker 2: It does require, I think I think this I I think the the idea is this really has to be either real time in some way, you know, WebSockets implementation, the app itself. Goal longer term is to have that kind of capability anyway. But with a policy based, you know, if we are able to, you know, walk the conditional tree and we can we can see that and pull the data necessary. Now it might be that we wanna limit, you know, number of conditions that you can apply or number of levels deep you can go with a conditional. Right?\u003C/p>\u003Cp>Because I don't know that we can have an you know, the infinite depth capabilities. You know, I can go 18 levels deep in a condition that seems insane to kinda try and cash all that, or even manage\u003C/p>\u003Cp>Speaker 1: all that in front end.\u003C/p>\u003Cp>Speaker 2: But is it you know, maybe it's a 1 or a 2 level deep is what is allowed, from a conditional rules perspective kind of thing where it's manageable, controllable, and sustainable.\u003C/p>\u003Cp>Speaker 1: The the thing to me though when it comes to conditional fields, to me, that is more a form builder type of thing than an access control type of thing. So having to configure how the form behaves on a policy to policy basis feels hard to manage, if that makes sense. Because now you're the output form is just it's hard to expect what it's hard to know what to expect once you have, you know, multiple different policies doing multiple different things when it comes to form building. Now this is a complete sidebar. That's also the beauty of these sessions.\u003C/p>\u003Cp>Right? Divergent thinking.\u003C/p>\u003Cp>Speaker 0: Love it.\u003C/p>\u003Cp>Speaker 1: Here we go. Strap in, folks. It's there's there's another singer, Annette. See I see you nodding over there. But one thing that we have been sort of, you know, floating the idea of is this idea of, like, what if we decouple the data model from the form.\u003C/p>\u003Cp>Right? So it's decouple the actual actual how you interact with the data from the data model itself. So therefore, you could have multiple forms for the same database table. Right? And then in a policy or in a role or whatever, you would choose what is the form that we wanna use for this particular table, for this particular set of users.\u003C/p>\u003Cp>Because the one of the other known I mean, issues might be a bit of a big word, but one of the other downsides that I've on my personal wish list, it's kinda like if you have read access, we we show and hide fields that you'd expect. Right? You don't know that a field exists. It doesn't show up in the form. It also means that if you're doing a form building exercise where you have, like, multiple columns, like, 2 things side by side, and all of a sudden one disappears, you know, the form kind of reflows, but it it results in a bit of an unexpected state.\u003C/p>\u003Cp>Right? Mhmm. So by having, you know, that form, having that form decoupled from the data model, now you could just say, okay. We're gonna make a form that we know will look exactly like this. Like, what you see is what you get for the form or the role that we attach it to.\u003C/p>\u003Cp>This is, again, a way bigger discussion than just a little brain fart dumping out into the world here. But that is that is, you know, one of the ways around this because then you do have conditional fields per role or per policy group or whatever you wanna call it.\u003C/p>\u003Cp>Speaker 0: Alright. Many, many different things. I'm trying to I'm trying to find a way where we can, you know, like like, define a little pathway for us right now, but it's it's very hard because there's so much so many different things that we could do, technically. So yeah. Yeah.\u003C/p>\u003Cp>My initial feeling, like, when I read about this was, yeah, it sounds very reasonable, like, in the naive way, you know, the very naive, first understanding of the of the problem. Very similar or basically what you said in the beginning. Alright. So we do know when we open the form, what people used inside of the conditions. Alright.\u003C/p>\u003Cp>How about we then fetch those things, all of the related stuff to separately from the table? Alright. So far so good. Then the permission issue comes in. Alright.\u003C/p>\u003Cp>Are they allowed to read this? Yes. No. Alright. What do we do if they and, and then it gets tricky, and then it starts to spiral.\u003C/p>\u003Cp>Alright. Goddamn. Okay.\u003C/p>\u003Cp>Speaker 1: We got we got\u003C/p>\u003Cp>Speaker 0: a couple. Yeah. We we got a couple of steps that sound like alright. Alright. Maybe maybe yes.\u003C/p>\u003Cp>Yeah. And okay, permissions.\u003C/p>\u003Cp>Speaker 1: There's there's always the point where we could put limitations in place. Right? It's like, we like to think with the least amount of limitations as we can while keeping it fast. But to Tim's point earlier, we could make a line in the sand and say, okay. You know what?\u003C/p>\u003Cp>Nested relational data is only allowed if you have read access to those those data points. Otherwise, it's just not intended to work. Because that way, we can remove the server component, keep it on the app site, and make it work the way you'd expect to make it work fast. But we put a ceiling in place to make that happen. Right?\u003C/p>\u003Cp>That is a very real, a very real in between. I'm I'm still been noodling on that that idea that you had, Jonathan, to, like, could WebSockets potentially help with this? And the more I think about it, the more I'm like, maybe, just maybe. Because if that database call is heavily cached and we send, you know, a message of, like, here's the stage change ID such and such, and then the API will just respond as fast as it can with, like, the the combined change and the new form that comes out of that. If we can heavily cache it enough, we can make that work.\u003C/p>\u003Cp>Now I see Tim typing in the chat. I'm curious if he's gonna say the same thing. I knew it. That was exactly what I was gonna say. He put in the chat, WebSockets are great, but we cannot rely on them for stuff like this as they're not a hard requirement to run direct this.\u003C/p>\u003Cp>Speaker 2: Not yet.\u003C/p>\u003Cp>Speaker 0: And this is this is a\u003C/p>\u003Cp>Speaker 1: different question, of course. Like, should it be a hard requirement or not? Right? Because and this is again a a bit of a sidecar sidebar from from this, this particular discussion. Because the way we implement the WebSockets right now I mean, first and foremost, we haven't really used them in the app yet, for very similar reasons to this actually, which is, like, we have to be careful with relying on stuff, maybe, yes, no, and then tricky tricky.\u003C/p>\u003Cp>The the the real question is, you know, WebSockets are not supported everywhere like regular HTTP requests are. Right? So for example, there's there's a couple of platform as a service providers that just will not work with WebSockets in your container or something. Right? Because there's so many hoops you could jump through.\u003C/p>\u003Cp>You gotta go from, like, you know, the CDN to, like, some sort of load balancer to some sort of proxy container to some sort of, you know, container that has the actual connection. Yeah. And to to Tim's point in the chat now too, if you wanna do snazzy things on the edge, like scaling back to 0 containers or something, you cannot have a persistent connection at all. Right? Which is another very good point.\u003C/p>\u003Cp>I know there was another this another discussion thread that has seen some activity recently around, being able to run directives in a serverless environment, which, oh, boy, is a whole different session of one of these. I'm sure. But if that were ever, you know, a deployment target that we wanna officially support, then WebSockets are just out. They're just unavailable to rely on, right? And then the question really becomes like, okay, what what is more important to us supporting serverless environment scaling down to 0?\u003C/p>\u003Cp>Or are we gonna say, well, Directus is just a a a tool that is intended to be a long running server because with cron jobs and hooks and all that kind of stuff. And therefore, WebSockets are just enabled just like the API and you can use them and we can heavily rely on it in the app to make it faster and a better experience. Right? That is gonna be a difficult call to make, because it's it's it's, at the end of the day, a little bit of a subjective one. I know it's it's, we haven't really done all the pros and cons of research and all that kind of stuff.\u003C/p>\u003Cp>But it's like, you know, people have very strong opinions on this kind of stuff. Very strong opinions.\u003C/p>\u003Cp>Speaker 0: We have to be careful, with Tim. He probably has one of those.\u003C/p>\u003Cp>Speaker 1: Like, one of those nasty opinions.\u003C/p>\u003Cp>Speaker 0: One of these nasty, nasty opinions. Oh, no. No. No. No.\u003C/p>\u003Cp>Alright. Yeah. Yeah. With the angel emoji. Alright.\u003C/p>\u003Cp>So far so good. Then let's maybe, you know, do the little, exercise. Alright. Let's say we go down that route that we mentioned with alright. You can't put conditions on stuff that you can't read or that this specific user can't read.\u003C/p>\u003Cp>Alright. This would have a couple of repercussions. Right? Like, then alright. You have multiple different different user roles.\u003C/p>\u003Cp>Do you then, as an admin that is configuring this collection, do you want to? Probably not. But do you want to actually configure then these things between different roles all the time. That sounds like a big pain, to be honest. Like, very annoying.\u003C/p>\u003Cp>Would we? Yeah. I mean, we do have to attach it to some kind of role. Right? Because, as of right now, you know, there can be, like, unlimited different types of user roles.\u003C/p>\u003Cp>Yeah. And some of them can read those fields. Some of them don't. We don't know that. Would we like to share this then with some type of diffing between those?\u003C/p>\u003Cp>But oh, man. This this just sounds like spaghetti, like, the largest bowl of spaghetti that you can think of. Weird. It doesn't sound enticing to go down.\u003C/p>\u003Cp>Speaker 1: Yeah. I think the the the conflict that we're finding ourselves in is that we know you can configure conditions for fields that you might not have access to and then it doesn't work. Right? So what are we gonna do to help the admin user in that situation? Like, we need to educate them on this.\u003C/p>\u003Cp>We need to educate them on the, on the on the limitation there or show it somehow or prevent them from making that mistake in the first place by connecting it tightly to a role somehow. Because once you connect it tightly to a role, we know what fields are available, and we can only service those in the conditions. Right? Mhmm. I agree with your earlier sentiment when you were, like, configuring that on the role and having to reconfigure it for every single role that might access this thing feels like a nightmare.\u003C/p>\u003Cp>That feels like so much extra work. Mostly because and and I briefly touched on this before, but mostly because I really see this as a form building tool, not so much an access control thing. Right?\u003C/p>\u003Cp>Speaker 0: Yeah.\u003C/p>\u003Cp>Speaker 1: It's to me, it's similar that you wanna have 2 fields side by side. I wanna have one show up and hide based on the value of the other. That's that's all sort of form building magic, not so much access control magic. So I I kinda strongly feel like we don't wanna conflate those 2 and and put, like, too much form building stuff in access control. Because it Right.\u003C/p>\u003Cp>Speaker 0: It just makes me context. Yeah. Thanks. So, similarly alright. How about then we reverse this a little bit?\u003C/p>\u003Cp>So, let's say, as of right now, you know, the admin goes into the collection thingy into the conditions and configures, you know, how it's supposed to look like, all of the different conditions, you know, height depending on this checkbox, make the title red. And then we attach a roll to that filter and we can now check, you know, is this role can this role even apply this filter? And we can immediately just say, oh, no. This role is not compatible with this filter because it can't read x and y and z. And this would also solve, like, solve let's let's in big big big quotation marks, solve that problem of, you know, like, having multiple user problems having multiple user roles that you could, you know, just say, alright.\u003C/p>\u003Cp>But this filter is, yeah. I I'm already, like, thinking while I'm talking. So then you come into this whole thing. Alright. Maybe you want to have different conditions for different user roles.\u003C/p>\u003Cp>Maybe.\u003C/p>\u003Cp>Speaker 1: Here we are again.\u003C/p>\u003Cp>Speaker 0: Here we go. Here we go.\u003C/p>\u003Cp>Speaker 1: Love it. That's the moment where it starts spinning again. Tim, just in the chat, does not make sense to build your forms based on what fields you have access to? Which, yes, I think that is kinda closing closing in on the the sort of wild wicked idea of saying, what if you can just configure multiple different forms and you can just make a form that is dedicated to, you know, one one role? So that way you can you know for a fact that all the conditions exist and all the fields exist, and the way you configure the form and the layout is tailor made for that role because the only fields that exist are the ones that exist for the, for the item.\u003C/p>\u003Cp>Speaker 0: Yeah. I can I can feel I can already, like, feel the pain through just thinking about this of, you know, the then, like, synchronizing between different types of forms between different types of user roles and oh, man? It's getting it's getting a little bit of rough. Let's say let's say rough. Alright.\u003C/p>\u003Cp>Tim has another thing. You effectively already do that using access control as the form will not render fields you don't have access to. Yeah.\u003C/p>\u003Cp>Speaker 1: Which I think might become an issue at some point in the not too distant future. Because one other thing that we've sort of been been noodling about, Jetta the Jetta, is the idea of a little bit more flexible grit for forms. So right now, it's it's a 2. Right? You can either make a full width or you have 2 side by side.\u003C/p>\u003Cp>That's it. We also just been thinking about, like, what if we make that just a configurable number with some with some responsive breakpoints potentially. You could make it a 12 grid. You could make it in the 8 grid. Whatever.\u003C/p>\u003Cp>Right? At that point, if the field in in column number 6 disappears because of redexes, we cannot we can no longer sort of cleverly reflow it, to make sense. Right? Because now we legitimately just don't know where things are supposed to go anymore on the page because it just it it just has to be become a a gap, basically. At that point, we might end up having to just show, like, there used to be a field here, but you don't know about it.\u003C/p>\u003Cp>Right? Because otherwise, the whole form layout is\u003C/p>\u003Cp>Speaker 0: tell anyone.\u003C/p>\u003Cp>Speaker 1: Because otherwise, the form layout is just gonna look either broken because you're gonna end up with blank spots all over the place, or, you know, if if we're trying to I I think it's safe to say that we're trying to sort of reorganize it on the fly. It will break, because we just don't know what needs to go where at that point. Because it would be a multidimensional grid. Right? That will be 2 dimensional because you can have things go 2 rows or 2 columns, etcetera, and then you have a problem.\u003C/p>\u003Cp>Right? Kinda like, I think of dashboards basically in terms of just positioning stuff all over the place. But if we go that route, if if that ever comes to fruition, right, again, it's just a random thought. It's not actively being worked on or anything. But, if we're going in that direction, I think we need to have some sort of way to have a form per role anyways.\u003C/p>\u003Cp>Because otherwise, you know, you're gonna either have a form with a bunch of holes in it or with place holders that you're like, hee hee. You can't actually see this. Or, you know, or it just needs to be per role because that way you can just make one that is, you know, tailor made for for that particular role.\u003C/p>\u003Cp>Speaker 0: Well, whether or not, we're actually, you know, looking into this, we already have our first customer. Then he said, I'm sold on the option to build a form per roll.\u003C/p>\u003Cp>Speaker 1: So good.\u003C/p>\u003Cp>Speaker 0: Sold it already. It was fast.\u003C/p>\u003Cp>Speaker 2: I like it. So if we can inherit, like, a global so it inherits the the default kinda data model form that you configure, and then allow you to adjust that on the specific role, I think that's actually pretty freaking cool because we do have those kinds of use cases where, you know, this particular business and especially if we could apply specific conditionals on that form, it means that, you know, my business user versus my consumer user could have a very different form experience intentionally and different conditionals. Right? The the default conditional for the business user presets those conditions and organization. I I kinda love the idea.\u003C/p>\u003Cp>Whether or not again, this this comes back to whether or not this actually we we decide to allow additional depth, you know, conditionals. Just having that particular feature seems kind of amazing. As long as we can inherit the default, then if I don't need that kind of capability, I can just use the default and manage the default that we'll get. If I've got a custom reason for adjusting the form. Pretty brilliant.\u003C/p>\u003Cp>I like it.\u003C/p>\u003Cp>Speaker 0: So there's a question by Benny Wade. Could we make groups configurable per row rather than making a whole form per row? Keep it a bit more modular.\u003C/p>\u003Cp>Speaker 1: AKA, can we nest these forms?\u003C/p>\u003Cp>Speaker 0: Yeah. That that Let's\u003C/p>\u003Cp>Speaker 1: check as we check-in with our friend v form and see how he feels about it.\u003C/p>\u003Cp>Speaker 0: -Oh, boy. Can't wait. Guys, if you enjoy\u003C/p>\u003Cp>Speaker 1: messaging, please. Where you have the forms that or the view of the page or whatever you wanna call it is the same for everybody, but then you just have a section where it's like this section only shows up for x role. Right? Could be interesting. That is a conditional field in and of itself, of course, where it's like, the condition is show or hide this thing if current role is x y z.\u003C/p>\u003Cp>Right? Which now I'm thinking about it. I'm pretty sure that exists. Present time. I'm pretty sure you can this is something I'll have to test, actually, because I know we have those dynamic variables for current user and current role in those.\u003C/p>\u003Cp>I don't remember if we support those in conditional fields. Because if we do, you can step a group and have a conditional field on the group that says current role equals x y z and then hide the whole group. We do not,\u003C/p>\u003Cp>Speaker 0: Tim. Tim and a chat. Why not? Why not?\u003C/p>\u003Cp>Speaker 1: He calls me out he calls me out on my bluff. It's happens happens sometimes. Yeah. But that would theoretically be a a soul for the same thing, though. Right?\u003C/p>\u003Cp>Or you could just say the whole group is hidden for a role, and therefore, no problem. You make it so that you can have the same field in different presentation section configured per role? Right. Right. So the same field multiple times.\u003C/p>\u003Cp>Yeah. That is that is another thing when it comes to dynamic form building and, just full stop dynamic form building at that point. Right? Because right now, the form is data model first. It's like you have a title field, therefore, you can now have a title input because it's 1 to 1 to the data model.\u003C/p>\u003Cp>Right? With a form building thing, maybe you have 2 title fields, like, 2 fields that point to the same underlying data thing. Right? There's instinct. I don't know why the hell you would do that, but you could.\u003C/p>\u003Cp>For for some interface, it may set I mean, in this this example where it's like you have the same field in different sections and the section show and hide based on the role, it starts to make sense again. I for admin users, it'd be interesting, but it it yeah. For sure. Then for, I I think there's a a definite interesting use case for certain data types where it would help to have multiple fields, multiple visual fields for the same underlying column. Think about, like, an address interface face or something.\u003C/p>\u003Cp>Right? Where you wanna have address line 1, 2, and then, ZIP code and all that kind of stuff, but you wanna save it as one field in your data model. Not super uncommon, or as a let long sort of search thing, right, where you have a let and a long input and then an address field, and those are all connected. So you can type in an address and it'll geo look up the let long, but then the thing that's saved in the database is just the let long. So there's definitely, you know, some additional things that we unlock with that sort of modular form idea.\u003C/p>\u003Cp>Right?\u003C/p>\u003Cp>Speaker 0: Alright. So what I gathered from this, is that we're basically about to build our own page building framework where we can dynamically close plugs. So we're basically set, you know? Like, director's page building, that sounds like a great idea. Okay.\u003C/p>\u003Cp>On the\u003C/p>\u003Cp>Speaker 1: So just to solve condition fields. That's that's the beauty of it, isn't it? How did we how did we get here for just solving nested conditional fields?\u003C/p>\u003Cp>Speaker 0: Yeah. It all started so innocently. You know?\u003C/p>\u003Cp>Speaker 1: It's true.\u003C/p>\u003Cp>Speaker 0: I just want to hide a field, and now we're basically embarking on a mission to\u003C/p>\u003Cp>Speaker 1: Okay. This is this is actually this is a good thing because this is a perfect example of the sort of, you know, request review session. For those who've been here before, you've seen this happen before. It's like we go completely off the rails in all directions, and then now let's try to see how we can actually get this back on track for nested conditional fields. Right?\u003C/p>\u003Cp>So as a you know, in a potential future utopia where you can just magically conquer up any sort of form, any sort of view that you possibly want. Great. But as of right now, I'm kind of thinking, based on everything that we talked about so far, it, to me, makes the most sense to follow Tim's suggestion from earlier, which is basically you cannot put the field and conditional fields that the user does not have read access to. Right? I think that is that is a safe call.\u003C/p>\u003Cp>I think doing it on the API side, we're never gonna be able to get it just performant enough, and we don't really wanna make WebSockets a requirement for this to work. So I think as of today, you know, what can we actually achieve in the next month or 3? We would most likely keep the client side, keep it fast so we can do all the calculations on the client. It has to be from current fields that you have read access to. The main difference that we have to do is that we have to dynamically, when you open the page the first time, we have to load up what is the nested data structure of this item based on the rules used in conditional fields.\u003C/p>\u003Cp>And then have some sort of utility function that can cleverly combine the stage changes on top of that. Right? We have to account for the differences like many to one ID versus nested object. We have to account for things like the one to many update structure versus array. But that that way, we can merge that and we can do a client side.\u003C/p>\u003Cp>Right? I don't think we should do that per role. That just feels like a nightmare to configure, to be completely honest.\u003C/p>\u003Cp>Speaker 0: Yeah. And\u003C/p>\u003Cp>Speaker 1: a lot of a lot of duplication. Again, in a utopic utopic utopic? Utopia stick future. Utopia like future. Utopian?\u003C/p>\u003Cp>Utopian future, you know, where you have more of this flexible form idea. At that point, you know, you can say, okay, When someone I'm already boring Jonathan to death, I see. When when you open this this page for this particular role, we use form xyz instead but that is again a way way future discussion. But then I think, you know, we can support the core ask for this this feature request, which is if I say nested author dot name, I expect that the lookup, what is the name of the nested author no matter what. If I select an existing one, it needs to look at the name of the existing one.\u003C/p>\u003Cp>If I change somebody's name, it needs to look at the changed name. Right? That is something that we can I'm pretty hopeful we can turn that into some sort of usability function that we can run relatively quickly on the client side and make this happen. Right?\u003C/p>\u003Cp>Speaker 0: Yeah. That shouldn't be shouldn't be impossible. Yeah. Yeah. Look at the from Natron.\u003C/p>\u003Cp>Speaker 1: And 10 rabbits with 1 multiracial conditional stone. Yeah. Exactly. As an admin that's configuring these conditional fields to another person in the chat, it would be nice to see the whole form that a person with a given role would see. Maybe a view as role option somewhere.\u003C/p>\u003Cp>Fully a 100% agree. To Jonathan's point, there's another feature request about that user impersonation. Again, very high on my personal, wish list. Right? I would love it as an admin.\u003C/p>\u003Cp>And not so not just for the for the particular form and settings or something. I really want there to be a way for admins to just say, browse the whole app, impersonating a different role so that you can just click around and see exactly what that user can see and do. Right? From a visual perspective, we'll probably have to have some sort of banner, zoom out a little bit or whatever. We'll figure it out what that looks like.\u003C/p>\u003Cp>But that way, you can just configure it, see the whole thing as, you know, that particular user. Now especially dreaming wish list, it'd be great if you could just change the form while you're on the page looking at what the form looks like for that given your role. But let's I'll get ahead of ourselves.\u003C/p>\u003Cp>Speaker 0: We're going back. We're going back, guys. Back to the page.\u003C/p>\u003Cp>Speaker 1: We're spinning. We're spinning again. We're spinning again. Let's not spin too much. Yeah.\u003C/p>\u003Cp>But no. That's a it's it is a very good idea because also with the other feature request that we talked about. Was it last time or not too long ago where we're talking about the rules and permissions as a whole. Right? And these policy units and whatnot.\u003C/p>\u003Cp>Now that these policies become way more composable, buzzword shot, we can actually you you also have the problem that it becomes a little bit harder to figure out what is the actual permission for this one user now. Right? Because it could come from multiple different places and you can have on the user overrides and that kind of stuff. So I think user impersonation becomes way more important, with that in mind as well.\u003C/p>\u003Cp>Speaker 0: Great. Let's see. We caught up to the chat. If anyone has any last questions, please let us know. There's not much time left.\u003C/p>\u003Cp>I was running out. Just the the call to action, you know, just to get them going.\u003C/p>\u003Cp>Speaker 1: Yeah. Just a moment. Please like and subscribe.\u003C/p>\u003Cp>Speaker 0: Yeah. Yeah. Yeah. Yeah.\u003C/p>\u003Cp>Speaker 1: Hit that notification bell so you'll stay up to date.\u003C/p>\u003Cp>Speaker 0: But if you truly want to stay up to date, you should head to direct us dot io/tv. I I nearly said dot tv. Yeah. Alright. No.\u003C/p>\u003Cp>But seriously, on the directors dot iotv, there's lots of interesting series that you can check out, such as this one and also other ones. And enjoy. And\u003C/p>\u003Cp>Speaker 2: see how Directus TV was built on Directus. Very cool. It's exciting.\u003C/p>\u003Cp>Speaker 1: That is pretty cool.\u003C/p>\u003Cp>Speaker 0: We have Jeron to join literally in the last minute. Hey there.\u003C/p>\u003Cp>Speaker 1: Hey there. Thank you for joining. How you doing? We're about to call it. Goodbye.\u003C/p>\u003Cp>Speaker 2: Anyway. Very, very exciting.\u003C/p>\u003Cp>Speaker 1: As always, thank everybody so much for watching. This was yet another talk where I was, like, going into it, it's like, oh, this feels like a small little bug that we could just fix. Right? And then we talk about it now, and I'm like, oh, man. Okay.\u003C/p>\u003Cp>Speaker 0: It deep go. Building a form builder and page builder. Now now\u003C/p>\u003Cp>Speaker 1: we're getting snazzy with it. But that's that's the beauty of these sessions, and I love it every time. So those are joining. Thank you so much. See you guys in 2 weeks from now.\u003C/p>\u003Cp>Or oh, no. Wait. That's the one that we're skipping for the, you know, the special week week. Yep.\u003C/p>\u003Cp>Speaker 2: It'll be, 4 weeks before our next one, folks. Thanks so much. Appreciate your patience. There's some big announcements coming that that this next week's time or next 2 week time slot is gonna be consumed with other events, and keep an eye out for the live events and things going on that week. So very exciting announcements on the way.\u003C/p>\u003Cp>We're we're excited to have such an awesome community. Have a great day. Have a great week.\u003C/p>","Love it all. Yeah. Hello. Welcome everybody once again. Thank you for joining us again in our biweekly, bi monthly. I always forget the difference between the 2, but they're also interchangeable. Our bimonthly, twice a month, session where we go over, you know, feature requests and try to go in deep, find all of the edge cases, think about everything that we possibly wanna support ever of the universe, and then bring it back down to number 42. Today, we're talking about supported nested relational values in conditional fields, which feels like a, oh, just support nested relational values. Easy. Until you start thinking about it for real, which is what we're gonna do today, and realize that it's probably not as easy as it sounds because that seems to be far from the course for these sessions. As it always So before we dive in on the every single time, before we get in too deep on the technical problems, you wanna, outline what what this is all about, Daniel? Yes. So, just for anyone that has not used this feature before, it's pretty, I think it's pretty niche. I mean, I have not extensively used it in the past, but, a little bit here and there. And I think lots of people, share this experience. But, if if you use this feature, conditional fields, you will eventually run into this little problem. So it is about the ability to conditionally render, for example, or hide or show or change fields inside of your collection edit or your item edit page depending on other fields. So you open up an item and you have a couple of groups depending on how much information there is inside of your item. It might be useful for you as a user or for, you know, to make it easier for actual users of your directus instance to hide a couple of fields, for example, so lessen the, you know, initial information overload, for example. Or you could also make use of it to actually enhance the visual, the the user experience. There's lots of stuff that you can do. Also, you know, require different fields if a different field has a specific condition, if it meets a specific condition. So lots of interesting stuff that you can do and, like, really, really customize how your editing experience looks, how it feels, and improve it for your users. And, so this is just the overall, like, high level description of what this does. But this issue that has been opened for a little bit, a little tiny, tiny, tiny while. So, it is about this exact scenario. So where you want a field to have a new, let let's say you want to hide something depending on if this item has some type of property in in a relation. I don't think I, describe this very well. But, so you want the to apply these conditions depending on some nested property. And this currently is a little bit tricky, for us because this stems stems from an architecture standpoint, like, how our forms work as of right now. So this is not like, you know, we're just missing a little if statement maybe, and then we could enable this. It's a little bit more more involved, but we'll explore this a little bit. So, yeah, this is what this issue is about. You want to, you know, conditionally style or, you know, change your existing fields depending on the nested property. And it's currently a little problematic because if you open up a form or your item page, I mean, we currently do not load every single nested relation because, you know, that it could be bad. It could be good. It could be bad depending on how large your item is. So, technically, if you open up your item page, we do not have that type of information as of right now. So you can't actually apply conditions because we don't have that information inside of the form, which is the root of the problem. So how do we fix that? Good question. Problem number 2 is we might not even have access to the info that you're trying to use, which makes this a heck of a lot more tricky to think. Yeah. Tack tack on permissions, and suddenly this gets very, very complicate. I mean and how deep is this? Right? So in my case, right, where many to any, this can this, I've seen clients with anywhere from 5 to 18 levels deep in this relational model. How much data do you load up into the current view? Right? This can get very first, Gary, you know, this can get a little bit of hands in from the chat. You know? Let's involve the chat a little bit. So So just to just to summarize this to, those three main Please, let's problems at first. Right? So right now, those conditional fields are just using the information that is visible on the form, right, with the edits applied because it needs to be reactive to what the user does. Then once you go relationally deep, we have a bit a problem because that information just doesn't exist in the context of that page at present time. Right? So that in and of itself could be easy enough by saying, okay. Let's just fetch all of the paths that are used within the conditional fields, and then at least we have that data. But we fetch it separately from the actual form content just for conditional fields purposes. That would solve part of this. Right? But then the second problem that makes that part a little tricky is that we have to merge it with the edits made by the user in the form. Right? So now we're dealing with differences in data types and how you configure them, which is one of the the sort of bigger the the second issue. Because theoretically speaking, you know, conditional fields check against the staged value of the form. So therefore, if you select, you know, a many to one item, you could check against the ID that you have selected. If you make a nested update, you could theoretically, through the rules, check for the nested value and and change it. The difficulty is, like, if you select an existing item, now the data that is staged is just a UUID. Right? It's not a nested object of values. So if your conditional field says, author names or nested name and author has to be reg, then it becomes tricky if you select the existing author because now you're checking the rule is nested field name has to be reg, but you're checking it against the u a d string. Right? Because that's the actual data that you're about to save. So that's that's another big big mismatch there. And that problem compounds the further down you go, obviously. Right? So the other thing is when you update, a one to many, we have that difference in syntax where you can provide an array of all the items or you can provide, you know, the create update, delete statements individually, which is what the app uses because it's still easier to manage for larger datasets. But that again also means that you now have to check against 2 data types and it works a little bit unlike you would expect. Right? That's kind of the the the TLDR for this. The 3rd major issue is permissions. Right? So as an administrator, you could set hide, a certain set of fields if a hidden field for this user, like, that's something they can't see is enabled or disabled, which for the end user is invisible and therefore the app can't actually run the check against it because it doesn't even know that the field exists. Right? So that needs a totally different solution where the check doesn't even happen on the app client side. The check happens on the server side. So it can check against data that the client user might not even have access to in the first place. Right? So those are the 3 major sort of problem spaces that we have with this particular feature. All of which need some sort of specialized solution for conditional fields. And hopefully, we can find some sort of direction that is 1, you know, one endpoint that rule them all, so to speak. That's a top order. I guess. We we have some interactions. Yeah. Exactly. So we have a little bit of chat. How about having a field, that just show calculated data from other columns? So it's not a column in a database, a column just for showing some calculation. So if I'm understanding correctly, to summarize that, what we're saying is instead of trying to use the nested values like an actual nest of the tree, why not have one alias field that just pulls up the relevant bit of data? So it's always just the string name, for example, from an author, and then you can conditional fields against that. Right? So instead of trying to dynamically do it against the whole tree, you're just pulling out the data that's relevant, and then the conditional fields check only runs on the top level. Alright. But lots to think about. There we go. I've done it in. Fit this problem before, so what I do is to just create another extra foreign key. It can be used to filter the current items onto many drop down. Problem is that the user need to do another selection to enable this filtering. That's kind of a similar idea. Right? Yeah. Where it's like instead of trying to nest it deeply, you just pull the value back up in some sort of way, either automatically or by having the user chip choose it, and then you operate against the static value of that field. Now the the interesting thing here is that one of the problems that we're seeing is that the way it works technically makes sense. Right? You you validate the conditions against whatever the third stage value is with the user's changes applied. Where it falls on its face is that the expectation is that it will do nested relational lookups and then dynamically apply the changes in that tree and then check against that. Right? So that could potentially solve for the first two. Right? Where we're saying, okay. We can make some sort of utility function that says, what is the conditional field rule? What data do we need for that? Then apply the current edits on top of that in a way that fits the model, right, the model for the conditional fields. So, therefore, if you selected an an ID for many to 1, we have to go fetch the nested data for that so not the permission. I saw it on the screen. It's in a different order now. So it's for the the app data context and then the nested relationships. For the permissions piece, though, we have an issue. Right? Because at the, like, the end of the day, we cannot run that in the app. That's that's basically the long story short. So those for for those who have been eyeing the GitHub repo like a hawk, there was actually a PR not too long ago with an issue, in a in a similar vein, but about the permission checks. Right? So some users were running into some issues where the application would allow you to change fields that you didn't have update permission to, for that exact reason because the update permissions were using a field that the app cannot read because you didn't have read permissions to those fields. So, therefore, the app couldn't know if you had access or not. So it would just default to, like, okay. You can do it. And then once you hit save, the API would just throw an error and be like, no. You cannot do it actually. Right? The way we solved for that is with a new endpoint in the API that basically say, hey. For the current user, am I able to update this particular item in this particular collection? Right? And it will return, like, these are the fields that you can edit, as far as I understand. I I'm a little hazing the execs, you know, IO, but that is effectively the gist of it. Right? And it feels like It feels like this feature will probably go in a very similar direction, where we need to have some sort of API endpoint where the app can say, okay. Here's the current about to be safe changes. For the for the current user, what should the conditional state be, I guess? Right? Because that's the only way. If the the app cannot read fields that are used in the conditions, it's kinda game over. Right? However Interesting. How how would how would that endpoint look like? Like, what type of payload how would that translate all of the different requirements that we have? Interesting. So I'd imagine I I know the requirements generally are, a, we need to fetch all of the data that is used in the, conditional fields rules. Right? So we just have to look up what are all the fields and what is the whole tree that is used within the conditional fields and fetch just those in the exact same structure so so we can run the checks against it. Right? Then we need to dynamically apply all of the staged changes from the user because one very important use case for conditional fields is things like, you know, you click a toggle and you show and hide fields conditionally. Right? That's kind of one of the major use cases for this. So it needs to be real time. And then the last thing right now, I'm pretty sure that's, it just returns. I I think what we do right now is we effectively just loop over and and then merge the field's configuration for the current item with the conditional field result, sort of smash them together. Right? So if, like, the default field is hidden in your conditional fields, you have field that's visible, then that takes precedence, and we merge them together by by field key. Right? So we dynamically update the area of fields that exist within the form based on that logic. So to translate that into an endpoint, you would most likely have to have an endpoint that takes what collection are we in, what item are we in, because that might affect, you know, the the IDs and all that kind of stuff. And then what is the changes that you've currently made so we can dynamically merge those and then do all of that logic on the server side and effectively return a new list of fields that should be visible in the app. Right? That's theoretically possible. Tricky thing, performance. Right? It it is exactly. Like, I was already, like like, inhaling and just to, you know, finish your sentence so I can say that. Exactly. So, yeah, that that would probably then lead to, you know, some delay because, let's say, you type a name pretty quickly, you know, like, example, whatever. Now you made, like, I don't know, 6, 7, 8, whatever it is that you're typing. The key presses, alright, do we debounce those? Then, alright, we have another little delay. So we then have to contact the API, which gets the stuff back, and then we have another little delay. And then the whole experience might suffer depending on how exactly we do it. Because, like, even if we now if we now, start, like, debouncing, that could lead to other problems. You know? Like, if if we want something to change, if the the the the text field contains a specific substring or something. Yeah. Then then that won't trigger fast enough, basically, which, you know, is kinda not the point. That is that's really hitting it on the head because this has to be you click a toggle, stuff shows up. That's that's the goal. Right? So it needs to be immediate and interactive. So if you debounce it for a second or something, to your point, the experience is gonna suck because you click a button and then Yeah. You're already looking somewhere else and then magically stuff shows up. Right? This, it's instant. Right? Because the app has all the context and data and permissions and things that it needs, so this is instantaneous for this to show or hide. Mhmm. You know, make required, do whatever. The the toggle here, the app side is doing all that, and it's almost instantaneous where you go server side now if you're having to send back to server. I'm wondering, does WebSockets' real time kinds of capabilities help at all in this space if we work towards I mean, again, we've always wanted to make the app real time so that we can do, you know, multi multi user editing of records and things. Yeah. I think, realistically, the main it it would reduce the network latency a little bit, but I think the main time spent on this is re fetching the existing item data and then merging on the changes. Right? Now this is a nice segue because I just read it in the chat. Does it have to be solved dynamically on the fly? Question mark. I think the answer is yes, unfortunately, because it's based on the current user changes, so it's always have to be dynamic. Is it possible to require users to save the query somewhere, save like a SQL stored procedure kind of thing? If so, would that make it easier to resolve? Yes and no. I mean, it's again, because it's based on the current sexual users changes, we can't really have that prepared because you don't know what those changes will be. That being said, you know, if the item that you've just read, we could cache that for a little while. Right? The tricky bit is just when do you invalidate that cache? That's been a bit of an issue before, right, where right now we have to sort of auto purge the whole thing and it's kind of inefficient, which is a very high on my personal wish list item, but let's not psych sidetrack too much on that in this one. So so the the problem is we can cache that particular call to the database and just be like, oh, in the last, you know, 10 minutes, we already fetched this. It's probably the same. But if some other user changed it in between, you know, it gets a little bit tricky. But we could cache the database call for sure for sure. If so, would that make it easier to resolve? Yeah. It would make it a little bit faster. We still have the network latency though. Right? Even if the API would just respond immediately from all the caches and skips all the execution, just by the nature of it having to go over the Internet, you know, you might have your the the API that you're talking to might be in a different region or something that might be, you know, a 100 200 milliseconds latency just from that. And then it's just the experience is gonna suffer a lot. Like, a lot. Right? Yeah. To a point where, oh, I see our own team here in the chat mentioning a similar thing where it's like, maybe conditions should just not support fields you don't have the permissions to. Because that way, you know, all the commissions, because then then you have this issue where it has to be on the API side. Right? So maybe one of the requirements that we're learning here now is that it kinda has to be on the app just to be able to keep that instant, feedback loop going. And then to mention for conditions not to support fields you don't have permissions to though, you have to configure it on a sort of per role basis what those conditions are because only on the role do you know what fields are available in the condition, Which is true, although that makes configuration hack a lot more annoying. Because if you just have you know, I wanna show an email field when you click, subscribe to newsletter or something. Then now you have to reconfigure that for every single role. Right? Yeah. Chicken. There's always plan c, which is just aggressively saying no relational fields and conditions. That's kind of what we've been doing so far. You know? It it sucks. Does Paul is does the new policy system maybe allow us some better flexibility so that it's not on a per role? It's configured, but Oh, don't get me started. But, again, it's a lot of and no. It does require, I think I think this I I think the the idea is this really has to be either real time in some way, you know, WebSockets implementation, the app itself. Goal longer term is to have that kind of capability anyway. But with a policy based, you know, if we are able to, you know, walk the conditional tree and we can we can see that and pull the data necessary. Now it might be that we wanna limit, you know, number of conditions that you can apply or number of levels deep you can go with a conditional. Right? Because I don't know that we can have an you know, the infinite depth capabilities. You know, I can go 18 levels deep in a condition that seems insane to kinda try and cash all that, or even manage all that in front end. But is it you know, maybe it's a 1 or a 2 level deep is what is allowed, from a conditional rules perspective kind of thing where it's manageable, controllable, and sustainable. The the thing to me though when it comes to conditional fields, to me, that is more a form builder type of thing than an access control type of thing. So having to configure how the form behaves on a policy to policy basis feels hard to manage, if that makes sense. Because now you're the output form is just it's hard to expect what it's hard to know what to expect once you have, you know, multiple different policies doing multiple different things when it comes to form building. Now this is a complete sidebar. That's also the beauty of these sessions. Right? Divergent thinking. Love it. Here we go. Strap in, folks. It's there's there's another singer, Annette. See I see you nodding over there. But one thing that we have been sort of, you know, floating the idea of is this idea of, like, what if we decouple the data model from the form. Right? So it's decouple the actual actual how you interact with the data from the data model itself. So therefore, you could have multiple forms for the same database table. Right? And then in a policy or in a role or whatever, you would choose what is the form that we wanna use for this particular table, for this particular set of users. Because the one of the other known I mean, issues might be a bit of a big word, but one of the other downsides that I've on my personal wish list, it's kinda like if you have read access, we we show and hide fields that you'd expect. Right? You don't know that a field exists. It doesn't show up in the form. It also means that if you're doing a form building exercise where you have, like, multiple columns, like, 2 things side by side, and all of a sudden one disappears, you know, the form kind of reflows, but it it results in a bit of an unexpected state. Right? Mhmm. So by having, you know, that form, having that form decoupled from the data model, now you could just say, okay. We're gonna make a form that we know will look exactly like this. Like, what you see is what you get for the form or the role that we attach it to. This is, again, a way bigger discussion than just a little brain fart dumping out into the world here. But that is that is, you know, one of the ways around this because then you do have conditional fields per role or per policy group or whatever you wanna call it. Alright. Many, many different things. I'm trying to I'm trying to find a way where we can, you know, like like, define a little pathway for us right now, but it's it's very hard because there's so much so many different things that we could do, technically. So yeah. Yeah. My initial feeling, like, when I read about this was, yeah, it sounds very reasonable, like, in the naive way, you know, the very naive, first understanding of the of the problem. Very similar or basically what you said in the beginning. Alright. So we do know when we open the form, what people used inside of the conditions. Alright. How about we then fetch those things, all of the related stuff to separately from the table? Alright. So far so good. Then the permission issue comes in. Alright. Are they allowed to read this? Yes. No. Alright. What do we do if they and, and then it gets tricky, and then it starts to spiral. Alright. Goddamn. Okay. We got we got a couple. Yeah. We we got a couple of steps that sound like alright. Alright. Maybe maybe yes. Yeah. And okay, permissions. There's there's always the point where we could put limitations in place. Right? It's like, we like to think with the least amount of limitations as we can while keeping it fast. But to Tim's point earlier, we could make a line in the sand and say, okay. You know what? Nested relational data is only allowed if you have read access to those those data points. Otherwise, it's just not intended to work. Because that way, we can remove the server component, keep it on the app site, and make it work the way you'd expect to make it work fast. But we put a ceiling in place to make that happen. Right? That is a very real, a very real in between. I'm I'm still been noodling on that that idea that you had, Jonathan, to, like, could WebSockets potentially help with this? And the more I think about it, the more I'm like, maybe, just maybe. Because if that database call is heavily cached and we send, you know, a message of, like, here's the stage change ID such and such, and then the API will just respond as fast as it can with, like, the the combined change and the new form that comes out of that. If we can heavily cache it enough, we can make that work. Now I see Tim typing in the chat. I'm curious if he's gonna say the same thing. I knew it. That was exactly what I was gonna say. He put in the chat, WebSockets are great, but we cannot rely on them for stuff like this as they're not a hard requirement to run direct this. Not yet. And this is this is a different question, of course. Like, should it be a hard requirement or not? Right? Because and this is again a a bit of a sidecar sidebar from from this, this particular discussion. Because the way we implement the WebSockets right now I mean, first and foremost, we haven't really used them in the app yet, for very similar reasons to this actually, which is, like, we have to be careful with relying on stuff, maybe, yes, no, and then tricky tricky. The the the real question is, you know, WebSockets are not supported everywhere like regular HTTP requests are. Right? So for example, there's there's a couple of platform as a service providers that just will not work with WebSockets in your container or something. Right? Because there's so many hoops you could jump through. You gotta go from, like, you know, the CDN to, like, some sort of load balancer to some sort of proxy container to some sort of, you know, container that has the actual connection. Yeah. And to to Tim's point in the chat now too, if you wanna do snazzy things on the edge, like scaling back to 0 containers or something, you cannot have a persistent connection at all. Right? Which is another very good point. I know there was another this another discussion thread that has seen some activity recently around, being able to run directives in a serverless environment, which, oh, boy, is a whole different session of one of these. I'm sure. But if that were ever, you know, a deployment target that we wanna officially support, then WebSockets are just out. They're just unavailable to rely on, right? And then the question really becomes like, okay, what what is more important to us supporting serverless environment scaling down to 0? Or are we gonna say, well, Directus is just a a a tool that is intended to be a long running server because with cron jobs and hooks and all that kind of stuff. And therefore, WebSockets are just enabled just like the API and you can use them and we can heavily rely on it in the app to make it faster and a better experience. Right? That is gonna be a difficult call to make, because it's it's it's, at the end of the day, a little bit of a subjective one. I know it's it's, we haven't really done all the pros and cons of research and all that kind of stuff. But it's like, you know, people have very strong opinions on this kind of stuff. Very strong opinions. We have to be careful, with Tim. He probably has one of those. Like, one of those nasty opinions. One of these nasty, nasty opinions. Oh, no. No. No. No. Alright. Yeah. Yeah. With the angel emoji. Alright. So far so good. Then let's maybe, you know, do the little, exercise. Alright. Let's say we go down that route that we mentioned with alright. You can't put conditions on stuff that you can't read or that this specific user can't read. Alright. This would have a couple of repercussions. Right? Like, then alright. You have multiple different different user roles. Do you then, as an admin that is configuring this collection, do you want to? Probably not. But do you want to actually configure then these things between different roles all the time. That sounds like a big pain, to be honest. Like, very annoying. Would we? Yeah. I mean, we do have to attach it to some kind of role. Right? Because, as of right now, you know, there can be, like, unlimited different types of user roles. Yeah. And some of them can read those fields. Some of them don't. We don't know that. Would we like to share this then with some type of diffing between those? But oh, man. This this just sounds like spaghetti, like, the largest bowl of spaghetti that you can think of. Weird. It doesn't sound enticing to go down. Yeah. I think the the the conflict that we're finding ourselves in is that we know you can configure conditions for fields that you might not have access to and then it doesn't work. Right? So what are we gonna do to help the admin user in that situation? Like, we need to educate them on this. We need to educate them on the, on the on the limitation there or show it somehow or prevent them from making that mistake in the first place by connecting it tightly to a role somehow. Because once you connect it tightly to a role, we know what fields are available, and we can only service those in the conditions. Right? Mhmm. I agree with your earlier sentiment when you were, like, configuring that on the role and having to reconfigure it for every single role that might access this thing feels like a nightmare. That feels like so much extra work. Mostly because and and I briefly touched on this before, but mostly because I really see this as a form building tool, not so much an access control thing. Right? Yeah. It's to me, it's similar that you wanna have 2 fields side by side. I wanna have one show up and hide based on the value of the other. That's that's all sort of form building magic, not so much access control magic. So I I kinda strongly feel like we don't wanna conflate those 2 and and put, like, too much form building stuff in access control. Because it Right. It just makes me context. Yeah. Thanks. So, similarly alright. How about then we reverse this a little bit? So, let's say, as of right now, you know, the admin goes into the collection thingy into the conditions and configures, you know, how it's supposed to look like, all of the different conditions, you know, height depending on this checkbox, make the title red. And then we attach a roll to that filter and we can now check, you know, is this role can this role even apply this filter? And we can immediately just say, oh, no. This role is not compatible with this filter because it can't read x and y and z. And this would also solve, like, solve let's let's in big big big quotation marks, solve that problem of, you know, like, having multiple user problems having multiple user roles that you could, you know, just say, alright. But this filter is, yeah. I I'm already, like, thinking while I'm talking. So then you come into this whole thing. Alright. Maybe you want to have different conditions for different user roles. Maybe. Here we are again. Here we go. Here we go. Love it. That's the moment where it starts spinning again. Tim, just in the chat, does not make sense to build your forms based on what fields you have access to? Which, yes, I think that is kinda closing closing in on the the sort of wild wicked idea of saying, what if you can just configure multiple different forms and you can just make a form that is dedicated to, you know, one one role? So that way you can you know for a fact that all the conditions exist and all the fields exist, and the way you configure the form and the layout is tailor made for that role because the only fields that exist are the ones that exist for the, for the item. Yeah. I can I can feel I can already, like, feel the pain through just thinking about this of, you know, the then, like, synchronizing between different types of forms between different types of user roles and oh, man? It's getting it's getting a little bit of rough. Let's say let's say rough. Alright. Tim has another thing. You effectively already do that using access control as the form will not render fields you don't have access to. Yeah. Which I think might become an issue at some point in the not too distant future. Because one other thing that we've sort of been been noodling about, Jetta the Jetta, is the idea of a little bit more flexible grit for forms. So right now, it's it's a 2. Right? You can either make a full width or you have 2 side by side. That's it. We also just been thinking about, like, what if we make that just a configurable number with some with some responsive breakpoints potentially. You could make it a 12 grid. You could make it in the 8 grid. Whatever. Right? At that point, if the field in in column number 6 disappears because of redexes, we cannot we can no longer sort of cleverly reflow it, to make sense. Right? Because now we legitimately just don't know where things are supposed to go anymore on the page because it just it it just has to be become a a gap, basically. At that point, we might end up having to just show, like, there used to be a field here, but you don't know about it. Right? Because otherwise, the whole form layout is tell anyone. Because otherwise, the form layout is just gonna look either broken because you're gonna end up with blank spots all over the place, or, you know, if if we're trying to I I think it's safe to say that we're trying to sort of reorganize it on the fly. It will break, because we just don't know what needs to go where at that point. Because it would be a multidimensional grid. Right? That will be 2 dimensional because you can have things go 2 rows or 2 columns, etcetera, and then you have a problem. Right? Kinda like, I think of dashboards basically in terms of just positioning stuff all over the place. But if we go that route, if if that ever comes to fruition, right, again, it's just a random thought. It's not actively being worked on or anything. But, if we're going in that direction, I think we need to have some sort of way to have a form per role anyways. Because otherwise, you know, you're gonna either have a form with a bunch of holes in it or with place holders that you're like, hee hee. You can't actually see this. Or, you know, or it just needs to be per role because that way you can just make one that is, you know, tailor made for for that particular role. Well, whether or not, we're actually, you know, looking into this, we already have our first customer. Then he said, I'm sold on the option to build a form per roll. So good. Sold it already. It was fast. I like it. So if we can inherit, like, a global so it inherits the the default kinda data model form that you configure, and then allow you to adjust that on the specific role, I think that's actually pretty freaking cool because we do have those kinds of use cases where, you know, this particular business and especially if we could apply specific conditionals on that form, it means that, you know, my business user versus my consumer user could have a very different form experience intentionally and different conditionals. Right? The the default conditional for the business user presets those conditions and organization. I I kinda love the idea. Whether or not again, this this comes back to whether or not this actually we we decide to allow additional depth, you know, conditionals. Just having that particular feature seems kind of amazing. As long as we can inherit the default, then if I don't need that kind of capability, I can just use the default and manage the default that we'll get. If I've got a custom reason for adjusting the form. Pretty brilliant. I like it. So there's a question by Benny Wade. Could we make groups configurable per row rather than making a whole form per row? Keep it a bit more modular. AKA, can we nest these forms? Yeah. That that Let's check as we check-in with our friend v form and see how he feels about it. -Oh, boy. Can't wait. Guys, if you enjoy messaging, please. Where you have the forms that or the view of the page or whatever you wanna call it is the same for everybody, but then you just have a section where it's like this section only shows up for x role. Right? Could be interesting. That is a conditional field in and of itself, of course, where it's like, the condition is show or hide this thing if current role is x y z. Right? Which now I'm thinking about it. I'm pretty sure that exists. Present time. I'm pretty sure you can this is something I'll have to test, actually, because I know we have those dynamic variables for current user and current role in those. I don't remember if we support those in conditional fields. Because if we do, you can step a group and have a conditional field on the group that says current role equals x y z and then hide the whole group. We do not, Tim. Tim and a chat. Why not? Why not? He calls me out he calls me out on my bluff. It's happens happens sometimes. Yeah. But that would theoretically be a a soul for the same thing, though. Right? Or you could just say the whole group is hidden for a role, and therefore, no problem. You make it so that you can have the same field in different presentation section configured per role? Right. Right. So the same field multiple times. Yeah. That is that is another thing when it comes to dynamic form building and, just full stop dynamic form building at that point. Right? Because right now, the form is data model first. It's like you have a title field, therefore, you can now have a title input because it's 1 to 1 to the data model. Right? With a form building thing, maybe you have 2 title fields, like, 2 fields that point to the same underlying data thing. Right? There's instinct. I don't know why the hell you would do that, but you could. For for some interface, it may set I mean, in this this example where it's like you have the same field in different sections and the section show and hide based on the role, it starts to make sense again. I for admin users, it'd be interesting, but it it yeah. For sure. Then for, I I think there's a a definite interesting use case for certain data types where it would help to have multiple fields, multiple visual fields for the same underlying column. Think about, like, an address interface face or something. Right? Where you wanna have address line 1, 2, and then, ZIP code and all that kind of stuff, but you wanna save it as one field in your data model. Not super uncommon, or as a let long sort of search thing, right, where you have a let and a long input and then an address field, and those are all connected. So you can type in an address and it'll geo look up the let long, but then the thing that's saved in the database is just the let long. So there's definitely, you know, some additional things that we unlock with that sort of modular form idea. Right? Alright. So what I gathered from this, is that we're basically about to build our own page building framework where we can dynamically close plugs. So we're basically set, you know? Like, director's page building, that sounds like a great idea. Okay. On the So just to solve condition fields. That's that's the beauty of it, isn't it? How did we how did we get here for just solving nested conditional fields? Yeah. It all started so innocently. You know? It's true. I just want to hide a field, and now we're basically embarking on a mission to Okay. This is this is actually this is a good thing because this is a perfect example of the sort of, you know, request review session. For those who've been here before, you've seen this happen before. It's like we go completely off the rails in all directions, and then now let's try to see how we can actually get this back on track for nested conditional fields. Right? So as a you know, in a potential future utopia where you can just magically conquer up any sort of form, any sort of view that you possibly want. Great. But as of right now, I'm kind of thinking, based on everything that we talked about so far, it, to me, makes the most sense to follow Tim's suggestion from earlier, which is basically you cannot put the field and conditional fields that the user does not have read access to. Right? I think that is that is a safe call. I think doing it on the API side, we're never gonna be able to get it just performant enough, and we don't really wanna make WebSockets a requirement for this to work. So I think as of today, you know, what can we actually achieve in the next month or 3? We would most likely keep the client side, keep it fast so we can do all the calculations on the client. It has to be from current fields that you have read access to. The main difference that we have to do is that we have to dynamically, when you open the page the first time, we have to load up what is the nested data structure of this item based on the rules used in conditional fields. And then have some sort of utility function that can cleverly combine the stage changes on top of that. Right? We have to account for the differences like many to one ID versus nested object. We have to account for things like the one to many update structure versus array. But that that way, we can merge that and we can do a client side. Right? I don't think we should do that per role. That just feels like a nightmare to configure, to be completely honest. Yeah. And a lot of a lot of duplication. Again, in a utopic utopic utopic? Utopia stick future. Utopia like future. Utopian? Utopian future, you know, where you have more of this flexible form idea. At that point, you know, you can say, okay, When someone I'm already boring Jonathan to death, I see. When when you open this this page for this particular role, we use form xyz instead but that is again a way way future discussion. But then I think, you know, we can support the core ask for this this feature request, which is if I say nested author dot name, I expect that the lookup, what is the name of the nested author no matter what. If I select an existing one, it needs to look at the name of the existing one. If I change somebody's name, it needs to look at the changed name. Right? That is something that we can I'm pretty hopeful we can turn that into some sort of usability function that we can run relatively quickly on the client side and make this happen. Right? Yeah. That shouldn't be shouldn't be impossible. Yeah. Yeah. Look at the from Natron. And 10 rabbits with 1 multiracial conditional stone. Yeah. Exactly. As an admin that's configuring these conditional fields to another person in the chat, it would be nice to see the whole form that a person with a given role would see. Maybe a view as role option somewhere. Fully a 100% agree. To Jonathan's point, there's another feature request about that user impersonation. Again, very high on my personal, wish list. Right? I would love it as an admin. And not so not just for the for the particular form and settings or something. I really want there to be a way for admins to just say, browse the whole app, impersonating a different role so that you can just click around and see exactly what that user can see and do. Right? From a visual perspective, we'll probably have to have some sort of banner, zoom out a little bit or whatever. We'll figure it out what that looks like. But that way, you can just configure it, see the whole thing as, you know, that particular user. Now especially dreaming wish list, it'd be great if you could just change the form while you're on the page looking at what the form looks like for that given your role. But let's I'll get ahead of ourselves. We're going back. We're going back, guys. Back to the page. We're spinning. We're spinning again. We're spinning again. Let's not spin too much. Yeah. But no. That's a it's it is a very good idea because also with the other feature request that we talked about. Was it last time or not too long ago where we're talking about the rules and permissions as a whole. Right? And these policy units and whatnot. Now that these policies become way more composable, buzzword shot, we can actually you you also have the problem that it becomes a little bit harder to figure out what is the actual permission for this one user now. Right? Because it could come from multiple different places and you can have on the user overrides and that kind of stuff. So I think user impersonation becomes way more important, with that in mind as well. Great. Let's see. We caught up to the chat. If anyone has any last questions, please let us know. There's not much time left. I was running out. Just the the call to action, you know, just to get them going. Yeah. Just a moment. Please like and subscribe. Yeah. Yeah. Yeah. Yeah. Hit that notification bell so you'll stay up to date. But if you truly want to stay up to date, you should head to direct us dot io/tv. I I nearly said dot tv. Yeah. Alright. No. But seriously, on the directors dot iotv, there's lots of interesting series that you can check out, such as this one and also other ones. And enjoy. And see how Directus TV was built on Directus. Very cool. It's exciting. That is pretty cool. We have Jeron to join literally in the last minute. Hey there. Hey there. Thank you for joining. How you doing? We're about to call it. Goodbye. Anyway. Very, very exciting. As always, thank everybody so much for watching. This was yet another talk where I was, like, going into it, it's like, oh, this feels like a small little bug that we could just fix. Right? And then we talk about it now, and I'm like, oh, man. Okay. It deep go. Building a form builder and page builder. Now now we're getting snazzy with it. But that's that's the beauty of these sessions, and I love it every time. So those are joining. Thank you so much. See you guys in 2 weeks from now. Or oh, no. Wait. That's the one that we're skipping for the, you know, the special week week. Yep. It'll be, 4 weeks before our next one, folks. Thanks so much. Appreciate your patience. There's some big announcements coming that that this next week's time or next 2 week time slot is gonna be consumed with other events, and keep an eye out for the live events and things going on that week. So very exciting announcements on the way. We're we're excited to have such an awesome community. Have a great day. Have a great week.",[216,217,218],"bad648f8-fb30-4a79-ab4f-df5678800ac9","b1a78d8c-341f-4e4e-91d7-1c98574b7b6c","a09e4bf5-1fa6-4813-b642-53b986e1fdf9",[],{"reps":221},[222,278],{"name":223,"sdr":8,"link":224,"countries":225,"states":227},"John Daniels","https://meet.directus.io/meetings/john2144/john-contact-form-meeting",[226],"United States",[228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277],"Michigan","Indiana","Ohio","West Virginia","Kentucky","Virginia","Tennessee","North Carolina","South Carolina","Georgia","Florida","Alabama","Mississippi","New York","MI","IN","OH","WV","KY","VA","TN","NC","SC","GA","FL","AL","MS","NY","Connecticut","CT","Delaware","DE","Maine","ME","Maryland","MD","Massachusetts","MA","New Hampshire","NH","New Jersey","NJ","Pennsylvania","PA","Rhode Island","RI","Vermont","VT","Washington DC","DC",{"name":279,"link":280,"countries":281},"Michelle Riber","https://meetings.hubspot.com/mriber",[282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,259,470,471],"Albania","ALB","Algeria","DZA","Andorra","AND","Angola","AGO","Austria","AUT","Belgium","BEL","Benin","BEN","Bosnia and Herzegovina","BIH","Botswana","BWA","Bulgaria","BGR","Burkina Faso","BFA","Burundi","BDI","Cameroon","CMR","Cape Verde","CPV","Central African Republic","CAF","Chad","TCD","Comoros","COM","Côte d'Ivoire","CIV","Croatia","HRV","Czech Republic","CZE","Democratic Republic of Congo","COD","Denmark","DNK","Djibouti","DJI","Egypt","EGY","Equatorial Guinea","GNQ","Eritrea","ERI","Estonia","EST","Eswatini","SWZ","Ethiopia","ETH","Finland","FIN","France","FRA","Gabon","GAB","Gambia","GMB","Ghana","GHA","Greece","GRC","Guinea","GIN","Guinea-Bissau","GNB","Hungary","HUN","Iceland","ISL","Ireland","IRL","Italy","ITA","Kenya","KEN","Latvia","LVA","Lesotho","LSO","Liberia","LBR","Libya","LBY","Liechtenstein","LIE","Lithuania","LTU","Luxembourg","LUX","Madagascar","MDG","Malawi","MWI","Mali","MLI","Malta","MLT","Mauritania","MRT","Mauritius","MUS","Moldova","MDA","Monaco","MCO","Montenegro","MNE","Morocco","MAR","Mozambique","MOZ","Namibia","NAM","Niger","NER","Nigeria","NGA","North Macedonia","MKD","Norway","NOR","Poland","POL","Portugal","PRT","Republic of Congo","COG","Romania","ROU","Rwanda","RWA","San Marino","SMR","São Tomé and Príncipe","STP","Senegal","SEN","Serbia","SRB","Seychelles","SYC","Sierra Leone","SLE","Slovakia","SVK","Slovenia","SVN","Somalia","SOM","South Africa","ZAF","South Sudan","SSD","Spain","ESP","Sudan","SDN","Sweden","SWE","Tanzania","TZA","Togo","TGO","Tunisia","TUN","Uganda","UGA","United Kingdom","GBR","Vatican City","VAT","Zambia","ZMB","Zimbabwe","ZWE","UK","Germany","Netherlands","Switzerland","CH","NL",1773850436217]