<commit_before>let args = {
    frequency:10,					// ( How often the object sends the values - milliseconds )
    gravityNormalized:true,			// ( If the gravity related values to be normalized )
    orientationBase:GyroNorm.GAME,	// ( Can be GyroNorm.GAME or GyroNorm.WORLD. gn.GAME returns orientation values with respect to the head direction of the device. gn.WORLD returns the orientation values with respect to the actual north direction of the world. )
    decimalCount:0,					// ( How many digits after the decimal point will there be in the return values )
    logger:logger,			        // ( Function to be called to log messages from gyronorm.js )
    screenAdjusted:true			    // ( If set to true it will return screen adjusted values. )
};
//
let gn = new GyroNorm();

gn.init(args).then(function(){

    let isAvailable = gn.isAvailable();
    if(!isAvailable.deviceOrientationAvailable) {
        logger({message:'Device orientation is not available.'});
    }
    // if(!isAvailable.accelerationAvailable) {
    //     logger({message:'Device acceleration is not available.'});
    // }
    // if(!isAvailable.accelerationIncludingGravityAvailable) {
    //     logger({message:'Device acceleration incl. gravity is not available.'});
    // }
    // if(!isAvailable.rotationRateAvailable) {
    //     logger({message:'Device rotation rate is not available.'});
    // }
    //else {
    //    start_gn();
    //}

}).catch(function(e){
    console.log(e);
});

function logger(data) {
    document.getElementById("error-message").innerHTML = data.message + "
";
}
function stop_gn() { //todo make button for stop
    gn.stop();
}

function start_gn() { //todo make button for start
    gn.start(gncbt);
    //gn.setHeadDirection();
}
const up = document.getElementById("up");
const down = document.getElementById("down");
const left = document.getElementById("left");
const right = document.getElementById("right");
const output = document.getElementById("output");

var lastBut = 'h';

function sendIfChanged(b){
   if (b != lastBut){
     button(b);
     lastBut =b;
   }
}

function gncbt(data){
   let wheel = data.dm.gy;
   let drive = data.dm.gz;
   logger({message:"data is ("+data.dm.gx+","+data.dm.gy+","+data.dm.gz+")"});

   var nb = 'h';
   if  (wheel > 2){
      nb = 'l';
   } else if (wheel < 2) {
      nb = 'r';
   } else if (drive > 2) {
      nb = 'f';
   } else if (drive < 2) {
      nb = 'b';
   }
   sendIfChanged(nb);
}

/*
function gnCallBack(data) {
    gn.start(function(data){
        const up = document.getElementById("up");
        const down = document.getElementById("down");
        const left = document.getElementById("left");
        const right = document.getElementById("right");
        let output = document.getElementById("output");

        // Process:
        let direction = Math.round(data.do.alpha);	    // DIRECTION ( deviceorientation event alpha value )
        // data.do.beta		( deviceorientation event beta value )
        let speed = Math.round(data.do.gamma);	    // SPEED ( deviceorientation event gamma value )
        // data.do.absolute	( deviceorientation event absolute value )

        // data.dm.x		( devicemotion event acceleration x value )
        // data.dm.y		( devicemotion event acceleration y value )
        // data.dm.z		( devicemotion event acceleration z value )

        // data.dm.gx		( devicemotion event accelerationIncludingGravity x value )
        // data.dm.gy		( devicemotion event accelerationIncludingGravity y value )
        // data.dm.gz		( devicemotion event accelerationIncludingGravity z value )

        // data.dm.alpha	( devicemotion event rotationRate alpha value )
        // data.dm.beta		( devicemotion event rotationRate beta value )
        // data.dm.gamma	( devicemotion event rotationRate gamma value )

        output.innerHTML = "Direction: " + direction +
            "
 Speed: " + speed;

        if (direction > 0 && direction < 180) {
            button("l");
            left.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 Turning left ";
        } else {
            button("h");
            left.style.backgroundColor ="white";
        }
        if (direction > 180 && direction < 360) {
            button("r");
            right.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 Turning right ";
        } else {
            button("h");
            right.style.backgroundColor ="white";
        }
        if (speed < -2) {
            button("b");
            down.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 backwards";
        } else {
            button("h");
            down.style.backgroundColor ="white";
        }
        if (speed > 2) {
            button("f");
            up.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 forwards";
        } else {
            button("h");
            up.style.backgroundColor ="white";
        }
    });
}
*/
function norm_gn() {
    gn.normalizeGravity(true);
}
function org_gn() {
    gn.normalizeGravity(false);
}
function set_head_gn() {
    gn.setHeadDirection();
}
<commit_msg>better logic<commit_after>let args = {
    frequency:10,					// ( How often the object sends the values - milliseconds )
    gravityNormalized:true,			// ( If the gravity related values to be normalized )
    orientationBase:GyroNorm.GAME,	// ( Can be GyroNorm.GAME or GyroNorm.WORLD. gn.GAME returns orientation values with respect to the head direction of the device. gn.WORLD returns the orientation values with respect to the actual north direction of the world. )
    decimalCount:0,					// ( How many digits after the decimal point will there be in the return values )
    logger:logger,			        // ( Function to be called to log messages from gyronorm.js )
    screenAdjusted:true			    // ( If set to true it will return screen adjusted values. )
};
//
let gn = new GyroNorm();

gn.init(args).then(function(){

    let isAvailable = gn.isAvailable();
    if(!isAvailable.deviceOrientationAvailable) {
        logger({message:'Device orientation is not available.'});
    }
    // if(!isAvailable.accelerationAvailable) {
    //     logger({message:'Device acceleration is not available.'});
    // }
    // if(!isAvailable.accelerationIncludingGravityAvailable) {
    //     logger({message:'Device acceleration incl. gravity is not available.'});
    // }
    // if(!isAvailable.rotationRateAvailable) {
    //     logger({message:'Device rotation rate is not available.'});
    // }
    //else {
    //    start_gn();
    //}

}).catch(function(e){
    console.log(e);
});

function logger(data) {
    document.getElementById("error-message").innerHTML = data.message + "
";
}
function stop_gn() { //todo make button for stop
    gn.stop();
}

function start_gn() { //todo make button for start
    gn.start(gncbt);
    //gn.setHeadDirection();
}
const up = document.getElementById("up");
const down = document.getElementById("down");
const left = document.getElementById("left");
const right = document.getElementById("right");
const output = document.getElementById("output");

var lastBut = 'h';

function sendIfChanged(b){
   if (b != lastBut){
     button(b);
     lastBut =b;
   }
}

function gncbt(data){
   let wheel = data.dm.gy;
   let drive = data.dm.gz;
   logger({message:"data is ("+data.dm.gx+","+data.dm.gy+","+data.dm.gz+")"});

   var nb = 'h';
   if  (wheel > 2){
      nb = 'l';
   } else if (wheel < -2) {
      nb = 'r';
   } else if (drive > 2) {
      nb = 'f';
   } else if (drive < -2) {
      nb = 'b';
   }
   sendIfChanged(nb);
}

/*
function gnCallBack(data) {
    gn.start(function(data){
        const up = document.getElementById("up");
        const down = document.getElementById("down");
        const left = document.getElementById("left");
        const right = document.getElementById("right");
        let output = document.getElementById("output");

        // Process:
        let direction = Math.round(data.do.alpha);	    // DIRECTION ( deviceorientation event alpha value )
        // data.do.beta		( deviceorientation event beta value )
        let speed = Math.round(data.do.gamma);	    // SPEED ( deviceorientation event gamma value )
        // data.do.absolute	( deviceorientation event absolute value )

        // data.dm.x		( devicemotion event acceleration x value )
        // data.dm.y		( devicemotion event acceleration y value )
        // data.dm.z		( devicemotion event acceleration z value )

        // data.dm.gx		( devicemotion event accelerationIncludingGravity x value )
        // data.dm.gy		( devicemotion event accelerationIncludingGravity y value )
        // data.dm.gz		( devicemotion event accelerationIncludingGravity z value )

        // data.dm.alpha	( devicemotion event rotationRate alpha value )
        // data.dm.beta		( devicemotion event rotationRate beta value )
        // data.dm.gamma	( devicemotion event rotationRate gamma value )

        output.innerHTML = "Direction: " + direction +
            "
 Speed: " + speed;

        if (direction > 0 && direction < 180) {
            button("l");
            left.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 Turning left ";
        } else {
            button("h");
            left.style.backgroundColor ="white";
        }
        if (direction > 180 && direction < 360) {
            button("r");
            right.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 Turning right ";
        } else {
            button("h");
            right.style.backgroundColor ="white";
        }
        if (speed < -2) {
            button("b");
            down.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 backwards";
        } else {
            button("h");
            down.style.backgroundColor ="white";
        }
        if (speed > 2) {
            button("f");
            up.style.backgroundColor ="#00A7FF";
            output.innerHTML += "
 forwards";
        } else {
            button("h");
            up.style.backgroundColor ="white";
        }
    });
}
*/
function norm_gn() {
    gn.normalizeGravity(true);
}
function org_gn() {
    gn.normalizeGravity(false);
}
function set_head_gn() {
    gn.setHeadDirection();
}
<|endoftext|>


<commit_before>var CronJob = require('cron').CronJob;

const async = require('async');
const Quickshifts_customer_timeline = require('../models/Quickshifts_customer_timeline.js');
const Secondaryshift = require('../models/Secondaryshift.js');
const Shift = require('../models/Shift.js');
const User = require('../models/User.js');
const EventEmitter = require('events');
/*
-----------------------------------------------------
-------GETTING ALL INFORMATION NEEDED FOR PAGE LOAD
-----------------------------------------------------
*/

//a function to only return unique values of an array, used in the below code
//search for onlyUnique
function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function get_pretty_date(value){
  var start_date = new Date(value)
  var s_year = start_date.getFullYear();
  var s_month = start_date.getMonth() + 1;
  if(s_month <= 9)
      s_month = '0'+s_month;
  var s_day= start_date.getDate();
  if(s_day <= 9)
      s_day = '0'+s_day;

  var s_prettyDate = s_month +'-'+ s_day + '-'+  s_year
  return s_prettyDate
}

function addDays(date, days) {
    var result = new Date(date);
    result.setDate(result.getDate() + days);
    return result;
}

/*
new CronJob('* * * * * *', function() {
  console.log('You will see this message every second');
  Quickshifts_customer_timeline.find(function (err,docs){
    if (err) { return callback(err); }
      //setting an array up to collect distinct manager user_id
      var manager_user_ids = []
      //console.log(docs)
      //collating all the manager user id's then using a function defined above
      //to get unique manager user ids'
      for (i = 0; i <= docs.length-1; i++) {
        manager_user_ids.push(docs[i].manager_userid)
      }
      var unique_manager_user_ids = manager_user_ids.filter(onlyUnique);

      var max_per_manager = []

      //goal with the below code is to 1) get the max schedule #

      //looping through manager user_id's and comparing to with the overall json
      for (i = 0; i<= unique_manager_user_ids.length-1; i++){
        for(j = 0; j<= docs.length-1; j++){
          if (unique_manager_user_ids[i] == docs[j].manager_userid ){
             if (!max_per_manager[i] || parseInt(docs[j].week_num) > parseInt(max_per_manager[i].week_num)){
                 max_per_manager[i] = docs[j];
             }
          }
        }
      }

      //now i need to loop through the array of maxes and identifty the ones that are
      // less than 5 weeks out
      var five_weeks_from_now = new Date().getTime() + (5*7*60*60*24*1000);
      var lastest_schedule_start_date = new Date()

      for (i = 0; i<=max_per_manager.length-1; i++ ){

        lastest_schedule_start_date = new Date(max_per_manager[i].schedule_start)

        if (lastest_schedule_start_date < five_weeks_from_now){
          // 1) need to see how many weeks i need to fill in to exceed 5 weeks
          // 2) need to set loop parameter to be from 1
          // 3) need to save to database

          //step 1
          var timeDiff = Math.abs(five_weeks_from_now - lastest_schedule_start_date);
          var diffDays = Math.ceil(timeDiff / (7 * 1000 * 3600 * 24));

          var schedule_start = new Date(lastest_schedule_start_date);
          var schedule_end = new Date(lastest_schedule_start_date);
          var schedule_release = new Date(schedule_start - (7*60*60*24*1000));
          var employee_lockout = new Date(schedule_start - (8*60*60*24*1000));
          var manager_lockout = new Date(schedule_start - (13*60*60*24*1000));

          schedule_start.setTime((schedule_start.getTime()+(7*60*60*24*1000)))
          schedule_end.setTime((schedule_end.getTime()+(13*60*60*24*1000)))

          //step 2
          for(j = 0; j<= diffDays; j ++){

            schedule_start.setTime((schedule_start.getTime()+(j*7*60*60*24*1000)))
            schedule_end.setTime((schedule_end.getTime()+(j*7*60*60*24*1000)))
            schedule_release.setTime((schedule_release.getTime()+(j*7*60*60*24*1000)))
            employee_lockout.setTime((employee_lockout.getTime()+(j*7*60*60*24*1000)))
            manager_lockout.setTime((manager_lockout.getTime()+(j*7*60*60*24*1000)))
*/
            /* define what needs to be saved*/
/*            const quickshifts_customer_timeline = new Quickshifts_customer_timeline({
              "week_num": parseInt(max_per_manager[i].week_num) + j + 1,
              "manager_userid" : max_per_manager[i].manager_userid,
              "manager_email"  : max_per_manager[i].manager_email,
              "schedule_start" : schedule_start.toDateString(),
              "schedule_end"  : schedule_end.toDateString(),
              "final_schedule_release"  : schedule_release.toDateString(),
              "employee_lockout"  : employee_lockout.toDateString(),
              "manager_lockout"  : manager_lockout.toDateString()
              });

            //quickshifts_customer_timeline.save((err) => {
            //  if (err) {
            //    return next(err);
            //  }
            //  console.log(quickshifts_customer_timeline)
            //  console.log("SAVED!");
            //});

          }

        }
      }

    //where Quickshifts_customer_timeline.find ends
    }
  // where cronjob ends
  )

}, null, true, 'America/Los_Angeles');

*/

new CronJob('* * * * * *', function() {
  console.log('You will see this message every second');
  var locals = {};
  var tasks = [
      function(callback){
        Secondaryshift.find(function (err, docs) {
          if (err) { return callback(err); }
          if (docs != null){
            locals.shifts = docs;
            callback();
          }
          else{
            locals.shifts = docs;
            callback();
          }
        });
      },
      function(callback){
        Shift.find(function (err, docs) {
          if (err) { return callback(err); }
          if (docs != null){
            locals.all_shifts = docs;
            callback();
          }
          else{
            locals.all_shifts = docs;
            callback();
          }
        });
      },

      function(callback){
          Quickshifts_customer_timeline.find( function (err, docs1) {
          if (err) { return next(err); }
          if (docs1 != null){
            locals.schedule = docs1;
            callback();
          }
          else{
            locals.schedule = docs1;
            callback();
          }

        });
      },

      function(callback){
          User.find({user_type: "schedule_type"}, function (err, docs1) {
          if (err) { return next(err); }
          if (docs1 != null){
            locals.manage = docs1;
            callback();
          }
          else{
            locals.manage = docs1;
            callback();
          }

        });
      },

  ];

async.parallel(tasks, function(err) {
    if (err) return next(err);
    //getting manager id for the first manager
    //console.log(locals.manage[0]._id)

    //******
    //******
    //iterating through all the manager_id's
    var manager_id
    for (var i = 0; i < locals.manage.length; i++){
        manager_id = locals.manage[i]._id
        //console.log(manager_id)
        //console.log(locals.shifts)

        //******
        //******
        //getting the max_date for what is currently in the secondary shifts table
        var max_date;
        for (var j=0 ; j<locals.shifts.length ; j++) {
            if (!max_date || parseInt(locals.shifts[j].date_range_start) > parseInt(max_date)){
              max_date = locals.shifts[j].date_range_start;
            }
         }

         //if there is no data in shifts the set date to a random date very
         //far in pass
         if(locals.shifts.length == 0){
           max_date = '01-01-1972'
         }

         //******
         //******
         // iterating through all the customer timelines and comparing
         // with the max date to understand if
        var schedule_dates_greater_than_max= []

        for(var j=0; j< locals.schedule.length; j++){
          //need to convert date to the same format
          var s_prettyDate = get_pretty_date(locals.schedule[j].schedule_start)

          //comparing to see if the current max date is smaller than
          //anything in the schedule array
          if (s_prettyDate >max_date){
            schedule_dates_greater_than_max.push(s_prettyDate)
          }
        }

        //******
        //******
        //checking to ensure there were things added to the array above, if not
        //i don't want to send any data processing to next steps outlined below
        if(schedule_dates_greater_than_max.length >0){

          //need to add code so i can push the dates from schedule_dates_greater_than_max
          //into a json and build information about schedules around that
          for(var j=0; j<schedule_dates_greater_than_max.length; j++){

            //ensuring that the there are shifts in the data
            if (locals.all_shifts.length >= 1){

              //for any given shift add the corresponding schedule start
              // and end date to the secondary shifts json
              //then i will add it to the database
              for(var p=0; p< locals.all_shifts.length; p++){

                var thedate = addDays(schedule_dates_greater_than_max[j], 6)
                var theprettydate = get_pretty_date(thedate)

                var start_date = schedule_dates_greater_than_max[j]
                var end_date = theprettydate

                const sec_shift = new Secondaryshift({
                  userid: manager_id,
                  date_range_start: start_date,
                  date_range_end: end_date,
                  employee_type: locals.all_shifts[p].employee_type,
                  days_worked: locals.all_shifts[p].days_worked,
                  num_employees: locals.all_shifts[p].num_employees,
                  shift_start_time: locals.all_shifts[p].shift_start_time,
                  shift_end_time: locals.all_shifts[p].shift_end_time}
                );

                //saving the shfit :)
                sec_shift.save((err) => {
                  if (err) {return next(err);}
                  console.log("SAVED!");
                });
              }
            }
          }
        }

     }

//ending async parallel call
});
}, null, true, 'America/Los_Angeles');
<commit_msg>fixed manager issues with the cron test.js for secondary shifts<commit_after>var CronJob = require('cron').CronJob;

const async = require('async');
const Quickshifts_customer_timeline = require('../models/Quickshifts_customer_timeline.js');
const Secondaryshift = require('../models/Secondaryshift.js');
const Shift = require('../models/Shift.js');
const User = require('../models/User.js');
const EventEmitter = require('events');
/*
-----------------------------------------------------
-------GETTING ALL INFORMATION NEEDED FOR PAGE LOAD
-----------------------------------------------------
*/

//a function to only return unique values of an array, used in the below code
//search for onlyUnique
function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function get_pretty_date(value){
  var start_date = new Date(value)
  var s_year = start_date.getFullYear();
  var s_month = start_date.getMonth() + 1;
  if(s_month <= 9)
      s_month = '0'+s_month;
  var s_day= start_date.getDate();
  if(s_day <= 9)
      s_day = '0'+s_day;

  var s_prettyDate = s_month +'-'+ s_day + '-'+  s_year
  return s_prettyDate
}

function addDays(date, days) {
    var result = new Date(date);
    result.setDate(result.getDate() + days);
    return result;
}

/*
new CronJob('* * * * * *', function() {
  console.log('You will see this message every second');
  Quickshifts_customer_timeline.find(function (err,docs){
    if (err) { return callback(err); }
      //setting an array up to collect distinct manager user_id
      var manager_user_ids = []
      //console.log(docs)
      //collating all the manager user id's then using a function defined above
      //to get unique manager user ids'
      for (i = 0; i <= docs.length-1; i++) {
        manager_user_ids.push(docs[i].manager_userid)
      }
      var unique_manager_user_ids = manager_user_ids.filter(onlyUnique);

      var max_per_manager = []

      //goal with the below code is to 1) get the max schedule #

      //looping through manager user_id's and comparing to with the overall json
      for (i = 0; i<= unique_manager_user_ids.length-1; i++){
        for(j = 0; j<= docs.length-1; j++){
          if (unique_manager_user_ids[i] == docs[j].manager_userid ){
             if (!max_per_manager[i] || parseInt(docs[j].week_num) > parseInt(max_per_manager[i].week_num)){
                 max_per_manager[i] = docs[j];
             }
          }
        }
      }

      //now i need to loop through the array of maxes and identifty the ones that are
      // less than 5 weeks out
      var five_weeks_from_now = new Date().getTime() + (5*7*60*60*24*1000);
      var lastest_schedule_start_date = new Date()

      for (i = 0; i<=max_per_manager.length-1; i++ ){

        lastest_schedule_start_date = new Date(max_per_manager[i].schedule_start)

        if (lastest_schedule_start_date < five_weeks_from_now){
          // 1) need to see how many weeks i need to fill in to exceed 5 weeks
          // 2) need to set loop parameter to be from 1
          // 3) need to save to database

          //step 1
          var timeDiff = Math.abs(five_weeks_from_now - lastest_schedule_start_date);
          var diffDays = Math.ceil(timeDiff / (7 * 1000 * 3600 * 24));

          var schedule_start = new Date(lastest_schedule_start_date);
          var schedule_end = new Date(lastest_schedule_start_date);
          var schedule_release = new Date(schedule_start - (7*60*60*24*1000));
          var employee_lockout = new Date(schedule_start - (8*60*60*24*1000));
          var manager_lockout = new Date(schedule_start - (13*60*60*24*1000));

          schedule_start.setTime((schedule_start.getTime()+(7*60*60*24*1000)))
          schedule_end.setTime((schedule_end.getTime()+(13*60*60*24*1000)))

          //step 2
          for(j = 0; j<= diffDays; j ++){

            schedule_start.setTime((schedule_start.getTime()+(j*7*60*60*24*1000)))
            schedule_end.setTime((schedule_end.getTime()+(j*7*60*60*24*1000)))
            schedule_release.setTime((schedule_release.getTime()+(j*7*60*60*24*1000)))
            employee_lockout.setTime((employee_lockout.getTime()+(j*7*60*60*24*1000)))
            manager_lockout.setTime((manager_lockout.getTime()+(j*7*60*60*24*1000)))
*/
            /* define what needs to be saved*/
/*            const quickshifts_customer_timeline = new Quickshifts_customer_timeline({
              "week_num": parseInt(max_per_manager[i].week_num) + j + 1,
              "manager_userid" : max_per_manager[i].manager_userid,
              "manager_email"  : max_per_manager[i].manager_email,
              "schedule_start" : schedule_start.toDateString(),
              "schedule_end"  : schedule_end.toDateString(),
              "final_schedule_release"  : schedule_release.toDateString(),
              "employee_lockout"  : employee_lockout.toDateString(),
              "manager_lockout"  : manager_lockout.toDateString()
              });

            //quickshifts_customer_timeline.save((err) => {
            //  if (err) {
            //    return next(err);
            //  }
            //  console.log(quickshifts_customer_timeline)
            //  console.log("SAVED!");
            //});

          }

        }
      }

    //where Quickshifts_customer_timeline.find ends
    }
  // where cronjob ends
  )

}, null, true, 'America/Los_Angeles');

*/

new CronJob('* * * * * *', function() {
  console.log('You will see this message every second');
  var locals = {};
  var tasks = [
      function(callback){
        Secondaryshift.find(function (err, docs) {
          if (err) { return callback(err); }
          if (docs != null){
            locals.shifts = docs;
            callback();
          }
          else{
            locals.shifts = docs;
            callback();
          }
        });
      },
      function(callback){
        Shift.find(function (err, docs) {
          if (err) { return callback(err); }
          if (docs != null){
            locals.all_shifts = docs;
            callback();
          }
          else{
            locals.all_shifts = docs;
            callback();
          }
        });
      },

      function(callback){
          Quickshifts_customer_timeline.find( function (err, docs1) {
          if (err) { return next(err); }
          if (docs1 != null){
            locals.schedule = docs1;
            callback();
          }
          else{
            locals.schedule = docs1;
            callback();
          }

        });
      },

      function(callback){
          User.find({user_type: "schedule_type"}, function (err, docs1) {
          if (err) { return next(err); }
          if (docs1 != null){
            locals.manage = docs1;
            callback();
          }
          else{
            locals.manage = docs1;
            callback();
          }

        });
      },

  ];

async.parallel(tasks, function(err) {
    if (err) return next(err);
    //getting manager id for the first manager
    //console.log(locals.manage[0]._id)

    //******
    //******
    //iterating through all the manager_id's
    var manager_id
    for (var i = 0; i < locals.manage.length; i++){
        manager_id = locals.manage[i]._id
        //console.log(manager_id)
        //console.log(locals.shifts)

        //******
        //******
        //getting the max_date for what is currently in the secondary shifts table
        var max_date;
        for (var j=0 ; j<locals.shifts.length ; j++) {
          if (manager_id == locals.shifts[j].user_id) {
            if (!max_date || parseInt(locals.shifts[j].date_range_start) > parseInt(max_date)){
              max_date = locals.shifts[j].date_range_start;
            }
          }
         }

         //if there is no data in shifts the set date to a random date very
         //far in pass
         if(locals.shifts.length == 0){
           max_date = '01-01-1972'
         }

         //******
         //******
         // iterating through all the customer timelines and comparing
         // with the max date to understand if
        var schedule_dates_greater_than_max= []

        for(var j=0; j< locals.schedule.length; j++){
          if(manager_id == locals.schedule[j].manager_userid){

            //need to convert date to the same format
            var s_prettyDate = get_pretty_date(locals.schedule[j].schedule_start)

            //comparing to see if the current max date is smaller than
            //anything in the schedule array
            if (s_prettyDate >max_date){
              schedule_dates_greater_than_max.push(s_prettyDate)
            }
        }
        }

        //******
        //******
        //checking to ensure there were things added to the array above, if not
        //i don't want to send any data processing to next steps outlined below
        if(schedule_dates_greater_than_max.length >0){

          //need to add code so i can push the dates from schedule_dates_greater_than_max
          //into a json and build information about schedules around that
          for(var j=0; j<schedule_dates_greater_than_max.length; j++){

            //ensuring that the there are shifts in the data
            if (locals.all_shifts.length >= 1){

              //for any given shift add the corresponding schedule start
              // and end date to the secondary shifts json
              //then i will add it to the database
              for(var p=0; p< locals.all_shifts.length; p++){
                if(manager_id == locals.all_shifts[p].userid){
                  var thedate = addDays(schedule_dates_greater_than_max[j], 6)
                  var theprettydate = get_pretty_date(thedate)

                  var start_date = schedule_dates_greater_than_max[j]
                  var end_date = theprettydate

                  const sec_shift = new Secondaryshift({
                    userid: manager_id,
                    date_range_start: start_date,
                    date_range_end: end_date,
                    employee_type: locals.all_shifts[p].employee_type,
                    days_worked: locals.all_shifts[p].days_worked,
                    num_employees: locals.all_shifts[p].num_employees,
                    shift_start_time: locals.all_shifts[p].shift_start_time,
                    shift_end_time: locals.all_shifts[p].shift_end_time}
                  );

                  //saving the shfit :)
                  sec_shift.save((err) => {
                    if (err) {return next(err);}
                    console.log("SAVED!");
                  });
                }
              }
            }
          }
        }

     }

//ending async parallel call
});
}, null, true, 'America/Los_Angeles');
<|endoftext|>


<commit_before>import styled from 'styled-components'
import {Box} from '@primer/components'

const Table = styled.table`
  display: table !important;
  border-collapse: separate;
  border-spacing: 0 4px;

  tr,
  td,
  th {
    border: 0 !important;
  }

  td,
  th {
    text-align: left;
  }

  tr {
    background-color: transparent !important;
  }
`

Table.Row = styled(Box).attrs({as: 'tr'})``
Table.Cell = styled(Box).attrs({as: 'td'})``

export default Table
<commit_msg>fix <caption> alignment, add borderSpacing<commit_after>import styled from 'styled-components'
import PropTypes from 'prop-types'
import {Box} from '@primer/components'

const Table = styled.table`
  display: table !important;
  border-collapse: separate;
  border-spacing: ${props => props.borderSpacing};

  tr,
  td,
  th {
    border: 0 !important;
  }

  caption,
  td,
  th {
    padding: 4px 8px !important;
    text-align: left;
  }

  tr {
    background-color: transparent !important;
  }
`

Table.propTypes = {
  borderSpacing: PropTypes.string
}

Table.defaultProps = {
  borderSpacing: '0 4px'
}

Table.Row = styled(Box).attrs({as: 'tr'})``
Table.Cell = styled(Box).attrs({as: 'td'})``

export default Table
<|endoftext|>


<commit_before>import { createTranslator } from 'kolibri.utils.i18n';

const groupMgmtStrings = createTranslator('GroupManagementStrings', {
  // Actions
  addLearnersAction: 'Add learners',
  manageLearners: 'Manage learners',
  add: 'Add',
  update: 'Update',
  addAndRemove: 'Add',

  // Labels
  addLearnersLabel: "Add learners to '{groupName}'",
  createNewGroupLabel: 'Create new group',
  currentGroups: 'Current groups',
  deleteGroupLabel: 'Delete group',
  removeFromCurrent: 'Remove learners from current groups',
  selectAllToggle: 'Select all',
  selectedLabel: 'Selected',
  selectGroupsLabel: 'Select groups',
  selectLearnersLabel: 'Select learners',
  selectLearnerToggle: 'Select learner',

  // Longer text
  areYouSurePrompt: "Are you sure you want to delete '{ groupName }'?",
  noLearnersDescription: 'There are no learners in this group',

  // notifications
  groupDeletedNotice: 'Group deleted',
  groupCreatedNotice: 'Group ceated',
  addedLearnersNotice:
    'Added {value, number, integer} {value, plural, one {learner} other {learners}}',
  removedLearnersNotice:
    'Removed {value, number, integer} {value, plural, one {learner} other {learners}}',
});

const groupMgmtStringsMixin = {
  computed: {
    groupMgmtStrings() {
      return groupMgmtStrings;
    },
  },
};

export { groupMgmtStrings, groupMgmtStringsMixin };
<commit_msg>Fix typo<commit_after>import { createTranslator } from 'kolibri.utils.i18n';

const groupMgmtStrings = createTranslator('GroupManagementStrings', {
  // Actions
  addLearnersAction: 'Add learners',
  manageLearners: 'Manage learners',
  add: 'Add',
  update: 'Update',
  addAndRemove: 'Add',

  // Labels
  addLearnersLabel: "Add learners to '{groupName}'",
  createNewGroupLabel: 'Create new group',
  currentGroups: 'Current groups',
  deleteGroupLabel: 'Delete group',
  removeFromCurrent: 'Remove learners from current groups',
  selectAllToggle: 'Select all',
  selectedLabel: 'Selected',
  selectGroupsLabel: 'Select groups',
  selectLearnersLabel: 'Select learners',
  selectLearnerToggle: 'Select learner',

  // Longer text
  areYouSurePrompt: "Are you sure you want to delete '{ groupName }'?",
  noLearnersDescription: 'There are no learners in this group',

  // notifications
  groupDeletedNotice: 'Group deleted',
  groupCreatedNotice: 'Group created',
  addedLearnersNotice:
    'Added {value, number, integer} {value, plural, one {learner} other {learners}}',
  removedLearnersNotice:
    'Removed {value, number, integer} {value, plural, one {learner} other {learners}}',
});

const groupMgmtStringsMixin = {
  computed: {
    groupMgmtStrings() {
      return groupMgmtStrings;
    },
  },
};

export { groupMgmtStrings, groupMgmtStringsMixin };
<|endoftext|>


<commit_before>'use strict';

(function() {
  angular.module('archivesSpaceController', ['alertService', 'sipArrangeService', 'transferService', 'ui.bootstrap']).

  controller('ArchivesSpaceController', ['$scope', '$modal', 'Alert', 'ArchivesSpace', 'SipArrange', 'Transfer', function($scope, $modal, Alert, ArchivesSpace, SipArrange, Transfer) {
    var levels_of_description = ArchivesSpace.get_levels_of_description().$object;
      $scope.edit = function(node) {
        var form = $modal.open({
          templateUrl: 'archivesspace/form.html',
          controller: 'ArchivesSpaceEditController',
          controllerAs: 'form',
          resolve: {
            levels: function() {
              return levels_of_description;
            },
            title: function() {
              return node.title;
            },
            level: function() {
              return node.levelOfDescription;
            },
          },
        });
        form.result.then(function(result) {
          // Assign these to variables so we can restore them if the PUT fails
          var original_title = node.title;
          var original_level = node.levelOfDescription;

          node.title = result.title;
          node.levelOfDescription = result.level;
          // Any node with pending requests will be marked as non-editable
          node.request_pending = true;

          var on_success = function(response) {
            node.request_pending = false;
          };

          var on_failure = function(error) {
            // Restore the original title/level since the request failed
            node.title = original_title;
            node.levelOfDescription = original_level;
            node.request_pending = false;

            var title = node.title;
            if (node.identifier) {
              title = title + ' (' + node.identifier + ')';
            }

            Alert.alerts.push({
              type: 'danger',
              message: 'Unable to submit edits to record "' + title + '"; check dashboard logs.',
            });
          };

          ArchivesSpace.edit(node.id, node).then(on_success, on_failure);
        });
      };

      $scope.add_child = function(node) {
        var form = $modal.open({
          templateUrl: 'archivesspace/form.html',
          controller: 'ArchivesSpaceEditController',
          controllerAs: 'form',
          resolve: {
            levels: function() {
              return ArchivesSpace.get_levels_of_description().$object;
            },
            title: function() {
              return '';
            },
            level: function() {
              return '';
            },
          },
        });
        form.result.then(function(result) {
          result.levelOfDescription = result.level;

          var on_success = function(response) {
            result.id = response.id;
            if (!node.has_children) {
              node.has_children = true;
              node.children = [];
              node.children_fetched = false;
            }
            node.children.push(result);
          };

          var on_failure = function(error) {
            Alert.alerts.append({
              type: 'danger',
              message: 'Unable to add new child record to record ' + node.id,
            });
          };

          ArchivesSpace.add_child(node.id, result).then(on_success, on_failure);
        });
      };

      $scope.options = {
        dirSelectable: true,
        equality: function(a, b) {
          if (a === undefined || b === undefined) {
            return false;
          } else if (a.id && b.id) {
            return a.id === b.id;
          } else {
            return a.path === b.path;
          }
        },
        isLeaf: function(node) {
          return !node.has_children;
        },
      };

      // Loads the children of the specified element,
      // along with arranged SIP contents that might exist
      var load_element_children = function(node) {
        $scope.loading = true;

        var on_failure_aspace = function(error) {
          Alert.alerts.push({
            type: 'danger',
            message: 'Unable to fetch record ' + node.id + ' from ArchivesSpace!',
          });
          $scope.loading = false;
        };

        var on_failure_arrange = function(error) {
          Alert.alerts.push({
            type: 'danger',
            message: 'Unable to fetch record ' + node.path + ' from Arrangement!',
          });
          $scope.loading = false;
        };

        node.children = [];

        if (node.id) {  // ArchivesSpace node
          ArchivesSpace.get_children(node.id).then(function(children) {
            node.children = node.children.concat(children);
            node.children_fetched = true;
            $scope.loading = false;
          }, on_failure_aspace);

          // Also call into SIP arrange to see if there are any contents at this
          // level of description; if so, render them like any other ASpace objects
          ArchivesSpace.list_arrange_contents(node.id, node).then(function(entries) {
            node.children = node.children.concat(entries);
          });
        } else {  // SipArrange node
          SipArrange.list_contents(node.path, node).then(function(entries) {
            node.children = entries;
            node.children_fetched = true;
            $scope.loading = false;
          }, on_failure_arrange);
        }
      };

      $scope.on_toggle = function(node, expanded) {
        if (!expanded || !node.has_children || node.children_fetched) {
          return;
        }

        load_element_children(node);
      };

      // TODO: handle failure to contact ArchivesSpace here;
      //       probably want to scope this to only happen if ASpace pane is opened.
      //       (The controller is always instantiated before the pane opens,
      //       so adding an alert here would always render even if ArchivesSpace
      //       wasn't clicked.)
      ArchivesSpace.all().then(function(data) {
        $scope.data = data;
      });

      // Prevent a given file or its descendants from being dragged more than once
      var dragged_ids = [];
      var log_ids = function(file) {
        dragged_ids.push(file.id);
        if (file.children) {
          for (var i = 0; i < file.children.length; i++) {
            log_ids(file.children[i]);
          }
        }
      }

      // Filter the list of dragged files to contain only files with the "display"
      // parameter, so that only visibly selected files are dragged over
      var filter_files = function(file) {
        if (!file.display) {
          return {};
        }

        // Filter children recursively
        if (file.children) {
          var children = file.children;
          file.children = [];
          angular.forEach(children, function(child) {
            child = filter_files(child);
            // Omit empty objects, or directories whose children have all been filtered out
            if (child.id && child.type === 'file' || (child.children && child.children.length > 0)) {
              file.children.push(child);
            }
          });
        }

        return file;
      };

      $scope.drop = function(unused, ui) {
        if ($scope.loading) {
          return;
        }

        var file_uuid = ui.draggable.attr('uuid');
        var file = Transfer.id_map[file_uuid];
        if (dragged_ids.indexOf(file_uuid) !== -1) {
          alert('File "' + file.title + '" already added.');
          return;
        }

        if (this.id) {  // ArchivesSpace information object
          return drop_onto_aspace_record.apply(this, [file]);
        } else {  // file within arrange
          return drop_onto_arrange_directory.apply(this, [file]);
        }
      };

      var drop_onto_aspace_record = function(file) {
        var self = this;

        // create a deep copy of the file and its children so we don't mutate
        // the copies used in the backlog
        file = filter_files(_.extend({}, file));
        if (!file.id) {
          return;
        }

        var on_directory_creation = function(response) {
          // Add path to parent
          self.path = response.path;
          ArchivesSpace.copy_to_arrange(self.id, '/originals/' + source_path).then(on_copy);
        };

        var on_copy = function() {
          if ($scope.expanded_nodes.indexOf(self) === -1) {
            $scope.expanded_nodes.push(self);
            // expanded event will not fire if the node was programmatically expanded - this loads children
            $scope.on_toggle(self, true);
          } else {
            // Reload the directory to reflect new contents
            load_element_children(self);
          }
        };

        var source_path;
        if (file.type === 'file') {
          source_path = file.relative_path;
        } else {
          source_path = file.relative_path + '/';
        }

        $scope.$apply(function() {
          $scope.loading = true;

          ArchivesSpace.create_directory(self.id).then(on_directory_creation);
        });
      };

      var drop_onto_arrange_directory = function(file) {
        var self = this;

        // Reload the directory to reflect new contents
        var on_success = function(entries) {
          self.parent.children = entries;
        };

        $scope.$apply(function() {
          SipArrange.list_contents('/arrange/' + self.parent.path, self.parent.parent).then(on_success);
        });
      };

      $scope.finalize_arrangement = function(node) {
        var on_success = function() {
          Alert.alerts.push({
            type: 'success',
            message: 'Successfully started SIP from record "' + node.title + '"',
          });
        };
        var on_failure = function(error) {
          var message;
          // error.message won't be defined if this returned an HTML 500
          if (error.message && error.message.startsWith('No SIP Arrange mapping')) {
            message = 'Unable to start SIP; no files arranged into record "' + node.title + '".';
          } else {
            message = 'Unable to start SIP; check dashboard logs.';
          }
          Alert.alerts.push({
            type: 'danger',
            message: message,
          });
        };

        ArchivesSpace.start_sip(node.id).then(on_success, on_failure);
      };
    }]).

  controller('ArchivesSpaceEditController', ['$modalInstance', 'levels', 'level', 'title', function($modalInstance, levels, level, title) {
    var vm = this;

    vm.levels = levels;
    vm.level = level;
    vm.title = title;

    vm.ok = function() {
      $modalInstance.close(vm);
    };
    vm.cancel = function() {
      $modalInstance.dismiss('cancel');
    };
  }]);
})();
<commit_msg>ArchivesSpace: children track their parent<commit_after>'use strict';

(function() {
  angular.module('archivesSpaceController', ['alertService', 'sipArrangeService', 'transferService', 'ui.bootstrap']).

  controller('ArchivesSpaceController', ['$scope', '$modal', 'Alert', 'ArchivesSpace', 'SipArrange', 'Transfer', function($scope, $modal, Alert, ArchivesSpace, SipArrange, Transfer) {
    var levels_of_description = ArchivesSpace.get_levels_of_description().$object;
      $scope.edit = function(node) {
        var form = $modal.open({
          templateUrl: 'archivesspace/form.html',
          controller: 'ArchivesSpaceEditController',
          controllerAs: 'form',
          resolve: {
            levels: function() {
              return levels_of_description;
            },
            title: function() {
              return node.title;
            },
            level: function() {
              return node.levelOfDescription;
            },
          },
        });
        form.result.then(function(result) {
          // Assign these to variables so we can restore them if the PUT fails
          var original_title = node.title;
          var original_level = node.levelOfDescription;

          node.title = result.title;
          node.levelOfDescription = result.level;
          // Any node with pending requests will be marked as non-editable
          node.request_pending = true;

          var on_success = function(response) {
            node.request_pending = false;
          };

          var on_failure = function(error) {
            // Restore the original title/level since the request failed
            node.title = original_title;
            node.levelOfDescription = original_level;
            node.request_pending = false;

            var title = node.title;
            if (node.identifier) {
              title = title + ' (' + node.identifier + ')';
            }

            Alert.alerts.push({
              type: 'danger',
              message: 'Unable to submit edits to record "' + title + '"; check dashboard logs.',
            });
          };

          ArchivesSpace.edit(node.id, node).then(on_success, on_failure);
        });
      };

      $scope.add_child = function(node) {
        var form = $modal.open({
          templateUrl: 'archivesspace/form.html',
          controller: 'ArchivesSpaceEditController',
          controllerAs: 'form',
          resolve: {
            levels: function() {
              return ArchivesSpace.get_levels_of_description().$object;
            },
            title: function() {
              return '';
            },
            level: function() {
              return '';
            },
          },
        });
        form.result.then(function(result) {
          result.levelOfDescription = result.level;

          var on_success = function(response) {
            result.id = response.id;
            result.parent = node;
            if (!node.has_children) {
              node.has_children = true;
              node.children = [];
              node.children_fetched = false;
            }
            node.children.push(result);
          };

          var on_failure = function(error) {
            Alert.alerts.append({
              type: 'danger',
              message: 'Unable to add new child record to record ' + node.id,
            });
          };

          ArchivesSpace.add_child(node.id, result).then(on_success, on_failure);
        });
      };

      $scope.options = {
        dirSelectable: true,
        equality: function(a, b) {
          if (a === undefined || b === undefined) {
            return false;
          } else if (a.id && b.id) {
            return a.id === b.id;
          } else {
            return a.path === b.path;
          }
        },
        isLeaf: function(node) {
          return !node.has_children;
        },
      };

      // Loads the children of the specified element,
      // along with arranged SIP contents that might exist
      var load_element_children = function(node) {
        $scope.loading = true;

        var on_failure_aspace = function(error) {
          Alert.alerts.push({
            type: 'danger',
            message: 'Unable to fetch record ' + node.id + ' from ArchivesSpace!',
          });
          $scope.loading = false;
        };

        var on_failure_arrange = function(error) {
          Alert.alerts.push({
            type: 'danger',
            message: 'Unable to fetch record ' + node.path + ' from Arrangement!',
          });
          $scope.loading = false;
        };

        node.children = [];

        if (node.id) {  // ArchivesSpace node
          ArchivesSpace.get_children(node.id).then(function(children) {
            children.map(function(element) { element.parent = node; });
            node.children = node.children.concat(children);
            node.children_fetched = true;
            $scope.loading = false;
          }, on_failure_aspace);

          // Also call into SIP arrange to see if there are any contents at this
          // level of description; if so, render them like any other ASpace objects
          ArchivesSpace.list_arrange_contents(node.id, node).then(function(entries) {
            node.children = node.children.concat(entries);
          });
        } else {  // SipArrange node
          SipArrange.list_contents(node.path, node).then(function(entries) {
            node.children = entries;
            node.children_fetched = true;
            $scope.loading = false;
          }, on_failure_arrange);
        }
      };

      $scope.on_toggle = function(node, expanded) {
        if (!expanded || !node.has_children || node.children_fetched) {
          return;
        }

        load_element_children(node);
      };

      // TODO: handle failure to contact ArchivesSpace here;
      //       probably want to scope this to only happen if ASpace pane is opened.
      //       (The controller is always instantiated before the pane opens,
      //       so adding an alert here would always render even if ArchivesSpace
      //       wasn't clicked.)
      ArchivesSpace.all().then(function(data) {
        $scope.data = data;
      });

      // Prevent a given file or its descendants from being dragged more than once
      var dragged_ids = [];
      var log_ids = function(file) {
        dragged_ids.push(file.id);
        if (file.children) {
          for (var i = 0; i < file.children.length; i++) {
            log_ids(file.children[i]);
          }
        }
      }

      // Filter the list of dragged files to contain only files with the "display"
      // parameter, so that only visibly selected files are dragged over
      var filter_files = function(file) {
        if (!file.display) {
          return {};
        }

        // Filter children recursively
        if (file.children) {
          var children = file.children;
          file.children = [];
          angular.forEach(children, function(child) {
            child = filter_files(child);
            // Omit empty objects, or directories whose children have all been filtered out
            if (child.id && child.type === 'file' || (child.children && child.children.length > 0)) {
              file.children.push(child);
            }
          });
        }

        return file;
      };

      $scope.drop = function(unused, ui) {
        if ($scope.loading) {
          return;
        }

        var file_uuid = ui.draggable.attr('uuid');
        var file = Transfer.id_map[file_uuid];
        if (dragged_ids.indexOf(file_uuid) !== -1) {
          alert('File "' + file.title + '" already added.');
          return;
        }

        if (this.id) {  // ArchivesSpace information object
          return drop_onto_aspace_record.apply(this, [file]);
        } else {  // file within arrange
          return drop_onto_arrange_directory.apply(this, [file]);
        }
      };

      var drop_onto_aspace_record = function(file) {
        var self = this;

        // create a deep copy of the file and its children so we don't mutate
        // the copies used in the backlog
        file = filter_files(_.extend({}, file));
        if (!file.id) {
          return;
        }

        var on_directory_creation = function(response) {
          // Add path to parent
          self.path = response.path;
          ArchivesSpace.copy_to_arrange(self.id, '/originals/' + source_path).then(on_copy);
        };

        var on_copy = function() {
          if ($scope.expanded_nodes.indexOf(self) === -1) {
            $scope.expanded_nodes.push(self);
            // expanded event will not fire if the node was programmatically expanded - this loads children
            $scope.on_toggle(self, true);
          } else {
            // Reload the directory to reflect new contents
            load_element_children(self);
          }
        };

        var source_path;
        if (file.type === 'file') {
          source_path = file.relative_path;
        } else {
          source_path = file.relative_path + '/';
        }

        $scope.$apply(function() {
          $scope.loading = true;

          ArchivesSpace.create_directory(self.id).then(on_directory_creation);
        });
      };

      var drop_onto_arrange_directory = function(file) {
        var self = this;

        // Reload the directory to reflect new contents
        var on_success = function(entries) {
          self.parent.children = entries;
        };

        $scope.$apply(function() {
          SipArrange.list_contents('/arrange/' + self.parent.path, self.parent.parent).then(on_success);
        });
      };

      $scope.finalize_arrangement = function(node) {
        var on_success = function() {
          Alert.alerts.push({
            type: 'success',
            message: 'Successfully started SIP from record "' + node.title + '"',
          });
        };
        var on_failure = function(error) {
          var message;
          // error.message won't be defined if this returned an HTML 500
          if (error.message && error.message.startsWith('No SIP Arrange mapping')) {
            message = 'Unable to start SIP; no files arranged into record "' + node.title + '".';
          } else {
            message = 'Unable to start SIP; check dashboard logs.';
          }
          Alert.alerts.push({
            type: 'danger',
            message: message,
          });
        };

        ArchivesSpace.start_sip(node.id).then(on_success, on_failure);
      };
    }]).

  controller('ArchivesSpaceEditController', ['$modalInstance', 'levels', 'level', 'title', function($modalInstance, levels, level, title) {
    var vm = this;

    vm.levels = levels;
    vm.level = level;
    vm.title = title;

    vm.ok = function() {
      $modalInstance.close(vm);
    };
    vm.cancel = function() {
      $modalInstance.dismiss('cancel');
    };
  }]);
})();
<|endoftext|>


<commit_before>(function (root) {
  "use strict";

  root.GOVUK.GDM = root.GOVUK.GDM || {};
  root.GOVUK.GDM.analytics = {
    'register': function () {
      var cookieDomain = (root.document.domain === 'www.digitalmarketplace.service.gov.uk') ? '.digitalmarketplace.service.gov.uk' : root.document.domain;
      var universalId = 'UA-49258698-1';

      GOVUK.Analytics.load();
      GOVUK.analytics = new GOVUK.Analytics({
        universalId: universalId,
        cookieDomain: cookieDomain,
        receiveCrossDomainTracking: true
      });
      GOVUK.analytics.addLinkedTrackerDomain('digitalservicesstore.service.gov.uk');
    }
  };
})(window);
<commit_msg>No longer set cross-domain tracking<commit_after>(function (root) {
  "use strict";

  root.GOVUK.GDM = root.GOVUK.GDM || {};
  root.GOVUK.GDM.analytics = {
    'register': function () {
      var cookieDomain = (root.document.domain === 'www.digitalmarketplace.service.gov.uk') ? '.digitalmarketplace.service.gov.uk' : root.document.domain;
      var universalId = 'UA-49258698-1';

      GOVUK.Analytics.load();
      GOVUK.analytics = new GOVUK.Analytics({
        universalId: universalId,
        cookieDomain: cookieDomain
      });
    }
  };
})(window);
<|endoftext|>


<commit_before>var path = require('path');
var utils = require('./utils');
var config = require('../config');

function resolve(dir) {
    return path.join(__dirname, '..', dir);
}

module.exports = {
    entry: {
        app: './examples/index.js'
    },
    output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
        publicPath: process.env.NODE_ENV === 'production'
            ? config.build.assetsPublicPath
            : config.dev.assetsPublicPath
    },
    resolve: {
        extensions: ['.js', '.json'],
        alias: {
            'src': resolve('src'),
            'examples': resolve('examples'),
            'assets': resolve('examples/assets'),
            'sass': resolve('examples/assets/sass'),
            'stylesheets': resolve('examples/assets/stylesheets'),
            'components': resolve('examples/components'),
            'containers': resolve('examples/containers'),
            'modules': resolve('examples/containers/app/modules'),
            'dist': resolve('dist'),
            'vendors': resolve('examples/vendors'),
            'reduxes': resolve('examples/reduxes'),
            'docs': resolve('docs')
        }
    },
    module: {
        rules: [{
            test: /\.js$/,
            loader: 'babel-loader',
            include: [resolve('examples'), resolve('src')]
        }, {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url-loader',
            query: {
                limit: 1000,
                name: utils.assetsPath('img/[name].[hash:7].[ext]')
            }
        }, {
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'url-loader',
            query: {
                limit: 1000,
                name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
            }
        }, {
            test: /\.json$/,
            loader: 'json-loader'
        }, {
            test: /\.ht?ml/,
            loader: 'html-loader'
        }]
    }
};<commit_msg>update webpack config<commit_after>const path = require('path'),
    utils = require('./utils'),
    config = require('../config');

function resolve(dir) {
    return path.join(__dirname, '..', dir);
}

module.exports = {
    entry: {
        app: './examples/index.js'
    },
    output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
        publicPath: process.env.NODE_ENV === 'production'
            ? config.build.assetsPublicPath
            : config.dev.assetsPublicPath
    },
    resolve: {
        extensions: ['.js', '.json'],
        alias: {
            'src': resolve('src'),
            'examples': resolve('examples'),
            'assets': resolve('examples/assets'),
            'sass': resolve('examples/assets/sass'),
            'stylesheets': resolve('examples/assets/stylesheets'),
            'components': resolve('examples/components'),
            'containers': resolve('examples/containers'),
            'modules': resolve('examples/containers/app/modules'),
            'dist': resolve('dist'),
            'vendors': resolve('examples/vendors'),
            'reduxes': resolve('examples/reduxes'),
            'docs': resolve('docs')
        }
    },
    module: {
        rules: [{
            test: /\.js$/,
            loader: 'babel-loader',
            include: [resolve('examples'), resolve('src')]
        }, {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url-loader',
            query: {
                limit: 1000,
                name: utils.assetsPath('img/[name].[hash:7].[ext]')
            }
        }, {
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'url-loader',
            query: {
                limit: 1000,
                name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
            }
        }, {
            test: /\.json$/,
            loader: 'json-loader'
        }, {
            test: /\.ht?ml/,
            loader: 'html-loader'
        }]
    }
};<|endoftext|>


<commit_before><commit_msg>Fixes js console error<commit_after><|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require typeahead/typeahead.bundle
//= require chosen/chosen.jquery
//= require ladda/spin
//= require ladda/ladda
//= require jquery
//= require handlebars/handlebars
//= require_self
// Ladda
Ladda.bind('.ladda-button');<commit_msg>Revert "turn off ember"<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require typeahead/typeahead.bundle
//= require chosen/chosen.jquery
//= require ladda/spin
//= require ladda/ladda
//= require jquery
//= require handlebars/handlebars
//= require ember
//= require ember-data
//= require_self
//= require ./hanuman_ember
//= require ./surveys
//= require ./templates/all

// Ladda
Ladda.bind('.ladda-button');

// for more details see: http://emberjs.com/guides/application/
window.App = Ember.Application.create({
  LOG_TRANSITIONS: true
})
<|endoftext|>


<commit_before>(function ($) {
  $.fn.hideChildren = function (opts) {
    function create (element) {
      return $(document.createElement(element));
    }
    var options = $.extend({}, $.fn.hideChildren.defaults, opts);
    return this.each(function () {
      var $list = $(this),
          $children = $list.children(),
          $lastChild,
          $toggler,
          $toggleContainer,
          $layover;
      if ($children.length > options.startAtIndex + 2) {
        $layover = create("div").addClass("layover");
        $lastChild = $($children.get(options.startAtIndex - 1)).addClass("fader").append($layover);
        $children.slice(options.startAtIndex).hide();
        $toggleContainer = create("li").addClass("toggler").appendTo($list);
        $toggler = create("a").attr("href", "#").click(function (e) {
          e.preventDefault();
          $children.show();
          $toggleContainer.remove();
          $layover.remove();
          $lastChild.removeClass("fader");
        }).text(options.togglerText).appendTo($toggleContainer);
      }
    });
  };
  $.fn.hideChildren.defaults = {
    "startAtIndex": 3,
    "togglerText": "Vis alle"
  };
}(jQuery));<commit_msg>Fixing the build (JS lint).<commit_after>(function ($) {
  $.fn.hideChildren = function (opts) {
    function create(element) {
      return $(document.createElement(element));
    }
    var options = $.extend({}, $.fn.hideChildren.defaults, opts);
    return this.each(function () {
      var $list, $children, $lastChild, $toggler, $toggleContainer, $layover;

      $list = $(this);
      $children = $list.children();

      if ($children.length > options.startAtIndex + 2) {
        $layover = create("div").addClass("layover");
        $lastChild = $($children.get(options.startAtIndex - 1)).addClass("fader").append($layover);
        $children.slice(options.startAtIndex).hide();
        $toggleContainer = create("li").addClass("toggler").appendTo($list);
        $toggler = create("a").attr("href", "#").click(function (e) {
          e.preventDefault();
          $children.show();
          $toggleContainer.remove();
          $layover.remove();
          $lastChild.removeClass("fader");
        }).text(options.togglerText).appendTo($toggleContainer);
      }
    });
  };

  $.fn.hideChildren.defaults = {
    "startAtIndex": 3,
    "togglerText": "Vis alle"
  };
}(jQuery));<|endoftext|>


<commit_before>// The graph used for the visualization. added to own file
// to separate code for visualizing and keeping track of graph

var nodes = [];
var edges = [];
var graph;

function Graph(cy){
    this.addNode = function(n){
        if(typeof findNode(n.id) != 'undefined') {
            return
        }

        n.graphics.name = n.graphics.name.split(" ")
        if(n.name === "\"bg\"") {
            console.log(n.graphics.name[0])
            var a = n.graphics.name[0].split("/")
            var b = a[a.length-1]
            var url = "http://localhost:8080/public/pathways/"+b
            n.graphics.bgimage = url
            n.graphics.bgcolor = "#fff"
            n.graphics.name = ""
        }
        else{
            n.graphics.bgimage = "";
        }

        n.graphics.name = n.graphics.name.toString().replace(/,/g, " ")

        n.graphics.valign = "center"
        if(n.graphics.name.substr(0,2) == "C0"){
            n.graphics.valign = "bottom"
        }

        var no = {
            group: 'nodes',
            data: {
                id: ''+ n.id,
                name: JSON.parse(n.name),
                graphics: n.graphics,
                //background-image: "test.png",
            },
            position: {
                x: n.graphics.x,
                y: n.graphics.y
            },
            //grabbable: false,
            locked: true,
        };
        var  gr = no.data.graphics;

        if(gr.name == "" && gr.bgimage == ""){
            return
        }
        nodes.push(no);
        cy.add(no);

    };

    this.addEdge = function(e){
        var s = findNode(e.source);
        var t = findNode(e.target);

        if(typeof s == 'undefined' || typeof t == 'undefined'){
            return
        }

        var ed = {
            group: "edges",
            data: {
                source: ''+e.source,
                target: ''+e.target,
            },
        };

        edges.push(ed);
        //cy.add(ed);

    }

    var findNode = function (id) {
        for (var i in nodes) {
            if (nodes[i]["data"]["id"] === ''+id) {
                return nodes[i];
            }
        };
    };

    var update = function() {
        //cy.layout();
    }
}

<commit_msg>should not be localhost no<commit_after>// The graph used for the visualization. added to own file
// to separate code for visualizing and keeping track of graph

var nodes = [];
var edges = [];
var graph;

function Graph(cy){
    this.addNode = function(n){
        if(typeof findNode(n.id) != 'undefined') {
            return
        }

        n.graphics.name = n.graphics.name.split(" ")
        if(n.name === "\"bg\"") {
            console.log(n.graphics.name[0])
            var a = n.graphics.name[0].split("/")
            var b = a[a.length-1]
            var url = window.location.hostname+":8080/public/pathways/"+b
            n.graphics.bgimage = url
            n.graphics.bgcolor = "#fff"
            n.graphics.name = ""
        }
        else{
            n.graphics.bgimage = "";
        }

        n.graphics.name = n.graphics.name.toString().replace(/,/g, " ")

        n.graphics.valign = "center"
        if(n.graphics.name.substr(0,2) == "C0"){
            n.graphics.valign = "bottom"
        }

        var no = {
            group: 'nodes',
            data: {
                id: ''+ n.id,
                name: JSON.parse(n.name),
                graphics: n.graphics,
                //background-image: "test.png",
            },
            position: {
                x: n.graphics.x,
                y: n.graphics.y
            },
            //grabbable: false,
            locked: true,
        };
        var  gr = no.data.graphics;

        if(gr.name == "" && gr.bgimage == ""){
            return
        }
        nodes.push(no);
        cy.add(no);

    };

    this.addEdge = function(e){
        var s = findNode(e.source);
        var t = findNode(e.target);

        if(typeof s == 'undefined' || typeof t == 'undefined'){
            return
        }

        var ed = {
            group: "edges",
            data: {
                source: ''+e.source,
                target: ''+e.target,
            },
        };

        edges.push(ed);
        //cy.add(ed);

    }

    var findNode = function (id) {
        for (var i in nodes) {
            if (nodes[i]["data"]["id"] === ''+id) {
                return nodes[i];
            }
        };
    };

    var update = function() {
        //cy.layout();
    }
}

<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview (Deprecated) Events fired as a result of UI actions in
 * Blockly's editor.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.module('Blockly.Events.Ui');
goog.module.declareLegacyNamespace();

/* eslint-disable-next-line no-unused-vars */
const Block = goog.requireType('Blockly.Block');
const Events = goog.require('Blockly.Events');
const UiBase = goog.require('Blockly.Events.UiBase');
const object = goog.require('Blockly.utils.object');
const registry = goog.require('Blockly.registry');

/**
 * Class for a UI event.
 * @param {?Block=} opt_block The affected block.  Null for UI events
 *     that do not have an associated block.  Undefined for a blank event.
 * @param {string=} opt_element One of 'selected', 'comment', 'mutatorOpen',
 *     etc.
 * @param {*=} opt_oldValue Previous value of element.
 * @param {*=} opt_newValue New value of element.
 * @extends {UiBase}
 * @deprecated December 2020. Instead use a more specific UI event.
 * @constructor
 */
const Ui = function(opt_block, opt_element, opt_oldValue, opt_newValue) {
  const workspaceId = opt_block ? opt_block.workspace.id : undefined;
  Ui.superClass_.constructor.call(this, workspaceId);

  this.blockId = opt_block ? opt_block.id : null;
  this.element = typeof opt_element == 'undefined' ? '' : opt_element;
  this.oldValue = typeof opt_oldValue == 'undefined' ? '' : opt_oldValue;
  this.newValue = typeof opt_newValue == 'undefined' ? '' : opt_newValue;
};
object.inherits(Ui, UiBase);

/**
 * Type of this event.
 * @type {string}
 */
Ui.prototype.type = Events.UI;

/**
 * Encode the event as JSON.
 * @return {!Object} JSON representation.
 */
Ui.prototype.toJson = function() {
  const json = Ui.superClass_.toJson.call(this);
  json['element'] = this.element;
  if (this.newValue !== undefined) {
    json['newValue'] = this.newValue;
  }
  if (this.blockId) {
    json['blockId'] = this.blockId;
  }
  return json;
};

/**
 * Decode the JSON event.
 * @param {!Object} json JSON representation.
 */
Ui.prototype.fromJson = function(json) {
  Ui.superClass_.fromJson.call(this, json);
  this.element = json['element'];
  this.newValue = json['newValue'];
  this.blockId = json['blockId'];
};

registry.register(registry.Type.EVENT, Events.UI, Ui);
exports = Ui;
<commit_msg>Add newline to core/events/events_ui.js<commit_after>/**
 * @license
 * Copyright 2018 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview (Deprecated) Events fired as a result of UI actions in
 * Blockly's editor.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.module('Blockly.Events.Ui');
goog.module.declareLegacyNamespace();

/* eslint-disable-next-line no-unused-vars */
const Block = goog.requireType('Blockly.Block');
const Events = goog.require('Blockly.Events');
const UiBase = goog.require('Blockly.Events.UiBase');
const object = goog.require('Blockly.utils.object');
const registry = goog.require('Blockly.registry');

/**
 * Class for a UI event.
 * @param {?Block=} opt_block The affected block.  Null for UI events
 *     that do not have an associated block.  Undefined for a blank event.
 * @param {string=} opt_element One of 'selected', 'comment', 'mutatorOpen',
 *     etc.
 * @param {*=} opt_oldValue Previous value of element.
 * @param {*=} opt_newValue New value of element.
 * @extends {UiBase}
 * @deprecated December 2020. Instead use a more specific UI event.
 * @constructor
 */
const Ui = function(opt_block, opt_element, opt_oldValue, opt_newValue) {
  const workspaceId = opt_block ? opt_block.workspace.id : undefined;
  Ui.superClass_.constructor.call(this, workspaceId);

  this.blockId = opt_block ? opt_block.id : null;
  this.element = typeof opt_element == 'undefined' ? '' : opt_element;
  this.oldValue = typeof opt_oldValue == 'undefined' ? '' : opt_oldValue;
  this.newValue = typeof opt_newValue == 'undefined' ? '' : opt_newValue;
};
object.inherits(Ui, UiBase);

/**
 * Type of this event.
 * @type {string}
 */
Ui.prototype.type = Events.UI;

/**
 * Encode the event as JSON.
 * @return {!Object} JSON representation.
 */
Ui.prototype.toJson = function() {
  const json = Ui.superClass_.toJson.call(this);
  json['element'] = this.element;
  if (this.newValue !== undefined) {
    json['newValue'] = this.newValue;
  }
  if (this.blockId) {
    json['blockId'] = this.blockId;
  }
  return json;
};

/**
 * Decode the JSON event.
 * @param {!Object} json JSON representation.
 */
Ui.prototype.fromJson = function(json) {
  Ui.superClass_.fromJson.call(this, json);
  this.element = json['element'];
  this.newValue = json['newValue'];
  this.blockId = json['blockId'];
};

registry.register(registry.Type.EVENT, Events.UI, Ui);

exports = Ui;
<|endoftext|>


<commit_before>/**
 * Copyright 2016 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  LayoutRectDef,
  layoutRectFromDomRect,
  layoutRectLtwh,
  moveLayoutRect,
} from '../../src/layout-rect';
import {Observable} from '../../src/observable';
import {throttle} from '../../src/utils/rate-limit';

/**
 * @typedef {{
 *   viewportRect: !LayoutRectDef,
 *   targetRect: !LayoutRectDef,
 * }}
 */
let PositionEntryDef;

/** @const */
const MIN_EVENT_INTERVAL_IN_MS = 100;

/** @const */
const AMP_INABOX_POSITION_OBSERVER = 'ampInaboxPositionObserver';

export class PositionObserver {
  /**
   * @param {!Window} win
   */
  constructor(win) {
    /** @private {!Window} */
    this.win_ = win;
    /** @private {?Observable} */
    this.positionObservable_ = null;
    /** @protected {!Element} */
    this.scrollingElement_ = getScrollingElement(this.win_);
    /** @private {?LayoutRectDef} */
    this.viewportRect_ = null;
  }

  /**
   * Start to observe the target element's position change and trigger callback.
   * TODO: maybe take DOM mutation into consideration
   * @param {!Element} element
   * @param {function(!PositionEntryDef)} callback
   * @return {!UnlistenDef}
   */
  observe(element, callback) {
    if (!this.positionObservable_) {
      this.positionObservable_ = new Observable();
      const listener = throttle(
        this.win_,
        () => {
          this.update_();
          this.positionObservable_.fire();
        },
        MIN_EVENT_INTERVAL_IN_MS
      );
      this.update_();
      this.win_.addEventListener('scroll', listener, true);
      this.win_.addEventListener('resize', listener, true);
    }
    // Send the 1st ping immediately
    callback(this.getPositionEntry_(element));
    return this.positionObservable_.add(() => {
      callback(this.getPositionEntry_(element));
    });
  }

  /**
   * Updates viewport rect.
   */
  update_() {
    this.viewportRect_ = this.getViewportRect();
  }

  /**
   * @param {!Element} element
   * @return {!PositionEntryDef}
   * @private
   */
  getPositionEntry_(element) {
    return {
      'viewportRect': /** @type {!LayoutRectDef} */ (this.viewportRect_),
      // relative position to viewport
      'targetRect': this.getTargetRect(element),
    };
  }

  /**
   * A  method to get viewport rect
   * @return {LayoutRectDef}
   */
  getViewportRect() {
    const {scrollingElement_: scrollingElement, win_: win} = this;

    const scrollLeft =
      scrollingElement./*OK*/ scrollLeft || win./*OK*/ pageXOffset;
    const scrollTop =
      scrollingElement./*OK*/ scrollTop || win./*OK*/ pageYOffset;
    return layoutRectLtwh(
      Math.round(scrollLeft),
      Math.round(scrollTop),
      win./*OK*/ innerWidth,
      win./*OK*/ innerHeight
    );
  }

  /**
   * Get the element's layout rect relative to the viewport. Attempt to walk up
   * the DOM and add the offset of all nested parent iframes since
   * getBoundingClientRect() is only relative to the immediate window. Assumes
   * that all parent frames are friendly and can be inspected (because the
   * element itself can be inspected as well).
   * @param {!Element} element
   * @return {!LayoutRectDef}
   */
  getTargetRect(element) {
    let targetRect = layoutRectFromDomRect(
      element./*OK*/ getBoundingClientRect()
    );
    const parentWin = element.ownerDocument.defaultView;
    for (
      let j = 0, tempWin = parentWin;
      j < 10 && tempWin != this.win_ && tempWin != this.win_.top;
      j++, tempWin = tempWin.parent
    ) {
      const parentFrameRect = layoutRectFromDomRect(
        tempWin.frameElement./*OK*/ getBoundingClientRect()
      );
      targetRect = moveLayoutRect(
        targetRect,
        parentFrameRect.left,
        parentFrameRect.top
      );
    }
    return targetRect;
  }
}

/**
 * @param {!Window} win
 * @return {!Element}
 */
function getScrollingElement(win) {
  const doc = win.document;
  if (doc./*OK*/ scrollingElement) {
    return doc./*OK*/ scrollingElement;
  }
  if (
    doc.body &&
    // Due to https://bugs.webkit.org/show_bug.cgi?id=106133, WebKit
    // browsers have to use `body` and NOT `documentElement` for
    // scrolling purposes. This has mostly being resolved via
    // `scrollingElement` property, but this branch is still necessary
    // for backward compatibility purposes.
    isWebKit(win.navigator.userAgent)
  ) {
    return doc.body;
  }
  return doc.documentElement;
}

/**
 * Whether the current browser is based on the WebKit engine.
 * @param {string} ua
 * @return {boolean}
 */
function isWebKit(ua) {
  return /WebKit/i.test(ua) && !/Edge/i.test(ua);
}

/**
 * Use an existing position observer within the window, if any.
 * @param {!Window} win
 * @return {!PositionObserver}
 */
export function getPositionObserver(win) {
  win[AMP_INABOX_POSITION_OBSERVER] =
    win[AMP_INABOX_POSITION_OBSERVER] || new PositionObserver(win);
  return win[AMP_INABOX_POSITION_OBSERVER];
}
<commit_msg>🐛 Don't assume window is always available for inabox. It can be already destroyed (#26265)<commit_after>/**
 * Copyright 2016 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  LayoutRectDef,
  layoutRectFromDomRect,
  layoutRectLtwh,
  moveLayoutRect,
} from '../../src/layout-rect';
import {Observable} from '../../src/observable';
import {throttle} from '../../src/utils/rate-limit';

/**
 * @typedef {{
 *   viewportRect: !LayoutRectDef,
 *   targetRect: !LayoutRectDef,
 * }}
 */
let PositionEntryDef;

/** @const */
const MIN_EVENT_INTERVAL_IN_MS = 100;

/** @const */
const AMP_INABOX_POSITION_OBSERVER = 'ampInaboxPositionObserver';

export class PositionObserver {
  /**
   * @param {!Window} win
   */
  constructor(win) {
    /** @private {!Window} */
    this.win_ = win;
    /** @private {?Observable} */
    this.positionObservable_ = null;
    /** @protected {!Element} */
    this.scrollingElement_ = getScrollingElement(this.win_);
    /** @private {?LayoutRectDef} */
    this.viewportRect_ = null;
  }

  /**
   * Start to observe the target element's position change and trigger callback.
   * TODO: maybe take DOM mutation into consideration
   * @param {!Element} element
   * @param {function(!PositionEntryDef)} callback
   * @return {!UnlistenDef}
   */
  observe(element, callback) {
    if (!this.positionObservable_) {
      this.positionObservable_ = new Observable();
      const listener = throttle(
        this.win_,
        () => {
          this.update_();
          this.positionObservable_.fire();
        },
        MIN_EVENT_INTERVAL_IN_MS
      );
      this.update_();
      this.win_.addEventListener('scroll', listener, true);
      this.win_.addEventListener('resize', listener, true);
    }
    // Send the 1st ping immediately
    callback(this.getPositionEntry_(element));
    return this.positionObservable_.add(() => {
      callback(this.getPositionEntry_(element));
    });
  }

  /**
   * Updates viewport rect.
   */
  update_() {
    this.viewportRect_ = this.getViewportRect();
  }

  /**
   * @param {!Element} element
   * @return {!PositionEntryDef}
   * @private
   */
  getPositionEntry_(element) {
    return {
      'viewportRect': /** @type {!LayoutRectDef} */ (this.viewportRect_),
      // relative position to viewport
      'targetRect': this.getTargetRect(element),
    };
  }

  /**
   * A  method to get viewport rect
   * @return {LayoutRectDef}
   */
  getViewportRect() {
    const {scrollingElement_: scrollingElement, win_: win} = this;

    const scrollLeft =
      scrollingElement./*OK*/ scrollLeft || win./*OK*/ pageXOffset;
    const scrollTop =
      scrollingElement./*OK*/ scrollTop || win./*OK*/ pageYOffset;
    return layoutRectLtwh(
      Math.round(scrollLeft),
      Math.round(scrollTop),
      win./*OK*/ innerWidth,
      win./*OK*/ innerHeight
    );
  }

  /**
   * Get the element's layout rect relative to the viewport. Attempt to walk up
   * the DOM and add the offset of all nested parent iframes since
   * getBoundingClientRect() is only relative to the immediate window. Assumes
   * that all parent frames are friendly and can be inspected (because the
   * element itself can be inspected as well).
   * @param {!Element} element
   * @return {!LayoutRectDef}
   */
  getTargetRect(element) {
    let targetRect = layoutRectFromDomRect(
      element./*OK*/ getBoundingClientRect()
    );
    const parentWin = element.ownerDocument.defaultView;
    for (
      let j = 0, tempWin = parentWin;
      j < 10 &&
      // win can be null if the ad iframe is already destroyed
      tempWin &&
      tempWin != this.win_ &&
      tempWin != this.win_.top;
      j++, tempWin = tempWin.parent
    ) {
      const parentFrameRect = layoutRectFromDomRect(
        tempWin.frameElement./*OK*/ getBoundingClientRect()
      );
      targetRect = moveLayoutRect(
        targetRect,
        parentFrameRect.left,
        parentFrameRect.top
      );
    }
    return targetRect;
  }
}

/**
 * @param {!Window} win
 * @return {!Element}
 */
function getScrollingElement(win) {
  const doc = win.document;
  if (doc./*OK*/ scrollingElement) {
    return doc./*OK*/ scrollingElement;
  }
  if (
    doc.body &&
    // Due to https://bugs.webkit.org/show_bug.cgi?id=106133, WebKit
    // browsers have to use `body` and NOT `documentElement` for
    // scrolling purposes. This has mostly being resolved via
    // `scrollingElement` property, but this branch is still necessary
    // for backward compatibility purposes.
    isWebKit(win.navigator.userAgent)
  ) {
    return doc.body;
  }
  return doc.documentElement;
}

/**
 * Whether the current browser is based on the WebKit engine.
 * @param {string} ua
 * @return {boolean}
 */
function isWebKit(ua) {
  return /WebKit/i.test(ua) && !/Edge/i.test(ua);
}

/**
 * Use an existing position observer within the window, if any.
 * @param {!Window} win
 * @return {!PositionObserver}
 */
export function getPositionObserver(win) {
  win[AMP_INABOX_POSITION_OBSERVER] =
    win[AMP_INABOX_POSITION_OBSERVER] || new PositionObserver(win);
  return win[AMP_INABOX_POSITION_OBSERVER];
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Function.RegisterNamespace("Test.Aura.Component");

[Fixture]
Test.Aura.Component.ComponentTest=function(){
	// Mock the exp() function defined in Aura.js, this is originally used for exposing members using a export.js file
	Mocks.GetMock(Object.Global(), "exp", function() {
	})(function() {
		// #import aura.component.Component
	});

    [Fixture]
    function GetDef(){
      [Fact]
      function ReturnsNullForInvalidComponent(){
	  //Arrange
	  var target = null;
	  var mockPriv = Mocks.GetMock(Object.Global(), "ComponentPriv" , function(){});
	  mockPriv(function(){
	      target = new Component();
	      target.assertValid = function(){return false};
	  });

	  //Act
	  var actual = target.getDef();

	  //Assert
	  Assert.Null(actual);
      }

      [Fact]
      function ReturnsComponentDef(){
	  //Arrange
	  var expected = "Expected ComponentDef";
	  var target = null;
	  var mockPriv = Mocks.GetMock(Object.Global(), "ComponentPriv" , function(){});
	  mockPriv(function(){
	      target = new Component();
	      target.assertValid = function(){return true};
	      target.priv.componentDef = expected;
	  });

	  //Act
	  var actual = target.getDef();

	  //Assert
	  Assert.Equal(expected, actual);
      }
    }

}<commit_msg>Merging origin/lin/master-pending/xunit-test-for-document-index into master<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Function.RegisterNamespace("Test.Aura.Component");

[Fixture]
Test.Aura.Component.ComponentTest=function(){
	// Mock the exp() function defined in Aura.js, this is originally used for exposing members using a export.js file
    Mocks.GetMock(Object.Global(), "exp", function(){})(function()
        {Mocks.GetMock(Object.Global(), "$A", function(){})(function(){
            $A.ns = {};
            // #import aura.component.Component
        });
    });

    [Fixture]
    function Index() {
    	//this cover when component is invalid
        [Fact]
        function ReturnsNullForInvalidComponent() {
            //Arrange
            var target = null;
            var mockPriv = Mocks.GetMock(Object.Global(), "ComponentPriv" , function(){});
            mockPriv(function(){
                target = new Component();
                target.assertValid = function(){return false};
            });
            //Act
            var actual = target.index(null,null);
            //Assert
            Assert.Null(actual);
        }
        //this cover when delegateValueProvider is not null
        [Fact]
        function ReturnsResultFromDelegateValueProvider() {
            //Arrange
            var localid = "testLocalId";
            var globalid = "testGlobalId";
            var expected = "id from delegateValueProvider";
            var actual = null;
            var mockPriv = Mocks.GetMocks(Object.Global(), {
                "ComponentPriv" : function(){}
            });
            var targetValueProvider={
                index:function(lid,gid){
                    if((lid==localid)&&(gid==globalid)) return expected;
                }
            };
            mockPriv(function(){
                target = new Component();
                target.assertValid = function(){return true};
                target.priv.delegateValueProvider = targetValueProvider;
            });
            //Act
            mockPriv(function(){
                actual = target.index(localid,globalid);
            });
            //Assert
            Assert.Equal(expected, actual);
        }

        //this cover when index[locaid] does not exist
        [Fact]
        function InitLocalIdWithGlobalId() {
            //Arrange
            var localid = "testLocalId";
            var globalid = "testGlobalId";
            var expected = globalid;
            var target = null;
            var actual=null;
            var mockPriv = Mocks.GetMock(Object.Global(), "ComponentPriv" , function(){});
            mockPriv(function(){
                target = new Component();
                target.assertValid = function(){return true};
                target.priv.index = null;
            });
            //Act
            target.index(localid,globalid);
            actual = target.priv.index[localid];
            //Assert
            Assert.Equal(expected, actual);
        }

        //this cover when index[locaid] exist but not an array
        [Fact]
        function AppendLocalIdWithGlobalId() {
            //Arrange
            var localid = "testLocalId";
            var globalid = "testGlobalId2";
            var original_globalid = "testGlobalId1";
            var expected = [original_globalid,globalid];
            var target = null;
            var actual=null;
            var mockPriv = Mocks.GetMocks(Object.Global(), {
                "$A" : {
                    util : {
                        isArray : function() {return false;}
                    }
                },
                "ComponentPriv" : function(){}
            });
            mockPriv(function(){
                target = new Component();
                target.assertValid = function(){return true};
                target.priv.index = [];
                target.priv.index[localid] = original_globalid;
            });
            //Act
            mockPriv(function(){
                target.index(localid,globalid);
                actual = target.priv.index[localid];
            });
            //Assert
            Assert.Equal(expected, actual);
        }

        //this cover when index[locaid] is already an array
        [Fact]
        function AppendLocalIdArrayWithGlobalId() {
            //Arrange
            var localid = "testLocalId";
            var globalid = "testGlobalId2";
            var original_globalid_array = ["testGlobalId1"];
            var expected = ["testGlobalId1",globalid];
            var target = null;
            var actual=null;
            var mockPriv = Mocks.GetMocks(Object.Global(), {
                "$A" : {
                    util : {
                        isArray : function() {return true;}
                    }
                },
                "ComponentPriv" : function(){}
            });
            mockPriv(function(){
                target = new Component();
                target.assertValid = function(){return true};
                target.priv.index = [];
                target.priv.index[localid] = original_globalid_array;
            });
            //Act
            mockPriv(function(){
            target.index(localid,globalid);
            actual = target.priv.index[localid];
            });
            //Assert
            Assert.Equal(expected, actual);
        }
    }//end of [Fixture] Index()

    [Fixture]
    function GetDef(){
        [Fact]
        function ReturnsNullForInvalidComponent(){
        	//Arrange
        	var target = null;
        	var mockPriv = Mocks.GetMock(Object.Global(), "ComponentPriv" , function(){});
        	mockPriv(function(){
        		target = new Component();
        		target.assertValid = function(){return false};
        	});
        	//Act
        	var actual = target.getDef();
        	//Assert
        	Assert.Null(actual);
        }

        [Fact]
        function ReturnsComponentDef(){
        	//Arrange
        	var expected = "Expected ComponentDef";
        	var target = null;
        	var mockPriv = Mocks.GetMock(Object.Global(), "ComponentPriv" , function(){});
        	mockPriv(function(){
              target = new Component();
              target.assertValid = function(){return true};
              target.priv.componentDef = expected;
              });
        	//Act
        	var actual = target.getDef();
        	//Assert
        	Assert.Equal(expected, actual);
        }
    }//end of [Fixture]function GetDef()

}
<|endoftext|>