<commit_before>//= require photo_selectors

function nombres_comunes_todos()
{
    $('#nombres_comunes_todos').load("/especies/" + TAXON.id + "/nombres-comunes-todos");
}

function imagenes_taxon(p)
{
    $.ajax(
        {
            url: BDI_API,
            type: 'GET',
            data: {p: p}
        }).done(function (fotos) {

        }).error(function (error) {
            $('#imagenes_taxon').html('Lo sentimos, no contamos con una imágen para esta especie, ¿quieres contribuir proporcionando una imágen?');
        });
}

$(document).ready(function(){
    cual_ficha = '';

    info = function(){
        $('#ficha-div').slideUp();
        $('#info-div').slideDown();
        return false;
    };

    ficha = function(){
        $('#info-div').slideUp();
        $('#ficha-div').slideDown();
        return false;
    };

    muestraBibliografiaNombres = function(ident){
        var id=ident.split('_')[2];
        $("#biblio_"+id).dialog();
        return false;
    };

    despliegaOcontrae = function(id)
    {
        var sufijo = id.substring(5);

        if ($("#nodo_" + sufijo + " li").length > 0)
        {
            var minus = $('#span_' + sufijo).hasClass("glyphicon-minus");

            if (minus)
                $('#span_' + sufijo).removeClass("glyphicon-minus").addClass("glyphicon-plus");

            $("#nodo_" + sufijo + " li").remove();

        } else {
            var origin_id = window.location.pathname.split('/')[2];

            $.ajax(
                {
                    url: "/especies/" + sufijo + "/hojas_arbol_identado?origin_id=" + origin_id
                }).done(function(nodo)
                {
                    var plus = $('#span_' + sufijo).hasClass("glyphicon-plus");

                    if (plus)
                        $('#span_' + sufijo).removeClass("glyphicon-plus").addClass("glyphicon-minus");

                    return $("#nodo_" + sufijo).append(nodo);
                });
        }
        return false;
    };

    $(document).on('click', '#boton_pdf', function(){
        window.open("/especies/"+TAXON.id+".pdf?from="+cual_ficha);
    });

    $(document).on('change', '#from', function(){
        cual_ficha = $(this).val();

        $.ajax({
            url: "/especies/"+TAXON.id+"/describe?from="+cual_ficha,
            method: 'get',
            success: function(data, status) {
                $('.taxon_description').replaceWith(data);
            },
            error: function(request, status, error) {
                $('.taxon_description').loadingShades('close');
            }
        });
    });

    $(document).on('click', '.historial_ficha', function(){
        var comentario_id = $(this).attr('comentario_id');
        var especie_id = $(this).attr('especie_id');
        $("#historial_ficha_" + comentario_id).load("/especies/"+especie_id+"/comentarios/"+comentario_id+"/respuesta_externa?ficha=1");
        $("#historial_ficha_" + comentario_id).slideDown();
        return false;
    });

    $('#pestañas').tabs(); // Inicia los tabs
    $('#modal_reproduce').on('show.bs.modal', function (event) {
//        $('#modal_reproduce_body').html("
Cargando... Por favor, espera
");

        var button = $(event.relatedTarget); // Button that triggered the modal
        var url = button.data('url');
        var title = button.data('title');
        var video = $(document.createElement("video")).append($(document.createElement("source")).attr('src', url));

        $('#modal_reproduce_label').text(title);
        $('#modal_reproduce_body').append(video);
    });

    $('#modal_reproduce').on('hide.bs.modal', function(){$('#modal_reproduce_body').empty()});// eliminar contenido del body en la reproduccion de los videos

    $('#pestañas > .nav a').click(function(){
        $('#pestañas > .nav li').removeClass("active");
        $(this).parent().addClass("active");
    }).one('click',function(){
        if (!Boolean($(this).hasClass('noLoad'))){
            idPestaña = this.getAttribute('href');
            pestaña = '/especies/'+TAXON.id+'/'+idPestaña.replace('#','');
            $(idPestaña).load(pestaña);
        }
    });

    // Inicia los proveedores de fotos
    $('#edit_photos_dialog').dialog({
        modal: true,
        title: 'Escoge las fotos para este grupo o especie',
        autoOpen: false,
        width: 700,
        open: function( event, ui ) {
            $('#edit_photos_dialog').loadingShades('Cargando...', {cssClass: 'smallloading'});
            $('#edit_photos_dialog').load('/especies/'+TAXON.id+'/edit_photos', function(){
                var photoSelectorOptions = {
                    defaultQuery: TAXON.nombre_cientifico,
                    skipLocal: true,
                    baseURL: '/conabio/photo_fields',
                    taxon_id: TAXON.id,
                    urlParams: {
                        authenticity_token: $('meta[name=csrf-token]').attr('content'),
                        limit: 14
                    },
                    afterQueryPhotos: function(q, wrapper, options) {
                        $(wrapper).imagesLoaded(function() {
                            $('#edit_photos_dialog').centerDialog()
                        })
                    }
                };

                $('.tabs', this).tabs({
                    beforeActivate: function( event, ui ) {
                        if ($(ui.newPanel).attr('id') == 'flickr_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            //$('.taxon_photos', ui.newPanel).photoSelector(photoSelectorOptions)
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/flickr/photo_fields'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'inat_obs_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/taxa/'+TAXON.id+'/observation_photos'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'eol_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/eol/photo_fields'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'wikimedia_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/wikimedia_commons/photo_fields'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'conabio_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {taxon_id: TAXON.id, baseURL: '/conabio/photo_fields'})
                            )
                        }

                        $(ui.newPanel).addClass('loaded')
                        $('#edit_photos_dialog').centerDialog()
                    },
                    create: function( event, ui) {
                        $('.taxon_photos', ui.panel).photoSelector(photoSelectorOptions);
                        $(ui.panel).addClass('loaded')
                        $('#edit_photos_dialog').centerDialog()
                    }
                })
            })
        }
    });
});
<commit_msg>limpieza show.js<commit_after>//= require photo_selectors

function nombres_comunes_todos()
{
    $('#nombres_comunes_todos').load("/especies/" + TAXON.id + "/nombres-comunes-todos");
}

function imagenes_taxon(p)
{
    $.ajax(
        {
            url: BDI_API,
            type: 'GET',
            data: {p: p}
        }).done(function (fotos) {

        }).error(function (error) {
            $('#imagenes_taxon').html('Lo sentimos, no contamos con una imágen para esta especie, ¿quieres contribuir proporcionando una imágen?');
        });
}

$(document).ready(function(){
    cual_ficha = '';

    info = function(){
        $('#ficha-div').slideUp();
        $('#info-div').slideDown();
        return false;
    };

    ficha = function(){
        $('#info-div').slideUp();
        $('#ficha-div').slideDown();
        return false;
    };

    muestraBibliografiaNombres = function(ident){
        var id=ident.split('_')[2];
        $("#biblio_"+id).dialog();
        return false;
    };

    despliegaOcontrae = function(id)
    {
        var sufijo = id.substring(5);

        if ($("#nodo_" + sufijo + " li").length > 0)
        {
            var minus = $('#span_' + sufijo).hasClass("glyphicon-minus");

            if (minus)
                $('#span_' + sufijo).removeClass("glyphicon-minus").addClass("glyphicon-plus");

            $("#nodo_" + sufijo + " li").remove();

        } else {
            var origin_id = window.location.pathname.split('/')[2];

            $.ajax(
                {
                    url: "/especies/" + sufijo + "/hojas_arbol_identado?origin_id=" + origin_id
                }).done(function(nodo)
                {
                    var plus = $('#span_' + sufijo).hasClass("glyphicon-plus");

                    if (plus)
                        $('#span_' + sufijo).removeClass("glyphicon-plus").addClass("glyphicon-minus");

                    return $("#nodo_" + sufijo).append(nodo);
                });
        }
        return false;
    };

    $(document).on('click', '#boton_pdf', function(){
        window.open("/especies/"+TAXON.id+".pdf?from="+cual_ficha);
    });

    $(document).on('change', '#from', function(){
        cual_ficha = $(this).val();

        $.ajax({
            url: "/especies/"+TAXON.id+"/describe?from="+cual_ficha,
            method: 'get',
            success: function(data, status) {
                $('.taxon_description').replaceWith(data);
            },
            error: function(request, status, error) {
                $('.taxon_description').loadingShades('close');
            }
        });
    });

    $(document).on('click', '.historial_ficha', function(){
        var comentario_id = $(this).attr('comentario_id');
        var especie_id = $(this).attr('especie_id');
        $("#historial_ficha_" + comentario_id).load("/especies/"+especie_id+"/comentarios/"+comentario_id+"/respuesta_externa?ficha=1");
        $("#historial_ficha_" + comentario_id).slideDown();
        return false;
    });

    $('#pestañas').tabs(); // Inicia los tabs
    $('#modal_reproduce').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget); // Button that triggered the modal
        var video = $(document.createElement("video")).attr('controls','').attr('controlsList', 'nodownload').attr('autoplay','');
        var source = $(document.createElement("source")).attr('src', button.data('url'));

        $('#modal_reproduce_label > a').attr('href', button.data('title'));
        $('#modal_reproduce_body').append(video.append(source));
    });

    $('#modal_reproduce').on('hide.bs.modal', function(){$('#modal_reproduce_body').empty()});// eliminar contenido del body en la reproduccion de los videos

    $('#pestañas > .nav a').click(function(){
        $('#pestañas > .nav li').removeClass("active");
        $(this).parent().addClass("active");
    }).one('click',function(){
        if (!Boolean($(this).hasClass('noLoad'))){
            idPestaña = this.getAttribute('href');
            pestaña = '/especies/'+TAXON.id+'/'+idPestaña.replace('#','');
            $(idPestaña).load(pestaña);
        }
    });

    // Inicia los proveedores de fotos
    $('#edit_photos_dialog').dialog({
        modal: true,
        title: 'Escoge las fotos para este grupo o especie',
        autoOpen: false,
        width: 700,
        open: function( event, ui ) {
            $('#edit_photos_dialog').loadingShades('Cargando...', {cssClass: 'smallloading'});
            $('#edit_photos_dialog').load('/especies/'+TAXON.id+'/edit_photos', function(){
                var photoSelectorOptions = {
                    defaultQuery: TAXON.nombre_cientifico,
                    skipLocal: true,
                    baseURL: '/conabio/photo_fields',
                    taxon_id: TAXON.id,
                    urlParams: {
                        authenticity_token: $('meta[name=csrf-token]').attr('content'),
                        limit: 14
                    },
                    afterQueryPhotos: function(q, wrapper, options) {
                        $(wrapper).imagesLoaded(function() {
                            $('#edit_photos_dialog').centerDialog()
                        })
                    }
                };

                $('.tabs', this).tabs({
                    beforeActivate: function( event, ui ) {
                        if ($(ui.newPanel).attr('id') == 'flickr_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            //$('.taxon_photos', ui.newPanel).photoSelector(photoSelectorOptions)
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/flickr/photo_fields'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'inat_obs_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/taxa/'+TAXON.id+'/observation_photos'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'eol_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/eol/photo_fields'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'wikimedia_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {baseURL: '/wikimedia_commons/photo_fields'})
                            )
                        } else if ($(ui.newPanel).attr('id') == 'conabio_taxon_photos' && !$(ui.newPanel).hasClass('loaded')) {
                            $('.taxon_photos', ui.newPanel).photoSelector(
                                $.extend(true, {}, photoSelectorOptions, {taxon_id: TAXON.id, baseURL: '/conabio/photo_fields'})
                            )
                        }

                        $(ui.newPanel).addClass('loaded')
                        $('#edit_photos_dialog').centerDialog()
                    },
                    create: function( event, ui) {
                        $('.taxon_photos', ui.panel).photoSelector(photoSelectorOptions);
                        $(ui.panel).addClass('loaded')
                        $('#edit_photos_dialog').centerDialog()
                    }
                })
            })
        }
    });
});
<|endoftext|>


<commit_before>$(document).ready(function(){
    var max = 300;

  $('#expenses_grid').on('keyup','#expense_description',function() {
    var len = $(this).val().length;
    var char = max - len;
    if (len >= max) {
      $('#charNum').text(char + ' chars left');
      $('#charNum').css('color', 'red');
      $('.new_expense input[type=submit]').attr('disabled','disabled');
    } else {
      $('#charNum').text(char + ' chars left');
      $('#charNum').css('color', 'grey');
      $('.new_expense input[type=submit]').removeAttr('disabled');
    }
  });

  var old_budget = parseFloat($('h4 .best_in_place[data-bip-attribute="budget"]').text().replace(/[A-Za-z$-,]/g, ""))
  var balance = parseFloat($('#balance-field').text().replace(/[A-Za-z$-,]/g, ""))

  $('h4 .best_in_place[data-bip-attribute="budget"]').change(function(e){
    new_budget = (e.target.value) * 1
    var total_spent = old_budget - balance;
    var new_balance = (new_budget - total_spent).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
    $('#balance-field').text('$' + new_balance)
    var formatted = new_budget.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
    $('h5 .best_in_place[data-bip-attribute="budget"]').text('$' + formatted)
  })

  $("#menu-toggle").click(function(e) {
      e.preventDefault();
      $("#wrapper").toggleClass("active");
  });

  $('#expense_form').hide();

  $('#trip_form').on('click', 'input[type=submit]', function(event){
    $('#trip_form').hide();
    $('#expense_form').show();
  });

  $('input#expense_location_id').geocomplete();

  $('form').on('click','.add_fields', function(event){
    event.preventDefault();
    time = new Date().getTime();
    regexp = new RegExp($(this).data('id'), 'g');
    $(this).before($(this).data('fields').replace(regexp, time));
  });
  // $('#add-location').click(function(e){
  //   e.preventDefault();
  //   addLegForm();
  // })

$('body').on('click','.location',function(e){
  $(this).geocomplete();
});

$('#expenses_grid').on('click','#add-expense', function(e){
  e.preventDefault();
  $('#new_expense').show();
  $('#add-expense').hide();
  $('#expense_currency_id').select2();
});

$('#expenses_grid').on('submit','#new_expense',function(e){
  e.preventDefault();
  var old_balance = parseFloat($('#balance-field').text().replace(/[A-Za-z$-,]/g, ""));
  $.ajax ({
    url: $(e.target).attr('action'),
    type: 'POST',
    data: $(e.target).serialize()
  }).done(function(data){
    $('.event-list').append(data);
    var usd = parseFloat($('.event-list li:last-child .usd-cost-field').text().replace(/[A-Za-z$-,]/g, ""));
    var new_balance = (old_balance - usd).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
    $('#balance-field').text('$' + new_balance)
    clearInputs();
  });
});

clearInputs = function(){
  $("input[name='expense[usd_cost]'").val("");
  $("input[name='expense[location_id]'").val("");
  $("input[name='expense[cost]'").val("");
  $("input[name='expense[category_id]'").val("");
  $("textarea[name='expense[description]'").val("");
  $("input[name='expense[title]'").val("");
  $('select option:contains("Category")').prop('selected',true);
  $('#charNum').text(max + ' chars left');
  };
});

<commit_msg>Delegate editing budget to wrapper div<commit_after>$(document).ready(function(){
    var max = 300;

  $('#expenses_grid').on('keyup','#expense_description',function() {
    var len = $(this).val().length;
    var char = max - len;
    if (len >= max) {
      $('#charNum').text(char + ' chars left');
      $('#charNum').css('color', 'red');
      $('.new_expense input[type=submit]').attr('disabled','disabled');
    } else {
      $('#charNum').text(char + ' chars left');
      $('#charNum').css('color', 'grey');
      $('.new_expense input[type=submit]').removeAttr('disabled');
    }
  });

  $('#wrapper').on('change','h4 .best_in_place[data-bip-attribute="budget"]', function(e) {
    console.log("CHANGED BUDGET");
    new_budget = (e.target.value) * 1;
    var total_spent = old_budget - balance;
    var new_balance = (new_budget - total_spent).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
    $('#balance-field').text('$' + new_balance);

  });

  $("#menu-toggle").click(function(e) {
      e.preventDefault();
      $("#wrapper").toggleClass("active");
  });

  $('#expense_form').hide();

  $('#trip_form').on('click', 'input[type=submit]', function(event){
    $('#trip_form').hide();
    $('#expense_form').show();
  });

  $('input#expense_location_id').geocomplete();

  $('form').on('click','.add_fields', function(event){
    event.preventDefault();
    time = new Date().getTime();
    regexp = new RegExp($(this).data('id'), 'g');
    $(this).before($(this).data('fields').replace(regexp, time));
  });
  // $('#add-location').click(function(e){
  //   e.preventDefault();
  //   addLegForm();
  // })

$('body').on('click','.location',function(e){
  $(this).geocomplete();
});

$('#expenses_grid').on('click','#add-expense', function(e){
  e.preventDefault();
  $('#new_expense').show();
  $('#add-expense').hide();
  $('#expense_currency_id').select2();
});

$('#expenses_grid').on('submit','#new_expense',function(e){
  e.preventDefault();
  var old_balance = parseFloat($('#balance-field').text().replace(/[A-Za-z$-,]/g, ""));
  $.ajax ({
    url: $(e.target).attr('action'),
    type: 'POST',
    data: $(e.target).serialize()
  }).done(function(data){
    $('.event-list').append(data);
    var usd = parseFloat($('.event-list li:last-child .usd-cost-field').text().replace(/[A-Za-z$-,]/g, ""));
    var new_balance = (old_balance - usd).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
    $('#balance-field').text('$' + new_balance)
    clearInputs();
  });
});

clearInputs = function(){
  $("input[name='expense[usd_cost]'").val("");
  $("input[name='expense[location_id]'").val("");
  $("input[name='expense[cost]'").val("");
  $("input[name='expense[category_id]'").val("");
  $("textarea[name='expense[description]'").val("");
  $("input[name='expense[title]'").val("");
  $('select option:contains("Category")').prop('selected',true);
  $('#charNum').text(max + ' chars left');
  };
});

<|endoftext|>


<commit_before>Yacs = new function () {
  var self = this;

/* ======================================================================== *
    Network
 * ======================================================================== */

  self.get = function (uri, callback) {
    req = new XMLHttpRequest();
    req.open('GET', uri);
    req.onreadystatechange = function () {
      if (req.readyState == 4 && callback) {
        callback(req.responseText, req.status == 200)
      }
    }
    req.send();
  };

  self.api = function (model, params, callback) {
    var query = "?";
    for (var param in params) {
      if (params.hasOwnProperty(param)) {
        var val = params[param];
        if (Array.isArray()) val = val.join(',')
        query += param + '=' + val + '&';
      }
    }
    var uri = '/api/v5/' + model + '.json' + query;
    self.get(uri, function (response, success) {
      callback(!success || JSON.parse(response), success);
    });
  };

/* ======================================================================== *
    ORM
 * ======================================================================== */

  self.models = { };

  var Model = function (name, options) {
    options = options || {};
    var self = this;
    var childParam = 'show_' + options.has_many;

    self.store = { all: [], id: {} };
    self.preloaded = false;

    self.query = function (params, callback) {
      Yacs.api(name, params, callback);
    };

    self.preload = function (callback) {
      var params = {};
      if (options.has_many)
        params[childParam] = true;
      self.query(params, function (data, success) {
        if (success) {
          var models = data[name];
          for (var m in models) {
            self.store.all = models;
            self.store.id[models[m].id] = models[m];
            if (options.has_many) {
              var children = [];
              for (var n in models[m][options.has_many]) {
                var child = models[m][options.has_many][n];
                Yacs.models[options.has_many].store.id[child.id] = child;
                children.push(child);
              }
              Yacs.models[options.has_many].store.all = children;
            }
          }
          preloaded = true;
        }
        if (callback)
          callback(data, success);
      });
    }
  };

  var addModel = function (name, options) {
    return self.models[name] = new Model(name, options);
  }

  addModel('schools',     { has_many: 'departments' });
  addModel('departments', { has_many: 'courses'     });
  addModel('courses',     { has_many: 'sections'    });
  addModel('sections' );
  addModel('schedules');

/* ======================================================================== *
    DOM
 * ======================================================================== */

  self.views = { };

  NodeList.prototype.each = Array.prototype.forEach;
  HTMLCollection.prototype.each = Array.prototype.forEach;

 // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
  var matches = function (elm, selector) {
    var matches = (elm.document || elm.ownerDocument).querySelectorAll(selector);
    var i = matches.length;
    while (--i >= 0 && matches.item(i) !== elm);
    return i > -1;
  }

  var loaded = false;
  self.onload = function (func) {
    document.addEventListener("DOMContentLoaded", func, false);
  }
  self.onload(function () { loaded = true; })

  self.setContents = function (html) {
    document.getElementById('content').innerHTML = html;
  }

  self.clearContents = function () {
    Yacs.setContents('');
  }

  self.on = function (eventType, elem, callback) {
    elem.addEventListener(eventType, function (event) {
      callback(elem, event);
    });
  };
}();

Yacs.views.header = function () {
  var homeButton = document.getElementById('page-title');
  var searchbar = document.getElementById('searchbar');
  var scheduleButton = document.getElementById("schedule-btn");
  Yacs.on('click', homeButton, function () { Yacs.views.departments(); });
  Yacs.on('click', scheduleButton, function () { Yacs.views.schedule(); });
  Yacs.on('keydown', document, function (elem, event) {
    var key = event.keyCode;
    if (!(event.ctrlKey || event.metaKey)) {
      if (key >= 32 && key <= 127) {
        if (key == 127 && searchbar.value.length <= 1)
          Yacs.views.departments();
        searchbar.focus();
      } else if (key == 13) {
        if (searchbar.value) {
          Yacs.models.courses.query({ search: searchbar.value }, function (data, success) {
            if (success)
              Yacs.views.courses(data);
          });
        } else {
          Yacs.views.departments();
        }
      } else if ((key == 8 || key == 46) && searchbar.value.length <= 1) {
        Yacs.views.departments();
      }
    }
  });
};

/* ======================================================================== *
    Initializers
 * ======================================================================== */

Yacs.onload(function () {
  Yacs.models.schools.preload(function (data) {
    Yacs.views.departments(data);
  });
  Yacs.views.header();
});
<commit_msg>starts adding jsdoc to yacs.js<commit_after>/**
 * YACS singleton. This object is the top-level namespace for all YACS functionality.
 */
Yacs = new function () {
  var self = this;

/* ======================================================================== *
    Network
 * ======================================================================== */

  /**
   * Performs an AJAX request
   * @param  {String} uri - URI of request
   * @param  {Function} callback - callback
   * @return {undefined}
   */
  self.get = function (uri, callback) {
    req = new XMLHttpRequest();
    req.open('GET', uri);
    req.onreadystatechange = function () {
      if (req.readyState == 4 && callback) {
        callback(req.responseText, req.status == 200)
      }
    }
    req.send();
  };

  /**
   * Performs an AJAX request to the YACS API.
   * @param  {String} model - name of the route to request
   * @param  {Object} params - query parameters as a hash
   * @param  {Function} callback - callback
   * @return {undefined}
   */
  self.api = function (model, params, callback) {
    var query = "?";
    for (var param in params) {
      if (params.hasOwnProperty(param)) {
        var val = params[param];
        if (Array.isArray()) val = val.join(',')
        query += param + '=' + val + '&';
      }
    }
    var uri = '/api/v5/' + model + '.json' + query;
    self.get(uri, function (response, success) {
      callback(!success || JSON.parse(response), success);
    });
  };

/* ======================================================================== *
    ORM
 * ======================================================================== */

  self.models = { };
  /**
   * @constructor Represents a collection of objects obtained from the YACS API
   * @param {String} name - pluralized name of collection
   * @param {Object} [options] properties - extra properties of the collection
   * @param {String} [options.has_many] - name of one-to-many association
   */
  var Model = function (name, options) {
    options = options || {};
    var self = this;
    var childParam = 'show_' + options.has_many;

    self.store = { all: [], id: {} };
    self.preloaded = false;

    self.query = function (params, callback) {
      Yacs.api(name, params, callback);
    };

    self.preload = function (callback) {
      var params = {};
      if (options.has_many)
        params[childParam] = true;
      self.query(params, function (data, success) {
        if (success) {
          var models = data[name];
          for (var m in models) {
            self.store.all = models;
            self.store.id[models[m].id] = models[m];
            if (options.has_many) {
              var children = [];
              for (var n in models[m][options.has_many]) {
                var child = models[m][options.has_many][n];
                Yacs.models[options.has_many].store.id[child.id] = child;
                children.push(child);
              }
              Yacs.models[options.has_many].store.all = children;
            }
          }
          preloaded = true;
        }
        if (callback)
          callback(data, success);
      });
    }
  };

  var addModel = function (name, options) {
    return self.models[name] = new Model(name, options);
  }

  addModel('schools',     { has_many: 'departments' });
  addModel('departments', { has_many: 'courses'     });
  addModel('courses',     { has_many: 'sections'    });
  addModel('sections' );
  addModel('schedules');

/* ======================================================================== *
    DOM
 * ======================================================================== */

  self.views = { };

  NodeList.prototype.each = Array.prototype.forEach;
  HTMLCollection.prototype.each = Array.prototype.forEach;

 // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
  var matches = function (elm, selector) {
    var matches = (elm.document || elm.ownerDocument).querySelectorAll(selector);
    var i = matches.length;
    while (--i >= 0 && matches.item(i) !== elm);
    return i > -1;
  }

  var loaded = false;
  self.onload = function (func) {
    document.addEventListener("DOMContentLoaded", func, false);
  }
  self.onload(function () { loaded = true; })

  self.setContents = function (html) {
    document.getElementById('content').innerHTML = html;
  }

  self.clearContents = function () {
    Yacs.setContents('');
  }

  self.on = function (eventType, elem, callback) {
    elem.addEventListener(eventType, function (event) {
      callback(elem, event);
    });
  };
}();

Yacs.views.header = function () {
  var homeButton = document.getElementById('page-title');
  var searchbar = document.getElementById('searchbar');
  var scheduleButton = document.getElementById("schedule-btn");
  Yacs.on('click', homeButton, function () { Yacs.views.departments(); });
  Yacs.on('click', scheduleButton, function () { Yacs.views.schedule(); });
  Yacs.on('keydown', document, function (elem, event) {
    var key = event.keyCode;
    if (!(event.ctrlKey || event.metaKey)) {
      if (key >= 32 && key <= 127) {
        if (key == 127 && searchbar.value.length <= 1)
          Yacs.views.departments();
        searchbar.focus();
      } else if (key == 13) {
        if (searchbar.value) {
          Yacs.models.courses.query({ search: searchbar.value }, function (data, success) {
            if (success)
              Yacs.views.courses(data);
          });
        } else {
          Yacs.views.departments();
        }
      } else if ((key == 8 || key == 46) && searchbar.value.length <= 1) {
        Yacs.views.departments();
      }
    }
  });
};

/* ======================================================================== *
    Initializers
 * ======================================================================== */

Yacs.onload(function () {
  Yacs.models.schools.preload(function (data) {
    Yacs.views.departments(data);
  });
  Yacs.views.header();
});
<|endoftext|>


<commit_before>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

(function() {

    'use strict';

    /**
     * @ngdoc service
     * @name requisition-view.requisitionViewFactory
     *
     * @description
     * Takes a requisition and determines what the user is able to view.
     */
    angular
        .module('requisition-view')
        .factory('requisitionViewFactory', factory);

    factory.$inject = ['$q', 'permissionService', 'REQUISITION_RIGHTS'];

    function factory($q, permissionService, REQUISITION_RIGHTS) {

        var factory = {
            canSubmit: canSubmit,
            canAuthorize: canAuthorize,
            canApproveAndReject: canApproveAndReject,
            canDelete: canDelete,
            canSkip: canSkip,
            canSync: canSync
        }
        return factory;

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canSubmit
         *
         * @description
         * Determines whether the user can submit or not. Returns true only if requisition
         * is initiated/rejected and user has permission to create requisition.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user submit this requisition
         */
        function canSubmit(userId, requisition) {
            if (requisition.$isInitiated() || requisition.$isRejected()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canAuthorize
         *
         * @description
         * Determines whether the user can authorize or not. Returns true only if requisition
         * is submitted and user has permission to authorize requisition.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user authorize this requisition
         */
        function canAuthorize(userId, requisition) {
            if (requisition.$isSubmitted()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_AUTHORIZE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canApproveAndReject
         *
         * @description
         * Determines whether the user can approve and reject or not. Returns true only if
         * requisition is authorized or in approval and user has permission to approve requisition.
         *
         * @param  {String} user user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user approve and reject this requisition
         */
        function canApproveAndReject(user, requisition) {
            if (requisition.$isAuthorized() || requisition.$isInApproval()) {
                return hasRightForProgramAndFacility(user.id, REQUISITION_RIGHTS.REQUISITION_APPROVE, requisition.program.id, requisition.facility.id)
                    .then(function (result) {
                        return result && user.getRoleAssignments(undefined, requisition.supervisoryNode, requisition.program.id).length > 0
                    });
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canDelete
         *
         * @description
         * Determines whether the user can delete or not. Returns true only if
         * user has permission to delete requisition. User needs to have create right when
         * requisition is initiated and authorize right when requisition is in submitted state.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user delete this requisition
         */
        function canDelete(userId, requisition) {
            if (requisition.$isInitiated() || requisition.$isRejected() || requisition.$isSkipped()) {
                return $q.all([
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_DELETE, requisition.program.id, requisition.facility.id),
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id)
                ]).then(function(responses) {
                    var hasDeleteRight = responses[0],
                        hasCreateRight = responses[1];

                    if (hasDeleteRight && hasCreateRight) {
                        return $q.resolve(true);
                    } else {
                        return $q.resolve(false);
                    }
                });
            } else if (requisition.$isSubmitted()) {
                return $q.all([
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_DELETE, requisition.program.id, requisition.facility.id),
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_AUTHORIZE, requisition.program.id, requisition.facility.id)
                ]).then(function(responses) {
                    var hasDeleteRight = responses[0],
                        hasAuthorizeRight = responses[1];

                    if (hasDeleteRight && hasAuthorizeRight) {
                        return $q.resolve(true);
                    } else {
                        return $q.resolve(false);
                    }
                });
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canSkip
         *
         * @description
         * Determines whether the user can skip requisition or not.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user skip this requisition
         */
        function canSkip(userId, requisition) {
            if ((requisition.$isInitiated() || requisition.$isRejected()) &&
                requisition.program.periodsSkippable &&
                !requisition.emergency) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canSync
         *
         * @description
         * Determines whether the user can sync with server or not.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user sync this requisition
         */
        function canSync(userId, requisition) {
            if (requisition.$isInitiated() || requisition.$isRejected()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id);
            } else if (requisition.$isSubmitted()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_AUTHORIZE, requisition.program.id, requisition.facility.id);
            } else if (requisition.$isAuthorized() || requisition.$isInApproval()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_APPROVE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        function hasRightForProgramAndFacility(userId, rightName, programId, facilityId) {
            return permissionService.hasPermission(userId, {
                right: rightName,
                programId: programId,
                facilityId: facilityId
            })
            .then(function() {
                return $q.resolve(true);
            })
            .catch(function() {
                return $q.resolve(false);
            });
        }
    }

})();
<commit_msg>OLMIS-5134: added missing semicolon<commit_after>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

(function() {

    'use strict';

    /**
     * @ngdoc service
     * @name requisition-view.requisitionViewFactory
     *
     * @description
     * Takes a requisition and determines what the user is able to view.
     */
    angular
        .module('requisition-view')
        .factory('requisitionViewFactory', factory);

    factory.$inject = ['$q', 'permissionService', 'REQUISITION_RIGHTS'];

    function factory($q, permissionService, REQUISITION_RIGHTS) {

        var factory = {
            canSubmit: canSubmit,
            canAuthorize: canAuthorize,
            canApproveAndReject: canApproveAndReject,
            canDelete: canDelete,
            canSkip: canSkip,
            canSync: canSync
        }
        return factory;

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canSubmit
         *
         * @description
         * Determines whether the user can submit or not. Returns true only if requisition
         * is initiated/rejected and user has permission to create requisition.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user submit this requisition
         */
        function canSubmit(userId, requisition) {
            if (requisition.$isInitiated() || requisition.$isRejected()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canAuthorize
         *
         * @description
         * Determines whether the user can authorize or not. Returns true only if requisition
         * is submitted and user has permission to authorize requisition.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user authorize this requisition
         */
        function canAuthorize(userId, requisition) {
            if (requisition.$isSubmitted()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_AUTHORIZE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canApproveAndReject
         *
         * @description
         * Determines whether the user can approve and reject or not. Returns true only if
         * requisition is authorized or in approval and user has permission to approve requisition.
         *
         * @param  {String} user user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user approve and reject this requisition
         */
        function canApproveAndReject(user, requisition) {
            if (requisition.$isAuthorized() || requisition.$isInApproval()) {
                return hasRightForProgramAndFacility(user.id, REQUISITION_RIGHTS.REQUISITION_APPROVE, requisition.program.id, requisition.facility.id)
                    .then(function (result) {
                        return result && user.getRoleAssignments(undefined, requisition.supervisoryNode, requisition.program.id).length > 0;
                    });
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canDelete
         *
         * @description
         * Determines whether the user can delete or not. Returns true only if
         * user has permission to delete requisition. User needs to have create right when
         * requisition is initiated and authorize right when requisition is in submitted state.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user delete this requisition
         */
        function canDelete(userId, requisition) {
            if (requisition.$isInitiated() || requisition.$isRejected() || requisition.$isSkipped()) {
                return $q.all([
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_DELETE, requisition.program.id, requisition.facility.id),
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id)
                ]).then(function(responses) {
                    var hasDeleteRight = responses[0],
                        hasCreateRight = responses[1];

                    if (hasDeleteRight && hasCreateRight) {
                        return $q.resolve(true);
                    } else {
                        return $q.resolve(false);
                    }
                });
            } else if (requisition.$isSubmitted()) {
                return $q.all([
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_DELETE, requisition.program.id, requisition.facility.id),
                    hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_AUTHORIZE, requisition.program.id, requisition.facility.id)
                ]).then(function(responses) {
                    var hasDeleteRight = responses[0],
                        hasAuthorizeRight = responses[1];

                    if (hasDeleteRight && hasAuthorizeRight) {
                        return $q.resolve(true);
                    } else {
                        return $q.resolve(false);
                    }
                });
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canSkip
         *
         * @description
         * Determines whether the user can skip requisition or not.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user skip this requisition
         */
        function canSkip(userId, requisition) {
            if ((requisition.$isInitiated() || requisition.$isRejected()) &&
                requisition.program.periodsSkippable &&
                !requisition.emergency) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        /**
         * @ngdoc method
         * @methodOf requisition-view.requisitionViewFactory
         * @name canSync
         *
         * @description
         * Determines whether the user can sync with server or not.
         *
         * @param  {String} userId id of user to check
         * @param  {Object} requisition requisition to check
         * @return {Boolean} can user sync this requisition
         */
        function canSync(userId, requisition) {
            if (requisition.$isInitiated() || requisition.$isRejected()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_CREATE, requisition.program.id, requisition.facility.id);
            } else if (requisition.$isSubmitted()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_AUTHORIZE, requisition.program.id, requisition.facility.id);
            } else if (requisition.$isAuthorized() || requisition.$isInApproval()) {
                return hasRightForProgramAndFacility(userId, REQUISITION_RIGHTS.REQUISITION_APPROVE, requisition.program.id, requisition.facility.id);
            } else {
                return $q.resolve(false);
            }
        }

        function hasRightForProgramAndFacility(userId, rightName, programId, facilityId) {
            return permissionService.hasPermission(userId, {
                right: rightName,
                programId: programId,
                facilityId: facilityId
            })
            .then(function() {
                return $q.resolve(true);
            })
            .catch(function() {
                return $q.resolve(false);
            });
        }
    }

})();
<|endoftext|>


<commit_before>// @flow

import React from 'react';
import cx from 'classnames';
import RandomQuote from '../RandomQuote';
import Flex from 'app/components/Layout/Flex';
import { Image } from 'app/components/Image';
import bekkLogo from 'app/assets/bekk_white.png';

// CSS
import styles from './Footer.css';
import { hiddenOnMobile } from 'app/styles/utilities.css';

type Props = {
  loggedIn: boolean
};

const Footer = (props: Props) => (

      <Flex column>
        <Flex row>

Lego

              Velkommen til LEGO, den nye nettsiden til Abakus. Vi i Webkom har
              arbeidet lenge med denne siden og håper den faller i smak.
              Spørsmål eller rapportering av feil gjøres til{' '}
              webkom@abakus.no.

            <RandomQuote loggedIn={props.loggedIn} />

Kontakt oss

            abakus@abakus.no

Abakus

Sem Sælands vei 7-9

7034 Trondheim

        </Flex>
        <Image className={styles.bekk} src={bekkLogo} />
      </Flex>

);

export default Footer;
<commit_msg>Remove invalid prop in Flex container in Footer<commit_after>// @flow

import React from 'react';
import cx from 'classnames';
import RandomQuote from '../RandomQuote';
import Flex from 'app/components/Layout/Flex';
import { Image } from 'app/components/Image';
import bekkLogo from 'app/assets/bekk_white.png';

// CSS
import styles from './Footer.css';
import { hiddenOnMobile } from 'app/styles/utilities.css';

type Props = {
  loggedIn: boolean
};

const Footer = (props: Props) => (

      <Flex column>
        <Flex>

Lego

              Velkommen til LEGO, den nye nettsiden til Abakus. Vi i Webkom har
              arbeidet lenge med denne siden og håper den faller i smak.
              Spørsmål eller rapportering av feil gjøres til{' '}
              webkom@abakus.no.

            <RandomQuote loggedIn={props.loggedIn} />

Kontakt oss

            abakus@abakus.no

Abakus

Sem Sælands vei 7-9

7034 Trondheim

        </Flex>
        <Image className={styles.bekk} src={bekkLogo} />
      </Flex>

);

export default Footer;
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import purebem from 'purebem';

const block = purebem.of('pending-count');

const PendingCount = React.createClass({

    propTypes: {
        ownerId: PropTypes.string.isRequired,
        pending: PropTypes.number.isRequired,
        userId: PropTypes.string.isRequired
    },

    render() {
        const { ownerId, pendingCount, userId } = this.props;

        if (ownerId !== userId || pending === 0) {
            return null;
        }

        return (
            { pending }
        );
    }

});

export default PendingCount;
<commit_msg>connect PendingCount but keep local state for now<commit_after>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import purebem from 'purebem';

import { firebase } from 'app/firebase';
import { filter } from 'app/lodash';

const block = purebem.of('pending-count');

const PendingCount = React.createClass({

    propTypes: {
        project: PropTypes.object.isRequired,
        user: PropTypes.shape({
            uid: PropTypes.string,
            name: PropTypes.string,
            email: PropTypes.string,
            photoURL: PropTypes.string
        }).isRequired
    },

    getInitialState() {
        return {
            pending: 0
        };
    },

    componentWillMount() {
        const { pid } = this.props.project;
        firebase.database().ref(`members/${pid}`).on('value', (snap) => {
            const pending = filter(snap.val(), { 'role': 'pending' }).length;
            this.setState({ pending });
        });
    },

    render() {
        const { project, user } = this.props;

        if (project.uid !== user.uid || this.state.pending === 0) {
            return null;
        }

        return (
            { this.state.pending }
        );
    }

});

const mapStateToProps = (state) => {
    return {
        user: state.user
    };
};

export default connect(mapStateToProps)(PendingCount);
<|endoftext|>


<commit_before>'use strict';

module.exports =

/*@ngInject*/
function ProofreadingPlayCtrl(
  $scope, $state, ProofreadingService, RuleService, _
) {
  $scope.id = $state.params.id;

  function error(e) {
    $state.go('index');
  }

  /* Returns null or an array of matches */
  //TODO Only looking for line break tags right now
  function htmlMatches(text) {
    if (!text) {
      return null;
    }
    return text.match(/<\s*br\s*?\/>/g);
  }

  function prepareProofreading(pf) {
    $scope.passageQuestions = {};
    pf.replace(/{\+([^-]+)-([^|]+)\|([^}]+)}/g, function(key, plus, minus, ruleNumber) {
      $scope.passageQuestions[key] = {
        plus: plus,
        minus: minus,
        ruleNumber: ruleNumber
      };
      pf = pf.replace(key, minus.split(/\s/).join('|'));
    });
    var prepared = _.chain(pf.split(/\s/))
      .filter(function removeNullWords(n) {
        return n !== '';
      })
      .map(function parseHtmlTokens(w) {
        var matches = htmlMatches(w);
        if (matches) {
          _.each(matches, function(match) {
            if (w !== match) {
              w = w.replace(new RegExp(match, 'g'), ' ' + match + ' ');
            }
          });
          w = w.trim();
          return w.split(/\s/);
        }
        return w;
      })
      .flatten()
      .map(function parseHangingPfQuestionsWithNoSpace(w) {
        _.each($scope.passageQuestions, function(v, key) {
          if (w !== key && w.indexOf(key) !== -1) {
            w = w.split(key).join(' ' + key).split(/\s/);
          }
        });
        return w;
      })
      .flatten()
      .map(function(w) {
        w = w.replace(/\|/g, ' ');
        var passageQuestion = _.findWhere($scope.passageQuestions, {minus: w});
        if (passageQuestion) {
          var c = _.clone(passageQuestion);
          c.text = c.minus;
          c.responseText = c.text;
          return c;
        } else {
          return {
            text: w,
            responseText: w
          };
        }
      })
      .map(function trim(w) {
        w.text = w.text.trim();
        w.responseText = w.responseText.trim();
        return w;
      })
      .value();

    return prepared;

  }

  $scope.obscure = function(key) {
    return btoa(key);
  };

  $scope.ubObscure = function(o) {
    return atob(o);
  };

  ProofreadingService.getProofreading($scope.id).then(function(pf) {
    pf.passage = prepareProofreading(pf.passage);
    $scope.pf = pf;
  }, error);

  $scope.submitPassage = function(passage) {
    function isValid(passageEntry) {
      if (_.has(passageEntry, 'minus')) {
        //A grammar entry
        return passageEntry.responseText === passageEntry.plus;
      } else {
        //A regular word
        return passageEntry.text === passageEntry.responseText;
      }
    }
    var errors = [];
    _.each(passage, function(p) {
      if (!isValid(p)) {
        errors.push(p);
      }
    });
    if (errors.length > 1) {
      showErrors(errors);
    } else {
      showNext();
    }
  };

  $scope.isBr = function(text) {
    return htmlMatches(text) !== null;
  };

  function showErrors(errors) {
    $scope.errors = errors;
  }

  function showNext() {

  }
};
<commit_msg>Remove tokens that are only spaces.<commit_after>'use strict';

module.exports =

/*@ngInject*/
function ProofreadingPlayCtrl(
  $scope, $state, ProofreadingService, RuleService, _
) {
  $scope.id = $state.params.id;

  function error(e) {
    $state.go('index');
  }

  /* Returns null or an array of matches */
  //TODO Only looking for line break tags right now
  function htmlMatches(text) {
    if (!text) {
      return null;
    }
    return text.match(/<\s*br\s*?\/>/g);
  }

  function prepareProofreading(pf) {
    $scope.passageQuestions = {};
    pf.replace(/{\+([^-]+)-([^|]+)\|([^}]+)}/g, function(key, plus, minus, ruleNumber) {
      $scope.passageQuestions[key] = {
        plus: plus,
        minus: minus,
        ruleNumber: ruleNumber
      };
      pf = pf.replace(key, minus.split(/\s/).join('|'));
    });
    var prepared = _.chain(pf.split(/\s/))
      .filter(function removeNullWords(n) {
        return n !== '';
      })
      .map(function parseHtmlTokens(w) {
        var matches = htmlMatches(w);
        if (matches) {
          _.each(matches, function(match) {
            if (w !== match) {
              w = w.replace(new RegExp(match, 'g'), ' ' + match + ' ');
            }
          });
          w = w.trim();
          return w.split(/\s/);
        }
        return w;
      })
      .flatten()
      .map(function parseHangingPfQuestionsWithNoSpace(w) {
        _.each($scope.passageQuestions, function(v, key) {
          if (w !== key && w.indexOf(key) !== -1) {
            w = w.split(key).join(' ' + key).split(/\s/);
          }
        });
        return w;
      })
      .flatten()
      .map(function(w) {
        w = w.replace(/\|/g, ' ');
        var passageQuestion = _.findWhere($scope.passageQuestions, {minus: w});
        if (passageQuestion) {
          var c = _.clone(passageQuestion);
          c.text = c.minus;
          c.responseText = c.text;
          return c;
        } else {
          return {
            text: w,
            responseText: w
          };
        }
      })
      .map(function trim(w) {
        w.text = w.text.trim();
        w.responseText = w.responseText.trim();
        return w;
      })
      .filter(function removeSpaces(w) {
        return w.text !== '';
      })
      .value();

    return prepared;

  }

  $scope.obscure = function(key) {
    return btoa(key);
  };

  $scope.ubObscure = function(o) {
    return atob(o);
  };

  ProofreadingService.getProofreading($scope.id).then(function(pf) {
    pf.passage = prepareProofreading(pf.passage);
    $scope.pf = pf;
  }, error);

  $scope.submitPassage = function(passage) {
    function isValid(passageEntry) {
      if (_.has(passageEntry, 'minus')) {
        //A grammar entry
        return passageEntry.responseText === passageEntry.plus;
      } else {
        //A regular word
        return passageEntry.text === passageEntry.responseText;
      }
    }
    var errors = [];
    _.each(passage, function(p) {
      if (!isValid(p)) {
        errors.push(p);
      }
    });
    if (errors.length > 1) {
      showErrors(errors);
    } else {
      showNext();
    }
  };

  $scope.isBr = function(text) {
    return htmlMatches(text) !== null;
  };

  function showErrors(errors) {
    $scope.errors = errors;
  }

  function showNext() {

  }
};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';

import './index.css';

const Search = React.createClass({
  propTypes: {
    onChange: PropTypes.func.isRequired,
  },

  render() {
    return (

        <input
          type="search"
          placeholder="Search"
          className="Search-input"
          onChange={(event) => this.props.onChange(event.target.value)}
        />

    );
  },
});

export default Search;
<commit_msg>Add autofocus to search input field<commit_after>import React, { PropTypes } from 'react';

import './index.css';

const Search = React.createClass({
  propTypes: {
    onChange: PropTypes.func.isRequired,
  },

  render() {
    return (

        <input
          type="search"
          placeholder="Search"
          className="Search-input"
          onChange={(event) => this.props.onChange(event.target.value)}
          autoFocus
        />

    );
  },
});

export default Search;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import _ from 'lodash';
import bows from 'bows';
import moment from 'moment';
import sundial from 'sundial';
import { translate, Trans } from 'react-i18next';
import ClipboardButton from 'react-clipboard.js';

// tideline dependencies & plugins
import tidelineBlip from 'tideline/plugins/blip';
const BasicsChart = tidelineBlip.basics;

import { components as vizComponents, utils as vizUtils } from '@tidepool/viz';
const Loader = vizComponents.Loader;
const getTimezoneFromTimePrefs = vizUtils.datetime.getTimezoneFromTimePrefs;
const getLocalizedCeiling = vizUtils.datetime.getLocalizedCeiling;

import Stats from './stats';
import BgSourceToggle from './bgSourceToggle';
import Header from './header';
import Footer from './footer';
import { BG_DATA_TYPES } from '../../core/constants';
import basicsText from './basicsText';

class Basics extends Component {
  static propTypes = {
    bgPrefs: React.PropTypes.object.isRequired,
    bgSource: React.PropTypes.oneOf(BG_DATA_TYPES),
    chartPrefs: React.PropTypes.object.isRequired,
    dataUtil: React.PropTypes.object,
    endpoints: React.PropTypes.arrayOf(React.PropTypes.string),
    timePrefs: React.PropTypes.object.isRequired,
    patient: React.PropTypes.object,
    patientData: React.PropTypes.object.isRequired,
    pdf: React.PropTypes.object.isRequired,
    permsOfLoggedInUser: React.PropTypes.object.isRequired,
    onClickRefresh: React.PropTypes.func.isRequired,
    onClickNoDataRefresh: React.PropTypes.func.isRequired,
    onSwitchToBasics: React.PropTypes.func.isRequired,
    onSwitchToDaily: React.PropTypes.func.isRequired,
    onClickPrint: React.PropTypes.func.isRequired,
    onSwitchToSettings: React.PropTypes.func.isRequired,
    onSwitchToBgLog: React.PropTypes.func.isRequired,
    onUpdateChartDateRange: React.PropTypes.func.isRequired,
    trackMetric: React.PropTypes.func.isRequired,
    updateBasicsData: React.PropTypes.func.isRequired,
    updateBasicsSettings: React.PropTypes.func.isRequired,
    updateChartPrefs: React.PropTypes.func.isRequired,
    uploadUrl: React.PropTypes.string.isRequired,
  };

  static displayName = 'Basics';

  constructor(props) {
    super(props);
    this.chartType = 'basics';
    this.log = bows('Basics View');

    this.state = this.getInitialState();
  }

  getInitialState = () => ({
    atMostRecent: true,
    inTransition: false,
    title: this.getTitle(),
  });

  componentWillMount = () => {
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');

    if (dateRange) {
      const endpoints = [
        dateRange[0],
        getLocalizedCeiling(dateRange[1], this.props.timePrefs).toISOString(),
      ];

      this.props.onUpdateChartDateRange(endpoints);
    }
  };

  render = () => {
    return (

        <Header
          chartType={this.chartType}
          patient={this.props.patient}
          printReady={!!this.props.pdf.url}
          atMostRecent={true}
          inTransition={this.state.inTransition}
          title={this.state.title}
          onClickBasics={this.handleClickBasics}
          onClickOneDay={this.handleClickOneDay}
          onClickTrends={this.handleClickTrends}
          onClickRefresh={this.props.onClickRefresh}
          onClickSettings={this.props.onSwitchToSettings}
          onClickBgLog={this.handleClickBgLog}
          onClickPrint={this.handleClickPrint}
        ref="header" />

              <Loader show={this.props.loading} overlay={true} />
              {this.isMissingBasics() ? this.renderMissingBasicsMessage() : this.renderChart()}

                <ClipboardButton
                  className='copyButton'
                  button-title={'For email or notes'}
                  data-clipboard-target="#copyBasicsText"
                  onSuccess = {this.copyBasicsClicked}
                >

{'Copy as text'}

                </ClipboardButton>

                   {basicsText(this.props.patient, this.props.patientData, this.props.dataUtil, this.props.chartPrefs)}

                <BgSourceToggle
                  bgSource={this.props.dataUtil.bgSource}
                  bgSources={this.props.dataUtil.bgSources}
                  chartPrefs={this.props.chartPrefs}
                  chartType={this.chartType}
                  onClickBgSourceToggle={this.toggleBgDataSource}
                />
                <Stats
                  bgPrefs={this.props.bgPrefs}
                  bgSource={this.props.dataUtil.bgSource}
                  chartPrefs={this.props.chartPrefs}
                  chartType={this.chartType}
                  dataUtil={this.props.dataUtil}
                  endpoints={this.props.endpoints}
                  onAverageDailyDoseInputChange={this.handleAverageDailyDoseInputChange}
                />

      );
  };

  renderChart = () => {
    return (

        <BasicsChart
          bgClasses={this.props.bgPrefs.bgClasses}
          bgUnits={this.props.bgPrefs.bgUnits}
          onSelectDay={this.handleSelectDay}
          patient={this.props.patient}
          patientData={this.props.patientData}
          permsOfLoggedInUser={this.props.permsOfLoggedInUser}
          timePrefs={this.props.timePrefs}
          updateBasicsData={this.props.updateBasicsData}
          updateBasicsSettings={this.props.updateBasicsSettings}
          ref="chart"
          trackMetric={this.props.trackMetric} />

    );
  };

  renderMissingBasicsMessage = () => {
    const self = this;
    const { t } = this.props;
    const handleClickUpload = function() {
      self.props.trackMetric('Clicked Partial Data Upload, No Pump Data for Basics');
    };

    return (
      <Trans className="patient-data-message patient-data-message-loading" i18nKey="html.basics-no-uploaded-data">

The Basics view shows a summary of your recent device activity, but it looks like you haven't uploaded device data yet.

To see the Basics, upload some device data.

If you just uploaded, try refreshing.

      </Trans>
    );
  };

  getTitle = () => {
    const { t } = this.props;
    if (this.isMissingBasics()) {
      return '';
    }
    const timePrefs = this.props.timePrefs
    let timezone;
    if (!timePrefs.timezoneAware) {
      timezone = 'UTC';
    }
    else {
      timezone = timePrefs.timezoneName || 'UTC';
    }
    const basicsData = this.props.patientData.basicsData;
    const dtMask = t('MMM D, YYYY');

    return sundial.formatInTimezone(basicsData.dateRange[0], timezone, dtMask) +
      ' - ' + sundial.formatInTimezone(basicsData.dateRange[1], timezone, dtMask);
  }

  isMissingBasics = () => {
    const basicsData = _.get(this.props, 'patientData.basicsData', {});
    let data;

    if (basicsData.data) {
      data = basicsData.data;
    }
    else {
      return true;
    }

    // require at least one relevant data point to show The Basics
    const basicsDataLength = _.flatten(_.map(_.values(data), 'data')).length;
    return basicsDataLength === 0;
  };

  // handlers
  toggleBgDataSource = (e, bgSource) => {
    if (e) {
      e.preventDefault();
    }

    const bgSourceLabel = bgSource === 'cbg' ? 'CGM' : 'BGM';
    this.props.trackMetric(`Basics Click to ${bgSourceLabel}`);

    const prefs = _.cloneDeep(this.props.chartPrefs);
    prefs.basics.bgSource = bgSource;
    this.props.updateChartPrefs(prefs);
  };

  handleAverageDailyDoseInputChange = (inputValue, suffixValue) => {
    const prefs = _.cloneDeep(this.props.chartPrefs);
    prefs.basics.averageDailyDose = {
      inputValue,
      suffixValue,
    };
    this.props.updateChartPrefs(prefs);
  };

  handleClickBasics = e => {
    if (e) {
      e.preventDefault();
    }
    return;
  };

  handleClickTrends = e => {
    if (e) {
      e.preventDefault();
    }
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');
    this.props.onSwitchToTrends(dateRange[1]);
  };

  handleClickOneDay = e => {
    if (e) {
      e.preventDefault();
    }
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');
    this.props.onSwitchToDaily(dateRange[1]);
  };

  handleClickPrint = e => {
    if (e) {
      e.preventDefault();
    }

    this.props.onClickPrint(this.props.pdf);
  };

  handleClickBgLog = e => {
    if (e) {
      e.preventDefault();
    }
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');
    this.props.onSwitchToBgLog(dateRange[1]);
  };

  handleSelectDay = (date, title) => {
    this.props.onSwitchToDaily(date, title);
  };

  copyBasicsClicked = () => {
    this.props.trackMetric('Clicked Basics Settings');
  };
};

export default translate()(Basics);
<commit_msg>Small formatting cleanup for copybutton markup<commit_after>import React, { Component } from 'react';
import _ from 'lodash';
import bows from 'bows';
import moment from 'moment';
import sundial from 'sundial';
import { translate, Trans } from 'react-i18next';
import ClipboardButton from 'react-clipboard.js';

// tideline dependencies & plugins
import tidelineBlip from 'tideline/plugins/blip';
const BasicsChart = tidelineBlip.basics;

import { components as vizComponents, utils as vizUtils } from '@tidepool/viz';
const Loader = vizComponents.Loader;
const getTimezoneFromTimePrefs = vizUtils.datetime.getTimezoneFromTimePrefs;
const getLocalizedCeiling = vizUtils.datetime.getLocalizedCeiling;

import Stats from './stats';
import BgSourceToggle from './bgSourceToggle';
import Header from './header';
import Footer from './footer';
import { BG_DATA_TYPES } from '../../core/constants';
import basicsText from './basicsText';

class Basics extends Component {
  static propTypes = {
    bgPrefs: React.PropTypes.object.isRequired,
    bgSource: React.PropTypes.oneOf(BG_DATA_TYPES),
    chartPrefs: React.PropTypes.object.isRequired,
    dataUtil: React.PropTypes.object,
    endpoints: React.PropTypes.arrayOf(React.PropTypes.string),
    timePrefs: React.PropTypes.object.isRequired,
    patient: React.PropTypes.object,
    patientData: React.PropTypes.object.isRequired,
    pdf: React.PropTypes.object.isRequired,
    permsOfLoggedInUser: React.PropTypes.object.isRequired,
    onClickRefresh: React.PropTypes.func.isRequired,
    onClickNoDataRefresh: React.PropTypes.func.isRequired,
    onSwitchToBasics: React.PropTypes.func.isRequired,
    onSwitchToDaily: React.PropTypes.func.isRequired,
    onClickPrint: React.PropTypes.func.isRequired,
    onSwitchToSettings: React.PropTypes.func.isRequired,
    onSwitchToBgLog: React.PropTypes.func.isRequired,
    onUpdateChartDateRange: React.PropTypes.func.isRequired,
    trackMetric: React.PropTypes.func.isRequired,
    updateBasicsData: React.PropTypes.func.isRequired,
    updateBasicsSettings: React.PropTypes.func.isRequired,
    updateChartPrefs: React.PropTypes.func.isRequired,
    uploadUrl: React.PropTypes.string.isRequired,
  };

  static displayName = 'Basics';

  constructor(props) {
    super(props);
    this.chartType = 'basics';
    this.log = bows('Basics View');

    this.state = this.getInitialState();
  }

  getInitialState = () => ({
    atMostRecent: true,
    inTransition: false,
    title: this.getTitle(),
  });

  componentWillMount = () => {
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');

    if (dateRange) {
      const endpoints = [
        dateRange[0],
        getLocalizedCeiling(dateRange[1], this.props.timePrefs).toISOString(),
      ];

      this.props.onUpdateChartDateRange(endpoints);
    }
  };

  render = () => {
    return (

        <Header
          chartType={this.chartType}
          patient={this.props.patient}
          printReady={!!this.props.pdf.url}
          atMostRecent={true}
          inTransition={this.state.inTransition}
          title={this.state.title}
          onClickBasics={this.handleClickBasics}
          onClickOneDay={this.handleClickOneDay}
          onClickTrends={this.handleClickTrends}
          onClickRefresh={this.props.onClickRefresh}
          onClickSettings={this.props.onSwitchToSettings}
          onClickBgLog={this.handleClickBgLog}
          onClickPrint={this.handleClickPrint}
        ref="header" />

              <Loader show={this.props.loading} overlay={true} />
              {this.isMissingBasics() ? this.renderMissingBasicsMessage() : this.renderChart()}

                <ClipboardButton
                  className='copyButton'
                  button-title={'For email or notes'}
                  data-clipboard-target="#copyBasicsText"
                  onSuccess = {this.copyBasicsClicked}
                >

{'Copy as text'}

                </ClipboardButton>

                   {basicsText(this.props.patient, this.props.patientData, this.props.dataUtil, this.props.chartPrefs)}

                <BgSourceToggle
                  bgSource={this.props.dataUtil.bgSource}
                  bgSources={this.props.dataUtil.bgSources}
                  chartPrefs={this.props.chartPrefs}
                  chartType={this.chartType}
                  onClickBgSourceToggle={this.toggleBgDataSource}
                />
                <Stats
                  bgPrefs={this.props.bgPrefs}
                  bgSource={this.props.dataUtil.bgSource}
                  chartPrefs={this.props.chartPrefs}
                  chartType={this.chartType}
                  dataUtil={this.props.dataUtil}
                  endpoints={this.props.endpoints}
                  onAverageDailyDoseInputChange={this.handleAverageDailyDoseInputChange}
                />

      );
  };

  renderChart = () => {
    return (

        <BasicsChart
          bgClasses={this.props.bgPrefs.bgClasses}
          bgUnits={this.props.bgPrefs.bgUnits}
          onSelectDay={this.handleSelectDay}
          patient={this.props.patient}
          patientData={this.props.patientData}
          permsOfLoggedInUser={this.props.permsOfLoggedInUser}
          timePrefs={this.props.timePrefs}
          updateBasicsData={this.props.updateBasicsData}
          updateBasicsSettings={this.props.updateBasicsSettings}
          ref="chart"
          trackMetric={this.props.trackMetric} />

    );
  };

  renderMissingBasicsMessage = () => {
    const self = this;
    const { t } = this.props;
    const handleClickUpload = function() {
      self.props.trackMetric('Clicked Partial Data Upload, No Pump Data for Basics');
    };

    return (
      <Trans className="patient-data-message patient-data-message-loading" i18nKey="html.basics-no-uploaded-data">

The Basics view shows a summary of your recent device activity, but it looks like you haven't uploaded device data yet.

To see the Basics, upload some device data.

If you just uploaded, try refreshing.

      </Trans>
    );
  };

  getTitle = () => {
    const { t } = this.props;
    if (this.isMissingBasics()) {
      return '';
    }
    const timePrefs = this.props.timePrefs
    let timezone;
    if (!timePrefs.timezoneAware) {
      timezone = 'UTC';
    }
    else {
      timezone = timePrefs.timezoneName || 'UTC';
    }
    const basicsData = this.props.patientData.basicsData;
    const dtMask = t('MMM D, YYYY');

    return sundial.formatInTimezone(basicsData.dateRange[0], timezone, dtMask) +
      ' - ' + sundial.formatInTimezone(basicsData.dateRange[1], timezone, dtMask);
  }

  isMissingBasics = () => {
    const basicsData = _.get(this.props, 'patientData.basicsData', {});
    let data;

    if (basicsData.data) {
      data = basicsData.data;
    }
    else {
      return true;
    }

    // require at least one relevant data point to show The Basics
    const basicsDataLength = _.flatten(_.map(_.values(data), 'data')).length;
    return basicsDataLength === 0;
  };

  // handlers
  toggleBgDataSource = (e, bgSource) => {
    if (e) {
      e.preventDefault();
    }

    const bgSourceLabel = bgSource === 'cbg' ? 'CGM' : 'BGM';
    this.props.trackMetric(`Basics Click to ${bgSourceLabel}`);

    const prefs = _.cloneDeep(this.props.chartPrefs);
    prefs.basics.bgSource = bgSource;
    this.props.updateChartPrefs(prefs);
  };

  handleAverageDailyDoseInputChange = (inputValue, suffixValue) => {
    const prefs = _.cloneDeep(this.props.chartPrefs);
    prefs.basics.averageDailyDose = {
      inputValue,
      suffixValue,
    };
    this.props.updateChartPrefs(prefs);
  };

  handleClickBasics = e => {
    if (e) {
      e.preventDefault();
    }
    return;
  };

  handleClickTrends = e => {
    if (e) {
      e.preventDefault();
    }
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');
    this.props.onSwitchToTrends(dateRange[1]);
  };

  handleClickOneDay = e => {
    if (e) {
      e.preventDefault();
    }
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');
    this.props.onSwitchToDaily(dateRange[1]);
  };

  handleClickPrint = e => {
    if (e) {
      e.preventDefault();
    }

    this.props.onClickPrint(this.props.pdf);
  };

  handleClickBgLog = e => {
    if (e) {
      e.preventDefault();
    }
    const dateRange = _.get(this.props, 'patientData.basicsData.dateRange');
    this.props.onSwitchToBgLog(dateRange[1]);
  };

  handleSelectDay = (date, title) => {
    this.props.onSwitchToDaily(date, title);
  };

  copyBasicsClicked = () => {
    this.props.trackMetric('Clicked Basics Settings');
  };
};

export default translate()(Basics);
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';

const { Component, computed, RSVP, ObjectProxy, inject } = Ember;
const { PromiseArray } = DS;
const { service } = inject;

export default Component.extend({
  store: service(),
  course: null,
  includeUnpublishedSessions: false,
  tagName: 'section',
  classNames: ['printable course'],
  sortTitle: ['title'],
  sortDirectorsBy: ['lastName', 'firstName'],
  sortedDirectors: computed.sort('course.directors', 'sortDirectorsBy'),
  sortedMeshDescriptors: computed.sort('course.meshDescriptors', 'sortTitle'),
  sortedSessionProxies: computed('course.sessions.[]', function(){
    const course = this.get('course');
    if(!course){
      return [];
    }
    let deferred = RSVP.defer();
    let SessionProxy = ObjectProxy.extend({
      sortTitle: ['title'],
      sortedMeshDescriptors: computed.sort('content.meshDescriptors', 'sortTitle'),
      sessionLearningMaterials: computed('content', function(){
        let session = this.get('content').get('id');
        return this.get('store').query('sessionLearningMaterial', {
          filters: {
            session
          }
        });
      })
    });
    course.get('sessions').then(sessions => {
      if (!this.get('includeUnpublishedSessions')) {
        sessions = sessions.filterBy('isPublishedOrScheduled');
      }
      let proxiedSessions = sessions.map(function(session){
        return SessionProxy.create({
          content: session
        });
      });
      deferred.resolve(proxiedSessions.sortBy('title'));
    });

    return PromiseArray.create({
      promise: deferred.promise
    });

  }),

  courseLearningMaterials: computed('course', function(){
    let course = this.get('course').get('id');
    return this.get('store').query('courseLearningMaterial', {
      filters: {
        course
      }
    });
  }),

});
<commit_msg>replaced DS.PromiseArray with RSVP.Promise.<commit_after>import Ember from 'ember';

const { Component, computed, RSVP, ObjectProxy, inject } = Ember;
const { Promise } = RSVP;
const { service } = inject;

export default Component.extend({
  store: service(),
  course: null,
  includeUnpublishedSessions: false,
  tagName: 'section',
  classNames: ['printable course'],
  sortTitle: ['title'],
  sortDirectorsBy: ['lastName', 'firstName'],
  sortedDirectors: computed.sort('course.directors', 'sortDirectorsBy'),
  sortedMeshDescriptors: computed.sort('course.meshDescriptors', 'sortTitle'),
  sortedSessionProxies: computed('course.sessions.[]', function(){
    return new Promise(resolve => {

      const course = this.get('course');
      if(!course){
        return [];
      }

      let SessionProxy = ObjectProxy.extend({
        sortTitle: ['title'],
        sortedMeshDescriptors: computed.sort('content.meshDescriptors', 'sortTitle'),
        sessionLearningMaterials: computed('content', function(){
          let session = this.get('content').get('id');
          return this.get('store').query('sessionLearningMaterial', {
            filters: {
              session
            }
          });
        })
      });
      course.get('sessions').then(sessions => {
        if (!this.get('includeUnpublishedSessions')) {
          sessions = sessions.filterBy('isPublishedOrScheduled');
        }
        let proxiedSessions = sessions.map(function(session){
          return SessionProxy.create({
            content: session
          });
        });
        resolve(proxiedSessions.sortBy('title'));
      });

    });
  }),

  courseLearningMaterials: computed('course', function(){
    let course = this.get('course').get('id');
    return this.get('store').query('courseLearningMaterial', {
      filters: {
        course
      }
    });
  }),

});
<|endoftext|>