<commit_before>const _ = require("underscore"),
  async = require("async"),
  through2 = require("through2"),
  clone = require("clone"),
  promisify = require("util.promisify"),
  mergeDefaults = require("merge-defaults"),
  configDefaults = require("require-directory")(module, "config"),
  helpers = require("./helpers.js"),
  path = require("path"),
  toIco = require("to-ico");

(() => {
  "use strict";

  _.mergeDefaults = mergeDefaults;

  function favicons(source, parameters, next) {
    const config = clone(configDefaults),
      options = _.mergeDefaults(parameters || {}, config.defaults),
      µ = helpers(options);

    function createFavicon(
      sourceset,
      properties,
      name,
      platformOptions,
      callback
    ) {
      if (path.extname(name) === ".ico") {
        async.map(
          properties.sizes,
          (sizeProperties, cb) => {
            const newProperties = clone(properties);

            newProperties.width = sizeProperties.width;
            newProperties.height = sizeProperties.height;

            const tempName = `favicon-temp-${newProperties.width}x${
              newProperties.height
            }.png`;

            createFavicon(
              sourceset,
              newProperties,
              tempName,
              platformOptions,
              cb
            );
          },
          (error, results) => {
            if (error) {
              return callback(error);
            }

            const files = results.map(icoImage => icoImage.contents);

            toIco(files)
              .then(buffer => callback(null, { name, contents: buffer }))
              .catch(callback);
          }
        );
      } else {
        const maximum = Math.max(properties.width, properties.height),
          offset = Math.round(maximum / 100 * platformOptions.offset) || 0,
          background = µ.General.background(platformOptions.background);

        if (platformOptions.disableTransparency) {
          properties.transparent = false;
        }

        async.waterfall(
          [
            cb =>
              µ.Images.nearest(sourceset, properties, offset)
                .then(result => cb(null, result))
                .catch(cb),
            (nearest, cb) =>
              µ.Images.read(nearest.file)
                .then(result => cb(null, result))
                .catch(cb),
            (buffer, cb) =>
              µ.Images.resize(buffer, properties, offset)
                .then(result => cb(null, result))
                .catch(cb),
            (resizedBuffer, cb) =>
              µ.Images.create(properties, background)
                .then(canvas => cb(null, resizedBuffer, canvas))
                .catch(cb),
            (resizedBuffer, canvas, cb) =>
              µ.Images.composite(
                canvas,
                resizedBuffer,
                properties,
                offset,
                maximum
              )
                .then(result => cb(null, result))
                .catch(cb),
            (composite, cb) =>
              µ.Images.getBuffer(composite, cb)
                .then(result => cb(null, result))
                .catch(cb)
          ],
          (error, buffer) => callback(error, { name, contents: buffer })
        );
      }
    }

    function createHTML(platform, callback) {
      const html = [];

      async.forEachOf(
        config.html[platform],
        (tag, selector, cb) =>
          µ.HTML.parse(tag, (error, metadata) =>
            cb(html.push(metadata) && error)
          ),
        error => callback(error, html)
      );
    }

    function createFiles(platform, platformOptions, callback) {
      const files = [];

      async.forEachOf(
        config.files[platform],
        (properties, name, cb) =>
          µ.Files.create(properties, name, platformOptions)
            .then(file => cb(files.push(file) && null))
            .catch(cb),
        error => callback(error, files)
      );
    }

    function createFavicons(sourceset, platform, platformOptions, callback) {
      const images = [];

      async.forEachOf(
        config.icons[platform],
        (properties, name, cb) =>
          createFavicon(
            sourceset,
            properties,
            name,
            platformOptions,
            (error, image) => cb(images.push(image) && error)
          ),
        error => callback(error, images)
      );
    }

    function createPlatform(sourceset, platform, platformOptions) {
      return Promise.all([
        promisify(createFavicons)(sourceset, platform, platformOptions),
        promisify(createFiles)(platform, platformOptions),
        promisify(createHTML)(platform)
      ]);
    }

    function create(sourceset) {
      return Promise.all(
        Object.keys(options.icons)
          .filter(platform => options.icons[platform])
          .map(platform =>
            createPlatform(
              sourceset,
              platform,
              µ.General.preparePlatformOptions(
                platform,
                options.icons[platform],
                options
              )
            )
          )
      ).then(responses => ({
        images: [].concat(...responses.map(r => r[0])),
        files: [].concat(...responses.map(r => r[1])),
        html: [].concat(...responses.map(r => r[2])).sort()
      }));
    }

    async.waterfall(
      [
        callback =>
          µ.General.source(source)
            .then(result => callback(null, result))
            .catch(callback),
        (sourceset, callback) =>
          create(sourceset)
            .then(result => callback(null, result))
            .catch(callback),
        (response, callback) => {
          if (options.pipeHTML) {
            µ.Files.create(response.html, options.html, false)
              .then(file => {
                response.files = [...response.files, file];
                return response;
              })
              .then(result => callback(null, result))
              .catch(callback);
          } else {
            return callback(null, response);
          }
        }
      ],
      (error, response) =>
        error
          ? next(error)
          : next(null, {
              images: _.compact(response.images),
              files: _.compact(response.files),
              html: _.compact(response.html)
            })
    );
  }

  function stream(params, handleHtml) {
    const config = clone(configDefaults),
      µ = helpers(params);

    function processDocuments(documents, html, callback) {
      async.each(
        documents,
        (document, cb) => µ.HTML.update(document, html, config.html, cb),
        error => callback(error)
      );
    }

    /* eslint func-names: 0, no-invalid-this: 0 */
    return through2.obj(function(file, encoding, callback) {
      const that = this;

      if (file.isNull()) {
        return callback(null, file);
      }

      if (file.isStream()) {
        return callback(new Error("[gulp-favicons] Streaming not supported"));
      }

      async.waterfall(
        [
          cb => favicons(file.contents, params, cb),
          (response, cb) =>
            async.each(
              response.images.concat(response.files),
              (image, c) => {
                that.push(µ.General.vinyl(image, file));
                c();
              },
              error => cb(error, response)
            ),
          (response, cb) => {
            if (handleHtml) {
              handleHtml(response.html);
              return cb(null);
            }
            if (params.html && !params.pipeHTML) {
              const documents =
                typeof params.html === "object" ? params.html : [params.html];

              processDocuments(documents, response.html, cb);
            } else {
              return cb(null);
            }
          }
        ],
        error => callback(error)
      );
    });
  }

  module.exports = promisify(favicons);
  module.exports.config = configDefaults;
  module.exports.stream = stream;
})();
<commit_msg>promisify createFavicon<commit_after>const _ = require("underscore"),
  async = require("async"),
  through2 = require("through2"),
  clone = require("clone"),
  promisify = require("util.promisify"),
  mergeDefaults = require("merge-defaults"),
  configDefaults = require("require-directory")(module, "config"),
  helpers = require("./helpers.js"),
  path = require("path"),
  toIco = require("to-ico");

(() => {
  "use strict";

  _.mergeDefaults = mergeDefaults;

  function favicons(source, parameters, next) {
    const config = clone(configDefaults),
      options = _.mergeDefaults(parameters || {}, config.defaults),
      µ = helpers(options);

    function createFavicon(sourceset, properties, name, platformOptions) {
      if (path.extname(name) === ".ico") {
        return Promise.all(
          properties.sizes.map(({ width, height }) =>
            createFavicon(
              sourceset,
              Object.assign({}, properties, { width, height }),
              `${width}x${height}.png`,
              platformOptions
            )
          )
        ).then(results =>
          toIco(results.map(({ contents }) => contents)).then(buffer => ({
            name,
            contents: buffer
          }))
        );
      }

      const maximum = Math.max(properties.width, properties.height),
        offset = Math.round(maximum / 100 * platformOptions.offset) || 0,
        background = µ.General.background(platformOptions.background);

      if (platformOptions.disableTransparency) {
        properties.transparent = false;
      }

      return Promise.all([
        µ.Images.create(properties, background),
        µ.Images.nearest(sourceset, properties, offset)
          .then(nearest => µ.Images.read(nearest.file))
          .then(buffer => µ.Images.resize(buffer, properties, offset))
      ])
        .then(([canvas, buffer]) =>
          µ.Images.composite(canvas, buffer, properties, offset, maximum)
        )
        .then(µ.Images.getBuffer)
        .then(contents => ({ name, contents }));
    }

    function createHTML(platform, callback) {
      const html = [];

      async.forEachOf(
        config.html[platform],
        (tag, selector, cb) =>
          µ.HTML.parse(tag, (error, metadata) =>
            cb(html.push(metadata) && error)
          ),
        error => callback(error, html)
      );
    }

    function createFiles(platform, platformOptions, callback) {
      const files = [];

      async.forEachOf(
        config.files[platform],
        (properties, name, cb) =>
          µ.Files.create(properties, name, platformOptions)
            .then(file => cb(files.push(file) && null))
            .catch(cb),
        error => callback(error, files)
      );
    }

    function createFavicons(sourceset, platform, platformOptions, callback) {
      const images = [];

      async.forEachOf(
        config.icons[platform],
        (properties, name, cb) =>
          createFavicon(sourceset, properties, name, platformOptions)
            .then(image => cb(images.push(image) && null))
            .catch(cb),
        error => callback(error, images)
      );
    }

    function createPlatform(sourceset, platform, platformOptions) {
      return Promise.all([
        promisify(createFavicons)(sourceset, platform, platformOptions),
        promisify(createFiles)(platform, platformOptions),
        promisify(createHTML)(platform)
      ]);
    }

    function create(sourceset) {
      return Promise.all(
        Object.keys(options.icons)
          .filter(platform => options.icons[platform])
          .map(platform =>
            createPlatform(
              sourceset,
              platform,
              µ.General.preparePlatformOptions(
                platform,
                options.icons[platform],
                options
              )
            )
          )
      ).then(responses => ({
        images: [].concat(...responses.map(r => r[0])),
        files: [].concat(...responses.map(r => r[1])),
        html: [].concat(...responses.map(r => r[2])).sort()
      }));
    }

    async.waterfall(
      [
        callback =>
          µ.General.source(source)
            .then(result => callback(null, result))
            .catch(callback),
        (sourceset, callback) =>
          create(sourceset)
            .then(result => callback(null, result))
            .catch(callback),
        (response, callback) => {
          if (options.pipeHTML) {
            µ.Files.create(response.html, options.html, false)
              .then(file => {
                response.files = [...response.files, file];
                return response;
              })
              .then(result => callback(null, result))
              .catch(callback);
          } else {
            return callback(null, response);
          }
        }
      ],
      (error, response) =>
        error
          ? next(error)
          : next(null, {
              images: _.compact(response.images),
              files: _.compact(response.files),
              html: _.compact(response.html)
            })
    );
  }

  function stream(params, handleHtml) {
    const config = clone(configDefaults),
      µ = helpers(params);

    function processDocuments(documents, html, callback) {
      async.each(
        documents,
        (document, cb) => µ.HTML.update(document, html, config.html, cb),
        error => callback(error)
      );
    }

    /* eslint func-names: 0, no-invalid-this: 0 */
    return through2.obj(function(file, encoding, callback) {
      const that = this;

      if (file.isNull()) {
        return callback(null, file);
      }

      if (file.isStream()) {
        return callback(new Error("[gulp-favicons] Streaming not supported"));
      }

      async.waterfall(
        [
          cb => favicons(file.contents, params, cb),
          (response, cb) =>
            async.each(
              response.images.concat(response.files),
              (image, c) => {
                that.push(µ.General.vinyl(image, file));
                c();
              },
              error => cb(error, response)
            ),
          (response, cb) => {
            if (handleHtml) {
              handleHtml(response.html);
              return cb(null);
            }
            if (params.html && !params.pipeHTML) {
              const documents =
                typeof params.html === "object" ? params.html : [params.html];

              processDocuments(documents, response.html, cb);
            } else {
              return cb(null);
            }
          }
        ],
        error => callback(error)
      );
    });
  }

  module.exports = promisify(favicons);
  module.exports.config = configDefaults;
  module.exports.stream = stream;
})();
<|endoftext|>


<commit_before>import {
  buildPriorityQueue,
  getChangeListeners,
  getPreCommitListeners,
  getPriorityQueue,
  mixinNotifier,
  queueNotification
} from './utils';

function notifyPreCommit(source, changes) {
  let canceled = false;
  const queue = getPriorityQueue(source, 'preCommitPriorityQueue');
  if (queue.length === 0) {
    buildPriorityQueue(getPreCommitListeners.call(source), queue);
  }
  queue.forEach(function (item) {
    canceled = ( item.callback(source, changes, canceled, item.priority) === false ) || canceled;
  });
  return canceled;
}

/**
 * Structures the prototype to define a bindable property
 * on the first write when "this" is an instance of the
 * class or prototype.
 *
 * @param {Object} descriptor The Descriptor provided by the call to the decorator
 */
export function bindable(descriptor) {
  descriptor.finisher = function (clazz) {
    // Mixin
    mixinNotifier(clazz.prototype);
  };
  const {descriptor: propertyDescriptor, key} = descriptor;
  descriptor.kind = 'method';
  descriptor.placement = 'prototype';
  descriptor.descriptor = ( function (initialValue, propertyDescriptor, property) {
    let value = initialValue;
    return {
      get: ( propertyDescriptor.get || function () {
        return value;
      } ),
      set: function (newValue) {
        const self = this;
        const suspendNotifications = self.suspendNotifications;
        const oldValue = value;
        // Honor an existing setter if any
        if (typeof propertyDescriptor.set === 'function') {
          propertyDescriptor.set.call(self, newValue);
          // Mutations? Casts?
          if (propertyDescriptor.get) {
            value = propertyDescriptor.get.call(self);
          }
        }
        if (value === newValue || notifyPreCommit(self, {[property]: {oldValue, newValue}})) {
          return;
        }
        value = newValue;
        if (suspendNotifications === false && !getChangeListeners.call(self).values().next().done) {
          queueNotification(self, property, oldValue, newValue);
        }
      },
      enumerable: propertyDescriptor.enumerable !== undefined ? propertyDescriptor.enumerable : true
    }
  } )(descriptor.initializer ? descriptor.initializer() : null, descriptor.descriptor, key);

  delete descriptor.initializer;
  return descriptor;
}

export { queueNotification };
<commit_msg>Minor cleanup<commit_after>import {
  buildPriorityQueue,
  getChangeListeners,
  getPreCommitListeners,
  getPriorityQueue,
  mixinNotifier,
  queueNotification
} from './utils';

function notifyPreCommit(source, changes) {
  let canceled = false;
  const queue = getPriorityQueue(source, 'preCommitPriorityQueue');
  if (queue.length === 0) {
    buildPriorityQueue(getPreCommitListeners.call(source), queue);
  }
  queue.forEach(function (item) {
    canceled = ( item.callback(source, changes, canceled, item.priority) === false ) || canceled;
  });
  return canceled;
}

/**
 * Structures the prototype to define a bindable property
 * on the first write when "this" is an instance of the
 * class or prototype.
 *
 * @param {Object} descriptor The Descriptor provided by the call to the decorator
 */
export function bindable(descriptor) {
  descriptor.finisher = function (clazz) {
    // Mixin
    mixinNotifier(clazz.prototype);
  };
  const {key} = descriptor;
  descriptor.kind = 'method';
  descriptor.placement = 'prototype';
  descriptor.descriptor = ( function (initialValue, propertyDescriptor, property) {
    let value = initialValue;
    return {
      get: ( propertyDescriptor.get || function () {
        return value;
      } ),
      set: function (newValue) {
        const self = this;
        const suspendNotifications = self.suspendNotifications;
        const oldValue = value;
        // Honor an existing setter if any
        if (typeof propertyDescriptor.set === 'function') {
          propertyDescriptor.set.call(self, newValue);
          // Mutations? Casts?
          if (propertyDescriptor.get) {
            value = propertyDescriptor.get.call(self);
          }
        }
        if (value === newValue || notifyPreCommit(self, {[ property ]: {oldValue, newValue}})) {
          return;
        }
        value = newValue;
        if (suspendNotifications === false && !getChangeListeners.call(self).values().next().done) {
          queueNotification(self, property, oldValue, newValue);
        }
      },
      enumerable: propertyDescriptor.enumerable !== undefined ? propertyDescriptor.enumerable : true
    }
  } )(descriptor.initializer ? descriptor.initializer() : null, descriptor.descriptor, key);

  delete descriptor.initializer;
  return descriptor;
}

export { queueNotification };
<|endoftext|>


<commit_before>import _ from 'lodash'
import configureStrategies from './configure/strategies'
import configureRoutes from './configure/routes'
import configureMiddleware from './configure/middleware'
import configureSerializing from './configure/serialize'
import sessionOrToken from './middleware/sessionOrToken'
import createAuthMiddleware from './middleware/authorised'
import createInternalMiddleware from './middleware/internal'
import AccessToken from './models/AccessToken'
import RefreshToken from './models/RefreshToken'
import {createToken} from './lib'

const defaults = {
  middleware: {
    initialize: true,
    session: true,
  },
  paths: {
    login: '/login',
    logout: '/logout',
    loginStatus: '/login-status',
    register: '/register',
    resetRequest: '/reset-request',
    reset: '/reset',
    confirm: '/confirm-email',
    success: '/',
  },
  serializing: {

  },
  login: {
    userQuery: email => ({email}),
    isValidUsername: email => email && _.isString(email) && email.match(/.+@.+/),
    usernameField: 'email',
    passwordField: 'password',
    badRequestMessage: 'Missing credentials',
    resetTokenExpiresMs: 1000 * 60 * 60 * 24 * 7, // 7 days
    extraRegisterParams: [],
  },
  sendConfirmationEmail: (user, callback) => {
    console.log('[fl-auth] sendConfirmationEmail not configured. No email confirmation email will be sent. Token:', user.get('email'), user.get('emailConfirmationToken'))
    callback()
  },
  sendResetEmail: (user, callback) => {
    console.log('[fl-auth] sendResetEmail not configured. No password reset email will be sent. Reset token:', user.get('email'), user.get('resetToken'))
    callback()
  },

  setReturnTo: (req, res, next) => {
    req.session.returnTo = req.query.returnTo || req.headers.referer
    req.session.save(err => {
      if (err) console.log('[fl-auth] Error saving session', err)
      next()
    })
  }
}

const oAuthDefaults = {
  facebook: {
    url: process.env.URL,
    paths: {
      redirect: '/auth/facebook',
      callback: '/auth/facebook/callback',
      mobile: '/auth/facebook/mobile',
    },
    scope: ['email'],
    profileFields: [
      'id',
      'displayName',
      'email',
      'cover',
      'name',
      'age_range',
      'link',
      'locale',
      'picture',
      'timezone',
      'updated_time',
      'verified',
    ],
    onLogin: (user, profile, isNew, callback) => callback(),
  },
  linkedin: {
    url: process.env.URL,
    paths: {
      redirect: '/auth/linkedin',
      callback: '/auth/linkedin/callback',
    },
    scope: ['r_emailaddress', 'r_basicprofile'],
    profileFields: ['first-name', 'last-name', 'email-address', 'formatted-name', 'location', 'industry', 'summary', 'specialties', 'positions', 'picture-url', 'public-profile-url'],
    onLogin: (user, profile, isNew, callback) => callback(),
  },
}

export default function configure(_options={}) {
  const options = _.merge(defaults, _options)
  if (!options.app) throw new Error('[fl-auth] init: Missing app from options')
  if (!options.User) options.User = require('./models/user')

  if (!options.serializing.serializeUser) {
    options.serializing.serializeUser = (user, callback) => {
      if (!user) return callback(new Error('[fl-auth] User missing'))
      callback(null, user.id)
    }
  }
  if (!options.serializing.deserializeUser) {
    options.serializing.deserializeUser = (id, callback) => options.User.cursor({id, $one: true}).toJSON(callback)
  }

  if (options.facebook) options.facebook = _.merge(oAuthDefaults.facebook, options.facebook)
  if (options.linkedin) options.linkedin = _.merge(oAuthDefaults.linkedin, options.linkedin)

  configureMiddleware(options)
  configureSerializing(options)
  configureStrategies(options)
  configureRoutes(options)
}

export {configure, sessionOrToken, createAuthMiddleware, createInternalMiddleware, AccessToken, RefreshToken, createToken}
<commit_msg>Default returnTo<commit_after>import _ from 'lodash'
import configureStrategies from './configure/strategies'
import configureRoutes from './configure/routes'
import configureMiddleware from './configure/middleware'
import configureSerializing from './configure/serialize'
import sessionOrToken from './middleware/sessionOrToken'
import createAuthMiddleware from './middleware/authorised'
import createInternalMiddleware from './middleware/internal'
import AccessToken from './models/AccessToken'
import RefreshToken from './models/RefreshToken'
import {createToken} from './lib'

const defaults = {
  middleware: {
    initialize: true,
    session: true,
  },
  paths: {
    login: '/login',
    logout: '/logout',
    loginStatus: '/login-status',
    register: '/register',
    resetRequest: '/reset-request',
    reset: '/reset',
    confirm: '/confirm-email',
    success: '/',
  },
  serializing: {

  },
  login: {
    userQuery: email => ({email}),
    isValidUsername: email => email && _.isString(email) && email.match(/.+@.+/),
    usernameField: 'email',
    passwordField: 'password',
    badRequestMessage: 'Missing credentials',
    resetTokenExpiresMs: 1000 * 60 * 60 * 24 * 7, // 7 days
    extraRegisterParams: [],
  },
  sendConfirmationEmail: (user, callback) => {
    console.log('[fl-auth] sendConfirmationEmail not configured. No email confirmation email will be sent. Token:', user.get('email'), user.get('emailConfirmationToken'))
    callback()
  },
  sendResetEmail: (user, callback) => {
    console.log('[fl-auth] sendResetEmail not configured. No password reset email will be sent. Reset token:', user.get('email'), user.get('resetToken'))
    callback()
  },

  setReturnTo: (req, res, next) => {
    req.session.returnTo = req.query.returnTo || req.headers.referer || '/'
    req.session.save(err => {
      if (err) console.log('[fl-auth] Error saving session', err)
      next()
    })
  }
}

const oAuthDefaults = {
  facebook: {
    url: process.env.URL,
    paths: {
      redirect: '/auth/facebook',
      callback: '/auth/facebook/callback',
      mobile: '/auth/facebook/mobile',
    },
    scope: ['email'],
    profileFields: [
      'id',
      'displayName',
      'email',
      'cover',
      'name',
      'age_range',
      'link',
      'locale',
      'picture',
      'timezone',
      'updated_time',
      'verified',
    ],
    onLogin: (user, profile, isNew, callback) => callback(),
  },
  linkedin: {
    url: process.env.URL,
    paths: {
      redirect: '/auth/linkedin',
      callback: '/auth/linkedin/callback',
    },
    scope: ['r_emailaddress', 'r_basicprofile'],
    profileFields: ['first-name', 'last-name', 'email-address', 'formatted-name', 'location', 'industry', 'summary', 'specialties', 'positions', 'picture-url', 'public-profile-url'],
    onLogin: (user, profile, isNew, callback) => callback(),
  },
}

export default function configure(_options={}) {
  const options = _.merge(defaults, _options)
  if (!options.app) throw new Error('[fl-auth] init: Missing app from options')
  if (!options.User) options.User = require('./models/user')

  if (!options.serializing.serializeUser) {
    options.serializing.serializeUser = (user, callback) => {
      if (!user) return callback(new Error('[fl-auth] User missing'))
      callback(null, user.id)
    }
  }
  if (!options.serializing.deserializeUser) {
    options.serializing.deserializeUser = (id, callback) => options.User.cursor({id, $one: true}).toJSON(callback)
  }

  if (options.facebook) options.facebook = _.merge(oAuthDefaults.facebook, options.facebook)
  if (options.linkedin) options.linkedin = _.merge(oAuthDefaults.linkedin, options.linkedin)
    console.log('paths', options.paths)
  configureMiddleware(options)
  configureSerializing(options)
  configureStrategies(options)
  configureRoutes(options)
}

export {configure, sessionOrToken, createAuthMiddleware, createInternalMiddleware, AccessToken, RefreshToken, createToken}
<|endoftext|>


<commit_before>/* global gapi:false */

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux'
import { Provider } from 'react-redux';
import moment from 'moment';
import App from './App';
import Bible from './bible';
import './index.css';
import { API_KEY, CLIENT_ID } from './config';

const FILE_NAME = 'data.json';

const INITIAL_STATE = {
  version: 1,
  chapterIndex: 0,
  checks: {},
  links: [
    {
      label: 'NWT English',
      url: 'http://m.wol.jw.org/en/wol/b/r1/lp-e/nwt/E/2013/{book}/{chapter}'
    },
    {
      label: 'Rbi8 Japanese',
      url: 'http://m.wol.jw.org/ja/wol/b/r7/lp-j/Rbi8/J/1985/{book}/{chapter}'
    }
  ]
};

const loadGoogleAPIClient = (callback) => {
  const signinButton = document.getElementById('signin');
  let auth2;

  const updateSigninStatus = (isSignedIn) => {
    if (isSignedIn) {
      callback();
    } else {
      signinButton.style.display = 'block';
    }
  }

  const initAuth = () => {
    gapi.client.setApiKey(API_KEY);
    auth2 = gapi.auth2.init({
      client_id: CLIENT_ID,
      scope: 'https://www.googleapis.com/auth/drive.appdata'
    }).then(() => {
      auth2 = gapi.auth2.getAuthInstance();
      auth2.isSignedIn.listen(updateSigninStatus);
      updateSigninStatus(auth2.isSignedIn.get());
    });
  }

  window.handleClientLoad = () => {
    gapi.load('client:auth2', initAuth);
  }

  const script = document.createElement('script');
  script.src = "https://apis.google.com/js/client.js?onload=handleClientLoad";
  document.getElementsByTagName('head')[0].appendChild(script);

  signinButton.addEventListener("click", (event) => {
    gapi.auth2.getAuthInstance().signIn();
  });
};

const updateFile = (fileId, fileMetadata, content, callback, errCallback) => {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  const multipartRequestBody = delimiter +
    'Content-Type: application/json\r\n\r\n' +
    JSON.stringify(fileMetadata) +
    delimiter +
    'Content-Type: application/json\r\n\r\n' +
    JSON.stringify(content) +
    close_delim;

  const arg = {
    path: '/upload/drive/v3/files/' + encodeURIComponent(fileId) + '?uploadType=multipart',
    method: 'PATCH',
    headers: {
      'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
    },
    body: multipartRequestBody
  };

  gapi.client.request(arg).then(
    (resp) => {
      if (callback) {
        callback(resp.result.id);
      }
    },
    errCallback);
};

const createFile = (name, callback, errCallback) => {
  gapi.client.drive.files.create({
    resource: {
      name,
      parents: ['appDataFolder'],
      mimeType: 'application/json'
    },
    useContentAsIndexableText: true
  }).then((resp) => {
    callback(resp.result.id);
  }, errCallback);
};

const loadFile = (fileId) => {
  return gapi.client.drive.files.get({
    fileId,
    alt: 'media'
  });
};

const loadDataFile = (name, callback, errCallback) => {
  gapi.client.drive.files.list({
    spaces: 'appDataFolder',
    q: `name='${name}'`,
    fields: 'files(id, name)'
  }).then((resp) => {
    const files = resp.result.files;
    if (files && files.length > 0) {
      callback(files[0].id);
    } else {
      createFile(name, (fileId) => {
        updateFile(fileId, {}, INITIAL_STATE, callback, errCallback);
      }, errCallback);
    }
  });
};

const runApplication = (fileId, errCallback) => {
  loadFile(fileId).then((resp) => {
    const initialState = JSON.parse(resp.body);

    const reducer = (state = initialState, action) => {
      let newState = state;
      switch(action.type) {
        case 'PREV': {
          const chapterIndex = Bible.getPreviousChapterIndex(state.chapterIndex);
          newState = Object.assign({}, state, { chapterIndex });
          break;
        }
        case 'NEXT': {
          const chapterIndex = Bible.getNextChapterIndex(state.chapterIndex);
          newState = Object.assign({}, state, { chapterIndex });
          break;
        }
        case 'CHECK': {
          let checks = Object.assign({}, state.checks);
          if (action.checked) {
              checks[state.chapterIndex] = moment();
          } else {
              delete checks[state.chapterIndex];
          }
          newState = Object.assign({}, state, { checks });
          break;
        }
        default:
          break;
      }

      updateFile(fileId, {}, newState, null, errCallback);

      console.log(JSON.stringify(newState, null, 2));
      return newState;
    };

    const store = createStore(reducer);

    ReactDOM.render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    );
  }, errCallback);
};

loadGoogleAPIClient(() => {
  const errorLog = (reason) => {
    console.log('Error: ' + reason.result.error.message);
  };
  gapi.client.load('drive', 'v3').then(() => {
    loadDataFile(FILE_NAME, (fileId) => {
      runApplication(fileId, errorLog);
    }, errorLog);
  });
});
<commit_msg>Reractoring`<commit_after>/* global gapi:false */

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux'
import { Provider } from 'react-redux';
import moment from 'moment';
import App from './App';
import Bible from './bible';
import './index.css';
import { API_KEY, CLIENT_ID } from './config';

const FILE_NAME = 'data.json';

const INITIAL_STATE = {
  version: 1,
  chapterIndex: 0,
  checks: {},
  links: [
    {
      label: 'NWT English',
      url: 'http://m.wol.jw.org/en/wol/b/r1/lp-e/nwt/E/2013/{book}/{chapter}'
    },
    {
      label: 'Rbi8 Japanese',
      url: 'http://m.wol.jw.org/ja/wol/b/r7/lp-j/Rbi8/J/1985/{book}/{chapter}'
    }
  ]
};

const loadGoogleAPIClient = (callback) => {
  const signinButton = document.getElementById('signin');
  let auth2;

  const updateSigninStatus = (isSignedIn) => {
    if (isSignedIn) {
      callback();
    } else {
      signinButton.style.display = 'block';
    }
  }

  const initAuth = () => {
    gapi.client.setApiKey(API_KEY);
    auth2 = gapi.auth2.init({
      client_id: CLIENT_ID,
      scope: 'https://www.googleapis.com/auth/drive.appdata'
    }).then(() => {
      auth2 = gapi.auth2.getAuthInstance();
      auth2.isSignedIn.listen(updateSigninStatus);
      updateSigninStatus(auth2.isSignedIn.get());
    });
  }

  window.handleClientLoad = () => {
    gapi.load('client:auth2', initAuth);
  }

  const script = document.createElement('script');
  script.src = "https://apis.google.com/js/client.js?onload=handleClientLoad";
  document.getElementsByTagName('head')[0].appendChild(script);

  signinButton.addEventListener("click", (event) => {
    gapi.auth2.getAuthInstance().signIn();
  });
};

const createFile = (fileMetadata, content, callback, errCallback) => {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  const multipartRequestBody = delimiter +
    'Content-Type: application/json\r\n\r\n' +
    JSON.stringify(fileMetadata) +
    delimiter +
    'Content-Type: application/json\r\n\r\n' +
    JSON.stringify(content) +
    close_delim;

  const arg = {
    path: '/upload/drive/v3/files',
    method: 'POST',
    params: {
      uploadType: 'multipart'
    },
    headers: {
      'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
    },
    body: multipartRequestBody
  };

  gapi.client.request(arg).then(
    (resp) => {
      if (callback) {
        callback(resp.result.id);
      }
    },
    errCallback);
};

const updateFile = (fileId, fileMetadata, content, callback, errCallback) => {
  const arg = {
    path: '/upload/drive/v3/files/' + fileId,
    method: 'PATCH',
    params: {
      uploadType: 'media'
    },
    body: JSON.stringify(content)
  };

  gapi.client.request(arg).then(
    (resp) => {
      if (callback) {
        callback(resp.result.id);
      }
    },
    errCallback);
};

const loadFile = (fileId, callback, errCallback) => {
  return gapi.client.drive.files.get({
    fileId,
    alt: 'media'
  }).then((resp) => {
    callback(JSON.parse(resp.body));
  }, errCallback);
};

const getDataFileId = (name, callback, errCallback) => {
  gapi.client.load('drive', 'v3').then(() => {
    gapi.client.drive.files.list({
      spaces: 'appDataFolder',
      q: `name='${name}'`,
      fields: 'files(id, name)'
    }).then((resp) => {
      const files = resp.result.files;
      if (files && files.length > 0) {
        callback(files[0].id);
      } else {
        createFile({
            name,
            parents: ['appDataFolder'],
            mimeType: 'application/json'
        }, INITIAL_STATE, callback, errCallback);
      }
    });
  }, errCallback);
};

const runApplication = (fileId, errCallback) => {
  loadFile(fileId, (initialState) => {
    const reducer = (state = initialState, action) => {
      let newState = state;
      switch(action.type) {
        case 'PREV': {
          const chapterIndex = Bible.getPreviousChapterIndex(state.chapterIndex);
          newState = Object.assign({}, state, { chapterIndex });
          break;
        }
        case 'NEXT': {
          const chapterIndex = Bible.getNextChapterIndex(state.chapterIndex);
          newState = Object.assign({}, state, { chapterIndex });
          break;
        }
        case 'CHECK': {
          let checks = Object.assign({}, state.checks);
          if (action.checked) {
              checks[state.chapterIndex] = moment();
          } else {
              delete checks[state.chapterIndex];
          }
          newState = Object.assign({}, state, { checks });
          break;
        }
        default:
          break;
      }

      updateFile(fileId, {}, newState, null, errCallback);

      console.log(JSON.stringify(newState, null, 2));
      return newState;
    };

    const store = createStore(reducer);

    ReactDOM.render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    );
  }, errCallback);
};

loadGoogleAPIClient(() => {
  const errorLog = (reason) => {
    console.log('Error: ' + reason.result.error.message);
  };
  getDataFileId(FILE_NAME, (fileId) => {
    runApplication(fileId, errorLog);
  }, errorLog);
});
<|endoftext|>


<commit_before>import React from 'react';
import { render } from 'react-dom';
import Firebase from 'firebase';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import { Map, OrderedMap } from 'immutable';
import _ from 'lodash';

const firebaseRef = new Firebase('https://blazing-fire-8383.firebaseio.com/');

const SHOW = 'SHOW';
const ADD = 'ADD';
const UPDATE = 'UPDATE';
const REMOVE = 'REMOVE';

let idAvailable = 0;
function getUniqueId() {
  return idAvailable++;
}

const reducer = (state = {}, action) => {
  switch (action.type) {
    case SHOW:
      let obj = Object.assign(state, action.payload.values);
      idAvailable = Object.keys(obj).length;
      return obj;

    case ADD:
      return Object.assign({}, state, {
        [getUniqueId()]: action.payload.todo
      });

    case UPDATE:
      return Object.assign({}, state, {
        [action.payload.id]: action.payload.todo
      });

    case REMOVE:
      return _.omit(state, [action.payload.id]);

    default:
      return state;
  }
  return state;
}

const logger = createLogger();
const store = createStore(reducer, applyMiddleware(thunk, logger));

const localShowTodo = (values) => {
  return { type: SHOW, payload: { values } };
}
const localAddTodo = (todo) => {
  return { type: ADD, payload: { todo } };
}
const localUpdateTodo = (id, todo) => {
  return { type: UPDATE, payload: { id, todo } };
}
const localRemoveTodo = (id) => {
  return { type: REMOVE, payload: { id } };
}

const showTodo = () => {
  return (dispatch) => {
    firebaseRef.on('value', (allValues) => {
      if(allValues) {
        dispatch(localShowTodo(allValues.val()));
      }
    });
  };
}

const addTodo = (todo) => {
  return (dispatch) => {
    dispatch(localAddTodo(todo));
    firebaseRef.set(store.getState());
  };
}

const updateTodo = (id, todo) => {
  return (dispatch) => {
    dispatch(localUpdateTodo(id, todo));
    let firebaseRefUpdate = firebaseRef.child(id);
    firebaseRefUpdate.update({[id]: todo});
  };
}

const removeTodo = (id) => {
  return (dispatch) => {
    dispatch(localRemoveTodo(id));
    let firebaseRefRemove = firebaseRef.child(id);
    firebaseRefRemove.remove();
  };
}

/*console.log(Map(store.getState()).equals(Map({})));
store.dispatch(showTodo());
setTimeout(store.dispatch(addTodo('title')), 200);
setTimeout(store.dispatch(addTodo('title2')), 200);
setTimeout(store.dispatch(addTodo('title3')), 200);
console.log(Map(store.getState()).equals(Map({ 0: 'title', 1: 'title2', 2: 'title3'})));
store.dispatch(updateTodo(3, 'title1'));
console.log(Map(store.getState()).equals(Map({ 0: 'title1', 1: 'title2', 2: 'title3'})));
store.dispatch(removeTodo(0));
store.dispatch(removeTodo(1));
store.dispatch(removeTodo(2));
console.log(Map(store.getState()).equals(Map({})));*/

class Teste extends React.Component {
  constructor(props) {
    super(props);
    this.state = { todos: {} };
  }

  componentDidMount() {
    store.dispatch(showTodo());
    console.log(store.getState());
    this.setState({todos: store.getState()});
  }

  render() {
    return(

lista

          {Object.keys(this.state.todos).map((t) => {
            return(

{this.state.todos[t]}

            );
          })}

    );
  }
}

render(<Teste />, document.getElementById('root'));
<commit_msg>some errors of sintax fixeds<commit_after>import React from 'react';
import { render } from 'react-dom';
import Firebase from 'firebase';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import { Map, OrderedMap } from 'immutable';
import _ from 'lodash';

const firebaseRef = new Firebase('https://blazing-fire-8383.firebaseio.com/');

const SHOW = 'SHOW';
const ADD = 'ADD';
const UPDATE = 'UPDATE';
const REMOVE = 'REMOVE';

let idAvailable = 0;
function getUniqueId() {
  return idAvailable++;
}

const reducer = (state = {}, action) => {
  switch (action.type) {
    case SHOW:
      let obj = Object.assign({}, state, action.payload.values);
      idAvailable = Object.keys(obj).length;
      return obj;

    case ADD:
      return Object.assign({}, state, {
        [getUniqueId()]: action.payload.todo
      });

    case UPDATE:
      return Object.assign({}, state, {
        [action.payload.id]: action.payload.todo
      });

    case REMOVE:
      return _.omit(state, [action.payload.id]);

    default:
      return state;
  }
}

const logger = createLogger();
const store = createStore(reducer, applyMiddleware(thunk, logger));

const localShowTodo = (values) => {
  return { type: SHOW, payload: { values } };
}
const localAddTodo = (todo) => {
  return { type: ADD, payload: { todo } };
}
const localUpdateTodo = (id, todo) => {
  return { type: UPDATE, payload: { id, todo } };
}
const localRemoveTodo = (id) => {
  return { type: REMOVE, payload: { id } };
}

const showTodo = () => {
  return (dispatch) => {
    firebaseRef.on('value', (allValues) => {
      if(allValues) {
        dispatch(localShowTodo(allValues.val()));
      }
    });
  };
}

const addTodo = (todo) => {
  return (dispatch) => {
    dispatch(localAddTodo(todo));
    firebaseRef.set(store.getState());
  };
}

const updateTodo = (id, todo) => {
  return (dispatch) => {
    dispatch(localUpdateTodo(id, todo));
    let firebaseRefUpdate = firebaseRef.child(id);
    firebaseRefUpdate.update({[id]: todo});
  };
}

const removeTodo = (id) => {
  return (dispatch) => {
    dispatch(localRemoveTodo(id));
    let firebaseRefRemove = firebaseRef.child(id);
    firebaseRefRemove.remove();
  };
}

/*console.log(Map(store.getState()).equals(Map({})));
store.dispatch(showTodo());
setTimeout(store.dispatch(addTodo('title')), 200);
setTimeout(store.dispatch(addTodo('title2')), 200);
setTimeout(store.dispatch(addTodo('title3')), 200);
console.log(Map(store.getState()).equals(Map({ 0: 'title', 1: 'title2', 2: 'title3'})));
store.dispatch(updateTodo(3, 'title1'));
console.log(Map(store.getState()).equals(Map({ 0: 'title1', 1: 'title2', 2: 'title3'})));
store.dispatch(removeTodo(0));
store.dispatch(removeTodo(1));
store.dispatch(removeTodo(2));
console.log(Map(store.getState()).equals(Map({})));*/

class Teste extends React.Component {
  constructor(props) {
    super(props);
    this.state = { todos: {} };
  }

  componentDidMount() {
    store.dispatch(showTodo());
    let lista = store.getState();
    console.log(lista);
    this.setState({todos: lista});
  }

  render() {
    return(

lista

          {Object.keys(this.state.todos).map((t) => {
            return(

{this.state.todos[t]}

            );
          })}

    );
  }
}

render(<Teste />, document.getElementById('root'));
<|endoftext|>


<commit_before>/**
 * Created by longhao on 2017/5/4.
 */

var winston = require('winston');
var fs = require('fs');
var path = require('path');
var nconf = require('nconf');
var async = require('async');
var _ = require('lodash');

var express = require('express');
var app = express();
var server;

var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var useragent = require('express-useragent');

var connectRedis = require("connect-redis")(session);
var storeRedis = new connectRedis({
    host: nconf.get('redis:host'),
    port: nconf.get('redis:port'),
    ttl: nconf.get('redis:ttl'),
    db: 0
});

var utils = require('./server/utils');
var logger = require('./server/logger');
var userAgent = require('./server/socket.io/userAgent');

// init config file
nconf.argv().env().file({
    file: path.join(__dirname, 'config.json')
});

if (nconf.get('app:ssl')) {
    server = require('https').createServer({
        key: fs.readFileSync(nconf.get('app:ssl').key),
        cert: fs.readFileSync(nconf.get('app:ssl').cert),
    }, app);
} else {
    server = require('http').createServer(app);
}

module.exports.server = server;

server.on('error', function (err) {
    winston.error(err);
    if (err.code === 'EADDRINUSE') {
        winston.error('uuChat address in use, exiting...');
        process.exit(1);
    } else if (err.code === 'EADDRNOTAVAIL') {
        winston.error('uuChat ip address is not avail, exiting...');
        process.exit(1);
    } else {
        throw err;
    }
});

server.sessionStore = function() {
    var redisHost = nconf.get('redis:host');
    if (_.isEmpty(redisHost)) {
        var SequelizeStore = require('connect-session-sequelize')(session.Store);
        var sequelize = require('./server/models/index').sequelize;
        winston.info(sequelize.Message);
        return new SequelizeStore({
            db: sequelize
        });
    } else {
        return storeRedis;
    }
};

module.exports.listen = function (callback) {
    callback = callback || function () { };
    async.waterfall([
        function (next) {
            setupExpress(app, next);
            next();
        },
        function (next) {
            checkRedisStarted(next);

        },
        function () {
            listen();
        }
    ], function (err) {
        if (err) {
            switch (err.message) {
                case 'redis-need-start':
                    winston.error('you need to start redis, eg: redis-server /usr/local/redis/redis.conf &');
                    break;
                case 'redis-version-too-lower':
                    winston.error('you redis version is too lower , please update redis version above 3.0.0');
                    break;
                case 'logger-folder-need-create':
                    winston.error('logger folder need create in root directory.');
                default:
                    winston.error(err);
                    break;
            }
            process.exit();
        }
        callback();
    });
};

//check redis has started;

function checkRedisStarted(callback){
    var redisHost = nconf.get('redis:host');
    if (!_.isEmpty(redisHost)) {
        utils.lsof(nconf.get('redis:port'), function (data) {
            if (data.length > 0) {
                winston.info('');
                winston.info("[redis] has started");
            } else {
                callback(new Error('redis-need-start'));
            }
        });

        //version print
        if (global.env !== 'development') {
            var _redis = require("../node_modules/connect-redis/node_modules/redis"),
                client = _redis.createClient();
            client.info(function () {
                var info = client.server_info;
                var versions = info.versions;
                if (versions[0] < 3) {
                    callback(new Error('redis-version-too-lower'));
                } else {
                    winston.info("[redis] version = %s", info.redis_version);
                    winston.info("[redis] executable = %s", info.executable);
                    winston.info("[redis] config file = %s", info.config_file);
                    winston.info('');
                }
            });
        }
    }

    callback();
}

function setupExpress(app, callback) {
    var middleware = require('./server/middleware');

    app.set('showStackError', true);
    app.disable('x-powered-by'); // http://expressjs.com/zh-cn/advanced/best-practice-security.html
    app.set('json spaces', process.env.NODE_ENV === 'development' ? 4 : 0);

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser(nconf.get('socket.io:secretKey')));

    app.use(session({
        store: server.sessionStore(),
        secret: nconf.get('socket.io:secretKey'),
        key: nconf.get('socket.io:sessionKey'),
        cookie: setupCookie(),
        resave: true,
        saveUninitialized: true
    }));
    app.use(useragent.express());

    if (global.env === 'development') {
        var webpack = require('webpack');
        var webpackMiddleware = require('webpack-dev-middleware');
        var webpackHotMiddleware = require('webpack-hot-middleware');
        var config = require('../tools/webpack.config.dev.js');
        var compiler = webpack(config);
        var middlewareDev = webpackMiddleware(compiler, {
            publicPath: config.output.publicPath,
            contentBase: 'src',
            stats: {
                colors: true,
                hash: false,
                timings: true,
                chunks: false,
                chunkModules: false,
                modules: false
            }
        });

        app.use(middlewareDev);
        app.use(webpackHotMiddleware(compiler, {
            log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000
        }));

        app.use(express.static(path.join(__dirname, '../build/static')));

        app.get('/', function response(req, res) {
            res.write(middlewareDev.fileSystem.readFileSync(path.join(__dirname, '../build/app.html')));
            res.end();
        });
        app.get('/demo', function response(req, res) {
            setupSession(req, res);
            res.write(middlewareDev.fileSystem.readFileSync(path.join(__dirname, '../build/customer.html')));
            res.end();
        });
        app.get('/console', function response(req, res) {
            res.write(middlewareDev.fileSystem.readFileSync(path.join(__dirname, '../build/console.html')));
            res.end();
        });
        app.get('/console/index', function response(req, res) {
            if(!req.session.csid) {
                res.redirect('/console');
            }
            res.write(middlewareDev.fileSystem.readFileSync(path.join(__dirname, '../build/console.html')));
            res.end();
        });
        app.get('/chat', function response(req, res) {
            res.write(middlewareDev.fileSystem.readFileSync(path.join(__dirname, '../build/app.html')));
            res.end();
        });
        app.get('/register', function response(req, res) {
            res.write(middlewareDev.fileSystem.readFileSync(path.join(__dirname, '../build/app.html')));
            res.end();
        });

    } else {
        app.set('views', path.join(__dirname, '../build/views'));
        app.use(express.static(path.join(__dirname, '../build/')));

        app.get('/', function response(req, res) {
            res.render(path.join(__dirname, '../build/app.html'));
        });
        app.get('/demo', function response(req, res) {
            setupSession(req, res);
            res.render(path.join(__dirname, '../build/customer.html'));
        });
        app.get('/chat', function response(req, res) {
            if(!req.session.csid) {
                res.redirect('/');
            }
            res.render(path.join(__dirname, '../build/app.html'));
        });
        app.get('/console', function response(req, res) {
            res.render(path.join(__dirname, '../build/console.html'));
        });
        app.get('/console/index', function response(req, res) {
            if(!req.session.csid) {
                res.redirect('/console');
            }
            res.render(path.join(__dirname, '../build/console.html'));
        });
        app.get('/register', function response(req, res) {
            res.render(path.join(__dirname, '../build/app.html'));
        });
    }

    app.set('view engine', 'html');
    app.engine('html', require('ejs').renderFile);

    app.enable('view cache');

    if (global.env !== 'development') {
        app.enable('cache');
        app.enable('minification');
    }

    setupFavicon(app);

    app.use('/static/images', express.static(path.join(__dirname, './client/static/images')));
    app.use('/content/upload', express.static(path.join(__dirname, '../content/upload')));
    app.use('/content/avatar', express.static(path.join(__dirname, '../content/avatar')));

    var routes = require('./server/routes');
    routes(app, middleware);

    //app.use(middleware.checkAccountPermissions);

    setupAutoLocale(app, callback);

    // http://expressjs.com/zh-cn/starter/faq.html
    // catch 404 and forward to error handler
    app.use(function(req, res, next) {
        logger.error("~~~~~~ has 404 error, please see browser console log!");
        res.status(404).send('can not find page!');
    });
    app.use(function(err, req, res, next) {
        logger.error(err.stack);
        res.status(503).send('system has problem.');
    });

    winston.info('setup express success!');
}

function setupFavicon(app) {
    var faviconPath = 'favicon.ico';
    faviconPath = path.join(nconf.get('app:base_dir'), 'public', faviconPath.replace(/assets\/uploads/, 'uploads'));
    if (utils.fileExistsSync(faviconPath)) {
        app.use(nconf.get('app:relative_path'), favicon(faviconPath));
    }
}

function setupCookie() {
    var oneMonth = 30 * 86400000;

    var cookie = {
        expires: new Date(Date.now() + oneMonth)
    };

    var relativePath = nconf.get('app:relative_path');
    if (relativePath !== '') {
        cookie.path = relativePath;
    }

    return cookie;
}

function setupSession(req, res) {
    var cid = '';
    var ua = req.useragent;
    if (req.session.cid) {
        cid = req.session.cid;
    } else {
        cid = require('uuid/v4')();  //gen uuid
        req.session.cid = cid;
        ua.needSnycDB = true;
    }

    //res.cookie('uu.c', cid, {expires: new Date(Date.now() + 900000), httpOnly: true, path: '/'});

    var headers = req ? req.headers : {};
    var host = headers.host;
    var referer = headers.referer || '';

    if (!host) {
        var url = require('url');
        host = url.parse(referer).host || '';
    }
    var ip = headers['x-forwarded-for'] || req.connection.remoteAddress;

    ua.cid = cid;
    ua.ip = ip;
    ua.host = host;
    ua.url = referer;
    userAgent.create(ua);
    winston.info('Customer session had set');
}

function setupAutoLocale(app, callback) {

}

function listen() {
    var configAddress = nconf.get('app:address');
    var address = ((configAddress === '0.0.0.0' || !configAddress) ? '0.0.0.0' : configAddress);

    //server.listen.apply(server, args);
    server.listen(nconf.get('app:port'), address, function () {
        process.setMaxListeners(0);
        process.env.TZ = 'Hongkong';
    });
    server.on('listening', function onListening() {
        var addr = server.address();
        var bind = typeof addr === 'string' ?
            'pipe ' + addr :
            'port ' + addr.port;
        winston.info('Listening on ' + bind);
    });
}
<commit_msg>filter css, js , images withour auth, and refactor code<commit_after>/**
 * Created by longhao on 2017/5/4.
 */

var winston = require('winston');
var fs = require('fs');
var path = require('path');
var nconf = require('nconf');
var async = require('async');
var _ = require('lodash');

var express = require('express');
var app = express();
var server;

var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var useragent = require('express-useragent');

var connectRedis = require("connect-redis")(session);
var storeRedis = new connectRedis({
    host: nconf.get('redis:host'),
    port: nconf.get('redis:port'),
    ttl: nconf.get('redis:ttl'),
    db: 0
});

var utils = require('./server/utils');
var logger = require('./server/logger');
var userAgent = require('./server/socket.io/userAgent');

// init config file
nconf.argv().env().file({
    file: path.join(__dirname, 'config.json')
});

if (nconf.get('app:ssl')) {
    server = require('https').createServer({
        key: fs.readFileSync(nconf.get('app:ssl').key),
        cert: fs.readFileSync(nconf.get('app:ssl').cert),
    }, app);
} else {
    server = require('http').createServer(app);
}

module.exports.server = server;

server.on('error', function (err) {
    winston.error(err);
    if (err.code === 'EADDRINUSE') {
        winston.error('uuChat address in use, exiting...');
        process.exit(1);
    } else if (err.code === 'EADDRNOTAVAIL') {
        winston.error('uuChat ip address is not avail, exiting...');
        process.exit(1);
    } else {
        throw err;
    }
});

server.sessionStore = function() {
    var redisHost = nconf.get('redis:host');
    if (_.isEmpty(redisHost)) {
        var SequelizeStore = require('connect-session-sequelize')(session.Store);
        var sequelize = require('./server/models/index').sequelize;
        winston.info(sequelize.Message);
        return new SequelizeStore({
            db: sequelize
        });
    } else {
        return storeRedis;
    }
};

module.exports.listen = function (callback) {
    callback = callback || function () { };
    async.waterfall([
        function (next) {
            setupExpress(app, next);
            next();
        },
        function (next) {
            checkRedisStarted(next);

        },
        function () {
            listen();
        }
    ], function (err) {
        if (err) {
            switch (err.message) {
                case 'redis-need-start':
                    winston.error('you need to start redis, eg: redis-server /usr/local/redis/redis.conf &');
                    break;
                case 'redis-version-too-lower':
                    winston.error('you redis version is too lower , please update redis version above 3.0.0');
                    break;
                case 'logger-folder-need-create':
                    winston.error('logger folder need create in root directory.');
                default:
                    winston.error(err);
                    break;
            }
            process.exit();
        }
        callback();
    });
};

function baseHtmlRoute(app, middlewareDev) {
    app.use(express.static(path.join(__dirname, '../build')));
    //need filter css, js, images files
    app.use(fileFilters);
    app.use(session({
        store: server.sessionStore(),
        secret: nconf.get('socket.io:secretKey'),
        key: nconf.get('socket.io:sessionKey'),
        cookie: setupCookie(),
        resave: false,
        saveUninitialized: true
    }));

    app.get('/', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/demo', function response(req, res) {
        setupSession(req, res);
        var html = path.join(__dirname, '../build/customer.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/console', function response(req, res) {
        var html = path.join(__dirname, '../build/console.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/console/index', function response(req, res) {
        if (!req.session.csid) {
            res.redirect('/console');
        }
        var html = path.join(__dirname, '../build/console.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/chat', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/register', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
}

function htmlRender(middlewareDev, res, html) {
    if (middlewareDev) {
        res.write(middlewareDev.fileSystem.readFileSync(html));
        res.end();
    } else {
        res.render(html);
    }
}

function setupExpress(app, callback) {
    var middleware = require('./server/middleware');

    app.set('showStackError', true);
    app.disable('x-powered-by'); // http://expressjs.com/zh-cn/advanced/best-practice-security.html
    app.set('json spaces', process.env.NODE_ENV === 'development' ? 4 : 0);

    app.use('/static/images', express.static(path.join(__dirname, './client/static/images')));
    app.use('/content/upload', express.static(path.join(__dirname, '../content/upload')));
    app.use('/content/avatar', express.static(path.join(__dirname, '../content/avatar')));

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser(nconf.get('socket.io:secretKey')));

    app.use(useragent.express());

    if (global.env === 'development') {
        var webpack = require('webpack');
        var webpackMiddleware = require('webpack-dev-middleware');
        var webpackHotMiddleware = require('webpack-hot-middleware');
        var config = require('../tools/webpack.config.dev.js');
        var compiler = webpack(config);
        var middlewareDev = webpackMiddleware(compiler, {
            publicPath: config.output.publicPath,
            contentBase: 'src',
            stats: {
                colors: true,
                hash: false,
                timings: true,
                chunks: false,
                chunkModules: false,
                modules: false
            }
        });

        app.use(middlewareDev);
        app.use(webpackHotMiddleware(compiler, {
            log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000
        }));

        baseHtmlRoute(app, middlewareDev);
    } else {
        baseHtmlRoute(app, null);
    }

    app.set('view engine', 'html');
    app.engine('html', require('ejs').renderFile);

    app.enable('view cache');

    if (global.env !== 'development') {
        app.enable('cache');
        app.enable('minification');
    }

    setupFavicon(app);

    var routes = require('./server/routes');
    routes(app, middleware);

    //app.use(middleware.checkAccountPermissions);

    setupAutoLocale(app, callback);

    // http://expressjs.com/zh-cn/starter/faq.html
    // catch 404 and forward to error handler
    app.use(function(req, res, next) {
        logger.error("~~~~~~ has 404 error, please see browser console log!");
        res.status(404).send('can not find page!');
    });
    app.use(function(err, req, res, next) {
        logger.error(err.stack);
        res.status(503).send('system has problem.');
    });

    winston.info('setup express success!');
}

function setupFavicon(app) {
    var faviconPath = path.join(nconf.get('app:base_dir'), 'static/images/uuchat.ico');
    if (utils.fileExistsSync(faviconPath)) {
        app.use(favicon(faviconPath));
    }
}

function setupCookie() {
    var oneMonth = 30 * 86400000;

    var cookie = {
        expires: new Date(Date.now() + oneMonth)
    };

    var relativePath = nconf.get('app:relative_path');
    if (relativePath !== '') {
        cookie.path = relativePath;
    }

    return cookie;
}

function setupSession(req, res) {
    var cid = '';
    var ua = req.useragent;
    if (req.session.cid) {
        cid = req.session.cid;
    } else {
        cid = require('uuid/v4')();  //gen uuid
        req.session.cid = cid;
        ua.needSnycDB = true;
    }

    //res.cookie('uu.c', cid, {expires: new Date(Date.now() + 900000), httpOnly: true, path: '/'});

    var headers = req ? req.headers : {};
    var host = headers.host;
    var referer = headers.referer || '';

    if (!host) {
        var url = require('url');
        host = url.parse(referer).host || '';
    }
    var ip = headers['x-forwarded-for'] || req.connection.remoteAddress;

    ua.cid = cid;
    ua.ip = ip;
    ua.host = host;
    ua.url = req.protocol + '://' + req.get('host') + req.originalUrl;
    userAgent.create(ua);
    winston.info('Customer session had set');
}

function fileFilters(req, res, next) {
    //var url = req.protocol + '://' + req.get('host') + req.originalUrl;
    var originalUrl = req.originalUrl;
    winston.info(originalUrl);
    var fileFilters = ['.css', '.js', '.png', '.jpg', '.jpeg', '.ico'];
    var flag = false;
    for (suffix in fileFilters) {
        if (_.endsWith(originalUrl, fileFilters[suffix])) {
            flag = true;
            break;
        }
    }
    if (flag) {
        // return direct
        res.render(path.join(__dirname, originalUrl));
    } else {
        next();
    }
}

//check redis has started;

function checkRedisStarted(callback){
    var redisHost = nconf.get('redis:host');
    if (!_.isEmpty(redisHost)) {
        utils.lsof(nconf.get('redis:port'), function (data) {
            if (data.length > 0) {
                winston.info('');
                winston.info("[redis] has started");
            } else {
                callback(new Error('redis-need-start'));
            }
        });

        //version print
        if (global.env !== 'development') {
            var _redis = require("../node_modules/connect-redis/node_modules/redis"),
                client = _redis.createClient();
            client.info(function () {
                var info = client.server_info;
                var versions = info.versions;
                if (versions[0] < 3) {
                    callback(new Error('redis-version-too-lower'));
                } else {
                    winston.info("[redis] version = %s", info.redis_version);
                    winston.info("[redis] executable = %s", info.executable);
                    winston.info("[redis] config file = %s", info.config_file);
                    winston.info('');
                }
            });
        }
    }

    callback();
}

function setupAutoLocale(app, callback) {

}

function listen() {
    var configAddress = nconf.get('app:address');
    var address = ((configAddress === '0.0.0.0' || !configAddress) ? '0.0.0.0' : configAddress);

    //server.listen.apply(server, args);
    server.listen(nconf.get('app:port'), address, function () {
        process.setMaxListeners(0);
        process.env.TZ = 'Hongkong';
    });
    server.on('listening', function onListening() {
        var addr = server.address();
        var bind = typeof addr === 'string' ?
            'pipe ' + addr :
            'port ' + addr.port;
        winston.info('Listening on ' + bind);
    });
}
<|endoftext|>


<commit_before>define([
  'extensions/views/single_stat',
  'extensions/collections/collection'
], function (SingleStatView, Collection) {
  describe("SingleStatView", function () {

    var collectionOptions = {
      checkName: "anything",
      "data-group": "anything",
      "data-type": "monitoring"
    };

    describe("initialize", function () {
      describe("collection events", function () {
        var view, collection;
        beforeEach(function () {
          spyOn(SingleStatView.prototype, 'render');
          collection = new Collection();
          view = new SingleStatView({
            collection: collection
          });
        });

        it("re-renders on reset", function () {
          collection.trigger('reset');
          expect(view.render).toHaveBeenCalled();
        });

        it("re-renders on sync", function () {
          collection.trigger('sync');
          expect(view.render).toHaveBeenCalled();
        });

        it("re-renders on error", function () {
          collection.trigger('error');
          expect(view.render).toHaveBeenCalled();
        });
      });
    });

    describe("extracting the stat from the collection", function () {

      var stubCollection = {
        on: function () {},
        getValue: function () { return 5; },
        getCurrentSelection: function () {
          return {
            selectedModel: null,
            selectedModelIndex: null
          };
        }
      };

      it("Should try to get a value from a collection", function () {
        spyOn(stubCollection, 'getValue').andCallThrough();
        view = new SingleStatView({
          collection: stubCollection,
          getValue: function () { return this.collection.getValue(); }
        });
        jasmine.renderView(view, function () {
          expect(stubCollection.getValue).toHaveBeenCalled();
          expect(view.$el.html()).toEqual("5");
        });
      });
    });

    it("should display calculated value in a strong tag by default", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar");
      });
    });

    it("should display calculated value in a custom wrapping tag when configured", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        valueTag: 'em',
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar");
      });
    });

    it("should display calculated value without a wrapping tag when configured", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        valueTag: '',
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar");
      });
    });

    it("should display calculated value and label", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        },
        getLabel: function () {
          return 'label';
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar label");
      });
    });

    it("should not display different values when the selection changes by default", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        },
        getLabel: function () {
          return 'label';
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar label");
        collection.selectItem(0);
        expect(view.$el.html()).toEqual("bar label");
      });
    });

    it("should display different values when the selection changes when configured", function () {
      var collection = new Collection([{
        foo: 'bar',
        a: 'b'
      }], collectionOptions);

      var view = new SingleStatView({
        changeOnSelected: true,
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        },
        getLabel: function () {
          return 'label';
        },
        getValueSelected: function (selection) {
          return selection.selectedModel.get('a');
        },
        getLabelSelected: function (selection) {
          return 'selected';
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar label");
        collection.selectItem(0);
        expect(view.$el.html()).toEqual("b selected");
        collection.selectItem(null);
        expect(view.$el.html()).toEqual("bar label");
      });
    });

    it("should display (no data) when data is missing", function () {
      var collection = new Collection([{
        "foo": null
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("(no data)");
      });
    });
  });
});
<commit_msg>Added tests for events on single_stat.<commit_after>define([
  'extensions/views/single_stat',
  'extensions/collections/collection'
], function (SingleStatView, Collection) {
  describe("SingleStatView", function () {

    var collectionOptions = {
      checkName: "anything",
      "data-group": "anything",
      "data-type": "monitoring"
    };

    describe("initialize", function () {

      describe("collection events", function () {

        var view, collection;

        beforeEach(function () {
          spyOn(SingleStatView.prototype, 'render');
          collection = new Collection();
          view = new SingleStatView({
            collection: collection
          });
        });

        it("re-renders on reset", function () {
          collection.trigger('reset');
          expect(view.render).toHaveBeenCalled();
        });

        it("re-renders on sync", function () {
          collection.trigger('sync');
          expect(view.render).toHaveBeenCalled();
        });

        it("re-renders on error", function () {
          collection.trigger('error');
          expect(view.render).toHaveBeenCalled();
        });

        describe("changeOnSelected", function () {

          it("should not listen to change:selected by default", function () {
            collection.trigger('change:selected');
            expect(view.render).not.toHaveBeenCalled();
          });

          it("should listen to change:selected when changeOnSelected is true", function () {
            view.changeOnSelected = true;
            view.initialize();

            collection.trigger('change:selected');
            expect(view.render).toHaveBeenCalled();
          });

        });
      });
    });

    describe("onChangeSelected", function () {

      var view, collection;

      beforeEach(function () {
        spyOn(SingleStatView.prototype, 'render');
        collection = new Collection();
        view = new SingleStatView({
          collection: collection
        });
      });

      it("sets selectedModel if available", function () {
        var model = jasmine.createSpy('myfakeModel');

        expect(view.selectedModel).toBeUndefined();

        view.onChangeSelected(null, null, model, null);

        expect(view.selectedModel).toEqual(model);
      });

      it("sets selectedModel to first item if passed array", function () {
        var model = jasmine.createSpy('myfakeModel');
        view.onChangeSelected(null, null, [model], null);

        expect(view.selectedModel).toEqual(model);
      });

      it("calls render", function () {
        view.onChangeSelected();
        expect(view.render).toHaveBeenCalled();
      });
    });

    describe("extracting the stat from the collection", function () {

      var stubCollection = {
        on: function () {},
        getValue: function () { return 5; },
        getCurrentSelection: function () {
          return {
            selectedModel: null,
            selectedModelIndex: null
          };
        }
      };

      it("Should try to get a value from a collection", function () {
        spyOn(stubCollection, 'getValue').andCallThrough();
        view = new SingleStatView({
          collection: stubCollection,
          getValue: function () { return this.collection.getValue(); }
        });
        jasmine.renderView(view, function () {
          expect(stubCollection.getValue).toHaveBeenCalled();
          expect(view.$el.html()).toEqual("5");
        });
      });
    });

    it("should display calculated value in a strong tag by default", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar");
      });
    });

    it("should display calculated value in a custom wrapping tag when configured", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        valueTag: 'em',
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar");
      });
    });

    it("should display calculated value without a wrapping tag when configured", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        valueTag: '',
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar");
      });
    });

    it("should display calculated value and label", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        },
        getLabel: function () {
          return 'label';
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar label");
      });
    });

    it("should not display different values when the selection changes by default", function () {
      var collection = new Collection([{
        "foo": 'bar'
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        },
        getLabel: function () {
          return 'label';
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar label");
        collection.selectItem(0);
        expect(view.$el.html()).toEqual("bar label");
      });
    });

    it("should display different values when the selection changes when configured", function () {
      var collection = new Collection([{
        foo: 'bar',
        a: 'b'
      }], collectionOptions);

      var view = new SingleStatView({
        changeOnSelected: true,
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        },
        getLabel: function () {
          return 'label';
        },
        getValueSelected: function (selection) {
          return selection.selectedModel.get('a');
        },
        getLabelSelected: function (selection) {
          return 'selected';
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("bar label");
        collection.selectItem(0);
        expect(view.$el.html()).toEqual("b selected");
        collection.selectItem(null);
        expect(view.$el.html()).toEqual("bar label");
      });
    });

    it("should display (no data) when data is missing", function () {
      var collection = new Collection([{
        "foo": null
      }], collectionOptions);

      var view = new SingleStatView({
        collection: collection,
        getValue: function () {
          return this.collection.first().get('foo');
        }
      });

      jasmine.renderView(view, function () {
        expect(view.$el.html()).toEqual("(no data)");
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
*
*/
define(function(require, exports, module) {

    var zhCN = require('datatableZh');
    var editorCN = require('i18n');
    exports.index = function ($, tableId, customers, materials) {
        var editor = new $.fn.dataTable.Editor({
            ajax: {
                create: {
                    type: 'POST',
                    url: '/admin/customer-price',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                edit: {
                    type: 'PUT',
                    url: '/admin/customer-price/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                remove: {
                    type: 'DELETE',
                    url: '/admin/customer-price/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                }
            },
            i18n: editorCN,
            table: "#" + tableId,
            idSrc: 'id',
            fields: [
                { 'label':  '经销商', 'name': 'fcust_id', 'type': 'select', 'options': customers},
                { 'label':  '产品', 'name': 'fmaterial_id', 'type': 'select', 'options': materials},
                { 'label':  '销售起数量', 'name': 'fmin_qty', def: 0},
                { 'label':  '销售止数量', 'name': 'fmax_qty', def: 1000000},
                { 'label':  '单价/箱', 'name': 'fprice_box', },
                { 'label':  '单价/瓶', 'name': 'fprice_bottle', },
            ]
        });

        editor.on('open', function (e, json, data) {
            $("#DTE_Field_fcust_id").selectpicker({liveSearch: true});
            $("#DTE_Field_fmaterial_id").selectpicker({liveSearch: true});
        })
        var table = $("#" + tableId).DataTable({
            dom: "lBfrtip",
            language: zhCN,
            processing: true,
            serverSide: true,
            select: true,
            paging: true,
            rowId: "id",
            ajax: '/admin/customer-price/pagination',
            columns: [
                {  'data': 'id' },
                {  'data': 'fcust_id', render: function (data, type, full) {
                    return full.customer.fname;
                } },
                {  'data': 'fmaterial_id', render: function (data, type, full) {
                    return full.material.fname
                } },
                {  'data': 'fspecification' },
                {  'data': 'fsale_unit' },
                {  'data': 'fmin_qty' },
                {  'data': 'fmax_qty' },
                {  'data': 'fprice_box' },
                {  'data': 'fprice_bottle' },
                {  'data': 'fdocument_status', render: function (data, type, full) {
                    return document_status(data);
                } },
                {  'data': 'fis_valid', render: function (data, type, full) {
                    return data == 1 ? '是' : '否';
                } },
                {  'data': 'fcreate_date' },
                {  'data': 'fmodify_date' },
            ],
            buttons: [
                // { text: '新增', action: function () { }  },
                // { text: '编辑', className: 'edit', enabled: false },
                // { text: '删除', className: 'delete', enabled: false },
                {extend: "create", text: '新增', editor: editor},
                {extend: "edit", text: '编辑', editor: editor},
                {extend: "remove", text: '删除', editor: editor},
                {text: '审核', className: 'check', enabled: false},
                {text: '反审核', className: 'uncheck', enabled: false},
                {extend: 'excel', text: '导出Excel'},
                {extend: 'print', text: '打印'},
                //{extend: 'colvis', text: '列显示'}
            ]
        });

        table.on( 'select', checkBtn).on( 'deselect', checkBtn);

        function checkBtn(e, dt, type, indexes) {
            // var count = table.rows( { selected: true } ).count();
            // table.buttons( ['.edit', '.delete'] ).enable(count > 0);
            checkEditEnabble(table, ['.check'], ['.uncheck']);
        }
        //审核
        $(".check").on('click', function () {
            dataCheck(table, '/admin/customer-price/check');
        })

        $(".uncheck").on('click', function () {
            dataCheck(table, '/admin/customer-price/uncheck');
        })
    }

});<commit_msg>bug fix<commit_after>/**
*
*/
define(function(require, exports, module) {

    var zhCN = require('datatableZh');
    var editorCN = require('i18n');
    exports.index = function ($, tableId, customers, materials) {
        var editor = new $.fn.dataTable.Editor({
            ajax: {
                create: {
                    type: 'POST',
                    url: '/admin/customer-price',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                edit: {
                    type: 'PUT',
                    url: '/admin/customer-price/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                remove: {
                    type: 'DELETE',
                    url: '/admin/customer-price/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                }
            },
            i18n: editorCN,
            table: "#" + tableId,
            idSrc: 'id',
            fields: [
                { 'label':  '经销商', 'name': 'fcust_id', 'type': 'select', 'options': customers},
                { 'label':  '产品', 'name': 'fmaterial_id', 'type': 'select', 'options': materials},
                { 'label':  '销售起数量', 'name': 'fmin_qty', def: 0},
                { 'label':  '销售止数量', 'name': 'fmax_qty', def: 1000000},
                { 'label':  '单价/箱', 'name': 'fprice_box', },
                { 'label':  '单价/瓶', 'name': 'fprice_bottle', },
            ]
        });

        editor.on('open', function (e, json, data) {
            $("#DTE_Field_fcust_id").selectpicker({liveSearch: true});
            $("#DTE_Field_fmaterial_id").selectpicker({liveSearch: true});
        })
        var table = $("#" + tableId).DataTable({
            dom: "lBfrtip",
            language: zhCN,
            processing: true,
            serverSide: true,
            select: true,
            paging: true,
            rowId: "id",
            ajax: '/admin/customer-price/pagination',
            columns: [
                {  'data': 'id' },
                {  'data': 'fcust_id', render: function (data, type, full) {
                    return full.customer ? full.customer.fname : '';
                } },
                {  'data': 'fmaterial_id', render: function (data, type, full) {
                    return full.material.fname
                } },
                {  'data': 'fspecification' },
                {  'data': 'fsale_unit' },
                {  'data': 'fmin_qty' },
                {  'data': 'fmax_qty' },
                {  'data': 'fprice_box' },
                {  'data': 'fprice_bottle' },
                {  'data': 'fdocument_status', render: function (data, type, full) {
                    return document_status(data);
                } },
                {  'data': 'fis_valid', render: function (data, type, full) {
                    return data == 1 ? '是' : '否';
                } },
                {  'data': 'fcreate_date' },
                {  'data': 'fmodify_date' },
            ],
            buttons: [
                // { text: '新增', action: function () { }  },
                // { text: '编辑', className: 'edit', enabled: false },
                // { text: '删除', className: 'delete', enabled: false },
                {extend: "create", text: '新增', editor: editor},
                {extend: "edit", text: '编辑', editor: editor},
                {extend: "remove", text: '删除', editor: editor},
                {text: '审核', className: 'check', enabled: false},
                {text: '反审核', className: 'uncheck', enabled: false},
                {extend: 'excel', text: '导出Excel'},
                {extend: 'print', text: '打印'},
                //{extend: 'colvis', text: '列显示'}
            ]
        });

        table.on( 'select', checkBtn).on( 'deselect', checkBtn);

        function checkBtn(e, dt, type, indexes) {
            // var count = table.rows( { selected: true } ).count();
            // table.buttons( ['.edit', '.delete'] ).enable(count > 0);
            checkEditEnabble(table, ['.check'], ['.uncheck']);
        }
        //审核
        $(".check").on('click', function () {
            dataCheck(table, '/admin/customer-price/check');
        })

        $(".uncheck").on('click', function () {
            dataCheck(table, '/admin/customer-price/uncheck');
        })
    }

});<|endoftext|>


<commit_before>WDCNZ = {
	text:["Tech talks for web devs","Web dev conversations","JavaScript, HTML5, CSS", ".NET, PHP, Ruby","Mobile, Security, Scale"],
	currentIndex:0,
	init:function(){
		this.interval = setInterval(this.rotateText,5000,this)
	},
	rotateText:function(){
		WDCNZ.currentIndex++;
		if(WDCNZ.currentIndex>=WDCNZ.text.length)
		{
			WDCNZ.currentIndex = 0;
		}
		WDCNZ.fadeText();
		setTimeout(WDCNZ.setText,500);

	},
	fadeText:function(){
		$(".b-line").addClass('fade');
	},
	setText:function()
	{

		$(".b-line").text(WDCNZ.text[WDCNZ.currentIndex]);
		$(".b-line").removeClass('fade');
	},
}

jQuery(function($){
   WDCNZ.init();
});<commit_msg>removing platforms from the carousel as alienates Pyththon users<commit_after>WDCNZ = {
	text:["Tech talks for web devs","Web dev conversations","JavaScript, HTML5, CSS","Mobile, Security, Scale"],
	currentIndex:0,
	init:function(){
		this.interval = setInterval(this.rotateText,5000,this)
	},
	rotateText:function(){
		WDCNZ.currentIndex++;
		if(WDCNZ.currentIndex>=WDCNZ.text.length)
		{
			WDCNZ.currentIndex = 0;
		}
		WDCNZ.fadeText();
		setTimeout(WDCNZ.setText,500);

	},
	fadeText:function(){
		$(".b-line").addClass('fade');
	},
	setText:function()
	{

		$(".b-line").text(WDCNZ.text[WDCNZ.currentIndex]);
		$(".b-line").removeClass('fade');
	},
}

jQuery(function($){
   WDCNZ.init();
});<|endoftext|>