<commit_before>this.mmooc = this.mmooc || {};

this.mmooc.enroll = (function() {
  return {
    changeEnrollInformationPolicyLink: function() {
      var informationPolicy = $('.ic-Self-enrollment-footer__Secondary > a');
      informationPolicy.attr("href", mmooc.settings.privacyPolicyLink);
    },
    changeEnrollPage: function() {
      this.changeEnrollInformationPolicyLink();
    },
    printAllCoursesContainer: function() {
      html = mmooc.util.renderTemplateWithData('allcoursescontainer', {
        courseLabel: mmooc.i18n.CoursePlural.toLowerCase(),
        allAvailableCoursesIngress: mmooc.i18n.AllAvailableCoursesIngress,
        linkToMyCourses: mmooc.utilRoot.getLinkToMyCourses(),
        isAuthenticated: mmooc.util.isAuthenticated()
      });
      document.title = 'Tilgjengelige ' + mmooc.i18n.CoursePlural.toLowerCase();
      document.getElementById('content').innerHTML = html;
    },
    goToAllCourses() {
        $('#mmooc-all-courses-btn').click(function() {
          const linkToMyCourses = mmooc.utilRoot.getLinkToMyCourses();
          window.location.href = linkToMyCourses;
        })
    },
    printAllCourses: function() {
      var self = this;
      html = "

";
      $('.mmooc-all-courses-list').append(html);
      mmooc.api.getAllPublicCourses(function(allCourses) {
        mmooc.api.getEnrolledCourses(function(enrolledCourses) {
          var allCoursesWithStatus = mmooc.enroll.setCourseEnrolledStatus(
            allCourses,
            enrolledCourses
          );

          allCoursesWithStatusSorted = mmooc.util.sortCourses(allCoursesWithStatus);
          var categorys = mmooc.util.getCourseCategories(allCoursesWithStatusSorted);

          /* If the amount of courses is large, the filter select box and corresponding javascript code in allcoursescontainer.hbs should be enabled

          mmooc.enroll.populateFilter(categorys);

          $("#filter").change(function () {
            mmooc.enroll.applyFilter();
          });

          */

          var coursesCategorized = mmooc.util.getCoursesCategorized(
            allCoursesWithStatusSorted,
            categorys
          );

          $('.mmooc-loader-wrapper').remove();

          for (var i = 0; i < coursesCategorized.length; i++) {
            const coursesCategory = coursesCategorized[i];
            const coursesEnrolledAmount = mmooc.util.filter(
              coursesCategory.courses,
              function(course) {
                return course.enrolled === true
            }).length;
            const coursesAmount = coursesCategory.courses && coursesCategory.courses.length;

            var isAuthenticated = mmooc.util.isAuthenticated();
            var courseRegisterText = mmooc.i18n.LogInCanvas;
            if(isAuthenticated) {
              courseRegisterText = mmooc.i18n.CourseRegisterWhenAuthenticated;
            }
            html = mmooc.util.renderTemplateWithData('allcourseslist', {
              queryString: mmooc.hrefQueryString,
              title: coursesCategory.title,
              isAuthenticated: isAuthenticated,
              courses: coursesCategory.courses,
              coursesEnrolledAmount: coursesEnrolledAmount,
              coursesAmount: coursesAmount,
              coursesAmountText: mmooc.i18n.CoursesAmount(coursesAmount),
              courseLabel: mmooc.i18n.Course.toLowerCase(),
              goToCourse: mmooc.i18n.GoToCourse,
              courseRegister: courseRegisterText,
              openCoursesGroupText: mmooc.i18n.OpenCoursesGroup,
              closeCoursesGroupText: mmooc.i18n.CloseCoursesGroup,
              YouAreRegisteredToXCoursesText: mmooc.i18n.YouAreRegisteredToXCourses(coursesEnrolledAmount),
              index: i
            });
            $('.mmooc-all-courses-list').append(html);
          }

          // Displays information, that there is no current courses available to enroll
          if (coursesCategorized.length == 0) {
            html = '
' + mmooc.i18n.NoCoursesInfo + '
';
            $('.mmooc-all-courses-list').append(html);
          }

          mmooc.enroll.insertModalAndOverlay();
          mmooc.enroll.setClickHandlers();

          // TODO: move if there is a better place for this code - it handles course list UI
          // accordion UI
          $('.mmooc-accordion-header').click(event => {
            let accordionIndex = event.target.getAttribute('index');

            if (
              $(`#mmooc-accordion-header-${accordionIndex}`).hasClass(
                'mmooc-accordion-header-active'
              )
            ) {
              $(`#mmooc-accordion-header-${accordionIndex}`).toggleClass(
                'mmooc-accordion-header-active'
              );
            } else {
              $('.mmooc-accordion-header-active').removeClass(
                'mmooc-accordion-header-active'
              );

              $(`#mmooc-accordion-header-${accordionIndex}`).addClass(
                'mmooc-accordion-header-active'
              );
            }

            // remove active tabs when new accordion element is clicked
            $('.mmooc-tab-head').removeClass('mmooc-tab-head-active');
            $('.mmooc-tab-content').removeClass('mmooc-tab-content-active');
            $('.mmooc-tabs-mobile-header-active').removeClass(
              'mmooc-tabs-mobile-header-active'
            );
            $('.mmooc-tabs-mobile-content-active').removeClass(
              'mmooc-tabs-mobile-content-active'
            );

            // add active class to first tab when the accordion element is opened
            $('.mmooc-tab-head-0').addClass('mmooc-tab-head-active');
            $('.mmooc-tab-content-0').addClass('mmooc-tab-content-active');
          });

          // tabs
          $('.mmooc-tab-head').click(event => {
            let tabIndex = event.target.getAttribute('index');

            $('.mmooc-tab-head').removeClass('mmooc-tab-head-active');
            $(`#mmooc-tab-head-${tabIndex}`).addClass('mmooc-tab-head-active');

            $('.mmooc-tab-content').removeClass('mmooc-tab-content-active');
            $(`#mmooc-tab-content-${tabIndex}`).addClass(
              'mmooc-tab-content-active'
            );
          });

          // tabs-mobile

          $('.mmooc-tabs-mobile-header').click(event => {
            let mobileTabIndex = event.target.getAttribute('index');

            if (
              $(`#mmooc-tabs-mobile-header-${mobileTabIndex}`).hasClass(
                'mmooc-tabs-mobile-header-active'
              )
            ) {
              $(`#mmooc-tabs-mobile-header-${mobileTabIndex}`).toggleClass(
                'mmooc-tabs-mobile-header-active'
              );
              $(`#mmooc-tabs-mobile-content-${mobileTabIndex}`).toggleClass(
                'mmooc-tabs-mobile-content-active'
              );
            } else {
              $('.mmooc-tabs-mobile-header-active').removeClass(
                'mmooc-tabs-mobile-header-active'
              );
              $('.mmooc-tabs-mobile-content-active').removeClass(
                'mmooc-tabs-mobile-content-active'
              );

              $(`#mmooc-tabs-mobile-header-${mobileTabIndex}`).addClass(
                'mmooc-tabs-mobile-header-active'
              );
              $(`#mmooc-tabs-mobile-content-${mobileTabIndex}`).addClass(
                'mmooc-tabs-mobile-content-active'
              );
            }
          });

          self.createHashTags();
          self.scrollToCourse();
        });
      });
    },
    createHashTags: function() {
        $('span').click(function(e) {
          if ($(this).filter("[data-name='course']")) {
            var hashTag = $(e.currentTarget).attr("class")
            window.location.hash = hashTag;
          }
        });

        $("button[data-title]").click(function(e){
          var firstCourseId = $(this).siblings().find('span').eq(0).attr('class');
          var hashTag = firstCourseId;
          window.location.hash = hashTag;
        })
    },
    scrollToCourse: function () {
        var currentHash = window.location.hash.split('#');
        var courses = $('span').filter("[data-name='course']");

        courses.each(function (i, el) {
          var currentElementId = $(el).attr('class');
          if (currentHash[1] === currentElementId) {
            var categoryElement = $(el).closest('section').find('button').eq(0);
            categoryElement.trigger("click");

            var mobileViewport = window.matchMedia("(max-width: 650px)");

            if(mobileViewport.matches) {
              $([document.documentElement, document.body]).animate({
                scrollTop: $(el).find('button').offset().top
              }, 500);
            }else {
              $([document.documentElement, document.body]).animate({
                scrollTop: $("." + currentElementId).offset().top
              }, 500);
            }
            var courseTab = $(el).find('button');
            courseTab.trigger("click");
          }
        })
    },
    setCourseEnrolledStatus: function(allCourses, enrolledCourses) {
      var allCoursesWithStatus = [];
      for (var i = 0; i < allCourses.length; i++) {
        allCourses[i].course.enrolled = false;
        for (var j = 0; j < enrolledCourses.length; j++) {
          if (allCourses[i].course.id == enrolledCourses[j].id) {
            allCourses[i].course.enrolled = true;
          }
        }
        allCoursesWithStatus.push(allCourses[i].course);
      }
      return allCoursesWithStatus;
    },
    insertModalAndOverlay: function() {
      $('body').append("

");
      $('body').append("

");
    },
    handleEnrollClick: function(e, html) {
      $('.mmooc-modal').html(html);
      $('.mmooc-modal-overlay').show();
      $('.mmooc-modal').show();
      $('.mmooc-modal .modal-back').click(function(e) {
        e.preventDefault();
        $('.mmooc-modal-overlay').hide();
        $('.mmooc-modal').hide();
      });
    },
    setClickHandlers: function() {
      $('.notenrolled').click(function(e) {
        e.preventDefault();
        var html = $(this)
          .next()
          .html();
        mmooc.enroll.handleEnrollClick(e, html);
      });
      $('.all-courses-show-modal').click(function(e) {
        e.preventDefault();
        var html = $(this)
          .parent()
          .next()
          .html();
        mmooc.enroll.handleEnrollClick(e, html);
      });
      $('.mmooc-modal-overlay').click(function(e) {
        e.preventDefault();
        $('.mmooc-modal-overlay').hide();
        $('.mmooc-modal').hide();
      });
      $(document).on('keydown', function(e) {
        if (e.keyCode === 27) {
          $('.mmooc-modal-overlay').hide();
          $('.mmooc-modal').hide();
        }
      });
    },
    populateFilter: function(categorys) {
      var options =
        '<option value="Alle">Alle tilgjengelige ' +
        mmooc.i18n.CoursePlural.toLowerCase() +
        '</option>';
      for (var i = 0; i < categorys.length; i++) {
        options +=
          '<option value="' + categorys[i] + '">' + categorys[i] + '</option>';
      }
      $('#filter').append(options);
    },
    applyFilter: function() {
      var value = $('#filter').val();
      if (value == 'Alle') {
        $('.mmooc-all-courses-list').removeClass('filter-active');
        $('.mmooc-all-courses-list h2').each(function() {
          $(this).show();
          $(this)
            .next()
            .show();
        });
      } else {
        $('.mmooc-all-courses-list').addClass('filter-active');
        $('.mmooc-all-courses-list h2').each(function() {
          if ($(this).text() == value) {
            $(this).show();
            $(this)
              .next()
              .show();
          } else {
            $(this).hide();
            $(this)
              .next()
              .hide();
          }
        });
      }
    }
  };
})();
<commit_msg>Add forgot password button to enroll page<commit_after>this.mmooc = this.mmooc || {};

this.mmooc.enroll = (function() {
  return {
    changeEnrollInformationPolicyLink: function() {
      var informationPolicy = $('.ic-Self-enrollment-footer__Secondary > a');
      informationPolicy.attr("href", mmooc.settings.privacyPolicyLink);
    },
    addForgotPasswordLink: function() {
      const buttonId = 'selfEnrollmentForgotPassword';
      const forgotPasswordButtonHtml =
        '<button id="'+ buttonId +'" class="btn btn-primary" style="display: none;" type="submit">' +
        'Glemt passord?</button>';

      const parentDiv = $('.ic-Self-enrollment-footer__Primary');
      parentDiv.prepend(forgotPasswordButtonHtml);

      const forgotPasswordButton = $(`#${buttonId}`);
      forgotPasswordButton.on('click', _ => window.location = '/login/canvas?normalLogin=1&design=udir&gp');

      const alreadyHasUserButton = $('#selfEnrollmentAuthRegLogin');
      alreadyHasUserButton.on('click', _ => forgotPasswordButton.show());

      const newUserButton = $('#selfEnrollmentAuthRegCreate');
      newUserButton.on('click', _ => forgotPasswordButton.hide());
    },
    changeEnrollPage: function() {
      this.changeEnrollInformationPolicyLink();
      this.addForgotPasswordLink();
    },
    printAllCoursesContainer: function() {
      html = mmooc.util.renderTemplateWithData('allcoursescontainer', {
        courseLabel: mmooc.i18n.CoursePlural.toLowerCase(),
        allAvailableCoursesIngress: mmooc.i18n.AllAvailableCoursesIngress,
        linkToMyCourses: mmooc.utilRoot.getLinkToMyCourses(),
        isAuthenticated: mmooc.util.isAuthenticated()
      });
      document.title = 'Tilgjengelige ' + mmooc.i18n.CoursePlural.toLowerCase();
      document.getElementById('content').innerHTML = html;
    },
    goToAllCourses() {
        $('#mmooc-all-courses-btn').click(function() {
          const linkToMyCourses = mmooc.utilRoot.getLinkToMyCourses();
          window.location.href = linkToMyCourses;
        })
    },
    printAllCourses: function() {
      var self = this;
      html = "

";
      $('.mmooc-all-courses-list').append(html);
      mmooc.api.getAllPublicCourses(function(allCourses) {
        mmooc.api.getEnrolledCourses(function(enrolledCourses) {
          var allCoursesWithStatus = mmooc.enroll.setCourseEnrolledStatus(
            allCourses,
            enrolledCourses
          );

          allCoursesWithStatusSorted = mmooc.util.sortCourses(allCoursesWithStatus);
          var categorys = mmooc.util.getCourseCategories(allCoursesWithStatusSorted);

          /* If the amount of courses is large, the filter select box and corresponding javascript code in allcoursescontainer.hbs should be enabled

          mmooc.enroll.populateFilter(categorys);

          $("#filter").change(function () {
            mmooc.enroll.applyFilter();
          });

          */

          var coursesCategorized = mmooc.util.getCoursesCategorized(
            allCoursesWithStatusSorted,
            categorys
          );

          $('.mmooc-loader-wrapper').remove();

          for (var i = 0; i < coursesCategorized.length; i++) {
            const coursesCategory = coursesCategorized[i];
            const coursesEnrolledAmount = mmooc.util.filter(
              coursesCategory.courses,
              function(course) {
                return course.enrolled === true
            }).length;
            const coursesAmount = coursesCategory.courses && coursesCategory.courses.length;

            var isAuthenticated = mmooc.util.isAuthenticated();
            var courseRegisterText = mmooc.i18n.LogInCanvas;
            if(isAuthenticated) {
              courseRegisterText = mmooc.i18n.CourseRegisterWhenAuthenticated;
            }
            html = mmooc.util.renderTemplateWithData('allcourseslist', {
              queryString: mmooc.hrefQueryString,
              title: coursesCategory.title,
              isAuthenticated: isAuthenticated,
              courses: coursesCategory.courses,
              coursesEnrolledAmount: coursesEnrolledAmount,
              coursesAmount: coursesAmount,
              coursesAmountText: mmooc.i18n.CoursesAmount(coursesAmount),
              courseLabel: mmooc.i18n.Course.toLowerCase(),
              goToCourse: mmooc.i18n.GoToCourse,
              courseRegister: courseRegisterText,
              openCoursesGroupText: mmooc.i18n.OpenCoursesGroup,
              closeCoursesGroupText: mmooc.i18n.CloseCoursesGroup,
              YouAreRegisteredToXCoursesText: mmooc.i18n.YouAreRegisteredToXCourses(coursesEnrolledAmount),
              index: i
            });
            $('.mmooc-all-courses-list').append(html);
          }

          // Displays information, that there is no current courses available to enroll
          if (coursesCategorized.length == 0) {
            html = '
' + mmooc.i18n.NoCoursesInfo + '
';
            $('.mmooc-all-courses-list').append(html);
          }

          mmooc.enroll.insertModalAndOverlay();
          mmooc.enroll.setClickHandlers();

          // TODO: move if there is a better place for this code - it handles course list UI
          // accordion UI
          $('.mmooc-accordion-header').click(event => {
            let accordionIndex = event.target.getAttribute('index');

            if (
              $(`#mmooc-accordion-header-${accordionIndex}`).hasClass(
                'mmooc-accordion-header-active'
              )
            ) {
              $(`#mmooc-accordion-header-${accordionIndex}`).toggleClass(
                'mmooc-accordion-header-active'
              );
            } else {
              $('.mmooc-accordion-header-active').removeClass(
                'mmooc-accordion-header-active'
              );

              $(`#mmooc-accordion-header-${accordionIndex}`).addClass(
                'mmooc-accordion-header-active'
              );
            }

            // remove active tabs when new accordion element is clicked
            $('.mmooc-tab-head').removeClass('mmooc-tab-head-active');
            $('.mmooc-tab-content').removeClass('mmooc-tab-content-active');
            $('.mmooc-tabs-mobile-header-active').removeClass(
              'mmooc-tabs-mobile-header-active'
            );
            $('.mmooc-tabs-mobile-content-active').removeClass(
              'mmooc-tabs-mobile-content-active'
            );

            // add active class to first tab when the accordion element is opened
            $('.mmooc-tab-head-0').addClass('mmooc-tab-head-active');
            $('.mmooc-tab-content-0').addClass('mmooc-tab-content-active');
          });

          // tabs
          $('.mmooc-tab-head').click(event => {
            let tabIndex = event.target.getAttribute('index');

            $('.mmooc-tab-head').removeClass('mmooc-tab-head-active');
            $(`#mmooc-tab-head-${tabIndex}`).addClass('mmooc-tab-head-active');

            $('.mmooc-tab-content').removeClass('mmooc-tab-content-active');
            $(`#mmooc-tab-content-${tabIndex}`).addClass(
              'mmooc-tab-content-active'
            );
          });

          // tabs-mobile

          $('.mmooc-tabs-mobile-header').click(event => {
            let mobileTabIndex = event.target.getAttribute('index');

            if (
              $(`#mmooc-tabs-mobile-header-${mobileTabIndex}`).hasClass(
                'mmooc-tabs-mobile-header-active'
              )
            ) {
              $(`#mmooc-tabs-mobile-header-${mobileTabIndex}`).toggleClass(
                'mmooc-tabs-mobile-header-active'
              );
              $(`#mmooc-tabs-mobile-content-${mobileTabIndex}`).toggleClass(
                'mmooc-tabs-mobile-content-active'
              );
            } else {
              $('.mmooc-tabs-mobile-header-active').removeClass(
                'mmooc-tabs-mobile-header-active'
              );
              $('.mmooc-tabs-mobile-content-active').removeClass(
                'mmooc-tabs-mobile-content-active'
              );

              $(`#mmooc-tabs-mobile-header-${mobileTabIndex}`).addClass(
                'mmooc-tabs-mobile-header-active'
              );
              $(`#mmooc-tabs-mobile-content-${mobileTabIndex}`).addClass(
                'mmooc-tabs-mobile-content-active'
              );
            }
          });

          self.createHashTags();
          self.scrollToCourse();
        });
      });
    },
    createHashTags: function() {
        $('span').click(function(e) {
          if ($(this).filter("[data-name='course']")) {
            var hashTag = $(e.currentTarget).attr("class")
            window.location.hash = hashTag;
          }
        });

        $("button[data-title]").click(function(e){
          var firstCourseId = $(this).siblings().find('span').eq(0).attr('class');
          var hashTag = firstCourseId;
          window.location.hash = hashTag;
        })
    },
    scrollToCourse: function () {
        var currentHash = window.location.hash.split('#');
        var courses = $('span').filter("[data-name='course']");

        courses.each(function (i, el) {
          var currentElementId = $(el).attr('class');
          if (currentHash[1] === currentElementId) {
            var categoryElement = $(el).closest('section').find('button').eq(0);
            categoryElement.trigger("click");

            var mobileViewport = window.matchMedia("(max-width: 650px)");

            if(mobileViewport.matches) {
              $([document.documentElement, document.body]).animate({
                scrollTop: $(el).find('button').offset().top
              }, 500);
            }else {
              $([document.documentElement, document.body]).animate({
                scrollTop: $("." + currentElementId).offset().top
              }, 500);
            }
            var courseTab = $(el).find('button');
            courseTab.trigger("click");
          }
        })
    },
    setCourseEnrolledStatus: function(allCourses, enrolledCourses) {
      var allCoursesWithStatus = [];
      for (var i = 0; i < allCourses.length; i++) {
        allCourses[i].course.enrolled = false;
        for (var j = 0; j < enrolledCourses.length; j++) {
          if (allCourses[i].course.id == enrolledCourses[j].id) {
            allCourses[i].course.enrolled = true;
          }
        }
        allCoursesWithStatus.push(allCourses[i].course);
      }
      return allCoursesWithStatus;
    },
    insertModalAndOverlay: function() {
      $('body').append("

");
      $('body').append("

");
    },
    handleEnrollClick: function(e, html) {
      $('.mmooc-modal').html(html);
      $('.mmooc-modal-overlay').show();
      $('.mmooc-modal').show();
      $('.mmooc-modal .modal-back').click(function(e) {
        e.preventDefault();
        $('.mmooc-modal-overlay').hide();
        $('.mmooc-modal').hide();
      });
    },
    setClickHandlers: function() {
      $('.notenrolled').click(function(e) {
        e.preventDefault();
        var html = $(this)
          .next()
          .html();
        mmooc.enroll.handleEnrollClick(e, html);
      });
      $('.all-courses-show-modal').click(function(e) {
        e.preventDefault();
        var html = $(this)
          .parent()
          .next()
          .html();
        mmooc.enroll.handleEnrollClick(e, html);
      });
      $('.mmooc-modal-overlay').click(function(e) {
        e.preventDefault();
        $('.mmooc-modal-overlay').hide();
        $('.mmooc-modal').hide();
      });
      $(document).on('keydown', function(e) {
        if (e.keyCode === 27) {
          $('.mmooc-modal-overlay').hide();
          $('.mmooc-modal').hide();
        }
      });
    },
    populateFilter: function(categorys) {
      var options =
        '<option value="Alle">Alle tilgjengelige ' +
        mmooc.i18n.CoursePlural.toLowerCase() +
        '</option>';
      for (var i = 0; i < categorys.length; i++) {
        options +=
          '<option value="' + categorys[i] + '">' + categorys[i] + '</option>';
      }
      $('#filter').append(options);
    },
    applyFilter: function() {
      var value = $('#filter').val();
      if (value == 'Alle') {
        $('.mmooc-all-courses-list').removeClass('filter-active');
        $('.mmooc-all-courses-list h2').each(function() {
          $(this).show();
          $(this)
            .next()
            .show();
        });
      } else {
        $('.mmooc-all-courses-list').addClass('filter-active');
        $('.mmooc-all-courses-list h2').each(function() {
          if ($(this).text() == value) {
            $(this).show();
            $(this)
              .next()
              .show();
          } else {
            $(this).hide();
            $(this)
              .next()
              .hide();
          }
        });
      }
    }
  };
})();
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  errorHandler = require('./errors.server.controller'),
  _ = require('lodash'),
  async = require('async'),
  Transaction = mongoose.model('Transaction'),
  User = mongoose.model('User');

exports.list = function(req, res) {
  Transaction.aggregate()
    .match({
      '$or': [
        { user: req.user._id },
        { friend: req.user._id }
      ],
      status: { $nin: ['paid', 'revoked'] }
    })
    .group({
      _id: {
        friend: {
          $cond: {
            if: { $eq: ['$friend', req.user._id] },
            then: '$user',
            else: {
              $ifNull: ['$friend', '$to']
            }
          }
        }
      },
      total: {
        $sum: {
          $cond: {
            if: {
              $or: [
                { $and: [
                  { $eq: ['$user', req.user._id] },
                  { $eq: ['$kind', 'receive'] }
                ]},
                { $and: [
                  { $eq: ['$friend', req.user._id] },
                  { $eq: ['$kind', 'pay'] }
                ]}
              ]
            },
            then: '$value',
            else: { $multiply: ['$value', -1] }
          }
        }
      },
      average: { $avg: '$value' },
      count: { $sum: 1 }
    })
    .exec(function(err, result) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        var payables = [];

        async.each(result, function(payable, done) {
          User.findById(payable._id.friend).select('id displayName').exec(function(err, friend) {
            if (friend) {
              payable._id.to = friend.displayName;
            } else {
              payable._id.to = payable._id.friend;
            }
            payables.push(payable);
            done();
          });
        }, function(err) {
          res.jsonp(payables);
        });

      }
    });
};
<commit_msg>alterando a sintaxe do $cond<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  errorHandler = require('./errors.server.controller'),
  _ = require('lodash'),
  async = require('async'),
  Transaction = mongoose.model('Transaction'),
  User = mongoose.model('User');

exports.list = function(req, res) {
  Transaction.aggregate()
    .match({
      '$or': [
        { user: req.user._id },
        { friend: req.user._id }
      ],
      status: { $nin: ['paid', 'revoked'] }
    })
    .group({
      _id: {
        friend: {
          $cond: [
            { $eq: ['$friend', req.user._id] },
            '$user',
            { $ifNull: ['$friend', '$to'] }
          ]
        }
      },
      total: {
        $sum: {
          $cond: [
            {
              $or: [
                { $and: [
                  { $eq: ['$user', req.user._id] },
                  { $eq: ['$kind', 'receive'] }
                ]},
                { $and: [
                  { $eq: ['$friend', req.user._id] },
                  { $eq: ['$kind', 'pay'] }
                ]}
              ]
            },
            '$value',
            { $multiply: ['$value', -1] }
          ]
        }
      },
      average: { $avg: '$value' },
      count: { $sum: 1 }
    })
    .exec(function(err, result) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        var payables = [];

        async.each(result, function(payable, done) {
          User.findById(payable._id.friend).select('id displayName').exec(function(err, friend) {
            if (friend) {
              payable._id.to = friend.displayName;
            } else {
              payable._id.to = payable._id.friend;
            }
            payables.push(payable);
            done();
          });
        }, function(err) {
          res.jsonp(payables);
        });

      }
    });
};
<|endoftext|>


<commit_before>var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);

requirejs(["rAppid"], function (rAppid) {
    rAppid.defineClass("js.ui.PlaceHolder",
        ["underscore", "js.core.UIComponent", "js.core.Content"], function (_, UIComponent, Content) {
            return UIComponent.inherit({
                render: function () {
                    if (this.isRendered()) {
                        return this.$el;
                    }

                    this.$textNode = document.createTextNode("");
                    this.$el = this.$textNode;

                    return this.$el;
                },
                clear: function () {
                    this.set({content: this.$textNode});
                },
                _renderContent: function (content) {
                    var children;
                    if (content instanceof Content) {
                        children = content.$children;
                    } else if (_.isArray(content)) {
                        children = content;
                    } else {
                        children = [content];
                    }

                    var child, el;
                    for (var i = 0; i < children.length; i++) {
                        child = children[i];
                        if (child.render) {
                            el = child.render();
                            var parentNode = this.$el.parentNode;
                            parentNode.insertBefore(el, this.$el);
                        }
                    }
                }
            });
        }
    );
});<commit_msg>removed PlaceHolder, because case sensity error<commit_after><|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Word = mongoose.model('Word'),
	_ = require('lodash');

/**
 * Show the current Synonym
 */
exports.read = function(req, res) {
	res.jsonp(req.synonyms);
};

exports.synonymous = function(req, res) {
	var synonymized = req.body.synonymize;
	var words = req.body.synonymize.toLowerCase().split(/\b/);
	words.filter(function unique(value, index, self) {
		return self.indexOf(value) === index;
	});

	// Asynch-recurse loop
	function synonym(i, callback) {
		if (i < words.length) {
			Word.findOne({word: words[i]}).exec(function(err, synonyms) {
				if (err) return err;
				if (synonyms && synonyms.numberOfSynonyms != 0) {
					// Replace word with a random synonym
					var replace = synonyms.synonyms[Math.floor(Math.random() * synonyms.synonyms.length)];
					synonymized = synonymized.replace(new RegExp('\\b'+words[i]+'\\b', 'gi'), replace);
				}
				synonym(i + 1, callback);
			});
		} else {
			callback();
		}
	}
	synonym(0, function() {
		res.send({synonymized: synonymized});
	});
};

/**
 * Synonym middleware
 */
exports.getSynonyms = function(req, res, next) {
	Word.findOne({word: req.params.word}).exec(function(err, synonyms) {
		if (err) return next(err);
		// if (! synonyms) return next(new Error('Failed to load synonyms for word' + req.params.word));
		if (! synonyms) {
			req.synonyms = {word: req.params.word, synonyms: [req.params.word]};
			next();
		} else {
			req.synonyms = synonyms;
			next();
		}
	});
};<commit_msg>Fix logical error<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Word = mongoose.model('Word'),
	_ = require('lodash');

/**
 * Show the current Synonym
 */
exports.read = function(req, res) {
	res.jsonp(req.synonyms);
};

exports.synonymous = function(req, res) {
	var synonymized = req.body.synonymize;
	var words = req.body.synonymize.toLowerCase().split(/\b/);
	words.filter(function unique(value, index, self) {
		return self.indexOf(value) === index;
	});

	// Asynch-recurse loop
	function synonym(i, callback) {
		if (i < words.length) {
			Word.findOne({word: words[i]}).exec(function(err, synonyms) {
				if (err) return err;
				if (synonyms && synonyms.numberOfSynonyms !== 0) {
					// Replace word with a random synonym
					var replace = synonyms.synonyms[Math.floor(Math.random() * synonyms.synonyms.length)];
					synonymized = synonymized.replace(new RegExp('\\b'+words[i]+'\\b', 'gi'), replace);
				}
				synonym(i + 1, callback);
			});
		} else {
			callback();
		}
	}
	synonym(0, function() {
		res.send({synonymized: synonymized});
	});
};

/**
 * Synonym middleware
 */
exports.getSynonyms = function(req, res, next) {
	Word.findOne({word: req.params.word}).exec(function(err, synonyms) {
		if (err) return next(err);
		// if (! synonyms) return next(new Error('Failed to load synonyms for word' + req.params.word));
		if (! synonyms) {
			req.synonyms = {word: req.params.word, synonyms: [req.params.word]};
			next();
		} else {
			req.synonyms = synonyms;
			next();
		}
	});
};<|endoftext|>


<commit_before>import Deferred from 'dojo/Deferred';
import lang from 'dojo/_base/lang';

import { urls} from 'js/config';
import resources from 'resources';
import { getUrlParams } from 'utils/params';
import arcgisUtils from 'esri/arcgis/utils';
import layerKeys from 'constants/LayerConstants';

const SEPARATOR = ';';

const pruneValues = (dict) => {
  Object.keys(dict).forEach((key) => {
    if (dict[key] === '' || dict[key] === undefined || dict[key] === null) {
      delete dict[key];
    }
  });
  return dict;
};

/**
* Takes a string and parse it into an array based on separator, e.g hey;you; => ['hey', 'you', '']
* This will remove any blanks from the array as well, e.g. ['hey', 'you', ''] => ['hey', 'you']
*/
const parseIntoArray = (resourceString) => {
  return resourceString.split(SEPARATOR).filter((value) => {
    return value !== undefined && value !== '';
  });
};

/**
 * This function globally filters layers marked as false in the core config from the table of contents,
 * and optionally accepts an array of objects containing a layer within a property
 */
const filterLayers = ({layers, layerKey}) => {
  return layers.filter(layer => {
    layer = layerKey ? layer[layerKey] : layer;
    switch (layer.id) {
      case layerKeys.VIIRS_ACTIVE_FIRES:
        return resources.viirsFires;
      case layerKeys.MODIS_ACTIVE_FIRES:
        return resources.modisFires;
      case layerKeys.LAND_COVER:
        return resources.landCover;
      case layerKeys.AG_BIOMASS:
        return resources.aboveGroundBiomass;
      case layerKeys.IFL:
        return resources.intactForests;
      case layerKeys.PRIMARY_FORESTS:
        return resources.primaryForests;
      case layerKeys.FORMA_ALERTS:
        return resources.forma;
      case layerKeys.GLOB_MANGROVE:
        return resources.mangroves;
      case layerKeys.IMAZON_SAD:
        return resources.sadAlerts;
      case layerKeys.GLAD_ALERTS:
        return resources.gladAlerts;
      case layerKeys.TERRA_I_ALERTS:
        return resources.terraIAlerts;
      case layerKeys.RECENT_IMAGERY:
        return resources.recentImagery;
      default:
        return true;
    }
  });
};

/**
* This function formats the resources object by adding information to it
* The default values in the resources match the values from AGOL, to make
* them easier to consume in my components, do all the formatting here
*/
const formatResources = () => {
  const appUrl = location.href.replace(location.search, '');
  //- LANGUAGE SETTINGS START
  resources.labels = {};
  resources.labels[resources.language] = {
    title: resources.title,
    subtitle: resources.subtitle,
    narrative: resources.narrative,
    webmapMenuName: resources.webmapMenuName
  };
  //- parse map themes for default laguage if present
  const names = resources.mapThemes ? parseIntoArray(resources.mapThemes) : [];
  const appids = resources.mapThemeIds ? parseIntoArray(resources.mapThemeIds) : [];

  if (names.length === appids.length && names.length > 0) {
    resources.labels[resources.language].themes = [];
    names.forEach((name, i) => {
      let url = `${appUrl}?appid=${appids[i].trim()}`;
      if (appids[i] === '#') {
        url = appUrl + '?';
      }

      resources.labels[resources.language].themes.push({
        label: name.trim(),
        url: url
      });
    });
  }

  const langUrlParam = getUrlParams(location.href).l;
  if (langUrlParam && langUrlParam === resources.alternativeLanguage) {
    resources.useAlternativeLanguage = true;
  }
  //- Add content for second language if configured
  if (resources.useAlternativeLanguage && resources.alternativeLanguage) {
    resources.labels[resources.alternativeLanguage] = {
      title: resources.alternativeLanguageTitle,
      subtitle: resources.alternativeLanguageSubtitle,
      narrative: resources.alternativeNarrative || resources.narrative,
      webmapMenuName: resources.alternativeWebmapMenuName || resources.webmapMenuName
    };
    //- parse map themes for second laguage if present
    const secondNames = resources.alternativeMapThemes ? parseIntoArray(resources.alternativeMapThemes) : [];
    if (secondNames.length === appids.length && names.length > 0) {
      resources.labels[resources.alternativeLanguage].themes = [];
      secondNames.forEach((name, i) => {
        resources.labels[resources.alternativeLanguage].themes.push({
          label: name.trim(),
          url: `${appUrl}?appid=${appids[i].trim()}`
        });
      });
    }
  }
  //- LANGUAGE SETTINGS END

  //- Restoration Module Configurations
  if (resources.restorationModule) {
    //- Parse the restoration module options if they are in AGOL
    if (resources.restorationOptions) {
      let optionLabels = parseIntoArray(resources.restorationOptions);
      const rasterIds = parseIntoArray(resources.restorationOptionsRasterIds);
      //- Make it in a format easier to consume in our components
      resources.labels[resources.language].restorationOptions = [];
      optionLabels.forEach((label, index) => {
        resources.labels[resources.language].restorationOptions.push({
          id: `$${rasterIds[index]}`,
          label: label
        });
      });

      //- Parse the options, colors, and any other content that will be used in the analysis
      resources.slopeAnalysisPotentialColors = parseIntoArray(resources.slopePotentialColors);
      resources.labels[resources.language].slopeAnalysisPotentialOptions = parseIntoArray(resources.slopePotentialOptions);
      //- Add description text
      resources.labels[resources.language].restorationChartDescription = resources.restorationChartDescription;
      resources.labels[resources.language].restorationTableDescription = resources.restorationTableDescription;
      resources.labels[resources.language].slopeDescription = resources.slopeDescription;
      //- Add the slope options in another language if configured
      if (resources.useAlternativeLanguage) {
        // Slope Options
        resources.labels[resources.alternativeLanguage].slopeAnalysisPotentialOptions = parseIntoArray(resources.alternativeSlopePotentialOptions);
        // Restoration Options
        optionLabels = parseIntoArray(resources.alternativeRestorationOptions);
        resources.labels[resources.alternativeLanguage].restorationOptions = [];
        optionLabels.forEach((label, index) => {
          resources.labels[resources.alternativeLanguage].restorationOptions.push({
            id: `$${rasterIds[index]}`,
            label: label
          });
        });
        //- Add description text
        resources.labels[resources.alternativeLanguage].restorationChartDescription = resources.alternativeRestorationChartDescription;
        resources.labels[resources.alternativeLanguage].restorationTableDescription = resources.alternativeRestorationTableDescription;
        resources.labels[resources.alternativeLanguage].slopeDescription = resources.alternativeSlopeDescription;
      }
    }
    //- Parse slope class names if present
    if (resources.slopeClassNames) {
      resources.slopeClasses = parseIntoArray(resources.slopeClassNames);
      resources.slopeColors = parseIntoArray(resources.slopeClassColors);
    }
    //- Parse tree cover class names if present
    if (resources.treeCoverClassNames) {
      resources.treeCoverClasses = parseIntoArray(resources.treeCoverClassNames);
      resources.treeCoverColors = parseIntoArray(resources.treeCoverClassColors);
    }
    //- Parse land cover class names if present
    if (resources.landCoverClassNames) {
      resources.landCoverClasses = parseIntoArray(resources.landCoverClassNames);
      resources.landCoverColors = parseIntoArray(resources.landCoverClassColors);
    }
    //- Parse population density class names if present
    if (resources.populationClassNames) {
      resources.populationClasses = parseIntoArray(resources.populationClassNames);
      resources.populationColors = parseIntoArray(resources.populationClassColors);
    }

    //- Parse rainfall class names if present
    if (resources.rainfallClassNames) {
      resources.rainfallClasses = parseIntoArray(resources.rainfallClassNames);
      resources.rainfallColors = parseIntoArray(resources.rainfallClassColors);
    }
  }

  //- Remove Layers from resources.layers if configured
  Object.keys(resources.layerPanel).forEach((group) => {
    const groupSettings = resources.layerPanel[group];
    if (!groupSettings.layers) { return; }
    resources.layerPanel[group].layers = filterLayers({layers: resources.layerPanel[group].layers});
  });

  //- Separate remote data layers
  const remoteDataLayers = [];
  Object.keys(resources.layerPanel).forEach(groupId => {
    if (!remoteDataLayers[groupId]) { remoteDataLayers[groupId] = []; }
    const groupSettings = resources.layerPanel[groupId];
    if (!groupSettings.layers) { return; }
    resources.layerPanel[groupId].layers = resources.layerPanel[groupId].layers.filter(layer => {
      if (layer.type === 'remoteDataLayer') {
        remoteDataLayers.push({
          order: layer.order,
          groupId,
          layer,
        });
        return false;
      } else {
        return true;
      }
    });
  });

  const remoteDataLayerRequests = remoteDataLayers
  .map((item, j) => fetch(`${urls.forestWatchLayerApi}/${item.layer.uuid}`)
    .then(response => response.json())
    .then(json => json.data)
    .then(layer => fetch(layer.attributes.layerConfig.metadata)
    .then(response => response.json())
    .then(metadata => {
        const attributes = layer.attributes;
        const itemGroup = item.group;
        Object.keys(remoteDataLayers[j].layer).forEach(layerProp => {
          if (layerProp !== 'type' && layerProp !== 'uuid') {
            if (layerProp === 'legendConfig') {
              attributes[layerProp] = remoteDataLayers[j].layer[layerProp];
            } else {
              layer.attributes.layerConfig[layerProp] = remoteDataLayers[j].layer[layerProp];
            }
          }
        });
        item.layer = layer.attributes.layerConfig;
        item.group = itemGroup;
        item.layer.metadata = {
          metadata,
          legendConfig: attributes.legendConfig
        };
        return item;
      })
    )
  );

  //- Update path if it is relative to point to local
  const base = window._app.base ? window._app.base + '/' : '';
  if (resources.logoUrl && resources.logoUrl.indexOf('.') === 0) {
    resources.logoUrl = base + resources.logoUrl;
  }

  // Object.keys(resources.basemaps).forEach((language) => {
  //   Object.keys(resources.basemaps[language]).forEach((bm) => {
  //     const basemap = resources.basemaps[language][bm];
  //     if (basemap.thumbnailUrl && basemap.thumbnailUrl.indexOf('.') === 0) {
  //       basemap.thumbnailUrl = base + basemap.thumbnailUrl;
  //#endregion//     }
  //   });
  // });

  resources.layerPanel.GROUP_BASEMAP.layers.forEach((basemap) => {
    if (basemap.thumbnailUrl && basemap.thumbnailUrl.indexOf('.') === 0) {
      basemap.thumbnailUrl = base + basemap.thumbnailUrl;
    }
  });

  return Promise.all(remoteDataLayerRequests)
  .then(remoteLayers => {
    remoteLayers = filterLayers({layers: remoteLayers, layerKey: 'layer'});
    remoteLayers.forEach(item => {
      item.layer.order = item.order; // item.order is the value we set in resources, this needs to be added to the layer object
      resources.layerPanel[item.groupId].layers.push(item.layer);
    });
    return resources;
  });
};

export default {

  /**
  * Fetch application information from arcgis online and merge it in to our local resources
  * @param {string=} id - optional app id, if you dont provide it, it will attempt to get it from url
  * @return {promise} promise
  */
  getAppInfo: (id, constructorParams) => {
    const promise = new Deferred();
    const appid = id ? id : getUrlParams(location.href).appid;

    // Set the sharinghost to the correct location so the app can find the webmap content
    if (!resources.sharinghost) { resources.sharinghost = 'https://www.arcgis.com'; }
    arcgisUtils.arcgisUrl = `${resources.sharinghost}/sharing/rest/content/items`;

    if (!appid) {
      //- Format the resources before resolving
      formatResources().then(formattedResources => {
        promise.resolve(formattedResources);
      });
      return promise;
    }

    arcgisUtils.getItem(appid).then(res => {
      let agolValues = res.itemData && res.itemData.values;

      if (constructorParams) {
        //- Prune constructorParams by removing null keys
        constructorParams = pruneValues(constructorParams);

        //- This will merge all the settings in
        lang.mixin(resources, constructorParams);
      }

      //- If we dont have agol settings, save the defaults, else merge them in
      if (!agolValues) {
        //- Format the resources before resolving
        formatResources().then(formattedResources => {
          promise.resolve(formattedResources);
        });
        return promise;
      } else {
        //- Prune agolValues by removing null keys
        agolValues = pruneValues(agolValues);

        //- This will merge all the settings in, but some things need a little massaging
        lang.mixin(resources, agolValues);

        //- Put the appid in settings so its easy to get to elsewhere in the app without rereading the url
        resources.appid = appid;

        //- Format the resources before resolving
        formatResources().then(formattedResources => {
          promise.resolve(formattedResources);
        });

      }

    }, err => {
      if (brApp.debug) { console.warn(`template.getAppInfo >> ${err.message}`); }
      formatResources().then(formattedResources => {
        promise.resolve(formattedResources);
      });
    });

    return promise;
  }

};
<commit_msg>Properly mixing in constructorParams to the report<commit_after>import Deferred from 'dojo/Deferred';
import lang from 'dojo/_base/lang';

import { urls} from 'js/config';
import resources from 'resources';
import { getUrlParams } from 'utils/params';
import arcgisUtils from 'esri/arcgis/utils';
import layerKeys from 'constants/LayerConstants';

const SEPARATOR = ';';

const pruneValues = (dict) => {
  Object.keys(dict).forEach((key) => {
    if (dict[key] === '' || dict[key] === undefined || dict[key] === null) {
      delete dict[key];
    }
  });
  return dict;
};

/**
* Takes a string and parse it into an array based on separator, e.g hey;you; => ['hey', 'you', '']
* This will remove any blanks from the array as well, e.g. ['hey', 'you', ''] => ['hey', 'you']
*/
const parseIntoArray = (resourceString) => {
  return resourceString.split(SEPARATOR).filter((value) => {
    return value !== undefined && value !== '';
  });
};

/**
 * This function globally filters layers marked as false in the core config from the table of contents,
 * and optionally accepts an array of objects containing a layer within a property
 */
const filterLayers = ({layers, layerKey}) => {
  return layers.filter(layer => {
    layer = layerKey ? layer[layerKey] : layer;
    switch (layer.id) {
      case layerKeys.VIIRS_ACTIVE_FIRES:
        return resources.viirsFires;
      case layerKeys.MODIS_ACTIVE_FIRES:
        return resources.modisFires;
      case layerKeys.LAND_COVER:
        return resources.landCover;
      case layerKeys.AG_BIOMASS:
        return resources.aboveGroundBiomass;
      case layerKeys.IFL:
        return resources.intactForests;
      case layerKeys.PRIMARY_FORESTS:
        return resources.primaryForests;
      case layerKeys.FORMA_ALERTS:
        return resources.forma;
      case layerKeys.GLOB_MANGROVE:
        return resources.mangroves;
      case layerKeys.IMAZON_SAD:
        return resources.sadAlerts;
      case layerKeys.GLAD_ALERTS:
        return resources.gladAlerts;
      case layerKeys.TERRA_I_ALERTS:
        return resources.terraIAlerts;
      case layerKeys.RECENT_IMAGERY:
        return resources.recentImagery;
      default:
        return true;
    }
  });
};

/**
* This function formats the resources object by adding information to it
* The default values in the resources match the values from AGOL, to make
* them easier to consume in my components, do all the formatting here
*/
const formatResources = () => {
  const appUrl = location.href.replace(location.search, '');
  //- LANGUAGE SETTINGS START
  resources.labels = {};
  resources.labels[resources.language] = {
    title: resources.title,
    subtitle: resources.subtitle,
    narrative: resources.narrative,
    webmapMenuName: resources.webmapMenuName
  };
  //- parse map themes for default laguage if present
  const names = resources.mapThemes ? parseIntoArray(resources.mapThemes) : [];
  const appids = resources.mapThemeIds ? parseIntoArray(resources.mapThemeIds) : [];

  if (names.length === appids.length && names.length > 0) {
    resources.labels[resources.language].themes = [];
    names.forEach((name, i) => {
      let url = `${appUrl}?appid=${appids[i].trim()}`;
      if (appids[i] === '#') {
        url = appUrl + '?';
      }

      resources.labels[resources.language].themes.push({
        label: name.trim(),
        url: url
      });
    });
  }

  const langUrlParam = getUrlParams(location.href).l;
  if (langUrlParam && langUrlParam === resources.alternativeLanguage) {
    resources.useAlternativeLanguage = true;
  }
  //- Add content for second language if configured
  if (resources.useAlternativeLanguage && resources.alternativeLanguage) {
    resources.labels[resources.alternativeLanguage] = {
      title: resources.alternativeLanguageTitle,
      subtitle: resources.alternativeLanguageSubtitle,
      narrative: resources.alternativeNarrative || resources.narrative,
      webmapMenuName: resources.alternativeWebmapMenuName || resources.webmapMenuName
    };
    //- parse map themes for second laguage if present
    const secondNames = resources.alternativeMapThemes ? parseIntoArray(resources.alternativeMapThemes) : [];
    if (secondNames.length === appids.length && names.length > 0) {
      resources.labels[resources.alternativeLanguage].themes = [];
      secondNames.forEach((name, i) => {
        resources.labels[resources.alternativeLanguage].themes.push({
          label: name.trim(),
          url: `${appUrl}?appid=${appids[i].trim()}`
        });
      });
    }
  }
  //- LANGUAGE SETTINGS END

  //- Restoration Module Configurations
  if (resources.restorationModule) {
    //- Parse the restoration module options if they are in AGOL
    if (resources.restorationOptions) {
      let optionLabels = parseIntoArray(resources.restorationOptions);
      const rasterIds = parseIntoArray(resources.restorationOptionsRasterIds);
      //- Make it in a format easier to consume in our components
      resources.labels[resources.language].restorationOptions = [];
      optionLabels.forEach((label, index) => {
        resources.labels[resources.language].restorationOptions.push({
          id: `$${rasterIds[index]}`,
          label: label
        });
      });

      //- Parse the options, colors, and any other content that will be used in the analysis
      resources.slopeAnalysisPotentialColors = parseIntoArray(resources.slopePotentialColors);
      resources.labels[resources.language].slopeAnalysisPotentialOptions = parseIntoArray(resources.slopePotentialOptions);
      //- Add description text
      resources.labels[resources.language].restorationChartDescription = resources.restorationChartDescription;
      resources.labels[resources.language].restorationTableDescription = resources.restorationTableDescription;
      resources.labels[resources.language].slopeDescription = resources.slopeDescription;
      //- Add the slope options in another language if configured
      if (resources.useAlternativeLanguage) {
        // Slope Options
        resources.labels[resources.alternativeLanguage].slopeAnalysisPotentialOptions = parseIntoArray(resources.alternativeSlopePotentialOptions);
        // Restoration Options
        optionLabels = parseIntoArray(resources.alternativeRestorationOptions);
        resources.labels[resources.alternativeLanguage].restorationOptions = [];
        optionLabels.forEach((label, index) => {
          resources.labels[resources.alternativeLanguage].restorationOptions.push({
            id: `$${rasterIds[index]}`,
            label: label
          });
        });
        //- Add description text
        resources.labels[resources.alternativeLanguage].restorationChartDescription = resources.alternativeRestorationChartDescription;
        resources.labels[resources.alternativeLanguage].restorationTableDescription = resources.alternativeRestorationTableDescription;
        resources.labels[resources.alternativeLanguage].slopeDescription = resources.alternativeSlopeDescription;
      }
    }
    //- Parse slope class names if present
    if (resources.slopeClassNames) {
      resources.slopeClasses = parseIntoArray(resources.slopeClassNames);
      resources.slopeColors = parseIntoArray(resources.slopeClassColors);
    }
    //- Parse tree cover class names if present
    if (resources.treeCoverClassNames) {
      resources.treeCoverClasses = parseIntoArray(resources.treeCoverClassNames);
      resources.treeCoverColors = parseIntoArray(resources.treeCoverClassColors);
    }
    //- Parse land cover class names if present
    if (resources.landCoverClassNames) {
      resources.landCoverClasses = parseIntoArray(resources.landCoverClassNames);
      resources.landCoverColors = parseIntoArray(resources.landCoverClassColors);
    }
    //- Parse population density class names if present
    if (resources.populationClassNames) {
      resources.populationClasses = parseIntoArray(resources.populationClassNames);
      resources.populationColors = parseIntoArray(resources.populationClassColors);
    }

    //- Parse rainfall class names if present
    if (resources.rainfallClassNames) {
      resources.rainfallClasses = parseIntoArray(resources.rainfallClassNames);
      resources.rainfallColors = parseIntoArray(resources.rainfallClassColors);
    }
  }

  //- Remove Layers from resources.layers if configured
  Object.keys(resources.layerPanel).forEach((group) => {
    const groupSettings = resources.layerPanel[group];
    if (!groupSettings.layers) { return; }
    resources.layerPanel[group].layers = filterLayers({layers: resources.layerPanel[group].layers});
  });

  //- Separate remote data layers
  const remoteDataLayers = [];
  Object.keys(resources.layerPanel).forEach(groupId => {
    if (!remoteDataLayers[groupId]) { remoteDataLayers[groupId] = []; }
    const groupSettings = resources.layerPanel[groupId];
    if (!groupSettings.layers) { return; }
    resources.layerPanel[groupId].layers = resources.layerPanel[groupId].layers.filter(layer => {
      if (layer.type === 'remoteDataLayer') {
        remoteDataLayers.push({
          order: layer.order,
          groupId,
          layer,
        });
        return false;
      } else {
        return true;
      }
    });
  });

  const remoteDataLayerRequests = remoteDataLayers
  .map((item, j) => fetch(`${urls.forestWatchLayerApi}/${item.layer.uuid}`)
    .then(response => response.json())
    .then(json => json.data)
    .then(layer => fetch(layer.attributes.layerConfig.metadata)
    .then(response => response.json())
    .then(metadata => {
        const attributes = layer.attributes;
        const itemGroup = item.group;
        Object.keys(remoteDataLayers[j].layer).forEach(layerProp => {
          if (layerProp !== 'type' && layerProp !== 'uuid') {
            if (layerProp === 'legendConfig') {
              attributes[layerProp] = remoteDataLayers[j].layer[layerProp];
            } else {
              layer.attributes.layerConfig[layerProp] = remoteDataLayers[j].layer[layerProp];
            }
          }
        });
        item.layer = layer.attributes.layerConfig;
        item.group = itemGroup;
        item.layer.metadata = {
          metadata,
          legendConfig: attributes.legendConfig
        };
        return item;
      })
    )
  );

  //- Update path if it is relative to point to local
  const base = window._app.base ? window._app.base + '/' : '';
  if (resources.logoUrl && resources.logoUrl.indexOf('.') === 0) {
    resources.logoUrl = base + resources.logoUrl;
  }

  // Object.keys(resources.basemaps).forEach((language) => {
  //   Object.keys(resources.basemaps[language]).forEach((bm) => {
  //     const basemap = resources.basemaps[language][bm];
  //     if (basemap.thumbnailUrl && basemap.thumbnailUrl.indexOf('.') === 0) {
  //       basemap.thumbnailUrl = base + basemap.thumbnailUrl;
  //#endregion//     }
  //   });
  // });

  resources.layerPanel.GROUP_BASEMAP.layers.forEach((basemap) => {
    if (basemap.thumbnailUrl && basemap.thumbnailUrl.indexOf('.') === 0) {
      basemap.thumbnailUrl = base + basemap.thumbnailUrl;
    }
  });

  return Promise.all(remoteDataLayerRequests)
  .then(remoteLayers => {
    remoteLayers = filterLayers({layers: remoteLayers, layerKey: 'layer'});
    remoteLayers.forEach(item => {
      item.layer.order = item.order; // item.order is the value we set in resources, this needs to be added to the layer object
      resources.layerPanel[item.groupId].layers.push(item.layer);
    });
    return resources;
  });
};

export default {

  /**
  * Fetch application information from arcgis online and merge it in to our local resources
  * @param {string=} id - optional app id, if you dont provide it, it will attempt to get it from url
  * @return {promise} promise
  */
  getAppInfo: (id, constructorParams) => {
    const promise = new Deferred();
    const appid = id ? id : getUrlParams(location.href).appid;

    // Set the sharinghost to the correct location so the app can find the webmap content
    if (!resources.sharinghost) { resources.sharinghost = 'https://www.arcgis.com'; }
    arcgisUtils.arcgisUrl = `${resources.sharinghost}/sharing/rest/content/items`;

    if (!appid) {

      if (constructorParams) {
        //- Prune constructorParams by removing null keys
        constructorParams = pruneValues(constructorParams);

        //- This will merge all the settings in
        lang.mixin(resources, constructorParams);
      }

      //- Format the resources before resolving
      formatResources().then(formattedResources => {
        promise.resolve(formattedResources);
      });
      return promise;
    }

    arcgisUtils.getItem(appid).then(res => {
      let agolValues = res.itemData && res.itemData.values;

      if (constructorParams) {
        //- Prune constructorParams by removing null keys
        constructorParams = pruneValues(constructorParams);

        //- This will merge all the settings in
        lang.mixin(resources, constructorParams);
      }

      //- If we dont have agol settings, save the defaults, else merge them in
      if (!agolValues) {
        //- Format the resources before resolving
        formatResources().then(formattedResources => {
          promise.resolve(formattedResources);
        });
        return promise;
      } else {
        //- Prune agolValues by removing null keys
        agolValues = pruneValues(agolValues);

        //- This will merge all the settings in, but some things need a little massaging
        lang.mixin(resources, agolValues);

        //- Put the appid in settings so its easy to get to elsewhere in the app without rereading the url
        resources.appid = appid;

        //- Format the resources before resolving
        formatResources().then(formattedResources => {
          promise.resolve(formattedResources);
        });

      }

    }, err => {
      if (brApp.debug) { console.warn(`template.getAppInfo >> ${err.message}`); }
      formatResources().then(formattedResources => {
        promise.resolve(formattedResources);
      });
    });

    return promise;
  }

};
<|endoftext|>


<commit_before>import usersApi from 'core/api/users'

export default {
  namespaced: true,

  state: {
    loading: {
      classrooms: false,
      teachers: false
    },

    isSchoolAdministrator: false,
    administratedTeachers: [],
  },

  mutations: {
    toggleLoading: (state, key) => state.loading[key] = !state.loading[key],

    addTeachers: (state, teachers) => {
      state.administratedTeachers = teachers;
    },
  },

  actions: {
    fetchTeachers: ({ commit, rootState }) => {
      const administratedTeachers = rootState.me.administratedTeachers || []
      if (administratedTeachers.length === 0) {
        return
      }

      commit('toggleLoading', 'teachers')

      return usersApi
        .fetchByIds({
          fetchByIds: administratedTeachers,
          includeTrialRequests: true
        })
        .then(res =>  {
          if (res) {
            commit('addTeachers', res)
          } else {
            throw new Error('Unexpected response from teachers by ID API.')
          }
        })
        .catch((e) => noty({ text: 'Fetch teachers failure' + e, type: 'error' }))
        .finally(() => commit('toggleLoading', 'teachers'))
    },
  }
}

<commit_msg>Split user queries into batches with max length 100 to fix 502 school admin dashboard (#5762)<commit_after>import usersApi from 'core/api/users'

export default {
  namespaced: true,

  state: {
    loading: {
      classrooms: false,
      teachers: false
    },

    isSchoolAdministrator: false,
    administratedTeachers: [],
  },

  mutations: {
    toggleLoading: (state, key) => state.loading[key] = !state.loading[key],

    addTeachers: (state, teachers) => {
      state.administratedTeachers = teachers;
    },
  },

  actions: {
    fetchTeachers: ({ commit, rootState }) => {
      const administratedTeachers = rootState.me.administratedTeachers || []
      if (administratedTeachers.length === 0) {
        return
      }

      commit('toggleLoading', 'teachers')

      const groupSize = 100
      const groups = Math.ceil(administratedTeachers.length / (groupSize * 1.0))
      const userPromises = []
      let lastStartIndex = 0

      for (let i = 0; i < groups; i++) {
        let endIndex = lastStartIndex + groupSize

        userPromises.push(
          usersApi
            .fetchByIds({
              fetchByIds: administratedTeachers.slice(lastStartIndex, endIndex),
              includeTrialRequests: true
            })
            .then(res => {
              if (res) {
                return res
              } else {
                throw new Error('Unexpected response from teachers by ID API.')
              }
            })
        )

        lastStartIndex = endIndex
      }

      return Promise.all(userPromises)
        .then(groupResults => groupResults.flat())
        .then(combinedResults => commit('addTeachers', combinedResults))
        .catch((e) => noty({ text: 'Fetch teachers failure' + e, type: 'error' }))
        .finally(() => commit('toggleLoading', 'teachers'))
    },
  }
}

<|endoftext|>


<commit_before>/*
Language: Crystal
Author: TSUYUSATO Kitsune <make.just.on@gmail.com>
*/

function(hljs) {
  var NUM_SUFFIX = '(_[uif](8|16|32|64))?';
  var CRYSTAL_IDENT_RE = '[a-zA-Z_]\\w*[!?=]?';
  var RE_STARTER = '!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|' +
    '>>|>|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
  var CRYSTAL_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\][=?]?';
  var CRYSTAL_KEYWORDS = {
    keyword:
      'abstract alias as asm begin break case class def do else elsif end ensure enum extend for fun if ifdef ' +
      'include instance_sizeof is_a? lib macro module next of out pointerof private protected rescue responds_to? ' +
      'return require self sizeof struct super then type typeof undef union unless until when while with yield ' +
      '__DIR__ __FILE__ __LINE__',
    literal: 'false nil true'
  };
  var SUBST = {
    className: 'subst',
    begin: '#{', end: '}',
    keywords: CRYSTAL_KEYWORDS
  };
  var EXPANSION = {
    className: 'expansion',
    variants: [
      {begin: '\\{\\{', end: '\\}\\}'},
      {begin: '\\{%', end: '%\\}'}
    ],
    keywords: CRYSTAL_KEYWORDS,
    relevance: 10
  };

  function recursiveParen(begin, end) {
    var
    contains = [{begin: begin, end: end}];
    contains[0].contains = contains;
    return contains;
  }
  var STRING = {
    className: 'string',
    contains: [hljs.BACKSLASH_ESCAPE, SUBST],
    variants: [
      {begin: /'/, end: /'/},
      {begin: /"/, end: /"/},
      {begin: /`/, end: /`/},
      {begin: '%w?\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
      {begin: '%w?\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
      {begin: '%w?{', end: '}', contains: recursiveParen('{', '}')},
      {begin: '%w?<', end: '>', contains: recursiveParen('<', '>')},
      {begin: '%w?/', end: '/'},
      {begin: '%w?%', end: '%'},
      {begin: '%w?-', end: '-'},
      {begin: '%w?\\|', end: '\\|'},
    ],
    relevance: 0,
  };
  var REGEXP = {
    begin: '(' + RE_STARTER + ')\\s*',
    contains: [
      {
        className: 'regexp',
        contains: [hljs.BACKSLASH_ESCAPE, SUBST],
        variants: [
          {begin: '/', end: '/[a-z]*'},
          {begin: '%r\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
          {begin: '%r\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
          {begin: '%r{', end: '}', contains: recursiveParen('{', '}')},
          {begin: '%r<', end: '>', contains: recursiveParen('<', '>')},
          {begin: '%r/', end: '/'},
          {begin: '%r%', end: '%'},
          {begin: '%r-', end: '-'},
          {begin: '%r\\|', end: '\\|'},
        ]
      }
    ],
    relevance: 0
  };
  var REGEXP2 = {
    className: 'regexp',
    contains: [hljs.BACKSLASH_ESCAPE, SUBST],
    variants: [
      {begin: '%r\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
      {begin: '%r\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
      {begin: '%r{', end: '}', contains: recursiveParen('{', '}')},
      {begin: '%r<', end: '>', contains: recursiveParen('<', '>')},
      {begin: '%r/', end: '/'},
      {begin: '%r%', end: '%'},
      {begin: '%r-', end: '-'},
      {begin: '%r\\|', end: '\\|'},
    ],
    relevance: 0
  };
  var ATTRIBUTE = {
    className: 'annotation',
    begin: '@\\[', end: '\\]',
    relevance: 5
  };
  var CRYSTAL_DEFAULT_CONTAINS = [
    EXPANSION,
    STRING,
    REGEXP,
    REGEXP2,
    ATTRIBUTE,
    hljs.HASH_COMMENT_MODE,
    {
      className: 'class',
      beginKeywords: 'class module struct', end: '$|;',
      illegal: /=/,
      contains: [
        hljs.HASH_COMMENT_MODE,
        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
        {
          className: 'inheritance',
          begin: '<\\s*',
          contains: [{
            className: 'parent',
            begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE
          }]
        }
      ]
    },
    {
      className: 'class',
      beginKeywords: 'lib enum union', end: '$|;',
      illegal: /=/,
      contains: [
        hljs.HASH_COMMENT_MODE,
        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
      ],
      relevance: 10
    },
    {
      className: 'function',
      beginKeywords: 'def', end: /\B\b/,
      contains: [
        hljs.inherit(hljs.TITLE_MODE, {
          begin: CRYSTAL_METHOD_RE,
          endsParent: true
        })
      ]
    },
    {
      className: 'function',
      beginKeywords: 'fun macro', end: /\B\b/,
      contains: [
        hljs.inherit(hljs.TITLE_MODE, {
          begin: CRYSTAL_METHOD_RE,
          endsParent: true
        })
      ],
      relevance: 5
    },
    {
      className: 'constant',
      begin: '(::)?(\\b[A-Z]\\w*(::)?)+',
      relevance: 0
    },
    {
      className: 'symbol',
      begin: hljs.UNDERSCORE_IDENT_RE + '(\\!|\\?)?:',
      relevance: 0
    },
    {
      className: 'symbol',
      begin: ':',
      contains: [STRING, {begin: CRYSTAL_METHOD_RE}],
      relevance: 0
    },
    {
      className: 'number',
      variants: [
        { begin: '\\b0b([01_]*[01])' + NUM_SUFFIX },
        { begin: '\\b0o([0-7_]*[0-7])' + NUM_SUFFIX },
        { begin: '\\b0x([A-Fa-f0-9_]*[A-Fa-f0-9])' + NUM_SUFFIX },
        { begin: '\\b(([0-9][0-9_]*[0-9]|[0-9])(\\.[0-9_]*[0-9])?([eE][+-]?[0-9_]*[0-9])?)' + NUM_SUFFIX}
      ],
      relevance: 0
    },
    {
      className: 'variable',
      begin: '(\\$\\W)|((\\$|\\@\\@?|%)(\\w+))'
    }
  ];
  SUBST.contains = CRYSTAL_DEFAULT_CONTAINS;
  ATTRIBUTE.contains = CRYSTAL_DEFAULT_CONTAINS;
  EXPANSION.contains = CRYSTAL_DEFAULT_CONTAINS.slice(1); // without EXPANSION

  return {
    aliases: ['cr'],
    lexemes: CRYSTAL_IDENT_RE,
    keywords: CRYSTAL_KEYWORDS,
    contains: CRYSTAL_DEFAULT_CONTAINS
  };
}
<commit_msg>Crystal dosen't hava `undef` keyword now.<commit_after>/*
Language: Crystal
Author: TSUYUSATO Kitsune <make.just.on@gmail.com>
*/

function(hljs) {
  var NUM_SUFFIX = '(_[uif](8|16|32|64))?';
  var CRYSTAL_IDENT_RE = '[a-zA-Z_]\\w*[!?=]?';
  var RE_STARTER = '!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|' +
    '>>|>|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
  var CRYSTAL_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\][=?]?';
  var CRYSTAL_KEYWORDS = {
    keyword:
      'abstract alias as asm begin break case class def do else elsif end ensure enum extend for fun if ifdef ' +
      'include instance_sizeof is_a? lib macro module next of out pointerof private protected rescue responds_to? ' +
      'return require self sizeof struct super then type typeof union unless until when while with yield ' +
      '__DIR__ __FILE__ __LINE__',
    literal: 'false nil true'
  };
  var SUBST = {
    className: 'subst',
    begin: '#{', end: '}',
    keywords: CRYSTAL_KEYWORDS
  };
  var EXPANSION = {
    className: 'expansion',
    variants: [
      {begin: '\\{\\{', end: '\\}\\}'},
      {begin: '\\{%', end: '%\\}'}
    ],
    keywords: CRYSTAL_KEYWORDS,
    relevance: 10
  };

  function recursiveParen(begin, end) {
    var
    contains = [{begin: begin, end: end}];
    contains[0].contains = contains;
    return contains;
  }
  var STRING = {
    className: 'string',
    contains: [hljs.BACKSLASH_ESCAPE, SUBST],
    variants: [
      {begin: /'/, end: /'/},
      {begin: /"/, end: /"/},
      {begin: /`/, end: /`/},
      {begin: '%w?\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
      {begin: '%w?\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
      {begin: '%w?{', end: '}', contains: recursiveParen('{', '}')},
      {begin: '%w?<', end: '>', contains: recursiveParen('<', '>')},
      {begin: '%w?/', end: '/'},
      {begin: '%w?%', end: '%'},
      {begin: '%w?-', end: '-'},
      {begin: '%w?\\|', end: '\\|'},
    ],
    relevance: 0,
  };
  var REGEXP = {
    begin: '(' + RE_STARTER + ')\\s*',
    contains: [
      {
        className: 'regexp',
        contains: [hljs.BACKSLASH_ESCAPE, SUBST],
        variants: [
          {begin: '/', end: '/[a-z]*'},
          {begin: '%r\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
          {begin: '%r\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
          {begin: '%r{', end: '}', contains: recursiveParen('{', '}')},
          {begin: '%r<', end: '>', contains: recursiveParen('<', '>')},
          {begin: '%r/', end: '/'},
          {begin: '%r%', end: '%'},
          {begin: '%r-', end: '-'},
          {begin: '%r\\|', end: '\\|'},
        ]
      }
    ],
    relevance: 0
  };
  var REGEXP2 = {
    className: 'regexp',
    contains: [hljs.BACKSLASH_ESCAPE, SUBST],
    variants: [
      {begin: '%r\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
      {begin: '%r\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
      {begin: '%r{', end: '}', contains: recursiveParen('{', '}')},
      {begin: '%r<', end: '>', contains: recursiveParen('<', '>')},
      {begin: '%r/', end: '/'},
      {begin: '%r%', end: '%'},
      {begin: '%r-', end: '-'},
      {begin: '%r\\|', end: '\\|'},
    ],
    relevance: 0
  };
  var ATTRIBUTE = {
    className: 'annotation',
    begin: '@\\[', end: '\\]',
    relevance: 5
  };
  var CRYSTAL_DEFAULT_CONTAINS = [
    EXPANSION,
    STRING,
    REGEXP,
    REGEXP2,
    ATTRIBUTE,
    hljs.HASH_COMMENT_MODE,
    {
      className: 'class',
      beginKeywords: 'class module struct', end: '$|;',
      illegal: /=/,
      contains: [
        hljs.HASH_COMMENT_MODE,
        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
        {
          className: 'inheritance',
          begin: '<\\s*',
          contains: [{
            className: 'parent',
            begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE
          }]
        }
      ]
    },
    {
      className: 'class',
      beginKeywords: 'lib enum union', end: '$|;',
      illegal: /=/,
      contains: [
        hljs.HASH_COMMENT_MODE,
        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
      ],
      relevance: 10
    },
    {
      className: 'function',
      beginKeywords: 'def', end: /\B\b/,
      contains: [
        hljs.inherit(hljs.TITLE_MODE, {
          begin: CRYSTAL_METHOD_RE,
          endsParent: true
        })
      ]
    },
    {
      className: 'function',
      beginKeywords: 'fun macro', end: /\B\b/,
      contains: [
        hljs.inherit(hljs.TITLE_MODE, {
          begin: CRYSTAL_METHOD_RE,
          endsParent: true
        })
      ],
      relevance: 5
    },
    {
      className: 'constant',
      begin: '(::)?(\\b[A-Z]\\w*(::)?)+',
      relevance: 0
    },
    {
      className: 'symbol',
      begin: hljs.UNDERSCORE_IDENT_RE + '(\\!|\\?)?:',
      relevance: 0
    },
    {
      className: 'symbol',
      begin: ':',
      contains: [STRING, {begin: CRYSTAL_METHOD_RE}],
      relevance: 0
    },
    {
      className: 'number',
      variants: [
        { begin: '\\b0b([01_]*[01])' + NUM_SUFFIX },
        { begin: '\\b0o([0-7_]*[0-7])' + NUM_SUFFIX },
        { begin: '\\b0x([A-Fa-f0-9_]*[A-Fa-f0-9])' + NUM_SUFFIX },
        { begin: '\\b(([0-9][0-9_]*[0-9]|[0-9])(\\.[0-9_]*[0-9])?([eE][+-]?[0-9_]*[0-9])?)' + NUM_SUFFIX}
      ],
      relevance: 0
    },
    {
      className: 'variable',
      begin: '(\\$\\W)|((\\$|\\@\\@?|%)(\\w+))'
    }
  ];
  SUBST.contains = CRYSTAL_DEFAULT_CONTAINS;
  ATTRIBUTE.contains = CRYSTAL_DEFAULT_CONTAINS;
  EXPANSION.contains = CRYSTAL_DEFAULT_CONTAINS.slice(1); // without EXPANSION

  return {
    aliases: ['cr'],
    lexemes: CRYSTAL_IDENT_RE,
    keywords: CRYSTAL_KEYWORDS,
    contains: CRYSTAL_DEFAULT_CONTAINS
  };
}
<|endoftext|>


<commit_before>export const initialState = {
  loading: true,
  error: false,
  layerSpec: {},
  options: {
    mapTypeId: 'GFWdefault',
    backgroundColor: '#99b3cc',
    disableDefaultUI: true,
    panControl: false,
    zoomControl: false,
    mapTypeControl: false,
    scaleControl: true,
    streetViewControl: false,
    overviewMapControl: false,
    tilt: 0,
    scrollwheel: false,
    center: { lat: 15, lng: 27 },
    zoom: 2,
    minZoom: 2,
    maxZoom: 14
  },
  settings: {},
  showMapMobile: false
};

const setLayerSpecLoading = (state, { payload }) => ({
  ...state,
  ...payload
});

const setLayerSpec = (state, { payload }) => ({
  ...state,
  layerSpec: payload,
  loading: false
});

const setMapOptions = (state, { payload }) => ({
  ...state,
  options: payload
});

const setShowMapMobile = (state, { payload }) => ({
  ...state,
  showMapMobile: payload
});

const setMapZoom = (state, { payload }) => {
  const { maxZoom, minZoom, zoom } = state.options;
  const { value, sum } = payload;
  let newZoom = sum ? zoom + sum : value;
  if (zoom > maxZoom) {
    newZoom = minZoom;
  } else if (zoom < minZoom) {
    newZoom = minZoom;
  }

  return {
    ...state,
    options: {
      ...state.options,
      zoom: newZoom
    }
  };
};

export default {
  setLayerSpecLoading,
  setLayerSpec,
  setMapOptions,
  setMapZoom,
  setShowMapMobile
};
<commit_msg>update map background<commit_after>export const initialState = {
  loading: true,
  error: false,
  layerSpec: {},
  options: {
    mapTypeId: 'GFWdefault',
    backgroundColor: '#A4DBFD',
    disableDefaultUI: true,
    panControl: false,
    zoomControl: false,
    mapTypeControl: false,
    scaleControl: true,
    streetViewControl: false,
    overviewMapControl: false,
    tilt: 0,
    scrollwheel: false,
    center: { lat: 15, lng: 27 },
    zoom: 2,
    minZoom: 2,
    maxZoom: 14
  },
  settings: {},
  showMapMobile: false
};

const setLayerSpecLoading = (state, { payload }) => ({
  ...state,
  ...payload
});

const setLayerSpec = (state, { payload }) => ({
  ...state,
  layerSpec: payload,
  loading: false
});

const setMapOptions = (state, { payload }) => ({
  ...state,
  options: payload
});

const setShowMapMobile = (state, { payload }) => ({
  ...state,
  showMapMobile: payload
});

const setMapZoom = (state, { payload }) => {
  const { maxZoom, minZoom, zoom } = state.options;
  const { value, sum } = payload;
  let newZoom = sum ? zoom + sum : value;
  if (zoom > maxZoom) {
    newZoom = minZoom;
  } else if (zoom < minZoom) {
    newZoom = minZoom;
  }

  return {
    ...state,
    options: {
      ...state.options,
      zoom: newZoom
    }
  };
};

export default {
  setLayerSpecLoading,
  setLayerSpec,
  setMapOptions,
  setMapZoom,
  setShowMapMobile
};
<|endoftext|>


<commit_before>import Immutable from 'immutable';
import { COLUMN_MEDIA_RESIZE } from '../actions/column_media';

const initialState = Immutable.Map({
  scale: null,
  single: null,
  wide: null,
});

function resize(state, { columnCount, defaultPage, single: givenSingle, window: givenWindow }) {
  const single = state.get('single') || givenSingle;
  const widthCandidate = (givenWindow.innerWidth - 300) / columnCount;
  const width = single ? givenWindow.innerWidth : Math.max(widthCandidate, 330);
  const wide = !defaultPage || width < givenWindow.innerHeight;
  let scale;

  if (!defaultPage || (!single && widthCandidate < 330)) {
    scale = '230px';
  } else if (!wide) {
    scale = '50vh';
  } else if (single) {
    scale = '100vw';
  } else {
    scale = `calc((100vw - 300px)/${columnCount} - 100px)`;
  }

  return state.merge({ scale, single, wide });
}

export default function columnMedia(state = initialState, action) {
  switch (action.type) {
  case COLUMN_MEDIA_RESIZE:
    return resize(state, action);
  default:
    return state;
  }
}
<commit_msg>Fix media scaling on single column layout<commit_after>import Immutable from 'immutable';
import { COLUMN_MEDIA_RESIZE } from '../actions/column_media';

const initialState = Immutable.Map({
  scale: null,
  single: null,
  wide: null,
});

function resize(state, { columnCount, defaultPage, single: givenSingle, window: givenWindow }) {
  const single = state.get('single') || givenSingle;
  const widthCandidate = (givenWindow.innerWidth - 300) / columnCount;
  const width = single ? givenWindow.innerWidth : Math.max(widthCandidate, 330);
  const wide = !defaultPage || width < givenWindow.innerHeight;
  let scale;

  if (!defaultPage || (!single && widthCandidate < 330)) {
    scale = '230px';
  } else if (!wide) {
    scale = '50vh';
  } else if (single) {
    scale = 'calc(50vw - 100px)';
  } else {
    scale = `calc((100vw - 300px)/${columnCount} - 100px)`;
  }

  return state.merge({ scale, single, wide });
}

export default function columnMedia(state = initialState, action) {
  switch (action.type) {
  case COLUMN_MEDIA_RESIZE:
    return resize(state, action);
  default:
    return state;
  }
}
<|endoftext|>