How to merge multiple steps into one undo / redo? - mxgraph

I use mxGraph to make an editor. When the user clicks a button once, I need to perform many steps in the graph (such as moving the position of some nodes, adding or deleting some nodes, and modifying the properties of some nodes).
Generally, I can use mxModel.setValue (), mxGraph.removeCells () to complete one operation, but the user needs to press ctrl + z multiple times to restore the original state of the graph.
How to merge any number of operations into one operation and restore the state of the entire graph with one undo / redo?

I don't know if this is what you are looking for, but if everything you do between one model.beginUpdate() and a model.endUpdate() belongs to the same "undo" action. By calling the mxUndoManager.undo once you should be able to undo all of them at once...

Related

Foundry Scenarios edited data materialized as dataset

Is it possible to materialize the edits made as part of a scenario into a dataset in foundry?
I want for each scenario to write out the primary keys of the objects edited as part of the scenario.
The motivation is that I need to run multiple processes to compute metrics as part of the changed values for each scenario, at a scale and runtime that is not possible to do with Functions.
Edit with details:
The thing is that I am not doing actual edits to the objects for the object type, I don't want to apply it.
I tested out the "Action Log" and it does not seem like this picks up "uncommitted" actions, meaning actions that is just run as part of a scenario. Also, it does not seem to be a link to the scenario it was a part of, even if the changes were committed.
The workflow is that I have Object Type A, and I define multiple scenarios S on a subset of the objects in A.
Each scenario might make something like 50k edits to a subset of A, through multiple Actions backed by a Function.
I save some of the scenarios. Now I am able to load these scenarios and "apply" them on A again in Workshop.
However I need to be able to get all the primary keys, and the edited values of A materialized into a dataset (for each scenario), as I need to run some transformation logic to compute a metric for the change as part of each scenario (at a scale and execution time not possible in Functions).
The Action Log did not seem to help a lot for this. How do I get the "edits" as part of a saved scenario into a dataset?
The only logic you can run BEFORE applying will be functions.
Not sure about your exact logic but Function's Custom Aggregations can be very powerful: Docs here
this might not directly let you calculate the Diff but you could use the scenario compare widgets in workshop to compare your aggregation between multiple Scenarios
e.g. you have a function that sums(total profit)
Your Workshop could show:
Current Data:
$10k
Scenario A:
$5k
Scneario B:
$13k
instead of like:
Scenario A:
-$5k
Scenario B:
+$3k
Afaik there's no first class way of doing this (yet).
"Applying" a scenario basically means you're submitting the actions queued on the scenario to the ontology. So neither the actions nor the ontology are aware that they came from a scenario.
What I've been doing to achieve what you're working on is using the "Action Log". It's still in Beta so you might need to ask for it to be enabled. It will allow you on each action to define a "log" object to be created that can track the pks of your edited objects per Action.
How I do the action log is:
My Action log has the "timestamp" of the action when they were run.
My Scenarios have the "timestamp" of when it was applied.
Since "Applying a Scenario" means -> actually running all actions on Ontology (underlying data) this gets me this structure if I sort everything by timestamp:
Action 1
Action 2
Scenario A applied
Action 3
Action 4
Scenario B applied
this allows you to do a mapping later on of Action 1/2 must come from Scenario A and Action 3+4 come from Scenario B.
EDIT: Apparently you might be able to use the Scenario RID directly in the Action Logs too (which is a recent addition I haven't adopted yet)
This won't allow you tho to compute (in transforms...) anything BEFORE applying a scenario tho

Need form to display checkbox, radiobutton group, or listbox based on task type

I've been trying to whip up a simple MS-Access task-tracking application for personal use. My basic data model is a task-definition table (in which I can define daily tasks) and a task-result table (in which I can track which tasks I've performed on a given day).
I'm trying to build a form which
1) lists all daily tasks (sorted by time-of-day, an attribute of each task), and
2) next to each task, displays a widget that lets me mark the task as complete.
Here's the rub, though. I have three (and may add more) different types of tasks:
simple yes/no tasks (for which a single checkbox widget would work)
score-able tasks that allow me to track how well the task was done (for which a radio-button group would fit), and
"complex" tasks comprised of several yes/no sub-tasks (for which a multi-selection list-box would fit).
I've gotten as far as building the form so it lists all tasks in desired order, but I am 100% stuck on how to code the (conditional) data-entry widget. Though I've had no difficulty in implementing each widget individually, my best effort is a task list with just check-boxes, just radio group, or just list boxes. I have no idea how to tell the form to "look at" the type of each task and present the appropriate widget beside it.
I'm almost ready to throw in the towel and just hard-code all the tasks into the form, in a fixed order, along with their appropriate widget. Is there a way to implement this in a more elegant manner?
[an aside] I chose MS-Access somewhat arbitrarily, and am learning MS-Access forms as I go. If anyone feels I'm stuck by virtue of choosing the wrong tool for the job, feel free to let me know
As resolved in the comments to original question, it seems the main obstacle is the limitations of continuous forms. Because Access treats each column of continuous forms as an atomic element, there are very few options available to differentiate their presentation. The only tool that comes close is Conditional Formatting, and the closest approach to selectively hiding/showing fields is to hide text-box fields using text colors that "camouflage" them into the background color.
This limitation leads to my potential work-around.
To recap the objective: Within a given day, I want to list a [table-driven] set of tasks. Each task has options of "Yes/No", "Choose one of N choices", or "Choose 0 to N of N choices". Depending on the type of task, it should be rendered (respectively) as a single checkbox (yes/no), a radio button group (choose one), or an checkbox group (choose many).
(An aside: I realize, as I type this, that the first type is really a subclass of the third type, but that doesn't really make the core issue go away)
The proposed idea:
At the time the form is launched, a query can be run which will tell exactly which task will fall into exactly which position. In other words, before "drawing" today's tasks, the database can answer which task will be in position 1, which will be in position 2, and so on. Additionally, I can safely say that there will never be more than, say, 20 tasks (though the actual number of task on any given day can vary).
Which leads me to wonder: what if I designed the form with 20 "slots", and in each slot, had 3 overlaying presentations: one for Yes/No tasks, one for a "Choose one" tasks, and one for "Choose many" tasks. (60 total - sounds horrific, but I'd hope copy/paste would come to the rescue).
When Access renders the form, each slot would query for the "nth" task of the day (so the 1st slot would query for the first task, the 2nd slot for the second task, and so on). The "visible" option would then be set to "Yes" for only the presentation that matched the type of task returned by the query. So if the 3rd slot, querying for the 3rd task, received a task of the "yes/no" variety, only the "yes/no" prompt would be displayed.
For what it's worth, I do have a working version of my application already (though checking & unchecking check-boxes according to whether a task is labeled as "pick one" or "pick many" definitely grates on me). So if there's a reason to think this new approach won't work, I'd be happy to hear it before I throw any real development time at it.

Is there a way to lock a record in a MySQL table for a specific period of time?

Friends,
I have a table that contains data on the two parents of students at a college. Each parent will be sent an email with a link to a web page that will display the parent data that we currently have on record (names, email addresses, mailing addresses, employment information, etc.), and will be able to edit the data in order to update our records.
Since each parent will receive a link to the same data, and will be able to update the same fields, there is the potential for both parents opening the data at the same time, and then one parent submitting changes, then the other submitting changes which would overwrite those submitted by the first parent.
In order to avoid this, I have thought of using the method I've read about in which a timestamp field exists in the parent data record, and that timestamp is used as a hidden field on the form. Then, if both parents load the form, they'll both have the same timestamp stored in the form. When the first parent submits her/his updates, though, the timestamp field will update, and when the form is submitted by the second parent, the timestamp from her/his form will not be the same as the timestamp in the table, and the program (a Perl CGI) would alert the 2nd parent to this fact, and tell them to reload the form or risk overwriting the data submitted by the first parent.
That will work, but the person for whom I'm creating this form has asked if, instead, there's a way to lock the record in the table as soon as the first parent loads the form, and if the second parent tries to load the form while the lock exists, the form will tell them to wait until later (or words to that effect). The lock would be in place either until the form is submitted by parent one, or until one hour (or some specific period of time) has passed. Is this even do-able? I've been Googling, and don't see specific examples of this having been done.
Is there some better solution to this issue of needing to prevent two people from updating the same record, and the second submitter overwriting data submitted by the first.
Thanks for any help you can provide!
Doug
*******to address the comment by "inspiredcoder," here are some more details about what I'm concerned with here:
What I'm trying to avoid having happen is that parent 1 opens the form and starts making changes to the data. Before parent 1 submits those changes, parent 2 opens the form and also starts making different changes to the same fields being edited by parent 1. Parent 1 then submits her/his changes. Parent 2 then submits her/his changes, overwriting the changes made by parent 1.
What I would prefer is that parent 2 would not be able to even begin making changes if parent 1 has opened the form. The changes made by both parents need to be captured, and not overwritten.
The method of using the timestamp as I describe in my initial post can be used to prevent parent 2 from overwriting the data, but it also will mean that they'd have to reload the form to see the changes submitted by parent 1, and in doing so, would lose any of the edits they'd made in the form prior to them trying to submit it and getting the notice to reload. I'd like to avoid them having to re-enter their changes, and the only way to accomplish this seems to be to prevent them from even opening the form if it is already being edited, but I'd want that "lock" on the form/data to timeout after an hour or so in case parent 1 walks away with the form open but unsubmitted.
*****To answer a question by "ThisSuitIsBlackNot": Each parent can edit the same fields. One field asks for activities in which the parents are involved. Let's say Parent 1 enters five activities. If Parent 2 sees the form before Parent 1's edits have been submitted, he/she may enter completely different items, which upon submission would overwrite the activities submitted by Parent 1. If, on the other hand, Parent 2 could be stopped from accessing the form until after Parent 1 has finished her/his edits, then when Parent 2 can load the form, she/he will see everything that Parent 1 entered, rather than an empty form field, and may choose to modify what Parent 1 submitted, overwrite it completely, or not make any changes.
There's a reason you're not finding any info on how to do this. It is a very tough problem that no one has a good solution for regardless of which tech stack you're using. In your case, I'm not convinced that it is actually a terribly important issue to solve because the data does not seem crucial or mission critical. And besides, if there are changes they will likely be the same.
I've been in many design discussions where this issue came up. After hours of arguing the result is always the same: Last one in wins.
That said, here are a couple of simpler ideas you could try:
Simply email both parents (or whoever's registered as a guardian) whenever data on that page changes. This solution is stupid simple and easy to implement. If you're already using email services in other parts of the app then it becomes nearly trivial.
Not so simple: Whenever a request is made to edit the data, create a hash of the data as is to send back with the response to the client. When the edited data is sent in to update the row, check the data against the hash. If the hashes don't match it means that someone else has modified the data while the other parent was looking at it. The trouble with this solution is that you have to create these hashes and lug them around through several layers of the app making your programming non-trivial.
This statement caught my eye in a later edit of your OP:
The changes made by both parents need to be captured, and not
overwritten.
That single business rule actually makes things quite simple for you. All you need to do is to ALWAYS create objects when they do not have a unique identifier (probably 0 or -1). When objects do have an ID, meaning they have already been created, you simply update.
There is an assumption here that edits will likely be performed non-destructively on the same data. e.g. One parent creating an activity and the other parent editing it. There is a chance of duplicate activities but that's a situation easily resolved with a delete.
This way, no one parent can overwrite the other's data blindly and unknowingly.
Regardless of what you do though, do not try to find a perfect solution. It just doesn't happen. I know, I've been writing line of business apps for over 15 years. Apply your time and talents to something that you can get right, which the application and its business rules.
I would suggest reading up on database isolation levels. I believe MySQL defaults to repeatable read. You can confirm your isolation level at the DB level by running "SHOW GLOBAL VARIABLES LIKE 'tx_isolation';" Each transaction in this configuration is already placing a lock. Whether it is getting a row level or escalating depends on factors such as how indexes are being hit etc, by the query. If you fire off transaction A to update a record then subsequently fire off transaction B, transaction B is already in a holding pattern until transaction A completes its work in this configuration. If you set this to read commited, reads no longer block each other with locking (updates, etc still place locks). In lieu of implicit locks on reads you can be explicit using the select for update to try and force a lock on the read.
I mention brushing up on locking mechanics as trying to brute force locking without extreme knowledge of the back end DB mechanics can lend itself to deadlock central.
It seems like in your scenario this is more about user perception that what they are reading is up to date when they submit the changes. The DB is really doing it's job as designed. I have seen architecture to address this user perception issue by only allowing one user in a record at a time (locking out other users from the record while someone is it) handled in some middle ware code, etc. Or by using SOA architecture to push notifications to users in the record that a changed occurred by another user.

JTable + TableCellEditor: Buffer changes on data

my questions targets at editable JTables (using TableCellEditor).
Some tools (like SQLDeveloper) allow the user to edit multiple records, create new one or delete existing records. The table shows the modified records, but the modifications are local only, until the user clicks a "save" button (or "commit" in case of SQLDeveloper). The user can also revert all his changes.
What is the best way to implement this behaviour in a Swing application with a JTable?
I don't think, that a tool like SQLDeveloper creates a copy of records listed in the table. My first idea was to create a TableModel that wraps another TableModels (this allows me to use an arbitrary implementation of TableModel) and stores only the values of the modified cells. This works fine, when the number of rows does not change. But how to handle inserting or removing rows?
Thanks in advance for any hints.
Markus
Inside your TableModel your can register a TableModelListener with the parent TableModel and process the events for insertion or deletion accordingly also within your model.

Save and get arbitrary sort order in SQL Server

My client wants to sort products by drag & drop. The drag & drop part is easy with javascript.
My problem is how do I save and get the sort order?
I'm using .net c# and SQL Server 2008.
When I move a product and drop it in a new position I get the id of the product that's moved, product in front and product behind. With this data I want to update the sort order of products.
I was thinking of adding a field with position, but then I guess I have to update every item when position changes.
In general adding an additional position field is the only thing you can do, to get truly arbitrary ordering.
But you can implement it in several ways. Here are two ways I've implemented myself some time ago.
1. Method: Update all position values, by looping over your items and performing an UPDATE statement for every position.
This is easy to implement, but because of the many updates, it's not good for many items and/or large tables. Especially if you do it via Ajax and perform a complete re-ordering on every change in the list.
2. Method: Do a smart update of only the affected rows.
SELECT all items in the current sort order (The "old list") (Usually fast compared to an UPDATE statement)
Iterate over all items from the "new list" and compare each item to the item from the old list at the same position/index. If the items are the same, don't do anything
If the items are different find that item from the old list, which should actually be at that position and update its position value accordingly (Some lookup data structure might be useful here)
That way you only have to perform minimal database updates, but you'll have more complex code.
Personally I'd go with the first way, until the database updates actually become a performance problem.
We have a sort column but yes we have to re-index all rows as things change. You could mitigate this by assigning sort's in large enough increments to allow some level of movability before you have to do this, such as in 10's or 100's but that's not the best solution and I'd be interested to see what other ideas people have.
If you can capture each move programatically (with up and down buttons for example) then you can just swap the position numbers of the row moving and the row being moved. Make sure that you add new rows at the max position + 1.