<commit_before>/* call using this enclosure
  (function(){
    var url = 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.js';
    document.head.appendChild(document.createElement('script')).src=url;
    function initialize(){
      if (typeof(Dashboard) !== 'undefined' && typeof(ko) !== 'undefined' && ko.dataFor(app) !== undefined) {
          //console.log('Knockout:');console.log(ko);console.log('App:');console.log(ko.dataFor(app));
          db = new Dashboard(ko.dataFor(app))
      } else {
          setTimeout(function(){initialize()}, 100);
      }
    }
    initialize();
  })();
*/

function Dashboard(app) {
  var self = this;
  this.app = app;
  console.log(this.app);
  this.Tools = {
    bobParse: function(raw){
      var clients = [], data = {};
      // exit on null entry
      if ( raw === null ) return;
      for (var cells = raw.replace(/Basic[\r\n\s\ta-z]*Partner ID[\t\s]+/i, '').split(/\t/),
        client = {}, cols = ['Account ID',	'Account Start Date',	'Account Bucket',	'Account Spend',
        'Date of Next Ticket',	'Engaged Status',	'Timezone',	'Welcome Call',	'Keyword Research',
        'Local Profile Tab',	'Obtain or Create Google Logins',	'Create and Verify Google Profile',
        'Obtain Site Access',	'Implement Onsite Edits',	'Create Yahoo Account',	'Create and Verify Yahoo Profile',
        'Create and Verify Bing Profile',	'Install Analytics',	'Company Name',	'Contact Name',	'Website URL',
        'Email Address',	'Phone Number',	'Partner ID',];
        cells.length>0;){
        var keys = Object.keys(client).length;
        if (keys<cols.length-1){
          var param = cols[keys];
          client[param] = cells[0];
          cells.shift();
        } else {
          client.count = keys;
          clients.push(client);
          client = {};
        }
      }
      for (var i=0;i<clients.length;i++){
        var date = clients[i]['Date of Next Ticket'];
        if (data[date] === undefined) data[date] = [];
        data[date].push(clients[i]);
      }
      return data;
    },
    bobCal: function(){},
    todoistExport: function(){
      var view;
      if (ko.dataFor(window.app) !== undefined){
        view = ko.dataFor(window.app).contentViewModel();
      } else if (ko.dataFor(self.app) !== undefined){
        view = ko.dataFor(self.app).contentViewModel();
      }
      if (! view.hasOwnProperty('customersDataTable')){
        bootbox.alert('No client in active view.\nTry running this tool while viewing a client.');
        return 1;
      } else {
        console.log(view);
        if (typeof(view.customersDataTable) === undefined) {console.log('No customersDataTable');return;}
        var data = view.customersDataTable.dataSource(),
        taskDate = function(day){
          var days = [new Date(),new Date(),new Date()];
          if (days[0].getDay() == 5) {
            days[1].setDate(days[0].getDate()+3);
            days[2].setDate(days[0].getDate()+4);
          } else if (days[0].getDay() == 4) {
            days[1].setDate(days[0].getDate()+1);
            days[2].setDate(days[0].getDate()+4);
          } else {
            days[1].setDate(days[0].getDate()+1);
            days[2].setDate(days[0].getDate()+2);
          }
          return 'date '+days[day].toDateString().substring(4);
        },
        text = data.CustomerId+' - '+data.Name;
        text += '[[NOTE]]: https://launchpad.boostability.com/#customerservice/customersearch/'+data.CustomerId;
        text += '\n...'+data.CustomerId+' Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Call [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Email [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Call [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Email [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Email [['+taskDate(2)+']]';
        text += '\n...'+data.CustomerId+' Keyword Research';
        text += '\n...'+data.CustomerId+' Local Profile';
        bootbox.alert(text);
      }
    },
    openClient: function(client) {
      self.app.showManageCustomer(client);
    },
    closeClient: function() {
      var buttons = document.getElementsByClassName('close'),
      i = buttons.length - 1;
      if (i >= 1) buttons[i - 1].click();
    },
    createElement: function(parent, tag, attributes) {
      var element = parent.appendChild(document.createElement(tag));
      for (var attribute in attributes) {
        if (attributes.hasOwnProperty(attribute)) {
          element[attribute] = attributes[attribute];
        }
      }
      return element;
    },
  };
  this.Tickets = {
    calendar: function(month, year, data) {
      if (typeof(month) == Object) {data = month, month = null;}
      console.log(data);
      this.current_date = new Date();
      this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
      this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
      this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
      this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
      this.draw = function(ele){
          if (this.month > 11) {
            this.month -= 12;
            this.year += 1;
          } else if (month < 0) {
            this.month += 12;
            this.year -= 1;
          }
          // get dates
          var startingDay = new Date(this.year, this.month, 1).getDay(),
          endingDate = new Date(this.year, this.month + 1, 0),
          monthLength = endingDate.getDate(),
          inLastRow = 6 - endingDate.getDay();

          // generate header
          this.table = document.createElement('table');
          this.head = document.createElement('thead');
          this.prev = document.createElement('th');
          this.next = document.createElement('th');
          this.title = document.createElement('th');
          this.days = document.createElement('tr');
          this.body = document.createElement('tbody');
          this.cells = '';
          this.table.setAttribute('class', 'calendar');
          this.table.appendChild(this.head);
          this.head.appendChild(this.prev);
          this.prev.innerHTML = "«";
          this.prev.id = 'prev';
          this.head.appendChild(this.title);
          this.head.appendChild(this.next);
          this.next.innerHTML = "»";
          this.next.id = 'next';
          this.table.appendChild(this.days);
          this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
          this.title.setAttribute('colspan', '5');
          this.days.setAttribute('class', 'header');
          for (var i = 0; i <= 6; i++ ) this.cells += '' + this.day_labels[i] + '	';
          this.days.innerHTML = this.cells;

          //generate calendar
          var html = '
';
          if ( startingDay ) html += '	';
          for (var day = 1; day <= monthLength; day++) {
          html += '
' + day + '
';
          //if data argument present, append key value for current day
          if (data) {
            var today = (this.month+1)+'/'+day+'/'+this.year;
            if (data[today]) html += '
'+Object.keys(data[today]).length+' Clients
';
          }
          html += '	';
          if ( (day + startingDay) % 7 === 0 && day != monthLength ) html += '

';
          }
          if ( inLastRow ) html += '	';
          html += '
';
          this.table.innerHTML += html;
          if (ele) {
            ele.innerHTML = this.table.outerHTML;
          } else {
            return this.table.outerHTML;
          }
          // save reference to dom node in object
          this.node = ele;
          // save reference to calendar object for enclosure scope
          var cal = this;
              (function(){
            // save calendar object reference for listeners
            var self = this;
                self.prev.addEventListener('click', function(){
              cal.month--;
                    cal.draw(cal.node);
                });
            self.next.addEventListener('click', function(){
                    cal.month++;
              cal.draw(cal.node);
                });
                document.onkeydown = function(e) {
                  e = e || window.event;
                    if (e.keyCode == '37') {
                    // left arrow
                    cal.month--;
                    cal.draw(cal.node);
                    } else if (e.keyCode == '39') {
                        // right arrow
                        cal.month++;
                    cal.draw(cal.node);
                    }
                };
              })();
        };
    },
    getTickets: function() {
      //get tickets
      if (self.app.contentViewModel() !== undefined){
        if (typeof(self.app.contentViewModel().myTickets) === "function"){
          self.Tickets.ticketArray = self.app.contentViewModel().myTickets();
        }
      } else if (localStorage.getItem('ticketCache') !== null){
        self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
      }
      //return results
      if (self.Tickets.ticketArray) {
        localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        return self.Tickets.ticketArray;
      } else {
        alert('Unable to access tickets at this time!');
        return [];
      }
    },
    getCritical: function() {
      var tickets = this.getTickets(),
      critical = [];
      for (var i = 0; i < tickets.length; i++) {
        if (tickets[i].ScheduledEndDate < new Date()) {
          critical.push(tickets[i]);
        }
      }
      if (tickets.length > 0){
        return critical;
      } else {
        return false;
      }
    },
    countCritical: function() {
      var criticals = self.Tickets.getCritical();
      if (criticals) {
        return 'Critical Tickets: ' + criticals.length + '';
      } else {
        return 'Error loading tickets!';
      }
    },
    sortTickets: function(tickets){
      if (! tickets){
        tickets = this.getTickets();
      }
      var data = {};
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        date = new Date(ticket.ScheduledEndDate),
        day = date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear();
        if (! data[day]){ data[day] = [];}
        data[day].push(ticket);
      }
      return data;
    },
    listTickets: function(tickets){
      var list = document.createElement('ul');
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        listItem = document.createElement('li'),
        text = ticket.CompanyName+': '+ticket.TicketTypeName;
        text += ' (Due: '+(ticket.ScheduledEndDate.getMonth()+1);
        text += '/'+ticket.ScheduledEndDate.getDate()+'/';
        text += ticket.ScheduledEndDate.getFullYear()+')';
        listItem.innerHTML = text;
        list.appendChild(listItem);
      }
      return list;
    },
    tryCache: function(){
      try {
        if (self.Tickets.ticketArray) {
          localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        }
      } catch(err) {
        setTimeout(function(){self.Tickets.tryCache();}, 1000);
      }
    },
  };
  this.HTML = {};
  this.HTML.dashboard = this.Tools.createElement(document.body, 'div', {
        className: 'navbar navbar-inverse navbar-fixed-bottom',
        id: 'dashboard',
  });
  this.HTML.style = this.Tools.createElement(this.HTML.dashboard, 'link', {
    rel: 'stylesheet',
    type: 'text/css',
    href: 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.css',
  }),
  this.HTML.nav = this.Tools.createElement(this.HTML.dashboard, 'ul', {
    className: 'nav navbar-nav',
  }),
  this.HTML.tools = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tools',
    className: 'dropup',
  }),
  this.HTML.toolsMenu = this.Tools.createElement(this.HTML.tools, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.todoistExport = this.Tools.createElement(this.HTML.toolsMenu, 'li', {
    innerHTML: 'Todoist Export',
    onclick: function(){
      self.Tools.todoistExport();
    },
  }),
  this.HTML.tickets = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tickets',
    className: 'dropup',
  }),
  this.HTML.ticketsMenu = this.Tools.createElement(this.HTML.tickets, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.ticketCalendar = this.Tools.createElement(this.HTML.ticketsMenu, 'li', {
    innerHTML: 'Calendar',
    onclick: function(){
      var node = bootbox.alert('none')[0].children[0].children[0].children[0],
      data = self.Tickets.sortTickets();
      console.log(data);
      calendar = new self.Tickets.calendar(data);
      calendar.draw(node);
    }
  }),
  this.HTML.critical = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: self.Tickets.countCritical(), //'Click to show Critical',
    id: 'critical',
    onclick: function(){this.innerHTML = self.Tickets.countCritical();},
  });

  window.beforeunload = function(){
    self.Tickets.tryCache();
  };
  window.onhashchange = function(){
    if (window.location.href == 'https://launchpad.boostability.com/#/customerservice/activetickets'){
      self.Tickets.tryCache();
    }
  };
  if (localStorage.getItem('ticketCache') !== null) self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
}
<commit_msg>Update dashboard.js<commit_after>/* call using this enclosure
  (function(){
    var url = 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.js';
    document.head.appendChild(document.createElement('script')).src=url;
    function initialize(){
      if (typeof(Dashboard) !== 'undefined' && typeof(ko) !== 'undefined' && ko.dataFor(app) !== undefined) {
          //console.log('Knockout:');console.log(ko);console.log('App:');console.log(ko.dataFor(app));
          db = new Dashboard(ko.dataFor(app))
      } else {
          setTimeout(function(){initialize()}, 100);
      }
    }
    initialize();
  })();
*/

function Dashboard(app) {
  var self = this;
  this.app = app;
  console.log(this.app);
  this.Tools = {
    bobParse: function(raw){
      var clients = [], data = {};
      // exit on null entry
      if ( raw === null ) return;
      for (var cells = raw.replace(/Basic[\r\n\s\ta-z]*Partner ID[\t\s]+/i, '').split(/\t/),
        client = {}, cols = ['Account ID',	'Account Start Date',	'Account Bucket',	'Account Spend',
        'Date of Next Ticket',	'Engaged Status',	'Timezone',	'Welcome Call',	'Keyword Research',
        'Local Profile Tab',	'Obtain or Create Google Logins',	'Create and Verify Google Profile',
        'Obtain Site Access',	'Implement Onsite Edits',	'Create Yahoo Account',	'Create and Verify Yahoo Profile',
        'Create and Verify Bing Profile',	'Install Analytics',	'Company Name',	'Contact Name',	'Website URL',
        'Email Address',	'Phone Number',	'Partner ID',];
        cells.length>0;){
        var keys = Object.keys(client).length;
        if (keys<cols.length-1){
          var param = cols[keys];
          client[param] = cells[0];
          cells.shift();
        } else {
          client.count = keys;
          clients.push(client);
          client = {};
        }
      }
      for (var i=0;i<clients.length;i++){
        var date = clients[i]['Date of Next Ticket'];
        if (data[date] === undefined) data[date] = [];
        data[date].push(clients[i]);
      }
      return data;
    },
    bobCal: function(){},
    todoistExport: function(){
      var view;
      if (ko.dataFor(window.app) !== undefined){
        view = ko.dataFor(window.app).contentViewModel();
      } else if (ko.dataFor(self.app) !== undefined){
        view = ko.dataFor(self.app).contentViewModel();
      }
      if (! view.hasOwnProperty('customersDataTable')){
        bootbox.alert('No client in active view.\nTry running this tool while viewing a client.');
        return 1;
      } else {
        console.log(view);
        if (typeof(view.customersDataTable) === undefined) {console.log('No customersDataTable');return;}
        var data = view.customersDataTable.dataSource(),
        taskDate = function(day){
          var days = [new Date(),new Date(),new Date()];
          if (days[0].getDay() == 5) {
            days[1].setDate(days[0].getDate()+3);
            days[2].setDate(days[0].getDate()+4);
          } else if (days[0].getDay() == 4) {
            days[1].setDate(days[0].getDate()+1);
            days[2].setDate(days[0].getDate()+4);
          } else {
            days[1].setDate(days[0].getDate()+1);
            days[2].setDate(days[0].getDate()+2);
          }
          return 'date '+days[day].toDateString().substring(4);
        },
        textarea = document.createElement('textarea'),
        text = data.CustomerId+' - '+data.Name;
        text += '[[NOTE]]: https://launchpad.boostability.com/#customerservice/customersearch/'+data.CustomerId;
        text += '\n...'+data.CustomerId+' Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Call [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Email [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Call [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Email [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Email [['+taskDate(2)+']]';
        text += '\n...'+data.CustomerId+' Keyword Research';
        text += '\n...'+data.CustomerId+' Local Profile';
        textarea.value = text;
        bootbox.alert(textarea);
      }
    },
    openClient: function(client) {
      self.app.showManageCustomer(client);
    },
    closeClient: function() {
      var buttons = document.getElementsByClassName('close'),
      i = buttons.length - 1;
      if (i >= 1) buttons[i - 1].click();
    },
    createElement: function(parent, tag, attributes) {
      var element = parent.appendChild(document.createElement(tag));
      for (var attribute in attributes) {
        if (attributes.hasOwnProperty(attribute)) {
          element[attribute] = attributes[attribute];
        }
      }
      return element;
    },
  };
  this.Tickets = {
    calendar: function(month, year, data) {
      if (typeof(month) == Object) {data = month, month = null;}
      console.log(data);
      this.current_date = new Date();
      this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
      this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
      this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
      this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
      this.draw = function(ele){
          if (this.month > 11) {
            this.month -= 12;
            this.year += 1;
          } else if (month < 0) {
            this.month += 12;
            this.year -= 1;
          }
          // get dates
          var startingDay = new Date(this.year, this.month, 1).getDay(),
          endingDate = new Date(this.year, this.month + 1, 0),
          monthLength = endingDate.getDate(),
          inLastRow = 6 - endingDate.getDay();

          // generate header
          this.table = document.createElement('table');
          this.head = document.createElement('thead');
          this.prev = document.createElement('th');
          this.next = document.createElement('th');
          this.title = document.createElement('th');
          this.days = document.createElement('tr');
          this.body = document.createElement('tbody');
          this.cells = '';
          this.table.setAttribute('class', 'calendar');
          this.table.appendChild(this.head);
          this.head.appendChild(this.prev);
          this.prev.innerHTML = "«";
          this.prev.id = 'prev';
          this.head.appendChild(this.title);
          this.head.appendChild(this.next);
          this.next.innerHTML = "»";
          this.next.id = 'next';
          this.table.appendChild(this.days);
          this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
          this.title.setAttribute('colspan', '5');
          this.days.setAttribute('class', 'header');
          for (var i = 0; i <= 6; i++ ) this.cells += '' + this.day_labels[i] + '	';
          this.days.innerHTML = this.cells;

          //generate calendar
          var html = '
';
          if ( startingDay ) html += '	';
          for (var day = 1; day <= monthLength; day++) {
          html += '
' + day + '
';
          //if data argument present, append key value for current day
          if (data) {
            var today = (this.month+1)+'/'+day+'/'+this.year;
            if (data[today]) html += '
'+Object.keys(data[today]).length+' Clients
';
          }
          html += '	';
          if ( (day + startingDay) % 7 === 0 && day != monthLength ) html += '

';
          }
          if ( inLastRow ) html += '	';
          html += '
';
          this.table.innerHTML += html;
          if (ele) {
            ele.innerHTML = this.table.outerHTML;
          } else {
            return this.table.outerHTML;
          }
          // save reference to dom node in object
          this.node = ele;
          // save reference to calendar object for enclosure scope
          var cal = this;
              (function(){
            // save calendar object reference for listeners
            var self = this;
                self.prev.addEventListener('click', function(){
              cal.month--;
                    cal.draw(cal.node);
                });
            self.next.addEventListener('click', function(){
                    cal.month++;
              cal.draw(cal.node);
                });
                document.onkeydown = function(e) {
                  e = e || window.event;
                    if (e.keyCode == '37') {
                    // left arrow
                    cal.month--;
                    cal.draw(cal.node);
                    } else if (e.keyCode == '39') {
                        // right arrow
                        cal.month++;
                    cal.draw(cal.node);
                    }
                };
              })();
        };
    },
    getTickets: function() {
      //get tickets
      if (self.app.contentViewModel() !== undefined){
        if (typeof(self.app.contentViewModel().myTickets) === "function"){
          self.Tickets.ticketArray = self.app.contentViewModel().myTickets();
        }
      } else if (localStorage.getItem('ticketCache') !== null){
        self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
      }
      //return results
      if (self.Tickets.ticketArray) {
        localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        return self.Tickets.ticketArray;
      } else {
        alert('Unable to access tickets at this time!');
        return [];
      }
    },
    getCritical: function() {
      var tickets = this.getTickets(),
      critical = [];
      for (var i = 0; i < tickets.length; i++) {
        if (tickets[i].ScheduledEndDate < new Date()) {
          critical.push(tickets[i]);
        }
      }
      if (tickets.length > 0){
        return critical;
      } else {
        return false;
      }
    },
    countCritical: function() {
      var criticals = self.Tickets.getCritical();
      if (criticals) {
        return 'Critical Tickets: ' + criticals.length + '';
      } else {
        return 'Error loading tickets!';
      }
    },
    sortTickets: function(tickets){
      if (! tickets){
        tickets = this.getTickets();
      }
      var data = {};
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        date = new Date(ticket.ScheduledEndDate),
        day = date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear();
        if (! data[day]){ data[day] = [];}
        data[day].push(ticket);
      }
      return data;
    },
    listTickets: function(tickets){
      var list = document.createElement('ul');
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        listItem = document.createElement('li'),
        text = ticket.CompanyName+': '+ticket.TicketTypeName;
        text += ' (Due: '+(ticket.ScheduledEndDate.getMonth()+1);
        text += '/'+ticket.ScheduledEndDate.getDate()+'/';
        text += ticket.ScheduledEndDate.getFullYear()+')';
        listItem.innerHTML = text;
        list.appendChild(listItem);
      }
      return list;
    },
    tryCache: function(){
      try {
        if (self.Tickets.ticketArray) {
          localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        }
      } catch(err) {
        setTimeout(function(){self.Tickets.tryCache();}, 1000);
      }
    },
  };
  this.HTML = {};
  this.HTML.dashboard = this.Tools.createElement(document.body, 'div', {
        className: 'navbar navbar-inverse navbar-fixed-bottom',
        id: 'dashboard',
  });
  this.HTML.style = this.Tools.createElement(this.HTML.dashboard, 'link', {
    rel: 'stylesheet',
    type: 'text/css',
    href: 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.css',
  }),
  this.HTML.nav = this.Tools.createElement(this.HTML.dashboard, 'ul', {
    className: 'nav navbar-nav',
  }),
  this.HTML.tools = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tools',
    className: 'dropup',
  }),
  this.HTML.toolsMenu = this.Tools.createElement(this.HTML.tools, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.todoistExport = this.Tools.createElement(this.HTML.toolsMenu, 'li', {
    innerHTML: 'Todoist Export',
    onclick: function(){
      self.Tools.todoistExport();
    },
  }),
  this.HTML.tickets = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tickets',
    className: 'dropup',
  }),
  this.HTML.ticketsMenu = this.Tools.createElement(this.HTML.tickets, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.ticketCalendar = this.Tools.createElement(this.HTML.ticketsMenu, 'li', {
    innerHTML: 'Calendar',
    onclick: function(){
      var node = bootbox.alert('none')[0].children[0].children[0].children[0],
      data = self.Tickets.sortTickets();
      console.log(data);
      calendar = new self.Tickets.calendar(data);
      calendar.draw(node);
    }
  }),
  this.HTML.critical = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: self.Tickets.countCritical(), //'Click to show Critical',
    id: 'critical',
    onclick: function(){this.innerHTML = self.Tickets.countCritical();},
  });

  window.beforeunload = function(){
    self.Tickets.tryCache();
  };
  window.onhashchange = function(){
    if (window.location.href == 'https://launchpad.boostability.com/#/customerservice/activetickets'){
      self.Tickets.tryCache();
    }
  };
  if (localStorage.getItem('ticketCache') !== null) self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
}
<|endoftext|>


<commit_before>/**
 * Generic handler for collapsible bbcode boxes.
 *
 * @author	Alexander Ebert
 * @copyright	2001-2018 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @module	WoltLabSuite/Core/Bbcode/Collapsible
 */
define([], function() {
	"use strict";

	var _containers = elByClass('jsCollapsibleBbcode');

	/**
	 * @exports	WoltLabSuite/Core/Bbcode/Collapsible
	 */
	return {
		observe: function() {
			var container, toggleButton;
			while (_containers.length) {
				container = _containers[0];

				// find the matching toggle button
				toggleButton = null;
				elBySelAll('.toggleButton:not(.jsToggleButtonEnabled)', container, function (button) {
					//noinspection JSReferencingMutableVariableFromClosure
					if (button.closest('.jsCollapsibleBbcode') === container) {
						toggleButton = button;
					}
				});

				if (toggleButton) {
					(function (container, toggleButton) {
						var toggle = function (event) {
							if (container.classList.toggle('collapsed')) {
								toggleButton.textContent = elData(toggleButton, 'title-expand');

								if (event instanceof Event) {
									// negative top value means the upper boundary is not within the viewport
									var top = container.getBoundingClientRect().top;
									if (top < 0) {
										var y = window.pageYOffset + (top - 100);
										if (y < 0) y = 0;
										window.scrollTo(window.pageXOffset, y);
									}
								}
							}
							else {
								toggleButton.textContent = elData(toggleButton, 'title-collapse');
							}
						};

						toggleButton.classList.add('jsToggleButtonEnabled');
						toggleButton.addEventListener(WCF_CLICK_EVENT, toggle);

						// expand boxes that are initially scrolled
						if (container.scrollTop !== 0) {
							toggle();
						}
					})(container, toggleButton);
				}

				container.classList.remove('jsCollapsibleBbcode');
			}
		}
	};
});
<commit_msg>Automatically expand code boxes when a line anchor is clicked<commit_after>/**
 * Generic handler for collapsible bbcode boxes.
 *
 * @author	Alexander Ebert
 * @copyright	2001-2018 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @module	WoltLabSuite/Core/Bbcode/Collapsible
 */
define([], function() {
	"use strict";

	var _containers = elByClass('jsCollapsibleBbcode');

	/**
	 * @exports	WoltLabSuite/Core/Bbcode/Collapsible
	 */
	return {
		observe: function() {
			var container, toggleButton;
			while (_containers.length) {
				container = _containers[0];

				// find the matching toggle button
				toggleButton = null;
				elBySelAll('.toggleButton:not(.jsToggleButtonEnabled)', container, function (button) {
					//noinspection JSReferencingMutableVariableFromClosure
					if (button.closest('.jsCollapsibleBbcode') === container) {
						toggleButton = button;
					}
				});

				if (toggleButton) {
					(function (container, toggleButton) {
						var toggle = function (event) {
							if (container.classList.toggle('collapsed')) {
								toggleButton.textContent = elData(toggleButton, 'title-expand');

								if (event instanceof Event) {
									// negative top value means the upper boundary is not within the viewport
									var top = container.getBoundingClientRect().top;
									if (top < 0) {
										var y = window.pageYOffset + (top - 100);
										if (y < 0) y = 0;
										window.scrollTo(window.pageXOffset, y);
									}
								}
							}
							else {
								toggleButton.textContent = elData(toggleButton, 'title-collapse');
							}
						};

						toggleButton.classList.add('jsToggleButtonEnabled');
						toggleButton.addEventListener(WCF_CLICK_EVENT, toggle);

						// expand boxes that are initially scrolled
						if (container.scrollTop !== 0) {
							toggle();
						}
						container.addEventListener('scroll', function () {
							if (container.classList.contains('collapsed')) {
								toggle();
							}
						});
					})(container, toggleButton);
				}

				container.classList.remove('jsCollapsibleBbcode');
			}
		}
	};
});
<|endoftext|>


<commit_before>/**
 * Download vendor deps
 */

'use strict';

// Intrinsic mods
var path = require('path');
var https   = require('https');

// Npm mods
var _ = require('lodash');
var fs = require('fs-extra');

// Pkg.json
var pkgJson = require('./../package.json');

// Files we need and the projects from whence they came.
// @todo: check whether this actually is set?
var assets = pkgJson.postInstallAssets;

/*
 * Get the minor version of the current project
 */
var getMinorVersion = function() {

  // Should already be loaded but just in case
  if (!pkgJson) {
    pkgJson = require('./../package.json');
  }

  // Split the version and send back the minor part
  var parts = pkgJson.version.split('.');
  return parts[1];

};

/*
 * Simple function to make a github api request
 */
var request = function(options, callback) {

  // Request object
  var req = https.request(options, function(res) {

    // Need a string not a buffer
    res.setEncoding('utf8');

    // Collector
    var responseString = '';

    // Collect the stream
    res.on('data', function(data) {
      responseString += data;
    });

    // Return the JSON parsed stream
    res.on('end', function() {
      callback(JSON.parse(responseString));
    });

  });

  // Handle errors
  req.on('error', function(err) {
    console.error(err);
  });

  // End request
  req.end();

};

/*
 * We can't rely on Kalabox stuff in this file so we need to do this
 * to get the users home dir
 */
var getHomeDir = function() {

  // Check the env for the home path
  var platformIsWindows = process.platform === 'win32';
  var envKey = platformIsWindows ? 'USERPROFILE' : 'HOME';

  // Homeward bound
  return process.env[envKey];

};

/*
 * We can't rely on Kalabox stuff in this file so we need to do this
 * to get dev mod
 */
var getDevMode = function() {

  // Set for usage later
  var devMode;

  // If the environment is a no go try to load from custom kalabox.json
  if (process.env.KALABOX_DEV === undefined) {

    // Construct kbox.json path
    var kboxJsonFile = path.join(getHomeDir(), '.kalabox', 'kalabox.json');

    // Check it kbox json exists
    if (fs.existsSync(kboxJsonFile)) {

      // Load it
      var kboxJson = require(kboxJsonFile);

      // Use its dev mode if its set
      devMode = (kboxJson.devMode) ? kboxJson.devMode : false;

    }
  }

  // Use the envvar if its set
  else {

    // Set it
    devMode = (process.env.KALABOX_DEV) ? process.env.KALABOX_DEV : false;

  }

  // Return something
  return devMode;

};

/*
 * Get the project tag/branch we should be pulling from
 */
var getProjectVersion = function(project, callback) {

  // If we are in dev mode this is trivial
  if (getDevMode() === true || getDevMode() === 'true') {
    callback('master');
  }
  // If not we need to do some exploration on the github API
  else {
    // Request opts to find the github tags for a project
    var options = {
      hostname: 'api.github.com',
      port: 443,
      path: '/repos/kalabox/' + project + '/tags',
      method: 'GET',
      json: true,
      headers: {'User-Agent': 'Kalabox'}
    };

    // Make teh request
    request(options, function(data) {

      // Get the minor version of the current project
      var projectVer = getMinorVersion();

      // Grab the first tag that shares the minor version
      // we assume this lists the most recent tags first
      var minorVersion = _.result(_.find(data, function(release) {
        if (release.name) {
          var minorVersionParts = release.name.split('.');
          return projectVer.toString() === minorVersionParts[1];
        }
        // @todo: What happens if we have no project releases for this version?
      }), 'name');

      callback(minorVersion);

    });
  }

};

/*
 * Get the minor version for a kalabox github project based on the
 * minor version of this project
 */
var writeInternetFile = function(project, location, callback) {

  // Get version we are going to use before we start
  getProjectVersion(project, function(version) {

    // This protects against the use case where you aren't in dev mode
    // but you also have no published packages for the minor version
    if (version === undefined) {
      callback(false);
    }
    else {
      // this should be the github path
      var urlPath = path.join('kalabox', project, version, location);

      // Request opts for RAW github content
      var options = {
        hostname: 'raw.githubusercontent.com',
        port: 443,
        path: '/' + urlPath,
        method: 'GET',
        headers: {'User-Agent': 'Kalabox'}
      };

      // Create our vendor dirs if needed
      var filePath = path.join('vendor', project, path.dirname(location));
      fs.mkdirsSync(filePath);

      // Construct the file object
      var fileName = path.basename(location);
      var file = fs.createWriteStream(path.join(filePath, fileName));

      // Make the request and write the stream to file
      var req = https.request(options, function(res) {

        // Wrtie stream to disk
        res.on('data', function(d) {
          file.write(d);
        });

        // Return some stuff
        res.on('end', function() {
          callback(urlPath, filePath);
        });

      });

      // Fin
      req.end();

      // Errors
      req.on('error', function(err) {
        console.error(err);
      });
    }
  });

};

// Downlaod our files and put them in their place
_.forEach(assets, function(files, project) {
  _.forEach(files, function(file, purpose) {

    var options = {
      hostname: 'api.github.com',
      port: 443,
      path: '/repos/kalabox/' + project + '/tags',
      method: 'GET',
      json: true,
      headers: {'User-Agent': 'Kalabox'}
    };

    writeInternetFile(project, file, function(url, loc) {
      var msg;
      if (url === false) {
        msg = 'No latest package for this version. Try running in devMode';
      }
      else {
        msg = 'Grabbed a file from ' + url + ' doth put it hither: ' + loc;
      }
      console.log(msg);
    });

  });
});
<commit_msg>#446: Because WINDOZE<commit_after>/**
 * Download vendor deps
 */

'use strict';

// Intrinsic mods
var path = require('path');
var https   = require('https');

// Npm mods
var _ = require('lodash');
var fs = require('fs-extra');

// Pkg.json
var pkgJson = require('./../package.json');

// Files we need and the projects from whence they came.
// @todo: check whether this actually is set?
var assets = pkgJson.postInstallAssets;

/*
 * Get the minor version of the current project
 */
var getMinorVersion = function() {

  // Should already be loaded but just in case
  if (!pkgJson) {
    pkgJson = require('./../package.json');
  }

  // Split the version and send back the minor part
  var parts = pkgJson.version.split('.');
  return parts[1];

};

/*
 * Simple function to make a github api request
 */
var request = function(options, callback) {

  // Request object
  var req = https.request(options, function(res) {

    // Need a string not a buffer
    res.setEncoding('utf8');

    // Collector
    var responseString = '';

    // Collect the stream
    res.on('data', function(data) {
      responseString += data;
    });

    // Return the JSON parsed stream
    res.on('end', function() {
      callback(JSON.parse(responseString));
    });

  });

  // Handle errors
  req.on('error', function(err) {
    console.error(err);
  });

  // End request
  req.end();

};

/*
 * We can't rely on Kalabox stuff in this file so we need to do this
 * to get the users home dir
 */
var getHomeDir = function() {

  // Check the env for the home path
  var platformIsWindows = process.platform === 'win32';
  var envKey = platformIsWindows ? 'USERPROFILE' : 'HOME';

  // Homeward bound
  return process.env[envKey];

};

/*
 * We can't rely on Kalabox stuff in this file so we need to do this
 * to get dev mod
 */
var getDevMode = function() {

  // Set for usage later
  var devMode;

  // If the environment is a no go try to load from custom kalabox.json
  if (process.env.KALABOX_DEV === undefined) {

    // Construct kbox.json path
    var kboxJsonFile = path.join(getHomeDir(), '.kalabox', 'kalabox.json');

    // Check it kbox json exists
    if (fs.existsSync(kboxJsonFile)) {

      // Load it
      var kboxJson = require(kboxJsonFile);

      // Use its dev mode if its set
      devMode = (kboxJson.devMode) ? kboxJson.devMode : false;

    }
  }

  // Use the envvar if its set
  else {

    // Set it
    devMode = (process.env.KALABOX_DEV) ? process.env.KALABOX_DEV : false;

  }

  // Return something
  return devMode;

};

/*
 * Get the project tag/branch we should be pulling from
 */
var getProjectVersion = function(project, callback) {

  // If we are in dev mode this is trivial
  if (getDevMode() === true || getDevMode() === 'true') {
    callback('master');
  }
  // If not we need to do some exploration on the github API
  else {
    // Request opts to find the github tags for a project
    var options = {
      hostname: 'api.github.com',
      port: 443,
      path: '/repos/kalabox/' + project + '/tags',
      method: 'GET',
      json: true,
      headers: {'User-Agent': 'Kalabox'}
    };

    // Make teh request
    request(options, function(data) {

      // Get the minor version of the current project
      var projectVer = getMinorVersion();

      // Grab the first tag that shares the minor version
      // we assume this lists the most recent tags first
      var minorVersion = _.result(_.find(data, function(release) {
        if (release.name) {
          var minorVersionParts = release.name.split('.');
          return projectVer.toString() === minorVersionParts[1];
        }
        // @todo: What happens if we have no project releases for this version?
      }), 'name');

      callback(minorVersion);

    });
  }

};

/*
 * Get the minor version for a kalabox github project based on the
 * minor version of this project
 */
var writeInternetFile = function(project, location, callback) {

  // Get version we are going to use before we start
  getProjectVersion(project, function(version) {

    // This protects against the use case where you aren't in dev mode
    // but you also have no published packages for the minor version
    if (version === undefined) {
      callback(false);
    }
    else {
      // this should be the github path
      var urlPath = ['kalabox', project, version, location].join('/');

      // Request opts for RAW github content
      var options = {
        hostname: 'raw.githubusercontent.com',
        port: 443,
        path: '/' + urlPath,
        method: 'GET',
        headers: {'User-Agent': 'Kalabox'}
      };

      // Create our vendor dirs if needed
      var filePath = path.join('vendor', project, path.dirname(location));
      fs.mkdirsSync(filePath);

      // Construct the file object
      var fileName = path.basename(location);
      var file = fs.createWriteStream(path.join(filePath, fileName));

      // Make the request and write the stream to file
      var req = https.request(options, function(res) {

        // Wrtie stream to disk
        res.on('data', function(d) {
          file.write(d);
        });

        // Return some stuff
        res.on('end', function() {
          callback(urlPath, filePath);
        });

      });

      // Fin
      req.end();

      // Errors
      req.on('error', function(err) {
        console.error(err);
      });
    }
  });

};

// Downlaod our files and put them in their place
_.forEach(assets, function(files, project) {
  _.forEach(files, function(file, purpose) {

    var options = {
      hostname: 'api.github.com',
      port: 443,
      path: '/repos/kalabox/' + project + '/tags',
      method: 'GET',
      json: true,
      headers: {'User-Agent': 'Kalabox'}
    };

    writeInternetFile(project, file, function(url, loc) {
      var msg;
      if (url === false) {
        msg = 'No latest package for this version. Try running in devMode';
      }
      else {
        msg = 'Grabbed a file from ' + url + ' doth put it hither: ' + loc;
      }
      console.log(msg);
    });

  });
});
<|endoftext|>


<commit_before>import * as Base64ToUint8Array_tester from "./Base64ToUint8Array_tester.js";
import * as GSheet_tester from "./GSheet_tester.js";
import * as ScriptLoader from "../ScriptLoader.js";
import * as ValueMax from "../ValueMax.js";

window.addEventListener("load", event => {
  ScriptLoader.createPromise("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.7.0/dist/tf.min.js").then(test); });

function test() {
  console.log("util testing...");
  let delayMilliseconds = 1000;

  // Aggregate all progress about util_tester.
  let progress = new ValueMax.Percentage.Aggregate();
  let progress_Base64ToUint8Array_tester = progress.addChild( new ValueMax.Percentage.Aggregate() );
  let progress_GSheet_tester = progress.addChild( new ValueMax.Percentage.Aggregate() );

  let progressReceiver = new ValueMax.Receiver.HTMLProgress.createByTitle_or_getDummy("TestProgressBar");

//   for await ( let progressRoot of Base64ToUint8Array_tester.tester( progress_Base64ToUint8Array_tester ) ) {
//   }

  function* testerAll() {
    yield* Base64ToUint8Array_tester.tester( progress_Base64ToUint8Array_tester );
    yield* GSheet_tester.tester( progress_GSheet_tester );
  }

  let tester = testerAll();

  let testPromise = PartTime.forOf(
    tester,
    ( progressRoot ) => { progressReceiver.setValueMax( progressRoot.valuePercentage, progressRoot.maxPercentage ); }, // Report progress to UI.
    delayMilliseconds
  ).then(r => {
  });

//   progressReceiver.informDone(r); // Inform UI progress done.

  testPromise.then(values => {
    console.log("util testing... Done.");
  });

//!!! ...unfinished... test case by multipler web worker?
}
<commit_msg>Update util_tester.js<commit_after>import * as Base64ToUint8Array_tester from "./Base64ToUint8Array_tester.js";
import * as GSheet_tester from "./GSheet_tester.js";
import * as ScriptLoader from "../ScriptLoader.js";
import * as ValueMax from "../ValueMax.js";
import * as PartTime from "../PartTime.js";

window.addEventListener("load", event => {
  ScriptLoader.createPromise("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.7.0/dist/tf.min.js").then(test); });

function test() {
  console.log("util testing...");
  let delayMilliseconds = 1000;

  // Aggregate all progress about util_tester.
  let progress = new ValueMax.Percentage.Aggregate();
  let progress_Base64ToUint8Array_tester = progress.addChild( new ValueMax.Percentage.Aggregate() );
  let progress_GSheet_tester = progress.addChild( new ValueMax.Percentage.Aggregate() );

  let progressReceiver = new ValueMax.Receiver.HTMLProgress.createByTitle_or_getDummy("TestProgressBar");

//   for await ( let progressRoot of Base64ToUint8Array_tester.tester( progress_Base64ToUint8Array_tester ) ) {
//   }

  function* testerAll() {
    yield* Base64ToUint8Array_tester.tester( progress_Base64ToUint8Array_tester );
    yield* GSheet_tester.tester( progress_GSheet_tester );
  }

  let tester = testerAll();

  let testPromise = PartTime.forOf(
    tester,
    ( progressRoot ) => { progressReceiver.setValueMax( progressRoot.valuePercentage, progressRoot.maxPercentage ); }, // Report progress to UI.
    delayMilliseconds
  ).then(r => {
  });

//   progressReceiver.informDone(r); // Inform UI progress done.

  testPromise.then(values => {
    console.log("util testing... Done.");
  });

//!!! ...unfinished... test case by multipler web worker?
}
<|endoftext|>


<commit_before>// routes.js
const nextRoutes = require('next-routes');
const routes = module.exports = nextRoutes();

// ========================= ADMIN ROUTES =====================
routes.add('admin_home', '/admin', 'admin/Data');
// DATA
routes.add('admin_data', '/admin/data/:tab?', 'admin/Data');
routes.add('admin_data_detail', '/admin/data/:tab/:id/:subtab?', 'admin/DataDetail');
// PARTNERS
routes.add('admin_partners', '/admin/partners/:tab?/:subtab?', 'admin/partners');
// PAGES
routes.add('admin_pages', '/admin/pages/:tab?/:subtab?', 'admin/Pages');
routes.add('admin_pages_detail', '/admin/pages/:tab/:id/:subtab?', 'admin/PagesDetail');
// USERS
routes.add('admin_users', '/admin/users/:tab?/:subtab?', 'admin/users');

// ========================= APP ROUTES =====================
routes.add('home', '/home', 'app/Home');

routes.add('about', '/about', 'app/About');
routes.add('about_partners', '/about/partners', 'app/Partners');
routes.add('partner', '/about/partners/:id', 'app/PartnerDetail');

routes.add('data', '/data', 'app/Explore'); // TODO: create the data page
routes.add('explore', '/data/explore', 'app/Explore');
routes.add('explore_detail', '/data/explore/:id', 'app/ExploreDetail');
routes.add('pulse', '/data/pulse', 'app/Pulse');
routes.add('dashboards', '/data/dashboards/:slug?', 'app/Dashboards');
routes.add('insights', '/data/insights', 'app/Home'); // TODO: create the insights page

// ----- GET INVOLVED -----
routes.add('get_involved', '/get-involved', 'app/GetInvolved');
routes.add('get_involved_detail', '/get-involved/:id', 'app/GetInvolvedDetail');

// ------ MY RW ------------
routes.add('myrw', '/myrw/:tab?/:subtab?', 'app/MyRW');
<commit_msg>home is root<commit_after>// routes.js
const nextRoutes = require('next-routes');
const routes = module.exports = nextRoutes();

// ========================= ADMIN ROUTES =====================
routes.add('admin_home', '/admin', 'admin/Data');
// DATA
routes.add('admin_data', '/admin/data/:tab?', 'admin/Data');
routes.add('admin_data_detail', '/admin/data/:tab/:id/:subtab?', 'admin/DataDetail');
// PARTNERS
routes.add('admin_partners', '/admin/partners/:tab?/:subtab?', 'admin/partners');
// PAGES
routes.add('admin_pages', '/admin/pages/:tab?/:subtab?', 'admin/Pages');
routes.add('admin_pages_detail', '/admin/pages/:tab/:id/:subtab?', 'admin/PagesDetail');
// USERS
routes.add('admin_users', '/admin/users/:tab?/:subtab?', 'admin/users');

// ========================= APP ROUTES =====================
routes.add('home', '/', 'app/Home');

routes.add('about', '/about', 'app/About');
routes.add('about_partners', '/about/partners', 'app/Partners');
routes.add('partner', '/about/partners/:id', 'app/PartnerDetail');

routes.add('data', '/data', 'app/Explore'); // TODO: create the data page
routes.add('explore', '/data/explore', 'app/Explore');
routes.add('explore_detail', '/data/explore/:id', 'app/ExploreDetail');
routes.add('pulse', '/data/pulse', 'app/Pulse');
routes.add('dashboards', '/data/dashboards/:slug?', 'app/Dashboards');
routes.add('insights', '/data/insights', 'app/Home'); // TODO: create the insights page

// ----- GET INVOLVED -----
routes.add('get_involved', '/get-involved', 'app/GetInvolved');
routes.add('get_involved_detail', '/get-involved/:id', 'app/GetInvolvedDetail');

// ------ MY RW ------------
routes.add('myrw', '/myrw/:tab?/:subtab?', 'app/MyRW');
<|endoftext|>


<commit_before>'use strict'

const { Router } = require('express')
const { UnauthorizedError } = require('../lib/errors')
const models = require('../lib/model')
const {EditLog} = require('../lib/edit-logs')

const { requiresAuthentication, scopeOrganizationMiddleware } = require('../lib/permissions')

const async = require('async'),
      moment = require('moment'),
      mongoose = require('mongoose'),
      _ = require('lodash');

const debug = require('debug')('isari:export');

const ObjectId = mongoose.Types.ObjectId;

// UTILS

function formatKind(kind){
	if (kind === "E")
		return "update"
	if (kind === "D")
		return "delete"
	if (kind === "N")
		return "create"
	//by default fall back to update
	return "update"
}

module.exports = Router().get('/:model/:itemId?', requiresAuthentication, getEditLog)

function getEditLog(req, res){
	let model = req.params.model
	const itemId = req.params.itemId
	const query = req.query

	// User has to be central admin to access editLog list feature
	if (!itemId && req.userCentralRole !== 'admin'){
		res.send(UnauthorizedError({ title: 'EditLog is restricted to central admin users'}))
	}

	// User has to have write access on an object to access its editlog
	if(
		(model === 'people' && itemId && !req.userCanEditPeople(itemId)) ||
	 	(model === 'activity' && itemId && !req.userCanEditActivity(itemId)) ||
	 	(model === 'organization' && itemId && !req.userCanEditOrganization(itemId))
	  ){
		res.send(UnauthorizedError({ title: 'Write access is mandatory to access EditLog'}))
	}

	// build the mongo query to editLog collection
	model = _.capitalize(model)
	const mongoQuery = {model}
	if (itemId)
		mongoQuery.item = itemId

	EditLog.aggregate([
		{'$match':mongoQuery},
		{'$lookup':{
	          from: "people",
	          localField: "whoID",
	          foreignField: "_id",
	          as: "creator"
        }},
        // {'$lookup':{
	       //    from: "organizations",
	       //    localField: "creator.isariAuthorizedCenters.organization",
	       //    foreignField: "_id",
	       //    as: "isariLabs"
        // }},
        {'$lookup':{
	          from: model === 'People' ? 'people' : (model === 'Organization' ? 'organizations' : 'activities'),
	          localField: "item",
	          foreignField: "_id",
	          as: "itemObject"
        }},
		// skip and limit
		{'$skip':query.skip ? +query.skip : 0},
		{'$limit':query.limit ? +query.limit : 50}

		])
		.then(data => {
		const edits = []
		data.forEach(d => {
			const edit = {}
			edit.who = {
				id: d.whoID,
				name: (d.creator[0].firstName ? d.creator[0].firstName+' ': '')+ d.creator[0].name,
				roles: d.creator[0].isariAuthorizedCenters ?
						d.creator[0].isariAuthorizedCenters.map(iac =>({lab:iac.organization,role:iac.isariRole})):
						[]
			}
			console.log(d)
			edit.date = d.date
			edit.item = { id:d.item}
			if (model === "People" && d.itemObject[0])
				edit.item.name = (d.itemObject[0].firstName ? d.itemObject[0].firstName+' ': '')+ d.itemObject[0].name
			else
				if (d.itemObject[0])
					edit.item.name = d.itemObject[0].acronym || d.itemObject[0].name

			edit.action = d.action

			if (edit.action === 'update'){

				edit.diff = d.diff.filter(d => d[0].path[0] !== 'latestChangeBy')
							.map(d => {
								d = d[0]
								if (d.path.includes("id"))
									return undefined
								const diff = {path: d.path.filter(e => typeof e !== 'number')}

								if (d.kind === 'A'){
									//array case...
									if (d.item.lhs)
										diff.valueBefore = d.item.lhs
									if(d.item.rhs)
										diff.valueAfter = d.item.rhs
									diff.editType = formatKind(d.item.kind)
								}
								else {
									if (d.lhs)
										diff.valueBefore = d.lhs
									if( d.rhs)
										diff.valueAfter = d.rhs
									diff.editType = formatKind(d.kind)
								}
								return diff
							}).filter(d => d)
			}
			else{
				edit.diff = d.data
			}

			edits.push(edit)
		})

		return res.status(200).send(edits)
	})

}

function formatEditLogs(editLogs){

}<commit_msg>updates api added action, path filters and corrected bug for item query relates #429<commit_after>'use strict'

const { Router } = require('express')
const { UnauthorizedError } = require('../lib/errors')
const models = require('../lib/model')
const {EditLog} = require('../lib/edit-logs')

const { requiresAuthentication, scopeOrganizationMiddleware } = require('../lib/permissions')

const async = require('async'),
      moment = require('moment'),
      mongoose = require('mongoose'),
      _ = require('lodash');

const debug = require('debug')('isari:export');

const ObjectId = mongoose.Types.ObjectId;

// UTILS

function formatKind(kind){
	if (kind === "E")
		return "update"
	if (kind === "D")
		return "delete"
	if (kind === "N")
		return "create"
	//by default fall back to update
	return "update"
}

module.exports = Router().get('/:model/:itemId?', requiresAuthentication, getEditLog)

function getEditLog(req, res){
	let model = req.params.model
	// params
	const itemId = req.params.itemId
	const query = req.query

	// User has to be central admin to access editLog list feature
	if (!itemId && req.userCentralRole !== 'admin'){
		res.send(UnauthorizedError({ title: 'EditLog is restricted to central admin users'}))
	}

	// User has to have write access on an object to access its editlog
	if(
		(model === 'people' && itemId && !req.userCanEditPeople(itemId)) ||
	 	(model === 'activity' && itemId && !req.userCanEditActivity(itemId)) ||
	 	(model === 'organization' && itemId && !req.userCanEditOrganization(itemId))
	  ){
		res.send(UnauthorizedError({ title: 'Write access is mandatory to access EditLog'}))
	}

	// build the mongo query to editLog collection
	model = _.capitalize(model)
	const mongoQuery = {model}
	if (itemId)
		mongoQuery.item = ObjectId(itemId)
	console.log(query.path)
	if (query.path)
		mongoQuery['diff'] = {'$elemMatch': {"0.path":query.path}}
	if (query.action)
		mongoQuery['action'] = query.action

	EditLog.aggregate([
		{'$match':mongoQuery},
		{'$lookup':{
	          from: "people",
	          localField: "whoID",
	          foreignField: "_id",
	          as: "creator"
        }},
        // {'$lookup':{
	       //    from: "organizations",
	       //    localField: "creator.isariAuthorizedCenters.organization",
	       //    foreignField: "_id",
	       //    as: "isariLabs"
        // }},
        {'$lookup':{
	          from: model === 'People' ? 'people' : (model === 'Organization' ? 'organizations' : 'activities'),
	          localField: "item",
	          foreignField: "_id",
	          as: "itemObject"
        }},
        // TODO : project to only usefull fields to limit payload
        // {'$project':{
        // 	whoID:1,
        // 	"creator.firstName":1,
        // 	"creator.name":1,
        // 	"creator.isariAuthorizedCenters":1,

        // }}
		// skip and limit
		{'$skip':query.skip ? +query.skip : 0},
		{'$limit':query.limit ? +query.limit : 100}

		])
		.then(data => {
		const edits = []
		data.forEach(d => {
			const edit = {}
			edit.who = {
				id: d.whoID,
				name: (d.creator[0].firstName ? d.creator[0].firstName+' ': '')+ d.creator[0].name,
				roles: d.creator[0].isariAuthorizedCenters ?
						d.creator[0].isariAuthorizedCenters.map(iac =>({lab:iac.organization,role:iac.isariRole})):
						[]
			}

			edit.date = d.date
			edit.item = { id:d.item}
			if (model === "People" && d.itemObject[0])
				edit.item.name = (d.itemObject[0].firstName ? d.itemObject[0].firstName+' ': '')+ d.itemObject[0].name
			else
				if (d.itemObject[0])
					edit.item.name = d.itemObject[0].acronym || d.itemObject[0].name

			edit.action = d.action

			if (edit.action === 'update'){

				edit.diff = d.diff.filter(d => d[0].path[0] !== 'latestChangeBy')
							.map(d => {
								d = d[0]
								if (d.path.includes("id"))
									return undefined
								const diff = {path: d.path.filter(e => typeof e !== 'number')}

								if (d.kind === 'A'){
									//array case...
									if (d.item.lhs)
										diff.valueBefore = d.item.lhs
									if(d.item.rhs)
										diff.valueAfter = d.item.rhs
									diff.editType = formatKind(d.item.kind)
								}
								else {
									if (d.lhs)
										diff.valueBefore = d.lhs
									if( d.rhs)
										diff.valueAfter = d.rhs
									diff.editType = formatKind(d.kind)
								}
								return diff
							}).filter(d => d)
			}
			else{
				// that's actually a bad idea, performance-wise.
				// This data contain the whole document !
				edit.diff = {}
				if (edit.action === "create"){
					edit.diff.valueAfter = d.data
					edit.diff.editType = 'create'
				}
				if (edit.action === "delete"){
					edit.diff.valueBefore = d.data
					edit.diff.editType = 'delete'
				}
			}

			edits.push(edit)
		})

		return res.status(200).send(edits)
	})

}

function formatEditLogs(editLogs){

}<|endoftext|>


<commit_before>define(function() {

  'use strict';

  function CodeTableView(mode, bitWidth, lens) {
    this.bits = new Uint8Array(1 << bitWidth);
    this.op = new Uint8Array(1 << bitWidth);
    this.val = new Uint16Array(1 << bitWidth);

    var count = new Uint16Array(16 /*MAXBITS+1*/); // number of codes of each length
    for (var sym = 0; sym < lens.length; sym++) {
      count[lens[sym]]++;
    }

    // bound code lengths, force root to be within code lengths
    var root = bitWidth;
    var max;
    for (max = 15 /* MAXBITS */; max >= 1; max--) {
      if (count[max] > 0) break;
    }
    if (root > max) root = max;
    if (max === 0) {
      /* no symbols to code at all */
      this.op[0] = this.op[1] = 64; // invalid code number
      this.bits[0] = this.bits[1] = 1;
      this.val[0] = this.val[1] = 0;
      this.bitWidth = 1;
      return; // no symbols, but wait for decoding to report error
    }
    var min;
    for (min = 1; min < max; min++) {
      if (count[min] !== 0) break;
    }
    if (root < min) root = min;

    this.bitWidth = root;

    /* check for an over-subscribed or incomplete set of lengths */
    var left = 1;
    for (var len = 1; len <= 15 /* MAXBITS */; len++) {
      left <<= 1;
      left -= count[len];
      if (left < 0) throw new Error('over-subscribed');
    }
    if (left > 0 && (mode == 'codes' || max !== 1)) {
      throw new Error('incomplete set');
    }

    // generate offsets into symbol table for each length for sorting
    var offs = new Uint16Array(16 /*MAXBITS+1*/);
    for (var len = 1; len < 15 /*MAXBITS*/; len++) {
      offs[len+1] = offs[len] + count[len];
    }

    // sort symbols by length, by symbol order within each length
    var work = new Uint16Array(288);
    for (var sym = 0; sym < lens.length; sym++) {
      if (lens[sym] > 0) {
        work[offs[lens[sym]]++] = sym & 0xffff;
      }
    }

    var base, extra, end;

    /* set up for code type */
    switch (mode) {
      case 'codes':
        base = extra = work;    /* dummy value--not used */
        end = 19;
        break;
      case 'lens':
        base = new Uint16Array(285 + 3);
        base.set([ /* Length codes 257..285 base */
          3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
          35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0], 257);
        extra = new Uint16Array(285 + 3);
        extra.set([ /* Length codes 257..285 extra */
          16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
          19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78], 257);
        end = 256;
        break;
      case 'dists':
        base = new Uint16Array([ /* Distance codes 0..29 base */
          1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
          257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
          8193, 12289, 16385, 24577, 0, 0]);
        extra = new Uint16Array([ /* Distance codes 0..29 extra */
          16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
          23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
          28, 28, 29, 29, 64, 64]);
        end = -1;
        break;
      default: throw new Error('unknown mode: ' + mode);
    }

    /* initialize state for loop */
    var huff = 0,       //  starting code
      sym = 0,          // starting code symbol
      len = min,        // starting code length
      next = 0,         // current table to fill in
      curr = root,      // current table index bits
      drop = 0,         // current bits to drop from code for index
      low = -1 >>> 0,   // trigger new sub-table when len > root
      used = 1 << root; // use root table entries
    var mask = used - 1;  // mask for comparing low

    /* check available table space */
    if ((mode === 'lens' && used > CodeTableView.ENOUGH_LENS)
    ||  (mode === 'dists' && used > CodeTableView.ENOUGH_DISTS)) {
      throw new Error('not enough table space');
    }

    /* process all codes and make table entries */
    for (;;) {
      /* create table entry */
      var here_op, here_val, here_bits = (len - drop) & 0xff;
      if (work[sym] < end) {
        here_op = 0;
        here_val = work[sym];
      }
      else if (work[sym] > end) {
        here_op = extra[work[sym]] & 0xff;
        here_val = base[work[sym]];
      }
      else {
        here_op = 32 + 64; // end of block
        here_val = 0;
      }

      /* replicate for those indices with low len bits equal to huff */
      var incr = 1 << (len - drop);
      var fill = 1 << curr;
      min = fill; // save offset to next table
      do {
        fill -= incr;
        var n = next + (huff >> drop) + fill;
        this.op[n] = here_op; this.bits[n] = here_bits; this.val[n] = here_val;
      } while (fill !== 0);

      /* backwards increment the len-bit code huff */
      incr = 1 << (len - 1);
      while (huff & incr) incr >>= 1;
      if (incr !== 0) {
        huff &= incr - 1;
        huff += incr;
      }
      else huff = 0;

      /* go to next symbol, update count, len */
      sym++;
      if (--count[len] == 0) {
        if (len === max) break;
        len = lens[work[sym]];
      }

      /* create new sub-table if needed */
      if (len > root && (huff & mask) !== low) {
        /* if first time, transition to sub-tables */
        if (drop === 0) drop = root;

        /* increment past last table */
        next += min; // here min is 1 << curr

        /* determine length of next table */
        curr = len - drop;
        left = 1 << curr;
        while (curr + drop < max) {
          left -= count[curr + drop];
          if (left <= 0) break;
          curr++;
          left <<= 1;
        }

        /* check for enough space */
        used += 1 << curr;
        if ((mode === 'lens' && used > CodeTableView.ENOUGH_LENS)
        ||  (mode === 'dists' && used > CodeTableView.ENOUGH_DISTS)) {
          throw new Error('not enough space');
        }

        /* point entry in root table to sub-table */
        low = huff & mask;
        this.op[low] = cur & 0xff;
        this.bits[low] = root & 0xff;
        this.val[low] = next & 0xffff;
      }
    }

    /*
    fill in remaining table entry if code is incomplete (guaranteed to have
    at most one remaining entry, since if the code is incomplete, the
    maximum code length that was allowed to get this far is one bit)
    */
    if (huff !== 0) {
      this.op[next + huff] = 64; // invalid code marker
      this.bits[next + huff] = (len - drop) & 0xff;
      this.val[next + huff] = 0;
    }
  }
  CodeTable.prototype = {
    get length() {
      return 1 << this.bitWidth;
    },
    get mask() {
      return (1 << this.bitWidth) - 1;
    },
  }

  CodeTableView.ENOUGH_LENS = 852;
  CodeTableView.ENOUGH_DISTS = 592;

  // initialize fixed tables
  var lens, sym;

  lens = new Uint16Array(288);
  sym = 0;
  while (sym < 144) lens[sym++] = 8;
  while (sym < 256) lens[sym++] = 9;
  while (sym < 280) lens[sym++] = 7;
  while (sym < lens.length) lens[sym++] = 8;
  CodeTableView.fixedLengthTable = new CodeTableView('lens', 9, lens);

  lens = new Uint16Array(32);
  sym = 0;
  while (sym < lens.length) lens[sym++] = 5;
  CodeTableView.fixedDistanceTable = new CodeTableView('dists', 5, lens);

  return CodeTableView;

});
<commit_msg>Fix type name<commit_after>define(function() {

  'use strict';

  function CodeTableView(mode, bitWidth, lens) {
    this.bits = new Uint8Array(1 << bitWidth);
    this.op = new Uint8Array(1 << bitWidth);
    this.val = new Uint16Array(1 << bitWidth);

    var count = new Uint16Array(16 /*MAXBITS+1*/); // number of codes of each length
    for (var sym = 0; sym < lens.length; sym++) {
      count[lens[sym]]++;
    }

    // bound code lengths, force root to be within code lengths
    var root = bitWidth;
    var max;
    for (max = 15 /* MAXBITS */; max >= 1; max--) {
      if (count[max] > 0) break;
    }
    if (root > max) root = max;
    if (max === 0) {
      /* no symbols to code at all */
      this.op[0] = this.op[1] = 64; // invalid code number
      this.bits[0] = this.bits[1] = 1;
      this.val[0] = this.val[1] = 0;
      this.bitWidth = 1;
      return; // no symbols, but wait for decoding to report error
    }
    var min;
    for (min = 1; min < max; min++) {
      if (count[min] !== 0) break;
    }
    if (root < min) root = min;

    this.bitWidth = root;

    /* check for an over-subscribed or incomplete set of lengths */
    var left = 1;
    for (var len = 1; len <= 15 /* MAXBITS */; len++) {
      left <<= 1;
      left -= count[len];
      if (left < 0) throw new Error('over-subscribed');
    }
    if (left > 0 && (mode == 'codes' || max !== 1)) {
      throw new Error('incomplete set');
    }

    // generate offsets into symbol table for each length for sorting
    var offs = new Uint16Array(16 /*MAXBITS+1*/);
    for (var len = 1; len < 15 /*MAXBITS*/; len++) {
      offs[len+1] = offs[len] + count[len];
    }

    // sort symbols by length, by symbol order within each length
    var work = new Uint16Array(288);
    for (var sym = 0; sym < lens.length; sym++) {
      if (lens[sym] > 0) {
        work[offs[lens[sym]]++] = sym & 0xffff;
      }
    }

    var base, extra, end;

    /* set up for code type */
    switch (mode) {
      case 'codes':
        base = extra = work;    /* dummy value--not used */
        end = 19;
        break;
      case 'lens':
        base = new Uint16Array(285 + 3);
        base.set([ /* Length codes 257..285 base */
          3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
          35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0], 257);
        extra = new Uint16Array(285 + 3);
        extra.set([ /* Length codes 257..285 extra */
          16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
          19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78], 257);
        end = 256;
        break;
      case 'dists':
        base = new Uint16Array([ /* Distance codes 0..29 base */
          1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
          257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
          8193, 12289, 16385, 24577, 0, 0]);
        extra = new Uint16Array([ /* Distance codes 0..29 extra */
          16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
          23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
          28, 28, 29, 29, 64, 64]);
        end = -1;
        break;
      default: throw new Error('unknown mode: ' + mode);
    }

    /* initialize state for loop */
    var huff = 0,       //  starting code
      sym = 0,          // starting code symbol
      len = min,        // starting code length
      next = 0,         // current table to fill in
      curr = root,      // current table index bits
      drop = 0,         // current bits to drop from code for index
      low = -1 >>> 0,   // trigger new sub-table when len > root
      used = 1 << root; // use root table entries
    var mask = used - 1;  // mask for comparing low

    /* check available table space */
    if ((mode === 'lens' && used > CodeTableView.ENOUGH_LENS)
    ||  (mode === 'dists' && used > CodeTableView.ENOUGH_DISTS)) {
      throw new Error('not enough table space');
    }

    /* process all codes and make table entries */
    for (;;) {
      /* create table entry */
      var here_op, here_val, here_bits = (len - drop) & 0xff;
      if (work[sym] < end) {
        here_op = 0;
        here_val = work[sym];
      }
      else if (work[sym] > end) {
        here_op = extra[work[sym]] & 0xff;
        here_val = base[work[sym]];
      }
      else {
        here_op = 32 + 64; // end of block
        here_val = 0;
      }

      /* replicate for those indices with low len bits equal to huff */
      var incr = 1 << (len - drop);
      var fill = 1 << curr;
      min = fill; // save offset to next table
      do {
        fill -= incr;
        var n = next + (huff >> drop) + fill;
        this.op[n] = here_op; this.bits[n] = here_bits; this.val[n] = here_val;
      } while (fill !== 0);

      /* backwards increment the len-bit code huff */
      incr = 1 << (len - 1);
      while (huff & incr) incr >>= 1;
      if (incr !== 0) {
        huff &= incr - 1;
        huff += incr;
      }
      else huff = 0;

      /* go to next symbol, update count, len */
      sym++;
      if (--count[len] == 0) {
        if (len === max) break;
        len = lens[work[sym]];
      }

      /* create new sub-table if needed */
      if (len > root && (huff & mask) !== low) {
        /* if first time, transition to sub-tables */
        if (drop === 0) drop = root;

        /* increment past last table */
        next += min; // here min is 1 << curr

        /* determine length of next table */
        curr = len - drop;
        left = 1 << curr;
        while (curr + drop < max) {
          left -= count[curr + drop];
          if (left <= 0) break;
          curr++;
          left <<= 1;
        }

        /* check for enough space */
        used += 1 << curr;
        if ((mode === 'lens' && used > CodeTableView.ENOUGH_LENS)
        ||  (mode === 'dists' && used > CodeTableView.ENOUGH_DISTS)) {
          throw new Error('not enough space');
        }

        /* point entry in root table to sub-table */
        low = huff & mask;
        this.op[low] = cur & 0xff;
        this.bits[low] = root & 0xff;
        this.val[low] = next & 0xffff;
      }
    }

    /*
    fill in remaining table entry if code is incomplete (guaranteed to have
    at most one remaining entry, since if the code is incomplete, the
    maximum code length that was allowed to get this far is one bit)
    */
    if (huff !== 0) {
      this.op[next + huff] = 64; // invalid code marker
      this.bits[next + huff] = (len - drop) & 0xff;
      this.val[next + huff] = 0;
    }
  }
  CodeTableView.prototype = {
    get length() {
      return 1 << this.bitWidth;
    },
    get mask() {
      return (1 << this.bitWidth) - 1;
    },
  }

  CodeTableView.ENOUGH_LENS = 852;
  CodeTableView.ENOUGH_DISTS = 592;

  // initialize fixed tables
  var lens, sym;

  lens = new Uint16Array(288);
  sym = 0;
  while (sym < 144) lens[sym++] = 8;
  while (sym < 256) lens[sym++] = 9;
  while (sym < 280) lens[sym++] = 7;
  while (sym < lens.length) lens[sym++] = 8;
  CodeTableView.fixedLengthTable = new CodeTableView('lens', 9, lens);

  lens = new Uint16Array(32);
  sym = 0;
  while (sym < lens.length) lens[sym++] = 5;
  CodeTableView.fixedDistanceTable = new CodeTableView('dists', 5, lens);

  return CodeTableView;

});
<|endoftext|>


<commit_before>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*  define a state transition  */
$cs.transition = function () {
    /*  special case  */
    if (arguments.length === 1 && arguments[0] === null) {
        /*  remove all user-defined transitions  */
        _cs.states_clear();
        return;
    }

    /*  determine parameters  */
    var params = $cs.params("transition", arguments, {
        target: { pos: 0, def: null, req: true },
        enter:  { pos: 1, def: null, req: true },
        leave:  { pos: 2, def: null, req: true },
        color:  { pos: 3, def: null, req: true },
        source: {         def: null            }
    });

    /*  add new state  */
    _cs.states_add(
        params.target,
        params.enter,
        params.leave,
        params.color,
        params.source
    );
};

/*  initialize state transition set with a reasonable default  */
$cs.transition("created",      "create",  "destroy", "#cc3333"); /* created and attached to component tree */
$cs.transition("prepared",     "prepare", "cleanup", "#eabc43"); /* prepared and ready for rendering */
$cs.transition("materialized", "render",  "release", "#6699cc"); /* rendered onto the DOM tree */
$cs.transition("visible",      "show",    "hide",    "#669933"); /* visible to the user */

<commit_msg>add a 'configured' state which sometimes is useful between 'created' and 'prepared'<commit_after>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*  define a state transition  */
$cs.transition = function () {
    /*  special case  */
    if (arguments.length === 1 && arguments[0] === null) {
        /*  remove all user-defined transitions  */
        _cs.states_clear();
        return;
    }

    /*  determine parameters  */
    var params = $cs.params("transition", arguments, {
        target: { pos: 0, def: null, req: true },
        enter:  { pos: 1, def: null, req: true },
        leave:  { pos: 2, def: null, req: true },
        color:  { pos: 3, def: null, req: true },
        source: {         def: null            }
    });

    /*  add new state  */
    _cs.states_add(
        params.target,
        params.enter,
        params.leave,
        params.color,
        params.source
    );
};

/*  initialize state transition set with a reasonable default  */
$cs.transition("created",      "create",  "destroy",  "#cc3333"); /* created and attached to component tree */
$cs.transition("configured",   "setup",   "teardown", "#eabc43"); /* configured and wired */
$cs.transition("prepared",     "prepare", "cleanup",  "#f2ec00"); /* prepared and ready for rendering */
$cs.transition("materialized", "render",  "release",  "#6699cc"); /* rendered onto the DOM tree */
$cs.transition("visible",      "show",    "hide",     "#669933"); /* visible to the user */

<|endoftext|>


<commit_before>const merge = require('webpack-merge');
const path = require('path');
const webpack = require('webpack');
const NpmInstallPlugin = require('npm-install-webpack-plugin');
const stylelint = require('stylelint');
const configSuitcss = require('stylelint-config-suitcss');

const TARGET = process.env.npm_lifecycle_event;
const PATHS = {
  app: path.join(__dirname, 'app'),
  build: path.join(__dirname, 'build')
};

process.env.BABEL_ENV = TARGET;

const common = {
  // Entry accepts a path or an object of entries. We'll be using the
  // latter form given it's convenient with more complex configurations.
  entry: {
    javascript: './app/js/app.js',
    html: './app/index.html'
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: PATHS.build,
    filename: './js/app.js'
  },
  module: {
    preLoaders: [
      {
	test: /\.jsx?$/,
	loaders: ['eslint'],
	include: PATHS.app
      },
      {
	test: /\.css$/,
	loaders: ['postcss'],
	include: PATHS.app
      }
    ],
    loaders: [
      {
	test: /\.html$/,
	loader: 'file?name=[name].[ext]'
      },
      {
        // Test expects a RegExp! Note the slashes!
        test: /\.css$/,
        loaders: ['style', 'css'],
        // Include accepts either a path or an array of paths.
        include: PATHS.app
      },
      {
	test: /\.jsx?$/,
	loaders: ['babel?cacheDirectory'],
	include: PATHS.app
      }
    ]
  },
  postcss: function () {
    return [stylelint(configSuitcss)];
  }
};

if (TARGET === 'start' || !TARGET) {
  module.exports = merge(common, {
    devtool: 'eval-source-map',
    devServer: {
      contentBase: PATHS.build,
        // Enable history API fallback so HTML5 History API based
        // routing works. This is a good default that will come
        // in handy in more complicated setups.
        historyApiFallback: true,
        hot: true,
        inline: true,
        progress: true,

        // Display only errors to reduce the amount of output.
        stats: 'errors-only',

        // Parse host and port from env so this is easy to customize.
        //
        // If you use Vagrant or Cloud9, set
        // host: process.env.HOST || '0.0.0.0';
        //
        // 0.0.0.0 is available to all network devices unlike default
        // localhost
        host: process.env.HOST,
        port: process.env.PORT
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new NpmInstallPlugin({
          save: true // --save
        })
      ]
  });
}

if(TARGET === 'build') {
  module.exports = merge(common, {
    plugins: [
      new webpack.optimize.UglifyJsPlugin({minimize: true})
    ]
  });
}
<commit_msg>Change requires to imports in webpack config<commit_after>import merge from 'webpack-merge';
import path from 'path';
import webpack from 'webpack';
import NpmInstallPlugin from 'npm-install-webpack-plugin';
import stylelint from 'stylelint';
import configSuitcss from 'stylelint-config-suitcss';

const TARGET = process.env.npm_lifecycle_event;
const PATHS = {
  app: path.join(__dirname, 'app'),
  build: path.join(__dirname, 'build')
};

process.env.BABEL_ENV = TARGET;

const common = {
  // Entry accepts a path or an object of entries. We'll be using the
  // latter form given it's convenient with more complex configurations.
  entry: {
    javascript: './app/js/app.js',
    html: './app/index.html'
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: PATHS.build,
    filename: './js/app.js'
  },
  module: {
    preLoaders: [
      {
	test: /\.jsx?$/,
	loaders: ['eslint'],
	include: PATHS.app
      },
      {
	test: /\.css$/,
	loaders: ['postcss'],
	include: PATHS.app
      }
    ],
    loaders: [
      {
	test: /\.html$/,
	loader: 'file?name=[name].[ext]'
      },
      {
        // Test expects a RegExp! Note the slashes!
        test: /\.css$/,
        loaders: ['style', 'css'],
        // Include accepts either a path or an array of paths.
        include: PATHS.app
      },
      {
	test: /\.jsx?$/,
	loaders: ['babel?cacheDirectory'],
	include: PATHS.app
      }
    ]
  },
  postcss: function () {
    return [stylelint(configSuitcss)];
  }
};

if (TARGET === 'start' || !TARGET) {
  module.exports = merge(common, {
    devtool: 'eval-source-map',
    devServer: {
      contentBase: PATHS.build,
        // Enable history API fallback so HTML5 History API based
        // routing works. This is a good default that will come
        // in handy in more complicated setups.
        historyApiFallback: true,
        hot: true,
        inline: true,
        progress: true,

        // Display only errors to reduce the amount of output.
        stats: 'errors-only',

        // Parse host and port from env so this is easy to customize.
        //
        // If you use Vagrant or Cloud9, set
        // host: process.env.HOST || '0.0.0.0';
        //
        // 0.0.0.0 is available to all network devices unlike default
        // localhost
        host: process.env.HOST,
        port: process.env.PORT
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new NpmInstallPlugin({
          save: true // --save
        })
      ]
  });
}

if(TARGET === 'build') {
  module.exports = merge(common, {
    plugins: [
      new webpack.optimize.UglifyJsPlugin({minimize: true})
    ]
  });
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import IconText from '../IconText';
import css from './ButtonIconText.css';

class ButtonIconText extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hovering: false,
    };
  }

  hover(hovering) {
    this.setState({
      hovering,
    });
  }

  render() {
    const { onClick, ...other } = this.props;
    const { hovering } = this.state;
    return (
      <button
        className={css.button}
        onClick={onClick}
        onMouseEnter={() => this.hover(true)}
        onMouseLeave={() => this.hover(false)}
        {...other}
      >
        <IconText hovering={hovering} {...other} />
      </button>
    );
  }
}

ButtonIconText.propTypes = {
  onClick: PropTypes.func.isRequired,
};

export default ButtonIconText;
<commit_msg>Make ButtonIconText button proptypes explicit<commit_after>import React, { Component, PropTypes } from 'react';
import IconText from '../IconText';
import css from './ButtonIconText.css';

class ButtonIconText extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hovering: false,
    };
  }

  hover(hovering) {
    this.setState({
      hovering,
    });
  }

  render() {
    const { onClick, ...other } = this.props;
    const { hovering } = this.state;
    return (
      <button
        className={css.button}
        onClick={onClick}
        onMouseEnter={() => this.hover(true)}
        onMouseLeave={() => this.hover(false)}
      >
        <IconText hovering={hovering} {...other} />
      </button>
    );
  }
}

ButtonIconText.defaultProps = {
  disabled: false,
};

ButtonIconText.propTypes = {
  onClick: PropTypes.func.isRequired,
  disabled: PropTypes.bool,
};

export default ButtonIconText;
<|endoftext|>


<commit_before>const path = require('path');
const Dropbox = require('dropbox');
const express = require('express');
const magnet = require('magnet-uri');
const WebTorrent = require('webtorrent');
const firebase = require('firebase');
var client = new WebTorrent();
var dbx = new Dropbox({
  accessToken: process.env.DROPBOX_ACCESS_TOKEN
});
var router = express.Router();
const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.FIREBASE_DB_URL,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID
};

firebase.initializeApp(firebaseConfig);
let database = firebase.database();

/* GET home page. */
router.get('/', function(req, res) {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// this provides download link for downloaded files
router.get('/download', function(req, res) {
  var file = path.join(__dirname, 'tmp', req.query.file);
  var fileName = path.basename(file);
  console.log(`Dowloading ${fileName} ...`);
  res.download(file, fileName); // Set disposition and send it.
});

// to add torrent enter 'http://your_url.com/torAdd?magnet=magnet_link
router.get('/torAdd', function(req, res) {
  console.log('started');
  client.add(req.query.magnet, {
    path: 'tmp'
  }, (torrent) => {
    let parsedInfo = magnet.decode(torrent.magnetURI);
    torrent.on('done', () => {
      console.log('torrent download finished');
      torrent.files.forEach(function(file, index) {
        console.log(`${file.length} ${file.path} \n`);
        // Must be a publicly accessible URL for Dropbox upload to work
        var url = encodeURI(`${req.protocol}://${req.hostname}/download?file=${file.path}`);
        console.log(url);
        dbx.filesSaveUrl({
            path: `/Saves/${file.path}`,
            url: url
          })
          .then((response) => {
            // Async upload started
            if (response['.tag'] === 'async_job_id') {
              // check async upload status
              database.ref(`${torrent.infoHash}/name`).set(parsedInfo.name);
              checkComplete(torrent.infoHash, response['async_job_id']);
              console.log(`Started async upload: ${response['async_job_id']}`);
            } else if (response['.tag'] === 'complete') {
              console.log(`Downloaded ${file.name}`);
            }
            console.log(response);
          })
          .catch((error) => {
            console.log(error);
          });
      });
    });
  });
  res.send('downloading');
});

let checkStatus = (jobId) => {
  return dbx.filesSaveUrlCheckJobStatus({
    async_job_id: jobId
  });
};

let checkComplete = (hash, jobId) => {
  console.log('Checking status of ', jobId);
  checkStatus(jobId)
    .then((response) => {
      // 'in_progress' | 'complete' | 'failed'
      database.ref(`${hash}/items/${jobId}`).set(response['.tag']);
      switch (response['.tag']) {
        case 'in_progress':
          // Call the function again after 10 seconds
          setTimeout(
            function() {
              process.nextTick(checkComplete, hash, jobId);
            }, 10 * 1000);
          break;
        case 'failed':
          console.log('Failed: ', response['failed'])
          break;
        case 'complete':
          console.log(`${jobId} download complete`)
          break;
      }
    })
    .catch((error) => {
      console.error(error);
    });
};

module.exports = router;
<commit_msg>Remove unused firebase env variables<commit_after>const path = require('path');
const Dropbox = require('dropbox');
const express = require('express');
const magnet = require('magnet-uri');
const WebTorrent = require('webtorrent');
const firebase = require('firebase');

const client = new WebTorrent();
const router = express.Router();

const dbx = new Dropbox({
  accessToken: process.env.DROPBOX_ACCESS_TOKEN
});
const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  databaseURL: process.env.FIREBASE_DB_URL
};

firebase.initializeApp(firebaseConfig);
let database = firebase.database();

/* GET home page. */
router.get('/', function(req, res) {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// this provides download link for downloaded files
router.get('/download', function(req, res) {
  const file = path.join(__dirname, 'tmp', req.query.file);
  const fileName = path.basename(file);
  console.log(`Dowloading ${fileName} ...`);
  res.download(file, fileName);
});

// to add torrent enter 'http://your_url.com/torAdd?magnet=magnet_link
router.get('/torAdd', function(req, res) {
  console.log('started');
  client.add(req.query.magnet, {
    path: 'tmp'
  }, (torrent) => {
    const parsedInfo = magnet.decode(torrent.magnetURI);
    torrent.on('done', () => {
      console.log('torrent download finished');
      torrent.files.forEach(function(file, index) {
        console.log(`${file.length} ${file.path} \n`);
        // Must be a publicly accessible URL for Dropbox upload to work
        const url = encodeURI(`${req.protocol}://${req.hostname}/download?file=${file.path}`);
        console.log(url);
        dbx.filesSaveUrl({
            path: `/Saves/${file.path}`,
            url: url
          })
          .then((response) => {
            // Async upload started
            if (response['.tag'] === 'async_job_id') {
              // check async upload status
              database.ref(`${torrent.infoHash}/name`).set(parsedInfo.name);
              checkComplete(torrent.infoHash, response['async_job_id']);
              console.log(`Started async upload: ${response['async_job_id']}`);
            } else if (response['.tag'] === 'complete') {
              console.log(`Downloaded ${file.name}`);
            }
            console.log(response);
          })
          .catch((error) => {
            console.log(error);
          });
      });
    });
  });
  res.send('downloading');
});

let checkStatus = (jobId) => {
  return dbx.filesSaveUrlCheckJobStatus({
    async_job_id: jobId
  });
};

let checkComplete = (hash, jobId) => {
  console.log(`Checking status of ${jobId}`);
  checkStatus(jobId)
    .then((response) => {
      // 'in_progress' | 'complete' | 'failed'
      database.ref(`${hash}/items/${jobId}`).set(response['.tag']);
      switch (response['.tag']) {
        case 'in_progress':
          // Call the function again after 10 seconds
          setTimeout(
            function() {
              process.nextTick(checkComplete, hash, jobId);
            }, 10 * 1000);
          break;
        case 'failed':
          console.log('Failed: ', response['failed'])
          break;
        case 'complete':
          console.log(`${jobId} download complete`)
          break;
      }
    })
    .catch((error) => {
      console.error(error);
    });
};

module.exports = router;
<|endoftext|>


<commit_before>const rp = require('request-promise');
const cheerio = require('cheerio');

const getStreakBody = (userName) => {
	var options = {
		uri: `https://github.com/users/${userName}/contributions`,
		transform: function (body) {
			return cheerio.load(body);
		}
	};

	return rp(options)

	.then(function ($) {

			const currentDateStreak = [];
			let currentStreak = [];

			$('.day').each(function (index) {

				const date = new Date($(this).prop('data-date'));
				date.setHours(0, 0, 0, 0);

				const commit = $(this).prop('data-count');

				if (currentDateStreak[index - 1]) {
					const tempDate = currentDateStreak[index - 1].date;
					tempDate.setDate(tempDate.getDate() + 1);
					tempDate.setHours(0, 0, 0, 0);

					if (commit > 0 && date.getTime() === tempDate.getTime()) {
						currentStreak.push({
							date: date,
							commit: commit
						});
					} else {
						if(index < ($('.day').length -1)){
							currentStreak = [];
						}
					}
				}

				currentDateStreak.push({
					date: date
				});

			});
			return currentStreak;
		})
		.catch(function (err) {
			console.log('errror', err);
		});
};

module.exports = {
	getStreakBody
};<commit_msg>refactor server<commit_after>const rp = require('request-promise');
const cheerio = require('cheerio');

const getStreakBody = (userName) => {
	var options = {
		uri: `https://github.com/users/${userName}/contributions`,
		transform: function (body) {
			return cheerio.load(body);
		}
	};

	return rp(options)
		.then(function ($) {

			let commit = 0;
			let currentStreak = [];

			$('.day').each(function (index) {

				const date = $(this).prop('data-date')
				const commitQuantity = $(this).prop('data-count');

				console.log(`------------------${userName}----------------------`);
				console.log('commit atual: ', commitQuantity);
				console.log('commit anterior: ', commit);
				console.log('date: ', date);

				if (commitQuantity > 0 && commit > 0 || index === 0) {
					currentStreak.push({
						date: date,
						commit: commit
					});
				} else {
					currentStreak = [];
				}

				commit = $(this).prop('data-count');
			});

			return currentStreak;
		})
		.catch(function (err) {
			console.log('errror', err);
		});
};

module.exports = {
	getStreakBody
};<|endoftext|>


<commit_before>/**
 * Created by manhhailua on 1/4/17.
 */

import path from 'path';
import webpack from 'webpack';
import yargs from 'yargs';
import {
  version,
  description,
  author,
  license,
  homepage,
} from './package.json';

const { env, name, release } = yargs.argv;
const isProduction = (env === 'production');
const libraryName = name || 'Library';
let libraryFileName = '';

if (!isProduction && !release) {
  libraryFileName = `${libraryName}.js`;
} else if (isProduction && !release) {
  libraryFileName = `${libraryName}.build.js`;
} else {
  libraryFileName = `${libraryName}.min.js`;
}

const config = {

  entry: `${__dirname}/src/index.js`,

  devtool: 'source-map',

  output: {
    path: `${__dirname}/build`,
    filename: libraryFileName,
    library: libraryName,
    libraryTarget: 'umd',
    umdNamedDefine: true,
  },

  module: {
    loaders: [
      {
        test: /(\.js)$/,
        loader: 'babel',
        exclude: /(node_modules|bower_components)/,
        query: {
          compact: 'auto',
        },
      },
      {
        test: /(\.js)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
      },
    ],
  },

  resolve: {
    alias: {
      vue$: `${__dirname}/node_modules/vue/dist/vue.common.js`,
    },
    root: path.resolve('./src'),
    extensions: ['', '.js'],
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': (isProduction && release) ? '"production"' : '"development"',
    }),
    ...isProduction ? [new webpack.optimize.UglifyJsPlugin({ compress: { warnings: true } })] : [],
    // optimize module ids by occurence count
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.BannerPlugin(`${libraryFileName} v${version}\n${description}\n© 2016-${new Date().getFullYear()} ${author}\nReleased under the ${license} License.\n${homepage}`),
  ],

};

export default config;
<commit_msg>truncate all other comments<commit_after>/**
 * Created by manhhailua on 1/4/17.
 */

import path from 'path';
import webpack from 'webpack';
import yargs from 'yargs';
import {
  version,
  description,
  author,
  license,
  homepage,
} from './package.json';

const { env, name, release } = yargs.argv;
const isProduction = (env === 'production');
const libraryName = name || 'Library';
let libraryFileName = '';

if (!isProduction && !release) {
  libraryFileName = `${libraryName}.js`;
} else if (isProduction && !release) {
  libraryFileName = `${libraryName}.build.js`;
} else {
  libraryFileName = `${libraryName}.min.js`;
}

const config = {

  entry: `${__dirname}/src/index.js`,

  devtool: 'source-map',

  output: {
    path: `${__dirname}/build`,
    filename: libraryFileName,
    library: libraryName,
    libraryTarget: 'umd',
    umdNamedDefine: true,
  },

  module: {
    loaders: [
      {
        test: /(\.js)$/,
        loader: 'babel',
        exclude: /(node_modules|bower_components)/,
        query: {
          compact: 'auto',
        },
      },
      {
        test: /(\.js)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
      },
    ],
  },

  resolve: {
    alias: {
      vue$: `${__dirname}/node_modules/vue/dist/vue.common.js`,
    },
    root: path.resolve('./src'),
    extensions: ['', '.js'],
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': (isProduction && release) ? '"production"' : '"development"',
    }),
    ...isProduction ? [
      new webpack.optimize.UglifyJsPlugin({
        compress: { warnings: true },
        comments: false,
      }),
    ] : [],
    // optimize module ids by occurence count
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.BannerPlugin(`${libraryFileName} v${version}\n${description}\n© 2016-${new Date().getFullYear()} ${author}\nReleased under the ${license} License.\n${homepage}`),
  ],

};

export default config;
<|endoftext|>