<commit_before>/* Upload pattern.
 *
 * Options:
 *    showTitle(boolean): show/hide the h1 title (true)
 *    url(string): If not used with a form, this option must provide the URL to submit to or baseUrl with relativePath needs to be used (null)
 *    baseUrl(string): to be used in conjunction with relativePath to generate submission urls based on related items (null)
 *    relativePath(string): again, to be used with baseUrl to create upload url (null)
 *    initialFolder(string): UID of initial folder related items widget should have selected (null)
 *    currentPath(string): Current path related items is starting with (null)
 *    clickable(boolean): If you can click on container to also upload (false)
 *    className(string): value for class attribute in the form element ('upload')
 *    paramName(string): value for name attribute in the file input element ('file')
 *    ajaxUpload(boolean): true or false for letting the widget upload the files via ajax. If false the form will act like a normal form. (true)
 *    wrap(boolean): true or false for wrapping this element using the value of wrapperTemplate. (false)
 *    wrapperTemplate(string): HTML template for wrapping around with this element. ('
')
 *    resultTemplate(string): HTML template for the element that will contain file information. ('

Drop files here...

')
 *    autoCleanResults(boolean): condition value for the file preview in div element to fadeout after file upload is completed. (true)
 *    previewsContainer(selector): JavaScript selector for file preview in div element. (.upload-previews)
 *    container(selector): JavaScript selector for where to put upload stuff into in case of form. If not provided it will be place before the first submit button. ('')
 *    relatedItems(object): Related items pattern options. Will only use only if relativePath is used to use correct upload destination ({ attributes: ["UID", "Title", "Description", "getURL", "Type", "path", "ModificationDate"], batchSize: 20, basePath: "/", vocabularyUrl: null, width: 500, maximumSelectionSize: 1, placeholder: "Search for item on site..." })
 *
 * Documentation:
 *
 *    # On a div element
 *
 *    {{ example-1 }}
 *
 * Example: example-1
 *

 *

 *
Something here that is useful

 *
Something else here that is useful

 *
Another thing here that is useful

 *

 *

 *
 *
 * License:
 *    Copyright (C) 2010 Plone Foundation
 *
 *    This program is free software; you can redistribute it and/or modify it
 *    under the terms of the GNU General Public License as published by the
 *    Free Software Foundation; either version 2 of the License.
 *
 *    This program is distributed in the hope that it will be useful, but
 *    WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 *    Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

define([
  'jquery',
  'underscore',
  'mockup-patterns-base',
  'mockup-patterns-relateditems',
  'dropzone',
  'text!mockup-patterns-upload-url/templates/upload.xml',
  'text!mockup-patterns-upload-url/templates/preview.xml',
  'mockup-i18n'
], function($, _, Base, RelatedItems, Dropzone,
            UploadTemplate, PreviewTemplate, i18n) {
  'use strict';

  /* we do not want this plugin to auto discover */
  Dropzone.autoDiscover = false;

  i18n.loadCatalog('widgets');
  var _t = i18n.MessageFactory('widgets');

  var UploadPattern = Base.extend({
    name: 'upload',
    defaults: {
      showTitle: true,
      url: null, // XXX MUST provide url to submit to OR be in a form
      className: 'upload',
      wrap: false,
      wrapperTemplate: '
',
      fileaddedClassName: 'dropping',
      useTus: false,
      container: '',
      ajaxUpload: true,

      paramName: 'file',
      clickable: true,
      addRemoveLinks: false,
      autoCleanResults: true,
      previewsContainer: '.previews',
      previewTemplate: null,
      maxFiles: null,
      maxFilesize: 99999999, // let's not have a max by default...

      relatedItems: {
        // UID attribute is required here since we're working with related items
        attributes: ['UID', 'Title', 'Description', 'getURL', 'Type', 'path', 'ModificationDate'],
        batchSize: 20,
        basePath: '/',
        vocabularyUrl: null,
        width: 500,
        maximumSelectionSize: 1,
        placeholder: _t('Search for item on site...')
      }
    },

    //placeholder: 'Search for item on site...'
    init: function() {
      var self = this,
          template = UploadTemplate;

      // values that will change current processing
      self.currentPath = self.options.currentPath;
      self.numFiles = 0;
      self.currentFile = 0;

      template = _.template(template, {_t: _t});
      self.$el.addClass(self.options.className);
      self.$el.append(template);

      self.$progress = $('.progress-bar-success', self.$el);

      if (!self.options.showTitle) {
        self.$el.find('h2.title').hide();
      }

      if (!self.options.ajaxUpload) {
        // no ajax upload, drop the fallback
        $('.fallback', this.$el).remove();
        if (this.$el.hasClass('.upload-container')) {
          this.$el.addClass('no-ajax-upload');
        } else {
          this.$el.closest('.upload-container').addClass('no-ajax-upload');
        }
      }

      if (self.options.wrap) {
        self.$el.wrap(self.options.wrapperTemplate);
        self.$el = self.$el.parent();
      }

      if (self.options.baseUrl && self.options.relativePath){
        // only use related items if we can generate paths based urls
        self.$pathInput = $('input[name="location"]', self.$el);
        self.relatedItems = self.setupRelatedItems(self.$pathInput);
      } else {
        $('input[name="location"]', self.$el).parent().remove();
        self.relatedItems = null;
      }

      var $uploadArea = $('.upload-area', self.$el);

      $('button.browse', self.$el).click(function(e) {
        e.preventDefault();
        e.stopPropagation();
        // we trigger the dropzone dialog!
        self.dropzone.hiddenFileInput.click();
      });

      var dzoneOptions = this.getDzoneOptions();

      try {
        // if init of Dropzone fails it says nothing and
        // it fails silently. Using this block we make sure
        // that if you break it w/ some weird or missing option
        // you can get a proper log of it
        //
        self.dropzone = new Dropzone($uploadArea[0], dzoneOptions);
      } catch (e) {
        if (window.DEBUG) {
          // log it!
          console.log(e);
        }
        throw e;
      }

      self.dropzone.on('addedfile', function(file) {
        //console.log('file added!!');
        // show upload controls
        self.showControls();
        // self.$el.addClass(fileaddedClassName);
        // setTimeout(function() {
        //   if (!processing) {
        //     process();
        //   }
        // }, 100);
      });

      self.dropzone.on('removedfile', function() {
        if (self.dropzone.files.length < 1) {
          self.hideControls();
        }
      });

      if (self.options.autoCleanResults) {
        self.dropzone.on('complete', function(file) {
          setTimeout(function() {
            $(file.previewElement).fadeOut();
          }, 3000);
        });
      }

      self.dropzone.on('complete', function(file) {
        if (self.dropzone.files.length < 1) {
          self.hideControls();
        }
      });

      self.dropzone.on('totaluploadprogress', function(pct) {
        // need to caclulate total pct here in reality since we're manually
        // processing each file one at a time.
        pct = ((((self.currentFile - 1) * 100) + pct) / (self.numFiles * 100)) * 100;
        self.$progress.attr('aria-valuenow', pct).css('width', pct + '%');
      });

      $('.upload-all', self.$el).click(function (e) {
        e.preventDefault();
        e.stopPropagation();
        self.processUpload({
          finished: function() {
            self.$progress.attr('aria-valuenow', 0).css('width', '0%');
          }
        });
      });
    },

    showControls: function() {
      var self = this;
      $('.controls', self.$el).fadeIn('slow');
    },

    hideControls: function() {
      var self = this;
      $('.controls', self.$el).fadeOut('slow');
    },

    pathJoin: function() {
      var parts = [];
      _.each(arguments, function(part) {
        if (!part){
          return;
        }
        if (part[0] === '/'){
          part = part.substring(1);
        }
        if (part[part.length - 1] === '/'){
          part = part.substring(0, part.length - 1);
        }
        parts.push(part);
      });
      return parts.join('/');
    },

    getUrl: function() {

      var self = this;
      var url = self.options.url;
      if (!url) {
        if (self.options.baseUrl && self.options.relativePath){
          url = self.options.baseUrl;
          if (url[url.length - 1] !== '/'){
            url = url + '/';
          }
          url = url + self.pathJoin(self.currentPath, self.options.relativePath);
        } else {
          var $form = self.$el.parents('form');
          if ($form.length > 0){
            url = $form.attr('action');
          } else {
            url = window.location.href;
          }
        }
      }
      return url;
    },

    getDzoneOptions: function() {
      var self = this;

      // clickable option
      if (typeof(self.options.clickable) === 'string') {
        if (self.options.clickable === 'true') {
          self.options.clickable = true;
        } else {
          self.options.clickable = false;
        }
      }

      var options = $.extend({}, self.options);
      options.url = self.getUrl();
      // XXX force to only upload one at a time,
      // right now we don't support multiple for backends
      options.uploadMultiple = false;

      delete options.wrap;
      delete options.wrapperTemplate;
      delete options.resultTemplate;
      delete options.autoCleanResults;
      delete options.fileaddedClassName;
      delete options.useTus;

      if (self.options.previewsContainer) {
        /*
         * if they have a select but it's not an id, let's make an id selector
         * so we can target the correct container. dropzone is weird here...
         */
        var $preview = self.$el.find(self.options.previewsContainer);
        if ($preview.length > 0) {
          options.previewsContainer = $preview[0];
        }
      }

      // XXX: do we need to allow this?
      options.autoProcessQueue = false;
      // options.addRemoveLinks = true;  // we show them in the template
      options.previewTemplate = PreviewTemplate;

      // if our element is a form we should force some values
      // https://github.com/enyo/dropzone/wiki/Combine-normal-form-with-Dropzone
      return options;
    },

    processUpload: function(options) {
      if (!options){
        options = {};
      }

      var self = this,
          processing = false,
          useTus = self.options.useTus,
          fileaddedClassName = self.options.fileaddedClassName,
          finished = options.finished;

      self.numFiles = self.dropzone.files.length;
      self.currentFile = 0;

      function process() {
        processing = true;
        if (self.dropzone.files.length === 0) {
          processing = false;
          self.$el.removeClass(fileaddedClassName);
          if (finished !== undefined && typeof(finished) === 'function'){
            finished();
          }
          return;
        }
        var file = self.dropzone.files[0];
        if ([Dropzone.SUCCESS, Dropzone.ERROR, Dropzone.CANCELED]
            .indexOf(file.status) !== -1) {
          // remove it
          self.dropzone.removeFile(file);
          process();
        } else if (file.status !== Dropzone.UPLOADING) {
          // start processing file
          if (useTus && window.tus) {
            // use tus upload if installed
            self.handleTusUpload(file);
          } else {
            // otherwise, just use dropzone to process
            self.currentFile += 1;
            self.dropzone.processFile(file);
          }
          setTimeout(process, 100);
        } else {
          // currently processing
          setTimeout(process, 100);
        }
      }
      process();
    },

    handleTusUpload: function(file) {
      /* this needs fixing... */
      var self = this,
          $preview = $(file.previewElement),
          chunkSize = 1024 * 1024 * 5; // 5mb chunk size

      file.status = Dropzone.UPLOADING;

      window.tus.upload(file, {
        endpoint: self.dropzone.options.url,
        headers: {
          'FILENAME': file.name
        },
        chunkSize: chunkSize
      }).fail(function() {
        console.alert('Error uploading with TUS resumable uploads');
        file.status = Dropzone.ERROR;
      }).progress(function(e, bytesUploaded, bytesTotal) {
        var percentage = (bytesUploaded / bytesTotal * 100);
        self.$progress.attr('aria-valuenow', percentage).css('width', percentage + '%');
        self.$progress.html(_t('uploading...
') +
                            self.formatBytes(bytesUploaded) +
                            ' / ' + self.formatBytes(bytesTotal));
      }).done(function(url, file) {
        file.status = Dropzone.SUCCESS;
        self.dropzone.emit('success', file);
        self.dropzone.emit('complete', file);
      });
    },

    formatBytes: function(bytes) {
      var kb = Math.round(bytes / 1024);
      if (kb < 1024) {
        return kb + ' KiB';
      }
      var mb = Math.round(kb / 1024);
      if (mb < 1024) {
        return mb + ' MB';
      }
      return Math.round(mb / 1024) + ' GB';
    },

    setupRelatedItems: function($input) {
      var self = this;
      var options = self.options.relatedItems;
      if (self.options.initialFolder){
        $input.attr('value', self.options.initialFolder);
      }
      var ri = new RelatedItems($input, options);
      ri.$el.on('change', function() {
        var result = $(this).select2('data');
        if (result.length > 0){
          self.currentPath = result[0].path;
        } else {
          self.currentPath = null;
        }
        self.options.url = self.dropzone.options.url = self.getUrl();
      });
      return ri;
    }

  });

  return UploadPattern;

});
<commit_msg>ie9 fixes<commit_after>/* Upload pattern.
 *
 * Options:
 *    showTitle(boolean): show/hide the h1 title (true)
 *    url(string): If not used with a form, this option must provide the URL to submit to or baseUrl with relativePath needs to be used (null)
 *    baseUrl(string): to be used in conjunction with relativePath to generate submission urls based on related items (null)
 *    relativePath(string): again, to be used with baseUrl to create upload url (null)
 *    initialFolder(string): UID of initial folder related items widget should have selected (null)
 *    currentPath(string): Current path related items is starting with (null)
 *    clickable(boolean): If you can click on container to also upload (false)
 *    className(string): value for class attribute in the form element ('upload')
 *    paramName(string): value for name attribute in the file input element ('file')
 *    ajaxUpload(boolean): true or false for letting the widget upload the files via ajax. If false the form will act like a normal form. (true)
 *    wrap(boolean): true or false for wrapping this element using the value of wrapperTemplate. (false)
 *    wrapperTemplate(string): HTML template for wrapping around with this element. ('
')
 *    resultTemplate(string): HTML template for the element that will contain file information. ('

Drop files here...

')
 *    autoCleanResults(boolean): condition value for the file preview in div element to fadeout after file upload is completed. (true)
 *    previewsContainer(selector): JavaScript selector for file preview in div element. (.upload-previews)
 *    container(selector): JavaScript selector for where to put upload stuff into in case of form. If not provided it will be place before the first submit button. ('')
 *    relatedItems(object): Related items pattern options. Will only use only if relativePath is used to use correct upload destination ({ attributes: ["UID", "Title", "Description", "getURL", "Type", "path", "ModificationDate"], batchSize: 20, basePath: "/", vocabularyUrl: null, width: 500, maximumSelectionSize: 1, placeholder: "Search for item on site..." })
 *
 * Documentation:
 *
 *    # On a div element
 *
 *    {{ example-1 }}
 *
 * Example: example-1
 *

 *

 *
Something here that is useful

 *
Something else here that is useful

 *
Another thing here that is useful

 *

 *

 *
 *
 * License:
 *    Copyright (C) 2010 Plone Foundation
 *
 *    This program is free software; you can redistribute it and/or modify it
 *    under the terms of the GNU General Public License as published by the
 *    Free Software Foundation; either version 2 of the License.
 *
 *    This program is distributed in the hope that it will be useful, but
 *    WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 *    Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

define([
  'jquery',
  'underscore',
  'mockup-patterns-base',
  'mockup-patterns-relateditems',
  'dropzone',
  'text!mockup-patterns-upload-url/templates/upload.xml',
  'text!mockup-patterns-upload-url/templates/preview.xml',
  'mockup-i18n'
], function($, _, Base, RelatedItems, Dropzone,
            UploadTemplate, PreviewTemplate, i18n) {
  'use strict';

  /* we do not want this plugin to auto discover */
  Dropzone.autoDiscover = false;

  i18n.loadCatalog('widgets');
  var _t = i18n.MessageFactory('widgets');

  var UploadPattern = Base.extend({
    name: 'upload',
    defaults: {
      showTitle: true,
      url: null, // XXX MUST provide url to submit to OR be in a form
      className: 'upload',
      wrap: false,
      wrapperTemplate: '
',
      fileaddedClassName: 'dropping',
      useTus: false,
      container: '',
      ajaxUpload: true,

      paramName: 'file',
      clickable: true,
      addRemoveLinks: false,
      autoCleanResults: true,
      previewsContainer: '.previews',
      previewTemplate: null,
      maxFiles: null,
      maxFilesize: 99999999, // let's not have a max by default...

      relatedItems: {
        // UID attribute is required here since we're working with related items
        attributes: ['UID', 'Title', 'Description', 'getURL', 'Type', 'path', 'ModificationDate'],
        batchSize: 20,
        basePath: '/',
        vocabularyUrl: null,
        width: 500,
        maximumSelectionSize: 1,
        placeholder: _t('Search for item on site...')
      }
    },

    //placeholder: 'Search for item on site...'
    init: function() {
      var self = this,
          template = UploadTemplate;

      // values that will change current processing
      self.currentPath = self.options.currentPath;
      self.numFiles = 0;
      self.currentFile = 0;

      template = _.template(template, {_t: _t});
      self.$el.addClass(self.options.className);
      self.$el.append(template);

      self.$progress = $('.progress-bar-success', self.$el);

      if (!self.options.showTitle) {
        self.$el.find('h2.title').hide();
      }

      if (!self.options.ajaxUpload) {
        // no ajax upload, drop the fallback
        $('.fallback', this.$el).remove();
        if (this.$el.hasClass('.upload-container')) {
          this.$el.addClass('no-ajax-upload');
        } else {
          this.$el.closest('.upload-container').addClass('no-ajax-upload');
        }
      }

      if (self.options.wrap) {
        self.$el.wrap(self.options.wrapperTemplate);
        self.$el = self.$el.parent();
      }

      if (self.options.baseUrl && self.options.relativePath){
        // only use related items if we can generate paths based urls
        self.$pathInput = $('input[name="location"]', self.$el);
        self.relatedItems = self.setupRelatedItems(self.$pathInput);
      } else {
        $('input[name="location"]', self.$el).parent().remove();
        self.relatedItems = null;
      }

      self.$dropzone = $('.upload-area', self.$el);

      $('button.browse', self.$el).click(function(e) {
        e.preventDefault();
        e.stopPropagation();
        // we trigger the dropzone dialog!
        self.dropzone.hiddenFileInput.click();
      });

      var dzoneOptions = this.getDzoneOptions();

      try {
        // if init of Dropzone fails it says nothing and
        // it fails silently. Using this block we make sure
        // that if you break it w/ some weird or missing option
        // you can get a proper log of it
        //
        self.dropzone = new Dropzone(self.$dropzone[0], dzoneOptions);
      } catch (e) {
        if (window.DEBUG) {
          // log it!
          console.log(e);
        }
        throw e;
      }

      self.$dropzone.on('addedfile', function(file) {
        self.showControls();
      });

      self.$dropzone.on('removedfile', function() {
        if (self.dropzone.files.length < 1) {
          self.hideControls();
        }
      });

      if (self.options.autoCleanResults) {
        self.$dropzone.on('complete', function(file) {
          setTimeout(function() {
            $(file.previewElement).fadeOut();
          }, 3000);
        });
      }

      self.$dropzone.on('complete', function(file) {
        if (self.dropzone.files.length < 1) {
          self.hideControls();
        }
      });

      self.$dropzone.on('totaluploadprogress', function(pct) {
        // need to caclulate total pct here in reality since we're manually
        // processing each file one at a time.
        pct = ((((self.currentFile - 1) * 100) + pct) / (self.numFiles * 100)) * 100;
        self.$progress.attr('aria-valuenow', pct).css('width', pct + '%');
      });

      $('.upload-all', self.$el).click(function (e) {
        e.preventDefault();
        e.stopPropagation();
        self.processUpload({
          finished: function() {
            self.$progress.attr('aria-valuenow', 0).css('width', '0%');
          }
        });
      });
    },

    showControls: function() {
      var self = this;
      $('.controls', self.$el).fadeIn('slow');
    },

    hideControls: function() {
      var self = this;
      $('.controls', self.$el).fadeOut('slow');
    },

    pathJoin: function() {
      var parts = [];
      _.each(arguments, function(part) {
        if (!part){
          return;
        }
        if (part[0] === '/'){
          part = part.substring(1);
        }
        if (part[part.length - 1] === '/'){
          part = part.substring(0, part.length - 1);
        }
        parts.push(part);
      });
      return parts.join('/');
    },

    getUrl: function() {

      var self = this;
      var url = self.options.url;
      if (!url) {
        if (self.options.baseUrl && self.options.relativePath){
          url = self.options.baseUrl;
          if (url[url.length - 1] !== '/'){
            url = url + '/';
          }
          url = url + self.pathJoin(self.currentPath, self.options.relativePath);
        } else {
          var $form = self.$el.parents('form');
          if ($form.length > 0){
            url = $form.attr('action');
          } else {
            url = window.location.href;
          }
        }
      }
      return url;
    },

    getDzoneOptions: function() {
      var self = this;

      // clickable option
      if (typeof(self.options.clickable) === 'string') {
        if (self.options.clickable === 'true') {
          self.options.clickable = true;
        } else {
          self.options.clickable = false;
        }
      }

      var options = $.extend({}, self.options);
      options.url = self.getUrl();
      // XXX force to only upload one at a time,
      // right now we don't support multiple for backends
      options.uploadMultiple = false;

      delete options.wrap;
      delete options.wrapperTemplate;
      delete options.resultTemplate;
      delete options.autoCleanResults;
      delete options.fileaddedClassName;
      delete options.useTus;

      if (self.options.previewsContainer) {
        /*
         * if they have a select but it's not an id, let's make an id selector
         * so we can target the correct container. dropzone is weird here...
         */
        var $preview = self.$el.find(self.options.previewsContainer);
        if ($preview.length > 0) {
          options.previewsContainer = $preview[0];
        }
      }

      // XXX: do we need to allow this?
      options.autoProcessQueue = false;
      // options.addRemoveLinks = true;  // we show them in the template
      options.previewTemplate = PreviewTemplate;

      // if our element is a form we should force some values
      // https://github.com/enyo/dropzone/wiki/Combine-normal-form-with-Dropzone
      return options;
    },

    processUpload: function(options) {
      if (!options){
        options = {};
      }

      var self = this,
          processing = false,
          useTus = self.options.useTus,
          fileaddedClassName = self.options.fileaddedClassName,
          finished = options.finished;

      self.numFiles = self.dropzone.files.length;
      self.currentFile = 0;

      function process() {
        processing = true;
        if (self.dropzone.files.length === 0) {
          processing = false;
          self.$el.removeClass(fileaddedClassName);
          if (finished !== undefined && typeof(finished) === 'function'){
            finished();
          }
          return;
        }
        var file = self.dropzone.files[0];
        if ([Dropzone.SUCCESS, Dropzone.ERROR, Dropzone.CANCELED]
            .indexOf(file.status) !== -1) {
          // remove it
          self.dropzone.removeFile(file);
          process();
        } else if (file.status !== Dropzone.UPLOADING) {
          // start processing file
          if (useTus && window.tus) {
            // use tus upload if installed
            self.handleTusUpload(file);
          } else {
            // otherwise, just use dropzone to process
            self.currentFile += 1;
            self.dropzone.processFile(file);
          }
          setTimeout(process, 100);
        } else {
          // currently processing
          setTimeout(process, 100);
        }
      }
      process();
    },

    handleTusUpload: function(file) {
      /* this needs fixing... */
      var self = this,
          $preview = $(file.previewElement),
          chunkSize = 1024 * 1024 * 5; // 5mb chunk size

      file.status = Dropzone.UPLOADING;

      window.tus.upload(file, {
        endpoint: self.dropzone.options.url,
        headers: {
          'FILENAME': file.name
        },
        chunkSize: chunkSize
      }).fail(function() {
        if(window.DEBUG){
          console.alert('Error uploading with TUS resumable uploads');
        }
        file.status = Dropzone.ERROR;
      }).progress(function(e, bytesUploaded, bytesTotal) {
        var percentage = (bytesUploaded / bytesTotal * 100);
        self.$progress.attr('aria-valuenow', percentage).css('width', percentage + '%');
        self.$progress.html(_t('uploading...
') +
                            self.formatBytes(bytesUploaded) +
                            ' / ' + self.formatBytes(bytesTotal));
      }).done(function(url, file) {
        file.status = Dropzone.SUCCESS;
        self.dropzone.emit('success', file);
        self.dropzone.emit('complete', file);
      });
    },

    formatBytes: function(bytes) {
      var kb = Math.round(bytes / 1024);
      if (kb < 1024) {
        return kb + ' KiB';
      }
      var mb = Math.round(kb / 1024);
      if (mb < 1024) {
        return mb + ' MB';
      }
      return Math.round(mb / 1024) + ' GB';
    },

    setupRelatedItems: function($input) {
      var self = this;
      var options = self.options.relatedItems;
      if (self.options.initialFolder){
        $input.attr('value', self.options.initialFolder);
      }
      var ri = new RelatedItems($input, options);
      ri.$el.on('change', function() {
        var result = $(this).select2('data');
        if (result.length > 0){
          self.currentPath = result[0].path;
        } else {
          self.currentPath = null;
        }
        self.options.url = self.dropzone.options.url = self.getUrl();
      });
      return ri;
    }

  });

  return UploadPattern;

});
<|endoftext|>


<commit_before>define(['bootstrap', 'options', 'filters', 'profiles', 'tooltips'], function (news, options, Filters, Profiles, Tooltips) {

    // Function.prototype.bind() polyfill
    // ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
    if (!Function.prototype.bind) {
        Function.prototype.bind = function (oThis) {
            if (typeof this !== 'function') {
                throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
            }
            var aArgs = Array.prototype.slice.call(arguments, 1),
                fToBind = this,
                FNOP = function () {},
                fBound = function () {
                    return fToBind.apply(this instanceof FNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
                };
            if (this.prototype) {
                FNOP.prototype = this.prototype;
            }
            fBound.prototype = new FNOP();
            return fBound;
        };
    }

    var Facewall = function () {
        this.filters = new Filters();
        this.profiles = new Profiles();
        this.tooltips = new Tooltips();
    };

    Facewall.prototype = {
        init: function () {
            news.$('body').removeClass('no-js');
            this.filters.init();
            this.profiles.init();
            this.tooltips.init();
            this.setEvents();
        },

        setEvents: function () {
            news.pubsub.on(options.events.showFace, this.showFace.bind(this));
            news.pubsub.on(options.events.hideFace, this.hideFace.bind(this));

            var $filterTab = news.$('.' + options.classes.filterTab);
            var $filterCheckbox = news.$('.' + options.classes.filterCheckbox);
            var $thumbnail = news.$('.' + options.classes.thumbnail);
            var $profileWrapper = news.$('.' + options.classes.profileWrapper);
            var $backToFacewallButton = news.$('.' + options.classes.backToFacewallButton);

            $filterTab.on('click', function (e) {
                e.preventDefault();
                news.pubsub.emit(options.events.filterTabClicked, [news.$(this)]);
            });

            $filterCheckbox.on('change', function () {
                news.pubsub.emit(options.events.applyFilter, [news.$(this).val()]);
            });

            $thumbnail.on('click', function (e) {
                e.preventDefault();
                news.pubsub.emit(options.events.showProfile, [news.$(this)]);
            });

            $thumbnail.on('mouseover', function (e) {
                // hide all tooltips first to avoid showTooltip being called when another tooltip is already active
                var $allThumbnails = news.$('.' + options.classes.thumbnail);
                news.pubsub.emit(options.events.hideTooltip, [$allThumbnails]);
                news.pubsub.emit(options.events.showTooltip, [news.$(this)]);
            });

            $thumbnail.on('mouseout', function (e) {
                news.pubsub.emit(options.events.hideTooltip, [news.$(this)]);
            });

            $thumbnail.on('focus', function () {
                // hide all tooltips first to avoid showTooltip being called when another tooltip is already active
                var $allThumbnails = news.$('.' + options.classes.thumbnail);
                news.pubsub.emit(options.events.hideTooltip, [$allThumbnails]);
                news.pubsub.emit(options.events.showTooltip, [news.$(this)]);
            });

            $thumbnail.on('blur', function () {
                news.pubsub.emit(options.events.hideTooltip, [news.$(this)]);
            });

            $backToFacewallButton.on('click', function () {
                news.pubsub.emit(options.events.hideProfile);
            });
        },

        showFace: function (filterSuffix) {
            var $listItem;
            if (filterSuffix) {
                $listItem = news.$('.' + options.classes.listLiBase + filterSuffix);
            } else {
                $listItem = news.$('.' + options.classes.listLi);
            }
            $listItem.addClass(options.classes.filteredListLi);
        },

        hideFace: function (filterSuffix) {
            var $listItem;
            if (filterSuffix) {
                $listItem = news.$('.' + options.classes.listLiBase + filterSuffix);
            } else {
                $listItem = news.$('.' + options.classes.listLi);
            }
            $listItem.removeClass(options.classes.filteredListLi);
        }
    };

    return Facewall;
});<commit_msg>added Array.indexOf() polyfill<commit_after>define(['bootstrap', 'options', 'filters', 'profiles', 'tooltips'], function (news, options, Filters, Profiles, Tooltips) {

    // Function.prototype.bind() polyfill
    // ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
    if (!Function.prototype.bind) {
        Function.prototype.bind = function (oThis) {
            if (typeof this !== 'function') {
                throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
            }
            var aArgs = Array.prototype.slice.call(arguments, 1),
                fToBind = this,
                FNOP = function () {},
                fBound = function () {
                    return fToBind.apply(this instanceof FNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
                };
            if (this.prototype) {
                FNOP.prototype = this.prototype;
            }
            fBound.prototype = new FNOP();
            return fBound;
        };
    }

    // Array.prototype.indexOf() polyfill
    // ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (searchElement, fromIndex) {
            var k;
            if (this == null) {
                throw new TypeError('"this" is null or not defined');
            }
            var O = Object(this);
            var len = O.length >>> 0;
            if (len === 0) { return -1; }
            var n = +fromIndex || 0;
            if (Math.abs(n) === Infinity) { n = 0; }
            if (n >= len) { return -1; }
            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            while (k < len) {
                if (k in O && O[k] === searchElement) { return k; }
                k++;
            }
            return -1;
        };
    }

    var Facewall = function () {
        this.filters = new Filters();
        this.profiles = new Profiles();
        this.tooltips = new Tooltips();
    };

    Facewall.prototype = {
        init: function () {
            news.$('body').removeClass('no-js');
            this.filters.init();
            this.profiles.init();
            this.tooltips.init();
            this.setEvents();
        },

        setEvents: function () {
            news.pubsub.on(options.events.showFace, this.showFace.bind(this));
            news.pubsub.on(options.events.hideFace, this.hideFace.bind(this));

            var $filterTab = news.$('.' + options.classes.filterTab);
            var $filterCheckbox = news.$('.' + options.classes.filterCheckbox);
            var $thumbnail = news.$('.' + options.classes.thumbnail);
            var $profileWrapper = news.$('.' + options.classes.profileWrapper);
            var $backToFacewallButton = news.$('.' + options.classes.backToFacewallButton);

            $filterTab.on('click', function (e) {
                e.preventDefault();
                news.pubsub.emit(options.events.filterTabClicked, [news.$(this)]);
            });

            $filterCheckbox.on('change', function () {
                news.pubsub.emit(options.events.applyFilter, [news.$(this).val()]);
            });

            $thumbnail.on('click', function (e) {
                e.preventDefault();
                news.pubsub.emit(options.events.showProfile, [news.$(this)]);
            });

            $thumbnail.on('mouseover', function (e) {
                // hide all tooltips first to avoid showTooltip being called when another tooltip is already active
                var $allThumbnails = news.$('.' + options.classes.thumbnail);
                news.pubsub.emit(options.events.hideTooltip, [$allThumbnails]);
                news.pubsub.emit(options.events.showTooltip, [news.$(this)]);
            });

            $thumbnail.on('mouseout', function (e) {
                news.pubsub.emit(options.events.hideTooltip, [news.$(this)]);
            });

            $thumbnail.on('focus', function () {
                // hide all tooltips first to avoid showTooltip being called when another tooltip is already active
                var $allThumbnails = news.$('.' + options.classes.thumbnail);
                news.pubsub.emit(options.events.hideTooltip, [$allThumbnails]);
                news.pubsub.emit(options.events.showTooltip, [news.$(this)]);
            });

            $thumbnail.on('blur', function () {
                news.pubsub.emit(options.events.hideTooltip, [news.$(this)]);
            });

            $backToFacewallButton.on('click', function () {
                news.pubsub.emit(options.events.hideProfile);
            });
        },

        showFace: function (filterSuffix) {
            var $listItem;
            if (filterSuffix) {
                $listItem = news.$('.' + options.classes.listLiBase + filterSuffix);
            } else {
                $listItem = news.$('.' + options.classes.listLi);
            }
            $listItem.addClass(options.classes.filteredListLi);
        },

        hideFace: function (filterSuffix) {
            var $listItem;
            if (filterSuffix) {
                $listItem = news.$('.' + options.classes.listLiBase + filterSuffix);
            } else {
                $listItem = news.$('.' + options.classes.listLi);
            }
            $listItem.removeClass(options.classes.filteredListLi);
        }
    };

    return Facewall;
});<|endoftext|>


<commit_before>const getUtilisationTable = require('../services/get-utilisation-table')
const ORG_UNIT_TYPE = require('../constants/organisation-unit-type-enum')

module.exports = function (router) {
  router.get(`/caseload-utilisation/${ORG_UNIT_TYPE.OFFENDER_MANAGER}/:id/`, function (req, res, next) {
    return res.render('utilisation', {
      utilisation: getUtilisationTable(ORG_UNIT_TYPE.OFFENDER_MANAGER, req.params.id, req.query.date)
    })
  })
}
<commit_msg>244: added post route to allow getting differing query results by year.<commit_after>const getUtilisationTable = require('../services/get-utilisation-table')
const ORG_UNIT_TYPE = require('../constants/organisation-unit-type-enum')

module.exports = function (router) {
  router.get(`/caseload-utilisation/${ORG_UNIT_TYPE.OFFENDER_MANAGER}/:id/`, function (req, res, next) {
    return res.render('utilisation', {
      utilisation: getUtilisationTable(ORG_UNIT_TYPE.OFFENDER_MANAGER, req.params.id, req.query.date)
    })
  })

  router.post(`/caseload-utilisation/${ORG_UNIT_TYPE.OFFENDER_MANAGER}/:userId/:year/`, function (req, res, next) {
    date = req.body.date
    splitDate = date.split('-', 3)
    return res.render('utilisation', {
      utilisation: getUtilisationTable(ORG_UNIT_TYPE.OFFENDER_MANAGER, req.params.userId, splitDate[0])
    })
  })
}
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version).to.exist;
        expect(npmPackage.version).to.exist;

        if (!expect(ioPackage.common.version).to.be.equal(npmPackage.version)) {
            console.log('ERROR: Version numbers in package.json and io-package.json differ!!');
        }

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
        }

        expect(ioPackage.common.authors).to.exist;
        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length).to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0]).to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors).to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('Testing for set authors field in io-package skipped because template adapter');
        }
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        expect(fileContentReadme.indexOf('## License'), 'The README.md needs to have a section ## License').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## Changelog').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## License').to.be.below(fileContentReadme.indexOf('## License'));
        done();
    });
});
<|endoftext|>


<commit_before>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var _minuteInMilliseconds = 60 * 1000;
var _hourInMilliseconds = _minuteInMilliseconds * 60;

exports.getCurrentDateTime = function() {
  return new tizen.TZDate();
};

exports.getLocalTimezone = function() {
  return _sendSyncMessage('GetLocalTimeZone').value;
};

var _availableTimezonesCache = [];

exports.getAvailableTimezones = function() {
  if (_availableTimezonesCache.length)
    return _availableTimezonesCache;
  _availableTimezonesCache = _sendSyncMessage('GetAvailableTimeZones').value;
  return _availableTimezonesCache;
};

exports.getDateFormat = function(shortformat) {
  if (shortformat)
    return 'd/m/y';
  return 'D, M d y';
};

exports.getTimeFormat = function() {
  return 'h:m:s';
};

exports.isLeapYear = function(year) {
  if (!(year % 400))
    return true;
  if (!(year % 100))
    return false;
  if (!(year % 4))
    return true;
  return false;
};

function _throwProperTizenException(e) {
  if (e instanceof TypeError)
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
  else if (e instanceof RangeError)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
  else
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
}

function _sendSyncMessage(cmd, timezone, value, trans, locale) {
  var msg = {
    'cmd': cmd,
    'timezone': timezone || '',
    'value': value || '',
    'trans': trans || '',
    'locale': locale || false
  };
  return JSON.parse(extension.internal.sendSyncMessage(JSON.stringify(msg)));
}

var TimeDurationUnit = [
  'MSECS',
  'SECS',
  'MINS',
  'HOURS',
  'DAYS'
];

tizen.TimeDuration = function(length, unit) {
  // FIXME(cmarcelo): This is a best effort to ensure that this function is
  // called as a constructor only. We may need to implement some native
  // primitive to ensure that.
  if (!this || this.constructor != tizen.TimeDuration)
    throw new TypeError;

  this.length = length || 0;
  this.unit = unit || 'MSECS';

  Object.defineProperty(this, 'length', {
    get: function() {
      return length; },
    set: function(NewValue) {
      if (NewValue != null)
        length = NewValue; }});

  Object.defineProperty(this, 'unit', {
    get: function() {
      return unit; },
    set: function(NewValue) {
      if (TimeDurationUnit.indexOf(NewValue) >= 0)
        unit = NewValue; }});

  if (TimeDurationUnit.indexOf(this.unit) == -1)
    this.unit = 'MSECS';
};

function getMultiplier(unit) {
  if (unit == 'MSECS')
    return 1.0;
  if (unit == 'SECS')
    return 1.0 * 1000.0;
  if (unit == 'MINS')
    return 60.0 * 1000.0;
  if (unit == 'HOURS')
    return 3600.0 * 1000.0;
  return 86400.0 * 1000.0;
}

function makeMillisecondsDurationObject(length) {
  var dayInMsecs = _hourInMilliseconds * 24;

  if ((length % dayInMsecs) == 0)
    return new tizen.TimeDuration(length / dayInMsecs, 'DAYS');

  return new tizen.TimeDuration(length, 'MSECS');
}

tizen.TimeDuration.prototype.getMilliseconds = function() {
  return getMultiplier(this.unit) * this.length;
};

tizen.TimeDuration.prototype.difference = function(other) {
  try {
    return makeMillisecondsDurationObject(this.getMilliseconds() -
                                          other.getMilliseconds());
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.equalsTo = function(other) {
  try {
    return this.getMilliseconds() == other.getMilliseconds();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.lessThan = function(other) {
  try {
    return this.getMilliseconds() < other.getMilliseconds();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.greaterThan = function(other) {
  try {
    return this.getMilliseconds() > other.getMilliseconds();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.toString = function() {
  return this.length + ' ' + this.unit;
};

tizen.TZDate = function(year, month, day, hours, minutes, seconds, milliseconds, timezone) {
  // FIXME(cmarcelo): This is a best effort to ensure that this function is
  // called as a constructor only. We may need to implement some native
  // primitive to ensure that.
  if (!this || this.constructor != tizen.TZDate)
    throw new TypeError;

  this.date_;
  this.timezone_ = timezone || tizen.time.getLocalTimezone();

  var hours = hours || 0;
  var minutes = minutes || 0;
  var seconds = seconds || 0;
  var milliseconds = milliseconds || 0;

  if (!arguments.length)
    this.date_ = new Date();
  else if (arguments.length == 1 || arguments.length == 2) {
    if (arguments[0] instanceof Date)
      this.date_ = arguments[0];
    else
      this.date_ = new Date();
    if (arguments[1])
      this.timezone_ = arguments[1];
  }
  else
    this.date_ = new Date(year, month, day, hours, minutes, seconds, milliseconds);

  if (tizen.time.getAvailableTimezones().indexOf(this.timezone_) < 0)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
};

function getTimezoneOffset(timezone, timeInMs) {
  return _sendSyncMessage('GetTimeZoneOffset', timezone, timeInMs).value;
}

function _getTimeWithOffset(date) {
  var OffsetInMilliseconds = date.getTimezoneOffset() * _minuteInMilliseconds * -1;
  return date.getTime() + OffsetInMilliseconds;
}

tizen.TZDate.prototype.getDate = function() {
  return this.date_.getDate();
};

tizen.TZDate.prototype.setDate = function(date) {
  this.date_.setDate(date);
};

tizen.TZDate.prototype.getDay = function() {
  return this.date_.getDay();
};

tizen.TZDate.prototype.getFullYear = function() {
  return this.date_.getFullYear();
};

tizen.TZDate.prototype.setFullYear = function(year) {
  this.date_.setFullYear(year);
};

tizen.TZDate.prototype.getHours = function() {
  return this.date_.getHours();
};

tizen.TZDate.prototype.setHours = function(hours) {
  this.date_.setHours(hours);
};

tizen.TZDate.prototype.getMilliseconds = function() {
  return this.date_.getMilliseconds();
};

tizen.TZDate.prototype.setMilliseconds = function(ms) {
  this.date_.setMilliseconds(ms);
};

tizen.TZDate.prototype.getMonth = function() {
  return this.date_.getMonth();
};

tizen.TZDate.prototype.setMonth = function(month) {
  this.date_.setMonth(month);
};

tizen.TZDate.prototype.getMinutes = function() {
  return this.date_.getMinutes();
};

tizen.TZDate.prototype.setMinutes = function(minutes) {
  this.date_.setMinutes(minutes);
};

tizen.TZDate.prototype.getSeconds = function() {
  return this.date_.getSeconds();
};

tizen.TZDate.prototype.setSeconds = function(seconds) {
  this.date_.setSeconds(seconds);
};

tizen.TZDate.prototype.getUTCDate = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                          _getTimeWithOffset(this.date_)) * -1));
  return d.getDate();
};

tizen.TZDate.prototype.setUTCDate = function(date) {
  this.date_.setUTCDate(date);
};

tizen.TZDate.prototype.getUTCDay = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                         _getTimeWithOffset(this.date_)) * -1));
  return d.getDay();
};

tizen.TZDate.prototype.getUTCFullYear = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                          _getTimeWithOffset(this.date_)) * -1));
  return d.getFullYear();
};

tizen.TZDate.prototype.setUTCFullYear = function(year) {
  this.date_.setUTCFullYear(year);
};

tizen.TZDate.prototype.getUTCHours = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                           _getTimeWithOffset(this.date_)) * -1));
  return d.getHours();
};

tizen.TZDate.prototype.setUTCHours = function(hours) {
  var offset_hours = getTimezoneOffset(this.timezone_, _getTimeWithOffset(this.date_)) /
                     _hourInMilliseconds;
  this.date_.setHours(hours + offset_hours);
};

tizen.TZDate.prototype.getUTCMilliseconds = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                              _getTimeWithOffset(this.date_)) * -1));
  return d.getMilliseconds();
};

tizen.TZDate.prototype.setUTCMilliseconds = function(ms) {
  this.date_.setUTCMilliseconds(ms);
};

tizen.TZDate.prototype.getUTCMinutes = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                             _getTimeWithOffset(this.date_)) * -1));
  return d.getMinutes();
};

tizen.TZDate.prototype.setUTCMinutes = function(minutes) {
  this.date_.setUTCMinutes(minutes);
};

tizen.TZDate.prototype.getUTCMonth = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                           _getTimeWithOffset(this.date_)) * -1));
  return d.getMonth();
};

tizen.TZDate.prototype.setUTCMonth = function(month) {
  this.date_.setUTCMonth(month);
};

tizen.TZDate.prototype.getUTCSeconds = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                         _getTimeWithOffset(this.date_)) * -1));
  return d.getSeconds();
};

tizen.TZDate.prototype.setUTCSeconds = function(secs) {
  this.date_.setUTCSeconds(secs);
};

tizen.TZDate.prototype.getTime = function() {
  return this.date_.getTime();
};

tizen.TZDate.prototype.getTimezone = function() {
  return this.timezone_;
};

tizen.TZDate.prototype.toTimezone = function(timezone) {
  if (!timezone)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
  var d = new tizen.TZDate(new Date(this.date_.getTime()), timezone);
  return d.addDuration(new tizen.TimeDuration((getTimezoneOffset(timezone) * 1) +
                                              (getTimezoneOffset(this.timezone_) * -1)));
};

tizen.TZDate.prototype.toLocalTimezone = function() {
  return this.toTimezone(tizen.time.getLocalTimezone());
};

tizen.TZDate.prototype.toUTC = function() {
  return this.toTimezone('GMT');
};

tizen.TZDate.prototype.difference = function(other) {
  try {
    return makeMillisecondsDurationObject(this.getTime() - other.getTime());
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.equalsTo = function(other) {
  try {
    return this.getTime() == other.getTime();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.earlierThan = function(other) {
  try {
    return this.getTime() < other.getTime();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.laterThan = function(other) {
  try {
    return this.getTime() > other.getTime();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.addDuration = function(duration) {
  try {
    var date = new tizen.TZDate(new Date(this.date_.getTime()), this.timezone_);
    date.setMilliseconds(duration.getMilliseconds() + date.getMilliseconds());
    return date;
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.toLocaleDateString = function() {
  var result = _sendSyncMessage('ToDateString', this.timezone_,
                                this.date_.getTime(), '', true);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toLocaleTimeString = function() {
  var result = _sendSyncMessage('ToTimeString', this.timezone_,
                                this.date_.getTime(), '', true);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toLocaleString = function() {
  var result = _sendSyncMessage('ToString', this.timezone_,
                                this.date_.getTime(), '', true);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toDateString = function() {
  var result = _sendSyncMessage('ToDateString', this.timezone_,
                                this.date_.getTime(), '', false);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toTimeString = function() {
  var result = _sendSyncMessage('ToTimeString', this.timezone_,
                                this.date_.getTime(), '', false);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toString = function() {
  var result = _sendSyncMessage('ToString', this.timezone_,
                                this.date_.getTime(), '', false);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.getTimezoneAbbreviation = function() {
  var result = _sendSyncMessage('GetTimeZoneAbbreviation', this.timezone_,
                                this.date_.getTime());

  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.secondsFromUTC = function() {
  return this.date_.getTimezoneOffset() * 60;
};

tizen.TZDate.prototype.isDST = function() {
  var result = _sendSyncMessage('IsDST', this.timezone_,
                                _getTimeWithOffset(this.date_));

  if (result.error)
    return false;
  return result.value;
};

tizen.TZDate.prototype.getPreviousDSTTransition = function() {
  var OffsetInMilliseconds = this.date_.getTimezoneOffset() * _minuteInMilliseconds * -1;
  var result = _sendSyncMessage('GetDSTTransition', this.timezone_,
                                _getTimeWithOffset(this.date_), 'NEXT_TRANSITION');

  if (result.error || result.value == 0)
    return undefined;
  return new tizen.TZDate(new Date(result.value - OffsetInMilliseconds), this.timezone_);
};

tizen.TZDate.prototype.getNextDSTTransition = function() {
  var OffsetInMilliseconds = this.date_.getTimezoneOffset() * _minuteInMilliseconds * -1;
  var result = _sendSyncMessage('GetDSTTransition', this.timezone_,
                                _getTimeWithOffset(this.date_), 'PREV_TRANSITION');

  if (result.error || result.value == 0)
    return undefined;
  return new tizen.TZDate(new Date(result.value - OffsetInMilliseconds), this.timezone_);
};
<commit_msg>[Time] Change getDSTTransition return from undefined to null<commit_after>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var _minuteInMilliseconds = 60 * 1000;
var _hourInMilliseconds = _minuteInMilliseconds * 60;

exports.getCurrentDateTime = function() {
  return new tizen.TZDate();
};

exports.getLocalTimezone = function() {
  return _sendSyncMessage('GetLocalTimeZone').value;
};

var _availableTimezonesCache = [];

exports.getAvailableTimezones = function() {
  if (_availableTimezonesCache.length)
    return _availableTimezonesCache;
  _availableTimezonesCache = _sendSyncMessage('GetAvailableTimeZones').value;
  return _availableTimezonesCache;
};

exports.getDateFormat = function(shortformat) {
  if (shortformat)
    return 'd/m/y';
  return 'D, M d y';
};

exports.getTimeFormat = function() {
  return 'h:m:s';
};

exports.isLeapYear = function(year) {
  if (!(year % 400))
    return true;
  if (!(year % 100))
    return false;
  if (!(year % 4))
    return true;
  return false;
};

function _throwProperTizenException(e) {
  if (e instanceof TypeError)
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
  else if (e instanceof RangeError)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
  else
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
}

function _sendSyncMessage(cmd, timezone, value, trans, locale) {
  var msg = {
    'cmd': cmd,
    'timezone': timezone || '',
    'value': value || '',
    'trans': trans || '',
    'locale': locale || false
  };
  return JSON.parse(extension.internal.sendSyncMessage(JSON.stringify(msg)));
}

var TimeDurationUnit = [
  'MSECS',
  'SECS',
  'MINS',
  'HOURS',
  'DAYS'
];

tizen.TimeDuration = function(length, unit) {
  // FIXME(cmarcelo): This is a best effort to ensure that this function is
  // called as a constructor only. We may need to implement some native
  // primitive to ensure that.
  if (!this || this.constructor != tizen.TimeDuration)
    throw new TypeError;

  this.length = length || 0;
  this.unit = unit || 'MSECS';

  Object.defineProperty(this, 'length', {
    get: function() {
      return length; },
    set: function(NewValue) {
      if (NewValue != null)
        length = NewValue; }});

  Object.defineProperty(this, 'unit', {
    get: function() {
      return unit; },
    set: function(NewValue) {
      if (TimeDurationUnit.indexOf(NewValue) >= 0)
        unit = NewValue; }});

  if (TimeDurationUnit.indexOf(this.unit) == -1)
    this.unit = 'MSECS';
};

function getMultiplier(unit) {
  if (unit == 'MSECS')
    return 1.0;
  if (unit == 'SECS')
    return 1.0 * 1000.0;
  if (unit == 'MINS')
    return 60.0 * 1000.0;
  if (unit == 'HOURS')
    return 3600.0 * 1000.0;
  return 86400.0 * 1000.0;
}

function makeMillisecondsDurationObject(length) {
  var dayInMsecs = _hourInMilliseconds * 24;

  if ((length % dayInMsecs) == 0)
    return new tizen.TimeDuration(length / dayInMsecs, 'DAYS');

  return new tizen.TimeDuration(length, 'MSECS');
}

tizen.TimeDuration.prototype.getMilliseconds = function() {
  return getMultiplier(this.unit) * this.length;
};

tizen.TimeDuration.prototype.difference = function(other) {
  try {
    return makeMillisecondsDurationObject(this.getMilliseconds() -
                                          other.getMilliseconds());
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.equalsTo = function(other) {
  try {
    return this.getMilliseconds() == other.getMilliseconds();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.lessThan = function(other) {
  try {
    return this.getMilliseconds() < other.getMilliseconds();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.greaterThan = function(other) {
  try {
    return this.getMilliseconds() > other.getMilliseconds();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TimeDuration.prototype.toString = function() {
  return this.length + ' ' + this.unit;
};

tizen.TZDate = function(year, month, day, hours, minutes, seconds, milliseconds, timezone) {
  // FIXME(cmarcelo): This is a best effort to ensure that this function is
  // called as a constructor only. We may need to implement some native
  // primitive to ensure that.
  if (!this || this.constructor != tizen.TZDate)
    throw new TypeError;

  this.date_;
  this.timezone_ = timezone || tizen.time.getLocalTimezone();

  var hours = hours || 0;
  var minutes = minutes || 0;
  var seconds = seconds || 0;
  var milliseconds = milliseconds || 0;

  if (!arguments.length)
    this.date_ = new Date();
  else if (arguments.length == 1 || arguments.length == 2) {
    if (arguments[0] instanceof Date)
      this.date_ = arguments[0];
    else
      this.date_ = new Date();
    if (arguments[1])
      this.timezone_ = arguments[1];
  }
  else
    this.date_ = new Date(year, month, day, hours, minutes, seconds, milliseconds);

  if (tizen.time.getAvailableTimezones().indexOf(this.timezone_) < 0)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
};

function getTimezoneOffset(timezone, timeInMs) {
  return _sendSyncMessage('GetTimeZoneOffset', timezone, timeInMs).value;
}

function _getTimeWithOffset(date) {
  var OffsetInMilliseconds = date.getTimezoneOffset() * _minuteInMilliseconds * -1;
  return date.getTime() + OffsetInMilliseconds;
}

tizen.TZDate.prototype.getDate = function() {
  return this.date_.getDate();
};

tizen.TZDate.prototype.setDate = function(date) {
  this.date_.setDate(date);
};

tizen.TZDate.prototype.getDay = function() {
  return this.date_.getDay();
};

tizen.TZDate.prototype.getFullYear = function() {
  return this.date_.getFullYear();
};

tizen.TZDate.prototype.setFullYear = function(year) {
  this.date_.setFullYear(year);
};

tizen.TZDate.prototype.getHours = function() {
  return this.date_.getHours();
};

tizen.TZDate.prototype.setHours = function(hours) {
  this.date_.setHours(hours);
};

tizen.TZDate.prototype.getMilliseconds = function() {
  return this.date_.getMilliseconds();
};

tizen.TZDate.prototype.setMilliseconds = function(ms) {
  this.date_.setMilliseconds(ms);
};

tizen.TZDate.prototype.getMonth = function() {
  return this.date_.getMonth();
};

tizen.TZDate.prototype.setMonth = function(month) {
  this.date_.setMonth(month);
};

tizen.TZDate.prototype.getMinutes = function() {
  return this.date_.getMinutes();
};

tizen.TZDate.prototype.setMinutes = function(minutes) {
  this.date_.setMinutes(minutes);
};

tizen.TZDate.prototype.getSeconds = function() {
  return this.date_.getSeconds();
};

tizen.TZDate.prototype.setSeconds = function(seconds) {
  this.date_.setSeconds(seconds);
};

tizen.TZDate.prototype.getUTCDate = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                          _getTimeWithOffset(this.date_)) * -1));
  return d.getDate();
};

tizen.TZDate.prototype.setUTCDate = function(date) {
  this.date_.setUTCDate(date);
};

tizen.TZDate.prototype.getUTCDay = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                         _getTimeWithOffset(this.date_)) * -1));
  return d.getDay();
};

tizen.TZDate.prototype.getUTCFullYear = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                          _getTimeWithOffset(this.date_)) * -1));
  return d.getFullYear();
};

tizen.TZDate.prototype.setUTCFullYear = function(year) {
  this.date_.setUTCFullYear(year);
};

tizen.TZDate.prototype.getUTCHours = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                           _getTimeWithOffset(this.date_)) * -1));
  return d.getHours();
};

tizen.TZDate.prototype.setUTCHours = function(hours) {
  var offset_hours = getTimezoneOffset(this.timezone_, _getTimeWithOffset(this.date_)) /
                     _hourInMilliseconds;
  this.date_.setHours(hours + offset_hours);
};

tizen.TZDate.prototype.getUTCMilliseconds = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                              _getTimeWithOffset(this.date_)) * -1));
  return d.getMilliseconds();
};

tizen.TZDate.prototype.setUTCMilliseconds = function(ms) {
  this.date_.setUTCMilliseconds(ms);
};

tizen.TZDate.prototype.getUTCMinutes = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                             _getTimeWithOffset(this.date_)) * -1));
  return d.getMinutes();
};

tizen.TZDate.prototype.setUTCMinutes = function(minutes) {
  this.date_.setUTCMinutes(minutes);
};

tizen.TZDate.prototype.getUTCMonth = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                           _getTimeWithOffset(this.date_)) * -1));
  return d.getMonth();
};

tizen.TZDate.prototype.setUTCMonth = function(month) {
  this.date_.setUTCMonth(month);
};

tizen.TZDate.prototype.getUTCSeconds = function() {
  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
                                         _getTimeWithOffset(this.date_)) * -1));
  return d.getSeconds();
};

tizen.TZDate.prototype.setUTCSeconds = function(secs) {
  this.date_.setUTCSeconds(secs);
};

tizen.TZDate.prototype.getTime = function() {
  return this.date_.getTime();
};

tizen.TZDate.prototype.getTimezone = function() {
  return this.timezone_;
};

tizen.TZDate.prototype.toTimezone = function(timezone) {
  if (!timezone)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
  var d = new tizen.TZDate(new Date(this.date_.getTime()), timezone);
  return d.addDuration(new tizen.TimeDuration((getTimezoneOffset(timezone) * 1) +
                                              (getTimezoneOffset(this.timezone_) * -1)));
};

tizen.TZDate.prototype.toLocalTimezone = function() {
  return this.toTimezone(tizen.time.getLocalTimezone());
};

tizen.TZDate.prototype.toUTC = function() {
  return this.toTimezone('GMT');
};

tizen.TZDate.prototype.difference = function(other) {
  try {
    return makeMillisecondsDurationObject(this.getTime() - other.getTime());
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.equalsTo = function(other) {
  try {
    return this.getTime() == other.getTime();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.earlierThan = function(other) {
  try {
    return this.getTime() < other.getTime();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.laterThan = function(other) {
  try {
    return this.getTime() > other.getTime();
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.addDuration = function(duration) {
  try {
    var date = new tizen.TZDate(new Date(this.date_.getTime()), this.timezone_);
    date.setMilliseconds(duration.getMilliseconds() + date.getMilliseconds());
    return date;
  } catch (e) {
    _throwProperTizenException(e);
  }
};

tizen.TZDate.prototype.toLocaleDateString = function() {
  var result = _sendSyncMessage('ToDateString', this.timezone_,
                                this.date_.getTime(), '', true);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toLocaleTimeString = function() {
  var result = _sendSyncMessage('ToTimeString', this.timezone_,
                                this.date_.getTime(), '', true);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toLocaleString = function() {
  var result = _sendSyncMessage('ToString', this.timezone_,
                                this.date_.getTime(), '', true);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toDateString = function() {
  var result = _sendSyncMessage('ToDateString', this.timezone_,
                                this.date_.getTime(), '', false);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toTimeString = function() {
  var result = _sendSyncMessage('ToTimeString', this.timezone_,
                                this.date_.getTime(), '', false);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.toString = function() {
  var result = _sendSyncMessage('ToString', this.timezone_,
                                this.date_.getTime(), '', false);
  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.getTimezoneAbbreviation = function() {
  var result = _sendSyncMessage('GetTimeZoneAbbreviation', this.timezone_,
                                this.date_.getTime());

  if (result.error)
    return '';
  return result.value;
};

tizen.TZDate.prototype.secondsFromUTC = function() {
  return this.date_.getTimezoneOffset() * 60;
};

tizen.TZDate.prototype.isDST = function() {
  var result = _sendSyncMessage('IsDST', this.timezone_,
                                _getTimeWithOffset(this.date_));

  if (result.error)
    return false;
  return result.value;
};

tizen.TZDate.prototype.getPreviousDSTTransition = function() {
  var OffsetInMilliseconds = this.date_.getTimezoneOffset() * _minuteInMilliseconds * -1;
  var result = _sendSyncMessage('GetDSTTransition', this.timezone_,
                                _getTimeWithOffset(this.date_), 'NEXT_TRANSITION');

  if (result.error || result.value == 0)
    return null;
  return new tizen.TZDate(new Date(result.value - OffsetInMilliseconds), this.timezone_);
};

tizen.TZDate.prototype.getNextDSTTransition = function() {
  var OffsetInMilliseconds = this.date_.getTimezoneOffset() * _minuteInMilliseconds * -1;
  var result = _sendSyncMessage('GetDSTTransition', this.timezone_,
                                _getTimeWithOffset(this.date_), 'PREV_TRANSITION');

  if (result.error || result.value == 0)
    return null;
  return new tizen.TZDate(new Date(result.value - OffsetInMilliseconds), this.timezone_);
};
<|endoftext|>


<commit_before>import { connect } from 'react-redux';
import { push } from 'react-router-redux';
import { buildFullTextRegex, fullTextRegexFilter } from '../Search/FullTextSearch';
import actions from './actions';
import ContainersList from '../Presentational/ContainersList/ContainersList';

function flatValues(o) {
  return [].concat(...Object.values(o)
    .filter(e => typeof e !== 'function')
    .map((e) => {
      if (typeof e === 'object') {
        return flatValues(e);
      }
      return e;
    }));
}

const mapStateToProps = (state) => {
  const regexFilter = buildFullTextRegex(state.filter);

  return {
    pending: !!state.pending[actions.FETCH_CONTAINERS],
    pendingInfo: !!state.pending[actions.INFO],
    containers: state.containers
      ? state.containers.filter(e => fullTextRegexFilter(flatValues(e).join(' '), regexFilter))
      : state.containers,
    filter: state.filter,
    error: state.error,
  };
};

const mapDispatchToProps = dispatch => ({
  onRefresh: () => dispatch(actions.info()),
  onAdd: () => dispatch(push('/containers/New')),
  onSelect: id => dispatch(push(`/containers/${id}`)),
  onLogout: () => dispatch(actions.logout()),
  onFilterChange: value => dispatch(actions.changeFilter(value)),
});

const ContainersListContainer = connect(mapStateToProps, mapDispatchToProps)(ContainersList);

/**
 * Container for handling list view.
 */
export default ContainersListContainer;
<commit_msg>Update ContainersListContainer.js<commit_after>import { connect } from 'react-redux';
import { push } from 'react-router-redux';
import { buildFullTextRegex, fullTextRegexFilter } from '../Search/FullTextSearch';
import actions from './actions';
import ContainersList from '../Presentational/ContainersList/ContainersList';

function flatValues(o) {
  return [].concat(...Object.values(o)
    .filter(e => typeof e !== 'function')
    .map((e) => {
      if (typeof e === 'object') {
        return flatValues(e);
      }
      return e;
    }));
}

const mapStateToProps = (state) => {
  const regexFilter = buildFullTextRegex(state.filter);

  // eslint-disable no-console
  return {
    pending: !!state.pending[actions.FETCH_CONTAINERS],
    pendingInfo: !!state.pending[actions.INFO],
    containers: state.containers
      ? state.containers.filter(e => console.log(e) || fullTextRegexFilter(flatValues(e).join(' '), regexFilter))
      : state.containers,
    filter: state.filter,
    error: state.error,
  };
};

const mapDispatchToProps = dispatch => ({
  onRefresh: () => dispatch(actions.info()),
  onAdd: () => dispatch(push('/containers/New')),
  onSelect: id => dispatch(push(`/containers/${id}`)),
  onLogout: () => dispatch(actions.logout()),
  onFilterChange: value => dispatch(actions.changeFilter(value)),
});

const ContainersListContainer = connect(mapStateToProps, mapDispatchToProps)(ContainersList);

/**
 * Container for handling list view.
 */
export default ContainersListContainer;
<|endoftext|>