[{"data":1,"prerenderedAt":453},["ShallowReactive",2],{"footer-primary":3,"footer-secondary":93,"footer-description":119,"request-review-17853":121,"request-review-17853-next":182,"sales-reps":201},{"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":160,"season":161,"seo":181},"84c7b3ac-fd85-4539-8f39-3247118bcbf2","17853","1008857977","In this recording of our live event on September 12th 2024, Nils, Jonathan, and Rijk discuss Optionally Delete Unused Files.","0a141eae-c91d-4519-bec4-1faf19b7ef37",45,[129],{"name":130,"url":131},"Discussion","https://github.com/directus/directus/discussions/17853",12,"2024-10-07","Optionally Delete Unused Files","\u003Cp>Speaker 0: Welcome back, everybody. Welcome to another request review. We have a very special guest here today. Welcome, Niels. He's 7 of our usual host, Daniel of the day.\u003C/p>\u003Cp>Jonathan, what are we gonna be talking about?\u003C/p>\u003Cp>Speaker 1: Today, we are going to talk about discussion number 17, 853. That is going to be about\u003C/p>\u003Cp>Speaker 0: My favorite.\u003C/p>\u003Cp>Speaker 1: File deletion and management. So this is primarily around the relational, file deletes. If you delete a file from a record or you delete a file from the file system or from the direct to files library, what are some better options for managing that relational delete. So currently, we do a do not delete on the file. It's kind of the default configuration.\u003C/p>\u003Cp>There are some cascading rules and things you can configure in some cases. But because files can be associated with so many different collections and records, this particular request is around, are there some additional options or features that we could add around improving that file management? Right. So that's the that's the general I'll drop a link just in case people didn't get it.\u003C/p>\u003Cp>Speaker 0: Yeah. So to kick that out right away, the, the important thing to note here, of course, is that direct to files, you both have this sort of, you know, physical file on disk, and you have a row in direct to files, the system table that contains additional metadata we cannot store on the file itself. Right? So think about, we store information about, the some of the exit data for easier retrieval. We store, things like width and height, file duration for for movies, I think, and audio files.\u003C/p>\u003Cp>We have some additional fields, focal points. Yeah. Exactly. Some location text, some optional metadata that's human configurable. And, of course, some information about what direct this user created, updated, and modified it, whatever.\u003C/p>\u003Cp>So we have a record in the relational database in the system stuff for for more information. So it also means that when it comes to automatically deleting those files, what we're talking about here is effectively a, you know, sort of cascade delete or a cascade update whenever that relational record is getting destroyed. Right? So from a usual database management perspective, this is a very standard task thing where it's like, okay. The ID of the file gets removed.\u003C/p>\u003Cp>I want there any record that uses it to be destroyed as well. Let's do the other way around. Right? The the foreign key gets removed, destroy the file. Now in this feature request, what which way is it going?\u003C/p>\u003Cp>Because I believe it's saying that they wanna delete the file when they delete the record where it's used rather than the other way around. Right?\u003C/p>\u003Cp>Speaker 1: Yeah. In this case, yes. They've mentioned it both directions or it's mentioned somewhere in here. But if you're deselecting or removing an item from a a record association. Right?\u003C/p>\u003Cp>So if you've got something simple like articles with a file associated, one of the option requests discussed here is if I delete or remove the file from here, that the user either automatically deletes the file from the file system, removes it from direct to files, ideally cleans it off the drive. But alternate options were to actually prompt the user for, do you wanna delete the file? And if yes, go ahead. Yeah. Lots of complexities that come with all of that.\u003C/p>\u003Cp>Right? Because file the file could be in use by another record. The other big thing with files, because files can be embedded inside of things like WYSIWYSIWYSIWYGs and block editors as relational. Right now, and this isn't this isn't necessarily a direct to specific issue. This is a SQL issue.\u003C/p>\u003Cp>Right? Unless you're maintaining dual relationals all over the place with everything related back into the file system or some mechanism to track because files can be associated with any number of collections and be embedded inside of rich text fields. How do we manage or understand those kinds of things as well? So there's a a number of factors, I think, that make this complex. But for now, at least what they're asking for is if I delete the file from the record, automatically delete the file or prompt the user, with an option to keep or delete the file.\u003C/p>\u003Cp>Speaker 0: So it's an interesting one there because the so so both those points, the first one to your point, this is this is a problem that has been as old as any sort of content management system on the planet is if you have a link to a file in a piece of text, is that a relational record? No. Is that a relationship in a database you can easily track? Also, no. So now on file delete, are you gonna be scanning through all of those blobs of text all over the place to sort of pseudo find relationships that is hella inefficient?\u003C/p>\u003Cp>Right? So how do you deal with that? That's that's a good one. The second one that is interesting is that this is kind of the going the wrong way, so to speak, if you compare it to how regular relationships work in a database. Right?\u003C/p>\u003Cp>So usually, when you say when you do a cascade delete, it would be the moment you delete the file, you delete all of the rows where it has been used in a foreign key. Am I saying that right? Or am I making this up? I was getting too confused, to be honest.\u003C/p>\u003Cp>Speaker 1: I think it goes the other way because the foreign key, at least in that case, like in my article case, the foreign key reference is actually here on this record. So we actually store the foreign key. So I believe the cascade is actually going the other way. So if I delete it from here and I tell it to cascade, it should cascade and delete the file. And I believe that actually does.\u003C/p>\u003Cp>So we can actually double check the settings, article because\u003C/p>\u003Cp>Speaker 0: we do some article in both ways in direct as I was just trying to remember if I wrote like myself which way the default is.\u003C/p>\u003Cp>Speaker 1: So the relationship in this case is directional from direct as follows. Right?\u003C/p>\u003Cp>Speaker 0: It was the rate that I said. It's like the moment you delete the file, you get to choose what you wanna do, with the forward key field. Right? Do you wanna nullify it, or do you wanna destroy the whole row that uses that forwarding key? So so that's why I meant with sort of like the feature request going the opposite way.\u003C/p>\u003Cp>Right? Because by a database and default, you're saying, okay, the moment you delete the file, delete everything where the file is used. But it feels like this feature request is going the other way. Right? They're saying the moment I deselect the file from a gallery post or something, I also want to trigger a deletion of the related file.\u003C/p>\u003Cp>Speaker 1: Yeah.\u003C/p>\u003Cp>Speaker 0: Yes. Key.\u003C/p>\u003Cp>Speaker 1: So now you're actually you are actually correct. It does go the other way. So if you delete the file, it's actually cleaning up the foreign key, right, is what we're technically do. Yep. My mistake.\u003C/p>\u003Cp>Speaker 0: So this and this is welcome back to the beauty of request review. If you haven't been here before, we always like to diverge as much as we can before we come back down to the notes at the top of the hour. The immediate question to me here becomes, is this a file specific thing, or is this just a directed data thing? Right? Is this something that you should be able to set up for everything where you're like, okay.\u003C/p>\u003Cp>The moment I I delete this record or deselect this relationship, I wanna be able to remove the thing on the other end. Is that a thing that we just wanna support as a more generic option or is this something that is inherently specific to files? Because it kinda sounds like that this is that this person was mentioning files just because that's the use case for this particular person and this website that they're building. But I could see this as be a relationship thing. Yep.\u003C/p>\u003Cp>Speaker 2: At least implementation wise, it's like equal, I would say. There should be no diff like, no technical difficulties to make it more advanced in a sense or more capable.\u003C/p>\u003Cp>Speaker 1: Yeah. No. I actually like that. I I think, especially as we move towards, you know, our our our future concepts of we want to support non sequel kinds of things. This means, to some degree, direct us needs to understand where things are being used and keep track of that so that otherwise, we can end up with a, you know, an even bigger mess.\u003C/p>\u003Cp>Right? Sync beyond files to records to data and content. I don't I've been trying to think about this because this comes up quite a bit. There's there's also things like one of the things that I've seen a number of times recently is, can I tell what the file is associated? Can it can can you show me what else you know, where is this file being used?\u003C/p>\u003Cp>Right? So that comes back to in particular, this is problematic for things like where it's embedded as a text, you know, inside of a rich text. My brain goes, how do we we would have to, in some way, keep track of the relationals as part of Directus. Because I did some searches on, like, SQL databases. How can you do this in c e?\u003C/p>\u003Cp>Yeah.\u003C/p>\u003Cp>Speaker 0: It's not really you you would have to pull up what are all of the foreign key constraints that go back to this table and then go search through all of those tables to find foreign keys with the ID, I guess. That's really the only way to do it.\u003C/p>\u003Cp>Speaker 1: Yeah. It is. And you can do some view things. You can do but you have to you know, it's it's complex. It's not something that's just simple to say, where is this?\u003C/p>\u003Cp>But if Directus in some way was actually keeping track in some way of, you know, think of some kind of an indexing or a mechanism of keeping track that when it gets associated, we track that it got associated in some way. Right? Call it a table. Call it a\u003C/p>\u003Cp>Speaker 0: The the difficulty there, of course, is that data could be live updating through all sorts of sources that's not direct us. So how do we keep that index up to date? Or is that something that we have to periodically re scrape to regenerate, which sounds tricky, or tricky to keep that, you know, consistent. Keep that keep that data integrity alive. This is also a feature request that immediately reminds me of be because of this connection, it reminds me of the one around, how do we warn people, about where stuff is used when you delete it?\u003C/p>\u003Cp>Because right now, you can set up the form keys to nullify a file, but if somebody deletes a file, they might not know where they're gonna be nullifying things automatically. Right? It's a very similar, where is this being used question except during delete.\u003C/p>\u003Cp>Speaker 1: Yep. And that's the that's the common request is I you know, at least I would like to know where this, you know, where this thing is where all this thing is being used. You know, what what all is it associated with in that sense\u003C/p>\u003Cp>Speaker 2: Yeah.\u003C/p>\u003Cp>Speaker 1: For tracking it down? Because if I yeah. You know, I wanna understand the impacts of me deleting a file or me deleting a record, what are the Right. Relational impacts?\u003C/p>\u003Cp>Speaker 0: Now looking up all those foreign keys is a pretty heavy thing. But in Directus, we do store that relational information already. So we should have the ability to say what are the relationships that have this collection in it, and then do a sort of aggregate search that says, okay. What is the count of items that have a foreign key to this item? Which should be a relatively e like, not easy, but a cheap operation to do rather.\u003C/p>\u003Cp>I mean, it depends on table size. There's always an asterisk, but we could, you know, do a what's the kind of items that are using the current primary key as a foreign key in the, related tables and then present that as well, right, where we say, okay. We know, this collection is being used in well, in this example's case, direct this files is being used in, photo albums. And therefore, we can say, when you delete this file, you're gonna set it to null in these in 3 different photo album records. Right?\u003C/p>\u003Cp>Is this something you wanna do? Yes or no? So at least be a little bit more helpful about that.\u003C/p>\u003Cp>Speaker 2: Yeah. I really like the idea of, like, having a Oh, sorry.\u003C/p>\u003Cp>Speaker 0: Oh, no. Go ahead. Go ahead, please, dude.\u003C/p>\u003Cp>Speaker 2: Yeah. I really like the idea of having, like, a graph view. Like, just in general, that would show you, okay, this would be deleted. This would be, like, nullified. This would be this this in-depth, that happened with on a delete.\u003C/p>\u003Cp>And, like, the data is already there in the API in the app. We just have to then visualize it with, like, a graph view or a list of things that get deleted, a list of things that get nullified. We aren't we kinda doing something with creating when creating, for example, relational stuff, we already say what we create. Like, do you know this yellow text list that we have on the data data model creation? We can just do the same for the deletion process, basically.\u003C/p>\u003Cp>If you delete an item, go through the whole schema of relations and see what links to what, and that's basically just recursively checking against each nested collection. And the fancy part then would be how to visualize this. And in in terms of, like, do we run it in a list? Do we run it in a fancy graph where it's like, this collection links to that collection, and this field in that collection would then delete another collection or something like that? Or would we just run it as a list very stupidly?\u003C/p>\u003Cp>Speaker 0: And to make that one slightly more complicated, what do you do if there is user input required? So, for example, if the default cascade is make it null, but the field is not nullable, then what? Right? Are we gonna Then\u003C/p>\u003Cp>Speaker 2: you get an escape.\u003C/p>\u003Cp>Speaker 0: Are we gonna tell them you cannot delete it because it's in use, Or are we gonna tell them, what do you wanna do with the 5 places where you're using this? You wanna replace it with something else? And is that something we wanna do in line? Or is it enough if we sell if we just say you cannot delete it right now, go fix the other stuff first? Like, which is also, you know, a flow that would be enough.\u003C/p>\u003Cp>I don't know if it's as useful.\u003C/p>\u003Cp>Speaker 1: Yeah. I think at least indicated that it exists somewhere and then saying, go clean it up before you can actually delete the file. That seems okay. You could give the option to say nullify where I'm at or place with something else where I'm at. Interesting.\u003C/p>\u003Cp>Interesting.\u003C/p>\u003Cp>Speaker 2: I'm I'm also wondering, is it is it is it not really, like, configuration error if you set the relation to nullify something that can't be null? That sounds like somebody has messed up things in that case, which we should also protect people from doing. But\u003C/p>\u003Cp>Speaker 0: Fair enough. Yeah. That that is that is fair. But the the default behavior for foreign key like that is to prevent the deletion, I think. So even if you don't set it to set nil, but you just leave it at the default, which is prevent the deletion, it'll just throw an error.\u003C/p>\u003Cp>Because I throw right now, we don't throw a SQL error that says I cannot delete form keeps Yeah.\u003C/p>\u003Cp>Speaker 2: Exactly. And then we should probably even, like, protect when setting up the relations that you shouldn't be able to set it to nullify something it can't be nullified to.\u003C/p>\u003Cp>Speaker 0: Yeah. But I think it's all the settings. Even the the mistake setup and the the default case. There's a case to be made that we wanna have some sort of user input moment in during the delete that says, okay. We're gonna be either nullifying if that's the setting, or we're gonna try to nullify if that's the setting, across 15 items in your your 12 collections.\u003C/p>\u003Cp>Or if it is a, prevent the deletion, the question could be, do you wanna replace where this is used with something else before you can delete it? Right? That would be a pretty helpful thing. I know we're getting a bit of trend for this particular feature request, but these are all kind of part of the bigger part of the same, sort of questions and user stories.\u003C/p>\u003Cp>Speaker 1: Agreed. And, again, I think he's got he's got some of those cases covered. They they've got some of those cases covered here. Right? So they know to delete the file, keep the file, prompt the user.\u003C/p>\u003Cp>I must\u003C/p>\u003Cp>Speaker 0: delete it\u003C/p>\u003Cp>Speaker 1: in the collection.\u003C/p>\u003Cp>Speaker 0: Well, to to get it back on track for this particular feature request though Yeah. Because the what we just described is, you know, if you wanna follow just a regular foreign key constraint, and we wanna inform the user of what's about to happen, that's part 1. We wanna allow them to take some action if they have to make some changes for it to go through. But then the third one, and that's the new thing in this feature, requested the question, do we wanna do it the other way around as well? Where unlike in a database, we allow a secondary foreign key constraint type of thing where we say, if you delete the the the record that holds the foreign key, delete the related thing.\u003C/p>\u003Cp>And that then has a sort of recursive compound effect where it's like, do we now show any other foreign keys that might exist on the thing that you're deleting through the foreign key that you just deleted? What?\u003C/p>\u003Cp>Speaker 1: Yeah.\u003C/p>\u003Cp>Speaker 0: I think that's probably one of the reasons why, you know, databases don't sort of recursive, like, have that way of doing it both ways because that really feels like, you know, you're you're quickly ending in a in a in a sort of infinite loop type of deal.\u003C/p>\u003Cp>Speaker 1: Yeah. And that might be where maybe you don't show them that. You just simply know that is still being so if they choose, say, the delete option to say, you know, I do wanna delete the file, or the the record in this case, then you could provide an indication that there are existing relationships. Are you really sure? And then it'll affect those other you know, it will affect other things, you know, and number of other things or just the fact that it exists, that it is actually related to other active items.\u003C/p>\u003Cp>So instead of and not try to show them what all because that could be a large number of things. I don't know that you'd want to try and show that in a dialogue box, but you could show this is related to any number of other things or this is related to other things. And therefore, you know, this could have catastrophic effects. Yes or no? And maybe even making an option that, you know, a toggle config flag or something on the settings of that says, if this is still related to other things, then they're not allowed to do that from a permissioning standpoint kind of thing.\u003C/p>\u003Cp>Then, you know, the option is, no, you can't delete this because this is related to other things. Go to the source record and clean it up and do whatever. Right? The whatever workflow. So I think you can go that route, maybe.\u003C/p>\u003Cp>Speaker 2: On another note, I'm also wondering if we should that it's it goes in a similar direction, but, like, protecting the users from making mistakes, would be like a feature where you have a protected collection, that basically says, okay, you have to, for example, enter the, the name or ID or some type of validation before you can actually delete the, the item in the collection. For example, if you're managing users and you don't want to mess up have, your managers mess up the user's collection because that could be catastrophic or something similar, where they would have to then, for example, enter something. And that would also tie into this, like, what happens on the delete part where it's like, okay. This collection is related to other collection that is protected, and we should also, in this collection, mind you that you're deleting something from another collection that is protected. Right?\u003C/p>\u003Cp>Speaker 0: Yes. Yes. Yes. Yes. This old man now this makes me think from a technical perspective.\u003C/p>\u003Cp>We're gonna dive a little deep here. But from a technical perspective, this makes me wonder right now, We rely on the database foreign key constraints for all this. Right? That we say, okay. You said it's a set null.\u003C/p>\u003Cp>That is literally a database foreign key index with a cascade set null. Right? Yeah. But that also means that from a Directus perspective, we're not triggering any logic or hooks or or anything necessarily on the Directus side for those nested deletes because we're just relying on the database to do it. Right?\u003C/p>\u003Cp>Which is a technically performant way, but at the same time, that does raise newer questions around, you know, if you have a flow that handles something on file, delete to clean something up. Right? And that file gets deleted through. Well, I guess a file is actually a bad example, ironically enough, because it's on the disk and not on the database. But if you have a flow that cleans up something, on a database change, but it is changed directly from a foreign key constraint that changes it.\u003C/p>\u003Cp>We're not triggering it as an event. Right?\u003C/p>\u003Cp>Speaker 2: Yeah. I think that was also one of the problems a lot of people had with working with flows that it wasn't, like, cascading these, like, deviate events to, to flows, basically, I think, which would also solve that problem in a sense, I think. Although, I don't remember exactly what the problem there was in detail because it's quite a long time ago, which where I had read through these issues. But I do still like the idea of, like, this this type of protected collection. I I do think that could I'm not sure.\u003C/p>\u003Cp>I haven't seen many press on that idea, but I do think it could be a nice enhancement just from on the side of, like, making sure you don't do anything. But, I mean, aren't we doing something sim I guess, no. We're not. But, for example, on the director's collection, you could technically delete those from the app. Right?\u003C/p>\u003Cp>But we somehow oh, oh, at least Yeah. No. In a sense, we also do some sort of protection there because, like, yeah, sure. You can do that technically, but you really shouldn't.\u003C/p>\u003Cp>Speaker 0: No. No. I'm pretty sure we're we're preventing any any direct to stable modification from the product itself. Yeah. Yeah.\u003C/p>\u003Cp>I mean, you can add custom fields and remove those, but you cannot mess with the the system ones, which I think is a separate feature request, actually, funnily enough. I don't know if we we I forgot if we did one of those, an episode of one of those, but there's a feature request to be able to update, you know, the locked system fields because some people are rightfully so saying, I don't use a description field on files. Can I just delete it? And I'm like, no. Right.\u003C/p>\u003Cp>Not at the moment.\u003C/p>\u003Cp>Speaker 1: Well, I think it was that was actually a permissioning thing. They wanted to be able to not show it. Right? Be able to deselect that as a visible option to the user.\u003C/p>\u003Cp>Speaker 0: That should be fine.\u003C/p>\u003Cp>Speaker 1: So that there there were some key things there. That was actually related to the permissioning. I remember that one because that was I was like, oh, you can't. Different description. There\u003C/p>\u003Cp>Speaker 2: are there\u003C/p>\u003Cp>Speaker 1: are things that you can't remove from the user view. Right? So, again, we do lock the fields, and I think we should we should allow it to have these. But on the access policy side for that particular one, it was, you know, if I'm in the content manager policy here that\u003C/p>\u003Cp>Speaker 0: called app access permission set has you can see your own user, but then that c includes some of those system fields that you may or may not care about. That's Yep.\u003C/p>\u003Cp>Speaker 1: Yep. Yep. So that was all related to this of, you know, if I'm in my directest users on the permissioning side of the app and those kinds of things in the read permissions here. Yeah. Custom coming down into the field permission, I can't deselect.\u003C/p>\u003Cp>So if I don't want to show, you know, the location of the title or the description, because we're not using them or whatever. There's only certain things you can deselect from the key fields.\u003C/p>\u003Cp>Speaker 0: So Yeah. No. That makes sense. That makes sense. That was a little bit.\u003C/p>\u003Cp>Speaker 2: Let's not get I\u003C/p>\u003Cp>Speaker 0: I recognize how bug big of his detour this is from what we're talking about. But\u003C/p>\u003Cp>Speaker 1: I guess the other thing that would be nice, the the one thing that our our locks currently prevent is, like, reordering the fields. Right? So, like, we stick the roll and some of the configuration details at the very bottom. Well, what if I wanted to roll up at the top in the item form to see it Yeah. In in a certain way?\u003C/p>\u003Cp>Speaker 0: I think our founders sells the topic for the next one of these.\u003C/p>\u003Cp>Speaker 1: Yeah. Sometimes. But back to file delete. What was I taking notes on? Larger configuration.\u003C/p>\u003Cp>Speaker 0: Now here's another very real question. I know there's, of course, enough upvotes for us to warn discussing this, but there's also a very real question of, is this something we want? Like, the whole flow of warning people for a cascade delete and doing it one way as per the database the way we do it now. Sure. That that feels like an obvious one.\u003C/p>\u003Cp>That that part, obvious to me. But this one is interesting where it's like I deselect a file from a relationship. Do I wanna be able to delete the file, or is that confusing?\u003C/p>\u003Cp>Speaker 1: For content user for the user experience, yes, I would like that option because the user doesn't want to the the user workflow wouldn't necessarily be I now have to go to the direct to file library, find that file. Once again, how do I find the file? Do I remember the file name? Do I do those things? How do I go and find and now delete that file?\u003C/p>\u003Cp>That I think is the the key thing from a content editors perspective. Yes or no?\u003C/p>\u003Cp>Speaker 2: Yeah. I'm I'm thinking about 80, 20\u003C/p>\u003Cp>Speaker 1: here we have to think about, but from a content editors experience, right, we find it we all find it very annoying if I have to go do 3 more steps to go delete something. Right? If I have to go now, remember to go back to the file library, go search and find the file, and then delete the file, only to find out that the file can't be deleted because it is being used. Or Right. Accidentally now not know that deleting the file has now removed it from some place that I didn't know about or didn't even have access to.\u003C/p>\u003Cp>That's the other permissioning adds another level of complexity to this. Right? So my ability to delete that file, well, it might be in use somewhere else. And that's another reason I think we shouldn't show the items or try to show items necessarily because they may not have access or permissions to where that file is being used. Mhmm.\u003C/p>\u003Cp>And so you get back to the concept of, well, how do I, you know, how do we deal with that? What do we what do we allow or not allow? I think it's a nice workflow, because commonly, right, it's not so much that we're I I think in most of these kind this this particular use case. Right? The file is only being used in the record that it was uploaded for, you know, you know, it's a gallery.\u003C/p>\u003Cp>It's something that they're doing in the, you know, the content users adding that for that specific thing. And then when they're done, they just want it cleaned up. We don't wanna have gigabytes of files laying around in our file storage and in our file systems that we're not using. Mhmm. Two questions.\u003C/p>\u003Cp>Just a thought.\u003C/p>\u003Cp>Speaker 0: One one thought. Two questions. One technical interesting difficulty is nested relational staged changes. As in, if I'm on an item where the file field is required and I choose to delete the file instead of deselect, is that file immediately deleted, or is that file only deleted the moment I hit save on the parent that I'm clicking the delete on? I think that is that is a question.\u003C/p>\u003Cp>And that is mostly around if you're in content versioning, for example. Right? And you make a new version of an existing thing and it uses the same file. If I click delete the file in the version, I now destroy the published one. You know what I mean?\u003C/p>\u003Cp>So that file should only be deleted the moment I publish the staged versions item. I think that's an interesting interesting little problem. But then how is that presented in the UI? Because if you have marked the file as deleted and then you select a different one, do we keep that as a state? Do we show a little indicator that you have 5 things scheduled to be deleted?\u003C/p>\u003Cp>Or how does that work? I think that's a difficult question. And then\u003C/p>\u003Cp>Speaker 1: That's how we're doing it. So that's how we do it today. Right? So we do show that indicator. Right?\u003C/p>\u003Cp>So if you go to I have that will work for that. On most of our relational kinds of things, some of the relational interfaces, we do indicate that you are deleting and adding. Right? So we're removing this. Right?\u003C/p>\u003Cp>We have that indicator there. We don't actually delete until you commit the record. Right? We don't actually propagate any of the changes until we\u003C/p>\u003Cp>Speaker 0: I'm I'm supposed to think of it right in a in a file picker, a deselect and a and a delete is very similar. You deselect with the intent to select a different one. Right? But if I deleted with the intent of selecting a different one, now I'm effectively presented with 2 changes that I made. We don't really have a UI pattern for that, yet, which is something what was it to think about when I left the ad.\u003C/p>\u003Cp>It's just like a regular drop down. It's all the same same problem. The second thing that popped to mind, and this is a bit of a bigger just think out loud type of thing, would it make more sense for a use case like this to make your own custom direct these files collection where there is no relationship to direct to files. There's a relationship just directly to the file. So you would have to store some of the required fields for that to work, like where is it on disk, what disk is it on.\u003C/p>\u003Cp>Is that a thing? Because technically speaking for direct test files, the only required columns to turn that into file management would be what adapter is this on and what is the the file path to find it. Everything else is is metadata that we use to enrich the platform, but not necessarily required to do file management.\u003C/p>\u003Cp>Speaker 1: Good. Then you've got to handle I mean, again, some of the key issues that we run into, right, with how does the file when and where does the file get uploaded? How is that managed? Or are you assuming that the file exists on that file system? Right?\u003C/p>\u003Cp>The the file interfaces do a whole lot of or the APIs. Right? The direct to these APIs do a whole lot of things for you. And we've, you know, some of those new enhancements around file streaming and restarting where you left off. And, you know, these capabilities, when you're dealing with files, it gets, you know, there's a lot of complexity there.\u003C/p>\u003Cp>And I don't think a lot of folks are gonna want to take that on as a I when I wanted to manage a custom extension that's doing these things for me or, you know, replicating the capabilities of the direct to SAP application. Flows is an option. Right? So that is something that there's actually a link. Someone else put a link in here on how they kind of configured a flow to do some of this.\u003C/p>\u003Cp>Speaker 0: Right. Right.\u003C/p>\u003Cp>Speaker 1: Down here. So this thread here, there's actually an example of a flow. Right? So we do have on hook. You can action based on file upload, based on item update, create, delete.\u003C/p>\u003Cp>So you can apply whatever custom logic. I think the main issue there is you don't get a user prompt per se in those cases.\u003C/p>\u003Cp>Speaker 2: I have I have another probably probably a bit of side of like, side topic idea. That like, not not side topic, but, what is it called? Going outside of the the main road. We could have something like reference counted tiles where it's like, okay. This file exists as long as there are any uses of it.\u003C/p>\u003Cp>And when there are no uses of it anymore, it automatically gets deleted, which then we could also look into something where it's like, okay. If I upload the same image twice, we do, like, a hash of the image to compare if we already have that file somewhere, and some fancy fancy things, which in the end should just make it easier to manage all these files. Like, with 500 people uploading separate files, you get the files collection in, like, a giant amount of people having stuff there. And, like, a reference counter thing could just make it a lot easier to manage all these different file or, like, deduplicate files and get rid of, like, unused ones because that's a thing I've run into even by just myself using directors.\u003C/p>\u003Cp>Speaker 1: Mhmm. Yeah. When you don't have direct file store access, which many times in SAS slash cloud slash whatever.\u003C/p>\u003Cp>Speaker 0: Very interesting to start. So my brain is immediately in 12 places with that comment.\u003C/p>\u003Cp>Speaker 2: But it's the\u003C/p>\u003Cp>Speaker 0: an additional piece of functionality around relational data files and otherwise is the show me where the stuff that is not used anywhere.\u003C/p>\u003Cp>Speaker 2: I think it's a very Yeah. That's a good point. Yeah.\u003C/p>\u003Cp>Speaker 0: Right. And this is something on on a layout level where it's like, okay, filter down by stuff that is not used anywhere else, which is, it does make me think of a comment that was on the chat a little earlier from our our own team that was like, hey. I'm already looking forward to the technical complexity of tracking references within text and JSON blobs in a barrel. Right? Which is very, very, very, very, very, very, very, very, pretty true.\u003C/p>\u003Cp>But\u003C/p>\u003Cp>Speaker 2: Yeah. And in that case, it definitely has to be restrained to things that, again, we can, like, check where it's, like, on JSON blobs or, like, repeat us. That will be very, very difficult and probably not feasible. But at least we, like, at least at least we make the option to if you want to have a feature like reference counted files, then there is a way to have it easily and without any manual labor, basically. You could still do a repeater, but then you won't have the fancy it's basically like the idea of a repeater.\u003C/p>\u003Cp>A repeater, you can slap on really quickly to have just any list of data, but it's nothing fancy. You can't fancy query that. I mean, now you can, but a long time\u003C/p>\u003Cp>Speaker 0: you couldn't.\u003C/p>\u003Cp>Speaker 1: Alright. Are we approaching a what do we think is actually achievable? What we would actually like it to do?\u003C/p>\u003Cp>Speaker 0: Oh, what do you want? I love it. I'm I'm still a little bit in two minds of this whole going doing doing for keeping strange whole place. And and the main reason there is because it kinda strays away from the database as the source of truth for this stuff, which could be a good thing because it unlocks other things, but it's quite a big breaking change in how we handle relationships just in general. Right?\u003C/p>\u003Cp>Because right now, foreign keys and direct relations are 1 to 1 the exact same. And we're reaching a point now with this where we're saying, well, we'll use foreign key constraints on the database for performance reasons because they're they're indexed, but we will not rely on them for this sort of behavior on foreign key changes. So, like, for things like, I wanna delete the related thing when I deselect the current thing, that is not a database thing anymore. That's the directest thing. We're just fine.\u003C/p>\u003Cp>It's just a little bigger change.\u003C/p>\u003Cp>Speaker 2: Or not, don't we have to anyways implement it in the future on the server side and not the database side on these constraints? Because when no supporting relations between databases, we can't have that anymore anyways. So we\u003C/p>\u003Cp>Speaker 0: Great.\u003C/p>\u003Cp>Speaker 2: Have to implement it ourselves anyway. So it's just on the road anyway. Yeah. Just a thing you have to pick up and then do, which is not as easy as it sounds. But Mhmm.\u003C/p>\u003Cp>Speaker 0: So with that in mind, I think some of the stuff that we talked about around, you know, warning and informing the user when a form key constraint is about to delete a bunch of stuff or set null to a bunch of stuff. I think that's an obvious thing. Definitely, it's something we wanna have. That would be a big quality of life improvement. I think doing the relationship the other way around, I think if something happened, it'd probably be a longer term thing just because it is a very big breaking change and how we handle relationships today that I wanna do a bit carefully and just more more planned out.\u003C/p>\u003Cp>The whole idea around custom tables for direct to files, I'm not feeling that one. I think that was a oh, you know, a bit of a brain fart. Just thinking that wrong. That's what these specials are for, but it doesn't feel like the right move right here. Because of all the the system logic that's going on under the hood, we we have to keep that in in control.\u003C/p>\u003Cp>What else was on the was Jonathan? You've been taking notes furiously. What am I missing?\u003C/p>\u003Cp>Speaker 1: I'm trying to keep up some of the workflow options, relationship existence, tracking kind of graph style or being able to understand the that was one thing that Nils mentioned just from a UX perspective. I think that's that almost feels more like the admin side and the data model having ERD style visibility and understanding that, oh, there is a relationship to files from x number of collections and being aware of those things. Taking it away from, you know, embedded inside of rich text or repeaters or weird things, but just the actual ERD, the understanding the graph of what is actually related to my content. From an admin perspective, that would be useful. I do really like the idea of at least understanding files is one of the most common things that I see around this, but we can also think, I was talking to Alex and, Antonio on our team this morning.\u003C/p>\u003Cp>They mentioned that, you know, many to any is another one that has this kind of weird thing where there's not an actual relationship. We do manage that in app. It applies to many to any though in the sense of I can go delete a component that might actually be in use somewhere and you don't get a warning of, hey, this is, you know, you you're you're impacting other things, or impacting something.\u003C/p>\u003Cp>Speaker 0: Deleting it from the relationship. You're not deleting the related item as of today rather. Like, that would be a similar to your point though. That's a similar thing with this feature request where if we add delete as a proper delete the related thing, then you're in a whole new world of how do you display that and how does that work? Does that happen to you sync or do the hood or yeah.\u003C/p>\u003Cp>Speaker 1: And I think a lot of this is probably considerations that need to be handled as part of, you know, the new abstraction layers and things where, as Nils mentioned. Right? Longer term, this is not going to you know, as we move to data federation next year, we're gonna need to be able to handle these things as Directus. Right? Understanding that now it's not just it's data in 2 different databases, right, that we've created a virtual relation for.\u003C/p>\u003Cp>We need to understand and track, I think, against I I think as you've said, isn't just a files thing. This really becomes a more kind of global direct us handling logic around how content can be connected to one another. Right? I'll take relationship out. It's just it's connected.\u003C/p>\u003Cp>It's there's there's some form of tracking that needs to be maintained. And I think as as you said, one of the problems that we have today is, well, if someone's doing stuff direct sequel, you know, we try to support all of that and make sure that we're aware of that. But I think as we move towards, you know, as you move towards something like this, well, if you choose to create or do things under the hood, you may not get them. It's the same thing that we do with activity and revision logging. You're not gonna get that.\u003C/p>\u003Cp>If you're doing something outside of the APIs, you don't get those benefits that exist within the Directus application. Now it could be that there's ways to crawl and find that they've done something and add that or indicate that there's something that then needs to be configured. But I think as we move towards Directus doing some of this logic in the abstraction layers, it's going to require that we handle these use cases in a in a comprehensive way.\u003C/p>\u003Cp>Speaker 0: Mhmm. Cool. Well, I think that probably concludes our our little discussion here around feature request 17 853. Any other last closing thoughts here, Neil's, Jonathan? Nope.\u003C/p>\u003Cp>Awesome. Well, cool. Well, thanks everybody for tuning in. As per usual, this will be up on direct us that a o slash TV. I hope you tune in next time about something else.\u003C/p>\u003Cp>Interesting, I'm sure. But until then, thank you for watching. Like and subscribe.\u003C/p>\u003Cp>Speaker 1: Subscribe. Thanks, team. Get in. Cheers.\u003C/p>","Welcome back, everybody. Welcome to another request review. We have a very special guest here today. Welcome, Niels. He's 7 of our usual host, Daniel of the day. Jonathan, what are we gonna be talking about? Today, we are going to talk about discussion number 17, 853. That is going to be about My favorite. File deletion and management. So this is primarily around the relational, file deletes. If you delete a file from a record or you delete a file from the file system or from the direct to files library, what are some better options for managing that relational delete. So currently, we do a do not delete on the file. It's kind of the default configuration. There are some cascading rules and things you can configure in some cases. But because files can be associated with so many different collections and records, this particular request is around, are there some additional options or features that we could add around improving that file management? Right. So that's the that's the general I'll drop a link just in case people didn't get it. Yeah. So to kick that out right away, the, the important thing to note here, of course, is that direct to files, you both have this sort of, you know, physical file on disk, and you have a row in direct to files, the system table that contains additional metadata we cannot store on the file itself. Right? So think about, we store information about, the some of the exit data for easier retrieval. We store, things like width and height, file duration for for movies, I think, and audio files. We have some additional fields, focal points. Yeah. Exactly. Some location text, some optional metadata that's human configurable. And, of course, some information about what direct this user created, updated, and modified it, whatever. So we have a record in the relational database in the system stuff for for more information. So it also means that when it comes to automatically deleting those files, what we're talking about here is effectively a, you know, sort of cascade delete or a cascade update whenever that relational record is getting destroyed. Right? So from a usual database management perspective, this is a very standard task thing where it's like, okay. The ID of the file gets removed. I want there any record that uses it to be destroyed as well. Let's do the other way around. Right? The the foreign key gets removed, destroy the file. Now in this feature request, what which way is it going? Because I believe it's saying that they wanna delete the file when they delete the record where it's used rather than the other way around. Right? Yeah. In this case, yes. They've mentioned it both directions or it's mentioned somewhere in here. But if you're deselecting or removing an item from a a record association. Right? So if you've got something simple like articles with a file associated, one of the option requests discussed here is if I delete or remove the file from here, that the user either automatically deletes the file from the file system, removes it from direct to files, ideally cleans it off the drive. But alternate options were to actually prompt the user for, do you wanna delete the file? And if yes, go ahead. Yeah. Lots of complexities that come with all of that. Right? Because file the file could be in use by another record. The other big thing with files, because files can be embedded inside of things like WYSIWYSIWYSIWYGs and block editors as relational. Right now, and this isn't this isn't necessarily a direct to specific issue. This is a SQL issue. Right? Unless you're maintaining dual relationals all over the place with everything related back into the file system or some mechanism to track because files can be associated with any number of collections and be embedded inside of rich text fields. How do we manage or understand those kinds of things as well? So there's a a number of factors, I think, that make this complex. But for now, at least what they're asking for is if I delete the file from the record, automatically delete the file or prompt the user, with an option to keep or delete the file. So it's an interesting one there because the so so both those points, the first one to your point, this is this is a problem that has been as old as any sort of content management system on the planet is if you have a link to a file in a piece of text, is that a relational record? No. Is that a relationship in a database you can easily track? Also, no. So now on file delete, are you gonna be scanning through all of those blobs of text all over the place to sort of pseudo find relationships that is hella inefficient? Right? So how do you deal with that? That's that's a good one. The second one that is interesting is that this is kind of the going the wrong way, so to speak, if you compare it to how regular relationships work in a database. Right? So usually, when you say when you do a cascade delete, it would be the moment you delete the file, you delete all of the rows where it has been used in a foreign key. Am I saying that right? Or am I making this up? I was getting too confused, to be honest. I think it goes the other way because the foreign key, at least in that case, like in my article case, the foreign key reference is actually here on this record. So we actually store the foreign key. So I believe the cascade is actually going the other way. So if I delete it from here and I tell it to cascade, it should cascade and delete the file. And I believe that actually does. So we can actually double check the settings, article because we do some article in both ways in direct as I was just trying to remember if I wrote like myself which way the default is. So the relationship in this case is directional from direct as follows. Right? It was the rate that I said. It's like the moment you delete the file, you get to choose what you wanna do, with the forward key field. Right? Do you wanna nullify it, or do you wanna destroy the whole row that uses that forwarding key? So so that's why I meant with sort of like the feature request going the opposite way. Right? Because by a database and default, you're saying, okay, the moment you delete the file, delete everything where the file is used. But it feels like this feature request is going the other way. Right? They're saying the moment I deselect the file from a gallery post or something, I also want to trigger a deletion of the related file. Yeah. Yes. Key. So now you're actually you are actually correct. It does go the other way. So if you delete the file, it's actually cleaning up the foreign key, right, is what we're technically do. Yep. My mistake. So this and this is welcome back to the beauty of request review. If you haven't been here before, we always like to diverge as much as we can before we come back down to the notes at the top of the hour. The immediate question to me here becomes, is this a file specific thing, or is this just a directed data thing? Right? Is this something that you should be able to set up for everything where you're like, okay. The moment I I delete this record or deselect this relationship, I wanna be able to remove the thing on the other end. Is that a thing that we just wanna support as a more generic option or is this something that is inherently specific to files? Because it kinda sounds like that this is that this person was mentioning files just because that's the use case for this particular person and this website that they're building. But I could see this as be a relationship thing. Yep. At least implementation wise, it's like equal, I would say. There should be no diff like, no technical difficulties to make it more advanced in a sense or more capable. Yeah. No. I actually like that. I I think, especially as we move towards, you know, our our our future concepts of we want to support non sequel kinds of things. This means, to some degree, direct us needs to understand where things are being used and keep track of that so that otherwise, we can end up with a, you know, an even bigger mess. Right? Sync beyond files to records to data and content. I don't I've been trying to think about this because this comes up quite a bit. There's there's also things like one of the things that I've seen a number of times recently is, can I tell what the file is associated? Can it can can you show me what else you know, where is this file being used? Right? So that comes back to in particular, this is problematic for things like where it's embedded as a text, you know, inside of a rich text. My brain goes, how do we we would have to, in some way, keep track of the relationals as part of Directus. Because I did some searches on, like, SQL databases. How can you do this in c e? Yeah. It's not really you you would have to pull up what are all of the foreign key constraints that go back to this table and then go search through all of those tables to find foreign keys with the ID, I guess. That's really the only way to do it. Yeah. It is. And you can do some view things. You can do but you have to you know, it's it's complex. It's not something that's just simple to say, where is this? But if Directus in some way was actually keeping track in some way of, you know, think of some kind of an indexing or a mechanism of keeping track that when it gets associated, we track that it got associated in some way. Right? Call it a table. Call it a The the difficulty there, of course, is that data could be live updating through all sorts of sources that's not direct us. So how do we keep that index up to date? Or is that something that we have to periodically re scrape to regenerate, which sounds tricky, or tricky to keep that, you know, consistent. Keep that keep that data integrity alive. This is also a feature request that immediately reminds me of be because of this connection, it reminds me of the one around, how do we warn people, about where stuff is used when you delete it? Because right now, you can set up the form keys to nullify a file, but if somebody deletes a file, they might not know where they're gonna be nullifying things automatically. Right? It's a very similar, where is this being used question except during delete. Yep. And that's the that's the common request is I you know, at least I would like to know where this, you know, where this thing is where all this thing is being used. You know, what what all is it associated with in that sense Yeah. For tracking it down? Because if I yeah. You know, I wanna understand the impacts of me deleting a file or me deleting a record, what are the Right. Relational impacts? Now looking up all those foreign keys is a pretty heavy thing. But in Directus, we do store that relational information already. So we should have the ability to say what are the relationships that have this collection in it, and then do a sort of aggregate search that says, okay. What is the count of items that have a foreign key to this item? Which should be a relatively e like, not easy, but a cheap operation to do rather. I mean, it depends on table size. There's always an asterisk, but we could, you know, do a what's the kind of items that are using the current primary key as a foreign key in the, related tables and then present that as well, right, where we say, okay. We know, this collection is being used in well, in this example's case, direct this files is being used in, photo albums. And therefore, we can say, when you delete this file, you're gonna set it to null in these in 3 different photo album records. Right? Is this something you wanna do? Yes or no? So at least be a little bit more helpful about that. Yeah. I really like the idea of, like, having a Oh, sorry. Oh, no. Go ahead. Go ahead, please, dude. Yeah. I really like the idea of having, like, a graph view. Like, just in general, that would show you, okay, this would be deleted. This would be, like, nullified. This would be this this in-depth, that happened with on a delete. And, like, the data is already there in the API in the app. We just have to then visualize it with, like, a graph view or a list of things that get deleted, a list of things that get nullified. We aren't we kinda doing something with creating when creating, for example, relational stuff, we already say what we create. Like, do you know this yellow text list that we have on the data data model creation? We can just do the same for the deletion process, basically. If you delete an item, go through the whole schema of relations and see what links to what, and that's basically just recursively checking against each nested collection. And the fancy part then would be how to visualize this. And in in terms of, like, do we run it in a list? Do we run it in a fancy graph where it's like, this collection links to that collection, and this field in that collection would then delete another collection or something like that? Or would we just run it as a list very stupidly? And to make that one slightly more complicated, what do you do if there is user input required? So, for example, if the default cascade is make it null, but the field is not nullable, then what? Right? Are we gonna Then you get an escape. Are we gonna tell them you cannot delete it because it's in use, Or are we gonna tell them, what do you wanna do with the 5 places where you're using this? You wanna replace it with something else? And is that something we wanna do in line? Or is it enough if we sell if we just say you cannot delete it right now, go fix the other stuff first? Like, which is also, you know, a flow that would be enough. I don't know if it's as useful. Yeah. I think at least indicated that it exists somewhere and then saying, go clean it up before you can actually delete the file. That seems okay. You could give the option to say nullify where I'm at or place with something else where I'm at. Interesting. Interesting. I'm I'm also wondering, is it is it is it not really, like, configuration error if you set the relation to nullify something that can't be null? That sounds like somebody has messed up things in that case, which we should also protect people from doing. But Fair enough. Yeah. That that is that is fair. But the the default behavior for foreign key like that is to prevent the deletion, I think. So even if you don't set it to set nil, but you just leave it at the default, which is prevent the deletion, it'll just throw an error. Because I throw right now, we don't throw a SQL error that says I cannot delete form keeps Yeah. Exactly. And then we should probably even, like, protect when setting up the relations that you shouldn't be able to set it to nullify something it can't be nullified to. Yeah. But I think it's all the settings. Even the the mistake setup and the the default case. There's a case to be made that we wanna have some sort of user input moment in during the delete that says, okay. We're gonna be either nullifying if that's the setting, or we're gonna try to nullify if that's the setting, across 15 items in your your 12 collections. Or if it is a, prevent the deletion, the question could be, do you wanna replace where this is used with something else before you can delete it? Right? That would be a pretty helpful thing. I know we're getting a bit of trend for this particular feature request, but these are all kind of part of the bigger part of the same, sort of questions and user stories. Agreed. And, again, I think he's got he's got some of those cases covered. They they've got some of those cases covered here. Right? So they know to delete the file, keep the file, prompt the user. I must delete it in the collection. Well, to to get it back on track for this particular feature request though Yeah. Because the what we just described is, you know, if you wanna follow just a regular foreign key constraint, and we wanna inform the user of what's about to happen, that's part 1. We wanna allow them to take some action if they have to make some changes for it to go through. But then the third one, and that's the new thing in this feature, requested the question, do we wanna do it the other way around as well? Where unlike in a database, we allow a secondary foreign key constraint type of thing where we say, if you delete the the the record that holds the foreign key, delete the related thing. And that then has a sort of recursive compound effect where it's like, do we now show any other foreign keys that might exist on the thing that you're deleting through the foreign key that you just deleted? What? Yeah. I think that's probably one of the reasons why, you know, databases don't sort of recursive, like, have that way of doing it both ways because that really feels like, you know, you're you're quickly ending in a in a in a sort of infinite loop type of deal. Yeah. And that might be where maybe you don't show them that. You just simply know that is still being so if they choose, say, the delete option to say, you know, I do wanna delete the file, or the the record in this case, then you could provide an indication that there are existing relationships. Are you really sure? And then it'll affect those other you know, it will affect other things, you know, and number of other things or just the fact that it exists, that it is actually related to other active items. So instead of and not try to show them what all because that could be a large number of things. I don't know that you'd want to try and show that in a dialogue box, but you could show this is related to any number of other things or this is related to other things. And therefore, you know, this could have catastrophic effects. Yes or no? And maybe even making an option that, you know, a toggle config flag or something on the settings of that says, if this is still related to other things, then they're not allowed to do that from a permissioning standpoint kind of thing. Then, you know, the option is, no, you can't delete this because this is related to other things. Go to the source record and clean it up and do whatever. Right? The whatever workflow. So I think you can go that route, maybe. On another note, I'm also wondering if we should that it's it goes in a similar direction, but, like, protecting the users from making mistakes, would be like a feature where you have a protected collection, that basically says, okay, you have to, for example, enter the, the name or ID or some type of validation before you can actually delete the, the item in the collection. For example, if you're managing users and you don't want to mess up have, your managers mess up the user's collection because that could be catastrophic or something similar, where they would have to then, for example, enter something. And that would also tie into this, like, what happens on the delete part where it's like, okay. This collection is related to other collection that is protected, and we should also, in this collection, mind you that you're deleting something from another collection that is protected. Right? Yes. Yes. Yes. Yes. This old man now this makes me think from a technical perspective. We're gonna dive a little deep here. But from a technical perspective, this makes me wonder right now, We rely on the database foreign key constraints for all this. Right? That we say, okay. You said it's a set null. That is literally a database foreign key index with a cascade set null. Right? Yeah. But that also means that from a Directus perspective, we're not triggering any logic or hooks or or anything necessarily on the Directus side for those nested deletes because we're just relying on the database to do it. Right? Which is a technically performant way, but at the same time, that does raise newer questions around, you know, if you have a flow that handles something on file, delete to clean something up. Right? And that file gets deleted through. Well, I guess a file is actually a bad example, ironically enough, because it's on the disk and not on the database. But if you have a flow that cleans up something, on a database change, but it is changed directly from a foreign key constraint that changes it. We're not triggering it as an event. Right? Yeah. I think that was also one of the problems a lot of people had with working with flows that it wasn't, like, cascading these, like, deviate events to, to flows, basically, I think, which would also solve that problem in a sense, I think. Although, I don't remember exactly what the problem there was in detail because it's quite a long time ago, which where I had read through these issues. But I do still like the idea of, like, this this type of protected collection. I I do think that could I'm not sure. I haven't seen many press on that idea, but I do think it could be a nice enhancement just from on the side of, like, making sure you don't do anything. But, I mean, aren't we doing something sim I guess, no. We're not. But, for example, on the director's collection, you could technically delete those from the app. Right? But we somehow oh, oh, at least Yeah. No. In a sense, we also do some sort of protection there because, like, yeah, sure. You can do that technically, but you really shouldn't. No. No. I'm pretty sure we're we're preventing any any direct to stable modification from the product itself. Yeah. Yeah. I mean, you can add custom fields and remove those, but you cannot mess with the the system ones, which I think is a separate feature request, actually, funnily enough. I don't know if we we I forgot if we did one of those, an episode of one of those, but there's a feature request to be able to update, you know, the locked system fields because some people are rightfully so saying, I don't use a description field on files. Can I just delete it? And I'm like, no. Right. Not at the moment. Well, I think it was that was actually a permissioning thing. They wanted to be able to not show it. Right? Be able to deselect that as a visible option to the user. That should be fine. So that there there were some key things there. That was actually related to the permissioning. I remember that one because that was I was like, oh, you can't. Different description. There are there are things that you can't remove from the user view. Right? So, again, we do lock the fields, and I think we should we should allow it to have these. But on the access policy side for that particular one, it was, you know, if I'm in the content manager policy here that called app access permission set has you can see your own user, but then that c includes some of those system fields that you may or may not care about. That's Yep. Yep. Yep. So that was all related to this of, you know, if I'm in my directest users on the permissioning side of the app and those kinds of things in the read permissions here. Yeah. Custom coming down into the field permission, I can't deselect. So if I don't want to show, you know, the location of the title or the description, because we're not using them or whatever. There's only certain things you can deselect from the key fields. So Yeah. No. That makes sense. That makes sense. That was a little bit. Let's not get I I recognize how bug big of his detour this is from what we're talking about. But I guess the other thing that would be nice, the the one thing that our our locks currently prevent is, like, reordering the fields. Right? So, like, we stick the roll and some of the configuration details at the very bottom. Well, what if I wanted to roll up at the top in the item form to see it Yeah. In in a certain way? I think our founders sells the topic for the next one of these. Yeah. Sometimes. But back to file delete. What was I taking notes on? Larger configuration. Now here's another very real question. I know there's, of course, enough upvotes for us to warn discussing this, but there's also a very real question of, is this something we want? Like, the whole flow of warning people for a cascade delete and doing it one way as per the database the way we do it now. Sure. That that feels like an obvious one. That that part, obvious to me. But this one is interesting where it's like I deselect a file from a relationship. Do I wanna be able to delete the file, or is that confusing? For content user for the user experience, yes, I would like that option because the user doesn't want to the the user workflow wouldn't necessarily be I now have to go to the direct to file library, find that file. Once again, how do I find the file? Do I remember the file name? Do I do those things? How do I go and find and now delete that file? That I think is the the key thing from a content editors perspective. Yes or no? Yeah. I'm I'm thinking about 80, 20 here we have to think about, but from a content editors experience, right, we find it we all find it very annoying if I have to go do 3 more steps to go delete something. Right? If I have to go now, remember to go back to the file library, go search and find the file, and then delete the file, only to find out that the file can't be deleted because it is being used. Or Right. Accidentally now not know that deleting the file has now removed it from some place that I didn't know about or didn't even have access to. That's the other permissioning adds another level of complexity to this. Right? So my ability to delete that file, well, it might be in use somewhere else. And that's another reason I think we shouldn't show the items or try to show items necessarily because they may not have access or permissions to where that file is being used. Mhmm. And so you get back to the concept of, well, how do I, you know, how do we deal with that? What do we what do we allow or not allow? I think it's a nice workflow, because commonly, right, it's not so much that we're I I think in most of these kind this this particular use case. Right? The file is only being used in the record that it was uploaded for, you know, you know, it's a gallery. It's something that they're doing in the, you know, the content users adding that for that specific thing. And then when they're done, they just want it cleaned up. We don't wanna have gigabytes of files laying around in our file storage and in our file systems that we're not using. Mhmm. Two questions. Just a thought. One one thought. Two questions. One technical interesting difficulty is nested relational staged changes. As in, if I'm on an item where the file field is required and I choose to delete the file instead of deselect, is that file immediately deleted, or is that file only deleted the moment I hit save on the parent that I'm clicking the delete on? I think that is that is a question. And that is mostly around if you're in content versioning, for example. Right? And you make a new version of an existing thing and it uses the same file. If I click delete the file in the version, I now destroy the published one. You know what I mean? So that file should only be deleted the moment I publish the staged versions item. I think that's an interesting interesting little problem. But then how is that presented in the UI? Because if you have marked the file as deleted and then you select a different one, do we keep that as a state? Do we show a little indicator that you have 5 things scheduled to be deleted? Or how does that work? I think that's a difficult question. And then That's how we're doing it. So that's how we do it today. Right? So we do show that indicator. Right? So if you go to I have that will work for that. On most of our relational kinds of things, some of the relational interfaces, we do indicate that you are deleting and adding. Right? So we're removing this. Right? We have that indicator there. We don't actually delete until you commit the record. Right? We don't actually propagate any of the changes until we I'm I'm supposed to think of it right in a in a file picker, a deselect and a and a delete is very similar. You deselect with the intent to select a different one. Right? But if I deleted with the intent of selecting a different one, now I'm effectively presented with 2 changes that I made. We don't really have a UI pattern for that, yet, which is something what was it to think about when I left the ad. It's just like a regular drop down. It's all the same same problem. The second thing that popped to mind, and this is a bit of a bigger just think out loud type of thing, would it make more sense for a use case like this to make your own custom direct these files collection where there is no relationship to direct to files. There's a relationship just directly to the file. So you would have to store some of the required fields for that to work, like where is it on disk, what disk is it on. Is that a thing? Because technically speaking for direct test files, the only required columns to turn that into file management would be what adapter is this on and what is the the file path to find it. Everything else is is metadata that we use to enrich the platform, but not necessarily required to do file management. Good. Then you've got to handle I mean, again, some of the key issues that we run into, right, with how does the file when and where does the file get uploaded? How is that managed? Or are you assuming that the file exists on that file system? Right? The the file interfaces do a whole lot of or the APIs. Right? The direct to these APIs do a whole lot of things for you. And we've, you know, some of those new enhancements around file streaming and restarting where you left off. And, you know, these capabilities, when you're dealing with files, it gets, you know, there's a lot of complexity there. And I don't think a lot of folks are gonna want to take that on as a I when I wanted to manage a custom extension that's doing these things for me or, you know, replicating the capabilities of the direct to SAP application. Flows is an option. Right? So that is something that there's actually a link. Someone else put a link in here on how they kind of configured a flow to do some of this. Right. Right. Down here. So this thread here, there's actually an example of a flow. Right? So we do have on hook. You can action based on file upload, based on item update, create, delete. So you can apply whatever custom logic. I think the main issue there is you don't get a user prompt per se in those cases. I have I have another probably probably a bit of side of like, side topic idea. That like, not not side topic, but, what is it called? Going outside of the the main road. We could have something like reference counted tiles where it's like, okay. This file exists as long as there are any uses of it. And when there are no uses of it anymore, it automatically gets deleted, which then we could also look into something where it's like, okay. If I upload the same image twice, we do, like, a hash of the image to compare if we already have that file somewhere, and some fancy fancy things, which in the end should just make it easier to manage all these files. Like, with 500 people uploading separate files, you get the files collection in, like, a giant amount of people having stuff there. And, like, a reference counter thing could just make it a lot easier to manage all these different file or, like, deduplicate files and get rid of, like, unused ones because that's a thing I've run into even by just myself using directors. Mhmm. Yeah. When you don't have direct file store access, which many times in SAS slash cloud slash whatever. Very interesting to start. So my brain is immediately in 12 places with that comment. But it's the an additional piece of functionality around relational data files and otherwise is the show me where the stuff that is not used anywhere. I think it's a very Yeah. That's a good point. Yeah. Right. And this is something on on a layout level where it's like, okay, filter down by stuff that is not used anywhere else, which is, it does make me think of a comment that was on the chat a little earlier from our our own team that was like, hey. I'm already looking forward to the technical complexity of tracking references within text and JSON blobs in a barrel. Right? Which is very, very, very, very, very, very, very, very, pretty true. But Yeah. And in that case, it definitely has to be restrained to things that, again, we can, like, check where it's, like, on JSON blobs or, like, repeat us. That will be very, very difficult and probably not feasible. But at least we, like, at least at least we make the option to if you want to have a feature like reference counted files, then there is a way to have it easily and without any manual labor, basically. You could still do a repeater, but then you won't have the fancy it's basically like the idea of a repeater. A repeater, you can slap on really quickly to have just any list of data, but it's nothing fancy. You can't fancy query that. I mean, now you can, but a long time you couldn't. Alright. Are we approaching a what do we think is actually achievable? What we would actually like it to do? Oh, what do you want? I love it. I'm I'm still a little bit in two minds of this whole going doing doing for keeping strange whole place. And and the main reason there is because it kinda strays away from the database as the source of truth for this stuff, which could be a good thing because it unlocks other things, but it's quite a big breaking change in how we handle relationships just in general. Right? Because right now, foreign keys and direct relations are 1 to 1 the exact same. And we're reaching a point now with this where we're saying, well, we'll use foreign key constraints on the database for performance reasons because they're they're indexed, but we will not rely on them for this sort of behavior on foreign key changes. So, like, for things like, I wanna delete the related thing when I deselect the current thing, that is not a database thing anymore. That's the directest thing. We're just fine. It's just a little bigger change. Or not, don't we have to anyways implement it in the future on the server side and not the database side on these constraints? Because when no supporting relations between databases, we can't have that anymore anyways. So we Great. Have to implement it ourselves anyway. So it's just on the road anyway. Yeah. Just a thing you have to pick up and then do, which is not as easy as it sounds. But Mhmm. So with that in mind, I think some of the stuff that we talked about around, you know, warning and informing the user when a form key constraint is about to delete a bunch of stuff or set null to a bunch of stuff. I think that's an obvious thing. Definitely, it's something we wanna have. That would be a big quality of life improvement. I think doing the relationship the other way around, I think if something happened, it'd probably be a longer term thing just because it is a very big breaking change and how we handle relationships today that I wanna do a bit carefully and just more more planned out. The whole idea around custom tables for direct to files, I'm not feeling that one. I think that was a oh, you know, a bit of a brain fart. Just thinking that wrong. That's what these specials are for, but it doesn't feel like the right move right here. Because of all the the system logic that's going on under the hood, we we have to keep that in in control. What else was on the was Jonathan? You've been taking notes furiously. What am I missing? I'm trying to keep up some of the workflow options, relationship existence, tracking kind of graph style or being able to understand the that was one thing that Nils mentioned just from a UX perspective. I think that's that almost feels more like the admin side and the data model having ERD style visibility and understanding that, oh, there is a relationship to files from x number of collections and being aware of those things. Taking it away from, you know, embedded inside of rich text or repeaters or weird things, but just the actual ERD, the understanding the graph of what is actually related to my content. From an admin perspective, that would be useful. I do really like the idea of at least understanding files is one of the most common things that I see around this, but we can also think, I was talking to Alex and, Antonio on our team this morning. They mentioned that, you know, many to any is another one that has this kind of weird thing where there's not an actual relationship. We do manage that in app. It applies to many to any though in the sense of I can go delete a component that might actually be in use somewhere and you don't get a warning of, hey, this is, you know, you you're you're impacting other things, or impacting something. Deleting it from the relationship. You're not deleting the related item as of today rather. Like, that would be a similar to your point though. That's a similar thing with this feature request where if we add delete as a proper delete the related thing, then you're in a whole new world of how do you display that and how does that work? Does that happen to you sync or do the hood or yeah. And I think a lot of this is probably considerations that need to be handled as part of, you know, the new abstraction layers and things where, as Nils mentioned. Right? Longer term, this is not going to you know, as we move to data federation next year, we're gonna need to be able to handle these things as Directus. Right? Understanding that now it's not just it's data in 2 different databases, right, that we've created a virtual relation for. We need to understand and track, I think, against I I think as you've said, isn't just a files thing. This really becomes a more kind of global direct us handling logic around how content can be connected to one another. Right? I'll take relationship out. It's just it's connected. It's there's there's some form of tracking that needs to be maintained. And I think as as you said, one of the problems that we have today is, well, if someone's doing stuff direct sequel, you know, we try to support all of that and make sure that we're aware of that. But I think as we move towards, you know, as you move towards something like this, well, if you choose to create or do things under the hood, you may not get them. It's the same thing that we do with activity and revision logging. You're not gonna get that. If you're doing something outside of the APIs, you don't get those benefits that exist within the Directus application. Now it could be that there's ways to crawl and find that they've done something and add that or indicate that there's something that then needs to be configured. But I think as we move towards Directus doing some of this logic in the abstraction layers, it's going to require that we handle these use cases in a in a comprehensive way. Mhmm. Cool. Well, I think that probably concludes our our little discussion here around feature request 17 853. Any other last closing thoughts here, Neil's, Jonathan? Nope. Awesome. Well, cool. Well, thanks everybody for tuning in. As per usual, this will be up on direct us that a o slash TV. I hope you tune in next time about something else. Interesting, I'm sure. But until then, thank you for watching. Like and subscribe. Subscribe. Thanks, team. Get in. Cheers.","published",[139,150],{"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",[],{"id":162,"number":163,"year":164,"episodes":165,"show":178},"6aa046f1-bd53-4510-9af0-c0f3daaf4415",1,"2024",[166,167,168,169,170,171,172,173,174,175,176,122,177],"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","12c8f72d-22fa-4ffa-a9d1-57047216fd1a","8896c934-aa2c-43b6-9342-8275682ab8b2","044b7c89-aaec-43b2-9d6d-6743a0fb5afd",{"title":179,"tile":180},"Request Review","73687d01-3734-4c28-aef7-e6fa8db4cf1e",{"title":8,"meta_description":8},{"id":177,"slug":183,"season":162,"vimeo_id":184,"description":185,"tile":186,"length":187,"resources":188,"people":8,"episode_number":191,"published":133,"title":192,"video_transcript_html":193,"video_transcript_text":194,"content":8,"seo":195,"status":137,"episode_people":196,"recommendations":200},"20594","1013663375","In this recording of our live event on September 12th 2024, Nils, Jonathan, and Hannes discuss Field locking and notifications.","18984108-11ac-467c-b8a1-44c264c8dac4",53,[189],{"name":130,"url":190},"https://github.com/directus/directus/discussions/20594",13,"Field Locking and Notifications","\u003Cp>Speaker 0: Let's rock and roll. I think this fundamentally comes down to something that we've been talking about off and on for a couple of years now is the ability to have things like collaborative editing, at least some level of notification somebody else is working a record as our as we all as as we all here know very well that it's a first save wins at the moment, and you have no idea if anybody else is editing a record that you happen to be editing. Generally, it works out. I don't think it's a frequent occurrence, but it's probably it is something that I think we would all like to see solved. And I'm hopeful that I think I see BrainSlug is in the audience as well.\u003C/p>\u003Cp>That's good because I think he's actually got a custom extension that actually uses websites to actually do this, for, like, live chat and other things. But I think he actually did something as a test, and we'll we'll get through that. But that's what I think this generally is, and we'll get this thing kicked off. I'll turn it to the brains of the operation, and let's roll through this thing. Shout if you need me to show something or pop over to somewhere, and we'll go.\u003C/p>\u003Cp>Speaker 1: Yeah. Tim is disappearing. Yes. I think\u003C/p>\u003Cp>Speaker 0: this was\u003C/p>\u003Cp>Speaker 1: actually a fairly easy feature request, you know, in of itself if you don't consider, like, all the possibilities you could evolve evolve to. Because in the end, it's just asking for, hey. We need a notification if someone is editing something, and that doesn't really it needs some kind of real time possibility, but it doesn't really need any collaborative editing efforts. It enhances it by already. If you put where WordPress does as well.\u003C/p>\u003Cp>Haven't used WordPress in a long, long time, but I think it had something to do with where I told you, hey. This is, this part is embedded by someone else, which is basically what this feature is asking for, just to give them heads up and just to improve the experience. But I think the author of the Hippo Trust, should also be in the audience. Maybe you can raise your hand or something, say hi, to see what you envisioned there. Oh, yeah.\u003C/p>\u003Cp>There he is. Because I know it's, like, just reading it, it seems like a fairly easy thing to implement and to consider. It just we just need to figure out, like, what are the extended use cases we wanna have with it. Is it enough to show that occasion as a starter? Who we able to wanna evolve it into collaborative editing and all of that?\u003C/p>\u003Cp>Because we already had a discussion on real time. I think I just went through a couple of discussions almost October last year, so there have been some discussions about that in general as well. And this feels like an obvious feature to merge into that as well. But I see that Uwe, Uwe. So, excuse me for butchering your name.\u003C/p>\u003Cp>He's typing right now, and he has some additional insight that he collected over last year that this feature request has been up and being voted by the community.\u003C/p>\u003Cp>Speaker 2: Yeah. And and to just give a bit more context from what I remember, I think this was, like, in the talks. Like, then when we started, like, working on WebSocket support and stuff like that, that's was, like, one of the, like, key things we looked at for, like, WebSockets and stuff. But as you mentioned, like, it doesn't really necessarily need WebSockets. You could also, like, pull, like, a get request each second in if you would want to go without WebSockets.\u003C/p>\u003Cp>Like, there's always, like, the possibility to implement this. It's just, like, about what do we want to have this as a real scope in terms of, like, we just implementing this is probably there's more to it in the end, basically. There's more we can do, more we can, like, find out before we go implement this feature. And yeah.\u003C/p>\u003Cp>Speaker 1: Also something to consider is can we implement it as an extension? Does it have to be in core, or is it something that could be a presentation interface, for example, which can, utilize the real time WebSocket API to figure out, like, is there anyone else editing it right now, maybe through a system collection or something that, along those lines where you write an item as soon as somebody is there and you kind of keep it alive, had it write a time stamp when it was last visited or something, and then you could figure out based on that if there currently is one editing it. I can certainly see going that route with an extension as well. It doesn't really need to be a core feature even though it could be nice to have as a core feature. Tim said that one thing he recalls about being difficult is that what do you show about the other user if editing, what the other user that is editing it?\u003C/p>\u003Cp>If you don't have the permissions for other users, I think you would just say, hey. There's one other user editing or something. It doesn't really it's nice to have a name and to have a thumbnail and profile picture and all of that, but it doesn't necessarily need it to function in the 1st place, I would say.\u003C/p>\u003Cp>Speaker 0: So that that was the question that I just wrote down is what's considered editing. Right? Is it just someone has the item record open and they have edit permissions, and therefore that's considered editing or they've actually made a change and that's considered editing. Just something that\u003C/p>\u003Cp>Speaker 1: Or step in between is have they focus on input, for example, if like a step towards editing.\u003C/p>\u003Cp>Speaker 2: Yep. Yeah. That's just another thing we, like, probably have to, like, decide on first for something like this could be implemented because that is like a known edge case. And, like, for example, if we would go with the locking route, where, like, an item gets locked if a user edits, then the real important question is, like, with that system, somebody could just, like, lock us, like, an item forever and not release it, and at any point of time in the future, and that would be a big problem because then you have, like, oh, my my colleague from work is not, giving me access to this item right now. I can't do my job, and that that is not an option, really.\u003C/p>\u003Cp>Speaker 1: So RCS, which is an ancient, vision control version control system from, like, the eighties, like, eighties, nineties from Unix. And they have this concept of locking a file. So if somebody locks a file, you're not able to edit it anymore, and you can, like, force unlock a file. So they certainly use that possibility as well. But Right.\u003C/p>\u003Cp>There is always gets overtook this kind of locking approach, where you're trying to negotiate and take these afterwards. I mean, in this case, I think, as well as the author of the PR, feature, I guess, sorry, said the notification itself should be the better option. Also, seems I wanna say simpler implementation wise because both of them kind of require either, some state on the server or requires some, entries in the database. Having the item page feels easier.\u003C/p>\u003Cp>Speaker 0: Yeah. Because you also have so as as Mills mentioned, right, you have the ability to potentially so we got a lock record route then how long do you allow that lock to remain held? And you automatically time it out and just, you know, that person loses their edits.\u003C/p>\u003Cp>Speaker 1: Mhmm.\u003C/p>\u003Cp>Speaker 0: You know? Or is there an admin way to force specific out of whack and now you got a record block that can't be accessed by the users in any way, shape, or form, even the original user that, you know, initiated the lock. So that means we need some admin, ways of managing and releasing force releasing and resetting locks.\u003C/p>\u003Cp>Speaker 1: Oh, Pedro brings up a very good point. We we have relations in directors, so you're not always just editing a single item, but you can basically walk a whole tree of changes and go 7 drawers deep and start editing, items that don't that aren't actually your item page. That is a very good call, which I haven't considered myself so far.\u003C/p>\u003Cp>Speaker 2: That that's yeah. And that in that sense, locking will probably be, like, very difficult to implement because then the question like, the real question is what even do we lock? Not only, like, when do we lock, but how and what and why. So that's way more tricky than just giving you the information of somebody. Like, in a perfect world, we would have to, like, live collaboration that basically solves the problem out of the box, but that's not really feasible, I think, at the moment in the core implementation of our app.\u003C/p>\u003Cp>So, like, some way of not like, not an either a notification bar or, like, a, like, a schedule to request to see if there's somebody editing your current item and then update it or something like that. That would be like a, I would say, trade off between what we can do right now with your time and what should improve the experience by, like, the minimum, at least. Like, the minimum, of, like, to yeah. Basically, to have some way of knowing that somebody is working on this cost right now, there isn't. I mean, I guess there is on the user because the user table has the records on the last edited item.\u003C/p>\u003Cp>So there is currently already the information stored in directors.\u003C/p>\u003Cp>Speaker 1: Well, the last page, which, gets terribly confusing if you have multiple tabs open. Right? And as soon as you start True.\u003C/p>\u003Cp>Speaker 2: In that case yeah.\u003C/p>\u003Cp>Speaker 1: The information gets up because that's a single entry.\u003C/p>\u003Cp>Speaker 2: But that would be, like, I would say, like, a good start to use that information that we already have to work on that week. Although, we if we were to, want to go for it, we could also make it, like, fully fetched then. Yeah. That's, like, that's also true. Yeah.\u003C/p>\u003Cp>Speaker 1: The problem with the last page is, like, it isn't very it it isn't really, like, a secure information on what is the user what the user is currently doing, because they might open 1 page, might open another page, and it not, like, might open the item page and then tab out, go to a different tab, and navigate in there. And suddenly, you lose all the information because it's really only intended as a way to basically bring the user back to the last page they open once they log out and log back in. That is the intention of page, to have like a more fluent experience when you revisit the same director's instance. So using that really doesn't seem like the right option, but Tim linked his experimental, live collaboration interface extension, which live collaboration really is a big word for it, I wouldn't say, because right now it's just a presentational interface that can notify you if somebody else is, working on the same item. And I just peruse that the code, Tim, please correct me, but it seem it seems like it's using our real time WebSocket, and it just sends custom messages over it.\u003C/p>\u003Cp>I don't know if it needs some does, the WebSocket implementation automatically fan it out to all connected clients, or is there some sort of a component as well in there that is necessary? I'm not able to use that one. I'm thinking, like, not while doing that, let's read some chats. Joshua, she's she's it suggests lock timeouts.\u003C/p>\u003Cp>Speaker 0: It's\u003C/p>\u003Cp>Speaker 1: certainly an option, 100%. Still leaves you with the possibility. What is a lock time out? Is it 5 minutes? Somebody might be editing longer than 5 minutes.\u003C/p>\u003Cp>Is it an hour you might wanna add it to an item sooner than an hour after your colleague left? So if we were to go to the lock route, there certainly has to be a mechanism for you. Yes. I'm sure I wanna override this lock. I wanna take the over this page, mechanism kind of.\u003C/p>\u003Cp>Yeah. I'm with, Pedro's on this, notification that is shown once the user starts editing a record should be great, And it's just a simple avatar of as a fallback, as we said, if the user currently editing the item doesn't have any information about other users or something that doesn't have the permissions.\u003C/p>\u003Cp>Speaker 2: Yeah. And another thing I am wondering right now, or thinking about is, regarding where we would want to store that information, who is currently editing what item. We could, like, store it somewhere in the user collection. We could store it somewhere on the item. So what I was thinking, for example, would be a custom interface that basically makes a request to the, API, on, like, somebody opened this item, a request goes like, because interface interface gets loaded, the interface lets the API know that, like, the value of this field gets then sent to the user's name.\u003C/p>\u003Cp>And, others visiting the same page, the basically, the data gets fetched from the API. And in that field will be the name of the current user who's editing that item, and that interface could then display that information. And that would also, like, require no real time WebSocket connections, and that would also be a very straightforward in that sense that it is very similar to the created or updated on or modified on, interface, which, like, could also make this as an extension because then we are not like, we can just flop, I mean, you're gonna have to edit your schema for that feature to work, and it is not like, it is basically an opt in feature in that case. But it would be very straightforward to implement even as an extension, and that could also be another interesting approach to this problem, basically.\u003C/p>\u003Cp>Speaker 1: So, basically, either extending your current items to a user, or you can even introduce a whole new table that is just a, a lookup table kind of, like, this user, this item timestamp could work. And then, basically, once a user opens the page, it looks up, and the user would have to refresh their page in order to for that information to update. Right? So it wouldn't live update.\u003C/p>\u003Cp>Speaker 2: Yeah. If somebody would leave it and would set it again to null, it wouldn't like, it there's no live update, but it is it allows you to give a get a hint of or if already somebody else opened it recently, basically. I think it\u003C/p>\u003Cp>Speaker 1: should be\u003C/p>\u003Cp>Speaker 2: This quite, like, quite nicely solves the problem in a very stupid way, I would say, and, like like, a very straightforward and simple way. And that might already be enough for, like, most people who want to have this feature. Although, like, the big drawback of this still is that you're basically editing your schema, and that's in that point, and that like, it is an opt in per collection and not just something that works out of the box, except you usually would create a separate table for that. Then it would be for all collections at once. Okay.\u003C/p>\u003Cp>Speaker 1: That is actually fine because you can just add a new field. It doesn't have to be a presentational field, but you can add, like, a\u003C/p>\u003Cp>Speaker 2: Yeah. Exactly. Yeah. We can just add a field that's a string, basically, and that gets set by the interface to the user's name who last opened it if there's none already in it. And that kinda could, like, trick around, like, real time and stuff and just, very, like, get to the point of there's just a name in there and or maybe concatenate even multiple names to each other.\u003C/p>\u003Cp>Speaker 1: The field could be reset. So I would I wouldn't just save the user, but it would also add a current timestamp as well. Okay. Just just for the problem Tim mentions. Like, for example, if your browser crashes, like, for example Yep.\u003C/p>\u003Cp>Normally, you would update the field actually with real time. That is kind of a necess null. That isn't really a necessity since you can send out beacon requests. I don't know if beacons can be post requests. I'm not a 100% sure, but there's a mechanism in a browser that is, like, even if the tab closes, please send out this request to this URL, which would kind of allow us to reset this field whenever a top uploads.\u003C/p>\u003Cp>It just leaves us with the additional problem of if your router crashes. Yeah. They are risky. They're not guaranteed to be a little bit all of our shenanigans that, time attribute, basically. Basically,\u003C/p>\u003Cp>Speaker 2: that's what we've got in the browser, I would say. Yeah. Regarding that disconnects, yeah.\u003C/p>\u003Cp>Speaker 1: WebSocket, but then you would have to go browser, like a module sorry. A bundle route where you also have some server side thing. Because right now we are just thinking, of terms how to implement it in extensions. But certainly, if you're going for implementing any core, there's more possibility to detect if a user has left a page because we can just continuously, we could just continuously monitor which WebSockets are connected, and we could send live updates as soon as the user navigates from there. So very certainly, it was a bit I'm just trying to, like, imagine if there's a possibility to do it, not in core so we can fast track it because, as you know, we have a director's left extension program, where we have extension experts currently developing a lot of features that are that have open feature requests, for example, but never get never really have been implemented in core so far, which is kind of like our experimentation program for figuring out, hey.\u003C/p>\u003Cp>These could be features that could let into core, but let's see if we can use bring them to users quicker by, getting the extension route just because as soon as you'll have a feature in core, you we always wanna make sure it works for 99% of the users, maybe not 99, but a lot of the users. So the process of bringing something to a core always, as you see with all these feature requests, is a lot more involved than just dropping quick extensions saying, hey. This is something experimental.\u003C/p>\u003Cp>Speaker 2: That's correct.\u003C/p>\u003Cp>Speaker 0: It's actually a trigger for me. Alex Vandervalk and I created a we've we had a use case from a client where they wanted to be able to do some relation they wanted to be able to do some enforcement on, or they wanted to know that someone had a current, like, project design. So or a technical design document. It was the one that they were working on right now. And so they wanted to because of that, they wanted to auto filter for those things and be able to indicate that for the user.\u003C/p>\u003Cp>It also then did relational enforcement, through the relational hierarchy of the technical design document, where you had software components and relationals and many to any's and all kinds of things going on. So what we actually did was we used because Directus is actually always you know, the the Directus application is always watching, you know, user actions and saving last page and all those things. We actually intercept that as part of a flow operation, And we if they change to a different technical design document, we auto update the current design document so that it it does the relational enforcement through the permissions and things like that.\u003C/p>\u003Cp>Speaker 2: So very weak.\u003C/p>\u003Cp>Speaker 0: Yeah. So this this actually does that. So this flow actually so this is kind of along Nils' lines of if you add a field or you add a collection that you wanna keep track of and that, you know, provide notification to the user, where you do those kinds of updates. Then in this case, we're actually updating. In this case, it's the direct user table.\u003C/p>\u003Cp>We're setting that to the current TDD that they're working on. So when they change TDDs, it automatically updates this, and therefore, we have that field throughout the relational enforcement. We've got that field, you know, and we can then with many of the filters or your field filters or your policy filters or whatever you wanna apply, we can then enforce that you can't add software components that are part of another TDD. And it was one of those kinds of use cases that we're actually solving. But I think it actually, in some degree, fits this use case as well.\u003C/p>\u003Cp>Speaker 1: That still leaves you with, like, the edge cases of multiple tabs, which wreak havoc with that or could potentially wreak havoc with that. Because right now, we don't really have, like, a possibility to try.\u003C/p>\u003Cp>Speaker 0: Do a bad job. It's actually gonna just do it based on whichever tab you have open and when you're navigating back. Yeah. The the multi tab is a problem anyway. Directus does weird stuff with this particular page save issue anyway.\u003C/p>\u003Cp>I've I've learned never to have multiple tabs of a directus instance open because it just it will wreck havoc on your stuff.\u003C/p>\u003Cp>Speaker 1: I love do a duveis or however you pronounce it, please let me know. Work around right now. They basically have a dedicated Slack channel where they message, I'm editing this, hands off.\u003C/p>\u003Cp>Speaker 2: I love it, damn that's most straightforward, just do it solution, I love it.\u003C/p>\u003Cp>Speaker 0: Out of band, out of band, SS7 messaging. Keep your hand up, miss.\u003C/p>\u003Cp>Speaker 1: That's beautiful.\u003C/p>\u003Cp>Speaker 0: I think\u003C/p>\u003Cp>Speaker 1: we have a solution. I had it short here. Thank you for attending.\u003C/p>\u003Cp>Speaker 0: So so you could use the flow in this case to do that. You could actually automate that and send this send the Slack message to say, hey. I've got this item open. Now, again, it comes back to, am I editing it, not editing it, that kind of thing. But Yeah.\u003C/p>\u003Cp>You could at least have a flow so you don't have to be the one going and typing in the channel that I'm in this record right now.\u003C/p>\u003Cp>Speaker 1: Coming back to, like, how it actually could be implemented, I think there is a viable route to have this implemented as an extension just because, we provide you with all the necessities to do it. We there is real time once you enable WebSockets. So you could potentially even life update the like, life update in a way of, the user who was currently editing the field just left, and you basically subscribe to the changes on that item if you go with the route to have it on this. On one eye like, on a, on the same item or if you introduce, like, Joshua or like I've been talking about, like, a separate table that contains all the locks or not locks, but the current edits or the user presence kind of, I think in collaborative adding new all these presence indication, which basically tells you like this user can get this item, which also allows you to have multiple, which also allows you at some point oh, yeah. Because you would have to so thinking out loud here.\u003C/p>\u003Cp>Coming back to the problem that, Petros mentioned, we have relation items. So we we can traverse an item to different items. And as soon as all of them have this tracking interface, all the necessary, hey. This item is being edited notifications would be there, and they would automatically, oh, they would automatically be gone. That is might be a problem.\u003C/p>\u003Cp>Well, anyways, so the the there is, like, a possibility to have that as an extension. That's kind of what I'm trying to say. And, yep. Because I'm kind of having\u003C/p>\u003Cp>Speaker 0: things for relational, so it's just does a relational edit because just because I'm editing this item doesn't mean I'm editing the relationship right around Oh,\u003C/p>\u003Cp>Speaker 1: yeah. No. No. No. They they would, for example, be loaded as soon as you start opening a drawer, for example, that interface would also be loaded.\u003C/p>\u003Cp>It knows where it's knows\u003C/p>\u003Cp>Speaker 0: and it would do the update and tag that. Yeah. The\u003C/p>\u003Cp>Speaker 1: only problem is the only problem is with that, you would typically use an unmount trigger or something. As soon as that interface is unmounted, you would say, hey. I'm not editing this item anymore. But if you're editing through another item, all those changes would be staged. So if you close the drawer, it actually would tell somebody else, hey, it's not being edited right now or anymore.\u003C/p>\u003Cp>But in fact, it is because in fact, you just made an edit and staged it, and it's only gonna be committed or saved to the database when you save the paradigm.\u003C/p>\u003Cp>Speaker 2: Yeah. That's a good point. With relational data, that that would be tricky to get right in the yeah. Although, it like, at least the the the the one way, the the setting, the username correctly works on relational items if you go for the route of having a field on the separate item, like, on each collection on based on adding a field for tracking, who's currently editing what.\u003C/p>\u003Cp>Speaker 1: But when do you, like, release that information? When do\u003C/p>\u003Cp>Speaker 2: you release That's a good question, which I not yet know the answer to.\u003C/p>\u003Cp>Speaker 1: Like, you would do it on an unknown trigger for the interface or something. Right. Tim says the way he's done it in his, experiment extension is that he only notifies if it has been saved in in the meantime so people can concurrently edit it. Ah. Not that they just notify, hey.\u003C/p>\u003Cp>This has been saved while you are still on this page, which certainly is an option as well. Just doesn't feel as nice, but it feels a lot simpler to implement with some resolving options. Okay. So, like, hey. Take my changes, override it, or take their changes kind of deal.\u003C/p>\u003Cp>Right?\u003C/p>\u003Cp>Speaker 0: Which is commented on the version control. Right? As the you get notified that someone else has made a change, the changes get merged into you can either choose to merge those changes or throw them away and lose out.\u003C/p>\u003Cp>Speaker 1: Which is more along the lines of, like, resolving a conflict and not really and notifying you of a conflict ahead, but not trying to prevent the, conflict before it actually happens, I guess, which is, like, true process or the same kind of thing. I'm honestly divided on which one is better. It won't be, like, trying to prevent the conflict before it's happening. It feels like the nicer user experience to me.\u003C/p>\u003Cp>Speaker 2: Yeah. Like, I I would always go for the user experience, though, in that you want to know in advance that somebody's editing something, not when somebody then actually did their changes and saved them. Because then you can, for example, communicate something with somebody who's working on the same project, on the same item in that sense. Are you editing fields that I'm editing too? Yes.\u003C/p>\u003Cp>No. And depending on that, they can either just continue working on it together or, like, wait for that other person to then actually do the changes and then the next person. Basically, they have the option of, do we have to do it in series, or can we make it in parallel, basically? Like, via Slack or something, like, like, basically talking that out. At least they know that somebody has had has the intent to do changes on this item in the future.\u003C/p>\u003Cp>Speaker 1: There is a Twitter account well, x account, whatever, that explores hideous, design decisions, UX design decisions. We could also add a button, boot this per pay $5 to boot this person out of that item or something.\u003C/p>\u003Cp>Speaker 2: I like it. Though yeah. That would be another option instead of going like the okay. We do it automatically when the user joins in these, we make it like an basically, like an option where it's like you opt in now to mark this item as you're currently editing, or you can leave it if you maybe, for example, like to even make the opt in optional in a sense, which is, like, even then more work to do. And it's probably nicer to make it automatically set to the current user by when editing.\u003C/p>\u003Cp>But, again, like, that opt in makes it also that you have to opt out of it kinda thing where where if it's automatic opt in, you expect to have it automatically, like, put your like, basically know when you're done editing. But if you manually opt it in, then you also have the expectation of you have to manually opt out again of editing this item, if that makes sense.\u003C/p>\u003Cp>Speaker 1: It might be automatic. Otherwise, it's just a hassle like an introduce additional hassle and nobody will start actually.\u003C/p>\u003Cp>Speaker 2: I mean, it's it's less of a hassle than going through Slack conversation and seeing if somebody has the same item name somewhere.\u003C/p>\u003Cp>Speaker 1: Yeah. It's still it's still not as nice as it could be if it's automatic. As that said, editing some editing field should be disabled for others, which introduces another possibility or option or\u003C/p>\u003Cp>Speaker 2: That would be possible through the field by, making filters. That that is if the if there's already text in that field where the name would be saved, that all other items are although that would make it different good for the person actually editing it themselves because then these figures would probably also apply for the same person. Although maybe you can fill it out by the user username and the username matching the in the field. I'm not sure how how crazy good our filter or, like, our, things for that are are that might also work, like I'm not sure.\u003C/p>\u003Cp>Speaker 1: I was actually thinking more along the lines of enhancing the notification, possibilities that basically saying this field has been modified by another user. So I have it in line with all the fields and have a notification for all the fields that have been edited in the meantime, which certainly is possible again with real time. It might introduce another permission hell because people might not be able to see some fields. And if we just send them over WebSocket, anybody can read it, which, yeah, introduces problems again. But from UX perspective, again, it's super, super nice to have the possibility to, being able to tell, hey.\u003C/p>\u003Cp>They edited the event name. They edited the Slack. They edited whatever, as an enhancement to the original request of just shown in banner on my like, for the full item, which then again already puts you more into the collaborative editing experience where you have presence markers on all your fields and, know who's currently doing live edits on the page and seeing the edits and all of that, which is would be amazing to have. But as you already said in the beginning, it's a long ways away with the current architecture of, directors just showing you what's in the database because effectively, that's just what we're doing. Right?\u003C/p>\u003Cp>As soon as something is in the database, you see the most recent data, present in there. We don't really have any mechanisms on top of that for distributing life changes and all that that aren't already committed to the database.\u003C/p>\u003Cp>Speaker 2: Oh, another interesting approach regarding the like, when is a user done with editing an item? This is, like, a crazy solution and probably not really feasible. I still want to go with it because it sounds quite fun. Instead of subscribing and unsubscribing from an item, we could go the road as long as a user is continuously pinging an endpoint, that he's currently editing. This was which also tackles the who which tab is currently open because only the active tab will then ping that endpoint basically ping a certain endpoint to let, the basically, back end know who where the user is currently editing something.\u003C/p>\u003Cp>And we just do it like a automatic opt out after a minute of not receiving a ping from that person. That would also be another interesting approach regarding the when is a user ready like, done with editing an item or something like that. But also that that also has edge cases in a lot of senses, like, in a lot of ways.\u003C/p>\u003Cp>Speaker 1: Yeah. Also, you can, like, you can do that through WebSockets as well since you just\u003C/p>\u003Cp>Speaker 2: Yeah. Track. I mean, yeah. I'm sure. I'm just thinking of, like, would it how tricky would it be to get this working without WebSockets?\u003C/p>\u003Cp>Because that's like, WebSockets makes it also a bit more, like, advanced in a lot of sense. Like, the the I I think we have, like, a ton of good documentation on how to do rest request with like, indirect us with extensions, but on WebSockets, I don't think there's a lot of documentation yet, which makes it difficult for, like, community members to implement features like that. There's always a way, but it's a lot more tricky, and that's I would assume. I'm not sure yet though.\u003C/p>\u003Cp>Speaker 1: We put a couple of guides on how to use the real time SDK, which provides you with a lot of options to use that already in base starting point of Tim's extension as well, for example.\u003C/p>\u003Cp>Speaker 2: Yeah. That's that's we have Tim's example. That's a good starting point.\u003C/p>\u003Cp>Speaker 1: Yeah. But yeah. So I think we agree it's a very good idea. We just aren't sure if it should be in core or if it can be extend an extension because if it can be an extension, let's try to go throughout first and then see it where it breaks and if there are things that have to be implemented for, just because of this many possibilities and flavors to implement this. And if we wanna tackle it, I feel like we should put it in line with presence indications and collaborative editing or at least some way of collaborative editing experience, and that is, like, the next step kind of.\u003C/p>\u003Cp>And I don't know if you wanna have a future in core which will be replacing the not just in future, for example.\u003C/p>\u003Cp>Speaker 2: Yeah. Sure. Not no. Yeah. Right.\u003C/p>\u003Cp>In yeah. I I am definitely on the side of, like, let's make this as an extension, and then people like, even people can go with different ways of implementation depending on their preferences. Like, maybe somebody prefers the way of doing it per item where it's like, we add a field to a collection, and that field stores the current user who's editing it. Maybe some people would prefer that solution, and there would be may maybe somebody else implements another solution where it's stored in a separate collection or where it's done on the WebSocket depending what the requirements or, like, where the interests are. And, having this an extension basically allows us also to explore what people prefer as an implementation and see, like, what implementation of this gets favored over time, and also helps us guide, like, in the next iterations of directors to to find out the right way to do this basically in advance.\u003C/p>\u003Cp>Speaker 1: Which is the exact pitch for directors' lab extensions, I wanna say. It allows us to experiment with features to figure out, like, what is correct, what sticks, what are the things we wanna see, once they might be coming to core. Another great example is the command palette, etcetera, which has been released a couple of\u003C/p>\u003Cp>Speaker 0: weeks ago.\u003C/p>\u003Cp>Speaker 2: I wonder by whom?\u003C/p>\u003Cp>Speaker 1: Because that explores a lot of concepts of, global extensions and everything that can be implemented in core at some point. But for now, there's ways around it, and we can use it to prototype features, and we can use it to prototype\u003C/p>\u003Cp>Speaker 2: stuff\u003C/p>\u003Cp>Speaker 1: like the editing notifications, for example, as well. Jonathan, you've been terribly silent while we've been chugging along here.\u003C/p>\u003Cp>Speaker 0: Yes. I'm just trying to keep up with you guys from writing notes over here. I actually like I I like the VIM style option that you guys have discussed here where you would actually say, just add a toggle at the top, and you can do this in your current data model. Right? You can use roles and permissions that restrict its read only unless you've actually toggled it to say, I wanna edit this item.\u003C/p>\u003Cp>Therefore, I can put the notification and update the notification to say, this user is currently editing. So you could have the flow and the hook and, extensions doing those things. But simply adding a field to the top of your item that says toggle on or off that I'm updating. Right? So VIM, you know, d I, whatever, you know, Linux editing editors who have always been that way where if I'm updating, I have to actually explicitly enter edit mode, and then I have to explicitly exit edit mode.\u003C/p>\u003Cp>So as long as I'm in edit mode, I have it locked. Now that means that I want the ability, you know, to give a flow manual button or other things where you could say, you know, I and it could be a flow button, right, that just says, I wanna enable edit on this. Therefore, send notification to the team that also is responsible.\u003C/p>\u003Cp>Speaker 2: Right. Yeah.\u003C/p>\u003Cp>Speaker 0: You'd send an email. You could send an in app notification. Or, again, just update another field next to it that says, I'm editing this. Therefore, if the administrators need to go in and override you, they could. But at that point, you can use role and policy permissions to say the policy permission is gonna say based on the toggle being an edit, I now have edit permissions on the appropriate fields that I'm allowed access to.\u003C/p>\u003Cp>I can make my edits, save my changes, and you could even make it so that if on save, if you wanted to, right, make your edits, if on save, that automatically toggles it back to unedit. Right? So you could do something like that for the users, and you'd have some control over the workflow there. So I like that idea.\u003C/p>\u003Cp>Speaker 1: Problem with that is it sounds terribly manual.\u003C/p>\u003Cp>Speaker 0: Sure.\u003C/p>\u003Cp>Speaker 2: It's Have the design just behind that. Yeah.\u003C/p>\u003Cp>Speaker 1: Having to have all the hands conditions, and also, additionally, I don't I'm not a 100% sure. I don't think so, to be honest, that it is possible with the current policies because policies are additive. So if you add like a policy, you can't edit this item except for this, and you have another policy which allows the user to edit certain fields in that item. They still will be will be able to edit, edit some fields on those items.\u003C/p>\u003Cp>Speaker 2: Although we don't have the option to make, like, fields disabled depending on other fields, like, these like, depending on things and Yeah.\u003C/p>\u003Cp>Speaker 1: You can\u003C/p>\u003Cp>Speaker 2: make it, like, if the the field has a certain value, other fields get disabled some or something like that. And, like, that's the point where I'm not certain that this would work because we have to make it relative to the user's name. But that could be, like, an option to have it like a no code basically, where you don't have to implement any extension and can get this running in a matter of, like, minute or, like, hours, config by just configuring directors in the end, basically. Hours as\u003C/p>\u003Cp>Speaker 1: soon as you start adding another field or another collection with 10 or 20 fields because you will have to go into every single field and apply that condition to it, because those are fields that you\u003C/p>\u003Cp>Speaker 2: will be horribly manual, but it will get the job done, basically. And for some people, that might already be enough. That's what I'm thinking. Like, a proper solution is always better than just doing it manually in a hacky way, but maybe that's better than writing single things in Slack. So Always better than Slack.\u003C/p>\u003Cp>Speaker 0: You know, it's definitely better than a than a Slack manual. I'm working on this item kind of. So that's that's a lot of work. That's a brutal thing. So\u003C/p>\u003Cp>Speaker 2: But, you know, you're terrific. Right? And then it would be a giant mess of configuration that would that you would have to go through, like, an giant effort for a simple feature that could be implemented with an extension. But on the other side, not everybody is an extension developer and hiring one could also be expensive. Like, I'm not sure.\u003C/p>\u003Cp>So that's maybe, like, you want to just have this and without any, like, effort input like, any large effort put into that and kick that configuration, that might be the way to go using, like, flows and, custom fields or something like that.\u003C/p>\u003Cp>Speaker 1: You still would have to have the user toggle that field and save it. Like, save the item, then only then once somebody else opens the item, you will be able to see it. So there's a lot of, like,\u003C/p>\u003Cp>Speaker 2: user flaws. Yeah.\u003C/p>\u003Cp>Speaker 1: It seems like there's more user error involved than writing a Slack message, because the fields will start appearing, as editable as soon as you toggle it, but you need to remember to save it before. Otherwise, nobody else would see it. So\u003C/p>\u003Cp>Speaker 2: Yeah.\u003C/p>\u003Cp>Speaker 1: Certainly is an option. Certainly isn't the route I would go for.\u003C/p>\u003Cp>Speaker 2: No. I probably neither, but I'm also like an I I I'm also able to develop my own extension. So that also solves the problem for me of, like, would I go the extension route? But, yeah, like, custom extensions, I think that's a great place to for that. Like, that's a powerful way to use, custom extensions, and to just basically extend Reactors without having to con like, to commit to a certain solution that we will decide on.\u003C/p>\u003Cp>Like, if we would now decide on this solution as the best, like, maybe for us right now at the moment, but maybe, like, we don't know of any of certain use cases where people would prefer another solution and, like, going the extension or, like, the lab route, that's definitely sounds like the best solution at the moment, to like, for everybody that people can try this feature out without having to, like, have it in core. And, then, like, depending on how this develops, people can then, like, we can then start looking into how does this get used and how often and how much, like, interest is behind that after it's gets in after it's get gets implemented as a custom extension, and then we can iterate on the next versions of directors to see what we want to have this rigging call just to make it, like, the setup a lot easier for people. Right?\u003C/p>\u003Cp>Speaker 1: And since we still have the original author of that feature request in the chat, I really wanna ask him to, like, as a closing thought kind of deal, because we're doing quarter like, 45 minutes usually for you, your entry, feature request. Right? Or is it a full hour?\u003C/p>\u003Cp>Speaker 0: It's technically a full hour, but we're well, I think we're just about there. I'm putting in some final notes here. But, yes, if they if they offer some ideas, I'd love to hear.\u003C/p>\u003Cp>Speaker 1: Have we covered whatever we were thinking about? Have we outlined the thoughts behind why it's currently not in core or how it could be implemented as an extension? And maybe, like, future options for collaborative editing, which kind of overtake this or replace it at some point. Jonathan, you will have to tell a story while he's telling chat, I think.\u003C/p>\u003Cp>Speaker 0: Yep. Nope. I'm just quickly I'm quickly scanning back through here to see if there was anything that we missed. I think we've covered the general requirements here. And I agree that longer term, I think, you know, ideally collaborative editing solves this problem outright.\u003C/p>\u003Cp>Right? Because then you've got field level notification of who's making changes, when they're making changes. It's real time. You see the changes in real time. But that's a story for another day.\u003C/p>\u003Cp>This this particular use case, I really like the idea of we can potentially put some solutions out into the wild, help us identify what are the edge cases. Because even with collaborative editing, what are the edge cases we're gonna run into? What are things that can happen or will happen? You know, relational always creates the complexity. Right?\u003C/p>\u003Cp>When you start digging into relationals and, you know, at what point are you locking or not locking, what points are you notifying, not notifying, handling some of those cases. And collaborative may just make that all go away. There may not be edge cases other than speed and performance of getting notifications back and forth, for the users. But,\u003C/p>\u003Cp>Speaker 1: Tim isn't allowed to participate in these\u003C/p>\u003Cp>Speaker 0: Oh, versions.\u003C/p>\u003Cp>Speaker 1: Versions. Should be fun. Yeah. Versions. We haven't really talked about versions in this whole thing.\u003C/p>\u003Cp>Right? That is yeah. You're not allowed to participate. I don't think so. You also versions.\u003C/p>\u003Cp>There's a thing like versions.\u003C/p>\u003Cp>Speaker 2: Yeah. That would make it a lot more difficult. Although I'm\u003C/p>\u003Cp>Speaker 1: sorry though. Do\u003C/p>\u003Cp>Speaker 0: for for the for the extensions, you can build your own. Right? That's an option. You can start with that today.\u003C/p>\u003Cp>Speaker 1: You bring it to a very good point. We as\u003C/p>\u003Cp>Speaker 0: the core team, I will get this in as a request into the Directus Labs extensions group. So that there is a core team that is working custom extensions as part of the marketplace. That's where things like yeah. You may have seen it today, but I have this I actually have this one installed. I love this one.\u003C/p>\u003Cp>The spreadsheet. Right? The spreadsheet layout, this ability to edit these things live right here. Fantastic. Love it.\u003C/p>\u003Cp>This has been one that was that's been asked for since the day I joined. I've I've heard people asking for spreadsheet style layout. So I\u003C/p>\u003Cp>Speaker 2: think I remember, Ben asking for this feature, like, in 2,000 well, at 2,021 or something, like, or even before that. So, yeah, it has been on a long road of, like, when will this come? When will this come?\u003C/p>\u003Cp>Speaker 1: When will\u003C/p>\u003Cp>Speaker 2: this get implemented?\u003C/p>\u003Cp>Speaker 1: But doom is bringing up a very good point because, yeah, sure. You don't use versions, but the reason why it's taking us so long to bring new stuff like this into core sometimes is you don't use versions, other people might. So everything that is in core has to work for all the features that we already support.\u003C/p>\u003Cp>Speaker 2: Didn't he set the other way around? Because it's like double negation. Is it like who does not use versions in a sense that, like, everybody use versions? Or am I misunderstanding his message?\u003C/p>\u003Cp>Speaker 0: No. Content versioning is\u003C/p>\u003Cp>Speaker 1: I would think Unless we have\u003C/p>\u003Cp>Speaker 0: fixed the permissioning problem, we still it it's it's very, very limited in its use case options and where you can actually today, because of publishing and editing permissions. So if I wanna main should technically be read only and locked, which is published state. But as soon as you create a content version, if you've got the main record locked, all content versions are locked without changing main. So there are permissioning issues, policy issues right now on the permissioning side that make content versioning difficult to use if not impossible. What's that?\u003C/p>\u003Cp>Speaker 1: Do we have an issue for that? I have to ask now because I was the one\u003C/p>\u003Cp>Speaker 0: Yep.\u003C/p>\u003Cp>Speaker 1: We had is it is it if you have a problem?\u003C/p>\u003Cp>Speaker 0: We've got open feature request for it. Yes.\u003C/p>\u003Cp>Speaker 1: What is feature request?\u003C/p>\u003Cp>Speaker 0: So it's a again, this comes back to, you know, the way the policies are implemented currently. It relies on the main permissioning rather than the version permission version having its own permissioning. Yeah. So you can lock things like I can prevent promoting. I can do things around.\u003C/p>\u003Cp>Can they create or not create, you know, versions? Can they promote or not promote versions? But the ability to edit that version is dependent on the permissions of main, and therefore, I can't do things like lock main, which means now a user, if they've got the permission, they can edit the published record live without doing it inside of a version. So there's some things that are problematic there.\u003C/p>\u003Cp>Speaker 1: That's a very good point. Yeah.\u003C/p>\u003Cp>Speaker 0: Neither here nor there. Just for the folks here, if you see anything in this particular project, this is kind of core team provided. It's not guaranteed that it's maintained long term, but you have if you see these in the marketplace, right, so Directus marketplace here, if you see those in this particular layout and if you see anyone with the let me put an AI space here. If you see anyone with this little check mark here, that tends to be core team. They've been approved, so you can at least trust that it's coming from a reliable source, in that sense, generally.\u003C/p>\u003Cp>But marketplace extensions is where this will would show up. So if we get the team to agree that they wanna take this on, you'll see that show up at some point in the next 2 to 4 months, generally. We tend to try and get these we're we're tend to roll out, these lab extensions on a monthly basis. So we've got well, again, no guarantees, but, hopefully, the team will decide that this is worthwhile. I'll put the feedback in to say that this seems like a really cool one to actually have out there in the wild to get this haptic feedback so that we know what we need to watch out for as we continue to implement these kinds of features in Directus\u003C/p>\u003Cp>Speaker 1: Core. So\u003C/p>\u003Cp>Speaker 2: so,\u003C/p>\u003Cp>Speaker 0: Petros, give it a give it an upvote or you're not finding the ticket, open a ticket. Yep. The this is\u003C/p>\u003Cp>Speaker 2: a I\u003C/p>\u003Cp>Speaker 0: ran into it. It was what the the first week that we rolled content versioning out, I had a client reach out. I need to be able to do I'm trying to do x y z, and it doesn't seem to be working. And I tried I tried flows. I tried work around.\u003C/p>\u003Cp>I tried all kinds of hacks. I could not get around the fact that main is driving permissions for the version. So it's, it is the there's a slight problem there. Although I guess you could with a flow, you could watch on main if main's in published, you could just prevent. But it's a it's a it's a bit hacky in the sense of the user can make a whole bunch of changes.\u003C/p>\u003Cp>Now try to save that and realize that they were in main to be blocked. But you can at least you could put some validation in place that force prevents that save.\u003C/p>\u003Cp>Speaker 1: Feels like a very good discussion topic for another feature request. So\u003C/p>\u003Cp>Speaker 2: Yeah. Absolutely. The point.\u003C/p>\u003Cp>Speaker 1: Straight to the point. Yeah. Of having versions and promoting and demoting versions, versions. Where we get those permissions from since, like, you correctly said all the permissions are determined by the main items since we have one, like, one permissioning engine in core. And it just looks at the main item, and it actually does it actually has a database evaluate all those permissions for you, which makes it easier in a lot of senses, but makes stuff like this where versions are actually separately maintained JSON blobs of that item a lot more difficult.\u003C/p>\u003Cp>Yeah.\u003C/p>\u003Cp>Speaker 0: Very true. But we're off topic. Any final parting thoughts on editing, notification?\u003C/p>\u003Cp>Speaker 1: Sounds cool.\u003C/p>\u003Cp>Speaker 2: It's like\u003C/p>\u003Cp>Speaker 1: there's an extension. There those are my final words I wanna say. Yeah. Because I definitely see the US improvement. I see the value in it.\u003C/p>\u003Cp>I'm just not a 100% sure if we can get it into core properly while keeping all the features we currently already have in mind in a reasonable time frame. Yep. It's\u003C/p>\u003Cp>Speaker 2: always the goddamn time.\u003C/p>\u003Cp>Speaker 0: Well, no.\u003C/p>\u003Cp>Speaker 2: Yeah. But let's let's see what we can do. Put it. Yeah.\u003C/p>\u003Cp>Speaker 1: And, I mean, we can also, like, put it out here. If you feel like, hey, that is an extension I'm gonna develop, reach out to us. Maybe we can help you.\u003C/p>\u003Cp>Speaker 2: That would be awesome. Yeah. I would love to hear people getting just their hands dirty in this.\u003C/p>\u003Cp>Speaker 1: Because in the end, anyone can develop an extension for directors. We try to make it as open and easy as possible. So if you feel like that is something you wanna try, reach out to any of us, and we'll see what the options are.\u003C/p>\u003Cp>Speaker 0: Actually, reach out via the ticket. So post your comments, thoughts, work, other things that you're doing. Let's make sure it gets back to this ticket so that we can actually track that progress. And Yeah. We'll try and do the same.\u003C/p>\u003Cp>We'll, again, when we we do these kinds of extension developments, we'll tag that back into this ticket. So if it gets accepted and committed and delivered, we'll we'll try to remember to populate that back into the ticket. Alright. Cool. Well,\u003C/p>\u003Cp>Speaker 1: well, honest sales.\u003C/p>\u003Cp>Speaker 0: Wonderful having you guys join on short notice.\u003C/p>\u003Cp>Speaker 2: Yeah. Was this last of the year?\u003C/p>\u003Cp>Speaker 1: As usual.\u003C/p>\u003Cp>Speaker 0: It's exciting. Team, thanks everyone for joining. Have a wonderful rest of your week. And as always, reach out through Discord or through the ticketing systems, and we're here to\u003C/p>\u003Cp>Speaker 1: help us find out. October 15th for the next change log that covers all the changes that will be released in the new version. If you're there.\u003C/p>\u003Cp>Speaker 0: And as always, this will be posted in the request review channel of the Directus IO TV.\u003C/p>\u003Cp>Speaker 1: Chat out everyone. Last chat message. All the feedback from this call is has actually been typed up by Jonathan while we were talking until Thursday.\u003C/p>\u003Cp>Speaker 0: I will see. Yeah. Well, I did. You guys feel free\u003C/p>\u003Cp>Speaker 1: to add\u003C/p>\u003Cp>Speaker 0: if I missed anything. Cheers, everyone.\u003C/p>\u003Cp>Speaker 2: Cheers. Cheers. Bye bye.\u003C/p>","Let's rock and roll. I think this fundamentally comes down to something that we've been talking about off and on for a couple of years now is the ability to have things like collaborative editing, at least some level of notification somebody else is working a record as our as we all as as we all here know very well that it's a first save wins at the moment, and you have no idea if anybody else is editing a record that you happen to be editing. Generally, it works out. I don't think it's a frequent occurrence, but it's probably it is something that I think we would all like to see solved. And I'm hopeful that I think I see BrainSlug is in the audience as well. That's good because I think he's actually got a custom extension that actually uses websites to actually do this, for, like, live chat and other things. But I think he actually did something as a test, and we'll we'll get through that. But that's what I think this generally is, and we'll get this thing kicked off. I'll turn it to the brains of the operation, and let's roll through this thing. Shout if you need me to show something or pop over to somewhere, and we'll go. Yeah. Tim is disappearing. Yes. I think this was actually a fairly easy feature request, you know, in of itself if you don't consider, like, all the possibilities you could evolve evolve to. Because in the end, it's just asking for, hey. We need a notification if someone is editing something, and that doesn't really it needs some kind of real time possibility, but it doesn't really need any collaborative editing efforts. It enhances it by already. If you put where WordPress does as well. Haven't used WordPress in a long, long time, but I think it had something to do with where I told you, hey. This is, this part is embedded by someone else, which is basically what this feature is asking for, just to give them heads up and just to improve the experience. But I think the author of the Hippo Trust, should also be in the audience. Maybe you can raise your hand or something, say hi, to see what you envisioned there. Oh, yeah. There he is. Because I know it's, like, just reading it, it seems like a fairly easy thing to implement and to consider. It just we just need to figure out, like, what are the extended use cases we wanna have with it. Is it enough to show that occasion as a starter? Who we able to wanna evolve it into collaborative editing and all of that? Because we already had a discussion on real time. I think I just went through a couple of discussions almost October last year, so there have been some discussions about that in general as well. And this feels like an obvious feature to merge into that as well. But I see that Uwe, Uwe. So, excuse me for butchering your name. He's typing right now, and he has some additional insight that he collected over last year that this feature request has been up and being voted by the community. Yeah. And and to just give a bit more context from what I remember, I think this was, like, in the talks. Like, then when we started, like, working on WebSocket support and stuff like that, that's was, like, one of the, like, key things we looked at for, like, WebSockets and stuff. But as you mentioned, like, it doesn't really necessarily need WebSockets. You could also, like, pull, like, a get request each second in if you would want to go without WebSockets. Like, there's always, like, the possibility to implement this. It's just, like, about what do we want to have this as a real scope in terms of, like, we just implementing this is probably there's more to it in the end, basically. There's more we can do, more we can, like, find out before we go implement this feature. And yeah. Also something to consider is can we implement it as an extension? Does it have to be in core, or is it something that could be a presentation interface, for example, which can, utilize the real time WebSocket API to figure out, like, is there anyone else editing it right now, maybe through a system collection or something that, along those lines where you write an item as soon as somebody is there and you kind of keep it alive, had it write a time stamp when it was last visited or something, and then you could figure out based on that if there currently is one editing it. I can certainly see going that route with an extension as well. It doesn't really need to be a core feature even though it could be nice to have as a core feature. Tim said that one thing he recalls about being difficult is that what do you show about the other user if editing, what the other user that is editing it? If you don't have the permissions for other users, I think you would just say, hey. There's one other user editing or something. It doesn't really it's nice to have a name and to have a thumbnail and profile picture and all of that, but it doesn't necessarily need it to function in the 1st place, I would say. So that that was the question that I just wrote down is what's considered editing. Right? Is it just someone has the item record open and they have edit permissions, and therefore that's considered editing or they've actually made a change and that's considered editing. Just something that Or step in between is have they focus on input, for example, if like a step towards editing. Yep. Yeah. That's just another thing we, like, probably have to, like, decide on first for something like this could be implemented because that is like a known edge case. And, like, for example, if we would go with the locking route, where, like, an item gets locked if a user edits, then the real important question is, like, with that system, somebody could just, like, lock us, like, an item forever and not release it, and at any point of time in the future, and that would be a big problem because then you have, like, oh, my my colleague from work is not, giving me access to this item right now. I can't do my job, and that that is not an option, really. So RCS, which is an ancient, vision control version control system from, like, the eighties, like, eighties, nineties from Unix. And they have this concept of locking a file. So if somebody locks a file, you're not able to edit it anymore, and you can, like, force unlock a file. So they certainly use that possibility as well. But Right. There is always gets overtook this kind of locking approach, where you're trying to negotiate and take these afterwards. I mean, in this case, I think, as well as the author of the PR, feature, I guess, sorry, said the notification itself should be the better option. Also, seems I wanna say simpler implementation wise because both of them kind of require either, some state on the server or requires some, entries in the database. Having the item page feels easier. Yeah. Because you also have so as as Mills mentioned, right, you have the ability to potentially so we got a lock record route then how long do you allow that lock to remain held? And you automatically time it out and just, you know, that person loses their edits. Mhmm. You know? Or is there an admin way to force specific out of whack and now you got a record block that can't be accessed by the users in any way, shape, or form, even the original user that, you know, initiated the lock. So that means we need some admin, ways of managing and releasing force releasing and resetting locks. Oh, Pedro brings up a very good point. We we have relations in directors, so you're not always just editing a single item, but you can basically walk a whole tree of changes and go 7 drawers deep and start editing, items that don't that aren't actually your item page. That is a very good call, which I haven't considered myself so far. That that's yeah. And that in that sense, locking will probably be, like, very difficult to implement because then the question like, the real question is what even do we lock? Not only, like, when do we lock, but how and what and why. So that's way more tricky than just giving you the information of somebody. Like, in a perfect world, we would have to, like, live collaboration that basically solves the problem out of the box, but that's not really feasible, I think, at the moment in the core implementation of our app. So, like, some way of not like, not an either a notification bar or, like, a, like, a schedule to request to see if there's somebody editing your current item and then update it or something like that. That would be like a, I would say, trade off between what we can do right now with your time and what should improve the experience by, like, the minimum, at least. Like, the minimum, of, like, to yeah. Basically, to have some way of knowing that somebody is working on this cost right now, there isn't. I mean, I guess there is on the user because the user table has the records on the last edited item. So there is currently already the information stored in directors. Well, the last page, which, gets terribly confusing if you have multiple tabs open. Right? And as soon as you start True. In that case yeah. The information gets up because that's a single entry. But that would be, like, I would say, like, a good start to use that information that we already have to work on that week. Although, we if we were to, want to go for it, we could also make it, like, fully fetched then. Yeah. That's, like, that's also true. Yeah. The problem with the last page is, like, it isn't very it it isn't really, like, a secure information on what is the user what the user is currently doing, because they might open 1 page, might open another page, and it not, like, might open the item page and then tab out, go to a different tab, and navigate in there. And suddenly, you lose all the information because it's really only intended as a way to basically bring the user back to the last page they open once they log out and log back in. That is the intention of page, to have like a more fluent experience when you revisit the same director's instance. So using that really doesn't seem like the right option, but Tim linked his experimental, live collaboration interface extension, which live collaboration really is a big word for it, I wouldn't say, because right now it's just a presentational interface that can notify you if somebody else is, working on the same item. And I just peruse that the code, Tim, please correct me, but it seem it seems like it's using our real time WebSocket, and it just sends custom messages over it. I don't know if it needs some does, the WebSocket implementation automatically fan it out to all connected clients, or is there some sort of a component as well in there that is necessary? I'm not able to use that one. I'm thinking, like, not while doing that, let's read some chats. Joshua, she's she's it suggests lock timeouts. It's certainly an option, 100%. Still leaves you with the possibility. What is a lock time out? Is it 5 minutes? Somebody might be editing longer than 5 minutes. Is it an hour you might wanna add it to an item sooner than an hour after your colleague left? So if we were to go to the lock route, there certainly has to be a mechanism for you. Yes. I'm sure I wanna override this lock. I wanna take the over this page, mechanism kind of. Yeah. I'm with, Pedro's on this, notification that is shown once the user starts editing a record should be great, And it's just a simple avatar of as a fallback, as we said, if the user currently editing the item doesn't have any information about other users or something that doesn't have the permissions. Yeah. And another thing I am wondering right now, or thinking about is, regarding where we would want to store that information, who is currently editing what item. We could, like, store it somewhere in the user collection. We could store it somewhere on the item. So what I was thinking, for example, would be a custom interface that basically makes a request to the, API, on, like, somebody opened this item, a request goes like, because interface interface gets loaded, the interface lets the API know that, like, the value of this field gets then sent to the user's name. And, others visiting the same page, the basically, the data gets fetched from the API. And in that field will be the name of the current user who's editing that item, and that interface could then display that information. And that would also, like, require no real time WebSocket connections, and that would also be a very straightforward in that sense that it is very similar to the created or updated on or modified on, interface, which, like, could also make this as an extension because then we are not like, we can just flop, I mean, you're gonna have to edit your schema for that feature to work, and it is not like, it is basically an opt in feature in that case. But it would be very straightforward to implement even as an extension, and that could also be another interesting approach to this problem, basically. So, basically, either extending your current items to a user, or you can even introduce a whole new table that is just a, a lookup table kind of, like, this user, this item timestamp could work. And then, basically, once a user opens the page, it looks up, and the user would have to refresh their page in order to for that information to update. Right? So it wouldn't live update. Yeah. If somebody would leave it and would set it again to null, it wouldn't like, it there's no live update, but it is it allows you to give a get a hint of or if already somebody else opened it recently, basically. I think it should be This quite, like, quite nicely solves the problem in a very stupid way, I would say, and, like like, a very straightforward and simple way. And that might already be enough for, like, most people who want to have this feature. Although, like, the big drawback of this still is that you're basically editing your schema, and that's in that point, and that like, it is an opt in per collection and not just something that works out of the box, except you usually would create a separate table for that. Then it would be for all collections at once. Okay. That is actually fine because you can just add a new field. It doesn't have to be a presentational field, but you can add, like, a Yeah. Exactly. Yeah. We can just add a field that's a string, basically, and that gets set by the interface to the user's name who last opened it if there's none already in it. And that kinda could, like, trick around, like, real time and stuff and just, very, like, get to the point of there's just a name in there and or maybe concatenate even multiple names to each other. The field could be reset. So I would I wouldn't just save the user, but it would also add a current timestamp as well. Okay. Just just for the problem Tim mentions. Like, for example, if your browser crashes, like, for example Yep. Normally, you would update the field actually with real time. That is kind of a necess null. That isn't really a necessity since you can send out beacon requests. I don't know if beacons can be post requests. I'm not a 100% sure, but there's a mechanism in a browser that is, like, even if the tab closes, please send out this request to this URL, which would kind of allow us to reset this field whenever a top uploads. It just leaves us with the additional problem of if your router crashes. Yeah. They are risky. They're not guaranteed to be a little bit all of our shenanigans that, time attribute, basically. Basically, that's what we've got in the browser, I would say. Yeah. Regarding that disconnects, yeah. WebSocket, but then you would have to go browser, like a module sorry. A bundle route where you also have some server side thing. Because right now we are just thinking, of terms how to implement it in extensions. But certainly, if you're going for implementing any core, there's more possibility to detect if a user has left a page because we can just continuously, we could just continuously monitor which WebSockets are connected, and we could send live updates as soon as the user navigates from there. So very certainly, it was a bit I'm just trying to, like, imagine if there's a possibility to do it, not in core so we can fast track it because, as you know, we have a director's left extension program, where we have extension experts currently developing a lot of features that are that have open feature requests, for example, but never get never really have been implemented in core so far, which is kind of like our experimentation program for figuring out, hey. These could be features that could let into core, but let's see if we can use bring them to users quicker by, getting the extension route just because as soon as you'll have a feature in core, you we always wanna make sure it works for 99% of the users, maybe not 99, but a lot of the users. So the process of bringing something to a core always, as you see with all these feature requests, is a lot more involved than just dropping quick extensions saying, hey. This is something experimental. That's correct. It's actually a trigger for me. Alex Vandervalk and I created a we've we had a use case from a client where they wanted to be able to do some relation they wanted to be able to do some enforcement on, or they wanted to know that someone had a current, like, project design. So or a technical design document. It was the one that they were working on right now. And so they wanted to because of that, they wanted to auto filter for those things and be able to indicate that for the user. It also then did relational enforcement, through the relational hierarchy of the technical design document, where you had software components and relationals and many to any's and all kinds of things going on. So what we actually did was we used because Directus is actually always you know, the the Directus application is always watching, you know, user actions and saving last page and all those things. We actually intercept that as part of a flow operation, And we if they change to a different technical design document, we auto update the current design document so that it it does the relational enforcement through the permissions and things like that. So very weak. Yeah. So this this actually does that. So this flow actually so this is kind of along Nils' lines of if you add a field or you add a collection that you wanna keep track of and that, you know, provide notification to the user, where you do those kinds of updates. Then in this case, we're actually updating. In this case, it's the direct user table. We're setting that to the current TDD that they're working on. So when they change TDDs, it automatically updates this, and therefore, we have that field throughout the relational enforcement. We've got that field, you know, and we can then with many of the filters or your field filters or your policy filters or whatever you wanna apply, we can then enforce that you can't add software components that are part of another TDD. And it was one of those kinds of use cases that we're actually solving. But I think it actually, in some degree, fits this use case as well. That still leaves you with, like, the edge cases of multiple tabs, which wreak havoc with that or could potentially wreak havoc with that. Because right now, we don't really have, like, a possibility to try. Do a bad job. It's actually gonna just do it based on whichever tab you have open and when you're navigating back. Yeah. The the multi tab is a problem anyway. Directus does weird stuff with this particular page save issue anyway. I've I've learned never to have multiple tabs of a directus instance open because it just it will wreck havoc on your stuff. I love do a duveis or however you pronounce it, please let me know. Work around right now. They basically have a dedicated Slack channel where they message, I'm editing this, hands off. I love it, damn that's most straightforward, just do it solution, I love it. Out of band, out of band, SS7 messaging. Keep your hand up, miss. That's beautiful. I think we have a solution. I had it short here. Thank you for attending. So so you could use the flow in this case to do that. You could actually automate that and send this send the Slack message to say, hey. I've got this item open. Now, again, it comes back to, am I editing it, not editing it, that kind of thing. But Yeah. You could at least have a flow so you don't have to be the one going and typing in the channel that I'm in this record right now. Coming back to, like, how it actually could be implemented, I think there is a viable route to have this implemented as an extension just because, we provide you with all the necessities to do it. We there is real time once you enable WebSockets. So you could potentially even life update the like, life update in a way of, the user who was currently editing the field just left, and you basically subscribe to the changes on that item if you go with the route to have it on this. On one eye like, on a, on the same item or if you introduce, like, Joshua or like I've been talking about, like, a separate table that contains all the locks or not locks, but the current edits or the user presence kind of, I think in collaborative adding new all these presence indication, which basically tells you like this user can get this item, which also allows you to have multiple, which also allows you at some point oh, yeah. Because you would have to so thinking out loud here. Coming back to the problem that, Petros mentioned, we have relation items. So we we can traverse an item to different items. And as soon as all of them have this tracking interface, all the necessary, hey. This item is being edited notifications would be there, and they would automatically, oh, they would automatically be gone. That is might be a problem. Well, anyways, so the the there is, like, a possibility to have that as an extension. That's kind of what I'm trying to say. And, yep. Because I'm kind of having things for relational, so it's just does a relational edit because just because I'm editing this item doesn't mean I'm editing the relationship right around Oh, yeah. No. No. No. They they would, for example, be loaded as soon as you start opening a drawer, for example, that interface would also be loaded. It knows where it's knows and it would do the update and tag that. Yeah. The only problem is the only problem is with that, you would typically use an unmount trigger or something. As soon as that interface is unmounted, you would say, hey. I'm not editing this item anymore. But if you're editing through another item, all those changes would be staged. So if you close the drawer, it actually would tell somebody else, hey, it's not being edited right now or anymore. But in fact, it is because in fact, you just made an edit and staged it, and it's only gonna be committed or saved to the database when you save the paradigm. Yeah. That's a good point. With relational data, that that would be tricky to get right in the yeah. Although, it like, at least the the the the one way, the the setting, the username correctly works on relational items if you go for the route of having a field on the separate item, like, on each collection on based on adding a field for tracking, who's currently editing what. But when do you, like, release that information? When do you release That's a good question, which I not yet know the answer to. Like, you would do it on an unknown trigger for the interface or something. Right. Tim says the way he's done it in his, experiment extension is that he only notifies if it has been saved in in the meantime so people can concurrently edit it. Ah. Not that they just notify, hey. This has been saved while you are still on this page, which certainly is an option as well. Just doesn't feel as nice, but it feels a lot simpler to implement with some resolving options. Okay. So, like, hey. Take my changes, override it, or take their changes kind of deal. Right? Which is commented on the version control. Right? As the you get notified that someone else has made a change, the changes get merged into you can either choose to merge those changes or throw them away and lose out. Which is more along the lines of, like, resolving a conflict and not really and notifying you of a conflict ahead, but not trying to prevent the, conflict before it actually happens, I guess, which is, like, true process or the same kind of thing. I'm honestly divided on which one is better. It won't be, like, trying to prevent the conflict before it's happening. It feels like the nicer user experience to me. Yeah. Like, I I would always go for the user experience, though, in that you want to know in advance that somebody's editing something, not when somebody then actually did their changes and saved them. Because then you can, for example, communicate something with somebody who's working on the same project, on the same item in that sense. Are you editing fields that I'm editing too? Yes. No. And depending on that, they can either just continue working on it together or, like, wait for that other person to then actually do the changes and then the next person. Basically, they have the option of, do we have to do it in series, or can we make it in parallel, basically? Like, via Slack or something, like, like, basically talking that out. At least they know that somebody has had has the intent to do changes on this item in the future. There is a Twitter account well, x account, whatever, that explores hideous, design decisions, UX design decisions. We could also add a button, boot this per pay $5 to boot this person out of that item or something. I like it. Though yeah. That would be another option instead of going like the okay. We do it automatically when the user joins in these, we make it like an basically, like an option where it's like you opt in now to mark this item as you're currently editing, or you can leave it if you maybe, for example, like to even make the opt in optional in a sense, which is, like, even then more work to do. And it's probably nicer to make it automatically set to the current user by when editing. But, again, like, that opt in makes it also that you have to opt out of it kinda thing where where if it's automatic opt in, you expect to have it automatically, like, put your like, basically know when you're done editing. But if you manually opt it in, then you also have the expectation of you have to manually opt out again of editing this item, if that makes sense. It might be automatic. Otherwise, it's just a hassle like an introduce additional hassle and nobody will start actually. I mean, it's it's less of a hassle than going through Slack conversation and seeing if somebody has the same item name somewhere. Yeah. It's still it's still not as nice as it could be if it's automatic. As that said, editing some editing field should be disabled for others, which introduces another possibility or option or That would be possible through the field by, making filters. That that is if the if there's already text in that field where the name would be saved, that all other items are although that would make it different good for the person actually editing it themselves because then these figures would probably also apply for the same person. Although maybe you can fill it out by the user username and the username matching the in the field. I'm not sure how how crazy good our filter or, like, our, things for that are are that might also work, like I'm not sure. I was actually thinking more along the lines of enhancing the notification, possibilities that basically saying this field has been modified by another user. So I have it in line with all the fields and have a notification for all the fields that have been edited in the meantime, which certainly is possible again with real time. It might introduce another permission hell because people might not be able to see some fields. And if we just send them over WebSocket, anybody can read it, which, yeah, introduces problems again. But from UX perspective, again, it's super, super nice to have the possibility to, being able to tell, hey. They edited the event name. They edited the Slack. They edited whatever, as an enhancement to the original request of just shown in banner on my like, for the full item, which then again already puts you more into the collaborative editing experience where you have presence markers on all your fields and, know who's currently doing live edits on the page and seeing the edits and all of that, which is would be amazing to have. But as you already said in the beginning, it's a long ways away with the current architecture of, directors just showing you what's in the database because effectively, that's just what we're doing. Right? As soon as something is in the database, you see the most recent data, present in there. We don't really have any mechanisms on top of that for distributing life changes and all that that aren't already committed to the database. Oh, another interesting approach regarding the like, when is a user done with editing an item? This is, like, a crazy solution and probably not really feasible. I still want to go with it because it sounds quite fun. Instead of subscribing and unsubscribing from an item, we could go the road as long as a user is continuously pinging an endpoint, that he's currently editing. This was which also tackles the who which tab is currently open because only the active tab will then ping that endpoint basically ping a certain endpoint to let, the basically, back end know who where the user is currently editing something. And we just do it like a automatic opt out after a minute of not receiving a ping from that person. That would also be another interesting approach regarding the when is a user ready like, done with editing an item or something like that. But also that that also has edge cases in a lot of senses, like, in a lot of ways. Yeah. Also, you can, like, you can do that through WebSockets as well since you just Yeah. Track. I mean, yeah. I'm sure. I'm just thinking of, like, would it how tricky would it be to get this working without WebSockets? Because that's like, WebSockets makes it also a bit more, like, advanced in a lot of sense. Like, the the I I think we have, like, a ton of good documentation on how to do rest request with like, indirect us with extensions, but on WebSockets, I don't think there's a lot of documentation yet, which makes it difficult for, like, community members to implement features like that. There's always a way, but it's a lot more tricky, and that's I would assume. I'm not sure yet though. We put a couple of guides on how to use the real time SDK, which provides you with a lot of options to use that already in base starting point of Tim's extension as well, for example. Yeah. That's that's we have Tim's example. That's a good starting point. Yeah. But yeah. So I think we agree it's a very good idea. We just aren't sure if it should be in core or if it can be extend an extension because if it can be an extension, let's try to go throughout first and then see it where it breaks and if there are things that have to be implemented for, just because of this many possibilities and flavors to implement this. And if we wanna tackle it, I feel like we should put it in line with presence indications and collaborative editing or at least some way of collaborative editing experience, and that is, like, the next step kind of. And I don't know if you wanna have a future in core which will be replacing the not just in future, for example. Yeah. Sure. Not no. Yeah. Right. In yeah. I I am definitely on the side of, like, let's make this as an extension, and then people like, even people can go with different ways of implementation depending on their preferences. Like, maybe somebody prefers the way of doing it per item where it's like, we add a field to a collection, and that field stores the current user who's editing it. Maybe some people would prefer that solution, and there would be may maybe somebody else implements another solution where it's stored in a separate collection or where it's done on the WebSocket depending what the requirements or, like, where the interests are. And, having this an extension basically allows us also to explore what people prefer as an implementation and see, like, what implementation of this gets favored over time, and also helps us guide, like, in the next iterations of directors to to find out the right way to do this basically in advance. Which is the exact pitch for directors' lab extensions, I wanna say. It allows us to experiment with features to figure out, like, what is correct, what sticks, what are the things we wanna see, once they might be coming to core. Another great example is the command palette, etcetera, which has been released a couple of weeks ago. I wonder by whom? Because that explores a lot of concepts of, global extensions and everything that can be implemented in core at some point. But for now, there's ways around it, and we can use it to prototype features, and we can use it to prototype stuff like the editing notifications, for example, as well. Jonathan, you've been terribly silent while we've been chugging along here. Yes. I'm just trying to keep up with you guys from writing notes over here. I actually like I I like the VIM style option that you guys have discussed here where you would actually say, just add a toggle at the top, and you can do this in your current data model. Right? You can use roles and permissions that restrict its read only unless you've actually toggled it to say, I wanna edit this item. Therefore, I can put the notification and update the notification to say, this user is currently editing. So you could have the flow and the hook and, extensions doing those things. But simply adding a field to the top of your item that says toggle on or off that I'm updating. Right? So VIM, you know, d I, whatever, you know, Linux editing editors who have always been that way where if I'm updating, I have to actually explicitly enter edit mode, and then I have to explicitly exit edit mode. So as long as I'm in edit mode, I have it locked. Now that means that I want the ability, you know, to give a flow manual button or other things where you could say, you know, I and it could be a flow button, right, that just says, I wanna enable edit on this. Therefore, send notification to the team that also is responsible. Right. Yeah. You'd send an email. You could send an in app notification. Or, again, just update another field next to it that says, I'm editing this. Therefore, if the administrators need to go in and override you, they could. But at that point, you can use role and policy permissions to say the policy permission is gonna say based on the toggle being an edit, I now have edit permissions on the appropriate fields that I'm allowed access to. I can make my edits, save my changes, and you could even make it so that if on save, if you wanted to, right, make your edits, if on save, that automatically toggles it back to unedit. Right? So you could do something like that for the users, and you'd have some control over the workflow there. So I like that idea. Problem with that is it sounds terribly manual. Sure. It's Have the design just behind that. Yeah. Having to have all the hands conditions, and also, additionally, I don't I'm not a 100% sure. I don't think so, to be honest, that it is possible with the current policies because policies are additive. So if you add like a policy, you can't edit this item except for this, and you have another policy which allows the user to edit certain fields in that item. They still will be will be able to edit, edit some fields on those items. Although we don't have the option to make, like, fields disabled depending on other fields, like, these like, depending on things and Yeah. You can make it, like, if the the field has a certain value, other fields get disabled some or something like that. And, like, that's the point where I'm not certain that this would work because we have to make it relative to the user's name. But that could be, like, an option to have it like a no code basically, where you don't have to implement any extension and can get this running in a matter of, like, minute or, like, hours, config by just configuring directors in the end, basically. Hours as soon as you start adding another field or another collection with 10 or 20 fields because you will have to go into every single field and apply that condition to it, because those are fields that you will be horribly manual, but it will get the job done, basically. And for some people, that might already be enough. That's what I'm thinking. Like, a proper solution is always better than just doing it manually in a hacky way, but maybe that's better than writing single things in Slack. So Always better than Slack. You know, it's definitely better than a than a Slack manual. I'm working on this item kind of. So that's that's a lot of work. That's a brutal thing. So But, you know, you're terrific. Right? And then it would be a giant mess of configuration that would that you would have to go through, like, an giant effort for a simple feature that could be implemented with an extension. But on the other side, not everybody is an extension developer and hiring one could also be expensive. Like, I'm not sure. So that's maybe, like, you want to just have this and without any, like, effort input like, any large effort put into that and kick that configuration, that might be the way to go using, like, flows and, custom fields or something like that. You still would have to have the user toggle that field and save it. Like, save the item, then only then once somebody else opens the item, you will be able to see it. So there's a lot of, like, user flaws. Yeah. It seems like there's more user error involved than writing a Slack message, because the fields will start appearing, as editable as soon as you toggle it, but you need to remember to save it before. Otherwise, nobody else would see it. So Yeah. Certainly is an option. Certainly isn't the route I would go for. No. I probably neither, but I'm also like an I I I'm also able to develop my own extension. So that also solves the problem for me of, like, would I go the extension route? But, yeah, like, custom extensions, I think that's a great place to for that. Like, that's a powerful way to use, custom extensions, and to just basically extend Reactors without having to con like, to commit to a certain solution that we will decide on. Like, if we would now decide on this solution as the best, like, maybe for us right now at the moment, but maybe, like, we don't know of any of certain use cases where people would prefer another solution and, like, going the extension or, like, the lab route, that's definitely sounds like the best solution at the moment, to like, for everybody that people can try this feature out without having to, like, have it in core. And, then, like, depending on how this develops, people can then, like, we can then start looking into how does this get used and how often and how much, like, interest is behind that after it's gets in after it's get gets implemented as a custom extension, and then we can iterate on the next versions of directors to see what we want to have this rigging call just to make it, like, the setup a lot easier for people. Right? And since we still have the original author of that feature request in the chat, I really wanna ask him to, like, as a closing thought kind of deal, because we're doing quarter like, 45 minutes usually for you, your entry, feature request. Right? Or is it a full hour? It's technically a full hour, but we're well, I think we're just about there. I'm putting in some final notes here. But, yes, if they if they offer some ideas, I'd love to hear. Have we covered whatever we were thinking about? Have we outlined the thoughts behind why it's currently not in core or how it could be implemented as an extension? And maybe, like, future options for collaborative editing, which kind of overtake this or replace it at some point. Jonathan, you will have to tell a story while he's telling chat, I think. Yep. Nope. I'm just quickly I'm quickly scanning back through here to see if there was anything that we missed. I think we've covered the general requirements here. And I agree that longer term, I think, you know, ideally collaborative editing solves this problem outright. Right? Because then you've got field level notification of who's making changes, when they're making changes. It's real time. You see the changes in real time. But that's a story for another day. This this particular use case, I really like the idea of we can potentially put some solutions out into the wild, help us identify what are the edge cases. Because even with collaborative editing, what are the edge cases we're gonna run into? What are things that can happen or will happen? You know, relational always creates the complexity. Right? When you start digging into relationals and, you know, at what point are you locking or not locking, what points are you notifying, not notifying, handling some of those cases. And collaborative may just make that all go away. There may not be edge cases other than speed and performance of getting notifications back and forth, for the users. But, Tim isn't allowed to participate in these Oh, versions. Versions. Should be fun. Yeah. Versions. We haven't really talked about versions in this whole thing. Right? That is yeah. You're not allowed to participate. I don't think so. You also versions. There's a thing like versions. Yeah. That would make it a lot more difficult. Although I'm sorry though. Do for for the for the extensions, you can build your own. Right? That's an option. You can start with that today. You bring it to a very good point. We as the core team, I will get this in as a request into the Directus Labs extensions group. So that there is a core team that is working custom extensions as part of the marketplace. That's where things like yeah. You may have seen it today, but I have this I actually have this one installed. I love this one. The spreadsheet. Right? The spreadsheet layout, this ability to edit these things live right here. Fantastic. Love it. This has been one that was that's been asked for since the day I joined. I've I've heard people asking for spreadsheet style layout. So I think I remember, Ben asking for this feature, like, in 2,000 well, at 2,021 or something, like, or even before that. So, yeah, it has been on a long road of, like, when will this come? When will this come? When will this get implemented? But doom is bringing up a very good point because, yeah, sure. You don't use versions, but the reason why it's taking us so long to bring new stuff like this into core sometimes is you don't use versions, other people might. So everything that is in core has to work for all the features that we already support. Didn't he set the other way around? Because it's like double negation. Is it like who does not use versions in a sense that, like, everybody use versions? Or am I misunderstanding his message? No. Content versioning is I would think Unless we have fixed the permissioning problem, we still it it's it's very, very limited in its use case options and where you can actually today, because of publishing and editing permissions. So if I wanna main should technically be read only and locked, which is published state. But as soon as you create a content version, if you've got the main record locked, all content versions are locked without changing main. So there are permissioning issues, policy issues right now on the permissioning side that make content versioning difficult to use if not impossible. What's that? Do we have an issue for that? I have to ask now because I was the one Yep. We had is it is it if you have a problem? We've got open feature request for it. Yes. What is feature request? So it's a again, this comes back to, you know, the way the policies are implemented currently. It relies on the main permissioning rather than the version permission version having its own permissioning. Yeah. So you can lock things like I can prevent promoting. I can do things around. Can they create or not create, you know, versions? Can they promote or not promote versions? But the ability to edit that version is dependent on the permissions of main, and therefore, I can't do things like lock main, which means now a user, if they've got the permission, they can edit the published record live without doing it inside of a version. So there's some things that are problematic there. That's a very good point. Yeah. Neither here nor there. Just for the folks here, if you see anything in this particular project, this is kind of core team provided. It's not guaranteed that it's maintained long term, but you have if you see these in the marketplace, right, so Directus marketplace here, if you see those in this particular layout and if you see anyone with the let me put an AI space here. If you see anyone with this little check mark here, that tends to be core team. They've been approved, so you can at least trust that it's coming from a reliable source, in that sense, generally. But marketplace extensions is where this will would show up. So if we get the team to agree that they wanna take this on, you'll see that show up at some point in the next 2 to 4 months, generally. We tend to try and get these we're we're tend to roll out, these lab extensions on a monthly basis. So we've got well, again, no guarantees, but, hopefully, the team will decide that this is worthwhile. I'll put the feedback in to say that this seems like a really cool one to actually have out there in the wild to get this haptic feedback so that we know what we need to watch out for as we continue to implement these kinds of features in Directus Core. So so, Petros, give it a give it an upvote or you're not finding the ticket, open a ticket. Yep. The this is a I ran into it. It was what the the first week that we rolled content versioning out, I had a client reach out. I need to be able to do I'm trying to do x y z, and it doesn't seem to be working. And I tried I tried flows. I tried work around. I tried all kinds of hacks. I could not get around the fact that main is driving permissions for the version. So it's, it is the there's a slight problem there. Although I guess you could with a flow, you could watch on main if main's in published, you could just prevent. But it's a it's a it's a bit hacky in the sense of the user can make a whole bunch of changes. Now try to save that and realize that they were in main to be blocked. But you can at least you could put some validation in place that force prevents that save. Feels like a very good discussion topic for another feature request. So Yeah. Absolutely. The point. Straight to the point. Yeah. Of having versions and promoting and demoting versions, versions. Where we get those permissions from since, like, you correctly said all the permissions are determined by the main items since we have one, like, one permissioning engine in core. And it just looks at the main item, and it actually does it actually has a database evaluate all those permissions for you, which makes it easier in a lot of senses, but makes stuff like this where versions are actually separately maintained JSON blobs of that item a lot more difficult. Yeah. Very true. But we're off topic. Any final parting thoughts on editing, notification? Sounds cool. It's like there's an extension. There those are my final words I wanna say. Yeah. Because I definitely see the US improvement. I see the value in it. I'm just not a 100% sure if we can get it into core properly while keeping all the features we currently already have in mind in a reasonable time frame. Yep. It's always the goddamn time. Well, no. Yeah. But let's let's see what we can do. Put it. Yeah. And, I mean, we can also, like, put it out here. If you feel like, hey, that is an extension I'm gonna develop, reach out to us. Maybe we can help you. That would be awesome. Yeah. I would love to hear people getting just their hands dirty in this. Because in the end, anyone can develop an extension for directors. We try to make it as open and easy as possible. So if you feel like that is something you wanna try, reach out to any of us, and we'll see what the options are. Actually, reach out via the ticket. So post your comments, thoughts, work, other things that you're doing. Let's make sure it gets back to this ticket so that we can actually track that progress. And Yeah. We'll try and do the same. We'll, again, when we we do these kinds of extension developments, we'll tag that back into this ticket. So if it gets accepted and committed and delivered, we'll we'll try to remember to populate that back into the ticket. Alright. Cool. Well, well, honest sales. Wonderful having you guys join on short notice. Yeah. Was this last of the year? As usual. It's exciting. Team, thanks everyone for joining. Have a wonderful rest of your week. And as always, reach out through Discord or through the ticketing systems, and we're here to help us find out. October 15th for the next change log that covers all the changes that will be released in the new version. If you're there. And as always, this will be posted in the request review channel of the Directus IO TV. Chat out everyone. Last chat message. All the feedback from this call is has actually been typed up by Jonathan while we were talking until Thursday. I will see. Yeah. Well, I did. You guys feel free to add if I missed anything. Cheers, everyone. Cheers. Cheers. Bye bye.","22421881-df9b-45ac-9008-a65f73b19434",[197,198,199],"64cc5c90-2113-43d9-b02a-476f57841394","1a4269ad-d7a5-42bb-bf94-b921d6972d5e","37101fb3-a511-4ca6-9005-acc6a5b525fe",[],{"reps":202},[203,259],{"name":204,"sdr":8,"link":205,"countries":206,"states":208},"John Daniels","https://meet.directus.io/meetings/john2144/john-contact-form-meeting",[207],"United States",[209,210,211,212,213,214,215,216,217,218,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],"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":260,"link":261,"countries":262},"Michelle Riber","https://meetings.hubspot.com/mriber",[263,264,265,266,267,268,269,270,271,272,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,240,451,452],"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",1773850454391]