<commit_before>// @flow

import SimpleChanDaemonPlugin from 'plugins/SimpleChanDaemonPlugin';
import Norbert from 'lib/Norbert';

export default class SedPlugin extends SimpleChanDaemonPlugin {
    init(norbert:Norbert) {
        super.init(norbert);
        this.requirePlugin('History');
    }

    getName() {
        return "Sed";
    }

    getHelp() {
        return {
            overview: "Watches for s/search/replace/flags style statements."
        };
    }

    getTriggers():[ (word:string, sender:string, channel:string, idx?:number) => false|
        (channel:string, sender:string, message:string, client:Norbert,triggered:string)=>void] {

        return [
            this.isSed
        ];
    }

    isSed(word:string, sender:string, channel:string, idx:number = 0) {
        return idx == 0 && word.startsWith('s/') ? this.handleReplaceMessage: false;
    }

    handleReplaceMessage(channel:string, sender:string, message:string, norbert:Norbert, triggered:string) {
        let parsed = this.parseSed(message);

        if(parsed === false) {
            return;
        }

        let {search, replace, flags} = parsed;

        let searchExp;

        try {
            searchExp = new RegExp(search, flags);
        } catch(e) {
            try {
                searchExp = new RegExp(search);
            } catch(e) {
                searchExp = search;
            }
        }

        //get recent 5 messages from this channel and try to apply them
        let stmt = norbert.db.prepare("SELECT * FROM history " +
            "WHERE `to`=? AND " +
            "   ID < (SELECT MAX(ID) FROM history) AND" +
            "   message NOT LIKE 's/%'" +
            "ORDER BY ID DESC LIMIT 5");
        stmt.all([channel], (err, rows) => {
            if(err) {
                console.error(err);
                norbert.client.say(channel, "error");
                return;
            }

            for(let i = 0; i < rows.length; i++) {
                let row = rows[i];

                if(row.message.match(searchExp)) {
                    let replaced = `${sender} suggests: <${row.from}> ${row.message.replace(searchExp, replace)}`;
                    norbert.client.say(channel, replaced);
                    break;
                }
            }
        })
    }

    parseSed(str:string) : {search: string, replace: string, flags: string}|false {
        if(!str.startsWith('s/')) {
            return false;
        }

        let search = [];
        let replace = [];
        let flags = [];
        let state = 0;

        //i = 2 because of the s/
        for(let i = 2; i < str.length; i++) {
            let chr = str[i];

            if((chr == '/' && str[i - 1] != "\\") ||
                (chr == '/' && str[i - 1] == "\\" && str[i - 2] == "\\")
            ) {
                state++;
                continue;
            }

            if(state == 0) {
                search.push(chr);
            } else if(state == 1) {
                replace.push(chr);
            } else if(state == 2) {
                flags.push(chr);
            }

        }

        search = search.join('');
        replace = replace.join('');
        flags = flags.join('');

        return {
            search, replace, flags
        }
    }
}<commit_msg>lol biny<commit_after>// @flow

import SimpleChanDaemonPlugin from 'plugins/SimpleChanDaemonPlugin';
import Norbert from 'lib/Norbert';

export default class SedPlugin extends SimpleChanDaemonPlugin {
    init(norbert:Norbert) {
        super.init(norbert);
        this.requirePlugin('History');
    }

    getName() {
        return "Sed";
    }

    getHelp() {
        return {
            overview: "Watches for s/search/replace/flags style statements."
        };
    }

    getTriggers():[ (word:string, sender:string, channel:string, idx?:number) => false|
        (channel:string, sender:string, message:string, client:Norbert,triggered:string)=>void] {

        return [
            this.isSed
        ];
    }

    isSed(word:string, sender:string, channel:string, idx:number = 0) {
        return idx == 0 && word.startsWith('s/') ? this.handleReplaceMessage: false;
    }

    handleReplaceMessage(channel:string, sender:string, message:string, norbert:Norbert, triggered:string) {
        let parsed = this.parseSed(message);

        if(parsed === false) {
            return;
        }

        let {search, replace, flags} = parsed;

        let searchExp;

        try {
            searchExp = new RegExp(search, flags);
        } catch(e) {
            try {
                searchExp = new RegExp(search);
            } catch(e) {
                return; //fail here because it's not a valid search
            }
        }

        //get recent 5 messages from this channel and try to apply them
        let stmt = norbert.db.prepare("SELECT * FROM history " +
            "WHERE `to`=? AND " +
            "   ID < (SELECT MAX(ID) FROM history) AND" +
            "   message NOT LIKE 's/%'" +
            "ORDER BY ID DESC LIMIT 5");
        stmt.all([channel], (err, rows) => {
            if(err) {
                console.error(err);
                norbert.client.say(channel, "error");
                return;
            }

            for(let i = 0; i < rows.length; i++) {
                let row = rows[i];

                if(row.message.match(searchExp)) {
                    let replaced = `${sender} suggests: <${row.from}> ${row.message.replace(searchExp, replace)}`;
                    norbert.client.say(channel, replaced);
                    break;
                }
            }
        })
    }

    parseSed(str:string) : {search: string, replace: string, flags: string}|false {
        if(!str.startsWith('s/')) {
            return false;
        }

        let search = [];
        let replace = [];
        let flags = [];
        let state = 0;

        //i = 2 because of the s/
        for(let i = 2; i < str.length; i++) {
            let chr = str[i];

            if((chr == '/' && str[i - 1] != "\\") ||
                (chr == '/' && str[i - 1] == "\\" && str[i - 2] == "\\")
            ) {
                state++;
                continue;
            }

            if(state == 0) {
                search.push(chr);
            } else if(state == 1) {
                replace.push(chr);
            } else if(state == 2) {
                flags.push(chr);
            }

        }

        search = search.join('');
        replace = replace.join('');
        flags = flags.join('');

        return {
            search, replace, flags
        }
    }
}<|endoftext|>


<commit_before>"use strict";

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var pokemonGoBasicSchema = new Schema({
    Number: {type: String},
    Name: {type: String},
    Classification: {type: String},
    Types: [String],
    Resistant: [String],
    Weaknesses: [String],
    Fast_Attacks: [{Name: {type: String}, Type: {type: String}, Damage: {type: Number}}],
    Special_Attacks: [{Name: {type: String}, Type: {type: String}, Damage: {type: Number}}],
    Weight: {
        Minimum: {type: String},
        Maximum: {type: String}
    },
    Height: {
        Minimum: {type: String},
        Maximum: {type: String}
    },
    FleeRate: Number,
    Next_evolutions: [{Number: Number, Name: {type: String}}],
    Previous_evolutions: [{Number: Number, Name: {type: String}}],
    MaxCP: Number,
    MaxHP: Number,
    gender: {
        abbreviation: {
            type: String, enum: ['m', 'f', 'g', 'h'] //m=male, f=female, g=genderless, h=hermaphrodite
        },
        male_ratio: Number,
        female_ratio: Number,
        breedable: Boolean
    }

});

module.exports = mongoose.model('pokemonGoBasic', pokemonGoBasicSchema);
<commit_msg>changed collection name<commit_after>"use strict";

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var pokemonGoBasicSchema = new Schema({
    Number: {type: String},
    Name: {type: String},
    Classification: {type: String},
    Types: [String],
    Resistant: [String],
    Weaknesses: [String],
    Fast_Attacks: [{Name: {type: String}, Type: {type: String}, Damage: {type: Number}}],
    Special_Attacks: [{Name: {type: String}, Type: {type: String}, Damage: {type: Number}}],
    Weight: {
        Minimum: {type: String},
        Maximum: {type: String}
    },
    Height: {
        Minimum: {type: String},
        Maximum: {type: String}
    },
    FleeRate: Number,
    Next_evolutions: [{Number: Number, Name: {type: String}}],
    Previous_evolutions: [{Number: Number, Name: {type: String}}],
    MaxCP: Number,
    MaxHP: Number,
    gender: {
        abbreviation: {
            type: String, enum: ['m', 'f', 'g', 'h'] //m=male, f=female, g=genderless, h=hermaphrodite
        },
        male_ratio: Number,
        female_ratio: Number,
        breedable: Boolean
    }

});

module.exports = mongoose.model('BasicPokemonDetail', pokemonGoBasicSchema);
<|endoftext|>


<commit_before>// I would mark my relationship with javascript as 'its complicated'
Lawnchair.plugin((function(){

    // methods we want to augment with before/after callback registery capability
    var methods = 'save batch get remove nuke'.split(' ')
    ,   registry = {before:{}, after:{}}

    // fill in the blanks
    for (var i = 0, l = methods.length; i < l; i++) {
        registry.before[methods[i]] = []
        registry.after[methods[i]] = []
    }

    return {
    // start of module

        // roll thru each method we with to augment
        init: function () {
            for (var i = 0, l = methods.length; i < l; i++) {
                this.evented(methods[i])
            }
        },
        // TODO make private
        // rewrites a method with before/after callback capability
        evented: function (methodName) {
            var oldy = this[methodName], self = this
            // overwrite the orig method
            this[methodName] = function() {
                var args              = [].slice.call(arguments)
                ,   beforeObj         = args[0]
                ,   oldCallback       = args[args.length - 1]
                ,   overwroteCallback = false

                // call before with obj
                this.fire('before', methodName, beforeObj)

                if (typeof oldCallback === 'function') {
                    // overwrite final callback with after method injection
                    args[args.length - 1] = function(record) {
                        oldCallback.call(self, record)
                        self.fire('after', methodName, record)
                    }
                    overwroteCallback = true
                }

                // finally call the orig method
                oldy.apply(self, args)

                // if there was no callback to override for after we invoke here
                if (!overwroteCallback)
                    self.fire('after', methodName, beforeObj)
            }
        },

        // TODO make private method for invoking callbacks
        fire: function (when, methodName, record) {
            var callbacks = registry[when][methodName]
            for (var i = 0, l = callbacks.length; i < l; i++) {
                callbacks[i].call(this, record)
            }
        },

        // TODO cleanup duplication here
        clearBefore: function(methodName) {
            registry.before[methodName] = []
        },

        clearAfter: function(methodName) {
            registry.after[methodName] = []
        },

        // register before callback for methodName
        before: function (methodName, callback) {
            registry.before[methodName].push(callback)
        },

        // register after callback for methodName
        after: function (methodName, callback) {
            registry.after[methodName].push(callback)
        }

    // end module
    }
})())

<commit_msg>tweaking hte callbacks<commit_after>// I would mark my relationship with javascript as 'its complicated'
Lawnchair.plugin((function(){

    // methods we want to augment with before/after callback registery capability
    var methods = 'save batch get remove nuke'.split(' ')
    ,   registry = {before:{}, after:{}}

    // fill in the blanks
    for (var i = 0, l = methods.length; i < l; i++) {
        registry.before[methods[i]] = []
        registry.after[methods[i]] = []
    }

    return {
    // start of module

        // roll thru each method we with to augment
        init: function () {
            for (var i = 0, l = methods.length; i < l; i++) {
                this.evented(methods[i])
            }
        },
        // TODO make private?
        // rewrites a method with before/after callback capability
        evented: function (methodName) {
            var oldy = this[methodName], self = this
            // overwrite the orig method
            this[methodName] = function() {
                var args              = [].slice.call(arguments)
                ,   beforeObj         = args[0]
                ,   oldCallback       = args[args.length - 1]
                ,   overwroteCallback = false

                // call before with obj
                this.fire('before', methodName, beforeObj)

                if (typeof oldCallback === 'function') {
                    // overwrite final callback with after method injection
                    args[args.length - 1] = function(record) {
                        oldCallback.call(self, record)
                        self.fire('after', methodName, record)
                    }
                    overwroteCallback = true
                }

                // finally call the orig method
                oldy.apply(self, args)

                // if there was no callback to override for after we invoke here
                if (!overwroteCallback)
                    self.fire('after', methodName, beforeObj)
            }
        },

        // TODO definitely make private method
        // for invoking callbacks
        fire: function (when, methodName, record) {
            var callbacks = registry[when][methodName]
            for (var i = 0, l = callbacks.length; i < l; i++) {
                callbacks[i].call(this, record)
            }
        },

        // TODO cleanup duplication that starts here..
        clearBefore: function(methodName) {
            registry.before[methodName] = []
        },

        clearAfter: function(methodName) {
            registry.after[methodName] = []
        },

        // register before callback for methodName
        before: function (methodName, callback) {
            registry.before[methodName].push(callback)
        },

        // register after callback for methodName
        after: function (methodName, callback) {
            registry.after[methodName].push(callback)
        }

    // end module
    }
})())

<|endoftext|>


<commit_before>//- JavaScript source code

//- method-Q2.js ~~
//                                                      ~~ (c) SRW, 07 Sep 2011

Object.prototype.Q = (function () {     //- (begin strict anonymous closure)
    "use strict";

 // Declarations

    var __DEBUG__, bookmarks, celebrate, define, die, map, methodQ, ply,
        postpone, reduce;

 // Fake macros

    __DEBUG__ = false;

 // Constructors

    function ExitFailure(report) {
        this.report = report;
        return this;
    }

    function ExitSuccess(report) {
        this.report = report;
        return this;
    }

    function QuanahVar(x) {
        var content, job, ready, revive, stack, that;
        content = x;
        job = undefined;
        ready = true;
        revive = function () {
            if (ready === true) {
                job = stack.shift();
                if (job !== undefined) {
                    try {
                        job.call(that, that.content);
                    } catch (err) {
                        that.trigger = err;
                    }
                }
            }
        };
        stack = [];
        that = this;
        define(that, "content", {
            configurable: false,
            enumerable: true,
            get: function () {
                if (__DEBUG__ === true) {
                    console.log("(tripped getter)");
                }
                return content;
            },
            set: function (x) {
                content = x;
                if (__DEBUG__ === true) {
                    console.log("(tripped setter)");
                }
                return content;
            }
        });
        define(that, "onready", {
            configurable: false,
            enumerable: true,
            get: function () {
             // This is intended to provide a means to inspect outstanding
             // tasks that have not yet been applied to the content's value
             // but JS pass-by-reference immediately implies that it could
             // be used to modify the queue in-place ...
                return (stack.length === 0) ? null : stack[0];
            },
            set: function (f) {
                if ((f instanceof Function) && (typeof f === 'function')) {
                    stack.push(f);
                    revive();
                } else {
                    throw new Error('"onready" only accepts functions.');
                }
            }
        });
        define(that, "trigger", {
            configurable: false,
            enumerable: true,
         // (no getter defined)
            set: function (x) {
                switch (x.constructor) {
                case ExitSuccess:
                    console.log("(exit success)");
                    ready = true;
                    return;
                case ExitFailure:
                    console.log("(exit failure)");
                    return;
                case TryAgainLater:
                    console.log("(try again later)");
                    stack.push(job);
                    ready = true;
                    return;
                default:
                    console.log(x);
                    console.log("(unknown trigger)");
                    return;
                }
            }
        });
        define(that, "type", {
            configurable: false,
            enumerable: true,
            value: "QuanahVar"
        });
        return that;
    }

    function TryAgainLater(message) {
        if (message.toString().length === 0) {
            this.message = "Dying ...";
        } else {
            this.message = message.toString();
        }
    }

    TryAgainLater.prototype = new Error();

 // Definitions

    if (location.port === "") {
     // This happens if we are actually using the rewrite rules I created
     // for my personal machine, but I haven't tested them on CouchOne ...
        bookmarks = {
            app:    location.href.replace(location.pathname, '/'),
            db:     location.href.replace(location.pathname, '/db/'),
            uuids:  location.href.replace(location.pathname,
                        '/_uuids?count=1000')
        };
    } else if (location.port === "5984") {
     // This is CouchDB's default debugging port, and the convention then
     // is to disable rewrite rules when using that port. In that case, I
     // have avoided hard-coding assumptions about the deployment target
     // by instead opting to navigate paths relative to the current URL.
        bookmarks = {
            app:    location.href.replace(location.pathname, '/') +
                        location.pathname.match(/([\w]+\/){3}/)[0],
            db:     location.href.replace(location.pathname, '/') +
                        location.pathname.match(/([\w]+\/){1}/)[0],
            uuids:  location.href.replace(location.pathname,
                        '/_uuids?count=1000')
        };
    } else {
     // Because this is still experimental, we may find problems.
        throw new Error("Relative path detection fell through.");
    }

    celebrate = function (message) {
        this.trigger = new ExitSuccess(message);
    };

    define = function (obj, key, params) {
        if (typeof Object.defineProperty === 'function') {
            define = function (obj, key, params) {
                return Object.defineProperty(obj, key, params);
            };
        } else {
            define = function (obj, key, params) {
                var prop;
                for (prop in params) {
                    if (params.hasOwnProperty(prop) === true) {
                        switch (prop) {
                        case "get":
                            obj.__defineGetter__(key, params[prop]);
                            break;
                        case "set":
                            obj.__defineSetter__(key, params[prop]);
                            break;
                        case "value":
                            delete obj[key];
                            obj[key] = params[prop];
                            break;
                        default:
                         // (placeholder)
                        }
                    }
                }
                return obj;
            };
        }
        return define(obj, key, params);
    };

    die = function (message) {
        this.trigger = new ExitFailure(message);
    };

    methodQ = function (f) {
        var x, y;
        x = new QuanahVar(this);
        switch (f.name) {
        case "map":
            x.onready = function (x) {
                y = map(x, f);
                celebrate.call(x, '(finished "map")');
            };
            return y;
        case "ply":
            x.onready = function (x) {
                ply(x, f);
                celebrate.call(x, '(finished "ply")');
            };
            return x;
        case "reduce":
            x.onready = function (x) {
                y = reduce(x, f);
                celebrate.call(x, '(finished "reduce")');
            };
            return y;
        default:
            x.onready = f;
            return x;
        }
    };

    map = function (x, f) {
        var y;
        if ((x instanceof Object) === false) {
            return f(x);
        } else {
            y = Object.create(Object.getPrototypeOf(x));
            ply(x, function (key, val) {
                y[key] = f(val);
            });
            return y;
        }
    };

    ply = function (x, f) {
        var key;
        if ((x instanceof Object) === false) {
            f(undefined, x);
        } else {
            for (key in x) {
                if (x.hasOwnProperty(key)) {
                    f(key, x[key]);
                }
            }
        }
    };

    postpone = function (message) {
        this.trigger = new TryAgainLater(message);
    };

    reduce = function (x, f) {
        var first, y;
        if ((x instanceof Object) === false) {
            throw new Error('Cannot "reduce" a primitive.');
        } else {
            first = true;
            ply(x, function (key, val) {
                if (first === true) {
                    first = false;
                    y = val;            //- initialize y
                } else {
                    y = f(y, val);      //- apply a simple left-reduce pattern
                }
            });
            return y;
        }
    };

    return methodQ;

}());                                   //- (end strict anonymous closure)

//- Demonstrations -- FOR DEBUGGING PURPOSES ONLY!

console.log([1, 2, 3, 4, 5].Q(function map(each) {
    "use strict";
    return 3 * each;
}));

[1, 2, 3, 4, 5].Q(function ply(key, val) {
    "use strict";
    console.log(key + ": " + val);
});

console.log([1, 2, 3, 4, 5].Q(function reduce(a, b) {
    "use strict";
    return a + b;
}));

//- vim:set syntax=javascript:
<commit_msg>The "QuanahVar" type is now stable enough I will consider putting the AJAX calls in and tying it to CouchDB again ... soon ;-)<commit_after>//- JavaScript source code

//- method-Q2.js ~~
//
//  For now, this supports some vaguely generalized array patterns, but they
//  can only be executed locally -- I don't want to deal with AJAX quite yet.
//
//                                                      ~~ (c) SRW, 07 Sep 2011

Object.prototype.Q = (function (global) {
    "use strict";

 // Declarations

    var __DEBUG__, bookmarks, celebrate, define, die, filter, map, methodQ,
        ply, postpone, reduce;

 // Fake macros

    __DEBUG__ = false;

 // Constructors

    function ExitFailure(report) {
        this.report = report;
        return this;
    }

    function ExitSuccess(report) {
        this.report = report;
        return this;
    }

    function QuanahVar(x) {
        var content, job, ready, revive, stack, that;
        content = x;
        job = undefined;
        ready = true;
        revive = function () {
            if (ready === true) {
                job = stack.shift();
                if (job !== undefined) {
                    try {
                        job.call(that, that.content);
                    } catch (err) {
                        that.trigger = err;
                    }
                }
            }
        };
        stack = [];
        that = this;
        define(that, "content", {
            configurable: false,
            enumerable: true,
            get: function () {
                if (__DEBUG__ === true) {
                    console.log("(tripped getter)");
                }
                return content;
            },
            set: function (x) {
                content = x;
                if (__DEBUG__ === true) {
                    console.log("(tripped setter)");
                }
                return content;
            }
        });
        define(that, "onready", {
            configurable: false,
            enumerable: true,
            get: function () {
             // This is intended to provide a means to inspect outstanding
             // tasks that have not yet been applied to the content's value
             // but JS pass-by-reference immediately implies that it could
             // be used to modify the queue in-place ...
                return (stack.length === 0) ? null : stack[0];
            },
            set: function (f) {
                if ((f instanceof Function) && (typeof f === 'function')) {
                    stack.push(f);
                    revive();
                } else {
                    throw new Error('"onready" only accepts functions.');
                }
            }
        });
        define(that, "trigger", {
            configurable: false,
            enumerable: true,
            get: function () {
             // (this is a placeholder so console inspection works correctly)
            },
            set: function (x) {
                switch (x.constructor) {
                case ExitSuccess:
                    if (__DEBUG__ === true) {
                        console.log("(exit success)");
                    }
                    ready = true;
                    return that;
                case ExitFailure:
                    if (__DEBUG__ === true) {
                        console.log("(exit failure)");
                    }
                    return that;
                case TryAgainLater:
                    if (__DEBUG__ === true) {
                        console.log("(try again later)");
                    }
                    stack.unshift(job); //- put it back in front of the rest
                    ready = false;
                    return that;
                default:
                    if (__DEBUG__ === true) {
                        console.log("(unknown trigger)");
                    }
                    return that;
                }
            }
        });
        define(that, "type", {
            configurable: false,
            enumerable: true,
            value: "QuanahVar"
        });
        return that;
    }

    function TryAgainLater(message) {
        if (message.toString().length === 0) {
            this.message = "Dying ...";
        } else {
            this.message = message.toString();
        }
    }

    TryAgainLater.prototype = new Error();

 // Definitions

    if (location.port === "") {
     // This happens if we are actually using the rewrite rules I created
     // for my personal machine, but I haven't tested them on CouchOne ...
        bookmarks = {
            app:    location.href.replace(location.pathname, '/'),
            db:     location.href.replace(location.pathname, '/db/'),
            uuids:  location.href.replace(location.pathname,
                        '/_uuids?count=1000')
        };
    } else if (location.port === "5984") {
     // This is CouchDB's default debugging port, and the convention then
     // is to disable rewrite rules when using that port. In that case, I
     // have avoided hard-coding assumptions about the deployment target
     // by instead opting to navigate paths relative to the current URL.
        bookmarks = {
            app:    location.href.replace(location.pathname, '/') +
                        location.pathname.match(/([\w]+\/){3}/)[0],
            db:     location.href.replace(location.pathname, '/') +
                        location.pathname.match(/([\w]+\/){1}/)[0],
            uuids:  location.href.replace(location.pathname,
                        '/_uuids?count=1000')
        };
    } else {
     // Because this is still experimental, we may find problems.
        throw new Error("Relative path detection fell through.");
    }

    celebrate = function (message) {
        this.trigger = new ExitSuccess(message);
    };

    define = function (obj, key, params) {
        if (typeof Object.defineProperty === 'function') {
            define = function (obj, key, params) {
                return Object.defineProperty(obj, key, params);
            };
        } else {
            define = function (obj, key, params) {
                var prop;
                for (prop in params) {
                    if (params.hasOwnProperty(prop) === true) {
                        switch (prop) {
                        case "get":
                            obj.__defineGetter__(key, params[prop]);
                            break;
                        case "set":
                            obj.__defineSetter__(key, params[prop]);
                            break;
                        case "value":
                            delete obj[key];
                            obj[key] = params[prop];
                            break;
                        default:
                         // (placeholder)
                        }
                    }
                }
                return obj;
            };
        }
        return define(obj, key, params);
    };

    die = function (message) {
        this.trigger = new ExitFailure(message);
    };

    filter = function (x, f) {
     // NOTE: This is only one possible interpretation of a generalized filter
     // pattern, and I wrote it sort of off-the-cuff. It may change!
        var y;
        if ((x instanceof Object) === false) {
         // For now, we simply won't allow it ...
            throw new Error('Cannot "filter" a primitive.');
        } else {
            y = Object.create(Object.getPrototypeOf(x));
            ply(x, function (key, val) {
                if (f(val) === true) {
                    y[key] = val;
                }
            });
        }
        return y;
    };

    map = function (x, f) {
        var y;
        if ((x instanceof Object) === false) {
            //y = f(x);
            throw new Error('Cannot "map" a primitive.');
        } else {
            y = Object.create(Object.getPrototypeOf(x));
            ply(x, function (key, val) {
                y[key] = f(val);
            });
        }
        return y;
    };

    methodQ = function (f) {
        var x, y;
        x = (this instanceof QuanahVar) ? this : new QuanahVar(this);
        y = new QuanahVar(null);
        switch (f.name) {
        case "filter":
            y.onready = function () {
                x.onready = function (data) {
                    y.content = filter(data, f);
                    celebrate.call(x, '(finished "filter")');
                    celebrate.call(y, '(finished "filter")');
                };
            };
            return y;
        case "map":
            y.onready = function () {
                x.onready = function (data) {
                    y.content = map(data, f);
                    celebrate.call(x, '(finished "map")');
                    celebrate.call(y, '(finished "map")');
                };
            };
            return y;
        case "ply":
            x.onready = function (x) {
                ply(x, f);
                celebrate('(finished "ply")');
            };
            return x;
        case "reduce":
            y.onready = function () {
                x.onready = function (data) {
                    y.content = reduce(data, f);
                    celebrate.call(x, '(finished "reduce")');
                    celebrate.call(y, '(finished "reduce")');
                };
            };
            return y;
        default:
            x.onready = f;
            return x;
        }
    };

    ply = function (x, f) {
        var key;
        if ((x instanceof Object) === false) {
            f(undefined, x);
        } else {
            for (key in x) {
                if (x.hasOwnProperty(key)) {
                    f(key, x[key]);
                }
            }
        }
    };

    postpone = function (message) {
        this.trigger = new TryAgainLater(message);
    };

    reduce = function (x, f) {
        var first, y;
        if ((x instanceof Object) === false) {
            throw new Error('Cannot "reduce" a primitive.');
        } else {
            first = true;
            ply(x, function (key, val) {
                if (first === true) {
                    first = false;
                    y = val;            //- initialize y
                } else {
                    y = f(y, val);      //- apply a simple left-reduce pattern
                }
            });
            return y;
        }
    };

    return methodQ;

}(function (outer_scope) {
    "use strict";
    return (this === null) ? outer_scope : this;
}.call(null, this)));

//- Demonstrations -- FOR DEBUGGING PURPOSES ONLY! The biggest thing to note
//  here is that my nice messaging functions are NOT available in this scope!

(function demos() {
    "use strict";

 // Declarations

    var puts, q, x, y;

 // Definitions

    puts = function () {
        console.log.apply(console, arguments);
    };

    //(q is defined at the end of this scope for clarity)

    x = [1, 2, 3, 4, 5];

    y = [];

 // Invocations

    y[0] = x.Q(function map(each) {
        return 3 * each;
    });

    y[0].onready = function (data) {
        console.log(data);              //> [3, 6, 9, 12, 15]
    };

    y[1] = x.Q(function reduce(a, b) {
        return a + b;
    });

    y[1].onready = function (data) {
        console.log(data);              //> 15
    };

    y[2] = x.
        Q(function map(each) {
            return each + 2;
        }).
        Q(function reduce(a, b) {
            return a * b;
        });

    y[2].onready = function (data) {
        console.log(data);              //> 2520
    };

    y[3] = x.
        Q(function filter(each) {
            return (each > 2);
        }).
        Q(function map(each) {
            return 2 * each;
        }).
        Q(function reduce(a, b) {
            return a + b;
        });

    y[3].onready = function (data) {
        console.log(data);              //> 24
    };

 // That part surprised me, so I wanted to take a closer look ...

    y[4] = x.
        Q(function filter(each) {
            return (each > 2);
        }).
        Q(function ply(key, val) {
            console.log(key + ": " + val);
        });

 // Also, I wanted to see how difficult it would be to modify the current
 // design to support a different invocation pattern -- it's trivial :-)

    q = function (f) {
        return function (x) {
            return x.Q(f);
        };
    };

    y[5] = q(function map(each) { return 2 * each; })(x);

    y[5].onready = function (data) {
        console.log(data);
    };

 // Finally, we'll just go ahead and print y to see what it looks like :-)

    console.log(y);

}());

//- vim:set syntax=javascript:
<|endoftext|>


<commit_before>import { Events } from 'quasar'
import { createQuerablePromise } from '../utils'

let schemaProxyMixin = {
  props: {
    schemaName: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      schema: null
    }
  },
  methods: {
    getSchema () {
      return this.schema
    },
    getSchemaId () {
      return this.schema ? this.schema.$id : ''
    },
    getSchemaName () {
      // When used with a service by default use the same name for schema as for service
      let schemaName = this.schemaName || this.service
      schemaName += this.objectId ? '.update' : '.create'
      if (this.perspective) {
        schemaName += ('-' + this.perspective)
      }
      return schemaName
    },
    loadSchema () {
      // Create a new mixin promise if required
      // In the JSON schema file we use a $id like 'http:/www.kalisio.xyz/schemas/service.operation-perspective.json#'
      const schemaName = this.getSchemaName()
      const schemaChanged = schemaName && !this.getSchemaId().includes(schemaName + '.json')
      if (!this.schemaPromise || schemaChanged) {
        // We need to load the schema now
        this.schemaPromise = createQuerablePromise(
          this.$load(schemaName, 'schema')
          .then(schema => {
            this.schema = schema
            // We need to force a refresh so that the schema is correctly
            // transfered to child component by Vuejs
            return this.$nextTick().then(() => schema)
          })
          .catch(error => {
            Events.$emit('error', error)
            throw error
          })
        )
      }
      return this.schemaPromise
    }
  }
}

export default schemaProxyMixin
<commit_msg>feat: added support for schema as JSON in schema mixin<commit_after>import { Events } from 'quasar'
import { createQuerablePromise } from '../utils'

let schemaProxyMixin = {
  props: {
    schemaName: {
      type: String,
      default: ''
    },
    schemaJson: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      schema: null
    }
  },
  methods: {
    getSchema () {
      return this.schema
    },
    getSchemaId () {
      return this.schema ? this.schema.$id : ''
    },
    getSchemaName () {
      // When used with a service by default use the same name for schema as for service
      let schemaName = this.schemaName || this.service
      schemaName += this.objectId ? '.update' : '.create'
      if (this.perspective) {
        schemaName += ('-' + this.perspective)
      }
      return schemaName
    },
    async loadSchemaFromResource (schemaName) {
      try {
        this.schema = await this.$load(schemaName, 'schema')
        return this.schema
      } catch (error) {
        Events.$emit('error', error)
        throw error
      }
    },
    async loadSchemaFromJson (json) {
      try {
        this.schema = JSON.parse(json)
        return this.schema
      } catch (error) {
        Events.$emit('error', error)
        throw error
      }
    },
    loadSchema () {
      // Create a new mixin promise if required
      // In the JSON schema file we use a $id like 'http:/www.kalisio.xyz/schemas/service.operation-perspective.json#'
      const schemaName = this.getSchemaName()
      const schemaChanged = schemaName && !this.getSchemaId().includes(schemaName + '.json')
      if (!this.schemaPromise || schemaChanged) {
        // We need to load the schema now
        this.schemaPromise = createQuerablePromise(this.schemaJson ?
          this.loadSchemaFromJson(this.schemaJson) :
          this.loadSchemaFromResource(schemaName))
      }
      return this.schemaPromise
    }
  }
}

export default schemaProxyMixin
<|endoftext|>


<commit_before>var http = require('q-io/http');

var assessmentData = require('./assessments'),
    HttpError = require('../error/HttpError');

var routes = {};

routes.publish = function (router) {

    router.get('/assess/:assessmentId', function (request, response) {
        var assessmentId = request.params.assessmentId;
        assessmentData
            .get(assessmentId)
            .then(function (assessment) {
                delete assessment.tests;
                delete assessment.tips;
                delete assessment.guides;
                response.json(assessment);
            })
            .catch(HttpError.handle(response));
    });

    router.post('/assess/:assessmentId', function (request, response) {
        var assessmentId = request.params.assessmentId;
        assessmentData.get(assessmentId)
            .then(function (assessment) {
                var compilationUnits = request.body.compilationUnits;
                var options = {
                    //url: 'http://localhost:5020/v1/',
                    url: 'http://54.171.154.216:5020/v1/',
                    method: 'POST',
                    body: [
                        JSON.stringify({
                            assessment: assessment,
                            compilationUnits: compilationUnits
                        })
                    ]
                };
                return http.request(http.normalizeRequest(options))
                    .then(function (submissionResponse) {
                        return submissionResponse.body.read().then(function (body) {
                            response
                                .status(submissionResponse.status)
                                .json(JSON.parse(body));
                        });
                    });
            })
            .catch(function (error) {
                console.log(error);
                response.status(500).send(error.message);
            });
    });

};

module.exports = routes;<commit_msg>compilationUnit => submittedCompilationUnit<commit_after>var http = require('q-io/http');

var assessmentData = require('./assessments'),
    HttpError = require('../error/HttpError');

var routes = {};

routes.publish = function (router) {

    router.get('/assess/:assessmentId', function (request, response) {
        var assessmentId = request.params.assessmentId;
        assessmentData
            .get(assessmentId)
            .then(function (assessment) {
                delete assessment.tests;
                delete assessment.tips;
                delete assessment.guides;
                response.json(assessment);
            })
            .catch(HttpError.handle(response));
    });

    router.post('/assess/:assessmentId', function (request, response) {
        var assessmentId = request.params.assessmentId;
        assessmentData.get(assessmentId)
            .then(function (assessment) {
                var submittedCompilationUnits = request.body.submittedCompilationUnits;
                var options = {
                    //url: 'http://localhost:5020/v1/',
                    url: 'http://54.171.154.216:5020/v1/',
                    method: 'POST',
                    body: [
                        JSON.stringify({
                            assessment: assessment,
                            submittedCompilationUnits: submittedCompilationUnits
                        })
                    ]
                };
                return http.request(http.normalizeRequest(options))
                    .then(function (submissionResponse) {
                        return submissionResponse.body.read().then(function (body) {
                            response
                                .status(submissionResponse.status)
                                .json(JSON.parse(body));
                        });
                    });
            })
            .catch(function (error) {
                console.log(error);
                response.status(500).send(error.message);
            });
    });

};

module.exports = routes;<|endoftext|>


<commit_before>import { useEffect, useCallback, useState, useRef } from 'react';
import { useApi, useCache, usePromiseCache } from 'react-components';

const PENDING = 1;
const RESOLVED = 2;
const REJECTED = 3;

const getStateToSync = (dataValue, promiseValue) => {
    const willInitialLoad = !dataValue && !promiseValue;

    const { value, status } = promiseValue || {};

    return [dataValue, status === PENDING || willInitialLoad, status === REJECTED ? value : undefined];
};

const mergeCache = (cache, value) => {
    cache.set({
        ...cache.get(),
        ...value
    });
};

/**
 * Creates an async fn model hook.
 * @return {function} the created hook
 */
const createUseModelHook = ({ key, get }) => {
    return () => {
        const promiseCache = usePromiseCache();
        const dataCache = useCache();
        const api = useApi();
        const dataValueRef = useRef();
        const promiseValueRef = useRef();

        const [state, setState] = useState(() => {
            const dataCacheState = dataCache.get();
            const promiseCacheState = promiseCache.get();

            const dataValue = dataCacheState[key];
            const promiseValue = promiseCacheState[key];

            return getStateToSync(dataValue, promiseValue);
        });

        const load = useCallback(async () => {
            const { status, value } = promiseCache.get()[key] || {};

            if (status === PENDING) {
                return value;
            }

            const promise = get(api);

            const getPromiseValue = (status, value) => {
                return {
                    [key]: {
                        status,
                        value
                    }
                };
            };

            mergeCache(promiseCache, getPromiseValue(PENDING, promise));

            promise
                .then((data) => {
                    mergeCache(promiseCache, getPromiseValue(RESOLVED, data));
                    mergeCache(dataCache, { [key]: data });
                })
                .catch((e) => {
                    mergeCache(promiseCache, getPromiseValue(REJECTED, e));
                });
        }, []);

        useEffect(() => {
            const cacheListener = () => {
                const dataValue = dataCache.get()[key];
                const promiseValue = promiseCache.get()[key];

                if (dataValueRef.current === dataValue && promiseValueRef.current === promiseValue) {
                    return;
                }

                setState(getStateToSync(dataValue, promiseValue));

                dataValueRef.current = dataValue;
                promiseValueRef.current = promiseValue;
            };

            const unsubscribeCache = dataCache.subscribe(cacheListener);
            const unsubscribePromiseCache = promiseCache.subscribe(cacheListener);

            const initialLoad = () => {
                const dataValue = dataCache.get()[key];
                const promiseValue = promiseCache.get()[key];

                dataValueRef.current = dataValue;
                promiseValueRef.current = promiseValue;

                // If data is not present in cache and not being fetched, load it
                if (!dataValue && !promiseValue) {
                    load();
                }
            };

            initialLoad();

            return () => {
                unsubscribeCache();
                unsubscribePromiseCache();
            };
        }, []);

        return [...state, load];
    };
};

export default createUseModelHook;
<commit_msg>Resolve data cache first<commit_after>import { useEffect, useCallback, useState, useRef } from 'react';
import { useApi, useCache, usePromiseCache } from 'react-components';

const PENDING = 1;
const RESOLVED = 2;
const REJECTED = 3;

const getStateToSync = (dataValue, promiseValue) => {
    const willInitialLoad = !dataValue && !promiseValue;

    const { value, status } = promiseValue || {};

    return [dataValue, status === PENDING || willInitialLoad, status === REJECTED ? value : undefined];
};

const mergeCache = (cache, value) => {
    cache.set({
        ...cache.get(),
        ...value
    });
};

/**
 * Creates an async fn model hook.
 * @return {function} the created hook
 */
const createUseModelHook = ({ key, get }) => {
    return () => {
        const promiseCache = usePromiseCache();
        const dataCache = useCache();
        const api = useApi();
        const dataValueRef = useRef();
        const promiseValueRef = useRef();

        const [state, setState] = useState(() => {
            const dataCacheState = dataCache.get();
            const promiseCacheState = promiseCache.get();

            const dataValue = dataCacheState[key];
            const promiseValue = promiseCacheState[key];

            return getStateToSync(dataValue, promiseValue);
        });

        const load = useCallback(async () => {
            const { status, value } = promiseCache.get()[key] || {};

            if (status === PENDING) {
                return value;
            }

            const promise = get(api);

            const getPromiseValue = (status, value) => {
                return {
                    [key]: {
                        status,
                        value
                    }
                };
            };

            mergeCache(promiseCache, getPromiseValue(PENDING, promise));

            promise
                .then((data) => {
                    mergeCache(dataCache, { [key]: data });
                    mergeCache(promiseCache, getPromiseValue(RESOLVED, data));
                })
                .catch((e) => {
                    mergeCache(promiseCache, getPromiseValue(REJECTED, e));
                });
        }, []);

        useEffect(() => {
            const cacheListener = () => {
                const dataValue = dataCache.get()[key];
                const promiseValue = promiseCache.get()[key];

                if (dataValueRef.current === dataValue && promiseValueRef.current === promiseValue) {
                    return;
                }

                setState(getStateToSync(dataValue, promiseValue));

                dataValueRef.current = dataValue;
                promiseValueRef.current = promiseValue;
            };

            const unsubscribeCache = dataCache.subscribe(cacheListener);
            const unsubscribePromiseCache = promiseCache.subscribe(cacheListener);

            const initialLoad = () => {
                const dataValue = dataCache.get()[key];
                const promiseValue = promiseCache.get()[key];

                dataValueRef.current = dataValue;
                promiseValueRef.current = promiseValue;

                // If data is not present in cache and not being fetched, load it
                if (!dataValue && !promiseValue) {
                    load();
                }
            };

            initialLoad();

            return () => {
                unsubscribeCache();
                unsubscribePromiseCache();
            };
        }, []);

        return [...state, load];
    };
};

export default createUseModelHook;
<|endoftext|>


<commit_before>const JSONRPC = require('./jsonrpc');
// const log = require('../util/log');

class JSONRPCWebSocket extends JSONRPC {
    constructor (webSocket) {
        super();

        this._ws = webSocket;
        this._ws.onmessage = e => this._onSocketMessage(e);
        this._ws.onopen = e => this._onSocketOpen(e);
        this._ws.onclose = e => this._onSocketClose(e);
        this._ws.onerror = e => this._onSocketError(e);
    }

    dispose () {
        this._ws.close();
        this._ws = null;
    }

    _onSocketOpen () {
    }

    _onSocketClose () {
    }

    _onSocketError () {
    }

    _onSocketMessage (e) {
        const json = JSON.parse(e.data);
        if (json.method !== 'characteristicDidChange') {
            // log.info(`received message: ${json}`);
        }
        this._handleMessage(json);
    }

    _sendMessage (message) {
        const messageText = JSON.stringify(message);
        this._ws.send(messageText);
    }
}

module.exports = JSONRPCWebSocket;
<commit_msg>remove logging<commit_after>const JSONRPC = require('./jsonrpc');
// const log = require('../util/log');

class JSONRPCWebSocket extends JSONRPC {
    constructor (webSocket) {
        super();

        this._ws = webSocket;
        this._ws.onmessage = e => this._onSocketMessage(e);
        this._ws.onopen = e => this._onSocketOpen(e);
        this._ws.onclose = e => this._onSocketClose(e);
        this._ws.onerror = e => this._onSocketError(e);
    }

    dispose () {
        this._ws.close();
        this._ws = null;
    }

    _onSocketOpen () {
    }

    _onSocketClose () {
    }

    _onSocketError () {
    }

    _onSocketMessage (e) {
        const json = JSON.parse(e.data);
        this._handleMessage(json);
    }

    _sendMessage (message) {
        const messageText = JSON.stringify(message);
        this._ws.send(messageText);
    }
}

module.exports = JSONRPCWebSocket;
<|endoftext|>


<commit_before>// Adapted from https://gist.github.com/paulirish/1579671 which derived from
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller.
// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon

// MIT license

if (!Date.now){
    Date.now = function() { return new Date().getTime(); };
}

(function() {
    var vendors = ['webkit', 'moz'];
    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
        var vp = vendors[i];
        window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
        window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame']
                                   || window[vp+'CancelRequestAnimationFrame']);
    }
    if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
        || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
        var lastTime = 0;
        window.requestAnimationFrame = function(callback) {
            var now = Date.now();
            var nextTime = Math.max(lastTime + 16, now);
            return setTimeout(function() { callback(lastTime = nextTime); },
                              nextTime - now);
        };
        window.cancelAnimationFrame = clearTimeout;
    }
}());
<commit_msg>jshint fix<commit_after>// Adapted from https://gist.github.com/paulirish/1579671 which derived from
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller.
// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon

// MIT license

if (!Date.now){
    Date.now = function() { return new Date().getTime(); };
}

(function() {
    var vendors = ['webkit', 'moz'];
    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
        var vp = vendors[i];
        window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
        window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame'] || window[vp+'CancelRequestAnimationFrame']);
    }
    if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || // iOS6 is buggy
            !window.requestAnimationFrame ||
            !window.cancelAnimationFrame
        ) {
        var lastTime = 0;
        window.requestAnimationFrame = function(callback) {
            var now = Date.now();
            var nextTime = Math.max(lastTime + 16, now);
            return setTimeout(function() { callback(lastTime = nextTime); },
                              nextTime - now);
        };
        window.cancelAnimationFrame = clearTimeout;
    }
}());
<|endoftext|>


<commit_before>// @flow

/**
 * Source Map Worker
 * @module utils/source-map-worker
 */

const networkRequest = require("devtools-network-request");
const { parse } = require("url");
const path = require("./path");
const { SourceMapConsumer, SourceMapGenerator } = require("source-map");
const { isJavaScript } = require("./source");
const assert = require("./assert");
const {
  originalToGeneratedId,
  generatedToOriginalId,
  isGeneratedId,
  isOriginalId
} = require("./source-map-util");

import type { Location, Source } from "../types";
type Message = {
  data: {
    id: string,
    method: string,
    args: Array<any>
  }
}

let sourceMapRequests = new Map();
let sourceMapsEnabled = false;

function clearSourceMaps() {
  sourceMapRequests.clear();
}

function enableSourceMaps() {
  sourceMapsEnabled = true;
}

function _resolveSourceMapURL(source: Source) {
  const { url = "", sourceMapURL = "" } = source;
  if (path.isURL(sourceMapURL) || url == "") {
    // If it's already a full URL or the source doesn't have a URL,
    // don't resolve anything.
    return sourceMapURL;
  } else if (path.isAbsolute(sourceMapURL)) {
    // If it's an absolute path, it should be resolved relative to the
    // host of the source.
    const { protocol = "", host = "" } = parse(url);
    return `${protocol}//${host}${sourceMapURL}`;
  }
  // Otherwise, it's a relative path and should be resolved relative
  // to the source.
  return `${path.dirname(url)}/${sourceMapURL}`;
}

/**
 * Sets the source map's sourceRoot to be relative to the source map url.
 * @memberof utils/source-map-worker
 * @static
 */
function _setSourceMapRoot(sourceMap, absSourceMapURL, source) {
  // No need to do this fiddling if we won't be fetching any sources over the
  // wire.
  if (sourceMap.hasContentsOfAllSources()) {
    return;
  }

  const base = path.dirname(
    (absSourceMapURL.indexOf("data:") === 0 && source.url) ?
      source.url :
      absSourceMapURL
  );

  if (sourceMap.sourceRoot) {
    sourceMap.sourceRoot = path.join(base, sourceMap.sourceRoot);
  } else {
    sourceMap.sourceRoot = base;
  }

  return sourceMap;
}

function _getSourceMap(generatedSourceId: string)
    : ?Promise<SourceMapConsumer> {
  return sourceMapRequests.get(generatedSourceId);
}

async function _resolveAndFetch(generatedSource: Source) : SourceMapConsumer {
  // Fetch the sourcemap over the network and create it.
  const sourceMapURL = _resolveSourceMapURL(generatedSource);
  const fetched = await networkRequest(
    sourceMapURL, { loadFromCache: false }
  );

  // Create the source map and fix it up.
  const map = new SourceMapConsumer(fetched.content);
  _setSourceMapRoot(map, sourceMapURL, generatedSource);
  return map;
}

function _fetchSourceMap(generatedSource: Source) {
  const existingRequest = sourceMapRequests.get(generatedSource.id);
  if (existingRequest) {
    // If it has already been requested, return the request. Make sure
    // to do this even if sourcemapping is turned off, because
    // pretty-printing uses sourcemaps.
    //
    // An important behavior here is that if it's in the middle of
    // requesting it, all subsequent calls will block on the initial
    // request.
    return existingRequest;
  } else if (!generatedSource.sourceMapURL || !sourceMapsEnabled) {
    return Promise.resolve(null);
  }

  // Fire off the request, set it in the cache, and return it.
  // Suppress any errors and just return null (ignores bogus
  // sourcemaps).
  const req = _resolveAndFetch(generatedSource).catch(() => null);
  sourceMapRequests.set(generatedSource.id, req);
  return req;
}

async function getOriginalURLs(generatedSource) {
  const map = await _fetchSourceMap(generatedSource);
  return map && map.sources;
}

async function getGeneratedLocation(location: Location, originalSource: Source)
    : Promise<Location> {
  if (!isOriginalId(location.sourceId)) {
    return location;
  }

  const generatedSourceId = originalToGeneratedId(location.sourceId);
  const map = await _getSourceMap(generatedSourceId);
  if (!map) {
    return location;
  }

  const { line, column } = map.generatedPositionFor({
    source: originalSource.url,
    line: location.line,
    column: location.column == null ? 0 : location.column
  });

  return {
    sourceId: generatedSourceId,
    line: line,
    // Treat 0 as no column so that line breakpoints work correctly.
    column: column === 0 ? undefined : column
  };
}

async function getOriginalLocation(location: Location) {
  if (!isGeneratedId(location.sourceId)) {
    return location;
  }

  const map = await _getSourceMap(location.sourceId);
  if (!map) {
    return location;
  }

  const { source: url, line, column } = map.originalPositionFor({
    line: location.line,
    column: location.column == null ? Infinity : location.column
  });

  if (url == null) {
    // No url means the location didn't map.
    return location;
  }

  return {
    sourceId: generatedToOriginalId(location.sourceId, url),
    line,
    column
  };
}

async function getOriginalSourceText(originalSource: Source) {
  assert(isOriginalId(originalSource.id),
         "Source is not an original source");

  const generatedSourceId = originalToGeneratedId(originalSource.id);
  const map = await _getSourceMap(generatedSourceId);
  if (!map) {
    return null;
  }

  let text = map.sourceContentFor(originalSource.url);
  if (!text) {
    text = (await networkRequest(
      originalSource.url, { loadFromCache: false }
    )).content;
  }

  return {
    text,
    contentType: isJavaScript(originalSource.url || "") ?
      "text/javascript" :
      "text/plain"
  };
}

function applySourceMap(generatedId, url, code, mappings) {
  const generator = new SourceMapGenerator({ file: url });
  mappings.forEach(mapping => generator.addMapping(mapping));
  generator.setSourceContent(url, code);

  const map = SourceMapConsumer(generator.toJSON());
  sourceMapRequests.set(generatedId, Promise.resolve(map));
}

const publicInterface = {
  getOriginalURLs,
  getGeneratedLocation,
  getOriginalLocation,
  getOriginalSourceText,
  enableSourceMaps,
  applySourceMap,
  clearSourceMaps
};

self.onmessage = function(msg: Message) {
  const { id, method, args } = msg.data;
  const response = publicInterface[method].apply(undefined, args);
  if (response instanceof Promise) {
    response.then(val => self.postMessage({ id, response: val }),
                  err => self.postMessage({ id, error: err }));
  } else {
    self.postMessage({ id, response });
  }
};
<commit_msg>Make sourcemapped location resolve forward instead of back (fixes #1252) (#1349)<commit_after>// @flow

/**
 * Source Map Worker
 * @module utils/source-map-worker
 */

const networkRequest = require("devtools-network-request");
const { parse } = require("url");
const path = require("./path");
const { SourceMapConsumer, SourceMapGenerator } = require("source-map");
const { isJavaScript } = require("./source");
const assert = require("./assert");
const {
  originalToGeneratedId,
  generatedToOriginalId,
  isGeneratedId,
  isOriginalId
} = require("./source-map-util");

import type { Location, Source } from "../types";
type Message = {
  data: {
    id: string,
    method: string,
    args: Array<any>
  }
}

let sourceMapRequests = new Map();
let sourceMapsEnabled = false;

function clearSourceMaps() {
  sourceMapRequests.clear();
}

function enableSourceMaps() {
  sourceMapsEnabled = true;
}

function _resolveSourceMapURL(source: Source) {
  const { url = "", sourceMapURL = "" } = source;
  if (path.isURL(sourceMapURL) || url == "") {
    // If it's already a full URL or the source doesn't have a URL,
    // don't resolve anything.
    return sourceMapURL;
  } else if (path.isAbsolute(sourceMapURL)) {
    // If it's an absolute path, it should be resolved relative to the
    // host of the source.
    const { protocol = "", host = "" } = parse(url);
    return `${protocol}//${host}${sourceMapURL}`;
  }
  // Otherwise, it's a relative path and should be resolved relative
  // to the source.
  return `${path.dirname(url)}/${sourceMapURL}`;
}

/**
 * Sets the source map's sourceRoot to be relative to the source map url.
 * @memberof utils/source-map-worker
 * @static
 */
function _setSourceMapRoot(sourceMap, absSourceMapURL, source) {
  // No need to do this fiddling if we won't be fetching any sources over the
  // wire.
  if (sourceMap.hasContentsOfAllSources()) {
    return;
  }

  const base = path.dirname(
    (absSourceMapURL.indexOf("data:") === 0 && source.url) ?
      source.url :
      absSourceMapURL
  );

  if (sourceMap.sourceRoot) {
    sourceMap.sourceRoot = path.join(base, sourceMap.sourceRoot);
  } else {
    sourceMap.sourceRoot = base;
  }

  return sourceMap;
}

function _getSourceMap(generatedSourceId: string)
    : ?Promise<SourceMapConsumer> {
  return sourceMapRequests.get(generatedSourceId);
}

async function _resolveAndFetch(generatedSource: Source) : SourceMapConsumer {
  // Fetch the sourcemap over the network and create it.
  const sourceMapURL = _resolveSourceMapURL(generatedSource);
  const fetched = await networkRequest(
    sourceMapURL, { loadFromCache: false }
  );

  // Create the source map and fix it up.
  const map = new SourceMapConsumer(fetched.content);
  _setSourceMapRoot(map, sourceMapURL, generatedSource);
  return map;
}

function _fetchSourceMap(generatedSource: Source) {
  const existingRequest = sourceMapRequests.get(generatedSource.id);
  if (existingRequest) {
    // If it has already been requested, return the request. Make sure
    // to do this even if sourcemapping is turned off, because
    // pretty-printing uses sourcemaps.
    //
    // An important behavior here is that if it's in the middle of
    // requesting it, all subsequent calls will block on the initial
    // request.
    return existingRequest;
  } else if (!generatedSource.sourceMapURL || !sourceMapsEnabled) {
    return Promise.resolve(null);
  }

  // Fire off the request, set it in the cache, and return it.
  // Suppress any errors and just return null (ignores bogus
  // sourcemaps).
  const req = _resolveAndFetch(generatedSource).catch(() => null);
  sourceMapRequests.set(generatedSource.id, req);
  return req;
}

async function getOriginalURLs(generatedSource) {
  const map = await _fetchSourceMap(generatedSource);
  return map && map.sources;
}

async function getGeneratedLocation(location: Location, originalSource: Source)
    : Promise<Location> {
  if (!isOriginalId(location.sourceId)) {
    return location;
  }

  const generatedSourceId = originalToGeneratedId(location.sourceId);
  const map = await _getSourceMap(generatedSourceId);
  if (!map) {
    return location;
  }

  const { line, column } = map.generatedPositionFor({
    source: originalSource.url,
    line: location.line,
    column: location.column == null ? 0 : location.column,
    bias: SourceMapConsumer.LEAST_UPPER_BOUND
  });

  return {
    sourceId: generatedSourceId,
    line: line,
    // Treat 0 as no column so that line breakpoints work correctly.
    column: column === 0 ? undefined : column
  };
}

async function getOriginalLocation(location: Location) {
  if (!isGeneratedId(location.sourceId)) {
    return location;
  }

  const map = await _getSourceMap(location.sourceId);
  if (!map) {
    return location;
  }

  const { source: url, line, column } = map.originalPositionFor({
    line: location.line,
    column: location.column == null ? Infinity : location.column
  });

  if (url == null) {
    // No url means the location didn't map.
    return location;
  }

  return {
    sourceId: generatedToOriginalId(location.sourceId, url),
    line,
    column
  };
}

async function getOriginalSourceText(originalSource: Source) {
  assert(isOriginalId(originalSource.id),
         "Source is not an original source");

  const generatedSourceId = originalToGeneratedId(originalSource.id);
  const map = await _getSourceMap(generatedSourceId);
  if (!map) {
    return null;
  }

  let text = map.sourceContentFor(originalSource.url);
  if (!text) {
    text = (await networkRequest(
      originalSource.url, { loadFromCache: false }
    )).content;
  }

  return {
    text,
    contentType: isJavaScript(originalSource.url || "") ?
      "text/javascript" :
      "text/plain"
  };
}

function applySourceMap(generatedId, url, code, mappings) {
  const generator = new SourceMapGenerator({ file: url });
  mappings.forEach(mapping => generator.addMapping(mapping));
  generator.setSourceContent(url, code);

  const map = SourceMapConsumer(generator.toJSON());
  sourceMapRequests.set(generatedId, Promise.resolve(map));
}

const publicInterface = {
  getOriginalURLs,
  getGeneratedLocation,
  getOriginalLocation,
  getOriginalSourceText,
  enableSourceMaps,
  applySourceMap,
  clearSourceMaps
};

self.onmessage = function(msg: Message) {
  const { id, method, args } = msg.data;
  const response = publicInterface[method].apply(undefined, args);
  if (response instanceof Promise) {
    response.then(val => self.postMessage({ id, response: val }),
                  err => self.postMessage({ id, error: err }));
  } else {
    self.postMessage({ id, response });
  }
};
<|endoftext|>


<commit_before>var
	kind = require('enyo/kind');

var
	Button = require('enyo/Button'),
	Checkbox = require('enyo/Checkbox'),
	Control = require('enyo/Control'),
	LightPanels = require('enyo/LightPanels');

module.exports = kind({
	name: 'enyo.sample.LightPanelsSample',
	classes: 'light-panels-sample enyo-unselectable',
	kind: Control,
	components: [
		{classes: 'light-panels-options', components: [
			{classes: 'horizontal-options', components: [
				{kind: Checkbox, name: 'cachingHorizontal', content: 'Caching', onchange: ''},
				{kind: Checkbox, name: 'multipleHorizontal', content: 'Multiple', onchange: ''}
			]},
			{classes: 'vertical-options', components: [
				{kind: Checkbox, name: 'cachingVertical', content: 'Caching', onchange: ''},
				{kind: Checkbox, name: 'multipleVertical', content: 'Multiple', onchange: ''}
			]}
		]},
		{classes: 'light-panels-set', components: [
			{kind: LightPanels, name: 'lightHorizontal'},
			{kind: LightPanels, name: 'lightVertical', orientation: 'vertical'}
		]}
	],
	bindings: [
		{from: '$.cachingHorizontal.checked', to: '$.lightHorizontal.cacheViews'},
		{from: '$.multipleHorizontal.checked', to: 'multipleHorizontal'},
		{from: '$.cachingVertical.checked', to: '$.lightVertical.cacheViews'},
		{from: '$.multipleVertical.checked', to: 'multipleVertical'}
	],
	rendered: kind.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			this.pushSinglePanel(this.$.lightHorizontal);
			this.pushSinglePanel(this.$.lightVertical);
		};
	}),
	pushSinglePanel: function (panels) {
		panels.pushPanel({
			classes: 'light-panel',
			panelId: 'panel-' + panels.getPanels().length,
			style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
			components: [
				{content: panels.getPanels().length, classes: 'label'},
				{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
				{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
			]
		}, {owner: this});
	},
	pushMultiplePanels: function (panels) {
		panels.pushPanels([
			{
				classes: 'light-panel',
				panelId: 'panel-' + panels.getPanels().length,
				style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
				components: [
					{content: panels.getPanels().length, classes: 'label'},
					{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
					{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
				]
			},
			{
				classes: 'light-panel',
				panelId: 'panel-' + (panels.getPanels().length + 1),
				style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
				components: [
					{content: panels.getPanels().length + 1, classes: 'label'},
					{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
					{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
				]
			},
			{
				classes: 'light-panel',
				panelId: 'panel-' + (panels.getPanels().length + 2),
				style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
				components: [
					{content: panels.getPanels().length + 2, classes: 'label'},
					{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
					{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
				]
			}
		], {owner: this});
	},
	prevTapped: function (sender, ev) {
		var panels = ev.originator.parent.parent;
		panels.previous();
		return true;
	},
	nextTapped: function (sender, ev) {
		var panels = ev.originator.parent.parent;
		if ((panels.name == 'lightHorizontal' && this.multipleHorizontal) || (panels.name == 'lightVertical' && this.multipleVertical)) {
			this.pushMultiplePanels(panels);
		} else {
			this.pushSinglePanel(panels);
		}
		return true;
	},
	bgcolors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
});
<commit_msg>ENYO-1981: Update sample to utilize enumeration.<commit_after>var
	kind = require('enyo/kind');

var
	Button = require('enyo/Button'),
	Checkbox = require('enyo/Checkbox'),
	Control = require('enyo/Control'),
	LightPanels = require('enyo/LightPanels'),
	Orientation = LightPanels.Orientation;

module.exports = kind({
	name: 'enyo.sample.LightPanelsSample',
	classes: 'light-panels-sample enyo-unselectable',
	kind: Control,
	components: [
		{classes: 'light-panels-options', components: [
			{classes: 'horizontal-options', components: [
				{kind: Checkbox, name: 'cachingHorizontal', content: 'Caching', onchange: ''},
				{kind: Checkbox, name: 'multipleHorizontal', content: 'Multiple', onchange: ''}
			]},
			{classes: 'vertical-options', components: [
				{kind: Checkbox, name: 'cachingVertical', content: 'Caching', onchange: ''},
				{kind: Checkbox, name: 'multipleVertical', content: 'Multiple', onchange: ''}
			]}
		]},
		{classes: 'light-panels-set', components: [
			{kind: LightPanels, name: 'lightHorizontal'},
			{kind: LightPanels, name: 'lightVertical', orientation: Orientation.VERTICAL}
		]}
	],
	bindings: [
		{from: '$.cachingHorizontal.checked', to: '$.lightHorizontal.cacheViews'},
		{from: '$.multipleHorizontal.checked', to: 'multipleHorizontal'},
		{from: '$.cachingVertical.checked', to: '$.lightVertical.cacheViews'},
		{from: '$.multipleVertical.checked', to: 'multipleVertical'}
	],
	rendered: kind.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			this.pushSinglePanel(this.$.lightHorizontal);
			this.pushSinglePanel(this.$.lightVertical);
		};
	}),
	pushSinglePanel: function (panels) {
		panels.pushPanel({
			classes: 'light-panel',
			panelId: 'panel-' + panels.getPanels().length,
			style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
			components: [
				{content: panels.getPanels().length, classes: 'label'},
				{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
				{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
			]
		}, {owner: this});
	},
	pushMultiplePanels: function (panels) {
		panels.pushPanels([
			{
				classes: 'light-panel',
				panelId: 'panel-' + panels.getPanels().length,
				style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
				components: [
					{content: panels.getPanels().length, classes: 'label'},
					{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
					{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
				]
			},
			{
				classes: 'light-panel',
				panelId: 'panel-' + (panels.getPanels().length + 1),
				style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
				components: [
					{content: panels.getPanels().length + 1, classes: 'label'},
					{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
					{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
				]
			},
			{
				classes: 'light-panel',
				panelId: 'panel-' + (panels.getPanels().length + 2),
				style: 'background-color: ' + this.bgcolors[Math.floor(Math.random() * this.bgcolors.length)],
				components: [
					{content: panels.getPanels().length + 2, classes: 'label'},
					{content: 'Prev', kind: Button, classes: 'previous', ontap: 'prevTapped'},
					{content: 'Next', kind: Button, classes: 'next', ontap: 'nextTapped'}
				]
			}
		], {owner: this});
	},
	prevTapped: function (sender, ev) {
		var panels = ev.originator.parent.parent;
		panels.previous();
		return true;
	},
	nextTapped: function (sender, ev) {
		var panels = ev.originator.parent.parent;
		if ((panels.name == 'lightHorizontal' && this.multipleHorizontal) || (panels.name == 'lightVertical' && this.multipleVertical)) {
			this.pushMultiplePanels(panels);
		} else {
			this.pushSinglePanel(panels);
		}
		return true;
	},
	bgcolors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
});
<|endoftext|>


<commit_before>/* ------------------------------------------------------------------------- *
 * Copyright 2002-2021, OpenNebula Project, OpenNebula Systems               *
 *                                                                           *
 * 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.                                            *
 * ------------------------------------------------------------------------- */
import { memo, useMemo, useCallback, ReactElement } from 'react'
import PropTypes from 'prop-types'
import { useHistory, generatePath } from 'react-router-dom'

import {
  AppleImac2021 as VncIcon,
  TerminalOutline as SshIcon,
  Windows as RdpIcon,
} from 'iconoir-react'
import { SubmitButton } from 'client/components/FormControl'

import { useViews } from 'client/features/Auth'
import { useLazyGetGuacamoleSessionQuery } from 'client/features/OneApi/vm'
import { useLazyGetVMRCSessionQuery } from 'client/features/OneApi/vcenter'
import {
  isVCenter,
  getHypervisor,
  nicsIncludesTheConnectionType,
  isAvailableAction,
} from 'client/models/VirtualMachine'
import { Translate } from 'client/components/HOC'
import { T, VM, RESOURCE_NAMES, VM_ACTIONS } from 'client/constants'
import { PATH } from 'client/apps/sunstone/routes'

const GUACAMOLE_BUTTONS = {
  [VM_ACTIONS.VNC]: { tooltip: T.Vnc, icon: <VncIcon /> },
  [VM_ACTIONS.SSH]: { tooltip: T.Ssh, icon: <SshIcon /> },
  [VM_ACTIONS.RDP]: { tooltip: T.Rdp, icon: <RdpIcon /> },
}

const GuacamoleButton = memo(({ vm, connectionType, onClick }) => {
  const { icon, tooltip } = GUACAMOLE_BUTTONS[connectionType]
  const history = useHistory()
  const [getSession, { isLoading }] = useLazyGetGuacamoleSessionQuery()

  const goToConsole = useCallback(
    async (evt) => {
      try {
        evt.stopPropagation()

        const params = { id: vm?.ID, type: connectionType }
        const session = await getSession(params).unwrap()

        typeof onClick === 'function'
          ? onClick(session)
          : history.push(generatePath(PATH.GUACAMOLE, params))
      } catch {}
    },
    [vm?.ID, connectionType, history, onClick]
  )

  return (
    <SubmitButton
      data-cy={`${vm?.ID}-${connectionType}`}
      icon={icon}
      tooltip={<Translate word={tooltip} />}
      isSubmitting={isLoading}
      onClick={goToConsole}
    />
  )
})

const VMRCButton = memo(({ vm, onClick }) => {
  const history = useHistory()
  const [getSession, { isLoading }] = useLazyGetVMRCSessionQuery()

  const goToConsole = useCallback(
    async (evt) => {
      try {
        evt.stopPropagation()

        const params = { id: vm?.ID }
        const session = await getSession(params).unwrap()

        typeof onClick === 'function'
          ? onClick(session)
          : history.push(generatePath(PATH.WMKS, params))
      } catch {}
    },
    [vm?.ID, history, onClick]
  )

  return (
    <SubmitButton
      data-cy={`${vm?.ID}-vmrc`}
      icon={<VncIcon />}
      tooltip={<Translate word={T.Vmrc} />}
      isSubmitting={isLoading}
      onClick={goToConsole}
    />
  )
})

const PreConsoleButton = memo(
  /**
   * @param {object} props - Props
   * @param {VM} props.vm - Virtual machine
   * @param {'vnc'|'ssh'|'rdp'|'vmrc'} props.connectionType - Connection type
   * @param {Function} [props.onClick] - Handle click for button
   * @returns {ReactElement} - Returns button if current user has permissions about the connection type
   */
  (props) => {
    const { vm, connectionType } = props
    const { view, [RESOURCE_NAMES.VM]: vmView } = useViews()

    const isDisabled = useMemo(() => {
      const noAction = vmView?.actions?.[connectionType] !== true
      const noAvailable = isAvailableAction(connectionType)(vm)
      const notHypervisor = !getHypervisor(vm)

      return noAction || noAvailable || notHypervisor
    }, [view, vm])

    const needNicConfig = useMemo(
      () => ![VM_ACTIONS.VNC, VM_ACTIONS.VMRC].includes(connectionType),
      [connectionType]
    )

    if (
      isDisabled ||
      (needNicConfig && !nicsIncludesTheConnectionType(vm, connectionType))
    ) {
      return null
    }

    if (isVCenter(vm)) {
      return connectionType === VM_ACTIONS.VMRC ? (
        <VMRCButton {...props} />
      ) : null
    }

    return <GuacamoleButton {...props} />
  }
)

const ButtonPropTypes = {
  vm: PropTypes.object,
  connectionType: PropTypes.string,
  onClick: PropTypes.func,
}

GuacamoleButton.propTypes = ButtonPropTypes
VMRCButton.propTypes = ButtonPropTypes
PreConsoleButton.propTypes = ButtonPropTypes

GuacamoleButton.displayName = 'GuacamoleButton'
VMRCButton.displayName = 'VMRCButton'
PreConsoleButton.displayName = 'PreConsoleButton'

export { PreConsoleButton as GuacamoleButton }
<commit_msg>M #~: Minor fix on remote buttons (#1888)<commit_after>/* ------------------------------------------------------------------------- *
 * Copyright 2002-2021, OpenNebula Project, OpenNebula Systems               *
 *                                                                           *
 * 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.                                            *
 * ------------------------------------------------------------------------- */
import { memo, useMemo, useCallback, ReactElement } from 'react'
import PropTypes from 'prop-types'
import { useHistory, generatePath } from 'react-router-dom'

import {
  AppleImac2021 as VncIcon,
  TerminalOutline as SshIcon,
  Windows as RdpIcon,
} from 'iconoir-react'
import { SubmitButton } from 'client/components/FormControl'

import { useViews } from 'client/features/Auth'
import { useLazyGetGuacamoleSessionQuery } from 'client/features/OneApi/vm'
import { useLazyGetVMRCSessionQuery } from 'client/features/OneApi/vcenter'
import {
  isVCenter,
  getHypervisor,
  nicsIncludesTheConnectionType,
  isAvailableAction,
} from 'client/models/VirtualMachine'
import { Translate } from 'client/components/HOC'
import { T, VM, RESOURCE_NAMES, VM_ACTIONS } from 'client/constants'
import { PATH } from 'client/apps/sunstone/routes'

const GUACAMOLE_BUTTONS = {
  [VM_ACTIONS.VNC]: { tooltip: T.Vnc, icon: <VncIcon /> },
  [VM_ACTIONS.SSH]: { tooltip: T.Ssh, icon: <SshIcon /> },
  [VM_ACTIONS.RDP]: { tooltip: T.Rdp, icon: <RdpIcon /> },
}

const GuacamoleButton = memo(({ vm, connectionType, onClick }) => {
  const { icon, tooltip } = GUACAMOLE_BUTTONS[connectionType]
  const history = useHistory()
  const [getSession, { isLoading }] = useLazyGetGuacamoleSessionQuery()

  const goToConsole = useCallback(
    async (evt) => {
      try {
        evt.stopPropagation()

        const params = { id: vm?.ID, type: connectionType }
        const session = await getSession(params).unwrap()

        typeof onClick === 'function'
          ? onClick(session)
          : history.push(generatePath(PATH.GUACAMOLE, params))
      } catch {}
    },
    [vm?.ID, connectionType, history, onClick]
  )

  return (
    <SubmitButton
      data-cy={`${vm?.ID}-${connectionType}`}
      icon={icon}
      tooltip={<Translate word={tooltip} />}
      isSubmitting={isLoading}
      onClick={goToConsole}
    />
  )
})

const VMRCButton = memo(({ vm, onClick }) => {
  const history = useHistory()
  const [getSession, { isLoading }] = useLazyGetVMRCSessionQuery()

  const goToConsole = useCallback(
    async (evt) => {
      try {
        evt.stopPropagation()

        const params = { id: vm?.ID }
        const session = await getSession(params).unwrap()

        typeof onClick === 'function'
          ? onClick(session)
          : history.push(generatePath(PATH.WMKS, params))
      } catch {}
    },
    [vm?.ID, history, onClick]
  )

  return (
    <SubmitButton
      data-cy={`${vm?.ID}-vmrc`}
      icon={<VncIcon />}
      tooltip={<Translate word={T.Vmrc} />}
      isSubmitting={isLoading}
      onClick={goToConsole}
    />
  )
})

const PreConsoleButton = memo(
  /**
   * @param {object} props - Props
   * @param {VM} props.vm - Virtual machine
   * @param {'vnc'|'ssh'|'rdp'|'vmrc'} props.connectionType - Connection type
   * @param {Function} [props.onClick] - Handle click for button
   * @returns {ReactElement} - Returns button if current user has permissions about the connection type
   */
  (props) => {
    const { vm, connectionType } = props
    const { view, [RESOURCE_NAMES.VM]: vmView } = useViews()

    const isDisabled = useMemo(() => {
      const noAction = vmView?.actions?.[connectionType] !== true
      const noAvailable = isAvailableAction(connectionType)(vm)
      const notHypervisor = !getHypervisor(vm)

      return noAction || noAvailable || notHypervisor
    }, [view, vm])

    const needNicConfig = useMemo(
      () => ![VM_ACTIONS.VNC, VM_ACTIONS.VMRC].includes(connectionType),
      [connectionType]
    )

    if (
      isDisabled ||
      (needNicConfig && !nicsIncludesTheConnectionType(vm, connectionType))
    ) {
      return null
    }

    if (connectionType === VM_ACTIONS.VMRC) {
      return isVCenter(vm) ? <VMRCButton {...props} /> : null
    }

    return !isVCenter(vm) ? <GuacamoleButton {...props} /> : null
  }
)

const ButtonPropTypes = {
  vm: PropTypes.object,
  connectionType: PropTypes.string,
  onClick: PropTypes.func,
}

GuacamoleButton.propTypes = ButtonPropTypes
VMRCButton.propTypes = ButtonPropTypes
PreConsoleButton.propTypes = ButtonPropTypes

GuacamoleButton.displayName = 'GuacamoleButton'
VMRCButton.displayName = 'VMRCButton'
PreConsoleButton.displayName = 'PreConsoleButton'

export { PreConsoleButton as GuacamoleButton }
<|endoftext|>


<commit_before>angular.module('ui.bootstrap.progressbar', [])

.constant('uibProgressConfig', {
  animate: true,
  max: 100
})

.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {
  var self = this,
      animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

  this.bars = [];
  $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;

  this.addBar = function(bar, element, attrs) {
    if (!animate) {
      element.css({'transition': 'none'});
    }

    this.bars.push(bar);

    bar.max = $scope.max;
    bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';

    bar.$watch('value', function(value) {
      bar.recalculatePercentage();
    });

    bar.recalculatePercentage = function() {
      bar.percent = +(100 * bar.value / bar.max).toFixed(2);

      var totalPercentage = self.bars.reduce(function(total, bar) {
        return total + bar.percent;
      }, 0);

      if (totalPercentage > 100) {
        bar.percent -= totalPercentage - 100;
      }
    };

    bar.$on('$destroy', function() {
      element = null;
      self.removeBar(bar);
    });
  };

  this.removeBar = function(bar) {
      this.bars.splice(this.bars.indexOf(bar), 1);
  };

  $scope.$watch('max', function(max) {
    self.bars.forEach(function(bar) {
      bar.max = $scope.max;
      bar.recalculatePercentage();
    });
  });
}])

.directive('uibProgress', function() {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    require: 'uibProgress',
    scope: {
      max: '=?'
    },
    templateUrl: 'template/progressbar/progress.html'
  };
})

.directive('uibBar', function() {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    require: '^uibProgress',
    scope: {
      value: '=',
      type: '@'
    },
    templateUrl: 'template/progressbar/bar.html',
    link: function(scope, element, attrs, progressCtrl) {
      progressCtrl.addBar(scope, element, attrs);
    }
  };
})

.directive('uibProgressbar', function() {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    scope: {
      value: '=',
      max: '=?',
      type: '@'
    },
    templateUrl: 'template/progressbar/progressbar.html',
    link: function(scope, element, attrs, progressCtrl) {
      progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
    }
  };
});

/* Deprecated progressbar below */

angular.module('ui.bootstrap.progressbar')

.value('$progressSuppressWarning', false)

.directive('progress', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    require: 'progress',
    scope: {
      max: '=?',
      title: '@?'
    },
    templateUrl: 'template/progressbar/progress.html',
    link: function() {
      if (!$progressSuppressWarning) {
        $log.warn('progress is now deprecated. Use uib-progress instead.');
      }
    }
  };
}])

.directive('bar', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    require: '^progress',
    scope: {
      value: '=',
      type: '@'
    },
    templateUrl: 'template/progressbar/bar.html',
    link: function(scope, element, attrs, progressCtrl) {
      if (!$progressSuppressWarning) {
        $log.warn('bar is now deprecated. Use uib-bar instead.');
      }
      progressCtrl.addBar(scope, element);
    }
  };
}])

.directive('progressbar', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    scope: {
      value: '=',
      max: '=?',
      type: '@'
    },
    templateUrl: 'template/progressbar/progressbar.html',
    link: function(scope, element, attrs, progressCtrl) {
      if (!$progressSuppressWarning) {
        $log.warn('progressbar is now deprecated. Use uib-progressbar instead.');
      }
      progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
    }
  };
}]);
<commit_msg>chore(progressbar): clean up code style<commit_after>angular.module('ui.bootstrap.progressbar', [])

.constant('uibProgressConfig', {
  animate: true,
  max: 100
})

.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {
  var self = this,
      animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

  this.bars = [];
  $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;

  this.addBar = function(bar, element, attrs) {
    if (!animate) {
      element.css({'transition': 'none'});
    }

    this.bars.push(bar);

    bar.max = $scope.max;
    bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';

    bar.$watch('value', function(value) {
      bar.recalculatePercentage();
    });

    bar.recalculatePercentage = function() {
      bar.percent = +(100 * bar.value / bar.max).toFixed(2);

      var totalPercentage = self.bars.reduce(function(total, bar) {
        return total + bar.percent;
      }, 0);

      if (totalPercentage > 100) {
        bar.percent -= totalPercentage - 100;
      }
    };

    bar.$on('$destroy', function() {
      element = null;
      self.removeBar(bar);
    });
  };

  this.removeBar = function(bar) {
    this.bars.splice(this.bars.indexOf(bar), 1);
  };

  $scope.$watch('max', function(max) {
    self.bars.forEach(function(bar) {
      bar.max = $scope.max;
      bar.recalculatePercentage();
    });
  });
}])

.directive('uibProgress', function() {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    require: 'uibProgress',
    scope: {
      max: '=?'
    },
    templateUrl: 'template/progressbar/progress.html'
  };
})

.directive('uibBar', function() {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    require: '^uibProgress',
    scope: {
      value: '=',
      type: '@'
    },
    templateUrl: 'template/progressbar/bar.html',
    link: function(scope, element, attrs, progressCtrl) {
      progressCtrl.addBar(scope, element, attrs);
    }
  };
})

.directive('uibProgressbar', function() {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    scope: {
      value: '=',
      max: '=?',
      type: '@'
    },
    templateUrl: 'template/progressbar/progressbar.html',
    link: function(scope, element, attrs, progressCtrl) {
      progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
    }
  };
});

/* Deprecated progressbar below */

angular.module('ui.bootstrap.progressbar')

.value('$progressSuppressWarning', false)

.directive('progress', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    require: 'progress',
    scope: {
      max: '=?',
      title: '@?'
    },
    templateUrl: 'template/progressbar/progress.html',
    link: function() {
      if (!$progressSuppressWarning) {
        $log.warn('progress is now deprecated. Use uib-progress instead.');
      }
    }
  };
}])

.directive('bar', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    require: '^progress',
    scope: {
      value: '=',
      type: '@'
    },
    templateUrl: 'template/progressbar/bar.html',
    link: function(scope, element, attrs, progressCtrl) {
      if (!$progressSuppressWarning) {
        $log.warn('bar is now deprecated. Use uib-bar instead.');
      }
      progressCtrl.addBar(scope, element);
    }
  };
}])

.directive('progressbar', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'UibProgressController',
    scope: {
      value: '=',
      max: '=?',
      type: '@'
    },
    templateUrl: 'template/progressbar/progressbar.html',
    link: function(scope, element, attrs, progressCtrl) {
      if (!$progressSuppressWarning) {
        $log.warn('progressbar is now deprecated. Use uib-progressbar instead.');
      }
      progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
    }
  };
}]);
<|endoftext|>