<commit_before>'use strict';
const Router = require('koa-router');
const logger = require('logger');
const ErrorSerializer = require('serializers/errorSerializer');
const ReportsSerializer = require('serializers/reportsSerializer');
const ReportsModel = require('models/reportsModel');
const ReportsValidator = require('validators/reportsValidator');
const AnswersModel = require('models/answersModel');
const passThrough = require('stream').PassThrough;
const json2csv = require('json2csv');
const ObjectId = require('mongoose').Types.ObjectId;
const ctRegisterMicroservice = require('ct-register-microservice-node');

const router = new Router({
    prefix: '/reports'
});

class ReportsRouter {

    static * getAll(){
        logger.info('Obtaining all reports');
        let filter = {
            $and: [
                { $or: [{
                    $and: [ {public: true}, {status: 'published'} ]},
                    {user: new ObjectId(this.state.loggedUser.id)}]
                }
            ]
        };
        if (this.state.query) {
            Object.keys(this.state.query).forEach((key) => {
                filter.$and.push({ [key]: this.state.query[key] });
            });
        }
        const reports = yield ReportsModel.find(filter);

        // get answer count for each report
        const numReports = reports.length;
        for (let i = 1; i < numReports; i++) {
            let answersFilter = {};
            if (this.state.loggedUser.role === 'ADMIN' || this.state.loggedUser.id === reports[i].user) {
                answersFilter = {
                    report: new ObjectId(reports[i].id)
                };
            } else {
                answersFilter = {
                    user: new ObjectId(this.state.loggedUser.id),
                    report: new ObjectId(this.params.id)
                };
            }
            const answers = yield AnswersModel.count(answersFilter);
            logger.info(answers);
            reports[i].answersCount = answers || 0;
        }

        this.body = ReportsSerializer.serialize(reports);
    }

    static * get(){
        logger.info(`Obtaining reports with id ${this.params.id}`);
        const report = yield ReportsModel.findOne({ _id: this.params.id });
        if (!report) {
            this.throw(404, 'Report not found with these permissions');
            return;
        }

        // get answers count for the report
        let answersFilter = {};
        if (this.state.loggedUser.role === 'ADMIN' || this.state.loggedUser.id === report.user) {
            answersFilter = {
                report: new ObjectId(this.params.id)
            };
        } else {
            answersFilter = {
                user: new ObjectId(this.state.loggedUser.id),
                report: new ObjectId(this.params.id)
            };
        }
        const answers = yield AnswersModel.count(answersFilter);
        report.answersCount = answers;

        this.body = ReportsSerializer.serialize(report);
    }

    static * save(){
        logger.info('Saving reports', this.request.body);
        const request = this.request.body;

        if (request.public && this.state.loggedUser.role !== 'ADMIN') {
            this.throw(404, 'Admin permissions required to save public templates');
            return;
        }

        const report = yield new ReportsModel({
            name: request.name,
            user: this.state.loggedUser.id,
            languages: request.languages,
            defaultLanguage: request.defaultLanguage,
            questions: request.questions,
            public: request.public,
            status: request.status
        }).save();

        // PATCH templateId onto area
        // Remove report if PATCH fails
        if (request.areaOfInterest) {
            const reportId = report._id.toString();
            try {
                const result = yield ctRegisterMicroservice.requestToMicroservice({
                    uri: `/v1/area/${request.areaOfInterest}`,
                    method: 'PATCH',
                    json: true,
                    body: {
                        templateId: reportId,
                        userId: this.state.loggedUser.id
                    }
                });
            } catch (e) {
                const result = yield ReportsModel.remove({ _id: reportId });
                logger.error(e);
                this.throw(500, 'Error creating templates: patch to area failed');
            }
        }

        this.body = ReportsSerializer.serialize(report);
    }

    static * update(){
        logger.info(`Updating template with id ${this.params.id}...`);
        const reportFilter = {
            $and: [
                { _id: new ObjectId(this.params.id) },
                { user: new ObjectId(this.state.loggedUser.id) }
            ]
        };
        const report = yield ReportsModel.findOne(reportFilter);
        const request = this.request.body;

        // if user did not create then return error
        if (!report) {
            this.throw(404, 'Report not found with these permissions');
            return;
        }

        // props allow to change even with answers
        if (request.name) {
            report.name = request.name;
        }
        if (request.status) {
            report.status = request.status;
        }
        if (request.languages) {
            report.languages = request.languages;
        }

        // if user is an admin, they can make the report public
        if (this.state.loggedUser.role === 'ADMIN' && request.public) {
            report.public = request.public;
        }

        // PATCH templateId onto area
        // Remove report if PATCH fails
        logger.info('Old area of interest:', request.oldAreaOfInterest);
        logger.info('New area of interest:', request.areaOfInterest);
        if (request.oldAreaOfInterest && (request.areaOfInterest !== request.oldAreaOfInterest)) {
            try {
                const result = yield ctRegisterMicroservice.requestToMicroservice({
                    uri: `/v1/area/${request.areaOfInterest}`,
                    method: 'PATCH',
                    json: true,
                    body: {
                        templateId: null,
                        userId: this.state.loggedUser.id
                    }
                });
            } catch (e) {
                logger.error(e);
                this.throw(500, 'Error patching templates: patch to area failed');
            }
        }

        if (request.areaOfInterest) {
            try {
                const result = yield ctRegisterMicroservice.requestToMicroservice({
                    uri: `/v1/area/${request.areaOfInterest}`,
                    method: 'PATCH',
                    json: true,
                    body: {
                        templateId: this.params.id,
                        userId: this.state.loggedUser.id
                    }
                });
            } catch (e) {
                logger.error(e);
                this.throw(500, 'Error patching templates: patch to area failed');
            }
        }

        // add answers count to return and updated date
        const answers = yield AnswersModel.count({report: new ObjectId(this.params.id)});
        report.answersCount = answers;
        report.updatedDate = Date.now;

        yield report.save();
        this.body = ReportsSerializer.serialize(report);
    }

    static * delete(){
        const aoi = this.state.query && this.state.query.aoi !== null ? this.state.query.aoi.split(',') : null;
        logger.info(`Checking report for answers...`);
        const answers = yield AnswersModel.count({report: new ObjectId(this.params.id)});
        if (answers.length > 0) {
            this.throw(403, 'This report has answers, you cannot delete. Please unpublish instead.');
        }
        logger.info(`Report has no answers.`);
        logger.info(`Deleting report with id ${this.params.id}...`);
        if (aoi !== null) {
            for (let i = 0; i < aoi.length; i++) {
                logger.debug(aoi[i]);
                logger.info(`PATCHing area ${aoi[i]} to remove template association...`);
                try {
                    const result = yield ctRegisterMicroservice.requestToMicroservice({
                        uri: `/v1/area/${aoi[i]}`,
                        method: 'PATCH',
                        json: true,
                        body: {
                            templateId: null,
                            userId: this.state.loggedUser.id
                        }
                    });
                    logger.info(`Area ${aoi[i]} patched.`);
                } catch (e) {
                    logger.error(e);
                    this.throw(500, e);
                }
            }
            logger.info('Areas patched. Remvoing template...');
        }

        // finally remove template
        const result = yield ReportsModel.remove({
            $and: [
                { _id: new ObjectId(this.params.id) },
                { user: new ObjectId(this.state.loggedUser.id) },
                { status: ['draft', 'unpublished'] }
            ]
        });

        if (!result || !result.result || result.result.ok === 0) {
            this.throw(404, 'Report not found with these permissions. You must be the owner to remove.');
            return;
        }
        this.body = '';
        this.statusCode = 204;
    }

    static * downloadAnswers() {
        logger.info(`Downloading answers for report ${this.params.id}`);
        this.set('Content-disposition', `attachment; filename=${this.params.id}.csv`);
        this.set('Content-type', 'text/csv');
        this.body = passThrough();

        const report = yield ReportsModel.findOne({
            $and: [
                { _id: new ObjectId(this.params.id) },
                { $or: [{public: true}, {user: new ObjectId(this.state.loggedUser.id)}] }
            ]
        });

        if (!report) {
            this.throw(404, 'Report not found with these permissions');
            return;
        }

        const questions = {};

        for (let i = 0; i < report.questions.length; i++) {
            const question = report.questions[i];
            questions[question.name] = null;
            if (question.childQuestions){
                for (let j = 0, lengthChild = question.childQuestions.length; j < lengthChild; j++ ){
                    questions[question.childQuestions[j].name] = null;
                }
            }
        }

        let filter = {};
        if (this.state.loggedUser.role === 'ADMIN') {
            filter = { report: this.params.id };
        } else {
            filter = {
                $and: [
                    { report: new ObjectId(this.params.id) },
                    { user: new ObjectId(this.state.loggedUser.id) }
                ]
            };
        }
        const answers = yield AnswersModel.find(filter);
        logger.info('Obtaining data');
        if (answers) {
            logger.info('Data found!');
            let data = null;

            for (let i = 0, length = answers.length; i < length; i++) {
                const answer = answers[i];
                const responses = Object.assign({}, questions);
                for(let j = 0, lengthResponses = answer.responses.length; j < lengthResponses; j++){
                    const res = answer.responses[j];
                    responses[res.name] = res.value;
                }
                logger.info('Writting...');
                data = json2csv({
                    data: responses,
                    hasCSVColumnTitle: i === 0
                }) + '\n';
                this.body.write(data);
            }
        } else {
            this.throw(404, 'No data found');
            return;
        }
        this.body.end();
    }
}

function * loggedUserToState(next) {
    if (this.query && this.query.loggedUser){
        this.state.loggedUser = JSON.parse(this.query.loggedUser);
        delete this.query.loggedUser;
    } else if (this.request.body && this.request.body.loggedUser) {
        this.state.loggedUser = this.request.body.loggedUser;
        delete this.request.body.loggedUser;
    } else {
        this.throw(401, 'Not logged');
        return;
    }
    yield next;
}

function * queryToState(next) {
    if (this.request.query && Object.keys(this.request.query).length > 0){
        this.state.query = this.request.query;
    }
    yield next;
}

function * checkPermission(next) {
    if (this.state.loggedUser.role === 'MANAGER' && (!this.state.loggedUser.extraUserData || this.state.loggedUser.extraUserData.apps || this.state.loggedUser.extraUserData.apps.indexOf('gfw') === -1)) {
        this.throw(403, 'Not authorized');
        return;
    }
    yield next;
}

function* checkAdmin(next) {
    if (!this.state.loggedUser || this.state.loggedUser.role === 'ADMIN') {
        this.throw(403, 'Not authorized');
        return;
    }
    yield next;
}

// check permission must be added at some point
router.post('/', loggedUserToState, ReportsValidator.create, ReportsRouter.save);
router.patch('/:id', loggedUserToState, ReportsValidator.update, ReportsRouter.update);
router.get('/', loggedUserToState, queryToState, ReportsRouter.getAll);
router.get('/:id', loggedUserToState, queryToState, ReportsRouter.get);
router.delete('/:id', loggedUserToState, queryToState, ReportsRouter.delete);
router.get('/:id/download-answers', loggedUserToState, ReportsRouter.downloadAnswers);

module.exports = router;
<commit_msg>fix: additional logic to patch areas in a better order<commit_after>'use strict';
const Router = require('koa-router');
const logger = require('logger');
const ErrorSerializer = require('serializers/errorSerializer');
const ReportsSerializer = require('serializers/reportsSerializer');
const ReportsModel = require('models/reportsModel');
const ReportsValidator = require('validators/reportsValidator');
const AnswersModel = require('models/answersModel');
const passThrough = require('stream').PassThrough;
const json2csv = require('json2csv');
const ObjectId = require('mongoose').Types.ObjectId;
const ctRegisterMicroservice = require('ct-register-microservice-node');

const router = new Router({
    prefix: '/reports'
});

class ReportsRouter {

    static * getAll(){
        logger.info('Obtaining all reports');
        let filter = {
            $and: [
                { $or: [{
                    $and: [ {public: true}, {status: 'published'} ]},
                    {user: new ObjectId(this.state.loggedUser.id)}]
                }
            ]
        };
        if (this.state.query) {
            Object.keys(this.state.query).forEach((key) => {
                filter.$and.push({ [key]: this.state.query[key] });
            });
        }
        const reports = yield ReportsModel.find(filter);

        // get answer count for each report
        const numReports = reports.length;
        for (let i = 1; i < numReports; i++) {
            let answersFilter = {};
            if (this.state.loggedUser.role === 'ADMIN' || this.state.loggedUser.id === reports[i].user) {
                answersFilter = {
                    report: new ObjectId(reports[i].id)
                };
            } else {
                answersFilter = {
                    user: new ObjectId(this.state.loggedUser.id),
                    report: new ObjectId(this.params.id)
                };
            }
            const answers = yield AnswersModel.count(answersFilter);
            logger.info(answers);
            reports[i].answersCount = answers || 0;
        }

        this.body = ReportsSerializer.serialize(reports);
    }

    static * get(){
        logger.info(`Obtaining reports with id ${this.params.id}`);
        const report = yield ReportsModel.findOne({ _id: this.params.id });
        if (!report) {
            this.throw(404, 'Report not found with these permissions');
            return;
        }

        // get answers count for the report
        let answersFilter = {};
        if (this.state.loggedUser.role === 'ADMIN' || this.state.loggedUser.id === report.user) {
            answersFilter = {
                report: new ObjectId(this.params.id)
            };
        } else {
            answersFilter = {
                user: new ObjectId(this.state.loggedUser.id),
                report: new ObjectId(this.params.id)
            };
        }
        const answers = yield AnswersModel.count(answersFilter);
        report.answersCount = answers;

        this.body = ReportsSerializer.serialize(report);
    }

    static * save(){
        logger.info('Saving reports', this.request.body);
        const request = this.request.body;

        if (request.public && this.state.loggedUser.role !== 'ADMIN') {
            this.throw(404, 'Admin permissions required to save public templates');
            return;
        }

        const report = yield new ReportsModel({
            name: request.name,
            user: this.state.loggedUser.id,
            languages: request.languages,
            defaultLanguage: request.defaultLanguage,
            questions: request.questions,
            public: request.public,
            status: request.status
        }).save();

        // PATCH templateId onto area
        // Remove report if PATCH fails
        if (request.areaOfInterest) {
            const reportId = report._id.toString();
            try {
                const result = yield ctRegisterMicroservice.requestToMicroservice({
                    uri: `/v1/area/${request.areaOfInterest}`,
                    method: 'PATCH',
                    json: true,
                    body: {
                        templateId: reportId,
                        userId: this.state.loggedUser.id
                    }
                });
            } catch (e) {
                const result = yield ReportsModel.remove({ _id: reportId });
                logger.error(e);
                this.throw(500, 'Error creating templates: patch to area failed');
            }
        }

        this.body = ReportsSerializer.serialize(report);
    }

    static * update(){
        logger.info(`Updating template with id ${this.params.id}...`);
        const reportFilter = {
            $and: [
                { _id: new ObjectId(this.params.id) },
                { user: new ObjectId(this.state.loggedUser.id) }
            ]
        };
        const report = yield ReportsModel.findOne(reportFilter);
        const request = this.request.body;

        // if user did not create then return error
        if (!report) {
            this.throw(404, 'Report not found with these permissions');
            return;
        }

        // props allow to change even with answers
        if (request.name) {
            report.name = request.name;
        }
        if (request.status) {
            report.status = request.status;
        }
        if (request.languages) {
            report.languages = request.languages;
        }

        // if user is an admin, they can make the report public
        if (this.state.loggedUser.role === 'ADMIN' && request.public) {
            report.public = request.public;
        }

        // PATCH templateId onto area
        // Remove report if PATCH fails
        if (request.areaOfInterest !== request.oldAreaOfInterest) {

            // remove old area
            if (request.oldAreaOfInterest) {
                logger.info(`PATCHing old area of interes ${request.oldAreaOfInterest}...`);
                try {
                    const result = yield ctRegisterMicroservice.requestToMicroservice({
                        uri: `/v1/area/${request.oldAreaOfInterest}`,
                        method: 'PATCH',
                        json: true,
                        body: {
                            templateId: null,
                            userId: this.state.loggedUser.id
                        }
                    });
                } catch (e) {
                    logger.error(e);
                    this.throw(500, 'PATCHing old area failed');
                }
            }

            // PATCH new area
            if (request.areaOfInterest) {
                logger.info(`PATCHing new area of interes ${request.oldAreaOfInterest}...`);
                try {
                    const result = yield ctRegisterMicroservice.requestToMicroservice({
                        uri: `/v1/area/${request.areaOfInterest}`,
                        method: 'PATCH',
                        json: true,
                        body: {
                            templateId: this.params.id,
                            userId: this.state.loggedUser.id
                        }
                    });
                } catch (e) {
                    logger.error(e);
                    this.throw(500, 'PATCHing new area failed');
                }
            }
        }

        if (request.areaOfInterest) {

        }

        // add answers count to return and updated date
        const answers = yield AnswersModel.count({report: new ObjectId(this.params.id)});
        report.answersCount = answers;
        report.updatedDate = Date.now;

        yield report.save();
        this.body = ReportsSerializer.serialize(report);
    }

    static * delete(){
        const aoi = this.state.query && this.state.query.aoi !== null ? this.state.query.aoi.split(',') : null;
        logger.info(`Checking report for answers...`);
        const answers = yield AnswersModel.count({report: new ObjectId(this.params.id)});
        if (answers.length > 0) {
            this.throw(403, 'This report has answers, you cannot delete. Please unpublish instead.');
        }
        logger.info(`Report has no answers.`);
        logger.info(`Deleting report with id ${this.params.id}...`);
        if (aoi !== null) {
            for (let i = 0; i < aoi.length; i++) {
                logger.debug(aoi[i]);
                logger.info(`PATCHing area ${aoi[i]} to remove template association...`);
                try {
                    const result = yield ctRegisterMicroservice.requestToMicroservice({
                        uri: `/v1/area/${aoi[i]}`,
                        method: 'PATCH',
                        json: true,
                        body: {
                            templateId: null,
                            userId: this.state.loggedUser.id
                        }
                    });
                    logger.info(`Area ${aoi[i]} patched.`);
                } catch (e) {
                    logger.error(e);
                    this.throw(500, e);
                }
            }
            logger.info('Areas patched. Remvoing template...');
        }

        // finally remove template
        const result = yield ReportsModel.remove({
            $and: [
                { _id: new ObjectId(this.params.id) },
                { user: new ObjectId(this.state.loggedUser.id) },
                { status: ['draft', 'unpublished'] }
            ]
        });

        if (!result || !result.result || result.result.ok === 0) {
            this.throw(404, 'Report not found with these permissions. You must be the owner to remove.');
            return;
        }
        this.body = '';
        this.statusCode = 204;
    }

    static * downloadAnswers() {
        logger.info(`Downloading answers for report ${this.params.id}`);
        this.set('Content-disposition', `attachment; filename=${this.params.id}.csv`);
        this.set('Content-type', 'text/csv');
        this.body = passThrough();

        const report = yield ReportsModel.findOne({
            $and: [
                { _id: new ObjectId(this.params.id) },
                { $or: [{public: true}, {user: new ObjectId(this.state.loggedUser.id)}] }
            ]
        });

        if (!report) {
            this.throw(404, 'Report not found with these permissions');
            return;
        }

        const questions = {};

        for (let i = 0; i < report.questions.length; i++) {
            const question = report.questions[i];
            questions[question.name] = null;
            if (question.childQuestions){
                for (let j = 0, lengthChild = question.childQuestions.length; j < lengthChild; j++ ){
                    questions[question.childQuestions[j].name] = null;
                }
            }
        }

        let filter = {};
        if (this.state.loggedUser.role === 'ADMIN') {
            filter = { report: this.params.id };
        } else {
            filter = {
                $and: [
                    { report: new ObjectId(this.params.id) },
                    { user: new ObjectId(this.state.loggedUser.id) }
                ]
            };
        }
        const answers = yield AnswersModel.find(filter);
        logger.info('Obtaining data');
        if (answers) {
            logger.info('Data found!');
            let data = null;

            for (let i = 0, length = answers.length; i < length; i++) {
                const answer = answers[i];
                const responses = Object.assign({}, questions);
                for(let j = 0, lengthResponses = answer.responses.length; j < lengthResponses; j++){
                    const res = answer.responses[j];
                    responses[res.name] = res.value;
                }
                logger.info('Writting...');
                data = json2csv({
                    data: responses,
                    hasCSVColumnTitle: i === 0
                }) + '\n';
                this.body.write(data);
            }
        } else {
            this.throw(404, 'No data found');
            return;
        }
        this.body.end();
    }
}

function * loggedUserToState(next) {
    if (this.query && this.query.loggedUser){
        this.state.loggedUser = JSON.parse(this.query.loggedUser);
        delete this.query.loggedUser;
    } else if (this.request.body && this.request.body.loggedUser) {
        this.state.loggedUser = this.request.body.loggedUser;
        delete this.request.body.loggedUser;
    } else {
        this.throw(401, 'Not logged');
        return;
    }
    yield next;
}

function * queryToState(next) {
    if (this.request.query && Object.keys(this.request.query).length > 0){
        this.state.query = this.request.query;
    }
    yield next;
}

function * checkPermission(next) {
    if (this.state.loggedUser.role === 'MANAGER' && (!this.state.loggedUser.extraUserData || this.state.loggedUser.extraUserData.apps || this.state.loggedUser.extraUserData.apps.indexOf('gfw') === -1)) {
        this.throw(403, 'Not authorized');
        return;
    }
    yield next;
}

function* checkAdmin(next) {
    if (!this.state.loggedUser || this.state.loggedUser.role === 'ADMIN') {
        this.throw(403, 'Not authorized');
        return;
    }
    yield next;
}

// check permission must be added at some point
router.post('/', loggedUserToState, ReportsValidator.create, ReportsRouter.save);
router.patch('/:id', loggedUserToState, ReportsValidator.update, ReportsRouter.update);
router.get('/', loggedUserToState, queryToState, ReportsRouter.getAll);
router.get('/:id', loggedUserToState, queryToState, ReportsRouter.get);
router.delete('/:id', loggedUserToState, queryToState, ReportsRouter.delete);
router.get('/:id/download-answers', loggedUserToState, ReportsRouter.downloadAnswers);

module.exports = router;
<|endoftext|>


<commit_before>'use strict';

module.exports = {
    'default': [
        'build',
        'test'
    ],
    'test': [
        'browserify:appCommon',
        'browserify:tests',
        'mocha'
    ],
    'build-js': [
        'eslint',
        'mkdir:build-assets-js',
        'browserify:appCommon',
        'uglify:appCommon'
    ],
    'build-css': [
        'prepare-bootstrap-variables',
        'concat:css-libs',
        'stylus:app',
        'cssmin:libs',
        'cssmin:app'
    ],
    'build-images': [
        'copyto:images'
    ],
    'build-fonts': [
        'copyto:bootstrap-fonts',
        'copyto:font-awesome-fonts',
        'copyto:ionicons-fonts'
    ],
    'build-html': [
        'replace:html_bad_chars',
        'bliss:appDebug'
    ],

    'prepare-phonegapcli-live': [
        'copyto:phonegap',
        'copyto:phonegapcli_res',
        'copyto:platform_merges',
        'bliss:cordovaConfigJson',
        'bliss:phonegap',
        'bliss:cordovaConfigXml',
        'notify:phonegap'
    ],
    'prepare-phonegapcli-dev': [
        'copyto:phonegap',
        'copyto:phonegapcli_res',
        'copyto:platform_merges',
        'bliss:cordovaConfigJson',
        'bliss:phonegapDev',
        'bliss:cordovaConfigXml',
        'notify:phonegap'
    ],

    'prepare-phonegapbuild-live': [
        'copyto:phonegap',
        'copyto:phonegapbuild_res',
        'bliss:cordovaConfigJson',
        'bliss:phonegap',
        'bliss:cordovaConfigXml',
        'zip:phonegap',
        'notify:phonegap'
    ],
    'prepare-phonegapbuild-dev': [
        'copyto:phonegap',
        'copyto:phonegapbuild_res',
        'bliss:cordovaConfigJson',
        'bliss:phonegapDev',
        'bliss:cordovaConfigXmlDev',
        'zip:phonegapDev',
        'notify:phonegap'
    ],

    //TODO: task that uses the PhoneGapBuild REST API to upload for build, using environment credentials

    'build-webapp-html': [
        'replace:html_bad_chars',
        'bliss:webapp',
        // TODO Fix problem with htmlmin; disabled temporarly
        //'htmlmin:webapp'
    ],
    'build-webapp-html-copy': [
        'build-webapp-html',
        'copyto:webapp_assets'
    ],
    'build-webapp': [
        'parallel:build-webapp',
        'copyto:webapp_assets'
    ],
    'atwork': [
        'connect:atbuild',
        'browserify:watchAppCommon',
        'watch'
    ],
    'build-landingPages': [
        'stylus:landingPages',
        'cssmin:landingPages',
        'replace:html_bad_chars',
        'bliss:landingPagesBuild',
        'htmlmin:landingPagesBuild',
        'copyto:images',
        'browserify:appCommon'
    ],
    'publish-landingPages': [
        'bliss:landingPagesWeb',
        'uglify:appCommon',
        'htmlmin:landingPagesWeb',
        'copyto:landingPages_assets'
    ]
};
<commit_msg>Fixed tasks, preventing error just testing (because of build/assets/js/activities folder) and better organized 'test' commands #460<commit_after>'use strict';

module.exports = {
    'default': [
        'build',
        'test-after-build'
    ],
    // If wants to run 'test' after a build, this task prevents doing duplicated work
    'test-after-build': [
        'browserify:tests',
        'mocha'
    ],
    // Run JavaScript testing
    'test': [
        'mkdir:build-assets-js',
        'browserify:appCommon',
        'browserify:tests',
        'mocha'
    ],
    'build-js': [
        'eslint',
        'mkdir:build-assets-js',
        'browserify:appCommon',
        'uglify:appCommon'
    ],
    'build-css': [
        'prepare-bootstrap-variables',
        'concat:css-libs',
        'stylus:app',
        'cssmin:libs',
        'cssmin:app'
    ],
    'build-images': [
        'copyto:images'
    ],
    'build-fonts': [
        'copyto:bootstrap-fonts',
        'copyto:font-awesome-fonts',
        'copyto:ionicons-fonts'
    ],
    'build-html': [
        'replace:html_bad_chars',
        'bliss:appDebug'
    ],

    'prepare-phonegapcli-live': [
        'copyto:phonegap',
        'copyto:phonegapcli_res',
        'copyto:platform_merges',
        'bliss:cordovaConfigJson',
        'bliss:phonegap',
        'bliss:cordovaConfigXml',
        'notify:phonegap'
    ],
    'prepare-phonegapcli-dev': [
        'copyto:phonegap',
        'copyto:phonegapcli_res',
        'copyto:platform_merges',
        'bliss:cordovaConfigJson',
        'bliss:phonegapDev',
        'bliss:cordovaConfigXml',
        'notify:phonegap'
    ],

    'prepare-phonegapbuild-live': [
        'copyto:phonegap',
        'copyto:phonegapbuild_res',
        'bliss:cordovaConfigJson',
        'bliss:phonegap',
        'bliss:cordovaConfigXml',
        'zip:phonegap',
        'notify:phonegap'
    ],
    'prepare-phonegapbuild-dev': [
        'copyto:phonegap',
        'copyto:phonegapbuild_res',
        'bliss:cordovaConfigJson',
        'bliss:phonegapDev',
        'bliss:cordovaConfigXmlDev',
        'zip:phonegapDev',
        'notify:phonegap'
    ],

    //TODO: task that uses the PhoneGapBuild REST API to upload for build, using environment credentials

    'build-webapp-html': [
        'replace:html_bad_chars',
        'bliss:webapp',
        // TODO Fix problem with htmlmin; disabled temporarly
        //'htmlmin:webapp'
    ],
    'build-webapp-html-copy': [
        'build-webapp-html',
        'copyto:webapp_assets'
    ],
    'build-webapp': [
        'parallel:build-webapp',
        'copyto:webapp_assets'
    ],
    'atwork': [
        'connect:atbuild',
        'browserify:watchAppCommon',
        'watch'
    ],
    'build-landingPages': [
        'stylus:landingPages',
        'cssmin:landingPages',
        'replace:html_bad_chars',
        'bliss:landingPagesBuild',
        'htmlmin:landingPagesBuild',
        'copyto:images',
        'browserify:appCommon'
    ],
    'publish-landingPages': [
        'bliss:landingPagesWeb',
        'uglify:appCommon',
        'htmlmin:landingPagesWeb',
        'copyto:landingPages_assets'
    ]
};
<|endoftext|>


<commit_before>// hypestore - HYPErtext STORage Engine
//
// rfc2616 server supporting transparent content
// storage and retrieval over HTTP

var express = require('express');
var fs = require('fs');

var app = express();

var path = require('path');
var server = require('http').createServer(app);
var util = require('util');
var getRawBody = require('raw-body');

var spawn = require('child_process').spawn;

app.use(express.static(__dirname + '/static'));
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(express.static(__dirname + '/public'));

var config = loadConfig();

if (!config) {
    console.log("FATAL: No config.json in current directory, exiting.");
} else {

    fs.exists(config.storage.contentLocation, function (exists) {

	if (exists) {
	    console.log("found content directory " + config.storage.contentLocation);
	    server.listen(config.port);
	    console.log("Listening on port: " + config.port);
	} else {
	    console.log("WARNING: location " + config.storage.contentLocation + " specified in config.json could not be found.  Trying to create...");

	    fs.mkdir(config.storage.contentLocation, function (exception) {

		if (exception) {
		    console.log("FATAL: Could not create directory " + config.storage.contentLocation);
		} else {
		    console.log("created directory " + config.storage.contentLocation);
		    server.listen(config.port);
		    console.log("Listening on port: " + config.port);
		}

	    });

	}

    });
}

// GET
app.get("/:resource", function (req, res) {

    console.log("req: " + util.inspect(req));

    var requestState = {};

    requestState.headers = req.headers;
    requestState.url = req.url;
    requestState.method = req.method;

    var file;
    if (req.params.resource == undefined) {
	file = config.storage.contentLocation + "/index.html";
    } else {
	file = config.storage.contentLocation + "/" + req.params.resource;
    }

    requestState.requestedFile = file;

    console.log("requestState: " + requestState);

    fs.readFile(file, function (err, data) {

	if (err) {
	    console.log("error opening file: " + file + ": " + util.inspect(err));

	    if (err.errno == 34) { // No such file or directory
		requestState.responseCode = 404;
		res.json(404, requestState);
	    } else {
		res.json(500, err);
	    }

	} else {
	    console.log("found data in " + file);

	    console.log("\n\n" + util.inspect(data));

	    // TODO:

	    // lookup content type of file from original submission
	    // set content-type header

	    res.send(200, data);

	}

    });

});

// PUT
app.put("/:resource", function (req, res) {

    // TODO:
    //
    // - map file extension to MIME
    // - validate known MIME types against client Accept header, 4xx Not Acceptable if no match
    // - handle hierarchical directory traversal

    var requestState = {};

    requestState.headers = req.headers;
    requestState.url = req.url;
    requestState.method = req.method;

    var file;
    if (!req.params.resource) {
	file = config.storage.contentLocation + "/index.html";
    } else {
	file = config.storage.contentLocation + "/" + req.params.resource;
    }

    requestState.requestedFile = file;

    console.log("requestState: " + util.inspect(requestState));
    console.log("contents of file: " + util.inspect(req));
    console.log("content type: " + req.get('Content-Type'));

    getRawBody(req, { length: req.headers['Content-Length'] }, function(err, buffer) {

	if (err) {

	    console.log("error getting raw body: " + util.inspect(err));
	    res.json(500, err);

	} else {

	    // TODO: write buffer to file

	    fs.writeFile(file, buffer, { flag: 'w' }, function (err) {

		if (err) {
		    console.log("error writing to file: " + file);
		    res.json(500, err);
		} else {
		    res.send(204);
		}

	    });

	}

    });

});

// POST -> should this even exist?
app.post("/:resource", function (req, res) {

    // TODO:

    // open file for writing

    res.json(405, { message: "Hypestore supports HTTP methods: GET, PUT, DELETE" });

});

function loadConfig() {
    console.log("Loading configuration for " + "./config.json");
    if (fs.existsSync("./config.json")) {
	var cfg = fs.readFileSync("./config.json", 'utf-8');
	return JSON.parse(cfg);
    } else {
	console.log("loadConfig: no config.json found");
	return undefined;
    }
}

<commit_msg>minor tweaks<commit_after>// hypestore - HYPErtext STORage Engine
//
// rfc2616 server supporting transparent content
// storage and retrieval over HTTP

var express = require('express');
var fs = require('fs');

var app = express();

var path = require('path');
var server = require('http').createServer(app);
var util = require('util');
var getRawBody = require('raw-body');

var spawn = require('child_process').spawn;

app.use(express.static(__dirname + '/static'));
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(express.static(__dirname + '/public'));

var config = loadConfig();

if (!config) {
    console.log("FATAL: No config.json in current directory, exiting.");
} else {

    fs.exists(config.storage.contentLocation, function (exists) {

	if (exists) {
	    console.log("found content directory " + config.storage.contentLocation);
	    server.listen(config.port);
	    console.log("Listening on port: " + config.port);
	} else {
	    console.log("WARNING: location " + config.storage.contentLocation + " specified in config.json could not be found.  Trying to create...");

	    fs.mkdir(config.storage.contentLocation, function (exception) {

		if (exception) {
		    console.log("FATAL: Could not create directory " + config.storage.contentLocation);
		} else {
		    console.log("created directory " + config.storage.contentLocation);
		    server.listen(config.port);
		    console.log("Listening on port: " + config.port);
		}

	    });

	}

    });
}

// GET
app.get("/:resource", function (req, res) {

    console.log("req: " + util.inspect(req));

    var requestState = {};

    requestState.headers = req.headers;
    requestState.url = req.url;
    requestState.method = req.method;

    var file;
    if (req.params.resource == undefined) {
	file = config.storage.contentLocation + "/index.html";
    } else {
	file = config.storage.contentLocation + "/" + req.params.resource;
    }

    requestState.requestedFile = file;

    console.log("requestState: " + requestState);

    fs.readFile(file, function (err, data) {

	if (err) {
	    console.log("error opening file: " + file + ": " + util.inspect(err));

	    if (err.errno == 34) { // No such file or directory
		requestState.responseCode = 404;
		res.json(404, requestState);
	    } else {
		res.json(500, err);
	    }

	} else {
	    console.log("found data in " + file);

	    console.log("\n\n" + util.inspect(data));

	    // TODO:

	    // lookup content type of file from original submission
	    // set content-type header

	    res.send(200, data);

	}

    });

});

// PUT
app.put("/:resource", function (req, res) {

    // TODO:
    //
    // - map file extension to MIME
    // - validate known MIME types against client Accept header, 4xx Not Acceptable if no match
    // - handle hierarchical directory traversal

    var requestState = {};

    requestState.headers = req.headers;
    requestState.url = req.url;
    requestState.method = req.method;

    var file;
    if (!req.params.resource) {
	file = config.storage.contentLocation + "/index.html";
    } else {
	file = config.storage.contentLocation + "/" + req.params.resource;
    }

    requestState.requestedFile = file;

    console.log("requestState: " + util.inspect(requestState));
    console.log("contents of file: " + util.inspect(req));
    console.log("content type: " + req.get('Content-Type'));

    getRawBody(req, { length: req.headers['Content-Length'] }, function(err, buffer) {

	if (err) {

	    console.log("error getting raw body: " + util.inspect(err));
	    res.json(500, err);

	} else {

	    fs.writeFile(file, buffer, { flag: 'w' }, function (err) {

		if (err) {
		    console.log("error writing to file: " + file);
		    res.json(500, err);
		} else {
		    res.send(204);
		}

	    });

	}

    });

});

// POST -> should this even exist?
app.post("/:resource", function (req, res) {

    // TODO:

    // open file for writing

    res.json(405, { message: "Hypestore supports HTTP methods: GET, PUT, DELETE" });

});

function loadConfig() {
    console.log("Loading configuration for " + "./config.json");
    if (fs.existsSync("./config.json")) {
	var cfg = fs.readFileSync("./config.json", 'utf-8');
	return JSON.parse(cfg);
    } else {
	console.log("loadConfig: no config.json found");
	return undefined;
    }
}

<|endoftext|>


<commit_before>/* driver.js: Primitives to deal with the way we store data on disk.
 * Copyright © 2011 Jan Keromnes, Thaddee Tyl. All rights reserved.
 * The following code is covered by the GPLv2 license. */

var nodefs = require('fs'),
    path = require('path'),
    child = require('child_process');

var cwd = process.cwd(),
    root = path.join(cwd, 'web'),
    metaRoot = path.join(cwd, 'meta');

// Switch between virtual and disk paths

function normalize(vpath) {
  // The following features several Windows hacks.
  var npath = path.normalize(('/' + vpath)
      .replace(/\\/g,'/').replace(/\/\//g,'/')).replace(/\\/g,'/');
  //console.log('NORMALIZED PATH OF', vpath, 'IS', npath);
  return npath;
}

function absolute(vpath) {
  var apath = path.join(root, normalize(vpath));
  //console.log('ABSOLUTE PATH OF', vpath, 'IS', apath);
  return apath;
};

function relative(vpath) {
  var rpath = path.join('web', normalize(vpath));
  //console.log('RELATIVE PATH OF', vpath, 'IS', rpath);
  return rpath;
};

function virtual(dpath) {
  var vpath = normalize(path.relative(root, dpath));
  //console.log('VIRTUAL PATH OF', dpath, 'IS', vpath);
  return vpath;
}

// Metadata saved to disk.

function metafile (vpath, cb) {
  var npath = normalize(vpath);     // Can you find an Apple troll?

  nodefs.stat(absolute(npath), function (err, stats) {
    if (!stats)
      console.error("Error while getting the metadata of", npath);
    else
      cb(err, path.join(metaRoot, npath, stats.isDirectory()? '.DS-Store': ''));
  });
}

function loadMeta (vpath, cb) {
  metafile(vpath, function (err, file) {
    if (err) cb(err);
    else nodefs.readFile(file, 'utf8', function (err, data) {
      if (err) cb(err);
      else cb(null, JSON.parse(data));
    });
  });
}

function dumpMeta (vpath, data, cb) {
  metafile(vpath, function (err, file) {
    // First, we need to create all directories down to the meta file
    // (excluding the file, that is).
    child.spawn('mkdir', ['-p',path.dirname(file)]).on('exit', function (code) {
      if (code !== 0) {
        console.error('Error: dumping metadata ended with code ' + code +
                      ' with directory', path.dirname(file));
        return;
      }

      // Then, we want to dump the metadata as JSON in that file.
      nodefs.writeFile(file, JSON.stringify(data), function (err) {
        if (err) console.error('While dumping metadata:', err.stack);
        if (typeof cb === 'function') cb(err);
      });
    });
  });
}

// Driver primitives

var primitives = {};  // Map from mime types to I/O primitives.

primitives['dir'] = {
  read: function(vpath, cb) {nodefs.readdir(absolute(vpath), cb);},
  mkfile: function(vpath, cb) {nodefs.writeFile(absolute(vpath), '', cb);},
  mkdir: function(vpath, cb) {nodefs.mkdir(absolute(vpath), cb);},
  rm: function(vpath, cb) {nodefs.rmdir(absolute(vpath), cb);}
};

primitives['binary'] = {
  read: function(vpath, cb) {nodefs.readFile(absolute(vpath), cb);},
  write: function(vpath, content, metadata, cb) {
    nodefs.writeFile(absolute(vpath), content, cb);
    dumpMeta(vpath, metadata);
  },
  rm: function(vpath, cb) {nodefs.unlink(absolute(vpath), cb);}
};

primitives['text/plain'] = {
  read: function(vpath, cb) {nodefs.readFile(absolute(vpath), 'utf8', cb);},
  write: function(vpath, content, metadata, cb) {
    nodefs.writeFile(absolute(vpath), content, 'utf8', cb);
    dumpMeta(vpath, metadata);
  },
  rm: primitives['binary'].rm
};

// Exports

exports.primitives = primitives;
exports.normalize = normalize;
exports.absolute = absolute;
exports.relative = relative;
exports.virtual = virtual;

exports.dumpMeta = dumpMeta;
exports.loadMeta = loadMeta;
<commit_msg>getting metadata even more safely.<commit_after>/* driver.js: Primitives to deal with the way we store data on disk.
 * Copyright © 2011 Jan Keromnes, Thaddee Tyl. All rights reserved.
 * The following code is covered by the GPLv2 license. */

var nodefs = require('fs'),
    path = require('path'),
    child = require('child_process');

var cwd = process.cwd(),
    root = path.join(cwd, 'web'),
    metaRoot = path.join(cwd, 'meta');

// Switch between virtual and disk paths

function normalize(vpath) {
  // The following features several Windows hacks.
  var npath = path.normalize(('/' + vpath)
      .replace(/\\/g,'/').replace(/\/\//g,'/')).replace(/\\/g,'/');
  //console.log('NORMALIZED PATH OF', vpath, 'IS', npath);
  return npath;
}

function absolute(vpath) {
  var apath = path.join(root, normalize(vpath));
  //console.log('ABSOLUTE PATH OF', vpath, 'IS', apath);
  return apath;
};

function relative(vpath) {
  var rpath = path.join('web', normalize(vpath));
  //console.log('RELATIVE PATH OF', vpath, 'IS', rpath);
  return rpath;
};

function virtual(dpath) {
  var vpath = normalize(path.relative(root, dpath));
  //console.log('VIRTUAL PATH OF', dpath, 'IS', vpath);
  return vpath;
}

// Metadata saved to disk.

function metafile (vpath, cb) {
  var npath = normalize(vpath);     // Can you find an Apple troll?

  nodefs.stat(absolute(npath), function (err, stats) {
    if (err || !stats) {
      console.error("Error while getting the metadata of", npath);
      cb(err);
    } else {
      cb(null, path.join(metaRoot, npath, stats.isDirectory()? '.DS-Store':''));
    }
  });
}

function loadMeta (vpath, cb) {
  metafile(vpath, function (err, file) {
    if (err) cb(err);
    else nodefs.readFile(file, 'utf8', function (err, data) {
      if (err) cb(err);
      else cb(null, JSON.parse(data));
    });
  });
}

function dumpMeta (vpath, data, cb) {
  metafile(vpath, function (err, file) {
    if (err)  {
      cb(err);
      return;
    }

    // First, we need to create all directories down to the meta file
    // (excluding the file, that is).
    child.spawn('mkdir', ['-p',path.dirname(file)]).on('exit', function (code) {
      if (code !== 0) {
        console.error('Error: dumping metadata ended with code ' + code +
                      ' with directory', path.dirname(file));
        return;
      }

      // Then, we want to dump the metadata as JSON in that file.
      nodefs.writeFile(file, JSON.stringify(data), function (err) {
        if (err) console.error('While dumping metadata:', err.stack);
        if (typeof cb === 'function') cb(err);
      });
    });
  });
}

// Driver primitives

var primitives = {};  // Map from mime types to I/O primitives.

primitives['dir'] = {
  read: function(vpath, cb) {nodefs.readdir(absolute(vpath), cb);},
  mkfile: function(vpath, cb) {nodefs.writeFile(absolute(vpath), '', cb);},
  mkdir: function(vpath, cb) {nodefs.mkdir(absolute(vpath), cb);},
  rm: function(vpath, cb) {nodefs.rmdir(absolute(vpath), cb);}
};

primitives['binary'] = {
  read: function(vpath, cb) {nodefs.readFile(absolute(vpath), cb);},
  write: function(vpath, content, metadata, cb) {
    nodefs.writeFile(absolute(vpath), content, cb);
    dumpMeta(vpath, metadata);
  },
  rm: function(vpath, cb) {nodefs.unlink(absolute(vpath), cb);}
};

primitives['text/plain'] = {
  read: function(vpath, cb) {nodefs.readFile(absolute(vpath), 'utf8', cb);},
  write: function(vpath, content, metadata, cb) {
    nodefs.writeFile(absolute(vpath), content, 'utf8', cb);
    dumpMeta(vpath, metadata);
  },
  rm: primitives['binary'].rm
};

// Exports

exports.primitives = primitives;
exports.normalize = normalize;
exports.absolute = absolute;
exports.relative = relative;
exports.virtual = virtual;

exports.dumpMeta = dumpMeta;
exports.loadMeta = loadMeta;
<|endoftext|>


<commit_before>angular.module('ww2Animations', ['ngAnimate']);

ww2Animations.animation('.chapter', function(){

  var animateUp = function(element, className, done) {
    if(className != 'active') {
      return;
    }
    element.css({
      position: 'absolute',
      top: 500,
      left: 0,
      display: 'block'
    });

    jQuery(element).animate({
      top: 0
    }, done);

    return function(cancel) {
      if(cancel) {
        element.stop();
      }
    };
  }

  var animateDown = function(element, className, done) {
    if(className != 'active'){
      return;
    }
    element.css({
      position: 'absolute',
      left: 0,
      top: 0
    });

    jquery(element).animate({
      top: -500
    }, done);

    return function(cancel) {
      if(cancel) {
        element.stop();
      }
    };
  }

  return {
    addClass: animateUp,
    removeClass: animateDown
  };
});
<commit_msg>def var animations<commit_after>var ww2Animations = angular.module('ww2Animations', ['ngAnimate']);

ww2Animations.animation('.chapter', function(){

  var animateUp = function(element, className, done) {
    if(className != 'active') {
      return;
    }
    element.css({
      position: 'absolute',
      top: 500,
      left: 0,
      display: 'block'
    });

    jQuery(element).animate({
      top: 0
    }, done);

    return function(cancel) {
      if(cancel) {
        element.stop();
      }
    };
  }

  var animateDown = function(element, className, done) {
    if(className != 'active'){
      return;
    }
    element.css({
      position: 'absolute',
      left: 0,
      top: 0
    });

    jquery(element).animate({
      top: -500
    }, done);

    return function(cancel) {
      if(cancel) {
        element.stop();
      }
    };
  }

  return {
    addClass: animateUp,
    removeClass: animateDown
  };
});
<|endoftext|>


<commit_before>import {element} from 'deku';

const _getMsg = chrome.i18n.getMessage;

function afterMount({props}, el) {
  const itemInfo = props.itemInfo;

  if (!globals.isFolder(itemInfo) &&
      itemInfo.url !== globals.separateThisUrl) {
    setTooltip(el, props);
  }
}

function clickHandler(event, {props, state}) {
  const itemInfo = props.itemInfo;

  switch (globals.getBookmarkType(itemInfo)) {
    case 'folder':
      break;

    case 'bookmark':
      openBookmark(getOpenBookmarkHandlerId(event), itemInfo.url);
  }
}

function contextMenuHandler(event, {props, state}, updateState) {
  // disable native context menu
  event.preventDefault();

  const itemInfo = props.itemInfo;

  globals.setRootState({
    menuTarget: itemInfo,
    mousePos: {x: event.x, y: event.y}
  });
}

function dragEndHandler(event, {props, state}) {

}

function dragOverHandler(event, {props, state}) {

}

function dragStartHandler(event, {props, state}) {

}

function getOpenBookmarkHandlerId(event) {
  const mouseButton = event.button;

  let switcher;

  if (mouseButton === 0) {
    switcher = 'Left';

    if (event.shiftKey) {
      switcher += 'Shift';
    } else if (event.ctrlKey) {
      switcher += 'Ctrl';
    }
  } else {
    switcher = 'Middle';
  }

  return globals.storage['clickBy' + switcher];
}

function mouseEnterHandler(event, {props, state}, updateState) {
  if (event.target !== event.delegateTarget) {
    return true;
  }

  const itemInfo = props.itemInfo;

  if (globals.isFolder(itemInfo)) {
    openFolder(props);
  } else {
    globals.removeTreeInfoFromIndex(props.trees, props.treeIndex + 1);
  }
}

function mouseLeaveHandler(event, {props, state}, updateState) {
  if (event.target !== event.delegateTarget) {
    return true;
  }
}

function openBookmark(handlerId, itemUrl) {
  switch (handlerId) {
    case 0: // current tab
    case 1: // current tab (w/o closing PmB)
      if (itemUrl.indexOf('javascript') !== 0) {
        chrome.tabs.update({url: itemUrl});
      } else {
        if (globals.storage.bookmarklet) {
          chrome.tabs.executeScript(null, {code: itemUrl});
        } else if (confirm(_getMsg('alert_bookmarklet'))) {
          globals.openOptionsPage();
        }
      }
      break;

    case 2: // new tab
    case 3: // background tab
    case 4: // background tab (w/o closing PmB)
      chrome.tabs.create({
        url: itemUrl,
        active: handlerId === 2
      });
      break;

    case 5: // new window
    case 6: // incognito window
      chrome.windows.create({
        url: itemUrl,
        incognito: handlerId === 6
      });
  }

  if (handlerId !== 1 && handlerId !== 4) {
    setTimeout(window.close, 200);
  }
}

function openFolder(props) {
  return globals.getSingleTree(props.itemInfo.id)
    .then((treeInfo) => {
      // clone the array to avoid polluting the prevState value
      const newTrees = props.trees.slice();
      const nextTreeIndex = props.treeIndex + 1;

      newTrees[nextTreeIndex] = treeInfo;

      globals.setRootState({
        trees: newTrees
      });
    });
}

function render({props, state}) {
  const itemClasses = [
    'item',
    'bookmark-item',
    'no-text-overflow'
  ];
  const itemInfo = props.itemInfo;

  const itemTitle = itemInfo.title || itemInfo.url;

  let iconSrc;
  let isDraggable = true;

  if (globals.isFolder(itemInfo)) {
    iconSrc = '/img/folder.png';

    if (globals.isRootFolder(itemInfo)) {
      itemClasses.push('root-folder');

      isDraggable = false;
    }
  } else {
    if (itemInfo.url === globals.separateThisUrl) {
      itemClasses.push('separator');
    } else {
      iconSrc = `chrome://favicon/${itemInfo.url}`;
    }
  }

  return (

      {itemTitle}

  );
}

function setTooltip(el, props) {
  const isSearching = !!props.searchResult;
  const itemInfo = props.itemInfo;
  const tooltipArr = [];

  const setTitle = () => {
    if (tooltipArr.length) {
      el.title = tooltipArr.join('\n');
    }
  };

  if (globals.storage.tooltip) {
    tooltipArr.push(itemInfo.title, itemInfo.url);
  }

  if (isSearching) {
    const breadcrumbArr = [];

    const getBreadcrumb = (breadId) => {
      chrome.bookmarks.get(breadId, (node) => {
        if (node === undefined) {
          return false;
        }

        const thisItemInfo = node[0];

        if (![itemInfo.id, '0'].includes(thisItemInfo.id)) {
          breadcrumbArr.unshift(thisItemInfo.title);
        }

        if (thisItemInfo.parentId !== undefined) {
          getBreadcrumb(thisItemInfo.parentId);
        } else {
          tooltipArr.unshift(breadcrumbArr.join(' > '));

          setTitle();
        }
      });
    };

    getBreadcrumb(itemInfo.id);
  } else {
    setTitle();
  }
}

export default {afterMount, render};
<commit_msg>Disable dragging when searching<commit_after>import {element} from 'deku';

const _getMsg = chrome.i18n.getMessage;

function afterMount({props}, el) {
  const itemInfo = props.itemInfo;

  if (!globals.isFolder(itemInfo) &&
      itemInfo.url !== globals.separateThisUrl) {
    setTooltip(el, props);
  }
}

function clickHandler(event, {props, state}) {
  const itemInfo = props.itemInfo;

  switch (globals.getBookmarkType(itemInfo)) {
    case 'folder':
      break;

    case 'bookmark':
      openBookmark(getOpenBookmarkHandlerId(event), itemInfo.url);
  }
}

function contextMenuHandler(event, {props, state}, updateState) {
  // disable native context menu
  event.preventDefault();

  const itemInfo = props.itemInfo;

  globals.setRootState({
    menuTarget: itemInfo,
    mousePos: {x: event.x, y: event.y}
  });
}

function dragEndHandler(event, {props, state}) {

}

function dragOverHandler(event, {props, state}) {

}

function dragStartHandler(event, {props, state}) {

}

function getOpenBookmarkHandlerId(event) {
  const mouseButton = event.button;

  let switcher;

  if (mouseButton === 0) {
    switcher = 'Left';

    if (event.shiftKey) {
      switcher += 'Shift';
    } else if (event.ctrlKey) {
      switcher += 'Ctrl';
    }
  } else {
    switcher = 'Middle';
  }

  return globals.storage['clickBy' + switcher];
}

function mouseEnterHandler(event, {props, state}, updateState) {
  if (event.target !== event.delegateTarget) {
    return true;
  }

  const itemInfo = props.itemInfo;

  if (globals.isFolder(itemInfo)) {
    openFolder(props);
  } else {
    globals.removeTreeInfoFromIndex(props.trees, props.treeIndex + 1);
  }
}

function mouseLeaveHandler(event, {props, state}, updateState) {
  if (event.target !== event.delegateTarget) {
    return true;
  }
}

function openBookmark(handlerId, itemUrl) {
  switch (handlerId) {
    case 0: // current tab
    case 1: // current tab (w/o closing PmB)
      if (itemUrl.indexOf('javascript') !== 0) {
        chrome.tabs.update({url: itemUrl});
      } else {
        if (globals.storage.bookmarklet) {
          chrome.tabs.executeScript(null, {code: itemUrl});
        } else if (confirm(_getMsg('alert_bookmarklet'))) {
          globals.openOptionsPage();
        }
      }
      break;

    case 2: // new tab
    case 3: // background tab
    case 4: // background tab (w/o closing PmB)
      chrome.tabs.create({
        url: itemUrl,
        active: handlerId === 2
      });
      break;

    case 5: // new window
    case 6: // incognito window
      chrome.windows.create({
        url: itemUrl,
        incognito: handlerId === 6
      });
  }

  if (handlerId !== 1 && handlerId !== 4) {
    setTimeout(window.close, 200);
  }
}

function openFolder(props) {
  return globals.getSingleTree(props.itemInfo.id)
    .then((treeInfo) => {
      // clone the array to avoid polluting the prevState value
      const newTrees = props.trees.slice();
      const nextTreeIndex = props.treeIndex + 1;

      newTrees[nextTreeIndex] = treeInfo;

      globals.setRootState({
        trees: newTrees
      });
    });
}

function render({props, state}) {
  const isSearching = !!props.searchResult;
  const itemClasses = [
    'item',
    'bookmark-item',
    'no-text-overflow'
  ];
  const itemInfo = props.itemInfo;

  const itemTitle = itemInfo.title || itemInfo.url;

  let iconSrc;
  let isDraggable = true;

  if (globals.isFolder(itemInfo)) {
    iconSrc = '/img/folder.png';

    if (globals.isRootFolder(itemInfo)) {
      itemClasses.push('root-folder');

      isDraggable = false;
    }
  } else {
    if (itemInfo.url === globals.separateThisUrl) {
      itemClasses.push('separator');
    } else {
      iconSrc = `chrome://favicon/${itemInfo.url}`;
    }
  }

  if (isSearching) {
    isDraggable = false;
  }

  return (

      {itemTitle}

  );
}

function setTooltip(el, props) {
  const isSearching = !!props.searchResult;
  const itemInfo = props.itemInfo;
  const tooltipArr = [];

  const setTitle = () => {
    if (tooltipArr.length) {
      el.title = tooltipArr.join('\n');
    }
  };

  if (globals.storage.tooltip) {
    tooltipArr.push(itemInfo.title, itemInfo.url);
  }

  if (isSearching) {
    const breadcrumbArr = [];

    const getBreadcrumb = (breadId) => {
      chrome.bookmarks.get(breadId, (node) => {
        if (node === undefined) {
          return false;
        }

        const thisItemInfo = node[0];

        if (![itemInfo.id, '0'].includes(thisItemInfo.id)) {
          breadcrumbArr.unshift(thisItemInfo.title);
        }

        if (thisItemInfo.parentId !== undefined) {
          getBreadcrumb(thisItemInfo.parentId);
        } else {
          tooltipArr.unshift(breadcrumbArr.join(' > '));

          setTitle();
        }
      });
    };

    getBreadcrumb(itemInfo.id);
  } else {
    setTitle();
  }
}

export default {afterMount, render};
<|endoftext|>


<commit_before>'use strict';

function onObjectSelected(e) {
  console.log("selected!");
  var selectedObject = e.target;
  $("#text-string").val("");
  selectedObject.hasRotatingPoint = true
  if (selectedObject && selectedObject.type === 'text') {
    //display text editor
    $("#texteditor").css('display', 'block');
    $("#text-string").val(selectedObject.getText());
    $('#text-fontcolor').miniColors('value',selectedObject.fill);
    $('#text-strokecolor').miniColors('value',selectedObject.strokeStyle);
    $("#imageeditor").css('display', 'block');
  }
  else if (selectedObject && selectedObject.type === 'image'){
    //display image editor
    $("#texteditor").css('display', 'none');
    $("#imageeditor").css('display', 'block');
  }
};

function onSelectedCleared(e){
  console.log("cleared!");
  $("#texteditor").css('display', 'none');
  $("#text-string").val("");
  $("#imageeditor").css('display', 'none');
};

function setFont(font){
  var activeObject = canvas.getActiveObject();
  if (activeObject && activeObject.type === 'text') {
    activeObject.fontFamily = font;
    canvas.renderAll();
  }
};

function removeWhite(){
  var activeObject = canvas.getActiveObject();
  if (activeObject && activeObject.type === 'image') {
    activeObject.filters[2] =  new fabric.Image.filters.RemoveWhite({hreshold: 100, distance: 10});//0-255, 0-255
    activeObject.applyFilters(canvas.renderAll.bind(canvas));
  }
};

/* Directives */
angular.module('monadexApp.directives', []).
  directive('appVersion', ['version', function(version) {
    return function(scope, elm, attrs) {
      elm.text(version);
    };
  }])
  .directive('tshirtDesigner', ['$document', function($document) {
    return {
      restrict: 'E',
      scope: {
        colors: '=tshirtcolors',
        images: '=tshirtimages',
        tshirtTypes: '=tshirttypes',
        fonts: '='
      },
      templateUrl: 'partials/tshirt-designer.html',
      link: function(scope, element, attrs) {
        $(window).load(function() {
          var canvas;
          var line1;
          var line2;
          var line3;
          var line4;

          //setup front side canvas
          canvas = new fabric.Canvas('tcanvas', {
            hoverCursor: 'pointer',
            selection: true,
            selectionBorderColor:'blue'
          });

          canvas.on({
            'object:moving': function(e) {
              e.target.opacity = 0.5;
            },
            'object:modified': function(e) {
              e.target.opacity = 1;
            },
            'object:selected':onObjectSelected,
            'selection:cleared':onSelectedCleared
          });

          // piggyback on `canvas.findTarget`, to fire "object:over" and "object:out" events
          canvas.findTarget = (function(originalFn) {
            return function() {
              var target = originalFn.apply(this, arguments);
              if (target) {
	        if (this._hoveredTarget !== target) {
	          canvas.fire('object:over', { target: target });
	          if (this._hoveredTarget) {
	            canvas.fire('object:out', { target: this._hoveredTarget });
	          }
	          this._hoveredTarget = target;
	        }
              }
              else if (this._hoveredTarget) {
	        canvas.fire('object:out', { target: this._hoveredTarget });
	        this._hoveredTarget = null;
              }
              return target;
            };
          })(canvas.findTarget);

          canvas.on('object:over', function(e) {
            //e.target.setFill('red');
            //canvas.renderAll();
          });

          canvas.on('object:out', function(e) {
            //e.target.setFill('green');
            //canvas.renderAll();
          });

          $('#add-text').click(function(){
            var text = $("#text-string").val();
            var textSample = new fabric.Text(text, {
              left: fabric.util.getRandomInt(0, 200),
              top: fabric.util.getRandomInt(0, 400),
              fontFamily: 'helvetica',
              angle: 0,
              fill: '#000000',
              scaleX: 0.5,
              scaleY: 0.5,
              fontWeight: '',
              hasRotatingPoint:true
            });
            canvas.add(textSample);
            canvas.item(canvas.item.length-1).hasRotatingPoint = true;
            $("#texteditor").css('display', 'block');
            $("#imageeditor").css('display', 'block');
          });

          $("#text-string").keyup(function(){
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.text = this.value;
              canvas.renderAll();
            }
          });

          $(".img-polaroid").on("click", function(e){
            var el = e.target;
            /*temp code*/
            var offset = 50;
            var left = fabric.util.getRandomInt(0 + offset, 200 - offset);
            var top = fabric.util.getRandomInt(0 + offset, 400 - offset);
            var angle = fabric.util.getRandomInt(-20, 40);
            var width = fabric.util.getRandomInt(30, 50);
            var opacity = (function(min, max){ return Math.random() * (max - min) + min; })(0.5, 1);

            fabric.Image.fromURL(el.src, function(image) {
              image.set({
                left: left,
                top: top,
                angle: 0,
                padding: 10,
                cornersize: 10,
                hasRotatingPoint:true
              });
              //image.scale(getRandomNum(0.1, 0.25)).setCoords();
              canvas.add(image);
            });
          });

          $('#remove-selected').click(function() {
            var activeObject = canvas.getActiveObject(),
            activeGroup = canvas.getActiveGroup();
            if (activeObject) {
              canvas.remove(activeObject);
              $("#text-string").val("");
            }
            else if (activeGroup) {
              var objectsInGroup = activeGroup.getObjects();
              canvas.discardActiveGroup();
              objectsInGroup.forEach(function(object) {
	        canvas.remove(object);
              });
            }
          });

          $('#bring-to-front').click(function() {
            var activeObject = canvas.getActiveObject(),
            activeGroup = canvas.getActiveGroup();
            if (activeObject) {
              activeObject.bringToFront();
            }
            else if (activeGroup) {
              var objectsInGroup = activeGroup.getObjects();
              canvas.discardActiveGroup();
              objectsInGroup.forEach(function(object) {
	        object.bringToFront();
              });
            }
          });

          $('#send-to-back').click(function() {
            var activeObject = canvas.getActiveObject(),
            activeGroup = canvas.getActiveGroup();
            if (activeObject) {
              activeObject.sendToBack();
            }
            else if (activeGroup) {
              var objectsInGroup = activeGroup.getObjects();
              canvas.discardActiveGroup();
              objectsInGroup.forEach(function(object) {
	        object.sendToBack();
              });
            }
          });

          $("#text-bold").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.fontWeight = (activeObject.fontWeight == 'bold' ? '' : 'bold');
              canvas.renderAll();
            }
          });

          $("#text-italic").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.fontStyle = (activeObject.fontStyle == 'italic' ? '' : 'italic');
              canvas.renderAll();
            }
          });

          $("#text-strike").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textDecoration = (activeObject.textDecoration == 'line-through' ? '' : 'line-through');
              canvas.renderAll();
            }
          });

          $("#text-underline").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textDecoration = (activeObject.textDecoration == 'underline' ? '' : 'underline');
              canvas.renderAll();
            }
          });

          $("#text-left").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textAlign = 'left';
              canvas.renderAll();
            }
          });

          $("#text-center").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textAlign = 'center';
              canvas.renderAll();
            }
          });

          $("#text-right").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textAlign = 'right';
              canvas.renderAll();
            }
          });

          $("#font-family").change(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.fontFamily = this.value;
              canvas.renderAll();
            }
          });

          $('#text-bgcolor').miniColors({
            change: function(hex, rgb) {
              var activeObject = canvas.getActiveObject();
              if (activeObject && activeObject.type === 'text') {
	        activeObject.backgroundColor = this.value;
	        canvas.renderAll();
              }
            },
            open: function(hex, rgb) {
              //
            },
            close: function(hex, rgb) {
              //
            }
          });

          $('#text-fontcolor').miniColors({
            change: function(hex, rgb) {
              var activeObject = canvas.getActiveObject();
              if (activeObject && activeObject.type === 'text') {
	        activeObject.fill = this.value;
	        canvas.renderAll();
              }
            },
            open: function(hex, rgb) {
              //
            },
            close: function(hex, rgb) {
              //
            }
          });

          $('#text-strokecolor').miniColors({
            change: function(hex, rgb) {
              var activeObject = canvas.getActiveObject();
              if (activeObject && activeObject.type === 'text') {
	        activeObject.strokeStyle = this.value;
	        canvas.renderAll();
              }
            },
            open: function(hex, rgb) {
              //
            },
            close: function(hex, rgb) {
              //
            }
          });

        //canvas.add(new fabric.fabric.Object({hasBorders:true,hasControls:false,hasRotatingPoint:false,selectable:false,type:'rect'}));
          $("#drawingArea").hover(
            function() {
              canvas.add(line1);
              canvas.add(line2);
              canvas.add(line3);
              canvas.add(line4);
              canvas.renderAll();
            },
            function() {
              canvas.remove(line1);
              canvas.remove(line2);
              canvas.remove(line3);
              canvas.remove(line4);
              canvas.renderAll();
            }
          );

          $('.color-preview').on("click", function(){
            var color = $(this).css("background-color");
            $("#shirtDiv").css("backgroundColor", color);
          });

          $('#flip').click(
            function() {
              if ($(this).attr("data-original-title") == "Show Back View") {
	        $(this).attr('data-original-title', 'Show Front View');
	        $("#tshirtFacing").attr("src","img/crew_back.png");
	        a = JSON.stringify(canvas);
	        canvas.clear();
	        try
	        {
	          var json = JSON.parse(b);
	          canvas.loadFromJSON(b);
	        }
	        catch(e)
	        {}

              } else {
	        $(this).attr('data-original-title', 'Show Back View');
	        $("#tshirtFacing").attr("src","img/crew_front.png");
	        b = JSON.stringify(canvas);
	        canvas.clear();
	        try
	        {
	          var json = JSON.parse(a);
	          canvas.loadFromJSON(a);
	        }
	        catch(e)
	        {}
              }
              canvas.renderAll();
              setTimeout(function() {
	        canvas.calcOffset();
              },200);
            });

          $(".clearfix button,a").tooltip();
          line1 = new fabric.Line([0,0,200,0], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
          line2 = new fabric.Line([199,0,200,399], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
          line3 = new fabric.Line([0,0,0,400], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
          line4 = new fabric.Line([0,400,200,399], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
        })}
    };
  }]);
<commit_msg>use directives variable<commit_after>'use strict';

function onObjectSelected(e) {
  console.log("selected!");
  var selectedObject = e.target;
  $("#text-string").val("");
  selectedObject.hasRotatingPoint = true
  if (selectedObject && selectedObject.type === 'text') {
    //display text editor
    $("#texteditor").css('display', 'block');
    $("#text-string").val(selectedObject.getText());
    $('#text-fontcolor').miniColors('value',selectedObject.fill);
    $('#text-strokecolor').miniColors('value',selectedObject.strokeStyle);
    $("#imageeditor").css('display', 'block');
  }
  else if (selectedObject && selectedObject.type === 'image'){
    //display image editor
    $("#texteditor").css('display', 'none');
    $("#imageeditor").css('display', 'block');
  }
};

function onSelectedCleared(e){
  console.log("cleared!");
  $("#texteditor").css('display', 'none');
  $("#text-string").val("");
  $("#imageeditor").css('display', 'none');
};

function setFont(font){
  var activeObject = canvas.getActiveObject();
  if (activeObject && activeObject.type === 'text') {
    activeObject.fontFamily = font;
    canvas.renderAll();
  }
};

function removeWhite(){
  var activeObject = canvas.getActiveObject();
  if (activeObject && activeObject.type === 'image') {
    activeObject.filters[2] =  new fabric.Image.filters.RemoveWhite({hreshold: 100, distance: 10});//0-255, 0-255
    activeObject.applyFilters(canvas.renderAll.bind(canvas));
  }
};

/* Directives */
var monadexDirectives = angular.module('monadexApp.directives', []);

monadexDirectives.directive('appVersion', ['version', function(version) {
    return function(scope, elm, attrs) {
      elm.text(version);
    };
  }]);

monadexDirectives.directive('tshirtDesigner', ['$document', function($document) {
    return {
      restrict: 'E',
      scope: {
        colors: '=tshirtcolors',
        images: '=tshirtimages',
        tshirtTypes: '=tshirttypes',
        fonts: '='
      },
      templateUrl: 'partials/tshirt-designer.html',
      link: function(scope, element, attrs) {
        $(window).load(function() {
          var canvas;
          var line1;
          var line2;
          var line3;
          var line4;

          //setup front side canvas
          canvas = new fabric.Canvas('tcanvas', {
            hoverCursor: 'pointer',
            selection: true,
            selectionBorderColor:'blue'
          });

          canvas.on({
            'object:moving': function(e) {
              e.target.opacity = 0.5;
            },
            'object:modified': function(e) {
              e.target.opacity = 1;
            },
            'object:selected':onObjectSelected,
            'selection:cleared':onSelectedCleared
          });

          // piggyback on `canvas.findTarget`, to fire "object:over" and "object:out" events
          canvas.findTarget = (function(originalFn) {
            return function() {
              var target = originalFn.apply(this, arguments);
              if (target) {
	        if (this._hoveredTarget !== target) {
	          canvas.fire('object:over', { target: target });
	          if (this._hoveredTarget) {
	            canvas.fire('object:out', { target: this._hoveredTarget });
	          }
	          this._hoveredTarget = target;
	        }
              }
              else if (this._hoveredTarget) {
	        canvas.fire('object:out', { target: this._hoveredTarget });
	        this._hoveredTarget = null;
              }
              return target;
            };
          })(canvas.findTarget);

          canvas.on('object:over', function(e) {
            //e.target.setFill('red');
            //canvas.renderAll();
          });

          canvas.on('object:out', function(e) {
            //e.target.setFill('green');
            //canvas.renderAll();
          });

          $('#add-text').click(function(){
            var text = $("#text-string").val();
            var textSample = new fabric.Text(text, {
              left: fabric.util.getRandomInt(0, 200),
              top: fabric.util.getRandomInt(0, 400),
              fontFamily: 'helvetica',
              angle: 0,
              fill: '#000000',
              scaleX: 0.5,
              scaleY: 0.5,
              fontWeight: '',
              hasRotatingPoint:true
            });
            canvas.add(textSample);
            canvas.item(canvas.item.length-1).hasRotatingPoint = true;
            $("#texteditor").css('display', 'block');
            $("#imageeditor").css('display', 'block');
          });

          $("#text-string").keyup(function(){
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.text = this.value;
              canvas.renderAll();
            }
          });

          $(".img-polaroid").on("click", function(e){
            var el = e.target;
            /*temp code*/
            var offset = 50;
            var left = fabric.util.getRandomInt(0 + offset, 200 - offset);
            var top = fabric.util.getRandomInt(0 + offset, 400 - offset);
            var angle = fabric.util.getRandomInt(-20, 40);
            var width = fabric.util.getRandomInt(30, 50);
            var opacity = (function(min, max){ return Math.random() * (max - min) + min; })(0.5, 1);

            fabric.Image.fromURL(el.src, function(image) {
              image.set({
                left: left,
                top: top,
                angle: 0,
                padding: 10,
                cornersize: 10,
                hasRotatingPoint:true
              });
              //image.scale(getRandomNum(0.1, 0.25)).setCoords();
              canvas.add(image);
            });
          });

          $('#remove-selected').click(function() {
            var activeObject = canvas.getActiveObject(),
            activeGroup = canvas.getActiveGroup();
            if (activeObject) {
              canvas.remove(activeObject);
              $("#text-string").val("");
            }
            else if (activeGroup) {
              var objectsInGroup = activeGroup.getObjects();
              canvas.discardActiveGroup();
              objectsInGroup.forEach(function(object) {
	        canvas.remove(object);
              });
            }
          });

          $('#bring-to-front').click(function() {
            var activeObject = canvas.getActiveObject(),
            activeGroup = canvas.getActiveGroup();
            if (activeObject) {
              activeObject.bringToFront();
            }
            else if (activeGroup) {
              var objectsInGroup = activeGroup.getObjects();
              canvas.discardActiveGroup();
              objectsInGroup.forEach(function(object) {
	        object.bringToFront();
              });
            }
          });

          $('#send-to-back').click(function() {
            var activeObject = canvas.getActiveObject(),
            activeGroup = canvas.getActiveGroup();
            if (activeObject) {
              activeObject.sendToBack();
            }
            else if (activeGroup) {
              var objectsInGroup = activeGroup.getObjects();
              canvas.discardActiveGroup();
              objectsInGroup.forEach(function(object) {
	        object.sendToBack();
              });
            }
          });

          $("#text-bold").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.fontWeight = (activeObject.fontWeight == 'bold' ? '' : 'bold');
              canvas.renderAll();
            }
          });

          $("#text-italic").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.fontStyle = (activeObject.fontStyle == 'italic' ? '' : 'italic');
              canvas.renderAll();
            }
          });

          $("#text-strike").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textDecoration = (activeObject.textDecoration == 'line-through' ? '' : 'line-through');
              canvas.renderAll();
            }
          });

          $("#text-underline").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textDecoration = (activeObject.textDecoration == 'underline' ? '' : 'underline');
              canvas.renderAll();
            }
          });

          $("#text-left").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textAlign = 'left';
              canvas.renderAll();
            }
          });

          $("#text-center").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textAlign = 'center';
              canvas.renderAll();
            }
          });

          $("#text-right").click(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.textAlign = 'right';
              canvas.renderAll();
            }
          });

          $("#font-family").change(function() {
            var activeObject = canvas.getActiveObject();
            if (activeObject && activeObject.type === 'text') {
              activeObject.fontFamily = this.value;
              canvas.renderAll();
            }
          });

          $('#text-bgcolor').miniColors({
            change: function(hex, rgb) {
              var activeObject = canvas.getActiveObject();
              if (activeObject && activeObject.type === 'text') {
	        activeObject.backgroundColor = this.value;
	        canvas.renderAll();
              }
            },
            open: function(hex, rgb) {
              //
            },
            close: function(hex, rgb) {
              //
            }
          });

          $('#text-fontcolor').miniColors({
            change: function(hex, rgb) {
              var activeObject = canvas.getActiveObject();
              if (activeObject && activeObject.type === 'text') {
	        activeObject.fill = this.value;
	        canvas.renderAll();
              }
            },
            open: function(hex, rgb) {
              //
            },
            close: function(hex, rgb) {
              //
            }
          });

          $('#text-strokecolor').miniColors({
            change: function(hex, rgb) {
              var activeObject = canvas.getActiveObject();
              if (activeObject && activeObject.type === 'text') {
	        activeObject.strokeStyle = this.value;
	        canvas.renderAll();
              }
            },
            open: function(hex, rgb) {
              //
            },
            close: function(hex, rgb) {
              //
            }
          });

        //canvas.add(new fabric.fabric.Object({hasBorders:true,hasControls:false,hasRotatingPoint:false,selectable:false,type:'rect'}));
          $("#drawingArea").hover(
            function() {
              canvas.add(line1);
              canvas.add(line2);
              canvas.add(line3);
              canvas.add(line4);
              canvas.renderAll();
            },
            function() {
              canvas.remove(line1);
              canvas.remove(line2);
              canvas.remove(line3);
              canvas.remove(line4);
              canvas.renderAll();
            }
          );

          $('.color-preview').on("click", function(){
            var color = $(this).css("background-color");
            $("#shirtDiv").css("backgroundColor", color);
          });

          $('#flip').click(
            function() {
              if ($(this).attr("data-original-title") == "Show Back View") {
	        $(this).attr('data-original-title', 'Show Front View');
	        $("#tshirtFacing").attr("src","img/crew_back.png");
	        a = JSON.stringify(canvas);
	        canvas.clear();
	        try
	        {
	          var json = JSON.parse(b);
	          canvas.loadFromJSON(b);
	        }
	        catch(e)
	        {}

              } else {
	        $(this).attr('data-original-title', 'Show Back View');
	        $("#tshirtFacing").attr("src","img/crew_front.png");
	        b = JSON.stringify(canvas);
	        canvas.clear();
	        try
	        {
	          var json = JSON.parse(a);
	          canvas.loadFromJSON(a);
	        }
	        catch(e)
	        {}
              }
              canvas.renderAll();
              setTimeout(function() {
	        canvas.calcOffset();
              },200);
            });

          $(".clearfix button,a").tooltip();
          line1 = new fabric.Line([0,0,200,0], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
          line2 = new fabric.Line([199,0,200,399], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
          line3 = new fabric.Line([0,0,0,400], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
          line4 = new fabric.Line([0,400,200,399], {"stroke":"#000000", "strokeWidth":1,hasBorders:false,hasControls:false,hasRotatingPoint:false,selectable:false});
        })}
    };
  }]);
<|endoftext|>