<commit_before>angular.module('report', ['shared', 'ui.bootstrap']);

angular.module('report')
    .controller('reportController', [
        '$scope', '$http', 'reportViewModel', '$filter', function ($scope, $http, viewModel, $filter) {

            $scope.init = function () {
                viewModel.Report.Parameters.forEach(function (param) {
                    //periods of type custom comes on the format Enum:from_to
                    if (param.InputType === 3) { //period
                        if (param.Value && ~param.Value.indexOf(':')) {
                            var temp = param.Value.split(':');
                            var enumValue = temp[0];

                            if (temp.length > 1) {
                                var values = temp[1].split('_');
                                param.from = values[0];
                                param.to = values[1];
                            }

                            param.EnumValue = enumValue;
                        } else {
                            param.EnumValue = param.Value;
                        }
                    }
                });

                $scope.viewModel = viewModel;

                $scope.triggerOnScreen = triggerOnScreen;
                $scope.periodChanged = periodChanged;
            };
            $scope.init();

            function periodChanged(parameter) {
                //9999 is custom..
                if (parameter.EnumValue === '9999') {
                    if (!parameter.from)
                        parameter.from = new Date();
                    if (!parameter.to)
                        parameter.to = new Date();

                    parameter.Value = parameter.EnumValue + ':' + parameter.from + '_' + parameter.to;

                    var text = parameter.Choices['9999'].split(':')[0];
                    if (parameter.from && parameter.to) {
                        var format = 'yyyy-MM-dd';
                        var from = $filter('date')(parameter.from, format);
                        var to = $filter('date')(parameter.from, format);
                        text += ': ' + from + ' - ' + to;
                    }
                    parameter.Choices['9999'] = text;
                } else
                    parameter.Value = parameter.EnumValue;
            }

            function triggerOnScreen() {
                if ($scope.selectedAction !== 'onScreen')
                    $scope.selectedAction = 'onScreen';
                else
                    $scope.$broadcast('refreshOnScreen');
            }
        }
    ]);<commit_msg>copy paste is nice<commit_after>angular.module('report', ['shared', 'ui.bootstrap']);

angular.module('report')
    .controller('reportController', [
        '$scope', '$http', 'reportViewModel', '$filter', function ($scope, $http, viewModel, $filter) {

            $scope.init = function () {
                viewModel.Report.Parameters.forEach(function (param) {
                    //periods of type custom comes on the format Enum:from_to
                    if (param.InputType === 3) { //period
                        if (param.Value && ~param.Value.indexOf(':')) {
                            var temp = param.Value.split(':');
                            var enumValue = temp[0];

                            if (temp.length > 1) {
                                var values = temp[1].split('_');
                                param.from = values[0];
                                param.to = values[1];
                            }

                            param.EnumValue = enumValue;
                        } else {
                            param.EnumValue = param.Value;
                        }
                    }
                });

                $scope.viewModel = viewModel;

                $scope.triggerOnScreen = triggerOnScreen;
                $scope.periodChanged = periodChanged;
            };
            $scope.init();

            function periodChanged(parameter) {
                //9999 is custom..
                if (parameter.EnumValue === '9999') {
                    if (!parameter.from)
                        parameter.from = new Date();
                    if (!parameter.to)
                        parameter.to = new Date();

                    parameter.Value = parameter.EnumValue + ':' + parameter.from + '_' + parameter.to;

                    var text = parameter.Choices['9999'].split(':')[0];
                    if (parameter.from && parameter.to) {
                        var format = 'yyyy-MM-dd';
                        var from = $filter('date')(parameter.from, format);
                        var to = $filter('date')(parameter.to, format);
                        text += ': ' + from + ' - ' + to;
                    }
                    parameter.Choices['9999'] = text;
                } else
                    parameter.Value = parameter.EnumValue;
            }

            function triggerOnScreen() {
                if ($scope.selectedAction !== 'onScreen')
                    $scope.selectedAction = 'onScreen';
                else
                    $scope.$broadcast('refreshOnScreen');
            }
        }
    ]);<|endoftext|>


<commit_before>const Member = ({
  avatar,
  name,
  email,
  secondLine
}) => `

  ${name}

Email: ${email}

      ${secondLine}

  grade

`;

$('.members ul').html([{
    avatar: 'lukas_hanzlik',
    name: 'Prezident - Lukáš Hanzlík',
    email: 'prezident@vkhcr.org, lukas.hanzlik@vkhcr.org',
    secondLine: 'Telefon: +420 721 270 518'
  },
  {
    avatar: 'unknown',
    name: 'Zástupce prezidenta, propagace - Tomáš Putna',
    email: 'tomas.putna@vkhcr.org, propagace@vkhcr.org',
    secondLine: ' '
  },
  {
    avatar: 'unknown',
    name: 'Finance - Adéla Štukavcová',
    email: 'finance@vrhcr.org',
    secondLine: ' '
  },
  {
    avatar: 'unknown',
    name: 'Fundraising, Foreign affairs - Monika Schottková',
    email: 'fundraising@vkhcr.org, foreignaffairs@vkhcr.org',
    secondLine: ' '
  }
].map(Member).join(''));
<commit_msg>remove "star" from member's item<commit_after>const Member = ({
  avatar,
  name,
  email,
  secondLine
}) => `

  ${name}

Email: ${email}

      ${secondLine}

`;

$('.members ul').html([{
    avatar: 'lukas_hanzlik',
    name: 'Prezident - Lukáš Hanzlík',
    email: 'prezident@vkhcr.org, lukas.hanzlik@vkhcr.org',
    secondLine: 'Telefon: +420 721 270 518'
  },
  {
    avatar: 'unknown',
    name: 'Zástupce prezidenta, propagace - Tomáš Putna',
    email: 'tomas.putna@vkhcr.org, propagace@vkhcr.org',
    secondLine: ' '
  },
  {
    avatar: 'unknown',
    name: 'Finance - Adéla Štukavcová',
    email: 'finance@vrhcr.org',
    secondLine: ' '
  },
  {
    avatar: 'unknown',
    name: 'Fundraising, Foreign affairs - Monika Schottková',
    email: 'fundraising@vkhcr.org, foreignaffairs@vkhcr.org',
    secondLine: ' '
  }
].map(Member).join(''));
<|endoftext|>


<commit_before>casper.test.begin('The fixedLogin exists', function suite(test) {
  var x = require('casper').selectXPath;
  var rand = Math.random(100000);
  var posterInput = "from gene" + rand;
  casper.start("https://chatterbackbone.herokuapp.com/", function() {
      test.assertExists('a.fixedLogin', "fixedLogin anchor is found");
      this.clickLabel('Pre-assigned username/password Login');
  });

  casper.then(function() {
    casper.waitForText('Share', function () {
      test.assertExists('a.postersharebutton', "poster share button is found");
    });
  });

  casper.then(function() {
    test.assertEval(function() {
        return document.querySelector("#feed-items-collection-placeholder").children.length > 2;
      });
  });
  casper.waitForSelector("textarea",
      function success() {
          this.test.assertExists("textarea");
          this.click("textarea");
      },
      function fail() {
          this.test.assertExists("textarea");
  });
  casper.waitForSelector("textarea",
      function success() {
          this.sendKeys("textarea", posterInput);
      },
      function fail() {
          this.test.assertExists("textarea");
  });
  casper.waitForSelector("a.postersharebutton",
      function success() {
          this.test.assertExists("a.postersharebutton");
          this.click("a.postersharebutton");
      },
      function fail() {
          this.test.assertExists(".postersharebutton.ui-btn.ui-shadow.ui-btn-corner-all.ui-mini.ui-btn-inline.ui-btn-hover-c.ui-btn-up-c .ui-btn-text");
  });
  casper.waitForText(posterInput,
    function success() {
 //     this.test.assertEval(function(posterInput) { return document.querySelector(".feeditembody span").textContent.indexOf(posterInput) > 0;}, posterInput);
 //   var evalResult = casper.evaluate(function(posterInput) { return document.querySelector(".feeditembody span").textContent.indexOf(posterInput) > 0;}, posterInput);
    this.test.assertTruthy(casper.evaluate(function(posterInput) { return document.querySelector(".feeditembody span").textContent.indexOf(posterInput) > 0;}, posterInput));
    },
    function fail() {
        this.test.assertExists("textarea");
  });

  casper.waitForSelector(x("//a[normalize-space(text())='Like']"),
      function success() {
          this.test.assertExists(x("//a[normalize-space(text())='Like']"));
          this.click(x("//a[normalize-space(text())='Like']"));
      },
      function fail() {
          this.test.assertExists(x("//a[normalize-space(text())='Like']"));
  });

    casper.run( function() {
      test.done();
    });
});
<commit_msg>Fixed jasmine-phantom problem.  Works great now<commit_after>casper.test.begin('The fixedLogin exists', function suite(test) {
  var x = require('casper').selectXPath;
  var rand = Math.random(100000);
  var posterInput = "from gene" + rand;
  casper.start("https://chatterbackbone.herokuapp.com/", function() {
      test.assertExists('a.fixedLogin', "fixedLogin anchor is found");
      this.clickLabel('Pre-assigned username/password Login');
  });

  casper.then(function() {
    casper.waitForText('Share', function () {
      test.assertExists('a.postersharebutton', "poster share button is found");
    });
  });

  casper.then(function() {
    test.assertEval(function() {
        return document.querySelector("#feed-items-collection-placeholder").children.length > 2;
      });
  });
  casper.waitForSelector("textarea",
      function success() {
          this.test.assertExists("textarea");
          this.click("textarea");
      },
      function fail() {
          this.test.assertExists("textarea");
  });
  casper.waitForSelector("textarea",
      function success() {
          this.sendKeys("textarea", posterInput);
      },
      function fail() {
          this.test.assertExists("textarea");
  });
  casper.waitForSelector("a.postersharebutton",
      function success() {
          this.test.assertExists("a.postersharebutton");
          this.click("a.postersharebutton");
      },
      function fail() {
          this.test.assertExists(".postersharebutton.ui-btn.ui-shadow.ui-btn-corner-all.ui-mini.ui-btn-inline.ui-btn-hover-c.ui-btn-up-c .ui-btn-text");
  });
  casper.waitForText(posterInput,
    function success() {
      this.test.assertTruthy(casper.evaluate(function(posterInput) { return document.querySelector(".feeditembody span").textContent.indexOf(posterInput) > 0;}, posterInput));
    },
    function fail() {
        this.test.assertExists("textarea");
  });

  casper.waitForSelector(x("//a[normalize-space(text())='Like']"),
      function success() {
          this.test.assertExists(x("//a[normalize-space(text())='Like']"));
          this.click(x("//a[normalize-space(text())='Like']"));
      },
      function fail() {
          this.test.assertExists(x("//a[normalize-space(text())='Like']"));
  });

    casper.run( function() {
      test.done();
    });
});
<|endoftext|>


<commit_before>// This text is a template of translation list.

// pre: ll_CC, locale name, examples: en_US, zh_CN
// 1. Copy and rename to ll_CC.js, translate these words.
// 2. in js/init.js:
//    Add '.translations('ll_CC', translations.ll_CC)' before '.determinePreferredLanguage();'
// 3. in index.html
//    Add '<script src="js/translate/ll_CC.js"></script>' after '<script src="js/libs/angular-translate.js"></script>'
// 4. To add Language to changeLanguage button, see "{{ 'Language' | translate }}" in index.html.
//    flag-icon usage:
//    https://github.com/lipis/flag-icon-css
// 5. Browser determining preferred language automatically.
//    http://angular-translate.github.io/docs/en/#/guide/07_multi-language

if(typeof translations == 'undefined'){
    translations = {};
}

translations.es_ES = {  // replace en_US to ll_CC, examples: zh_CN, de_AT.
// header
    'Search': 'Buscar',
    // Nav menu
    'Add': 'Añadir',
    'By URIs': 'URIs',
    'By Torrents': 'Torrents',
    'By Metalinks': 'Metalinks',
    'Manage': 'Administrar',
    'Pause All': 'Pausar Todos',
    'Resume Paused': 'Reanudar Pausados',
    'Purge Completed': 'Purgar Completados',
    'Settings': 'Ajustes',
    'Connection Settings': 'Ajustes de Conexión',
    'Global Settings': 'Ajustes Globales',
    'Server info': 'Info de Servidor',
    'About and contribute': 'Acerca y Colaborar',
    'Toggle navigation': 'Conmutar Navegación',
// body
// nav side bar
    'Miscellaneous': 'Otros',
    'Global Statistics': 'Estadísticas Globales',
    'About': 'Acerca de',
    'Displaying': 'Mostrando',
    'of': 'de',
    'downloads': 'descargas',
    'Language': 'Idioma',
// download filters
    'Download Filters': 'Filtros de Descargas',
    'Running': '',
    'Active': 'Activo',
    'Waiting': 'Esperando',
    'Complete': 'Completo',
    'Error': 'Error',
    'Paused': 'En Pausa',
    'Removed': 'Eliminado',
    'Hide linked meta-data': 'Ocultar metadatos adjuntos',
    'Displaying': 'Mostrando',
    'of': 'de',
    'downloads': 'descargas',
    'Toggle': 'Conmutar',
    'Reset filters': 'Restablecer Filtros',
// starred properties
    'Quick Access Settings': 'Ajustes Rápidos',
    'Save settings': 'Salvar Ajustes',
    'Currently no download in line to display, use the': 'En el momento no hay descargas para mostrar. ¡Use la opción',
    'download button to start downloading files!': 'para empezar a descargar sus archivos!',
    'Peers': 'Pares',
    'More Info': 'Mas Info',
    'Remove': 'Eliminar',
    '# of': '# de',
    'Length': 'Longitud',
// modals
    'Add Downloads By URIs': 'Añadir descargas por URIs',
    '- You can add multiple downloads (files) at the same time by putting URIs for each file on a separate line.':
        'Añada varias descargas colocando la URI de cada descarga en una línea separada.',
    '- You can also add multiple URIs (mirrors) for the *same* file. To do this, separate the URIs by a space.':
        'Puede añadir URIs de espejo para *el mismo* archivo. Separe cada URI con un espacio.',
    '- A URI can be HTTP(S)/FTP/BitTorrent-Magnet.': 'Una URI puede ser HTTP(S), FTP, BitTorrent o Magnet.',
    'E.g. to add 2 files (downloads) f1.jpg and f2.mp4 with 2 URIs (mirrors) each, add URIs as follows':
        'Ej: Para añadir dos descargas f1.jpg y f2.mp4 con dos URIs espejo cada una, añada las URIs así',
    'Download settings': 'Ajustes de Descargas',
    'Advanced settings': 'Ajustes Avanzados',
    'Cancel': 'Cancelar',
    'Start': 'Iniciar',
    'Choose': 'Escoja',
    'Quick Access (shown on the main page)': 'Acceso Rápido (Se muestra en la pág principal)',
// add torrent modal
    'Add Downloads By Torrents': 'Añadir descargas Torrent',
    '- Select the torrent from the local filesystem to start the download.': 'Seleccione el archivo Torrent de su equipo para iniciar la descarga',
    '- You can select multiple torrents to start multiple downloads.': 'Puede seleccionar varios torrents',
    '- To add a BitTorrent-Magnet URL, use the Add By URI option and add it there.': 'Para los enlaces Magnet, salga de este cuadro y use la opción Añadir \ URI',
    'Select Torrents': 'Escoja los Torrents',
    'Select a Torrent': 'Escoja el Torrent',
// add metalink modal
    'Add Downloads By Metalinks': 'Añadir descargas Metalink',
    'Select Metalinks': 'Seleccione el Metalink',
    '- Select the Metalink from the local filesystem to start the download.': 'Escoja el Metalink de su computador para iniciar la descarga',
    '- You can select multiple Metalinks to start multiple downloads.': 'Puede escoger varios Metalink',
    'Select a Metalink': 'Escoja el Metalink',
// select file modal
    'Choose files to start download for': 'Escoja los archivos que desea descargar',
    'Select to download': 'Escoja que descargar',
// settings modal
    'Aria2 RPC host and port': 'Servidor Aria2 y puerto',
    'Enter the host': 'Escriba la dirección',
    'Enter the IP or DNS name of the server on which the RPC for Aria2 is running (default: localhost)':
        'Escriba la dirección o nombre DNS del servidor Aria2 (por defecto: localhost)',
    'Enter the port': 'Escriba el puerto',
    'Enter the port of the server on which the RPC for Aria2 is running (default: 6800)':
        'Escriba el número del puerto del servidor Aria2 (por defecto: 6800)',
    'Enter the RPC path': 'Escriba la ruta RPC',
    'Enter the path for the Aria2 RPC endpoint (default: /jsonrpc)': 'Escriba la ruta de acceso RPC de Aria2 (por defecto: /jsonrpc)',
    'SSL/TLS encryption': 'Cifrado SSL/TLS',
    'Enable SSL/TLS encryption': 'Habilitar Cifrado SSL/TLS',
    'Enter the secret token (optional)': 'Escriba la frase Token',
    'Enter the Aria2 RPC secret token (leave empty if authentication is not enabled)':
        'Escriba la frase Token secreta (vacío si la autenticación está deshabilitada)',
    'Enter the username (optional)': 'Usuario (opcional)',
    'Enter the Aria2 RPC username (empty if authentication not enabled)':
        'Escriba el nombre de usuario (vacío si la autenticación está deshabilitada)',
    'Enter the password (optional)': 'Escriba la contraseña',
    'Enter the Aria2 RPC password (empty if authentication not enabled)': 'Escriba la contraseña RPC (vacío si la autenticación está deshabilitada)',
    'Enter base URL (optional)': 'Escriba la URL base (opcional)',
    'Direct Download': 'Descarga Directa',
    'If supplied, links will be created to enable direct download from the Aria2 server.':
        '',
    '(Requires appropriate webserver to be configured.)': '',
    'Save Connection configuration': '',
// server info modal
    'Aria2 server info': '',
    'Aria2 Version': '',
    'Features Enabled': '',
// about modal
    'To download the latest version of the project, add issues or to contribute back, head on to':
        '',
    'Or you can open the latest version in the browser through': '',
    'Close': '',
// lables
    'Download status':'',
    'Download Speed':'',
    'Upload Speed':'',
    'Estimated time':'',
    'Download Size':'',
    'Downloaded':'',
    'Progress':'',
    'Download Path':'',
    'Uploaded':'',
    'Download GID':'',
    'Number of Pieces':'',
    'Piece Length':''
};
<commit_msg>Done :)<commit_after>// This text is a template of translation list.

// pre: ll_CC, locale name, examples: en_US, zh_CN
// 1. Copy and rename to ll_CC.js, translate these words.
// 2. in js/init.js:
//    Add '.translations('ll_CC', translations.ll_CC)' before '.determinePreferredLanguage();'
// 3. in index.html
//    Add '<script src="js/translate/ll_CC.js"></script>' after '<script src="js/libs/angular-translate.js"></script>'
// 4. To add Language to changeLanguage button, see "{{ 'Language' | translate }}" in index.html.
//    flag-icon usage:
//    https://github.com/lipis/flag-icon-css
// 5. Browser determining preferred language automatically.
//    http://angular-translate.github.io/docs/en/#/guide/07_multi-language

if(typeof translations == 'undefined'){
    translations = {};
}

translations.es_ES = {  // replace en_US to ll_CC, examples: zh_CN, de_AT.
// header
    'Search': 'Buscar',
    // Nav menu
    'Add': 'Añadir',
    'By URIs': 'URIs',
    'By Torrents': 'Torrents',
    'By Metalinks': 'Metalinks',
    'Manage': 'Administrar',
    'Pause All': 'Pausar Todos',
    'Resume Paused': 'Reanudar Pausados',
    'Purge Completed': 'Purgar Completados',
    'Settings': 'Ajustes',
    'Connection Settings': 'Ajustes de Conexión',
    'Global Settings': 'Ajustes Globales',
    'Server info': 'Info de Servidor',
    'About and contribute': 'Acerca y Colaborar',
    'Toggle navigation': 'Conmutar Navegación',
// body
// nav side bar
    'Miscellaneous': 'Otros',
    'Global Statistics': 'Estadísticas Globales',
    'About': 'Acerca de',
    'Displaying': 'Mostrando',
    'of': 'de',
    'downloads': 'descargas',
    'Language': 'Idioma',
// download filters
    'Download Filters': 'Filtros de Descargas',
    'Running': '',
    'Active': 'Activo',
    'Waiting': 'Esperando',
    'Complete': 'Completo',
    'Error': 'Error',
    'Paused': 'En Pausa',
    'Removed': 'Eliminado',
    'Hide linked meta-data': 'Ocultar metadatos adjuntos',
    'Displaying': 'Mostrando',
    'of': 'de',
    'downloads': 'descargas',
    'Toggle': 'Conmutar',
    'Reset filters': 'Restablecer Filtros',
// starred properties
    'Quick Access Settings': 'Ajustes Rápidos',
    'Save settings': 'Salvar Ajustes',
    'Currently no download in line to display, use the': 'En el momento no hay descargas para mostrar. ¡Use la opción',
    'download button to start downloading files!': 'para empezar a descargar sus archivos!',
    'Peers': 'Pares',
    'More Info': 'Mas Info',
    'Remove': 'Eliminar',
    '# of': '# de',
    'Length': 'Longitud',
// modals
    'Add Downloads By URIs': 'Añadir descargas por URIs',
    '- You can add multiple downloads (files) at the same time by putting URIs for each file on a separate line.':
        'Añada varias descargas colocando la URI de cada descarga en una línea separada.',
    '- You can also add multiple URIs (mirrors) for the *same* file. To do this, separate the URIs by a space.':
        'Puede añadir URIs de espejo para *el mismo* archivo. Separe cada URI con un espacio.',
    '- A URI can be HTTP(S)/FTP/BitTorrent-Magnet.': 'Una URI puede ser HTTP(S), FTP, BitTorrent o Magnet.',
    'E.g. to add 2 files (downloads) f1.jpg and f2.mp4 with 2 URIs (mirrors) each, add URIs as follows':
        'Ej: Para añadir dos descargas f1.jpg y f2.mp4 con dos URIs espejo cada una, añada las URIs así',
    'Download settings': 'Ajustes de Descargas',
    'Advanced settings': 'Ajustes Avanzados',
    'Cancel': 'Cancelar',
    'Start': 'Iniciar',
    'Choose': 'Escoja',
    'Quick Access (shown on the main page)': 'Acceso Rápido (Se muestra en la pág principal)',
// add torrent modal
    'Add Downloads By Torrents': 'Añadir descargas Torrent',
    '- Select the torrent from the local filesystem to start the download.': 'Seleccione el archivo Torrent de su equipo para iniciar la descarga',
    '- You can select multiple torrents to start multiple downloads.': 'Puede seleccionar varios torrents',
    '- To add a BitTorrent-Magnet URL, use the Add By URI option and add it there.': 'Para los enlaces Magnet, salga de este cuadro y use la opción Añadir \ URI',
    'Select Torrents': 'Escoja los Torrents',
    'Select a Torrent': 'Escoja el Torrent',
// add metalink modal
    'Add Downloads By Metalinks': 'Añadir descargas Metalink',
    'Select Metalinks': 'Seleccione el Metalink',
    '- Select the Metalink from the local filesystem to start the download.': 'Escoja el Metalink de su computador para iniciar la descarga',
    '- You can select multiple Metalinks to start multiple downloads.': 'Puede escoger varios Metalink',
    'Select a Metalink': 'Escoja el Metalink',
// select file modal
    'Choose files to start download for': 'Escoja los archivos que desea descargar',
    'Select to download': 'Escoja que descargar',
// settings modal
    'Aria2 RPC host and port': 'Servidor Aria2 y puerto',
    'Enter the host': 'Escriba la dirección',
    'Enter the IP or DNS name of the server on which the RPC for Aria2 is running (default: localhost)':
        'Escriba la dirección o nombre DNS del servidor Aria2 (por defecto: localhost)',
    'Enter the port': 'Escriba el puerto',
    'Enter the port of the server on which the RPC for Aria2 is running (default: 6800)':
        'Escriba el número del puerto del servidor Aria2 (por defecto: 6800)',
    'Enter the RPC path': 'Escriba la ruta RPC',
    'Enter the path for the Aria2 RPC endpoint (default: /jsonrpc)': 'Escriba la ruta de acceso RPC de Aria2 (por defecto: /jsonrpc)',
    'SSL/TLS encryption': 'Cifrado SSL/TLS',
    'Enable SSL/TLS encryption': 'Habilitar Cifrado SSL/TLS',
    'Enter the secret token (optional)': 'Escriba la frase Token',
    'Enter the Aria2 RPC secret token (leave empty if authentication is not enabled)':
        'Escriba la frase Token secreta (vacío si la autenticación está deshabilitada)',
    'Enter the username (optional)': 'Usuario (opcional)',
    'Enter the Aria2 RPC username (empty if authentication not enabled)':
        'Escriba el nombre de usuario (vacío si la autenticación está deshabilitada)',
    'Enter the password (optional)': 'Escriba la contraseña',
    'Enter the Aria2 RPC password (empty if authentication not enabled)': 'Escriba la contraseña RPC (vacío si la autenticación está deshabilitada)',
    'Enter base URL (optional)': 'Escriba la URL base (opcional)',
    'Direct Download': 'Descarga Directa',
    'If supplied, links will be created to enable direct download from the Aria2 server.':
        'Esto permite crear enlaces de descarga de los archivos desde el servidor Aria2',
    '(Requires appropriate webserver to be configured.)': '(Requiere configuración apropiada del servidor web)',
    'Save Connection configuration': 'Guardar Configuración',
// server info modal
    'Aria2 server info': 'Información de servidor Aria2',
    'Aria2 Version': 'Versión de Aria2',
    'Features Enabled': 'Funcionalidad disponible',
// about modal
    'To download the latest version of the project, add issues or to contribute back, head on to':
        'Para obtener la última versión del proyecto, reportar problemas o colaborar, vaya a',
    'Or you can open the latest version in the browser through': 'Puede abrir la última versión en su navegador, directamente',
    'Close': 'Cerrar',
// lables
    'Download status':'Estado de descarga',
    'Download Speed':'Velocidad',
    'Upload Speed':'Vel. Subida',
    'Estimated time':'Tiempo estimado',
    'Download Size':'Tamaño',
    'Downloaded':'Descargado',
    'Progress':'Progreso',
    'Download Path':'Ruta de descarga',
    'Uploaded':'Subido',
    'Download GID':'GID de Descarga',
    'Number of Pieces':'N° de Piezas',
    'Piece Length':'Tamaño de pieza'
};
<|endoftext|>


<commit_before>var App = {
    model: {},
    collection: {},
    view: {},
};

/**
 * Pref model
 * Stored in localStorage
 */
App.model.Prefs = Backbone.Model.extend({
    defaults: {
        only_me: false
    },

    sync: function(method, model, options) {
        if (method == 'create' || method == 'update') {
            localStorage.setItem('prefs', JSON.stringify(model.toJSON()));
        } else if (method == 'read') {
            var prefs = localStorage.getItem('prefs');
            if (prefs) {
                try {
                    prefs = JSON.parse(prefs);
                } catch(e) {}
                options.success(prefs);
            }
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Current User model
 */
App.model.CurrentUser = Backbone.Model.extend({
    sync: function(method, model, options) {
        if (method == 'read') {
            return Trello.get('/members/me', {}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Card model
 */
App.model.Card = Backbone.Model.extend({
    sync: function(method, model, options) {
        if (method == 'update') {
            // only support update due date
            return Trello.put('/cards/'+ model.id, {due: model.get('badges').due}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Cards collection
 */
App.collection.Cards = Backbone.Collection.extend({
    model: App.model.Card,

    initialize: function(models, options) {
        this.options = options;
    },

    sync: function(method, model, options) {
        if (method == 'read') {
            return Trello.get('/boards/'+ this.options.board.id +'/cards/all', {badges: true}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Board model
 */
App.model.Board = Backbone.Model.extend({
    defaults: {
        hidden: false
    },

    initialize: function() {
        this._initFromLocalStorage();
        this.bind('change:hidden', this._saveStateToLocalStorage, this);
        this._cards = new App.collection.Cards([], {board: this});
    },

    cards: function() {
        return this._cards;
    },

    _initFromLocalStorage: function() {
        var value = this._getValue("false");
        if (value === "true" || value === "false") {
            this.set({hidden: (value === "true")});
        }
    },

    _saveStateToLocalStorage: function() {
        if (!window.localStorage) return;
        var key = 'board-state-'+ this.id +"-hidden";
        var value = window.localStorage.setItem(key, this.get('hidden'));
    },

    _getValue: function(defaultValue) {
        if (!window.localStorage) return defaultValue;
        var key = 'board-state-'+ this.id +"-hidden";
        var value = window.localStorage.getItem(key);
        if (value === null)
            return defaultValue;
        return value;
    }
});

/**
 * Board collection
 */
App.collection.Boards = Backbone.Collection.extend({
    model: App.model.Board,

    sync: function(method, model, options) {
        if (method == 'read') {
            return Trello.get('/members/my/boards', {filter: 'open'}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Render a card on fullcalendar
 */
App.view.Card = Backbone.View.extend({
    initialize: function() {
        this.model.bind('change', this.render, this);
    },

    render: function() {
        if (this.model.get('hidden')) {
            $(this.el).fullCalendar('removeEvents', this.model.id);
        } else {
            $(this.el).fullCalendar('removeEvents', this.model.id);
            var color = "#"+this.model.get('idBoard').substr(0, 6);
            $(this.el).fullCalendar('renderEvent', {
                backboneModel: this.model,
                id: this.model.id,
                allDay: false,
                title: this.model.get('name'),
                start: this.model.get('badges').due,
                color: color,
                url: this.model.get('url')
            }, true);
        }
        return this;
    },

    remove: function() {
        $(this.el).fullCalendar('removeEvents', this.model.id);
    }
});

/**
 * Render cards of one board
 */
App.view.CardsBoard = Backbone.View.extend({
    initialize: function() {
        this.views = [];
        this.model.cards().bind('reset', this.render, this);
    },

    render: function() {
        // remove previously events
        _(this.views).each(function(view) {
            view.remove();
        });
        this.views = this.model.cards().chain().map(_.bind(function(card) {
            // no arm, no chocolate
            if (!card.get('badges').due) return;
            return new App.view.Card({model: card,
                                      el: this.el}).render();
        }, this)).filter(function(view) {
            return view;
        }).value();
        return this;
    }
});

/**
 * Render all cards from all boards
 */
App.view.Cards = Backbone.View.extend({
    initialize: function() {
        this.collection.bind('reset', this.render, this);
    },

    render: function() {
        this.collection.each(_.bind(function(board) {
            new App.view.CardsBoard({model: board,
                                     el: this.el}).render();
        }, this));
        return this;
    }

});

App.view.Filter = Backbone.View.extend({
    events: {
        "click input": "click"
    },

    tagName: 'label',

    click: function(e) {
        var only_me = false;
        if ($(e.target).is(':checked')) {
            only_me = true;
        }
        this.model.set({only_me: only_me});
        this.model.save();
        $(this.el).toggleClass('checked');
    },

    render: function() {
        var input = this.make('input', {type: 'checkbox',
                                        value: "onlyme",
                                        checked: this.model.get('only_me')});
        $(this.el).text("Show only cards assigned to me")
                  .addClass((this.model.get('only_me') ? 'checked': ''))
                  .append(input);
        return this;
    }
});

/**
 * Render a board filter
 */
App.view.Board = Backbone.View.extend({
    events: {
        "click input": "click"
    },

    tagName: 'label',

    click: function(e) {
        var hidden = true;
        if ($(e.target).is(':checked')) {
            hidden = false;
        }
        this.model.set({hidden: hidden});
        $(this.el).toggleClass('checked');
    },

    render: function() {
        var input = this.make('input', {type: 'checkbox',
                                        value: this.model.id,
                                        checked: !this.model.get('hidden')});
        var color = "#"+this.model.id.substr(0, 6);
        $(this.el).css({'background-color': color})
                  .attr('title', 'Show cards from the board '+  this.model.get('name'))
                  .text(this.model.get('name'))
                  .append(input);
        if (!this.model.get('hidden') === true)
            $(this.el).addClass('checked');
        return this;
    }
});

/**
 * List of boards filters
 */
App.view.Boards = Backbone.View.extend({
    initialize: function() {
        this.collection.bind('reset', this.render, this);
    },

    render: function() {
        this.collection.each(_.bind(function(board) {
            var view = new App.view.Board({model: board}).render();
            $(view.el).appendTo(this.el);
        }, this));
    }
});

/**
 * Main view
 */
App.view.Calendar = Backbone.View.extend({
    initialize: function() {
        this.boards = new App.collection.Boards();
        this.currentUser = new App.model.CurrentUser();

        this.prefs = new App.model.Prefs();
        this.prefs.fetch();
        this.prefs.bind('change', this._updateBoardsVisibility, this);

        this.currentUser.fetch().done(_.bind(function() {
            this.boards.fetch();
        }, this));

        this.boards.bind('reset', this._getCards, this);
        this.boards.bind('change:hidden', this._updateBoardVisibility, this);
    },

    render: function() {
        this._createCalendar();
        new App.view.Boards({collection: this.boards,
                             el: this.$('#boards').get(0)}).render();
        new App.view.Cards({collection: this.boards,
                            el: this.$('#calendar').get(0)}).render();
        var filter = new App.view.Filter({model: this.prefs}).render();
        this.$('#prefs').append(filter.el);
        return this;
    },

    _updateBoardsVisibility: function() {
        this.boards.each(_.bind(function(board) {
            this._updateBoardVisibility(board);
        }, this));
    },

    _updateBoardVisibility: function(board) {
        board.cards().each(_.bind(function(card) {
            var hidden = board.get('hidden');
            if (!hidden && this.prefs.get('only_me') && !_(card.get('idMembers')).include(this.currentUser.id)) {
                hidden = true;
            }
            card.set({hidden: hidden});
        }, this));
    },

    _getCards: function() {
        this.boards.each(_.bind(function(board) {
            board.cards().fetch();
            board.cards().bind('reset', _.bind(this._updateBoardVisibility, this, board));
        }, this));
    },

    _createCalendar: function() {
        var calendar = this.$('#calendar').fullCalendar({
            header: {
	        left: 'prev,next today',
	        center: 'title',
	        right: 'month,agendaWeek,agendaDay'
	    },
            height: $(document).height() - 50,
            editable: true,
            disableResizing: true,
            ignoreTimezone: false,
            timeFormat: "H'h'(mm)",
            eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
                var card = event.backboneModel;
                var date = moment(event.start).format("YYYY-MM-DDTHH:mm:ssZ");
                var badges = _.extend({}, card.get('badges'), {due: date});
                card.set({badges: badges});
                card.save();
            }
        });
        $(window).resize(function() {
            calendar.fullCalendar('option', 'height', $(document).height() - 50);
        });
    }
});

$(document).ready(function() {
    var defaultOptions = {
        scope: {
            write: true
        },
        success: onAuthorize
    };
    /**
     * Authentication dance
     *  1. try to get a token from a previous session
     *  2. if no authorized token found, ask a token
     *  3. start application
     */
    Trello.authorize(_.extend({}, defaultOptions, {
        interactive: false
    }));

    if (!Trello.authorized()) {
        return Trello.authorize(defaultOptions);
    }

    function onAuthorize() {
        if (!Trello.authorized()) return Trello.authorize(defaultOptions);
        new App.view.Calendar({el: $('body').get(0)}).render();
    }
});
<commit_msg>Don't store prefs if localStorage is not available.<commit_after>var App = {
    model: {},
    collection: {},
    view: {},
};

/**
 * Pref model
 * Stored in localStorage
 */
App.model.Prefs = Backbone.Model.extend({
    defaults: {
        only_me: false
    },

    sync: function(method, model, options) {
        if (!window.localStorage) return;
        if (method == 'create' || method == 'update') {
            localStorage.setItem('prefs', JSON.stringify(model.toJSON()));
        } else if (method == 'read') {
            var prefs = localStorage.getItem('prefs');
            if (prefs) {
                try {
                    prefs = JSON.parse(prefs);
                } catch(e) {}
                options.success(prefs);
            }
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Current User model
 */
App.model.CurrentUser = Backbone.Model.extend({
    sync: function(method, model, options) {
        if (method == 'read') {
            return Trello.get('/members/me', {}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Card model
 */
App.model.Card = Backbone.Model.extend({
    sync: function(method, model, options) {
        if (method == 'update') {
            // only support update due date
            return Trello.put('/cards/'+ model.id, {due: model.get('badges').due}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Cards collection
 */
App.collection.Cards = Backbone.Collection.extend({
    model: App.model.Card,

    initialize: function(models, options) {
        this.options = options;
    },

    sync: function(method, model, options) {
        if (method == 'read') {
            return Trello.get('/boards/'+ this.options.board.id +'/cards/all', {badges: true}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Board model
 */
App.model.Board = Backbone.Model.extend({
    defaults: {
        hidden: false
    },

    initialize: function() {
        this._initFromLocalStorage();
        this.bind('change:hidden', this._saveStateToLocalStorage, this);
        this._cards = new App.collection.Cards([], {board: this});
    },

    cards: function() {
        return this._cards;
    },

    _initFromLocalStorage: function() {
        var value = this._getValue("false");
        if (value === "true" || value === "false") {
            this.set({hidden: (value === "true")});
        }
    },

    _saveStateToLocalStorage: function() {
        if (!window.localStorage) return;
        var key = 'board-state-'+ this.id +"-hidden";
        var value = window.localStorage.setItem(key, this.get('hidden'));
    },

    _getValue: function(defaultValue) {
        if (!window.localStorage) return defaultValue;
        var key = 'board-state-'+ this.id +"-hidden";
        var value = window.localStorage.getItem(key);
        if (value === null)
            return defaultValue;
        return value;
    }
});

/**
 * Board collection
 */
App.collection.Boards = Backbone.Collection.extend({
    model: App.model.Board,

    sync: function(method, model, options) {
        if (method == 'read') {
            return Trello.get('/members/my/boards', {filter: 'open'}, options.success, options.error);
        } else {
            throw "not (yet) supported";
        }
    }
});

/**
 * Render a card on fullcalendar
 */
App.view.Card = Backbone.View.extend({
    initialize: function() {
        this.model.bind('change', this.render, this);
    },

    render: function() {
        if (this.model.get('hidden')) {
            $(this.el).fullCalendar('removeEvents', this.model.id);
        } else {
            $(this.el).fullCalendar('removeEvents', this.model.id);
            var color = "#"+this.model.get('idBoard').substr(0, 6);
            $(this.el).fullCalendar('renderEvent', {
                backboneModel: this.model,
                id: this.model.id,
                allDay: false,
                title: this.model.get('name'),
                start: this.model.get('badges').due,
                color: color,
                url: this.model.get('url')
            }, true);
        }
        return this;
    },

    remove: function() {
        $(this.el).fullCalendar('removeEvents', this.model.id);
    }
});

/**
 * Render cards of one board
 */
App.view.CardsBoard = Backbone.View.extend({
    initialize: function() {
        this.views = [];
        this.model.cards().bind('reset', this.render, this);
    },

    render: function() {
        // remove previously events
        _(this.views).each(function(view) {
            view.remove();
        });
        this.views = this.model.cards().chain().map(_.bind(function(card) {
            // no arm, no chocolate
            if (!card.get('badges').due) return;
            return new App.view.Card({model: card,
                                      el: this.el}).render();
        }, this)).filter(function(view) {
            return view;
        }).value();
        return this;
    }
});

/**
 * Render all cards from all boards
 */
App.view.Cards = Backbone.View.extend({
    initialize: function() {
        this.collection.bind('reset', this.render, this);
    },

    render: function() {
        this.collection.each(_.bind(function(board) {
            new App.view.CardsBoard({model: board,
                                     el: this.el}).render();
        }, this));
        return this;
    }

});

App.view.Filter = Backbone.View.extend({
    events: {
        "click input": "click"
    },

    tagName: 'label',

    click: function(e) {
        var only_me = false;
        if ($(e.target).is(':checked')) {
            only_me = true;
        }
        this.model.set({only_me: only_me});
        this.model.save();
        $(this.el).toggleClass('checked');
    },

    render: function() {
        var input = this.make('input', {type: 'checkbox',
                                        value: "onlyme",
                                        checked: this.model.get('only_me')});
        $(this.el).text("Show only cards assigned to me")
                  .addClass((this.model.get('only_me') ? 'checked': ''))
                  .append(input);
        return this;
    }
});

/**
 * Render a board filter
 */
App.view.Board = Backbone.View.extend({
    events: {
        "click input": "click"
    },

    tagName: 'label',

    click: function(e) {
        var hidden = true;
        if ($(e.target).is(':checked')) {
            hidden = false;
        }
        this.model.set({hidden: hidden});
        $(this.el).toggleClass('checked');
    },

    render: function() {
        var input = this.make('input', {type: 'checkbox',
                                        value: this.model.id,
                                        checked: !this.model.get('hidden')});
        var color = "#"+this.model.id.substr(0, 6);
        $(this.el).css({'background-color': color})
                  .attr('title', 'Show cards from the board '+  this.model.get('name'))
                  .text(this.model.get('name'))
                  .append(input);
        if (!this.model.get('hidden') === true)
            $(this.el).addClass('checked');
        return this;
    }
});

/**
 * List of boards filters
 */
App.view.Boards = Backbone.View.extend({
    initialize: function() {
        this.collection.bind('reset', this.render, this);
    },

    render: function() {
        this.collection.each(_.bind(function(board) {
            var view = new App.view.Board({model: board}).render();
            $(view.el).appendTo(this.el);
        }, this));
    }
});

/**
 * Main view
 */
App.view.Calendar = Backbone.View.extend({
    initialize: function() {
        this.boards = new App.collection.Boards();
        this.currentUser = new App.model.CurrentUser();

        this.prefs = new App.model.Prefs();
        this.prefs.fetch();
        this.prefs.bind('change', this._updateBoardsVisibility, this);

        this.currentUser.fetch().done(_.bind(function() {
            this.boards.fetch();
        }, this));

        this.boards.bind('reset', this._getCards, this);
        this.boards.bind('change:hidden', this._updateBoardVisibility, this);
    },

    render: function() {
        this._createCalendar();
        new App.view.Boards({collection: this.boards,
                             el: this.$('#boards').get(0)}).render();
        new App.view.Cards({collection: this.boards,
                            el: this.$('#calendar').get(0)}).render();
        var filter = new App.view.Filter({model: this.prefs}).render();
        this.$('#prefs').append(filter.el);
        return this;
    },

    _updateBoardsVisibility: function() {
        this.boards.each(_.bind(function(board) {
            this._updateBoardVisibility(board);
        }, this));
    },

    _updateBoardVisibility: function(board) {
        board.cards().each(_.bind(function(card) {
            var hidden = board.get('hidden');
            if (!hidden && this.prefs.get('only_me') && !_(card.get('idMembers')).include(this.currentUser.id)) {
                hidden = true;
            }
            card.set({hidden: hidden});
        }, this));
    },

    _getCards: function() {
        this.boards.each(_.bind(function(board) {
            board.cards().fetch();
            board.cards().bind('reset', _.bind(this._updateBoardVisibility, this, board));
        }, this));
    },

    _createCalendar: function() {
        var calendar = this.$('#calendar').fullCalendar({
            header: {
	        left: 'prev,next today',
	        center: 'title',
	        right: 'month,agendaWeek,agendaDay'
	    },
            height: $(document).height() - 50,
            editable: true,
            disableResizing: true,
            ignoreTimezone: false,
            timeFormat: "H'h'(mm)",
            eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
                var card = event.backboneModel;
                var date = moment(event.start).format("YYYY-MM-DDTHH:mm:ssZ");
                var badges = _.extend({}, card.get('badges'), {due: date});
                card.set({badges: badges});
                card.save();
            }
        });
        $(window).resize(function() {
            calendar.fullCalendar('option', 'height', $(document).height() - 50);
        });
    }
});

$(document).ready(function() {
    var defaultOptions = {
        scope: {
            write: true
        },
        success: onAuthorize
    };
    /**
     * Authentication dance
     *  1. try to get a token from a previous session
     *  2. if no authorized token found, ask a token
     *  3. start application
     */
    Trello.authorize(_.extend({}, defaultOptions, {
        interactive: false
    }));

    if (!Trello.authorized()) {
        return Trello.authorize(defaultOptions);
    }

    function onAuthorize() {
        if (!Trello.authorized()) return Trello.authorize(defaultOptions);
        new App.view.Calendar({el: $('body').get(0)}).render();
    }
});
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright © 2016 The Waves Developers.                                     *
 *                                                                            *
 * See the LICENSE files at                                                   *
 * the top-level directory of this distribution for the individual copyright  *
 * holder information and the developer policies on copyright and licensing.  *
 *                                                                            *
 * Unless otherwise agreed in a custom licensing agreement, no part of the    *
 * Waves software, including this file, may be copied, modified, propagated,  *
 * or distributed except according to the terms contained in the LICENSE      *
 * file.                                                                      *
 *                                                                            *
 * Removal or modification of this copyright notice is prohibited.            *
 *                                                                            *
 ******************************************************************************/
/**
 * @depends {3rdparty/jquery-2.1.0.js}
 * @depends {3rdparty/jquery-validate.js}
 * @depends {3rdparty/bootstrap.js}
 * @depends {3rdparty/big.js}
 * @depends {3rdparty/jsbn.js}
 * @depends {3rdparty/jsbn2.js}
 * @depends {3rdparty/webdb.js}
 * @depends {3rdparty/growl.js}
 * @depends {axlsign/axlsign.js}
 * @depends {crypto/base58.js}
 * @depends {crypto/blake32.js}
 * @depends {crypto/keccak32.js}
 * @depends {crypto/passphrasegenerator.js}
 * @depends {crypto/sha256worker.js}
 * @depends {crypto/3rdparty/cryptojs/aes.js}
 * @depends {crypto/3rdparty/cryptojs/sha256.js}
 * @depends {crypto/3rdparty/jssha256.js}
 * @depends {crypto/3rdparty/seedrandom.js}
 * @depends {util/converters.js}
 * @depends {util/extensions.js}
 */
var Waves = (function(Waves, $, undefined) {
	"use strict";

    if (Waves.UI === undefined)
        Waves.UI = {};

    Waves.UI.sendWavesForm = {
        id : 'send-waves-form',
        containerId : 'wB-butSend-WAV',
        validator : undefined,
        getForm : function() {
            return $('#' + Waves.UI.sendWavesForm.id);
        },
        setupValidation : function() {
            $('#' + this.containerId).on($.modal.BEFORE_OPEN, function(event, modal) {
                Waves.UI.sendWavesForm.validator = Waves.UI.sendWavesForm.getForm().validate({
                    errorClass : 'wInput-error',
                    rules : {
                        wavesrecipient : {
                            required : true,
                            address : true
                        },
                        wavessendamount : {
                            required : true,
                            decimal : true,
                            min : Waves.UI.constants.MINIMUM_PAYMENT_AMOUNT
                        },
                        wavessendfee : {
                            required : true,
                            decimal : true,
                            min : Waves.UI.constants.MINIMUM_TRANSACTION_FEE
                        }
                    },
                    messages : {
                        wavesrecipient : {
                            required : 'Recipient account number is required'
                        },
                        wavessendamount : {
                            required : 'Amount to send is required',
                            decimal : 'Amount to send must be a decimal number with dot (.) as a decimal separator',
                            min : 'Payment amount is too small. It should be greater or equal to ' +
                                Waves.UI.constants.MINIMUM_PAYMENT_AMOUNT.toFixed(Waves.UI.constants.AMOUNT_DECIMAL_PLACES)
                        },
                        wavessendfee : {
                            required : 'Transaction fee is required',
                            decimal : 'Transaction fee must be a decimal number with dot (.) as a decimal separator',
                            min : 'Transactions fee is too small. It should be greater or equal to ' +
                                Waves.UI.constants.MINIMUM_TRANSACTION_FEE
                        }
                    }
                });
            });

            $('#' + this.containerId).on($.modal.BEFORE_CLOSE, function(event, modal) {
                if (Waves.UI.sendWavesForm.validator !== undefined)
                    Waves.UI.sendWavesForm.validator.resetForm();
            });
        },

        isValid : function() {
            return this.getForm().valid();
        }
    };

    $("#wB-butSend-WAV").on($.modal.OPEN, function(event, modal) {
        $("#wavesrecipient").focus();
    });

    $("#send-confirm").on("click", function(e) {
        e.preventDefault();

        var transactionFee = new Money($("#wavessendfee").val().replace(/\s+/g, ''), Currency.WAV);
        var sendAmount = new Money($("#wavessendamount").val().replace(/\s+/g, ''), Currency.WAV);
        var amount = sendAmount.toCoins();

        var senderPrivate = Base58.decode(Waves.privateKey);
        var addressText = $("#wavesrecipient").val().replace(/\s+/g, '');
        // validate display address knows that the address prefix is optional
        var recipient = Waves.Addressing.fromDisplayAddress(addressText);

        var wavesTime = Number(Waves.getTime());
        var fee = transactionFee.toCoins();

        var signatureData = Waves.signatureData(Waves.publicKey, recipient.getRawAddress(), amount, fee, wavesTime);
        var signature = Waves.nonDeterministicSign(senderPrivate, signatureData);

        var data = {
            "recipient": recipient.getRawAddress(),
            "timestamp": wavesTime,
            "signature": signature,
            "amount": amount,
            "senderPublicKey": Waves.publicKey,
            "sender": Waves.address.getRawAddress(),
            "fee": fee
        }

        Waves.apiRequest(Waves.api.waves.broadcastTransaction, JSON.stringify(data), function(response) {

            if(response.error !== undefined) {
                $.growl.error({ message: 'Error:'+response.error +' - '+response.message });
            } else {

                var successMessage = 'Sent '+ sendAmount.formatAmount(true) +' Wave
Recipient '+
                    recipient.getDisplayAddress().substr(0,15)+'...
Date: '+Waves.formatTimestamp(wavesTime);
                $.growl({ title: 'Payment sent! ', message: successMessage, size: 'large' });
                $("#wavesrecipient").val('');
                $("#wavessendamount").val('');

                $.modal.close();
                Waves.pages['mBB-wallet']();
            }
        });
    });

	$("#wavessend").on("click", function(e) {
        e.preventDefault();

        if (!Waves.UI.sendWavesForm.isValid())
            return;

        var transactionFee = new Money($(".custom-combobox-input").val().replace(/\s+/g, ''), Currency.WAV);
        var currentBalance = new Money($("#wavesCurrentBalance").val(), Currency.WAV);
        var maxSend = currentBalance.minus(transactionFee);
        var sendAmount = new Money($("#wavessendamount").val().replace(/\s+/g, ''), Currency.WAV);

        if (sendAmount.greaterThan(maxSend)) {
            $.growl.error({ message: 'Error: Not enough funds' });
            return;
        }

        var addressText = $("#wavesrecipient").val().replace(/\s+/g, '');
        $("#confirmation-amount").html(sendAmount.formatAmount(true));
        $("#confirmation-fee").html(transactionFee.formatAmount(true));
        $("#confirmation-address").html(addressText);

        $("#send-payment-confirmation").modal();
    });

    Waves.UI.sendWavesForm.setupValidation();

	return Waves;
}(Waves || {}, jQuery));<commit_msg>Fixed a bug when a transaction fee hasn't been propagated to the send method.<commit_after>/******************************************************************************
 * Copyright © 2016 The Waves Developers.                                     *
 *                                                                            *
 * See the LICENSE files at                                                   *
 * the top-level directory of this distribution for the individual copyright  *
 * holder information and the developer policies on copyright and licensing.  *
 *                                                                            *
 * Unless otherwise agreed in a custom licensing agreement, no part of the    *
 * Waves software, including this file, may be copied, modified, propagated,  *
 * or distributed except according to the terms contained in the LICENSE      *
 * file.                                                                      *
 *                                                                            *
 * Removal or modification of this copyright notice is prohibited.            *
 *                                                                            *
 ******************************************************************************/
/**
 * @depends {3rdparty/jquery-2.1.0.js}
 * @depends {3rdparty/jquery-validate.js}
 * @depends {3rdparty/bootstrap.js}
 * @depends {3rdparty/big.js}
 * @depends {3rdparty/jsbn.js}
 * @depends {3rdparty/jsbn2.js}
 * @depends {3rdparty/webdb.js}
 * @depends {3rdparty/growl.js}
 * @depends {axlsign/axlsign.js}
 * @depends {crypto/base58.js}
 * @depends {crypto/blake32.js}
 * @depends {crypto/keccak32.js}
 * @depends {crypto/passphrasegenerator.js}
 * @depends {crypto/sha256worker.js}
 * @depends {crypto/3rdparty/cryptojs/aes.js}
 * @depends {crypto/3rdparty/cryptojs/sha256.js}
 * @depends {crypto/3rdparty/jssha256.js}
 * @depends {crypto/3rdparty/seedrandom.js}
 * @depends {util/converters.js}
 * @depends {util/extensions.js}
 */
var Waves = (function(Waves, $, undefined) {
	"use strict";

    if (Waves.UI === undefined)
        Waves.UI = {};

    Waves.UI.sendWavesForm = {
        id : 'send-waves-form',
        containerId : 'wB-butSend-WAV',
        validator : undefined,
        getForm : function() {
            return $('#' + Waves.UI.sendWavesForm.id);
        },
        setupValidation : function() {
            $('#' + this.containerId).on($.modal.BEFORE_OPEN, function(event, modal) {
                Waves.UI.sendWavesForm.validator = Waves.UI.sendWavesForm.getForm().validate({
                    errorClass : 'wInput-error',
                    rules : {
                        wavesrecipient : {
                            required : true,
                            address : true
                        },
                        wavessendamount : {
                            required : true,
                            decimal : true,
                            min : Waves.UI.constants.MINIMUM_PAYMENT_AMOUNT
                        },
                        wavessendfee : {
                            required : true,
                            decimal : true,
                            min : Waves.UI.constants.MINIMUM_TRANSACTION_FEE
                        }
                    },
                    messages : {
                        wavesrecipient : {
                            required : 'Recipient account number is required'
                        },
                        wavessendamount : {
                            required : 'Amount to send is required',
                            decimal : 'Amount to send must be a decimal number with dot (.) as a decimal separator',
                            min : 'Payment amount is too small. It should be greater or equal to ' +
                                Waves.UI.constants.MINIMUM_PAYMENT_AMOUNT.toFixed(Waves.UI.constants.AMOUNT_DECIMAL_PLACES)
                        },
                        wavessendfee : {
                            required : 'Transaction fee is required',
                            decimal : 'Transaction fee must be a decimal number with dot (.) as a decimal separator',
                            min : 'Transactions fee is too small. It should be greater or equal to ' +
                                Waves.UI.constants.MINIMUM_TRANSACTION_FEE
                        }
                    }
                });
            });

            $('#' + this.containerId).on($.modal.BEFORE_CLOSE, function(event, modal) {
                if (Waves.UI.sendWavesForm.validator !== undefined)
                    Waves.UI.sendWavesForm.validator.resetForm();
            });
        },

        isValid : function() {
            return this.getForm().valid();
        }
    };

    $("#wB-butSend-WAV").on($.modal.OPEN, function(event, modal) {
        $("#wavesrecipient").focus();
    });

    $("#send-confirm").on("click", function(e) {
        e.preventDefault();

        var transactionFee = new Money($(".custom-combobox-input").val().replace(/\s+/g, ''), Currency.WAV);
        var sendAmount = new Money($("#wavessendamount").val().replace(/\s+/g, ''), Currency.WAV);
        var amount = sendAmount.toCoins();

        var senderPrivate = Base58.decode(Waves.privateKey);
        var addressText = $("#wavesrecipient").val().replace(/\s+/g, '');
        // validate display address knows that the address prefix is optional
        var recipient = Waves.Addressing.fromDisplayAddress(addressText);

        var wavesTime = Number(Waves.getTime());
        var fee = transactionFee.toCoins();

        var signatureData = Waves.signatureData(Waves.publicKey, recipient.getRawAddress(), amount, fee, wavesTime);
        var signature = Waves.nonDeterministicSign(senderPrivate, signatureData);

        var data = {
            "recipient": recipient.getRawAddress(),
            "timestamp": wavesTime,
            "signature": signature,
            "amount": amount,
            "senderPublicKey": Waves.publicKey,
            "sender": Waves.address.getRawAddress(),
            "fee": fee
        }

        Waves.apiRequest(Waves.api.waves.broadcastTransaction, JSON.stringify(data), function(response) {

            if(response.error !== undefined) {
                $.growl.error({ message: 'Error:'+response.error +' - '+response.message });
            } else {

                var successMessage = 'Sent '+ sendAmount.formatAmount(true) +' Wave
Recipient '+
                    recipient.getDisplayAddress().substr(0,15)+'...
Date: '+Waves.formatTimestamp(wavesTime);
                $.growl({ title: 'Payment sent! ', message: successMessage, size: 'large' });
                $("#wavesrecipient").val('');
                $("#wavessendamount").val('');

                $.modal.close();
                Waves.pages['mBB-wallet']();
            }
        });
    });

	$("#wavessend").on("click", function(e) {
        e.preventDefault();

        if (!Waves.UI.sendWavesForm.isValid())
            return;

        var transactionFee = new Money($(".custom-combobox-input").val().replace(/\s+/g, ''), Currency.WAV);
        var currentBalance = new Money($("#wavesCurrentBalance").val(), Currency.WAV);
        var maxSend = currentBalance.minus(transactionFee);
        var sendAmount = new Money($("#wavessendamount").val().replace(/\s+/g, ''), Currency.WAV);

        if (sendAmount.greaterThan(maxSend)) {
            $.growl.error({ message: 'Error: Not enough funds' });
            return;
        }

        var addressText = $("#wavesrecipient").val().replace(/\s+/g, '');
        $("#confirmation-amount").html(sendAmount.formatAmount(true));
        $("#confirmation-fee").html(transactionFee.formatAmount(true));
        $("#confirmation-address").html(addressText);

        $("#send-payment-confirmation").modal();
    });

    Waves.UI.sendWavesForm.setupValidation();

	return Waves;
}(Waves || {}, jQuery));<|endoftext|>


<commit_before>module.exports = {
    services: [
        {
            url: 'http://localhost:9870',
            type: 'presence'
        },
        {
            url: 'http://localhost:9871',
            type: 'realtime'
        },
    ]
};
<commit_msg>Use presence/realtime subdomains in matchmaker<commit_after>module.exports = {
    services: [
        {
            url: 'http://presence.unichat.eu',
            type: 'presence'
        },
        {
            url: 'http://realtime.unichat.eu',
            type: 'realtime'
        },
    ]
};
<|endoftext|>


<commit_before>document.getElementById("id_business_version").innerHTML = "Business version = 2017.11.28.0";

//window.addEventListener("deviceorientation", on_device_orientation);
window.addEventListener("devicemotion", on_device_motion);

var canvas = document.getElementById("id_canvas");
var ctx = canvas.getContext("2d");

//-----------------------------------------------------
function deseneaza_cerc(unghi1, unghi2)
{
		ctx.clearRect(0, 0, 400, 400);

		ctx.rect(0, 0, 400, 400);
		ctx.stroke();

		ctx.beginPath();
		ctx.arc(200 + unghi1 * 200 / 90, 200 + unghi2 * 200 / 90, 20, 0, 2 * Math.PI);
		ctx.fillStyle = "#FF0000";
		//ctx.fill();
		ctx.strokeStyle = "#00FF00";
		ctx.lineWidth = 5;
		ctx.stroke();
}
//-----------------------------------------------------
function on_device_orientation(e)
{
	deseneaza_cerc(e.gamma, e.beta);
}
//-----------------------------------------------------
function on_device_motion(e)
{
	var beta = Math.atan(e.accelerationIncludingGravity.y / e.accelerationIncludingGravity.z) * 180 / Math.PI;
	var gamma = -Math.atan(e.accelerationIncludingGravity.x / e.accelerationIncludingGravity.z) * 180 / Math.PI;

	deseneaza_cerc(gamma, beta);
}
//-----------------------------------------------------
<commit_msg>use gyroscope<commit_after>document.getElementById("id_business_version").innerHTML = "Business version = 2017.12.04.0"

window.addEventListener("deviceorientation", on_device_orientation);
//window.addEventListener("devicemotion", on_device_motion);

var canvas = document.getElementById("id_canvas");
var ctx = canvas.getContext("2d");

//-----------------------------------------------------
function deseneaza_cerc(unghi1, unghi2)
{
		ctx.clearRect(0, 0, 400, 400);

		ctx.rect(0, 0, 400, 400);
		ctx.stroke();

		ctx.beginPath();
		ctx.arc(200 + unghi1 * 200 / 90, 200 + unghi2 * 200 / 90, 20, 0, 2 * Math.PI);
		ctx.fillStyle = "#FF0000";
		//ctx.fill();
		ctx.strokeStyle = "#00FF00";
		ctx.lineWidth = 5;
		ctx.stroke();
}
//-----------------------------------------------------
function on_device_orientation(e)
{
	deseneaza_cerc(e.gamma, e.beta);
}
//-----------------------------------------------------
function on_device_motion(e)
{
	var beta = Math.atan(e.accelerationIncludingGravity.y / e.accelerationIncludingGravity.z) * 180 / Math.PI;
	var gamma = -Math.atan(e.accelerationIncludingGravity.x / e.accelerationIncludingGravity.z) * 180 / Math.PI;

	deseneaza_cerc(gamma, beta);
}
//-----------------------------------------------------
<|endoftext|>


<commit_before>/*
 the 'searches' modules provides a combination of
 Reflux.actions and Reflux.stores which trigger and store
 searches in different contexts.
*/
import _ from 'underscore';
import Reflux from 'reflux';
import $ from 'jquery';

import stores from './stores';
import actions from './actions';
import {dataInterface} from './dataInterface';
import {assign} from './utils';
import assetParserUtils from './assetParserUtils';

var searchDataInterface = (function(){
  return {
    assets: function(data) {
      return $.ajax({
        url: `${dataInterface.rootUrl}/assets/`,
        dataType: 'json',
        data: data,
        method: 'GET'
      });
    }
  };
})();

const clearSearchState = {
  searchState: 'none',
  searchResults: false,
  searchResultsList: [],
  searchFilterParams: {},
  searchResultsDisplayed: false,
  searchResultsFor: false,
  searchResultsSuccess: null,
  searchDebugQuery: false,
  searchResultsCount: 0,
};
const initialState = assign({
  cleared: false,

  defaultQueryState: 'none',
  defaultQueryFor: '',
  defaultQueryDebug: '',
  defaultQueryFilterParams: {},
  defaultQueryResults: '',
  defaultQueryResultsList: [],
  defaultQueryCount: 0,
}, clearSearchState);

function SearchContext(opts={}) {
  var ctx = this;
  var debounceTime = opts.debounceTime || 500;
  var jqxhrs = {};

  var search = Reflux.createAction({
    children: [
      'completed',
      'failed',
      'cancel',
      'refresh',
    ]
  });
  var latestSearchData;

  var searchStore = ctx.store = Reflux.createStore({
    init () {
      this.filterParams = {};
      this.state = {
        searchState: 'none',
      };
      this.listenTo(actions.resources.deleteAsset.completed, this.onDeleteAssetCompleted);
    },
    onDeleteAssetCompleted (asset) {
      console.log(asset);
      var filterOutDeletedAsset = ({listName}) => {
        // TODO: look into why sometimes this.state[listName] is not defined
        if (this.state[listName] != undefined) {
          let uid = asset.uid;
          let listLength = this.state[listName].length;
          let l = this.state[listName].filter(function(result){
            return result.uid !== uid;
          });
          if (l.length !== listLength) {
            let o = {};
            o[listName] = l;
            this.update(o);
          }
        }
      };
      filterOutDeletedAsset({listName: 'defaultQueryResultsList'});
      if (this.state.searchResultsList && this.state.searchResultsList.length > 0) {
        filterOutDeletedAsset({listName: 'searchResultsList'});
      }
    },
    update (items) {
      this.quietUpdate(items);
      this.triggerState();
    },
    triggerState () {
      this.trigger(this.state);
    },
    quietUpdate (items) {
      if (!items.cleared) {
        items.cleared = false;
      }
      assign(this.state, items);
    },
    filterTagQueryData () {
      if (this.filterTags) {
        return {
          q: this.filterTags,
        };
      }
    },
    removeItem (key) {
      delete this.state[key];
    },
    toDataObject () {
      var params = {};
      if (this.state.searchTags) {
        params.tags = this.state.searchTags;
      }
      if (this.state.searchString) {
        params.string = this.state.searchString;
      }
      if (this.state.parentUid) {
        params.parentUid = `parent__uid:${this.state.parentUid}`;
      }
      if (this.state.allPublic === true) {
        params.allPublic = true;
      }
      return assign({}, this.filterParams, params);
    },
    toQueryData (dataObject) {
      var searchParams = dataObject || this.toDataObject(),
          // _searchParamsClone = assign({}, searchParams),
          paramGroups = [],
          queryData = {};

      if ('tags' in searchParams) {
        if (searchParams.tags && searchParams.tags.length > 0) {
          paramGroups.push(
              searchParams.tags.map(function(t){
                return `tag:"${t.value}"`;
              }).join(' AND ')
            );
        }
        delete searchParams.tags;
      }
      if ('string' in searchParams) {
        if (searchParams.string && searchParams.string.length > 0) {
          paramGroups.push(
              searchParams.string
            );
        }
        delete searchParams.string;
      }
      if ('parent' in searchParams) {
        if (searchParams.parent && searchParams.parent.length > 0) {
          queryData.parent = searchParams.parent;
        }
        delete searchParams.parent;
      }
      if ('allPublic' in searchParams) {
        queryData.all_public = searchParams.allPublic;
        delete searchParams.allPublic;
      }
      paramGroups = paramGroups.concat(_.values(searchParams));
      if (paramGroups.length > 1) {
        queryData.q = paramGroups.map(function(s){
          return `(${s})`;
        }).join(' AND ');
      } else if (paramGroups.length === 1) {
        queryData.q = paramGroups[0];
      }
      return queryData;
    },
  });

  search.listen(function(_opts={}){
    /*
    search will query whatever values are in the store
    and will pass the values back to the store to be reflected
    in the components' states.
    */
    var dataObject = searchStore.toDataObject();
    var _dataObjectClone = assign({}, dataObject);
    var qData = searchStore.toQueryData(dataObject);
    var isSearch = !_opts.cacheAsDefaultSearch;

    // we can clean this up later, but right now, if the search query is empty
    // it cancels the search
    /*
    if (((d)=>{
      if (_opts.cacheAsDefaultSearch) {
        return false;
      }

      var hasTags = d.tags && d.tags.length && d.tags.length > 0;
      var hasString = d.string && d.string.length && d.string.length > 0;
      return !hasTags && !hasString;
    })(_dataObjectClone)) {
      return search.cancel();
    }
    */
    if (isSearch) {
      // cancel existing searches
      if (jqxhrs.search) {
        jqxhrs.search.searchAborted = true;
        jqxhrs.search.abort();
        jqxhrs.search = false;
      }
    }
    latestSearchData = {params: qData, dataObject: dataObject};
    var req = searchDataInterface.assets(qData)
      .done(function(data){
        search.completed(dataObject, data, {
          cacheAsDefaultSearch: _opts.cacheAsDefaultSearch,
        });
      })
      .fail(function(xhr){
        search.failed(xhr, dataObject);
      });

    jqxhrs[ isSearch ? 'search' : 'default' ] = req;

    if (isSearch) {
      searchStore.update({
        searchState: 'loading',
        searchFor: _dataObjectClone,
      });
    } else {
      searchStore.update({
        defaultQueryState: 'loading',
        defaultQueryFor: _dataObjectClone,
      });
    }
  });
  search.refresh.listen(function(){
    searchDataInterface.assets(latestSearchData.params)
      .done(function(data){
        search.completed(latestSearchData.dataObject, data, {
          cacheAsDefaultSearch: false,
        });
      })
      .fail(function(xhr){
        search.failed(xhr, latestSearchData.dataObject);
      });
  });

  search.completed.listen(function(searchParams, data, _opts){
    data.results = data.results.map(assetParserUtils.parsed);
    data.results.forEach(stores.allAssets.registerAssetOrCollection);

    var count = data.count;

    var newState;

    if (_opts.cacheAsDefaultSearch) {
      newState = {
        defaultQueryState: 'done',
        defaultQueryFor: searchParams,
        defaultQueryDebug: searchParams.__builtQueryString,
        defaultQueryFilterParams: searchStore.filterParams,
        defaultQueryResults: data,
        defaultQueryResultsList: data.results,
        defaultQueryCount: count,
        defaultQueryCategorizedResultsLists: {
          'Deployed': data.results.filter((asset) => {
            return asset.has_deployment && asset.deployment__active;
          }),
          'Draft': data.results.filter((asset) => {
            return !asset.has_deployment;
          }),
          'Archived': data.results.filter((asset) => {
            return asset.has_deployment && !asset.deployment__active;
          }),
          'Deleted': [], // not implemented yet
        }
      };
    } else {
      newState = {
        searchState: 'done',
        searchResultsFor: searchParams,
        searchDebugQuery: searchParams.__builtQueryString,
        searchBaseFilterParams: searchStore.filterParams,
        searchResults: data,
        // toQueryData() deletes searchParams.tags
        //searchTags: searchParams.tags,
        searchResultsList: data.results,
        searchResultsCount: count,

        // when to show search results (as opposed to default query)
        searchResultsDisplayed: true,
        searchResultsSuccess: count > 0,
        searchResultsCategorizedResultsLists: {
          'Deployed': data.results.filter((asset) => {
            return asset.has_deployment && asset.deployment__active;
          }),
          'Draft': data.results.filter((asset) => {
            return !asset.has_deployment;
          }),
          'Archived': data.results.filter((asset) => {
            return asset.has_deployment && !asset.deployment__active;
          }),
          'Deleted': [], // not implemented yet
        }
      };
    }
    searchStore.update(newState);
  });
  search.failed.listen(function(/*xhr, searchParams*/){
    // if (xhr.searchAborted) {
    //   log('search was canceled because a new search came up')
    // }
    // searchStore.update({
    //   searchState: 'failed',
    // })
  });
  search.cancel.listen(function(){
    if (jqxhrs.search) {
      jqxhrs.search.abort();
    }
    searchStore.update(assign({
      cleared: true
    }, clearSearchState));
  });
  this.mixin = {
    debouncedSearch: ( debounceTime ? _.debounce(search, debounceTime) : search ),
    searchValue: search,
    updateStore (vals) {
      searchStore.update(vals);
    },
    quietUpdateStore (vals) {
      searchStore.quietUpdate(vals);
    },
    searchStore: searchStore,
    searchDefault: function () {
      searchStore.quietUpdate(assign({
        cleared: true,
        searchString: false,
      }, clearSearchState));

      search({
        cacheAsDefaultSearch: true
      });
    },
    getSearchActions: function(){
      return {
        search: search,
      };
    },
  };
}

var commonMethods = {
  getInitialState () {
    return initialState;
  },
  componentDidMount () {
    this.extendSearchContext();
  },
  extendSearchContext () {
    var ctx,
        passedCtx = this.props.searchContext || this.state.searchContext;
    if (passedCtx instanceof SearchContext) {
      ctx = passedCtx;
    } else {
      ctx = getSearchContext(passedCtx);
    }
    assign(this, ctx.mixin);
  },
  searchTagsChange (tags) {
    this.quietUpdateStore({
      searchTags: tags
    });
    this.searchValue();
  },
  searchChangeEvent (evt) {
    this.quietUpdateStore({
      searchString: evt.target.value,
    });
    this.debouncedSearch();
  },
  searchClear () {
    this.searchStore.removeItem('searchString');
    this.searchStore.removeItem('searchTags');
    this.getSearchActions().search.cancel();
  },
};

function isSearchContext (ctx) {
  return (ctx instanceof SearchContext);
}

var contexts = {};

function getSearchContext(name, opts={}) {
  if (!contexts[name]) {
    contexts[name] = new SearchContext();
  }
  if (opts.filterParams) {
    contexts[name].store.filterParams = opts.filterParams;
  }
  if (opts.showDefault) {
    contexts[name].store.showDefault = opts.showDefault;
  }
  if (opts.filterTags) {
    contexts[name].store.filterTags = opts.filterTags;
  }
  return contexts[name];
}

module.exports = {
  getSearchContext: getSearchContext,
  common: commonMethods,
  isSearchContext: isSearchContext,
};
<commit_msg>cleanup console.log<commit_after>/*
 the 'searches' modules provides a combination of
 Reflux.actions and Reflux.stores which trigger and store
 searches in different contexts.
*/
import _ from 'underscore';
import Reflux from 'reflux';
import $ from 'jquery';

import stores from './stores';
import actions from './actions';
import {dataInterface} from './dataInterface';
import {assign} from './utils';
import assetParserUtils from './assetParserUtils';

var searchDataInterface = (function(){
  return {
    assets: function(data) {
      return $.ajax({
        url: `${dataInterface.rootUrl}/assets/`,
        dataType: 'json',
        data: data,
        method: 'GET'
      });
    }
  };
})();

const clearSearchState = {
  searchState: 'none',
  searchResults: false,
  searchResultsList: [],
  searchFilterParams: {},
  searchResultsDisplayed: false,
  searchResultsFor: false,
  searchResultsSuccess: null,
  searchDebugQuery: false,
  searchResultsCount: 0,
};
const initialState = assign({
  cleared: false,

  defaultQueryState: 'none',
  defaultQueryFor: '',
  defaultQueryDebug: '',
  defaultQueryFilterParams: {},
  defaultQueryResults: '',
  defaultQueryResultsList: [],
  defaultQueryCount: 0,
}, clearSearchState);

function SearchContext(opts={}) {
  var ctx = this;
  var debounceTime = opts.debounceTime || 500;
  var jqxhrs = {};

  var search = Reflux.createAction({
    children: [
      'completed',
      'failed',
      'cancel',
      'refresh',
    ]
  });
  var latestSearchData;

  var searchStore = ctx.store = Reflux.createStore({
    init () {
      this.filterParams = {};
      this.state = {
        searchState: 'none',
      };
      this.listenTo(actions.resources.deleteAsset.completed, this.onDeleteAssetCompleted);
    },
    onDeleteAssetCompleted (asset) {
      var filterOutDeletedAsset = ({listName}) => {
        // TODO: look into why sometimes this.state[listName] is not defined
        if (this.state[listName] != undefined) {
          let uid = asset.uid;
          let listLength = this.state[listName].length;
          let l = this.state[listName].filter(function(result){
            return result.uid !== uid;
          });
          if (l.length !== listLength) {
            let o = {};
            o[listName] = l;
            this.update(o);
          }
        }
      };
      filterOutDeletedAsset({listName: 'defaultQueryResultsList'});
      if (this.state.searchResultsList && this.state.searchResultsList.length > 0) {
        filterOutDeletedAsset({listName: 'searchResultsList'});
      }
    },
    update (items) {
      this.quietUpdate(items);
      this.triggerState();
    },
    triggerState () {
      this.trigger(this.state);
    },
    quietUpdate (items) {
      if (!items.cleared) {
        items.cleared = false;
      }
      assign(this.state, items);
    },
    filterTagQueryData () {
      if (this.filterTags) {
        return {
          q: this.filterTags,
        };
      }
    },
    removeItem (key) {
      delete this.state[key];
    },
    toDataObject () {
      var params = {};
      if (this.state.searchTags) {
        params.tags = this.state.searchTags;
      }
      if (this.state.searchString) {
        params.string = this.state.searchString;
      }
      if (this.state.parentUid) {
        params.parentUid = `parent__uid:${this.state.parentUid}`;
      }
      if (this.state.allPublic === true) {
        params.allPublic = true;
      }
      return assign({}, this.filterParams, params);
    },
    toQueryData (dataObject) {
      var searchParams = dataObject || this.toDataObject(),
          // _searchParamsClone = assign({}, searchParams),
          paramGroups = [],
          queryData = {};

      if ('tags' in searchParams) {
        if (searchParams.tags && searchParams.tags.length > 0) {
          paramGroups.push(
              searchParams.tags.map(function(t){
                return `tag:"${t.value}"`;
              }).join(' AND ')
            );
        }
        delete searchParams.tags;
      }
      if ('string' in searchParams) {
        if (searchParams.string && searchParams.string.length > 0) {
          paramGroups.push(
              searchParams.string
            );
        }
        delete searchParams.string;
      }
      if ('parent' in searchParams) {
        if (searchParams.parent && searchParams.parent.length > 0) {
          queryData.parent = searchParams.parent;
        }
        delete searchParams.parent;
      }
      if ('allPublic' in searchParams) {
        queryData.all_public = searchParams.allPublic;
        delete searchParams.allPublic;
      }
      paramGroups = paramGroups.concat(_.values(searchParams));
      if (paramGroups.length > 1) {
        queryData.q = paramGroups.map(function(s){
          return `(${s})`;
        }).join(' AND ');
      } else if (paramGroups.length === 1) {
        queryData.q = paramGroups[0];
      }
      return queryData;
    },
  });

  search.listen(function(_opts={}){
    /*
    search will query whatever values are in the store
    and will pass the values back to the store to be reflected
    in the components' states.
    */
    var dataObject = searchStore.toDataObject();
    var _dataObjectClone = assign({}, dataObject);
    var qData = searchStore.toQueryData(dataObject);
    var isSearch = !_opts.cacheAsDefaultSearch;

    // we can clean this up later, but right now, if the search query is empty
    // it cancels the search
    /*
    if (((d)=>{
      if (_opts.cacheAsDefaultSearch) {
        return false;
      }

      var hasTags = d.tags && d.tags.length && d.tags.length > 0;
      var hasString = d.string && d.string.length && d.string.length > 0;
      return !hasTags && !hasString;
    })(_dataObjectClone)) {
      return search.cancel();
    }
    */
    if (isSearch) {
      // cancel existing searches
      if (jqxhrs.search) {
        jqxhrs.search.searchAborted = true;
        jqxhrs.search.abort();
        jqxhrs.search = false;
      }
    }
    latestSearchData = {params: qData, dataObject: dataObject};
    var req = searchDataInterface.assets(qData)
      .done(function(data){
        search.completed(dataObject, data, {
          cacheAsDefaultSearch: _opts.cacheAsDefaultSearch,
        });
      })
      .fail(function(xhr){
        search.failed(xhr, dataObject);
      });

    jqxhrs[ isSearch ? 'search' : 'default' ] = req;

    if (isSearch) {
      searchStore.update({
        searchState: 'loading',
        searchFor: _dataObjectClone,
      });
    } else {
      searchStore.update({
        defaultQueryState: 'loading',
        defaultQueryFor: _dataObjectClone,
      });
    }
  });
  search.refresh.listen(function(){
    searchDataInterface.assets(latestSearchData.params)
      .done(function(data){
        search.completed(latestSearchData.dataObject, data, {
          cacheAsDefaultSearch: false,
        });
      })
      .fail(function(xhr){
        search.failed(xhr, latestSearchData.dataObject);
      });
  });

  search.completed.listen(function(searchParams, data, _opts){
    data.results = data.results.map(assetParserUtils.parsed);
    data.results.forEach(stores.allAssets.registerAssetOrCollection);

    var count = data.count;

    var newState;

    if (_opts.cacheAsDefaultSearch) {
      newState = {
        defaultQueryState: 'done',
        defaultQueryFor: searchParams,
        defaultQueryDebug: searchParams.__builtQueryString,
        defaultQueryFilterParams: searchStore.filterParams,
        defaultQueryResults: data,
        defaultQueryResultsList: data.results,
        defaultQueryCount: count,
        defaultQueryCategorizedResultsLists: {
          'Deployed': data.results.filter((asset) => {
            return asset.has_deployment && asset.deployment__active;
          }),
          'Draft': data.results.filter((asset) => {
            return !asset.has_deployment;
          }),
          'Archived': data.results.filter((asset) => {
            return asset.has_deployment && !asset.deployment__active;
          }),
          'Deleted': [], // not implemented yet
        }
      };
    } else {
      newState = {
        searchState: 'done',
        searchResultsFor: searchParams,
        searchDebugQuery: searchParams.__builtQueryString,
        searchBaseFilterParams: searchStore.filterParams,
        searchResults: data,
        // toQueryData() deletes searchParams.tags
        //searchTags: searchParams.tags,
        searchResultsList: data.results,
        searchResultsCount: count,

        // when to show search results (as opposed to default query)
        searchResultsDisplayed: true,
        searchResultsSuccess: count > 0,
        searchResultsCategorizedResultsLists: {
          'Deployed': data.results.filter((asset) => {
            return asset.has_deployment && asset.deployment__active;
          }),
          'Draft': data.results.filter((asset) => {
            return !asset.has_deployment;
          }),
          'Archived': data.results.filter((asset) => {
            return asset.has_deployment && !asset.deployment__active;
          }),
          'Deleted': [], // not implemented yet
        }
      };
    }
    searchStore.update(newState);
  });
  search.failed.listen(function(/*xhr, searchParams*/){
    // if (xhr.searchAborted) {
    //   log('search was canceled because a new search came up')
    // }
    // searchStore.update({
    //   searchState: 'failed',
    // })
  });
  search.cancel.listen(function(){
    if (jqxhrs.search) {
      jqxhrs.search.abort();
    }
    searchStore.update(assign({
      cleared: true
    }, clearSearchState));
  });
  this.mixin = {
    debouncedSearch: ( debounceTime ? _.debounce(search, debounceTime) : search ),
    searchValue: search,
    updateStore (vals) {
      searchStore.update(vals);
    },
    quietUpdateStore (vals) {
      searchStore.quietUpdate(vals);
    },
    searchStore: searchStore,
    searchDefault: function () {
      searchStore.quietUpdate(assign({
        cleared: true,
        searchString: false,
      }, clearSearchState));

      search({
        cacheAsDefaultSearch: true
      });
    },
    getSearchActions: function(){
      return {
        search: search,
      };
    },
  };
}

var commonMethods = {
  getInitialState () {
    return initialState;
  },
  componentDidMount () {
    this.extendSearchContext();
  },
  extendSearchContext () {
    var ctx,
        passedCtx = this.props.searchContext || this.state.searchContext;
    if (passedCtx instanceof SearchContext) {
      ctx = passedCtx;
    } else {
      ctx = getSearchContext(passedCtx);
    }
    assign(this, ctx.mixin);
  },
  searchTagsChange (tags) {
    this.quietUpdateStore({
      searchTags: tags
    });
    this.searchValue();
  },
  searchChangeEvent (evt) {
    this.quietUpdateStore({
      searchString: evt.target.value,
    });
    this.debouncedSearch();
  },
  searchClear () {
    this.searchStore.removeItem('searchString');
    this.searchStore.removeItem('searchTags');
    this.getSearchActions().search.cancel();
  },
};

function isSearchContext (ctx) {
  return (ctx instanceof SearchContext);
}

var contexts = {};

function getSearchContext(name, opts={}) {
  if (!contexts[name]) {
    contexts[name] = new SearchContext();
  }
  if (opts.filterParams) {
    contexts[name].store.filterParams = opts.filterParams;
  }
  if (opts.showDefault) {
    contexts[name].store.showDefault = opts.showDefault;
  }
  if (opts.filterTags) {
    contexts[name].store.filterTags = opts.filterTags;
  }
  return contexts[name];
}

module.exports = {
  getSearchContext: getSearchContext,
  common: commonMethods,
  isSearchContext: isSearchContext,
};
<|endoftext|>


<commit_before>/*
 * File: Options.BarChart.js
 *
*/

/*
  Object: Options.BarChart

  <BarChart> options.
  Other options included in the BarChart are <Options.Canvas>, <Options.Label>, <Options.Tips> and <Options.Events>.

  Syntax:

  (start code js)

  Options.BarChart = {
    animate: true,
    offset: 25,
    labelOffset: 3,
    barsOffset: 0,
    type: 'stacked',
    hoveredColor: '#9fd4ff',
    orientation: 'horizontal',
    showAggregates: true,
    showLabels: true
  };

  (end code)

  Example:

  (start code js)

  var barChart = new $jit.BarChart({
    animate: true,
    barsOffset: 10,
    type: 'stacked:gradient'
  });

  (end code)

  Parameters:

  animate - (boolean) Default's *true*. Whether to add animated transitions when filtering/restoring stacks.
  offset - (number) Default's *25*. Adds margin between the visualization and the canvas.
  labelOffset - (number) Default's *3*. Adds margin between the label and the default place where it should be drawn.
  barsOffset - (number) Default's *0*. Separation between bars.
  type - (string) Default's *'stacked'*. Stack style. Posible values are 'stacked', 'stacked:gradient' to add gradients.
  hoveredColor - (boolean|string) Default's *'#9fd4ff'*. Sets the selected color for a hovered bar stack.
  orientation - (string) Default's 'horizontal'. Sets the direction of the bars. Possible options are 'vertical' or 'horizontal'.
  showAggregates - (boolean) Default's *true*. Display the sum of the values of the different stacks.
  showLabels - (boolean) Default's *true*. Display the name of the slots.

*/

Options.BarChart = {
  $extend: true,

  animate: true,
  type: 'stacked', //stacked, grouped, : gradient
  offset: 25, //page offset
  labelOffset: 3, //label offset
  barsOffset: 0, //distance between bars
  hoveredColor: '#9fd4ff',
  orientation: 'horizontal',
  showAggregates: true,
  showLabels: true,
  Tips: {
    enable: false,
    onShow: $.empty,
    onHide: $.empty
  },
  Events: {
    enable: false,
    onClick: $.empty
  }
};<commit_msg>Document the fact that we can have grouped bars<commit_after>/*
 * File: Options.BarChart.js
 *
*/

/*
  Object: Options.BarChart

  <BarChart> options.
  Other options included in the BarChart are <Options.Canvas>, <Options.Label>, <Options.Tips> and <Options.Events>.

  Syntax:

  (start code js)

  Options.BarChart = {
    animate: true,
    offset: 25,
    labelOffset: 3,
    barsOffset: 0,
    type: 'stacked',
    hoveredColor: '#9fd4ff',
    orientation: 'horizontal',
    showAggregates: true,
    showLabels: true
  };

  (end code)

  Example:

  (start code js)

  var barChart = new $jit.BarChart({
    animate: true,
    barsOffset: 10,
    type: 'stacked:gradient'
  });

  (end code)

  Parameters:

  animate - (boolean) Default's *true*. Whether to add animated transitions when filtering/restoring stacks.
  offset - (number) Default's *25*. Adds margin between the visualization and the canvas.
  labelOffset - (number) Default's *3*. Adds margin between the label and the default place where it should be drawn.
  barsOffset - (number) Default's *0*. Separation between bars.
  type - (string) Default's *'stacked'*. Stack or grouped styles. Posible values are 'stacked', 'grouped', 'stacked:gradient', 'grouped:gradient' to add gradients.
  hoveredColor - (boolean|string) Default's *'#9fd4ff'*. Sets the selected color for a hovered bar stack.
  orientation - (string) Default's 'horizontal'. Sets the direction of the bars. Possible options are 'vertical' or 'horizontal'.
  showAggregates - (boolean) Default's *true*. Display the sum of the values of the different stacks.
  showLabels - (boolean) Default's *true*. Display the name of the slots.

*/

Options.BarChart = {
  $extend: true,

  animate: true,
  type: 'stacked', //stacked, grouped, : gradient
  offset: 25, //page offset
  labelOffset: 3, //label offset
  barsOffset: 0, //distance between bars
  hoveredColor: '#9fd4ff',
  orientation: 'horizontal',
  showAggregates: true,
  showLabels: true,
  Tips: {
    enable: false,
    onShow: $.empty,
    onHide: $.empty
  },
  Events: {
    enable: false,
    onClick: $.empty
  }
};<|endoftext|>