3
\$\begingroup\$

I've just done my first Angular.js project and can't help but feel I have too much code outside of the framework.

jsFiddle

This is a QA form scoring page that will eventually store it's results in a CRM system, the scoring has a bug but please ignore that.

I'm really after peer review and what the Angular framework can do to help make this code more supportable and maintainable. My CSS and HTML can be improved as well but I'm less worried about those.

Here is the JavaScript, at the top be part of the Angular framework.

var AmlMaxLowScore = 5;
var AmlMaxMedScore = 10;

var OppMaxLowScore = 5;
var OppMaxMedScore = 10;

//Questions are stored like this for amendment to IT Support who are not devs
var questions = [{
    Name: "Some AML Question.  If yes, then ignore the next two questions",
    Id: 10,
    Aml_Risk_Yes_Score: 5,
    Aml_Risk_No_Score: 0,
    Opp_Risk_Yes_Score: 0,
    Opp_Risk_No_Score: 0
  }, {
    Name: "Another AML Question.  If yes, then ignore the next question",
    Id: 20,
    Aml_Risk_Yes_Score: 3,
    Aml_Risk_No_Score: 0,
    Opp_Risk_Yes_Score: 0,
    Opp_Risk_No_Score: 0,
    Ignore_If_Questions_Any_Yes: [10]
  }, {
    Name: "FLorem ipsum praesent lacus senectus semper molestie etiam nisl adipiscing, mattis aliquam ipsum quisque erat aliquam vitae massa feugiat, donec ac vestibulum vel porta in elit primis. Eu vitae fermentum pellentesque facilisis proin quisque venenatis, bibendum nisi eget aptent id rhoncus, tristique nec ligula donec eros etiam.",
    Id: 30,
    Aml_Risk_Yes_Score: 1,
    Aml_Risk_No_Score: 0,
    Opp_Risk_Yes_Score: 0,
    Opp_Risk_No_Score: 0,
    Ignore_If_Questions_Any_Yes: [10, 20]
  }, {
    Name: "Varius quisque congue dolor feugiat urna dapibus gravida integer, senectus nam pretium mi tellus convallis dolor rutrum, curae aliquam potenti ornare pharetra lectus suscipit nullam sociosqu aliquam rutrum torquent vel nisi aenean.",
    Id: 40,
    Aml_Risk_Yes_Score: 0,
    Aml_Risk_No_Score: 0,
    Opp_Risk_Yes_Score: 3,
    Opp_Risk_No_Score: 0
  },
  {
  Name: "Integer tellus turpis egestas metus adipiscing nulla ultricies viverra mi, varius est cras bibendum ornare risus neque vel nibh quam, sapien ad ultrices commodo semper suscipit purus dolor senectus convallis vivamus quis?",
  Id: 50,
  Aml_Risk_Yes_Score: 0,
  Aml_Risk_No_Score: 1,
  Opp_Risk_Yes_Score: 0,
  Opp_Risk_No_Score: 3
}, 
];

console.log('1 class def');

//classes 
function answer(questionId, answer, comment) {
  this.id = questionId;
  this.answer = answer;
  this.comment = comment;
  this.toString = function() {
    return 'Q:' + this.id || 'ERROR' + ',A:' + this.answer || '' + ',' + this.comment || '';
  };
}


function questionAndAnswer(question) {
  var ansOrginal;
  var ans;
  var isRequredAns = [];

  //Set up ans
  ansOrginal = queries.getAnswerById(question.Id);
  ans = ansOrginal; //May need a copy here so we don't modify ansOrginal

  if (ans === undefined) {
    ans = new answer(question.Id);
  }

  //Set up isRequired dependents
  if (question.Ignore_If_Questions_Any_Yes) {
    var answersRequired = question.Ignore_If_Questions_Any_Yes;
    for (var i = 0; i < answersRequired.length; i++) {
      var a = queries.getAnswerById(answersRequired[i]);
      if (a) {
        isRequredAns.push(a);
        continue;
      }
      var message = 'Unable to find question ' + answersRequired[i] || 'NULL' + ' as specified in  Ignore_If_Questions_Any_Yes for question ' + question.Id;
      console.log(message);
      window.alert(message);
      throw new Error(message);
    }
  }

  this.question = question;
  this.answer = ans;
  this.isAnswerDirty = function() {
    return
    ans !== undefined && ansOrginal !== undefined && ansOrginal.answer != ans.answer && ansOrginal.comment != ans.comment;
  };
  this.isRequired = function() {
    //Ignore_If_Questions_Any_Yes or IsRequiredIfAllAreNo
    for (var i = 0; i < isRequredAns.length; i++) {
      if (isRequredAns[i].answer === 'Yes') return false;
    }
    return true;
  };

}

console.log('2 data layers');

var queries = new function() {
  this.unionAnswersWithQuestions = function(questions) {
    var qa = [];
    for (var i = 0; i < questions.length; i++) {

      //check for duplicate ID's
      for (var e = 0; e < qa.length; e++) {
        if (qa[e].id == questions[i].Id) {
          var message = 'Unable to render questions as Duplicate question id found.';
          console.log(message);
          window.alert(message);
          throw new Error(message);
        }
      }
      //the questionAndAnswer construtor references the global answers :(
      qa.push(new questionAndAnswer(questions[i]));
    }
    return qa;
  }

  this.getAnswerById = function(id) {
    for (var i = 0; i < answers.length; i++) {
      if (answers[i].id == id) {
        return answers[i];
      }
    }
    return;
  };
  this.getAmlRiskRating = function() {
    debugger;
    if (questionAndAnswers === undefined || questionAndAnswers.questions === undefined) return undefined;
    var score = 0;
    for (var i = 0; i < questionAndAnswers.questions.length; i++) {
      var q = questionAndAnswers.questions[i];
      if (q.isRequired()) {
        var a = q.answer;
        if (a === 'Yes') {
          score += q.Aml_Risk_Yes_Score;
        } else if (a === 'No') {
          score += q.Aml_Risk_No_Score;
        } else {
          //return undefined;
        }
      }
    }
    if (score <= AmlMaxLowScore) {
      return 'Low';
    } else if (score <= AmlMaxMedScore) {
      return 'Medium';
    }
    return 'High';
  };
    this.getOppRiskRating = function() {
    debugger;
    if (questionAndAnswers === undefined || questionAndAnswers.questions === undefined) return undefined;
    var score = 0;
    for (var i = 0; i < questionAndAnswers.questions.length; i++) {
      var q = questionAndAnswers.questions[i];
      if (q.isRequired()) {
        var a = q.answer;
        if (a === 'Yes') {
          score += q.Opp_Risk_Yes_Score;
        } else if (a === 'No') {
          score += q.Opp_Risk_No_Score;
        } else {
          //return undefined;
        }
      }
    }
    if (score <= OppMaxLowScore) {
      return 'Low';
    } else if (score <= OppMaxMedScore) {
      return 'Medium';
    }
    return 'High';
  };
}

//Only one instance needed
var crm = new function() {
  this.getAnswers = function() {
    console.log(' mocking answers that would be stored in CRM...');
    var a = [
      new answer(10, 'Yes'),
      new answer(20, 'No', 'Hello'),
      new answer(30),
      new answer(40, 'No', 'Multi/r/nline ')
    ];
    return a;
  };
  this.putAnswers = function(answerArray) {
    //Check that value has changed before actually making the field dirty
    //console.log("crm.putAnswers called " + angular.toJson(answerArray,true); 
    this.updateAmlScore(queries.getAmlRiskRating());
    this.updateOppScore(queries.getOppRiskRating());
  };
  this.updateAmlScore = function(score) {
    //Check that value has changed before actually making the field dirty
    console.log('crm.updateAmlScore called ' + score);
  };
  this.updateOppScore = function(score) {
    //Check that value has changed before actually making the field dirty
    console.log('crm.updateOppScore called ' + score);
  };
  this.consoleAnswers = function(answerArray) {
    for (var i = 0; i < answerArray.length; i++) {
      console.log('Answer: ' + answerArray[i].getInfo());
    }
  };
  return this;
}();

console.log('3 Init');

var answers = crm.getAnswers();
//Union answers with questions into new array
var questionAndAnswers = queries.unionAnswersWithQuestions(questions);



console.log('4 Angluar');

var app = angular.module("myApp", []);


app.controller('riskQuestions', ['$scope',
  function($scope) {
    $scope.questionAndAnswers = questionAndAnswers;
    $scope.$watch(function() {
      //toDo:  This fire very offten, two times per model change and every comment key press
      //Phase 2: it might be better to get a call from crmForm.Save event to make the code work better on older machines.
      crm.putAnswers(questionAndAnswers);
    });
  }
]);
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Codereview :) Just remember that the title should tell what the code does, not your concerns or any possible improvement. \$\endgroup\$
    – Caridorc
    Commented Dec 6, 2015 at 20:27

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.