<commit_before>const path = require('path')
const glob = require('glob')
const camelcase = require('lodash.camelcase')
const rollupBabel = require('rollup-plugin-babel')
const commonjs = require('rollup-plugin-commonjs')
const nodeResolve = require('rollup-plugin-node-resolve')
const json = require('rollup-plugin-json')
const replace = require('rollup-plugin-replace')
const {terser} = require('rollup-plugin-terser')
const nodeBuiltIns = require('rollup-plugin-node-builtins')
const nodeGlobals = require('rollup-plugin-node-globals')
const {sizeSnapshot} = require('rollup-plugin-size-snapshot')
const omit = require('lodash.omit')
const {
  pkg,
  hasFile,
  hasPkgProp,
  parseEnv,
  ifFile,
  fromRoot,
  uniq,
  writeExtraEntry,
} = require('../utils')

const here = p => path.join(__dirname, p)
const capitalize = s => s[0].toUpperCase() + s.slice(1)

const minify = parseEnv('BUILD_MINIFY', false)
const format = process.env.BUILD_FORMAT
const isPreact = parseEnv('BUILD_PREACT', false)
const isNode = parseEnv('BUILD_NODE', false)
const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name))
const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false)

const esm = format === 'esm'
const umd = format === 'umd'

const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce(
  (deps, dep) => {
    deps[dep] = capitalize(camelcase(dep))
    return deps
  },
  {},
)

const deps = Object.keys(pkg.dependencies || {})
const peerDeps = Object.keys(pkg.peerDependencies || {})
const defaultExternal = umd ? peerDeps : deps.concat(peerDeps)

const input = glob.sync(
  fromRoot(
    process.env.BUILD_INPUT ||
      ifFile(
        `src/${format}-entry.js`,
        `src/${format}-entry.js`,
        'src/index.js',
      ),
  ),
)
const codeSplitting = input.length > 1

if (
  codeSplitting &&
  uniq(input.map(single => path.basename(single))).length !== input.length
) {
  throw new Error(
    'Filenames of code-splitted entries should be unique to get deterministic output filenames.' +
      `\nReceived those: ${input}.`,
  )
}

const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || ''
const filenamePrefix =
  process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : '')
const globals = parseEnv(
  'BUILD_GLOBALS',
  isPreact ? Object.assign(defaultGlobals, {preact: 'preact'}) : defaultGlobals,
)
const external = parseEnv(
  'BUILD_EXTERNAL',
  isPreact ? defaultExternal.concat(['preact', 'prop-types']) : defaultExternal,
).filter((e, i, arry) => arry.indexOf(e) === i)

if (isPreact) {
  delete globals.react
  delete globals['prop-types'] // TODO: is this necessary?
  external.splice(external.indexOf('react'), 1)
}

const externalPattern = new RegExp(`^(${external.join('|')})($|/)`)
const externalPredicate =
  external.length === 0 ? () => false : id => externalPattern.test(id)

const filename = [
  pkg.name,
  filenameSuffix,
  `.${format}`,
  minify ? '.min' : null,
  '.js',
]
  .filter(Boolean)
  .join('')

const dirpath = path.join(...[filenamePrefix, 'dist'].filter(Boolean))

const output = [
  {
    name,
    ...(codeSplitting
      ? {dir: path.join(dirpath, format)}
      : {file: path.join(dirpath, filename)}),
    format: esm ? 'es' : format,
    exports: esm ? 'named' : 'auto',
    globals,
  },
]

const useBuiltinConfig =
  !hasFile('.babelrc') &&
  !hasFile('.babelrc.js') &&
  !hasFile('babel.config.js') &&
  !hasPkgProp('babel')
const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : []

const replacements = Object.entries(
  umd ? process.env : omit(process.env, ['NODE_ENV']),
).reduce((acc, [key, value]) => {
  let val
  if (value === 'true' || value === 'false' || Number.isInteger(+value)) {
    val = value
  } else {
    val = JSON.stringify(value)
  }
  acc[`process.env.${key}`] = val
  return acc
}, {})

module.exports = {
  input: codeSplitting ? input : input[0],
  output,
  experimentalCodeSplitting: codeSplitting,
  external: externalPredicate,
  plugins: [
    isNode ? nodeBuiltIns() : null,
    isNode ? nodeGlobals() : null,
    nodeResolve({preferBuiltins: isNode, jsnext: true, main: true}),
    commonjs({include: 'node_modules/**'}),
    json(),
    rollupBabel({
      presets: babelPresets,
      babelrc: !useBuiltinConfig,
      runtimeHelpers: useBuiltinConfig,
    }),
    replace(replacements),
    useSizeSnapshot ? sizeSnapshot({printInfo: false}) : null,
    minify ? terser() : null,
    codeSplitting &&
      ((writes = 0) => ({
        onwrite() {
          if (++writes !== input.length) {
            return
          }

          input
            .filter(single => single.indexOf('index.js') === -1)
            .forEach(single => {
              const chunk = path.basename(single)

              writeExtraEntry(chunk.replace(/\..+$/, ''), {
                cjs: `${dirpath}/cjs/${chunk}`,
                esm: `${dirpath}/esm/${chunk}`,
              })
            })
        },
      }))(),
  ].filter(Boolean),
}
<commit_msg>feat(rollup): simplify external (#80)<commit_after>const path = require('path')
const glob = require('glob')
const camelcase = require('lodash.camelcase')
const rollupBabel = require('rollup-plugin-babel')
const commonjs = require('rollup-plugin-commonjs')
const nodeResolve = require('rollup-plugin-node-resolve')
const json = require('rollup-plugin-json')
const replace = require('rollup-plugin-replace')
const {terser} = require('rollup-plugin-terser')
const nodeBuiltIns = require('rollup-plugin-node-builtins')
const nodeGlobals = require('rollup-plugin-node-globals')
const {sizeSnapshot} = require('rollup-plugin-size-snapshot')
const omit = require('lodash.omit')
const {
  pkg,
  hasFile,
  hasPkgProp,
  parseEnv,
  ifFile,
  fromRoot,
  uniq,
  writeExtraEntry,
} = require('../utils')

const here = p => path.join(__dirname, p)
const capitalize = s => s[0].toUpperCase() + s.slice(1)

const minify = parseEnv('BUILD_MINIFY', false)
const format = process.env.BUILD_FORMAT
const isPreact = parseEnv('BUILD_PREACT', false)
const isNode = parseEnv('BUILD_NODE', false)
const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name))
const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false)

const esm = format === 'esm'
const umd = format === 'umd'

const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce(
  (deps, dep) => {
    deps[dep] = capitalize(camelcase(dep))
    return deps
  },
  {},
)

const deps = Object.keys(pkg.dependencies || {})
const peerDeps = Object.keys(pkg.peerDependencies || {})
const defaultExternal = umd ? peerDeps : deps.concat(peerDeps)

const input = glob.sync(
  fromRoot(
    process.env.BUILD_INPUT ||
      ifFile(
        `src/${format}-entry.js`,
        `src/${format}-entry.js`,
        'src/index.js',
      ),
  ),
)
const codeSplitting = input.length > 1

if (
  codeSplitting &&
  uniq(input.map(single => path.basename(single))).length !== input.length
) {
  throw new Error(
    'Filenames of code-splitted entries should be unique to get deterministic output filenames.' +
      `\nReceived those: ${input}.`,
  )
}

const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || ''
const filenamePrefix =
  process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : '')
const globals = parseEnv(
  'BUILD_GLOBALS',
  isPreact ? Object.assign(defaultGlobals, {preact: 'preact'}) : defaultGlobals,
)
const external = parseEnv(
  'BUILD_EXTERNAL',
  isPreact ? defaultExternal.concat(['preact', 'prop-types']) : defaultExternal,
).filter((e, i, arry) => arry.indexOf(e) === i)

if (isPreact) {
  delete globals.react
  delete globals['prop-types'] // TODO: is this necessary?
  external.splice(external.indexOf('react'), 1)
}

const externalPattern = new RegExp(`^(${external.join('|')})($|/)`)

function externalPredicate(id) {
  const isDep = externalPattern.test(id)
  if (umd) {
    // for UMD, we want to bundle all non-peer deps
    return isDep
  }
  // for esm/cjs we want to make all node_modules external
  // TODO: support bundledDependencies if someone needs it ever...
  const isNodeModule = id.includes('node_modules')
  const isRelative = id.startsWith('.')
  return isDep || (!isRelative && !path.isAbsolute(id)) || isNodeModule
}

const filename = [
  pkg.name,
  filenameSuffix,
  `.${format}`,
  minify ? '.min' : null,
  '.js',
]
  .filter(Boolean)
  .join('')

const dirpath = path.join(...[filenamePrefix, 'dist'].filter(Boolean))

const output = [
  {
    name,
    ...(codeSplitting
      ? {dir: path.join(dirpath, format)}
      : {file: path.join(dirpath, filename)}),
    format: esm ? 'es' : format,
    exports: esm ? 'named' : 'auto',
    globals,
  },
]

const useBuiltinConfig =
  !hasFile('.babelrc') &&
  !hasFile('.babelrc.js') &&
  !hasFile('babel.config.js') &&
  !hasPkgProp('babel')
const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : []

const replacements = Object.entries(
  umd ? process.env : omit(process.env, ['NODE_ENV']),
).reduce((acc, [key, value]) => {
  let val
  if (value === 'true' || value === 'false' || Number.isInteger(+value)) {
    val = value
  } else {
    val = JSON.stringify(value)
  }
  acc[`process.env.${key}`] = val
  return acc
}, {})

module.exports = {
  input: codeSplitting ? input : input[0],
  output,
  experimentalCodeSplitting: codeSplitting,
  external: externalPredicate,
  plugins: [
    isNode ? nodeBuiltIns() : null,
    isNode ? nodeGlobals() : null,
    nodeResolve({preferBuiltins: isNode, jsnext: true, main: true}),
    commonjs({include: 'node_modules/**'}),
    json(),
    rollupBabel({
      presets: babelPresets,
      babelrc: !useBuiltinConfig,
      runtimeHelpers: useBuiltinConfig,
    }),
    replace(replacements),
    useSizeSnapshot ? sizeSnapshot({printInfo: false}) : null,
    minify ? terser() : null,
    codeSplitting &&
      ((writes = 0) => ({
        onwrite() {
          if (++writes !== input.length) {
            return
          }

          input
            .filter(single => single.indexOf('index.js') === -1)
            .forEach(single => {
              const chunk = path.basename(single)

              writeExtraEntry(chunk.replace(/\..+$/, ''), {
                cjs: `${dirpath}/cjs/${chunk}`,
                esm: `${dirpath}/esm/${chunk}`,
              })
            })
        },
      }))(),
  ].filter(Boolean),
}
<|endoftext|>


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

import {CONFIGS_DIR} from '../../paths'
import {join} from 'path'

const ESLINT_CONFIG_DIR = join(CONFIGS_DIR, 'eslint')

module.exports = {
  parser: 'Babel-ESLint',
  plugins: [
    'eslint-plugin-babel',
  ],
  extends: [
    join(ESLINT_CONFIG_DIR, 'core', 'best-practices.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'es2015.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'nodejs-and-commonjs.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'possible-errors.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'strict-mode.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'stylistic-issues.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'variables.js'),
  ],
}
<commit_msg>Pass env to eslint<commit_after>// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import {CONFIGS_DIR} from '../../paths'
import {join} from 'path'

let {env} = process.env
const ESLINT_CONFIG_DIR = join(CONFIGS_DIR, 'eslint')

module.exports = {
  env: {
    browser: env.includes('browser'),
    jest: env.includes('jest'),
    node: env.includes('node-js'),
  },
  parser: 'Babel-ESLint',
  plugins: [
    'eslint-plugin-babel',
  ],
  extends: [
    join(ESLINT_CONFIG_DIR, 'core', 'best-practices.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'es2015.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'nodejs-and-commonjs.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'possible-errors.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'strict-mode.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'stylistic-issues.js'),
    join(ESLINT_CONFIG_DIR, 'core', 'variables.js'),
  ],
}
<|endoftext|>


<commit_before>odoo.define('pos_restaurant.network_printer', function (require) {
    "use strict";

    var models = require('point_of_sale.models');
    var screens = require('point_of_sale.screens');
    var core = require('web.core');
    var Session = require('web.Session');
    var gui = require('point_of_sale.gui');
    var Printer = require('pos_restaurant.base');
    var devices = require('point_of_sale.devices');
    var chrome = require('point_of_sale.chrome');
    var PopupWidget = require('point_of_sale.popups');
    var QWeb = core.qweb;
    var mixins = require("web.mixins");

    var _t = core._t;

    models.load_models({
        model: 'restaurant.printer',
        fields: ['network_printer'],
        domain: null,
        loaded: function(self, printers){
            self.printers.forEach(function(item){
                var printer_obj = _.find(printers, function(printer){
                    return printer.id === item.config.id;
                });
                if (printer_obj.network_printer) {
                    item.config.network_printer = printer_obj.network_printer;
                    self.ready.then(function () {
                        var url = self.proxy.host;
                        if (!url) {
                            url = self.config.proxy_ip;
                            var protocol = window.location.protocol;
                            var port = ':8069';
                            if (protocol === "https:") {
                                port = ':443';
                            }
                            if(url.indexOf('//') < 0){
                                url = protocol + '//' + url;
                            }
                            if(url.indexOf(':',5) < 0){
                                url += port;
                            }
                        }
                        item.connection = new Session(void 0, url, { use_cors: true});
                    });
                }
            });
        },
    });

    Printer.include({
        print: function(receipt){
            var self = this;
            if (this.config.network_printer) {
                var network_proxy = this.config.proxy_ip;
                if(receipt) {
                    this.receipt_queue.push(receipt);
                }
                var send_printing_job = function(){
                    if(self.receipt_queue.length > 0) {
                        var r = self.receipt_queue.shift();
                        self.connection.rpc('/hw_proxy/print_xml_receipt', {
                            receipt: r,
                            proxy: network_proxy
                        }, {timeout: 5000}).then(function () {
                            send_printing_job();
                        }, function () {
                            self.receipt_queue.unshift(r);
                        });
                    }
                };
                send_printing_job();
            } else {
                this._super(receipt);
            }
        },
    });

    devices.ProxyDevice.include({
        init: function(parent,options){
            this.network_printer_keptalive = false;
            this.old_network_printer_status = false;
            this._super(parent,options);
        },
        keepalive: function(){
            var self = this;
            function network_printer_status(){
                self.connection.rpc('/hw_proxy/status_network_printers',{},{timeout:2500}).then(function(status){
                    if (self.old_network_printer_status !== status) {
                        self.old_network_printer_status = status;
                        self.trigger('change:network_printer_status', status);
                    }
                }, function(){
                    if (self.old_network_printer_status) {
                        self.old_network_printer_status.forEach(function(item){
                            item.status = 'offline';
                        });
                        self.trigger('change:network_printer_status', self.old_network_printer_status);
                    }
                }).always(function(){
                    setTimeout(network_printer_status,5000);
                });
            }
            if (!this.network_printer_keptalive) {
                this.network_printer_keptalive = true;
                network_printer_status();
            }
            this._super();
        },
        message : function(name,params){
            if (name === 'print_xml_receipt' && this.pos.config.receipt_printer_type === "network_printer") {
                var connection = new Session(void 0, this.pos.proxy.host, {
                    use_cors: true
                });
                var callbacks = this.notifications[name] || [];
                for(var i = 0; i < callbacks.length; i++){
                    callbacks[i](params);
                }
                params.proxy = this.pos.config.receipt_network_printer_ip;
                if(this.get('status').status !== 'disconnected'){
                    return connection.rpc('/hw_proxy/' + name, params || {});
                }
                return (new $.Deferred()).reject();
            }
            return this._super(name, params);
        },
        try_hard_to_connect: function(current_url, options){
            var self = this;
            var port = ':' + (options.port || '8069');
            var url = current_url;
            this.pos.receipt_printer_is_usb = true;
            if(url.indexOf('//') < 0){
                url = 'http://' + url;
            }
            if(url.indexOf(':',5) < 0){
                url += port;
            }
            var network_printers = this.pos.printers.filter(
                function(r){
                    return (r.config.network_printer === true);
                }
            );
            // Network printers are used when using receipt printers
            this.network_printers = [];
            network_printers.forEach(function(item){
                self.network_printers.push({'ip': item.config.proxy_ip, 'status': 'offline', 'name': item.config.name});
            });
            if (this.pos.config.receipt_printer_type === "network_printer") {
                this.pos.receipt_printer_is_usb = false;
            }
            return this._super(url, options).done(function(){
                self.send_network_printers_to_pos_box(url, self.network_printers);
            });
        },
        send_network_printers_to_pos_box: function(url, network_printers) {
            $.ajax({
                url: url + '/hw_proxy/network_printers',
                type: "POST",
                method: "POST",
                dataType: 'json',
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify({'jsonrpc': "2.0", 'method': "call", "params": {'network_printers': network_printers}}),
                timeout: 1000,
            });
        },
    });

    chrome.ProxyStatusWidget.include({
        start:function(){
            var self = this;
            this._super();
            // open popup window with devices from PosBox
            $(".js_proxy").click(function(){
                self.open_printers_in_popup();
            });
            this.pos.proxy.on('change:network_printer_status',this,function(status){
                self.set_network_printer_status(status);
            });
        },
        set_network_printer_status: function(status) {
            this.devices_status = status;
        },
        get_message_from_devices: function(status) {
            var msg = '';
            if (this.pos.config.iface_scan_via_proxy) {
                var scanner = status.drivers.scanner
                ? status.drivers.scanner.status
                : false;
                if( scanner !== 'connected' && scanner !== 'connecting'){
                    this.warning_status = true;
                    msg += _t('Scanner');
                }
            }
            if( this.pos.config.iface_electronic_scale ){
                var scale = status.drivers.scale
                ? status.drivers.scale.status
                : false;
                if( scale !== 'connected' && scale !== 'connecting' ){
                    this.warning_status = true;
                    msg = msg
                    ? msg + ' & '
                    : msg;
                    msg += _t('Scale');
                }
            }
            msg = msg
            ? msg + ' ' + _t('Offline')
            : msg;
            return msg;
        },
        set_smart_status: function(status){
            if(status.status === 'connected') {
                this.warning_status = false;

                if (this.pos.receipt_printer_is_usb) {
                    if( this.pos.config.iface_print_via_proxy ||
                        this.pos.config.iface_cashdrawer ) {
                        var printer = status.drivers.escpos
                        ? status.drivers.escpos.status
                        : false;
                        if( printer !== 'connected' && printer !== 'connecting'){
                            this.warning_status = true;
                            this.usb_printer_status = false;
                        } else {
                            this.usb_printer_status = true;
                        }
                    }
                }

                if (this.devices_status && this.devices_status.length) {
                    var offline_network_printer = this.devices_status.find(function(p) {
                        return p.status === "offline";
                    });
                    if (offline_network_printer) {
                        this.warning_status = true;
                    }
                }

                var message = this.get_message_from_devices(status);

                this.set_status(
                this.warning_status
                ? 'warning'
                : 'connected',
                message);
            } else {
                this._super(status);
            }
        },
        open_printers_in_popup: function() {
            // if exist network printer then open popup
            var network_printer = this.pos.printers.find(function(printer) {
                return printer.config.network_printer === true;
            });
            if (this.pos.config.receipt_printer_type === "network_printer" || network_printer) {
                this.gui.show_popup('proxy_printers', {
                    title: "Printers",
                    value: this.devices_status,
                    usb_status: this.usb_printer_status,
                });
            }
        },
    });

    var ProxyPrintersPopupWidget = PopupWidget.extend({
        template: 'ProxyPrintersPopupWidget',
        init: function(parent, options){
            this._super(parent, options);
            this.printer_cache = new screens.DomCache();
            this.usb_printer_cache = new screens.DomCache();
        },
        show: function(options){
            options = options || {};
            this._super(options);
            this.devices_status = options.value;
            this.usb_status = options.usb_status;
            var network_printers = false;

            // online network printers
            if (this.devices_status) {
                network_printers = this.devices_status;
            }
            // usb printer
            if (this.pos.receipt_printer_is_usb) {
                if (this.usb_status) {
                    this.usb_printer_status = [{'status':'online'}];
                } else {
                    this.usb_printer_status = [{'status':'offline'}];
                }
            } else if (this.pos.config.receipt_printer_type === "usb_printer") {
                this.usb_printer_status = [{'status':'offline'}];
            } else {
                this.usb_printer_status = false;
            }
            this.renderElement();
            this.render_network_list(network_printers);
            if (this.usb_printer_status) {
                this.render_usb_list(this.usb_printer_status);
            }
        },
        render_network_list: function(network_printers) {
            var network_contents = this.$el[0].querySelector('.network-printers-list-contents');
            network_contents.innerHTML = "";
            for(var i = 0, len = Math.min(network_printers.length,1000); i < len; i++){
                var printer = network_printers[i];
                var printerline_html = QWeb.render('NetworkPrinterLine',{widget: this, printer:network_printers[i]});
                var printerline = document.createElement('tbody');
                printerline.innerHTML = printerline_html;
                printerline = printerline.childNodes[1];
                printerline.classList.remove('highlight');
                network_contents.appendChild(printerline);
            }
        },
        render_usb_list: function(usb_printers) {
            var usb_contents = this.$el[0].querySelector('.usb-printers-list-contents');
            usb_contents.innerHTML = "";
            for(var i = 0, len = Math.min(1,1000); i < len; i++){
                var printer = usb_printers[i];
                var printerline = this.usb_printer_cache.get_node(1);
                if (!printerline) {
                    var printerline_html = QWeb.render('USBPrinterLine',{widget: this, printer:usb_printers[i]});
                    printerline = document.createElement('tbody');
                    printerline.innerHTML = printerline_html;
                    printerline = printerline.childNodes[1];
                    this.usb_printer_cache.cache_node(1,printerline);
                }
                printerline.classList.remove('highlight');
                usb_contents.appendChild(printerline);
            }
        },
    });
    gui.define_popup({name:'proxy_printers', widget: ProxyPrintersPopupWidget});
});
<commit_msg>:ambulance: url is undefined<commit_after>odoo.define('pos_restaurant.network_printer', function (require) {
    "use strict";

    var models = require('point_of_sale.models');
    var screens = require('point_of_sale.screens');
    var core = require('web.core');
    var Session = require('web.Session');
    var gui = require('point_of_sale.gui');
    var Printer = require('pos_restaurant.base');
    var devices = require('point_of_sale.devices');
    var chrome = require('point_of_sale.chrome');
    var PopupWidget = require('point_of_sale.popups');
    var QWeb = core.qweb;
    var mixins = require("web.mixins");

    var _t = core._t;

    models.load_models({
        model: 'restaurant.printer',
        fields: ['network_printer'],
        domain: null,
        loaded: function(self, printers){
            self.printers.forEach(function(item){
                var printer_obj = _.find(printers, function(printer){
                    return printer.id === item.config.id;
                });
                if (printer_obj.network_printer && self.config.proxy_ip) {
                    item.config.network_printer = printer_obj.network_printer;
                    self.ready.then(function () {
                        var url = self.proxy.host;
                        if (!url) {
                            url = self.config.proxy_ip;
                            var protocol = window.location.protocol;
                            var port = ':8069';
                            if (protocol === "https:") {
                                port = ':443';
                            }
                            if(url.indexOf('//') < 0){
                                url = protocol + '//' + url;
                            }
                            if(url.indexOf(':',5) < 0){
                                url += port;
                            }
                        }
                        item.connection = new Session(void 0, url, { use_cors: true});
                    });
                }
            });
        },
    });

    Printer.include({
        print: function(receipt){
            var self = this;
            if (this.config.network_printer) {
                var network_proxy = this.config.proxy_ip;
                if(receipt) {
                    this.receipt_queue.push(receipt);
                }
                var send_printing_job = function(){
                    if(self.receipt_queue.length > 0) {
                        var r = self.receipt_queue.shift();
                        self.connection.rpc('/hw_proxy/print_xml_receipt', {
                            receipt: r,
                            proxy: network_proxy
                        }, {timeout: 5000}).then(function () {
                            send_printing_job();
                        }, function () {
                            self.receipt_queue.unshift(r);
                        });
                    }
                };
                send_printing_job();
            } else {
                this._super(receipt);
            }
        },
    });

    devices.ProxyDevice.include({
        init: function(parent,options){
            this.network_printer_keptalive = false;
            this.old_network_printer_status = false;
            this._super(parent,options);
        },
        keepalive: function(){
            var self = this;
            function network_printer_status(){
                self.connection.rpc('/hw_proxy/status_network_printers',{},{timeout:2500}).then(function(status){
                    if (self.old_network_printer_status !== status) {
                        self.old_network_printer_status = status;
                        self.trigger('change:network_printer_status', status);
                    }
                }, function(){
                    if (self.old_network_printer_status) {
                        self.old_network_printer_status.forEach(function(item){
                            item.status = 'offline';
                        });
                        self.trigger('change:network_printer_status', self.old_network_printer_status);
                    }
                }).always(function(){
                    setTimeout(network_printer_status,5000);
                });
            }
            if (!this.network_printer_keptalive) {
                this.network_printer_keptalive = true;
                network_printer_status();
            }
            this._super();
        },
        message : function(name,params){
            if (name === 'print_xml_receipt' && this.pos.config.receipt_printer_type === "network_printer") {
                var connection = new Session(void 0, this.pos.proxy.host, {
                    use_cors: true
                });
                var callbacks = this.notifications[name] || [];
                for(var i = 0; i < callbacks.length; i++){
                    callbacks[i](params);
                }
                params.proxy = this.pos.config.receipt_network_printer_ip;
                if(this.get('status').status !== 'disconnected'){
                    return connection.rpc('/hw_proxy/' + name, params || {});
                }
                return (new $.Deferred()).reject();
            }
            return this._super(name, params);
        },
        try_hard_to_connect: function(current_url, options){
            var self = this;
            var port = ':' + (options.port || '8069');
            var url = current_url;
            this.pos.receipt_printer_is_usb = true;
            if(url.indexOf('//') < 0){
                url = 'http://' + url;
            }
            if(url.indexOf(':',5) < 0){
                url += port;
            }
            var network_printers = this.pos.printers.filter(
                function(r){
                    return (r.config.network_printer === true);
                }
            );
            // Network printers are used when using receipt printers
            this.network_printers = [];
            network_printers.forEach(function(item){
                self.network_printers.push({'ip': item.config.proxy_ip, 'status': 'offline', 'name': item.config.name});
            });
            if (this.pos.config.receipt_printer_type === "network_printer") {
                this.pos.receipt_printer_is_usb = false;
            }
            return this._super(url, options).done(function(){
                self.send_network_printers_to_pos_box(url, self.network_printers);
            });
        },
        send_network_printers_to_pos_box: function(url, network_printers) {
            $.ajax({
                url: url + '/hw_proxy/network_printers',
                type: "POST",
                method: "POST",
                dataType: 'json',
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify({'jsonrpc': "2.0", 'method': "call", "params": {'network_printers': network_printers}}),
                timeout: 1000,
            });
        },
    });

    chrome.ProxyStatusWidget.include({
        start:function(){
            var self = this;
            this._super();
            // open popup window with devices from PosBox
            $(".js_proxy").click(function(){
                self.open_printers_in_popup();
            });
            this.pos.proxy.on('change:network_printer_status',this,function(status){
                self.set_network_printer_status(status);
            });
        },
        set_network_printer_status: function(status) {
            this.devices_status = status;
        },
        get_message_from_devices: function(status) {
            var msg = '';
            if (this.pos.config.iface_scan_via_proxy) {
                var scanner = status.drivers.scanner
                ? status.drivers.scanner.status
                : false;
                if( scanner !== 'connected' && scanner !== 'connecting'){
                    this.warning_status = true;
                    msg += _t('Scanner');
                }
            }
            if( this.pos.config.iface_electronic_scale ){
                var scale = status.drivers.scale
                ? status.drivers.scale.status
                : false;
                if( scale !== 'connected' && scale !== 'connecting' ){
                    this.warning_status = true;
                    msg = msg
                    ? msg + ' & '
                    : msg;
                    msg += _t('Scale');
                }
            }
            msg = msg
            ? msg + ' ' + _t('Offline')
            : msg;
            return msg;
        },
        set_smart_status: function(status){
            if(status.status === 'connected') {
                this.warning_status = false;

                if (this.pos.receipt_printer_is_usb) {
                    if( this.pos.config.iface_print_via_proxy ||
                        this.pos.config.iface_cashdrawer ) {
                        var printer = status.drivers.escpos
                        ? status.drivers.escpos.status
                        : false;
                        if( printer !== 'connected' && printer !== 'connecting'){
                            this.warning_status = true;
                            this.usb_printer_status = false;
                        } else {
                            this.usb_printer_status = true;
                        }
                    }
                }

                if (this.devices_status && this.devices_status.length) {
                    var offline_network_printer = this.devices_status.find(function(p) {
                        return p.status === "offline";
                    });
                    if (offline_network_printer) {
                        this.warning_status = true;
                    }
                }

                var message = this.get_message_from_devices(status);

                this.set_status(
                this.warning_status
                ? 'warning'
                : 'connected',
                message);
            } else {
                this._super(status);
            }
        },
        open_printers_in_popup: function() {
            // if exist network printer then open popup
            var network_printer = this.pos.printers.find(function(printer) {
                return printer.config.network_printer === true;
            });
            if (this.pos.config.receipt_printer_type === "network_printer" || network_printer) {
                this.gui.show_popup('proxy_printers', {
                    title: "Printers",
                    value: this.devices_status,
                    usb_status: this.usb_printer_status,
                });
            }
        },
    });

    var ProxyPrintersPopupWidget = PopupWidget.extend({
        template: 'ProxyPrintersPopupWidget',
        init: function(parent, options){
            this._super(parent, options);
            this.printer_cache = new screens.DomCache();
            this.usb_printer_cache = new screens.DomCache();
        },
        show: function(options){
            options = options || {};
            this._super(options);
            this.devices_status = options.value;
            this.usb_status = options.usb_status;
            var network_printers = false;

            // online network printers
            if (this.devices_status) {
                network_printers = this.devices_status;
            }
            // usb printer
            if (this.pos.receipt_printer_is_usb) {
                if (this.usb_status) {
                    this.usb_printer_status = [{'status':'online'}];
                } else {
                    this.usb_printer_status = [{'status':'offline'}];
                }
            } else if (this.pos.config.receipt_printer_type === "usb_printer") {
                this.usb_printer_status = [{'status':'offline'}];
            } else {
                this.usb_printer_status = false;
            }
            this.renderElement();
            this.render_network_list(network_printers);
            if (this.usb_printer_status) {
                this.render_usb_list(this.usb_printer_status);
            }
        },
        render_network_list: function(network_printers) {
            var network_contents = this.$el[0].querySelector('.network-printers-list-contents');
            network_contents.innerHTML = "";
            for(var i = 0, len = Math.min(network_printers.length,1000); i < len; i++){
                var printer = network_printers[i];
                var printerline_html = QWeb.render('NetworkPrinterLine',{widget: this, printer:network_printers[i]});
                var printerline = document.createElement('tbody');
                printerline.innerHTML = printerline_html;
                printerline = printerline.childNodes[1];
                printerline.classList.remove('highlight');
                network_contents.appendChild(printerline);
            }
        },
        render_usb_list: function(usb_printers) {
            var usb_contents = this.$el[0].querySelector('.usb-printers-list-contents');
            usb_contents.innerHTML = "";
            for(var i = 0, len = Math.min(1,1000); i < len; i++){
                var printer = usb_printers[i];
                var printerline = this.usb_printer_cache.get_node(1);
                if (!printerline) {
                    var printerline_html = QWeb.render('USBPrinterLine',{widget: this, printer:usb_printers[i]});
                    printerline = document.createElement('tbody');
                    printerline.innerHTML = printerline_html;
                    printerline = printerline.childNodes[1];
                    this.usb_printer_cache.cache_node(1,printerline);
                }
                printerline.classList.remove('highlight');
                usb_contents.appendChild(printerline);
            }
        },
    });
    gui.define_popup({name:'proxy_printers', widget: ProxyPrintersPopupWidget});
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import _ from 'lodash';
import $ from 'jquery';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchWeatherFromOpenWeather } from '../actions/index';

import {AsyncTypeahead} from 'react-bootstrap-typeahead'; // ES2015
import 'react-bootstrap-typeahead/css/Typeahead.css';

class SearchBar extends Component {
    constructor(props) {
        super(props);
        // term: updated onInputChange
        // isLoading: needed for typeahead
        // caseSensitive: typeahead setting
        // city: is set to an object when a city is selected from the dropdown
        // options: list of cities returned from searching, used by typeahead
        this.state = {
            term: '',
            isLoading: false,
            caseSensitive: false,
            city: '',
            options: [],
            messageForUser: ''
        };

        this.onInputChange = this.onInputChange.bind(this);
        this.onFormSubmit = this.onFormSubmit.bind(this);
    }

    onFormSubmit(event) {
        event.preventDefault();
        const currentId = parseInt(this.state.city.id);
        // Check if the id has already been searched for.
        const hasCity = _.find(this.props.cities, ['id', currentId])

        if (hasCity) {
            return this.setState({
                messageForUser: 'This city is already listed below.'
            });
        }

        // Fetch weather data.
        this.props.fetchWeatherFromOpenWeather(this.state.city);
        this.setState({ messageForUser: '' });
    }

    // For typeahead
    onInputChange(query) {
        this.setState({isLoading: true});

        $.ajax({
          url:  `http://localhost/react-weather/sqlite/sqliteSearchForName.php?city=${query}`,
          type: 'GET',
          dataType: 'json'
        })
        .done(data => {
          if (data) {
            this.setState({
              isLoading: false,
              options: data.map(row => {
                // Typeahead filters by label.
                // Make a label with city, area, country name
                const label = `${row.city}, ${row.area}, ${row.country}`;
                return {...row, label }
              })
            });
          } else {
            this.setState({
              isLoading: false
            })
          }
        })
        .fail(e => {
          console.log(e);
        }) // ajax
    } // onInputChange

    render() {
        return (

                <form onSubmit={this.onFormSubmit} className="input-group">
                    <AsyncTypeahead
                        isLoading={this.state.isLoading}
                        onSearch={query => this.onInputChange(query)}
                        options={this.state.options}
                        ref="searchFor"

                        placeholder="Check the weather in your favorite cities"
                        className="form-control"
                        value={this.state.term}
                        onChange={city => this.setState({ city: city[0] }) }
                        />

                        <button type="submit" className="btn btn-secondary">Submit</button>

                </form>
                {this.state.messageForUser ?
{this.state.messageForUser}
 : undefined}

        );
    }
}

function mapStateToProps(state) {
    return { cities: state.weather }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ fetchWeatherFromOpenWeather }, dispatch);
}

// null means we don't need state here.
export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);<commit_msg>ref, className, value, term - removing each<commit_after>import React, { Component } from 'react';
import _ from 'lodash';
import $ from 'jquery';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchWeatherFromOpenWeather } from '../actions/index';

import {AsyncTypeahead} from 'react-bootstrap-typeahead'; // ES2015
import 'react-bootstrap-typeahead/css/Typeahead.css';

class SearchBar extends Component {
    constructor(props) {
        super(props);
        // isLoading: needed for typeahead
        // caseSensitive: typeahead setting
        // city: is set to an object when a city is selected from the dropdown
        // options: list of cities returned from searching, used by typeahead
        this.state = {
            isLoading: false,
            caseSensitive: false,
            city: '',
            options: [],
            messageForUser: ''
        };

        this.onInputChange = this.onInputChange.bind(this);
        this.onFormSubmit = this.onFormSubmit.bind(this);
    }

    onFormSubmit(event) {
        event.preventDefault();
        const currentId = parseInt(this.state.city.id);
        // Check if the id has already been searched for.
        const hasCity = _.find(this.props.cities, ['id', currentId])

        if (hasCity) {
            return this.setState({
                messageForUser: 'This city is already listed below.'
            });
        }

        // Fetch weather data.
        this.props.fetchWeatherFromOpenWeather(this.state.city);
        this.setState({ messageForUser: '' });
    }

    // For typeahead
    onInputChange(query) {
        this.setState({isLoading: true});

        $.ajax({
          url:  `http://localhost/react-weather/sqlite/sqliteSearchForName.php?city=${query}`,
          type: 'GET',
          dataType: 'json'
        })
        .done(data => {
          if (data) {
            this.setState({
              isLoading: false,
              options: data.map(row => {
                // Typeahead filters by label.
                // Make a label with city, area, country name
                const label = `${row.city}, ${row.area}, ${row.country}`;
                return {...row, label }
              })
            });
          } else {
            this.setState({
              isLoading: false
            })
          }
        })
        .fail(e => {
          console.log(e);
        }) // ajax
    } // onInputChange

    render() {
        return (

                <form onSubmit={this.onFormSubmit} className="input-group">
                    <AsyncTypeahead
                        isLoading={this.state.isLoading}
                        onSearch={query => this.onInputChange(query)}
                        options={this.state.options}

                        placeholder="Check the weather in your favorite cities"
                        onChange={city => this.setState({ city: city[0] }) }
                        />

                        <button type="submit" className="btn btn-secondary">Submit</button>

                </form>
                {this.state.messageForUser ?
{this.state.messageForUser}
 : undefined}

        );
    }
}

function mapStateToProps(state) {
    return { cities: state.weather }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ fetchWeatherFromOpenWeather }, dispatch);
}

// null means we don't need state here.
export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Grid, Row, Col, Well } from 'react-bootstrap/lib';
import {connect} from 'react-redux';
import config from '../../config';
import Helmet from 'react-helmet';
import superagent from 'superagent';

import { getBlogEntries } from '../../redux/actions/getBlogEntriesActions';

@connect((store) => {
  return {
    getBlogEntriesState: store.getBlogEntries.articleList,
  };
})

export default class Home extends Component {

  componentDidMount() {
    superagent
    .post('/community')
    .send({ loadStatus: 2 })
    .set('Accept', 'application/json')
    .end((error, res) => {
      if (res.body.status === 1) {
        this.props.dispatch(getBlogEntries(res.body.blogArticles));
      }
    });
  }

  static propTypes = {
    userLoggedIn: PropTypes.string
  }

  render() {
    const styles = require('./Home.scss');
    const { getBlogEntriesState } = this.props;
    // require the logo image both from client and server
    const logoImage = require('./logo.png');

    let blogContentDef = '';
    /*getBlogEntriesState.articles.sort(function(a, b){
        return b.unixtime-a.unixtime
    });*/
    getBlogEntriesState.articles.forEach(function(entry){
      blogContentDef += '

' + entry.titel + '

' + entry.markup + '
Author: ' + entry.userEmail + ' | ' + entry.timeFormatted + '
';
    });

    return (

        <Helmet title="Home"/>

{config.app.title}

{config.app.description}

{config.app.subdescription}

Neuste Blogeinträge

          <Grid>
            <Row className="show-grid" style="border: 1px solid red">
              <Col xs={12} md={6} style="border: 1px solid red"><{'Col xs={12} md={8}'} /></Col>
              <Col xs={12} md={6} style="border: 1px solid red"><{'Col xs={6} md={4}'} /></Col>
            </Row>
          </Grid>

    );
  }
}
<commit_msg>mexiko v8.3<commit_after>import React, { Component, PropTypes } from 'react';
import { Grid, Row, Col, Well, Label } from 'react-bootstrap/lib';
import {connect} from 'react-redux';
import config from '../../config';
import Helmet from 'react-helmet';
import superagent from 'superagent';

import { getBlogEntries } from '../../redux/actions/getBlogEntriesActions';

@connect((store) => {
  return {
    getBlogEntriesState: store.getBlogEntries.articleList,
  };
})

export default class Home extends Component {

  componentDidMount() {
    superagent
    .post('/community')
    .send({ loadStatus: 2 })
    .set('Accept', 'application/json')
    .end((error, res) => {
      if (res.body.status === 1) {
        this.props.dispatch(getBlogEntries(res.body.blogArticles));
      }
    });
  }

  static propTypes = {
    userLoggedIn: PropTypes.string
  }

  render() {
    const styles = require('./Home.scss');
    const { getBlogEntriesState } = this.props;
    // require the logo image both from client and server
    const logoImage = require('./logo.png');

    let blogContentDef = '';
    /*getBlogEntriesState.articles.sort(function(a, b){
        return b.unixtime-a.unixtime
    });*/
    getBlogEntriesState.articles.forEach(function(entry){
      blogContentDef += '

' + entry.titel + '

' + entry.markup + '
Author: ' + entry.userEmail + ' | ' + entry.timeFormatted + '
';
    });

    return (

        <Helmet title="Home"/>

{config.app.title}

{config.app.description}

{config.app.subdescription}

Neuste Blogeinträge

          <Grid>
            <Row className="show-grid">
              <Col xs={1}>{'Avatar'}</Col>
              <Col xs={2}>Project</Col>
              <Col xs={4}>{'Titel titel titel titel'}</Col>
              <Col xs={3}>ES6ReactJsSuperagent</Col>
              <Col xs={2}>{'07.11.2016 - 09:37'}</Col>
            </Row>
          </Grid>

    );
  }
}
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
// react-md
import FileInput from 'react-md/lib/FileInputs';
import Checkbox from 'react-md/lib/SelectionControls/Checkbox'
import TextField from 'react-md/lib/TextFields';
import Button from 'react-md/lib/Buttons';
import Switch from 'react-md/lib/SelectionControls/Switch';
import Subheader from 'react-md/lib/Subheaders';
import LinearProgress from 'react-md/lib/Progress/LinearProgress';
// Snackbar
import Snackbar from 'material-ui/Snackbar';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
// redux
import { connect } from 'react-redux'
import { addJob } from '../actions'
import { subtypingDescription } from '../middleware/subtyping'
// axios
import axios from 'axios'
import { API_ROOT } from '../middleware/api'
// router
import { Redirect } from 'react-router'
import Loading from '../components/Loading'

class Subtyping extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      file: null,
      pi: 90,
      amr: false,
      serotype: true,
      vf: true,
      submitted: false,
      open: false,
      msg: '',
      jobId: "",
      hasResult: false,
      groupresults: true,
      progress: 0
    }
  }
  _selectFile = (file) => {
    console.log(file)
    if (!file) { return; }
    this.setState({ file });
  }
  _updatePi = (value) => {
    this.setState({ pi: value });
  }
  _updateSerotype = (value) => {
    this.setState({ serotype: value })
  }
  _updateAmr = (value) => {
    this.setState({ amr: value })
  }
  _updateVf = (value) => {
    this.setState({ vf: value })
  }
  _updateGroupResults = (groupresults) => {
    this.setState({ groupresults })
  }
  _updateUploadProgress = ( progress ) => {
    this.setState({progress})
  }
  _handleSubmit = (e) => {
    e.preventDefault() // disable default HTML form behavior
    // open and msg are for Snackbar
    // uploading is to notify users
    this.setState({
      open: true,
      msg: "Genomes were submitted",
      uploading: true
    });
    // configure a progress for axios
    const createConfig = (_updateUploadProgress) => {
      var config = {
        onUploadProgress: function(progressEvent) {
          var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
          _updateUploadProgress(percentCompleted)
        }
      }
      return config
    }
    // create form data with files
    var data = new FormData()
    this.state.file.map((f) => {
      data.append('file', f)
    })
    // append options
    // to match spfy(angular)'s format, we dont use a dict
    data.append('options.pi', this.state.pi)
    data.append('options.amr', this.state.amr)
    data.append('options.serotype', this.state.serotype)
    data.append('options.vf', this.state.vf)
    // new option added in 4.2.0, group all files into a single result
    // this means polling in handled server-side
    data.append('options.groupresults', this.state.groupresults)
    // put
    axios.post(API_ROOT + 'upload', data, createConfig(this._updateUploadProgress))
      .then(response => {
        console.log(response)
        // no longer uploading
        this.setState({
          uploading: false
        })
        let jobs = response.data
        // handle the return
        for(let job in jobs){
          // console.log(job)
          // console.log(jobs[job].analysis)
          // check filename
          let f = ''
          for (let i in this.state.file){
            // recall that we incl the file path in response
            // console.log(jobs[job].file)
            // console.log(this.state.file[i])
            if(jobs[job].file.includes(this.state.file[i].name)){
              f = this.state.file[i].name
            }
          }
          if(jobs[job].analysis === "Antimicrobial Resistance"){
            this.props.dispatch(addJob(job,
              "Antimicrobial Resistance",
              new Date().toLocaleTimeString(),
              subtypingDescription(f, this.state.pi, false, false, this.state.amr)
            ))
          } else if (jobs[job].analysis === "Virulence Factors and Serotype") {
            let descrip = ''
            if (this.state.vf && this.state.serotype){descrip = "Virulence Factors and Serotype"}
            else if (this.state.vf && !this.state.serotype) {descrip = "Virulence Factors"}
            else if (!this.state.vf && this.state.serotype) {descrip = "Serotype"}
            this.props.dispatch(addJob(job,
              descrip,
              new Date().toLocaleTimeString(),
              subtypingDescription(f, this.state.pi, this.state.serotype, this.state.vf, false)
            ))
          } else if (jobs[job].analysis === "Subtyping") {
            // set the jobId state so we can use Loading
            const jobId = job
            this.setState({jobId})
            // dispatch
            this.props.dispatch(addJob(job,
              "Subtyping",
              new Date().toLocaleTimeString(),
              subtypingDescription(
                (this.state.file.length > 1 ?
                String(this.state.file.length + ' Files')
                :f), this.state.pi, this.state.serotype, this.state.vf, this.state.amr)
            ))
          }
        }
        const hasResult = true
        this.setState({hasResult})
      })
  };
  // Snackbar
  _handleRequestClose = () => {
    this.setState({
      open: false,
    });
  };
  render(){
    const { file, pi, amr, serotype, vf, groupresults, uploading, hasResult, progress } = this.state
    return (

        {/* uploading bar */}
        {(uploading && !hasResult) ?

            <MuiThemeProvider>
              <Snackbar
                open={this.state.open}
                message={this.state.msg}
                autoHideDuration={4000}
                onRequestClose={this.handleRequestClose}
              />
            </MuiThemeProvider>
            <LinearProgress key="progress" id="loading" value ={progress} />
            Uploading... {progress} %

          : ""
        }
        {/* actual form */}
        {(!hasResult && !uploading)?
          <form className="md-text-container md-grid">

              <FileInput
                id="inputFile"
                secondary
                label="Select File(s)"
                onChange={this._selectFile}
                multiple
              />
              <Switch
                id="groupResults"
                name="groupResults"
                label="Group files into a single result"
                checked={groupresults}
                onChange={this._updateGroupResults}
              />
              {!groupresults ?
                <Subheader primaryText="(Will split files & subtyping methods into separate results)" inset />
              : ''}
              <Checkbox
                id="serotype"
                name="check serotype"
                checked={serotype}
                onChange={this._updateSerotype}
                label="Serotype"
              />
              <Checkbox
                id="vf"
                name="check vf"
                checked={vf}
                onChange={this._updateVf}
                label="Virulence Factors"
              />
              <Checkbox
                id="amr"
                name="check amr"
                checked={amr}
                onChange={this._updateAmr}
                label="Antimicrobial Resistance"
              />
              {amr ?
                <Subheader primaryText="(Note: AMR increases run-time by several minutes per file)" inset />
              : ''}
              <TextField
                id="pi"
                value={pi}
                onChange={this._updatePi}
                helpText="Percent Identity for BLAST"
              />
              <Button
                raised
                secondary
                type="submit"
                label="Submit"
                disabled={!file}
                onClick={this._handleSubmit}
              />

              {this.state.file ? this.state.file.map(f => (
                <TextField
                  key={f.name}
                  defaultValue={f.name}
                />
              )) : ''}

          </form> :
          // if results are grouped, display the Loading page
          // else, results are separate and display the JobsList cards page
          (!uploading?(!groupresults?
            <Redirect to='/results' />:
            <Loading jobId={this.state.jobId} />
          ):"")
        }

    )
  }
}

Subtyping = connect()(Subtyping)

export default Subtyping
<commit_msg>CHANGE: switched to circular progress for uploading<commit_after>import React, { PureComponent } from 'react';
// react-md
import FileInput from 'react-md/lib/FileInputs';
import Checkbox from 'react-md/lib/SelectionControls/Checkbox'
import TextField from 'react-md/lib/TextFields';
import Button from 'react-md/lib/Buttons';
import Switch from 'react-md/lib/SelectionControls/Switch';
import Subheader from 'react-md/lib/Subheaders';
import CircularProgress from 'react-md/lib/Progress/CircularProgress';
// Snackbar
import Snackbar from 'material-ui/Snackbar';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
// redux
import { connect } from 'react-redux'
import { addJob } from '../actions'
import { subtypingDescription } from '../middleware/subtyping'
// axios
import axios from 'axios'
import { API_ROOT } from '../middleware/api'
// router
import { Redirect } from 'react-router'
import Loading from '../components/Loading'

class Subtyping extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      file: null,
      pi: 90,
      amr: false,
      serotype: true,
      vf: true,
      submitted: false,
      open: false,
      msg: '',
      jobId: "",
      hasResult: false,
      groupresults: true,
      progress: 0
    }
  }
  _selectFile = (file) => {
    console.log(file)
    if (!file) { return; }
    this.setState({ file });
  }
  _updatePi = (value) => {
    this.setState({ pi: value });
  }
  _updateSerotype = (value) => {
    this.setState({ serotype: value })
  }
  _updateAmr = (value) => {
    this.setState({ amr: value })
  }
  _updateVf = (value) => {
    this.setState({ vf: value })
  }
  _updateGroupResults = (groupresults) => {
    this.setState({ groupresults })
  }
  _updateUploadProgress = ( progress ) => {
    this.setState({progress})
  }
  _handleSubmit = (e) => {
    e.preventDefault() // disable default HTML form behavior
    // open and msg are for Snackbar
    // uploading is to notify users
    this.setState({
      open: true,
      msg: "Genomes were submitted",
      uploading: true
    });
    // configure a progress for axios
    const createConfig = (_updateUploadProgress) => {
      var config = {
        onUploadProgress: function(progressEvent) {
          var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
          _updateUploadProgress(percentCompleted)
        }
      }
      return config
    }
    // create form data with files
    var data = new FormData()
    this.state.file.map((f) => {
      data.append('file', f)
    })
    // append options
    // to match spfy(angular)'s format, we dont use a dict
    data.append('options.pi', this.state.pi)
    data.append('options.amr', this.state.amr)
    data.append('options.serotype', this.state.serotype)
    data.append('options.vf', this.state.vf)
    // new option added in 4.2.0, group all files into a single result
    // this means polling in handled server-side
    data.append('options.groupresults', this.state.groupresults)
    // put
    axios.post(API_ROOT + 'upload', data, createConfig(this._updateUploadProgress))
      .then(response => {
        console.log(response)
        // no longer uploading
        this.setState({
          uploading: false
        })
        let jobs = response.data
        // handle the return
        for(let job in jobs){
          // console.log(job)
          // console.log(jobs[job].analysis)
          // check filename
          let f = ''
          for (let i in this.state.file){
            // recall that we incl the file path in response
            // console.log(jobs[job].file)
            // console.log(this.state.file[i])
            if(jobs[job].file.includes(this.state.file[i].name)){
              f = this.state.file[i].name
            }
          }
          if(jobs[job].analysis === "Antimicrobial Resistance"){
            this.props.dispatch(addJob(job,
              "Antimicrobial Resistance",
              new Date().toLocaleTimeString(),
              subtypingDescription(f, this.state.pi, false, false, this.state.amr)
            ))
          } else if (jobs[job].analysis === "Virulence Factors and Serotype") {
            let descrip = ''
            if (this.state.vf && this.state.serotype){descrip = "Virulence Factors and Serotype"}
            else if (this.state.vf && !this.state.serotype) {descrip = "Virulence Factors"}
            else if (!this.state.vf && this.state.serotype) {descrip = "Serotype"}
            this.props.dispatch(addJob(job,
              descrip,
              new Date().toLocaleTimeString(),
              subtypingDescription(f, this.state.pi, this.state.serotype, this.state.vf, false)
            ))
          } else if (jobs[job].analysis === "Subtyping") {
            // set the jobId state so we can use Loading
            const jobId = job
            this.setState({jobId})
            // dispatch
            this.props.dispatch(addJob(job,
              "Subtyping",
              new Date().toLocaleTimeString(),
              subtypingDescription(
                (this.state.file.length > 1 ?
                String(this.state.file.length + ' Files')
                :f), this.state.pi, this.state.serotype, this.state.vf, this.state.amr)
            ))
          }
        }
        const hasResult = true
        this.setState({hasResult})
      })
  };
  // Snackbar
  _handleRequestClose = () => {
    this.setState({
      open: false,
    });
  };
  render(){
    const { file, pi, amr, serotype, vf, groupresults, uploading, hasResult, progress } = this.state
    return (

        {/* uploading bar */}
        {(uploading && !hasResult) ?

            <MuiThemeProvider>
              <Snackbar
                open={this.state.open}
                message={this.state.msg}
                autoHideDuration={4000}
                onRequestClose={this.handleRequestClose}
              />
            </MuiThemeProvider>
            <CircularProgress key="progress" id="loading" value={progress} centered={false} />
            Uploading... {progress} %

          : ""
        }
        {/* actual form */}
        {(!hasResult && !uploading)?
          <form className="md-text-container md-grid">

              <FileInput
                id="inputFile"
                secondary
                label="Select File(s)"
                onChange={this._selectFile}
                multiple
              />
              <Switch
                id="groupResults"
                name="groupResults"
                label="Group files into a single result"
                checked={groupresults}
                onChange={this._updateGroupResults}
              />
              {!groupresults ?
                <Subheader primaryText="(Will split files & subtyping methods into separate results)" inset />
              : ''}
              <Checkbox
                id="serotype"
                name="check serotype"
                checked={serotype}
                onChange={this._updateSerotype}
                label="Serotype"
              />
              <Checkbox
                id="vf"
                name="check vf"
                checked={vf}
                onChange={this._updateVf}
                label="Virulence Factors"
              />
              <Checkbox
                id="amr"
                name="check amr"
                checked={amr}
                onChange={this._updateAmr}
                label="Antimicrobial Resistance"
              />
              {amr ?
                <Subheader primaryText="(Note: AMR increases run-time by several minutes per file)" inset />
              : ''}
              <TextField
                id="pi"
                value={pi}
                onChange={this._updatePi}
                helpText="Percent Identity for BLAST"
              />
              <Button
                raised
                secondary
                type="submit"
                label="Submit"
                disabled={!file}
                onClick={this._handleSubmit}
              />

              {this.state.file ? this.state.file.map(f => (
                <TextField
                  key={f.name}
                  defaultValue={f.name}
                />
              )) : ''}

          </form> :
          // if results are grouped, display the Loading page
          // else, results are separate and display the JobsList cards page
          (!uploading?(!groupresults?
            <Redirect to='/results' />:
            <Loading jobId={this.state.jobId} />
          ):"")
        }

    )
  }
}

Subtyping = connect()(Subtyping)

export default Subtyping
<|endoftext|>


<commit_before>L.Control.Fullscreen = L.Control.extend({
    options: {
        position: 'topleft',
        title: 'View Fullscreen'
    },

    onAdd: function (map) {
        var container = L.DomUtil.create('div', 'leaflet-control-fullscreen leaflet-bar leaflet-control'),
            link = L.DomUtil.create('a', 'leaflet-control-fullscreen-button leaflet-bar-part', container);

        this._map = map;

        link.href = '#';
        link.title = this.options.title;

        L.DomEvent.on(link, 'click', this._click, this);

        return container;
    },

    _click: function (e) {
        L.DomEvent.stopPropagation(e);
        L.DomEvent.preventDefault(e);
        this._map.toggleFullscreen();
    }
});

L.Map.include({
    isFullscreen: function () {
        return this._isFullscreen;
    },

    toggleFullscreen: function () {
        var container = this.getContainer();
        if (this.isFullscreen()) {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.webkitCancelFullScreen) {
                document.webkitCancelFullScreen();
            } else {
                L.DomUtil.removeClass(container, 'leaflet-pseudo-fullscreen');
                this._isFullscreen = false;
                this.fire('fullscreenchange');
            }
        } else {
            if (container.requestFullscreen) {
                container.requestFullscreen();
            } else if (container.mozRequestFullScreen) {
                container.mozRequestFullScreen();
            } else if (container.webkitRequestFullscreen) {
                container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
            } else {
                L.DomUtil.addClass(container, 'leaflet-pseudo-fullscreen');
                this._isFullscreen = true;
                this.fire('fullscreenchange');
            }
        }
    },

    _onFullscreenChange: function () {
        var fullscreenElement =
            document.fullscreenElement ||
            document.mozFullScreenElement ||
            document.webkitFullscreenElement;

        if (fullscreenElement === this.getContainer()) {
            this._isFullscreen = true;
            this.fire('fullscreenchange');
        } else if (this._isFullscreen) {
            this._isFullscreen = false;
            this.fire('fullscreenchange');
        }
    }
});

L.Map.mergeOptions({
    fullscreenControl: false
});

L.Map.addInitHook(function () {
    if (this.options.fullscreenControl) {
        this.fullscreenControl = new L.Control.Fullscreen();
        this.addControl(this.fullscreenControl);
    }

    var fullscreenchange;

    if ('onfullscreenchange' in document) {
        fullscreenchange = 'fullscreenchange';
    } else if ('onmozfullscreenchange' in document) {
        fullscreenchange = 'mozfullscreenchange';
    } else if ('onwebkitfullscreenchange' in document) {
        fullscreenchange = 'webkitfullscreenchange';
    }

    if (fullscreenchange) {
        this.on('load', function () {
            L.DomEvent.on(document, fullscreenchange, this._onFullscreenChange, this);
        });

        this.on('unload', function () {
            L.DomEvent.off(document, fullscreenchange, this._onFullscreenChange);
        });
    }
});

L.control.fullscreen = function (options) {
    return new L.Control.Fullscreen(options);
};
<commit_msg>Use invalidateSize()<commit_after>L.Control.Fullscreen = L.Control.extend({
    options: {
        position: 'topleft',
        title: 'View Fullscreen'
    },

    onAdd: function (map) {
        var container = L.DomUtil.create('div', 'leaflet-control-fullscreen leaflet-bar leaflet-control'),
            link = L.DomUtil.create('a', 'leaflet-control-fullscreen-button leaflet-bar-part', container);

        this._map = map;

        link.href = '#';
        link.title = this.options.title;

        L.DomEvent.on(link, 'click', this._click, this);

        return container;
    },

    _click: function (e) {
        L.DomEvent.stopPropagation(e);
        L.DomEvent.preventDefault(e);
        this._map.toggleFullscreen();
    }
});

L.Map.include({
    isFullscreen: function () {
        return this._isFullscreen;
    },

    toggleFullscreen: function () {
        var container = this.getContainer();
        if (this.isFullscreen()) {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.webkitCancelFullScreen) {
                document.webkitCancelFullScreen();
            } else {
                L.DomUtil.removeClass(container, 'leaflet-pseudo-fullscreen');
                this.invalidateSize();
                this._isFullscreen = false;
                this.fire('fullscreenchange');
            }
        } else {
            if (container.requestFullscreen) {
                container.requestFullscreen();
            } else if (container.mozRequestFullScreen) {
                container.mozRequestFullScreen();
            } else if (container.webkitRequestFullscreen) {
                container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
            } else {
                L.DomUtil.addClass(container, 'leaflet-pseudo-fullscreen');
                this.invalidateSize();
                this._isFullscreen = true;
                this.fire('fullscreenchange');
            }
        }
    },

    _onFullscreenChange: function () {
        var fullscreenElement =
            document.fullscreenElement ||
            document.mozFullScreenElement ||
            document.webkitFullscreenElement;

        if (fullscreenElement === this.getContainer()) {
            this._isFullscreen = true;
            this.fire('fullscreenchange');
        } else if (this._isFullscreen) {
            this._isFullscreen = false;
            this.fire('fullscreenchange');
        }
    }
});

L.Map.mergeOptions({
    fullscreenControl: false
});

L.Map.addInitHook(function () {
    if (this.options.fullscreenControl) {
        this.fullscreenControl = new L.Control.Fullscreen();
        this.addControl(this.fullscreenControl);
    }

    var fullscreenchange;

    if ('onfullscreenchange' in document) {
        fullscreenchange = 'fullscreenchange';
    } else if ('onmozfullscreenchange' in document) {
        fullscreenchange = 'mozfullscreenchange';
    } else if ('onwebkitfullscreenchange' in document) {
        fullscreenchange = 'webkitfullscreenchange';
    }

    if (fullscreenchange) {
        this.on('load', function () {
            L.DomEvent.on(document, fullscreenchange, this._onFullscreenChange, this);
        });

        this.on('unload', function () {
            L.DomEvent.off(document, fullscreenchange, this._onFullscreenChange);
        });
    }
});

L.control.fullscreen = function (options) {
    return new L.Control.Fullscreen(options);
};
<|endoftext|>


<commit_before>function createElement( tag, attrs, ...children ) {
	if ( tag ) {
		const vNode = {
			tag
		};

		if ( attrs ) {
			if ( attrs.key !== undefined ) {
				vNode.key = attrs.key;
				delete attrs.key;
			}
			vNode.attrs = attrs;
		}

		if ( children.length ) {
			vNode.children = children;
		}

		return vNode;
	} else {
		return {
			text: tag
		};
	}
}

export default {
	createElement
};
<commit_msg>Revert "Simplify children handling."<commit_after>import isArray from '../util/isArray';

function createChildren( children ) {
	const childrenArray = [];

	if ( isArray( children ) ) {
		for ( let i = 0; i < children.length; i++ ) {
			const childItem = children[i];

			childrenArray.push( childItem );
		}
	}
	return childrenArray;
}

function createElement( tag, attrs, ...children ) {
	if ( tag ) {
		const vNode = {
			tag
		};

		if ( attrs ) {
			if ( attrs.key !== undefined ) {
				vNode.key = attrs.key;
				delete attrs.key;
			}
			vNode.attrs = attrs;
		}
		if ( children ) {
			if ( children.length ) {
				vNode.children = createChildren( children );
			} else {
				vNode.children = children[0];
			}
		}
		return vNode;
	} else {
		return {
			text: tag
		};
	}
}

export default {
	createElement
};
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const utils = require('../utils');
const Log = require('../log');
const mix = require('../mixins/mix');
const Heritable = require('../mixins/heritable');
const EntityMixin = require('../mixins/entity');

module.exports = class Entity extends mix(Heritable, EntityMixin) {

    constructor(name, config, parent) {
        super();
        this.isEntity = true;
        this._contextData = {};
        this._hasResolvedContext = false;
        this.initEntity(name, config, parent);
        this.setHeritable(parent);

        Object.defineProperty(this, 'status', {
            enumerable: true,
            get() {
                return this.source.statusInfo(this.getProp('status'));
            },
        });

        this.setProps(config);
    }

    getResolvedContext() {
        return this.source.resolve(this.context);
    }

    hasContext() {
        return this.getResolvedContext().then(context => Object.keys(context).length);
    }

    getContext() {
        return this._contextData;
    }

    toJSON() {
        const self = super.toJSON();
        self.isEntity = true;
        return self;
    }

    static defineProperty(key, opts) {
        if (_.isPlainObject(opts)) {
            Object.defineProperty(this.prototype, key, opts);
        } else {
            Object.defineProperty(this.prototype, key, {
                enumerable: true,
                writable: true,
                value: opts
            });
        }
    }

};
<commit_msg>Clone context to prevent pass-by-reference issues<commit_after>'use strict';

const _ = require('lodash');
const utils = require('../utils');
const Log = require('../log');
const mix = require('../mixins/mix');
const Heritable = require('../mixins/heritable');
const EntityMixin = require('../mixins/entity');

module.exports = class Entity extends mix(Heritable, EntityMixin) {

    constructor(name, config, parent) {
        super();
        this.isEntity = true;
        this._contextData = {};
        this._hasResolvedContext = false;
        this.initEntity(name, config, parent);
        this.setHeritable(parent);

        Object.defineProperty(this, 'status', {
            enumerable: true,
            get() {
                return this.source.statusInfo(this.getProp('status'));
            },
        });

        this.setProps(config);
    }

    getResolvedContext() {
        return this.source.resolve(this.context);
    }

    hasContext() {
        return this.getResolvedContext().then(context => Object.keys(context).length);
    }

    getContext() {
        return _.cloneDeep(this._contextData);
    }

    toJSON() {
        const self = super.toJSON();
        self.isEntity = true;
        return self;
    }

    static defineProperty(key, opts) {
        if (_.isPlainObject(opts)) {
            Object.defineProperty(this.prototype, key, opts);
        } else {
            Object.defineProperty(this.prototype, key, {
                enumerable: true,
                writable: true,
                value: opts
            });
        }
    }

};
<|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
==================================================================================================
*/

(function(undef)
{
	/** {Map} Maps simple property names to global property IDs */
	var propertyNameToId = {};

	/** {=String} Field where the data is stored */
	var store = "$$data";

	/**
	 * Property handling for simple key/value like properties which might have an optional init value.
	 *
	 * Supports the following configuration keys:
	 *
	 * - `type`: Check the incoming value for the given type or function.
	 * - `apply`: Link to function to call after a new value has been stored. The signature of the method is
	 * `function(newValue, oldValue)`
	 * - `fire`: Event to fire after a new value has been stored (and apply has been called). The listeners
	 * are called with 3 parameters: value, old value and property name.
	 * - `init`: Init value for the property. If no value is set or the property gets reset, the getter
	 * will return the `init` value.
	 * - `nullable`: Whether the property is able to store null values. This also allows the system to
	 * return `null` when no other value is available. Otherwise an error is thrown whenever no value is
	 * available.
	 *
	 * #break(core.property.Debug)
	 */
	core.Module("core.property.Simple",
	{
		/**
		 * {Map} Creates a new set of member methods for the given property @config {Map}.
		 *
		 * Please note that you need to define one of "init" or "nullable". Otherwise you
		 * might get errors during runtime function calls.
		 */
		create : function(config)
		{
			/*
			---------------------------------------------------------------------------
				 INTRO
			---------------------------------------------------------------------------
			*/

			// Shorthands: Better compression/obfuscation/performance
			var propertyName = config.name;
			var propertyNullable = config.nullable;
			var propertyInit = config.init;
			var propertyType = config.type;
			var propertyFire = config.fire;
			var propertyApply = config.apply;

			// Validation
			if (jasy.Env.isSet("debug"))
			{
				/** #require(ext.sugar.Object) */
				var invalidKeys = Object.validateKeys(config, "name,nullable,init,type,fire,apply".split(","));
				if (invalidKeys.length > 0) {
					throw new Error("Property declaration of " + propertyName + " contains invalid configuration keys: " + invalidKeys.join(", ") + "!");
				}

				core.Assert.isType(propertyName, "String");

				if (propertyNullable !== undef) {
					core.Assert.isType(propertyNullable, "Boolean");
				}

				if (propertyType) {
					// TODO
				}

				if (propertyFire) {
					core.Assert.isType(propertyFire, "String");
				}

				if (propertyApply) {
					core.Assert.isType(propertyApply, "Function");
				}
			}

			// Generate property ID
			// Identically named property might store data on the same field
			// as in this case this is typicall on different classes.
			var propertyId = propertyNameToId[propertyName];
			if (!propertyId) {
				propertyId = propertyNameToId[propertyName] = (core.property.Core.ID++);
			}

			// Prepare return value
			var members = {};

			/*
			---------------------------------------------------------------------------
				 METHODS :: GET
			---------------------------------------------------------------------------
			*/

			members.get = function()
			{
				var context, data, value;
				context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkGetter(context, config, arguments);
				}

				data = context[store];
				if (data) {
					value = data[propertyId];
				}

				if (value === undef)
				{
					if (propertyInit !== undef) {
						return propertyInit;
					}

					if (jasy.Env.isSet("debug"))
					{
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during get())");
						}
					}

					value = null;
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: INIT
			---------------------------------------------------------------------------
			*/

			if (propertyInit !== undef)
			{
				members.init = function()
				{
					var context=this, data=context[store];

					// Check whether there is already local data (which is higher prio than init data)
					if (!data || data[propertyId] === undef)
					{
						// Call apply
						if (propertyApply) {
							propertyApply.call(context, propertyInit, undef);
						}

						// Fire event
						if (propertyFire) {
							context.fireEvent(propertyFire, propertyInit, undef, propertyName);
						}
					}
				};
			}

			/*
			---------------------------------------------------------------------------
				 METHODS :: SET
			---------------------------------------------------------------------------
			*/

			members.set = function(value)
			{
				var context=this, data, old;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkSetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					data = context[store] = {};
				} else {
					old = data[propertyId];
				}

				if (value !== old)
				{
					if (old === undef && propertyInit !== undef) {
						old = propertyInit;
					}

					data[propertyId] = value;

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire) {
						context.fireEvent(propertyFire, value, old, propertyName);
					}
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: RESET
			---------------------------------------------------------------------------
			*/

			members.reset = function()
			{
				var context, data, old, value;
				context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkResetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					return;
				}

				old = data[propertyId];
				value = undef;

				if (old !== value)
				{
					data[propertyId] = value;

					if (propertyInit !== undef) {
						value = propertyInit;
					}
					else if (jasy.Env.isSet("debug"))
					{
						// Still no value. We warn about that the property is not nullable.
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during reset())");
						}
					}

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire) {
						context.fireEvent(propertyFire, value, old, propertyName);
					}
				}
			};

			/*
			---------------------------------------------------------------------------
				 DONE
			---------------------------------------------------------------------------
			*/

			return members;
		}
	});
})()
<commit_msg>Replaced fireEvent() in old stye with new style pooled event object creation.<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
==================================================================================================
*/

(function(undef)
{
	/** {Map} Maps simple property names to global property IDs */
	var propertyNameToId = {};

	/** {=String} Field where the data is stored */
	var store = "$$data";

	/**
	 * Property handling for simple key/value like properties which might have an optional init value.
	 *
	 * Supports the following configuration keys:
	 *
	 * - `type`: Check the incoming value for the given type or function.
	 * - `apply`: Link to function to call after a new value has been stored. The signature of the method is
	 * `function(newValue, oldValue)`
	 * - `fire`: Event to fire after a new value has been stored (and apply has been called). The listeners
	 * are called with 3 parameters: value, old value and property name.
	 * - `init`: Init value for the property. If no value is set or the property gets reset, the getter
	 * will return the `init` value.
	 * - `nullable`: Whether the property is able to store null values. This also allows the system to
	 * return `null` when no other value is available. Otherwise an error is thrown whenever no value is
	 * available.
	 *
	 * #break(core.property.Debug)
	 * #break(core.property.Event)
	 */
	core.Module("core.property.Simple",
	{
		/**
		 * {Map} Creates a new set of member methods for the given property @config {Map}.
		 *
		 * Please note that you need to define one of "init" or "nullable". Otherwise you
		 * might get errors during runtime function calls.
		 */
		create : function(config)
		{
			/*
			---------------------------------------------------------------------------
				 INTRO
			---------------------------------------------------------------------------
			*/

			// Shorthands: Better compression/obfuscation/performance
			var propertyName = config.name;
			var propertyNullable = config.nullable;
			var propertyInit = config.init;
			var propertyType = config.type;
			var propertyFire = config.fire;
			var propertyApply = config.apply;

			// Validation
			if (jasy.Env.isSet("debug"))
			{
				/** #require(ext.sugar.Object) */
				var invalidKeys = Object.validateKeys(config, "name,nullable,init,type,fire,apply".split(","));
				if (invalidKeys.length > 0) {
					throw new Error("Property declaration of " + propertyName + " contains invalid configuration keys: " + invalidKeys.join(", ") + "!");
				}

				core.Assert.isType(propertyName, "String");

				if (propertyNullable !== undef) {
					core.Assert.isType(propertyNullable, "Boolean");
				}

				if (propertyType) {
					// TODO
				}

				if (propertyFire) {
					core.Assert.isType(propertyFire, "String");
				}

				if (propertyApply) {
					core.Assert.isType(propertyApply, "Function");
				}
			}

			// Generate property ID
			// Identically named property might store data on the same field
			// as in this case this is typicall on different classes.
			var propertyId = propertyNameToId[propertyName];
			if (!propertyId) {
				propertyId = propertyNameToId[propertyName] = (core.property.Core.ID++);
			}

			// Prepare return value
			var members = {};

			/*
			---------------------------------------------------------------------------
				 METHODS :: GET
			---------------------------------------------------------------------------
			*/

			members.get = function()
			{
				var context, data, value;
				context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkGetter(context, config, arguments);
				}

				data = context[store];
				if (data) {
					value = data[propertyId];
				}

				if (value === undef)
				{
					if (propertyInit !== undef) {
						return propertyInit;
					}

					if (jasy.Env.isSet("debug"))
					{
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during get())");
						}
					}

					value = null;
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: INIT
			---------------------------------------------------------------------------
			*/

			if (propertyInit !== undef)
			{
				members.init = function()
				{
					var context=this, data=context[store];

					// Check whether there is already local data (which is higher prio than init data)
					if (!data || data[propertyId] === undef)
					{
						// Call apply
						if (propertyApply) {
							propertyApply.call(context, propertyInit, undef);
						}

						// Fire event
						if (propertyFire)
						{
							var eventObject = core.property.Event.obtain(propertyFire, propertyInit, undef, propertyName);
							context.dispatchEvent(eventObject);
							eventObject.release();
						}
					}
				};
			}

			/*
			---------------------------------------------------------------------------
				 METHODS :: SET
			---------------------------------------------------------------------------
			*/

			members.set = function(value)
			{
				var context=this, data, old;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkSetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					data = context[store] = {};
				} else {
					old = data[propertyId];
				}

				if (value !== old)
				{
					if (old === undef && propertyInit !== undef) {
						old = propertyInit;
					}

					data[propertyId] = value;

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire)
					{
						var eventObject = core.property.Event.obtain(propertyFire, value, old, propertyName);
						context.dispatchEvent(eventObject);
						eventObject.release();
					}
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: RESET
			---------------------------------------------------------------------------
			*/

			members.reset = function()
			{
				var context, data, old, value;
				context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkResetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					return;
				}

				old = data[propertyId];
				value = undef;

				if (old !== value)
				{
					data[propertyId] = value;

					if (propertyInit !== undef) {
						value = propertyInit;
					}
					else if (jasy.Env.isSet("debug"))
					{
						// Still no value. We warn about that the property is not nullable.
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during reset())");
						}
					}

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire)
					{
						var eventObject = core.property.Event.obtain(propertyFire, value, old, propertyName);
						context.dispatchEvent(eventObject);
						eventObject.release();
					}
				}
			};

			/*
			---------------------------------------------------------------------------
				 DONE
			---------------------------------------------------------------------------
			*/

			return members;
		}
	});
})()
<|endoftext|>