Creating 'amendments' of existing data but still storing the original values to go back to - version control of data

I have built an app that in simple terms generates documents based on data that is entered via various forms that the user completes in their account. A bit like a what lawyers might use to generate new contracts with automatically inputting personal client data after pulling this information from a client database.

In my app, once the user fills it out for the first time and marks it as the ‘final version’ this will be considered version 1 (or what ever the version they are working on at the time). It won’t be editable unless they ‘unlock’ it.

Now, when the user wants to come back a few months later and make a change they should be easily able to do so and re-generate the documents. However they are meddling with what we have already called version 1. In other words, it’s not designed for users to keep revisiting to make changes - users should be creating a new version when ever there is a significant change to make.

What I am trying to achieve is allowing users to press a button and create an ‘amendment’ which they can call version 2, 3 etc and each time create a change independent of the version preceding it.

In my mind the user will enter a page on the app where they will ask the app to duplicate the data currently stored for version 1 and re-create it but mark is version 2 instead. Then the user can make as many changes as they need, but know that the previous version is locked.

So, once the user initiates this duplication process to start, they select which version they want to view and go back to the form pages to see their respective version ready to view (if its already a version that is marked final), or edit (if they’ve just initiated an ‘amendment’).

I hope that makes sense.

One of my ideas is adding a constraint to each of the fields in the forms to do a search for a version number that is stored in the users profile. So the user create a version, say version 2, and then asks the app to select this version as the current version, the constraint in the fields of the forms searches for what the current version is set to. However, for this to work, I believe the app needs to still duplicate all the data but now register this under the newly specified version so it can be separated from what’s already stored.

Open to any other suggestions on how to achieve the above!

Is the document an actual separate data type with the fields under that? Or is it tied to the user? Are there a lot of different fields under the document?

EDIT: i mean a lot of “list of things” fields under the document, if you do a copy action on the document to make a new version, you’ll need to copy the lists as well

There are about 10 different forms (and about the same number of databases) called various things relating to the data they store (client information, project information etc). The document(s) collate various aspects of this data depending on what the data is - so there’s not really a separate data type for each document, if that’s what you mean.

So essentially a duplicate needs to be created from all of the data across these databases but under ‘version 2’

So I had to do something similar, I basically used the “Copy a list of things” action a lot. First you would copy the actual form, “Copy a list of things” then copy “Current page’s form:formatted as a list” since the action is looking for a list but you are just copying one thing. Then I was storing a list under the Form, so I had to make a copy of that list, then set the New form’s list to the result of copying the list… if that makes sense…

It sounds like I might be on the right track then in my proposed suggestion above then.

The solution seems to involve two main things from my view: copying/duplicating the current data in the form back into the same table but against a ‘version number’, and then the second part would be to get the user to specify which version they want to view in the front end (the form). They would specify this from their control panel in a drop down or something.

Then add a ‘Do a search for’ and add a constraint to only show the results for the table that match with the user’s select version number specified in their control panel.

Perhaps I’ll try this on one form and see what happens.

Hi!

I have a similar feature in my app. I have a data type called “Document Template” that has fields that link to other data types. So when i make a version i duplicate the Document Template without having to duplicate the other data types since it’s just links to the same items

Thanks for sharing. What about the data held in the database for the other items that don’t come under the data type Document Template - do they get updated in some way?

Also, can you possibly share what your workflow looks like for the duplication part of creating a new version?

I have 2 ways of versioning user input. First one is as mentioned, using a Document Template data type to link other data types under one.

Second one is a field in a data type that stores lists of text.
What i do for this is to setup a workflow that will store current date/time and the latest content formatted as text.

For example i have my data type Task in which i want to store versions of the field Description. In my client side workflow for when a task is created or updated it will create/update a Task but will also add to a Version field (the list of text).

This is what each text looks like in the Versions field; DateTime:extract (UNIX) | Description

Let’s breakdown why:

I convert the time to UNIX so that the list of text is sortable according to time (since you cannot sort lists of text any other way without plugins)

I use the “|” as a way to split the text between the DateTime and content of Description using the operator :splitby (|). This will let me display/apply data accordingly.

The reason why i have 2 methods is because i want to manage the “weight” of each data type to ensure search performance.

I use the first method to piece together potentially large data. I use the second method for data types i know will not get “heavy” overtime.

2 Likes

Just revisiting this after some more research.

It seems to me that the only way to use native duplication strategies is to use the ‘copy list of things’ feature in Bubble, but my issue is that nothing of what I want to duplicate is in a list. They are just multiple text fields etc. Some of my research shows that I can convert such fields into lists to make this work. The below video has been really helpful in visually playing out how this will work (and what the result will be).

However, something I’m not sure of it, once a thing is converted into a list, is that thing’s data type now ‘list of things’ or is it still it’s original data type, like ‘text’ for example?

Secondly, is there a way to convert the item back to a single thing, essentially a reverse of the above?

I actually only have one record in my table so this might work well for me (as although Bubble will convert it to a list, it will only actually be one item in this ‘list’). My issue is when I start to expand this app in a couple of months with APIs, the limitation of lists might cause me problems and cause confusion (hence me wanting to reverse the list conversion).

1 Like

Use the “Copy a list of things” but the list you provide will just be your single thing:formatted as list

Then when you need to refer to that result of the copy action do Result of step [your copy step]:first item

This method would be the equivalent to Bubble making a “Copy a thing” action.

1 Like

I’m going to use ‘result of step’ action to add the name and version number to that new entry. However, I want to stop Bubble from creating any new line items if the entry under the same already exists (based on an input field). I’ve only done this once before, and recall it’s something only the lines of using the ‘count’ variable in the ‘only when’ field in the workflow box. Is this the right approach?

When you do your copy action to create new revisions, why would there be a version with the same number? Wouldn’t you want it to find the latest revision, then +1 the version number every time?

Example:
Amendment is created, defaults to version 1.0. All those sub types are also created.

User presses copy to make a new revision,

  • You run the copy action for the Amendment
  • You run a copy action for the sub types
  • You then make changes to the Amendment copy step’s result, you change the version number to +1 the previous version.
  • You the make changes to the Subtype copy result, you change it’s main amendment to the result of your Copy an Amendment step.

Then if needed change the page’s thing to your new amendment so they can actually see the new copy

That’s right, all new revisions will have a new unique version number with that’s +1 or +0.1 - I’m thinking about the possibility someone comes along and makes a typo and pressed 2 instead of 3 and now there’s two version 2’s which means Bubble will get confused if there are workflows expecting there to be unique version numbers. As you’ve indicated I can get Bubble to +1 the version automatically but there might be occasions where the user wants to specify this themselves, which is totally fine.

Having a validation check to prevent this from happening will wake the user up in ensuring their proposed version is the right one - unless I can ask Bubble to auto populate this from the ‘version field’ (which is strictly numbers) with +1, and then the user can amend in the field directly.

I have pretty much successfully implemented those steps you’ve mentioned, just adding the final touches.

When you have your input field for typing the version number, make sure it’s set to decimal input, and make the minimum allowed value to be Do a search for Amendments sorted by version number, descending no, :last item's version number + 0.1

So at a minimum it would need to be 0.1 more than the last version.

All depends how fancy you want to get, you could have an input that’s disabled by default and the it shows what the next version would be, and the user could check a box saying they want to specify their own version, then the minimum could be what I proposed earlier.

And yes also you could have it check first if there’s a version number already the same but if you just prevent the same version from being made in the first place maybe the check isn’t needed?

Also

Bubble differentiates based off of the unique IDs so you could have 100 amendments all with Version 2.0 and it can still tell the difference between all of them, it’s just the users of course will have no idea which one is which

Otherwise yea on your button press you can have the Only when statement be Do a search for Amendments with a constraint with the Version = your version input’s value :count is 0 then it continues with the workflow.

Then you copy that workflow but make it :count > 0 and instead of your copy process you just have it show some red text saying one exists already with the same version.

Similar to on my test app type in TEST2 and press Create https://tylerboodman-test-app.bubbleapps.io/version-test?debug_mode=true
tylerboodman-test-app | Bubble Editor

1 Like

Thanks, this is exactly what I’ve built since my last post. A text that tells the user what the next version would be in both cases. The field will pre-populate with the +1 but they can easily enter what ever they want in there.

Now going to work on implementing the validation rule on preventing duplications.

I have noted a separate problem - when the user creates this amendment, in the 'copy a list ’ option in the workflow I have asked Bubble to run a search for the thing I want it to copy with a constraint that it searches for the name of the project in question. This works fine if there are no existing amendments present (as Bubble only duplicates the one entry). However, when I create an amendment, and then create another for the same project (so there are now two entries with the same project name, but versions keep them differentiated), Bubble duplicates them both.

I’ve been playing around with adding in new constraints under the search instruction, but my efforts have not worked in all circumstances such as when creating an amendment from scratch as one of the constraints I set needed there to be at least one prior amendment saved.

You can search for project with the same name, sort by version, descending no, pick the :last item, then do :formatted as list. That would find the latest one to copy instead of it copying all of them.

OR don’t do any searches, and instead when you do your copy action just pick your dropdown’s value:formatted as list since your dropdown seems like your dropdown has the exact project in question?

I’m not exactly sure your whole database structure, but it seems like you could benefit from a Trial data type, and an Amendment datatype, and under that type you have a field type “Trial” referencing it’s source trial? and another field “Version”?

So upon creation of a trial you immediately generate an amendment with a version of 1.0. Then as you create amendments with version 2.0, 3.0, you can search for all versions of a single Trial and get the edit history essentially

Thanks @tylerboodman, these look like promising solutions to try. I’m going to give these a go and report back.

To answer your question on the last post. I have a datatype for trial, amendment and each have trial (ie the name), version and date as well. I have made notes on your last point as this is what I thought as well. Interlinking the tables together would be ideal, and I already have this in my app and as version management would be an important part of this app’s functionality I can build this out again relatively quickly I hope.

Yes store the actual Trial itself not the text of the trial’s name.

If you have your Trial dropdown to pick from, you can have a repeating group searching for Amendments with a constraint Trial = Dropdown's Trial to get all the version history.

Also when you let the user type the version, if you’re checking for existing versions that won’t prevent them from typing a version EARLIER than the latest one. So if a V 1.0 exists, and a 2.0 exists, they could probably type 1.5 and it would technically be allowed but it would be a later version than 2.0…

You could have a dropdown saying it’s a minor revision or major revision, one option would automatically add 0.1, the other adds 1.0… no manual input.

Just a suggestion