diff --git a/wcsudat/accounts/tests.py b/wcsudat/accounts/tests.py
index 9524ee9b9acdfca87a8efd99517f87f1fae901a9..93de1659fad57d75f388b11b5b21779114bcfca3 100644
--- a/wcsudat/accounts/tests.py
+++ b/wcsudat/accounts/tests.py
@@ -7,8 +7,9 @@ class LoginViewTests(TestCase):
         response = self.client.post('/accounts/login/', {'username': 'test', 'password': 'Dj@ng0U$3r'})
         self.assertEqual(response.status_code, HTTPStatus.FOUND)
         response = self.client.get('/surveys/')
-        self.assertEqual(response.status_code, HTTPStatus.OK)
-        self.assertContains(response, "You are logged in as test")
+        self.assertEqual(response.status_code, HTTPStatus.FOUND)
+        # Should redirect to access page since the user doesn't have access to a group yet
+        self.assertEqual(str(response.url), "/surveys/access/")
     
     def test_empty_login(self):
         response = self.client.post('/accounts/login/', {'username': '', 'password': ''})
diff --git a/wcsudat/surveys/admin.py b/wcsudat/surveys/admin.py
index 75941ed032721ad86af6e32081850174ea7a9c19..2156063a2c213c613e07bbcac8558281a5c214a0 100644
--- a/wcsudat/surveys/admin.py
+++ b/wcsudat/surveys/admin.py
@@ -2,7 +2,9 @@ from django.contrib import admin
 from django.urls import reverse
 from django.utils.html import format_html
 
-# Register your models here.
+# This file controls how the database tables will be displayed on the admin page
+# Fields are the editable fields in a model page
+# List display is a list of fields to display on the model table page
 from .models import *
 
 from .views import calculate_risk
@@ -28,6 +30,9 @@ class QuestionInline(admin.TabularInline):
     extra = 0
 
     def edit(self, instance):
+        '''
+        This creates an edit button so that the Question can be accessed from the inline
+        '''
         url = reverse('admin:%s_%s_change' % \
             (instance._meta.app_label, instance._meta.model_name), 
             args=(instance.id,))
@@ -37,8 +42,11 @@ class ChoiceQuestionInline(admin.TabularInline):
     model = ChoiceQuestion
     readonly_fields = ('edit',)
     extra = 0
-
+    
     def edit(self, instance):
+        '''
+        This creates an edit button so that the Choice Question can be accessed from the inline
+        '''
         url = reverse('admin:%s_%s_change' % \
             (instance._meta.app_label, instance._meta.model_name), 
             args=(instance.id,))
@@ -50,6 +58,9 @@ class SubsectionInline(admin.TabularInline):
     extra = 0
 
     def edit(self, instance):
+        '''
+        This creates an edit button so that the Subsection can be accessed from the inline
+        '''
         url = reverse('admin:%s_%s_change' % \
             (instance._meta.app_label, instance._meta.model_name), 
             args=(instance.id,))
@@ -62,6 +73,9 @@ class SectionInline(admin.TabularInline):
     extra = 0
 
     def edit(self, instance):
+        '''
+        This creates an edit button so that the Section can be accessed from the inline
+        '''
         url = reverse('admin:%s_%s_change' % \
             (instance._meta.app_label, instance._meta.model_name), 
             args=(instance.id,))
diff --git a/wcsudat/surveys/apps.py b/wcsudat/surveys/apps.py
index 840a0c6ddeeb0d6427e4275f457f7d431407479a..22d48acce01c404317407bb8a3e9f4437094961f 100644
--- a/wcsudat/surveys/apps.py
+++ b/wcsudat/surveys/apps.py
@@ -1,5 +1,5 @@
 from django.apps import AppConfig
-
+# Default django app config
 
 class SurveysConfig(AppConfig):
     default_auto_field = 'django.db.models.BigAutoField'
diff --git a/wcsudat/surveys/models.py b/wcsudat/surveys/models.py
index 7104391410032f6426baa151620b6a0c2065ff72..139dc8a39c3ac49a5f98fe84ad38e890a546c9af 100644
--- a/wcsudat/surveys/models.py
+++ b/wcsudat/surveys/models.py
@@ -9,6 +9,11 @@ from datetime import datetime
 import time
 from colorfield.fields import ColorField
 
+# The classes in this file dictate the database configuration.
+# Each class is related to a table in the database
+# This helps to enforce third normal form.
+# For instance a foreignkey stores the id of the associated object whereas a manytomany 
+# field creates a new table to store relationships.
 
 class Feedback(models.Model):
     user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL, blank=True)
@@ -17,7 +22,6 @@ class Feedback(models.Model):
         return f"{str(self.user)}: {self.feedback_text}"
 
 class Client(models.Model):
-    # TODO Maybe change this to distinct choices for normalized data
     clinician = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL, blank=True)
     name = models.CharField(max_length=200)
     surname = models.CharField(max_length=200)
@@ -63,11 +67,17 @@ class Risk(models.Model):
         return self.risk_category
 
     def set_min_max(self):
+        '''
+        This function calculates the miniumum and maximum possible 
+        values for the risk based on the questions in the assessment
+        '''
         mn = 0
         mx = 0
         questions = ChoiceQuestion.objects.filter(risks__in=[self])
         for question in questions:
             numbers = [choice.risk_amount for choice in question.choices.all()]
+            if(len(numbers) == 0):
+                continue
             mn += min(numbers)
             mx += max(numbers)
         self.minimum = mn
@@ -75,8 +85,7 @@ class Risk(models.Model):
         self.save()
 
     def get_amount(self):
-        # TODO Make this work. We want to quickly query a sum of choice answer risk amounts for all answers in a survey answer
-        # grouped by the risk group
+        # TODO Remove
         survey_answer = SurveyAnswer.objects.all().order_by('-date_time')[0]
         # choicequestion__answer__subsection_answer__survey_answer=survey_answer
         sum = Choice.objects.filter(answer__subsection_answer__survey_answer=survey_answer, answer__choice_question__risks__in=[self]).annotate(sum_total=Sum('risk_amount'))
@@ -99,7 +108,7 @@ class Survey(models.Model):
 
     def __str__(self):
         return self.survey_text
-
+    # TODO Remove these
     def add_section(self, section_text):
         pass
 
@@ -110,6 +119,9 @@ class Survey(models.Model):
         pass
 
     def section_count(self):
+        '''
+        This function counts the number of sections in a survey
+        '''
         sections = Survey.objects.annotate(num_sections=Count('section')).filter(id=self.id,)
         return sections[0].num_sections if len(sections) > 0 else 0
 
@@ -127,6 +139,9 @@ class Section(models.Model):
         return str(self.order)
 
     def subsection_count(self):
+        '''
+        This function counts the number of subsections in a section
+        '''
         subsections = Section.objects.annotate(num_subsections=Count('subsection')).filter(id=self.id,)
         return subsections[0].num_subsections if len(subsections) > 0 else 0
 
@@ -145,19 +160,26 @@ class Subsection(models.Model):
     def ordering(self):
         return '{}.{}'.format(self.section.ordering() if self.section else 'x', self.order)
 
-    '''
-    Return a comma separated string of risk categories in this section
-    '''
+    # TODO Remove
     def risk_factors(self):
+        '''
+        Return a comma separated string of risk categories in this section
+        '''
         # TODO Remove duplicates from this list
         # This could be changed to return the queryset for further processing
         return ', '.join([str(r.risks) for r in ChoiceQuestion.objects.filter(subsection_id=self.id,)])
 
     def question_count(self):
+        '''
+        This function counts the number of questions in a subsection
+        '''
         questions = Subsection.objects.annotate(num_questions=Count('question')).filter(id=self.id,)
         return questions[0].num_questions if len(questions) > 0 else 0
 
     def choice_question_count(self):
+        '''
+        This function counts the number of questions in a subsection
+        '''
         choice_questions = Subsection.objects.annotate(num_choice_questions=Count('choicequestion')).filter(id=self.id,)
         return choice_questions[0].num_choice_questions if len(choice_questions) > 0 else 0
 
@@ -205,17 +227,19 @@ class ChoiceQuestion(models.Model):
     def __str__(self):
         return self.question_text # self.ordering() + ' ' + 
 
-    '''
-    Get all of the choice options as comma seperated strings
-    '''
+    # TODO Maybe remove these
     def choice_options(self):
+        '''
+        Get all of the choice options as comma seperated strings
+        '''
         # This could be changed to return the queryset for further processing
         return ', '.join([str(ch.choice_text) for ch in Choice.objects.filter(choicequestion=self,)])
     
-    '''
-    Get all of the risks options as comma seperated strings
-    '''
+    
     def risk_options(self):
+        '''
+        Get all of the risks options as comma seperated strings
+        '''
         # This could be changed to return the queryset for further processing
         return ', '.join([str(r.risk_category) for r in Risk.objects.filter(choicequestion=self,)])
 
@@ -237,15 +261,27 @@ class SurveyAnswer(models.Model):
         return self.date_time.strftime("%H:%M:%S")
 
     def close(self):
+        '''
+        This function closes a survey and sets the necessary fields 
+        '''
+        # We assume that if we were able to close the survey 
+        # then all the visible surveys are complete
         self.complete_subsections = len(SubsectionAnswer.special_objects.visible_in_survey(self))
         self.date_time = Now()
         self.in_progress = False
         self.save()
     
     def since(self):
+        '''
+        This function finds the largest non-zero time period which has passed since the survey was closed
+        It then returns the number of these that have passed 
+        '''
         if self.in_progress:
             return "In Progress"
+        # Get the time delta as total seconds
         t = int((timezone.now() - self.date_time).total_seconds())
+        # Parse as an epoch time. We then just need to calculate the 
+        # time units which have passed since 1970/1/1 00:00:00
         t = time.localtime(t)
         years = t[0] - 1970
         if years > 1:
@@ -286,9 +322,14 @@ class SurveyAnswer(models.Model):
         return "In Progress"
 
     def risks(self):
+        '''
+        This function creates a dictionary of the format 
+        Risk Groups: {Risks: {Risk Levels}}
+        and all of their associated data
+        Most importantly it sums the risk amount from each answer in the survey
+        and adds this to the dictionary
+        '''
         res_dict = {}
-        
-        # TODO Optimise
         for riskgroup in RiskGroup.objects.all().order_by('order'):
             res_dict[riskgroup.order] = {}
             res_dict[riskgroup.order][riskgroup.id] = {}
@@ -325,6 +366,10 @@ class SurveyAnswer(models.Model):
 
 class SubsectionAnswerManager(models.Manager):
     def visible_in_survey(self, survey_answer):
+        '''
+        Return a queryset of Subsection Answers in a given 
+        survey_answer if they return true for show_subsection
+        '''
         subsection_answers = SubsectionAnswer.objects.filter(survey_answer=survey_answer).order_by('subsection__section__order','subsection__order')
         ids = [answer.id for answer in subsection_answers if answer.show_subsection()]
         subsection_answers = subsection_answers.filter(id__in=ids)
@@ -340,6 +385,15 @@ class SubsectionAnswer(models.Model):
     special_objects = SubsectionAnswerManager()
 
     def show_subsection(self):
+        '''
+        This function checks to see if the subsection should be shown.
+        It does this by summing the risk amount for every answer with the same
+        risk type as the risk level requirement.
+        It then checks that the sum of the risk amount is greater than or equal to the
+        threshold amount.
+        '''
+        if not self.subsection:
+            return False
         requirement = self.subsection.risk_level_requirement
         if not requirement:
             return True
@@ -357,18 +411,19 @@ class SubsectionAnswer(models.Model):
         return str(self.subsection) + " answer"
 
 class AnswerManager(models.Manager):
+    # TODO remove
     def visible_in_subsection(self, subsection_answer):
         answers = Answer.objects.filter(subsection_answer=subsection_answer).order_by('order')
         ids = [answer.id for answer in answers if answer.show_question()]
         answers = answers.filter(id__in=ids)
         return answers
     
+    # TODO remove
     def incomplete_visible_in_subsection(self, subsection_answer):
         answers = self.visible_in_subsection(subsection_answer)
         ids = [answer.id for answer in answers if str(answer.answer()) == "" or answer.answer() == None]
         answers = answers.filter(id__in=ids)
         return answers
-
     def has_answer(self):
         answers = Answer.objects.all().filter(choice_answer__isnull=False)
         return answers
@@ -383,6 +438,7 @@ class Answer(models.Model):
     objects = models.Manager()
     special_objects = AnswerManager()
 
+    # TODO Remove
     def show_question(self):
         requirement = self.question().risk_level_requirement
         if not requirement:
@@ -427,6 +483,9 @@ class Answer(models.Model):
             )
         ]
     def question(self):
+        '''
+        Get the question object depending on whether it is a text or choice question
+        '''
         if self.text_question != None:
             return self.text_question
         elif self.choice_question != None:
@@ -435,6 +494,9 @@ class Answer(models.Model):
             return ''
         
     def answer(self):
+        '''
+        Get the answer object depending on whether it is a text or choice question
+        '''
         if self.text_question != None:
             return self.text_answer
         elif self.choice_question != None:
diff --git a/wcsudat/surveys/serializers.py b/wcsudat/surveys/serializers.py
index e763190bc468c86adc7090832fa7da2d07e05d37..8d750d11e2b80f458979cd827b72e32ebd028972 100644
--- a/wcsudat/surveys/serializers.py
+++ b/wcsudat/surveys/serializers.py
@@ -2,6 +2,11 @@ from random import choices
 from rest_framework import serializers
 from .models import *
 
+# This file contains serializers which convert data from the database into JSON dictionaries 
+# By default, foreignkey fields will be displayed as the id of the associated object
+# Using a serializer for the fields type with the source set to that field will change the id to a serialized dictionary
+# e.g. risk_level_requirement: 1 -> risk_level_requirement: {id: 1, risk: 1, level_name: "High", level_threshold: 5, color: "#FF0000"}
+
 class FeedbackSerializer(serializers.ModelSerializer):
 	class Meta:
 		model = Feedback
diff --git a/wcsudat/surveys/static/surveys/assessment.js b/wcsudat/surveys/static/surveys/assessment.js
index 96215ba5d1fabf17dbcb7de5647c09381d38dcb8..312a49d7f972c12eff638cf59bb1db0ae782235d 100644
--- a/wcsudat/surveys/static/surveys/assessment.js
+++ b/wcsudat/surveys/static/surveys/assessment.js
@@ -1,3 +1,6 @@
+/**
+ * Creates a csrf cookie
+ */
 function getCookie(name) {
     var cookieValue = null;
     if (document.cookie && document.cookie !== '') {
@@ -14,6 +17,11 @@ function getCookie(name) {
     return cookieValue;
 }
 var csrftoken = getCookie('csrftoken');
+
+// These variables are used to store the state of the assessment locally to prevent extra api calls
+// The snapshot lists are used to allow smooth re-rendering of the html as items in the list are replaced
+// instead of having to rebuild the entire list from scratch.
+// If the current list is longer than the old list then the rest of the elements in the old list are removed
 var activeItem = null
 var list_snapshot = {}
 var all_answers = {}
@@ -25,13 +33,12 @@ var risk_dict = {}
 var total_questions = 0
 var complete_questions = 0
 
+// Here we instantiate some events and components
 document.getElementById(`submit-button`).onclick = submitSurvey
 const scrollSpy = new bootstrap.ScrollSpy(document.getElementById('survey-wrapper'), {
     target: '#nav-wrapper',
     // rootMargin: "0px 0px -80% 0px"
 })
-
-
 var popup = document.getElementById("submit-popup")
 var popupClose = document.getElementById("popup-close")
 window.onclick = function(event) {
@@ -42,16 +49,20 @@ window.onclick = function(event) {
 popupClose.onclick = function() {
     popup.style.display = "none"
 }
+
+// Calling this function starts the chain of functions used to build the initial assessment page
 getSurvey()
 
+/**
+ * Fetch a list of subsection answers in the active assessment from the database
+ */
 function getSurvey(){
-    // Fetch all subsection answers
     var url = `http://127.0.0.1:8000/surveys/api/sub-answer-list/${client_id}/${survey}/`
     fetch(url)
     .then((resp) => resp.json())
     .then(function(data){
         all_subsections = data
-        // Could initialise all_answers here
+        // Create entries in the dictionary for each subsection to store a list of answers later on
         for(var i in all_subsections)
             list_snapshot[all_subsections[i].subsection_detail.id] = []
         getAnswers()
@@ -60,8 +71,10 @@ function getSurvey(){
     
 }
 
+/**
+ * Fetch a list of answers in the active assessment from the database
+ */
 function getAnswers(){
-    // Fetch all answers
     var url = `http://127.0.0.1:8000/surveys/api/full-answer-list/${client_id}/${survey}/`
     fetch(url)
     .then((resp) => resp.json())
@@ -70,7 +83,9 @@ function getAnswers(){
         
         for(var i in data){
             var id = data[i].subsection_answer_detail.subsection_detail.id
-            
+            // Store each answer in the dictionary grouped by subsection
+            // Each answer is also given a list index
+            // This data structure allows quick access to answer objects
             if(all_answers[id]){
                 all_answers[id].push(data[i])
                 data[i]['list_index'] = all_answers[id].length-1
@@ -84,9 +99,13 @@ function getAnswers(){
         calculateRisks()
     })
 }
-
+/**
+ * Create a dictionary of risks and calculate the total risk amount for the active assessment
+ */
 function calculateRisks(){
     risk_dict = {}
+    // Here we loop through each subsection and all of the choice answers in each one and
+    // calculate the total amount of risk for each risk type
     for(var k in all_subsections){
         var id = all_subsections[k].subsection_detail.id
         if(all_answers[id] === null)
@@ -109,6 +128,9 @@ function calculateRisks(){
     buildWrappers() 
 }
 
+/**
+ * Return a list of subsections that aren't currently locked by a risk level requirement
+ */
 function getActiveSubsectionList(){
     var list = []
     for(var i in all_subsections){
@@ -123,7 +145,9 @@ function getActiveSubsectionList(){
     return list
 }
 
-// Build all wrappers for active subsections and then call functions to build headers and lists in each
+/**
+ * Build all wrappers for active subsections and then call functions to build headers and lists in each
+ */
 function buildWrappers(){
     var wrapper = document.getElementById('survey-wrapper')
     
@@ -163,11 +187,15 @@ function buildWrappers(){
     wrapper_list_snapshot = list
     buildLists(list)
     buildNav()
+    // Refresh the scrollspy to resync all of the attached elements 
     scrollSpy.refresh()
     
     
 }
 
+/**
+ * Call functions to build lists of answers and headers in each wrapper
+ */
 function buildLists(active_subsections)
 {
     total_questions = 0
@@ -180,6 +208,9 @@ function buildLists(active_subsections)
     }
 }
 
+/**
+ * Build a navigation list to navigate between subsections
+ */
 function buildNav(){
     var wrapper = document.getElementById('nav-wrapper')
     
@@ -189,6 +220,8 @@ function buildNav(){
         //     continue
         var active = ""
         var element = document.getElementById(`nav-button-${i}`)
+        // This allows us to keep the active element from the scrollspy so that there 
+        // is no visual flashing when it is reset
         if(element && element.classList.contains('active'))
             active = "active"
         try{
@@ -222,7 +255,6 @@ function buildNav(){
         }
     }
     try{document.getElementById(`complete-progress`).remove()}catch(err){}
-    console.log('Questions', complete_questions, total_questions)
     if(total_questions > 0){
         var complete_pcnt = Math.round(100*complete_questions/total_questions)
         wrapper.innerHTML += `<div class="progress m-1" id="complete-progress">
@@ -235,6 +267,9 @@ function buildNav(){
     
 }
 
+/**
+ * Build the header for a given subsection with the section and subsection details
+ */
 function buildHeader(item, active_subsections){
 
     var wrapper = document.getElementById(`header-wrapper-${item}`)
@@ -265,6 +300,10 @@ function buildHeader(item, active_subsections){
     
 
 }
+
+/**
+ * Build the clinician notes input for a given subsection
+ */
 function buildNotes(subsection_index){
 
 
@@ -289,10 +328,15 @@ function buildNotes(subsection_index){
 
 }
 
+/**
+ * Build a list of questions and answer inputs for a given subsection
+ */
 function buildList(subsection_index, active_subsections){
     var wrapper = document.getElementById(`list-wrapper-${subsection_index}`)
     var list = []
     var id = active_subsections[subsection_index].subsection_detail.id
+    // We first create a list of answers in a subsection that should not be hidden by 
+    // risk level requirements by checking that their requirement has been met
     for(var i in all_answers[id]){
         var answer = all_answers[id][i]
         var required = null
@@ -311,6 +355,7 @@ function buildList(subsection_index, active_subsections){
         for (var i in list){
             total_questions++
             if(!list[i].choice_answer && (!list[i].text_answer || list[i].text_answer.trim()==="")){
+                // Subsection not complete
                 complete = false
             }else{
                 complete_questions++
@@ -321,14 +366,17 @@ function buildList(subsection_index, active_subsections){
             }catch(err){
 
             }
+            // Create the question text
             var title = `<span class="title" id="data-row-${list[i].id}-title">${parseInt(i)+1}. ${list[i].text}</span>`
             if (!list[i].choice_set_question)
             {
+                // Create the answer input for a text question
                 var answer = `<input id="data-row-${list[i].id}-answer" value="${list[i].text_answer}" class="answer-${id}" type="text submit">`
             }
             else
             {
                 var answer = `<div id="data-row-${list[i].id}-choice-answer" class="answer-${id} choice-wrapper d-flex justify-content-between">`
+                // Create the choice buttons for a choice question
                 for (var k in list[i].choice_set_question.choice_set)
                 {
                     var choice = list[i].choice_set_question.choice_set[k]
@@ -348,6 +396,7 @@ function buildList(subsection_index, active_subsections){
                 answer+="</div>"
             }
             
+            // Create the full question item
             var item = `
                 <div id="data-row-${id}-${i}" class="question-wrapper container">
                     <div class="container">
@@ -371,7 +420,7 @@ function buildList(subsection_index, active_subsections){
         }
 
         list_snapshot[id] = list
-
+        // Add necessary event listeners for the answer fields
         for (var i in list){
             var answerField = document.getElementsByClassName(`answer-${id}`)[i]
             if(answerField.id.includes('choice'))
@@ -400,6 +449,7 @@ function buildList(subsection_index, active_subsections){
 
 
         }
+    // If the completion status of a subsection has changed then update it on the server
     if(complete != active_subsections[subsection_index].complete){
         active_subsections[subsection_index].complete = complete
         updateComplete(active_subsections[subsection_index])
@@ -407,18 +457,23 @@ function buildList(subsection_index, active_subsections){
         
     
 }
+
+/**
+ * Check and submit the active assessment
+ */
 function submitSurvey(){
     
     var list = getActiveSubsectionList()
     var complete = true
-    var alert_text = "<p>Please complete the following subsections</p>"
-    console.log("Submit Data: ", list)
+    var alert_text = "<h2>Please complete the following subsections</h2>"
+    // Check to see if the assessment is complete
     for (var i in list){
         if(!list[i].complete){
             complete = false
             alert_text += `<p>${list[i].subsection_detail.subsection_name}</p>`
         }
     }
+    // Show a popup if the assessment is not complete, otherwise submit the assessment
     if(!complete){
         var popup_wrapper = document.getElementById('submit-popup-content-wrapper')
         popup_wrapper.innerHTML = alert_text
@@ -431,6 +486,10 @@ function submitSurvey(){
 
     
 }
+
+/**
+ * This function updates the clinician notes for the given subsection on the database
+ */
 function updateNotes(item, subsection_index){
     var active_subsections = getActiveSubsectionList()
     var id = active_subsections[subsection_index].id
@@ -451,6 +510,9 @@ function updateNotes(item, subsection_index){
     })
 }
 
+/**
+ * This function updates the complete field for the given subsection on the database
+ */
 function updateComplete(item){
     var url = `http://127.0.0.1:8000/surveys/api/sub-answer-update/${item.id}/`
     fetch(url, {
@@ -469,7 +531,9 @@ function updateComplete(item){
     })
 }
 
-
+/**
+ * This function updates the answer for a text question on the database
+ */
 function updateAnswer(item){
     var url = `http://127.0.0.1:8000/surveys/api/answer-update/${item.id}/`
     var new_answer = document.getElementById(`data-row-${item.id}-answer`).value
@@ -482,7 +546,7 @@ function updateAnswer(item){
         body:JSON.stringify({'text_answer':new_answer})
     }
     ).then(function(response){
-        
+        // Sync with database
         fetchAnswer(item)
         
         
@@ -490,6 +554,9 @@ function updateAnswer(item){
     //document.getElementById(`data-row-${item.id+1}-answer`).scrollIntoView()
 }
 
+/**
+ * This function updates the answer for a choice question on the database
+ */
 function updateChoiceAnswer(item){
     var url = `http://127.0.0.1:8000/surveys/api/answer-update/${item.id}/`
     var new_answer = document.querySelector(`input[name="choice-answer-${item.id}"]:checked`).value
@@ -510,12 +577,16 @@ function updateChoiceAnswer(item){
         body:JSON.stringify({'choice_answer':new_answer})
     }
     ).then(function(response){
+        // Sync with database
         fetchAnswer(item)
         
     })
     //document.getElementById(`data-row-${item.id+1}-answer`).scrollIntoView()
 }
 
+/**
+ * This function retrieves a single answer from the database to sync the client with the server
+ */
 function fetchAnswer(item){
     var url = `http://127.0.0.1:8000/surveys/api/answer-detail/${item.id}/`
     fetch(url)
diff --git a/wcsudat/surveys/static/surveys/client.js b/wcsudat/surveys/static/surveys/client.js
index acb3ed80e454799ae9883cce652a7e243893f62b..462d8d3f635cff499ea33e2ee86d95095c1f8da3 100644
--- a/wcsudat/surveys/static/surveys/client.js
+++ b/wcsudat/surveys/static/surveys/client.js
@@ -1,3 +1,6 @@
+/**
+ * Creates a csrf cookie
+ */
 function getCookie(name) {
     var cookieValue = null;
     if (document.cookie && document.cookie !== '') {
@@ -14,26 +17,29 @@ function getCookie(name) {
     return cookieValue;
     }
 var csrftoken = getCookie('csrftoken');
-//var clinician = "{{ user.id }}"
-var list_snapshot = []
 
+// These variables are used to manage state
+var list_snapshot = []
 var survey_answer_list = []
-//var selectedClient = "{{ client.id }}"
-
 var selectedSurvey = null
+var summary = {}	
 
+// Instantiate some components and event listeners
 var surveyFormWrapper = document.getElementById('survey-view-wrapper')
-
 var newSurveyButton = document.getElementById('new-survey')
-
 newSurveyButton.addEventListener('click', (function(item){
     return function(e){
         newSurvey()
     }
 })())				
                 
-var summary = {}				
+
+// Start building the client page
 getSurveyAnswers()
+
+/**
+ * Fetch a list of assessments for the active client from the database
+ */
 function getSurveyAnswers(){
     var url = `http://127.0.0.1:8000/surveys/api/survey-answer-list/${selectedClient}/`
 
@@ -45,11 +51,14 @@ function getSurveyAnswers(){
     })
 }
 
-
+/**
+ * Build a list of assessments for the active client
+ */
 function buildList(){
     // TODO Make sure the list doesn't get moved by other components being created
     var wrapper = document.getElementById('list-wrapper')
     //wrapper.innerHTML = ''
+    // Remove the loading spinner once we start building the list
     try{document.getElementById(`list-spinner`).remove()}catch(err){} 
     
     var list = survey_answer_list
@@ -58,6 +67,7 @@ function buildList(){
             wrapper.innerHTML = `<p><strong>This client has no assessments. Please click the button above to start a new one.</strong></p>`
             return
         }else{
+            // Set the selected survey to the most recent one by default
             selectedSurvey = list[0].id	
         }
         
@@ -92,6 +102,7 @@ function buildList(){
         }
         
         wrapper.innerHTML += item
+        // Calculate the average risk amounts over all complete assessments
         if(!list[i].in_progress /*&& list[i].id != selectedSurvey*/ && list[i].complete_subsections === 12)
             for(var order in list[i].risks)
                 for (var section in list[i].risks[order])
@@ -126,7 +137,7 @@ function buildList(){
         var answerField = document.getElementsByClassName('survey-row-item')[i]
         answerField.addEventListener('click', (function(item){
             return function(e){
-                getSurvey(item)
+                setSurvey(item)
             }
         })(list[i]))
     }
@@ -136,18 +147,26 @@ function buildList(){
         
     }
 
-
+/**
+ * Start a new assessment
+ */
 function newSurvey(){
     window.location.href = `/surveys/new-survey/${selectedClient}/`
 }
 
-function getSurvey(item){
-    selectedSurvey = item.id
+/**
+ * Set the selected assessment to the given assessment
+ */
+function setSurvey(survey){
+    selectedSurvey = survey.id
     buildList()
 }
 
+/**
+ * Show the details of the selected survey. This includes information about the assessment as well as risk radar charts for analysis
+ */
 function showDetails(){
-    // TODO Add animated loading icon
+    // TODO Refactor this into multiple functions
     surveyFormWrapper.className = "visible container"
     var wrapper = document.getElementById('survey-view-content')
     var url = `http://127.0.0.1:8000/surveys/api/survey-answer-detail/${selectedSurvey}/`
@@ -159,17 +178,20 @@ function showDetails(){
             
             if(data.complete_subsections <= 2)
             {
+                // Screening only
                 wrapper.innerHTML = `<p>Screening completed on ${data.date} at ${data.time}</p>`
                 wrapper.innerHTML += `<a href="/surveys/transcript/${selectedClient}/${selectedSurvey}/">View Transcript</a><br>`
                 wrapper.innerHTML += `<br><p><i class="bi-check-circle-fill text-success"></i> Low risk of substance abuse disorder.</p>`
             }
             else{
+                // Full assessment
             wrapper.innerHTML = `<p>Assessment completed on ${data.date} at ${data.time}</p>`
             wrapper.innerHTML += `<a href="/surveys/transcript/${selectedClient}/${selectedSurvey}/">View Transcript</a><br>`
             wrapper.innerHTML += `<br><p><i class="bi-exclamation-circle-fill text-danger"></i> High risk of substance abuse disorder</p>`
             for(var order in data.risks)
+             
             for (var section in data.risks[order]){
-                // console.log(data.risks[order][section].risks)
+                // Create a canvas and list for each risk group
                 if(JSON.stringify(data.risks[order][section].risks) === "{}")
                     continue
                 wrapper.innerHTML += `	<div class="container d-flex flex-row border-dark 
@@ -184,6 +206,8 @@ function showDetails(){
             }
         for(var order in data.risks)
         for (var section in data.risks[order]){
+            // Here section refers to the risk section or risk group
+            // Add all the risk amounts to the risk list
             var list_wrapper = document.getElementById(`survey-view-risks-${section}`)
             var list = data.risks[order][section].risks
             if(JSON.stringify(data.risks[order][section].risks) === "{}")
@@ -201,6 +225,7 @@ function showDetails(){
                 var amnt = list[i].amount
                 var summary_amnt = summary[i]
                 var color = ""
+                // Get the risk level and associated color
                 for (var k in list[i].levels){
                     var threshold = list[i].levels[k].level
                     if(amnt >= threshold)
@@ -210,7 +235,8 @@ function showDetails(){
                     }
                         
                 }
-                
+
+                // Create accordions with risk explanations
                 var item = `
                     <div class="accordion-item">
                         <h2 class="accordion-header" id="info-panel-${section}-${j}">
@@ -226,6 +252,7 @@ function showDetails(){
                         </div>
                     </div>
                 `
+                // Calculate the percent risk using the minimum and maximum risk values
                 container += item
                 var mn = list[i].minimum
                 var mx = list[i].maximum
@@ -236,7 +263,7 @@ function showDetails(){
                 values.push(pcnt)
                 summary_values.push(summary_pcnt)
                 
-                
+                // Create a progress bar to show the risk amount
                 container += `<div class="progress">
                 <div class="progress-bar" role="progressbar" style="width: ${pcnt}%; background-color: ${color} !important;" 
                 aria-valuenow="${amnt}" aria-valuemin="${mn}" aria-valuemax="${mx}"></div>
@@ -250,19 +277,8 @@ function showDetails(){
             }
             container += '</div>'
             list_wrapper.innerHTML += container
-            // j = 0
-            // for (var i in list){
-            //     document.getElementById(`info-${section}-${j}`).addEventListener('click', (function(label, text){
-            //         return function(e){
-            //             console.log('Clicked')
-            //             e.preventDefault()
-            //             $('#riskModalTitle').text(label)
-            //             $('#risk-modal-body').text(text)
-            //             $('#risk-modal').modal()
-            //         }
-            //     })(i, list[i].text))
-            //     j+=1
-            // }
+
+            // Calculate the colour for the chart
             total_pcnt /= (100*j)
             var high_is_good = data.risks[order][section].high_is_good
             if(high_is_good)
@@ -295,6 +311,7 @@ function showDetails(){
                 color = red
             var rgb = 'rgb(' + [color.r, color.g, color.b].join(',') + ')'
             var rgba = 'rgb(' + [color.r, color.g, color.b, 0.2].join(',') + ')'
+            // Configure chart options and datasets
             const dataset = {
                 labels: labels,
                 datasets: [{
@@ -337,6 +354,7 @@ function showDetails(){
                     }
                 },
             };
+            // Render the chart for the risk group
             new Chart(`chart-${section}`, config)
         }
         }
diff --git a/wcsudat/surveys/static/surveys/home.js b/wcsudat/surveys/static/surveys/home.js
index ddc54382faee032b50f2d1b40e7d93e364846330..667ef01a029f6a44a160bca4f1e0d53a06682ef6 100644
--- a/wcsudat/surveys/static/surveys/home.js
+++ b/wcsudat/surveys/static/surveys/home.js
@@ -1,3 +1,6 @@
+/**
+ * Creates a csrf cookie
+ */
 function getCookie(name) {
     var cookieValue = null;
     if (document.cookie && document.cookie !== '') {
@@ -15,10 +18,11 @@ function getCookie(name) {
   }
 var csrftoken = getCookie('csrftoken');
 
-// console.log(clinician)
+// This stores the snapshot for the client list and the selected client
 var list_snapshot = []
-
 var selectedClient = null
+
+// Input elements for the client edit/create
 var clientFormWrapper = document.getElementById('client-form-wrapper')
 var clientFormHeader = document.getElementById('client-form-header')
 var firstname = document.getElementById('name-input')
@@ -35,12 +39,12 @@ var education = document.getElementById('education-input')
 var police = document.getElementById('police-input')
 var clientForm = document.getElementById('client-form')
 
-
+// Activate all tooltips
 $(document).ready(function(){
     $('[data-toggle="tooltip"]').tooltip(); 
 });                
                 
-                
+// Control elements for the client panel as well as feedback element               
 var saveButton = document.getElementById('save-client')
 var editButton = document.getElementById('edit-client')
 var newSurveyButton = document.getElementById('new-survey')
@@ -52,6 +56,8 @@ var feedBackSubmitButton = document.getElementById('feedback-submit')
 
 var searchInput = document.getElementById('client-search-input')
 var searchText = ""
+
+// Add relevent event listeners
 searchInput.addEventListener('keyup', (function(item){
     return function(e){
         searchText = searchInput.value
@@ -116,29 +122,38 @@ feedBackSubmitButton.addEventListener('click', (function(item){
     }
 })())
 
-
+// Initialise the page by building a client list
 buildList()
 
+// Start the client panel in the new client state
 newClient()
 
-
+// Create a toast element for the feedback element and get the form
 const feedbackToast = document.getElementById('feedback-toast')
 const toast = new bootstrap.Toast(feedbackToast)
 
 const feedBackForm = document.getElementById('feedback-form')
 
-
+/**
+ * Show the feedback input toast
+ */
 function showFeedbackToast(){
     toast.show()
     feedBackButton.style.display = "none"
 }
 
+/**
+ * Hide the feedback input toast
+ */
 function hideFeedbackToast(){
     setTimeout(function() {
         feedBackButton.style.display = "block"
     }, 150);
 }
 
+/**
+ * Post the feedback to the database with the clinician as the user
+ */
 function submitFeedback(){
     var feedbackInput = document.getElementById('feedback-input')
     var url = `http://127.0.0.1:8000/surveys/api/feedback-create/`
@@ -157,7 +172,9 @@ function submitFeedback(){
     })
 }
 
-
+/**
+ * Build a list of client cards
+ */
 function buildList(){
     var wrapper = document.getElementById('list-wrapper')
     //wrapper.innerHTML = ''
@@ -172,6 +189,7 @@ function buildList(){
 
       var list = data
     var searchList = []
+    // Create a list of clients that match the search query
     for (var i in list){
         var found = searchText.trim()===""
         for(var k in searchValues){
@@ -196,6 +214,7 @@ function buildList(){
             searchList.push(list[i])
     }
     list = searchList
+    // Build the list of clients
     for (var i in list){
         try{
             document.getElementById(`client-row-${i}`).remove()
@@ -207,6 +226,7 @@ function buildList(){
         var risk_amnt = list[i].overall_risk
         if(!list[i].overall_risk)
             risk_amnt = 0
+        // This gives a color gradient depending on the client risk amount
         var colours_list = [
             // TODO Improve this color gradient
             "#9c0909",
@@ -217,7 +237,7 @@ function buildList(){
             
         var index = (colours_list.length-1)-Math.round(risk_amnt*(colours_list.length-1)) 
         var colour = colours_list[index]
-        // console.log(risk_amnt, index)
+        // This gives different icons depending on the client risk amount
         var icon_list = [
             `<i class="bi bi-chevron-double-up" style="color: ${colour}"></i>`,
             `<i class="bi bi-chevron-up" style="color: ${colour}"></i>`,
@@ -226,7 +246,9 @@ function buildList(){
         ]
         var icon_index = (icon_list.length-1)-Math.round(risk_amnt*(icon_list.length-1))
         var icon = icon_list[icon_index]
+        // Create a list entry with a button to view the surveys, create a new survey and edit the client
         if(selectedClient == list[i].id){
+            // These buttons are active
             item = `<div class="btn-group m-1 client-row-item" id="client-row-${i}" role="group" aria-label="client-row-${i}">
             <button type="button" class="btn btn-outline-primary text-start client-view-item"
             data-toggle="tooltip" data-placement="top" title="View Client Assessments"
@@ -234,7 +256,7 @@ function buildList(){
 
             <button type="button" class="btn btn-outline-primary new-survey-item"
             data-toggle="tooltip" data-placement="top" title="Start New Assessment"
-            ><i class="bi bi-book" aria-hidden="true"></i></button>
+            ><i class="bi bi-journal-plus" aria-hidden="true"></i></button>
 
             <button type="button" class="btn btn-outline-primary client-edit-item"
             data-toggle="tooltip" data-placement="top" title="Toggle Edit"
@@ -250,7 +272,7 @@ function buildList(){
 
                 <button type="button" class="btn btn-outline-dark new-survey-item"
                 data-toggle="tooltip" data-placement="top" title="Start New Assessment"
-                ><i class="bi bi-book" aria-hidden="true"></i></button>
+                ><i class="bi bi-journal-plus" aria-hidden="true"></i></button>
 
                 <button type="button" class="btn btn-outline-dark client-edit-item"
                 data-toggle="tooltip" data-placement="top" title="Toggle Edit"
@@ -269,7 +291,7 @@ function buildList(){
     }
 
     list_snapshot = list
-
+    // Add event listeners to each button for view surveys, new survey and edit client
     for (var i in list){
         var answerField = document.getElementsByClassName('new-survey-item')[i]
         answerField.addEventListener('click', (function(item){
@@ -294,6 +316,7 @@ function buildList(){
         var answerField = document.getElementsByClassName('client-edit-item')[i]
         answerField.addEventListener('click', (function(item){
             return function(e){
+                // Toggle between edit and new client
                 if(selectedClient != item.id){
                     selectedClient = item.id
                     getClient(item)
@@ -308,7 +331,7 @@ function buildList(){
             }
         })(list[i]))
     }
-    
+    // Re-activate tooltips
     var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
     var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
         return new bootstrap.Tooltip(tooltipTriggerEl)
@@ -316,7 +339,9 @@ function buildList(){
         })
     }
 
-//--------Function to populate the client details pane with selected clients details---------------------------------	
+/**
+ * Populate the client details pane with selected clients details
+ */	
 function getClient(item){ 
     // console.log(item)
     selectedClient = item.id
@@ -342,6 +367,9 @@ function getClient(item){
     buildList()
 }
 
+/**
+ * Set the panel mode to new client
+ */	
 function newClient(){
     selectedClient = null
     clientFormHeader.innerHTML = `<h4><div class="container" id="new-user-button" data-toggle="tooltip" data-placement="left" title="Add a New Client">
@@ -356,6 +384,9 @@ function newClient(){
     showDetails()
 }
 
+/**
+ * Set the panel mode to edit client
+ */	
 function editClient(){
     console.log(selectedClient)
     var form_controls = document.querySelectorAll('.client-form-control')
@@ -377,6 +408,9 @@ function editClient(){
     
 }
 
+/**
+ * Delete the client on the database
+ */	
 function deleteClient(){
     if(selectedClient){
         var url = `http://127.0.0.1:8000/surveys/api/client-delete/${selectedClient}/`
@@ -395,6 +429,9 @@ function deleteClient(){
     }
 }
 
+/**
+ * Update or save a client on the database
+ */	
 function saveClient(){
 
     if(selectedClient){
@@ -439,25 +476,30 @@ function saveClient(){
     })
 }
 
+/**
+ * Start a new assessment for the selected client
+ */	
 function newSurvey(){
     window.location.href = `/surveys/new-survey/${selectedClient}/`
 }
 
+/**
+ * View assessments for the selected client
+ */
 function viewSurveys(){
     window.location.href = `/surveys/view-surveys/${selectedClient}/`
 }
 
+/**
+ * Show the client panel
+ */
 function showDetails(){
     
-    if(clientFormWrapper.className == "visible container"){
-        clientFormWrapper.className = "invisible container"
-    }
-    else{
-        clientFormWrapper.className = "visible container"
-    }
+    // Show the panel
     clientFormWrapper.className = "visible container"
     var form_controls = document.querySelectorAll('.client-form-control')
     var form_controls_select = document.querySelectorAll('.client-form-control-select')
+    // Disable editting by default when a client is selected
     if(selectedClient){
         form_controls.forEach((form_control) => {
             form_control.setAttribute('readonly', true)
@@ -479,6 +521,4 @@ function showDetails(){
     var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
         return new bootstrap.Tooltip(tooltipTriggerEl)
     })
-}
-// TODO Client Create/Edit Form
-// TODO Change API for survey to use a client id
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/wcsudat/surveys/static/surveys/researcher.js b/wcsudat/surveys/static/surveys/researcher.js
index e31cba745796f9392d60ba1ea293d62719ff91d5..35529f8900afd79db39ade4715bb5638ce0c79ef 100644
--- a/wcsudat/surveys/static/surveys/researcher.js
+++ b/wcsudat/surveys/static/surveys/researcher.js
@@ -1,3 +1,6 @@
+/**
+ * Creates a csrf cookie
+ */
 function getCookie(name) {
     var cookieValue = null;
     if (document.cookie && document.cookie !== '') {
@@ -16,7 +19,9 @@ function getCookie(name) {
 var csrftoken = getCookie('csrftoken');
 
 var activeTable = "full-summary"
+// These are the possible database tables which can be accessed
 var tables = {
+    "full-summary": "Full Summary",
     "answer": "Answers",
     "choice": "Choices",
     "risk": "Risks",
@@ -26,23 +31,27 @@ var tables = {
     "section": "Sections",
     "choicequestion-risk": "Choice Question Risks",
     "choicequestion-choice": "Choice Question Choices",
-    "full-summary": "Full Summary",
 }
+
+// Initialise the page by building the selected table and navigation
 buildTable()
 buildNav()
 
+/**
+ * Build a navigation bar with different tables as well as the full summary tab
+ */
 function buildNav(){
     var wrapper = document.getElementById('nav-wrapper')
     wrapper.innerHTML = ""
-    if(activeTable != 'full-summary')
-        wrapper.innerHTML += `<a href="http://127.0.0.1:8000/surveys/api/csv/${activeTable}/"">Download CSV</a>`
     for(var table in tables){
-        var button = `<button id="nav-button-${table}" class="nav-button btn btn-secondary">${tables[table]}</button>`
+        var button = `<button id="nav-button-${table}" class="nav-button btn btn-secondary m-1">${tables[table]}</button>`
         if(table == activeTable){
-            button = `<button id="nav-button-${table}" class="nav-button btn btn-primary">${tables[table]}</button>`
+            button = `<button id="nav-button-${table}" class="nav-button btn btn-primary m-1">${tables[table]}</button>`
         }
         wrapper.innerHTML += button
     }
+    if(activeTable != 'full-summary')
+        wrapper.innerHTML += `<a href="http://127.0.0.1:8000/surveys/api/csv/${activeTable}/"">Download CSV</a>`
     for(var table in tables){
         var tableButton = document.getElementById(`nav-button-${table}`)
         tableButton.addEventListener('click', (function(item){
@@ -52,19 +61,33 @@ function buildNav(){
         })(table))
     }
 }
-function updateActiveTable(item){
-    activeTable = item
+
+/**
+ * Set the active table to the given table
+ */
+function updateActiveTable(table_name){
+    activeTable = table_name
     buildTable()
     buildNav()
 }
 // TODO Fixed navigation position
 // TODO List replacement for table creation to remove glitches caused by scrollbar appearing
 // or maybe have scrollbar always shown
+
+/**
+ * Build a table for the active table
+ */
 function buildTable(){
     var header_row = document.getElementById('fields')
     var wrapper = document.getElementById('summary-wrapper')
     var table_rows = document.getElementById('table-rows')
-    header_row.innerHTML = ""
+    // Show a loading spinner while we wait for the api request to complete
+    header_row.innerHTML = `
+    <div class="d-flex justify-content-center" id="list-spinner">
+        <div class="spinner-border" role="status">
+        <span class="visually-hidden">Loading...</span>
+        </div>
+    </div>`
     table_rows.innerHTML = ""
     wrapper.innerHTML = ""
     if(activeTable == 'full-summary'){
@@ -80,11 +103,23 @@ function buildTable(){
         var list = data
         console.log(data)
         var text = ""
+        header_row.innerHTML = ""
+        if(list.length === 0){
+            header_row.innerHTML = "<h2>No data to display.</h2>"
+            return
+        }
+
+        // Build the table header row
         for (var i in list[0]){
+            // Replace underscore followed by a lowercase letter with a space followed by the uppercase letter
+            // This converts from snake_case to spaced camelCase
+            // The first letter is then capitalised
+            // e.g. risk_group -> Risk Group
             var title = i.replace(/_([a-z])/g, function (g) { return ' ' + g[1].toUpperCase(); });
             title = title[0].toUpperCase() + title.substring(1)
             header_row.innerHTML += `<th scope="col">${title}</th>`
         }
+        // Build the body with the data
         for (var i in list){
             text += "<tr>"
             for (var k in list[i]){
@@ -108,6 +143,9 @@ function buildTable(){
     })
 }
 
+/**
+ * Build the summary
+ */
 function buildSummary(){
     var wrapper = document.getElementById('summary-wrapper')
     var url = `http://127.0.0.1:8000/surveys/api/summary/`
@@ -115,7 +153,10 @@ function buildSummary(){
     .then((resp) => resp.json())
     .then(function(data){
         var sections = data
+        wrapper.innerHTML = ""
         for(var section in sections){
+            // Display the section header and text as well as the subsection header
+            // If they are equal only display the section header
             wrapper.innerHTML += `<h2>${sections[section].name}</h2>`
             wrapper.innerHTML += `<h3>${sections[section].text}</h3>`
             var subsections = sections[section].subsections
@@ -130,14 +171,14 @@ function buildSummary(){
                     wrapper.innerHTML += `<h4>${questions[question].name}</h4>`
                     var bar = ``
                     var choices = questions[question].choices
-                    var mn = 0
-                    var mx = 0
+                    // Calculate the total answers for the question
+                    var total = 0
                     for(var choice in choices){
-                        if(choices[choice].votes > mx)
-                            mx = choices[choice].votes
+                        total += choices[choice].votes
                     }
                     for(var choice in choices){
-                        var pcnt = 100*choices[choice].votes/mx
+                        // Calculate the percentage of the total answers for each choice and display them
+                        var pcnt = 100*choices[choice].votes/total
                         bar += `<p>${choices[choice].name}</p><div class="progress">
                             <div class="progress-bar" role="progressbar" style="width: ${pcnt}%" 
                             aria-valuenow="${pcnt}" aria-valuemin="0" aria-valuemax="100">${choices[choice].votes}</div>
diff --git a/wcsudat/surveys/static/surveys/transcription.js b/wcsudat/surveys/static/surveys/transcription.js
index a1a020198f6cbf8c0db59152ca0dd2a79a30d3d8..5a4524cc2246ac746c4350ec4b04109a44fbc459 100644
--- a/wcsudat/surveys/static/surveys/transcription.js
+++ b/wcsudat/surveys/static/surveys/transcription.js
@@ -1,4 +1,7 @@
-function getCookie(name) {
+/**
+ * Creates a csrf cookie
+ */
+ function getCookie(name) {
     var cookieValue = null;
     if (document.cookie && document.cookie !== '') {
         var cookies = document.cookie.split(';');
@@ -14,6 +17,11 @@ function getCookie(name) {
     return cookieValue;
 }
 var csrftoken = getCookie('csrftoken');
+
+// These variables are used to store the state of the assessment locally to prevent extra api calls
+// The snapshot lists are used to allow smooth re-rendering of the html as items in the list are replaced
+// instead of having to rebuild the entire list from scratch.
+// If the current list is longer than the old list then the rest of the elements in the old list are removed
 var activeItem = null
 var list_snapshot = {}
 var all_answers = {}
@@ -23,13 +31,11 @@ var all_subsections = []
 var active_subsection = null
 var risk_dict = {}
 
-
+// Here we instantiate some events and components
 const scrollSpy = new bootstrap.ScrollSpy(document.getElementById('survey-wrapper'), {
     target: '#nav-wrapper',
     // rootMargin: "0px 0px -80% 0px"
 })
-
-
 var popup = document.getElementById("submit-popup")
 var popupClose = document.getElementById("popup-close")
 window.onclick = function(event) {
@@ -40,16 +46,20 @@ window.onclick = function(event) {
 popupClose.onclick = function() {
     popup.style.display = "none"
 }
+
+// Calling this function starts the chain of functions used to build the initial assessment page
 getSurvey()
 
+/**
+ * Fetch a list of subsection answers in the active assessment from the database
+ */
 function getSurvey(){
-    // Fetch all subsection answers
     var url = `http://127.0.0.1:8000/surveys/api/sub-answer-list/${client_id}/${survey}/`
     fetch(url)
     .then((resp) => resp.json())
     .then(function(data){
         all_subsections = data
-        // Could initialise all_answers here
+        // Create entries in the dictionary for each subsection to store a list of answers later on
         for(var i in all_subsections)
             list_snapshot[all_subsections[i].subsection_detail.id] = []
         getAnswers()
@@ -58,8 +68,10 @@ function getSurvey(){
     
 }
 
+/**
+ * Fetch a list of answers in the active assessment from the database
+ */
 function getAnswers(){
-    // Fetch all answers
     var url = `http://127.0.0.1:8000/surveys/api/full-answer-list/${client_id}/${survey}/`
     fetch(url)
     .then((resp) => resp.json())
@@ -68,7 +80,9 @@ function getAnswers(){
         
         for(var i in data){
             var id = data[i].subsection_answer_detail.subsection_detail.id
-            
+            // Store each answer in the dictionary grouped by subsection
+            // Each answer is also given a list index
+            // This data structure allows quick access to answer objects
             if(all_answers[id]){
                 all_answers[id].push(data[i])
                 data[i]['list_index'] = all_answers[id].length-1
@@ -82,9 +96,13 @@ function getAnswers(){
         calculateRisks()
     })
 }
-
+/**
+ * Create a dictionary of risks and calculate the total risk amount for the active assessment
+ */
 function calculateRisks(){
     risk_dict = {}
+    // Here we loop through each subsection and all of the choice answers in each one and
+    // calculate the total amount of risk for each risk type
     for(var k in all_subsections){
         var id = all_subsections[k].subsection_detail.id
         if(all_answers[id] === null)
@@ -107,6 +125,9 @@ function calculateRisks(){
     buildWrappers() 
 }
 
+/**
+ * Return a list of subsections that aren't currently locked by a risk level requirement
+ */
 function getActiveSubsectionList(){
     var list = []
     for(var i in all_subsections){
@@ -121,7 +142,9 @@ function getActiveSubsectionList(){
     return list
 }
 
-// Build all wrappers for active subsections and then call functions to build headers and lists in each
+/**
+ * Build all wrappers for active subsections and then call functions to build headers and lists in each
+ */
 function buildWrappers(){
     var wrapper = document.getElementById('survey-wrapper')
     
@@ -161,11 +184,15 @@ function buildWrappers(){
     wrapper_list_snapshot = list
     buildLists(list)
     buildNav()
+    // Refresh the scrollspy to resync all of the attached elements 
     scrollSpy.refresh()
     
     
 }
 
+/**
+ * Call functions to build lists of answers and headers in each wrapper
+ */
 function buildLists(active_subsections)
 {
     for(var i in active_subsections){
@@ -176,6 +203,9 @@ function buildLists(active_subsections)
     }
 }
 
+/**
+ * Build a navigation list to navigate between subsections
+ */
 function buildNav(){
     var wrapper = document.getElementById('nav-wrapper')
     
@@ -194,7 +224,6 @@ function buildNav(){
         var icon = ''
         if(subsection.icon)
             icon = `<i class="bi bi-${subsection.icon}" style="font-size: x-large;"></i>`
-        console.log(subsection)
         if(list[i].complete){
             complete_icon = `<i class="bi bi-check" style="font-size: x-large;"></i>`
             button = `<a id="nav-button-${i}" class="list-group-item list-group-item-action" 
@@ -214,11 +243,14 @@ function buildNav(){
             document.getElementById(`nav-button-${i}`).remove()
         }
     }
-
+    
     nav_list_snapshot = list
     
 }
 
+/**
+ * Build the header for a given subsection with the section and subsection details
+ */
 function buildHeader(item, active_subsections){
 
     var wrapper = document.getElementById(`header-wrapper-${item}`)
@@ -249,6 +281,10 @@ function buildHeader(item, active_subsections){
     
 
 }
+
+/**
+ * Build the clinician notes input for a given subsection
+ */
 function buildNotes(subsection_index){
 
 
@@ -273,10 +309,15 @@ function buildNotes(subsection_index){
 
 }
 
+/**
+ * Build a list of questions and answer inputs for a given subsection
+ */
 function buildList(subsection_index, active_subsections){
     var wrapper = document.getElementById(`list-wrapper-${subsection_index}`)
     var list = []
     var id = active_subsections[subsection_index].subsection_detail.id
+    // We first create a list of answers in a subsection that should not be hidden by 
+    // risk level requirements by checking that their requirement has been met
     for(var i in all_answers[id]){
         var answer = all_answers[id][i]
         var required = null
@@ -298,14 +339,17 @@ function buildList(subsection_index, active_subsections){
             }catch(err){
 
             }
-            var title = `<span class="title" id="data-row-${list[i].id}-title">${list[i].text}</span>`
+            // Create the question text
+            var title = `<span class="title" id="data-row-${list[i].id}-title">${parseInt(i)+1}. ${list[i].text}</span>`
             if (!list[i].choice_set_question)
             {
+                // Create the answer input for a text question
                 var answer = `<input id="data-row-${list[i].id}-answer" value="${list[i].text_answer}" class="answer-${id}" type="text submit" readonly >`
             }
             else
             {
                 var answer = `<div id="data-row-${list[i].id}-choice-answer" class="answer-${id} choice-wrapper d-flex justify-content-between">`
+                // Create the choice buttons for a choice question
                 for (var k in list[i].choice_set_question.choice_set)
                 {
                     var choice = list[i].choice_set_question.choice_set[k]
@@ -315,7 +359,6 @@ function buildList(subsection_index, active_subsections){
                     answer += `<label id="data-row-${id}-${i}-choice-${choice.id}-label"
                                 for="data-row-${id}-${i}-choice-${choice.id}-answer">${choice.choice_text}<br><br>${icon}`
                     answer += `<input class="d-none" id="data-row-${id}-${i}-choice-${choice.id}-answer" value="${choice.id}" name="choice-answer-${list[i].id}" type="radio"`
-                    // TODO change button fill as soon as it is clicked and then post data then re-render to synchronise with datastore
                     if(choice.id == list[i].choice_answer)
                     {	
                         answer += 'checked=""'
@@ -325,6 +368,7 @@ function buildList(subsection_index, active_subsections){
                 answer+="</div>"
             }
             
+            // Create the full question item
             var item = `
                 <div id="data-row-${id}-${i}" class="question-wrapper container">
                     <div class="container">
@@ -348,67 +392,12 @@ function buildList(subsection_index, active_subsections){
         }
 
         list_snapshot[id] = list
-
-        for (var i in list){
-            var answerField = document.getElementsByClassName(`answer-${id}`)[i]
-            if(answerField.id.includes('choice'))
-            {
-                answerField.addEventListener('click', (function(item){
-                return function(e){
-                    if(e.target.value)
-                        updateChoiceAnswer(item)
-                }
-                })(list[i]))
-                answerField.addEventListener('keypress', (function(item){
-                return function(e){
-                    if(e.target.value && e.key === 'Enter')
-                        updateChoiceAnswer(item)
-                }
-                })(list[i]))
-            }
-            else{
-                answerField.addEventListener('change', (function(item){
-                    return function(e){             
-                        updateAnswer(item)
-                    }
-                })(list[i]))
-            }
-            
-
-
-        }
-
-    
 }
-function submitSurvey(){
-    var url = `http://127.0.0.1:8000/surveys/api/sub-answer-list/${client_id}/${survey}/`
-    
-    
-    fetch(url)
-    .then((resp) => resp.json())
-    .then(function(data){
-        var list = data
-        var complete = true
-        var alert_text = "<p>Please complete the following subsections</p>"
-        console.log("Submit Data: ", list)
-        for (var i in list){
-            if(!list[i].complete){
-                complete = false
-                alert_text += `<p>${list[i].subsection_detail.subsection_name}</p>`
-            }
-        }
-        if(!complete){
-            var popup_wrapper = document.getElementById('submit-popup-content-wrapper')
-            popup_wrapper.innerHTML = alert_text
-            popup.style.display = "block"
-            console.log("Popup")
-        }
-        else{
-            window.location.href = `/surveys/submit-survey/${client_id}/${survey}/`
-        }
 
-    })
-}
+
+/**
+ * This function updates the clinician notes for the given subsection on the database
+ */
 function updateNotes(item, subsection_index){
     var active_subsections = getActiveSubsectionList()
     var id = active_subsections[subsection_index].id
@@ -428,57 +417,3 @@ function updateNotes(item, subsection_index){
         
     })
 }
-
-
-function updateAnswer(item){
-    var url = `http://127.0.0.1:8000/surveys/api/answer-update/${item.id}/`
-    var new_answer = document.getElementById(`data-row-${item.id}-answer`).value
-    fetch(url, {
-        method:'POST',
-        headers:{
-            'Content-type':'application/json',
-            'X-CSRFToken':csrftoken,
-        },
-        body:JSON.stringify({'text_answer':new_answer})
-    }
-    ).then(function(response){
-        
-        fetchAnswer(item)
-        
-    })
-}
-
-function updateChoiceAnswer(item){
-    var url = `http://127.0.0.1:8000/surveys/api/answer-update/${item.id}/`
-    var new_answer = document.querySelector(`input[name="choice-answer-${item.id}"]:checked`).value
-    // This code was to be used to set the button to filled as soon as it's clicked but it seems like it happens instantly already
-    // var id = item.subsection_answer_detail.subsection_detail.id
-    // var i = item.list_index
-    // var choice_id = item.choice_answer
-    // console.log(item)
-    // console.log(`data-row-${id}-${i}-choice-${choice_id}-label`)
-    // 
-    // console.log(document.getElementById(`data-row-${id}-${i}-choice-${choice_id}-label`).innerHTML)
-    fetch(url, {
-        method:'POST',
-        headers:{
-            'Content-type':'application/json',
-            'X-CSRFToken':csrftoken,
-        },
-        body:JSON.stringify({'choice_answer':new_answer})
-    }
-    ).then(function(response){
-        fetchAnswer(item)
-    })
-}
-
-function fetchAnswer(item){
-    var url = `http://127.0.0.1:8000/surveys/api/answer-detail/${item.id}/`
-    fetch(url)
-    .then((resp) => resp.json())
-    .then(function(data){
-        all_answers[item.subsection_answer_detail.subsection_detail.id][item.list_index] = data
-        all_answers[item.subsection_answer_detail.subsection_detail.id][item.list_index]['list_index'] = item.list_index
-        calculateRisks()
-    })
-}
diff --git a/wcsudat/surveys/templates/surveys/assessment.html b/wcsudat/surveys/templates/surveys/assessment.html
index cc242abd6aad848552c31dd27bda18025cb22198..7fdb4b2616e2c97c63299de37157b6b014f32bcb 100644
--- a/wcsudat/surveys/templates/surveys/assessment.html
+++ b/wcsudat/surveys/templates/surveys/assessment.html
@@ -6,8 +6,8 @@
 	<nav id="page-nav" aria-label="breadcrumb">
 		<ol class="breadcrumb welcome">
 			  <li class="breadcrumb-item"><a href = "{% url 'surveys:home' %}" ><i class="bi bi-house-fill homebutton" aria-hidden="true" type="submit"></i></a></li>
-			  <li class="breadcrumb-item" aria-current="page"><a href = "{% url 'surveys:client' client.id %}" ><i class="bi bi-person" aria-hidden="true"></i></a></li>
-			  <li class="breadcrumb-item bcactive" aria-current="page"><a href = "{% url 'surveys:client' client.id %}" ></a>Assessment for {{ client.name }} {{ client.surname }}</li>
+			  <li class="breadcrumb-item" aria-current="page"><a href = "{% url 'surveys:client' client.id %}" ><i class="bi bi-journals" aria-hidden="true"></i></a></li>
+			  <li class="breadcrumb-item bcactive" aria-current="page"><a href = "{% url 'surveys:client' client.id %}" ></a><i class="bi bi-journal-plus" aria-hidden="true"></i> Assessment for {{ client.name }} {{ client.surname }}</li>
 		</ol>
 	</nav> 
 	<form method="post" action = "{% url 'logout' %}">
diff --git a/wcsudat/surveys/templates/surveys/client.html b/wcsudat/surveys/templates/surveys/client.html
index d73d8a0fe6cc9c077a94a92101fddb817f6a388e..4feaa715d9a86eec2e138acc58dc09f3e2a69bfa 100644
--- a/wcsudat/surveys/templates/surveys/client.html
+++ b/wcsudat/surveys/templates/surveys/client.html
@@ -17,8 +17,8 @@
   	<body>
 		<nav id="page-nav" aria-label="breadcrumb">
 			<ol class="breadcrumb welcome">
-				<li class="breadcrumb-item"><a href = "{% url 'surveys:home' %}" ><i class="bi bi-house-fill" aria-hidden="true" type="submit"></i></a></li>
-				<li class="breadcrumb-item bcactive" aria-current="page">{{ client.name }} {{ client.surname }}</li>
+				<li class="breadcrumb-item"><a href = "{% url 'surveys:home' %}" ><i class="bi bi-house-fill homebutton" aria-hidden="true" type="submit"></i></a></li>
+				<li class="breadcrumb-item bcactive" aria-current="page"><i class="bi bi-journals" aria-hidden="true"></i> Assessments for {{ client.name }} {{ client.surname }}</li>
 			</ol>
 		</nav> 
 			<form method="post" action = "{% url 'logout' %}">
@@ -45,8 +45,8 @@
 		<div class="container-fluid all-content">
 			
 			<div class="container survey-container">
-				<button class="btn btn-primary" id="new-survey" data-toggle="tooltip" data-placement="top" title="New Survey">
-					<i class="bi bi-book" aria-hidden="true"></i>
+				<button class="btn btn-primary" id="new-survey" data-toggle="tooltip" data-placement="top" title="New Assessment">
+					<i class="bi bi-journal-plus" aria-hidden="true"></i>
 				</button>
 				<div class="list-group" id="list-wrapper">
 					<div class="d-flex justify-content-center" id="list-spinner">
diff --git a/wcsudat/surveys/templates/surveys/home.html b/wcsudat/surveys/templates/surveys/home.html
index 19b5ed4c1b53fd4b13663c9bf61568657808b23a..39a9a3eece49be00dc2d068aaf6fcbd3285ae888 100644
--- a/wcsudat/surveys/templates/surveys/home.html
+++ b/wcsudat/surveys/templates/surveys/home.html
@@ -498,7 +498,7 @@
 						<i class="bi bi-save" aria-hidden="true"></i>
 					</button>
 					<button type="button" class="btn btn-primary" id="edit-client">Edit</button>
-					<button type="button" class="btn btn-primary" id="new-survey">New Survey</button>
+					<button type="button" class="btn btn-primary" id="new-survey">New Assessment</button>
 					<button type="button" class="btn btn-primary" id="view-surveys">View Surveys</button>
 					<button type="button" class="btn btn-danger" id="delete-client">Delete</button>
 				</div>
diff --git a/wcsudat/surveys/templates/surveys/researcher.html b/wcsudat/surveys/templates/surveys/researcher.html
index f9ddb8e4ce2be0af58fa9874ebcdae93669099d5..667738614ed80c7b392a12c161c72530b09a8623 100644
--- a/wcsudat/surveys/templates/surveys/researcher.html
+++ b/wcsudat/surveys/templates/surveys/researcher.html
@@ -16,7 +16,7 @@
     </form>
 
     <div class = "container-fluid all-content d-flex flex-row w-100 mw-100">
-        <div class="container-fluid d-flex flex-column position-fixed" id="nav-wrapper">
+        <div class="container-fluid d-flex flex-column position-fixed p-3" id="nav-wrapper">
 
         </div>
         <div class="container m-200 padding-left:300px;" id="data-wrapper">
diff --git a/wcsudat/surveys/templates/surveys/subsection.html b/wcsudat/surveys/templates/surveys/subsection.html
index 40c907da484438d8c5b807011eef8ca67c5eb6e5..4ce07c153160e2fdf5c974c95e28c7354836d0d0 100644
--- a/wcsudat/surveys/templates/surveys/subsection.html
+++ b/wcsudat/surveys/templates/surveys/subsection.html
@@ -2,7 +2,7 @@
 {% block title %}Survey{% endblock %}
 {% block content %}
 {% if user.is_authenticated %}
-<p><a href="{% url 'surveys:survey' %}">New Survey</a></p>
+<p><a href="{% url 'surveys:survey' %}">New Assessment</a></p>
 <h1>{{ section.section_name }}</h1>
 <h2>{{ section.section_text }}</h2>
 {% if subsection.subsection_name != section.section_name %}
diff --git a/wcsudat/surveys/templates/surveys/transcription.html b/wcsudat/surveys/templates/surveys/transcription.html
index ad537d562c90f6d72f7d38b8e2f6689e35615a62..63b7d75c3ddbd6600bdf8e118ba857fa4676d048 100644
--- a/wcsudat/surveys/templates/surveys/transcription.html
+++ b/wcsudat/surveys/templates/surveys/transcription.html
@@ -7,8 +7,8 @@
 	<nav id="page-nav" aria-label="breadcrumb">
 		<ol class="breadcrumb welcome">
 			  <li class="breadcrumb-item"><a href = "{% url 'surveys:home' %}" ><i class="bi bi-house-fill homebutton" aria-hidden="true" type="submit"></i></a></li>
-			  <li class="breadcrumb-item" aria-current="page"><a href = "{% url 'surveys:client' client.id %}" ><i class="bi bi-person" aria-hidden="true"></i></a></li>
-			  <li class="breadcrumb-item bcactive" aria-current="page">Previous assessment for {{ client.name }} {{ client.surname }}</li>
+			  <li class="breadcrumb-item" aria-current="page"><a href = "{% url 'surveys:client' client.id %}" ><i class="bi bi-journals" aria-hidden="true"></i></a></li>
+			  <li class="breadcrumb-item bcactive" aria-current="page"><i class="bi bi-journal" aria-hidden="true"></i> Previous assessment for {{ client.name }} {{ client.surname }}</li>
 
 		</ol>
 	</nav> 
diff --git a/wcsudat/surveys/tests.py b/wcsudat/surveys/tests.py
index 8ecbe1fd2c4dd6c09f9b092882be5b0b72236b3b..28c3d1bcebdbf786de92e733c8df7be60168e095 100644
--- a/wcsudat/surveys/tests.py
+++ b/wcsudat/surveys/tests.py
@@ -13,7 +13,9 @@ class RiskModelTests(TestCase):
     and that the correct error messages are displayed
     '''
     def test_long_fields(self):
-        risk = Risk(risk_category = "a"*201, risk_explanation = "a"*2001)
+        risk_group = RiskGroup(group_name="Test")
+        risk_group.save()
+        risk = Risk(risk_category = "a"*201, risk_explanation = "a"*2001, risk_group = risk_group)
         with self.assertRaises(ValidationError) as e:
             risk.full_clean()
         self.assertEqual(str(e.exception),  
@@ -28,13 +30,15 @@ class RiskModelTests(TestCase):
     and that the correct error messages are displayed
     '''
     def test_empty_fields(self):
-        risk = Risk(risk_category = '', risk_explanation = '')
+        risk = Risk(risk_category = '', risk_explanation = '', risk_group = None)
         with self.assertRaises(ValidationError) as e:
             risk.full_clean()
         self.assertEqual(str(e.exception), 
         str({'risk_category': 
             ['This field cannot be blank.'], 
         'risk_explanation': 
+            ['This field cannot be blank.'], 
+        'risk_group': 
             ['This field cannot be blank.']}))
 
     '''
@@ -42,14 +46,71 @@ class RiskModelTests(TestCase):
     and that the correct error messages are displayed
     '''
     def test_null_fields(self):
-        risk = Risk(risk_category = None, risk_explanation = None)
+        risk = Risk(risk_category = None, risk_explanation = None, risk_group = None)
         with self.assertRaises(ValidationError) as e:
             risk.full_clean()
         self.assertEqual(str(e.exception), 
         str({'risk_category': 
             ['This field cannot be null.'], 
         'risk_explanation': 
-            ['This field cannot be null.']}))
+            ['This field cannot be null.'], 
+        'risk_group': 
+            ['This field cannot be blank.']}))
+
+
+    def test_set_min_max(self):
+        risk0 = Risk(risk_category = "Test", risk_explanation="Test")
+        risk1 = Risk(risk_category = "Test", risk_explanation="Test")
+        risk0.save()
+        risk1.save()
+
+        cq0 = ChoiceQuestion(question_text="Test")
+        cq1 = ChoiceQuestion(question_text="Test")
+        cq2 = ChoiceQuestion(question_text="Test")
+        cq3 = ChoiceQuestion(question_text="Test")
+        cq4 = ChoiceQuestion(question_text="Test")
+        cq0.save()
+        cq1.save()
+        cq2.save()
+        cq3.save()
+        cq4.save()
+
+
+        c0 = Choice(risk_amount=0)
+        c1 = Choice(risk_amount=1)
+        c2 = Choice(risk_amount=2)
+        c3 = Choice(risk_amount=3)
+        c4 = Choice(risk_amount=5)
+        c0.save()
+        c1.save()
+        c2.save()
+        c3.save()
+        c4.save()
+
+        cq0.choices.add(c0, c1, c2, c3, c4)
+        cq1.choices.add(c1, c2, c3)
+        cq2.choices.add(c3, c4)
+        cq3.choices.add(c1, c2)
+
+        cq0.risks.add(risk0)
+        cq1.risks.add(risk1)
+        cq2.risks.add(risk0, risk1)
+        cq4.risks.add(risk0)
+
+        cq0.save()
+        cq1.save()
+        cq2.save()
+        cq3.save()
+        cq4.save()
+        
+        risk0.set_min_max()
+        risk1.set_min_max()
+
+        self.assertEqual(risk0.minimum, 3)
+        self.assertEqual(risk0.maximum, 10)
+        self.assertEqual(risk1.minimum, 4)
+        self.assertEqual(risk1.maximum, 8)
+
 
 class RiskLevelModelTests(TestCase):
     pass
@@ -125,25 +186,6 @@ class SubsectionModelTests(TestCase):
         # The ordering should be "section order"."subsection order"
         self.assertEqual(subsection0.ordering(), "1.5")
 
-    '''
-    This tests that the risk category for the risk associated with a Choice Question
-    is correctly returned by the function
-    '''
-    def test_risk_factors(self):
-        # Create two risk objects with categories "Risk0" and "Risk1"
-        risk0 = Risk(risk_category = "Risk0")
-        risk0.save()
-        risk1 = Risk(risk_category = "Risk1")
-        risk1.save()
-        # Create a subsection for the ChoiceQuestion to reside on
-        subsection0 = Subsection(subsection_text = "0")
-        subsection0.save()
-        # Create a Choice Question with the risk set to the above risk
-        cq0 = ChoiceQuestion(subsection = subsection0, question_text = "Test0", risk = risk0)
-        cq0.save()
-        cq1 = ChoiceQuestion(subsection = subsection0, question_text = "Test1", risk = risk1)
-        cq1.save()
-        self.assertEqual(subsection0.risk_factors(), "Risk0, Risk1")
 
     '''
     This tests that the question counts for a subsection return the correct values 
@@ -180,11 +222,12 @@ class ChoiceModelTests(TestCase):
     pass
 
 class ChoiceQuestionModelTests(TestCase):
-    '''
-    This tests that the choice options for a Choice Question
-    are correctly returned by the function
-    '''
+    
     def test_choice_options(self):
+        '''
+        This tests that the choice options for a Choice Question
+        are correctly returned by the function
+        '''
         choice0 = Choice(choice_text = "Choice 0")
         choice1 = Choice(choice_text = "Choice 1")
         choice2 = Choice(choice_text = "Choice 2")
@@ -199,8 +242,58 @@ class ChoiceQuestionModelTests(TestCase):
         cq.choices.add(choice2)
         self.assertEqual(cq.choice_options(), "Choice 0, Choice 1, Choice 2")
 
+    def test_risk_options(self):
+        '''
+        This tests that the risks for a Choice Question
+        are correctly returned by the function
+        '''
+        risk0 = Risk(risk_category = "Risk 0", risk_explanation = "Risk 0")
+        risk1 = Risk(risk_category = "Risk 1", risk_explanation = "Risk 1")
+        risk2 = Risk(risk_category = "Risk 2", risk_explanation = "Risk 2")
+        risk0.save()
+        risk1.save()
+        risk2.save()
+        # Create a Choice Question with the risks set to the above risks
+        cq = ChoiceQuestion(question_text = "Test")
+        cq.save()
+        cq.risks.add(risk0)
+        cq.risks.add(risk1)
+        cq.risks.add(risk2)
+        self.assertEqual(cq.risk_options(), "Risk 0, Risk 1, Risk 2")
+
+class SurveyAnswerModelTests(TestCase):
+
+    def test_close(self):
+        survey_answer = SurveyAnswer()
+        survey_answer.save()
+        subsection = Subsection(subsection_name="Test")
+        subsection.save()
+        subsection_answer0 = SubsectionAnswer(survey_answer=survey_answer)
+        subsection_answer0.save()
+        subsection_answer1 = SubsectionAnswer(survey_answer=survey_answer, subsection=subsection)
+        subsection_answer1.save()
+        self.assertEqual(survey_answer.in_progress, True)
+        self.assertEqual(survey_answer.complete_subsections, 0)
+        survey_answer.close()
+        self.assertEqual(survey_answer.in_progress, False)
+        self.assertEqual(survey_answer.complete_subsections, 1)
+
+    def test_since(self):
+        pass
+
+    def test_risks(self):
+        pass
+    
+
 class SubsectionAnswerModelTests(TestCase):
-    pass
+
+    def test_show_subsection(self):
+        pass
+
+    def test_visible_in_survey(self):
+        pass
+
+    
 
 class AnswerModelTests(TestCase):
     '''
@@ -220,25 +313,26 @@ class AnswerModelTests(TestCase):
         # Answers with different combinations of various members
         # They are arranged in a truth table so 1010 means that there is a text question
         # and a choice question but no answers to either. 
-        # This is an invalid state as an answer should have one and only one type of question and an answer to this question
-        # Therefore only 1100 and 0011 should be valid states.
+        # 1010 is an invalid state as an answer should have one and only one type of question
+        # An answer does not can have no text or choice answer
+        # Therefore only 1000, 0010, 1100 and 0011 should be valid states.
         answers = [
-            Answer(subsection = sub_ans, text_question=None, text_answer=None, choice_question=None, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=None, text_answer=None, choice_question=None, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=None, text_answer=None, choice_question=cq, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=None, text_answer=None, choice_question=cq, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=None, text_answer=ans, choice_question=None, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=None, text_answer=ans, choice_question=None, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=None, text_answer=ans, choice_question=cq, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=None, text_answer=ans, choice_question=cq, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=q, text_answer=None, choice_question=None, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=q, text_answer=None, choice_question=None, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=q, text_answer=None, choice_question=cq, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=q, text_answer=None, choice_question=cq, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=q, text_answer=ans, choice_question=None, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=q, text_answer=ans, choice_question=None, choice_answer=cq_ans), 
-            Answer(subsection = sub_ans, text_question=q, text_answer=ans, choice_question=cq, choice_answer=None),
-            Answer(subsection = sub_ans, text_question=q, text_answer=ans, choice_question=cq, choice_answer=cq_ans),
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=None, choice_question=None, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=None, choice_question=None, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=None, choice_question=cq, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=None, choice_question=cq, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=ans, choice_question=None, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=ans, choice_question=None, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=ans, choice_question=cq, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=None, text_answer=ans, choice_question=cq, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=None, choice_question=None, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=None, choice_question=None, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=None, choice_question=cq, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=None, choice_question=cq, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=ans, choice_question=None, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=ans, choice_question=None, choice_answer=cq_ans), 
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=ans, choice_question=cq, choice_answer=None),
+            Answer(subsection_answer = sub_ans, text_question=q, text_answer=ans, choice_question=cq, choice_answer=cq_ans),
         ]
         valid = []
         for i, answer in enumerate(answers):
@@ -247,7 +341,7 @@ class AnswerModelTests(TestCase):
                 valid.append(i)
             except:
                 continue
-        self.assertEqual(valid, [3, 12])
+        self.assertEqual(valid, [2, 3, 8, 12])
 
     '''
     This tests that the methods for getting the question and answer correctly return them
@@ -264,12 +358,12 @@ class AnswerModelTests(TestCase):
         sub_ans = SubsectionAnswer()
         sub_ans.save()
         # Create answers with the different types of questions/answers
-        q_ans = Answer(subsection = sub_ans, text_question=q, text_answer=ans, choice_question=None, choice_answer=None)
-        cq_ans = Answer(subsection = sub_ans, text_question=None, text_answer=None, choice_question=cq, choice_answer=cq_ans)
+        q_ans = Answer(subsection_answer = sub_ans, text_question=q, text_answer=ans, choice_question=None, choice_answer=None)
+        cq_ans = Answer(subsection_answer = sub_ans, text_question=None, text_answer=None, choice_question=cq, choice_answer=cq_ans)
         q_ans.save()
         cq_ans.save()
-        self.assertEqual(str(q_ans.question()), "x.0 Question")
-        self.assertEqual(str(cq_ans.question()), "x.0 Choice Question")
+        self.assertEqual(str(q_ans.question()), "Question")
+        self.assertEqual(str(cq_ans.question()), "Choice Question")
         self.assertEqual(str(q_ans.answer()), "Answer")
         self.assertEqual(str(cq_ans.answer()), "Choice Answer - 0")
 
diff --git a/wcsudat/surveys/views.py b/wcsudat/surveys/views.py
index c18f40f43183d35360f6511b91db471b6970d9bb..89ab46e65f743644083172d77f84d0e79a6359f3 100644
--- a/wcsudat/surveys/views.py
+++ b/wcsudat/surveys/views.py
@@ -395,110 +395,14 @@ def viewSurvey(request, client_id, survey_answer_id):
 
 @login_required
 def survey(request, client_id, survey_answer_id):
-    return render(request, 'surveys/assessment.html', context={'client': Client.objects.get(id=client_id), 'survey': survey_answer_id})
     '''
-    Return a subsection page for a given survey and subsection number
+    Return the assessment page for a given client and survey answer
     '''
-    # TODO Prevent survey completion until all visible questions are answered
-
-    # Get the survey, subsection and subsection objects for the current page
-    survey_answer = SurveyAnswer.objects.filter(in_progress=True)[0]
-    survey_id = survey_answer.id
-    # TODO: Change these to "get" once order is unique
-    section = Section.objects.filter(order=section_order)[0]
-    subsection = Subsection.objects.filter(order=subsection_order, section = section)[0]
-    subsection_answer = SubsectionAnswer.objects.get(survey_answer=survey_answer, subsection=subsection)
-
-    # Create a list of subsections with links
-    all_sections = Section.objects.all().order_by('order')
-    all_subsections = []
-    for sec in all_sections:
-        all_subsections += sec.subsection_set.all()
-    links = [sub.ordering().replace('.', '/') + '/' for sub in all_subsections]
-    all_subsections = zip(all_subsections, links)
-
-
-    # Construct forms for each answer in the subsection
-    AnswerFormSet = modelformset_factory(
-        Answer, 
-        form=AnswerForm,
-        fields=('text_answer', 'choice_answer',), 
-        extra=0, 
-        edit_only=True,)
-
-    # Construct a list of the question details to be used to display the questions
-    questions = [{'question': q.question(), 'text': q.text_question != None} \
-        for q in Answer.special_objects.visible_in_subsection(subsection_answer)]
-    
-    # When the page is submitted it will have a POST method
-    if request.method == "POST":
-        
-        
-        # Get the data for the subsection components
-        parent_form = SubsectionAnswerForm(request.POST, instance=subsection_answer)
-        # Get the data from the answer objects
-        formset = AnswerFormSet(request.POST, queryset=Answer.special_objects.visible_in_subsection(subsection_answer),)
-        
-        # If they are both valid then save and redirect to next page or home page
-        # TODO Change to redirect to specific page depending on what is clicked
-        if formset.is_valid() and parent_form.is_valid():
-            formset.save()
-            parent_form.save()
-            for link in links:
-                if f'navigation-{link}' in request.POST:
-                    return HttpResponseRedirect(f'/surveys/survey/{link}')
-            link = f'{section_order}/{subsection_order}/'
-            print(link)
-            
-            if 'navigation-next' in request.POST:
-                print('navigation-next')
-                print(links.index(link))
-                if link in links and links.index(link)+1 < len(links):
-                    link = 'survey/'+links[links.index(link)+1]
-                    return HttpResponseRedirect(f'/surveys/{link}')
-                else: 
-                    return HttpResponseRedirect('/surveys/')
-            elif 'navigation-prev' in request.POST:
-                print('navigation-prev')
-                print(links.index(link))
-                if link in links and links.index(link)-1 >= 0:
-                    link = 'survey/'+links[links.index(link)-1]
-                    return HttpResponseRedirect(f'/surveys/{link}')
-                else: 
-                    return HttpResponseRedirect('/surveys/')
-            else:
-                return HttpResponseRedirect(f'/surveys/survey/{link}')
-
-    else:
-        # If it is not a submitted page, just fetch data from database
-        parent_form = SubsectionAnswerForm(instance=subsection_answer)
-        formset = AnswerFormSet(queryset=Answer.special_objects.visible_in_subsection(subsection_answer))
-    # Combine the questions with the answer forms so that they become associated
-    combined = zip(questions, formset)
-    
-    # Add the necessary fields to the context
-    context = {
-        'combined': combined,
-        'formset': formset, 
-        'parent_form': parent_form,
-        'section': section, 
-        'subsection': subsection,
-        'subsections': all_subsections,}
-    # Pass the context to the subsection page
-    return render(request, 'surveys/subsection.html', context)
+    return render(request, 'surveys/assessment.html', context={'client': Client.objects.get(id=client_id), 'survey': survey_answer_id})
 
 @login_required
 def newSurvey(request, client_id):
-    # TODO Possibly improve this behaviour to take the user to the open survey or prevent new survey when one is in progress
-    # or maybe prompt
-    # or use a URL with format survey_id/section_order/subsection_order/
-
-    # Close all open surveys when a new survey is created
-    # TODO pass a real user to this function
     client=Client.objects.get(id=client_id)
-    # for survey in SurveyAnswer.objects.filter(client=client):
-    #     survey.in_progress = False
-    #     survey.save()
     survey = SurveyAnswer(client=client)
     survey.save()
     client.selected_survey_id = survey.id