Personal Tasks CRUD Example

Something to keep in mind while programming to this API is anything you can do with Connections Online you can do with the API. However your access to data does not change so you will not be able to gain access to anything you currently cannot access using the main application.

This example will show you how to setup a page that does all the basic CRUD operations; Create, Read, Update, and Delete. We will use Ajax to make the call and JQuery to modify the objects on the page. You will see a lot of .hide and .show in this example. That is simply to remove items on the page that are not needed for the current operation.

If you want to skip to the completed product you can visit it here. It is a simple page that takes UserName Password a metric ID and allows you to update it.

We will be making API calls to tasks, the help documentation can be found at Task Help.

Basic Authentication:

For authentication we will use basic authentication with the username and password base 64 encoded. All of our communications will be going over SSL so they will stay safe and secure. In the code below we are getting the UserName and Password from textboxes on the HTML page, base64 Encoding them and then setting them in the Authorization header.

function AuthHeaders(request) {
    var restAuthHeader = btoa($('#txtUserName').val() + ':' + $('#txtPassword').val());
    request.withCredentials = true;
    request.setRequestHeader("Authorization", "Basic " + restAuthHeader);
}

The Basic Authentication method we just created will be called in all of our main functions. We will call it using this code, which you will see repeated in most of these examples.

 beforeSend: function (request) {
            AuthHeaders(request);
        },

Document Functions

This is a list of all the document functions. Any click event or change event will be here. The first function is for our click button. Once it is clicked we tell the event to prevent default and stop propagation. This will tell keep the button from taking any other types of action that we may not want. Next we set id equal to the data button and send it into GetTask.

The other items are all similar, the second item in our list is for our Individual select box, it is set so that anytime someone changes it the task list will be updated with the new person's tasks. Going down the list we see the login function call. This just wires the login button to call GetIndividual which will handle the login and populating the individual display list. Once we are logged in we have two new buttons, the logout and add screen buttons.

$(function () {
    $(document).on('click', '[data-id]', function (e) {
        e.preventDefault();
        e.stopPropagation();
        var id = $(this).data("id");
        GetTask(id);
    });
    $(document).on('change', '#selIndividuals', function (e) {
        e.preventDefault();
        e.stopPropagation();
        var id = $(this).val();
        GetTasks(id);
    });
    $(document).on('click', '#btnLogin', function (e) {
        e.preventDefault();
        e.stopPropagation();
        GetIndividuals();
        $('#divSelIndividual').show();
    });
    $(document).on('click', '#btnAddScreen', function (e) {
        e.preventDefault();
        e.stopPropagation();
        var id = $(this).val();
        AddScreen();
    });
    $(document).on('click', '#btnLogout', function (e) {
        e.preventDefault();
        e.stopPropagation();
        Logout();
    })
});

Login (Get Individuals)

This sections serves two purposes. It logs the user in and populates the individuals drop down. We can see the basics of the Ajax call at the top, with the call to AuthHeaders in the beforeSend. In the success we hide the login boxes and show the logout button which will also show us who we are logged in as. Then it calls LoadIndividual and passes data into it.

function GetIndividuals() {
    jQuery.support.cors = true;
    $.ajax({
        beforeSend: function (request) {
            AuthHeaders(request);
        },
        url: 'https://api.connectionsonline.net/v4/individuals',
        type: 'GET',
        dataType: 'json',
        success: function (data) {
            $('#divLogout').show();
            $('#divLogin').hide();</p>
            $('#btnLogout').empty();
            $('#btnLogout').append("<h4>You are logged in as " + $('#txtUserName').val().toString() + '.<br />Logout</h4>').show();
            LoadIndividual(data);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('jqXHR:');
            console.log(jqXHR);
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}

As the name implies this function will load the individuals into the dropdown list. This function loads all of the individuals into the dropdown and sorts them by their name.

function LoadIndividual(individuals) {
    $('#selindividuals').empty();
    $.each(individuals, function (key, val) {
        $('#selIndividuals').append('<option value="' + val.ID + '">' + val.FullName + '</option>');
    });
    sortDropDownListByText('#selIndividuals');
    $('#selIndividuals').prepend("<option value='0' selected='selected'>Choose One...</option>");
}

Cancel & Logout

Cancel

The cancel button will be used on both the create screen and update screen. This button will hide/clear the current edit menu and take you back to the view you were previously looking at.

function Cancel() {
    $('#divTasks').show();
    $('#result').hide();
    ClearFields();
    DisplaySetup();
}

Logout

This will log the user out. It will empty the contents of all fields and hide everything while showing the login options.

function Logout() {
    $('#divLogin').show();
    $('#divLogout').hide();
    $('#btnLogout').empty();
    $('#txtUserName').val(null);
    $('#txtPassword').val(null);
    $('#result').hide
    $('#divInputTask').hide();
    $('#divNewTaskIndividual').hide();
    $('#divAddTaskBar').hide();
    $('#divTasks').hide();
    $('#divAddTask').hide();
    $('#error').hide();
    $('#result').hide();
    $('#selIndividuals').empty();
    $('#divSelIndividual').hide();
    ClearFields();
}

Clear Fields

This is called by both the Cancel, logout, and update functions. All this function does is sets the values of the textboxes to null. This way if you logout the next person to log in can't see your information, Also if you update more than one document you are sure not to have any surprise values pop in.

function ClearFields() {
        $('#txtTaskIndividual').val(null);
    $('#txtTaskID').val(null);
    $('#selTaskParent').find(null);
    $('#txtName').val(null);
    $('#txtDescription').val(null);
    $('#txtPriority').val(null);
    $('#txtRank').val(null);
    $('#txtColor').val(null);
    $('#txtHoursActual').val(null);
    $('#txtHoursProjected').val(null);
    $('#txtStartDateActual').val(null);
    $('#txtStartDateProjected').val(null);
    $('#txtEndDateActual').val(null);
    $('#txtEndDateProjected').val(null);
    $('#txtMilestone').val(null);
    $('#txtTrackingLabel').val(null);
    $('#txtNearHighlightOverride').val(null);
}

Get all Tasks

Once a user selects an Individual, the change function in the functions section will call GetTasks. This function makes a call to the API and gets all the tasks. The call then sends that result to DisplayTasksTable which populates a table with the resulting tasks.

function GetTasks() {
    jQuery.support.cors = true;
    var id = $('#txtIndividualID').val();
    $.ajax({
        beforeSend: function (request) {
            AuthHeaders(request);
        },
        url: 'https://api.connectionsonline.net/v4/individuals/' + id + '/tasks/',
        type: 'GET',
        dataType: 'json',
        success: function (data) {
            DisplayTasksTable(data);
            $('#result').hide();
            $('#error').hide();
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide();
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('textStatus:');
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}
error: function (jqXHR, textStatus, errorThrown) {
    $('#result').hide();
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}

This function displays an Array of tasks in a table. First it sets up the table and taking the value from each task it appends that in a cell to the string. In front of each table row it will add an edit button, this will allow the user to open each task and edit them. Once it is finished it will close the table and post the entire string to the html div called "divTasks".

function DisplayTasksTable(tasks) {
    var tbl = $('<table border="1" class="table-responsive table-hover" id="table"><tr><td>Task ID</td><td>Individual ID</td><td>Parent ID</td><td>Name</td><td>Description</td><td>Priority</td><td>Rank</td><td>Color</td><td>Hours Actual</td><td>Hours Projected</td><td>Start Date Actual</td><td>Start Date Projected</td><td>End Date Actual</td><td>End Date Projected</td><td>Milestone</td><td>Tracking Label</td><td>Near Highlight Overrided</td></tr>');
    $.each(tasks, function (key, val) {
    tbl.append('<tr><td><button class="btn btn-primary" data-id="' + val.ID + '"><td>' + val.ID + '</td><td>' + val.AncestorID + '</td><td>' + val.ParentID + '</td><td>' + val.Name + '</td><td>' + val.Description + '</td><td>' + val.Priority + '</td><td>' + val.Rank + '</td><td>' + val.Color + '</td><td>' + val.HoursActual + '</td><td>' + val.HoursProjected + '</td><td>' + val.StartDateActual + '</td><td>' + val.StartDateProjected + '</td><td>' + val.EndDateActual + '</td><td>' + val.EndDateProjected + '</td><td>' + val.Milestone + '</td><td>' + val.TrackingLabel + '</td><td>' + val.NearHighlightOverride + '</td></tr>');
    });
    tbl.append("</table>")
    $('#divTasks').html(tbl).show();
}

Create a Task

Setup

Next we will create a task. The first thing we will do is setup an add screen. For this I setup the "AddScreen" function which will hide everything that isn't needed for adding an item and only show what you do need for it.

function AddScreen() {
    $('#divInputTask').show();
    $('#divNewTaskIndividual').show();
    $('#txtTaskIndividual').val($('#selIndividuals').find('option:selected').text());
    $('#divAddTaskBar').show();
    $('#divTasks').hide();
    $('#divAddTask').hide();
    $('#error').hide();
    $('#result').hide();
    $('#divSelIndividual').hide();
}

Create Task

The top of this function is setting up the task object to be sent to the API, it is taking the values from the fields on the page and assigning them to the Task object. Next, just like on our get functions we need to setup the call and tell it to expect JSON, in addition this time we have to turn our task object into JSON which is what "data: JSON.stringify(task)" does for us. Finally in the success portion we hide all the fields we don't need while showing the ones we do. The server will pass back the object we created which means we can display that to make sure all the information was entered correctly. The server will also give us information about where the object was created, which we are displaying in the result div. The last thing we need to do here is clear the fields so when we come back to this screen it is fresh and ready to enter new information.

function CreateTask() {
    jQuery.support.cors = true;
    var task = {
        AncestorID: $('#txtAncestorID').val(),
        ParentID: $('txtParentID').val(),
        Name: $('#txtName').val(),
        Description: $('#txtDescription').val(),
        Priority: $('#txtPriority').val(),
        Rank: $('#txtRank').val(),
        Color: $('#txtColor').val(),
        HoursActual: $('#txtHoursActual').val(),
        HoursProjected: $('#txtHoursProjected').val(),
        StartDateActual: $('#txtStartDateActual').val(),
        StartDateProjected: $('#txtStartDateProjected').val(),
        EndDateActual: $('#txtEndDateActual').val(),
        EndDateProjected: $('#txtEndDateProjected').val(),
        Milestone: $('#txtMilestone').val(),
        TrackingLabel: $('#txtTrackingLabel').val(),
        NearHighlightOverride: $('#txtNearHighlightOverride').val(),
    };
    $.ajax({
        beforeSend: function (request) {
            AuthHeaders(request);
        },
        url: 'https://api.connectionsonline.net/v4/tasks/',
        type: 'POST',
        data: JSON.stringify(task),
        contentType: "application/json;charset=utf-8",
        processData: true,
        success: function (data, status, xhr) {
            DisplayTaskTable(data);
            $('#error').hide();
            $('#inputTask').hide();
            $('#addTaskBar').hide();
            $('#divTasks').show();
            $('#addTask').show();
            $('#getTasks').show();
            $('#getTask').show();
            $('#result').html('<a href="' + xhr.getResponseHeader('Location') + '">' + xhr.getResponseHeader('Location') + '</a>').show();
            console.log(xhr.getResponseHeader('Location'));
            ClearFields();
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('jqXHR:');
            console.log(jqXHR);
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}

Update Task

Updating a task has several functions which I have broken off into their own sections so we can look at them individually.

Get Task

First important part to update an item is the Edit button. The function that controls this is at the top of the page under functions. We already have the button wired up so we first need to get the task in question. We could just load this task from the list, however there is a chance that is has been updated since we last loaded it. So to keep things simple we will just reload it here. This GetTask function will call the API and request all the current data for the task we are looking at and pass it into the LoadTask function.

function GetTask(id) {
    jQuery.support.cors = true;
    $.ajax({
        beforeSend: function (request) {
            AuthHeaders(request);
        },
        url: 'https://api.connectionsonline.net/v4/tasks/' + id,
        type: 'GET',
        dataType: 'json',
        success: function (data) {
            LoadTask(data);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide();
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}

Load Task

Once we have the current data for the item to be updated we will need to load it so it can be modified. In almost all of the text fields we are simply setting the value to the value we received from the call. There are two exceptions to this. The first is txtTaskIndividual, here we are looking at the option that was selected in the drop down menu and placing that in a text box, which in the example I have turned to read only. This field will not be updated even if you change it. The next difference is the selTaskParent field. It sets the selected property in the drop down to the task's Parent. After all the fields are loaded, the bottom part of this function will hide/show objects on the page to create the update page. The last section here will show/hide divs based on what is needed for updating the object.

function LoadTask(task) {
    $('#txtTaskIndividual').val($('#selIndividuals').find('option:selected').text());
    $('#selTaskParent').find(task.ParentID);
    $('#txtTaskID').val(task.ID);
    $('#txtName').val(task.Name);
    $('#txtDescription').val(task.Description);
    $('#txtPriority').val(task.Priority),
    $('#txtRank').val(task.Rank);
    $('#txtColor').val(task.Color);
    $('#txtHoursActual').val(task.HoursActual);
    $('#txtHoursProjected').val(task.HoursProjected);
    $('#txtStartDateActual').val(task.StartDateActual);
    $('#txtStartDateProjected').val(task.StartDateProjected);
    $('#txtEndDateActual').val(task.EndDateActual);
    $('#txtEndDateProjected').val(task.EndDateProjected);
    $('#txtMilestone').val(task.Milestone);
    $('#txtTrackingLabel').val(task.TrackingLabel);
    $('#txtNearHighlightOverride').val(task.NearHighlightOverride);
    $('#divInputTask').show();
    $('#divUpdateTaskBar').show();
    $('#divSelIndividual').hide();
    $('#divTasks').hide();
    $('#divAddTask').hide();
    $('#error').hide();
    $('#result').hide();
}

Update Task Function

Now we are ready to update the item. Once the update button is clicked it will call this function. Again the click action can be found at the top of this page under Functions. The update function will take all of the text boxes and put them in the variable task, which will then be turned into a json object and sent to the API. On a success the function will do 3 things, first it will display a "Task Updated" message in the result div. Next it will display the object that it updated in a table, the API will send this as a response. Finally it will empty the contents of all of the text fields

function UpdateTask() {
    jQuery.support.cors = true;
    var task = {
        ID: $('#txtTaskID').val(),
        ParentID: $('txtParentID').val(),
        Name: $('#txtName').val(),
        Description: $('#txtDescription').val(),
        Priority: $('#txtPriority').val(),
        Rank: $('#txtRank').val(),
        Color: $('#txtColor').val(),
        HoursActual: $('#txtHoursActual').val(),
        HoursProjected: $('#txtHoursProjected').val(),
        StartDateActual: $('#txtStartDateActual').val(),
        StartDateProjected: $('#txtStartDateProjected').val(),
        EndDateActual: $('#txtEndDateActual').val(),
        EndDateProjected: $('#txtEndDateProjected').val(),
        Milestone: $('#txtMilestone').val(),
        TrackingLabel: $('#txtTrackingLabel').val(),
        NearHighlightOverride: $('#txtNearHighlightOverride').val(),
    };
    $.ajax({
        beforeSend: function (request) {
            AuthHeaders(request);
        },
        url: 'https://api.connectionsonline.net/v4/tasks/',
        type: 'PUT',
        data: JSON.stringify(task),
        contentType: "application/json;charset=utf-8",
        processData: true,
        success: function (data, status, xhr) {
            DisplayTaskTable(data);
            $('#error').hide();
            $('#inputTask').hide();
            $('#updateTaskBar').hide();
            $('#result').html('Task Updated').show();
            ClearFields();
        },
         error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide
            $('#error').html('
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('jqXHR:');
            console.log(jqXHR);
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
        });
        }
        

Edit a Task

The next code is the main portion of our edit. When someone clicks the edit button, the click function will be triggered. This will call our GetTask function which is almost identical to GetTasks. The only differences are; the id is now a Task ID rather than Individual ID, the url has changed and in the success function we now call DisplayTaskTable instead of DisplayTasksTable, which you can see right below the GetTask function.

function GetTask() {
    jQuery.support.cors = true;
    var id = $('#txtTaskID').val();
    $.ajax({
        beforeSend: function (request) {
            AuthHeaders(request);
        },
        url: 'https://api.connectionsonline.net/v4/tasks/' + id,
        type: 'GET',
        dataType: 'json',
        success: function (data) {
            DisplayTaskTable(data);
            $('#error').hide();
        },
         error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide();
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}

Display Task

This function displays a single task. It will be called by the Update and Create Task functions.

function DisplayTaskTable(task) {
        var tbl = $('<table border="1" class="table-responsive table-hover">
            <tr><td>Task ID</td><td>Individual ID</td><td>Parent ID</td><td>Name</td><td>Description</td><td>Priority</td><td>Rank</td><td>Color</td><td>Hours Actual</td><td>Hours Projected</td><td>Start Date Actual</td><td>Start Date Projected</td><td>End Date Actual</td><td>End Date Projected</td><td>Milestone</td><td>Tracking Label</td><td>Near Highlight Overrided</td></tr>');
            tbl.append('
            <tr><td>' + task.ID + '</td><td>' + task.AncestorID + '</td><td>' + task.ParentID + '</td><td>' + task.Name + '</td><td>' + task.Description + '</td><td>' + task.Priority + '</td><td>' + task.Rank + '</td><td>' + task.Color + '</td><td>' + task.HoursActual + '</td><td>' + task.HoursProjected + '</td><td>' + task.StartDateActual + '</td><td>' + task.StartDateProjected + '</td><td>' + task.EndDateActual + '</td><td>' + task.EndDateProjected + '</td><td>' + task.Milestone + '</td><td>' + task.TrackingLabel + '</td><td>' + task.NearHighlightOverride + '</td></tr>
        </table>');
        $('#divTasks').html(tbl).show();
        }

Delete

Delete Check

The first section to the delete is a simple check. When you press the delete button on the page it will call DeleteTask(). This simply asks to confirm that you want to delete the item. If you click yes, it calls DeleteTaskInternalCall() If the user selects ok, it will call the DeleteTaskInternalCall function and the item will be deleted, otherwise if the user clicks cancel or the x in the upper right corner the delete command will not be called.

    
function DeleteTask() {
    if (confirm('Are you sure you want to delete this item?')) {
        DeleteTaskInternalCall();
    } else {
     }
}

Delete function

The delete function takes the task id and sends it into the API. This will mark the item deleted in the database. Please note that most items can be undeleted after they have been marked deleted. Once deleted this function will show the comment "Item Deleted" in the result div.

function DeleteTaskInternalCall() {
    jQuery.support.cors = true;
    var id = $('#txtTaskID').val();
    $.ajax({
        beforeSend: function (request) {
           AuthHeaders(request)
        },
        url: 'https://api.connectionsonline.net/v4/tasks/' + id,
        type: 'DELETE',
        contentType: "application/json;charset=utf-8",
        processData: true,
        success: function (data, status, xhr) {
            $('#divTasks').hide();
            $('#result').html('Item Deleted').show();
            DisplaySetup();
            console.log(xhr.getResponseHeader('Location'));
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#result').hide
            $('#error').html('<p>status code: ' + jqXHR.status + '</p><p>errorThrown: ' + errorThrown + '</p>').show();
            console.log('jqXHR:');
            console.log(jqXHR);
            console.log('textStatus:');
            console.log(textStatus);
            console.log('errorThrown:');
            console.log(errorThrown);
        }
    });
}