A Multi-submission importer for EasyForm
CC Attribution 3.0 Germany:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Lewis, Annette
I needed a way to mass import form submissions into Plone’s EasyForm, so after a bit of exploration and some creativity I built a custom CSV import tool. Through an Action on the tool-bar, a user can export a CSV with the appropriate form fields, update it, and import back to that form. Each row represents an EasyForm submission and mimics the submission process for that form. Even the form actions get processed. In this talk, I will walk through the my process examining how EasyForm handles submitted information, following the trail deep into CRUD forms, and piecing that newfound knowledge together to create the tool.
 All right. Hello. And welcome to my talk. I'm going to start sharing my slides here. There we go. And this is on my multi submission importer for easy form, which was a challenge of a title, but I've been introduced. I'm a net developer for six feet up. And I work primarily in Planner right now, but I also do Python programming and such from the time being. And what really happened here is I had a very specific problem that we are trying to solve. We had existing forms in a site. There were quite long forms and we needed to be able to mass import or submit multiple versions of this. And I tried a couple of different things like data grid field view wasn't quite as friendly for our clients and users. And the person filling out the form wouldn't be the site admin necessarily. So when we had registration forms and we need to import multiple registrations or multiple instances, but have it act like easy form, there wasn't quite a ready solution. So I did some research and some digging around and started thinking about what would the solution need to entail. And for that solution, we wanted to make sure that it was something that the site admins could facilitate. They could give it to somebody outside of the site and that they could import and mass. We wanted to make sure that it would work with just about any template that we had because the clients were allowed to create their own registration forms. So they would be changing this from time to time and it had to be flexible. We also wanted to make sure after working out some of the import steps that the site admins could preview the data, make sure nothing needed fixing or adjusting. And then once again that it executes all the actions of easy form. And that was incredibly important to us. So let's take a quick demo of what I ended up with. There we go. So right here I've got my Burdconf registration form. And if I go into actions, I have a new action called import forms from CSV. And that takes me to a page. And what I can do is I can download my CSV template. And I can also import my CSV. So an example of a downloaded template, and I just downloaded it ahead of time, right here, is it just gets all the fields and throws it into a CSV. So you have all the header rows that you can look against. And then I could fill this out. And I have an example of one filled out. For my Burd conference, I've got Bluestj and Big Red, the cardinal registering for my conference. And this is a filled out CSV. So I can choose this file, import that CSV data. It's going to fill this into the saved data view, which I just borrowed so that I could do this easily and more quickly. And then once I feel, huh, this is great. I think that also should be big as red cardinal, save my adjustments. Oh, this is missing and false. No, you're not approved. No, you're not actually approved either. And then I can go ahead and import this data. And what this is going to do is actually save the data into my saved data adapter or whatever actions I have in Easy Form. It'll just process it through those actions. And then also, we've got, this is an example of kind of the mail. My mail hogs working a little weird right now. But this is an example of the mail that you would get when that's submitted through. So in this case, I have mail for Cardi Red, me and Blue Boy because I had confirmation sign. So that's the example there of how it works. So what I want to go through is kind of how I got to this point. And like, I really didn't know that much about Easy Form and how it actually worked before I got into this. So I had to do some digging and I kind of figured out, okay, so I knew Easy Form uses dexterity. I then kind of realized, okay, so that works on CC3 form and then put on CC3 form and I kind of dug down and drilled through the pieces to kind of get an idea of what actually supports the forms and the processing and everything. And then had to work my way back to figure out how to build this. So first generating the CSV. And that was actually really easy because, and that's just a preview of that page again. Easy Form already had a handy dandy API for getting the schema and getting the field order. And so all I needed to do was point to that and then get it into a CSV that could be downloaded. So here I have just a snippet of code. So I made my download form CSV, which said that was that page with my two buttons. And I made a choice to just use the two buttons because it's one page that my clients go to and it's one page that these users can look for everything. So they don't have to remember where to search for things and that rides along with the form. And then my button just points to this download form CSV when you click on it. Oh, and then so what I'm doing is basically just making a call and getting that request. I take a date timestamp because I figured I kind of just lose track of forms. If it doesn't have a this is the day I downloaded this in case they make changes to the form, the title automatically have that date time on it. And then I went ahead as well and just made sure that I set the header. So it knows this is a CSV, put on the file name and then just use the CSV module there and the dictator to write those field names that I pulled from the get schema form and the get fields in order. And once again, that comes right from the easy form API. So that was pretty nice and easy to do as far as getting a CSV downloaded. And once again, that's just an example in a slightly easy to read format of what an example CSV for that form would look like. And that way now I have a file that the site admins can send to whoever needs to facilitate the group imports and then they can fill this out. Now we get into actually uploading the import and getting that data back in because that was the biggest challenge I think was getting it in and then processing it through easy form. So once again, same page, but this time we have the import CSV and the import CSV data button right there. And what that button actually hooks up into is my preview CSV import view that I have registered here. And one thing and I haven't dealt with uploading data as much for forms but this multi form data if you've never worked with forms and uploading very important for making sure that file attachment gets into your quest. Now at this point I knew I didn't want to recreate something from scratch so I was going to try and reuse and recycle as much as code as possible from things that already existed and then just override what I needed to do. So lots of subclassing and inheritance to try and get this to work. So I looked through once again the code base of what I was working with and I said save data form looked like a pretty good model of what I wanted to import and this was that kind of that's the save that adapter in easy form. So I said why don't I subclass that and just pass my data into that. And I noticed that actually inherited from card form. So this gave me an idea of where I could start with this edit form factory. That's what I could customize to make the form what I wanted and have it do what I wanted to do. So now I needed to make this intermediate screen so that we could review the import and actually pass the data into this item here. And based on what I learned I knew I could build that structure here. So I ended up making my own class here CSV import card and that inherited to save data form. And this view is the view I referred to earlier and in the CZ3 form layout it actually has the wrap form. So it just wraps your form in the clone view so it could be in the context in the visual context of the phone site. So that was nice and easy to just pop that into that. And then I had to override a couple of templates because the native template for save data form of course talks about save data and I didn't want to confuse my users. So I edited this just so I could get the title like review import and some of the text that goes along with that. And then this form really what it does is it renders all of the sub forms. So it renders all of that information and the sub form being each form submission or each row in this case. Also I have the import edit form and that's going to be my custom edit form so I can override certain parts of the form that save data would usually be bringing in. So now I've got spotted what format I need and the biggest thing was what does this need for me to get this fed in. How do I need to format my data? And I looked and saw get items seem to be what fed the information into the actual slides there. So now I have this get items format here in this description. I'm like okay now I know how I need to format the stuff that I get out of that CSV to start feeding that back into that save data adapter view grid. Oh right. Nope, other way. So actually ahead of time just put a couple of code bits together so it's a little easier I hope to display on this. But here we go. Review the import. So I talked about my class already and that was my snippet there. And so what I'm doing here is I'm importing my CSV and getting that data and putting it into this and returning that. And then this is actually getting that data. So let me see. There we go. That calls upon this to actually get the data out of the file. And so I go through and I actually run a little cleanup values function because it's user input. So I needed to keep control of what the users were putting in and kind of clean that up and make sure it was going to jive what I got on the end. So I had this cleanup value here. And once I cleaned it up I was returning the format that I needed this data to be in to go into that get items function. And this is an example of the cleanup values. And what it really does is just kind of make sure and this is really easy for me if I really helps me figure that out is make sure that I was getting daytime fields were going back in the way they needed to the sets in particular. So any of the multi choice text selection bits were going back in properly and cleaning up all that information so that when it gets read it would like check the boolean boxes it would make sure the drop downs have the right values and it would select the items in the set that needs to be selected. And then that's also took advantage of the cleanup that was already in easy for this API. So I actually just use this directly within my cleanup values to make sure that the sets are formatted correctly. So now this is my new get items where I have my I check if it has a file attachment or I check to see if I hit the edit button or if I had to reapply changes at that saved out of you. And then if it doesn't have that and it's missing the file attachment it throws them back to the import forms base so just a little checking in case the file disappears or something happens there. And then next reviewing the import part two which is actually handling the data once it's in there. And so I had my review import table that's my big view. And then I needed to make a couple changes to the actual table that was in the form as well just to get the buttons and some of the cues that I needed in the right spots. So that's back to my code. So there are two classes in particular that I needed to override the batch class class to methods functions batch I needed to override because I needed to export this particular variable here and make sure that it was not trying to read what already existed and save data doctor but reading what I was feeding into it. And then I had to edit get data and please excuse my nesting that needs to be flattened out a bit. But this was also once again just making sure that I'm iterating through the items setting up my field names and I'm actually checking against the fields that are already in the schema. So if in the CSV there's something that is in the column that doesn't exist in the schema, it's just going to ignore it. So it's not going to throw errors, it'll only load things that match the titles that are in the schema already. So this is doing those checks and then once again making sure that my sets are just correctly. So back to this side. And now the biggest thing is the data is uploaded. I've got it formatted. It's in the table. We're ready to hit submit and actually submit this to easy form. And so I briefly over read this button handler. And this is actually easy forms handle submit. So this is how what it does when it submits a page. So I kind of read this and observed it and said, okay, I need to do something like this. But in my own context. So this was my entry point. So I was already using that import edit form. I made that custom form and I was going to override its apply, save changes button with my own button. And that's my import form data button. And I kept a lot of what was already there. But in particular right here, this is where I'm starting to iterate through the rows. And so for each row in that data is one submission of my form that I wanted to go through. So right here, I have a function in my import class that's called submit form. And so as I go through the rows in the form, it's going to process this through that submit form action and submit it as if it was actually in easy form. And then just count the rows so I can say these are how many rows were imported just a little feedback for the users on how that's going. And I made it I made it to what my real chief objective goal was at this point, I wanted to submit this form. And so I this is my submit form submit form function there. And I just actually imported the easy form process actions code right there and just push it straight through that process. So I didn't have to write anything extra just connect the two pieces and let it roll. So now that was kind of just the beginning it was my first foray really diving into the forms and just kind of manipulating and pushing things into place to get what I needed to work in that context. And it taught me a lot I learned a whole lot. And I think the result was pretty cool is pretty useful for our use case. And of course, there's plenty of room for expanding, because it'd be nice if they could you know have a clear button or cancel button or add or delete rows and such but I felt it was a pretty nice stub for starting to get through this processing. Being able to submit forms in mass without having to repeat it one by one so really accomplishes the goal of passing this information to the users, letting them just fill this data out and then giving the site administrators an easy way to facilitate registering all these people. Well, whatever mailer actions or save adapter actions they have or custom scripts, it'll just go ahead and process that just mimic that process. Alright, so thank you for coming along. And I guess this is my my time for questions. If there's any questions. Yes, thank you very much for the great talk and I really enjoyed it that you showed it in depth how you made this adapter and also and we have indeed one question from Anthony. It's what happens during the data cleanup if a value is unusable such as a string that can't be changed to daytime ETC. Okay, so what I ended up doing is let me go through here and get back to my cleanup. So what I did in this cleanup is what will happen most times and for date field in particular is it'll just throw the value out. So this is that this was the real importance of having that intermediate screen where if something like this happened, they would be able to join the two ends together and kind of say, okay, well, that's not right. Or this is kind of off or something like that. So I try and look at it and I try and format it but if it doesn't format it, it'll just throw it out so it won't cause an error. So that way if things are malformed, it won't break the whole process for the users. And this was kind of the stub of starting to go through and trying to catch some of those instances and of course with data cleanup, it can be a lot depending on how many things you're trying to accommodate. But this was based on the forms I had what I could start to accommodate or what I knew I had to be able to accomplish for them. But I think date time and date were probably the trickiest ones as far as throwing values go. Anything else like if the sets weren't formatted correctly, it just wouldn't highlight the item in the set. And for like these boxes here, if the value was missing and I already fixed this one, it would say missing colon and what the value was. So I'll actually just re-import that. Pull that up. So it'll tell you that value was missing from that list and then that gives that administrator a chance to say, okay, I can fix this based on what they have there. So that's what they can do in those cases. There's another question. I wonder if this could be a pull request for a new easy form feature. I think it's definitely possible. I think when I started this, and this is something that it's really easy, especially if you ever have imposter syndrome, I thought this is just a small thing I'm doing in the corner of my world. And when I presented this to my team, they seemed really interested and that's how I ended up giving a talk on this in the first place. So I would definitely like to get this out there because I think there's so many great minds in the phone community and we could actually really take advantage of this. So I'm glad to get a stub out and see where it goes from there. Okay. So Fred asks, this is something that can be added to the add-on itself. I'm not sure exactly what this refers to or what would be needed for doing that. Can you do you get what? Yeah, I think it's something that could definitely be put into the add-on. So when I did it, of course, because it was in my own little add-on, most of this is actually just written. I think all of it is actually in my view style. So it's definitely something that, now I think about it, I would have definitely liked to put this into its own view or own API or give it its own little niche. But I think if we could create some of the API endpoints or something like that to make this a little easier, so it's maybe a little less hacky, I think it could definitely be integrated and just be part of easy form. I think the cleanup of the values would be the biggest thing, cleanup and error checking. Okay, so there are no more questions on Slido.
 All right. Hello. And welcome to my talk. I'm going to start sharing my slides here.  There we go. And this is on my multi submission importer for easy form, which was a challenge  of a title, but I've been introduced. I'm a net developer for six feet up. And I work  primarily in Planner right now, but I also do Python programming and such from the time  being. And what really happened here is I had a very specific problem that we are trying  to solve. We had existing forms in a site. There were quite long forms and we needed  to be able to mass import or submit multiple versions of this. And I tried a couple of  different things like data grid field view wasn't quite as friendly for our clients and  users. And the person filling out the form wouldn't be the site admin necessarily. So  when we had registration forms and we need to import multiple registrations or multiple  instances, but have it act like easy form, there wasn't quite a ready solution. So I  did some research and some digging around and started thinking about what would the  solution need to entail. And for that solution, we wanted to make sure that it was something  that the site admins could facilitate. They could give it to somebody outside of the site  and that they could import and mass. We wanted to make sure that it would work with just  about any template that we had because the clients were allowed to create their own registration  forms. So they would be changing this from time to time and it had to be flexible. We  also wanted to make sure after working out some of the import steps that the site admins  could preview the data, make sure nothing needed fixing or adjusting. And then once  again that it executes all the actions of easy form. And that was incredibly important  to us. So let's take a quick demo of what I ended up with. There we go. So right here  I've got my Burdconf registration form. And if I go into actions, I have a new action  called import forms from CSV. And that takes me to a page. And what I can do is I can download  my CSV template. And I can also import my CSV. So an example of a downloaded template,  and I just downloaded it ahead of time, right here, is it just gets all the fields and throws  it into a CSV. So you have all the header rows that you can look against. And then I could  fill this out. And I have an example of one filled out. For my Burd conference, I've got  Bluestj and Big Red, the cardinal registering for my conference. And this is a filled out  CSV. So I can choose this file, import that CSV data. It's going to fill this into the  saved data view, which I just borrowed so that I could do this easily and more quickly.  And then once I feel, huh, this is great. I think that also should be big as red cardinal,  save my adjustments. Oh, this is missing and false. No, you're not approved. No, you're  not actually approved either. And then I can go ahead and import this data. And what this  is going to do is actually save the data into my saved data adapter or whatever actions  I have in Easy Form. It'll just process it through those actions. And then also, we've  got, this is an example of kind of the mail. My mail hogs working a little weird right  now. But this is an example of the mail that you would get when that's submitted through.  So in this case, I have mail for Cardi Red, me and Blue Boy because I had confirmation  sign. So that's the example there of how it works. So what I want to go through is kind  of how I got to this point. And like, I really didn't know that much about Easy Form and  how it actually worked before I got into this. So I had to do some digging and I kind of  figured out, okay, so I knew Easy Form uses dexterity. I then kind of realized, okay,  so that works on CC3 form and then put on CC3 form and I kind of dug down and drilled  through the pieces to kind of get an idea of what actually supports the forms and the  processing and everything. And then had to work my way back to figure out how to build  this. So first generating the CSV. And that was actually really easy because, and that's  just a preview of that page again. Easy Form already had a handy dandy API for getting  the schema and getting the field order. And so all I needed to do was point to that and  then get it into a CSV that could be downloaded. So here I have just a snippet of code. So  I made my download form CSV, which said that was that page with my two buttons. And I made  a choice to just use the two buttons because it's one page that my clients go to and it's  one page that these users can look for everything. So they don't have to remember where to search  for things and that rides along with the form. And then my button just points to this download  form CSV when you click on it. Oh, and then so what I'm doing is basically just making  a call and getting that request. I take a date timestamp because I figured I kind of  just lose track of forms. If it doesn't have a this is the day I downloaded this in case  they make changes to the form, the title automatically have that date time on it. And then I went  ahead as well and just made sure that I set the header. So it knows this is a CSV, put  on the file name and then just use the CSV module there and the dictator to write those  field names that I pulled from the get schema form and the get fields in order. And once  again, that comes right from the easy form API. So that was pretty nice and easy to do  as far as getting a CSV downloaded. And once again, that's just an example in a slightly  easy to read format of what an example CSV for that form would look like. And that way  now I have a file that the site admins can send to whoever needs to facilitate the group  imports and then they can fill this out. Now we get into actually uploading the import  and getting that data back in because that was the biggest challenge I think was getting  it in and then processing it through easy form. So once again, same page, but this time  we have the import CSV and the import CSV data button right there. And what that button  actually hooks up into is my preview CSV import view that I have registered here. And one  thing and I haven't dealt with uploading data as much for forms but this multi form data  if you've never worked with forms and uploading very important for making sure that file attachment  gets into your quest. Now at this point I knew I didn't want to recreate something from  scratch so I was going to try and reuse and recycle as much as code as possible from things  that already existed and then just override what I needed to do. So lots of subclassing  and inheritance to try and get this to work. So I looked through once again the code base  of what I was working with and I said save data form looked like a pretty good model  of what I wanted to import and this was that kind of that's the save that adapter in easy  form. So I said why don't I subclass that and just pass my data into that. And I noticed  that actually inherited from card form. So this gave me an idea of where I could start  with this edit form factory. That's what I could customize to make the form what I wanted  and have it do what I wanted to do. So now I needed to make this intermediate screen  so that we could review the import and actually pass the data into this item here. And based  on what I learned I knew I could build that structure here. So I ended up making my own  class here CSV import card and that inherited to save data form. And this view is the view  I referred to earlier and in the CZ3 form layout it actually has the wrap form. So it  just wraps your form in the clone view so it could be in the context in the visual context  of the phone site. So that was nice and easy to just pop that into that. And then I had  to override a couple of templates because the native template for save data form of course  talks about save data and I didn't want to confuse my users. So I edited this just so  I could get the title like review import and some of the text that goes along with that.  And then this form really what it does is it renders all of the sub forms. So it renders  all of that information and the sub form being each form submission or each row in this case.  Also I have the import edit form and that's going to be my custom edit form so I can override  certain parts of the form that save data would usually be bringing in.  So now I've got spotted what format I need and the biggest thing was what does this need  for me to get this fed in. How do I need to format my data? And I looked and saw get items  seem to be what fed the information into the actual slides there. So now I have this get  items format here in this description. I'm like okay now I know how I need to format the  stuff that I get out of that CSV to start feeding that back into that save data adapter  view grid. Oh right. Nope, other way. So actually ahead of time just put a couple of code bits  together so it's a little easier I hope to display on this. But here we go. Review the  import. So I talked about my class already and that was my snippet there. And so what  I'm doing here is I'm importing my CSV and getting that data and putting it into this  and returning that. And then this is actually getting that data. So let me see. There we  go. That calls upon this to actually get the data out of the file. And so I go through  and I actually run a little cleanup values function because it's user input. So I needed  to keep control of what the users were putting in and kind of clean that up and make sure  it was going to jive what I got on the end. So I had this cleanup value here. And once  I cleaned it up I was returning the format that I needed this data to be in to go into  that get items function. And this is an example of the cleanup values. And what it really  does is just kind of make sure and this is really easy for me if I really helps me figure  that out is make sure that I was getting daytime fields were going back in the way they needed  to the sets in particular. So any of the multi choice text selection bits were going back  in properly and cleaning up all that information so that when it gets read it would like check  the boolean boxes it would make sure the drop downs have the right values and it would select  the items in the set that needs to be selected. And then that's also took advantage of the  cleanup that was already in easy for this API. So I actually just use this directly  within my cleanup values to make sure that the sets are formatted correctly. So now this  is my new get items where I have my I check if it has a file attachment or I check to  see if I hit the edit button or if I had to reapply changes at that saved out of you.  And then if it doesn't have that and it's missing the file attachment it throws them  back to the import forms base so just a little checking in case the file disappears or something  happens there. And then next reviewing the import part two which is actually handling  the data once it's in there. And so I had my review import table that's my big view.  And then I needed to make a couple changes to the actual table that was in the form as  well just to get the buttons and some of the cues that I needed in the right spots.  So that's back to my code. So there are two classes in particular that I needed to override  the batch class class to methods functions batch I needed to override because I needed  to export this particular variable here and make sure that it was not trying to read what  already existed and save data doctor but reading what I was feeding into it. And then I had  to edit get data and please excuse my nesting that needs to be flattened out a bit.  But this was also once again just making sure that I'm iterating through the items setting  up my field names and I'm actually checking against the fields that are already in the  schema. So if in the CSV there's something that is in the column that doesn't exist in  the schema, it's just going to ignore it. So it's not going to throw errors, it'll only  load things that match the titles that are in the schema already. So this is doing those  checks and then once again making sure that my sets are just correctly.  So back to this side. And now the biggest thing is the data is uploaded. I've got it  formatted. It's in the table. We're ready to hit submit and actually submit this to easy  form. And so I briefly over read this button handler. And this is actually easy forms handle  submit. So this is how what it does when it submits a page. So I kind of read this and  observed it and said, okay, I need to do something like this. But in my own context.  So this was my entry point. So I was already using that import edit form. I made that custom  form and I was going to override its apply, save changes button with my own button. And  that's my import form data button. And I kept a lot of what was already there. But in particular  right here, this is where I'm starting to iterate through the rows. And so for each row in that  data is one submission of my form that I wanted to go through. So right here, I have a function  in my import class that's called submit form. And so as I go through the rows in the form,  it's going to process this through that submit form action and submit it as if it was actually  in easy form. And then just count the rows so I can say these are how many rows were  imported just a little feedback for the users on how that's going. And I made it I made  it to what my real chief objective goal was at this point, I wanted to submit this form.  And so I this is my submit form submit form function there. And I just actually imported  the easy form process actions code right there and just push it straight through that process.  So I didn't have to write anything extra just connect the two pieces and let it roll. So  now that was kind of just the beginning it was my first foray really diving into the  forms and just kind of manipulating and pushing things into place to get what I needed to  work in that context. And it taught me a lot I learned a whole lot. And I think the result  was pretty cool is pretty useful for our use case. And of course, there's plenty of room  for expanding, because it'd be nice if they could you know have a clear button or cancel  button or add or delete rows and such but I felt it was a pretty nice stub for starting  to get through this processing. Being able to submit forms in mass without having to  repeat it one by one so really accomplishes the goal of passing this information to the  users, letting them just fill this data out and then giving the site administrators an  easy way to facilitate registering all these people. Well, whatever mailer actions or save  adapter actions they have or custom scripts, it'll just go ahead and process that just  mimic that process. Alright, so thank you for coming along. And I guess this is my my  time for questions. If there's any questions.  Yes, thank you very much for the great talk and I really enjoyed it that you showed it  in depth how you made this adapter and also and we have indeed one question from Anthony.  It's what happens during the data cleanup if a value is unusable such as a string that  can't be changed to daytime ETC.  Okay, so what I ended up doing is let me go through here and get back to my cleanup.  So what I did in this cleanup is what will happen most times and for date field in particular  is it'll just throw the value out. So this is that this was the real importance of having  that intermediate screen where if something like this happened, they would be able to  join the two ends together and kind of say, okay, well, that's not right. Or this is kind  of off or something like that.  So I try and look at it and I try and format it but if it doesn't format it, it'll just  throw it out so it won't cause an error. So that way if things are malformed, it won't  break the whole process for the users.  And this was kind of the stub of starting to go through and trying to catch some of those  instances and of course with data cleanup, it can be a lot depending on how many things  you're trying to accommodate. But this was based on the forms I had what I could start  to accommodate or what I knew I had to be able to accomplish for them.  But I think date time and date were probably the trickiest ones as far as throwing values  go. Anything else like if the sets weren't formatted correctly, it just wouldn't highlight  the item in the set.  And for like these boxes here, if the value was missing and I already fixed this one,  it would say missing colon and what the value was. So I'll actually just re-import that.  Pull that up.  So it'll tell you that value was missing from that list and then that gives that administrator  a chance to say, okay, I can fix this based on what they have there. So that's what they  can do in those cases.  There's another question. I wonder if this could be a pull request for a new easy form  feature.  I think it's definitely possible. I think when I started this, and this is something  that it's really easy, especially if you ever have imposter syndrome, I thought this is just  a small thing I'm doing in the corner of my world. And when I presented this to my team,  they seemed really interested and that's how I ended up giving a talk on this in the first  place. So I would definitely like to get this out there because I think there's so many  great minds in the phone community and we could actually really take advantage of this.  So I'm glad to get a stub out and see where it goes from there.  Okay. So Fred asks, this is something that can be added to the add-on itself. I'm not  sure exactly what this refers to or what would be needed for doing that. Can you do you get  what?  Yeah, I think it's something that could definitely be put into the add-on. So when I did it,  of course, because it was in my own little add-on, most of this is actually just written.  I think all of it is actually in my view style. So it's definitely something that, now I think  about it, I would have definitely liked to put this into its own view or own API or give  it its own little niche. But I think if we could create some of the API endpoints or  something like that to make this a little easier, so it's maybe a little less hacky,  I think it could definitely be integrated and just be part of easy form. I think the  cleanup of the values would be the biggest thing, cleanup and error checking.  Okay, so there are no more questions on Slido.
A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_0_1019.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_1020_1823.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_1824_1883.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_1884_1931.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_1932_2987.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_2988_3599.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_3600_3659.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_3660_5459.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_5460_5579.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_5580_6035.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_6036_6215.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_6216_8471.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_8472_8519.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_8520_16007.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_16008_16271.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_16272_27731.png A_Multi-submission_importer_for_EasyForm_-_Annette_0a3x8CLVqS4_27732_33642.png