<commit_before>import Vue from '../instance/vue'
import config from '../config'
import {
  extend,
  set,
  isObject,
  isArray,
  isPlainObject,
  hasOwn,
  camelize
} from './lang'
import { warn } from './debug'
import { commonTagRE, reservedTagRE } from './component'

/**
 * Option overwriting strategies are functions that handle
 * how to merge a parent option value and a child option
 * value into the final value.
 *
 * All strategy functions follow the same signature:
 *
 * @param {*} parentVal
 * @param {*} childVal
 * @param {Vue} [vm]
 */

var strats = config.optionMergeStrategies = Object.create(null)

/**
 * Helper that recursively merges two data objects together.
 */

function mergeData (to, from) {
  var key, toVal, fromVal
  for (key in from) {
    toVal = to[key]
    fromVal = from[key]
    if (!hasOwn(to, key)) {
      set(to, key, fromVal)
    } else if (isObject(toVal) && isObject(fromVal)) {
      mergeData(toVal, fromVal)
    }
  }
  return to
}

/**
 * Data
 */

strats.data = function (parentVal, childVal, vm) {
  if (!vm) {
    // in a Vue.extend merge, both should be functions
    if (!childVal) {
      return parentVal
    }
    if (typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.'
      )
      return parentVal
    }
    if (!parentVal) {
      return childVal
    }
    // when parentVal & childVal are both present,
    // we need to return a function that returns the
    // merged result of both functions... no need to
    // check if parentVal is a function here because
    // it has to be a function to pass previous merges.
    return function mergedDataFn () {
      return mergeData(
        childVal.call(this),
        parentVal.call(this)
      )
    }
  } else if (parentVal || childVal) {
    return function mergedInstanceDataFn () {
      // instance merge
      var instanceData = typeof childVal === 'function'
        ? childVal.call(vm)
        : childVal
      var defaultData = typeof parentVal === 'function'
        ? parentVal.call(vm)
        : undefined
      if (instanceData) {
        return mergeData(instanceData, defaultData)
      } else {
        return defaultData
      }
    }
  }
}

/**
 * El
 */

strats.el = function (parentVal, childVal, vm) {
  if (!vm && childVal && typeof childVal !== 'function') {
    process.env.NODE_ENV !== 'production' && warn(
      'The "el" option should be a function ' +
      'that returns a per-instance value in component ' +
      'definitions.'
    )
    return
  }
  var ret = childVal || parentVal
  // invoke the element factory if this is instance merge
  return vm && typeof ret === 'function'
    ? ret.call(vm)
    : ret
}

/**
 * Hooks and param attributes are merged as arrays.
 */

strats.init =
strats.created =
strats.ready =
strats.attached =
strats.detached =
strats.beforeCompile =
strats.compiled =
strats.beforeDestroy =
strats.destroyed = function (parentVal, childVal) {
  return childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : isArray(childVal)
        ? childVal
        : [childVal]
    : parentVal
}

/**
 * 0.11 deprecation warning
 */

strats.paramAttributes = function () {
  /* istanbul ignore next */
  process.env.NODE_ENV !== 'production' && warn(
    '"paramAttributes" option has been deprecated in 0.12. ' +
    'Use "props" instead.'
  )
}

/**
 * Assets
 *
 * When a vm is present (instance creation), we need to do
 * a three-way merge between constructor options, instance
 * options and parent options.
 */

function mergeAssets (parentVal, childVal) {
  var res = Object.create(parentVal)
  return childVal
    ? extend(res, guardArrayAssets(childVal))
    : res
}

config._assetTypes.forEach(function (type) {
  strats[type + 's'] = mergeAssets
})

/**
 * Events & Watchers.
 *
 * Events & watchers hashes should not overwrite one
 * another, so we merge them as arrays.
 */

strats.watch =
strats.events = function (parentVal, childVal) {
  if (!childVal) return parentVal
  if (!parentVal) return childVal
  var ret = {}
  extend(ret, parentVal)
  for (var key in childVal) {
    var parent = ret[key]
    var child = childVal[key]
    if (parent && !isArray(parent)) {
      parent = [parent]
    }
    ret[key] = parent
      ? parent.concat(child)
      : [child]
  }
  return ret
}

/**
 * Other object hashes.
 */

strats.props =
strats.methods =
strats.computed = function (parentVal, childVal) {
  if (!childVal) return parentVal
  if (!parentVal) return childVal
  var ret = Object.create(null)
  extend(ret, parentVal)
  extend(ret, childVal)
  return ret
}

/**
 * Default strategy.
 */

var defaultStrat = function (parentVal, childVal) {
  return childVal === undefined
    ? parentVal
    : childVal
}

/**
 * Make sure component options get converted to actual
 * constructors.
 *
 * @param {Object} options
 */

function guardComponents (options) {
  if (options.components) {
    var components = options.components =
      guardArrayAssets(options.components)
    var def
    var ids = Object.keys(components)
    for (var i = 0, l = ids.length; i < l; i++) {
      var key = ids[i]
      if (commonTagRE.test(key) || reservedTagRE.test(key)) {
        process.env.NODE_ENV !== 'production' && warn(
          'Do not use built-in or reserved HTML elements as component ' +
          'id: ' + key
        )
        continue
      }
      def = components[key]
      if (isPlainObject(def)) {
        components[key] = Vue.extend(def)
      }
    }
  }
}

/**
 * Ensure all props option syntax are normalized into the
 * Object-based format.
 *
 * @param {Object} options
 */

function guardProps (options) {
  var props = options.props
  var i, val
  if (isArray(props)) {
    options.props = {}
    i = props.length
    while (i--) {
      val = props[i]
      if (typeof val === 'string') {
        options.props[val] = null
      } else if (val.name) {
        options.props[val.name] = val
      }
    }
  } else if (isPlainObject(props)) {
    var keys = Object.keys(props)
    i = keys.length
    while (i--) {
      val = props[keys[i]]
      if (typeof val === 'function') {
        props[keys[i]] = { type: val }
      }
    }
  }
}

/**
 * Guard an Array-format assets option and converted it
 * into the key-value Object format.
 *
 * @param {Object|Array} assets
 * @return {Object}
 */

function guardArrayAssets (assets) {
  if (isArray(assets)) {
    var res = {}
    var i = assets.length
    var asset
    while (i--) {
      asset = assets[i]
      var id = typeof asset === 'function'
        ? ((asset.options && asset.options.name) || asset.id)
        : (asset.name || asset.id)
      if (!id) {
        process.env.NODE_ENV !== 'production' && warn(
          'Array-syntax assets must provide a "name" or "id" field.'
        )
      } else {
        res[id] = asset
      }
    }
    return res
  }
  return assets
}

/**
 * Merge two option objects into a new one.
 * Core utility used in both instantiation and inheritance.
 *
 * @param {Object} parent
 * @param {Object} child
 * @param {Vue} [vm] - if vm is present, indicates this is
 *                     an instantiation merge.
 */

export function mergeOptions (parent, child, vm) {
  guardComponents(child)
  guardProps(child)
  var options = {}
  var key
  if (child.mixins) {
    for (var i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }
  for (key in parent) {
    mergeField(key)
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
    var strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}

/**
 * Resolve an asset.
 * This function is used because child instances need access
 * to assets defined in its ancestor chain.
 *
 * @param {Object} options
 * @param {String} type
 * @param {String} id
 * @return {Object|Function}
 */

export function resolveAsset (options, type, id) {
  var assets = options[type]
  var camelizedId
  return assets[id] ||
    // camelCase ID
    assets[camelizedId = camelize(id)] ||
    // Pascal Case ID
    assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]
}

/**
 * Assert asset exists
 */

export function assertAsset (val, type, id) {
  if (!val) {
    process.env.NODE_ENV !== 'production' && warn(
      'Failed to resolve ' + type + ': ' + id
    )
  }
}
<commit_msg>ensure id is string when resolving asset (fix #2254)<commit_after>import Vue from '../instance/vue'
import config from '../config'
import {
  extend,
  set,
  isObject,
  isArray,
  isPlainObject,
  hasOwn,
  camelize
} from './lang'
import { warn } from './debug'
import { commonTagRE, reservedTagRE } from './component'

/**
 * Option overwriting strategies are functions that handle
 * how to merge a parent option value and a child option
 * value into the final value.
 *
 * All strategy functions follow the same signature:
 *
 * @param {*} parentVal
 * @param {*} childVal
 * @param {Vue} [vm]
 */

var strats = config.optionMergeStrategies = Object.create(null)

/**
 * Helper that recursively merges two data objects together.
 */

function mergeData (to, from) {
  var key, toVal, fromVal
  for (key in from) {
    toVal = to[key]
    fromVal = from[key]
    if (!hasOwn(to, key)) {
      set(to, key, fromVal)
    } else if (isObject(toVal) && isObject(fromVal)) {
      mergeData(toVal, fromVal)
    }
  }
  return to
}

/**
 * Data
 */

strats.data = function (parentVal, childVal, vm) {
  if (!vm) {
    // in a Vue.extend merge, both should be functions
    if (!childVal) {
      return parentVal
    }
    if (typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.'
      )
      return parentVal
    }
    if (!parentVal) {
      return childVal
    }
    // when parentVal & childVal are both present,
    // we need to return a function that returns the
    // merged result of both functions... no need to
    // check if parentVal is a function here because
    // it has to be a function to pass previous merges.
    return function mergedDataFn () {
      return mergeData(
        childVal.call(this),
        parentVal.call(this)
      )
    }
  } else if (parentVal || childVal) {
    return function mergedInstanceDataFn () {
      // instance merge
      var instanceData = typeof childVal === 'function'
        ? childVal.call(vm)
        : childVal
      var defaultData = typeof parentVal === 'function'
        ? parentVal.call(vm)
        : undefined
      if (instanceData) {
        return mergeData(instanceData, defaultData)
      } else {
        return defaultData
      }
    }
  }
}

/**
 * El
 */

strats.el = function (parentVal, childVal, vm) {
  if (!vm && childVal && typeof childVal !== 'function') {
    process.env.NODE_ENV !== 'production' && warn(
      'The "el" option should be a function ' +
      'that returns a per-instance value in component ' +
      'definitions.'
    )
    return
  }
  var ret = childVal || parentVal
  // invoke the element factory if this is instance merge
  return vm && typeof ret === 'function'
    ? ret.call(vm)
    : ret
}

/**
 * Hooks and param attributes are merged as arrays.
 */

strats.init =
strats.created =
strats.ready =
strats.attached =
strats.detached =
strats.beforeCompile =
strats.compiled =
strats.beforeDestroy =
strats.destroyed = function (parentVal, childVal) {
  return childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : isArray(childVal)
        ? childVal
        : [childVal]
    : parentVal
}

/**
 * 0.11 deprecation warning
 */

strats.paramAttributes = function () {
  /* istanbul ignore next */
  process.env.NODE_ENV !== 'production' && warn(
    '"paramAttributes" option has been deprecated in 0.12. ' +
    'Use "props" instead.'
  )
}

/**
 * Assets
 *
 * When a vm is present (instance creation), we need to do
 * a three-way merge between constructor options, instance
 * options and parent options.
 */

function mergeAssets (parentVal, childVal) {
  var res = Object.create(parentVal)
  return childVal
    ? extend(res, guardArrayAssets(childVal))
    : res
}

config._assetTypes.forEach(function (type) {
  strats[type + 's'] = mergeAssets
})

/**
 * Events & Watchers.
 *
 * Events & watchers hashes should not overwrite one
 * another, so we merge them as arrays.
 */

strats.watch =
strats.events = function (parentVal, childVal) {
  if (!childVal) return parentVal
  if (!parentVal) return childVal
  var ret = {}
  extend(ret, parentVal)
  for (var key in childVal) {
    var parent = ret[key]
    var child = childVal[key]
    if (parent && !isArray(parent)) {
      parent = [parent]
    }
    ret[key] = parent
      ? parent.concat(child)
      : [child]
  }
  return ret
}

/**
 * Other object hashes.
 */

strats.props =
strats.methods =
strats.computed = function (parentVal, childVal) {
  if (!childVal) return parentVal
  if (!parentVal) return childVal
  var ret = Object.create(null)
  extend(ret, parentVal)
  extend(ret, childVal)
  return ret
}

/**
 * Default strategy.
 */

var defaultStrat = function (parentVal, childVal) {
  return childVal === undefined
    ? parentVal
    : childVal
}

/**
 * Make sure component options get converted to actual
 * constructors.
 *
 * @param {Object} options
 */

function guardComponents (options) {
  if (options.components) {
    var components = options.components =
      guardArrayAssets(options.components)
    var def
    var ids = Object.keys(components)
    for (var i = 0, l = ids.length; i < l; i++) {
      var key = ids[i]
      if (commonTagRE.test(key) || reservedTagRE.test(key)) {
        process.env.NODE_ENV !== 'production' && warn(
          'Do not use built-in or reserved HTML elements as component ' +
          'id: ' + key
        )
        continue
      }
      def = components[key]
      if (isPlainObject(def)) {
        components[key] = Vue.extend(def)
      }
    }
  }
}

/**
 * Ensure all props option syntax are normalized into the
 * Object-based format.
 *
 * @param {Object} options
 */

function guardProps (options) {
  var props = options.props
  var i, val
  if (isArray(props)) {
    options.props = {}
    i = props.length
    while (i--) {
      val = props[i]
      if (typeof val === 'string') {
        options.props[val] = null
      } else if (val.name) {
        options.props[val.name] = val
      }
    }
  } else if (isPlainObject(props)) {
    var keys = Object.keys(props)
    i = keys.length
    while (i--) {
      val = props[keys[i]]
      if (typeof val === 'function') {
        props[keys[i]] = { type: val }
      }
    }
  }
}

/**
 * Guard an Array-format assets option and converted it
 * into the key-value Object format.
 *
 * @param {Object|Array} assets
 * @return {Object}
 */

function guardArrayAssets (assets) {
  if (isArray(assets)) {
    var res = {}
    var i = assets.length
    var asset
    while (i--) {
      asset = assets[i]
      var id = typeof asset === 'function'
        ? ((asset.options && asset.options.name) || asset.id)
        : (asset.name || asset.id)
      if (!id) {
        process.env.NODE_ENV !== 'production' && warn(
          'Array-syntax assets must provide a "name" or "id" field.'
        )
      } else {
        res[id] = asset
      }
    }
    return res
  }
  return assets
}

/**
 * Merge two option objects into a new one.
 * Core utility used in both instantiation and inheritance.
 *
 * @param {Object} parent
 * @param {Object} child
 * @param {Vue} [vm] - if vm is present, indicates this is
 *                     an instantiation merge.
 */

export function mergeOptions (parent, child, vm) {
  guardComponents(child)
  guardProps(child)
  var options = {}
  var key
  if (child.mixins) {
    for (var i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }
  for (key in parent) {
    mergeField(key)
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
    var strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}

/**
 * Resolve an asset.
 * This function is used because child instances need access
 * to assets defined in its ancestor chain.
 *
 * @param {Object} options
 * @param {String} type
 * @param {String} id
 * @return {Object|Function}
 */

export function resolveAsset (options, type, id) {
  /* istanbul ignore if */
  if (typeof id !== 'string') {
    return
  }
  var assets = options[type]
  var camelizedId
  return assets[id] ||
    // camelCase ID
    assets[camelizedId = camelize(id)] ||
    // Pascal Case ID
    assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]
}

/**
 * Assert asset exists
 */

export function assertAsset (val, type, id) {
  if (!val) {
    process.env.NODE_ENV !== 'production' && warn(
      'Failed to resolve ' + type + ': ' + id
    )
  }
}
<|endoftext|>


<commit_before>const nconf = require('nconf')

nconf
    .argv()
    .env({
        separator: '_'
    })
    .file('file-config', {
        file: 'linden_honey.json',
        dir: 'config',
        search: true
    })
    .defaults({
        LH: {
            APP: {
                NAME: 'Linden Honey Bot',
                PORT: process.env.PORT || 8080,
                MESSAGES: {
                    WELCOME: 'Welcome to the Linden Honey Server!\n\nPowered by Koa.js and Node.js\n\n\n\nИ всё идёт по плану...'
                }
            },
            SCRAPER: {
                ROUTER: {
                    ENABLED: false
                }
            }
        }
    })

nconf.required([
    'LH:DB:URL',
    'LH:SCRAPER:URL'
])

module.exports = nconf
<commit_msg>refactor(scraper): improve config<commit_after>const nconf = require('nconf')

nconf
    .argv()
    .env({
        separator: '_'
    })
    .file('file-config', {
        file: 'linden_honey.json',
        dir: 'config',
        search: true
    })
    .defaults({
        LH: {
            APP: {
                NAME: 'Linden Honey Bot',
                PORT: process.env.PORT || 8080,
                MESSAGES: {
                    WELCOME: 'Welcome to the Linden Honey Server!\n\nPowered by Koa.js and Node.js\n\n\n\nИ всё идёт по плану...'
                }
            },
            SCRAPER: {
                ROUTER: {
                    ENABLED: false
                }
            }
        }
    })

nconf.required([
    'LH:DB:URL',
    nconf.get('LH:SCRAPER:ROUTER:ENABLED') ? 'LH:SCRAPER:URL' : 'LH:SCRAPER:ROUTER:ENABLED'
])

module.exports = nconf
<|endoftext|>


<commit_before>import { window, document } from 'ssr-window';

const Device = (function Device() {
  const ua = window.navigator.userAgent;

  const device = {
    ios: false,
    android: false,
    androidChrome: false,
    desktop: false,
    windows: false,
    iphone: false,
    ipod: false,
    ipad: false,
    cordova: window.cordova || window.phonegap,
    phonegap: window.cordova || window.phonegap,
  };

  const windows = ua.match(/(Windows Phone);?[\s\/]+([\d.]+)?/); // eslint-disable-line
  const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
  const ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
  const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
  const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);

  // Windows
  if (windows) {
    device.os = 'windows';
    device.osVersion = windows[2];
    device.windows = true;
  }
  // Android
  if (android && !windows) {
    device.os = 'android';
    device.osVersion = android[2];
    device.android = true;
    device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
  }
  if (ipad || iphone || ipod) {
    device.os = 'ios';
    device.ios = true;
  }
  // iOS
  if (iphone && !ipod) {
    device.osVersion = iphone[2].replace(/_/g, '.');
    device.iphone = true;
  }
  if (ipad) {
    device.osVersion = ipad[2].replace(/_/g, '.');
    device.ipad = true;
  }
  if (ipod) {
    device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
    device.iphone = true;
  }
  // iOS 8+ changed UA
  if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
    if (device.osVersion.split('.')[0] === '10') {
      device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
    }
  }

  // Desktop
  device.desktop = !(device.os || device.android || device.webView);

  // Webview
  device.webView = (iphone || ipad || ipod) && ua.match(/.*AppleWebKit(?!.*Safari)/i);

  // Minimal UI
  if (device.os && device.os === 'ios') {
    const osVersionArr = device.osVersion.split('.');
    const metaViewport = document.querySelector('meta[name="viewport"]');
    device.minimalUi = !device.webView
      && (ipod || iphone)
      && (osVersionArr[0] * 1 === 7 ? osVersionArr[1] * 1 >= 1 : osVersionArr[0] * 1 > 7)
      && metaViewport && metaViewport.getAttribute('content').indexOf('minimal-ui') >= 0;
  }

  // Pixel Ratio
  device.pixelRatio = window.devicePixelRatio || 1;

  // Export object
  return device;
}());

export default Device;
<commit_msg>Fix ios 13 ipad detection<commit_after>import { window } from 'ssr-window';
import Support from './support';

const Device = (function Device() {
  const platform = window.navigator.platform;
  const ua = window.navigator.userAgent;

  const device = {
    ios: false,
    android: false,
    androidChrome: false,
    desktop: false,
    iphone: false,
    ipod: false,
    ipad: false,
    edge: false,
    ie: false,
    firefox: false,
    macos: false,
    windows: false,
    cordova: !!(window.cordova || window.phonegap),
    phonegap: !!(window.cordova || window.phonegap),
    electron: false,
  };

  const screenWidth = window.screen.width;
  const screenHeight = window.screen.height;

  const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
  let ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
  const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
  const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
  const ie = ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;
  const edge = ua.indexOf('Edge/') >= 0;
  const firefox = ua.indexOf('Gecko/') >= 0 && ua.indexOf('Firefox/') >= 0;
  const windows = platform === 'Win32';
  const electron = ua.toLowerCase().indexOf('electron') >= 0;
  let macos = platform === 'MacIntel';

  // iPadOs 13 fix
  if (!ipad
    && macos
    && Support.touch
    && (
      (screenWidth === 1024 && screenHeight === 1366) // Pro 12.9
      || (screenWidth === 834 && screenHeight === 1194) // Pro 11
      || (screenWidth === 834 && screenHeight === 1112) // Pro 10.5
      || (screenWidth === 768 && screenHeight === 1024) // other
    )
  ) {
    ipad = ua.match(/(Version)\/([\d.]+)/);
    macos = false;
  }

  device.ie = ie;
  device.edge = edge;
  device.firefox = firefox;

  // Android
  if (android && !windows) {
    device.os = 'android';
    device.osVersion = android[2];
    device.android = true;
    device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
  }
  if (ipad || iphone || ipod) {
    device.os = 'ios';
    device.ios = true;
  }
  // iOS
  if (iphone && !ipod) {
    device.osVersion = iphone[2].replace(/_/g, '.');
    device.iphone = true;
  }
  if (ipad) {
    device.osVersion = ipad[2].replace(/_/g, '.');
    device.ipad = true;
  }
  if (ipod) {
    device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
    device.ipod = true;
  }
  // iOS 8+ changed UA
  if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
    if (device.osVersion.split('.')[0] === '10') {
      device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
    }
  }

  // Webview
  device.webView = !!((iphone || ipad || ipod) && (ua.match(/.*AppleWebKit(?!.*Safari)/i) || window.navigator.standalone))
    || (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches);
  device.webview = device.webView;
  device.standalone = device.webView;

  // Desktop
  device.desktop = !(device.ios || device.android) || electron;
  if (device.desktop) {
    device.electron = electron;
    device.macos = macos;
    device.windows = windows;
    if (device.macos) {
      device.os = 'macos';
    }
    if (device.windows) {
      device.os = 'windows';
    }
  }

  // Pixel Ratio
  device.pixelRatio = window.devicePixelRatio || 1;

  // Export object
  return device;
}());

export default Device;
<|endoftext|>


<commit_before>const arr       = require('./arr');
const isType    = require('./isType');
const domUtils  = require('./domUtils');
const indexOf   = arr.indexOf;
const contains  = arr.contains;
const getWindow = require('./window').getWindow;

const useAttachEvent = ('attachEvent' in window) && !('addEventListener' in window);
const addEvent       = useAttachEvent?  'attachEvent': 'addEventListener';
const removeEvent    = useAttachEvent?  'detachEvent': 'removeEventListener';
const on             = useAttachEvent? 'on': '';

const elements          = [];
const targets           = [];
const attachedListeners = [];

// {
//   type: {
//     selectors: ['selector', ...],
//     contexts : [document, ...],
//     listeners: [[listener, useCapture], ...]
//   }
//  }
const delegatedEvents = {};

const documents = [];

function add (element, type, listener, useCapture) {
  let elementIndex = indexOf(elements, element);
  let target = targets[elementIndex];

  if (!target) {
    target = {
      events: {},
      typeCount: 0,
    };

    elementIndex = elements.push(element) - 1;
    targets.push(target);

    attachedListeners.push((useAttachEvent ? {
      supplied: [],
      wrapped : [],
      useCount: [],
    } : null));
  }

  if (!target.events[type]) {
    target.events[type] = [];
    target.typeCount++;
  }

  if (!contains(target.events[type], listener)) {
    let ret;

    if (useAttachEvent) {
      const { supplied, wrapped, useCount } = [ attachedListeners[elementIndex] ];
      const listenerIndex = indexOf(supplied, listener);

      const wrappedListener = wrapped[listenerIndex] || function (event) {
        if (!event.immediatePropagationStopped) {
          event.target = event.srcElement;
          event.currentTarget = element;

          event.preventDefault           = event.preventDefault           || preventDef;
          event.stopPropagation          = event.stopPropagation          || stopProp;
          event.stopImmediatePropagation = event.stopImmediatePropagation || stopImmProp;

          if (/mouse|click/.test(event.type)) {
            event.pageX = event.clientX + getWindow(element).document.documentElement.scrollLeft;
            event.pageY = event.clientY + getWindow(element).document.documentElement.scrollTop;
          }

          listener(event);
        }
      };

      ret = element[addEvent](on + type, wrappedListener, !!useCapture);

      if (listenerIndex === -1) {
        supplied.push(listener);
        wrapped.push(wrappedListener);
        useCount.push(1);
      }
      else {
        useCount[listenerIndex]++;
      }
    }
    else {
      ret = element[addEvent](type, listener, !!useCapture);
    }
    target.events[type].push(listener);

    return ret;
  }
}

function remove (element, type, listener, useCapture) {
  const elementIndex = indexOf(elements, element);
  const target = targets[elementIndex];

  if (!target || !target.events) {
    return;
  }

  let wrappedListener = listener;
  let listeners;
  let listenerIndex;

  if (useAttachEvent) {
    listeners = attachedListeners[elementIndex];
    listenerIndex = indexOf(listeners.supplied, listener);
    wrappedListener = listeners.wrapped[listenerIndex];
  }

  if (type === 'all') {
    for (type in target.events) {
      if (target.events.hasOwnProperty(type)) {
        remove(element, type, 'all');
      }
    }
    return;
  }

  if (target.events[type]) {
    const len = target.events[type].length;

    if (listener === 'all') {
      for (let i = 0; i < len; i++) {
        remove(element, type, target.events[type][i], !!useCapture);
      }
      return;
    }
    else {
      for (let i = 0; i < len; i++) {
        if (target.events[type][i] === listener) {
          element[removeEvent](on + type, wrappedListener, !!useCapture);
          target.events[type].splice(i, 1);

          if (useAttachEvent && listeners) {
            listeners.useCount[listenerIndex]--;
            if (listeners.useCount[listenerIndex] === 0) {
              listeners.supplied.splice(listenerIndex, 1);
              listeners.wrapped.splice(listenerIndex, 1);
              listeners.useCount.splice(listenerIndex, 1);
            }
          }

          break;
        }
      }
    }

    if (target.events[type] && target.events[type].length === 0) {
      target.events[type] = null;
      target.typeCount--;
    }
  }

  if (!target.typeCount) {
    targets.splice(elementIndex, 1);
    elements.splice(elementIndex, 1);
    attachedListeners.splice(elementIndex, 1);
  }
}

function addDelegate (selector, context, type, listener, useCapture) {
  if (!delegatedEvents[type]) {
    delegatedEvents[type] = {
      selectors: [],
      contexts : [],
      listeners: [],
    };

    // add delegate listener functions
    for (let i = 0; i < documents.length; i++) {
      add(documents[i], type, delegateListener);
      add(documents[i], type, delegateUseCapture, true);
    }
  }

  const delegated = delegatedEvents[type];
  let index;

  for (index = delegated.selectors.length - 1; index >= 0; index--) {
    if (delegated.selectors[index] === selector
        && delegated.contexts[index] === context) {
      break;
    }
  }

  if (index === -1) {
    index = delegated.selectors.length;

    delegated.selectors.push(selector);
    delegated.contexts .push(context);
    delegated.listeners.push([]);
  }

  // keep listener and useCapture flag
  delegated.listeners[index].push([listener, useCapture]);
}

function removeDelegate (selector, context, type, listener, useCapture) {
  const delegated = delegatedEvents[type];
  let matchFound = false;
  let index;

  if (!delegated) { return; }

  // count from last index of delegated to 0
  for (index = delegated.selectors.length - 1; index >= 0; index--) {
    // look for matching selector and context Node
    if (delegated.selectors[index] === selector
        && delegated.contexts[index] === context) {

      const listeners = delegated.listeners[index];

      // each item of the listeners array is an array: [function, useCaptureFlag]
      for (let i = listeners.length - 1; i >= 0; i--) {
        const fn = listeners[i][0];
        const useCap = listeners[i][1];

        // check if the listener functions and useCapture flags match
        if (fn === listener && useCap === useCapture) {
          // remove the listener from the array of listeners
          listeners.splice(i, 1);

          // if all listeners for this interactable have been removed
          // remove the interactable from the delegated arrays
          if (!listeners.length) {
            delegated.selectors.splice(index, 1);
            delegated.contexts .splice(index, 1);
            delegated.listeners.splice(index, 1);

            // remove delegate function from context
            remove(context, type, delegateListener);
            remove(context, type, delegateUseCapture, true);

            // remove the arrays if they are empty
            if (!delegated.selectors.length) {
              delegatedEvents[type] = null;
            }
          }

          // only remove one listener
          matchFound = true;
          break;
        }
      }

      if (matchFound) { break; }
    }
  }
}

// bound to the interactable context when a DOM event
// listener is added to a selector interactable
function delegateListener (event, useCapture) {
  const fakeEvent = {};
  const delegated = delegatedEvents[event.type];
  const eventTarget = (domUtils.getActualElement(event.path
    ? event.path[0]
    : event.target));
  let element = eventTarget;

  useCapture = useCapture? true: false;

  // duplicate the event so that currentTarget can be changed
  for (const prop in event) {
    fakeEvent[prop] = event[prop];
  }

  fakeEvent.originalEvent = event;
  fakeEvent.preventDefault = preventOriginalDefault;

  // climb up document tree looking for selector matches
  while (isType.isElement(element)) {
    for (let i = 0; i < delegated.selectors.length; i++) {
      const selector = delegated.selectors[i];
      const context = delegated.contexts[i];

      if (domUtils.matchesSelector(element, selector)
          && domUtils.nodeContains(context, eventTarget)
          && domUtils.nodeContains(context, element)) {

        const listeners = delegated.listeners[i];

        fakeEvent.currentTarget = element;

        for (let j = 0; j < listeners.length; j++) {
          if (listeners[j][1] === useCapture) {
            listeners[j][0](fakeEvent);
          }
        }
      }
    }

    element = domUtils.parentElement(element);
  }
}

function delegateUseCapture (event) {
  return delegateListener.call(this, event, true);
}

function preventDef () {
  this.returnValue = false;
}

function preventOriginalDefault () {
  this.originalEvent.preventDefault();
}

function stopProp () {
  this.cancelBubble = true;
}

function stopImmProp () {
  this.cancelBubble = true;
  this.immediatePropagationStopped = true;
}

module.exports = {
  add,
  remove,

  addDelegate,
  removeDelegate,

  delegateListener,
  delegateUseCapture,
  delegatedEvents,
  documents,

  useAttachEvent,

  _elements: elements,
  _targets: targets,
  _attachedListeners: attachedListeners,
};
<commit_msg>utils/events: fix events.on IE8 workaround<commit_after>const arr       = require('./arr');
const isType    = require('./isType');
const domUtils  = require('./domUtils');
const indexOf   = arr.indexOf;
const contains  = arr.contains;
const getWindow = require('./window').getWindow;

const useAttachEvent = ('attachEvent' in window) && !('addEventListener' in window);
const addEvent       = useAttachEvent?  'attachEvent': 'addEventListener';
const removeEvent    = useAttachEvent?  'detachEvent': 'removeEventListener';
const on             = useAttachEvent? 'on': '';

const elements          = [];
const targets           = [];
const attachedListeners = [];

// {
//   type: {
//     selectors: ['selector', ...],
//     contexts : [document, ...],
//     listeners: [[listener, useCapture], ...]
//   }
//  }
const delegatedEvents = {};

const documents = [];

function add (element, type, listener, useCapture) {
  let elementIndex = indexOf(elements, element);
  let target = targets[elementIndex];

  if (!target) {
    target = {
      events: {},
      typeCount: 0,
    };

    elementIndex = elements.push(element) - 1;
    targets.push(target);

    attachedListeners.push((useAttachEvent ? {
      supplied: [],
      wrapped : [],
      useCount: [],
    } : null));
  }

  if (!target.events[type]) {
    target.events[type] = [];
    target.typeCount++;
  }

  if (!contains(target.events[type], listener)) {
    let ret;

    if (useAttachEvent) {
      const { supplied, wrapped, useCount } = attachedListeners[elementIndex];
      const listenerIndex = indexOf(supplied, listener);

      const wrappedListener = wrapped[listenerIndex] || function (event) {
        if (!event.immediatePropagationStopped) {
          event.target = event.srcElement;
          event.currentTarget = element;

          event.preventDefault           = event.preventDefault           || preventDef;
          event.stopPropagation          = event.stopPropagation          || stopProp;
          event.stopImmediatePropagation = event.stopImmediatePropagation || stopImmProp;

          if (/mouse|click/.test(event.type)) {
            event.pageX = event.clientX + getWindow(element).document.documentElement.scrollLeft;
            event.pageY = event.clientY + getWindow(element).document.documentElement.scrollTop;
          }

          listener(event);
        }
      };

      ret = element[addEvent](on + type, wrappedListener, !!useCapture);

      if (listenerIndex === -1) {
        supplied.push(listener);
        wrapped.push(wrappedListener);
        useCount.push(1);
      }
      else {
        useCount[listenerIndex]++;
      }
    }
    else {
      ret = element[addEvent](type, listener, !!useCapture);
    }
    target.events[type].push(listener);

    return ret;
  }
}

function remove (element, type, listener, useCapture) {
  const elementIndex = indexOf(elements, element);
  const target = targets[elementIndex];

  if (!target || !target.events) {
    return;
  }

  let wrappedListener = listener;
  let listeners;
  let listenerIndex;

  if (useAttachEvent) {
    listeners = attachedListeners[elementIndex];
    listenerIndex = indexOf(listeners.supplied, listener);
    wrappedListener = listeners.wrapped[listenerIndex];
  }

  if (type === 'all') {
    for (type in target.events) {
      if (target.events.hasOwnProperty(type)) {
        remove(element, type, 'all');
      }
    }
    return;
  }

  if (target.events[type]) {
    const len = target.events[type].length;

    if (listener === 'all') {
      for (let i = 0; i < len; i++) {
        remove(element, type, target.events[type][i], !!useCapture);
      }
      return;
    }
    else {
      for (let i = 0; i < len; i++) {
        if (target.events[type][i] === listener) {
          element[removeEvent](on + type, wrappedListener, !!useCapture);
          target.events[type].splice(i, 1);

          if (useAttachEvent && listeners) {
            listeners.useCount[listenerIndex]--;
            if (listeners.useCount[listenerIndex] === 0) {
              listeners.supplied.splice(listenerIndex, 1);
              listeners.wrapped.splice(listenerIndex, 1);
              listeners.useCount.splice(listenerIndex, 1);
            }
          }

          break;
        }
      }
    }

    if (target.events[type] && target.events[type].length === 0) {
      target.events[type] = null;
      target.typeCount--;
    }
  }

  if (!target.typeCount) {
    targets.splice(elementIndex, 1);
    elements.splice(elementIndex, 1);
    attachedListeners.splice(elementIndex, 1);
  }
}

function addDelegate (selector, context, type, listener, useCapture) {
  if (!delegatedEvents[type]) {
    delegatedEvents[type] = {
      selectors: [],
      contexts : [],
      listeners: [],
    };

    // add delegate listener functions
    for (let i = 0; i < documents.length; i++) {
      add(documents[i], type, delegateListener);
      add(documents[i], type, delegateUseCapture, true);
    }
  }

  const delegated = delegatedEvents[type];
  let index;

  for (index = delegated.selectors.length - 1; index >= 0; index--) {
    if (delegated.selectors[index] === selector
        && delegated.contexts[index] === context) {
      break;
    }
  }

  if (index === -1) {
    index = delegated.selectors.length;

    delegated.selectors.push(selector);
    delegated.contexts .push(context);
    delegated.listeners.push([]);
  }

  // keep listener and useCapture flag
  delegated.listeners[index].push([listener, useCapture]);
}

function removeDelegate (selector, context, type, listener, useCapture) {
  const delegated = delegatedEvents[type];
  let matchFound = false;
  let index;

  if (!delegated) { return; }

  // count from last index of delegated to 0
  for (index = delegated.selectors.length - 1; index >= 0; index--) {
    // look for matching selector and context Node
    if (delegated.selectors[index] === selector
        && delegated.contexts[index] === context) {

      const listeners = delegated.listeners[index];

      // each item of the listeners array is an array: [function, useCaptureFlag]
      for (let i = listeners.length - 1; i >= 0; i--) {
        const fn = listeners[i][0];
        const useCap = listeners[i][1];

        // check if the listener functions and useCapture flags match
        if (fn === listener && useCap === useCapture) {
          // remove the listener from the array of listeners
          listeners.splice(i, 1);

          // if all listeners for this interactable have been removed
          // remove the interactable from the delegated arrays
          if (!listeners.length) {
            delegated.selectors.splice(index, 1);
            delegated.contexts .splice(index, 1);
            delegated.listeners.splice(index, 1);

            // remove delegate function from context
            remove(context, type, delegateListener);
            remove(context, type, delegateUseCapture, true);

            // remove the arrays if they are empty
            if (!delegated.selectors.length) {
              delegatedEvents[type] = null;
            }
          }

          // only remove one listener
          matchFound = true;
          break;
        }
      }

      if (matchFound) { break; }
    }
  }
}

// bound to the interactable context when a DOM event
// listener is added to a selector interactable
function delegateListener (event, useCapture) {
  const fakeEvent = {};
  const delegated = delegatedEvents[event.type];
  const eventTarget = (domUtils.getActualElement(event.path
    ? event.path[0]
    : event.target));
  let element = eventTarget;

  useCapture = useCapture? true: false;

  // duplicate the event so that currentTarget can be changed
  for (const prop in event) {
    fakeEvent[prop] = event[prop];
  }

  fakeEvent.originalEvent = event;
  fakeEvent.preventDefault = preventOriginalDefault;

  // climb up document tree looking for selector matches
  while (isType.isElement(element)) {
    for (let i = 0; i < delegated.selectors.length; i++) {
      const selector = delegated.selectors[i];
      const context = delegated.contexts[i];

      if (domUtils.matchesSelector(element, selector)
          && domUtils.nodeContains(context, eventTarget)
          && domUtils.nodeContains(context, element)) {

        const listeners = delegated.listeners[i];

        fakeEvent.currentTarget = element;

        for (let j = 0; j < listeners.length; j++) {
          if (listeners[j][1] === useCapture) {
            listeners[j][0](fakeEvent);
          }
        }
      }
    }

    element = domUtils.parentElement(element);
  }
}

function delegateUseCapture (event) {
  return delegateListener.call(this, event, true);
}

function preventDef () {
  this.returnValue = false;
}

function preventOriginalDefault () {
  this.originalEvent.preventDefault();
}

function stopProp () {
  this.cancelBubble = true;
}

function stopImmProp () {
  this.cancelBubble = true;
  this.immediatePropagationStopped = true;
}

module.exports = {
  add,
  remove,

  addDelegate,
  removeDelegate,

  delegateListener,
  delegateUseCapture,
  delegatedEvents,
  documents,

  useAttachEvent,

  _elements: elements,
  _targets: targets,
  _attachedListeners: attachedListeners,
};
<|endoftext|>


<commit_before>"use strict";

const {getProperties} = require("alhadis.utils");

Object.defineProperties(global, {
	ed:   {get: () => atom.workspace.getActiveTextEditor()},
	pane: {get: () => atom.workspace.getActivePane()},
	sel:  {get: () => global.ed.getLastSelection()},
	cur:  {get: () => global.ed.getLastCursor()},
	text: {
		get: () => global.ed.buffer.getText(),
		set: to => global.ed.buffer.setText(to)
	},
	row: {
		get: () => global.cur.getBufferRow(),
		set: to => global.cur.setBufferPosition([to, global.col])
	},
	col: {
		get: () => global.cur.getBufferColumn(),
		set: to => global.cur.setBufferPosition([global.row, to])
	},
});

Object.assign(global, {
	Electron: require("electron"),
	print:    require("print"),
	Path:     require("path"),
	fs:       require("fs"),

	traceEmissions: (function(){
		const prot = atom.emitter.constructor.prototype;
		const emit = prot.emit;
		return function(active){
			prot.emit = !active ? emit : function(name){
				if("did-update-state" !== name)
					console.trace(arguments);
				emit.apply(this, arguments);
			};
		}
	}()),

	dispatch(command, target = null){
		target = target || atom.views.getView(atom.workspace);
		return atom.commands.dispatch(target, command);
	},

	inced(clearCache = false){
		const editor = atom.workspace.getActiveTextEditor();
		const {path} = editor.buffer.file;
		if(clearCache) delete require.cache[path];
		return require(path);
	},

	keyGrep(subject, pattern){
		pattern = "string" === typeof pattern
			? new RegExp(pattern)
			: pattern;

		const output = {};
		const props = getProperties(subject);
		for(const key of props.keys())
			if(pattern.test(key))
				output[key] = subject[key];
		return output;
	},

	globaliseAtomClasses(){
		if(global.CompositeDisposable) return;
		const {CompositeDisposable, Disposable, Emitter, Point, Range} = require("atom");
		global.CompositeDisposable = CompositeDisposable;
		global.Disposable = Disposable;
		global.Emitter = Emitter;
		global.Point = Point;
		global.Range = Range;
	}
});
<commit_msg>Add shorthand globals for current editor's buffers<commit_after>"use strict";

const {getProperties} = require("alhadis.utils");

Object.defineProperties(global, {
	ed:   {get: () => atom.workspace.getActiveTextEditor()},
	pane: {get: () => atom.workspace.getActivePane()},
	sel:  {get: () => global.ed.getLastSelection()},
	cur:  {get: () => global.ed.getLastCursor()},
	tb:   {get: () => global.ed.tokenizedBuffer},
	buf:  {get: () => global.ed.buffer},
	text: {
		get: () => global.ed.buffer.getText(),
		set: to => global.ed.buffer.setText(to)
	},
	row: {
		get: () => global.cur.getBufferRow(),
		set: to => global.cur.setBufferPosition([to, global.col])
	},
	col: {
		get: () => global.cur.getBufferColumn(),
		set: to => global.cur.setBufferPosition([global.row, to])
	},
});

Object.assign(global, {
	Electron: require("electron"),
	print:    require("print"),
	Path:     require("path"),
	fs:       require("fs"),

	traceEmissions: (function(){
		const prot = atom.emitter.constructor.prototype;
		const emit = prot.emit;
		return function(active){
			prot.emit = !active ? emit : function(name){
				if("did-update-state" !== name)
					console.trace(arguments);
				emit.apply(this, arguments);
			};
		}
	}()),

	dispatch(command, target = null){
		target = target || atom.views.getView(atom.workspace);
		return atom.commands.dispatch(target, command);
	},

	inced(clearCache = false){
		const editor = atom.workspace.getActiveTextEditor();
		const {path} = editor.buffer.file;
		if(clearCache) delete require.cache[path];
		return require(path);
	},

	keyGrep(subject, pattern){
		pattern = "string" === typeof pattern
			? new RegExp(pattern)
			: pattern;

		const output = {};
		const props = getProperties(subject);
		for(const key of props.keys())
			if(pattern.test(key))
				output[key] = subject[key];
		return output;
	},

	globaliseAtomClasses(){
		if(global.CompositeDisposable) return;
		const {CompositeDisposable, Disposable, Emitter, Point, Range} = require("atom");
		global.CompositeDisposable = CompositeDisposable;
		global.Disposable = Disposable;
		global.Emitter = Emitter;
		global.Point = Point;
		global.Range = Range;
	}
});
<|endoftext|>


<commit_before>class Engine {

    static update(endNode) {

        if (endNode.isExecutable) {

            Engine.compile(endNode);

        } else {

            endNode.calculate();

        }

    };

    static compile(node) {

        // initialize the compilation, starting at the node root
        // if in a loop it will be the first of the propagation tree
        // else it is `node`

        const stream = new Stream(node);

        do {

            stream.calculate();

        } while (stream.next());

    };

}

class Stream {

    constructor(rootNode) {

        Object.assign(this, {
            root: rootNode,
            stream: [],
            current: rootNode,
        });

    }

    get current() {

        return this.stream[ this.stream.length-1 ];

    }

    set current(nextNode) {

        this.stream.push(nextNode);

    };

    calculate() {

        this.current.calculate(); // no propagation, right?

    };

    next() {

        const exeDocks = this.current.exeDocks.out;
        if (exeDocks.length && exeDocks[0].links.length) {

            return this.current = exeDocks[0].links[0].endDock.node;

        }

    }

}
<commit_msg>Removed unused Stream#root, renamed Stream#stream to Stream#nodes<commit_after>class Engine {

    static update(endNode) {

        if (endNode instanceof Executable) {

            Engine.compile(endNode);

        } else {

            endNode.calculate();

        }

    };

    static compile(node) {

        const stream = new Stream(node);

        do {

            stream.calculate();

        } while (stream.next());

    };

}

class Stream {

    constructor(currentNode) {

        this.nodes = [ currentNode.root ];

    }

    get current() {

        return this.nodes[ this.nodes.length - 1 ];

    }

    set current(nextNode) {

        this.nodes.push(nextNode);

    };

    calculate() {

        this.current.calculate(); // no propagation, right?

    };

    next() {

        const exeDocks = this.current.exeDocks.out;
        if (exeDocks.length && exeDocks[0].links.length) {

            return this.current = exeDocks[0].links[0].endDock.node;

        }

    };

}
<|endoftext|>


<commit_before>import { PAGE_BREAK_KEY, SECTION_TYPES } from '../constants/Constants';
import {
  ItemsSection,
  SectionChart,
  SectionDate,
  SectionGroupedList,
  SectionDivider,
  SectionDuration,
  SectionHeader,
  SectionImage,
  SectionJson,
  SectionList,
  SectionMarkdown,
  SectionNumber,
  SectionTable,
  SectionText,
  SectionHTML
} from '../components/Sections';
import { isNumber, isObjectLike, compact, isString, groupBy, get, isEmpty } from 'lodash';
import moment from 'moment-timezone';
import React from 'react';
import { processData } from './data';
import WidgetEmptyState from '../components/Sections/WidgetEmptyState';

function getDefaultEmptyNotification() {
  return 'No results found.';
}

function isPageBreakSection(section) {
  return !!get(section, 'layout.style.pageBreakBefore', false) || (section.type === SECTION_TYPES.markdown &&
      section.data && ((isString(section.data) ? section.data : section.data.text) || '').includes(PAGE_BREAK_KEY));
}

export function getSectionComponent(section, maxWidth) {
  let sectionToRender;
  switch (section.type) {
    case SECTION_TYPES.header:
      sectionToRender = (
        <SectionHeader
          header={section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.text:
      sectionToRender = (
        <SectionText
          text={isObjectLike(section.data) ? section.data.text : section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.html:
      sectionToRender = (
        <SectionHTML
          text={isObjectLike(section.data) ? section.data.text : section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.trend:
    case SECTION_TYPES.number: {
      let numberData;
      if (isNumber(section.data)) {
        numberData = { currSum: section.data };
      } else {
        numberData = section.data;
      }
      sectionToRender = (
        <SectionNumber
          layout={section.layout.layout}
          title={section.title}
          titleStyle={section.layout.titleStyle}
          numberStyle={section.layout.numberStyle}
          data={numberData}
          sign={section.layout.currencySign || section.layout.sign}
          signAlignment={section.layout.signAlignment}
          text={section.data}
          style={section.layout.style}
          valuesFormat={section.layout.valuesFormat}
          subTitle={section.layout.forceRangeMessage}
        />
      );
      break;
    }
    case SECTION_TYPES.duration:
      sectionToRender = (
        <SectionDuration
          data={section.data}
          chartProperties={section.layout.chartProperties}
          style={section.layout.style}
          titleStyle={section.titleStyle}
          title={section.title}
          forceRangeMessage={section.layout.forceRangeMessage}
        />
      );
      break;
    case SECTION_TYPES.list:
      if (Array.isArray(section.data) || isString(section.data)) {
        sectionToRender = (
          <SectionList
            data={section.data}
            columns={section.layout.tableColumns}
            classes={section.layout.classes}
            style={section.layout.style}
            titleStyle={section.titleStyle}
            title={section.title}
            emptyString={section.emptyNotification || getDefaultEmptyNotification()}
            forceRangeMessage={section.layout.forceRangeMessage}
          />
        );
      } else {
        sectionToRender = (
          <SectionGroupedList
            data={section.data}
            columns={section.layout.tableColumns}
            classes={section.layout.classes}
            style={section.layout.style}
            titleStyle={section.titleStyle}
            title={section.title}
            emptyString={section.emptyNotification || getDefaultEmptyNotification()}
            forceRangeMessage={section.layout.forceRangeMessage}
          />
        );
      }
      break;
    case SECTION_TYPES.markdown:
    case SECTION_TYPES.placeholder:
      sectionToRender = (
        <SectionMarkdown
          text={isObjectLike(section.data) ? section.data.text : section.data}
          style={section.layout.style}
          tableClasses={section.layout.tableClasses}
          doNotShowEmoji={section.layout.doNotShowEmoji}
          customClass={isPageBreakSection(section) ? 'page-break-section' : ''}
          forceRangeMessage={section.layout.forceRangeMessage}
        />
      );
      break;
    case SECTION_TYPES.date:
      sectionToRender = (
        <SectionDate
          date={section.layout.useCurrentTime ? moment() : section.data}
          style={section.layout.style}
          format={section.layout.format}
        />
      );
      break;
    case SECTION_TYPES.logo:
    case SECTION_TYPES.image:
      sectionToRender = (
        <SectionImage
          src={section.data}
          style={section.layout.style}
          alt={section.layout.alt}
          classes={section.layout.classes}
        />
      );
      break;
    case SECTION_TYPES.chart: {
      const dataType = get(section, 'query.type', null);
      const groupByField = get(section, 'query.groupBy', null);
      const chartGroupField = groupByField && groupByField.length > 0 ? groupByField[groupByField.length - 1] : null;
      const processedData = processData(dataType, section.data, groupByField);
      const processedLegendData = processData(dataType, section.layout.legend, groupByField);
      sectionToRender = (
        <SectionChart
          data={processedData}
          type={section.layout.chartType}
          style={section.layout.style}
          titleStyle={section.titleStyle}
          dimensions={section.layout.dimensions}
          chartProperties={section.layout.chartProperties}
          legend={processedLegendData}
          legendStyle={section.layout.legendStyle}
          sortBy={section.layout.sortBy}
          title={section.title}
          referenceLineX={section.layout.referenceLineX}
          referenceLineY={section.layout.referenceLineY}
          stacked={get(section, 'query.groupBy.length', 0) > 1 ||
          (Array.isArray(section.data) && section.data.some(group => get(group, 'groups.length') > 0))}
          fromDate={section.fromDate}
          toDate={section.toDate}
          reflectDimensions={section.layout.reflectDimensions}
          emptyString={section.emptyNotification || getDefaultEmptyNotification()}
          groupBy={chartGroupField}
          forceRangeMessage={section.layout.forceRangeMessage}
        />
      );
      break;
    }
    case SECTION_TYPES.table:
      if (isEmpty(section.data)) {
        sectionToRender = null;
        break;
      }
      sectionToRender = (
        <SectionTable
          data={section.data}
          columns={section.layout.tableColumns}
          readableHeaders={section.layout.readableHeaders}
          classes={section.layout.classes}
          style={section.layout.style}
          titleStyle={section.titleStyle}
          title={section.title}
          maxColumns={section.layout.maxColumns || (maxWidth ? maxWidth / 100 : 0)}
          emptyString={section.emptyNotification || getDefaultEmptyNotification()}
          forceRangeMessage={section.layout.forceRangeMessage}
          headerStyle={section.layout.headerStyle}
        />
      );
      break;
    case SECTION_TYPES.json:
      sectionToRender = (
        <SectionJson
          data={section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.divider:
      sectionToRender = (
        <SectionDivider
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.itemsSection:
      sectionToRender = (
        <ItemsSection
          style={section.layout.style}
          items={section.data}
          classes={section.layout.classes}
          titleStyle={section.titleStyle}
          title={section.title}
          description={section.description}
          columns={(section.layout.w / 4) * 2}
          hideItemTitleOnlyOne={section.hideItemTitleOnlyOne}
        />
      );
      break;
    case SECTION_TYPES.globalSection:
      sectionToRender = (

          {section.title &&
{section.title}
}
          {section.description &&
{section.description}
}
          <>
            {compact(Object.entries(groupBy(section.data || [], s => s.layout.rowPos)).map(([rowNum, subSections]) => {
              return (
                <div className="global-section-row" key={`${section.i}-${rowNum}`}>
                  {(subSections || []).map((subSection, i) => {
                    return (
                      <div key={`${section.i}-${rowNum}-subsection-${i}`} className="subsection-wrapper">
                        {getSectionComponent(subSection)}

                    );
                  })}

              );
            }))}
            { isEmpty(section.data) &&
              <WidgetEmptyState emptyString={section.emptyNotification || getDefaultEmptyNotification()} />
            }
          </>

      );
      break;
    default:
      return null;
  }
  return sectionToRender;
}
<commit_msg>CRTX-64873: Always display date in section if exists<commit_after>import { PAGE_BREAK_KEY, SECTION_TYPES } from '../constants/Constants';
import {
  ItemsSection,
  SectionChart,
  SectionDate,
  SectionGroupedList,
  SectionDivider,
  SectionDuration,
  SectionHeader,
  SectionImage,
  SectionJson,
  SectionList,
  SectionMarkdown,
  SectionNumber,
  SectionTable,
  SectionText,
  SectionHTML
} from '../components/Sections';
import { isNumber, isObjectLike, compact, isString, groupBy, get, isEmpty } from 'lodash';
import moment from 'moment-timezone';
import React from 'react';
import { processData } from './data';
import WidgetEmptyState from '../components/Sections/WidgetEmptyState';

function getDefaultEmptyNotification() {
  return 'No results found.';
}

function isPageBreakSection(section) {
  return !!get(section, 'layout.style.pageBreakBefore', false) || (section.type === SECTION_TYPES.markdown &&
      section.data && ((isString(section.data) ? section.data : section.data.text) || '').includes(PAGE_BREAK_KEY));
}

export function getSectionComponent(section, maxWidth) {
  let sectionToRender;
  switch (section.type) {
    case SECTION_TYPES.header:
      sectionToRender = (
        <SectionHeader
          header={section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.text:
      sectionToRender = (
        <SectionText
          text={isObjectLike(section.data) ? section.data.text : section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.html:
      sectionToRender = (
        <SectionHTML
          text={isObjectLike(section.data) ? section.data.text : section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.trend:
    case SECTION_TYPES.number: {
      let numberData;
      if (isNumber(section.data)) {
        numberData = { currSum: section.data };
      } else {
        numberData = section.data;
      }
      sectionToRender = (
        <SectionNumber
          layout={section.layout.layout}
          title={section.title}
          titleStyle={section.layout.titleStyle}
          numberStyle={section.layout.numberStyle}
          data={numberData}
          sign={section.layout.currencySign || section.layout.sign}
          signAlignment={section.layout.signAlignment}
          text={section.data}
          style={section.layout.style}
          valuesFormat={section.layout.valuesFormat}
          subTitle={section.layout.forceRangeMessage}
        />
      );
      break;
    }
    case SECTION_TYPES.duration:
      sectionToRender = (
        <SectionDuration
          data={section.data}
          chartProperties={section.layout.chartProperties}
          style={section.layout.style}
          titleStyle={section.titleStyle}
          title={section.title}
          forceRangeMessage={section.layout.forceRangeMessage}
        />
      );
      break;
    case SECTION_TYPES.list:
      if (Array.isArray(section.data) || isString(section.data)) {
        sectionToRender = (
          <SectionList
            data={section.data}
            columns={section.layout.tableColumns}
            classes={section.layout.classes}
            style={section.layout.style}
            titleStyle={section.titleStyle}
            title={section.title}
            emptyString={section.emptyNotification || getDefaultEmptyNotification()}
            forceRangeMessage={section.layout.forceRangeMessage}
          />
        );
      } else {
        sectionToRender = (
          <SectionGroupedList
            data={section.data}
            columns={section.layout.tableColumns}
            classes={section.layout.classes}
            style={section.layout.style}
            titleStyle={section.titleStyle}
            title={section.title}
            emptyString={section.emptyNotification || getDefaultEmptyNotification()}
            forceRangeMessage={section.layout.forceRangeMessage}
          />
        );
      }
      break;
    case SECTION_TYPES.markdown:
    case SECTION_TYPES.placeholder:
      sectionToRender = (
        <SectionMarkdown
          text={isObjectLike(section.data) ? section.data.text : section.data}
          style={section.layout.style}
          tableClasses={section.layout.tableClasses}
          doNotShowEmoji={section.layout.doNotShowEmoji}
          customClass={isPageBreakSection(section) ? 'page-break-section' : ''}
          forceRangeMessage={section.layout.forceRangeMessage}
        />
      );
      break;
    case SECTION_TYPES.date:
      sectionToRender = (
        <SectionDate
          date={section.data || (section.layout.useCurrentTime ? moment() : undefined)}
          style={section.layout.style}
          format={section.layout.format}
        />
      );
      break;
    case SECTION_TYPES.logo:
    case SECTION_TYPES.image:
      sectionToRender = (
        <SectionImage
          src={section.data}
          style={section.layout.style}
          alt={section.layout.alt}
          classes={section.layout.classes}
        />
      );
      break;
    case SECTION_TYPES.chart: {
      const dataType = get(section, 'query.type', null);
      const groupByField = get(section, 'query.groupBy', null);
      const chartGroupField = groupByField && groupByField.length > 0 ? groupByField[groupByField.length - 1] : null;
      const processedData = processData(dataType, section.data, groupByField);
      const processedLegendData = processData(dataType, section.layout.legend, groupByField);
      sectionToRender = (
        <SectionChart
          data={processedData}
          type={section.layout.chartType}
          style={section.layout.style}
          titleStyle={section.titleStyle}
          dimensions={section.layout.dimensions}
          chartProperties={section.layout.chartProperties}
          legend={processedLegendData}
          legendStyle={section.layout.legendStyle}
          sortBy={section.layout.sortBy}
          title={section.title}
          referenceLineX={section.layout.referenceLineX}
          referenceLineY={section.layout.referenceLineY}
          stacked={get(section, 'query.groupBy.length', 0) > 1 ||
          (Array.isArray(section.data) && section.data.some(group => get(group, 'groups.length') > 0))}
          fromDate={section.fromDate}
          toDate={section.toDate}
          reflectDimensions={section.layout.reflectDimensions}
          emptyString={section.emptyNotification || getDefaultEmptyNotification()}
          groupBy={chartGroupField}
          forceRangeMessage={section.layout.forceRangeMessage}
        />
      );
      break;
    }
    case SECTION_TYPES.table:
      if (isEmpty(section.data)) {
        sectionToRender = null;
        break;
      }
      sectionToRender = (
        <SectionTable
          data={section.data}
          columns={section.layout.tableColumns}
          readableHeaders={section.layout.readableHeaders}
          classes={section.layout.classes}
          style={section.layout.style}
          titleStyle={section.titleStyle}
          title={section.title}
          maxColumns={section.layout.maxColumns || (maxWidth ? maxWidth / 100 : 0)}
          emptyString={section.emptyNotification || getDefaultEmptyNotification()}
          forceRangeMessage={section.layout.forceRangeMessage}
          headerStyle={section.layout.headerStyle}
        />
      );
      break;
    case SECTION_TYPES.json:
      sectionToRender = (
        <SectionJson
          data={section.data}
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.divider:
      sectionToRender = (
        <SectionDivider
          style={section.layout.style}
        />
      );
      break;
    case SECTION_TYPES.itemsSection:
      sectionToRender = (
        <ItemsSection
          style={section.layout.style}
          items={section.data}
          classes={section.layout.classes}
          titleStyle={section.titleStyle}
          title={section.title}
          description={section.description}
          columns={(section.layout.w / 4) * 2}
          hideItemTitleOnlyOne={section.hideItemTitleOnlyOne}
        />
      );
      break;
    case SECTION_TYPES.globalSection:
      sectionToRender = (

          {section.title &&
{section.title}
}
          {section.description &&
{section.description}
}
          <>
            {compact(Object.entries(groupBy(section.data || [], s => s.layout.rowPos)).map(([rowNum, subSections]) => {
              return (
                <div className="global-section-row" key={`${section.i}-${rowNum}`}>
                  {(subSections || []).map((subSection, i) => {
                    return (
                      <div key={`${section.i}-${rowNum}-subsection-${i}`} className="subsection-wrapper">
                        {getSectionComponent(subSection)}

                    );
                  })}

              );
            }))}
            { isEmpty(section.data) &&
              <WidgetEmptyState emptyString={section.emptyNotification || getDefaultEmptyNotification()} />
            }
          </>

      );
      break;
    default:
      return null;
  }
  return sectionToRender;
}
<|endoftext|>


<commit_before>/* @flow */
import type { Narrow, Message, Stream, User } from '../types';
import { normalizeRecipients } from './message';

export const homeNarrow: Narrow = [];

export const homeNarrowStr: string = '[]';

export const isHomeNarrow = (narrow: Narrow): boolean => narrow.length === 0;

export const privateNarrow = (email: string): Narrow => [
  {
    operator: 'pm-with',
    operand: email,
  },
];

export const isPrivateNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'pm-with' && narrow[0].operand.indexOf(',') === -1;

export const groupNarrow = (emails: string[]): Narrow => [
  {
    operator: 'pm-with',
    operand: emails.join(),
  },
];

export const isGroupNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'pm-with' && narrow[0].operand.indexOf(',') >= 0;

export const isPrivateOrGroupNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'pm-with';

export const specialNarrow = (operand: string): Narrow => [
  {
    operator: 'is',
    operand,
  },
];

export const isSpecialNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'is';

export const allPrivateNarrow = specialNarrow('private');

export const allPrivateNarrowStr = JSON.stringify(allPrivateNarrow);

export const isAllPrivateNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'is' && narrow[0].operand === 'private';

export const streamNarrow = (stream: string): Narrow => [
  {
    operator: 'stream',
    operand: stream,
  },
];

export const isStreamNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'stream';

export const topicNarrow = (stream: string, topic: string): Narrow => [
  {
    operator: 'stream',
    operand: stream,
  },
  {
    operator: 'topic',
    operand: topic,
  },
];

export const isTopicNarrow = (narrow: Narrow): boolean =>
  narrow.length === 2 && narrow[1].operator === 'topic';

export const isStreamOrTopicNarrow = (narrow: Narrow): boolean =>
  narrow.length >= 1 && narrow[0].operator === 'stream';

export const searchNarrow = (query: string): Narrow => [
  {
    operator: 'search',
    operand: query,
  },
];

export const isSearchNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'search';

export const isMessageInNarrow = (message: Message, narrow: Narrow, ownEmail: string): boolean => {
  if (isHomeNarrow(narrow)) {
    return true;
  }

  if (isStreamNarrow(narrow) && message.display_recipient === narrow[0].operand) {
    return true;
  }

  if (
    isTopicNarrow(narrow) &&
    message.display_recipient === narrow[0].operand &&
    message.subject === narrow[1].operand
  ) {
    return true;
  }

  if (isPrivateOrGroupNarrow(narrow)) {
    const normalizedRecipients = normalizeRecipients(message.display_recipient);
    const normalizedNarrow = [...narrow[0].operand.split(','), ownEmail].sort().join(',');

    return normalizedRecipients === ownEmail || normalizedRecipients === normalizedNarrow;
  }

  if (isSpecialNarrow(narrow) && narrow[0].operand === message.type) {
    return true;
  }

  return false;
};

export const canSendToNarrow = (narrow: Narrow): boolean =>
  isPrivateNarrow(narrow) ||
  isGroupNarrow(narrow) ||
  isStreamNarrow(narrow) ||
  isTopicNarrow(narrow);

export const getNarrowFromMessage = (message: Message, email: string) => {
  if (Array.isArray(message.display_recipient)) {
    const recipient =
      message.display_recipient.length > 1
        ? message.display_recipient.filter(x => x.email !== email)
        : message.display_recipient;
    return groupNarrow(recipient.map(x => x.email));
  }

  if (message.subject && message.subject.length) {
    return topicNarrow(message.display_recipient, message.subject);
  }

  return streamNarrow(message.display_recipient);
};

export const validateNarrow = (narrow: Narrow, streams: Stream[], users: User[]): boolean => {
  if (isStreamOrTopicNarrow(narrow)) {
    // check if stream is not outdated
    return streams && streams.find(s => s.name === narrow[0].operand) !== undefined;
  } else if (isPrivateNarrow(narrow)) {
    // check user account is not deactivited
    return users && users.find(u => u.email === narrow[0].operand) !== undefined;
  }
  return isSpecialNarrow(narrow) || isHomeNarrow(narrow);
};
<commit_msg>Fix narrowing to groups not working (#1567)<commit_after>/* @flow */
import type { Narrow, Message, Stream, User } from '../types';
import { normalizeRecipients } from './message';

export const homeNarrow: Narrow = [];

export const homeNarrowStr: string = '[]';

export const isHomeNarrow = (narrow: Narrow): boolean => narrow.length === 0;

export const privateNarrow = (email: string): Narrow => [
  {
    operator: 'pm-with',
    operand: email,
  },
];

export const isPrivateNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'pm-with' && narrow[0].operand.indexOf(',') === -1;

export const groupNarrow = (emails: string[]): Narrow => [
  {
    operator: 'pm-with',
    operand: emails.join(),
  },
];

export const isGroupNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'pm-with' && narrow[0].operand.indexOf(',') >= 0;

export const isPrivateOrGroupNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'pm-with';

export const specialNarrow = (operand: string): Narrow => [
  {
    operator: 'is',
    operand,
  },
];

export const isSpecialNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'is';

export const allPrivateNarrow = specialNarrow('private');

export const allPrivateNarrowStr = JSON.stringify(allPrivateNarrow);

export const isAllPrivateNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'is' && narrow[0].operand === 'private';

export const streamNarrow = (stream: string): Narrow => [
  {
    operator: 'stream',
    operand: stream,
  },
];

export const isStreamNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'stream';

export const topicNarrow = (stream: string, topic: string): Narrow => [
  {
    operator: 'stream',
    operand: stream,
  },
  {
    operator: 'topic',
    operand: topic,
  },
];

export const isTopicNarrow = (narrow: Narrow): boolean =>
  narrow.length === 2 && narrow[1].operator === 'topic';

export const isStreamOrTopicNarrow = (narrow: Narrow): boolean =>
  narrow.length >= 1 && narrow[0].operator === 'stream';

export const searchNarrow = (query: string): Narrow => [
  {
    operator: 'search',
    operand: query,
  },
];

export const isSearchNarrow = (narrow: Narrow): boolean =>
  narrow.length === 1 && narrow[0].operator === 'search';

export const isMessageInNarrow = (message: Message, narrow: Narrow, ownEmail: string): boolean => {
  if (isHomeNarrow(narrow)) {
    return true;
  }

  if (isStreamNarrow(narrow) && message.display_recipient === narrow[0].operand) {
    return true;
  }

  if (
    isTopicNarrow(narrow) &&
    message.display_recipient === narrow[0].operand &&
    message.subject === narrow[1].operand
  ) {
    return true;
  }

  if (isPrivateOrGroupNarrow(narrow)) {
    const normalizedRecipients = normalizeRecipients(message.display_recipient);
    const normalizedNarrow = [...narrow[0].operand.split(','), ownEmail].sort().join(',');

    return normalizedRecipients === ownEmail || normalizedRecipients === normalizedNarrow;
  }

  if (isSpecialNarrow(narrow) && narrow[0].operand === message.type) {
    return true;
  }

  return false;
};

export const canSendToNarrow = (narrow: Narrow): boolean =>
  isPrivateNarrow(narrow) ||
  isGroupNarrow(narrow) ||
  isStreamNarrow(narrow) ||
  isTopicNarrow(narrow);

export const getNarrowFromMessage = (message: Message, email: string) => {
  if (Array.isArray(message.display_recipient)) {
    const recipient =
      message.display_recipient.length > 1
        ? message.display_recipient.filter(x => x.email !== email)
        : message.display_recipient;
    return groupNarrow(recipient.map(x => x.email));
  }

  if (message.subject && message.subject.length) {
    return topicNarrow(message.display_recipient, message.subject);
  }

  return streamNarrow(message.display_recipient);
};

export const validateNarrow = (narrow: Narrow, streams: Stream[], users: User[]): boolean => {
  if (isStreamOrTopicNarrow(narrow)) {
    // check if stream is not outdated
    return streams && streams.find(s => s.name === narrow[0].operand) !== undefined;
  }

  if (isPrivateNarrow(narrow)) {
    // check user account is not deactivited
    return users && users.find(u => u.email === narrow[0].operand) !== undefined;
  }

  return true;
};
<|endoftext|>


<commit_before>import { warn, warnAboutDepreation } from '../utils/utils.js'

export const defaultParams = {
  title: '',
  titleText: '',
  text: '',
  html: '',
  footer: '',
  icon: undefined,
  iconHtml: undefined,
  toast: false,
  animation: true,
  showClass: {
    popup: 'swal2-show',
    backdrop: 'swal2-backdrop-show',
    icon: 'swal2-icon-show',
  },
  hideClass: {
    popup: 'swal2-hide',
    backdrop: 'swal2-backdrop-hide',
    icon: 'swal2-icon-hide',
  },
  customClass: undefined,
  target: 'body',
  backdrop: true,
  heightAuto: true,
  allowOutsideClick: true,
  allowEscapeKey: true,
  allowEnterKey: true,
  stopKeydownPropagation: true,
  keydownListenerCapture: false,
  showConfirmButton: true,
  showCancelButton: false,
  preConfirm: undefined,
  confirmButtonText: 'OK',
  confirmButtonAriaLabel: '',
  confirmButtonColor: undefined,
  cancelButtonText: 'Cancel',
  cancelButtonAriaLabel: '',
  cancelButtonColor: undefined,
  buttonsStyling: true,
  reverseButtons: false,
  focusConfirm: true,
  focusCancel: false,
  showCloseButton: false,
  closeButtonHtml: '×',
  closeButtonAriaLabel: 'Close this dialog',
  showLoaderOnConfirm: false,
  imageUrl: undefined,
  imageWidth: undefined,
  imageHeight: undefined,
  imageAlt: '',
  timer: undefined,
  timerProgressBar: false,
  width: undefined,
  padding: undefined,
  background: undefined,
  input: undefined,
  inputPlaceholder: '',
  inputValue: '',
  inputOptions: {},
  inputAutoTrim: true,
  inputAttributes: {},
  inputValidator: undefined,
  validationMessage: undefined,
  grow: false,
  position: 'center',
  progressSteps: [],
  currentProgressStep: undefined,
  progressStepsDistance: undefined,
  onBeforeOpen: undefined,
  onOpen: undefined,
  onRender: undefined,
  onClose: undefined,
  onAfterClose: undefined,
  onDestroy: undefined,
  scrollbarPadding: true
}

export const updatableParams = [
  'title',
  'titleText',
  'text',
  'html',
  'icon',
  'customClass',
  'allowOutsideClick',
  'allowEscapeKey',
  'showConfirmButton',
  'showCancelButton',
  'confirmButtonText',
  'confirmButtonAriaLabel',
  'confirmButtonColor',
  'cancelButtonText',
  'cancelButtonAriaLabel',
  'cancelButtonColor',
  'buttonsStyling',
  'reverseButtons',
  'imageUrl',
  'imageWidth',
  'imageHeight',
  'imageAlt',
  'progressSteps',
  'currentProgressStep'
]

export const deprecatedParams = {
  animation: 'showClass" and "hideClass',
}

const toastIncompatibleParams = [
  'allowOutsideClick',
  'allowEnterKey',
  'backdrop',
  'focusConfirm',
  'focusCancel',
  'heightAuto',
  'keydownListenerCapture'
]

/**
 * Is valid parameter
 * @param {String} paramName
 */
export const isValidParameter = (paramName) => {
  return Object.prototype.hasOwnProperty.call(defaultParams, paramName)
}

/**
 * Is valid parameter for Swal.update() method
 * @param {String} paramName
 */
export const isUpdatableParameter = (paramName) => {
  return updatableParams.indexOf(paramName) !== -1
}

/**
 * Is deprecated parameter
 * @param {String} paramName
 */
export const isDeprecatedParameter = (paramName) => {
  return deprecatedParams[paramName]
}

const checkIfParamIsValid = (param) => {
  if (!isValidParameter(param)) {
    warn(`Unknown parameter "${param}"`)
  }
}

const checkIfToastParamIsValid = (param) => {
  if (toastIncompatibleParams.includes(param)) {
    warn(`The parameter "${param}" is incompatible with toasts`)
  }
}

const checkIfParamIsDeprecated = (param) => {
  if (isDeprecatedParameter(param)) {
    warnAboutDepreation(param, isDeprecatedParameter(param))
  }
}

/**
 * Show relevant warnings for given params
 *
 * @param params
 */
export const showWarningsForParams = (params) => {
  for (const param in params) {
    checkIfParamIsValid(param)

    if (params.toast) {
      checkIfToastParamIsValid(param)
    }

    checkIfParamIsDeprecated(param)
  }
}

export default defaultParams
<commit_msg>feat: make hideClass updatable (#1912)<commit_after>import { warn, warnAboutDepreation } from '../utils/utils.js'

export const defaultParams = {
  title: '',
  titleText: '',
  text: '',
  html: '',
  footer: '',
  icon: undefined,
  iconHtml: undefined,
  toast: false,
  animation: true,
  showClass: {
    popup: 'swal2-show',
    backdrop: 'swal2-backdrop-show',
    icon: 'swal2-icon-show',
  },
  hideClass: {
    popup: 'swal2-hide',
    backdrop: 'swal2-backdrop-hide',
    icon: 'swal2-icon-hide',
  },
  customClass: undefined,
  target: 'body',
  backdrop: true,
  heightAuto: true,
  allowOutsideClick: true,
  allowEscapeKey: true,
  allowEnterKey: true,
  stopKeydownPropagation: true,
  keydownListenerCapture: false,
  showConfirmButton: true,
  showCancelButton: false,
  preConfirm: undefined,
  confirmButtonText: 'OK',
  confirmButtonAriaLabel: '',
  confirmButtonColor: undefined,
  cancelButtonText: 'Cancel',
  cancelButtonAriaLabel: '',
  cancelButtonColor: undefined,
  buttonsStyling: true,
  reverseButtons: false,
  focusConfirm: true,
  focusCancel: false,
  showCloseButton: false,
  closeButtonHtml: '×',
  closeButtonAriaLabel: 'Close this dialog',
  showLoaderOnConfirm: false,
  imageUrl: undefined,
  imageWidth: undefined,
  imageHeight: undefined,
  imageAlt: '',
  timer: undefined,
  timerProgressBar: false,
  width: undefined,
  padding: undefined,
  background: undefined,
  input: undefined,
  inputPlaceholder: '',
  inputValue: '',
  inputOptions: {},
  inputAutoTrim: true,
  inputAttributes: {},
  inputValidator: undefined,
  validationMessage: undefined,
  grow: false,
  position: 'center',
  progressSteps: [],
  currentProgressStep: undefined,
  progressStepsDistance: undefined,
  onBeforeOpen: undefined,
  onOpen: undefined,
  onRender: undefined,
  onClose: undefined,
  onAfterClose: undefined,
  onDestroy: undefined,
  scrollbarPadding: true
}

export const updatableParams = [
  'title',
  'titleText',
  'text',
  'html',
  'icon',
  'hideClass',
  'customClass',
  'allowOutsideClick',
  'allowEscapeKey',
  'showConfirmButton',
  'showCancelButton',
  'confirmButtonText',
  'confirmButtonAriaLabel',
  'confirmButtonColor',
  'cancelButtonText',
  'cancelButtonAriaLabel',
  'cancelButtonColor',
  'buttonsStyling',
  'reverseButtons',
  'imageUrl',
  'imageWidth',
  'imageHeight',
  'imageAlt',
  'progressSteps',
  'currentProgressStep'
]

export const deprecatedParams = {
  animation: 'showClass" and "hideClass',
}

const toastIncompatibleParams = [
  'allowOutsideClick',
  'allowEnterKey',
  'backdrop',
  'focusConfirm',
  'focusCancel',
  'heightAuto',
  'keydownListenerCapture'
]

/**
 * Is valid parameter
 * @param {String} paramName
 */
export const isValidParameter = (paramName) => {
  return Object.prototype.hasOwnProperty.call(defaultParams, paramName)
}

/**
 * Is valid parameter for Swal.update() method
 * @param {String} paramName
 */
export const isUpdatableParameter = (paramName) => {
  return updatableParams.indexOf(paramName) !== -1
}

/**
 * Is deprecated parameter
 * @param {String} paramName
 */
export const isDeprecatedParameter = (paramName) => {
  return deprecatedParams[paramName]
}

const checkIfParamIsValid = (param) => {
  if (!isValidParameter(param)) {
    warn(`Unknown parameter "${param}"`)
  }
}

const checkIfToastParamIsValid = (param) => {
  if (toastIncompatibleParams.includes(param)) {
    warn(`The parameter "${param}" is incompatible with toasts`)
  }
}

const checkIfParamIsDeprecated = (param) => {
  if (isDeprecatedParameter(param)) {
    warnAboutDepreation(param, isDeprecatedParameter(param))
  }
}

/**
 * Show relevant warnings for given params
 *
 * @param params
 */
export const showWarningsForParams = (params) => {
  for (const param in params) {
    checkIfParamIsValid(param)

    if (params.toast) {
      checkIfToastParamIsValid(param)
    }

    checkIfParamIsDeprecated(param)
  }
}

export default defaultParams
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';

import { MODAL_KEYS } from '../utilities';

import { DataTablePageModal } from '../widgets/modals';
import { DataTable, DataTableHeaderRow, DataTableRow } from '../widgets/DataTable';
import { DataTablePageView, PageButton, PageInfo, SearchBar } from '../widgets';

import { getItemLayout } from './dataTableUtilities';

import { usePageReducer, useRecordListener } from '../hooks';

import globalStyles from '../globalStyles';
import { buttonStrings } from '../localization';

/**
 * Renders a mSupply mobile page with a customer requisition loaded for editing
 *
 * State:
 * Uses a reducer to manage state with `backingData` being a realm results
 * of items to display. `data` is a plain JS array of realm objects. data is
 * hydrated from the `backingData` for displaying in the interface.
 * i.e: When filtering, data is populated from filtered items of `backingData`.
 *
 * dataState is a simple map of objects corresponding to a row being displayed,
 * holding the state of a given row. Each object has the shape :
 * { isSelected, isDisabled },
 *
 * @prop {Object} requisition The realm transaction object for this invoice.
 * @prop {Func}   runWithLoadingIndicator Callback for displaying a fullscreen spinner.
 * @prop {String} routeName The current route name for the top of the navigation stack.
 */
export const CustomerRequisitionPage = ({ requisition, runWithLoadingIndicator, routeName }) => {
  const initialState = { page: routeName, pageObject: requisition };
  const [state, dispatch, instantDebouncedDispatch] = usePageReducer(initialState);

  const {
    data,
    dataState,
    sortBy,
    isAscending,
    modalKey,
    pageObject,
    keyExtractor,
    modalValue,
    searchTerm,
    PageActions,
    columns,
    getPageInfoColumns,
  } = state;

  // Listen for changes to this pages requisition. Refreshing data on side effects i.e. finalizing.
  useRecordListener(() => dispatch(PageActions.refreshData()), requisition, 'Requisition');

  const { isFinalised, comment } = pageObject;

  // On click handlers
  const onCloseModal = () => dispatch(PageActions.closeModal());
  const onAddItem = value => dispatch(PageActions.addRequisitionItem(value));
  const onEditComment = value => dispatch(PageActions.editComment(value, 'Requisition'));
  const onFilterData = value => dispatch(PageActions.filterData(value));
  const onEditSuppliedQuantity = (newValue, rowKey, columnKey) =>
    dispatch(PageActions.editSuppliedQuantity(newValue, rowKey, columnKey));
  const onSetSuppliedToRequested = () =>
    runWithLoadingIndicator(() => dispatch(PageActions.setSuppliedToRequested()));
  const onSetSuppliedToSuggested = () =>
    runWithLoadingIndicator(() => dispatch(PageActions.setSuppliedToSuggested()));

  const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [
    comment,
    isFinalised,
  ]);

  const getCallback = useCallback(colKey => {
    switch (colKey) {
      case 'suppliedQuantity':
        return onEditSuppliedQuantity;
      default:
        return null;
    }
  }, []);

  const getModalOnSelect = () => {
    switch (modalKey) {
      case MODAL_KEYS.SELECT_ITEM:
        return onAddItem;
      case MODAL_KEYS.REQUISITION_COMMENT_EDIT:
        return onEditComment;
      default:
        return null;
    }
  };

  const renderRow = useCallback(
    listItem => {
      const { item, index } = listItem;
      const rowKey = keyExtractor(item);
      return (
        <DataTableRow
          rowData={data[index]}
          rowKey={rowKey}
          columns={columns}
          isFinalised={isFinalised}
          getCallback={getCallback}
          rowIndex={index}
        />
      );
    },
    [data, dataState]
  );

  const renderHeader = useCallback(
    () => (
      <DataTableHeaderRow
        columns={columns}
        dispatch={instantDebouncedDispatch}
        sortAction={PageActions.sortData}
        isAscending={isAscending}
        sortBy={sortBy}
      />
    ),
    [sortBy, isAscending]
  );

  const {
    pageTopSectionContainer,
    pageTopLeftSectionContainer,
    pageTopRightSectionContainer,
  } = globalStyles;
  return (
    <DataTablePageView>
      <View style={pageTopSectionContainer}>
        <View style={pageTopLeftSectionContainer}>
          <PageInfo columns={pageInfoColumns} isEditingDisabled={isFinalised} />
          <SearchBar onChangeText={onFilterData} value={searchTerm} />
        </View>
        <View style={pageTopRightSectionContainer}>
          <PageButton
            style={globalStyles.topButton}
            text={buttonStrings.use_requested_quantities}
            onPress={onSetSuppliedToRequested}
            isDisabled={requisition.isFinalised}
          />
          <PageButton
            style={globalStyles.topButton}
            text={buttonStrings.use_suggested_quantities}
            onPress={onSetSuppliedToSuggested}
            isDisabled={isFinalised}
          />
        </View>
      </View>
      <DataTable
        data={data}
        renderRow={renderRow}
        renderHeader={renderHeader}
        keyExtractor={keyExtractor}
        getItemLayout={getItemLayout}
        columns={columns}
      />
      <DataTablePageModal
        fullScreen={false}
        isOpen={!!modalKey}
        modalKey={modalKey}
        onClose={onCloseModal}
        onSelect={getModalOnSelect()}
        dispatch={dispatch}
        currentValue={modalValue}
      />
    </DataTablePageView>
  );
};

/* eslint-disable react/forbid-prop-types */
CustomerRequisitionPage.propTypes = {
  runWithLoadingIndicator: PropTypes.func.isRequired,
  requisition: PropTypes.object.isRequired,
  routeName: PropTypes.string.isRequired,
};
<commit_msg>Add convert CustomerRequisitionPage to use redux<commit_after>/* eslint-disable react/forbid-prop-types */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import { connect } from 'react-redux';

import { MODAL_KEYS } from '../utilities';

import { DataTablePageModal } from '../widgets/modals';
import { DataTable, DataTableHeaderRow, DataTableRow } from '../widgets/DataTable';
import { DataTablePageView, PageButton, PageInfo, SearchBar } from '../widgets';

import { getItemLayout } from './dataTableUtilities';

import { useRecordListener } from '../hooks';

import globalStyles from '../globalStyles';
import { buttonStrings } from '../localization';

/**
 * Renders a mSupply mobile page with a customer requisition loaded for editing
 *
 * State:
 * Uses a reducer to manage state with `backingData` being a realm results
 * of items to display. `data` is a plain JS array of realm objects. data is
 * hydrated from the `backingData` for displaying in the interface.
 * i.e: When filtering, data is populated from filtered items of `backingData`.
 *
 * dataState is a simple map of objects corresponding to a row being displayed,
 * holding the state of a given row. Each object has the shape :
 * { isSelected, isDisabled },
 *
 * @prop {Object} requisition The realm transaction object for this invoice.
 * @prop {Func}   runWithLoadingIndicator Callback for displaying a fullscreen spinner.
 * @prop {String} routeName The current route name for the top of the navigation stack.
 */
export const CustomerRequisition = ({
  runWithLoadingIndicator,
  data,
  dispatch,
  dataState,
  sortBy,
  isAscending,
  modalKey,
  pageObject,
  keyExtractor,
  modalValue,
  searchTerm,
  PageActions,
  columns,
  getPageInfoColumns,
}) => {
  // Listen for changes to this pages requisition. Refreshing data on side effects i.e. finalizing.
  useRecordListener(() => dispatch(PageActions.refreshData()), pageObject, 'Requisition');

  const { isFinalised, comment } = pageObject;

  // On click handlers
  const onCloseModal = () => dispatch(PageActions.closeModal());
  const onAddItem = value => dispatch(PageActions.addRequisitionItem(value));
  const onEditComment = value => dispatch(PageActions.editComment(value, 'Requisition'));
  const onFilterData = value => dispatch(PageActions.filterData(value));
  const onEditSuppliedQuantity = (newValue, rowKey, columnKey) =>
    dispatch(PageActions.editSuppliedQuantity(newValue, rowKey, columnKey));
  const onSetSuppliedToRequested = () =>
    runWithLoadingIndicator(() => dispatch(PageActions.setSuppliedToRequested()));
  const onSetSuppliedToSuggested = () =>
    runWithLoadingIndicator(() => dispatch(PageActions.setSuppliedToSuggested()));

  const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [
    comment,
    isFinalised,
  ]);

  const getCallback = useCallback(colKey => {
    switch (colKey) {
      case 'suppliedQuantity':
        return onEditSuppliedQuantity;
      default:
        return null;
    }
  }, []);

  const getModalOnSelect = () => {
    switch (modalKey) {
      case MODAL_KEYS.SELECT_ITEM:
        return onAddItem;
      case MODAL_KEYS.REQUISITION_COMMENT_EDIT:
        return onEditComment;
      default:
        return null;
    }
  };

  const renderRow = useCallback(
    listItem => {
      const { item, index } = listItem;
      const rowKey = keyExtractor(item);
      return (
        <DataTableRow
          rowData={data[index]}
          rowKey={rowKey}
          columns={columns}
          isFinalised={isFinalised}
          getCallback={getCallback}
          rowIndex={index}
        />
      );
    },
    [data, dataState]
  );

  const renderHeader = useCallback(
    () => (
      <DataTableHeaderRow
        columns={columns}
        dispatch={dispatch}
        sortAction={PageActions.sortData}
        isAscending={isAscending}
        sortBy={sortBy}
      />
    ),
    [sortBy, isAscending]
  );

  const {
    pageTopSectionContainer,
    pageTopLeftSectionContainer,
    pageTopRightSectionContainer,
  } = globalStyles;
  return (
    <DataTablePageView>
      <View style={pageTopSectionContainer}>
        <View style={pageTopLeftSectionContainer}>
          <PageInfo columns={pageInfoColumns} isEditingDisabled={isFinalised} />
          <SearchBar onChangeText={onFilterData} value={searchTerm} />
        </View>
        <View style={pageTopRightSectionContainer}>
          <PageButton
            style={globalStyles.topButton}
            text={buttonStrings.use_requested_quantities}
            onPress={onSetSuppliedToRequested}
            isDisabled={isFinalised}
          />
          <PageButton
            style={globalStyles.topButton}
            text={buttonStrings.use_suggested_quantities}
            onPress={onSetSuppliedToSuggested}
            isDisabled={isFinalised}
          />
        </View>
      </View>
      <DataTable
        data={data}
        renderRow={renderRow}
        renderHeader={renderHeader}
        keyExtractor={keyExtractor}
        getItemLayout={getItemLayout}
        columns={columns}
      />
      <DataTablePageModal
        fullScreen={false}
        isOpen={!!modalKey}
        modalKey={modalKey}
        onClose={onCloseModal}
        onSelect={getModalOnSelect()}
        dispatch={dispatch}
        currentValue={modalValue}
      />
    </DataTablePageView>
  );
};

const mapStateToProps = state => {
  const { pages } = state;
  const { customerRequisition } = pages;
  return customerRequisition;
};

export const CustomerRequisitionPage = connect(mapStateToProps)(CustomerRequisition);

CustomerRequisition.defaultProps = {
  modalValue: null,
};

CustomerRequisition.propTypes = {
  dispatch: PropTypes.func.isRequired,
  data: PropTypes.array.isRequired,
  sortBy: PropTypes.string.isRequired,
  isAscending: PropTypes.bool.isRequired,
  searchTerm: PropTypes.string.isRequired,
  PageActions: PropTypes.object.isRequired,
  columns: PropTypes.array.isRequired,
  keyExtractor: PropTypes.func.isRequired,
  runWithLoadingIndicator: PropTypes.func.isRequired,
  dataState: PropTypes.object.isRequired,
  modalKey: PropTypes.string.isRequired,
  pageObject: PropTypes.object.isRequired,
  modalValue: PropTypes.any,
  getPageInfoColumns: PropTypes.func.isRequired,
};
<|endoftext|>