<commit_before>const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { UnusedFilesWebpackPlugin } = require('unused-files-webpack-plugin')
const StyleLintPlugin = require('stylelint-webpack-plugin')

const project = require('../project.config')

const inProject = path.resolve.bind(path, project.basePath)
const inProjectSrc = (file) => inProject(project.srcDir, file)

const __DEV__ = project.env === 'development'
const __TEST__ = project.env === 'test'
const __PROD__ = project.env === 'production'

const config = {
  entry: {
    app: [
      inProjectSrc(project.main)
    ]
  },

  devtool: project.sourcemaps ? 'source-map' : false,

  output: {
    path: inProject(project.outDir),
    filename: __DEV__ ? 'scripts/[name].js' : 'scripts/[name].[chunkhash].js',
    chunkFilename: __DEV__ ? 'scripts/modules/[name].js' : 'scripts/modules/[name].[chunkhash].js',
    publicPath: project.publicPath
  },

  resolve: {
    modules: [
      inProject(project.srcDir),
      'node_modules',
    ],
    extensions: [
      '.js',
      '.jsx',
      '.json'
    ],
    alias: {
      'common': inProject(project.srcDir),

      // Aliasing lodash.isequal to lodash/isEqual for perf purposes:
      // lodash.isequal embeds a lot of lodash that is already in the bundle.
      // This allows us to save about 4KB gzipped.
      'lodash.isequal': 'lodash/isEqual',

      'react': 'preact-compat',
      'react-dom': 'preact-compat'
    }
  },

  externals: project.externals,

  module: {
    rules: [],
  },

  plugins: [
    new webpack.DefinePlugin(Object.assign({
      'process.env': Object.entries(project.environment).reduce((env, entry) => {
        const key = entry[0]
        const value = process.env[key] || entry[1] || ''
        env[key] = JSON.stringify(value)
        return env
      }, {
        NODE_ENV: JSON.stringify(project.env)
      }),

      __DEV__,
      __TEST__,
      __PROD__
    }, project.globals)),

    new UnusedFilesWebpackPlugin({
      pattern: `${project.srcDir}/**/*.*`,
      globOptions: {
        ignore: [
          '**/__test__/**',
          '**/__mocks__/**',
        ]
      }
    })
  ]
}

// JavaScript
// ------------------------------------
if (__DEV__) {
  config.module.rules.push({
    test: /\.(js|jsx)$/,
    include: inProject(project.srcDir),
    loader: 'eslint-loader',
    enforce: 'pre'
  })
}

config.module.rules.push({
  test: /\.(js|jsx)$/,
  include: inProject(project.srcDir),
  use: [
    {
      loader: 'babel-loader',
      query: {
        cacheDirectory: true
      }
    }
  ]
})

// Styles
// ------------------------------------
const extractStyles = new ExtractTextPlugin({
  filename: 'styles/[name].[contenthash].css',
  allChunks: true,
  disable: !__PROD__
})

config.module.rules.push({
  test: /\.(sass|scss)$/,
  loader: extractStyles.extract({
    fallback: 'style-loader',
    use: [
      {
        loader: 'css-loader',
        options: {
          modules: true,
          camelCase: 'only',
          sourceMap: project.sourcemaps,
          minimize: {
            autoprefixer: {
              add: true,
              remove: true,
              browsers: ['last 2 versions']
            },
            discardComments: {
              removeAll : true
            },
            discardUnused: false,
            mergeIdents: false,
            reduceIdents: false,
            safe: true,
            sourcemap: project.sourcemaps
          }
        }
      },
      {
        loader: 'sass-loader',
        options: {
          sourceMap: project.sourcemaps,
          includePaths: [
            inProjectSrc('styles')
          ]
        }
      }
    ]
  })
})

config.plugins.push(extractStyles)

// Images
// ------------------------------------
config.module.rules.push({
  test: /\.(png|jpg|gif)$/,
  loader: 'url-loader',
  options: {
    limit: 8192
  }
})

// Fonts
// ------------------------------------
;[
  ['woff', 'application/font-woff'],
  ['woff2', 'application/font-woff2'],
  ['otf', 'font/opentype'],
  ['ttf', 'application/octet-stream'],
  ['eot', 'application/vnd.ms-fontobject'],
  ['svg', 'image/svg+xml'],
].forEach(([ extension, mimetype ]) => {
  config.module.rules.push({
    test: new RegExp(`\\.${extension}$`),
    loader: 'url-loader',
    options: {
      name: 'fonts/[name].[ext]',
      limit: 10000,
      mimetype
    }
  })
})

// HTML Template
// ------------------------------------
config.plugins.push(new HtmlWebpackPlugin({
  template: inProjectSrc('index.html'),
  inject: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeRedundantAttributes: true,
    useShortDoctype: true,
    removeEmptyAttributes: true,
    removeStyleLinkTypeAttributes: true,
    keepClosingSlash: true,
    minifyJS: true,
    minifyCSS: true,
    minifyURLs: true
  }
}))

// Development Tools
// ------------------------------------
if (__DEV__) {
  config.entry.app.push(
    `webpack-hot-middleware/client.js?path=${config.output.publicPath}__webpack_hmr`
  )
  config.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new StyleLintPlugin()
  )
}

// Bundle Splitting
// ------------------------------------
if (!__TEST__) {
  const bundles = ['manifest']

  if (project.vendors && project.vendors.length) {
    bundles.unshift('vendor')
    config.entry.vendor = project.vendors
  }

  config.plugins.push(new webpack.optimize.CommonsChunkPlugin({ names: bundles }))
  config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
    name: 'app',
    async: 'common',
    minChunks: 2
  }))
}

// Production Optimizations
// ------------------------------------
if (__PROD__) {
  config.plugins.push(
    new webpack.optimize.ModuleConcatenationPlugin(),

    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false,
    }),

    new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /fr/),

    new webpack.optimize.UglifyJsPlugin({
      sourceMap: !!config.devtool,
      comments: false,
      compress: {
        warnings: false,
        screw_ie8: true,
        conditionals: true,
        unused: true,
        comparisons: true,
        sequences: true,
        dead_code: true,
        evaluate: true,
        if_return: true,
        join_vars: true,
      },
      mangle: {
        screw_ie8: true
      },
      output: {
        comments: false,
        screw_ie8: true
      }
    }),

    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      openAnalyzer: false,
      reportFilename: path.join('..', project.reportDir, 'bundles.html'),
      defaultSizes: 'gzip'
    })
  )
}

module.exports = config
<commit_msg>Shorten and scope CSS class names by components<commit_after>const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { UnusedFilesWebpackPlugin } = require('unused-files-webpack-plugin')
const StyleLintPlugin = require('stylelint-webpack-plugin')

const project = require('../project.config')

const inProject = path.resolve.bind(path, project.basePath)
const inProjectSrc = (file) => inProject(project.srcDir, file)

const __DEV__ = project.env === 'development'
const __TEST__ = project.env === 'test'
const __PROD__ = project.env === 'production'

const config = {
  entry: {
    app: [
      inProjectSrc(project.main)
    ]
  },

  devtool: project.sourcemaps ? 'source-map' : false,

  output: {
    path: inProject(project.outDir),
    filename: __DEV__ ? 'scripts/[name].js' : 'scripts/[name].[chunkhash].js',
    chunkFilename: __DEV__ ? 'scripts/modules/[name].js' : 'scripts/modules/[name].[chunkhash].js',
    publicPath: project.publicPath
  },

  resolve: {
    modules: [
      inProject(project.srcDir),
      'node_modules',
    ],
    extensions: [
      '.js',
      '.jsx',
      '.json'
    ],
    alias: {
      'common': inProject(project.srcDir),

      // Aliasing lodash.isequal to lodash/isEqual for perf purposes:
      // lodash.isequal embeds a lot of lodash that is already in the bundle.
      // This allows us to save about 4KB gzipped.
      'lodash.isequal': 'lodash/isEqual',

      'react': 'preact-compat',
      'react-dom': 'preact-compat'
    }
  },

  externals: project.externals,

  module: {
    rules: [],
  },

  plugins: [
    new webpack.DefinePlugin(Object.assign({
      'process.env': Object.entries(project.environment).reduce((env, entry) => {
        const key = entry[0]
        const value = process.env[key] || entry[1] || ''
        env[key] = JSON.stringify(value)
        return env
      }, {
        NODE_ENV: JSON.stringify(project.env)
      }),

      __DEV__,
      __TEST__,
      __PROD__
    }, project.globals)),

    new UnusedFilesWebpackPlugin({
      pattern: `${project.srcDir}/**/*.*`,
      globOptions: {
        ignore: [
          '**/__test__/**',
          '**/__mocks__/**',
        ]
      }
    })
  ]
}

// JavaScript
// ------------------------------------
if (__DEV__) {
  config.module.rules.push({
    test: /\.(js|jsx)$/,
    include: inProject(project.srcDir),
    loader: 'eslint-loader',
    enforce: 'pre'
  })
}

config.module.rules.push({
  test: /\.(js|jsx)$/,
  include: inProject(project.srcDir),
  use: [
    {
      loader: 'babel-loader',
      query: {
        cacheDirectory: true
      }
    }
  ]
})

// Styles
// ------------------------------------
const extractStyles = new ExtractTextPlugin({
  filename: 'styles/[name].[contenthash].css',
  allChunks: true,
  disable: !__PROD__
})

config.module.rules.push({
  test: /\.(sass|scss)$/,
  loader: extractStyles.extract({
    fallback: 'style-loader',
    use: [
      {
        loader: 'css-loader',
        options: {
          modules: true,
          localIdentName: '[name]-[hash:base64:8]',
          camelCase: 'only',
          sourceMap: project.sourcemaps,
          minimize: {
            autoprefixer: {
              add: true,
              remove: true,
              browsers: ['last 2 versions']
            },
            discardComments: {
              removeAll : true
            },
            discardUnused: false,
            mergeIdents: false,
            reduceIdents: false,
            safe: true,
            sourcemap: project.sourcemaps
          }
        }
      },
      {
        loader: 'sass-loader',
        options: {
          sourceMap: project.sourcemaps,
          includePaths: [
            inProjectSrc('styles')
          ]
        }
      }
    ]
  })
})

config.plugins.push(extractStyles)

// Images
// ------------------------------------
config.module.rules.push({
  test: /\.(png|jpg|gif)$/,
  loader: 'url-loader',
  options: {
    limit: 8192
  }
})

// Fonts
// ------------------------------------
;[
  ['woff', 'application/font-woff'],
  ['woff2', 'application/font-woff2'],
  ['otf', 'font/opentype'],
  ['ttf', 'application/octet-stream'],
  ['eot', 'application/vnd.ms-fontobject'],
  ['svg', 'image/svg+xml'],
].forEach(([ extension, mimetype ]) => {
  config.module.rules.push({
    test: new RegExp(`\\.${extension}$`),
    loader: 'url-loader',
    options: {
      name: 'fonts/[name].[ext]',
      limit: 10000,
      mimetype
    }
  })
})

// HTML Template
// ------------------------------------
config.plugins.push(new HtmlWebpackPlugin({
  template: inProjectSrc('index.html'),
  inject: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeRedundantAttributes: true,
    useShortDoctype: true,
    removeEmptyAttributes: true,
    removeStyleLinkTypeAttributes: true,
    keepClosingSlash: true,
    minifyJS: true,
    minifyCSS: true,
    minifyURLs: true
  }
}))

// Development Tools
// ------------------------------------
if (__DEV__) {
  config.entry.app.push(
    `webpack-hot-middleware/client.js?path=${config.output.publicPath}__webpack_hmr`
  )
  config.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new StyleLintPlugin()
  )
}

// Bundle Splitting
// ------------------------------------
if (!__TEST__) {
  const bundles = ['manifest']

  if (project.vendors && project.vendors.length) {
    bundles.unshift('vendor')
    config.entry.vendor = project.vendors
  }

  config.plugins.push(new webpack.optimize.CommonsChunkPlugin({ names: bundles }))
  config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
    name: 'app',
    async: 'common',
    minChunks: 2
  }))
}

// Production Optimizations
// ------------------------------------
if (__PROD__) {
  config.plugins.push(
    new webpack.optimize.ModuleConcatenationPlugin(),

    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false,
    }),

    new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /fr/),

    new webpack.optimize.UglifyJsPlugin({
      sourceMap: !!config.devtool,
      comments: false,
      compress: {
        warnings: false,
        screw_ie8: true,
        conditionals: true,
        unused: true,
        comparisons: true,
        sequences: true,
        dead_code: true,
        evaluate: true,
        if_return: true,
        join_vars: true,
      },
      mangle: {
        screw_ie8: true
      },
      output: {
        comments: false,
        screw_ie8: true
      }
    }),

    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      openAnalyzer: false,
      reportFilename: path.join('..', project.reportDir, 'bundles.html'),
      defaultSizes: 'gzip'
    })
  )
}

module.exports = config
<|endoftext|>


<commit_before>angular.module('blissful', ['ngResource'])

.config(function($httpProvider) {
  $httpProvider.responseInterceptors.push('blissHttpInterceptor');
})

.factory('blissHttpInterceptor', function($q) {
  return function(promise) {
    return promise.then(function(response) {
      return response;
    }, function(response) {
      if (response.headers('X-Bliss-Error')) {
        alert('Error:\n' + response.data);
      }
      return $q.reject(response);
    });
  };
});

function ProjectController($scope, $http, $resource, $filter) {

  var Files = $resource('listfiles');

  var _dirty = false;
  var _save_timeout;

  // called from setTimeout after editor is marked dirty
  function save() {
    if (!_dirty) {
      return;
    }

    // TODO: fix me
    _dirty = false;

    set_status('Saving...');

    $scope.putfile($scope.currentFilename(), _editor.getValue());
  }

  function markDirty() {
    if (_save_timeout) {
      return;
    }
    _dirty = true;
    _save_timeout = setTimeout(function() {
      _save_timeout = null;
      save();
    }, 1000);
  }

  // editor onChange
  function editorOnChange(from, to, text, next) {
     markDirty();
  }

  $scope.prompt_file_delete = function() {
    var answer = prompt("Are you sure you want to delete " + $scope.currentFilename() + "?\nType 'yes' to confirm.", "no");
    if (!answer || answer.toLowerCase()[0] != 'y') {
      return;
    }
    $scope.deletepath($scope.currentFilename());
  }

  $scope.prompt_file_rename = function() {
    var new_filename = prompt(
        'New filename?\n(You may specify a full path such as: foo/bar.txt)',
        $scope.currentFilename());
    if (!new_filename) {
      return;
    }
    if (new_filename[0] == '/') {
      new_filename = new_filename.substr(1);
    }
    if (!new_filename || new_filename == $scope.currentFilename()) {
      return;
    }
    $scope.movefile($scope.currentFilename(), new_filename);
  }

  // setup file context menu clear handler
  window.addEventListener('click', function(evt) {
    document.getElementById('file-context-menu').style.display = 'None';
  }, false);

  $scope.file_context_menu = function(evt, i) {
    evt.stopPropagation();
    $scope.select(i);
    var menuDiv = document.getElementById('file-context-menu');
    menuDiv.style.display = 'block';
    menuDiv.style.left = evt.pageX + 'px';
    menuDiv.style.top = evt.pageY + 'px';
    var elem = document.getElementById('file-' + i);
    insertAfter(menuDiv, elem);
  };

  $scope.orderFilesAndSelectByPath = function(path) {
    $scope.files = $filter('orderBy')($scope.files, 'name');
    $scope.selectByPath(path);
  };

  $scope.insertPath = function(path) {
    if ($scope.selectByPath(path)) {
      return;
    }
    $scope.putfile(path, '');
    files = $scope.files;
    files.push({name: path});
    $scope.orderFilesAndSelectByPath(path);
  };

  $scope.prompt_for_new_file = function() {
    var filename = prompt('New filename?', '');
    if (!filename) {
      return;
    }
    if (filename[0] == '/') {
      filename = filename.substr(1)
    }

    $scope.insertPath(filename);
  };

  $scope.currentFilename = function() {
    return $scope.files[$scope.currentIndex].name;
  };

  $scope.deletepath = function(filename) {
    $http({method: 'POST',
           url: 'deletepath/' + encodeURI(filename)})
    .success(function(data, status, headers, config) {
      $scope.files.splice($scope.currentIndex, 1);
      $scope.select(0);
    });
  };

  $scope.movefile = function(path, newpath) {
    $http({method: 'POST',
         url: 'movefile/' + encodeURI(path),
         data: {newpath: newpath}})
    .success(function(data, status, headers, config) {
      $scope.files[$scope.currentIndex].name = newpath;
      $scope.orderFilesAndSelectByPath(newpath);
    });
  };

  $scope.putfile = function(filename, data) {
    $http({method: 'PUT',
           url: 'putfile/' + encodeURI(filename),
           data: data})
    .success(function(data, status, headers, config) {
      set_status(); // Saved
    });
  };

  $scope.selectByPath = function(path) {
    for (i in $scope.files) {
      if ($scope.files[i].name == path) {
        $scope.select(i);
        return true;
      }
    }
    return false;
  };

  $scope.select = function(i) {
    $scope.currentIndex = i;

    $http({method: 'GET',
           url: 'getfile/' + encodeURI($scope.currentFilename())})
    .success(function(data, status, headers, config) {
      // e.g. 'text/html; charset=UTF-8'
      var mime_type = headers('Content-Type');
      // strip '; charset=...'
      mime_type = mime_type.replace(/ ?;.*/, '');
      if (/^image\//.test(mime_type)) {
        source_image.setAttribute('src', config.url);
        source_container.setAttribute('class', 'image');
      } else {
        while(source_code.hasChildNodes()) {
          source_code.removeChild(source_code.childNodes[0]);
        }
        _editor = createEditor(mime_type);
        _editor.getScrollerElement().id = 'scroller-element';
        source_container.setAttribute('class', 'code');
        _editor.setValue(data);
        _editor.setOption('onChange', editorOnChange);
        _editor.focus();
      }
    });
  };

  var listfiles = function() {
    Files.query(function(files) {
      $scope.files = files;
      $scope.select(0);
    });
  };

  listfiles();

}
<commit_msg>$scope.currentFilename() should not fail when page is first loaded due to uninitialized $scope.files<commit_after>angular.module('blissful', ['ngResource'])

.config(function($httpProvider) {
  $httpProvider.responseInterceptors.push('blissHttpInterceptor');
})

.factory('blissHttpInterceptor', function($q) {
  return function(promise) {
    return promise.then(function(response) {
      return response;
    }, function(response) {
      if (response.headers('X-Bliss-Error')) {
        alert('Error:\n' + response.data);
      }
      return $q.reject(response);
    });
  };
});

function ProjectController($scope, $http, $resource, $filter) {

  var Files = $resource('listfiles');

  var _dirty = false;
  var _save_timeout;

  // called from setTimeout after editor is marked dirty
  function save() {
    if (!_dirty) {
      return;
    }

    // TODO: fix me
    _dirty = false;

    set_status('Saving...');

    $scope.putfile($scope.currentFilename(), _editor.getValue());
  }

  function markDirty() {
    if (_save_timeout) {
      return;
    }
    _dirty = true;
    _save_timeout = setTimeout(function() {
      _save_timeout = null;
      save();
    }, 1000);
  }

  // editor onChange
  function editorOnChange(from, to, text, next) {
     markDirty();
  }

  $scope.prompt_file_delete = function() {
    var answer = prompt("Are you sure you want to delete " + $scope.currentFilename() + "?\nType 'yes' to confirm.", "no");
    if (!answer || answer.toLowerCase()[0] != 'y') {
      return;
    }
    $scope.deletepath($scope.currentFilename());
  }

  $scope.prompt_file_rename = function() {
    var new_filename = prompt(
        'New filename?\n(You may specify a full path such as: foo/bar.txt)',
        $scope.currentFilename());
    if (!new_filename) {
      return;
    }
    if (new_filename[0] == '/') {
      new_filename = new_filename.substr(1);
    }
    if (!new_filename || new_filename == $scope.currentFilename()) {
      return;
    }
    $scope.movefile($scope.currentFilename(), new_filename);
  }

  // setup file context menu clear handler
  window.addEventListener('click', function(evt) {
    document.getElementById('file-context-menu').style.display = 'None';
  }, false);

  $scope.file_context_menu = function(evt, i) {
    evt.stopPropagation();
    $scope.select(i);
    var menuDiv = document.getElementById('file-context-menu');
    menuDiv.style.display = 'block';
    menuDiv.style.left = evt.pageX + 'px';
    menuDiv.style.top = evt.pageY + 'px';
    var elem = document.getElementById('file-' + i);
    insertAfter(menuDiv, elem);
  };

  $scope.orderFilesAndSelectByPath = function(path) {
    $scope.files = $filter('orderBy')($scope.files, 'name');
    $scope.selectByPath(path);
  };

  $scope.insertPath = function(path) {
    if ($scope.selectByPath(path)) {
      return;
    }
    $scope.putfile(path, '');
    files = $scope.files;
    files.push({name: path});
    $scope.orderFilesAndSelectByPath(path);
  };

  $scope.prompt_for_new_file = function() {
    var filename = prompt('New filename?', '');
    if (!filename) {
      return;
    }
    if (filename[0] == '/') {
      filename = filename.substr(1)
    }

    $scope.insertPath(filename);
  };

  $scope.currentFilename = function() {
    if (!$scope.files) return '';
    return $scope.files[$scope.currentIndex].name;
  };

  $scope.deletepath = function(filename) {
    $http({method: 'POST',
           url: 'deletepath/' + encodeURI(filename)})
    .success(function(data, status, headers, config) {
      $scope.files.splice($scope.currentIndex, 1);
      $scope.select(0);
    });
  };

  $scope.movefile = function(path, newpath) {
    $http({method: 'POST',
         url: 'movefile/' + encodeURI(path),
         data: {newpath: newpath}})
    .success(function(data, status, headers, config) {
      $scope.files[$scope.currentIndex].name = newpath;
      $scope.orderFilesAndSelectByPath(newpath);
    });
  };

  $scope.putfile = function(filename, data) {
    $http({method: 'PUT',
           url: 'putfile/' + encodeURI(filename),
           data: data})
    .success(function(data, status, headers, config) {
      set_status(); // Saved
    });
  };

  $scope.selectByPath = function(path) {
    for (i in $scope.files) {
      if ($scope.files[i].name == path) {
        $scope.select(i);
        return true;
      }
    }
    return false;
  };

  $scope.select = function(i) {
    $scope.currentIndex = i;

    $http({method: 'GET',
           url: 'getfile/' + encodeURI($scope.currentFilename())})
    .success(function(data, status, headers, config) {
      // e.g. 'text/html; charset=UTF-8'
      var mime_type = headers('Content-Type');
      // strip '; charset=...'
      mime_type = mime_type.replace(/ ?;.*/, '');
      if (/^image\//.test(mime_type)) {
        source_image.setAttribute('src', config.url);
        source_container.setAttribute('class', 'image');
      } else {
        while(source_code.hasChildNodes()) {
          source_code.removeChild(source_code.childNodes[0]);
        }
        _editor = createEditor(mime_type);
        _editor.getScrollerElement().id = 'scroller-element';
        source_container.setAttribute('class', 'code');
        _editor.setValue(data);
        _editor.setOption('onChange', editorOnChange);
        _editor.focus();
      }
    });
  };

  var listfiles = function() {
    Files.query(function(files) {
      $scope.files = files;
      $scope.select(0);
    });
  };

  listfiles();

}
<|endoftext|>


<commit_before>var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var WebpackMd5Hash = require('webpack-md5-hash');
var HashedModuleIdsPlugin = require('./HashedModuleIdsPlugin');

// 辅助函数
var utils = require('./utils');
var fullPath  = utils.fullPath;
var pickFiles = utils.pickFiles;

// 项目根路径
var ROOT_PATH = fullPath('../');
// 项目源码路径
var SRC_PATH = ROOT_PATH + '/src';
// 产出路径
var DIST_PATH = ROOT_PATH + '/dist';

// node_modules
var NODE_MODULES_PATH =  ROOT_PATH + '/node_modules';

var __DEV__ = process.env.NODE_ENV !== 'production';

var args = process.argv;
var uglify = args.indexOf('--uglify') > -1;

// conf
// import api from 'conf/api';
var alias = pickFiles({
  id: /(conf\/[^\/]+).js$/,
  pattern: SRC_PATH + '/conf/*.js'
});

// components
// import Alert from 'components/alert';
alias = Object.assign(alias, pickFiles({
  id: /(components\/[^\/]+)/,
  pattern: SRC_PATH + '/components/*/index.js'
}));

// reducers
// import reducers from 'reducers/index';
alias = Object.assign(alias, pickFiles({
  id: /(reducers\/[^\/]+).js/,
  pattern: SRC_PATH + '/js/reducers/*'
}));

// actions
// import actions from 'actions/index';
alias = Object.assign(alias, pickFiles({
  id: /(actions\/[^\/]+).js/,
  pattern: SRC_PATH + '/js/actions/*'
}));

alias = Object.assign(alias, {
  'react-router': NODE_MODULES_PATH + '/react-router/lib/index.js',
  'react-redux': NODE_MODULES_PATH + '/react-redux/lib/index.js',
  'redux': NODE_MODULES_PATH + '/redux/lib/index.js',
  'redux-thunk': NODE_MODULES_PATH + '/redux-thunk/lib/index.js'
});

var config = {
  context: SRC_PATH,
  entry: {
    app: [SRC_PATH + '/pages/app.js'],
    lib: [
      'react', 'react-dom', 'react-router',
      'redux', 'react-redux', 'redux-thunk'
    ],
  },
  output: {
    path: DIST_PATH,
    // chunkhash 不能与 --hot 同时使用
    // see https://github.com/webpack/webpack-dev-server/issues/377
    filename: __DEV__ ? 'js/[name].js' : 'js/[name].[chunkhash].js',
    chunkFilename: __DEV__ ? 'js/[name].js' : 'js/[name].[chunkhash].js'
  },
  module: {},
  resolve: {
    root: SRC_PATH,
    alias: alias
  },
  plugins: [
    new webpack.DefinePlugin({
      // http://stackoverflow.com/questions/30030031/passing-environment-dependent-variables-in-webpack
      "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    new webpack.optimize.CommonsChunkPlugin({
      names: ['lib', 'manifest']
    }),
    // 使用文件名替换数字作为模块ID
    // new webpack.NamedModulesPlugin(),
    // 使用 hash 作模块 ID，文件名作ID太长了，文件大小剧增
    new HashedModuleIdsPlugin(),
    // 根据文件内容生成 hash
    new WebpackMd5Hash()
  ]
};

// loaders
var CACHE_PATH = ROOT_PATH + '/cache';
config.module.loaders = [];

// 使用 babel 编译 jsx、es6
config.module.loaders.push({
  test: /\.js$/,
  exclude: /node_modules/,
  // 这里使用 loaders ，因为后面还需要添加 loader
  loaders: ['babel?cacheDirectory=' + CACHE_PATH]
});

// 编译 sass
if (__DEV__) {
  config.module.loaders.push({
    test: /\.(scss|css)$/,
    loaders: ['style', 'css', 'postcss', 'sass']
  });
} else {
  config.module.loaders.push({
    test: /\.(scss|css)$/,
    loader: ExtractTextPlugin.extract('style', 'css!postcss!sass')
  });
  config.plugins.push(
    new ExtractTextPlugin('css/[name].[contenthash].css')
  );
}

// css autoprefix
var precss = require('precss');
var autoprefixer = require('autoprefixer');
config.postcss = function() {
  return [precss, autoprefixer];
}

// 图片路径处理，压缩
config.module.loaders.push({
  test: /\.(?:jpg|gif|png|svg)$/,
  loaders: [
    'url?limit=8000&name=img/[hash].[ext]',
    'image-webpack'
  ]
});

// 压缩 js, css
if (uglify) {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      output: {
        comments: false
      }
    })
  );
}

// 去掉重复模块
if (!__DEV__) {
  config.plugins.push(
    new webpack.optimize.DedupePlugin()
  );
}

// html 页面
var HtmlwebpackPlugin = require('html-webpack-plugin');
config.plugins.push(
  new HtmlwebpackPlugin({
    filename: 'index.html',
    chunks: ['app', 'lib'],
    template: SRC_PATH + '/pages/app.html',
    minify: __DEV__ ? false : {
      collapseWhitespace: true,
      collapseInlineTagWhitespace: true,
      removeRedundantAttributes: true,
      removeEmptyAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeComments: true
    }
  })
);

// 内嵌 manifest 到 html 页面
config.plugins.push(function() {
  this.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-after-emit', function(file, callback) {
      var manifest = '';
      Object.keys(compilation.assets).forEach(function(filename) {
        if (/\/?manifest.[^\/]*js$/.test(filename)) {
          manifest = '<script>' + compilation.assets[filename].source() + '</script>';
        }
      });
      if (manifest) {
        var htmlSource = file.html.source();
        htmlSource = htmlSource.replace(/(<\/head>)/, manifest + '$1');
        file.html.source = function() {
          return htmlSource;
        };
      }
      callback(null, file);
    });
  });
});

module.exports = config;

<commit_msg>fix windows path error<commit_after>var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var WebpackMd5Hash = require('webpack-md5-hash');
var HashedModuleIdsPlugin = require('./HashedModuleIdsPlugin');
var path = require('path');

// 辅助函数
var utils = require('./utils');
var fullPath  = utils.fullPath;
var pickFiles = utils.pickFiles;

// 项目根路径
var ROOT_PATH = fullPath('../');
// 项目源码路径
//windows has "" as path separator
// var SRC_PATH = ROOT_PATH + '/src';
var SRC_PATH = path.join(ROOT_PATH, 'src');
// 产出路径
var DIST_PATH = ROOT_PATH + '/dist';

// node_modules
var NODE_MODULES_PATH =  ROOT_PATH + '/node_modules';

var __DEV__ = process.env.NODE_ENV !== 'production';

var args = process.argv;
var uglify = args.indexOf('--uglify') > -1;

// conf
// import api from 'conf/api';
var alias = pickFiles({
  id: /(conf\/[^\/]+).js$/,
  pattern: SRC_PATH + '/conf/*.js'
});

// components
// import Alert from 'components/alert';
alias = Object.assign(alias, pickFiles({
  id: /(components\/[^\/]+)/,
  pattern: SRC_PATH + '/components/*/index.js'
}));

// reducers
// import reducers from 'reducers/index';
alias = Object.assign(alias, pickFiles({
  id: /(reducers\/[^\/]+).js/,
  pattern: SRC_PATH + '/js/reducers/*'
}));

// actions
// import actions from 'actions/index';
alias = Object.assign(alias, pickFiles({
  id: /(actions\/[^\/]+).js/,
  pattern: SRC_PATH + '/js/actions/*'
}));

alias = Object.assign(alias, {
  'react-router': NODE_MODULES_PATH + '/react-router/lib/index.js',
  'react-redux': NODE_MODULES_PATH + '/react-redux/lib/index.js',
  'redux': NODE_MODULES_PATH + '/redux/lib/index.js',
  'redux-thunk': NODE_MODULES_PATH + '/redux-thunk/lib/index.js'
});

var config = {
  context: SRC_PATH,
  entry: {
    app: [SRC_PATH + '/pages/app.js'],
    lib: [
      'react', 'react-dom', 'react-router',
      'redux', 'react-redux', 'redux-thunk'
    ],
  },
  output: {
    path: DIST_PATH,
    // chunkhash 不能与 --hot 同时使用
    // see https://github.com/webpack/webpack-dev-server/issues/377
    filename: __DEV__ ? 'js/[name].js' : 'js/[name].[chunkhash].js',
    chunkFilename: __DEV__ ? 'js/[name].js' : 'js/[name].[chunkhash].js'
  },
  module: {},
  resolve: {
    root: SRC_PATH,
    alias: alias
  },
  plugins: [
    new webpack.DefinePlugin({
      // http://stackoverflow.com/questions/30030031/passing-environment-dependent-variables-in-webpack
      "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    new webpack.optimize.CommonsChunkPlugin({
      names: ['lib', 'manifest']
    }),
    // 使用文件名替换数字作为模块ID
    // new webpack.NamedModulesPlugin(),
    // 使用 hash 作模块 ID，文件名作ID太长了，文件大小剧增
    new HashedModuleIdsPlugin(),
    // 根据文件内容生成 hash
    new WebpackMd5Hash()
  ]
};

// loaders
var CACHE_PATH = ROOT_PATH + '/cache';
config.module.loaders = [];

// 使用 babel 编译 jsx、es6
config.module.loaders.push({
  test: /\.js$/,
  exclude: /node_modules/,
  // 这里使用 loaders ，因为后面还需要添加 loader
  loaders: ['babel?cacheDirectory=' + CACHE_PATH]
});

// 编译 sass
if (__DEV__) {
  config.module.loaders.push({
    test: /\.(scss|css)$/,
    loaders: ['style', 'css', 'postcss', 'sass']
  });
} else {
  config.module.loaders.push({
    test: /\.(scss|css)$/,
    loader: ExtractTextPlugin.extract('style', 'css!postcss!sass')
  });
  config.plugins.push(
    new ExtractTextPlugin('css/[name].[contenthash].css')
  );
}

// css autoprefix
var precss = require('precss');
var autoprefixer = require('autoprefixer');
config.postcss = function() {
  return [precss, autoprefixer];
}

// 图片路径处理，压缩
config.module.loaders.push({
  test: /\.(?:jpg|gif|png|svg)$/,
  loaders: [
    'url?limit=8000&name=img/[hash].[ext]',
    'image-webpack'
  ]
});

// 压缩 js, css
if (uglify) {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      output: {
        comments: false
      }
    })
  );
}

// 去掉重复模块
if (!__DEV__) {
  config.plugins.push(
    new webpack.optimize.DedupePlugin()
  );
}

// html 页面
var HtmlwebpackPlugin = require('html-webpack-plugin');
config.plugins.push(
  new HtmlwebpackPlugin({
    filename: 'index.html',
    chunks: ['app', 'lib'],
    template: SRC_PATH + '/pages/app.html',
    minify: __DEV__ ? false : {
      collapseWhitespace: true,
      collapseInlineTagWhitespace: true,
      removeRedundantAttributes: true,
      removeEmptyAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeComments: true
    }
  })
);

// 内嵌 manifest 到 html 页面
config.plugins.push(function() {
  this.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-after-emit', function(file, callback) {
      var manifest = '';
      Object.keys(compilation.assets).forEach(function(filename) {
        if (/\/?manifest.[^\/]*js$/.test(filename)) {
          manifest = '<script>' + compilation.assets[filename].source() + '</script>';
        }
      });
      if (manifest) {
        var htmlSource = file.html.source();
        htmlSource = htmlSource.replace(/(<\/head>)/, manifest + '$1');
        file.html.source = function() {
          return htmlSource;
        };
      }
      callback(null, file);
    });
  });
});

module.exports = config;

<|endoftext|>


<commit_before>import webpack from 'webpack';
import config  from '../../config';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';

const paths   = config.get('utils_paths'),
      globals = config.get('globals');

const webpackConfig = {
  name    : 'client',
  target  : 'web',
  devtool : 'source-map',
  entry   : {
    app : [
      paths.src('index')
    ]
  },
  output : {
    filename   : '[name].[hash].js',
    path       : paths.dist(),
    publicPath : '/'
  },
  plugins : [
    new webpack.DefinePlugin(config.get('globals')),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new ExtractTextPlugin('[name].[contenthash].css'),
    new HtmlWebpackPlugin({
      template : paths.src('index.html'),
      hash     : true,
      filename : 'index.html',
      minify   : globals.__PROD__,
      inject   : 'body'
    })
  ],
  resolve : {
    extensions : ['', '.js', '.jsx'],
    alias : config.get('utils_aliases')
  },
  module : {
    loaders : [
      {
        test : /\.(js|jsx)$/,
        include :  paths.project(config.get('dir_src')),
        loaders : ['babel?optional[]=runtime']
      },
      {
        test    : /\.scss$/,
        loaders : [
          'style-loader',
          'css-loader',
          'autoprefixer?browsers=last 2 version',
          'sass-loader?includePaths[]=' + paths.src('styles')
        ]
      }
    ]
  },
  eslint : {
    configFile  : paths.project('.eslintrc'),
    failOnError : globals.__PROD__,
    emitWarning : globals.__DEV__
  }
};

// ----------------------------------
// Vendor Bundle Configuration
// ----------------------------------
webpackConfig.entry.vendor = config.get('vendor_dependencies');

// NOTE: this is a temporary workaround. I don't know how to get Karma
// to include the vendor bundle that webpack creates, so to get around that
// we remove the bundle splitting when webpack is used with Karma.
const commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin(
  'vendor', '[name].[hash].js'
);
commonChunkPlugin.__KARMA_IGNORE__ = true;
webpackConfig.plugins.push(commonChunkPlugin);

// ----------------------------------
// Environment-Specific Defaults
// ----------------------------------
if (globals.__DEV__) {
  webpackConfig.entry.app.push(
    `webpack-dev-server/client?${config.get('webpack_public_path')}`,
    `webpack/hot/dev-server`
  );

  webpackConfig.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  );
}

if (globals.__PROD__) {

  // Compile CSS to its own file in production.
  webpackConfig.module.loaders = webpackConfig.module.loaders.map(loader => {
    if (/css/.test(loader.test)) {
      const [first, ...rest] = loader.loaders;

      loader.loader = ExtractTextPlugin.extract(first, rest.join('!'));
      delete loader.loaders;
    }

    return loader;
  });

  webpackConfig.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress : {
        'unused'    : true,
        'dead_code' : true
      }
    })
  );
}

// ------------------------------------
// Optional Configuration
// ------------------------------------
if (
  !globals.__DEV__ ||
  (globals.__DEV__ && config.get('webpack_lint_in_dev'))
) {
  webpackConfig.module.preLoaders = [
    {
      test : /\.(js|jsx)$/,
      loaders : ['eslint-loader'],
      include : paths.project(config.get('dir_src'))
    }
  ];
}

export default webpackConfig;
<commit_msg>Modify public path for build env<commit_after>import webpack from 'webpack';
import config  from '../../config';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';

const paths   = config.get('utils_paths'),
      globals = config.get('globals');

const webpackConfig = {
  name    : 'client',
  target  : 'web',
  devtool : 'source-map',
  entry   : {
    app : [
      paths.src('index')
    ]
  },
  output : {
    filename   : '[name].[hash].js',
    path       : paths.dist(),
    publicPath : ''
  },
  plugins : [
    new webpack.DefinePlugin(config.get('globals')),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new ExtractTextPlugin('[name].[contenthash].css'),
    new HtmlWebpackPlugin({
      template : paths.src('index.html'),
      hash     : true,
      filename : 'index.html',
      minify   : globals.__PROD__,
      inject   : 'body'
    })
  ],
  resolve : {
    extensions : ['', '.js', '.jsx'],
    alias : config.get('utils_aliases')
  },
  module : {
    loaders : [
      {
        test : /\.(js|jsx)$/,
        include :  paths.project(config.get('dir_src')),
        loaders : ['babel?optional[]=runtime']
      },
      {
        test    : /\.scss$/,
        loaders : [
          'style-loader',
          'css-loader',
          'autoprefixer?browsers=last 2 version',
          'sass-loader?includePaths[]=' + paths.src('styles')
        ]
      }
    ]
  },
  eslint : {
    configFile  : paths.project('.eslintrc'),
    failOnError : globals.__PROD__,
    emitWarning : globals.__DEV__
  }
};

// ----------------------------------
// Vendor Bundle Configuration
// ----------------------------------
webpackConfig.entry.vendor = config.get('vendor_dependencies');

// NOTE: this is a temporary workaround. I don't know how to get Karma
// to include the vendor bundle that webpack creates, so to get around that
// we remove the bundle splitting when webpack is used with Karma.
const commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin(
  'vendor', '[name].[hash].js'
);
commonChunkPlugin.__KARMA_IGNORE__ = true;
webpackConfig.plugins.push(commonChunkPlugin);

// ----------------------------------
// Environment-Specific Defaults
// ----------------------------------
if (globals.__DEV__) {
  webpackConfig.entry.app.push(
    `webpack-dev-server/client?${config.get('webpack_public_path')}`,
    `webpack/hot/dev-server`
  );

  webpackConfig.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  );
}

if (globals.__PROD__) {

  // Compile CSS to its own file in production.
  webpackConfig.module.loaders = webpackConfig.module.loaders.map(loader => {
    if (/css/.test(loader.test)) {
      const [first, ...rest] = loader.loaders;

      loader.loader = ExtractTextPlugin.extract(first, rest.join('!'));
      delete loader.loaders;
    }

    return loader;
  });

  webpackConfig.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress : {
        'unused'    : true,
        'dead_code' : true
      }
    })
  );
}

// ------------------------------------
// Optional Configuration
// ------------------------------------
if (
  !globals.__DEV__ ||
  (globals.__DEV__ && config.get('webpack_lint_in_dev'))
) {
  webpackConfig.module.preLoaders = [
    {
      test : /\.(js|jsx)$/,
      loaders : ['eslint-loader'],
      include : paths.project(config.get('dir_src'))
    }
  ];
}

export default webpackConfig;
<|endoftext|>


<commit_before>export const OrderExplorerComponent = {
  controller: ComponentController,
  controllerAs: 'vm',
  templateUrl: 'app/components/order-explorer/order-explorer.html',
};

/** @ngInject */
function ComponentController($filter, lodash, ListView, Language, OrdersState, EventNotifications, Session, RBAC, ModalService,
                             CollectionsApi, sprintf) {
  const vm = this;
  vm.$onInit = activate();
  function activate() {
    angular.extend(vm, {
      currentUser: Session.currentUser(),
      loading: false,
      orders: [],
      limit: 20,
      filterCount: 0,
      ordersList: [],
      selectedItemsList: [],
      limitOptions: [5, 10, 20, 50, 100, 200, 500, 1000],
      selectedItemsListCount: 0,
      // Functions
      resolveOrders: resolveOrders,
      listActionDisable: listActionDisable,
      // Config setup
      actionConfig: getActionConfig(),
      menuActions: getMenuActions(),
      toolbarConfig: getToolbarConfig(),
      listConfig: getListConfig(),
      expandedListConfig: getExpandedListConfig(),
    });

    resolveOrders(vm.limit, 0);
  }

  function getActionConfig() {
    return [
      {
        title: __('Lifecycle'),
        actionName: 'lifecycle',
        name: __('Lifecycle'),
        icon: 'fa fa-recycle',
        actions: [
          {
            icon: 'fa fa-check',
            name: __('Approve'),
            actionName: 'approve',
            title: __('Approve'),
            actionFn: approveRequests,
            isDisabled: false,
          }, {
            icon: 'fa fa-ban',
            name: __('Deny'),
            actionName: 'deny',
            title: __('Deny'),
            actionFn: denyRequests,
            isDisabled: false,
          },
        ],
      },
    ];
  }

  function getListConfig() {
    return {
      showSelectBox: checkApproval(),
      useExpandingRows: true,
      selectionMatchProp: 'id',
      onClick: expandRow,
      onCheckBoxChange: selectionChange,
    };
  }

  function getExpandedListConfig() {
    return {
      showSelectBox: checkApproval(),
      selectionMatchProp: 'id',
      onClick: selectItem,
      onCheckBoxChange: extendedSelectionChange,
    };
  }

  function getToolbarConfig() {
    const sortConfig = {
      fields: getOrderSortFields(),
      onSortChange: sortChange,
      isAscending: OrdersState.getSort().isAscending,
      currentField: OrdersState.getSort().currentField,
    };

    const filterConfig = {
      fields: getOrderFilterFields(),
      resultsCount: 0,
      appliedFilters: OrdersState.filterApplied ? OrdersState.getFilters() : [],
      onFilterChange: orderFilterChange,
    };

    return {
      sortConfig: sortConfig,
      filterConfig: filterConfig,
      actionsConfig: {
        actionsInclude: checkApproval(),
      },
    };
  }

  function getOrderFilterFields() {
    return [
      ListView.createFilterField('name', __('Name'), __('Filter by Name'), 'text'),
      ListView.createFilterField('id', __('Order ID'), __('Filter by ID'), 'text'),
      ListView.createFilterField('placed_at', __('Order Date'), __('Filter by Order Date'), 'text'),
    ];
  }

  function getOrderSortFields() {
    return [
      ListView.createSortField('name', __('Name'), 'alpha'),
      ListView.createSortField('id', __('Order ID'), 'numeric'),
      ListView.createSortField('placed_at', __('Order Date'), 'numeric'),
    ];
  }

  function getMenuActions() {
    return [
      {
        name: __('Duplicate'),
        actionName: 'duplicate',
        title: __('Duplicate Order'),
        actionFn: duplicateOrder,
        isDisabled: false,
      },
      {
        name: __('Remove'),
        actionName: 'remove',
        title: __('Remove Order'),
        actionFn: removeOrder,
        isDisabled: false,
      },
    ];
  }

  function expandRow(item) {
    if (!item.disableRowExpansion) {
      item.isExpanded = !item.isExpanded;
    }
  }

  function sortChange(sortId, direction) {
    OrdersState.setSort(sortId, direction);
    resolveOrders(vm.limit, 0);
  }

  function orderFilterChange(filters) {
    vm.ordersList = ListView.applyFilters(filters, vm.ordersList, vm.orders, OrdersState, orderMatchesFilter);
    resolveOrders(vm.limit, 0);
  }

  function orderMatchesFilter(item, filter) {
    if (filter.id === 'name') {
      return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'id') {
      return String(item.id).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'placed_at') {
      return $filter('date')(item.placed_at || item.updated_at).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    }

    return false;
  }

  function selectionChange(item) {
    if (angular.isDefined(item.service_requests)) {
      // if any child requests are unchecked, check them otherwise uncheck all
      if (item.service_requests.length === lodash.filter(item.service_requests, returnSelected).length) {
        item.service_requests.forEach((request) => {
          request.selected = false;
        });
      } else {
        item.service_requests.forEach((request) => {
          request.selected = true;
        });
      }
      vm.selectedItemsList = item.service_requests.filter(function(item) {
        return item.selected;
      });
    }
    vm.selectedItemsListCount = vm.selectedItemsList.length;
  }

  function extendedSelectionChange(item) {
    const parent = lodash.find(vm.ordersList, findItem);

    if (parent.service_requests.length === lodash.filter(parent.service_requests, returnSelected).length) {
      parent.selected = !parent.selected;
    } else {
      parent.selected = false;
    }

    lodash.indexOf(vm.selectedItemsList, item) === -1 ? vm.selectedItemsList.push(item) : lodash.pull(vm.selectedItemsList, item);

    vm.selectedItemsListCount = vm.selectedItemsList.length;

    function findItem(order) {
      return lodash.find(order.service_requests, item);
    }
  }

  function returnSelected(item) {
    return item.selected;
  }

  function resolveOrders(limit, offset) {
    vm.loading = true;
    OrdersState.getOrders(
      limit,
      offset,
      OrdersState.getFilters(),
      OrdersState.getSort().currentField,
      OrdersState.getSort().isAscending).then(querySuccess, queryFailure);

    function querySuccess(response) {
      vm.loading = false;
      vm.orders = [];
      vm.selectedItemsList = [];
      vm.toolbarConfig.filterConfig.resultsCount = vm.filterCount;

      angular.forEach(response.resources, checkExpansion);

      function checkExpansion(item) {
        if (angular.isDefined(item.id)) {
          item.disableRowExpansion = angular.isUndefined(item.service_requests)
            || (angular.isDefined(item.service_requests) && item.service_requests.length < 1);
          vm.orders.push(item);
        }
      }

      vm.ordersList = angular.copy(vm.orders);

      getFilterCount();
    }

    function queryFailure(error) {
      vm.loading = false;
      EventNotifications.error(__('There was an error loading orders.'));
    }
  }

  function getFilterCount() {
    OrdersState.getMinimal(OrdersState.getFilters()).then(querySuccess, queryFailure);

    function querySuccess(result) {
      vm.filterCount = result.subcount;
    }

    function queryFailure(error) {
      EventNotifications.error(__('There was an error loading orders.'));
    }
  }

  function approveRequests() {
    const modalOptions = {
      component: 'processRequestsModal',
      resolve: {
        requests: function() {
          return vm.selectedItemsList;
        },
        modalType: function() {
          return lodash.find(vm.selectedItemsList, isPending) ? 'invalid' : "approve";
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function denyRequests() {
    const modalOptions = {
      component: 'processRequestsModal',
      resolve: {
        requests: function() {
          return vm.selectedItemsList;
        },
        modalType: function() {
          return lodash.find(vm.selectedItemsList, isPending) ? 'invalid' : "deny";
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function duplicateOrder(action, item) {
    CollectionsApi.post('service_orders', null, null, {action: "copy", resources: [{id: item.id}]}).then(success, failure);

    function success(response) {
      EventNotifications.success(sprintf(__('%s was duplicated, id # %d.'), item.name, response.results[0].id));
      resolveOrders(vm.limit, 0);
    }

    function failure(error) {
      EventNotifications.error(sprintf(__('There was an error duplicating %s.'), item.name));
    }
  }

  function removeOrder(action, item) {
    const modalOptions = {
      component: 'processOrderModal',
      resolve: {
        order: function() {
          return item;
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function checkApproval() {
    return lodash.reduce(lodash.map(['miq_request_approval', 'miq_request_admin'], RBAC.has));
  }

  function isPending(item) {
    return item.approval_state === 'approved' || item.approval_state === 'denied';
  }

  function selectItem(item) {
    item.selected = !item.selected;
    extendedSelectionChange(item);
  }

  function listActionDisable(config, items) {
    items.length <= 0 ? config.isDisabled = true : config.isDisabled = false;
  }

  Language.fixState(OrdersState, vm.toolbarConfig);
}
<commit_msg>added polling to the order explorer<commit_after>export const OrderExplorerComponent = {
  controller: ComponentController,
  controllerAs: 'vm',
  templateUrl: 'app/components/order-explorer/order-explorer.html',
};

/** @ngInject */
function ComponentController($filter, lodash, ListView, Language, OrdersState, EventNotifications, Session, RBAC, ModalService,
                             CollectionsApi, sprintf, Polling) {
  const vm = this;
  vm.$onInit = activate();
  vm.$onDestroy = function() {
    Polling.stop('orderListPolling');
  };

  function activate() {
    angular.extend(vm, {
      currentUser: Session.currentUser(),
      loading: false,
      orders: [],
      limit: 20,
      filterCount: 0,
      ordersList: [],
      selectedItemsList: [],
      limitOptions: [5, 10, 20, 50, 100, 200, 500, 1000],
      selectedItemsListCount: 0,
      // Functions
      resolveOrders: resolveOrders,
      listActionDisable: listActionDisable,
      // Config setup
      actionConfig: getActionConfig(),
      menuActions: getMenuActions(),
      toolbarConfig: getToolbarConfig(),
      listConfig: getListConfig(),
      expandedListConfig: getExpandedListConfig(),
      offset: 0,
      pollingInterval: 10000,
    });

    resolveOrders(vm.limit, 0);
    Polling.start('orderListPolling', pollUpdateOrderList, vm.pollingInterval);
  }

  function getActionConfig() {
    return [
      {
        title: __('Lifecycle'),
        actionName: 'lifecycle',
        name: __('Lifecycle'),
        icon: 'fa fa-recycle',
        actions: [
          {
            icon: 'fa fa-check',
            name: __('Approve'),
            actionName: 'approve',
            title: __('Approve'),
            actionFn: approveRequests,
            isDisabled: false,
          }, {
            icon: 'fa fa-ban',
            name: __('Deny'),
            actionName: 'deny',
            title: __('Deny'),
            actionFn: denyRequests,
            isDisabled: false,
          },
        ],
      },
    ];
  }

  function getListConfig() {
    return {
      showSelectBox: checkApproval(),
      useExpandingRows: true,
      selectionMatchProp: 'id',
      onClick: expandRow,
      onCheckBoxChange: selectionChange,
    };
  }
  function pollUpdateOrderList() {
    resolveOrders(vm.limit, vm.offset, true);
  }
  function getExpandedListConfig() {
    return {
      showSelectBox: checkApproval(),
      selectionMatchProp: 'id',
      onClick: selectItem,
      onCheckBoxChange: extendedSelectionChange,
    };
  }

  function getToolbarConfig() {
    const sortConfig = {
      fields: getOrderSortFields(),
      onSortChange: sortChange,
      isAscending: OrdersState.getSort().isAscending,
      currentField: OrdersState.getSort().currentField,
    };

    const filterConfig = {
      fields: getOrderFilterFields(),
      resultsCount: 0,
      appliedFilters: OrdersState.filterApplied ? OrdersState.getFilters() : [],
      onFilterChange: orderFilterChange,
    };

    return {
      sortConfig: sortConfig,
      filterConfig: filterConfig,
      actionsConfig: {
        actionsInclude: checkApproval(),
      },
    };
  }

  function getOrderFilterFields() {
    return [
      ListView.createFilterField('name', __('Name'), __('Filter by Name'), 'text'),
      ListView.createFilterField('id', __('Order ID'), __('Filter by ID'), 'text'),
      ListView.createFilterField('placed_at', __('Order Date'), __('Filter by Order Date'), 'text'),
    ];
  }

  function getOrderSortFields() {
    return [
      ListView.createSortField('name', __('Name'), 'alpha'),
      ListView.createSortField('id', __('Order ID'), 'numeric'),
      ListView.createSortField('placed_at', __('Order Date'), 'numeric'),
    ];
  }

  function getMenuActions() {
    return [
      {
        name: __('Duplicate'),
        actionName: 'duplicate',
        title: __('Duplicate Order'),
        actionFn: duplicateOrder,
        isDisabled: false,
      },
      {
        name: __('Remove'),
        actionName: 'remove',
        title: __('Remove Order'),
        actionFn: removeOrder,
        isDisabled: false,
      },
    ];
  }

  function expandRow(item) {
    if (!item.disableRowExpansion) {
      item.isExpanded = !item.isExpanded;
    }
  }

  function sortChange(sortId, direction) {
    OrdersState.setSort(sortId, direction);
    resolveOrders(vm.limit, 0);
  }

  function orderFilterChange(filters) {
    vm.ordersList = ListView.applyFilters(filters, vm.ordersList, vm.orders, OrdersState, orderMatchesFilter);
    resolveOrders(vm.limit, 0);
  }

  function orderMatchesFilter(item, filter) {
    if (filter.id === 'name') {
      return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'id') {
      return String(item.id).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'placed_at') {
      return $filter('date')(item.placed_at || item.updated_at).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    }

    return false;
  }

  function selectionChange(item) {
    if (angular.isDefined(item.service_requests)) {
      // if any child requests are unchecked, check them otherwise uncheck all
      if (item.service_requests.length === lodash.filter(item.service_requests, returnSelected).length) {
        item.service_requests.forEach((request) => {
          request.selected = false;
        });
      } else {
        item.service_requests.forEach((request) => {
          request.selected = true;
        });
      }
      vm.selectedItemsList = item.service_requests.filter(function(item) {
        return item.selected;
      });
    }
    vm.selectedItemsListCount = vm.selectedItemsList.length;
  }

  function extendedSelectionChange(item) {
    const parent = lodash.find(vm.ordersList, findItem);

    if (parent.service_requests.length === lodash.filter(parent.service_requests, returnSelected).length) {
      parent.selected = !parent.selected;
    } else {
      parent.selected = false;
    }

    lodash.indexOf(vm.selectedItemsList, item) === -1 ? vm.selectedItemsList.push(item) : lodash.pull(vm.selectedItemsList, item);

    vm.selectedItemsListCount = vm.selectedItemsList.length;

    function findItem(order) {
      return lodash.find(order.service_requests, item);
    }
  }

  function returnSelected(item) {
    return item.selected;
  }

  function resolveOrders(limit, offset, refresh) {
    if (!refresh) {
      vm.loading = true;
    }
    var existingOrders = (angular.isDefined(vm.ordersList) && refresh ? angular.copy(vm.ordersList) : []);

    vm.offset = offset;
    OrdersState.getOrders(
      limit,
      offset,
      OrdersState.getFilters(),
      OrdersState.getSort().currentField,
      OrdersState.getSort().isAscending).then(querySuccess, queryFailure);

    function querySuccess(response) {
      vm.loading = false;
      vm.orders = [];
      vm.selectedItemsList = [];
      vm.toolbarConfig.filterConfig.resultsCount = vm.filterCount;

      angular.forEach(response.resources, checkExpansion);

      function checkExpansion(item) {
        if (angular.isDefined(item.id)) {
          item.disableRowExpansion = angular.isUndefined(item.service_requests)
            || (angular.isDefined(item.service_requests) && item.service_requests.length < 1);
          var dataRow = item;
          if (refresh) {
            dataRow = refreshRow(item);
          }
          vm.orders.push(dataRow);
        }
      }

      function refreshRow(item) {
        for (var i = 0; i < existingOrders.length; i++) {
          var currentOrder = existingOrders[i];
          if (currentOrder.id === item.id) {
            item.selected = (angular.isDefined(currentOrder.selected) ? currentOrder.selected : false);
            item.isExpanded = (angular.isDefined(currentOrder.isExpanded) ? currentOrder.isExpanded : false);
            if (item.selected) {
              vm.selectedItemsList.push(item);
            }
            existingOrders.splice(i, 1);
            break;
          }
        }

        return item;
      }

      vm.ordersList = angular.copy(vm.orders);

      getFilterCount();
    }

    function queryFailure(error) {
      vm.loading = false;
      EventNotifications.error(__('There was an error loading orders.'));
    }
  }

  function getFilterCount() {
    OrdersState.getMinimal(OrdersState.getFilters()).then(querySuccess, queryFailure);

    function querySuccess(result) {
      vm.filterCount = result.subcount;
    }

    function queryFailure(error) {
      EventNotifications.error(__('There was an error loading orders.'));
    }
  }

  function approveRequests() {
    const modalOptions = {
      component: 'processRequestsModal',
      resolve: {
        requests: function() {
          return vm.selectedItemsList;
        },
        modalType: function() {
          return lodash.find(vm.selectedItemsList, isPending) ? 'invalid' : "approve";
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function denyRequests() {
    const modalOptions = {
      component: 'processRequestsModal',
      resolve: {
        requests: function() {
          return vm.selectedItemsList;
        },
        modalType: function() {
          return lodash.find(vm.selectedItemsList, isPending) ? 'invalid' : "deny";
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function duplicateOrder(action, item) {
    CollectionsApi.post('service_orders', null, null, {action: "copy", resources: [{id: item.id}]}).then(success, failure);

    function success(response) {
      EventNotifications.success(sprintf(__('%s was duplicated, id # %d.'), item.name, response.results[0].id));
      resolveOrders(vm.limit, 0);
    }

    function failure(error) {
      EventNotifications.error(sprintf(__('There was an error duplicating %s.'), item.name));
    }
  }

  function removeOrder(action, item) {
    const modalOptions = {
      component: 'processOrderModal',
      resolve: {
        order: function() {
          return item;
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function checkApproval() {
    return lodash.reduce(lodash.map(['miq_request_approval', 'miq_request_admin'], RBAC.has));
  }

  function isPending(item) {
    return item.approval_state === 'approved' || item.approval_state === 'denied';
  }

  function selectItem(item) {
    item.selected = !item.selected;
    extendedSelectionChange(item);
  }

  function listActionDisable(config, items) {
    items.length <= 0 ? config.isDisabled = true : config.isDisabled = false;
  }

  Language.fixState(OrdersState, vm.toolbarConfig);
}
<|endoftext|>


<commit_before>import React from 'react';
import { Button, Icon, Modal, Container, Segment, Menu} from 'semantic-ui-react';

const headerStyle = {
    'textAlign': 'center'
};
const modalStyle = {
    top: '15%'
};

class AttachSubdeckModal extends React.Component{
  /*Props expected:
    buttonStyle = {
      classNames : string ->additional clases for the trigger button
      iconSize:  enum {large | medium |small} -> final size for displaying the icon of the button

   }*/
    constructor(props) {
        super(props);
        this.state = {
            modalOpen:false,
            activeItem:'MyDecks'
        };
        this.handleOpen = this.handleOpen.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.handleMyDecksClick = this.handleMyDecksClick.bind(this);
        this.handleSlideWikiClick = this.handleSlideWikiClick.bind(this);
    }

    handleOpen(){
        this.setState({
            modalOpen:true,
        });

    }

    handleClose(){
        this.setState({
            modalOpen:false,
        });

    }
    handleMyDecksClick(){
        this.setState({
            activeItem:'MyDecks'
        });
        console.log('ModalMyDecksClik');
    }
    handleSlideWikiClick(){
        this.setState({
            activeItem:'SlideWiki'
        });
        console.log('ModalSlideWikiClik');
    }
    render() {
        //From my Decks option content
        let myDecksContent = ;

        //From SlideWiki content
        let slideWikiContent = ;

        //Default Content
        let segmentPanelContent = {myDecksContent};

        if (this.state.activeItem === 'MyDecks'){
            segmentPanelContent = myDecksContent;

        }else{
            segmentPanelContent = slideWikiContent;
        }

        return (
          <Modal trigger={
                    <Button as="button" className={this.props.buttonStyle.classNames}
                      type="button" aria-label="Attach Slide" data-tooltip="Attach Slide"
                      basic icon open={this.state.modalOpen} onClick={this.handleOpen}>
                        <Icon.Group size={this.props.buttonStyle.iconSize}>
                            <Icon className="yellow" name="folder" />
                            <Icon className="corner" name="attach" />
                        </Icon.Group>
                    </Button>
                   }
                open={this.state.modalOpen}
                onClose={this.handleClose}
                size="large"
                role="dialog"
                aria-labelledby="attachSubdeckModal">
                <Modal.Header className="ui center aligned" as="h1" id="attachSubdeckModal">
                     Attach Deck
                </Modal.Header>
                <Modal.Content>
                  <Container>
                    <Segment color="blue" textAlign="center" padded>
                      <Menu attached='top' tabular>
                        <Menu.Item name='From My Decks' active={this.state.activeItem === 'MyDecks'} onClick={this.handleMyDecksClick} />
                        <Menu.Item name='From SlideWiki' active={this.state.activeItem === 'SlideWiki'} onClick={this.handleSlideWikiClick} />
                      </Menu>
                      <Segment attached='bottom'>
                        {segmentPanelContent}
                      </Segment>
                    </Segment>
                  </Container>
                </Modal.Content>
                <Modal.Actions>
                     <Button color="green" icon tabIndex="0" type="button" aria-label="Attach" data-tooltip="Attach">
                      <Icon name="attach"/>
                       Attach
                       <Icon name="attach"/>
                     </Button>

                    <Button color='red' tabIndex="0" type="button" aria-label="Cancel" data-tooltip="Cancel" onClick={this.handleClose} >
                      Cancel
                    </Button>
                </Modal.Actions>
           </Modal>

        );
    }

}
AttachSubdeckModal.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

export default AttachSubdeckModal;
<commit_msg>SWIK-1046-AddingSubdeck aria labels added to tabular menu<commit_after>import React from 'react';
import { Button, Icon, Modal, Container, Segment, Menu} from 'semantic-ui-react';

const headerStyle = {
    'textAlign': 'center'
};
const modalStyle = {
    top: '15%'
};

class AttachSubdeckModal extends React.Component{
  /*Props expected:
    buttonStyle = {
      classNames : string ->additional clases for the trigger button
      iconSize:  enum {large | medium |small} -> final size for displaying the icon of the button

   }*/
    constructor(props) {
        super(props);
        this.state = {
            modalOpen:false,
            activeItem:'MyDecks'
        };
        this.handleOpen = this.handleOpen.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.handleMyDecksClick = this.handleMyDecksClick.bind(this);
        this.handleSlideWikiClick = this.handleSlideWikiClick.bind(this);
    }

    handleOpen(){
        this.setState({
            modalOpen:true,
        });

    }

    handleClose(){
        this.setState({
            modalOpen:false,
        });

    }
    handleMyDecksClick(){
        this.setState({
            activeItem:'MyDecks'
        });
        console.log('ModalMyDecksClik');
    }
    handleSlideWikiClick(){
        this.setState({
            activeItem:'SlideWiki'
        });
        console.log('ModalSlideWikiClik');
    }
    render() {
        //From my Decks option content
        let myDecksContent = ;

        //From SlideWiki content
        let slideWikiContent = ;

        //Default Content
        let segmentPanelContent = {myDecksContent};

        if (this.state.activeItem === 'MyDecks'){
            segmentPanelContent = myDecksContent;

        }else{
            segmentPanelContent = slideWikiContent;
        }

        return (
          <Modal trigger={
                    <Button as="button" className={this.props.buttonStyle.classNames}
                      type="button" aria-label="Attach Slide" data-tooltip="Attach Slide"
                      basic icon open={this.state.modalOpen} onClick={this.handleOpen}>
                        <Icon.Group size={this.props.buttonStyle.iconSize}>
                            <Icon className="yellow" name="folder" />
                            <Icon className="corner" name="attach" />
                        </Icon.Group>
                    </Button>
                   }
                open={this.state.modalOpen}
                onClose={this.handleClose}
                size="large"
                role="dialog"
                aria-labelledby="attachSubdeckModal">
                <Modal.Header className="ui center aligned" as="h1" id="attachSubdeckModal">
                     Attach Deck
                </Modal.Header>
                <Modal.Content>
                  <Container>
                    <Segment color="blue" textAlign="center" padded>
                      <Menu attached='top' tabular>
                        <Menu.Item name='From My Decks' active={this.state.activeItem === 'MyDecks'} onClick={this.handleMyDecksClick} role="tab" tabIndex="0" />
                        <Menu.Item name='From SlideWiki' active={this.state.activeItem === 'SlideWiki'} onClick={this.handleSlideWikiClick} role="tab" tabIndex="0" />
                      </Menu>
                      <Segment attached='bottom'>
                        {segmentPanelContent}
                      </Segment>
                    </Segment>
                  </Container>
                </Modal.Content>
                <Modal.Actions>
                     <Button color="green" icon tabIndex="0" type="button" aria-label="Attach" data-tooltip="Attach">
                      <Icon name="attach"/>
                       Attach
                       <Icon name="attach"/>
                     </Button>

                    <Button color='red' tabIndex="0" type="button" aria-label="Cancel" data-tooltip="Cancel" onClick={this.handleClose} >
                      Cancel
                    </Button>
                </Modal.Actions>
           </Modal>

        );
    }

}
AttachSubdeckModal.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

export default AttachSubdeckModal;
<|endoftext|>


<commit_before>/*
 * bytelist.js v0.1
 *
 * Released under BSD 3-Clause License:
 * https://github.com/TinyJSDeveloper/bytelist.js/blob/master/LICENSE
 *
 * Copyright (c) 2014, TinyJSDeveloper
 * All rights reserved.
 */

function ByteMini()
{
this.value = [];

/// Tamanho da ByteArray:
this.size = function(){
	//@function_Start:
	return this.value.length;
	};

/// Converter uma String para uma Array de Char Codes:
this.intfyString = function(sentString){
	//@function_Start:
	var strArray = [];

	for(i = 0; i < sentString.length; i += 1){
		//@for_Start:
		strArray[i] = sentString.charCodeAt(i);
		}

	return strArray;
	};

/// Zerar a ByteArray:
this.clear = function(clearMode,startPos,howManyBytes){
	//@function_Start:
	if(howManyBytes < 1 || howManyBytes == null){
		//@if_Start:
		howManyBytes = 1;
		}

	if(clearMode === '@range'){
		//@if_Start:
		for(i = 0; i < howManyBytes; i += 1){
			//@for_Start:
			this.value.splice(startPos+i,1);
			}
		}

	else if(clearMode === '@all'){
		//@elseif_Start:
		this.value = [];
		}
	};

/// Escrever uma série de valores na ByteArray:
this.write = function(byteArray,typeMode,startPos){
	//@function_Start:
	var Uint8Data = new Uint8Array(1);

	if(startPos < 0 || startPos == null){
		//@if_Start:
		startPos = 0;
		}

	if(typeof byteArray === 'string'){
		//if_Start:
		byteArray = this.intfyString(byteArray);
		}

	for(i = 0; i < byteArray.length; i += 1){
		//@for_Start:
		Uint8Data[0] = byteArray[i];

		if(typeMode === '@ins'){
			//@if_Start:
			this.value.splice(startPos+i,0,Uint8Data[0]);
			}
		else if(typeMode === '@ovr'){
			//@elseif_Start:
			this.value[startPos+i] = Uint8Data[0];
			}
		else if(typeMode === '@rep'){
			//@elseif_Start:
			if(i === 0){
				//@if_Start:
				this.clear('@all');
				}

			this.value[i] = Uint8Data[0];
			}
		}
	};

/// Operações matemáticas:
this.math = function(sentValue,mathSymbol,startPos,howManyBytes){
	//@function_Start:
	var numArray = [];
	var numString;

	if(startPos < 0 || startPos == null){
		//@if_Start:
		startPos = 0;
		}

	if(howManyBytes < 1 || howManyBytes == null){
		//@if_Start:
		howManyBytes = 1;
		}

	for(i = 0; i < howManyBytes; i += 1){
		//@for_Start:
		numArray[i] = this.value[startPos+i];
		numArray[i] = numArray[i].toString(16);

		if(numArray[i].length % 2 === 1){
			//if_Start:
			numArray[i] = '0' + numArray[i];
			}
		}

	numString = numArray.join('');
	numString = parseInt(numString,16);

	if(mathSymbol === '@+'){
		//@if_Start:
		numString = numString + sentValue;
		}
	else if(mathSymbol === '@-'){
		//@elseif_Start:
		numString = numString - sentValue;
		}
	else if(mathSymbol === '@*'){
		//@elseif_Start:
		numString = numString * sentValue;
		}
	else if(mathSymbol === '@/'){
		//@elseif_Start:
		numString = numString / sentValue;
		}

	numString = numString.toString(16);
	for(i = numString.length; i < numArray.length*2; i += 1){
		//@for_Start:
		numString = '0' + numString;
		}

	for(i = 0; i < numArray.length; i += 1){
		//@for_Start:
		numArray[i] = numString[i*2] + numString[i*2+1];
		numArray[i] = parseInt(numArray[i],16);
		}

	this.write(numArray,'@ovr',startPos);
	};
}
<commit_msg>Global utility and ByteArray() constructor added!<commit_after>/*
 * bytelist.js v0.2
 *
 * Released under BSD 3-Clause License:
 * https://github.com/TinyJSDeveloper/bytelist.js/blob/master/LICENSE
 *
 * Copyright (c) 2014, TinyJSDeveloper
 * All rights reserved.
 */

function ByteList()
{
this.value = [];

/// Tamanho da ByteArray:
this.size = function(){
	//@function_Start:
	return this.value.length;
	};

/// Converter uma String para uma Array de Char Codes:
this.intfyString = function(sentString){
	//@function_Start:
	var strArray = [];

	for(i = 0; i < sentString.length; i += 1){
		//@for_Start:
		strArray[i] = sentString.charCodeAt(i);
		}

	return strArray;
	};

/// Zerar a ByteArray:
this.clear = function(clearMode,startPos,howManyBytes){
	//@function_Start:
	if(howManyBytes < 1 || howManyBytes == null){
		//@if_Start:
		howManyBytes = 1;
		}

	if(clearMode === '@range'){
		//@if_Start:
		for(i = 0; i < howManyBytes; i += 1){
			//@for_Start:
			this.value.splice(startPos+i,1);
			}
		}

	else if(clearMode === '@all'){
		//@elseif_Start:
		this.value = [];
		}
	};

/// Escrever uma série de valores na ByteArray:
this.write = function(byteArray,typeMode,startPos){
	//@function_Start:
	var Uint8Data = new Uint8Array(1);

	if(startPos < 0 || startPos == null){
		//@if_Start:
		startPos = 0;
		}

	if(typeof byteArray === 'string'){
		//if_Start:
		byteArray = this.intfyString(byteArray);
		}

	for(i = 0; i < byteArray.length; i += 1){
		//@for_Start:
		Uint8Data[0] = byteArray[i];

		if(typeMode === '@ins'){
			//@if_Start:
			this.value.splice(startPos+i,0,Uint8Data[0]);
			}
		else if(typeMode === '@ovr'){
			//@elseif_Start:
			this.value[startPos+i] = Uint8Data[0];
			}
		else if(typeMode === '@rep'){
			//@elseif_Start:
			if(i === 0){
				//@if_Start:
				this.clear('@all');
				}

			this.value[i] = Uint8Data[0];
			}
		}
	};

/// Operações matemáticas:
this.math = function(sentValue,mathSymbol,startPos,howManyBytes){
	//@function_Start:
	var numArray = [];
	var numString;

	if(startPos < 0 || startPos == null){
		//@if_Start:
		startPos = 0;
		}

	if(howManyBytes < 1 || howManyBytes == null){
		//@if_Start:
		howManyBytes = 1;
		}

	for(i = 0; i < howManyBytes; i += 1){
		//@for_Start:
		numArray[i] = this.value[startPos+i];
		numArray[i] = numArray[i].toString(16);

		if(numArray[i].length % 2 === 1){
			//if_Start:
			numArray[i] = '0' + numArray[i];
			}
		}

	numString = numArray.join('');
	numString = parseInt(numString,16);

	if(mathSymbol === '@+'){
		//@if_Start:
		numString = numString + sentValue;
		}
	else if(mathSymbol === '@-'){
		//@elseif_Start:
		numString = numString - sentValue;
		}
	else if(mathSymbol === '@*'){
		//@elseif_Start:
		numString = numString * sentValue;
		}
	else if(mathSymbol === '@/'){
		//@elseif_Start:
		numString = numString / sentValue;
		}

	numString = numString.toString(16);
	for(i = numString.length; i < numArray.length*2; i += 1){
		//@for_Start:
		numString = '0' + numString;
		}

	for(i = 0; i < numArray.length; i += 1){
		//@for_Start:
		numArray[i] = numString[i*2] + numString[i*2+1];
		numArray[i] = parseInt(numArray[i],16);
		}

	this.write(numArray,'@ovr',startPos);
	};
}
var $byte = new ByteList();

function ByteArray(arrayType,arraySize)
{
if(arrayType === '@static'){
	//@if_Start:
	arrayType = false;
	}
else if(arrayType === '@dynamic'){
	//@elseif_Start:
	arrayType = true;
	}

if(arraySize < 0 || arraySize == null){
	//@if_Start:
	arraySize = 0;
	}

this.value = new Uint8Array(arraySize);
this.isDynamic = arrayType;

/// Tamanho da ByteArray:
this.size = function(){
	//@function_Start:
	return this.value.length;
	};

/// Obter valor em formato não-Uint8:
this.nonByteValue = function(){
	//@function_Start:
	var pureArray = [];

	for(i = 0; i < this.size(); i += 1){
		//@for_Start:
		pureArray[i] = this.value[i];
		};

	return pureArray;
	};

/// Importar uma Array não-Uint8 para a ByteArray:
this.import = function(sentArray){
	//@function_Start:
	if(this.isDynamic === true){
		//@if_Start:
		this.value = new Uint8Array(sentArray.length);
		}

	for(i = 0; i < this.size(); i += 1){
			//@for_Start:
			this.value[i] = sentArray[i];
			}
	};

/// Escrever conteúdo na ByteArray:
this.write = function(byteArray,typeMode,startPos){
	//@function_Start:
	$byte.value = this.nonByteValue();
	$byte.write(byteArray,typeMode,startPos);
	this.import($byte.value);
	};

/// Limpar a ByteArray:
this.clear = function(clearMode,startPos,howManyBytes){
	//@function_Start:
	$byte.value = this.nonByteValue();
	$byte.clear(clearMode,startPos,howManyBytes);
	this.import($byte.value);
	};

/// Operações matemáticas:
this.math = function(sentValue,mathSymbol,startPos,howManyBytes){
	//@function_Start:
	$byte.value = this.nonByteValue();
	$byte.math(sentValue,mathSymbol,startPos,howManyBytes);
	this.import($byte.value);
	};
}
<|endoftext|>


<commit_before>var _ = require("underscore");
var Backbone = require("backbone");
var Models = require("./models");
var Views = require("./views");
var WorkspaceManager = require("./utils/workspace_manager");

//var saveDispatcher = _.clone(Backbone.Events);
var URL_CHAR_LIMIT = 7;

var ChannelEditRouter  = Backbone.Router.extend({
  nodeCollection: new Models.ContentNodeCollection(),
  initialize: function(options) {
    _.bindAll(this, "navigate_channel_home", "preview_page", "edit_page", "clipboard_page", "admin_page");
		this.nodeCollection = new Models.ContentNodeCollection();
		window.current_channel = window.channel && new Models.ChannelModel(window.channel);
		window.current_user = new Models.UserModel(window.user);
		window.workspace_manager = new WorkspaceManager();
		//this.listenTo(saveDispatcher, "save", this.save);
		this.channelCollection = new Models.ChannelCollection();
		this.fileformats = new Models.FileFormatCollection(window.fformats);
		this.formatpresets = new Models.FormatPresetCollection(window.presets);
		this.contentkinds = new Models.ContentKindCollection(window.kinds);
		this.languages = new Models.LanguageCollection(window.langs);
	},

  routes: {
		"": "navigate_channel_home",
		"administration/": "admin_page",
		":channel/edit(/:topic)(/:node)": "edit_page",
		":channel/staging(/:topic)(/:node)": "staging_page",
		":channel/view(/:topic)(/:node)": "preview_page",
		":channel/clipboard(/:topic)(/:node)": "clipboard_page"
  },

	navigate_channel_home: function() {
		window.languages = this.languages;
		var ChannelManageView = require("edit_channel/new_channel/views");
		var channel_manager_view = new ChannelManageView.ChannelListPage ({
			el: $("#channel-container"),
			collection: this.channelCollection
		});
	},

	admin_page: function(){
		var AdministrationView = require("edit_channel/admin/views");
		var admin_view = new AdministrationView.AdminView ({
			el: $("#admin-container")
		});
	},

	edit_page : function(channel, topic, node){
		var data = { "edit_mode_on" : true, "topic": topic, "node": node, "page": "edit" };
		this.open_channel(data, window.current_channel.get_root("main_tree"));
	},
	staging_page: function(channel, topic, node){
		var data = { "edit_mode_on" : true, "is_staging" : true, "topic": topic, "node": node, "page": "staging"  };
		this.open_channel(data, window.current_channel.get_root("staging_tree"));
	},
	preview_page : function(channel, topic, node){
		var data = {"topic": topic, "node": node, "page": "view"};
		this.open_channel(data, window.current_channel.get_root("main_tree"));
	},
	clipboard_page:function(channel, topic, node){
		var data = { "edit_mode_on" : true, "is_clipboard" : true, "topic": topic, "node": node, "page": "clipboard" };
		this.open_channel(true, true, false, window.current_user.get_clipboard());
	},
	open_channel: function(data, root){
		window.staging = data.is_staging || false;
		window.fileformats = this.fileformats ;
		window.channels = this.channelCollection;
		window.formatpresets = this.formatpresets;
		window.languages = this.languages;
		window.contentkinds = this.contentkinds;
		window.contenttags = new Models.TagCollection(window.current_channel.get('tags'));
		window.licenses = new Models.LicenseCollection(window.license_list);

		data.topic = data.topic || window.current_channel.get((data.is_staging)? "staging_tree" : "main_tree").node_id;
		window.current_page = data.page;
		this.update_url(data.topic, data.node, window.title);

		var EditViews = require("edit_channel/tree_edit/views");
		var edit_page_view = new EditViews.TreeEditView({
			el: $("#main-content-area"),
			collection: this.nodeCollection,
			edit: data.edit_mode_on && !window.current_channel.get('ricecooker_version'),
			model : root,
			path: data,
			is_clipboard : data.is_clipboard || false,
			staging: window.staging
		});
		if(!window.is_staging){
			var QueueView = require("edit_channel/queue/views");
			var queue = new QueueView.Queue({
		 		el: $("#queue-area"),
		 		collection: this.nodeCollection,
		 		clipboard_root : window.current_user.get_clipboard(),
				trash_root : window.current_channel.get_root("trash_tree"),
		 	});
		}
	},
	update_url: function(topic, node, replacement){
		window.topic = topic || window.topic;
		window.node = node;
		var urlString = window.current_channel.id + "/" + window.current_page;
		urlString += (window.topic)? "/" + window.topic.substring(0, URL_CHAR_LIMIT) : "";
		urlString += (window.node) ? "/" + window.node.substring(0, URL_CHAR_LIMIT) : "";
		if(replacement) {
			document.title = replacement;
		}
		this.navigate(urlString, {replace: !replacement});
	}
});

module.exports = ChannelEditRouter;
<commit_msg>Fix back button navigation<commit_after>var _ = require("underscore");
var Backbone = require("backbone");
var Models = require("./models");
var Views = require("./views");
var WorkspaceManager = require("./utils/workspace_manager");

//var saveDispatcher = _.clone(Backbone.Events);
var URL_CHAR_LIMIT = 7;

var ChannelEditRouter  = Backbone.Router.extend({
  nodeCollection: new Models.ContentNodeCollection(),
  initialize: function(options) {
    _.bindAll(this, "navigate_channel_home", "preview_page", "edit_page", "clipboard_page", "admin_page");
		this.nodeCollection = new Models.ContentNodeCollection();
		window.current_channel = window.channel && new Models.ChannelModel(window.channel);
		window.current_user = new Models.UserModel(window.user);
		window.workspace_manager = new WorkspaceManager();
		//this.listenTo(saveDispatcher, "save", this.save);
		this.channelCollection = new Models.ChannelCollection();
		this.fileformats = new Models.FileFormatCollection(window.fformats);
		this.formatpresets = new Models.FormatPresetCollection(window.presets);
		this.contentkinds = new Models.ContentKindCollection(window.kinds);
		this.languages = new Models.LanguageCollection(window.langs);
	},

  routes: {
		"": "navigate_channel_home",
		"administration/": "admin_page",
		":channel/edit(/:topic)(/:node)": "edit_page",
		":channel/staging(/:topic)(/:node)": "staging_page",
		":channel/view(/:topic)(/:node)": "preview_page",
		":channel/clipboard(/:topic)(/:node)": "clipboard_page"
  },

	navigate_channel_home: function() {
		window.languages = this.languages;
		var ChannelManageView = require("edit_channel/new_channel/views");
		var channel_manager_view = new ChannelManageView.ChannelListPage ({
			el: $("#channel-container"),
			collection: this.channelCollection
		});
	},

	admin_page: function(){
		var AdministrationView = require("edit_channel/admin/views");
		var admin_view = new AdministrationView.AdminView ({
			el: $("#admin-container")
		});
	},

	edit_page : function(channel, topic, node){
		var data = { "edit_mode_on" : true, "topic": topic, "node": node, "page": "edit" };
		this.open_channel(data, window.current_channel.get_root("main_tree"));
	},
	staging_page: function(channel, topic, node){
		var data = { "edit_mode_on" : true, "is_staging" : true, "topic": topic, "node": node, "page": "staging"  };
		this.open_channel(data, window.current_channel.get_root("staging_tree"));
	},
	preview_page : function(channel, topic, node){
		var data = {"topic": topic, "node": node, "page": "view"};
		this.open_channel(data, window.current_channel.get_root("main_tree"));
	},
	clipboard_page:function(channel, topic, node){
		var data = { "edit_mode_on" : true, "is_clipboard" : true, "topic": topic, "node": node, "page": "clipboard" };
		this.open_channel(true, true, false, window.current_user.get_clipboard());
	},
	open_channel: function(data, root){
		window.staging = data.is_staging || false;
		window.fileformats = this.fileformats ;
		window.channels = this.channelCollection;
		window.formatpresets = this.formatpresets;
		window.languages = this.languages;
		window.contentkinds = this.contentkinds;
		window.contenttags = new Models.TagCollection(window.current_channel.get('tags'));
		window.licenses = new Models.LicenseCollection(window.license_list);

		data.topic = data.topic || window.current_channel.get((data.is_staging)? "staging_tree" : "main_tree").node_id;
		window.current_page = data.page;
		this.update_url(data.topic, data.node);

		var EditViews = require("edit_channel/tree_edit/views");
		var edit_page_view = new EditViews.TreeEditView({
			el: $("#main-content-area"),
			collection: this.nodeCollection,
			edit: data.edit_mode_on && !window.current_channel.get('ricecooker_version'),
			model : root,
			path: data,
			is_clipboard : data.is_clipboard || false,
			staging: window.staging
		});
		if(!window.is_staging){
			var QueueView = require("edit_channel/queue/views");
			var queue = new QueueView.Queue({
		 		el: $("#queue-area"),
		 		collection: this.nodeCollection,
		 		clipboard_root : window.current_user.get_clipboard(),
				trash_root : window.current_channel.get_root("trash_tree"),
		 	});
		}
	},
	update_url: function(topic, node, replacement){
		window.topic = topic || window.topic;
		window.node = node;
		var urlString = window.current_channel.id + "/" + window.current_page;
		urlString += (window.topic)? "/" + window.topic.substring(0, URL_CHAR_LIMIT) : "";
		urlString += (window.node) ? "/" + window.node.substring(0, URL_CHAR_LIMIT) : "";
		if(replacement) {
			document.title = replacement;
		}
		this.navigate(urlString, {replace: !replacement});
	}
});

module.exports = ChannelEditRouter;
<|endoftext|>


<commit_before>describe('==== ADMIN ====', () => {
  var token = ''
  var uzantoModel1 = {"uzantnomo":"unuauzanto", "pasvorto": "iupasvort"};
  var uzantoModel2   = {"uzantnomo":"duauzanto", "pasvorto": "iupasvort"};

  //Before each test we empty the database
  before((done) => {
      createAdmin();
      cleanTable('administranto');
      token = generateToken();
      done();
  });

  describe('Admin sen agordo', () => {

    describe('GET /admin/agordita', () => {
      it('sen administrantoj en la sistemo',(done) => {
        request
          .get('/admin/agordita')
          .end((err,res) => {
            res.status.should.be.equal(200);
            res.body.should.have.property('agordita', false);
            done();
          });
      });
    });

  });

  describe('Admin kun agordo', () => {
    before((done) => {
      request
        .post('/admin/ensaluti')
        .send(uzantoModel1)
        .end((err,res) => {
          res.status.should.be.equal(201);
          res.body.should.have.property('message');
          done();
        });
    });

    describe('GET /admin/agordita', () => {
      it('kun administrantoj en la sistemo', (done) => {
        request
        .get('/admin/agordita')
        .end((err,res) => {
          res.status.should.be.equal(200);
          res.body.should.have.property('agordita', true);
          done();
        });
      });
    });

  });

});
<commit_msg>Aldonita unit test al admin<commit_after>/*
  INCOMPLETE
*/
describe('==== ADMIN ====', () => {
  var token = ''
  var uzantoModel1 = {"uzantnomo":"unuauzanto", "pasvorto": "iupasvort"};
  var uzantoModel2   = {"uzantnomo":"duauzanto", "pasvorto": "iupasvort"};

  //Before each test we empty the database
  before((done) => {
      createAdmin();
      cleanTable('administranto');
      token = generateToken();
      done();
  });

  describe('Admin sen agordo', () => {

    describe('GET /admin/agordita', () => {
      it('sen administrantoj en la sistemo',(done) => {
        request
          .get('/admin/agordita')
          .end((err,res) => {
            res.status.should.be.equal(200);
            res.body.should.have.property('agordita', false);
            done();
          });
      });
    });

  });

  describe('Admin kun agordo', () => {
    before((done) => {
      request
        .post('/admin/ensaluti')
        .send(uzantoModel1)
        .end((err,res) => {
          res.status.should.be.equal(201);
          res.body.should.have.property('message');
          done();
        });
    });

    describe('GET /admin/agordita', () => {
      it('kun administrantoj en la sistemo', (done) => {
        request
        .get('/admin/agordita')
        .end((err,res) => {
          res.status.should.be.equal(200);
          res.body.should.have.property('agordita', true);
          done();
        });
      });
    });

  });

});
<|endoftext|>


<commit_before>// Import AVA
import test from 'ava'

// Imports
import sleep from '../../src/util/sleep'

/**
 * Sleep 10 milliseconds.
 */
test('sleep 10 milliseconds', async t => {
  await t.notThrows(async () => {
    await sleep(10)
  })
})

/**
 * Sleep default time.
 */
test('sleep default time', async t => {
  await t.notThrows(async () => {
    await sleep()
  })
})

/**
 * Time must be number.
 */
test('time must be number', async t => {
  const prom = sleep('test')
  await t.throws(prom)
})

/**
 * Time must be integer.
 */
test('time must be integer', async t => {
  const prom = sleep(7.4)
  await t.throws(prom)
})
<commit_msg>Correct successful sleep tests<commit_after>// Import AVA
import test from 'ava'

// Imports
import sleep from '../../src/util/sleep'

/**
 * Sleep 10 milliseconds.
 */
test('sleep 10 milliseconds', async t => {
  const prom = sleep(10)
  await t.notThrows(prom)
})

/**
 * Sleep default time.
 */
test('sleep default time', async t => {
  const prom = sleep()
  await t.notThrows(prom)
})

/**
 * Time must be number.
 */
test('time must be number', async t => {
  const prom = sleep('test')
  await t.throws(prom)
})

/**
 * Time must be integer.
 */
test('time must be integer', async t => {
  const prom = sleep(7.4)
  await t.throws(prom)
})
<|endoftext|>