Adding Tasks

Up until now we have been working with the data that we initially populated the database with at the beginning of the tutorial. Now its time to add the ability to add a brand task.

In the previous page we added a Form with which we can edit an existing task's data, we are going to re-use that form for adding new tasks.

Adding a Task

The first step is to add another button to MainForm, this time called addButton with the title Add Task.

Form with added Add button

Double click on the button to add a new event handler addButton_Click.

In the event handler you need to add the following code which creates a new Task

private void addButton_Click(object sender, EventArgs e)
{
    Tasks.Tasks newTask = new Tasks.Tasks();

    using (var form = new AddEditTaskForm())
    {
        form.Text = "Edit New Task";
        form.DataContext = newTask;

        if (form.ShowDialog() != DialogResult.OK)
        {
            return;
        }

        newTask = form.DataContext;
    }

    this._dataModule.DataAdapter.InsertRow(newTask);
    this._dataSource.Add(newTask);
}

Problem

It is not currently obvious but your app now has a major problem. All new tasks are being assigned the user Id of 0, and not the Id of the logged in user.

SQL data from which shows the new task with User Id set to 0

To fix this we need to make a change to the relativity server.

Solution

All changes that are made in the client get passed to Relativity Server inside the Delta objects. There is one delta object per table. Each delta contains one or more changes. Each delta change contains the old (original) and new (modified) values. Within Relativity Server’s business rule scripting model, you can get access to the deltas and changes before the Relativity Server processes them. Using techniques similar to how you filtered data coming from the Relativity Server, you can now ensure that each new Task has its User field set to the ID of the current user before the Relativity Server tries to post it.

Schema Modeler

Go back to the Relativity Admin Tool and open the Schema Modeler. Expand the SCHEMA tree node and select the Scripts entry. Using the Add Event button, add the beforeProcessDeltaChange script handler.

As its name suggests, the beforeProcessDeltaChange event will be called just before processing a particular change from the delta object for the given table. In this script, you just need to obtain the current user ID from the session and update the delta change User field with its value.

// Called before each change is applied to the database
function beforeProcessDeltaChange(delta, change, wasRefreshed, canRemove)
{
  var userId = session['Login.Id'];
  change.newValues['User'] = userId;
  canRemove = false;
}

Back in your running application, try to apply the changes again and hopefully all will work.

An Improved Solution

Even though the application now works, there is a problem. The beforeProcessDeltaChange script will be run for every change in every delta before it gets processed. If you were to ever start adding records for another table in addition to the Tasks table, this script would try to update the User field on that table as well. You need to solve this by ensuring the delta change is for the Tasks table before you try to set the User field.

// Called before each change is applied to the database
function beforeProcessDeltaChange(delta, change, wasRefreshed, canRemove)
{
  if (delta.name == "Tasks") {
    var userId = session['Login.Id'];
    change.newValues['User'] = userId;
    canRemove = false;
  }
}

Records that are being updated should already have the User field set from when the record was added, so although it doesn't hurt to set it again, it's not very clean or efficient, so you might want to ensure that the script only sets the User field when the delta is for an insert.

// Called before each change is applied to the database
function beforeProcessDeltaChange(delta, change, wasRefreshed, canRemove)
{
  if (delta.name == "Tasks" && change.isInsert) {
    var userId = session['Login.Id'];
    change.newValues['User'] = userId;
    canRemove = false;
  }
}

Now when you look at the data in the SQL Database you can see that the new task has a user ID 1 which matches the user we are testing with (Alex).

SQL data showing the User Id is fixed

We've fixed that issue, unfortuantly it exposes another issue; namely that the app currently retrieves all the tasks regardless of which user is logged in.

We will fix that issue in a moment in Server-Side Scripting. First we will make it possible to delete a task so we can delete the task with the User Id of 0.