<commit_before>'use strict';

const Author     = require('./lib/Author'),
    Page         = require('./lib/Page'),
    Post         = require('./lib/Post'),
    argv         = require('yargs').argv,
    del          = require('del'),
    express      = require('express'),
    extend       = require('jquery-extend'),
    fs           = require('fs'),
    g            = require('gulp-load-plugins')(),
    gulp         = require('gulp'),
    hb           = require('handlebars'),
    highlight    = require('highlight.js'),
    layouts      = require('handlebars-layouts'),
    moment       = require('moment'),
    path         = require('path'),
    reviewerList = require('./lib/hb-helper-reviewerlist');

// Config HB
layouts.register(hb);
hb.registerHelper('reviewerList', reviewerList);

// Shared data object for passing between tasks
let data;

// Clean data and build dirs
gulp.task('clean', done => {
    fs.readFile('src/data/careers.json', 'utf-8', (err, careers) => {
        if (err) throw err;

        data = {
            authors   : [], // Populated by 'authors' task
            posts     : [], // Populated by 'posts' task
            tags      : [], // Populated by 'posts' task
            careers   : JSON.parse(careers),
            pageTitle : 'Airware Makers',
            year      : moment().format('YYYY'),
            timestamp : moment().format('YYYY-MM-DD-HH-mm-ss')
        };

        del([
            'build/**',
            '!build'
        ]).then(done());
    });
});

// Copy static files to build dir
gulp.task('static', () => {
    return gulp.src('src/static/**')
        .pipe(g.if('robots.txt', g.tap(file => {
            if (process.env.TRAVIS_BRANCH == 'master') {
                file.contents = new Buffer('');
            }
        })))
        .pipe(gulp.dest('build'));
});

// Minify and combine all CSS
gulp.task('styles', () => {
    return gulp.src([
        'node_modules/bootstrap/dist/css/bootstrap.css',
        'node_modules/highlight.js/styles/default.css',
        'src/less/custom.less'
    ])
    .pipe(g.sourcemaps.init({ loadMaps : true }))
    .pipe(g.if('*.less', g.less()))
    .pipe(g.concat('all.min.css'))
    .pipe(g.cssnano())
    .pipe(g.sourcemaps.write('.'))
    .pipe(gulp.dest('build/css'));
});

// Minify and combine all JavaScript
gulp.task('scripts', () => {
    return gulp.src('src/js/*.js')
        .pipe(g.babel({
            presets  : [ 'es2015' ],
            comments : true
        }))
        .pipe(g.addSrc.prepend([
            'node_modules/jquery/dist/jquery.js',
            'node_modules/velocity-animate/velocity.js',
            'node_modules/velocity-animate/velocity.ui.js',
            'node_modules/hammerjs/hammer.js',
            'node_modules/jquery-hammerjs/jquery.hammer.js',
            'node_modules/bootstrap/dist/js/bootstrap.js'
        ]))
        .pipe(g.concat('all.min.js'))
        .pipe(g.uglify({ preserveComments : 'some' }))
        .pipe(gulp.dest('build'));
});

// Register HB partials
gulp.task('partials', () => {
    return gulp.src('src/partials/*.html')
        .pipe(g.tap(file => {
            hb.registerPartial(path.parse(file.path).name, file.contents.toString());
        }));
});

// Load authors
gulp.task('authors', () => {
    return gulp.src('src/authors/*.md')
        .pipe(g.frontMatter())
        .pipe(g.marked())
        .pipe(g.tap(file => {
            const author = new Author(extend(true, {}, file.frontMatter, {
                slug : path.parse(file.path).name,
                bio  : file.contents.toString()
            }));
            data.authors.push(author);
        }));
});

// Generate posts
gulp.task('posts', done => {
    fs.readFile('src/partials/post.html', 'utf-8', (err, str) => {
        if (err) throw err;
        const template = hb.compile(str);

        gulp.src('src/posts/*.md')
            .pipe(g.frontMatter())
            .pipe(g.marked({
                highlight : code => {
                    return highlight.highlightAuto(code).value;
                }
            }))
            .pipe(g.tap(file => {
                const post = new Post(extend(true, {}, file.frontMatter, {
                    path      : file.path,
                    content   : file.contents.toString(),
                    authors   : data.authors,
                    careers   : data.careers,
                    pageTitle : data.pageTitle,
                    year      : data.year,
                    timestamp : data.timestamp
                }));

                // Populate the posts object for reuse
                data.posts.push(post);

                // Alter the path, write the rendered template, and put back in stream
                file.path = post.path;
                file.contents = new Buffer(template(post));
            }))
            .pipe(g.htmlmin({ collapseWhitespace : true }))
            .pipe(gulp.dest('build'))
            .on('end', () => {
                // Sort posts by date descending
                data.posts.sort((a, b) => {
                    return moment(a.date).format('X') < moment(b.date).format('X'); // DESC
                });
                done();
            });
    });
});

// Generate posts
gulp.task('pages', done => {
    fs.readFile('src/partials/rss.xml', 'utf-8', (err, rssStr) => {
        if (err) throw err;
        const rssTemplate = hb.compile(rssStr);

        gulp.src('src/pages/**/*.html')
            .pipe(g.frontMatter())
            .pipe(g.tap(file => {
                file.data = new Page(extend(true, {}, file.frontMatter, {
                    path      : file.path,
                    posts     : data.posts,
                    year      : data.year,
                    careers   : data.careers,
                    timestamp : data.timestamp,
                    pageTitle : data.pageTitle
                }));
                file.path = file.data.path;
                const template = hb.compile(file.contents.toString());
                file.contents = new Buffer(template(file.data));
            }))
            .pipe(g.htmlmin({ collapseWhitespace : true }))
            .pipe(gulp.dest('build'))
            .pipe(g.filter(file => {
                return file.data.rss;
            }))
            .pipe(g.tap(file => {
                file.path = file.data.rssPath;
                file.contents = new Buffer(rssTemplate(file.data));
            }))
            .pipe(gulp.dest('build'))
            .on('end', done);
    });
});

// Run tests and product coverage
gulp.task('test', () => {
    return gulp.src('test/*.js')
        .pipe(g.mocha({
            require : [ 'should' ]
        }));
});

// Lint as JS files (including this one)
gulp.task('lint', () => {
    return gulp.src([
        'gulpfile.js',
        'src/js/*.js',
        'test/*.js',
        'lib/*.js',
        '!node_modules/**'
    ])
    .pipe(g.eslint())
    .pipe(g.eslint.format());
});

// Serve files for local development
gulp.task('serve', done => {
    const port = argv.p || 3000;

    express()
        .use(express.static('build'))
        .use((req, res) => {
            res.status(404)
                .sendFile(path.join(__dirname, '/build/error.html'));
        })
        .listen(port, () => {
            g.util.log('Server listening on port', port);
            done();
        });
});

// Check deps with David service
gulp.task('deps', () => {
    return gulp.src('package.json')
        .pipe(g.david({ update : true }))
        .pipe(gulp.dest('.'));
});

// Examine package.json for unused deps (except for frontend and gulp)
gulp.task('package', g.depcheck({
    ignoreMatches : [
        'babel-preset-es2015',
        'bootstrap',
        'gulp-*',
        'hammerjs',
        'jquery-hammerjs',
        'jquery',
        'should',
        'velocity-animate'
    ]
}));

// Watch certain files
gulp.task('watch', () => {
    const paths = [
        'src/**/*.*',
        'test/*.js',
        'lib/*.js'
    ];

    gulp.watch(paths, [ 'build' ])
        .on('change', e => {
            g.util.log('File', e.path, 'was', e.type);
        });
});

// Build Macro
gulp.task('build', done => {
    g.sequence(
        'clean',
        [ 'static', 'styles', 'scripts', 'partials', 'authors' ],
        'posts',
        'pages',
        'test',
        'lint'
    )(done);
});

// Deploy to AWS S3
gulp.task('deploy', () => {
    const publisher = g.awspublish.create({
        accessKeyId     : process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey : process.env.AWS_SECRET_ACCESS_KEY,
        region          : 'us-east-1',
        params          : { Bucket : argv.b }
    });

    return gulp.src('build/**')
        .pipe(g.awspublish.gzip())
        .pipe(publisher.publish())
        .pipe(publisher.sync())
        .pipe(g.awspublish.reporter());
});

// What to do when you run `$ gulp`
gulp.task('default', done => {
    g.sequence(
        'deps',
        'package',
        'build',
        'watch',
        'serve'
    )(done);
});
<commit_msg>JS sourcemaps<commit_after>'use strict';

const Author     = require('./lib/Author'),
    Page         = require('./lib/Page'),
    Post         = require('./lib/Post'),
    argv         = require('yargs').argv,
    del          = require('del'),
    express      = require('express'),
    extend       = require('jquery-extend'),
    fs           = require('fs'),
    g            = require('gulp-load-plugins')(),
    gulp         = require('gulp'),
    hb           = require('handlebars'),
    highlight    = require('highlight.js'),
    layouts      = require('handlebars-layouts'),
    moment       = require('moment'),
    path         = require('path'),
    reviewerList = require('./lib/hb-helper-reviewerlist');

// Config HB
layouts.register(hb);
hb.registerHelper('reviewerList', reviewerList);

// Shared data object for passing between tasks
let data;

// Clean data and build dirs
gulp.task('clean', done => {
    fs.readFile('src/data/careers.json', 'utf-8', (err, careers) => {
        if (err) throw err;

        data = {
            authors   : [], // Populated by 'authors' task
            posts     : [], // Populated by 'posts' task
            tags      : [], // Populated by 'posts' task
            careers   : JSON.parse(careers),
            pageTitle : 'Airware Makers',
            year      : moment().format('YYYY'),
            timestamp : moment().format('YYYY-MM-DD-HH-mm-ss')
        };

        del([
            'build/**',
            '!build'
        ]).then(done());
    });
});

// Copy static files to build dir
gulp.task('static', () => {
    return gulp.src('src/static/**')
        .pipe(g.if('robots.txt', g.tap(file => {
            if (process.env.TRAVIS_BRANCH == 'master') {
                file.contents = new Buffer('');
            }
        })))
        .pipe(gulp.dest('build'));
});

// Minify and combine all CSS
gulp.task('styles', () => {
    return gulp.src([
        'node_modules/bootstrap/dist/css/bootstrap.css',
        'node_modules/highlight.js/styles/default.css',
        'src/less/custom.less'
    ])
    .pipe(g.sourcemaps.init({ loadMaps : true }))
    .pipe(g.if('*.less', g.less()))
    .pipe(g.concat('all.min.css'))
    .pipe(g.cssnano())
    .pipe(g.sourcemaps.write('.'))
    .pipe(gulp.dest('build/css'));
});

// Minify and combine all JavaScript
gulp.task('scripts', () => {
    return gulp.src([
        'node_modules/jquery/dist/jquery.js',
        'node_modules/velocity-animate/velocity.js',
        'node_modules/velocity-animate/velocity.ui.js',
        'node_modules/hammerjs/hammer.js',
        'node_modules/jquery-hammerjs/jquery.hammer.js',
        'node_modules/bootstrap/dist/js/bootstrap.js',
        'src/js/*.js'
    ])
    .pipe(g.sourcemaps.init({ loadMaps : true }))
    .pipe(g.babel({
        presets  : [ 'es2015' ],
        comments : true,
        compact  : false
    }))
    .pipe(g.concat('all.min.js'))
    .pipe(g.uglify({ preserveComments : 'some' }))
    .pipe(g.sourcemaps.write('.'))
    .pipe(gulp.dest('build'));
});

// Register HB partials
gulp.task('partials', () => {
    return gulp.src('src/partials/*.html')
        .pipe(g.tap(file => {
            hb.registerPartial(path.parse(file.path).name, file.contents.toString());
        }));
});

// Load authors
gulp.task('authors', () => {
    return gulp.src('src/authors/*.md')
        .pipe(g.frontMatter())
        .pipe(g.marked())
        .pipe(g.tap(file => {
            const author = new Author(extend(true, {}, file.frontMatter, {
                slug : path.parse(file.path).name,
                bio  : file.contents.toString()
            }));
            data.authors.push(author);
        }));
});

// Generate posts
gulp.task('posts', done => {
    fs.readFile('src/partials/post.html', 'utf-8', (err, str) => {
        if (err) throw err;
        const template = hb.compile(str);

        gulp.src('src/posts/*.md')
            .pipe(g.frontMatter())
            .pipe(g.marked({
                highlight : code => {
                    return highlight.highlightAuto(code).value;
                }
            }))
            .pipe(g.tap(file => {
                const post = new Post(extend(true, {}, file.frontMatter, {
                    path      : file.path,
                    content   : file.contents.toString(),
                    authors   : data.authors,
                    careers   : data.careers,
                    pageTitle : data.pageTitle,
                    year      : data.year,
                    timestamp : data.timestamp
                }));

                // Populate the posts object for reuse
                data.posts.push(post);

                // Alter the path, write the rendered template, and put back in stream
                file.path = post.path;
                file.contents = new Buffer(template(post));
            }))
            .pipe(g.htmlmin({ collapseWhitespace : true }))
            .pipe(gulp.dest('build'))
            .on('end', () => {
                // Sort posts by date descending
                data.posts.sort((a, b) => {
                    return moment(a.date).format('X') < moment(b.date).format('X'); // DESC
                });
                done();
            });
    });
});

// Generate posts
gulp.task('pages', done => {
    fs.readFile('src/partials/rss.xml', 'utf-8', (err, rssStr) => {
        if (err) throw err;
        const rssTemplate = hb.compile(rssStr);

        gulp.src('src/pages/**/*.html')
            .pipe(g.frontMatter())
            .pipe(g.tap(file => {
                file.data = new Page(extend(true, {}, file.frontMatter, {
                    path      : file.path,
                    posts     : data.posts,
                    year      : data.year,
                    careers   : data.careers,
                    timestamp : data.timestamp,
                    pageTitle : data.pageTitle
                }));
                file.path = file.data.path;
                const template = hb.compile(file.contents.toString());
                file.contents = new Buffer(template(file.data));
            }))
            .pipe(g.htmlmin({ collapseWhitespace : true }))
            .pipe(gulp.dest('build'))
            .pipe(g.filter(file => {
                return file.data.rss;
            }))
            .pipe(g.tap(file => {
                file.path = file.data.rssPath;
                file.contents = new Buffer(rssTemplate(file.data));
            }))
            .pipe(gulp.dest('build'))
            .on('end', done);
    });
});

// Run tests and product coverage
gulp.task('test', () => {
    return gulp.src('test/*.js')
        .pipe(g.mocha({
            require : [ 'should' ]
        }));
});

// Lint as JS files (including this one)
gulp.task('lint', () => {
    return gulp.src([
        'gulpfile.js',
        'src/js/*.js',
        'test/*.js',
        'lib/*.js',
        '!node_modules/**'
    ])
    .pipe(g.eslint())
    .pipe(g.eslint.format());
});

// Serve files for local development
gulp.task('serve', done => {
    const port = argv.p || 3000;

    express()
        .use(express.static('build'))
        .use((req, res) => {
            res.status(404)
                .sendFile(path.join(__dirname, '/build/error.html'));
        })
        .listen(port, () => {
            g.util.log('Server listening on port', port);
            done();
        });
});

// Check deps with David service
gulp.task('deps', () => {
    return gulp.src('package.json')
        .pipe(g.david({ update : true }))
        .pipe(gulp.dest('.'));
});

// Examine package.json for unused deps (except for frontend and gulp)
gulp.task('package', g.depcheck({
    ignoreMatches : [
        'babel-preset-es2015',
        'bootstrap',
        'gulp-*',
        'hammerjs',
        'jquery-hammerjs',
        'jquery',
        'should',
        'velocity-animate'
    ]
}));

// Watch certain files
gulp.task('watch', () => {
    const paths = [
        'src/**/*.*',
        'test/*.js',
        'lib/*.js'
    ];

    gulp.watch(paths, [ 'build' ])
        .on('change', e => {
            g.util.log('File', e.path, 'was', e.type);
        });
});

// Build Macro
gulp.task('build', done => {
    g.sequence(
        'clean',
        [ 'static', 'styles', 'scripts', 'partials', 'authors' ],
        'posts',
        'pages',
        'test',
        'lint'
    )(done);
});

// Deploy to AWS S3
gulp.task('deploy', () => {
    const publisher = g.awspublish.create({
        accessKeyId     : process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey : process.env.AWS_SECRET_ACCESS_KEY,
        region          : 'us-east-1',
        params          : { Bucket : argv.b }
    });

    return gulp.src('build/**')
        .pipe(g.awspublish.gzip())
        .pipe(publisher.publish())
        .pipe(publisher.sync())
        .pipe(g.awspublish.reporter());
});

// What to do when you run `$ gulp`
gulp.task('default', done => {
    g.sequence(
        'deps',
        'package',
        'build',
        'watch',
        'serve'
    )(done);
});
<|endoftext|>


<commit_before>require.paths.unshift(require('path').join(__dirname, '..'));

var events = require('events'),
    util = require('util');

var definers  = require('resourcer/schema').definers;
var resourcer = require('resourcer');

//
// CRUD
//
this.Resource = function () {};

this.Resource.filter = require('resourcer/resource/view').filter;

this.Resource.views = {};

this.Resource.init = function () {
    this.emit('init', this);
};
this.Resource.register = function () {
    return resourcer.register(this.resource, this);
};
this.Resource.unregister = function () {
    return resourcer.unregister(this.resource);
};
this.Resource._request = function (/* method, [key, obj], callback */) {
    var args     = Array.prototype.slice.call(arguments),
        that     = this,
        callback = args.pop(),
        method   = args.shift(),
        key      = args.shift(),
        obj      = args.shift();

    key && args.push(key);
    obj && args.push(obj.properties ? obj.properties : obj);

    this.emit(method + "Begin", obj);

    args.push(function (e, result) {
        var Factory;

        if (e) {
            if (e.status >= 500) {
                throw new(Error)(e);
            } else {
                that.emit("error", e, obj);
                callback(e);
            }
        } else {
            if (Array.isArray(result)) {
                result = result.map(function (r) {
                    return resourcer.instantiate.call(that, r);
                });
            } else {
                if (['get', 'find', 'view'].indexOf(method) !== -1) {
                    result = resourcer.instantiate.call(that, result);
                } else if (method === 'update') {
                    that.connection.cache.update(key, obj);
                } else {
                    that.connection.cache.put(key, obj);
                }
            }
            that.emit(method + "End", result, obj);
            callback(null, result);
        }
    });
    this.connection[method].apply(this.connection, args);
};
this.Resource.get = function (id, callback) {
    if (! id) { throw new(Error)('key is undefined') }
    return this._request("get", id, callback);
};
this.Resource.create = function (attrs, callback) {
    var instance = new(this)(attrs);
    instance.save(function (e, res) {
        if (res) {
            instance._id  = instance._id || res.id;
            res.rev && (instance._rev = res.rev);
        }
        callback(e, instance);
    });
};
this.Resource.save = function (obj, callback) {
    return this._request("save", obj.key, obj, callback);
};
this.Resource.destroy = function (key, callback) {
    return this._request("destroy", key, callback);
};
this.Resource.update = function (key, obj, callback) {
    return this._request("update", key, obj, callback);
};
this.Resource.all = function (callback) {
    return this._request("all", callback);
};
this.Resource.view = function (path, params, callback) {
    return this._request("view", path, params, callback);
};
this.Resource.find = function (conditions, callback) {
    if (typeof(conditions) !== "object") {
        throw new(TypeError)("`find` takes an object as first argument.");
    }
    return this._request("find", conditions, callback);
};
this.Resource.__defineGetter__('connection', function () {
    return this._connection || resourcer.connection;
});
this.Resource.__defineSetter__('connection', function (val) {
    return this._connection = val;
});
this.Resource.__defineGetter__('engine', function () {
    return this._engine || resourcer.engine;
});
this.Resource.__defineSetter__('engine', function (val) {
    return this._engine = val;
});
this.Resource.use     = function () { return resourcer.use.apply(this, arguments) };
this.Resource.connect = function () { return resourcer.connect.apply(this, arguments) };

this.Resource.__defineGetter__('resource', function () {
    return this._resource;
});
this.Resource.__defineSetter__('resource', function (name) {
    return this._resource = name;
});
this.Resource.property = function (name, typeOrSchema, schema) {
    var definer = {};
    var type = (function () {
        switch (typeof(typeOrSchema)) {
            case "string":    return typeOrSchema;
            case "function":  return typeOrSchema.name.toLowerCase();
            case "object":    schema = typeOrSchema;
            case "undefined": return "string";
            default:          throw new(Error)("Argument Error");
        }
    })();

    schema = schema || {};
    schema.type = schema.type || type;

    this.schema.properties[name] = definer.property = schema;

    resourcer.mixin(definer, definers.all, definers[schema.type] || {});

    return definer;
};

this.Resource.define = function (schema) {
    return resourcer.mixin(this.schema, schema);
};
this.Resource.__defineGetter__('properties', function () {
    return this.schema.properties;
});
this.Resource.__defineSetter__('key', function (val) { return this._key = val });
this.Resource.__defineGetter__('key', function ()    { return this._key });

//
// Synchronize a Resource's design document with the database.
//
this.Resource.sync = function (callback) {
    var that = this,
        id   = ["_design", this.resource].join('/');

    if (this.connection.protocol === 'database') {
        this._design = this._design || {};

        if (this._design._rev) { return callback(null) }

        this.connection.head(id, function (e, headers, status) {
            if (headers.etag) {
                that._design._rev = headers.etag.slice(1, -1);
            }
            that.connection.put(id, that._design, function (e, res) {
                if (e) {/* TODO: Catch errors here. Needs a rewrite, because of the race */}
                        /* condition, when the design doc is trying to be written in parallel */
                else {
                    // We might not need to wait for the document to be
                    // persisted, before returning it. If for whatever reason
                    // the insert fails, it'll just re-attempt it. For now though,
                    // to be on the safe side, we wait.
                    that._design._rev = res.rev;
                    callback(null, that._design);
                }
            });
        });
    } else { callback(null) }
};

//
// Prototype
//
this.Resource.prototype = {
    save: function (callback) {
        var that = this;
        if (this.isValid) {
            this.constructor.save(this, function (e, res) {
                if (!e) { that.isNewRecord = false }
                callback(e, res);
            });
        } else {
        }
    },
    update: function (obj, callback) {
        this.properties = obj;
        return this.save(callback);
    },
    destroy: function () {},
    reload: function () {},
    isNewRecord: true,
    readProperty: function (k) {
        return this._properties[k];
    },
    writeProperty: function (k, val) {
        return this._properties[k] = val;
    },

    get key () {
        return this[this.constructor.key];
    },
    get id () {
        if (this.constructor.key === '_id') { return this._id }
        else                                { return undefined }
    },
    get isValid () {
        return true;
    },

    get properties () {
        return this._properties;
    },
    set properties (props) {
        var that = this;
        Object.keys(props).forEach(function (k) {
            that[k] = props[k];
        });
        return props;
    },
    toJSON: function () {
        return resourcer.clone(this._properties);
    },
    inspect: function () {
        return util.inspect(this._properties);
    },
    toString: function () {
        return JSON.stringify(this._properties);
    }
};

resourcer.clone = function (obj) {
    var clone = {};
    var keys = Object.keys(obj);
    for (var i = 0; i < keys.length; i ++) {
        clone[keys[i]] = obj[keys[i]];
    }
    return clone;
};

resourcer.instantiate = function (obj) {
    var instance, Factory;

    obj.resource = obj.resource || this.resource;
    Factory = resourcer.resources[obj.resource];

    if (instance = this.connection.cache.get(obj[this.key])) {
        return instance.toJSON instanceof Function ? instance : new(Factory)(instance);
    } else if (Factory) {
        return new(Factory)(obj);
    } else {
        throw new(Error)("unrecognised resource '" + obj.resource + "'");
    }
};

//
// Utilities
//
function capitalize(str) {
    return str && str[0].toUpperCase() + str.slice(1);
}
<commit_msg>(new) ctime & mtime on resources<commit_after>require.paths.unshift(require('path').join(__dirname, '..'));

var events = require('events'),
    util = require('util');

var definers  = require('resourcer/schema').definers;
var resourcer = require('resourcer');

//
// CRUD
//
this.Resource = function () {};

this.Resource.filter = require('resourcer/resource/view').filter;

this.Resource.views = {};

this.Resource.init = function () {
    this.emit('init', this);
};
this.Resource.register = function () {
    return resourcer.register(this.resource, this);
};
this.Resource.unregister = function () {
    return resourcer.unregister(this.resource);
};
this.Resource._request = function (/* method, [key, obj], callback */) {
    var args     = Array.prototype.slice.call(arguments),
        that     = this,
        callback = args.pop(),
        method   = args.shift(),
        key      = args.shift(),
        obj      = args.shift();

    key && args.push(key);
    obj && args.push(obj.properties ? obj.properties : obj);

    this.emit(method + "Begin", obj);

    args.push(function (e, result) {
        var Factory;

        if (e) {
            if (e.status >= 500) {
                throw new(Error)(e);
            } else {
                that.emit("error", e, obj);
                callback(e);
            }
        } else {
            if (Array.isArray(result)) {
                result = result.map(function (r) {
                    return resourcer.instantiate.call(that, r);
                });
            } else {
                if (['get', 'find', 'view'].indexOf(method) !== -1) {
                    result = resourcer.instantiate.call(that, result);
                } else if (method === 'update') {
                    that.connection.cache.update(key, obj);
                } else {
                    that.connection.cache.put(key, obj);
                }
            }
            that.emit(method + "End", result, obj);
            callback(null, result);
        }
    });
    this.connection[method].apply(this.connection, args);
};
this.Resource.get = function (id, callback) {
    if (! id) { throw new(Error)('key is undefined') }
    return this._request("get", id, callback);
};
this.Resource.create = function (attrs, callback) {
    attrs.ctime = attrs.mtime = Date.now();

    var instance = new(this)(attrs);

    instance.save(function (e, res) {
        if (res) {
            instance._id  = instance._id || res.id;
            res.rev && (instance._rev = res.rev);
        }
        callback(e, instance);
    });
};
this.Resource.save = function (obj, callback) {
    obj.mtime = Date.now();
    return this._request("save", obj.key, obj, callback);
};
this.Resource.destroy = function (key, callback) {
    return this._request("destroy", key, callback);
};
this.Resource.update = function (key, obj, callback) {
    obj.mtime = Date.now();
    return this._request("update", key, obj, callback);
};
this.Resource.all = function (callback) {
    return this._request("all", callback);
};
this.Resource.view = function (path, params, callback) {
    return this._request("view", path, params, callback);
};
this.Resource.find = function (conditions, callback) {
    if (typeof(conditions) !== "object") {
        throw new(TypeError)("`find` takes an object as first argument.");
    }
    return this._request("find", conditions, callback);
};
this.Resource.__defineGetter__('connection', function () {
    return this._connection || resourcer.connection;
});
this.Resource.__defineSetter__('connection', function (val) {
    return this._connection = val;
});
this.Resource.__defineGetter__('engine', function () {
    return this._engine || resourcer.engine;
});
this.Resource.__defineSetter__('engine', function (val) {
    return this._engine = val;
});
this.Resource.use     = function () { return resourcer.use.apply(this, arguments) };
this.Resource.connect = function () { return resourcer.connect.apply(this, arguments) };

this.Resource.__defineGetter__('resource', function () {
    return this._resource;
});
this.Resource.__defineSetter__('resource', function (name) {
    return this._resource = name;
});
this.Resource.property = function (name, typeOrSchema, schema) {
    var definer = {};
    var type = (function () {
        switch (typeof(typeOrSchema)) {
            case "string":    return typeOrSchema;
            case "function":  return typeOrSchema.name.toLowerCase();
            case "object":    schema = typeOrSchema;
            case "undefined": return "string";
            default:          throw new(Error)("Argument Error");
        }
    })();

    schema = schema || {};
    schema.type = schema.type || type;

    this.schema.properties[name] = definer.property = schema;

    resourcer.mixin(definer, definers.all, definers[schema.type] || {});

    return definer;
};

this.Resource.define = function (schema) {
    return resourcer.mixin(this.schema, schema);
};
this.Resource.__defineGetter__('properties', function () {
    return this.schema.properties;
});
this.Resource.__defineSetter__('key', function (val) { return this._key = val });
this.Resource.__defineGetter__('key', function ()    { return this._key });

//
// Synchronize a Resource's design document with the database.
//
this.Resource.sync = function (callback) {
    var that = this,
        id   = ["_design", this.resource].join('/');

    if (this.connection.protocol === 'database') {
        this._design = this._design || {};

        if (this._design._rev) { return callback(null) }

        this.connection.head(id, function (e, headers, status) {
            if (headers.etag) {
                that._design._rev = headers.etag.slice(1, -1);
            }
            that.connection.put(id, that._design, function (e, res) {
                if (e) {/* TODO: Catch errors here. Needs a rewrite, because of the race */}
                        /* condition, when the design doc is trying to be written in parallel */
                else {
                    // We might not need to wait for the document to be
                    // persisted, before returning it. If for whatever reason
                    // the insert fails, it'll just re-attempt it. For now though,
                    // to be on the safe side, we wait.
                    that._design._rev = res.rev;
                    callback(null, that._design);
                }
            });
        });
    } else { callback(null) }
};

//
// Prototype
//
this.Resource.prototype = {
    save: function (callback) {
        var that = this;
        if (this.isValid) {
            this.constructor.save(this, function (e, res) {
                if (!e) { that.isNewRecord = false }
                callback(e, res);
            });
        } else {
        }
    },
    update: function (obj, callback) {
        this.properties = obj;
        return this.save(callback);
    },
    destroy: function () {},
    reload: function () {},
    isNewRecord: true,
    readProperty: function (k) {
        return this._properties[k];
    },
    writeProperty: function (k, val) {
        return this._properties[k] = val;
    },

    get key () {
        return this[this.constructor.key];
    },
    get id () {
        if (this.constructor.key === '_id') { return this._id }
        else                                { return undefined }
    },
    get isValid () {
        return true;
    },

    get properties () {
        return this._properties;
    },
    set properties (props) {
        var that = this;
        Object.keys(props).forEach(function (k) {
            that[k] = props[k];
        });
        return props;
    },
    toJSON: function () {
        return resourcer.clone(this._properties);
    },
    inspect: function () {
        return util.inspect(this._properties);
    },
    toString: function () {
        return JSON.stringify(this._properties);
    }
};

resourcer.clone = function (obj) {
    var clone = {};
    var keys = Object.keys(obj);
    for (var i = 0; i < keys.length; i ++) {
        clone[keys[i]] = obj[keys[i]];
    }
    return clone;
};

resourcer.instantiate = function (obj) {
    var instance, Factory;

    obj.resource = obj.resource || this.resource;
    Factory = resourcer.resources[obj.resource];

    if (instance = this.connection.cache.get(obj[this.key])) {
        return instance.toJSON instanceof Function ? instance : new(Factory)(instance);
    } else if (Factory) {
        return new(Factory)(obj);
    } else {
        throw new(Error)("unrecognised resource '" + obj.resource + "'");
    }
};

//
// Utilities
//
function capitalize(str) {
    return str && str[0].toUpperCase() + str.slice(1);
}
<|endoftext|>


<commit_before>// @flow

import {
  type ActionMeta,
  type OptionType,
  type OptionsType,
  type ValueType,
} from '../types';

export type OptionContextType = 'menu' | 'value';

export type GuidanceContextType = 'menu' | 'input' | 'value';

export type AriaLiveProp = 'polite' | 'off' | 'assertive';

export type AriaSelectionType = ActionMeta & {
  value?: ValueType,
};

export type AriaGuidanceProps = {
  // String value of selectProp aria-label
  'aria-label'?: string,
  // String indicating user's current context and availabile keyboard interactivity
  context: GuidanceContextType,
  // Boolean value of selectProp isSearchable
  isSearchable?: boolean,
  // Boolean value of selectProp isMulti
  isMulti?: boolean,
  // Boolean value of selectProp isDisabled
  isDisabled?: boolean,
  // Boolean value of selectProp tabSelectsValue
  tabSelectsValue?: boolean,
};

export type AriaOnChangeProps = ActionMeta & {
  // selected option(s) of the Select
  selectValue?: ValueType,
  // String derived label from selected or removed option/value
  label?: string,
  // Boolean indicating if the selected menu option is disabled
  isDisabled?: boolean,
};

export type AriaOnFilterProps = {
  // String indicating current inputValue of the input
  inputValue: string,
  // String dervied from selectProp screenReaderStatus
  resultsMessage: string,
};

export type AriaOnFocusProps = {
  // String indicating whether the option was focused in the menu or as (multi-) value
  context: OptionContextType,
  // Option that is being focused
  focused: OptionType,
  // Boolean indicating whether focused menu option has been disabled
  isDisabled?: boolean,
  // Boolean indicating whether focused menu option is an already selcted option
  isSelected?: boolean,
  // String derived label from focused option/value
  label?: string,
  // Options provided as props to Select used to determine indexing
  options?: OptionsType,
  // selected option(s) of the Select
  selectValue?: ValueType,
};

export type AriaLiveMessagesProps = {
  // Guidance message used to convey component state and specific keyboard interactivity
  guidance?: (tprops: AriaGuidanceProps) => string,
  // OnChange message used to convey changes to value but also called when user selects disabled option
  onChange?: (props: AriaOnChangeProps) => string,
  // OnFilter message used to convey information about filtered results displayed in the menu
  onFilter?: (props: AriaOnFilterProps) => string,
  // OnFocus message used to convey information about the currently focused option or value
  onFocus?: (props: AriaOnFocusProps) => string,
};

export const defaultAriaLiveMessages = {
  guidance: (props: AriaGuidanceProps) => {
    const {
      isSearchable,
      isMulti,
      isDisabled,
      tabSelectsValue,
      context,
    } = props;
    switch (context) {
      case 'menu':
        return `Use Up and Down to choose options${
          isDisabled
            ? ''
            : ', press Enter to select the currently focused option'
        }, press Escape to exit the menu${
          tabSelectsValue
            ? ', press Tab to select the option and exit the menu'
            : ''
        }.`;
      case 'input':
        return `${props['aria-label'] || 'Select'} is focused ${
          isSearchable ? ',type to refine list' : ''
        }, press Down to open the menu, ${
          isMulti ? ' press left to focus selected values' : ''
        }`;
      case 'value':
        return 'Use left and right to toggle between focused values, press Backspace to remove the currently focused value';
      default:
        return '';
    }
  },

  onChange: (props: AriaOnChangeProps) => {
    const { action, label = '', isDisabled } = props;
    switch (action) {
      case 'deselect-option':
      case 'pop-value':
      case 'remove-value':
        return `option ${label}, deselected.`;
      case 'select-option':
        return isDisabled
          ? `option ${label} is disabled. Select another option.`
          : `option ${label}, selected.`;
      default:
        return '';
    }
  },

  onFocus: (props: AriaOnFocusProps) => {
    const {
      context,
      focused = {},
      options,
      label = '',
      selectValue,
      isDisabled,
      isSelected,
    } = props;

    const getArrayIndex = (arr, item) =>
      arr && arr.length ? `${arr.indexOf(item) + 1} of ${arr.length}` : '';

    if (context === 'value' && selectValue) {
      return `value ${label} focused, ${getArrayIndex(selectValue, focused)}.`;
    }

    if (context === 'menu') {
      const disabled = isDisabled ? ' disabled' : '';
      const status = `${isSelected ? 'selected' : 'focused'}${disabled}`;
      return `option ${label} ${status}, ${getArrayIndex(options, focused)}.`;
    }
    return '';
  },

  onFilter: (props: AriaOnFilterProps) => {
    const { inputValue, resultsMessage } = props;
    return `${resultsMessage}${
      inputValue ? ' for search term ' + inputValue : ''
    }.`;
  },
};
<commit_msg>Fix props typo<commit_after>// @flow

import {
  type ActionMeta,
  type OptionType,
  type OptionsType,
  type ValueType,
} from '../types';

export type OptionContextType = 'menu' | 'value';

export type GuidanceContextType = 'menu' | 'input' | 'value';

export type AriaLiveProp = 'polite' | 'off' | 'assertive';

export type AriaSelectionType = ActionMeta & {
  value?: ValueType,
};

export type AriaGuidanceProps = {
  // String value of selectProp aria-label
  'aria-label'?: string,
  // String indicating user's current context and availabile keyboard interactivity
  context: GuidanceContextType,
  // Boolean value of selectProp isSearchable
  isSearchable?: boolean,
  // Boolean value of selectProp isMulti
  isMulti?: boolean,
  // Boolean value of selectProp isDisabled
  isDisabled?: boolean,
  // Boolean value of selectProp tabSelectsValue
  tabSelectsValue?: boolean,
};

export type AriaOnChangeProps = ActionMeta & {
  // selected option(s) of the Select
  selectValue?: ValueType,
  // String derived label from selected or removed option/value
  label?: string,
  // Boolean indicating if the selected menu option is disabled
  isDisabled?: boolean,
};

export type AriaOnFilterProps = {
  // String indicating current inputValue of the input
  inputValue: string,
  // String dervied from selectProp screenReaderStatus
  resultsMessage: string,
};

export type AriaOnFocusProps = {
  // String indicating whether the option was focused in the menu or as (multi-) value
  context: OptionContextType,
  // Option that is being focused
  focused: OptionType,
  // Boolean indicating whether focused menu option has been disabled
  isDisabled?: boolean,
  // Boolean indicating whether focused menu option is an already selcted option
  isSelected?: boolean,
  // String derived label from focused option/value
  label?: string,
  // Options provided as props to Select used to determine indexing
  options?: OptionsType,
  // selected option(s) of the Select
  selectValue?: ValueType,
};

export type AriaLiveMessagesProps = {
  // Guidance message used to convey component state and specific keyboard interactivity
  guidance?: (props: AriaGuidanceProps) => string,
  // OnChange message used to convey changes to value but also called when user selects disabled option
  onChange?: (props: AriaOnChangeProps) => string,
  // OnFilter message used to convey information about filtered results displayed in the menu
  onFilter?: (props: AriaOnFilterProps) => string,
  // OnFocus message used to convey information about the currently focused option or value
  onFocus?: (props: AriaOnFocusProps) => string,
};

export const defaultAriaLiveMessages = {
  guidance: (props: AriaGuidanceProps) => {
    const {
      isSearchable,
      isMulti,
      isDisabled,
      tabSelectsValue,
      context,
    } = props;
    switch (context) {
      case 'menu':
        return `Use Up and Down to choose options${
          isDisabled
            ? ''
            : ', press Enter to select the currently focused option'
        }, press Escape to exit the menu${
          tabSelectsValue
            ? ', press Tab to select the option and exit the menu'
            : ''
        }.`;
      case 'input':
        return `${props['aria-label'] || 'Select'} is focused ${
          isSearchable ? ',type to refine list' : ''
        }, press Down to open the menu, ${
          isMulti ? ' press left to focus selected values' : ''
        }`;
      case 'value':
        return 'Use left and right to toggle between focused values, press Backspace to remove the currently focused value';
      default:
        return '';
    }
  },

  onChange: (props: AriaOnChangeProps) => {
    const { action, label = '', isDisabled } = props;
    switch (action) {
      case 'deselect-option':
      case 'pop-value':
      case 'remove-value':
        return `option ${label}, deselected.`;
      case 'select-option':
        return isDisabled
          ? `option ${label} is disabled. Select another option.`
          : `option ${label}, selected.`;
      default:
        return '';
    }
  },

  onFocus: (props: AriaOnFocusProps) => {
    const {
      context,
      focused = {},
      options,
      label = '',
      selectValue,
      isDisabled,
      isSelected,
    } = props;

    const getArrayIndex = (arr, item) =>
      arr && arr.length ? `${arr.indexOf(item) + 1} of ${arr.length}` : '';

    if (context === 'value' && selectValue) {
      return `value ${label} focused, ${getArrayIndex(selectValue, focused)}.`;
    }

    if (context === 'menu') {
      const disabled = isDisabled ? ' disabled' : '';
      const status = `${isSelected ? 'selected' : 'focused'}${disabled}`;
      return `option ${label} ${status}, ${getArrayIndex(options, focused)}.`;
    }
    return '';
  },

  onFilter: (props: AriaOnFilterProps) => {
    const { inputValue, resultsMessage } = props;
    return `${resultsMessage}${
      inputValue ? ' for search term ' + inputValue : ''
    }.`;
  },
};
<|endoftext|>


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

// This code is a mix of these three sample programs:
// https://github.com/spark/google-cloud-datastore-tutorial/blob/master/tutorial.js
// https://cloud.google.com/appengine/docs/flexible/nodejs/writing-and-responding-to-pub-sub-messages
// https://cloud.google.com/appengine/docs/flexible/nodejs/using-cloud-datastore

// [START app]
'use strict';

// [START setup]

var express = require('express');

var app = express();

// I'm not really sure if this is needed
app.enable('trust proxy');

// By default, the client will authenticate using the service account file
// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
// the project specified by the GCLOUD_PROJECT environment variable. See
// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
// These environment variables are set automatically on Google App Engine
var Datastore = require('@google-cloud/datastore');

// Instantiate a datastore client
var datastore = Datastore();

//By default, the client will authenticate using the service account file
//specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
//the project specified by the GCLOUD_PROJECT environment variable. See
//https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
//These environment variables are set automatically on Google App Engine
var PubSub = require('@google-cloud/pubsub');

//Instantiate a pubsub client
var pubsub = PubSub();

//The following environment variables are set by app.yaml when running on GAE,
//but will need to be manually set when running locally.
var PUBSUB_VERIFICATION_TOKEN = process.env.PUBSUB_VERIFICATION_TOKEN;

var topic = pubsub.topic(process.env.PUBSUB_TOPIC);

var subscription = pubsub.subscription(process.env.PUBSUB_SUBSCRIPTION_NAME);

// [END setup]

// This code from here:
// https://github.com/spark/google-cloud-datastore-tutorial/blob/master/tutorial.js
function storeEvent(message) {
    var key = datastore.key('ParticleEvent');

    // You can uncomment some of the other things if you want to store them in the database
    var obj = {
		gc_pub_sub_id: message.id,
		device_id: message.attributes.device_id,
		event: message.attributes.event,
		published_at: message.attributes.published_at,
	    	temperature: message.data
	}

    // Copy the data in message.data, the Particle event data, as top-level
    // elements in obj. This breaks the data out into separate columns.
    for (var prop in message.data) {
        if (message.data.hasOwnProperty(prop)) {
            obj[prop] = message.data[prop];
        }
    }

    datastore.save({
        key: key,
        data: obj
    }, function(err) {
		if(err) {
			console.log('There was an error storing the event', err);
		}
		console.log('stored in datastore', obj);
    });

};

subscription.on('message', function(message) {
	console.log('event received', message);
	// Called every time a message is received.
	// message.id = ID used to acknowledge its receival.
	// message.data = Contents of the message.
	// message.attributes = Attributes of the message.
	storeEvent(message);
	message.ack();
});

// [START listen]
var server = app.listen(process.env.PORT || 8080, function () {
  console.log('App listening on port %s', server.address().port);
  console.log('Press Ctrl+C to quit.');
});
// [END listen]
// [END app]

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

// This code is a mix of these three sample programs:
// https://github.com/spark/google-cloud-datastore-tutorial/blob/master/tutorial.js
// https://cloud.google.com/appengine/docs/flexible/nodejs/writing-and-responding-to-pub-sub-messages
// https://cloud.google.com/appengine/docs/flexible/nodejs/using-cloud-datastore

// [START app]
'use strict';

// [START setup]

var express = require('express');

var app = express();

// I'm not really sure if this is needed
app.enable('trust proxy');

// By default, the client will authenticate using the service account file
// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
// the project specified by the GCLOUD_PROJECT environment variable. See
// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
// These environment variables are set automatically on Google App Engine
var Datastore = require('@google-cloud/datastore');

// Instantiate a datastore client
var datastore = Datastore();

//By default, the client will authenticate using the service account file
//specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
//the project specified by the GCLOUD_PROJECT environment variable. See
//https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
//These environment variables are set automatically on Google App Engine
var PubSub = require('@google-cloud/pubsub');

//Instantiate a pubsub client
var pubsub = PubSub();

//The following environment variables are set by app.yaml when running on GAE,
//but will need to be manually set when running locally.
var PUBSUB_VERIFICATION_TOKEN = process.env.PUBSUB_VERIFICATION_TOKEN;

var topic = pubsub.topic(process.env.PUBSUB_TOPIC);

var subscription = pubsub.subscription(process.env.PUBSUB_SUBSCRIPTION_NAME);

// [END setup]

// This code from here:
// https://github.com/spark/google-cloud-datastore-tutorial/blob/master/tutorial.js
function storeEvent(message) {
    var key = datastore.key('officedata');

    // You can uncomment some of the other things if you want to store them in the database
    var obj = {
		gc_pub_sub_id: message.id,
		device_id: message.attributes.device_id,
		event: message.attributes.event,
		published_at: message.attributes.published_at,
	    	temperature: message.data
	}

    // Copy the data in message.data, the Particle event data, as top-level
    // elements in obj. This breaks the data out into separate columns.
    for (var prop in message.data) {
        if (message.data.hasOwnProperty(prop)) {
            obj[prop] = message.data[prop];
        }
    }

    datastore.save({
        key: key,
        data: obj
    }, function(err) {
		if(err) {
			console.log('There was an error storing the event', err);
		}
		console.log('stored in datastore', obj);
    });

};

subscription.on('message', function(message) {
	console.log('event received', message);
	// Called every time a message is received.
	// message.id = ID used to acknowledge its receival.
	// message.data = Contents of the message.
	// message.attributes = Attributes of the message.
	storeEvent(message);
	message.ack();
});

// [START listen]
var server = app.listen(process.env.PORT || 8080, function () {
  console.log('App listening on port %s', server.address().port);
  console.log('Press Ctrl+C to quit.');
});
// [END listen]
// [END app]

module.exports = app;
<|endoftext|>


<commit_before>
module.exports = function(app){

        var route = require('./_gen/event.gen')(app);

    /**
     * Custom Code Goes here
     */
	route.auth_event_hide = function(req, res, next){
		if(req.user){
			if(req.is_admin){
				return next();
			}
			if(req.event.data.user && req.event.data.user._id == req.user._id){
				return next();
			}
			/*for(var i in req.event.accounts){
				if(req.event.accounts[i]._id == req.user._id){
					return next();
				}
			}*/
		}
		return next(new Error(403));
	}

	var _init = route.init;
	route.init = function(uri){
		_init(uri);
		if(!uri) uri = '/events';
		app.all(uri + '/:event/hide',[
			route.auth_event_hide,
			function(req, res, next){
				if(!req.event){
					return next(new Error(404));
				}
				req.event.mutedDate = new Date();
				return req.event.save(function(err){
					if(err) return next(err);
					return next();
				});
			},
			route.render_detail
		]);

	}
    return route;

}<commit_msg>fixing delete route<commit_after>
module.exports = function(app){

        var route = require('./_gen/event.gen')(app);

    /**
     * Custom Code Goes here
     */
	route.auth_event_hide = function(req, res, next){
		if(req.user){
			if(req.is_admin){
				return next();
			}
			if(req.event.data.user && req.user._id.equals(req.event.data.user._id)){
				return next();
			}
			/*for(var i in req.event.accounts){
				if(req.event.accounts[i]._id == req.user._id){
					return next();
				}
			}*/
		}
		return next(new Error(403));
	}

	var _init = route.init;
	route.init = function(uri){
		_init(uri);
		if(!uri) uri = '/events';
		app.all(uri + '/:event/hide',[
			route.auth_event_hide,
			function(req, res, next){
				if(!req.event){
					return next(new Error(404));
				}
				req.event.mutedDate = new Date();
				return req.event.save(function(err){
					if(err) return next(err);
					return next();
				});
			},
			route.render_detail
		]);

	}
    return route;

}<|endoftext|>


<commit_before><commit_msg>Add config for a details component<commit_after>module.exports = {
  title: 'Details',
  status: 'wip',
  context: {
    summary: 'Summary text',
    text: 'Details text'
  },
  arguments: ['summary', 'text']
}
<|endoftext|>


<commit_before>'use strict';

angular.module('stew')
  .controller('StewdentController',
	      ['$scope', '$http', '$modal', '$location', '$window', 'Stewdent', 'token', 'StewdentCreate', 'usSpinnerService', 'lodash',
	       function ($scope, $http, $modal, $location, $window, Stewdent, token, StewdentCreate, usSpinnerService, lodash) {

		 $scope.user = token.getUser();

		 $scope.dobDateOptions = {
		   dateFormat: 'dd/mm/yy',
		   maxDate: -1
		 };

		 $scope.uniYearDateOptions = {
		   dateFormat: 'yyyy'
		 };

		 $scope.errors = [];

		 $scope.genders = ['Male', 'Female', 'Not specified'];
		 $scope.states = ['QLD', 'NSW', 'VIC', 'TAS', 'SA', 'WA', 'NT', 'ACT'];
		 $scope.unis = [
		   'Australian Catholic University',
		   'Australian National University',
		   'Bond University',
		   'Central Queensland University',
		   'Charles Darwin University',
		   'Charles Sturt University',
		   'Curtin University',
		   'Deakin University',
		   'Edith Cowan University',
		   'Federation University',
		   'Flinders University',
		   'Griffith University',
		   'James Cook University',
		   'La Trobe University',
		   'Macquarie University',
		   'Monash University',
		   'Murdoch University',
		   'Queensland University of Technology',
		   'RMIT University',
		   'Southern Cross University',
		   'Swinburne University of Technology',
		   'University of Adelaide',
		   'University of Canberra',
		   'University of Melbourne',
		   'University of New England',
		   'University of New South Wales',
		   'University of Newcastle',
		   'University of Notre Dame',
		   'University of Queensland',
		   'University of South Australia',
		   'University of Southern Queensland',
		   'University of Sydney',
		   'University of Tasmania',
		   'University of Technology Sydney',
		   'University of the Sunshine Coast',
		   'University of Western Australia',
		   'University of Western Sydney',
		   'University of Wollongong',
		   'Victoria University'
		 ];

		 $scope.create = function () {

		   // open a modal for confimation
		   var confirmModal = $modal.open({
		     templateUrl: 'static/js/views/stewdent/confirm-Modal.html',
		     controller: 'ConfirmationController'
		   });
		   // if the modal is confirmed then continue
		   confirmModal.result.then(function() {

		     usSpinnerService.spin('spinner-1');
		     $scope.errors = [];

		     $window.scrollTo(0,0);

		     // send data to backend
		     $http.post('/newStew/', $scope.stewdent).
		       success(function(data) {
			 $http.post('/skill/' + data.pk, $scope.skills).
			   success(function(data) {
			     $scope.clear();
			     usSpinnerService.stop('spinner-1');
			     $scope.open();
			   })
			   .error(function(data) {
			     alert("Oooops, something is broken.  We're still in beta, please contact thestewau@gmail.com");
			     console.log(data);
			   });
		       })
		       .error(function(data) {
			 usSpinnerService.stop('spinner-1');
			 for (var key in data) {
			   $scope.errors.push(data[key]);
			 }
			 $scope.errors.push("Something broke! We\'re still in beta so please contact thestewau@gmail.com");
		       });
		   });

		 };

		 // clear the form
		 $scope.clear = function () {
		   $scope.stewdent = {
		     "first_name": "",
		     "last_name": "",
		     "gender": "",
		     "dob": "",
		     "university": "",
		     "student_num": "",
		     "degree": "",
		     "start_year": "",
		     "end_year": "",
		     "occupation": "",
		     "phone_num": "",
		     "student_email": "",
		     "address": "",
		     "city": "",
		     "state": "",
		     "post_code": "",
		     "country": "",
		     "id": ""
		   };
		   $scope.skills = {
		     "computer": ""
		   };
		 };

		 // open the thank you modal, this might soon be removed
		 $scope.open = function () {
		   var stewdentSave = $modal.open({
		     templateUrl: 'thankyou-modal.html',
		     controller: 'ThankyouModalController'
		   });
		 };

		 // logout the user
		 $scope.logout = function() {
		   console.log("logout");
		   token.logout();
		   $location.path('/login');
		 };

		 $scope.toolTipOne =
		   "
" +
		   "Examples for each skill category include but aren’t limited to:" +
		   "
Creative Design - Graphic design, Photoshop editing, Web & App UI design, Infographics, Posters/Flyers
" +
		   "
Tech Design - 2D & 3D modelling, Architecture, CAD, Drafting, Industrial design
" +
		   "
Programming/IT - Wordpress, Website dev, Mobile Apps, Software dev, Database dev
" +
		   "
Online Marketing - Analytics, Social Media, SEO, Traffic generation, Blogging, Web PR
" +
		   "
Writing - Creative writing, Speeches, Reports, Translation, Web content, Proofing/Editing
" +
		   "
Video/Music – Video/Audio editing, Production, Animation, Mastering, Song writing
" +
		   "
Financial - Tax Returns, Accounting
" +
		   "
Research/Analysis - Market Research, User testing, General Research, Database analysis, Data collection
" +
		   "
In-Person – Sales, User testing, Face-to-face marketing, Customer service, Tutoring, Event management
" +
		   "
";
		 $scope.toolTipTwo = "
Please also provide any releveant software you feel competent with, for each skill category.
" +
		   "Eg.
Creative Design - Adobe Photoshop, Illustrator
" +
		   "
Tech Design - Autocad, Revit
";

	       }])
  .controller('ThankyouModalController', ['$scope', '$modalInstance',
					  function($scope, $modalInstance) {
					    $scope.ok = function() {
					      $modalInstance.close();
					    };
					  }])
  .controller('ConfirmationController', ['$scope', '$modalInstance', function($scope, $modalInstance)  {
    $scope.yes = function() {
      $modalInstance.close();
    };

    $scope.no = function() {
      $modalInstance.dismiss();
    };
  }]);
<commit_msg>updated controller with the actual contact email<commit_after>'use strict';

angular.module('stew')
  .controller('StewdentController',
	      ['$scope', '$http', '$modal', '$location', '$window', 'Stewdent', 'token', 'StewdentCreate', 'usSpinnerService', 'lodash',
	       function ($scope, $http, $modal, $location, $window, Stewdent, token, StewdentCreate, usSpinnerService, lodash) {

		 $scope.user = token.getUser();

		 $scope.dobDateOptions = {
		   dateFormat: 'dd/mm/yy',
		   maxDate: -1
		 };

		 $scope.uniYearDateOptions = {
		   dateFormat: 'yyyy'
		 };

		 $scope.errors = [];

		 $scope.genders = ['Male', 'Female', 'Not specified'];
		 $scope.states = ['QLD', 'NSW', 'VIC', 'TAS', 'SA', 'WA', 'NT', 'ACT'];
		 $scope.unis = [
		   'Australian Catholic University',
		   'Australian National University',
		   'Bond University',
		   'Central Queensland University',
		   'Charles Darwin University',
		   'Charles Sturt University',
		   'Curtin University',
		   'Deakin University',
		   'Edith Cowan University',
		   'Federation University',
		   'Flinders University',
		   'Griffith University',
		   'James Cook University',
		   'La Trobe University',
		   'Macquarie University',
		   'Monash University',
		   'Murdoch University',
		   'Queensland University of Technology',
		   'RMIT University',
		   'Southern Cross University',
		   'Swinburne University of Technology',
		   'University of Adelaide',
		   'University of Canberra',
		   'University of Melbourne',
		   'University of New England',
		   'University of New South Wales',
		   'University of Newcastle',
		   'University of Notre Dame',
		   'University of Queensland',
		   'University of South Australia',
		   'University of Southern Queensland',
		   'University of Sydney',
		   'University of Tasmania',
		   'University of Technology Sydney',
		   'University of the Sunshine Coast',
		   'University of Western Australia',
		   'University of Western Sydney',
		   'University of Wollongong',
		   'Victoria University'
		 ];

		 $scope.create = function () {

		   // open a modal for confimation
		   var confirmModal = $modal.open({
		     templateUrl: 'static/js/views/stewdent/confirm-Modal.html',
		     controller: 'ConfirmationController'
		   });
		   // if the modal is confirmed then continue
		   confirmModal.result.then(function() {

		     usSpinnerService.spin('spinner-1');
		     $scope.errors = [];

		     $window.scrollTo(0,0);

		     // send data to backend
		     $http.post('/newStew/', $scope.stewdent).
		       success(function(data) {
			 $http.post('/skill/' + data.pk, $scope.skills).
			   success(function(data) {
			     $scope.clear();
			     usSpinnerService.stop('spinner-1');
			     $scope.open();
			   })
			   .error(function(data) {
			     alert("Oooops, something is broken.  We're still in beta, please contact info@thestew.com.au");
			     console.log(data);
			   });
		       })
		       .error(function(data) {
			 usSpinnerService.stop('spinner-1');
			 for (var key in data) {
			   $scope.errors.push(data[key]);
			 }
			 $scope.errors.push("Something broke! We\'re still in beta so please contact info@thestew.com.au");
		       });
		   });

		 };

		 // clear the form
		 $scope.clear = function () {
		   $scope.stewdent = {
		     "first_name": "",
		     "last_name": "",
		     "gender": "",
		     "dob": "",
		     "university": "",
		     "student_num": "",
		     "degree": "",
		     "start_year": "",
		     "end_year": "",
		     "occupation": "",
		     "phone_num": "",
		     "student_email": "",
		     "address": "",
		     "city": "",
		     "state": "",
		     "post_code": "",
		     "country": "",
		     "id": ""
		   };
		   $scope.skills = {
		     "computer": ""
		   };
		 };

		 // open the thank you modal, this might soon be removed
		 $scope.open = function () {
		   var stewdentSave = $modal.open({
		     templateUrl: 'thankyou-modal.html',
		     controller: 'ThankyouModalController'
		   });
		 };

		 // logout the user
		 $scope.logout = function() {
		   console.log("logout");
		   token.logout();
		   $location.path('/login');
		 };

		 $scope.toolTipOne =
		   "
" +
		   "Examples for each skill category include but aren’t limited to:" +
		   "
Creative Design - Graphic design, Photoshop editing, Web & App UI design, Infographics, Posters/Flyers
" +
		   "
Tech Design - 2D & 3D modelling, Architecture, CAD, Drafting, Industrial design
" +
		   "
Programming/IT - Wordpress, Website dev, Mobile Apps, Software dev, Database dev
" +
		   "
Online Marketing - Analytics, Social Media, SEO, Traffic generation, Blogging, Web PR
" +
		   "
Writing - Creative writing, Speeches, Reports, Translation, Web content, Proofing/Editing
" +
		   "
Video/Music – Video/Audio editing, Production, Animation, Mastering, Song writing
" +
		   "
Financial - Tax Returns, Accounting
" +
		   "
Research/Analysis - Market Research, User testing, General Research, Database analysis, Data collection
" +
		   "
In-Person – Sales, User testing, Face-to-face marketing, Customer service, Tutoring, Event management
" +
		   "
";
		 $scope.toolTipTwo = "
Please also provide any releveant software you feel competent with, for each skill category.
" +
		   "Eg.
Creative Design - Adobe Photoshop, Illustrator
" +
		   "
Tech Design - Autocad, Revit
";

	       }])
  .controller('ThankyouModalController', ['$scope', '$modalInstance',
					  function($scope, $modalInstance) {
					    $scope.ok = function() {
					      $modalInstance.close();
					    };
					  }])
  .controller('ConfirmationController', ['$scope', '$modalInstance', function($scope, $modalInstance)  {
    $scope.yes = function() {
      $modalInstance.close();
    };

    $scope.no = function() {
      $modalInstance.dismiss();
    };
  }]);
<|endoftext|>


<commit_before>frappe.provide('frappe.ui.form');

erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
	"Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Shipping Rule", "Loyalty Program",
	"Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool",
	"Subscription", "Purchase Order", "Journal Entry", "Material Request", "Purchase Receipt", "Landed Cost Item", "Asset"];

erpnext.child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
	"Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction",
	"Landed Cost Item", "Asset Value Adjustment", "Opening Invoice Creation Tool Item", "Subscription Plan"];

frappe.call({
	method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters",
	callback: function(r){
		erpnext.dimension_filters = r.message[0];
		erpnext.default_dimensions = r.message[1];
	}
});

erpnext.doctypes_with_dimensions.forEach((doctype) => {
	frappe.ui.form.on(doctype, {
		onload: function(frm) {
			erpnext.dimension_filters.forEach((dimension) => {
				frappe.model.with_doctype(dimension['document_type'], () => {
					if (frappe.meta.has_field(dimension['document_type'], 'is_group')) {
						frm.set_query(dimension['fieldname'], {
							"is_group": 0
						});
					}

					if (Object.keys(erpnext.default_dimensions).length > 0) {
						if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
							if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) {
								frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
							}
						}

						if (frm.doc.items && frm.doc.items.length && frm.doc.docstatus === 0
							&& (!frm.doc.items[0][dimension['fieldname']])) {
							frm.doc.items[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
						}

						if (frm.doc.accounts && frm.doc.accounts.length && frm.doc.docstatus === 0
							&& (!frm.doc.items[0][dimension['fieldname']])) {
							frm.doc.accounts[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
						}
					}
				});
			});
		},

		company: function(frm) {
			if(frm.doc.company && (Object.keys(erpnext.default_dimensions).length > 0)) {
				erpnext.dimension_filters.forEach((dimension) => {
					if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
						frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
					}
				});
			}
		},
	});
});

erpnext.child_docs.forEach((doctype) => {
	frappe.ui.form.on(doctype, {
		items_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
			});
		},

		accounts_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
			});
		},

		company: function(frm) {
			if(frm.doc.company) {
				erpnext.dimension_filters.forEach((dimension) => {
					frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
				});
			}
		},

		items_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
			});
		},

		accounts_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
			});
		}
	});
});<commit_msg>fix: Default dimension set code cleanup<commit_after>frappe.provide('frappe.ui.form');

let default_dimensions = {};

let doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
	"Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Shipping Rule", "Loyalty Program",
	"Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool",
	"Subscription", "Purchase Order", "Journal Entry", "Material Request", "Purchase Receipt", "Landed Cost Item", "Asset"];

let child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
	"Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction",
	"Landed Cost Item", "Asset Value Adjustment", "Opening Invoice Creation Tool Item", "Subscription Plan"];

frappe.call({
	method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters",
	callback: function(r) {
		erpnext.dimension_filters = r.message[0];
		default_dimensions = r.message[1];
	}
});

doctypes_with_dimensions.forEach((doctype) => {
	frappe.ui.form.on(doctype, {
		onload: function(frm) {
			erpnext.dimension_filters.forEach((dimension) => {
				frappe.model.with_doctype(dimension['document_type'], () => {
					if (frappe.meta.has_field(dimension['document_type'], 'is_group')) {
						frm.set_query(dimension['fieldname'], {
							"is_group": 0
						});
					}
				});
			});
		},

		company: function(frm) {
			if(frm.doc.company && (Object.keys(default_dimensions || {}).length > 0)
				&& default_dimensions[frm.doc.company]) {
				frm.trigger('update_dimension');
			}
		},

		update_dimension: function(frm) {
			erpnext.dimension_filters.forEach((dimension) => {
				if (frm.is_new()) {
					if (frm.doc.company && Object.keys(default_dimensions || {}).length > 0
						&& default_dimensions[frm.doc.company]) {

						if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
							frm.set_value(dimension['fieldname'],
								default_dimensions[frm.doc.company][dimension['document_type']]);
						}

						$.each(frm.doc.items || frm.doc.accounts || [], function(i, row) {
							frappe.model.set_value(row.doctype, row.name, dimension['fieldname'],
								default_dimensions[frm.doc.company][dimension['document_type']])
						});
					}
				}
			});
		}
	});
});

child_docs.forEach((doctype) => {
	frappe.ui.form.on(doctype, {
		items_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
			});
		},

		accounts_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
			});
		},

		items_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
			});
		},

		accounts_add: function(frm, cdt, cdn) {
			erpnext.dimension_filters.forEach((dimension) => {
				var row = frappe.get_doc(cdt, cdn);
				frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
			});
		}
	});
});<|endoftext|>


<commit_before>var XLSX = require('xlsx');
var chai = require('chai');
var expect = chai.expect;
var DTable = require('../../utils/helper/decision-table');
var fs = require('fs');

var excelWorkbookPath = 'test/data/PostBureauRiskCategory2.xlsx';

describe("Internal tests...", function() {
  it('should be that parseXLS() returns an array', function() {

    var csvJson = DTable._.parseXLS(excelWorkbookPath)
    expect(Array.isArray(csvJson)).to.equal(true)
  });

  it('should be that parseCsv() returns an object', function(){
    var csvJson = DTable._.parseXLS(excelWorkbookPath);
    var resultObject = DTable._.parseCsv(csvJson);
    var values = Object.values(resultObject);

    expect(Array.isArray(values)).to.equal(true);

    values.forEach(v => expect(v).to.be.string );
  });

  it('should create the decision object without context property', function(){
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var dto = DTable.csv_to_decision_table(values[0]);
    expect(dto.context).to.be.undefined;
  });

  it('should be that makeContext() returns an object', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var boxedExpression = fs.readFileSync('test\\data\\BoxedExpression-PostBureauRiskCategoryTable-Compressed.txt', { encoding: 'utf8' });
    // boxedExpression = boxedExpression.replace(/(\r\n|\n|\t)/g, '')
    var dto = DTable.csv_to_decision_table(values[0]);
    // debugger;
    var result = DTable._.makeContext(values[0], dto)

    expect(result).to.be.object

    expect(Object.keys(result)).to.eql(['qn', 'expression'])
  })

  it.skip('should parse decision table worksheet correctly', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var boxedExpression = fs.readFileSync('test\\data\\BoxedExpression-PostBureauRiskCategoryTable-Compressed.txt', { encoding: 'utf8' });
    // boxedExpression = boxedExpression.replace(/(\r\n|\n|\t)/g, '')
    var dto = DTable.csv_to_decision_table(values[0]);
    // debugger;
    var result = DTable._.makeContext(values[0], dto).contextString
      + '\n'; //adding this to avoid problem with editor
    // console.log({a: boxedExpression, b: result})
    fs.writeFileSync('file1.txt', boxedExpression, { encoding: 'utf8'})
    fs.writeFileSync('file2.txt', result, { encoding: 'utf8'})
    // expect(boxedExpression).to.equal(result)
    expect(boxedExpression.localeCompare(result)).to.equal(0)
  });

  it('should detect if a sheet is a decision table model', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var result = DTable._.isDecisionTableModel(values[1])

    expect(result).to.equal(false)

    result = DTable._.isDecisionTableModel(values[0])

    expect(result).to.equal(true)
  });

  it('should parse a business model worksheet correctly', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var businessModelCsv = values[1];
    // console.log(businessModelCsv)
    debugger;
    var contextString = DTable._.makeContext(businessModelCsv).expression

    // here is the contextEntry object for the speific model
    //note: you'll have to manually verify this
    var contextEntries = [
      'Post Bureau Risk Category Table',
      {
        "Existing Customer" : "Applicant. ExistingCustomer",
        "Credit Score" : "Report. CreditScore",
        "Application Risk Score": "Affordability Model(Applicant, Product). Application Risk Score"
      }
    ];

    var expected = DTable._.generateContextString(contextEntries);

    expect(contextString).to.equal(expected)
  });

  it('should parse the qualified name of worksheet', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var businessModelCsv = values[1];

    var ctxObj = DTable._.makeContext(businessModelCsv)

    expect(ctxObj.qn).to.be.defined
    expect(ctxObj.qn).to.equal("Post Bureau Risk Category")
  })
});

describe.skip('Excel workbook parsing...', function() {
  it.skip('should parse a workbook to a json-feel boxed expression', function(){
    var jsonFeel = DTable.parseWorkbook(excelWorkbookPath);

    //this jsonFeel should have two keys
    var keys = Object.keys(jsonFeel)
    expect(keys.length).to.equal(2)

    //their values should be a FEEL string
    keys.map(key => {
      var val = jsonFeel[key]
      expect(val).to.be.defined
      expect(val).to.be.string
    })
  });
});

<commit_msg>defunct test case commenting<commit_after>var XLSX = require('xlsx');
var chai = require('chai');
var expect = chai.expect;
var DTable = require('../../utils/helper/decision-table');
var fs = require('fs');

var excelWorkbookPath = 'test/data/PostBureauRiskCategory2.xlsx';

describe("Internal tests...", function() {
  it('should be that parseXLS() returns an array', function() {

    var csvJson = DTable._.parseXLS(excelWorkbookPath)
    expect(Array.isArray(csvJson)).to.equal(true)
  });

  it('should be that parseCsv() returns an object', function(){
    var csvJson = DTable._.parseXLS(excelWorkbookPath);
    var resultObject = DTable._.parseCsv(csvJson);
    var values = Object.values(resultObject);

    expect(Array.isArray(values)).to.equal(true);

    values.forEach(v => expect(v).to.be.string );
  });

  // it('should create the decision object without context property', function(){
  //   var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
  //   var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
  //   var values = Object.values(excelSheetsJsonCsv);
  //   var dto = DTable.csv_to_decision_table(values[0]);
  //   expect(dto.context).to.be.undefined;
  // });

  it('should be that makeContext() returns an object', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var boxedExpression = fs.readFileSync('test\\data\\BoxedExpression-PostBureauRiskCategoryTable-Compressed.txt', { encoding: 'utf8' });
    // boxedExpression = boxedExpression.replace(/(\r\n|\n|\t)/g, '')
    var dto = DTable.csv_to_decision_table(values[0]);
    // debugger;
    var result = DTable._.makeContext(values[0], dto)

    expect(result).to.be.object

    expect(Object.keys(result)).to.eql(['qn', 'expression'])
  })

  it.skip('should parse decision table worksheet correctly', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var boxedExpression = fs.readFileSync('test\\data\\BoxedExpression-PostBureauRiskCategoryTable-Compressed.txt', { encoding: 'utf8' });
    // boxedExpression = boxedExpression.replace(/(\r\n|\n|\t)/g, '')
    var dto = DTable.csv_to_decision_table(values[0]);
    // debugger;
    var result = DTable._.makeContext(values[0], dto).contextString
      + '\n'; //adding this to avoid problem with editor
    // console.log({a: boxedExpression, b: result})
    fs.writeFileSync('file1.txt', boxedExpression, { encoding: 'utf8'})
    fs.writeFileSync('file2.txt', result, { encoding: 'utf8'})
    // expect(boxedExpression).to.equal(result)
    expect(boxedExpression.localeCompare(result)).to.equal(0)
  });

  it('should detect if a sheet is a decision table model', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var result = DTable._.isDecisionTableModel(values[1])

    expect(result).to.equal(false)

    result = DTable._.isDecisionTableModel(values[0])

    expect(result).to.equal(true)
  });

  it('should parse a business model worksheet correctly', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var businessModelCsv = values[1];
    // console.log(businessModelCsv)
    debugger;
    var contextString = DTable._.makeContext(businessModelCsv).expression

    // here is the contextEntry object for the speific model
    //note: you'll have to manually verify this
    var contextEntries = [
      'Post Bureau Risk Category Table',
      {
        "Existing Customer" : "Applicant. ExistingCustomer",
        "Credit Score" : "Report. CreditScore",
        "Application Risk Score": "Affordability Model(Applicant, Product). Application Risk Score"
      }
    ];

    var expected = DTable._.generateContextString(contextEntries);

    expect(contextString).to.equal(expected)
  });

  it('should parse the qualified name of worksheet', function() {
    var excelSheetsCsvPartial = DTable._.parseXLS(excelWorkbookPath);
    var excelSheetsJsonCsv = DTable._.parseCsv(excelSheetsCsvPartial);
    var values = Object.values(excelSheetsJsonCsv);
    var businessModelCsv = values[1];

    var ctxObj = DTable._.makeContext(businessModelCsv)

    expect(ctxObj.qn).to.be.defined
    expect(ctxObj.qn).to.equal("Post Bureau Risk Category")
  })
});

describe.skip('Excel workbook parsing...', function() {
  it.skip('should parse a workbook to a json-feel boxed expression', function(){
    var jsonFeel = DTable.parseWorkbook(excelWorkbookPath);

    //this jsonFeel should have two keys
    var keys = Object.keys(jsonFeel)
    expect(keys.length).to.equal(2)

    //their values should be a FEEL string
    keys.map(key => {
      var val = jsonFeel[key]
      expect(val).to.be.defined
      expect(val).to.be.string
    })
  });
});

<|endoftext|>


<commit_before>"use strict";

import {ChangeEmitter} from "../utils/ChangeEmitter.js";
import AppDispatcher from "../dispatcher/AppDispatcher";

import NowPlayingConstants from "../constants/NowPlayingConstants.js";
import PlaylistConstants from "../constants/PlaylistConstants.js";
import CursorConstants from "../constants/CursorConstants.js";

import CursorStore from "./CursorStore.js";
import PlaylistStore from "./PlaylistStore.js";

import CtrlConstants from "../constants/ControlConstants.js";

var CONTROL_EVENT = "control";

var currentPlaying = null;
var currentRepeat = null;
var _currentTrack = null;

function setCurrentTrackSource(source) {
  localStorage.setItem("currentTrackSource", source);
}

function currentTrackSource() {
  var s = localStorage.getItem("currentTrackSource");
  if (s === null) {
    return null;
  }
  return s;
}

function setCurrentTrack(track) {
  localStorage.setItem("currentTrack", JSON.stringify(track));
  _currentTrack = track;
}

function _playing() {
  var v = localStorage.getItem("playing");
  if (v === null) {
    return false;
  }
  return JSON.parse(v);
}

function _repeat() {
  var v = localStorage.getItem("repeat");
  if (v === null) {
    return false;
  }
  return JSON.parse(v);
}

function playing() {
  if (currentPlaying === null) {
    currentPlaying = _playing();
  }
  return currentPlaying;
}

function repeat() {
  if (currentRepeat === null) {
    currentRepeat = _repeat();
  }
  return currentRepeat;
}

function setPlaying(v) {
  currentPlaying = v;
  localStorage.setItem("playing", JSON.stringify(v));
}

function setRepeat(v) {
  currentRepeat = v;
  localStorage.setItem("repeat", JSON.stringify(v));
}

function currentTrack() {
  if (_currentTrack === null) {
    var c = localStorage.getItem("currentTrack");
    if (c === null) {
      return null;
    }
    _currentTrack = JSON.parse(c);
  }
  return _currentTrack;
}

class NowPlayingStore extends ChangeEmitter {
  getPlaying() {
    return playing();
  }

  getRepeat() {
    return repeat();
  }

  getTrack() {
    return currentTrack();
  }

  getSource() {
    return currentTrackSource();
  }

  emitControl(type, value) {
    this.emit(CONTROL_EVENT, type, value);
  }

  /**
   * @param {function} callback
   */
  addControlListener(callback) {
    this.on(CONTROL_EVENT, callback);
  }

  /**
   * @param {function} callback
   */
  removeControlListener(callback) {
    this.removeListener(CONTROL_EVENT, callback);
  }
}

var _nowPlayingStore = new NowPlayingStore();

_nowPlayingStore.dispatchToken = AppDispatcher.register(function(payload) {
  var action = payload.action;
  var source = payload.source;

  if (source === "SERVER_ACTION") {
    if (action.actionType === CtrlConstants.CTRL) {
      switch (action.data.action) {

        case CtrlConstants.PLAY:
          setPlaying(true);
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.PAUSE:
          setPlaying(false);
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.NEXT:
          /* fallsthrough */
        case CtrlConstants.PREV:
          AppDispatcher.waitFor([
            CursorStore.dispatchToken,
          ]);
          setCurrentTrack(CursorStore.getCurrentTrack());
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.TOGGLE_PLAY_PAUSE:
          setPlaying(!_nowPlayingStore.getPlaying());
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.TOGGLE_REPEAT:
          setRepeat(!_nowPlayingStore.getRepeat());
          _nowPlayingStore.emitChange();
          break;

        case "repeat":
          setRepeat(action.data.Value);
          _nowPlayingStore.emitChange();
          break;

        case "time":
          _nowPlayingStore.emitControl(NowPlayingConstants.SET_CURRENT_TIME, action.data.Value);
          break;

        default:
          console.log("Unknown action:", action.data.action);
          break;
      }
    }

    if (action.actionType === CursorConstants.CURSOR) {
      AppDispatcher.waitFor([
        CursorStore.dispatchToken,
      ]);
      setCurrentTrack(CursorStore.getCurrentTrack());
      _nowPlayingStore.emitChange();
    }
  }

  if (source === "VIEW_ACTION") {
    switch (action.actionType) {

      case NowPlayingConstants.ENDED:
        if (action.repeat === true) {
          setRepeat(false);
          _nowPlayingStore.emitControl(NowPlayingConstants.SET_CURRENT_TIME, 0);
          setPlaying(true);
          _nowPlayingStore.emitChange();
          break;
        }

        if (action.source !== "cursor") {
          break;
        }
        /* falls through */
      case CursorConstants.PREV:
        /* falls through */
      case CursorConstants.NEXT:
        AppDispatcher.waitFor([
          CursorStore.dispatchToken,
        ]);
        setCurrentTrack(CursorStore.getCurrentTrack());
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_PLAYING:
        setPlaying(action.playing);
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_REPEAT:
        setRepeat(action.repeat);
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_CURRENT_TIME:
        _nowPlayingStore.emitControl(NowPlayingConstants.SET_CURRENT_TIME, action.currentTime);
        break;

      case CursorConstants.SET:
        AppDispatcher.waitFor([
          CursorStore.dispatchToken,
        ]);
        setCurrentTrack(CursorStore.getCurrentTrack());
        if (!playing()) {
          setPlaying(true);
        }
        setCurrentTrackSource("cursor");
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_CURRENT_TRACK:
        setCurrentTrack(action.track);
        setCurrentTrackSource("collection");
        _nowPlayingStore.emitChange();
        break;

      case PlaylistConstants.ADD_ITEM_PLAY_NOW:
        AppDispatcher.waitFor([
          PlaylistStore.dispatchToken,
        ]);
        console.warn("Not implemented.");
        _nowPlayingStore.emitChange();
        break;

      default:
        break;
    }
  }

  return true;
});

export default _nowPlayingStore;
<commit_msg>Avoid sending NowPlayingStore events when unnecessary.<commit_after>"use strict";

import {ChangeEmitter} from "../utils/ChangeEmitter.js";
import AppDispatcher from "../dispatcher/AppDispatcher";

import NowPlayingConstants from "../constants/NowPlayingConstants.js";
import PlaylistConstants from "../constants/PlaylistConstants.js";
import CursorConstants from "../constants/CursorConstants.js";

import CursorStore from "./CursorStore.js";
import PlaylistStore from "./PlaylistStore.js";

import CtrlConstants from "../constants/ControlConstants.js";

var CONTROL_EVENT = "control";

var currentPlaying = null;
var currentRepeat = null;
var _currentTrack = null;

function setCurrentTrackSource(source) {
  localStorage.setItem("currentTrackSource", source);
}

function currentTrackSource() {
  var s = localStorage.getItem("currentTrackSource");
  if (s === null) {
    return null;
  }
  return s;
}

function setCurrentTrack(track) {
  let change = true;
  if (_currentTrack !== null) {
    change = (_currentTrack.id !== track.id);
  }
  localStorage.setItem("currentTrack", JSON.stringify(track));
  _currentTrack = track;
  return change;
}

function _playing() {
  var v = localStorage.getItem("playing");
  if (v === null) {
    return false;
  }
  return JSON.parse(v);
}

function _repeat() {
  var v = localStorage.getItem("repeat");
  if (v === null) {
    return false;
  }
  return JSON.parse(v);
}

function playing() {
  if (currentPlaying === null) {
    currentPlaying = _playing();
  }
  return currentPlaying;
}

function repeat() {
  if (currentRepeat === null) {
    currentRepeat = _repeat();
  }
  return currentRepeat;
}

function setPlaying(v) {
  currentPlaying = v;
  localStorage.setItem("playing", JSON.stringify(v));
}

function setRepeat(v) {
  currentRepeat = v;
  localStorage.setItem("repeat", JSON.stringify(v));
}

function currentTrack() {
  if (_currentTrack === null) {
    var c = localStorage.getItem("currentTrack");
    if (c === null) {
      return null;
    }
    _currentTrack = JSON.parse(c);
  }
  return _currentTrack;
}

class NowPlayingStore extends ChangeEmitter {
  getPlaying() {
    return playing();
  }

  getRepeat() {
    return repeat();
  }

  getTrack() {
    return currentTrack();
  }

  getSource() {
    return currentTrackSource();
  }

  emitControl(type, value) {
    this.emit(CONTROL_EVENT, type, value);
  }

  /**
   * @param {function} callback
   */
  addControlListener(callback) {
    this.on(CONTROL_EVENT, callback);
  }

  /**
   * @param {function} callback
   */
  removeControlListener(callback) {
    this.removeListener(CONTROL_EVENT, callback);
  }
}

var _nowPlayingStore = new NowPlayingStore();

_nowPlayingStore.dispatchToken = AppDispatcher.register(function(payload) {
  var action = payload.action;
  var source = payload.source;

  if (source === "SERVER_ACTION") {
    if (action.actionType === CtrlConstants.CTRL) {
      switch (action.data.action) {

        case CtrlConstants.PLAY:
          setPlaying(true);
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.PAUSE:
          setPlaying(false);
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.NEXT:
          /* fallsthrough */
        case CtrlConstants.PREV:
          AppDispatcher.waitFor([
            CursorStore.dispatchToken,
          ]);
          if (setCurrentTrack(CursorStore.getCurrentTrack())) {
            _nowPlayingStore.emitChange();
          }
          break;

        case CtrlConstants.TOGGLE_PLAY_PAUSE:
          setPlaying(!_nowPlayingStore.getPlaying());
          _nowPlayingStore.emitChange();
          break;

        case CtrlConstants.TOGGLE_REPEAT:
          setRepeat(!_nowPlayingStore.getRepeat());
          _nowPlayingStore.emitChange();
          break;

        case "repeat":
          setRepeat(action.data.Value);
          _nowPlayingStore.emitChange();
          break;

        case "time":
          _nowPlayingStore.emitControl(NowPlayingConstants.SET_CURRENT_TIME, action.data.Value);
          break;

        default:
          console.log("Unknown action:", action.data.action);
          break;
      }
    }

    if (action.actionType === CursorConstants.CURSOR) {
      AppDispatcher.waitFor([
        CursorStore.dispatchToken,
      ]);
      setCurrentTrackSource("cursor");
      if (setCurrentTrack(CursorStore.getCurrentTrack())) {
        _nowPlayingStore.emitChange();
      }
    }
  }

  if (source === "VIEW_ACTION") {
    switch (action.actionType) {

      case NowPlayingConstants.ENDED:
        if (action.repeat === true) {
          setRepeat(false);
          _nowPlayingStore.emitControl(NowPlayingConstants.SET_CURRENT_TIME, 0);
          setPlaying(true);
          _nowPlayingStore.emitChange();
          break;
        }

        if (action.source !== "cursor") {
          break;
        }
        /* falls through */
      case CursorConstants.PREV:
        /* falls through */
      case CursorConstants.NEXT:
        AppDispatcher.waitFor([
          CursorStore.dispatchToken,
        ]);
        setCurrentTrack(CursorStore.getCurrentTrack());
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_PLAYING:
        setPlaying(action.playing);
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_REPEAT:
        setRepeat(action.repeat);
        _nowPlayingStore.emitChange();
        break;

      case NowPlayingConstants.SET_CURRENT_TIME:
        _nowPlayingStore.emitControl(NowPlayingConstants.SET_CURRENT_TIME, action.currentTime);
        break;

      case CursorConstants.SET:
        AppDispatcher.waitFor([
          CursorStore.dispatchToken,
        ]);
        setCurrentTrackSource("cursor");
        let change = setCurrentTrack(CursorStore.getCurrentTrack());
        if (!playing()) {
          change = true;
          setPlaying(true);
        }
        if (change) {
          _nowPlayingStore.emitChange();
        }
        break;

      case NowPlayingConstants.SET_CURRENT_TRACK:
        setCurrentTrack(action.track);
        setCurrentTrackSource("collection");
        _nowPlayingStore.emitChange();
        break;

      case PlaylistConstants.ADD_ITEM_PLAY_NOW:
        AppDispatcher.waitFor([
          PlaylistStore.dispatchToken,
        ]);
        console.warn("Not implemented.");
        _nowPlayingStore.emitChange();
        break;

      default:
        break;
    }
  }

  return true;
});

export default _nowPlayingStore;
<|endoftext|>