<commit_before>'use strict'

// external deps
var ObjectId = require("mongodb").ObjectId;
var UomManager = require('./uom-manager');
var BaseManager = require('module-toolkit').BaseManager;
var i18n = require('dl-i18n');

// internal deps
require('mongodb-toolkit');
var DLModels = require('dl-models');
var map = DLModels.map;
var Product = DLModels.master.Product;
var UomManager = require('./uom-manager');
var CurrencyManager = require('./currency-manager');

module.exports = class ProductManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.master.collection.Product);
        this.uomManager = new UomManager(db, user);
        this.currencyManager = new CurrencyManager(db, user);
    }

    _getQuery(paging) {
        var deleted = {
            _deleted: false
        };
        var query = paging.keyword ? {
            '$and': [deleted]
        } : deleted;

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var filterCode = {
                'code': {
                    '$regex': regex
                }
            };
            var filterName = {
                'name': {
                    '$regex': regex
                }
            };
            var $or = {
                '$or': [filterCode, filterName]
            };

            query['$and'].push($or);
        }

        return query;
    }

    _validate(product) {
        var errors = {};
        var valid = product;

        // 1. begin: Declare promises.
        var getProductPromise = this.collection.singleOrDefault({
            _id: {
                '$ne': new ObjectId(valid._id)
            },
            code: valid.code
        });

        var getUom = valid.uom && ObjectId.isValid(valid.uom._id) ? this.uomManager.getSingleByIdOrDefault(valid.uom._id) : Promise.resolve(null);
        // 2. begin: Validation.
        return Promise.all([getProductPromise, getUom])
            .then((results) => {
                var _module = results[0];
                var _uom = results[1];

                if (!valid.code || valid.code == '')
                    errors["code"] = i18n.__("Product.code.isRequired:%s is required", i18n.__("Product.code._:Code")); // "Kode tidak boleh kosong.";
                else if (_module) {
                    errors["code"] = i18n.__("Product.code.isExists:%s is already exists", i18n.__("Product.code._:Code")); // "Kode sudah terdaftar.";
                }

                if (!valid.name || valid.name == '')
                    errors["name"] = i18n.__("Product.name.isRequired:%s is required", i18n.__("Product.name._:Name")); // "Nama tidak boleh kosong.";

                if (!valid.uom) {
                    errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                if (valid.uom) {
                    if (!valid.uom.unit || valid.uom.unit == '')
                        errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                else if (_uom){
                    errors["uom"] = i18n.__("Product.uom.noExists:%s is not exists", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }

                // 2c. begin: check if data has any error, reject if it has.
                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require('module-toolkit').ValidationError;
                    return Promise.reject(new ValidationError('Product Manager : data does not pass validation' + JSON.stringify(errors), errors));
                }

                valid.uom = _uom;
                valid.price = parseInt(valid.price);
                valid.currency.rate = parseInt(valid.currency.rate);
                valid.uomId = new ObjectId(valid.uom._id);
                if (!valid.stamp)
                    valid = new Product(valid);
                valid.stamp(this.user.username, 'manager');
                return Promise.resolve(valid);
            });
    }

    getProduct() {
        return new Promise((resolve, reject) => {
            var query = {
                _deleted: false
            };
            this.collection
                .where(query)
                .execute()
                .then(products => {
                    resolve(products);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    insert(dataFile) {
        return new Promise((resolve, reject) => {
            var product, uom, currency;
            this.getProduct()
                .then(results => {
                    this.uomManager.getUOM()
                        .then(uoms => {
                            this.currencyManager.getCurrency()
                                .then(currencies => {
                                    product = results.data;
                                    uom = uoms.data;
                                    currency = currencies.data;
                                    var data = [];
                                    if (dataFile != "") {
                                        for (var i = 1; i < dataFile.length; i++) {
                                            data.push({ "code": dataFile[i][0], "name": dataFile[i][1], "uom": dataFile[i][2], "currency": dataFile[i][3], "price": dataFile[i][4], "tags":dataFile[i][5], "description": dataFile[i][6] });
                                        }
                                    }
                                    var dataError = [], errorMessage;
                                    for (var i = 0; i < data.length; i++) {
                                        errorMessage = "";
                                        if (data[i]["code"] === "" || data[i]["code"] === undefined) {
                                            errorMessage = errorMessage + "Kode tidak boleh kosong, ";
                                        }
                                        if (data[i]["name"] === "" || data[i]["name"] === undefined) {
                                            errorMessage = errorMessage + "Nama tidak boleh kosong, ";
                                        }
                                        if (data[i]["uom"] === "" || data[i]["uom"] === undefined) {
                                            errorMessage = errorMessage + "Satuan tidak boleh kosong, ";
                                        }
                                        if (data[i]["currency"] === "" || data[i]["currency"] === undefined) {
                                            errorMessage = errorMessage + "Mata Uang tidak boleh kosong, ";
                                        }
                                        if (data[i]["price"] === "" || data[i]["price"] === undefined) {
                                            errorMessage = errorMessage + "Harga tidak boleh kosong, ";
                                        } else if (isNaN(data[i]["price"])) {
                                            errorMessage = errorMessage + "Harga harus numerik, ";
                                        }
                                        else {
                                            var rateTemp = (data[i]["price"]).toString().split(".");
                                            if (rateTemp[1] === undefined) {
                                            } else if (rateTemp[1].length > 2) {
                                                errorMessage = errorMessage + "Harga maksimal memiliki 2 digit dibelakang koma, ";
                                            }
                                        }
                                        for (var j = 0; j < product.length; j++) {
                                            if (product[j]["code"] === data[i]["code"]) {
                                                errorMessage = errorMessage + "Kode tidak boleh duplikat, ";
                                            }
                                            if (product[j]["name"] === data[i]["name"]) {
                                                errorMessage = errorMessage + "Nama tidak boleh duplikat, ";
                                            }
                                        }
                                        var flagUom = false;
                                        for (var j = 0; j < uom.length; j++) {
                                            if (uom[j]["unit"] === data[i]["uom"]) {
                                                flagUom = true;
                                                break;
                                            }
                                        }
                                        if (flagUom === false) {
                                            errorMessage = errorMessage + "Satuan tidak terdaftar di Master Satuan, ";
                                        }
                                        var flagCurrency = false;
                                        for (var j = 0; j < currency.length; j++) {
                                            if (currency[j]["code"] !== data[i]["currency"]) {
                                                flagCurrency = true;
                                                break;
                                            }
                                        }
                                        if (flagCurrency === false) {
                                            errorMessage = errorMessage + "Mata Uang tidak terdaftar di Master Mata Uang";
                                        }

                                        if (errorMessage !== "") {
                                            dataError.push({ "code": data[i]["code"], "name": data[i]["name"], "uom": data[i]["uom"], "currency": data[i]["currency"], "price": data[i]["price"], "tags":data[i]["tags"], "description": data[i]["description"], "Error": errorMessage });
                                        }
                                    }
                                    if (dataError.length === 0) {
                                        var newProduct = [];
                                        for (var i = 0; i < data.length; i++) {
                                            var valid = new Product(data[i]);
                                            for (var c = 0; c < currency.length; c++) {
                                                for (var j = 0; j < uom.length; j++) {
                                                    if (data[i]["uom"] == uom[j]["unit"] && data[i]["currency"] == currency[c]["code"]) {
                                                        valid.currency = currency[c];
                                                        valid.currency.rate = parseInt(valid.currency.rate);
                                                        valid.price = parseInt(valid.price);
                                                        valid.uomId = new ObjectId(uom[j]["_id"]);
                                                        valid.uom = uom[j];
                                                        valid.stamp(this.user.username, 'manager');
                                                        this.collection.insert(valid)
                                                            .then(id => {
                                                                this.getSingleById(id)
                                                                    .then(resultItem => {
                                                                        newProduct.push(resultItem)
                                                                        resolve(newProduct);
                                                                    })
                                                                    .catch(e => {
                                                                        reject(e);
                                                                    });
                                                            })
                                                            .catch(e => {
                                                                reject(e);
                                                            });
                                                        break;
                                                    }

                                                }
                                            }
                                        }
                                    } else {
                                        resolve(dataError);
                                    }
                                })
                        })
                })
        })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.master.collection.Product}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var codeIndex = {
            name: `ix_${map.master.collection.Product}_code`,
            key: {
                code: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, codeIndex]);
    }
};
<commit_msg>adding method getMaterial to Product Master for<commit_after>'use strict'

// external deps
var ObjectId = require("mongodb").ObjectId;
var UomManager = require('./uom-manager');
var BaseManager = require('module-toolkit').BaseManager;
var i18n = require('dl-i18n');
var assert = require('assert');

// internal deps
require('mongodb-toolkit');
var DLModels = require('dl-models');
var map = DLModels.map;
var Product = DLModels.master.Product;
var UomManager = require('./uom-manager');
var CurrencyManager = require('./currency-manager');

module.exports = class ProductManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.master.collection.Product);
        this.uomManager = new UomManager(db, user);
        this.currencyManager = new CurrencyManager(db, user);
    }

    _getQuery(paging) {
        var deleted = {
            _deleted: false
        };
        var query = paging.keyword ? {
            '$and': [deleted]
        } : deleted;

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var filterCode = {
                'code': {
                    '$regex': regex
                }
            };
            var filterName = {
                'name': {
                    '$regex': regex
                }
            };
            var $or = {
                '$or': [filterCode, filterName]
            };

            query['$and'].push($or);
        }

        return query;
    }

    _validate(product) {
        var errors = {};
        var valid = product;

        // 1. begin: Declare promises.
        var getProductPromise = this.collection.singleOrDefault({
            _id: {
                '$ne': new ObjectId(valid._id)
            },
            code: valid.code
        });

        var getUom = valid.uom && ObjectId.isValid(valid.uom._id) ? this.uomManager.getSingleByIdOrDefault(valid.uom._id) : Promise.resolve(null);
        // 2. begin: Validation.
        return Promise.all([getProductPromise, getUom])
            .then((results) => {
                var _module = results[0];
                var _uom = results[1];

                if (!valid.code || valid.code == '')
                    errors["code"] = i18n.__("Product.code.isRequired:%s is required", i18n.__("Product.code._:Code")); // "Kode tidak boleh kosong.";
                else if (_module) {
                    errors["code"] = i18n.__("Product.code.isExists:%s is already exists", i18n.__("Product.code._:Code")); // "Kode sudah terdaftar.";
                }

                if (!valid.name || valid.name == '')
                    errors["name"] = i18n.__("Product.name.isRequired:%s is required", i18n.__("Product.name._:Name")); // "Nama tidak boleh kosong.";

                if (!valid.uom) {
                    errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                if (valid.uom) {
                    if (!valid.uom.unit || valid.uom.unit == '')
                        errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                else if (_uom){
                    errors["uom"] = i18n.__("Product.uom.noExists:%s is not exists", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }

                // 2c. begin: check if data has any error, reject if it has.
                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require('module-toolkit').ValidationError;
                    return Promise.reject(new ValidationError('Product Manager : data does not pass validation' + JSON.stringify(errors), errors));
                }

                valid.uom = _uom;
                valid.price = parseInt(valid.price);
                valid.currency.rate = parseInt(valid.currency.rate);
                valid.uomId = new ObjectId(valid.uom._id);
                if (!valid.stamp)
                    valid = new Product(valid);
                valid.stamp(this.user.username, 'manager');
                return Promise.resolve(valid);
            });
    }

    getProduct() {
        return new Promise((resolve, reject) => {
            var query = {
                _deleted: false
            };
            this.collection
                .where(query)
                .execute()
                .then(products => {
                    resolve(products);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    insert(dataFile) {
        return new Promise((resolve, reject) => {
            var product, uom, currency;
            this.getProduct()
                .then(results => {
                    this.uomManager.getUOM()
                        .then(uoms => {
                            this.currencyManager.getCurrency()
                                .then(currencies => {
                                    product = results.data;
                                    uom = uoms.data;
                                    currency = currencies.data;
                                    var data = [];
                                    if (dataFile != "") {
                                        for (var i = 1; i < dataFile.length; i++) {
                                            data.push({ "code": dataFile[i][0], "name": dataFile[i][1], "uom": dataFile[i][2], "currency": dataFile[i][3], "price": dataFile[i][4], "tags":dataFile[i][5], "description": dataFile[i][6] });
                                        }
                                    }
                                    var dataError = [], errorMessage;
                                    for (var i = 0; i < data.length; i++) {
                                        errorMessage = "";
                                        if (data[i]["code"] === "" || data[i]["code"] === undefined) {
                                            errorMessage = errorMessage + "Kode tidak boleh kosong, ";
                                        }
                                        if (data[i]["name"] === "" || data[i]["name"] === undefined) {
                                            errorMessage = errorMessage + "Nama tidak boleh kosong, ";
                                        }
                                        if (data[i]["uom"] === "" || data[i]["uom"] === undefined) {
                                            errorMessage = errorMessage + "Satuan tidak boleh kosong, ";
                                        }
                                        if (data[i]["currency"] === "" || data[i]["currency"] === undefined) {
                                            errorMessage = errorMessage + "Mata Uang tidak boleh kosong, ";
                                        }
                                        if (data[i]["price"] === "" || data[i]["price"] === undefined) {
                                            errorMessage = errorMessage + "Harga tidak boleh kosong, ";
                                        } else if (isNaN(data[i]["price"])) {
                                            errorMessage = errorMessage + "Harga harus numerik, ";
                                        }
                                        else {
                                            var rateTemp = (data[i]["price"]).toString().split(".");
                                            if (rateTemp[1] === undefined) {
                                            } else if (rateTemp[1].length > 2) {
                                                errorMessage = errorMessage + "Harga maksimal memiliki 2 digit dibelakang koma, ";
                                            }
                                        }
                                        for (var j = 0; j < product.length; j++) {
                                            if (product[j]["code"] === data[i]["code"]) {
                                                errorMessage = errorMessage + "Kode tidak boleh duplikat, ";
                                            }
                                            if (product[j]["name"] === data[i]["name"]) {
                                                errorMessage = errorMessage + "Nama tidak boleh duplikat, ";
                                            }
                                        }
                                        var flagUom = false;
                                        for (var j = 0; j < uom.length; j++) {
                                            if (uom[j]["unit"] === data[i]["uom"]) {
                                                flagUom = true;
                                                break;
                                            }
                                        }
                                        if (flagUom === false) {
                                            errorMessage = errorMessage + "Satuan tidak terdaftar di Master Satuan, ";
                                        }
                                        var flagCurrency = false;
                                        for (var j = 0; j < currency.length; j++) {
                                            if (currency[j]["code"] !== data[i]["currency"]) {
                                                flagCurrency = true;
                                                break;
                                            }
                                        }
                                        if (flagCurrency === false) {
                                            errorMessage = errorMessage + "Mata Uang tidak terdaftar di Master Mata Uang";
                                        }

                                        if (errorMessage !== "") {
                                            dataError.push({ "code": data[i]["code"], "name": data[i]["name"], "uom": data[i]["uom"], "currency": data[i]["currency"], "price": data[i]["price"], "tags":data[i]["tags"], "description": data[i]["description"], "Error": errorMessage });
                                        }
                                    }
                                    if (dataError.length === 0) {
                                        var newProduct = [];
                                        for (var i = 0; i < data.length; i++) {
                                            var valid = new Product(data[i]);
                                            for (var c = 0; c < currency.length; c++) {
                                                for (var j = 0; j < uom.length; j++) {
                                                    if (data[i]["uom"] == uom[j]["unit"] && data[i]["currency"] == currency[c]["code"]) {
                                                        valid.currency = currency[c];
                                                        valid.currency.rate = parseInt(valid.currency.rate);
                                                        valid.price = parseInt(valid.price);
                                                        valid.uomId = new ObjectId(uom[j]["_id"]);
                                                        valid.uom = uom[j];
                                                        valid.stamp(this.user.username, 'manager');
                                                        this.collection.insert(valid)
                                                            .then(id => {
                                                                this.getSingleById(id)
                                                                    .then(resultItem => {
                                                                        newProduct.push(resultItem)
                                                                        resolve(newProduct);
                                                                    })
                                                                    .catch(e => {
                                                                        reject(e);
                                                                    });
                                                            })
                                                            .catch(e => {
                                                                reject(e);
                                                            });
                                                        break;
                                                    }

                                                }
                                            }
                                        }
                                    } else {
                                        resolve(dataError);
                                    }
                                })
                        })
                })
        })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.master.collection.Product}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var codeIndex = {
            name: `ix_${map.master.collection.Product}_code`,
            key: {
                code: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, codeIndex]);
    }

    getProductByTags(key,tag){
        return new Promise((resolve, reject) => {
            var regex=new RegExp(key,"i");
            var regex2= new RegExp(tag,"i");
            this.collection.aggregate(
                    [{
                        $match: {
                            $and:[{
                                    $and:[{
                                        "tags": regex2
                                    },{
                                    "_deleted": false
                                }]
                        },{
                                "name": {
                                    "$regex": regex
                                }
                            }]
                        }
                    }]
                )
                .toArray(function(err, result) {
                    assert.equal(err, null);
                    resolve(result);
                });
            });
    }
};
<|endoftext|>


<commit_before>        "waterpulse": {
              inherit: true,
                basePower: 80
        }
    },

        "submission": {
              inherit: true,
                accuracy: 100,
                basePower: 120,
                category: "Physical",
                secondary: {
                        chance: 10,
                        volatileStatus: 'flinch'
        }
    },

        "lunardance": {
              inherit: true,
                accuracy: true,
                basePower: 0,
                isViable: true,
                boosts: {
                        spa: 1,
                        spe: 1
                },
                secondary: false,
                target: "self",
                type: "Psychic"
        }
    },

        "airslash": {
              inherit: true,
                basePower: 90,
        }
    },

        "leafguard": {
               inherit: true,
                onResidualOrder: 5,
                onResidualSubOrder: 1,
                onResidual: function(pokemon) {
                        if (pokemon.status && this.isWeather('sunnyday')) {
                                this.debug('leafguard');
                                pokemon.cureStatus();
        }
    },

        "reckless": {
              inherit: true,
                onBasePower: function(basePower, attacker, defender, move) {
                        if (move.recoil || move.hasCustomRecoil) {
                                this.debug('Reckless boost');
                                return basePower * 15/10;
        }
    },

        "telepathy": {
              inherit: true,
                onSourceFaint: function(target, source, effect) {
                        if (effect && effect.effectType === 'Move') {
                                this.boost({spa:1}, source);
        }
    },
<commit_msg>Update mechanics.js<commit_after>        "waterpulse": {
              inherit: true,
                basePower: 80
        }
    },

        "submission": {
              inherit: true,
                accuracy: 100,
                basePower: 120,
                category: "Physical",
                secondary: {
                        chance: 10,
                        volatileStatus: 'flinch'
        }
    },

        "lunardance": {
              inherit: true,
                accuracy: true,
                basePower: 0,
                isViable: true,
                boosts: {
                        spa: 1,
                        spe: 1
                },
                secondary: false,
                target: "self",
                type: "Psychic"
        }
    },

        "airslash": {
              inherit: true,
                basePower: 90,
        }
    },
  exports.BattleAbilities = {
        "leafguard": {
               inherit: true,
                onResidualOrder: 5,
                onResidualSubOrder: 1,
                onResidual: function(pokemon) {
                        if (pokemon.status && this.isWeather('sunnyday')) {
                                this.debug('leafguard');
                                pokemon.cureStatus();
        }
    },

        "reckless": {
              inherit: true,
                onBasePower: function(basePower, attacker, defender, move) {
                        if (move.recoil || move.hasCustomRecoil) {
                                this.debug('Reckless boost');
                                return basePower * 15/10;
        }
    },

        "telepathy": {
              inherit: true,
                onSourceFaint: function(target, source, effect) {
                        if (effect && effect.effectType === 'Move') {
                                this.boost({spa:1}, source);
        }
    },
<|endoftext|>


<commit_before>"use strict";

/**
 * Page revision API module
 *
 * Main tasks:
 * - keep track of titles, and provide listings for them
 * - keep track of MediaWiki revisions and their metadata
 * - translate MediaWiki revisions into timeuuid ranges for property queries
 * - detect edit conflicts
 */

var rbUtil = require('../lib/rbUtil.js');
var URI = require('swagger-router').URI;

// TODO: move to module
var fs = require('fs');
var yaml = require('js-yaml');
var spec = yaml.safeLoad(fs.readFileSync(__dirname + '/page_revisions.yaml'));

// Title Revision Service
function PRS (options) {
    this.options = options;
    this.log = options.log || function(){};
}

PRS.prototype.tableName = 'title_revisions';
PRS.prototype.tableURI = function(domain) {
    return new URI([domain,'sys','table',this.tableName,'']);
};

// Get the schema for the revision table
PRS.prototype.getTableSchema = function () {
    return {
        table: this.tableName,
        attributes: {
            // listing: /titles.rev/Barack_Obama/master/
            // @specific time: /titles.rev/Barack_Obama?ts=20140312T20:22:33.3Z
            title: 'string',
            rev: 'int',             // MediaWiki oldid
            latest_rev: 'int',      // Latest MediaWiki revision
            tid: 'timeuuid',
            // revision deletion or suppression, can be:
            // - sha1hidden, commenthidden, texthidden
            hidden: 'set<string>',
            // Revision tags. Examples:
            // - minor revision
            tags: 'set<string>',
            // Page renames. null, to:destination or from:source
            // Followed for linear history, possibly useful for branches / drafts
            renames: 'set<string>',
            nextrev_tid: 'timeuuid',// tid of next revision, or null
            latest_tid: 'timeuuid', // static, CAS synchronization point
            // revision metadata in individual attributes for ease of indexing
            user_id: 'int',         // stable for contributions etc
            user_text: 'string',
            comment: 'string'
        },
        index: [
            { attribute: 'title', type: 'hash' },
            { attribute: 'rev', type: 'range', order: 'desc' },
            { attribute: 'latest_rev', type: 'static' },
            { attribute: 'tid', type: 'range', order: 'desc' }
        ],
        secondaryIndexes: {
            by_rev: [
                { attribute: 'rev', type: 'hash' },
                { attribute: 'tid', type: 'range', order: 'desc' },
                { attribute: 'title', type: 'range', order: 'asc' },
                { attribute: 'hidden', type: 'proj' },
                { attribute: 'tags', type: 'proj' }
            ]
        }
    };
};

// /page/
PRS.prototype.listTitles = function(restbase, req, options) {
    var rp = req.params;
    var listReq = {
        uri: this.tableURI(rp.domain),
        body: {
            table: this.tableName,
            proj: ['title'],
            distinct: true
        }
    };

    return restbase.get(listReq)
    .then(function(res) {
        if (res.status === 200) {
            res.body.items = res.body.items.map(function(row) {
                return row.title;
            });
        }
        return res;
    });
};

PRS.prototype.fetchAndStoreMWRevision = function (restbase, req) {
    var self = this;
    var rp = req.params;
    // Try to resolve MW oldids to tids
    var apiReq = {
        uri: new URI([rp.domain,'sys','action','query']),
        body: {
            format: 'json',
            action: 'query',
            prop: 'revisions',
            continue: '',
            rvprop: 'ids|timestamp|user|userid|size|sha1|contentmodel|comment|tags'
        }
    };
    if (/^[0-9]+$/.test(rp.revision)) {
        apiReq.body.revids = rp.revision;
    } else {
        apiReq.body.titles = rp.title;
    }
    return restbase.post(apiReq)
    .then(function(apiRes) {
        var items = apiRes.body.items;
        if (!items.length || !items[0].revisions) {
            throw new rbUtil.HTTPError({
                status: 404,
                body: {
                    type: 'not_found#page_revisions',
                    description: 'Page or revision not found.',
                    apiResponse: apiRes
                }
            });
        }
        // the response item
        var dataResp = apiRes.body.items[0];
        // the revision info
        var apiRev = dataResp.revisions[0];
        // are there any hidden fields set?
        var hidden = Object.keys(apiRev).filter(function(key) { return /hidden$/.test(key) });
        // the tid to store this info under
        var tid = rbUtil.tidFromDate(apiRev.timestamp);
        return restbase.put({ // Save / update the revision entry
            uri: self.tableURI(rp.domain),
            body: {
                table: self.tableName,
                attributes: {
                    // FIXME: if a title has been given, check it
                    // matches the one returned by the MW API
                    // cf. https://phabricator.wikimedia.org/T87393
                    title: dataResp.title,
                    rev: parseInt(apiRev.revid),
                    tid: tid,
                    user_id: apiRev.userid,
                    user_text: apiRev.user,
                    comment: apiRev.comment,
                    tags: apiRev.tags,
                    hidden: hidden
                }
            }
        })
        .then(function() {
            rp.revision = apiRev.revid + '';
            rp.title = dataResp.title;
            return self.getTitleRevision(restbase, req);
        });
    });
};

PRS.prototype.getTitleRevision = function(restbase, req) {
    var self = this;
    var rp = req.params;
    var revisionRequest;
    if (/^[0-9]+$/.test(rp.revision)) {
        // Check the local db
        revisionRequest = restbase.get({
            uri: this.tableURI(rp.domain),
            body: {
                table: this.tableName,
                attributes: {
                    title: rp.title,
                    rev: parseInt(rp.revision)
                },
                limit: 1
            }
        })
        .catch(function(e) {
            if (e.status !== 404) {
                throw e;
            }
            return self.fetchAndStoreMWRevision(restbase, req);
        });
    } else if (rp.revision === 'latest') {
        revisionRequest = self.fetchAndStoreMWRevision(restbase, req);
    } else {
        throw new Error("Invalid revision: " + rp.revision);
    }
    return revisionRequest
    .then(function(res) {
        if (!res.headers) {
            res.headers = {};
        }
        res.headers.etag = res.body.items[0].tid;
        return res;
    });
    // TODO: handle other revision formats (tid)
};

PRS.prototype.listTitleRevisions = function(restbase, req) {
    var rp = req.params;
    return restbase.get({
        uri: this.tableURI(rp.domain),
        body: {
            table: this.tableName,
            attributes: {
                title: rp.title
            },
            proj: ['rev']
        }
    })
    .then(function(res) {
        // Flatten to an array of revisions rather than an array of objects
        res.body.items = res.body.items.map(function(row) {
            return row.rev;
        });
        return res;
    });
};

PRS.prototype.getRevision = function(restbase, req) {
    var rp = req.params;
    var self = this;
    // sanity check
    if (!/^[0-9]+$/.test(rp.revision)) {
        throw new rbUtil.HTTPError({
            status: 400,
            body: {
                type: 'invalidRevision',
                description: 'Invalid revision specified.'
            }
        });
    }
    if (req.headers && /no-cache/.test(req.headers['cache-control'])) {
        // ask the MW API directly and
        // store and return its result
        return this.fetchAndStoreMWRevision(restbase, req);
    }
    // check the storage, and, if no match is found
    // ask the MW API about the revision
    return restbase.get({
        uri: this.tableURI(rp.domain),
        body: {
            table: this.tableName,
            index: 'by_rev',
            attributes: {
                rev: parseInt(rp.revision)
            },
            limit: 1
        }
    })
    .catch(function(e) {
        if (e.status !== 404) {
            throw e;
        }
        return self.fetchAndStoreMWRevision(restbase, req);
    });
};

module.exports = function(options) {
    var prs = new PRS(options);
    // XXX: add docs
    return {
        spec: spec,
        operations: {
            listTitles: prs.listTitles.bind(prs),
            listTitleRevisions: prs.listTitleRevisions.bind(prs),
            getTitleRevision: prs.getTitleRevision.bind(prs),
            //getTitleRevisionId: prs.getTitleRevisionId.bind(prs)
            getRevision: prs.getRevision.bind(prs),
        },
        resources: [
            {
                // Revision table
                uri: '/{domain}/sys/table/' + prs.tableName,
                body: prs.getTableSchema()
            }
        ]
    };
};
<commit_msg>Rename 'hidden' to 'restrictions'<commit_after>"use strict";

/**
 * Page revision API module
 *
 * Main tasks:
 * - keep track of titles, and provide listings for them
 * - keep track of MediaWiki revisions and their metadata
 * - translate MediaWiki revisions into timeuuid ranges for property queries
 * - detect edit conflicts
 */

var rbUtil = require('../lib/rbUtil.js');
var URI = require('swagger-router').URI;

// TODO: move to module
var fs = require('fs');
var yaml = require('js-yaml');
var spec = yaml.safeLoad(fs.readFileSync(__dirname + '/page_revisions.yaml'));

// Title Revision Service
function PRS (options) {
    this.options = options;
    this.log = options.log || function(){};
}

PRS.prototype.tableName = 'title_revisions';
PRS.prototype.tableURI = function(domain) {
    return new URI([domain,'sys','table',this.tableName,'']);
};

// Get the schema for the revision table
PRS.prototype.getTableSchema = function () {
    return {
        table: this.tableName,
        attributes: {
            // listing: /titles.rev/Barack_Obama/master/
            // @specific time: /titles.rev/Barack_Obama?ts=20140312T20:22:33.3Z
            title: 'string',
            rev: 'int',             // MediaWiki oldid
            latest_rev: 'int',      // Latest MediaWiki revision
            tid: 'timeuuid',
            // revision deletion or suppression, can be:
            // - sha1hidden, commenthidden, texthidden
            restrictions: 'set<string>',
            // Revision tags. Examples:
            // - minor revision
            tags: 'set<string>',
            // Page renames. null, to:destination or from:source
            // Followed for linear history, possibly useful for branches / drafts
            renames: 'set<string>',
            nextrev_tid: 'timeuuid',// tid of next revision, or null
            latest_tid: 'timeuuid', // static, CAS synchronization point
            // revision metadata in individual attributes for ease of indexing
            user_id: 'int',         // stable for contributions etc
            user_text: 'string',
            comment: 'string'
        },
        index: [
            { attribute: 'title', type: 'hash' },
            { attribute: 'rev', type: 'range', order: 'desc' },
            { attribute: 'latest_rev', type: 'static' },
            { attribute: 'tid', type: 'range', order: 'desc' }
        ],
        secondaryIndexes: {
            by_rev: [
                { attribute: 'rev', type: 'hash' },
                { attribute: 'tid', type: 'range', order: 'desc' },
                { attribute: 'title', type: 'range', order: 'asc' },
                { attribute: 'restrictions', type: 'proj' },
                { attribute: 'tags', type: 'proj' }
            ]
        }
    };
};

// /page/
PRS.prototype.listTitles = function(restbase, req, options) {
    var rp = req.params;
    var listReq = {
        uri: this.tableURI(rp.domain),
        body: {
            table: this.tableName,
            proj: ['title'],
            distinct: true
        }
    };

    return restbase.get(listReq)
    .then(function(res) {
        if (res.status === 200) {
            res.body.items = res.body.items.map(function(row) {
                return row.title;
            });
        }
        return res;
    });
};

PRS.prototype.fetchAndStoreMWRevision = function (restbase, req) {
    var self = this;
    var rp = req.params;
    // Try to resolve MW oldids to tids
    var apiReq = {
        uri: new URI([rp.domain,'sys','action','query']),
        body: {
            format: 'json',
            action: 'query',
            prop: 'revisions',
            continue: '',
            rvprop: 'ids|timestamp|user|userid|size|sha1|contentmodel|comment|tags'
        }
    };
    if (/^[0-9]+$/.test(rp.revision)) {
        apiReq.body.revids = rp.revision;
    } else {
        apiReq.body.titles = rp.title;
    }
    return restbase.post(apiReq)
    .then(function(apiRes) {
        var items = apiRes.body.items;
        if (!items.length || !items[0].revisions) {
            throw new rbUtil.HTTPError({
                status: 404,
                body: {
                    type: 'not_found#page_revisions',
                    description: 'Page or revision not found.',
                    apiResponse: apiRes
                }
            });
        }
        // the response item
        var dataResp = apiRes.body.items[0];
        // the revision info
        var apiRev = dataResp.revisions[0];
        // are there any restrictions set?
        var restrictions = Object.keys(apiRev).filter(function(key) { return /hidden$/.test(key) });
        // the tid to store this info under
        var tid = rbUtil.tidFromDate(apiRev.timestamp);
        return restbase.put({ // Save / update the revision entry
            uri: self.tableURI(rp.domain),
            body: {
                table: self.tableName,
                attributes: {
                    // FIXME: if a title has been given, check it
                    // matches the one returned by the MW API
                    // cf. https://phabricator.wikimedia.org/T87393
                    title: dataResp.title,
                    rev: parseInt(apiRev.revid),
                    tid: tid,
                    user_id: apiRev.userid,
                    user_text: apiRev.user,
                    comment: apiRev.comment,
                    tags: apiRev.tags,
                    restrictions: restrictions
                }
            }
        })
        .then(function() {
            rp.revision = apiRev.revid + '';
            rp.title = dataResp.title;
            return self.getTitleRevision(restbase, req);
        });
    });
};

PRS.prototype.getTitleRevision = function(restbase, req) {
    var self = this;
    var rp = req.params;
    var revisionRequest;
    if (/^[0-9]+$/.test(rp.revision)) {
        // Check the local db
        revisionRequest = restbase.get({
            uri: this.tableURI(rp.domain),
            body: {
                table: this.tableName,
                attributes: {
                    title: rp.title,
                    rev: parseInt(rp.revision)
                },
                limit: 1
            }
        })
        .catch(function(e) {
            if (e.status !== 404) {
                throw e;
            }
            return self.fetchAndStoreMWRevision(restbase, req);
        });
    } else if (rp.revision === 'latest') {
        revisionRequest = self.fetchAndStoreMWRevision(restbase, req);
    } else {
        throw new Error("Invalid revision: " + rp.revision);
    }
    return revisionRequest
    .then(function(res) {
        if (!res.headers) {
            res.headers = {};
        }
        res.headers.etag = res.body.items[0].tid;
        return res;
    });
    // TODO: handle other revision formats (tid)
};

PRS.prototype.listTitleRevisions = function(restbase, req) {
    var rp = req.params;
    return restbase.get({
        uri: this.tableURI(rp.domain),
        body: {
            table: this.tableName,
            attributes: {
                title: rp.title
            },
            proj: ['rev']
        }
    })
    .then(function(res) {
        // Flatten to an array of revisions rather than an array of objects
        res.body.items = res.body.items.map(function(row) {
            return row.rev;
        });
        return res;
    });
};

PRS.prototype.getRevision = function(restbase, req) {
    var rp = req.params;
    var self = this;
    // sanity check
    if (!/^[0-9]+$/.test(rp.revision)) {
        throw new rbUtil.HTTPError({
            status: 400,
            body: {
                type: 'invalidRevision',
                description: 'Invalid revision specified.'
            }
        });
    }
    if (req.headers && /no-cache/.test(req.headers['cache-control'])) {
        // ask the MW API directly and
        // store and return its result
        return this.fetchAndStoreMWRevision(restbase, req);
    }
    // check the storage, and, if no match is found
    // ask the MW API about the revision
    return restbase.get({
        uri: this.tableURI(rp.domain),
        body: {
            table: this.tableName,
            index: 'by_rev',
            attributes: {
                rev: parseInt(rp.revision)
            },
            limit: 1
        }
    })
    .catch(function(e) {
        if (e.status !== 404) {
            throw e;
        }
        return self.fetchAndStoreMWRevision(restbase, req);
    });
};

module.exports = function(options) {
    var prs = new PRS(options);
    // XXX: add docs
    return {
        spec: spec,
        operations: {
            listTitles: prs.listTitles.bind(prs),
            listTitleRevisions: prs.listTitleRevisions.bind(prs),
            getTitleRevision: prs.getTitleRevision.bind(prs),
            //getTitleRevisionId: prs.getTitleRevisionId.bind(prs)
            getRevision: prs.getRevision.bind(prs),
        },
        resources: [
            {
                // Revision table
                uri: '/{domain}/sys/table/' + prs.tableName,
                body: prs.getTableSchema()
            }
        ]
    };
};
<|endoftext|>


<commit_before>'use strict';

let crypto = require('crypto');
let request = require('request');
let Promise = require('bluebird');
let debug = require("debug")("service");

module.exports = class ServiceLine {

    constructor(channel_id, channel_secret, channel_access_token){
        this._channel_id = channel_id;
        this._channel_secret = channel_secret;
        this._channel_access_token = channel_access_token;
    }

    send(to, messages){
        return new Promise((resolve, reject) => {
            let headers = {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + this._channel_access_token
            };
            let body = {
                to: to,
                messages: messages
            }
            let url = 'https://api.line.me/v2/bot/message/push';
            request({
                url: url,
                method: 'POST',
                headers: headers,
                body: body,
                json: true
            }, (error, response, body) => {
                (error) ? reject(error) : resolve();
            });
        });
    }

    reply(reply_token, messages){
        return new Promise((resolve, reject) => {
            let headers = {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + this._channel_access_token
            };
            let body = {
                replyToken: reply_token,
                messages: messages
            }
            let url = 'https://api.line.me/v2/bot/message/reply';
            debug(`headers is ${headers}`);
            debug(`body is ${body}`);
            debug(`url is ${url}`);
            request({
                url: url,
                method: 'POST',
                headers: headers,
                body: body,
                json: true
            }, (error, response, body) => {
                (error) ? reject(error) : resolve(body);
            });
        });
    }

    validate_signature(signature, raw_body){
        // Signature Validation
        let hash = crypto.createHmac('sha256', this._channel_secret).update(raw_body).digest('base64');
        if (hash != signature) {
            return false;
        }
        return true;
    }

};
<commit_msg>changed sample skill to selectable question<commit_after>'use strict';

let crypto = require('crypto');
let request = require('request');
let Promise = require('bluebird');
let debug = require("debug")("service");

module.exports = class ServiceLine {

    constructor(channel_id, channel_secret, channel_access_token){
        this._channel_id = channel_id;
        this._channel_secret = channel_secret;
        this._channel_access_token = channel_access_token;
    }

    send(to, messages){
        return new Promise((resolve, reject) => {
            let headers = {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + this._channel_access_token
            };
            let body = {
                to: to,
                messages: messages
            }
            let url = 'https://api.line.me/v2/bot/message/push';
            request({
                url: url,
                method: 'POST',
                headers: headers,
                body: body,
                json: true
            }, (error, response, body) => {
                (error) ? reject(error) : resolve();
            });
        });
    }

    reply(reply_token, messages){
        return new Promise((resolve, reject) => {
            let headers = {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + this._channel_access_token
            };
            let body = {
                replyToken: reply_token,
                messages: messages
            }
            let url = 'https://api.line.me/v2/bot/message/reply';
            debug(`headers is follwing`);
            debug(headers);
            debug(`body is following`);
            debug(body);
            debug(`url is following`);
            debug(url);
            request({
                url: url,
                method: 'POST',
                headers: headers,
                body: body,
                json: true
            }, (error, response, body) => {
                debug(error);
                debug(body);
                (error) ? reject(error) : resolve(body);
            });
        });
    }

    validate_signature(signature, raw_body){
        // Signature Validation
        let hash = crypto.createHmac('sha256', this._channel_secret).update(raw_body).digest('base64');
        if (hash != signature) {
            return false;
        }
        return true;
    }

};
<|endoftext|>


<commit_before>export default class ActorSystem {
  constructor(dispatcher) {
    this.dispatcher = dispatcher;
  }

  spawn(coroutine) {
    coroutine(this.dispatcher).next();
  }
}
<commit_msg>allow passing additional arguments to actor<commit_after>export default class ActorSystem {
  constructor(dispatcher) {
    this.dispatcher = dispatcher;
  }

  spawn(coroutine, ...args) {
    coroutine(this.dispatcher, ...args).next();
  }
}
<|endoftext|>


<commit_before>console.log("Awolumate Samuel");
console.log("I am ThirdSamuel");

/*14 - number
-80 - number
8.5 - number
true - boolean
(5 < 7) - boolean
null - unidentified
3.142 - number
"pi" - string
67 + 18 - number
*/

//CONVERTING BINARY TO DECIMAL
function DecimalToBinary(DecimalValue){
		var BinaryValue = '';
		// Loop from 2^64/2 to 1
		for (var i=64; i>=1; i--){
			// Is 2^i/2 within DecimalValue?
			if(DecimalValue >= Math.pow(2,i)/2){
				// If so, add a 1 to BinaryValue and subtract 2^i/2 from DecimalValue
				BinaryValue = BinaryValue+'1';
				DecimalValue = DecimalValue - (Math.pow(2,i)/2);
			}
			else if(BinaryValue.indexOf("1") != -1){
				// If not, add a 0, but only if there is already a 1 in the value
				BinaryValue = BinaryValue+'0';
			}
		}
		return BinaryValue;
	}
	function BinaryToDecimal(BinaryValue){
		var DecimalValue = 0;
		// Flip the character array (aka string) in order to make itterating over it easier
		BinaryValue = BinaryValue.split("").reverse().join("");
		// Loop over BinaryValue (from left to right)
		for (var i=BinaryValue.length-1;i>=0;i--){
			// Is there a 1 in the place?
			if(BinaryValue[i] == '1'){
				// If so, add 2^i/2 to DecimalValue
				DecimalValue = DecimalValue + (Math.pow(2,i+1)/2);
			}
		}
		return DecimalValue;
	};

	//ASSIGNMENT 3
	<commit_msg>This is another code update<commit_after>console.log("Awolumate Samuel");
console.log("I am ThirdSamuel");

/*14 - number
-80 - number
8.5 - number
true - boolean
(5 < 7) - boolean
null - unidentified
3.142 - number
"pi" - string
67 + 18 - number
*/

//CONVERTING BINARY TO DECIMAL
function DecimalToBinary(DecimalValue){
		var BinaryValue = '';
		// Loop from 2^64/2 to 1
		for (var i=64; i>=1; i--){
			// Is 2^i/2 within DecimalValue?
			if(DecimalValue >= Math.pow(2,i)/2){
				// If so, add a 1 to BinaryValue and subtract 2^i/2 from DecimalValue
				BinaryValue = BinaryValue+'1';
				DecimalValue = DecimalValue - (Math.pow(2,i)/2);
			}
			else if(BinaryValue.indexOf("1") != -1){
				// If not, add a 0, but only if there is already a 1 in the value
				BinaryValue = BinaryValue+'0';
			}
		}
		return BinaryValue;
	}
	function BinaryToDecimal(BinaryValue){
		var DecimalValue = 0;
		// Flip the character array (aka string) in order to make itterating over it easier
		BinaryValue = BinaryValue.split("").reverse().join("");
		// Loop over BinaryValue (from left to right)
		for (var i=BinaryValue.length-1;i>=0;i--){
			// Is there a 1 in the place?
			if(BinaryValue[i] == '1'){
				// If so, add 2^i/2 to DecimalValue
				DecimalValue = DecimalValue + (Math.pow(2,i+1)/2);
			}
		}
		return DecimalValue;
	};

	//ASSIGNMENT 3
	var countBs = function(proteins) {
	var num = 0;
	for (var i = 0; i < proteins.length; i++){
		if (proteins.charAt(i) === "B"){
			num ++;
		}
	} console.log(num)
}
countBs("My Best Food")

var countChar = function (proteins, checkthis){
var num = 0;
	for (var i = 0; i < proteins.length; i++){
		if (proteins.charAt(i) === checkthis){
			num ++;
		}

	} console.log(num)
}
countChar("My Best Food", "m");<|endoftext|>


<commit_before>'use strict';

angular.module('core').config(['toastrConfig',
  function (toastrConfig) {
    angular.extend(toastrConfig, {
      allowHtml: false,
      autoDismiss: true,
      closeButton: true,
      // containerId: 'toast-container',
      maxOpened: 5,
      newestOnTop: false,
      positionClass: 'toast-bottom-right',
      preventDuplicates: false,
      preventOpenDuplicates: false,
      target: 'body'
    });
  }
]);

angular.module('core').config(['$provide',
  function ($provide) {
    $provide.decorator('taOptions', ['taRegisterTool', 'taToolFunctions', 'ngDialog', '$delegate',
      function (taRegisterTool, taToolFunctions, dialog, taOptions) {
        // $delegate is the taOptions we are decorating
        // here we override the default toolbars specified in taOptions.
        taOptions.toolbar = [
          ['clear', 'h1', 'h2', 'h3'],
          ['ul', 'ol'],
          ['bold', 'italics'],
          ['insertLink', 'insertVideo']
        ];

        // Create our own insertImage button
        taRegisterTool('customInsertImage', {
          iconclass: "fa fa-picture-o",
          action: function () {
            var textAngular = this;

            // var savedSelection = rangy.saveSelection();
            // var modalInstance = $modal.open({
            //   // Put a link to your template here or whatever
            //   template: 'Enter the url to your image:<input type="text" ng-model="img.url"><button ng-click="submit()">OK</button>',
            //   size: 'sm',
            //   controller: ['$modalInstance', '$scope',
            //     function ($modalInstance, $scope) {
            //       $scope.img = {
            //         url: ''
            //       };
            //       $scope.submit = function () {
            //         $modalInstance.close($scope.img.url);
            //       };
            //     }
            //   ]
            // });

            // modalInstance.result.then(function (imgUrl) {
            //   rangy.restoreSelection(savedSelection);
            //   textAngular.$editor().wrapSelection('insertImage', imgUrl);
            // });
            return false;
          },
        });
        taRegisterTool('uploadImage', {
          buttontext: 'Select Image',
          iconclass: "fa fa-image",
          action: function (deferred, restoreSelection) {
            var self = this;
            dialog.openConfirm({
              // controller: 'PollInputController',
              templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
            }).then(confirm => {
              alert(1);
            }, reject => {
            });
            console.log('Clicked');
            // $mdDialog.show({
            //   templateUrl: 'uploadImagesCont.tmpl.html',
            //   parent: angular.element(document.body),
            //   //controller: textAngularUploadImage,
            //   clickOutsideToClose: false
            // }).then(function (result) {
            //   sel.collapseToEnd();
            //   self.$editor().wrapSelection('insertImage', $rootScope.ImageResult);
            //   deferred.resolve();
            // });
            return false;
          }
        });
        taRegisterTool('uploadImage2', {
        iconclass: "fa fa-picture-o",
        tooltiptext: 'Upload an image',
        onElementSelect: {
          element: 'img',
          action: taToolFunctions.imgOnSelectAction
        },
        action: function() {
          var $editor = this.$editor;

          // Create a virtual input element.
          var input = document.createElement('input');
          input.type = 'file';
          input.accept = "image/*";

          input.onchange = function() {
            var reader = new FileReader();

            if (this.files && this.files[0]) {
              reader.onload = function(e) {
                $editor().wrapSelection('insertHtml', '', true);
              };

              reader.readAsDataURL(this.files[0]);
            }
          };

          // Click on a virtual input element.
          input.click();
        }
      });
        taOptions.toolbar[3].push('customInsertImage', 'uploadImage', 'uploadImage2');
        return taOptions;
      }
    ]);
  }
]);<commit_msg>Commited from lenh at Wed, Jul 12, 2017 10:29:09 AM<commit_after>'use strict';

angular.module('core').config(['toastrConfig',
  function (toastrConfig) {
    angular.extend(toastrConfig, {
      allowHtml: false,
      autoDismiss: true,
      closeButton: true,
      // containerId: 'toast-container',
      maxOpened: 5,
      newestOnTop: false,
      positionClass: 'toast-bottom-right',
      preventDuplicates: false,
      preventOpenDuplicates: false,
      target: 'body'
    });
  }
]);

angular.module('core').config(['$provide',
  function ($provide) {
    $provide.decorator('taOptions', ['taRegisterTool', 'taToolFunctions', 'ngDialog', '$delegate',
      function (taRegisterTool, taToolFunctions, dialog, taOptions) {
        // $delegate is the taOptions we are decorating
        // here we override the default toolbars specified in taOptions.
        // taOptions.toolbar = [
        //   ['clear', 'h1', 'h2', 'h3'],
        //   ['ul', 'ol'],
        //   ['bold', 'italics'],
        //   ['insertLink', 'insertVideo']
        // ];

        taRegisterTool('uploadImage', {
        iconclass: "fa fa-picture-o",
        tooltiptext: 'Upload an image',
        onElementSelect: {
          element: 'img',
          action: taToolFunctions.imgOnSelectAction
        },
        action: function() {
          var $editor = this.$editor;

          // Create a virtual input element.
          var input = document.createElement('input');
          input.type = 'file';
          input.accept = "image/*";

          input.onchange = function() {
            var reader = new FileReader();

            if (this.files && this.files[0]) {
              reader.onload = function(e) {
                $editor().wrapSelection('insertHtml', '', true);
              };

              reader.readAsDataURL(this.files[0]);
            }
          };

          // Click on a virtual input element.
          input.click();
        }
      });
        taOptions.toolbar[3].push('uploadImage');
        return taOptions;
      }
    ]);
  }
]);<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	$C = require('collection.js');

const
	{String} = require('sugar'),
	{args} = require('./helpers.webpack');

const
	fs = require('fs'),
	path = require('path'),
	findUp = require('find-up'),
	glob = require('glob'),
	mkdirp = require('mkdirp'),
	hasha = require('hasha'),
	pzlr = require('@pzlr/build-core');

const
	IN_PROCESS = 3;

/**
 * Builds entry points for WebPack by the specified parameters and returns a tree of dependencies
 *
 * @param {string} entries - path to base entry points
 * @param {string} blocks - path to a block folder
 * @param {string} lib - path to a lib folder
 * @param {string} output - output path
 * @param {string} cache - path to a cache folder
 * @param {string} assetsJSON - path to assets.json file
 * @returns {{processes, entry, dependencies, commonPacks}}
 */
module.exports = function ({entries, blocks, lib, output, cache, assetsJSON}) {
	let
		cacheFile;

	if (cache) {
		mkdirp.sync(cache);
		cacheFile = path.join(cache, 'graph.json');
		if (fs.existsSync(cacheFile)) {
			return require(cacheFile);
		}
	}

	function getCommonName(i) {
		return `common_${i}`;
	}

	const
		components = '!(core|models|libs|entries)/**/@(index|*.index).js';

	const files = [].concat(
		glob.sync(path.join(lib, '@v4fire/client/src', components)),
		glob.sync(path.join(blocks, components))
	);

	// Load index declarations of blocks
	const blockMap = $C(files).reduce((map, el) => {
		const
			decl = pzlr.declaration.parse(fs.readFileSync(el)),
			cwd = path.dirname(el),
			url = (ext) => path.join(cwd, `${decl.name}.${ext}`);

		const
			logic = url('js'),
			style = url('styl'),
			tpl = url('ss'),
			html = url('ess');

		if (fs.existsSync(logic)) {
			decl.logic = logic;
		}

		if (fs.existsSync(style)) {
			decl.style = style;
		}

		if (fs.existsSync(tpl)) {
			decl.tpl = tpl;
		}

		if (fs.existsSync(html)) {
			decl.html = html;
		}

		if (decl.libs.length) {
			const root = findUp.sync('src', {cwd});
			$C(decl.libs).set((el) => path.join(root, el));
		}

		decl.src = el;
		map[decl.name] = decl;
		return map;
	}, {});

	// Parse --build arguments
	let entriesFilter;
	if (typeof args.build === 'string') {
		entriesFilter = $C(args.build.split(',')).reduce((map, el) => (map[el] = true, map), {});
		entriesFilter.index = true;
	}

	// Load entries
	const entriesList = $C(glob.sync(path.join(entries, '*.js'))).get((el) => {
		if (entriesFilter) {
			return entriesFilter[path.basename(el, '.js')];
		}

		return true;
	});

	// Build a graph with dependencies for each block
	function getBlocks(name, runtimeDependencies = [], compileDependencies = [], parents = []) {
		compileDependencies.unshift(name);
		runtimeDependencies.unshift(name);

		const
			block = blockMap[name];

		if (!block) {
			throw new Error(`Block "${name}" not exists!`);
		}

		$C(block.dependencies).forEach((block) => {
			block = path.basename(block.replace(/^@/, ''));
			compileDependencies.unshift(block);
			runtimeDependencies.unshift(block);
			getBlocks(block, runtimeDependencies, compileDependencies);
		});

		if (block.parent) {
			const parent = path.basename(block.parent);
			runtimeDependencies.unshift(parent);
			parents.unshift(parent);
			getBlocks(parent, runtimeDependencies, compileDependencies, parents);
		}

		block.compileDependencies = new Set(compileDependencies);
		block.runtimeDependencies = new Set(runtimeDependencies);
		block.parents = new Set(parents);

		return runtimeDependencies;
	}

	// Returns dependencies from a file with entries
	function getDependencies(dir, file, arr = []) {
		$C(file.split(/\r?\n|\r/)).forEach((el) => {
			if (!/^import\s+('|")(.*?)\1;?/.test(el)) {
				return;
			}

			const
				url = RegExp.$2;

			if (/^\.\//.test(url)) {
				getDependencies(
					path.join(dir, path.dirname(url)),
					fs.readFileSync(path.join(dir, `${url}.js`), 'utf-8'),
					arr
				);

			} else {
				arr.push(url);
			}
		});

		return arr;
	}

	// Parses a file with entries
	function extractFile(dir, file) {
		let list = [];

		$C(getDependencies(dir, file)).forEach((el) => {
			const
				name = path.basename(el, '.js'),
				block = blockMap[name];

			if (!/^[ibpgv]-/.test(name) || !block) {
				list.push(el);
				return;
			}

			list = list.concat(getBlocks(name));
		});

		return [...new Set(list)];
	}

	const
		packs = {},
		weights = {};

	// Load entries
	$C(entriesList).forEach((el) => {
		const
			list = packs[path.basename(el, '.js')] = extractFile(path.dirname(el), fs.readFileSync(el, 'utf-8'));

		$C(list).forEach((block) => {
			if (block in weights) {
				weights[block]++;

			} else {
				weights[block] = 0;
			}
		});
	});

	// Find common modules (weight > 1)
	const commonPacks = [];
	$C(weights).forEach((i, key) => {
		if (i > 1) {
			const pos = entriesList.length - i - 1;
			(commonPacks[pos] = commonPacks[pos] || new Set()).add(key);
		}
	});

	// Remove empty modules
	$C(commonPacks).remove((el) => !el);

	// Configure dependencies for each entry point
	const dependencies = {};
	$C(packs).forEach((list, name) => {
		const
			dep = dependencies[name] = dependencies[name] || new Set(),
			newList = [];

		$C(list).forEach((block) => {
			const
				pos = $C(commonPacks).one.search((set) => set.has(block));

			if (pos === null) {
				newList.push(block);

			} else {
				dep.add(pos);
			}
		});

		dependencies[name] = [...dep].sort((a, b) => a - b).map((i) => getCommonName(i));
		packs[name] = newList;
	});

	// Generate new entry points
	const entry = {};
	$C(commonPacks).forEach((list, i) => entry[getCommonName(i)] = list);
	$C(packs).forEach((list, name) => entry[name] = new Set(list));

	// Temporary folder for webpack entry points
	const tmpEntries = path.join(entries, 'tmp');
	mkdirp.sync(tmpEntries);

	function isNodeModule(url) {
		return !path.isAbsolute(url) && /[^./~]/.test(url);
	}

	function getUrl(url) {
		const
			r = (s) => s.replace(/\\/g, '/');

		if (isNodeModule(url)) {
			return r(url);
		}

		return r(path.relative(tmpEntries, url));
	}

	// Generate webpack entry points
	const processes = [{}];
	$C(entry).forEach((list, name) => {
		delete entry[name];

		// JS

		const
			blackName = /^[iv]-/,
			logicTaskName = `${name}.js`,
			logicFile = path.join(tmpEntries, logicTaskName);

		fs.writeFileSync(logicFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block) {
				$C(block.libs).forEach((el) => str += `require('${el}');\n`);
			}

			if (!block || block && block.logic) {
				const url = block ? block.logic : isNodeModule(name) ? name : path.resolve(tmpEntries, '../', name);
				str += `require('${getUrl(url)}');\n`;
			}

			return str;
		}, ''));

		entry[logicTaskName] = logicFile;
		processes[0][logicTaskName] = logicFile;

		// CSS

		const
			styleTaskName = `${name}$style`,
			styleFile = path.join(tmpEntries, `${name}.styl`);

		fs.writeFileSync(styleFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block && block.style && !blackName.test(name)) {
				const url = getUrl(block.style);
				str += `@import "${url}"\n`;

				if (/^[bp]-/.test(name)) {
					str +=
						`
.${name}
	extends($${String.camelize(name, false)})

`;
				}
			}

			return str;
		}, ''));

		let union = processes[processes.length - 1];
		if (processes.length === 1 || $C(union).length() > IN_PROCESS) {
			processes.push(union = {});
		}

		entry[styleTaskName] = union[styleTaskName] = styleFile;

		// TEMPLATES

		const
			tplTaskName = `${name}_tpl.js`,
			tplFile = path.join(tmpEntries, `${name}.ss${!args.fast ? '.js' : ''}`);

		fs.writeFileSync(tplFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block && block.tpl && !blackName.test(name)) {
				const url = getUrl(block.tpl);
				str += args.fast ? `- include '${url}'\n` : `Object.assign(TPLS, require('./${url}'));\n`;
			}

			return str;
		}, !args.fast ? 'window.TPLS = window.TPLS || {};\n' : ''));

		if (args.fast) {
			const tplRequireFileUrl = path.join(tmpEntries, tplTaskName);
			fs.writeFileSync(tplRequireFileUrl, `Object.assign(window.TPLS = window.TPLS || {}, require('./${getUrl(tplFile)}'));\n`);
			entry[tplTaskName] = union[tplTaskName] = tplRequireFileUrl;

		} else {
			entry[tplTaskName] = union[tplTaskName] = tplFile;
		}

		// HTML

		const
			htmlTaskName = `${name}_view`,
			htmlFile = path.join(tmpEntries, `${htmlTaskName}.html.js`);

		fs.writeFileSync(htmlFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block && block.html && !blackName.test(name)) {
				str += `require('./${getUrl(block.html)}');\n`;
			}

			return str;
		}, ''));

		entry[htmlTaskName] = union[htmlTaskName] = htmlFile;
	});

	const finalCommonPacks = ['index.js'].concat($C(commonPacks).map((el, i) => `${getCommonName(i)}.js`));
	mkdirp.sync(path.dirname(output));

	// Generate dependence declarations
	$C(dependencies).forEach((el, key) => {
		if (key !== 'index' && !el.includes('index')) {
			el.unshift('index');
		}

		el.push(key);

		const
			content = `ModuleDependencies.add("${key}", ${JSON.stringify(el)});`,
			name = `${key}.dependencies`;

		const src = output
			.replace(/\[name]/g, `${name}.js`)
			.replace(/\[hash:?(\d*)]/, (str, length) => {
				const res = hasha(content, {algorithm: 'md5'});
				return length ? res.substr(0, Number(length)) : res;
			});

		fs.writeFileSync(src, content);

		let fd;
		try {
			fd = fs.openSync(assetsJSON, 'r+');

		} catch (_) {
			fd = fs.openSync(assetsJSON, 'w+');
		}

		const
			file = fs.readFileSync(fd, 'utf-8'),
			assets = file ? JSON.parse(file) : {};

		assets[name] = {js: src};
		fs.writeFileSync(fd, JSON.stringify(assets));
		fs.closeSync(fd);
	});

	const res = {
		processes,
		entry,
		dependencies,
		commonPacks: finalCommonPacks
	};

	if (cacheFile) {
		fs.writeFileSync(cacheFile, JSON.stringify(res, null, 2));
		process.env.FROM_CACHE = true;
	}

	return res;
};
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	$C = require('collection.js');

const
	{String} = require('sugar'),
	{args} = require('./helpers.webpack');

const
	fs = require('fs'),
	path = require('path'),
	findUp = require('find-up'),
	glob = require('glob'),
	mkdirp = require('mkdirp'),
	hasha = require('hasha'),
	pzlr = require('@pzlr/build-core');

const
	IN_PROCESS = 3;

/**
 * Builds entry points for WebPack by the specified parameters and returns a tree of dependencies
 *
 * @param {string} entries - path to base entry points
 * @param {string} blocks - path to a block folder
 * @param {string} lib - path to a lib folder
 * @param {string} output - output path
 * @param {string} cache - path to a cache folder
 * @param {string} assetsJSON - path to assets.json file
 * @returns {{processes, entry, dependencies, commonPacks}}
 */
module.exports = function ({entries, blocks, lib, output, cache, assetsJSON}) {
	let
		cacheFile;

	if (cache) {
		mkdirp.sync(cache);
		cacheFile = path.join(cache, 'graph.json');
		if (fs.existsSync(cacheFile)) {
			return require(cacheFile);
		}
	}

	function getCommonName(i) {
		return `common_${i}`;
	}

	const
		components = '!(core|models|libs|entries)/**/@(index|*.index).js';

	const files = [].concat(
		glob.sync(path.join(lib, '@v4fire/client/src', components)),
		glob.sync(path.join(blocks, components))
	);

	// Load index declarations of blocks
	const blockMap = $C(files).reduce((map, el) => {
		const
			decl = pzlr.declaration.parse(fs.readFileSync(el)),
			cwd = path.dirname(el),
			url = (ext) => path.join(cwd, `${decl.name}.${ext}`);

		const
			logic = url('js'),
			style = url('styl'),
			tpl = url('ss'),
			html = url('ess');

		if (fs.existsSync(logic)) {
			decl.logic = logic;
		}

		if (fs.existsSync(style)) {
			decl.style = style;
		}

		if (fs.existsSync(tpl)) {
			decl.tpl = tpl;
		}

		if (fs.existsSync(html)) {
			decl.html = html;
		}

		if (decl.libs.length) {
			const root = findUp.sync('src', {cwd});
			$C(decl.libs).set((el) => path.join(root, el));
		}

		decl.src = el;
		map[decl.name] = decl;
		return map;
	}, {});

	// Parse --build arguments
	let entriesFilter;
	if (typeof args.build === 'string') {
		entriesFilter = $C(args.build.split(',')).reduce((map, el) => (map[el] = true, map), {});
		entriesFilter.index = true;
	}

	// Load entries
	const entriesList = $C(glob.sync(path.join(entries, '*.js'))).get((el) => {
		if (entriesFilter) {
			return entriesFilter[path.basename(el, '.js')];
		}

		return true;
	});

	// Build a graph with dependencies for each block
	function getBlocks(name, runtimeDependencies = [], compileDependencies = [], parents = []) {
		compileDependencies.unshift(name);
		runtimeDependencies.unshift(name);

		const
			block = blockMap[name];

		if (!block) {
			throw new Error(`Block "${name}" not exists!`);
		}

		$C(block.dependencies).forEach((block) => {
			block = path.basename(block.replace(/^@/, ''));
			compileDependencies.unshift(block);
			runtimeDependencies.unshift(block);
			getBlocks(block, runtimeDependencies, compileDependencies);
		});

		if (block.parent) {
			const parent = path.basename(block.parent);
			runtimeDependencies.unshift(parent);
			parents.unshift(parent);
			getBlocks(parent, runtimeDependencies, compileDependencies, parents);
		}

		block.compileDependencies = new Set(compileDependencies);
		block.runtimeDependencies = new Set(runtimeDependencies);
		block.parents = new Set(parents);

		return runtimeDependencies;
	}

	function isNodeModule(url) {
		return !path.isAbsolute(url) && /[^./\\]/.test(url);
	}

	// Returns dependencies from a file with entries
	function getDependencies(dir, file, arr = []) {
		$C(file.split(/\r?\n|\r/)).forEach((el) => {
			if (!/^import\s+('|")(.*?)\1;?/.test(el)) {
				return;
			}

			const
				url = RegExp.$2;

			if (/^\.\//.test(url)) {
				dir = isNodeModule(url) ? lib : dir;
				getDependencies(
					path.join(dir, path.dirname(url)),
					fs.readFileSync(path.join(dir, `${url}.js`), 'utf-8'),
					arr
				);

			} else {
				arr.push(url);
			}
		});

		return arr;
	}

	// Parses a file with entries
	function extractFile(dir, file) {
		let list = [];

		$C(getDependencies(dir, file)).forEach((el) => {
			const
				name = path.basename(el, '.js'),
				block = blockMap[name];

			if (!/^[ibpgv]-/.test(name) || !block) {
				list.push(el);
				return;
			}

			list = list.concat(getBlocks(name));
		});

		return [...new Set(list)];
	}

	const
		packs = {},
		weights = {};

	// Load entries
	$C(entriesList).forEach((el) => {
		const
			list = packs[path.basename(el, '.js')] = extractFile(path.dirname(el), fs.readFileSync(el, 'utf-8'));

		$C(list).forEach((block) => {
			if (block in weights) {
				weights[block]++;

			} else {
				weights[block] = 0;
			}
		});
	});

	// Find common modules (weight > 1)
	const commonPacks = [];
	$C(weights).forEach((i, key) => {
		if (i > 1) {
			const pos = entriesList.length - i - 1;
			(commonPacks[pos] = commonPacks[pos] || new Set()).add(key);
		}
	});

	// Remove empty modules
	$C(commonPacks).remove((el) => !el);

	// Configure dependencies for each entry point
	const dependencies = {};
	$C(packs).forEach((list, name) => {
		const
			dep = dependencies[name] = dependencies[name] || new Set(),
			newList = [];

		$C(list).forEach((block) => {
			const
				pos = $C(commonPacks).one.search((set) => set.has(block));

			if (pos === null) {
				newList.push(block);

			} else {
				dep.add(pos);
			}
		});

		dependencies[name] = [...dep].sort((a, b) => a - b).map((i) => getCommonName(i));
		packs[name] = newList;
	});

	// Generate new entry points
	const entry = {};
	$C(commonPacks).forEach((list, i) => entry[getCommonName(i)] = list);
	$C(packs).forEach((list, name) => entry[name] = new Set(list));

	// Temporary folder for webpack entry points
	const tmpEntries = path.join(entries, 'tmp');
	mkdirp.sync(tmpEntries);

	function getUrl(url) {
		const
			r = (s) => s.replace(/\\/g, '/');

		if (isNodeModule(url)) {
			return r(url);
		}

		return r(path.relative(tmpEntries, url));
	}

	// Generate webpack entry points
	const processes = [{}];
	$C(entry).forEach((list, name) => {
		delete entry[name];

		// JS

		const
			blackName = /^[iv]-/,
			logicTaskName = `${name}.js`,
			logicFile = path.join(tmpEntries, logicTaskName);

		fs.writeFileSync(logicFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block) {
				$C(block.libs).forEach((el) => str += `require('${el}');\n`);
			}

			if (!block || block && block.logic) {
				const url = block ? block.logic : isNodeModule(name) ? name : path.resolve(tmpEntries, '../', name);
				str += `require('${getUrl(url)}');\n`;
			}

			return str;
		}, ''));

		entry[logicTaskName] = logicFile;
		processes[0][logicTaskName] = logicFile;

		// CSS

		const
			styleTaskName = `${name}$style`,
			styleFile = path.join(tmpEntries, `${name}.styl`);

		fs.writeFileSync(styleFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block && block.style && !blackName.test(name)) {
				const url = getUrl(block.style);
				str += `@import "${url}"\n`;

				if (/^[bp]-/.test(name)) {
					str +=
						`
.${name}
	extends($${String.camelize(name, false)})

`;
				}
			}

			return str;
		}, ''));

		let union = processes[processes.length - 1];
		if (processes.length === 1 || $C(union).length() > IN_PROCESS) {
			processes.push(union = {});
		}

		entry[styleTaskName] = union[styleTaskName] = styleFile;

		// TEMPLATES

		const
			tplTaskName = `${name}_tpl.js`,
			tplFile = path.join(tmpEntries, `${name}.ss${!args.fast ? '.js' : ''}`);

		fs.writeFileSync(tplFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block && block.tpl && !blackName.test(name)) {
				const url = getUrl(block.tpl);
				str += args.fast ? `- include '${url}'\n` : `Object.assign(TPLS, require('./${url}'));\n`;
			}

			return str;
		}, !args.fast ? 'window.TPLS = window.TPLS || {};\n' : ''));

		if (args.fast) {
			const tplRequireFileUrl = path.join(tmpEntries, tplTaskName);
			fs.writeFileSync(tplRequireFileUrl, `Object.assign(window.TPLS = window.TPLS || {}, require('./${getUrl(tplFile)}'));\n`);
			entry[tplTaskName] = union[tplTaskName] = tplRequireFileUrl;

		} else {
			entry[tplTaskName] = union[tplTaskName] = tplFile;
		}

		// HTML

		const
			htmlTaskName = `${name}_view`,
			htmlFile = path.join(tmpEntries, `${htmlTaskName}.html.js`);

		fs.writeFileSync(htmlFile, $C(list).reduce((str, name) => {
			const
				block = blockMap[name];

			if (block && block.html && !blackName.test(name)) {
				str += `require('./${getUrl(block.html)}');\n`;
			}

			return str;
		}, ''));

		entry[htmlTaskName] = union[htmlTaskName] = htmlFile;
	});

	const finalCommonPacks = ['index.js'].concat($C(commonPacks).map((el, i) => `${getCommonName(i)}.js`));
	mkdirp.sync(path.dirname(output));

	// Generate dependence declarations
	$C(dependencies).forEach((el, key) => {
		if (key !== 'index' && !el.includes('index')) {
			el.unshift('index');
		}

		el.push(key);

		const
			content = `ModuleDependencies.add("${key}", ${JSON.stringify(el)});`,
			name = `${key}.dependencies`;

		const src = output
			.replace(/\[name]/g, `${name}.js`)
			.replace(/\[hash:?(\d*)]/, (str, length) => {
				const res = hasha(content, {algorithm: 'md5'});
				return length ? res.substr(0, Number(length)) : res;
			});

		fs.writeFileSync(src, content);

		let fd;
		try {
			fd = fs.openSync(assetsJSON, 'r+');

		} catch (_) {
			fd = fs.openSync(assetsJSON, 'w+');
		}

		const
			file = fs.readFileSync(fd, 'utf-8'),
			assets = file ? JSON.parse(file) : {};

		assets[name] = {js: src};
		fs.writeFileSync(fd, JSON.stringify(assets));
		fs.closeSync(fd);
	});

	const res = {
		processes,
		entry,
		dependencies,
		commonPacks: finalCommonPacks
	};

	if (cacheFile) {
		fs.writeFileSync(cacheFile, JSON.stringify(res, null, 2));
		process.env.FROM_CACHE = true;
	}

	return res;
};
<|endoftext|>