0

I'm working on a piece of javascript that sets a color value based on the status of a healthcheck. The string color values tie into the CSS I'm working with, and the string statuses tie into the health checks reported to this script.

This function is designed to set the color value for each healthcheck, AND return an overall status of the system. The overall status should be correspond to the worst condition health check (e.g. if most are "ok", and one is "fatal", overall should be "danger").

The current code works to set individual color values, but not the overall. Is there an "elegant" way to set the overall without having to use lots of nested if statements?

function getStatus(checks) {
  var overall = '';
  for (j in checks) {
    checks[j]['color'] = '';
      switch (checks[j].status) {
          case 'OK':
              checks[j]['color'] = 'success';
              break;
          case 'INFO':
              checks[j]['color'] = 'info';
              break;
          case 'WARN':
              checks[j]['color'] = 'warning';
              break;
          case 'ERROR':
              checks[j]['color'] = 'danger';
              break;
          case 'FATAL':
              checks[j]['color'] = 'danger';
              break;
      }
  }
  return overall;
}

I could do something like this:

case 'WARN':
    if (overall === "OK" || overall === "INFO") {
        overall = 'warning'; 
    }

... but that gets messy, especially when checking for "ERROR" which must be greater than 3 values, but less than one. Is there a more effective way?

Huangism
  • 16,278
  • 7
  • 48
  • 74
vastlysuperiorman
  • 1,694
  • 19
  • 27
  • just do `var fatal = false;` and in you fatal case, set fatal to true. Then your return is `return fatal` and based off it being true or false, display whatever you like. edit: i see you need it for warn, error and fatal? Is that accurate? – Ronnie Sep 17 '14 at 17:58
  • How is this related to angularJS ? It's pure javascript. – Cyril Duchon-Doris Sep 17 '14 at 18:00
  • @CyrilDD you're right. The part I've included here is pure javascript--the angular isn't relevant to my question. Updated accordingly. – vastlysuperiorman Sep 17 '14 at 18:11

3 Answers3

1

Use numbers instead of strings and then (if I've understood what you're trying to do) its simply a case of returning the highest status you receive. You can use an associative array to store the string representation, error code and color for each status in separate objects and move those around (with the advantage that you can bin off that switch statement):

 var statuses = {
  ok:     { code: 1, status: 'OK', color: 'success'},
  info:   { code: 2, status: 'INFO', color: 'info'},
  warn:   { code: 3, status: 'WARN', color: 'warning'},
  error:  { code: 4, status: 'ERROR', color: 'danger'},
  fatal:  { code: 5, status: 'FATAL', color: 'danger'},
}

// example checks
var checks = [statuses['ok'], statuses['warn'], statuses['fatal']];

function getStatus(checks) {

  var overall = statuses['ok'];

  for (check in checks) {
    if (check.code > overall.code) {
      overall = check;
    }
  }
  return overall;
}
net.uk.sweet
  • 12,444
  • 2
  • 24
  • 42
  • Rolling back the previous edit which I don't think was acceptable as it fundamentally changed the answer. @editor - I think in this instance you should have posted your own answer rather than editing mine. – net.uk.sweet Sep 17 '14 at 18:39
1

Well there's no other choice ? But some improvements are possible. Add another for loop + a switch. If there's an error somewhere, you don't need to continue the loop and you can return 'danger'

overall = 'success'

for (j in checks) {
    switch (checks[j].status) {

        case 'OK':
            break;
        case 'INFO':
            if (overall === 'success')
                overall = 'info'
            break;
        case 'WARN':
            if (overall === 'success' || overall === 'warning')
                overall = 'warning'
            break;
        case 'ERROR':
        case 'FATAL':
            return 'danger'
    }
}
Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
  • Hmm sorry, I might be confused : what are the possible values for 'overall' ? Just 'ok', 'warning', and 'danger' ? Or 'OK', 'INFO', 'WARN', 'DANGER' and 'FATAL' ? – Cyril Duchon-Doris Sep 17 '14 at 18:16
  • The values 'OK', 'INFO', 'WARN', 'DANGER' and 'FATAL' are to be translated to one of 'success', 'info', 'warning' or 'danger'. The function receives var checks containing multiple values in the first list. Overall is returned containing one from the second list. Editing my answer to clarify. – vastlysuperiorman Sep 17 '14 at 18:34
  • I updated my answer to reflect that, assuming OK < INFO < WARN < ERROR/FATAL – Cyril Duchon-Doris Sep 17 '14 at 19:29
0

Following net.uk.sweet's answer, you might want to define an enum to store the values of status

medical.status = {
  INFO : 0,
  OK : 1,
  WARNING : 2,
  DANGER : 3,
  FATAL : 4
}

And in the rest of your code, instead of giving string values to checks[j], you should assign one of these constants :

checks[j].status = medical.status.DANGER

Then you can use the < operator just like in net.uk.sweet's answer

Community
  • 1
  • 1
Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
  • I'm editing already existing code--input will always be one of INFO, OK, WARNING, ERROR, FATAL, and output must always be one of success, info, warning, danger. I do think enum is a good idea though. – vastlysuperiorman Sep 17 '14 at 18:44