[{"data":1,"prerenderedAt":463},["ShallowReactive",2],{"footer-primary":3,"footer-secondary":93,"footer-description":119,"request-review-18618":121,"request-review-18618-next":192,"sales-reps":211},{"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":8,"episode_number":132,"published":133,"title":134,"video_transcript_html":135,"video_transcript_text":136,"content":8,"status":137,"episode_people":138,"recommendations":170,"season":171,"seo":191},"12c8f72d-22fa-4ffa-a9d1-57047216fd1a","18618","1000292187","In this recording of our live event on August 15 2024, Daniel, Jonathan, and Rick discuss import and export options for flows","d71dfd7c-0662-41cc-aece-dfa8bc79919a",54,[129],{"name":130,"url":131},"Discussion","https://github.com/directus/directus/discussions/18618",10,"2024-08-22","Import & Export option for Flows","\u003Cp>Speaker 0: Welcome to another episode of request review. What are we talking about today?\u003C/p>\u003Cp>Speaker 1: We're talking about import and export options for flows.\u003C/p>\u003Cp>Speaker 0: Oh. Now then if he says a like that, it sounds\u003C/p>\u003Cp>Speaker 2: Why don't we just edit then? You know? It should be quick fix. Right?\u003C/p>\u003Cp>Speaker 0: I think that's a great idea. Well, with that being said, thank you so much for watching. Find this episode on of course, I'm kidding. There's there's interesting, as per usual, these episodes, that's why we do them. Some fun edge cases here to consider.\u003C/p>\u003Cp>First and foremost, for those, you know, out of the loop flows, automation workflows, you can set up, you know, triggers. If somebody saves a thing, somebody hits an endpoint, somebody clicks a button in the app, do something. Right? And that something is a set of individual operations, different blocks, so to speak. You can connect together to make it do things.\u003C/p>\u003Cp>Now if you create multiple similar flows or you wanna move them to and from different installations, having some sort of way to import them and export them makes sense. Right? Just as a core set of functionality, absolutely. Somebody in the chat too. You know, flow and operation import is the number one thing that breaks when we sync our schemas and database across different projects.\u003C/p>\u003Cp>So why doesn't it not exist then, or why does it not work properly?\u003C/p>\u003Cp>Speaker 2: That's a good question. I think, that was before my time. So you're probably better equipped to answer that question.\u003C/p>\u003Cp>Speaker 1: There's there's a variety of things that happen here. Right? So schema differentials. Right? So if the scheme is different ahead of the flows being imported, if you're watching and monitoring things that don't exist in that import side, problematic, variables, referencing data and information that doesn't exist in one system to another.\u003C/p>\u003Cp>There's a flows are moving flows, I mean, the APIs are there. We do it all the time with our templating stuff, but we do that in a very controlled way where we're importing and handling the relationals. Because once again, now you've got relational data operations to the flows themselves and all of the data. What I've got a marketplace operation that's not installed in the next environment, there's, you know, there's a there's a great many things that have to be validated and checked, especially on import. Export, not so much, but on import, import gets\u003C/p>\u003Cp>Speaker 0: Absolutely. Has to be And then another important part of those same edge cases there is what about options that need to be different installation to installation, but, you know, 90% of the rest of it is the same. So for example, a a super simple flow that I oftentimes use as an example is, you know, you make a change and you trigger a build on your CD platform, like a Netlify build or something. That production Netlify URL is different project to project because you're building different websites, but the flow configuration, the trigger, you know, the setup for making the request and all that is the same. Cool.\u003C/p>\u003Cp>So looking at this discussion here on GitHub, basic example, motivation. Now the motivation makes a lot of sense. That's just basically, you know, what we're what we're talking about here. I think there's no no discussion on, the usefulness here. When it comes to actual implementation, there's a question of, do we tie this to part of the schema snapshot and apply logic?\u003C/p>\u003Cp>Right? Do we really treat this as it's part of your project's configuration, and we wanna move that between different instances? Or do we treat this more as a kinda more traditional import export like we have for regular collections where you can just say, well, give me all of the operations, and we'll reimport them back in.\u003C/p>\u003Cp>Speaker 2: To me, personally, it sounds more of the traditional way. Like, the correct way would be the traditional way because flows are not specifically schemas. Right? Like like, they're entries in the table, and that's not the schema, those would be items, and I think we should sync them separately. But yeah.\u003C/p>\u003Cp>Speaker 0: And immediately, people start chat typing in the chat. I love it. So this is this is a fun discussion that that has come up in the past in in these request review sessions anyways, but we're we're yet to reach the the the silver bullet answer for what is schema or what is configuration. Right? Flows is to me is one of those points where I think 80% of it is configuration of your project.\u003C/p>\u003Cp>And if you wanna duplicate your project or if you wanna move that from dev to prod or you wanna, you know, use it as a template starting point for something else, you can make the argument that it's definitely part of the same thing that is just one unit of export for the whole configuration of your project. Right? So that's schema and and flows. Last time we were talking about it, you know, it was in the context of roles and permissions, which is a similar but different, you know, part of data, part not. But to to just Josh's point here in the chat, in the data model, you know, the flows are just data in the database.\u003C/p>\u003Cp>But for the perspective of that end user, they're all part of the application that you're, you know, configuring, right, which makes sense. And in that case, you can definitely make the argument, oh, it's just part of, you know, the the application model settings, schema export, and and apply. But that still raises the question, is it the blanket everything? How do you subset it? Because for the schema right now, it's it's everything.\u003C/p>\u003Cp>And how do you deal with options that are different? And how do you deal with active versus inactive? Do we deactivate them on import by default just to be safe. Because you could have a cron thing that could go haywire and talk to, you know, 3rd party production systems if you just spin it up in a new thing.\u003C/p>\u003Cp>Speaker 2: Very valid points. And I and I do see the argument also from Joshua. It kinda it does make sense, right, if you interpret the flows as being part of your infrastructure, then they do kind of feel\u003C/p>\u003Cp>Speaker 0: schemey. Scheme.\u003C/p>\u003Cp>Speaker 2: I'm gonna use that. Scheme esque. Yeah. I I can see that argument. Okay.\u003C/p>\u003Cp>I'm kinda okay. Like in, in the beginning I was like, no, no, no, no. The data, they just stayed up. Those are rules. But now thinking about it, yeah.\u003C/p>\u003Cp>Speaker 0: It's the rules.\u003C/p>\u003Cp>Speaker 2: Damn. Interesting. Yeah. Kinda I'm kinda torn. I'm kinda in between.\u003C/p>\u003Cp>Like, it does it does make a hell of a lot of sense, but,\u003C/p>\u003Cp>Speaker 0: they got a lot. It's funny because we we keep finding ourselves coming back to the age old question of what is and isn't, project configuration that should be sort of version controlled is kinda the the where that's going. Right? Where you wanna have a file that you version control and that includes a bunch of stuff versus within the data, so you differentiate between the 2. And this is this is kinda what earlier when I said, oh, if I make if I build flow, the whole flow but I want the URL that we're talking to to be different.\u003C/p>\u003Cp>So that URL should be in the same static file export. Then by definition, it needs to be in this static file. Right? Because otherwise, you have to do both. Is that easier to maintain?\u003C/p>\u003Cp>Is that worse? Right? But if you're treating it as I wanna have a template that I use to create new projects, but then manage the rest in the project itself, that would still work. If you're treating it as the file becomes the source of truth, now you have to make duplicates of the same, you know, config files to make it work for your different projects. Might be a good thing.\u003C/p>\u003Cp>Might not be a good thing.\u003C/p>\u003Cp>Speaker 2: Did we did we actually, I think there's another small thing, related to this with, like, if if I just want to quickly export one specific one or, I had a not sure if this is, like, a slight tangent that we should go down on, but, when I played around with flows, I had the problem of, I created, like, 15 or 20 different ones, because I was, you know, trying it out and, they got automatically generated. And I had this little gripe with our way of displaying them because there was no, possibility to actually select multiple ones and delete multiple ones. And that kinda sounds to me like if we touch this, you know, with selecting them, exporting them, maybe, you know, filtering them so you only export a couple of them, it feels like selecting them would also fall or, like, lend itself to also be done with this issue. Right? But this is kinda a little different.\u003C/p>\u003Cp>Sorry. Just came to mind.\u003C/p>\u003Cp>Speaker 0: No. Yeah. You're absolutely right, though. Yeah.\u003C/p>\u003Cp>Speaker 2: Okay. So Joshua says, for a user story, we use tons of flows in production and development across 2 applications with the following workflow. We run the whole application locally, modify flows, code extensions. Okay. So far so good.\u003C/p>\u003Cp>Export the schema flows, collections, fields, etcetera etcetera, using a schema sync extension. Okay. So far so good. Commit the schema to version control and build images. Okay.\u003C/p>\u003Cp>In production, import the schema collections and flows as defined in the image. Alright. The result is that flows are always consistent between development and production, and the production flows are immutable. It makes sense. But this, I I guess this is to the point that I said earlier.\u003C/p>\u003Cp>Right? With then, you know, if you want to have, like, development flows production flows, then you have to duplicate them and both of them.\u003C/p>\u003Cp>Speaker 0: Here we go the route in the chat as well saying, you know, what I usually do is try to keep the flows clean by saying, the only thing I export is the values everywhere. And then for the parts where you use different day the data model, there's a sort of settings collection, I imagine, for those flow operations.\u003C/p>\u003Cp>Speaker 2: So you're actually fetching your needed stuff out of your database, and those fields would be different on your dev machine and the production environment. Correct?\u003C/p>\u003Cp>Speaker 0: Right. Yeah. It's basically the way to have that sort of 90%, 10%, you know, split I described earlier solved by using a a settings collection for that, which which makes me think, is that something that could be a native thing where at the top of whatever the file export is for flows, there is a set of very tools you can define, reuse within the file. So you have a single file source of truth that then the app, once you're importing it, the requests, what values do you wanna use for these variables to get food for thought. Right?\u003C/p>\u003Cp>For for those new in this session, it's always about divergently thinking through all of the options, and all of the edge cases and then trying to converge back to, okay, what is something we can do today versus the long term plan? That would be a kinda cool in between, I think, where, you know, in the static file, we have to make sure it's human readable and easy to manage, of course, but you can have you can just describe at the top of the file. Here's a couple of variables that I wanna be installation installation, and then reuse those in your operation settings. The moment you you know, from within Directus where you're using those flows, we can show a a sort of mini form in options that says, okay. What what are those variable values?\u003C/p>\u003Cp>Okay. Okay. Then I think one other thing in, in close that has been there's there's a couple of I mean, I don't know if it's a bug, but it's kind of annoying to deal with is that right now flows make an operations to tables. And it works right. So if you're using the current APIs, you have an export for operations expect you have an export for flows.\u003C/p>\u003Cp>Flows are sort of it's it's a one to many type of thing. Right? You have more 1 or more operations per flow. A very normalized SQL data model for that, which in its, you know, theoretical purity is correct. But it does also definitely mean that sometimes if you're importing operations where the flows doesn't exist, you get foreign key constraint problems.\u003C/p>\u003Cp>Right? Because you're pointing it to a flow that doesn't exist. It also means that when you're exporting it, you end up with 2 different export flows, one for the operations. So that is a bit of an order of insertion interesting thing. It also means that every operation points to the next operation it needs to trigger.\u003C/p>\u003Cp>So that also means that operation insertion order matters, in that table. And, again, that all makes sense from a SQL database perspective, but definitely not, you know, the most user friendly way to do it. And that is just, you know, the the thing you learn over time in in terms of the data model. The question actually came up just now. I see it in the chat, Joshua.\u003C/p>\u003Cp>Out of curiosity, you know, why is that a separate table instead of a big JSON field? Concerns about size and speed, script operations. The, it's partially because JSON fields were just not as well supported or existed at all. And at that point, it did become a bit of a, you know, performance concern in some databases. Luckily, you know, I know 2024, that is that is a different, picture now or, you know, even SQLite has support for for JSF, JSON fields, which is fantastic.\u003C/p>\u003Cp>Concerns about speed has been sort of resolved because of that because now databases can store them, you know, efficiently instead of the large text blob. Size is a concern still a little bit, and that is a similar thing where before it was just a text field, you know, databases were fairly inefficient around storing, you know, unbound blobs of text that would have been JSON but that should also now be way more doable across the SQL vendors. So for what it's worth, I actually think that now, especially now with SQLite support and Oracle DB also being on the JSON train, this is now a new question, right? Should operation just be a nested object on a flow? To which the answer is probably yes, actually, because it's always a tight coupling.\u003C/p>\u003Cp>You're not really moving an operation from one flow to another And storing the actual flow as a nested tree of operations is more efficient, so we don't have to stitch together that tree from from the c port rows. That was just the thing we couldn't do yet, you know, when we when we shipped flows, but nowadays, for sure. Yeah. So that is that is also an interesting thing, which helps with exporting and importing and helps with the ease of authoring it as a file. Right?\u003C/p>\u003Cp>Because if we're saying that operations are represented as a nested tree, kinda like, for those who are familiar with it, like CICD pipelines in GitHub or or those tools, it's oftentimes just a YAML file that says it runs step, step, step, step. Right? So a flow could be a very similar syntax in that sense if we store it that way.\u003C/p>\u003Cp>Speaker 2: Sounds reasonable.\u003C/p>\u003Cp>Speaker 0: And it's only a tiny method for I can change.\u003C/p>\u003Cp>Speaker 2: Okay. So we talked a little bit. How does it look like? How could it look like? Why would this feature be not as easy as you think?\u003C/p>\u003Cp>It's probably our standard go to.\u003C/p>\u003Cp>Speaker 0: So I think in its purest form, just export everything from one flow and import everything from one flow, either through a duplicate button or a separate endpoint. That is not super tricky. The insertion order when you're doing the import is a bit of technical complexity on the implementer side. But from a user experience perspective, it shouldn't be the end of the world. I think the real questions that we have to prepare ourselves for are around what happens if you have a flow that does something destructive and like a cron.\u003C/p>\u003Cp>And the moment you import it, it starts wreaking havoc. Right? Do we import them as disabled by default? Is that what you want? If you're in an environment where your prod is just importing it and and otherwise, it's considered immutable, you want them to be active instead of inactive.\u003C/p>\u003Cp>Right? So how do we do with deal with that? And then around that variableness of you have the flow that's the same, but you have some of the settings that need to be different. Is that something that we have to bake in, or is that something that we say, well, sucks. That just doesn't exist, and you have to duplicate files.\u003C/p>\u003Cp>I think it's worth at least thinking through those questions even if the initial implementation is just going to be, you know, almost the exact same what was described here, which is just import flows, export flows. Bang. Right?\u003C/p>\u003Cp>Speaker 2: According to Joshua, having a, destructive crone is just a skill issue. Fair enough. Problem problem fixed. One less problem to worry about. Alright.\u003C/p>\u003Cp>And, yeah, okay. So so the so the template ability, it it really does sound like a mustache template kinda thing. But, like, I'm I mean, we had a similar thing before, right, with, like, the script operation, for example, where it pulls in, like, your environment. So technically, the environment variables could be different. So you can actually have differing logic inside of them.\u003C/p>\u003Cp>Speaker 0: Yeah. And we do allow you know, in every operation, we allow you to use a value out of a previous step. So using, you know, the the suggestion that we set as a settings table is is a very good alternative, I think. Honestly, it makes a lot of sense. It makes a lot of sense.\u003C/p>\u003Cp>But that is something that we have to just say, okay. If that is our recommended approach, then let's document it as such, because we know it is a I I I mean, of course, we haven't done the the full surveys and everything else, but I would assume that this is a fairly common use case where, you know, the the main use story here is you have a dev environment, you export it so you have a single source of truth that's version controlled, and then you use that to power your production instance. Right? So you use the UI and everything else to configure it, and then you use the code as your immutable source of truth for prod. That's that's sort of the the first user story.\u003C/p>\u003Cp>And I think the second one is really that you have the export as a templated starting point or templated source of truth for multiple projects that are all in prod. Right? So either it is a starting point where if you spin up a new, you know, templated, the, event website or something and they're all the same, so you wanna use the same kickoff point. You have multiple production instances that use the same config. Right?\u003C/p>\u003Cp>That I think those are basically the main to, use cases for for this. Mhmm. And I think in both cases, there's a case to be made for, you know, template ability or at least the the variable, settings, which, again, table.\u003C/p>\u003Cp>Speaker 2: Table does sound pretty good. Pretty pretty reasonable. And similar to what you said, Rijk, earlier, or Jonathan rather, I think, the flows, according to Joshua, you know, if you import something, you could be referencing some tables that no longer exist. So how do we deal with that? Error messages, error pop ups, aborting, disabling the flow and just, you\u003C/p>\u003Cp>Speaker 0: know I think there's also a good data modeling question to that to be honest. I think for operations right now those settings that hold a a field or a collection name, those are basically just a string. Right? And then we, one once the operation runs, it uses that string to try to read data from those tables and whatnot. I think the only solution here is that we treat those as a separate data type.\u003C/p>\u003Cp>So instead of saying it's a string, we say it has to be a collection reference. And therefore, the moment you do an export or import, Directus as a platform can recognize what those settings are supposed to be and validate if they are valid paths. Yes or no. Right? So I I think the the the longer term answer to this question would be to treat those as different data types where it's like, okay, collection reference, field reference.\u003C/p>\u003Cp>So therefore, we can validate it on import or export or both, and almost do like a if you ever see it in in Word or Pages when you open the document, somebody had a bunch of custom fonts and it shows, you know, cannot use cannot find these fonts. Choose what you wanna use instead. That would be kinda the only way I can imagine that to work. Yeah? Mhmm.\u003C/p>\u003Cp>Speaker 2: I mean, if we, yeah, if we treat, you know, the, flows as part of your schema or your your infrastructure, your application, and if then an imported flow does not work because of, you know, like an an unreferenced or wrongly referenced thing in an operation, then technically we should reject that whole import because your entire application becomes inconsistent or can can could become inconsistent. So think, like, if we really consider it part of your application and your whole infrastructure, then we just have to reject everything if something goes wrong.\u003C/p>\u003Cp>Speaker 0: Hans makes a good point here in, in the chat saying, you know, same with role IDs in the permission settings. Effectively, what we're talking about is foreign key constraints, but in JSON, right, where it's like you have a a blob of settings that is different and unique to an operation type because every operation is different and we don't have like a we don't have individual tables for each of the operation types or something where that'd be insane. But what we're talking about here is effectively, how do we do forward key constraints within an operation here? Right? And exactly everything comes back to cache invalidation, naming things, and validating and structure data formats.\u003C/p>\u003Cp>That's great. Yeah. But some sort of way, you know, in the operation value, if we can read it statically, that'd be great, you know, where you can look at an operation settings value and just be recognize what are supposed to be form keys. It could be some sort of unique value syntax, although that feels a little proprietary. It could be, you know, that the operation defines, a sort of JSON schema type of thing that we know what that unstructured data type is supposed to be so we can validate it.\u003C/p>\u003Cp>But, yeah, at the end of the day, what we're talking about is really much foreign key constraints for, operational layout settings and everything else.\u003C/p>\u003Cp>Speaker 2: Yeah. Validation. Just to because I got curious, like, I'm, I think, just to getting back to the import order, like, please correct me if I'm wrong. So I think, if I remember correctly, the flow, references the first operation, and then each operation references the next operation. So the order of operate the the order of import would have to start with the first operate no.\u003C/p>\u003Cp>Because then you can't access you can't reference the second one. Oh, okay. So you have to do it backwards. Yeah.\u003C/p>\u003Cp>Speaker 0: Yeah. Yeah. Yeah. Yeah. Exactly.\u003C/p>\u003Cp>Speaker 2: Exactly. Exactly.\u003C/p>\u003Cp>Speaker 0: I'm still the father\u003C/p>\u003Cp>Speaker 2: to change.\u003C/p>\u003Cp>Speaker 0: Go on. It's the other way, bro.\u003C/p>\u003Cp>Speaker 2: Teacher, that's wrong. No. Right. I can see you have to step step through it once and then just pop off the stack and then go backwards. Okay.\u003C/p>\u003Cp>Speaker 0: Which is also why, you know, I mentioned if we save it as a nested object tree as is and just treat it as one big blob, right, instead of a semi structured thing, that that simplifies export import, like, tremendously, really, because we don't have to do that. We don't have to care about, insertion order because it's all nested on the flow. So, therefore, you don't have those foreign keys pointing back and forth. And a resolve and a reject just becomes a nested object instead of, what you call it, reference to a different, thing in the flat list. Right?\u003C/p>\u003Cp>So that simplifies quite a bit, in in that sense. It's a bit of a break and change for tooling that exists against the operations endpoint, but it would make this a lot a lot less annoying. And I think it also solves one other bug. We we've had a bug in flows where people have run-in into where if you're editing a flow, and I think it's you disconnect operation, then you try to reconnect it somewhere else\u003C/p>\u003Cp>Speaker 1: Right.\u003C/p>\u003Cp>Speaker 0: You get that error that is, like, cannot 4 giga straight. Right? Because you're, Yep.\u003C/p>\u003Cp>Speaker 1: You have to\u003C/p>\u003Cp>Speaker 0: disconnect it. You're dealing with 4 giga\u003C/p>\u003Cp>Speaker 1: from reconnect it in the order that you want. Yeah. It's a Yeah.\u003C/p>\u003Cp>Speaker 0: Exactly. And that is because you're trying to change those foreign key and how they point to each other in a way that is database technically speaking.\u003C/p>\u003Cp>Speaker 1: We have to answer that question for clients on\u003C/p>\u003Cp>Speaker 0: probably almost It's it's a it's theoretically correct. It's also annoying as hell. Yeah. It's one of those\u003C/p>\u003Cp>Speaker 2: Is neck beard correct? Actually actually, it is correct.\u003C/p>\u003Cp>Speaker 0: It is. Pure. It's database pure. Suck\u003C/p>\u003Cp>Speaker 2: it. Yeah. Oh, asks, are we talking about creating custom operations from the UI? No. We are actually talking about importing and exporting flows.\u003C/p>\u003Cp>So, for example, if you export your current schema and import your schema into your new environment, Should flows be included, how should how would that look like, etcetera etcetera.\u003C/p>\u003Cp>Speaker 1: So the template CLI utility that Alex and Bryant and the team put together, we migrate everything including flows. But we have full control over everything. It it's exporting content and schema and everything else comes back in in the appropriate order. So your schema, your, you know, updates and things that need to exist before flows get created all happens as part of that kind of operation steps through the CLI. So configuration as code, kind of the general thoughts that we're working towards there will help with this generally, but I I was taking notes here.\u003C/p>\u003Cp>I saw some of the comments over here. If you're updating an existing flow, Well, if you're updating something in production, flow migration is now gonna have to be maintenance window for anybody doing that. Right? Because if you've got active flows, you've got crons, you've got other things that are going on, if you suddenly come in and hammer a flow that made changes, you're gonna cause issues. You can break, you can lose data, cause problems.\u003C/p>\u003Cp>Transactional processing and other things can be impacted with updating an existing flow. So because currently, you know, our practice with the CLI tool is we delete all the operations and recreate them in order to avoid any kind of, you know, what changed or didn't change just from a complexity standpoint. But those are things that we're gonna have to consider as well as when you're migrating a flow. Are you updating the existing flow, or are you gonna delete and recreate?\u003C/p>\u003Cp>Speaker 0: Yeah. But,\u003C/p>\u003Cp>Speaker 1: you know, from an operational standpoint, my my alerts go off from a security risk perspective of if I'm using Flows for invoice processing or I'm using Flows as part of a payment process, which we have clients doing, And we're suddenly gonna, you know, whack a flow and recreate it, or we're gonna update it in some way. What are the operational impacts and risks of doing that? And they've gone crazy in the chat again.\u003C/p>\u003Cp>Speaker 0: To Hamza's point, that's kind of always a problem with with any sort of data migration. Right? If you import anything new into a production environment, you gotta make sure that you know what you're importing. That's that's the name of the game. That is also why, you know, the static file route in between is is what we're all talking about here.\u003C/p>\u003Cp>So that becomes your source of truth, and that is version controlled so you can see when it was updated by who. You can have some, you know, review processes in place to make sure that it has needs to have sign off, all that kind of stuff. But, yeah, it is technically always just a problem with any sort of data migration. If you have a settings table and import whatever on top of it, then it also breaks. Thinking about the settings table a little bit more, Are the settings always tied to a flow or is it more common to have settings that are global to your whole project and then happen to be reused in the flow?\u003C/p>\u003Cp>The reason why I'm saying that is in in a flow execution, we have that data object. Right? So that holds the all the data that's available in the operations and in the flow. One of the fields in there is that dollar sign trigger. That is just the information of the flow itself.\u003C/p>\u003Cp>Like, what caused it to trigger? I figured we could just have an additional flag in there for any sort of custom data that you wanna just have in that flow global, Right? That you can then reuse in those operations with the existing tools. So therefore, you can make a flow field, flow setting, Netlify URL and that just is becomes one of those data things that you can in in your request operation, you can use the parenthesis the the curly brackets, to reference back to your global flow data. Right?\u003C/p>\u003Cp>That could be a a sort of alternative to a settings table, but it would be unique to each individual flow. Yeah. Exactly what Joshua is saying right now. It's basically specific flow environment variables. Right?\u003C/p>\u003Cp>It would be, you know, environments in the, just that flow. And, yeah, you could theoretically already do that. You could use script operations or you could use the the JSON operation to just return, you know, some static data and then use that elsewhere. That's very true. Very true.\u003C/p>\u003Cp>But it could be a native thing. Then when you export and import it, you just have it as a sort of flow level thing, instead of as a separate operation.\u003C/p>\u003Cp>Speaker 2: Oh, I mean yeah. There's definitely both, both options. Like, having a global thing, is very useful for general stuff, like, even general info between operations, like a brand name, a URL that you reuse in between different actions. But I can also see, you know, the usefulness of tying something specifically to one, thing just for one thing. Sounds pretty good.\u003C/p>\u003Cp>I guess the the the, the actual question is just, okay, how do you manage that in a good way? You know, like, how do we make it pretty? How do we make it a good UX? But I yeah. It it makes sense from,\u003C/p>\u003Cp>Speaker 0: and One one I know Brian and Kevin will yell at me for if I don't bring it up. How do you save it encrypted? Like, some of those settings could very well be, you know, an API token or or things like that. Right? So how do you make sure that that stays secure as well?\u003C/p>\u003Cp>Speaker 1: Yep. That's why I I I think traditionally, most people seen here end up creating a custom table, that's an admin accessible only table. It's not given any permissions for anybody else. You can then store hashed keys. You can store data and values that are masked, only accessible to the administrators kinds of things.\u003C/p>\u003Cp>But I, you know, I've run into this. I actually had this report just a, like, a default language as a filter right across a flow. I was doing a bunch of flow operations and they were nested translations, and I wanted to be able to just say, oh, I only want a specific language. And then I was and you can do things like it's it's simple enough to do a run script that just exports the value. So now you've got that variable in memory, right, in in the data data payloads.\u003C/p>\u003Cp>But Right.\u003C/p>\u003Cp>Speaker 0: So That's that's where it gets that's oh, here comes another site engine. That's the fun thing about these episodes, man. I thought this is gonna be a 10 minute topic, and here we are 45 minutes in, and I just realized something new. When it comes to secret values like that, we have to store them encrypted, not hashed because we have to be able to decrypt them for use in the actual operation. Right?\u003C/p>\u003Cp>So when you make a request and you have to include some sort of token, it needs to be the original token, not the encrypted version. But to the chat's question here from Joshua again, you've been killing all of these questions. Thank you for them. You know, who's allowed to see the config? Right?\u003C/p>\u003Cp>Then, well, I'd say for the right UX at this, you can insert them once, and then that's it. Right? We don't show them again. But at the exact same time, you can then use a run script operation, return them, and then there they are. Right?\u003C/p>\u003Cp>So it's it's just a bit of a fake fake sense of security. They are encrypted into the database to make sure that that stays as secure as we can, so it will never be I mean, that's that's kinda this is kinda the crux of it. I it will never be exported as is, but at the same time, you know, does that matter? Even when you're doing it, it's not a closed closed.\u003C/p>\u003Cp>Speaker 2: Right? Yeah. Yeah. Especially since flows are, at least at least right now, just, an admin exclusive thing. So we kinda you know, like, security schmecurity.\u003C/p>\u003Cp>You know? Like, if you're already an admin, you you have different problems. Like, if your attacker is already an admin, your flow keys are the least of your worries, basically.\u003C/p>\u003Cp>Speaker 0: Yeah. Yes. No. Yes. No.\u003C/p>\u003Cp>Yes. No. Maybe. It's it's tricky in that sense. It's it's weird, though, when you think about it.\u003C/p>\u003Cp>And this is the same when you're talking from a platform team perspective, this is the same problem you're seeing on, you know, AWS secrets manager or d o environment variables or something like that. If you have an encrypted value and you save it, you then, you know, s h into your container, you do print f and there they are. Right? It's like they're stored as secure as possible, but then in your running process, you can just print the environment and everything is right there. But you gotta figure out what is what is the right move.\u003C/p>\u003Cp>Right? Because it can you have read only access to flows where they're hidden? But then if you have update access now, by definition, you have a way to expose them. Right? Is there a way is there a different security level where there should be the the sort of admins that have access to secure stuff and admins that can edit flows, but they're not the same thing?\u003C/p>\u003Cp>That that's a different question. Yeah. I\u003C/p>\u003Cp>Speaker 2: mean, if if we go down, you know, the the settings table route, then we already profit from our, authentication, authorization, system. So, you know, you you can already then assign oh, exclusively these people are allowed to read them, look at them, and stuff like that. So You don't need to plan out every case ahead of time. Well, then you're you're in the wrong stream, my friend. This this is what we do.\u003C/p>\u003Cp>Speaker 0: And again, this is this is the divergent part of all this. Right? This is luckily Yeah. A lot of these things are not blockers to at least get to the minimum viable, which is let us explore these damn things.\u003C/p>\u003Cp>Speaker 2: But Right.\u003C/p>\u003Cp>Speaker 0: These these are the things that people will, you know, use it for and maybe use it wrongly and then maybe expose themselves to massive headaches and issues down the line. So I do I do wanna at least be aware of the types of things that we might see in the future. So we can either prevent it in code, make it better, make it make it better down the line or document it in a way or just warn people about some of the dangers that they might hit. Right? It's, it's it's fun that you mentioned it, but at the same time, we've seen people do shit before.\u003C/p>\u003Cp>It's like, make a cron job that runs every second and put something in the table. Table blows up. Whose fault is that? Right? Did we did we have to do something to prevent that?\u003C/p>\u003Cp>Is that a user error? That who's who's responsible? Exactly. Featurex activity, see revisions. Working working on that, by the way.\u003C/p>\u003Cp>Unrelated for this call.\u003C/p>\u003Cp>Speaker 2: Don't tell. Don't tell. Hooray. Okay.\u003C/p>\u003Cp>Speaker 0: I don't want the sidetracked too much, but, yeah, we have the, retention settings for that coming, shipping fairly soon. Thank god. Yes, Amar. If you want to.\u003C/p>\u003Cp>Speaker 2: No. I\u003C/p>\u003Cp>Speaker 0: don't wanna get in trouble with HR. I don't think that's a good idea.\u003C/p>\u003Cp>Speaker 2: Goosebumps. Oh, no. Okay. So, just just keeping the time, in mind, we don't have that much time left. So maybe we should start to kinda converge now a little bit, You know, yeah, just to, get back on track a little bit.\u003C/p>\u003Cp>Oh, wow. And then the whole essay drops\u003C/p>\u003Cp>Speaker 0: from Yeah. There goes the next 10 minutes.\u003C/p>\u003Cp>Speaker 2: Oh, wow. Should we read that aloud? Are there bad words in it? Looks good. Okay.\u003C/p>\u003Cp>In my humble opinion, the whole edit complexity of environment migration I'm using directdis comes from the yaw application becoming data itself. Alright. While not using Directus, you can run different versions of the application side by side, and it's easy to switch version which version is running because the structure is defined within the application. Wildirectors, most of you. My guy, there there's not a single dot in that sentence.\u003C/p>\u003Cp>Oh my god. That's that's one sentence.\u003C/p>\u003Cp>Speaker 0: Don't throw too much shade. And it the the gist of it is because all the configuration is in the database instead of in code, therefore, you have migrations back and forth prompts. Right? And to Joshua's point, that is definitely a configuration as code discussion, which I think we had a couple episodes ago, actually, which is a great segue. Directs.i0/tv under request review.\u003C/p>\u003Cp>Highly recommend it. The the the 5 second summary of that discussion is really around there's multiple use cases. Right? There's a lot of people that prefer configuring everything from the UX and UI and then making an export. So by definition, it is in the database.\u003C/p>\u003Cp>Right? It's it's a mixed environment where there needs to be a two way binding into configuration. We don't wanna end up in a sort of again, the choices are different different use cases, different type of people. I'd I'd rather not end up with a sanity slash strappy type of environment where you have to pull things locally to code, you know, your settings and then redeploy it. That is just not quite the vision that we have for, you know, the ease of use and the user experience for this.\u003C/p>\u003Cp>Also, I know from some inside chatter that they're trying to get out of that as well. So this is this is a bit of a two way binding discussion.\u003C/p>\u003Cp>Speaker 2: Did you did you see They updated their comment and broke up the paragraph into multiple sentences now.\u003C/p>\u003Cp>Speaker 0: Danielle, look at what you've done. I think this is called cyberbullies. We don't condone that here.\u003C/p>\u003Cp>Speaker 2: Oh, no. Thank you for thank you for the, not not, what is it? Thank you for your cooperation, Wolfolas. Thanks for being here. Thanks for your message.\u003C/p>\u003Cp>We do appreciate it.\u003C/p>\u003Cp>Speaker 1: I'm not sure how you say it, but Wolf Wolf of us is an awesome contributor. He's been an incredible community member and contributor and helps out across everywhere across the platform. So\u003C/p>\u003Cp>Speaker 0: we are\u003C/p>\u003Cp>Speaker 2: It turns out.\u003C/p>\u003Cp>Speaker 0: Anyhoo, to your point then, converging it down to okay. What can we do? I think the the question that I do have is, do we wanna look into storing this as a nested JSON blob versus a separate table? Right? It would be a bit of a breaking change, but it simplifies both the output files and it simplifies the, the way to import it for us quite a bit.\u003C/p>\u003Cp>And it also solves that cannot resolve foreign key type thing bug in the same time. Right? The alternative is that we don't do that, but we avoid that breaking change in the operations endpoint with the downside that then for both export and import, we have to make sure that the whole nested tree is included at all times. And then during import, we do it in the correct insertion order. Right?\u003C/p>\u003Cp>Gut feeling wise, I'm kinda leaning towards let's blop it all as a nest of blob because it simplifies things. At the same time, couple downsides of that is that I think we'd lose the ability to choose what fields are returned from operations. I don't know if that matters as much if you're dealing with flows. Theoretically speaking, most of the databases now should support field selection for JSON. But seeing that we're talking about a theoretical infinitely deep object, that might be tricky.\u003C/p>\u003Cp>Right? Or we have to filter it down in in post after we got the data back.\u003C/p>\u003Cp>Speaker 2: Quick quick tangent. Can SQLite do that? I'm not sure. I don't think so. Right?\u003C/p>\u003Cp>Speaker 0: I think that update came earlier this year that they have some sort of SQL path, JSON path selection. Yeah.\u003C/p>\u003Cp>Speaker 2: They they've\u003C/p>\u003Cp>Speaker 1: got some JSON path.\u003C/p>\u003Cp>Speaker 0: Yeah. It's fairly recent. That's also one of the reasons why I missed we couldn't really do this earlier. Right?\u003C/p>\u003Cp>Speaker 2: Yeah. Oh, that's nice. Okay. Okay.\u003C/p>\u003Cp>Speaker 1: Yeah. So the lights are getting a lot of attention because you've got companies like Terso and others that are using this distributed edge file based databasing, caching kinds of things. So there's some there's a lot of work going on in that space and SQLite's gotten some pretty good attention.\u003C/p>\u003Cp>Speaker 0: But, I\u003C/p>\u003Cp>Speaker 1: mean, vendor variation, I think, as we move towards hopefully, as we move towards Duris, you know, whether or not that vendor supports it, then we can decide sourcing wise how we handle that. But for the main\u003C/p>\u003Cp>Speaker 2: I'm a big proponent of s Eskelet. Like, if if we if I do something, it it I wanted it for an SQLite, please. Okay. The end of this tangent. I'm sorry to I just I was curious.\u003C/p>\u003Cp>Yeah. Okay.\u003C/p>\u003Cp>Speaker 0: So so I think because, you know, the nested JSON stuff is something we haven't historically done because we couldn't really do that cross database vendor properly support it. It is something that probably comes with new issues that we don't know about yet. Right? So oh, yeah. Somebody actually mentioned it here too.\u003C/p>\u003Cp>It was like, Joshua again. Get a shout out, Josh. Stick with the current structure because making breaking breaking changes to the operation config will get to be a huge problem if using nested JSON objects. It's gonna be easier if you have a single row that changes. Just fair enough.\u003C/p>\u003Cp>And also see support for older databases and vendors that don't have JSON support. Also true.\u003C/p>\u003Cp>Speaker 2: Although,\u003C/p>\u003Cp>Speaker 0: I I wanna say that the ones that don't have an end of life I guess SQLite, the previous version, not yet, of course. Yeah. So and and, also, obviously, the big breaking change. People have been exporting, importing things through the APIs. The separate tools have been made.\u003C/p>\u003Cp>We saw that BCC schema sync shout out earlier. So we wanna make sure that that is not a huge freaking change either, right, where we just completely wreck any of those existing things. So sticking with the current structure probably makes the most sense. And then that raises the question around, you know, data integrity and import order, but that is a technical problem to solve that we just have to do during import. So that does mean that it'll probably be a separate way that we, do this than than compared to your usual export import just because order matters and that integrity matters.\u003C/p>\u003Cp>No. That's fine.\u003C/p>\u003Cp>Speaker 2: That should be really doable. You know? Walk the tree once and then just pop off from the back.\u003C/p>\u003Cp>Speaker 0: Yeah. And and the age old question, is this part of the schema export? Yes or no?\u003C/p>\u003Cp>Speaker 2: Oh, right. The the gonna\u003C/p>\u003Cp>Speaker 0: be a discussion for a different day, which is discussion we've had before around roles. And the yeah. But Joshua basically is concluding as well. We just need some schema export flags, which is, like, what do we include? What do we not include?\u003C/p>\u003Cp>This this this is the discussion we had exactly the same around roles. Do you wanna include roles and permissions? Probably. Do you wanna include users? Probably not.\u003C/p>\u003Cp>Do you wanna include permissions? Probably. Do you wanna include all of the permissions or just the ones that are about your production databases? Probably just the prod ones. How do you filter that down?\u003C/p>\u003Cp>This is the exact same stuff. Right? Is it all the flows? Is it some of the flows? How do you choose which of the flows are included and which ones aren't?\u003C/p>\u003Cp>Do we just export everything and then assume that somebody goes into the file and deletes them manually? Lots of more fun questions to be had in this. And for that, I wanna say, subscribe, like, and subscribe.\u003C/p>\u003Cp>Speaker 1: Nope. I think\u003C/p>\u003Cp>Speaker 2: Hit the bell. Hit the bell.\u003C/p>\u003Cp>Speaker 1: Always been.\u003C/p>\u003Cp>Speaker 0: Hit the bell and make sure you don't miss that episode when we go deep on that.\u003C/p>\u003Cp>Speaker 1: Now selective import export is gonna be needed for most of these things, I think. And ideally, whether export could export everything, but selective import on the import side, the ability to choose what I'm actually merging into the next iteration is is key.\u003C/p>\u003Cp>Speaker 2: Right.\u003C/p>\u003Cp>Speaker 0: Oh, that being said, I've not been muting. I'm muting. I'm muting. I'm muting. And I'm muting.\u003C/p>\u003Cp>The the doorbell is ringing, so I just wanted to make sure it didn't get too annoying. But that being said, we're at the top of the hour here. There's one more question that just came in. So another quick thought, what about pulling changes instead of pushing them in? Like, a sort of federation type of thing where you link data from multiple direct instances, you pull change from another instance.\u003C/p>\u003Cp>That sounds like a discussion for another day.\u003C/p>\u003Cp>Speaker 1: I think we've had that as part of the dual syncing as part of the configuration as code anyway. It is something that we we've we're we're thinking about, on that side of the house, and that's this is part of that as well. Right? So the configuration as code affects this, having utilities that make this easy now, versus, you know\u003C/p>\u003Cp>Speaker 0: Yeah. I I think that two way bind to me always has the file in between. So you push it from dev to file, and you pull it from prod from file. That is kind of the the the one to jump. Anyways, with that being said, thank you all for tuning in.\u003C/p>\u003Cp>Thank you all for the great questions and ideas in the chat. This episode will be available on Directus TV in the very near future. Shout out to shout out to Nat. Dan, did you make sure there's any any Zingers in here? Do we have the thumbnail?\u003C/p>\u003Cp>Speaker 2: Oh, that's not quite sure. May may maybe the the technically technically correct, maybe. I'm not sure.\u003C/p>\u003Cp>Speaker 0: There you go. That's that's the perfect one. That being said, check it out drex. Io/tv. We'll be doing this again in in the near future.\u003C/p>","Welcome to another episode of request review. What are we talking about today? We're talking about import and export options for flows. Oh. Now then if he says a like that, it sounds Why don't we just edit then? You know? It should be quick fix. Right? I think that's a great idea. Well, with that being said, thank you so much for watching. Find this episode on of course, I'm kidding. There's there's interesting, as per usual, these episodes, that's why we do them. Some fun edge cases here to consider. First and foremost, for those, you know, out of the loop flows, automation workflows, you can set up, you know, triggers. If somebody saves a thing, somebody hits an endpoint, somebody clicks a button in the app, do something. Right? And that something is a set of individual operations, different blocks, so to speak. You can connect together to make it do things. Now if you create multiple similar flows or you wanna move them to and from different installations, having some sort of way to import them and export them makes sense. Right? Just as a core set of functionality, absolutely. Somebody in the chat too. You know, flow and operation import is the number one thing that breaks when we sync our schemas and database across different projects. So why doesn't it not exist then, or why does it not work properly? That's a good question. I think, that was before my time. So you're probably better equipped to answer that question. There's there's a variety of things that happen here. Right? So schema differentials. Right? So if the scheme is different ahead of the flows being imported, if you're watching and monitoring things that don't exist in that import side, problematic, variables, referencing data and information that doesn't exist in one system to another. There's a flows are moving flows, I mean, the APIs are there. We do it all the time with our templating stuff, but we do that in a very controlled way where we're importing and handling the relationals. Because once again, now you've got relational data operations to the flows themselves and all of the data. What I've got a marketplace operation that's not installed in the next environment, there's, you know, there's a there's a great many things that have to be validated and checked, especially on import. Export, not so much, but on import, import gets Absolutely. Has to be And then another important part of those same edge cases there is what about options that need to be different installation to installation, but, you know, 90% of the rest of it is the same. So for example, a a super simple flow that I oftentimes use as an example is, you know, you make a change and you trigger a build on your CD platform, like a Netlify build or something. That production Netlify URL is different project to project because you're building different websites, but the flow configuration, the trigger, you know, the setup for making the request and all that is the same. Cool. So looking at this discussion here on GitHub, basic example, motivation. Now the motivation makes a lot of sense. That's just basically, you know, what we're what we're talking about here. I think there's no no discussion on, the usefulness here. When it comes to actual implementation, there's a question of, do we tie this to part of the schema snapshot and apply logic? Right? Do we really treat this as it's part of your project's configuration, and we wanna move that between different instances? Or do we treat this more as a kinda more traditional import export like we have for regular collections where you can just say, well, give me all of the operations, and we'll reimport them back in. To me, personally, it sounds more of the traditional way. Like, the correct way would be the traditional way because flows are not specifically schemas. Right? Like like, they're entries in the table, and that's not the schema, those would be items, and I think we should sync them separately. But yeah. And immediately, people start chat typing in the chat. I love it. So this is this is a fun discussion that that has come up in the past in in these request review sessions anyways, but we're we're yet to reach the the the silver bullet answer for what is schema or what is configuration. Right? Flows is to me is one of those points where I think 80% of it is configuration of your project. And if you wanna duplicate your project or if you wanna move that from dev to prod or you wanna, you know, use it as a template starting point for something else, you can make the argument that it's definitely part of the same thing that is just one unit of export for the whole configuration of your project. Right? So that's schema and and flows. Last time we were talking about it, you know, it was in the context of roles and permissions, which is a similar but different, you know, part of data, part not. But to to just Josh's point here in the chat, in the data model, you know, the flows are just data in the database. But for the perspective of that end user, they're all part of the application that you're, you know, configuring, right, which makes sense. And in that case, you can definitely make the argument, oh, it's just part of, you know, the the application model settings, schema export, and and apply. But that still raises the question, is it the blanket everything? How do you subset it? Because for the schema right now, it's it's everything. And how do you deal with options that are different? And how do you deal with active versus inactive? Do we deactivate them on import by default just to be safe. Because you could have a cron thing that could go haywire and talk to, you know, 3rd party production systems if you just spin it up in a new thing. Very valid points. And I and I do see the argument also from Joshua. It kinda it does make sense, right, if you interpret the flows as being part of your infrastructure, then they do kind of feel schemey. Scheme. I'm gonna use that. Scheme esque. Yeah. I I can see that argument. Okay. I'm kinda okay. Like in, in the beginning I was like, no, no, no, no. The data, they just stayed up. Those are rules. But now thinking about it, yeah. It's the rules. Damn. Interesting. Yeah. Kinda I'm kinda torn. I'm kinda in between. Like, it does it does make a hell of a lot of sense, but, they got a lot. It's funny because we we keep finding ourselves coming back to the age old question of what is and isn't, project configuration that should be sort of version controlled is kinda the the where that's going. Right? Where you wanna have a file that you version control and that includes a bunch of stuff versus within the data, so you differentiate between the 2. And this is this is kinda what earlier when I said, oh, if I make if I build flow, the whole flow but I want the URL that we're talking to to be different. So that URL should be in the same static file export. Then by definition, it needs to be in this static file. Right? Because otherwise, you have to do both. Is that easier to maintain? Is that worse? Right? But if you're treating it as I wanna have a template that I use to create new projects, but then manage the rest in the project itself, that would still work. If you're treating it as the file becomes the source of truth, now you have to make duplicates of the same, you know, config files to make it work for your different projects. Might be a good thing. Might not be a good thing. Did we did we actually, I think there's another small thing, related to this with, like, if if I just want to quickly export one specific one or, I had a not sure if this is, like, a slight tangent that we should go down on, but, when I played around with flows, I had the problem of, I created, like, 15 or 20 different ones, because I was, you know, trying it out and, they got automatically generated. And I had this little gripe with our way of displaying them because there was no, possibility to actually select multiple ones and delete multiple ones. And that kinda sounds to me like if we touch this, you know, with selecting them, exporting them, maybe, you know, filtering them so you only export a couple of them, it feels like selecting them would also fall or, like, lend itself to also be done with this issue. Right? But this is kinda a little different. Sorry. Just came to mind. No. Yeah. You're absolutely right, though. Yeah. Okay. So Joshua says, for a user story, we use tons of flows in production and development across 2 applications with the following workflow. We run the whole application locally, modify flows, code extensions. Okay. So far so good. Export the schema flows, collections, fields, etcetera etcetera, using a schema sync extension. Okay. So far so good. Commit the schema to version control and build images. Okay. In production, import the schema collections and flows as defined in the image. Alright. The result is that flows are always consistent between development and production, and the production flows are immutable. It makes sense. But this, I I guess this is to the point that I said earlier. Right? With then, you know, if you want to have, like, development flows production flows, then you have to duplicate them and both of them. Here we go the route in the chat as well saying, you know, what I usually do is try to keep the flows clean by saying, the only thing I export is the values everywhere. And then for the parts where you use different day the data model, there's a sort of settings collection, I imagine, for those flow operations. So you're actually fetching your needed stuff out of your database, and those fields would be different on your dev machine and the production environment. Correct? Right. Yeah. It's basically the way to have that sort of 90%, 10%, you know, split I described earlier solved by using a a settings collection for that, which which makes me think, is that something that could be a native thing where at the top of whatever the file export is for flows, there is a set of very tools you can define, reuse within the file. So you have a single file source of truth that then the app, once you're importing it, the requests, what values do you wanna use for these variables to get food for thought. Right? For for those new in this session, it's always about divergently thinking through all of the options, and all of the edge cases and then trying to converge back to, okay, what is something we can do today versus the long term plan? That would be a kinda cool in between, I think, where, you know, in the static file, we have to make sure it's human readable and easy to manage, of course, but you can have you can just describe at the top of the file. Here's a couple of variables that I wanna be installation installation, and then reuse those in your operation settings. The moment you you know, from within Directus where you're using those flows, we can show a a sort of mini form in options that says, okay. What what are those variable values? Okay. Okay. Then I think one other thing in, in close that has been there's there's a couple of I mean, I don't know if it's a bug, but it's kind of annoying to deal with is that right now flows make an operations to tables. And it works right. So if you're using the current APIs, you have an export for operations expect you have an export for flows. Flows are sort of it's it's a one to many type of thing. Right? You have more 1 or more operations per flow. A very normalized SQL data model for that, which in its, you know, theoretical purity is correct. But it does also definitely mean that sometimes if you're importing operations where the flows doesn't exist, you get foreign key constraint problems. Right? Because you're pointing it to a flow that doesn't exist. It also means that when you're exporting it, you end up with 2 different export flows, one for the operations. So that is a bit of an order of insertion interesting thing. It also means that every operation points to the next operation it needs to trigger. So that also means that operation insertion order matters, in that table. And, again, that all makes sense from a SQL database perspective, but definitely not, you know, the most user friendly way to do it. And that is just, you know, the the thing you learn over time in in terms of the data model. The question actually came up just now. I see it in the chat, Joshua. Out of curiosity, you know, why is that a separate table instead of a big JSON field? Concerns about size and speed, script operations. The, it's partially because JSON fields were just not as well supported or existed at all. And at that point, it did become a bit of a, you know, performance concern in some databases. Luckily, you know, I know 2024, that is that is a different, picture now or, you know, even SQLite has support for for JSF, JSON fields, which is fantastic. Concerns about speed has been sort of resolved because of that because now databases can store them, you know, efficiently instead of the large text blob. Size is a concern still a little bit, and that is a similar thing where before it was just a text field, you know, databases were fairly inefficient around storing, you know, unbound blobs of text that would have been JSON but that should also now be way more doable across the SQL vendors. So for what it's worth, I actually think that now, especially now with SQLite support and Oracle DB also being on the JSON train, this is now a new question, right? Should operation just be a nested object on a flow? To which the answer is probably yes, actually, because it's always a tight coupling. You're not really moving an operation from one flow to another And storing the actual flow as a nested tree of operations is more efficient, so we don't have to stitch together that tree from from the c port rows. That was just the thing we couldn't do yet, you know, when we when we shipped flows, but nowadays, for sure. Yeah. So that is that is also an interesting thing, which helps with exporting and importing and helps with the ease of authoring it as a file. Right? Because if we're saying that operations are represented as a nested tree, kinda like, for those who are familiar with it, like CICD pipelines in GitHub or or those tools, it's oftentimes just a YAML file that says it runs step, step, step, step. Right? So a flow could be a very similar syntax in that sense if we store it that way. Sounds reasonable. And it's only a tiny method for I can change. Okay. So we talked a little bit. How does it look like? How could it look like? Why would this feature be not as easy as you think? It's probably our standard go to. So I think in its purest form, just export everything from one flow and import everything from one flow, either through a duplicate button or a separate endpoint. That is not super tricky. The insertion order when you're doing the import is a bit of technical complexity on the implementer side. But from a user experience perspective, it shouldn't be the end of the world. I think the real questions that we have to prepare ourselves for are around what happens if you have a flow that does something destructive and like a cron. And the moment you import it, it starts wreaking havoc. Right? Do we import them as disabled by default? Is that what you want? If you're in an environment where your prod is just importing it and and otherwise, it's considered immutable, you want them to be active instead of inactive. Right? So how do we do with deal with that? And then around that variableness of you have the flow that's the same, but you have some of the settings that need to be different. Is that something that we have to bake in, or is that something that we say, well, sucks. That just doesn't exist, and you have to duplicate files. I think it's worth at least thinking through those questions even if the initial implementation is just going to be, you know, almost the exact same what was described here, which is just import flows, export flows. Bang. Right? According to Joshua, having a, destructive crone is just a skill issue. Fair enough. Problem problem fixed. One less problem to worry about. Alright. And, yeah, okay. So so the so the template ability, it it really does sound like a mustache template kinda thing. But, like, I'm I mean, we had a similar thing before, right, with, like, the script operation, for example, where it pulls in, like, your environment. So technically, the environment variables could be different. So you can actually have differing logic inside of them. Yeah. And we do allow you know, in every operation, we allow you to use a value out of a previous step. So using, you know, the the suggestion that we set as a settings table is is a very good alternative, I think. Honestly, it makes a lot of sense. It makes a lot of sense. But that is something that we have to just say, okay. If that is our recommended approach, then let's document it as such, because we know it is a I I I mean, of course, we haven't done the the full surveys and everything else, but I would assume that this is a fairly common use case where, you know, the the main use story here is you have a dev environment, you export it so you have a single source of truth that's version controlled, and then you use that to power your production instance. Right? So you use the UI and everything else to configure it, and then you use the code as your immutable source of truth for prod. That's that's sort of the the first user story. And I think the second one is really that you have the export as a templated starting point or templated source of truth for multiple projects that are all in prod. Right? So either it is a starting point where if you spin up a new, you know, templated, the, event website or something and they're all the same, so you wanna use the same kickoff point. You have multiple production instances that use the same config. Right? That I think those are basically the main to, use cases for for this. Mhmm. And I think in both cases, there's a case to be made for, you know, template ability or at least the the variable, settings, which, again, table. Table does sound pretty good. Pretty pretty reasonable. And similar to what you said, Rijk, earlier, or Jonathan rather, I think, the flows, according to Joshua, you know, if you import something, you could be referencing some tables that no longer exist. So how do we deal with that? Error messages, error pop ups, aborting, disabling the flow and just, you know I think there's also a good data modeling question to that to be honest. I think for operations right now those settings that hold a a field or a collection name, those are basically just a string. Right? And then we, one once the operation runs, it uses that string to try to read data from those tables and whatnot. I think the only solution here is that we treat those as a separate data type. So instead of saying it's a string, we say it has to be a collection reference. And therefore, the moment you do an export or import, Directus as a platform can recognize what those settings are supposed to be and validate if they are valid paths. Yes or no. Right? So I I think the the the longer term answer to this question would be to treat those as different data types where it's like, okay, collection reference, field reference. So therefore, we can validate it on import or export or both, and almost do like a if you ever see it in in Word or Pages when you open the document, somebody had a bunch of custom fonts and it shows, you know, cannot use cannot find these fonts. Choose what you wanna use instead. That would be kinda the only way I can imagine that to work. Yeah? Mhmm. I mean, if we, yeah, if we treat, you know, the, flows as part of your schema or your your infrastructure, your application, and if then an imported flow does not work because of, you know, like an an unreferenced or wrongly referenced thing in an operation, then technically we should reject that whole import because your entire application becomes inconsistent or can can could become inconsistent. So think, like, if we really consider it part of your application and your whole infrastructure, then we just have to reject everything if something goes wrong. Hans makes a good point here in, in the chat saying, you know, same with role IDs in the permission settings. Effectively, what we're talking about is foreign key constraints, but in JSON, right, where it's like you have a a blob of settings that is different and unique to an operation type because every operation is different and we don't have like a we don't have individual tables for each of the operation types or something where that'd be insane. But what we're talking about here is effectively, how do we do forward key constraints within an operation here? Right? And exactly everything comes back to cache invalidation, naming things, and validating and structure data formats. That's great. Yeah. But some sort of way, you know, in the operation value, if we can read it statically, that'd be great, you know, where you can look at an operation settings value and just be recognize what are supposed to be form keys. It could be some sort of unique value syntax, although that feels a little proprietary. It could be, you know, that the operation defines, a sort of JSON schema type of thing that we know what that unstructured data type is supposed to be so we can validate it. But, yeah, at the end of the day, what we're talking about is really much foreign key constraints for, operational layout settings and everything else. Yeah. Validation. Just to because I got curious, like, I'm, I think, just to getting back to the import order, like, please correct me if I'm wrong. So I think, if I remember correctly, the flow, references the first operation, and then each operation references the next operation. So the order of operate the the order of import would have to start with the first operate no. Because then you can't access you can't reference the second one. Oh, okay. So you have to do it backwards. Yeah. Yeah. Yeah. Yeah. Yeah. Exactly. Exactly. Exactly. I'm still the father to change. Go on. It's the other way, bro. Teacher, that's wrong. No. Right. I can see you have to step step through it once and then just pop off the stack and then go backwards. Okay. Which is also why, you know, I mentioned if we save it as a nested object tree as is and just treat it as one big blob, right, instead of a semi structured thing, that that simplifies export import, like, tremendously, really, because we don't have to do that. We don't have to care about, insertion order because it's all nested on the flow. So, therefore, you don't have those foreign keys pointing back and forth. And a resolve and a reject just becomes a nested object instead of, what you call it, reference to a different, thing in the flat list. Right? So that simplifies quite a bit, in in that sense. It's a bit of a break and change for tooling that exists against the operations endpoint, but it would make this a lot a lot less annoying. And I think it also solves one other bug. We we've had a bug in flows where people have run-in into where if you're editing a flow, and I think it's you disconnect operation, then you try to reconnect it somewhere else Right. You get that error that is, like, cannot 4 giga straight. Right? Because you're, Yep. You have to disconnect it. You're dealing with 4 giga from reconnect it in the order that you want. Yeah. It's a Yeah. Exactly. And that is because you're trying to change those foreign key and how they point to each other in a way that is database technically speaking. We have to answer that question for clients on probably almost It's it's a it's theoretically correct. It's also annoying as hell. Yeah. It's one of those Is neck beard correct? Actually actually, it is correct. It is. Pure. It's database pure. Suck it. Yeah. Oh, asks, are we talking about creating custom operations from the UI? No. We are actually talking about importing and exporting flows. So, for example, if you export your current schema and import your schema into your new environment, Should flows be included, how should how would that look like, etcetera etcetera. So the template CLI utility that Alex and Bryant and the team put together, we migrate everything including flows. But we have full control over everything. It it's exporting content and schema and everything else comes back in in the appropriate order. So your schema, your, you know, updates and things that need to exist before flows get created all happens as part of that kind of operation steps through the CLI. So configuration as code, kind of the general thoughts that we're working towards there will help with this generally, but I I was taking notes here. I saw some of the comments over here. If you're updating an existing flow, Well, if you're updating something in production, flow migration is now gonna have to be maintenance window for anybody doing that. Right? Because if you've got active flows, you've got crons, you've got other things that are going on, if you suddenly come in and hammer a flow that made changes, you're gonna cause issues. You can break, you can lose data, cause problems. Transactional processing and other things can be impacted with updating an existing flow. So because currently, you know, our practice with the CLI tool is we delete all the operations and recreate them in order to avoid any kind of, you know, what changed or didn't change just from a complexity standpoint. But those are things that we're gonna have to consider as well as when you're migrating a flow. Are you updating the existing flow, or are you gonna delete and recreate? Yeah. But, you know, from an operational standpoint, my my alerts go off from a security risk perspective of if I'm using Flows for invoice processing or I'm using Flows as part of a payment process, which we have clients doing, And we're suddenly gonna, you know, whack a flow and recreate it, or we're gonna update it in some way. What are the operational impacts and risks of doing that? And they've gone crazy in the chat again. To Hamza's point, that's kind of always a problem with with any sort of data migration. Right? If you import anything new into a production environment, you gotta make sure that you know what you're importing. That's that's the name of the game. That is also why, you know, the static file route in between is is what we're all talking about here. So that becomes your source of truth, and that is version controlled so you can see when it was updated by who. You can have some, you know, review processes in place to make sure that it has needs to have sign off, all that kind of stuff. But, yeah, it is technically always just a problem with any sort of data migration. If you have a settings table and import whatever on top of it, then it also breaks. Thinking about the settings table a little bit more, Are the settings always tied to a flow or is it more common to have settings that are global to your whole project and then happen to be reused in the flow? The reason why I'm saying that is in in a flow execution, we have that data object. Right? So that holds the all the data that's available in the operations and in the flow. One of the fields in there is that dollar sign trigger. That is just the information of the flow itself. Like, what caused it to trigger? I figured we could just have an additional flag in there for any sort of custom data that you wanna just have in that flow global, Right? That you can then reuse in those operations with the existing tools. So therefore, you can make a flow field, flow setting, Netlify URL and that just is becomes one of those data things that you can in in your request operation, you can use the parenthesis the the curly brackets, to reference back to your global flow data. Right? That could be a a sort of alternative to a settings table, but it would be unique to each individual flow. Yeah. Exactly what Joshua is saying right now. It's basically specific flow environment variables. Right? It would be, you know, environments in the, just that flow. And, yeah, you could theoretically already do that. You could use script operations or you could use the the JSON operation to just return, you know, some static data and then use that elsewhere. That's very true. Very true. But it could be a native thing. Then when you export and import it, you just have it as a sort of flow level thing, instead of as a separate operation. Oh, I mean yeah. There's definitely both, both options. Like, having a global thing, is very useful for general stuff, like, even general info between operations, like a brand name, a URL that you reuse in between different actions. But I can also see, you know, the usefulness of tying something specifically to one, thing just for one thing. Sounds pretty good. I guess the the the, the actual question is just, okay, how do you manage that in a good way? You know, like, how do we make it pretty? How do we make it a good UX? But I yeah. It it makes sense from, and One one I know Brian and Kevin will yell at me for if I don't bring it up. How do you save it encrypted? Like, some of those settings could very well be, you know, an API token or or things like that. Right? So how do you make sure that that stays secure as well? Yep. That's why I I I think traditionally, most people seen here end up creating a custom table, that's an admin accessible only table. It's not given any permissions for anybody else. You can then store hashed keys. You can store data and values that are masked, only accessible to the administrators kinds of things. But I, you know, I've run into this. I actually had this report just a, like, a default language as a filter right across a flow. I was doing a bunch of flow operations and they were nested translations, and I wanted to be able to just say, oh, I only want a specific language. And then I was and you can do things like it's it's simple enough to do a run script that just exports the value. So now you've got that variable in memory, right, in in the data data payloads. But Right. So That's that's where it gets that's oh, here comes another site engine. That's the fun thing about these episodes, man. I thought this is gonna be a 10 minute topic, and here we are 45 minutes in, and I just realized something new. When it comes to secret values like that, we have to store them encrypted, not hashed because we have to be able to decrypt them for use in the actual operation. Right? So when you make a request and you have to include some sort of token, it needs to be the original token, not the encrypted version. But to the chat's question here from Joshua again, you've been killing all of these questions. Thank you for them. You know, who's allowed to see the config? Right? Then, well, I'd say for the right UX at this, you can insert them once, and then that's it. Right? We don't show them again. But at the exact same time, you can then use a run script operation, return them, and then there they are. Right? So it's it's just a bit of a fake fake sense of security. They are encrypted into the database to make sure that that stays as secure as we can, so it will never be I mean, that's that's kinda this is kinda the crux of it. I it will never be exported as is, but at the same time, you know, does that matter? Even when you're doing it, it's not a closed closed. Right? Yeah. Yeah. Especially since flows are, at least at least right now, just, an admin exclusive thing. So we kinda you know, like, security schmecurity. You know? Like, if you're already an admin, you you have different problems. Like, if your attacker is already an admin, your flow keys are the least of your worries, basically. Yeah. Yes. No. Yes. No. Yes. No. Maybe. It's it's tricky in that sense. It's it's weird, though, when you think about it. And this is the same when you're talking from a platform team perspective, this is the same problem you're seeing on, you know, AWS secrets manager or d o environment variables or something like that. If you have an encrypted value and you save it, you then, you know, s h into your container, you do print f and there they are. Right? It's like they're stored as secure as possible, but then in your running process, you can just print the environment and everything is right there. But you gotta figure out what is what is the right move. Right? Because it can you have read only access to flows where they're hidden? But then if you have update access now, by definition, you have a way to expose them. Right? Is there a way is there a different security level where there should be the the sort of admins that have access to secure stuff and admins that can edit flows, but they're not the same thing? That that's a different question. Yeah. I mean, if if we go down, you know, the the settings table route, then we already profit from our, authentication, authorization, system. So, you know, you you can already then assign oh, exclusively these people are allowed to read them, look at them, and stuff like that. So You don't need to plan out every case ahead of time. Well, then you're you're in the wrong stream, my friend. This this is what we do. And again, this is this is the divergent part of all this. Right? This is luckily Yeah. A lot of these things are not blockers to at least get to the minimum viable, which is let us explore these damn things. But Right. These these are the things that people will, you know, use it for and maybe use it wrongly and then maybe expose themselves to massive headaches and issues down the line. So I do I do wanna at least be aware of the types of things that we might see in the future. So we can either prevent it in code, make it better, make it make it better down the line or document it in a way or just warn people about some of the dangers that they might hit. Right? It's, it's it's fun that you mentioned it, but at the same time, we've seen people do shit before. It's like, make a cron job that runs every second and put something in the table. Table blows up. Whose fault is that? Right? Did we did we have to do something to prevent that? Is that a user error? That who's who's responsible? Exactly. Featurex activity, see revisions. Working working on that, by the way. Unrelated for this call. Don't tell. Don't tell. Hooray. Okay. I don't want the sidetracked too much, but, yeah, we have the, retention settings for that coming, shipping fairly soon. Thank god. Yes, Amar. If you want to. No. I don't wanna get in trouble with HR. I don't think that's a good idea. Goosebumps. Oh, no. Okay. So, just just keeping the time, in mind, we don't have that much time left. So maybe we should start to kinda converge now a little bit, You know, yeah, just to, get back on track a little bit. Oh, wow. And then the whole essay drops from Yeah. There goes the next 10 minutes. Oh, wow. Should we read that aloud? Are there bad words in it? Looks good. Okay. In my humble opinion, the whole edit complexity of environment migration I'm using directdis comes from the yaw application becoming data itself. Alright. While not using Directus, you can run different versions of the application side by side, and it's easy to switch version which version is running because the structure is defined within the application. Wildirectors, most of you. My guy, there there's not a single dot in that sentence. Oh my god. That's that's one sentence. Don't throw too much shade. And it the the gist of it is because all the configuration is in the database instead of in code, therefore, you have migrations back and forth prompts. Right? And to Joshua's point, that is definitely a configuration as code discussion, which I think we had a couple episodes ago, actually, which is a great segue. Directs.i0/tv under request review. Highly recommend it. The the the 5 second summary of that discussion is really around there's multiple use cases. Right? There's a lot of people that prefer configuring everything from the UX and UI and then making an export. So by definition, it is in the database. Right? It's it's a mixed environment where there needs to be a two way binding into configuration. We don't wanna end up in a sort of again, the choices are different different use cases, different type of people. I'd I'd rather not end up with a sanity slash strappy type of environment where you have to pull things locally to code, you know, your settings and then redeploy it. That is just not quite the vision that we have for, you know, the ease of use and the user experience for this. Also, I know from some inside chatter that they're trying to get out of that as well. So this is this is a bit of a two way binding discussion. Did you did you see They updated their comment and broke up the paragraph into multiple sentences now. Danielle, look at what you've done. I think this is called cyberbullies. We don't condone that here. Oh, no. Thank you for thank you for the, not not, what is it? Thank you for your cooperation, Wolfolas. Thanks for being here. Thanks for your message. We do appreciate it. I'm not sure how you say it, but Wolf Wolf of us is an awesome contributor. He's been an incredible community member and contributor and helps out across everywhere across the platform. So we are It turns out. Anyhoo, to your point then, converging it down to okay. What can we do? I think the the question that I do have is, do we wanna look into storing this as a nested JSON blob versus a separate table? Right? It would be a bit of a breaking change, but it simplifies both the output files and it simplifies the, the way to import it for us quite a bit. And it also solves that cannot resolve foreign key type thing bug in the same time. Right? The alternative is that we don't do that, but we avoid that breaking change in the operations endpoint with the downside that then for both export and import, we have to make sure that the whole nested tree is included at all times. And then during import, we do it in the correct insertion order. Right? Gut feeling wise, I'm kinda leaning towards let's blop it all as a nest of blob because it simplifies things. At the same time, couple downsides of that is that I think we'd lose the ability to choose what fields are returned from operations. I don't know if that matters as much if you're dealing with flows. Theoretically speaking, most of the databases now should support field selection for JSON. But seeing that we're talking about a theoretical infinitely deep object, that might be tricky. Right? Or we have to filter it down in in post after we got the data back. Quick quick tangent. Can SQLite do that? I'm not sure. I don't think so. Right? I think that update came earlier this year that they have some sort of SQL path, JSON path selection. Yeah. They they've got some JSON path. Yeah. It's fairly recent. That's also one of the reasons why I missed we couldn't really do this earlier. Right? Yeah. Oh, that's nice. Okay. Okay. Yeah. So the lights are getting a lot of attention because you've got companies like Terso and others that are using this distributed edge file based databasing, caching kinds of things. So there's some there's a lot of work going on in that space and SQLite's gotten some pretty good attention. But, I mean, vendor variation, I think, as we move towards hopefully, as we move towards Duris, you know, whether or not that vendor supports it, then we can decide sourcing wise how we handle that. But for the main I'm a big proponent of s Eskelet. Like, if if we if I do something, it it I wanted it for an SQLite, please. Okay. The end of this tangent. I'm sorry to I just I was curious. Yeah. Okay. So so I think because, you know, the nested JSON stuff is something we haven't historically done because we couldn't really do that cross database vendor properly support it. It is something that probably comes with new issues that we don't know about yet. Right? So oh, yeah. Somebody actually mentioned it here too. It was like, Joshua again. Get a shout out, Josh. Stick with the current structure because making breaking breaking changes to the operation config will get to be a huge problem if using nested JSON objects. It's gonna be easier if you have a single row that changes. Just fair enough. And also see support for older databases and vendors that don't have JSON support. Also true. Although, I I wanna say that the ones that don't have an end of life I guess SQLite, the previous version, not yet, of course. Yeah. So and and, also, obviously, the big breaking change. People have been exporting, importing things through the APIs. The separate tools have been made. We saw that BCC schema sync shout out earlier. So we wanna make sure that that is not a huge freaking change either, right, where we just completely wreck any of those existing things. So sticking with the current structure probably makes the most sense. And then that raises the question around, you know, data integrity and import order, but that is a technical problem to solve that we just have to do during import. So that does mean that it'll probably be a separate way that we, do this than than compared to your usual export import just because order matters and that integrity matters. No. That's fine. That should be really doable. You know? Walk the tree once and then just pop off from the back. Yeah. And and the age old question, is this part of the schema export? Yes or no? Oh, right. The the gonna be a discussion for a different day, which is discussion we've had before around roles. And the yeah. But Joshua basically is concluding as well. We just need some schema export flags, which is, like, what do we include? What do we not include? This this this is the discussion we had exactly the same around roles. Do you wanna include roles and permissions? Probably. Do you wanna include users? Probably not. Do you wanna include permissions? Probably. Do you wanna include all of the permissions or just the ones that are about your production databases? Probably just the prod ones. How do you filter that down? This is the exact same stuff. Right? Is it all the flows? Is it some of the flows? How do you choose which of the flows are included and which ones aren't? Do we just export everything and then assume that somebody goes into the file and deletes them manually? Lots of more fun questions to be had in this. And for that, I wanna say, subscribe, like, and subscribe. Nope. I think Hit the bell. Hit the bell. Always been. Hit the bell and make sure you don't miss that episode when we go deep on that. Now selective import export is gonna be needed for most of these things, I think. And ideally, whether export could export everything, but selective import on the import side, the ability to choose what I'm actually merging into the next iteration is is key. Right. Oh, that being said, I've not been muting. I'm muting. I'm muting. I'm muting. And I'm muting. The the doorbell is ringing, so I just wanted to make sure it didn't get too annoying. But that being said, we're at the top of the hour here. There's one more question that just came in. So another quick thought, what about pulling changes instead of pushing them in? Like, a sort of federation type of thing where you link data from multiple direct instances, you pull change from another instance. That sounds like a discussion for another day. I think we've had that as part of the dual syncing as part of the configuration as code anyway. It is something that we we've we're we're thinking about, on that side of the house, and that's this is part of that as well. Right? So the configuration as code affects this, having utilities that make this easy now, versus, you know Yeah. I I think that two way bind to me always has the file in between. So you push it from dev to file, and you pull it from prod from file. That is kind of the the the one to jump. Anyways, with that being said, thank you all for tuning in. Thank you all for the great questions and ideas in the chat. This episode will be available on Directus TV in the very near future. Shout out to shout out to Nat. Dan, did you make sure there's any any Zingers in here? Do we have the thumbnail? Oh, that's not quite sure. May may maybe the the technically technically correct, maybe. I'm not sure. There you go. That's that's the perfect one. That being said, check it out drex. Io/tv. We'll be doing this again in in the near future.","published",[139,150,160],{"people_id":140},{"id":141,"first_name":142,"last_name":143,"avatar":144,"bio":145,"links":146},"23ebcf2c-4374-4f5c-8198-f8ad497fd856","Rijk","van Zanten","7ef9652f-3835-432c-a43a-c5fe13001f31","CTO of Directus",[147],{"url":148,"service":149},"https://directus.io/team/rijk-van-zanten","website",{"people_id":151},{"id":152,"first_name":153,"last_name":154,"avatar":155,"bio":156,"links":157},"0d906492-75f0-45d9-abf7-ab779bf1ed08","Jonathan","Wagner","5062e4df-a198-4b40-af47-42362d3c0551","Sales Engineering Manager at Directus",[158],{"url":159,"service":149},"https://directus.io/team/jonathan-wagner",{"people_id":161},{"id":162,"first_name":163,"last_name":164,"avatar":165,"bio":166,"links":167},"07ec688d-251d-4efe-bc17-73848402d43b","Daniel","Biegler","8897b70f-c524-460a-8990-58cc5c3be886","Engineer at Directus",[168],{"url":169,"service":149},"https://directus.io/team/daniel-biegler",[],{"id":172,"number":173,"year":174,"episodes":175,"show":188},"6aa046f1-bd53-4510-9af0-c0f3daaf4415",1,"2024",[176,177,178,179,180,181,182,183,184,122,185,186,187],"daed2c08-703a-43d6-ac97-aacac61be4c0","86fa152b-6a8b-477e-94b5-bd91e1202d21","0b5f4343-1494-455b-b41a-25811c151242","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","8896c934-aa2c-43b6-9342-8275682ab8b2","84c7b3ac-fd85-4539-8f39-3247118bcbf2","044b7c89-aaec-43b2-9d6d-6743a0fb5afd",{"title":189,"tile":190},"Request Review","73687d01-3734-4c28-aef7-e6fa8db4cf1e",{"title":8,"meta_description":8},{"id":185,"slug":193,"season":172,"vimeo_id":194,"description":195,"tile":196,"length":127,"resources":197,"people":8,"episode_number":200,"published":201,"title":202,"video_transcript_html":203,"video_transcript_text":204,"content":8,"seo":205,"status":137,"episode_people":206,"recommendations":210},"9161","1004131420","In this recording of our live event on August 29th 2024, Daniel, Jonathan, and Rijk discuss Additional Form/Field Layout Options.","fb2eeeee-6c4e-4227-adb1-9806fc50f2cf",[198],{"name":130,"url":199},"https://github.com/directus/directus/discussions/9161",11,"2024-08-29","Additional Form/Field Layout Options","\u003Cp>Speaker 0: We are covering additional form and field layout options. This is actually related to our item editing experience, and it is something that I would actually love to have. We're very we have some awesome capabilities right now, but the 2 field across kinda limitation, it would be nice to have some more flexibility there. So that's our discussion. This is discussion number 9161.\u003C/p>\u003Cp>I'll drop it in the chat in case anyone wants to follow along there.\u003C/p>\u003Cp>Speaker 1: Oh, 4 digits. You know, it's an old one when you're in the 4 digits.\u003C/p>\u003Cp>Speaker 0: Oh, yeah. This is an oldie. An oldie but a goodie. This was an October 26, 2021 Ben Haines special.\u003C/p>\u003Cp>Speaker 2: Oh, damn.\u003C/p>\u003Cp>Speaker 0: But it actually surprisingly, this was pre RFC, but Ben actually put in example screenshots, good description. It wasn't just a one liner. I I was actually very pleasantly surprised when I opened this up to review it.\u003C/p>\u003Cp>Speaker 1: Yeah. It's it's a good day when the feature request is not a one liner. It's Yes. It's great. Yeah.\u003C/p>\u003Cp>Speaker 0: So I will let you guys kick it off. Alright. Well, 4 pages.\u003C/p>\u003Cp>Speaker 2: Yeah. Right. So if I understand this correctly, we are talking about having a different layout for editing entries, which we currently do in 2 columns. You can divide your editing experience into a left column, right column, or go through with the whole input field? And wouldn't it be nice if we could do something else?\u003C/p>\u003Cp>I guess, it's the question. What could we have?\u003C/p>\u003Cp>Speaker 0: So yeah. That's the the general question is a little bit more flexibility, more feet you know, again, things like toggles. Right? Don't need even half width. They could be 25%.\u003C/p>\u003Cp>3rd. You know, maybe maybe a percentage based. Some of the more the more interesting feature styles, I think, that we can do today or that are possible. So Ben's got some different examples of what you might wanna have for layout options. Although this this was actually noted a little bit further down in this request that putting the label to the side is actually negatively impacting to users' experience.\u003C/p>\u003Cp>It's not not a recommended practice in general, but having some flexibility and being able to do some things. I think more so just being able to add more more configuration in the layout style, and and how things get positioned It's the general my my general client feedback, community feedback that I've heard, you know, in general with meetings and talking to people is just the ability to have more flexibility in the item editing design experience.\u003C/p>\u003Cp>Speaker 2: So quick question.\u003C/p>\u003Cp>Speaker 1: Yeah. I was gonna I I I think you're gonna go the same way as I'm gonna go, Daniel, but I'll let you go first.\u003C/p>\u003Cp>Speaker 2: Not sure. I'm I'm just, I just want to clarify a little bit because, because of the screenshot. So currently, I think we're only talking or a question. Are we only talking about the layout in and of itself? So just positioning of elements beside each other, or are we also talking about different visual styles for the same interfaces?\u003C/p>\u003Cp>Because, when you scroll down a little bit, for the checkboxes, for example, they look different than what we have currently. Is also part of this, idea that, for example, you can have multiple different, toggles? Let's say the this one this let's call it filled in toggle or a different toggle. What about the, like like, what is it checkboxes? Now the selects where you can only select 1, like radio buttons for example cause they are a couple of examples here right the product category for example.\u003C/p>\u003Cp>Because they look different. Like, are we currently just talking about the layout or are we also talking about different styles?\u003C/p>\u003Cp>Speaker 0: Let's look.\u003C/p>\u003Cp>Speaker 2: Okay. Oh,\u003C/p>\u003Cp>Speaker 0: no. He's got interface options to add well. So he's adding additional interface optioning capabilities as well. I thought, initially, I missed that. I thought it was just the item view formatting, you know, tab styles, other kinds of capabilities potentially.\u003C/p>\u003Cp>It's another frequent one that we see is instead of having just a full list of fields. Right? We have detailed things currently, but like a tab style interface there as a presentation layer. Could be other things we can consider. We can decide what we want this to be.\u003C/p>\u003Cp>We can narrow this. We can put this into RFC spec format, when we're done. So I'm happy to, well, you know, we'll do our let's do explode and then figure out\u003C/p>\u003Cp>Speaker 2: what we\u003C/p>\u003Cp>Speaker 0: want this to actually cover when we're done. So primary things that clients currently right? This is your current capability. Let me grab one that's got some, do I have one with groups? Remember if I've got something with field groups in it.\u003C/p>\u003Cp>Top of my, those products haven't.\u003C/p>\u003Cp>Speaker 1: Why?\u003C/p>\u003Cp>Speaker 2: You guys I think in in the end, when we when we scope down again, in the end, we can probably, like, make a make a rough, MVP of this feature where we just say, okay, maybe this is just it. But if you wanna take it further, then it would also include different, visuals for the same interface.\u003C/p>\u003Cp>Speaker 0: Yeah. So these are kind of your current options. Right? You can have field groupings. Right?\u003C/p>\u003Cp>And otherwise, you got it didn't half with. So to me yeah. I think we should start with with let's let's think about the I think I mean, options to existing interfaces could be discussed here. But I think in general, the way that this thing started and the way that I see this, the the biggest struggle that clients have today is you have very limited kinds of options actual form editing experience. How things can be laid out.\u003C/p>\u003Cp>Yeah. For sure. I think the other parts,\u003C/p>\u003Cp>Speaker 1: you know, a toggle instead of a checkbox, that's a new interface. That's just a custom interface or an option or stuff like that. But it doesn't really change the way the form itself is rendered. So I think for the sake of this discussion, we can focus on that. Cool.\u003C/p>\u003Cp>I think some of the bigger ones that we see here in the feature request is around where does the field label and description go. I think that is sort of one bucket. Does it go top? Does it go bottom? Does it go left?\u003C/p>\u003Cp>Does it go right? Then around how do certain groups come together? So there's like a sort of a new group UI, like a group of the title, and it's in a gray box instead of on a white background sort of visually, you know, cluster some of these form inputs, which then made some where the descriptions go. And then the other one is around, and it's not so much in the original screenshots, funnily enough, but it is I think of an important one here to bring up is what does the grit look like if you go beyond 2? Right?\u003C/p>\u003Cp>And and, where I can see this discussion going quickly is what about responsive? How does that work? And what about, on the screen that is about 6 meters wide, to make that work in a way that is still user friendly?\u003C/p>\u003Cp>Speaker 2: That is a good question. I this reminds me of a small little bug if we want to just take a little tangent for a story time. Because we have this little bug, where if you have a checkbox with multiple, options, we change the way how they are displayed depending on how many options you have. So if you only have 2, then they are right beside each other. But, for example, or if you have, like, I don't know, 5 or let's say 10, then we put them below each other.\u003C/p>\u003Cp>And we had this interesting fun little little bug is that we made this also dependent on the content of those checkboxes. So if you have long text, then we actually, you know, span the whole width so you can actually read the thing inside of the checkbox. But what this resulted in is that actually, in like languages which are very short and there are languages that which are very long, like in German words, you know, which means that you have different layouts depending on what kind of language you have. And then, there were a couple users that used Chinese characters, Mandarin characters. And this then resulted, like, if you translate it and then you got different layouts for different languages and stuff, that that was quite quite a fun thing.\u003C/p>\u003Cp>I think I fixed that, by the way. But, okay. Enough of that. Sorry. Yeah.\u003C/p>\u003Cp>Let's see. I mean, there's there's lots of perspectives. Right? Like, how many columns should that be dynamic? Do we want to provide a fixed fixed width as of right now?\u003C/p>\u003Cp>Like, 2. Let's just say, okay. You get 12. Is that good enough? And how do you configure the responsiveness?\u003C/p>\u003Cp>Then how do we have breakpoints? How many breakpoints do we have? 2, mobile, desktop, but not every screen is the same. How do you configure that? Do do we even want to configure that?\u003C/p>\u003Cp>Like, yes, but no. Meh. I mean, really, how much database work and actual data modeling are you interested in doing on mobile, to be honest? Like, how many people actually, editing the databases and data records on the phone? Like, how important is he's he's funny.\u003C/p>\u003Cp>The answer\u003C/p>\u003Cp>Speaker 1: is very important.\u003C/p>\u003Cp>Speaker 0: This guy does.\u003C/p>\u003Cp>Speaker 1: You'd you'd be surprised by how many people use mobile or mobile adjacent stuff now too. Right? If you have the folks with flip phones and you have people with with, you know, small iPads or, yeah. Yeah. Just going by the chat.\u003C/p>\u003Cp>People are saying the same thing too. Mobile interface, main point, which isn't direct is people editing videos on their phones. The people do everything on their phones nowadays, and I'm one of them too for what it's worth. So when it comes to grit and responsive, this is this is one of the reasons why, there's a lot of apps that are sort of, like, app builders, like a read tool, for example, that opt to make it a scrollable window when you go smaller for this exact reason so it doesn't have to do any sort of weird new reflowing. There is tools out there that I won't name by name that just straight up say there's no native there's no responsive design at all.\u003C/p>\u003Cp>There's no mobile version. There is different ways of of handling that. The way Directus does it right now is in the in the sort of 2 grid in the 2 up, the screen gets too small, becomes a one up. And that an easy easy enough sort of reflow to make. Right?\u003C/p>\u003Cp>Because whatever used to be side by side is now beneath each other, and that is good enough. Right? It it's it's what you'd sort of expect to happen, and it doesn't really cause anything too strange, from happening. If you're in a 6 column grid or so, like, if I'm scrolling down this feature request a little bit more, there were some screenshots from a tool called They have, like, a a sort of rich layout, which is roughly 4 columns. But then within, you know, one of the columns, there's another sort of 6 column y thing nested.\u003C/p>\u003Cp>And now I'm like, okay. Well, if you're responsibly squishing that down, weird things will happen. Like, what goes where? How does it flow? How does it grow?\u003C/p>\u003Cp>Do you expect, like, the 4th column to become, 3 columns of white when it goes to the next one? Do you intend it to still be blocked, but then you have 3 and 1 sort of weirdly underneath it? Or does it switch forward to a 2 grid? There's there's weird questions that happen at that point when you go down. And all so how does it interact with other fields that are then further down the page?\u003C/p>\u003Cp>Right? So right now, because every field is basically just in the same, same list of fields, It would start showing up side by side with other fields in that same grid, which could get funky and sort of unintentional. So one way around that potentially is to instead of doing a grid, let me do it now where it is based always one column, but there's a group type for creating grid sections in your form. Right? Because that way, it will always wrap within just that group.\u003C/p>\u003Cp>You don't your unintended interactions with other fields further down the page. And then that also means that you can start nesting those in whatever way you want. So if you're trying to re replicate that sort of 4 knocks set up where you have 4 columns, where the 4th column itself is like a a 6 column grid or something, you could because you can start nesting those those grid forms. Right? And it it kinda starts responsively matching the column size rather than the form size.\u003C/p>\u003Cp>Hannes in the chat says, additional groups feel cumbersome to set up. Yeah. Fair. Although at the same time, you know, to achieve the same thing that we have now, you could have one group and just put everything in it. Doesn't necessarily, you know is that is that what the price of admission get for, flexibility in the new layouts?\u003C/p>\u003Cp>And then on that same note, you know, the the some of the other layout settings, like, is the field name on the left or on the top, the description on the top or on the bottom, that kind of stuff could be settings of a group. Like, it doesn't have to be, settings of the whole form at once. Right? We could also say that the form, by definition, just has one root group, and therefore, it's always there, but it uses the same same system.\u003C/p>\u003Cp>Speaker 2: Alright. I can see that work in my hand. Like, is there a leaner way with less clicking? Currently trying to, like because if for me for me personally, the I I want I would want it to be as least intrusive as it can be because because I just wanna set up my thing and I wanna keep going. Right?\u003C/p>\u003Cp>Like I do not want to spend my time with designing, you know, layout. Like like this is like, I'm not sure how to say it. Like I I want to model stuff, I want to make like this this is how it how it works now. Like I just want to model stuff left, right, things and move on, you know. And I have other stuff to do.\u003C/p>\u003Cp>I have problems to solve as a administrator, let's say, of an instance, and I just wanna put some stuff in and keep going. So if you then have to jump through hoops and and, you know, like with all the, oh, but then on mobile, because I didn't, click on the full width. Now on mobile it is only half and it looks bad. And then I have to click this again and then the drawer opens again and I have to go into specific settings of a thing and then close the drawer again and choose the other. And that's that that feels icky.\u003C/p>\u003Cp>Like, I'm not sure if if we could design it in a way maybe with just small little toggles, like, without, specific options for those interfaces, when, like, the drawer opens, maybe we can make them just, small little toggles that you quickly go through just just without leaving the modeling page. Maybe maybe I don't know, like, it did did that make sense?\u003C/p>\u003Cp>Speaker 1: It does. It it's a, you know, it's a tricky thing because on the one hand, it's like if you wanna do it sort of quick and dirty, so to speak, then that's fine. That should be possible. At the same time, if you wanna make the best user experience for your end user so so let me back up a little bit. I think there's a difference in, flow when you're first setting it up and you're doing the data modeling versus when your data modeling is done and sort of finalized and you go into the details to make it a nicer user experience for your end user.\u003C/p>\u003Cp>At which point, you might set up, you know, I wanna use monospace for an input and add a little icon to make it, you know, friendlier for the end user, that kind of stuff. Right? I think that is also where this whole gridding stuff comes in. It's like, do you care about grids and how it responsibly shows up side by side instead of ordered top to bottom? Well, if you're doing the data modeling, possibly, probably not.\u003C/p>\u003Cp>It's just like you need to have the fields to check if it works, build the integration, move on. Right? Only then when your data modeling piece is done, can you circle back and be like, okay. Now I'm gonna spend an hour or so to just really make this form the best form it can possibly be for the use case that I have. I wanna conditionally show and hide some things.\u003C/p>\u003Cp>I wanna do it in certain sections have to be like a 4 up grid or a half half width group where, I wanna order it differently, etcetera, etcetera. Right? So I think there's 2 different points in time and 2 different, user flows that that are related. So to your point, I do agree. It's like for that first one, I mean, you're just setting up the data modeling, experimenting with what fields and what names and everything else.\u003C/p>\u003Cp>Quick and dirty. You don't wanna be slowed down by having to think about, is it 2 or 4 or 6 columns? Like, who cares? Just go quick. Right?\u003C/p>\u003Cp>Make it work. But I do think that is where we can introduce that additional flexibility that we're talking about as part of this this feature request to saying, well, if we hard code this form to be 4 columns instead of 2, we're gonna have the same discussion a month from now where it's like, okay. What about 6? Right?\u003C/p>\u003Cp>Speaker 2: Yeah. And we're\u003C/p>\u003Cp>Speaker 1: gonna have the same discussion a month from now where it's like, okay. Somebody wants 12. So by doing it as a group extension type where we say, okay. The group is just the thing that makes it x number of columns and we don't care. We allow that flexibility in a sort of opt in type of fashion rather than us having to predefine, okay, a direct this form is always x.\u003C/p>\u003Cp>Like, it is now. We say it's always to deal with it. Right?\u003C/p>\u003Cp>Speaker 2: Yeah. For for me, priority would be, just looking at at the screen right now, let's see, let's look at the theming group, right, or the SEO group also. I would like to avoid, or it would be it is near and dear to my heart, you know. Like, if I now want to split the theming group, I don't, like, I don't want to be the kind of back end where you have to click on the, 3 dots, then a dialogue or, like, a popover opens, then you have to click on edit fields, then the drawer opens, then you have to go inside of that, and then you have to configure some type of grid system and break points and stuff and then the whole thing closes and then, oops, I forgot one thing, I have to go through the entire thing again like this. Like I really want to avoid that.\u003C/p>\u003Cp>So I'm like, okay, And we maybe make sure that this doesn't happen. Maybe we can include some controls that are maybe enough already on the screen right now. So like, side the three points where the options would be, maybe there could be quick toggles where you can very quickly just with one click, like, boop, and then it's half view. And, you can configure it and then another click, boop, it's it's it's the mobile view. And then you can configure it again.\u003C/p>\u003Cp>Yeah. How about that?\u003C/p>\u003Cp>Speaker 1: So the reason why it has to be a drawer now is that those groups and interfaces themselves are an extension type. So, therefore, we don't know what those options are. Right? So if somebody makes a new custom grid group now, which you could theoretically, the options for that group is like a an open ended question mark. It's just a set of fields, and we don't know what they are.\u003C/p>\u003Cp>And we don't know how to, you know we we know how to render them because we ask you we ask the extensions, like, what options do you wanna render? And it's basically just another view component. Right? So it's like a black we just anything goes into that drawer and have have at it. So we can do that.\u003C/p>\u003Cp>We'll have to come up with some sort of standardized syntax for those plugins to say, here is the 2 or 3 things I wanna be able to edit in line that makes sense for this type of thing that I'm doing. Or we have to go the other way and say, well, we just built more of an Apple approach. That's who it where we say, well, the direct extensions are special and they get to do some of these inline things, but regular extensions are back to the old drawer style. You know what I mean? It's just that that flexibility angle because all of these are extensions.\u003C/p>\u003Cp>Speaker 2: Yeah. I get it. That's a bummer. Like, because we we strive and we always, our strength, right, is that everything is so super duper flexible that you can do anything yourself. Yeah.\u003C/p>\u003Cp>But for this, can we?\u003C/p>\u003Cp>Speaker 1: It's a question. Right? I I think when it comes to the drag and drop UI of of doing the layout of the form, if if you have a 4 grid, we have to show it as a 4 grid in line there as well in your editing experience. Like, that, I think, is is definitely something that we have to code in. But then if there's a group that has an option for number of grids, how does that how do we connect the dots?\u003C/p>\u003Cp>Right? How do we know that the grid column option in or an extension should be mapped to our editing experience for the form that makes it so that makes it work like that. Or again, maybe that there's the case that we say, well, you know, the way to handle grids is just not an extension type and there's no way for extensions to do that. It's just the native direct listing. Where we stay, okay, form layout, order, and grid, that is just a a direct as native thing.\u003C/p>\u003Cp>You can change it through extensions or anything else. You can still make a custom group, but the layouting options for that is not something that we can natively, manage on your behalf. Like, that that is also, you know, an option.\u003C/p>\u003Cp>Speaker 2: Mhmm. Yeah. Like, I I would be like, let let's let's just, you know, the, gut gut feeling is just this sounds reasonable because it's not actually concerning your data. It's just like our our, product UI. So it makes sense that we have this control of the layout.\u003C/p>\u003Cp>But I can already see, like, it's this is gonna be the first comment in that PR. It's like, oh, but I really would like to do this in my thing. Can we can we add that also? And then every time. Every content.\u003C/p>\u003Cp>Okay. Alright. So so this is the layout type of thing of that PR of that of that RC. I think it just okay. Let's you said in the beginning the other interfaces are mostly just other interfaces, so they aren't really concerned with this.\u003C/p>\u003Cp>Speaker 1: I think the difference between a checkbox and a toggle, that is an interface option or that is a new interface. I don't think that has anything to do necessarily with form rendering. So I think for the sake of this art for this discussion, we can just keep the scope to form rendering itself. I saw there there was some a couple of good points in the chat earlier right before we started with a couple of points around a little bit more general updates to forms and and interfaces, what we can do with it. 20 minutes ago, somebody was saying, it will be cool if you have, like, a 3, 4 column layout instead of just 2, expand the form width.\u003C/p>\u003Cp>So it's like the whole screen instead of just, you know, a a max width. But you could kinda do because there's, like, a full width option for an individual in the face or group, but it's I I do agree it's the whole form. It doesn't quite quite work like that. Aligning the form itself to the left or the center of the screen or maybe even the right. And then it gets into which I feel like a bit of a different feature request, but I wanna call it out because it's in all caps, so it sounds important.\u003C/p>\u003Cp>Actual relation drop downs, which I think is just make making sure that a second drop down is updated based on the value of the first drop down, which is, again, kind of not really\u003C/p>\u003Cp>Speaker 0: formed. I think it's actually I think it's actually more related to the relational interface itself right now. They always go to a drawer. I think it's more of the so like, a many to 1 or one to many.\u003C/p>\u003Cp>Speaker 1: Oh, that part of that nature drop down.\u003C/p>\u003Cp>Speaker 0: As opposed to a drawer pop. Yeah. That's an interface itself. That to me is again, I think we're kind of a little out of scope for this for what I think we want this review to cover in detail. Okay.\u003C/p>\u003Cp>Yes. There are there are dozens of things we would all like to have on the interfaces side of the house, but that's why custom extensions exist and you can't build them. So although, you know, this grouping style that we support, I have seen tab style, the group interfaces where someone has built a custom interface that actually does, like, tab styling and multiple fields and tabs and things inside their groups. So custom extensions support those kinds of things. Yes.\u003C/p>\u003Cp>Relational drop downs instead of drawers would be really nice in many use cases.\u003C/p>\u003Cp>Speaker 1: You know, it's, you know, it's funny. This is a complete sidebar, and I I wanna be cognizant that we don't end up spending 20 minutes on this because it's an easy one to slip into. But the many to 1 interface, the drop down one that opens drawer, it has the the actual drop down bits built in. It like, when we built it, it had that baked in. It's the problem was that similarly with most every other thing in direct is, like, week 2, somebody was like, I have a 100,000 items in the related\u003C/p>\u003Cp>Speaker 0: Yes. Related table and I I am now going to break your interface. Outright.\u003C/p>\u003Cp>Speaker 1: The drop down only shows the first a 100, so I cannot find the thing to select. And I'm like, yep. Yep. Yep. Yep.\u003C/p>\u003Cp>Yep.\u003C/p>\u003Cp>Speaker 0: Yep. So then\u003C/p>\u003Cp>Speaker 1: then we made the call to, like, always show it as a drawer, which works for everything, but it's it's not as nice as a little drop down. But it it used to work like that at one point in time. Yeah. Yep. Yep.\u003C/p>\u003Cp>Speaker 0: I know we've had bring that\u003C/p>\u003Cp>Speaker 1: back as a as an option to to but but the the funny thing there is, like, to do it the best way possible, we need to have an updated count of the number of related items at any point, and getting that count can be very slow if you have 100 of 1,000 of them. So we have to come up with some sort of way to cache the count our site first so we have a sort of estimate count that we can use and then update that over time because, otherwise, it's gonna be not performing enough to do you know? Anyways, long story short\u003C/p>\u003Cp>Speaker 0: Yes. Similar thing that so we did that for the actual layouts, as part of that performance improvement a year or so back, a year and a half back, where you started caching the accounts and not running the count every single time, only watching for changes or what. I'm not sure what happens behind the scenes in the caching aspects. But for those clients who had millions of rows of data and being able to present that and reflect that and not pulling\u003C/p>\u003Cp>Speaker 1: everything Something like that. Yeah.\u003C/p>\u003Cp>Speaker 0: On the counts. That's so The database running every single time you clicked was hugely performance impacting. So\u003C/p>\u003Cp>Speaker 1: Yeah. There's there's also some databases, and this is, of course, where the devil's in the details here. Some databases also have a difference between, an estimate count versus the actual count. So, like, in Postgres, there's a system table that keeps an estimate count that is not guaranteed to be accurate, but it's sort of a ballpark. So at least, you know, are we over under on 1,000, or is it just, you know, a couple?\u003C/p>\u003Cp>Yeah. So there's also a world this is again a big sidebar, but such goes in these episodes. There's also a world where we first get the estimate count, which is cheap. And then if that estimate count is less than a couple thousand, then we meet the actual account. So we can show that.\u003C/p>\u003Cp>Nice. Anyways, that is a whole different\u003C/p>\u003Cp>Speaker 0: That is a very different ballgame and Oh, okay. Another discussion.\u003C/p>\u003Cp>Speaker 2: Mhmm. Mhmm. That that's a fun one. Okay. How many items do I have?\u003C/p>\u003Cp>And you asked the database and it's saying, probably 10,000 maybe? Best I can do.\u003C/p>\u003Cp>Speaker 1: Yeah. It's it's an interesting problem though because it's one of those things where in order to know that, it's it's, what is that in COMS size? Is that one of those o n problems or an o two problem? Where you know what I mean. Right?\u003C/p>\u003Cp>Where it's like, the more items you have, the slower it gets linearly to count the number of items. So, therefore, if you have a table with with 20,000,000 rows in it, how do you know it's 20,000,000 rows efficiently? That's weird. Yeah. Oh, and, yeah, that's that's what I thought.\u003C/p>\u003Cp>It's it's clear that if not comp side. I'm still just a UX designer, guys. Take it easy. Cool. Some of some of the other stuff in the chat here before I I miss it again.\u003C/p>\u003Cp>So it says, I wanna speak with a person with a 100,000 items. I need a quick chat.\u003C/p>\u003Cp>Speaker 0: Oh, for\u003C/p>\u003Cp>Speaker 1: what it's worth, we, we even do a similar thing ourselves where we have, you know, we keep, error logs for, you know, certain cloud deployments. Those error logs have a one to many back to the project, so we can see the most recent 10 per project. Right? But that also means that the whole error logs table can be in the millions. So that one to many needs to be prepared for, you know, what that looks like if you said select existing, and now all of a sudden you have a list of 10,000,000.\u003C/p>\u003Cp>Like, how does that work? Right? It it's it's a very real thing that people do, ourselves included, which makes some of these discussions a lot more fun if you're thinking about it many to one. I am making the drop down nice and easy. Nope.\u003C/p>\u003Cp>Yep. Cool. And then on this another one says here, it feels like we could add a special component that can be defined for group interfaces where they decide on the layout for field layout. Right. Yeah.\u003C/p>\u003Cp>So this is similar. This is going back to the, how do we do inline options for groups? Right? So honest suggestion here is basically saying, well, maybe just like inner like options for interfaces, there's a way to say, let the actual form extension itself decide how to render on the settings page so we can make that optimized, which is, yep, interesting. Something along those lines.\u003C/p>\u003Cp>There's something about a half width group. That's fine. Otherwise, do it with 2 columns. I think we touched on the other stuff. Right?\u003C/p>\u003Cp>Cool. Then the second thing is around in this feature request rather, is around, where does the label go in a form? And is it something that you should be changing? Or is that something that is just not something you should care about? It's an interesting one.\u003C/p>\u003Cp>Kava is it it gets to a bit of a user experience question. Right? And and this is, again, a topic that can easily get off the reels in terms of theming and customization and how far do we wanna take it in the sense of, you know, if you give the end user infinite flexibility in this kind of stuff, you also give them infinite food guns to make it trash, right, for the for the end user. So there's a there's a very real discussion around, you know, is form labels left aligned input, right aligned? Is that good for good?\u003C/p>\u003Cp>There be opinions. Is that good for the end user or not? Right? And then the question becomes, who should be in charge of making that call? Because we make a lot of calls because it's a studio.\u003C/p>\u003Cp>Right? And it's the same, yeah. Yeah. Hans says the same now. It's a layout too.\u003C/p>\u003Cp>Once you have weird layout problems, you get a similar similar, UX problem. Right? But the question becomes, who's responsible? Right? Do we say well, because we built the studio, we have good defaults.\u003C/p>\u003Cp>We wanna make sure that everybody has a good user experience. That's what we pride ourselves on. Therefore, are we gonna limit some of these things? Or are we gonna say, go nuts, and it's your problem, which is great for some and a problem for others. Right?\u003C/p>\u003Cp>And we've seen this before. We've seen this in the past. Like, when we ship theming, which I think has been been pretty pretty good to have, generally speaking. It opens some of those questions too. Right?\u003C/p>\u003Cp>Because I I know, my very own Kevin made a, like a teenage mutant Ninja Turtles one, or or what do we call it? Something non something not trademark related, as as a sort of experiment to see where how far you can take it, but it's also objectively horrendous. It's objectively bad, right, for for user experience wise. But who who's who's responsible then? Right?\u003C/p>\u003Cp>And and where do you draw that line? I think it's an interesting question here too because, like, if we make a if we kept just if you make a 12 column grid, you can do some very powerful, easy to use layouts. You can also easily make a garbage nightmare. Just like you can make a dumpster fire. Who's then responsible for the dumpster fire part of that?\u003C/p>\u003Cp>Speaker 2: Yeah. Because the yeah. Like you said, this is an actual thing. Like, if somebody badly configures their instance, it may reflect even bad on us because, like, the users come in and say, like, oh, what what what oh, brother. Oh.\u003C/p>\u003Cp>What what happened here? You know? Like, Directus is ugly. Directus doesn't work. Oh, this is not good.\u003C/p>\u003Cp>And then it reflects bad on us. So actually, we should think about that we make I mean, you know, flexibility is nice. It is it is cool, and it is one very, very good point for us. But to what extent? Like you said, okay.\u003C/p>\u003Cp>So we we do have to so\u003C/p>\u003Cp>Speaker 1: quickly and I love it.\u003C/p>\u003Cp>Speaker 2: We do have to draw a line somewhere.\u003C/p>\u003Cp>Speaker 1: There there's an interesting part of the tech industry that people have been yelling about for decades now, which is the whole Android versus iOS thing. Right? Or Linux versus Mac OS thing, which is, like, for the longest time on iOS, you cannot you can you can reorder your app icons, and that's about as much customization as you get. Right? For the first couple of iOS, if the background was black, shut up.\u003C/p>\u003Cp>Your wallpaper on the lock screen was the was the globe. No options. Right? And then they were like, oh, maybe maybe you can have maybe you can have a wallpaper, and then you could have some fish instead of a globe, and then that was it. Right?\u003C/p>\u003Cp>But then, you know, people on on the Android side of the house have been screaming for decades. Like, oh, my wallpaper moves this fantastic life great. But, also, you can make an absolute dumpster fire of of your phone, which is whose problem is that? Right? Is that is that you're gonna make it better for the power users, but you also give a bunch of food guns to everybody else?\u003C/p>\u003Cp>And for what it's worth, Apple is now doing the same thing, I think, right, with this new iOS 18 where you can, like, tint your app callers or something, and it looks horrendously bad just just objectively. Of course, it's an opinion, but I'm right. It's objectively bad. Where because you just see the icon from, like, I don't know, Notion or something turned bright yellow because you you tinted it that way. It's just not good.\u003C/p>\u003Cp>It's just not work. But the question is, like, you you can make it good with a bit of effort, but people don't will not. Is that is that a problem? Like, is that\u003C/p>\u003Cp>Speaker 2: It it the older I get, the more I think, yes. That's a problem.\u003C/p>\u003Cp>Speaker 1: Because the So you're gonna look at an iPhone now, and you're like, man, that is ugly. It's so good and hard to use, and I don't care. But at the same time, the the people that set it up that way for themselves, they might love it. It might be their preferred Yep. You know, becomes an opinion thing.\u003C/p>\u003Cp>Right? But it's like, how do you decide where to draw a line?\u003C/p>\u003Cp>Speaker 2: Yeah. Quick. Because there was the the quote from, I think Henry Ford, was it? Like, with the car, like, you can have, the Ford in any color that you'd like as long as the color is black. Black.\u003C/p>\u003Cp>Yeah. Right? Yeah. The same for iOS. You can you can do anything you like, but as long as it's not what you like.\u003C/p>\u003Cp>Yeah.\u003C/p>\u003Cp>Speaker 0: As long as you like what we like.\u003C/p>\u003Cp>Speaker 2: Right? Exactly. Yeah. So, like, I I think I personally I mean, of course, this is just, you know, opinion piece. Careful.\u003C/p>\u003Cp>It's I think we should be for the live stream, and I posted a picture of, Tim did Ios screens. It it is something.\u003C/p>\u003Cp>Speaker 1: And these are the ones done well, mind you. Anyways yeah. So so for for the listener, it's basically, you know, 5 different iOS screenshots with, like, different color background, and then all of the front, front end, all of the the icon colors, is is the same color as the background. So, therefore, at a glance, everything looks the exact same. It's just that's that's the main issue for me.\u003C/p>\u003Cp>It's like, I don't know what app is what app anymore because they all look identical to me now. Google oh, man. This is such a sidebar again. But Google did the same thing. Right?\u003C/p>\u003Cp>When they went through the whole material design thing, now every single Google app looks the exact same. If I log in to our Google Workspace and I click on apps, I just see the exact same icon, like, 200 times, and they are all the same. It's there's a small variation in shape, and I just don't know it. Anyways, yeah, it is let's try to get that back on track. It it is an interesting discussion in general, though, for of, like, how far do you let people take it?\u003C/p>\u003Cp>And and is it a good thing, or is it a bad thing? And where do you draw the line? I think in this case, as long as we have good defaults, I wanna on the side of let them have the flexibility, but make sure that by default, for the people that don't spend the time setting it up, it looks good and it works well. Right? Mhmm.\u003C/p>\u003Cp>I think that's kinda where your earlier suggestion comes in for, like, if I just wanna go in at a con at a bunch of fields and not think about it, we need to make sure that things work out the right way at that point. It's like, what makes sense? Help the user as much as possible to have a good default. And then if you wanna go in and be like, well, I want my address field right aligned next to an email and the name field, and then the address needs to be split up between, like, street and and number, and then all this kind of more detailed stuff, they can come back in and start using grids and and nested groups and all that kind of stuff to do it. But by default, you know, we'll we'll make it as good as we can.\u003C/p>\u003Cp>Speaker 0: Yep. And it's\u003C/p>\u003Cp>Speaker 1: a very hands off approach. It's like you break it, you fix it.\u003C/p>\u003Cp>Speaker 0: My my final question before we kinda diverge back, any compliance or standards we need to consider here? WCAG,\u003C/p>\u003Cp>Speaker 1: accessible I\u003C/p>\u003Cp>Speaker 2: don't think so right now.\u003C/p>\u003Cp>Speaker 1: Always. I mean, I assume that the the the, it's funny you mentioned it because, I mean, yes and no. It's it's another question of who's responsible. Like, if if our defaults should always, yes, I think, we should always provide the tooling to make it as accessible as possible and to easy as use as possible. But at the same time, if you wanna go in and remove all of the field labels and align it in a way that turns it into a piece of art, is that allowed?\u003C/p>\u003Cp>It is. That's part of\u003C/p>\u003Cp>Speaker 0: that question. I'm more considering I think right now, we do have some issues in the space, and I don't know if it is if it's part of this that would fix that or be part of you know, if we're gonna touch some of this stuff anyway, like, tabbing. Right? Being able to tab through your item fields and, you know, be able to quickly navigate to things. Some of that doesn't work very well right now in the data studio.\u003C/p>\u003Cp>Speaker 1: Yeah. Yeah.\u003C/p>\u003Cp>Speaker 0: Or at all. Right. And so just some, I just, I, because I've been doing so much standard and security.\u003C/p>\u003Cp>Speaker 1: It it it's a very good point, though. It's it is very true. It's like if you have, you know, a a if if you went nuts, so you have a super rich grid and everything sort of aligns funky, funkily. What is the tab order, and does that make sense? And is that something that somebody needs to be able to configure?\u003C/p>\u003Cp>Do you tab in and out of groups? Do you tab in and out of individual fields? How do you make sure that the tabbing order is visually consistent with what's about to happen? It's a difficult question for sure. For sure.\u003C/p>\u003Cp>And it and it goes right back to the who's responsible. Right? Who's responsible for all of this at that point? This this could even very quickly turn political in the sense of, is it the tool builder who's at fault, or is it the tool wielder who's at fault? No.\u003C/p>\u003Cp>No. No. No. No. No.\u003C/p>\u003Cp>I think I think some good guardrails today, but, you know, let's,\u003C/p>\u003Cp>Speaker 0: let me let me try\u003C/p>\u003Cp>Speaker 1: to summarize this discussion as the only the only thing stopping a bad guy with a form is a good guy with a form. If we get it, who's responsible?\u003C/p>\u003Cp>Speaker 2: I think I\u003C/p>\u003Cp>Speaker 0: think good guardrails, with some flexibility inside the rails. Right? And I think it's Yeah. It's always worked out well for us in general. I'm okay with some level of right to to some degree.\u003C/p>\u003Cp>Right? I think what we're trying to do here is improve the current experience.\u003C/p>\u003Cp>Speaker 1: Yeah.\u003C/p>\u003Cp>Speaker 0: We don't have to give ultimate any flexibility. Right? It is our data. You you wanna do that? Build your own, you know, use the APIs, build whatever you want.\u003C/p>\u003Cp>Right?\u003C/p>\u003Cp>Speaker 1: You have you have that\u003C/p>\u003Cp>Speaker 0: flexibility today. You can build an interface in front of this or a\u003C/p>\u003Cp>Speaker 1: Sure. You can build your own direct just for like\u003C/p>\u003Cp>Speaker 2: oh, yeah. Yeah.\u003C/p>\u003Cp>Speaker 0: Yeah. And, you know, to some degree, right, web design and things that people are building, some of the applications and tooling that people will build on top of the directors APIs. They have this flex they have the ultimate flexibility to build whatever they want. You wanna use the data studio. Again, we have a reputation.\u003C/p>\u003Cp>We have our own. And and I think good guardrails, good guidelines, and, you know, just configuration options. I think there's some of that as just adding some additional configuration parameters to allow for you know, we do wanna follow good accessibility practice. In order to do that, there has to be some options for that. And we can put some default, or we can just say these are the defaults.\u003C/p>\u003Cp>Right? The the defaults are what they are. Just making it so that it actually works and meets the guidelines at a minimum. I like it. Cool.\u003C/p>\u003Cp>Alright. We've got, 8 minutes, 7 minutes. How do we wanna start wrapping up, gents?\u003C/p>\u003Cp>Speaker 1: I think I\u003C/p>\u003Cp>Speaker 2: mean, it's just okay. Go for it. Go for it.\u003C/p>\u003Cp>Speaker 1: I was gonna say circling back to the initial thing of is a grid a system thing or is it more of a group type setup? I think I'm kinda leaning towards even though it is a bit more setup, doing it the group style way. Because that way, you can start nesting things. You can start configuring it to your heart's content. You can mix and match.\u003C/p>\u003Cp>You can have a section that is a 4. You can have a section that's a 6 upwards, 2, or 1, and mix and match on the page. I think making that a sort of nestable thing feels like the right move. We can still say that the form itself by default is one of those units, right, for ease of setup. So if you just want the whole field the whole form to be a 2 up, then you're done by default.\u003C/p>\u003Cp>Absolutely. But making that a sort of thing you can nest as a section feels like a powerful thing to have. Because that's what's gonna allow for one of these things where you have a 4 up, but then in the 4th column, you have a thing that also has field side by side, right, to make that as flexible as you want. I think when it comes to form label, that feels like a very system y type of thing. Like, we render a form with or without those groups with with grids, and then maybe on the form level, maybe on the the grid group form, whatever you wanna call it level, or maybe both, you can just set, okay, left line top of line, label and we can be a bit more flexible in that.\u003C/p>\u003Cp>And the same goes for the description. Right? Show at the bottom, show at the top. Those could be be just a toggle for for the form in in general. The new styles for check boxes, those types of things, the the the making them into 1 drop down and actual drop down.\u003C/p>\u003Cp>I think that is interface options. That's just separate from from this discussion to me. And then last but not least, there's 2 things coming in from our favorite team, which is our own. Sounds like we're in the last 8 minutes. Should different interface styles be just styles in existing interfaces or new extensions or interfaces?\u003C/p>\u003Cp>Opinions. Opinions. Opinions. I think it has all to do with the user experience. So to me, a checkbox and a toggle are effectively the same thing from a user experience perspective because you clicked enable, you clicked to disable.\u003C/p>\u003Cp>They're the same. Right? So to me, a toggle is just a different visual representation of the same underlying thing. This is the pain. Don't hate me too hard.\u003C/p>\u003Cp>It's a it's a different visual style for the same thing. When it comes to and and, funnily enough, we are not always good about doing it this way either. Right? So, for example, we have a drop down single select and a drop down multi select. In our components in code, it's the same component.\u003C/p>\u003Cp>A bit hard to maintain, arguably. Shouldn't have done that. We'll probably refect it at some point. Mhmm. Because the user experience is different.\u003C/p>\u003Cp>Right? Because one is, like, you're you're rendering a list of things. You're checking off multiple. You render it. Now when it comes to a multi select as a list of checkboxes versus a drop down that then shows the list of checkboxes, that is again a different visual style for the same interaction.\u003C/p>\u003Cp>Right? But where do you draw the line? Because in that example, you could say, well, they're visually so incredibly different. And for the end user, they might expect them to be do 2 different things. So where do you draw that line?\u003C/p>\u003Cp>I think it's just an opinion in a case by case. Right? It's like in this case, I would say a list of checkboxes or a drop down where you can select multiple things. Those are so different from, like, a mindset perspective that we should make it 2 different interfaces even though they do the exact same thing. You choose you pick and choose 1 or more things from a list, and that's what you're doing.\u003C/p>\u003Cp>Speaker 2: Yeah. Especially if you have 2 different styles, like you said, right, with with the drop down or they could have different options, and then we would have to respect those also in the in the drawer, for example, depending, you know, on what you have. But this has to be configurable then also for extensions. And that also sounds like okay. Just make a new interface.\u003C/p>\u003Cp>It everything is in order. It is just like that. Deal with it.\u003C/p>\u003Cp>Speaker 0: Yeah. Go with it.\u003C/p>\u003Cp>Speaker 2: It sounds very\u003C/p>\u003Cp>Speaker 1: There's there's 2 more fun ones for the last 2 minutes here. Tim asked, make it difficult nearing the end, will it be able to configure conditions across groups and sections? I think the answer is yes. I think conditions for an individual field or group should always be able to listen to anything else on the form, just whatever nesting level you're in. Of course, there's the same responsibility things.\u003C/p>\u003Cp>Like, if you listen to something that is visually completely disconnected and related, you can make it very difficult to use for your end users. But from a technical angle, I think we should make it possible. And then the last question here now is saying, what about applying conditions on hiding or disabling fields in the relation drawer based on the state of the form? And for that, I'd like to say tune back in 2 weeks from now. That that is a bit of a different discussion around how that drawer works.\u003C/p>\u003Cp>The the relation drawer right now, you know, it renders the same layout that you use for that collection, in the main sort of layout for that collection. So, therefore, the fields that show up are are the same that you see on the layout page for that collection. It also means it's a bit tricky to dynamically change that because it is matching the other one, but that is a different moving level. It should be possible with custom CSS and a group extension. Yep.\u003C/p>\u003Cp>Yep. Yep. Yep.\u003C/p>\u003Cp>Speaker 0: So many ideas.\u003C/p>\u003Cp>Speaker 1: Anyways, with that, we're at the top of the hour. I wanna thank you all very much for tuning in once again. We'll be back at some point in the near future.\u003C/p>\u003Cp>Speaker 0: I think\u003C/p>\u003Cp>Speaker 1: we're in another one in 2 weeks from now. Make sure to find this on direct to zio slash tv. Any other closing thoughts? Dan, John?\u003C/p>\u003Cp>Speaker 2: I figured it out.\u003C/p>\u003Cp>Speaker 0: Thanks to the community and all the good feedback on these on these issues. I'll post comments here shortly and then, Greg, if we need to do a full RFC on this one, we can work it out.\u003C/p>\u003Cp>Speaker 1: Sounds good.\u003C/p>\u003Cp>Speaker 0: Alright, team. Have a wonderful rest of your day.\u003C/p>","We are covering additional form and field layout options. This is actually related to our item editing experience, and it is something that I would actually love to have. We're very we have some awesome capabilities right now, but the 2 field across kinda limitation, it would be nice to have some more flexibility there. So that's our discussion. This is discussion number 9161. I'll drop it in the chat in case anyone wants to follow along there. Oh, 4 digits. You know, it's an old one when you're in the 4 digits. Oh, yeah. This is an oldie. An oldie but a goodie. This was an October 26, 2021 Ben Haines special. Oh, damn. But it actually surprisingly, this was pre RFC, but Ben actually put in example screenshots, good description. It wasn't just a one liner. I I was actually very pleasantly surprised when I opened this up to review it. Yeah. It's it's a good day when the feature request is not a one liner. It's Yes. It's great. Yeah. So I will let you guys kick it off. Alright. Well, 4 pages. Yeah. Right. So if I understand this correctly, we are talking about having a different layout for editing entries, which we currently do in 2 columns. You can divide your editing experience into a left column, right column, or go through with the whole input field? And wouldn't it be nice if we could do something else? I guess, it's the question. What could we have? So yeah. That's the the general question is a little bit more flexibility, more feet you know, again, things like toggles. Right? Don't need even half width. They could be 25%. 3rd. You know, maybe maybe a percentage based. Some of the more the more interesting feature styles, I think, that we can do today or that are possible. So Ben's got some different examples of what you might wanna have for layout options. Although this this was actually noted a little bit further down in this request that putting the label to the side is actually negatively impacting to users' experience. It's not not a recommended practice in general, but having some flexibility and being able to do some things. I think more so just being able to add more more configuration in the layout style, and and how things get positioned It's the general my my general client feedback, community feedback that I've heard, you know, in general with meetings and talking to people is just the ability to have more flexibility in the item editing design experience. So quick question. Yeah. I was gonna I I I think you're gonna go the same way as I'm gonna go, Daniel, but I'll let you go first. Not sure. I'm I'm just, I just want to clarify a little bit because, because of the screenshot. So currently, I think we're only talking or a question. Are we only talking about the layout in and of itself? So just positioning of elements beside each other, or are we also talking about different visual styles for the same interfaces? Because, when you scroll down a little bit, for the checkboxes, for example, they look different than what we have currently. Is also part of this, idea that, for example, you can have multiple different, toggles? Let's say the this one this let's call it filled in toggle or a different toggle. What about the, like like, what is it checkboxes? Now the selects where you can only select 1, like radio buttons for example cause they are a couple of examples here right the product category for example. Because they look different. Like, are we currently just talking about the layout or are we also talking about different styles? Let's look. Okay. Oh, no. He's got interface options to add well. So he's adding additional interface optioning capabilities as well. I thought, initially, I missed that. I thought it was just the item view formatting, you know, tab styles, other kinds of capabilities potentially. It's another frequent one that we see is instead of having just a full list of fields. Right? We have detailed things currently, but like a tab style interface there as a presentation layer. Could be other things we can consider. We can decide what we want this to be. We can narrow this. We can put this into RFC spec format, when we're done. So I'm happy to, well, you know, we'll do our let's do explode and then figure out what we want this to actually cover when we're done. So primary things that clients currently right? This is your current capability. Let me grab one that's got some, do I have one with groups? Remember if I've got something with field groups in it. Top of my, those products haven't. Why? You guys I think in in the end, when we when we scope down again, in the end, we can probably, like, make a make a rough, MVP of this feature where we just say, okay, maybe this is just it. But if you wanna take it further, then it would also include different, visuals for the same interface. Yeah. So these are kind of your current options. Right? You can have field groupings. Right? And otherwise, you got it didn't half with. So to me yeah. I think we should start with with let's let's think about the I think I mean, options to existing interfaces could be discussed here. But I think in general, the way that this thing started and the way that I see this, the the biggest struggle that clients have today is you have very limited kinds of options actual form editing experience. How things can be laid out. Yeah. For sure. I think the other parts, you know, a toggle instead of a checkbox, that's a new interface. That's just a custom interface or an option or stuff like that. But it doesn't really change the way the form itself is rendered. So I think for the sake of this discussion, we can focus on that. Cool. I think some of the bigger ones that we see here in the feature request is around where does the field label and description go. I think that is sort of one bucket. Does it go top? Does it go bottom? Does it go left? Does it go right? Then around how do certain groups come together? So there's like a sort of a new group UI, like a group of the title, and it's in a gray box instead of on a white background sort of visually, you know, cluster some of these form inputs, which then made some where the descriptions go. And then the other one is around, and it's not so much in the original screenshots, funnily enough, but it is I think of an important one here to bring up is what does the grit look like if you go beyond 2? Right? And and, where I can see this discussion going quickly is what about responsive? How does that work? And what about, on the screen that is about 6 meters wide, to make that work in a way that is still user friendly? That is a good question. I this reminds me of a small little bug if we want to just take a little tangent for a story time. Because we have this little bug, where if you have a checkbox with multiple, options, we change the way how they are displayed depending on how many options you have. So if you only have 2, then they are right beside each other. But, for example, or if you have, like, I don't know, 5 or let's say 10, then we put them below each other. And we had this interesting fun little little bug is that we made this also dependent on the content of those checkboxes. So if you have long text, then we actually, you know, span the whole width so you can actually read the thing inside of the checkbox. But what this resulted in is that actually, in like languages which are very short and there are languages that which are very long, like in German words, you know, which means that you have different layouts depending on what kind of language you have. And then, there were a couple users that used Chinese characters, Mandarin characters. And this then resulted, like, if you translate it and then you got different layouts for different languages and stuff, that that was quite quite a fun thing. I think I fixed that, by the way. But, okay. Enough of that. Sorry. Yeah. Let's see. I mean, there's there's lots of perspectives. Right? Like, how many columns should that be dynamic? Do we want to provide a fixed fixed width as of right now? Like, 2. Let's just say, okay. You get 12. Is that good enough? And how do you configure the responsiveness? Then how do we have breakpoints? How many breakpoints do we have? 2, mobile, desktop, but not every screen is the same. How do you configure that? Do do we even want to configure that? Like, yes, but no. Meh. I mean, really, how much database work and actual data modeling are you interested in doing on mobile, to be honest? Like, how many people actually, editing the databases and data records on the phone? Like, how important is he's he's funny. The answer is very important. This guy does. You'd you'd be surprised by how many people use mobile or mobile adjacent stuff now too. Right? If you have the folks with flip phones and you have people with with, you know, small iPads or, yeah. Yeah. Just going by the chat. People are saying the same thing too. Mobile interface, main point, which isn't direct is people editing videos on their phones. The people do everything on their phones nowadays, and I'm one of them too for what it's worth. So when it comes to grit and responsive, this is this is one of the reasons why, there's a lot of apps that are sort of, like, app builders, like a read tool, for example, that opt to make it a scrollable window when you go smaller for this exact reason so it doesn't have to do any sort of weird new reflowing. There is tools out there that I won't name by name that just straight up say there's no native there's no responsive design at all. There's no mobile version. There is different ways of of handling that. The way Directus does it right now is in the in the sort of 2 grid in the 2 up, the screen gets too small, becomes a one up. And that an easy easy enough sort of reflow to make. Right? Because whatever used to be side by side is now beneath each other, and that is good enough. Right? It it's it's what you'd sort of expect to happen, and it doesn't really cause anything too strange, from happening. If you're in a 6 column grid or so, like, if I'm scrolling down this feature request a little bit more, there were some screenshots from a tool called They have, like, a a sort of rich layout, which is roughly 4 columns. But then within, you know, one of the columns, there's another sort of 6 column y thing nested. And now I'm like, okay. Well, if you're responsibly squishing that down, weird things will happen. Like, what goes where? How does it flow? How does it grow? Do you expect, like, the 4th column to become, 3 columns of white when it goes to the next one? Do you intend it to still be blocked, but then you have 3 and 1 sort of weirdly underneath it? Or does it switch forward to a 2 grid? There's there's weird questions that happen at that point when you go down. And all so how does it interact with other fields that are then further down the page? Right? So right now, because every field is basically just in the same, same list of fields, It would start showing up side by side with other fields in that same grid, which could get funky and sort of unintentional. So one way around that potentially is to instead of doing a grid, let me do it now where it is based always one column, but there's a group type for creating grid sections in your form. Right? Because that way, it will always wrap within just that group. You don't your unintended interactions with other fields further down the page. And then that also means that you can start nesting those in whatever way you want. So if you're trying to re replicate that sort of 4 knocks set up where you have 4 columns, where the 4th column itself is like a a 6 column grid or something, you could because you can start nesting those those grid forms. Right? And it it kinda starts responsively matching the column size rather than the form size. Hannes in the chat says, additional groups feel cumbersome to set up. Yeah. Fair. Although at the same time, you know, to achieve the same thing that we have now, you could have one group and just put everything in it. Doesn't necessarily, you know is that is that what the price of admission get for, flexibility in the new layouts? And then on that same note, you know, the the some of the other layout settings, like, is the field name on the left or on the top, the description on the top or on the bottom, that kind of stuff could be settings of a group. Like, it doesn't have to be, settings of the whole form at once. Right? We could also say that the form, by definition, just has one root group, and therefore, it's always there, but it uses the same same system. Alright. I can see that work in my hand. Like, is there a leaner way with less clicking? Currently trying to, like because if for me for me personally, the I I want I would want it to be as least intrusive as it can be because because I just wanna set up my thing and I wanna keep going. Right? Like I do not want to spend my time with designing, you know, layout. Like like this is like, I'm not sure how to say it. Like I I want to model stuff, I want to make like this this is how it how it works now. Like I just want to model stuff left, right, things and move on, you know. And I have other stuff to do. I have problems to solve as a administrator, let's say, of an instance, and I just wanna put some stuff in and keep going. So if you then have to jump through hoops and and, you know, like with all the, oh, but then on mobile, because I didn't, click on the full width. Now on mobile it is only half and it looks bad. And then I have to click this again and then the drawer opens again and I have to go into specific settings of a thing and then close the drawer again and choose the other. And that's that that feels icky. Like, I'm not sure if if we could design it in a way maybe with just small little toggles, like, without, specific options for those interfaces, when, like, the drawer opens, maybe we can make them just, small little toggles that you quickly go through just just without leaving the modeling page. Maybe maybe I don't know, like, it did did that make sense? It does. It it's a, you know, it's a tricky thing because on the one hand, it's like if you wanna do it sort of quick and dirty, so to speak, then that's fine. That should be possible. At the same time, if you wanna make the best user experience for your end user so so let me back up a little bit. I think there's a difference in, flow when you're first setting it up and you're doing the data modeling versus when your data modeling is done and sort of finalized and you go into the details to make it a nicer user experience for your end user. At which point, you might set up, you know, I wanna use monospace for an input and add a little icon to make it, you know, friendlier for the end user, that kind of stuff. Right? I think that is also where this whole gridding stuff comes in. It's like, do you care about grids and how it responsibly shows up side by side instead of ordered top to bottom? Well, if you're doing the data modeling, possibly, probably not. It's just like you need to have the fields to check if it works, build the integration, move on. Right? Only then when your data modeling piece is done, can you circle back and be like, okay. Now I'm gonna spend an hour or so to just really make this form the best form it can possibly be for the use case that I have. I wanna conditionally show and hide some things. I wanna do it in certain sections have to be like a 4 up grid or a half half width group where, I wanna order it differently, etcetera, etcetera. Right? So I think there's 2 different points in time and 2 different, user flows that that are related. So to your point, I do agree. It's like for that first one, I mean, you're just setting up the data modeling, experimenting with what fields and what names and everything else. Quick and dirty. You don't wanna be slowed down by having to think about, is it 2 or 4 or 6 columns? Like, who cares? Just go quick. Right? Make it work. But I do think that is where we can introduce that additional flexibility that we're talking about as part of this this feature request to saying, well, if we hard code this form to be 4 columns instead of 2, we're gonna have the same discussion a month from now where it's like, okay. What about 6? Right? Yeah. And we're gonna have the same discussion a month from now where it's like, okay. Somebody wants 12. So by doing it as a group extension type where we say, okay. The group is just the thing that makes it x number of columns and we don't care. We allow that flexibility in a sort of opt in type of fashion rather than us having to predefine, okay, a direct this form is always x. Like, it is now. We say it's always to deal with it. Right? Yeah. For for me, priority would be, just looking at at the screen right now, let's see, let's look at the theming group, right, or the SEO group also. I would like to avoid, or it would be it is near and dear to my heart, you know. Like, if I now want to split the theming group, I don't, like, I don't want to be the kind of back end where you have to click on the, 3 dots, then a dialogue or, like, a popover opens, then you have to click on edit fields, then the drawer opens, then you have to go inside of that, and then you have to configure some type of grid system and break points and stuff and then the whole thing closes and then, oops, I forgot one thing, I have to go through the entire thing again like this. Like I really want to avoid that. So I'm like, okay, And we maybe make sure that this doesn't happen. Maybe we can include some controls that are maybe enough already on the screen right now. So like, side the three points where the options would be, maybe there could be quick toggles where you can very quickly just with one click, like, boop, and then it's half view. And, you can configure it and then another click, boop, it's it's it's the mobile view. And then you can configure it again. Yeah. How about that? So the reason why it has to be a drawer now is that those groups and interfaces themselves are an extension type. So, therefore, we don't know what those options are. Right? So if somebody makes a new custom grid group now, which you could theoretically, the options for that group is like a an open ended question mark. It's just a set of fields, and we don't know what they are. And we don't know how to, you know we we know how to render them because we ask you we ask the extensions, like, what options do you wanna render? And it's basically just another view component. Right? So it's like a black we just anything goes into that drawer and have have at it. So we can do that. We'll have to come up with some sort of standardized syntax for those plugins to say, here is the 2 or 3 things I wanna be able to edit in line that makes sense for this type of thing that I'm doing. Or we have to go the other way and say, well, we just built more of an Apple approach. That's who it where we say, well, the direct extensions are special and they get to do some of these inline things, but regular extensions are back to the old drawer style. You know what I mean? It's just that that flexibility angle because all of these are extensions. Yeah. I get it. That's a bummer. Like, because we we strive and we always, our strength, right, is that everything is so super duper flexible that you can do anything yourself. Yeah. But for this, can we? It's a question. Right? I I think when it comes to the drag and drop UI of of doing the layout of the form, if if you have a 4 grid, we have to show it as a 4 grid in line there as well in your editing experience. Like, that, I think, is is definitely something that we have to code in. But then if there's a group that has an option for number of grids, how does that how do we connect the dots? Right? How do we know that the grid column option in or an extension should be mapped to our editing experience for the form that makes it so that makes it work like that. Or again, maybe that there's the case that we say, well, you know, the way to handle grids is just not an extension type and there's no way for extensions to do that. It's just the native direct listing. Where we stay, okay, form layout, order, and grid, that is just a a direct as native thing. You can change it through extensions or anything else. You can still make a custom group, but the layouting options for that is not something that we can natively, manage on your behalf. Like, that that is also, you know, an option. Mhmm. Yeah. Like, I I would be like, let let's let's just, you know, the, gut gut feeling is just this sounds reasonable because it's not actually concerning your data. It's just like our our, product UI. So it makes sense that we have this control of the layout. But I can already see, like, it's this is gonna be the first comment in that PR. It's like, oh, but I really would like to do this in my thing. Can we can we add that also? And then every time. Every content. Okay. Alright. So so this is the layout type of thing of that PR of that of that RC. I think it just okay. Let's you said in the beginning the other interfaces are mostly just other interfaces, so they aren't really concerned with this. I think the difference between a checkbox and a toggle, that is an interface option or that is a new interface. I don't think that has anything to do necessarily with form rendering. So I think for the sake of this art for this discussion, we can just keep the scope to form rendering itself. I saw there there was some a couple of good points in the chat earlier right before we started with a couple of points around a little bit more general updates to forms and and interfaces, what we can do with it. 20 minutes ago, somebody was saying, it will be cool if you have, like, a 3, 4 column layout instead of just 2, expand the form width. So it's like the whole screen instead of just, you know, a a max width. But you could kinda do because there's, like, a full width option for an individual in the face or group, but it's I I do agree it's the whole form. It doesn't quite quite work like that. Aligning the form itself to the left or the center of the screen or maybe even the right. And then it gets into which I feel like a bit of a different feature request, but I wanna call it out because it's in all caps, so it sounds important. Actual relation drop downs, which I think is just make making sure that a second drop down is updated based on the value of the first drop down, which is, again, kind of not really formed. I think it's actually I think it's actually more related to the relational interface itself right now. They always go to a drawer. I think it's more of the so like, a many to 1 or one to many. Oh, that part of that nature drop down. As opposed to a drawer pop. Yeah. That's an interface itself. That to me is again, I think we're kind of a little out of scope for this for what I think we want this review to cover in detail. Okay. Yes. There are there are dozens of things we would all like to have on the interfaces side of the house, but that's why custom extensions exist and you can't build them. So although, you know, this grouping style that we support, I have seen tab style, the group interfaces where someone has built a custom interface that actually does, like, tab styling and multiple fields and tabs and things inside their groups. So custom extensions support those kinds of things. Yes. Relational drop downs instead of drawers would be really nice in many use cases. You know, it's, you know, it's funny. This is a complete sidebar, and I I wanna be cognizant that we don't end up spending 20 minutes on this because it's an easy one to slip into. But the many to 1 interface, the drop down one that opens drawer, it has the the actual drop down bits built in. It like, when we built it, it had that baked in. It's the problem was that similarly with most every other thing in direct is, like, week 2, somebody was like, I have a 100,000 items in the related Yes. Related table and I I am now going to break your interface. Outright. The drop down only shows the first a 100, so I cannot find the thing to select. And I'm like, yep. Yep. Yep. Yep. Yep. Yep. So then then we made the call to, like, always show it as a drawer, which works for everything, but it's it's not as nice as a little drop down. But it it used to work like that at one point in time. Yeah. Yep. Yep. I know we've had bring that back as a as an option to to but but the the funny thing there is, like, to do it the best way possible, we need to have an updated count of the number of related items at any point, and getting that count can be very slow if you have 100 of 1,000 of them. So we have to come up with some sort of way to cache the count our site first so we have a sort of estimate count that we can use and then update that over time because, otherwise, it's gonna be not performing enough to do you know? Anyways, long story short Yes. Similar thing that so we did that for the actual layouts, as part of that performance improvement a year or so back, a year and a half back, where you started caching the accounts and not running the count every single time, only watching for changes or what. I'm not sure what happens behind the scenes in the caching aspects. But for those clients who had millions of rows of data and being able to present that and reflect that and not pulling everything Something like that. Yeah. On the counts. That's so The database running every single time you clicked was hugely performance impacting. So Yeah. There's there's also some databases, and this is, of course, where the devil's in the details here. Some databases also have a difference between, an estimate count versus the actual count. So, like, in Postgres, there's a system table that keeps an estimate count that is not guaranteed to be accurate, but it's sort of a ballpark. So at least, you know, are we over under on 1,000, or is it just, you know, a couple? Yeah. So there's also a world this is again a big sidebar, but such goes in these episodes. There's also a world where we first get the estimate count, which is cheap. And then if that estimate count is less than a couple thousand, then we meet the actual account. So we can show that. Nice. Anyways, that is a whole different That is a very different ballgame and Oh, okay. Another discussion. Mhmm. Mhmm. That that's a fun one. Okay. How many items do I have? And you asked the database and it's saying, probably 10,000 maybe? Best I can do. Yeah. It's it's an interesting problem though because it's one of those things where in order to know that, it's it's, what is that in COMS size? Is that one of those o n problems or an o two problem? Where you know what I mean. Right? Where it's like, the more items you have, the slower it gets linearly to count the number of items. So, therefore, if you have a table with with 20,000,000 rows in it, how do you know it's 20,000,000 rows efficiently? That's weird. Yeah. Oh, and, yeah, that's that's what I thought. It's it's clear that if not comp side. I'm still just a UX designer, guys. Take it easy. Cool. Some of some of the other stuff in the chat here before I I miss it again. So it says, I wanna speak with a person with a 100,000 items. I need a quick chat. Oh, for what it's worth, we, we even do a similar thing ourselves where we have, you know, we keep, error logs for, you know, certain cloud deployments. Those error logs have a one to many back to the project, so we can see the most recent 10 per project. Right? But that also means that the whole error logs table can be in the millions. So that one to many needs to be prepared for, you know, what that looks like if you said select existing, and now all of a sudden you have a list of 10,000,000. Like, how does that work? Right? It it's it's a very real thing that people do, ourselves included, which makes some of these discussions a lot more fun if you're thinking about it many to one. I am making the drop down nice and easy. Nope. Yep. Cool. And then on this another one says here, it feels like we could add a special component that can be defined for group interfaces where they decide on the layout for field layout. Right. Yeah. So this is similar. This is going back to the, how do we do inline options for groups? Right? So honest suggestion here is basically saying, well, maybe just like inner like options for interfaces, there's a way to say, let the actual form extension itself decide how to render on the settings page so we can make that optimized, which is, yep, interesting. Something along those lines. There's something about a half width group. That's fine. Otherwise, do it with 2 columns. I think we touched on the other stuff. Right? Cool. Then the second thing is around in this feature request rather, is around, where does the label go in a form? And is it something that you should be changing? Or is that something that is just not something you should care about? It's an interesting one. Kava is it it gets to a bit of a user experience question. Right? And and this is, again, a topic that can easily get off the reels in terms of theming and customization and how far do we wanna take it in the sense of, you know, if you give the end user infinite flexibility in this kind of stuff, you also give them infinite food guns to make it trash, right, for the for the end user. So there's a there's a very real discussion around, you know, is form labels left aligned input, right aligned? Is that good for good? There be opinions. Is that good for the end user or not? Right? And then the question becomes, who should be in charge of making that call? Because we make a lot of calls because it's a studio. Right? And it's the same, yeah. Yeah. Hans says the same now. It's a layout too. Once you have weird layout problems, you get a similar similar, UX problem. Right? But the question becomes, who's responsible? Right? Do we say well, because we built the studio, we have good defaults. We wanna make sure that everybody has a good user experience. That's what we pride ourselves on. Therefore, are we gonna limit some of these things? Or are we gonna say, go nuts, and it's your problem, which is great for some and a problem for others. Right? And we've seen this before. We've seen this in the past. Like, when we ship theming, which I think has been been pretty pretty good to have, generally speaking. It opens some of those questions too. Right? Because I I know, my very own Kevin made a, like a teenage mutant Ninja Turtles one, or or what do we call it? Something non something not trademark related, as as a sort of experiment to see where how far you can take it, but it's also objectively horrendous. It's objectively bad, right, for for user experience wise. But who who's who's responsible then? Right? And and where do you draw that line? I think it's an interesting question here too because, like, if we make a if we kept just if you make a 12 column grid, you can do some very powerful, easy to use layouts. You can also easily make a garbage nightmare. Just like you can make a dumpster fire. Who's then responsible for the dumpster fire part of that? Yeah. Because the yeah. Like you said, this is an actual thing. Like, if somebody badly configures their instance, it may reflect even bad on us because, like, the users come in and say, like, oh, what what what oh, brother. Oh. What what happened here? You know? Like, Directus is ugly. Directus doesn't work. Oh, this is not good. And then it reflects bad on us. So actually, we should think about that we make I mean, you know, flexibility is nice. It is it is cool, and it is one very, very good point for us. But to what extent? Like you said, okay. So we we do have to so quickly and I love it. We do have to draw a line somewhere. There there's an interesting part of the tech industry that people have been yelling about for decades now, which is the whole Android versus iOS thing. Right? Or Linux versus Mac OS thing, which is, like, for the longest time on iOS, you cannot you can you can reorder your app icons, and that's about as much customization as you get. Right? For the first couple of iOS, if the background was black, shut up. Your wallpaper on the lock screen was the was the globe. No options. Right? And then they were like, oh, maybe maybe you can have maybe you can have a wallpaper, and then you could have some fish instead of a globe, and then that was it. Right? But then, you know, people on on the Android side of the house have been screaming for decades. Like, oh, my wallpaper moves this fantastic life great. But, also, you can make an absolute dumpster fire of of your phone, which is whose problem is that? Right? Is that is that you're gonna make it better for the power users, but you also give a bunch of food guns to everybody else? And for what it's worth, Apple is now doing the same thing, I think, right, with this new iOS 18 where you can, like, tint your app callers or something, and it looks horrendously bad just just objectively. Of course, it's an opinion, but I'm right. It's objectively bad. Where because you just see the icon from, like, I don't know, Notion or something turned bright yellow because you you tinted it that way. It's just not good. It's just not work. But the question is, like, you you can make it good with a bit of effort, but people don't will not. Is that is that a problem? Like, is that It it the older I get, the more I think, yes. That's a problem. Because the So you're gonna look at an iPhone now, and you're like, man, that is ugly. It's so good and hard to use, and I don't care. But at the same time, the the people that set it up that way for themselves, they might love it. It might be their preferred Yep. You know, becomes an opinion thing. Right? But it's like, how do you decide where to draw a line? Yeah. Quick. Because there was the the quote from, I think Henry Ford, was it? Like, with the car, like, you can have, the Ford in any color that you'd like as long as the color is black. Black. Yeah. Right? Yeah. The same for iOS. You can you can do anything you like, but as long as it's not what you like. Yeah. As long as you like what we like. Right? Exactly. Yeah. So, like, I I think I personally I mean, of course, this is just, you know, opinion piece. Careful. It's I think we should be for the live stream, and I posted a picture of, Tim did Ios screens. It it is something. And these are the ones done well, mind you. Anyways yeah. So so for for the listener, it's basically, you know, 5 different iOS screenshots with, like, different color background, and then all of the front, front end, all of the the icon colors, is is the same color as the background. So, therefore, at a glance, everything looks the exact same. It's just that's that's the main issue for me. It's like, I don't know what app is what app anymore because they all look identical to me now. Google oh, man. This is such a sidebar again. But Google did the same thing. Right? When they went through the whole material design thing, now every single Google app looks the exact same. If I log in to our Google Workspace and I click on apps, I just see the exact same icon, like, 200 times, and they are all the same. It's there's a small variation in shape, and I just don't know it. Anyways, yeah, it is let's try to get that back on track. It it is an interesting discussion in general, though, for of, like, how far do you let people take it? And and is it a good thing, or is it a bad thing? And where do you draw the line? I think in this case, as long as we have good defaults, I wanna on the side of let them have the flexibility, but make sure that by default, for the people that don't spend the time setting it up, it looks good and it works well. Right? Mhmm. I think that's kinda where your earlier suggestion comes in for, like, if I just wanna go in at a con at a bunch of fields and not think about it, we need to make sure that things work out the right way at that point. It's like, what makes sense? Help the user as much as possible to have a good default. And then if you wanna go in and be like, well, I want my address field right aligned next to an email and the name field, and then the address needs to be split up between, like, street and and number, and then all this kind of more detailed stuff, they can come back in and start using grids and and nested groups and all that kind of stuff to do it. But by default, you know, we'll we'll make it as good as we can. Yep. And it's a very hands off approach. It's like you break it, you fix it. My my final question before we kinda diverge back, any compliance or standards we need to consider here? WCAG, accessible I don't think so right now. Always. I mean, I assume that the the the, it's funny you mentioned it because, I mean, yes and no. It's it's another question of who's responsible. Like, if if our defaults should always, yes, I think, we should always provide the tooling to make it as accessible as possible and to easy as use as possible. But at the same time, if you wanna go in and remove all of the field labels and align it in a way that turns it into a piece of art, is that allowed? It is. That's part of that question. I'm more considering I think right now, we do have some issues in the space, and I don't know if it is if it's part of this that would fix that or be part of you know, if we're gonna touch some of this stuff anyway, like, tabbing. Right? Being able to tab through your item fields and, you know, be able to quickly navigate to things. Some of that doesn't work very well right now in the data studio. Yeah. Yeah. Or at all. Right. And so just some, I just, I, because I've been doing so much standard and security. It it it's a very good point, though. It's it is very true. It's like if you have, you know, a a if if you went nuts, so you have a super rich grid and everything sort of aligns funky, funkily. What is the tab order, and does that make sense? And is that something that somebody needs to be able to configure? Do you tab in and out of groups? Do you tab in and out of individual fields? How do you make sure that the tabbing order is visually consistent with what's about to happen? It's a difficult question for sure. For sure. And it and it goes right back to the who's responsible. Right? Who's responsible for all of this at that point? This this could even very quickly turn political in the sense of, is it the tool builder who's at fault, or is it the tool wielder who's at fault? No. No. No. No. No. No. I think I think some good guardrails today, but, you know, let's, let me let me try to summarize this discussion as the only the only thing stopping a bad guy with a form is a good guy with a form. If we get it, who's responsible? I think I think good guardrails, with some flexibility inside the rails. Right? And I think it's Yeah. It's always worked out well for us in general. I'm okay with some level of right to to some degree. Right? I think what we're trying to do here is improve the current experience. Yeah. We don't have to give ultimate any flexibility. Right? It is our data. You you wanna do that? Build your own, you know, use the APIs, build whatever you want. Right? You have you have that flexibility today. You can build an interface in front of this or a Sure. You can build your own direct just for like oh, yeah. Yeah. Yeah. And, you know, to some degree, right, web design and things that people are building, some of the applications and tooling that people will build on top of the directors APIs. They have this flex they have the ultimate flexibility to build whatever they want. You wanna use the data studio. Again, we have a reputation. We have our own. And and I think good guardrails, good guidelines, and, you know, just configuration options. I think there's some of that as just adding some additional configuration parameters to allow for you know, we do wanna follow good accessibility practice. In order to do that, there has to be some options for that. And we can put some default, or we can just say these are the defaults. Right? The the defaults are what they are. Just making it so that it actually works and meets the guidelines at a minimum. I like it. Cool. Alright. We've got, 8 minutes, 7 minutes. How do we wanna start wrapping up, gents? I think I mean, it's just okay. Go for it. Go for it. I was gonna say circling back to the initial thing of is a grid a system thing or is it more of a group type setup? I think I'm kinda leaning towards even though it is a bit more setup, doing it the group style way. Because that way, you can start nesting things. You can start configuring it to your heart's content. You can mix and match. You can have a section that is a 4. You can have a section that's a 6 upwards, 2, or 1, and mix and match on the page. I think making that a sort of nestable thing feels like the right move. We can still say that the form itself by default is one of those units, right, for ease of setup. So if you just want the whole field the whole form to be a 2 up, then you're done by default. Absolutely. But making that a sort of thing you can nest as a section feels like a powerful thing to have. Because that's what's gonna allow for one of these things where you have a 4 up, but then in the 4th column, you have a thing that also has field side by side, right, to make that as flexible as you want. I think when it comes to form label, that feels like a very system y type of thing. Like, we render a form with or without those groups with with grids, and then maybe on the form level, maybe on the the grid group form, whatever you wanna call it level, or maybe both, you can just set, okay, left line top of line, label and we can be a bit more flexible in that. And the same goes for the description. Right? Show at the bottom, show at the top. Those could be be just a toggle for for the form in in general. The new styles for check boxes, those types of things, the the the making them into 1 drop down and actual drop down. I think that is interface options. That's just separate from from this discussion to me. And then last but not least, there's 2 things coming in from our favorite team, which is our own. Sounds like we're in the last 8 minutes. Should different interface styles be just styles in existing interfaces or new extensions or interfaces? Opinions. Opinions. Opinions. I think it has all to do with the user experience. So to me, a checkbox and a toggle are effectively the same thing from a user experience perspective because you clicked enable, you clicked to disable. They're the same. Right? So to me, a toggle is just a different visual representation of the same underlying thing. This is the pain. Don't hate me too hard. It's a it's a different visual style for the same thing. When it comes to and and, funnily enough, we are not always good about doing it this way either. Right? So, for example, we have a drop down single select and a drop down multi select. In our components in code, it's the same component. A bit hard to maintain, arguably. Shouldn't have done that. We'll probably refect it at some point. Mhmm. Because the user experience is different. Right? Because one is, like, you're you're rendering a list of things. You're checking off multiple. You render it. Now when it comes to a multi select as a list of checkboxes versus a drop down that then shows the list of checkboxes, that is again a different visual style for the same interaction. Right? But where do you draw the line? Because in that example, you could say, well, they're visually so incredibly different. And for the end user, they might expect them to be do 2 different things. So where do you draw that line? I think it's just an opinion in a case by case. Right? It's like in this case, I would say a list of checkboxes or a drop down where you can select multiple things. Those are so different from, like, a mindset perspective that we should make it 2 different interfaces even though they do the exact same thing. You choose you pick and choose 1 or more things from a list, and that's what you're doing. Yeah. Especially if you have 2 different styles, like you said, right, with with the drop down or they could have different options, and then we would have to respect those also in the in the drawer, for example, depending, you know, on what you have. But this has to be configurable then also for extensions. And that also sounds like okay. Just make a new interface. It everything is in order. It is just like that. Deal with it. Yeah. Go with it. It sounds very There's there's 2 more fun ones for the last 2 minutes here. Tim asked, make it difficult nearing the end, will it be able to configure conditions across groups and sections? I think the answer is yes. I think conditions for an individual field or group should always be able to listen to anything else on the form, just whatever nesting level you're in. Of course, there's the same responsibility things. Like, if you listen to something that is visually completely disconnected and related, you can make it very difficult to use for your end users. But from a technical angle, I think we should make it possible. And then the last question here now is saying, what about applying conditions on hiding or disabling fields in the relation drawer based on the state of the form? And for that, I'd like to say tune back in 2 weeks from now. That that is a bit of a different discussion around how that drawer works. The the relation drawer right now, you know, it renders the same layout that you use for that collection, in the main sort of layout for that collection. So, therefore, the fields that show up are are the same that you see on the layout page for that collection. It also means it's a bit tricky to dynamically change that because it is matching the other one, but that is a different moving level. It should be possible with custom CSS and a group extension. Yep. Yep. Yep. Yep. So many ideas. Anyways, with that, we're at the top of the hour. I wanna thank you all very much for tuning in once again. We'll be back at some point in the near future. I think we're in another one in 2 weeks from now. Make sure to find this on direct to zio slash tv. Any other closing thoughts? Dan, John? I figured it out. Thanks to the community and all the good feedback on these on these issues. I'll post comments here shortly and then, Greg, if we need to do a full RFC on this one, we can work it out. Sounds good. Alright, team. Have a wonderful rest of your day.","f5bdab73-98c5-4b82-82cd-d08babe50bca",[207,208,209],"f89c7bab-7b50-4e16-ba47-6c56fd82cf60","13cd4775-d2d1-4305-967e-7282174f4af3","d512e3fc-2b28-4f38-8f0d-25b7041c22bf",[],{"reps":212},[213,269],{"name":214,"sdr":8,"link":215,"countries":216,"states":218},"John Daniels","https://meet.directus.io/meetings/john2144/john-contact-form-meeting",[217],"United States",[219,220,221,222,223,224,225,226,227,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],"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":270,"link":271,"countries":272},"Michelle Riber","https://meetings.hubspot.com/mriber",[273,274,275,276,277,278,279,280,281,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,250,461,462],"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",1773850452859]