<commit_before>/**
 * Creating a sidebar enables you to:
 - create an ordered group of docs
 - render a sidebar for each doc of that group
 - provide next/previous navigation

 The sidebars can be generated from the filesystem, or explicitly defined here.

 Create as many sidebars as you want.
 */

module.exports = {
    documentation: [
        'user_guide/index',
        {
            label: 'First steps and tutorials',
            type: 'category',
            collapsed: false,
            link: {
                type: 'generated-index',
                title: 'First steps',
                description: 'Learn how and where to get started with Unleash.',
                slug: '/tutorials',
            },
            items: [
                'user_guide/unleash_overview',
                'user_guide/important-concepts',
                'user_guide/quickstart',
            ],
        },
        {
            label: 'How-to guides',
            collapsed: false,
            type: 'category',
            link: {
                type: 'generated-index',
                title: 'How-to guides',
                description: 'Step-by-step recipes for you to follow.',
                slug: '/how-to',
            },
            items: [
                {
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: Unleash API',
                        description: 'Learn how to work with the Unleash API',
                        slug: '/how-to/api',
                    },
                    label: 'API',
                    items: ['user_guide/api-token', 'advanced/api_access'],
                },
                {
                    label: 'Feature toggles, strategies, context',
                    items: [
                        'how-to/how-to-add-strategy-constraints',
                        'user_guide/create_feature_toggle',
                        'how-to/how-to-define-custom-context-fields',
                        'how-to/how-to-use-custom-strategies',
                    ],
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: general Unleash tasks',
                        description:
                            'Guides for how to perform general Unleash tasks.',
                        slug: '/how-to/misc',
                    },
                },
                {
                    label: 'Users and permissions',
                    items: [
                        'user_guide/user-management',
                        'how-to/how-to-create-and-assign-custom-project-roles',
                    ],
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: users and permissions',
                        description: 'Users and permission how-to guides.',
                        slug: '/how-to/users-and-permissions',
                    },
                },
                {
                    label: 'Single Sign-On (SSO)',
                    items: [
                        'advanced/sso-open-id-connect',
                        'advanced/sso-saml',
                        'advanced/sso-saml-keycloak',
                        'advanced/sso-google',
                    ],
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: Single Sign-On',
                        description: 'Single Sign-On how-to guides.',
                        slug: '/how-to/sso',
                    },
                },
                ,
            ],
        },
        {
            label: 'Reference documentation',
            collapsed: false,
            type: 'category',
            link: {
                type: 'generated-index',
                title: 'Reference documentation',
                description:
                    'Technical reference documentation relating to Unleash, including APIs, SDKs, Unleash concepts and deployment.',
                slug: '/reference',
            },
            items: [
                {
                    type: 'category',
                    link: { type: 'doc', id: 'addons/index' },
                    items: [
                        'addons/datadog',
                        'addons/slack',
                        'addons/teams',
                        'addons/webhook',
                    ],
                    label: 'Addons',
                },
                {
                    type: 'category',
                    link: { type: 'doc', id: 'api/index' },
                    label: 'APIs',
                    items: [
                        {
                            'Admin API': [
                                'api/admin/addons',
                                'api/admin/context',
                                'api/admin/events',
                                'api/admin/feature-toggles-v2',
                                'api/admin/feature-types',
                                'api/admin/features',
                                'api/admin/features-archive',
                                'api/admin/metrics',
                                'api/admin/projects',
                                'api/admin/state',
                                'api/admin/strategies',
                                'api/admin/user-admin',
                                {
                                    type: 'category',
                                    label: 'subcat',
                                    link: {
                                        type: 'generated-index',
                                        title: 'Subcat',
                                        description: 'Lorem ipsum',
                                        slug: '/api/subcat',
                                    },
                                    items: ['api/admin/user-admin'],
                                },
                            ],
                            'Client API': [
                                'api/client/features',
                                'api/client/metrics',
                                'api/client/register',
                            ],
                            'System API': [
                                'api/internal/internal',
                                'api/internal/health',
                            ],
                        },
                        'api/open_api',
                    ],
                },
                {
                    type: 'category',
                    label: 'Client SDKs',
                    link: { type: 'doc', id: 'sdks/index' },
                    items: [
                        {
                            type: 'category',
                            label: 'Server-side SDKs',
                            items: [
                                'sdks/go_sdk',
                                'sdks/java_sdk',
                                'sdks/node_sdk',
                                'sdks/php_sdk',
                                'sdks/python_sdk',
                                'sdks/ruby_sdk',
                                {
                                    type: 'link',
                                    href: 'https://github.com/unleash/unleash-client-rust',
                                    label: 'Rust SDK',
                                },
                                'sdks/dot_net_sdk',
                            ],
                        },
                        {
                            type: 'category',
                            label: 'Client-side SDKs',
                            items: [
                                'sdks/android_proxy_sdk',
                                'sdks/proxy-ios',
                                'sdks/proxy-javascript',
                                'sdks/proxy-react',
                            ],
                        },
                        {
                            type: 'link',
                            label: 'Community SDKs',
                            href: '/sdks#community-sdks',
                        },
                    ],
                },
                {
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'Deployment and management of Unleash',
                        description:
                            'All you need to learn how to deploy and manage your own Unleash instance.',
                        slug: '/deploy',
                    },
                    label: 'Deploy and manage Unleash',
                    items: [
                        'deploy/getting_started',
                        'deploy/configuring_unleash',
                        'deploy/database-setup',
                        'deploy/database_backup',
                        'deploy/email',
                        'deploy/google_auth',
                        'deploy/import_export',
                        'deploy/migration_guide',
                        'deploy/securing_unleash',
                    ],
                },
                {
                    type: 'category',
                    label: 'Integrations',
                    link: { type: 'doc', id: 'integrations/integrations' },
                    items: [
                        {
                            'Jira Server': [
                                'integrations/jira_server_plugin_installation',
                                'integrations/jira_server_plugin_usage',
                            ],
                        },
                        ,
                    ],
                },
                {
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'Unleash concepts',
                        description:
                            'Documents describing the inner parts of Unleash.',
                        slug: '/reference/concepts',
                    },
                    label: 'Unleash concepts',
                    items: [
                        'user_guide/activation_strategy',
                        'advanced/archived_toggles',
                        'advanced/audit_log',
                        'advanced/custom_activation_strategy',
                        'user_guide/environments',
                        'advanced/feature_toggle_types',
                        'advanced/toggle_variants',
                        'user_guide/projects',
                        'user_guide/rbac',
                        'advanced/enterprise-authentication',
                        'advanced/stickiness',
                        'advanced/strategy_constraints',
                        'advanced/tags',
                        'user_guide/technical_debt',
                        'user_guide/unleash_context',
                        'sdks/unleash-proxy',
                    ],
                },
            ],
        },
        {
            label: 'Topic guides',
            collapsed: false,
            type: 'category',
            link: {
                type: 'generated-index',
                title: 'Topic guides',
                description:
                    'Discussions, explanations, and explorations regarding topics related to Unleash.',
                slug: '/topics',
            },
            items: ['topics/a-b-testing'],
        },
    ],
};
<commit_msg>fix(docs): remove test subcat from sidebar<commit_after>/**
 * Creating a sidebar enables you to:
 - create an ordered group of docs
 - render a sidebar for each doc of that group
 - provide next/previous navigation

 The sidebars can be generated from the filesystem, or explicitly defined here.

 Create as many sidebars as you want.
 */

module.exports = {
    documentation: [
        'user_guide/index',
        {
            label: 'First steps and tutorials',
            type: 'category',
            collapsed: false,
            link: {
                type: 'generated-index',
                title: 'First steps',
                description: 'Learn how and where to get started with Unleash.',
                slug: '/tutorials',
            },
            items: [
                'user_guide/unleash_overview',
                'user_guide/important-concepts',
                'user_guide/quickstart',
            ],
        },
        {
            label: 'How-to guides',
            collapsed: false,
            type: 'category',
            link: {
                type: 'generated-index',
                title: 'How-to guides',
                description: 'Step-by-step recipes for you to follow.',
                slug: '/how-to',
            },
            items: [
                {
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: Unleash API',
                        description: 'Learn how to work with the Unleash API',
                        slug: '/how-to/api',
                    },
                    label: 'API',
                    items: ['user_guide/api-token', 'advanced/api_access'],
                },
                {
                    label: 'Feature toggles, strategies, context',
                    items: [
                        'how-to/how-to-add-strategy-constraints',
                        'user_guide/create_feature_toggle',
                        'how-to/how-to-define-custom-context-fields',
                        'how-to/how-to-use-custom-strategies',
                    ],
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: general Unleash tasks',
                        description:
                            'Guides for how to perform general Unleash tasks.',
                        slug: '/how-to/misc',
                    },
                },
                {
                    label: 'Users and permissions',
                    items: [
                        'user_guide/user-management',
                        'how-to/how-to-create-and-assign-custom-project-roles',
                    ],
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: users and permissions',
                        description: 'Users and permission how-to guides.',
                        slug: '/how-to/users-and-permissions',
                    },
                },
                {
                    label: 'Single Sign-On (SSO)',
                    items: [
                        'advanced/sso-open-id-connect',
                        'advanced/sso-saml',
                        'advanced/sso-saml-keycloak',
                        'advanced/sso-google',
                    ],
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'How-to: Single Sign-On',
                        description: 'Single Sign-On how-to guides.',
                        slug: '/how-to/sso',
                    },
                },
                ,
            ],
        },
        {
            label: 'Reference documentation',
            collapsed: false,
            type: 'category',
            link: {
                type: 'generated-index',
                title: 'Reference documentation',
                description:
                    'Technical reference documentation relating to Unleash, including APIs, SDKs, Unleash concepts and deployment.',
                slug: '/reference',
            },
            items: [
                {
                    type: 'category',
                    link: { type: 'doc', id: 'addons/index' },
                    items: [
                        'addons/datadog',
                        'addons/slack',
                        'addons/teams',
                        'addons/webhook',
                    ],
                    label: 'Addons',
                },
                {
                    type: 'category',
                    link: { type: 'doc', id: 'api/index' },
                    label: 'APIs',
                    items: [
                        {
                            'Admin API': [
                                'api/admin/addons',
                                'api/admin/context',
                                'api/admin/events',
                                'api/admin/feature-toggles-v2',
                                'api/admin/feature-types',
                                'api/admin/features',
                                'api/admin/features-archive',
                                'api/admin/metrics',
                                'api/admin/projects',
                                'api/admin/state',
                                'api/admin/strategies',
                                'api/admin/user-admin',
                            ],
                            'Client API': [
                                'api/client/features',
                                'api/client/metrics',
                                'api/client/register',
                            ],
                            'System API': [
                                'api/internal/internal',
                                'api/internal/health',
                            ],
                        },
                        'api/open_api',
                    ],
                },
                {
                    type: 'category',
                    label: 'Client SDKs',
                    link: { type: 'doc', id: 'sdks/index' },
                    items: [
                        {
                            type: 'category',
                            label: 'Server-side SDKs',
                            items: [
                                'sdks/go_sdk',
                                'sdks/java_sdk',
                                'sdks/node_sdk',
                                'sdks/php_sdk',
                                'sdks/python_sdk',
                                'sdks/ruby_sdk',
                                {
                                    type: 'link',
                                    href: 'https://github.com/unleash/unleash-client-rust',
                                    label: 'Rust SDK',
                                },
                                'sdks/dot_net_sdk',
                            ],
                        },
                        {
                            type: 'category',
                            label: 'Client-side SDKs',
                            items: [
                                'sdks/android_proxy_sdk',
                                'sdks/proxy-ios',
                                'sdks/proxy-javascript',
                                'sdks/proxy-react',
                            ],
                        },
                        {
                            type: 'link',
                            label: 'Community SDKs',
                            href: '/sdks#community-sdks',
                        },
                    ],
                },
                {
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'Deployment and management of Unleash',
                        description:
                            'All you need to learn how to deploy and manage your own Unleash instance.',
                        slug: '/deploy',
                    },
                    label: 'Deploy and manage Unleash',
                    items: [
                        'deploy/getting_started',
                        'deploy/configuring_unleash',
                        'deploy/database-setup',
                        'deploy/database_backup',
                        'deploy/email',
                        'deploy/google_auth',
                        'deploy/import_export',
                        'deploy/migration_guide',
                        'deploy/securing_unleash',
                    ],
                },
                {
                    type: 'category',
                    label: 'Integrations',
                    link: { type: 'doc', id: 'integrations/integrations' },
                    items: [
                        {
                            'Jira Server': [
                                'integrations/jira_server_plugin_installation',
                                'integrations/jira_server_plugin_usage',
                            ],
                        },
                        ,
                    ],
                },
                {
                    type: 'category',
                    link: {
                        type: 'generated-index',
                        title: 'Unleash concepts',
                        description:
                            'Documents describing the inner parts of Unleash.',
                        slug: '/reference/concepts',
                    },
                    label: 'Unleash concepts',
                    items: [
                        'user_guide/activation_strategy',
                        'advanced/archived_toggles',
                        'advanced/audit_log',
                        'advanced/custom_activation_strategy',
                        'user_guide/environments',
                        'advanced/feature_toggle_types',
                        'advanced/toggle_variants',
                        'user_guide/projects',
                        'user_guide/rbac',
                        'advanced/enterprise-authentication',
                        'advanced/stickiness',
                        'advanced/strategy_constraints',
                        'advanced/tags',
                        'user_guide/technical_debt',
                        'user_guide/unleash_context',
                        'sdks/unleash-proxy',
                    ],
                },
            ],
        },
        {
            label: 'Topic guides',
            collapsed: false,
            type: 'category',
            link: {
                type: 'generated-index',
                title: 'Topic guides',
                description:
                    'Discussions, explanations, and explorations regarding topics related to Unleash.',
                slug: '/topics',
            },
            items: ['topics/a-b-testing'],
        },
    ],
};
<|endoftext|>


<commit_before>'use strict';

/*
 * Factory for setting up a FabricJS drawing surface on a canvas.
 * Also sets up callbacks for PeerJS, so it can receive line data
 * and draw them accordingly.
 */

angular.module('drawinghandler', [])
.factory('drawingFactory', function (configFactory, $window, $state, $timeout, peerFactory) {
    // References to two of the canvasi
    var remoteCanvas = null;
    var localCanvas  = null;

    // Configuration object
    var config = configFactory.getValue('drawings');

    // Array that will eventually contain a bunch of angular $timeouts
    // We need to keep track of em so we can easily cancel them all if need be
    var pathRemoveTimers = [];

    var canvasSize = {
        width:  $window.innerWidth *  config.size.width,
        height: $window.innerHeight * config.size.height
    };

    // Takes in a selector and an optionals object
    // Size of canvas has to be calculated at runtime
    var initFabricJS = function (canvasId, opts) {
        var fabricCanvas = new fabric.Canvas(canvasId, {
            isDrawingMode: true,
            renderOnAddRemove: false,
            selection: false,
            stateful: false,
            width: canvasSize.width,
            height: canvasSize.height
        });

        fabricCanvas.calcOffset();
        fabricCanvas.freeDrawingBrush.width = config.brushWidth;
        fabricCanvas.freeDrawingBrush.color = config.localColor;

        fabricCanvas.isArrowModeOn = false;
        fabricCanvas.isMouseCurrentlyPressed = false;

        fabricCanvas.toggleArrowDrawingMode = function () {
            this.isDrawingMode   = !this.isDrawingMode;
            this.isArrowModeOn   = !this.isArrowModeOn;
        };

        if (opts.isRemote === true) {
            remoteCanvas = fabricCanvas;
            fabricCanvas.tag = 'remote';
        } else if (opts.isRemote === false) {
            localCanvas = fabricCanvas;
            fabricCanvas.tag = 'local';
        }

        return fabricCanvas;
    };

    var removePathFromCanvas = function (canvas, path) {
        canvas.remove(path);
        canvas.renderAll(false);
    };

    var createPathRemoveTimer = function (canvas, path) {
        var timer = $timeout(function () {
            removePathFromCanvas(canvas, path);
        }, config.drawingRemoveTime);

        pathRemoveTimers.push(timer);
    };

    var cancelPathRemoveTimers = function () {
        pathRemoveTimers.forEach(function (t) {
            $timeout.cancel(t);
        });
    };

    var setUpCanvasEvents = function (canvas) {
        canvas.on('path:created', function (e) {
            var data = angular.toJson(e.path);

            var dataToSend = {
                type                          : 'newPathCreated',
                tag                           : canvas.tag,
                data                          : data,
                remoteCanvasSize              : canvasSize
            };

            peerFactory.sendDataToPeer(angular.toJson(dataToSend));

            e.path.selectable = false;

            createPathRemoveTimer(canvas, e.path);
        });

        canvas.on('mouse:down', function (e) {
            var pointer;
            var points;

            if (canvas.isArrowModeOn === true) {
                this.isMouseCurrentlyPressed = true;
                pointer = canvas.getPointer(e.e);
                points = [pointer.x, pointer.y, pointer.x, pointer.y];

                this.currentArrow = new fabric.Line(points, {
                    strokeWidth: config.arrows.strokeWidth,
                    fill: config.localColor,
                    stroke: config.localColor,
                    selectable: false,
                    originX: 'center',
                    originY: 'center'
                });

                this.currentArrow.startingX = pointer.x;
                this.currentArrow.startingY = pointer.y;

                this.currentArrowHead = new fabric.Triangle({
                    width: config.arrows.headWidth,
                    height: config.arrows.headHeight,
                    fill: config.localColor,
                    stroke: config.localColor,
                    selectable: false,
                    originX: 'center',
                    originY: 'center',
                    top: pointer.y,
                    left: pointer.x
                });

                canvas.add(this.currentArrow);
                canvas.add(this.currentArrowHead);
            }});

        canvas.on('mouse:move', function (e) {
            var pointer;

            var startingX;
            var startingY;

            var currentY;
            var currentX;

            var headAngle;

            if (this.isArrowModeOn === true) {
                if (!this.isMouseCurrentlyPressed) return;

                pointer = canvas.getPointer(e.e);

                startingX = this.currentArrow.startingX;
                startingY = this.currentArrow.startingY;

                currentY = pointer.y;
                currentX = pointer.x;

                headAngle = Math.atan2(currentY - startingY, currentX - startingX);
                headAngle *= 180 / Math.PI;
                headAngle += 90;

                this.currentArrow.set({ x2: pointer.x, y2: pointer.y });
                this.currentArrowHead.set({ left: pointer.x, top: pointer.y, angle: headAngle });
                canvas.renderAll();
            }
        });

        canvas.on('mouse:up', function () {
            var arrowData;
            var dataToSend;

            if (this.isArrowModeOn === true) {
                this.isMouseCurrentlyPressed = false;
                arrowData = { line: this.currentArrow, head: this.currentArrowHead };

                dataToSend = {
                    type                          : 'newArrowCreated',
                    tag                           : canvas.tag,
                    data                          : arrowData,
                    remoteCanvasSize              : canvasSize
                };

                peerFactory.sendDataToPeer(angular.toJson(dataToSend));
            }
        });
    };

    var addPathToCanvas = function (canvasTag, pathData, remoteCanvasSize) {
        if (canvasTag === 'local') {
            addNewPathToCanvas(remoteCanvas, pathData, remoteCanvasSize);
        } else if (canvasTag === 'remote') {
            addNewPathToCanvas(localCanvas, pathData, remoteCanvasSize);
        }
    };

    var addNewPathToCanvas = function (canvas, pathData, remoteCanvasSize) {
        pathData = angular.fromJson(pathData);
        fabric.util.enlivenObjects([pathData], function (objects) {
            objects.forEach(function (o) {
                o.stroke = config.remoteColor;

                o.set({
                    top:    o.top    / (remoteCanvasSize.height / canvasSize.height),
                    left:   o.left   / (remoteCanvasSize.width  / canvasSize.width),
                    scaleY: o.scaleX / (remoteCanvasSize.height / canvasSize.height),
                    scaleX: o.scaleY / (remoteCanvasSize.width  / canvasSize.width),
                    selectable: false
                });

                canvas.add(o);
                canvas.renderAll(true);
                createPathRemoveTimer(canvas, o);
            });
        });
    };

    var addArrowToCanvas = function (canvasTag, arrowData, remoteCanvasSize) {
        if (canvasTag === 'local') {
            addNewArrowToCanvas(remoteCanvas, arrowData, remoteCanvasSize);
        } else if (canvasTag === 'remote') {
            addNewArrowToCanvas(localCanvas, arrowData, remoteCanvasSize);
        }
    };

    var addNewArrowToCanvas = function (canvas, arrowData, remoteCanvasSize) {
        fabric.util.enlivenObjects([arrowData.line, arrowData.head], function (objects) {
            objects.forEach(function (o) {
                o.stroke = config.remoteColor;
                o.fill = config.remoteColor;

                o.set({
                    top:    o.top    / (remoteCanvasSize.height / canvasSize.height),
                    left:   o.left   / (remoteCanvasSize.width  / canvasSize.width),
                    scaleY: o.scaleX / (remoteCanvasSize.height / canvasSize.height),
                    scaleX: o.scaleY / (remoteCanvasSize.width  / canvasSize.width)
                });

                canvas.add(o);
                canvas.renderAll(true);
            });
        });
    };

    var setUpDrawingCanvas = function (canvasId, opts) {
        var canvas = initFabricJS(canvasId, opts);
        setUpCanvasEvents(canvas);
    };

    var clearCanvas = function (canvas) {
        canvas.clear();
    };

    // Public API begins here
    return {
        setUpRemoteCanvas: function (canvasId, opts) {
            if (!remoteCanvas) {
                opts.isRemote = true;
                setUpDrawingCanvas(canvasId, opts);
            }
        },
        setUpLocalCanvas: function (canvasId, opts) {
            if (!localCanvas) {
                opts.isRemote = false;
                setUpDrawingCanvas(canvasId, opts);
            }
        },
        toggleArrowDrawingMode: function () {
            remoteCanvas.toggleArrowDrawingMode();
            localCanvas.toggleArrowDrawingMode();
        },
        setUpDataCallbacks: function () {
            peerFactory.registerCallback('newPathCreated', function (data) {
                var parsedData = angular.fromJson(data);
                addPathToCanvas(parsedData.tag, parsedData.data, parsedData.remoteCanvasSize);
            });

            peerFactory.registerCallback('newArrowCreated', function (data) {
                var parsedData = angular.fromJson(data);
                addArrowToCanvas(parsedData.tag, parsedData.data, parsedData.remoteCanvasSize);
            });
        },
        clearLocalCanvas: function () {
            clearCanvas(localCanvas);
        },
        clearRemoteCanvas: function () {
            clearCanvas(remoteCanvas);
        },
        tearDownDrawingFactory: function () {
            cancelPathRemoveTimers();
            peerFactory.clearCallback('newPathCreated');
            peerFactory.clearCallback('newArrowCreated');
        }
    };
});

<commit_msg>Disable automatic path removal<commit_after>'use strict';

/*
 * Factory for setting up a FabricJS drawing surface on a canvas.
 * Also sets up callbacks for PeerJS, so it can receive line data
 * and draw them accordingly.
 */

angular.module('drawinghandler', [])
.factory('drawingFactory', function (configFactory, $window, $state, $timeout, peerFactory) {
    // References to two of the canvasi
    var remoteCanvas = null;
    var localCanvas  = null;

    // Configuration object
    var config = configFactory.getValue('drawings');

    // Array that will eventually contain a bunch of angular $timeouts
    // We need to keep track of em so we can easily cancel them all if need be
    var pathRemoveTimers = [];

    var canvasSize = {
        width:  $window.innerWidth *  config.size.width,
        height: $window.innerHeight * config.size.height
    };

    // Takes in a selector and an optionals object
    // Size of canvas has to be calculated at runtime
    var initFabricJS = function (canvasId, opts) {
        var fabricCanvas = new fabric.Canvas(canvasId, {
            isDrawingMode: true,
            renderOnAddRemove: false,
            selection: false,
            stateful: false,
            width: canvasSize.width,
            height: canvasSize.height
        });

        fabricCanvas.calcOffset();
        fabricCanvas.freeDrawingBrush.width = config.brushWidth;
        fabricCanvas.freeDrawingBrush.color = config.localColor;

        fabricCanvas.isArrowModeOn = false;
        fabricCanvas.isMouseCurrentlyPressed = false;

        fabricCanvas.toggleArrowDrawingMode = function () {
            this.isDrawingMode   = !this.isDrawingMode;
            this.isArrowModeOn   = !this.isArrowModeOn;
        };

        if (opts.isRemote === true) {
            remoteCanvas = fabricCanvas;
            fabricCanvas.tag = 'remote';
        } else if (opts.isRemote === false) {
            localCanvas = fabricCanvas;
            fabricCanvas.tag = 'local';
        }

        return fabricCanvas;
    };

    var removePathFromCanvas = function (canvas, path) {
        canvas.remove(path);
        canvas.renderAll(false);
    };

    var createPathRemoveTimer = function (canvas, path) {
        var timer = $timeout(function () {
            removePathFromCanvas(canvas, path);
        }, config.drawingRemoveTime);

        pathRemoveTimers.push(timer);
    };

    var cancelPathRemoveTimers = function () {
        pathRemoveTimers.forEach(function (t) {
            $timeout.cancel(t);
        });
    };

    var setUpCanvasEvents = function (canvas) {
        canvas.on('path:created', function (e) {
            var data = angular.toJson(e.path);

            var dataToSend = {
                type                          : 'newPathCreated',
                tag                           : canvas.tag,
                data                          : data,
                remoteCanvasSize              : canvasSize
            };

            peerFactory.sendDataToPeer(angular.toJson(dataToSend));

            e.path.selectable = false;

            //createPathRemoveTimer(canvas, e.path);
        });

        canvas.on('mouse:down', function (e) {
            var pointer;
            var points;

            if (canvas.isArrowModeOn === true) {
                this.isMouseCurrentlyPressed = true;
                pointer = canvas.getPointer(e.e);
                points = [pointer.x, pointer.y, pointer.x, pointer.y];

                this.currentArrow = new fabric.Line(points, {
                    strokeWidth: config.arrows.strokeWidth,
                    fill: config.localColor,
                    stroke: config.localColor,
                    selectable: false,
                    originX: 'center',
                    originY: 'center'
                });

                this.currentArrow.startingX = pointer.x;
                this.currentArrow.startingY = pointer.y;

                this.currentArrowHead = new fabric.Triangle({
                    width: config.arrows.headWidth,
                    height: config.arrows.headHeight,
                    fill: config.localColor,
                    stroke: config.localColor,
                    selectable: false,
                    originX: 'center',
                    originY: 'center',
                    top: pointer.y,
                    left: pointer.x
                });

                canvas.add(this.currentArrow);
                canvas.add(this.currentArrowHead);
            }});

        canvas.on('mouse:move', function (e) {
            var pointer;

            var startingX;
            var startingY;

            var currentY;
            var currentX;

            var headAngle;

            if (this.isArrowModeOn === true) {
                if (!this.isMouseCurrentlyPressed) return;

                pointer = canvas.getPointer(e.e);

                startingX = this.currentArrow.startingX;
                startingY = this.currentArrow.startingY;

                currentY = pointer.y;
                currentX = pointer.x;

                headAngle = Math.atan2(currentY - startingY, currentX - startingX);
                headAngle *= 180 / Math.PI;
                headAngle += 90;

                this.currentArrow.set({ x2: pointer.x, y2: pointer.y });
                this.currentArrowHead.set({ left: pointer.x, top: pointer.y, angle: headAngle });
                canvas.renderAll();
            }
        });

        canvas.on('mouse:up', function () {
            var arrowData;
            var dataToSend;

            if (this.isArrowModeOn === true) {
                this.isMouseCurrentlyPressed = false;
                arrowData = { line: this.currentArrow, head: this.currentArrowHead };

                dataToSend = {
                    type                          : 'newArrowCreated',
                    tag                           : canvas.tag,
                    data                          : arrowData,
                    remoteCanvasSize              : canvasSize
                };

                peerFactory.sendDataToPeer(angular.toJson(dataToSend));
            }
        });
    };

    var addPathToCanvas = function (canvasTag, pathData, remoteCanvasSize) {
        if (canvasTag === 'local') {
            addNewPathToCanvas(remoteCanvas, pathData, remoteCanvasSize);
        } else if (canvasTag === 'remote') {
            addNewPathToCanvas(localCanvas, pathData, remoteCanvasSize);
        }
    };

    var addNewPathToCanvas = function (canvas, pathData, remoteCanvasSize) {
        pathData = angular.fromJson(pathData);
        fabric.util.enlivenObjects([pathData], function (objects) {
            objects.forEach(function (o) {
                o.stroke = config.remoteColor;

                o.set({
                    top:    o.top    / (remoteCanvasSize.height / canvasSize.height),
                    left:   o.left   / (remoteCanvasSize.width  / canvasSize.width),
                    scaleY: o.scaleX / (remoteCanvasSize.height / canvasSize.height),
                    scaleX: o.scaleY / (remoteCanvasSize.width  / canvasSize.width),
                    selectable: false
                });

                canvas.add(o);
                canvas.renderAll(true);
                //createPathRemoveTimer(canvas, o);
            });
        });
    };

    var addArrowToCanvas = function (canvasTag, arrowData, remoteCanvasSize) {
        if (canvasTag === 'local') {
            addNewArrowToCanvas(remoteCanvas, arrowData, remoteCanvasSize);
        } else if (canvasTag === 'remote') {
            addNewArrowToCanvas(localCanvas, arrowData, remoteCanvasSize);
        }
    };

    var addNewArrowToCanvas = function (canvas, arrowData, remoteCanvasSize) {
        fabric.util.enlivenObjects([arrowData.line, arrowData.head], function (objects) {
            objects.forEach(function (o) {
                o.stroke = config.remoteColor;
                o.fill = config.remoteColor;

                o.set({
                    top:    o.top    / (remoteCanvasSize.height / canvasSize.height),
                    left:   o.left   / (remoteCanvasSize.width  / canvasSize.width),
                    scaleY: o.scaleX / (remoteCanvasSize.height / canvasSize.height),
                    scaleX: o.scaleY / (remoteCanvasSize.width  / canvasSize.width)
                });

                canvas.add(o);
                canvas.renderAll(true);
            });
        });
    };

    var setUpDrawingCanvas = function (canvasId, opts) {
        var canvas = initFabricJS(canvasId, opts);
        setUpCanvasEvents(canvas);
    };

    var clearCanvas = function (canvas) {
        canvas.clear();
    };

    // Public API begins here
    return {
        setUpRemoteCanvas: function (canvasId, opts) {
            if (!remoteCanvas) {
                opts.isRemote = true;
                setUpDrawingCanvas(canvasId, opts);
            }
        },
        setUpLocalCanvas: function (canvasId, opts) {
            if (!localCanvas) {
                opts.isRemote = false;
                setUpDrawingCanvas(canvasId, opts);
            }
        },
        toggleArrowDrawingMode: function () {
            remoteCanvas.toggleArrowDrawingMode();
            localCanvas.toggleArrowDrawingMode();
        },
        setUpDataCallbacks: function () {
            peerFactory.registerCallback('newPathCreated', function (data) {
                var parsedData = angular.fromJson(data);
                addPathToCanvas(parsedData.tag, parsedData.data, parsedData.remoteCanvasSize);
            });

            peerFactory.registerCallback('newArrowCreated', function (data) {
                var parsedData = angular.fromJson(data);
                addArrowToCanvas(parsedData.tag, parsedData.data, parsedData.remoteCanvasSize);
            });
        },
        clearLocalCanvas: function () {
            clearCanvas(localCanvas);
        },
        clearRemoteCanvas: function () {
            clearCanvas(remoteCanvas);
        },
        tearDownDrawingFactory: function () {
            cancelPathRemoveTimers();
            peerFactory.clearCallback('newPathCreated');
            peerFactory.clearCallback('newArrowCreated');
        }
    };
});

<|endoftext|>


<commit_before>module.exports = {
  Sidebar: [
    "getting_started",
    {
      type: "category",
      label: "Concepts",
      items: [
        "concepts/providers",
        "concepts/reading",
        "concepts/combining_providers",
        // "concepts/computed",
        {
          type: "category",
          label: "Modifiers",
          items: [
            "concepts/modifiers/family",
            "concepts/modifiers/auto_dispose",
          ],
        },
      ],
    },
    {
      type: "category",
      label: "Cookbooks",
      items: ["cookbooks/testing", "cookbooks/refresh"],
    },
    {
      type: "category",
      label: "Examples",
      items: [
        {
          type: "link",
          label: "Counter",
          href:
            "https://github.com/rrousselGit/river_pod/tree/master/examples/counter",
        },
        {
          type: "link",
          label: "Todo list",
          href:
            "https://github.com/rrousselGit/river_pod/tree/master/examples/todos",
        },
        {
          type: "link",
          label: "Marvel API",
          href:
            "https://github.com/rrousselGit/river_pod/tree/master/examples/marvel",
        },
      ],
    },
    {
      type: "category",
      label: "Api references",
      items: [
        {
          type: "link",
          label: "riverpod",
          href:
            "https://pub.dev/documentation/riverpod/latest/riverpod/riverpod-library.html",
        },
        {
          type: "link",
          label: "flutter_riverpod",
          href:
            "https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/flutter_riverpod-library.html",
        },
        {
          type: "link",
          label: "hooks_riverpod",
          href:
            "https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/hooks_riverpod-library.html",
        },
      ],
    },
  ],
};
<commit_msg>Hide refresh cookbook<commit_after>module.exports = {
  Sidebar: [
    "getting_started",
    {
      type: "category",
      label: "Concepts",
      items: [
        "concepts/providers",
        "concepts/reading",
        "concepts/combining_providers",
        // "concepts/computed",
        {
          type: "category",
          label: "Modifiers",
          items: [
            "concepts/modifiers/family",
            "concepts/modifiers/auto_dispose",
          ],
        },
      ],
    },
    {
      type: "category",
      label: "Cookbooks",
      items: [
        "cookbooks/testing",
        //"cookbooks/refresh",
      ],
    },
    {
      type: "category",
      label: "Examples",
      items: [
        {
          type: "link",
          label: "Counter",
          href:
            "https://github.com/rrousselGit/river_pod/tree/master/examples/counter",
        },
        {
          type: "link",
          label: "Todo list",
          href:
            "https://github.com/rrousselGit/river_pod/tree/master/examples/todos",
        },
        {
          type: "link",
          label: "Marvel API",
          href:
            "https://github.com/rrousselGit/river_pod/tree/master/examples/marvel",
        },
      ],
    },
    {
      type: "category",
      label: "Api references",
      items: [
        {
          type: "link",
          label: "riverpod",
          href:
            "https://pub.dev/documentation/riverpod/latest/riverpod/riverpod-library.html",
        },
        {
          type: "link",
          label: "flutter_riverpod",
          href:
            "https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/flutter_riverpod-library.html",
        },
        {
          type: "link",
          label: "hooks_riverpod",
          href:
            "https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/hooks_riverpod-library.html",
        },
      ],
    },
  ],
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';

let catchers = [];

export function catcherWatcher(keyCode) {
  const char = String.fromCharCode(keyCode);
  for (const catcher of catchers) {
    catcher.history += char;
    if (catcher.history.length > catcher.sequence.length) {
      catcher.history = catcher.history.slice(1)
    }
    if (catcher.history.toUpperCase() === catcher.sequence.toUpperCase()) {
      catcher.history = [];
      catcher.cb();
    }
  }
}

export function addCatcher(sequence, cb) {
  const id = Math.random().toString(36).substring(2, 10);
  catchers.push({ id, sequence, cb, history: [] });
  return id;
}

export function removeCatcher(id) {
  catchers = catchers.filter(catcher => catcher.id !== id);
}

export default (catcher, cb) => BaseComponent => {
  return class CatcherComponent extends Component {

    componentDidMount() {
      const _props = this.props;
      this.id = addCatcher(catcher, () => cb.call(this, _props));
    }

    componentWillUnmount() {
      removeCatcher(this.id);
    }

    render() {
      return <BaseComponent/>;
    }
  };
}<commit_msg>fix pass props to component<commit_after>import React, { Component } from 'react';

let catchers = [];

export function catcherWatcher(keyCode) {
  const char = String.fromCharCode(keyCode);
  for (const catcher of catchers) {
    catcher.history += char;
    if (catcher.history.length > catcher.sequence.length) {
      catcher.history = catcher.history.slice(1)
    }
    if (catcher.history.toUpperCase() === catcher.sequence.toUpperCase()) {
      catcher.history = [];
      catcher.cb();
    }
  }
}

export function addCatcher(sequence, cb) {
  const id = Math.random().toString(36).substring(2, 10);
  catchers.push({ id, sequence, cb, history: [] });
  return id;
}

export function removeCatcher(id) {
  catchers = catchers.filter(catcher => catcher.id !== id);
}

export default (catcher, cb) => BaseComponent => {
  return class CatcherComponent extends Component {

    componentDidMount() {
      const _props = this.props;
      this.id = addCatcher(catcher, () => cb.call(this, _props));
    }

    componentWillUnmount() {
      removeCatcher(this.id);
    }

    render() {
      return React.createElement(BaseComponent, this.props);
    }
  };
}<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash'),
	mongoose = require('mongoose'),
	crm_services = require('../CRM/crm_services.js');

exports.getAgent = function(agentID) {
	crm_services.getAgent(agentID, function(agent) {
		callback(agent);
	}

exports.getContactHistory = function(agentID, customerID) {
	crm_services.getContactHistory(agentID, customerID, function(contacts) {
		callback(contacts);
	});
};

exports.getCustomer = function(customerID) {
	crm_services.getCustomer(customerID, function(customer) {
		callback(customer);
	});
};<commit_msg>small fixes to customer facade<commit_after>'use strict';

var _ = require('lodash'),
	mongoose = require('mongoose'),
	crm_services = require('../CRM/crm_services.js');

exports.getAgent = function(agentID) {
	crm_services.getAgent(agentID, function(agent) {
		callback(agent);
	});
};

exports.getContactHistory = function(agentID, customerID) {
	crm_services.getContactHistory(agentID, customerID, function(contacts) {
		callback(contacts);
	});
};

exports.getCustomer = function(customerID) {
	crm_services.getCustomer(customerID, function(customer) {
		callback(customer);
	});
};<|endoftext|>


<commit_before>/**
 * **************************************************
 * **************************************************
 * **************************************************
 * ******************** CHAKMAK  *********************
 * **************************************************
 * **************************************************
 */

/**
 * @author Upendra Dev Singh
 * @description A small pubsub utility
 *
 * MIT Licence
 */

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

;(function(definition){
	var	hasDefine = typeof define === 'function' && define.amd,			// AMD
		hasExports = typeof module !== 'undefined' && module.exports;	// Commonjs

	// Setup the root object, `window` (`self`) in the browser, or `global` in the node.js server.
    // We use `self` instead of `window` for `WebWorker` support.

    var root = (typeof self == 'object' && self.self === self && self) || (typeof global == 'object' && global.global === global && global);

	if(hasDefine){
		define(['exports'], function(exports) {
		    // Export global even in AMD case
			// Avoid duplicate bu default

		    root.Chakmak = definition(exports);
		});
	// node.js or commonjs
	}else if(hasExports){
		definition(exports);
	// Finally, as browser global
	}else{
		definition(root);
	}
}(function(root){

	var Chakmak = {};

	root.Chakmak = Chakmak;

	Chakmak.version = '0.0.1';

	/**
	 * Creates an object with given properties and methods
	 *
	 *
	 * @param  {Object} staticProps Properties to be added to newly constructed object
	 * @param  {Object} methods Functions to be added to newly constructed object prototype
	 * @return {Object} Return an new object
	 */
	function create(staticProps, methods){
		var Parent = this;	// Publisher or Subscriber Object
		var child;			// New Object to be created

		// A child class constructor inheritted from Parent class
		function Child(){
			return Parent.call(this);
		}

		// Inherit Child Class from current parent class
		Child.prototype = Object.create(Parent.prototype);
		Child.prototype.constructor = Child;

		// Copy all the custom method to Child class prototype
		if(typeof methods === 'object'){
			for(var key in methods){
				Child.prototype[key] = methods[key];
			}
		}

		// maintain a copy of parent class into new child class
		Child.__super__ = Parent.prototype;

		child = new Child();

		if(typeof staticProps === 'object'){
			for(var key in staticProps){
				add.call(child, key, staticProps[key]);
			}
		}

		return child;
	}
	/**
	 * Add a property to current object
	 * @param {string} key
	 * @param {object|string} value
	 */
	function add(key, value){
		this.private[key] = value;

		Object.defineProperty(this, key, {
			get: function(){return this.private[key];},
			set: function(newVal){
				var event = new Event(key + ':change');
				console.log('The value has been changed from ' + this.private[key] + ' to ' +newVal);
				this.private[key] = newVal;
				document.dispatchEvent(event);
			},
			enumerable: true,
  			configurable: true
		})
	}

	/**
	 * Publisher Class
	 * Publisher is a data model.
	 * When Publisher detect a change in state it notify it all the Subscriber with Custom Javascript Event
	 */

	var pub = Chakmak.Publisher = function Publisher(){
		Object.defineProperty(this, 'private', {
			value: {},
			writable: true,
			enumerable: false,
			configurable: true
		})
	};

	// Publisher public method
	// Publisher prototype definition

	pub.prototype.addProperty = add;

	/**
	 * Subscriber Class
	 * Subscriber is a View Object.
	 * Subscriber will be subscribed to one or many Publisher.
	 * When an publisher notify a change in state subcriber will execute its render method to update the view
	 *
	 */
	var sub = Chakmak.Subscriber = function Subscriber(){
		Object.defineProperty(this, 'private', {
			value: {},
			writable: true,
			enumerable: false,
			configurable: true
		})
	};

	// Subscriber public method
	// Subscriber prototype definition

	sub.prototype.subscribe = function(publisher, event){
		var _this = this;
		this.publisher = publisher;
		this.render();
		document.addEventListener(event, _this.render.bind(_this));
	}

	// Adding a static method to Pub and Sub classes
	// This will create a new instance of a class without calling end user new explicitly
	Chakmak.Publisher.create = Chakmak.Subscriber.create = create;

}));
<commit_msg>UPDATE: update to version 0.0.2<commit_after>/**
 * **************************************************
 * **************************************************
 * **************************************************
 * ******************** CHAKMAK  *********************
 * **************************************************
 * **************************************************
 */

/**
 * @author Upendra Dev Singh
 * @description A small pubsub utility
 *
 * MIT Licence
 */

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

;(function(definition){
	var	hasDefine = typeof define === 'function' && define.amd,			// AMD
		hasExports = typeof module !== 'undefined' && module.exports;	// Commonjs

	// Setup the root object, `window` (`self`) in the browser, or `global` in the node.js server.
    // We use `self` instead of `window` for `WebWorker` support.

    var root = (typeof self == 'object' && self.self === self && self) || (typeof global == 'object' && global.global === global && global);

	if(hasDefine){
		define(['exports'], function(exports) {
		    // Export global even in AMD case
			// Avoid duplicate bu default

		    root.Chakmak = definition(exports);
		});
	// node.js or commonjs
	}else if(hasExports){
		definition(exports);
	// Finally, as browser global
	}else{
		definition(root);
	}
}(function(root){

	var Chakmak = {};

	root.Chakmak = Chakmak;

	Chakmak.version = '0.0.2';

	/**
	 * Creates an object with given properties and methods
	 *
	 *
	 * @param  {Object} staticProps Properties to be added to newly constructed object
	 * @param  {Object} methods Functions to be added to newly constructed object prototype
	 * @return {Object} Return an new object
	 */
	function create(staticProps, methods){
		var Parent = this;	// Publisher or Subscriber Object
		var child;			// New Object to be created

		// A child class constructor inheritted from Parent class
		function Child(){
			return Parent.call(this);
		}

		// Inherit Child Class from current parent class
		Child.prototype = Object.create(Parent.prototype);
		Child.prototype.constructor = Child;

		// Copy all the custom method to Child class prototype
		if(typeof methods === 'object'){
			for(var key in methods){
				Child.prototype[key] = methods[key];
			}
		}

		// maintain a copy of parent class into new child class
		Child.__super__ = Parent.prototype;

		child = new Child();

		if(typeof staticProps === 'object'){
			for(var key in staticProps){
				add.call(child, key, staticProps[key]);
			}
		}

		return child;
	}
	/**
	 * Add a property to current object
	 * @param {string} key
	 * @param {object|string} value
	 */
	function add(key, value){
		this.private[key] = value;

		Object.defineProperty(this, key, {
			get: function(){return this.private[key];},
			set: function(newVal){
				var event = new Event(key + ':change');
				console.log('The value has been changed from ' + this.private[key] + ' to ' +newVal);
				this.private[key] = newVal;
				document.dispatchEvent(event);
			},
			enumerable: true,
  			configurable: true
		})
	}

	/**
	 * Publisher Class
	 * Publisher is a data model.
	 * When Publisher detect a change in state it notify it all the Subscriber with Custom Javascript Event
	 */

	var pub = Chakmak.Publisher = function Publisher(){
		Object.defineProperty(this, 'private', {
			value: {},
			writable: true,
			enumerable: false,
			configurable: true
		})
	};

	// Publisher public method
	// Publisher prototype definition

	pub.prototype.addProperty = add;

	/**
	 * Subscriber Class
	 * Subscriber is a View Object.
	 * Subscriber will be subscribed to one or many Publisher.
	 * When an publisher notify a change in state subcriber will execute its render method to update the view
	 *
	 */
	var sub = Chakmak.Subscriber = function Subscriber(){
		Object.defineProperty(this, 'private', {
			value: {},
			writable: true,
			enumerable: false,
			configurable: true
		})
	};

	// Subscriber public method
	// Subscriber prototype definition

	sub.prototype.subscribe = function(publisher, event){
		var _this = this;
		this.publisher = publisher;
		this.render();
		document.addEventListener(event, _this.render.bind(_this));
	}

	// Adding a static method to Pub and Sub classes
	// This will create a new instance of a class without calling end user new explicitly
	Chakmak.Publisher.create = Chakmak.Subscriber.create = create;

}));
<|endoftext|>


<commit_before>/* eslint node/no-deprecated-api: 1 */
import config from '../config'
import crypto from 'crypto'
import externalFunctions from './functions'
import fs from 'fs'
import path from 'path'
import requestOrigins from '@twreporter/core/lib/constants/request-origins'
import template from 'lodash/template'
import url from 'url'
import util from 'util'
import webpackAssets from '../webpack-assets.json'

function generateRuntimeCaching(runtimeCaching) {
  return runtimeCaching.reduce(function(prev, curr) {
    let line
    if (curr.default) {
      line = util.format('\ntoolbox.router.default = toolbox.%s;', curr.default)
    } else {
      let urlPattern = curr.urlPattern
      if (typeof urlPattern === 'string') {
        urlPattern = JSON.stringify(urlPattern)
      }

      if (!(urlPattern instanceof RegExp || typeof urlPattern === 'string')) {
        throw new Error('runtimeCaching.urlPattern must be a string or RegExp')
      }

      line = util.format(
        '\ntoolbox.router.%s(%s, %s, %s);',
        // Default to setting up a 'get' handler.
        curr.method || 'get',
        // urlPattern might be a String or a RegExp. sw-toolbox supports both.
        urlPattern,
        // If curr.handler is a string, then assume it's the name of one
        // of the built-in sw-toolbox strategies.
        // E.g. 'networkFirst' -> toolbox.networkFirst
        // If curr.handler is something else (like a function), then just
        // include its body inline.
        (typeof curr.handler === 'string' ? 'toolbox.' : '') + curr.handler,
        // Default to no options.
        JSON.stringify(curr.options)
      )
    }

    return prev + line
  }, '')
}

const releaseBranch = config.releaseBranch
const origin = url.parse(
  requestOrigins.forClientSideRendering[releaseBranch].api
)

const apiURLPrefix = `${origin.protocol}//${origin.hostname}(:${origin.port})?`
const hash = crypto
  .createHash('sha1')
  .update(JSON.stringify(webpackAssets))
  .digest('hex')
const cacheName = 'sw-precache-twreporter-' + hash
const staticFilesToCache = [
  webpackAssets.javascripts.main,
  webpackAssets.javascripts.manifest,
  ...webpackAssets.javascripts.vendors,
  ...webpackAssets.javascripts.chunks,
  ...webpackAssets.stylesheets,
  '/',
  '/sw-fallback-page',
]
const swFilePath = path.resolve(__dirname, '../sw.js')
const swTemplatePath = './service-worker.tmpl'

const fallback = '/sw-fallback-page'
const pagePatternToCache = [
  /^\/(a|topics|tags|category|categories)\//,
  /^\/$/,
  /^\/photography/,
]

const tmpl = fs.readFileSync(path.resolve(__dirname, swTemplatePath), 'utf8')
const swToolBoxCode = fs
  .readFileSync(require.resolve('sw-toolbox/sw-toolbox.js'), 'utf8')
  .replace('//# sourceMappingURL=sw-toolbox.js.map', '')
const param = {
  cacheName,
  staticFilesToCache: JSON.stringify(staticFilesToCache),
  fallbackPage: fallback,
  pagePatternToCache: JSON.stringify(
    pagePatternToCache.map(regex => {
      return regex.source
    })
  ),
  externalFunctions,
  swToolBoxCode: swToolBoxCode,
  runtimeCaching: generateRuntimeCaching([
    {
      urlPattern: new RegExp(apiURLPrefix + '/v1/posts'),
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'posts-cache',
          maxEntries: 50,
        },
      },
    },
    {
      urlPattern: new RegExp(apiURLPrefix + '/v1/topics'),
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'topics-cache',
          maxEntries: 10,
        },
      },
    },
    {
      urlPattern: new RegExp(apiURLPrefix + '/v1/index_page(_categories)?'),
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'index-page-cache',
        },
      },
    },
  ]),
}

const populatedTmpl = template(tmpl)(param)

fs.writeFileSync(swFilePath, populatedTmpl)
<commit_msg>refactor: update service-worker-generator.js<commit_after>/* eslint node/no-deprecated-api: 1 */
import config from '../config'
import crypto from 'crypto'
import externalFunctions from './functions'
import fs from 'fs'
import path from 'path'
import requestOrigins from '@twreporter/core/lib/constants/request-origins'
import template from 'lodash/template'
import url from 'url'
import util from 'util'
import webpackAssets from '../webpack-assets.json'

function generateRuntimeCaching(runtimeCaching) {
  return runtimeCaching.reduce(function(prev, curr) {
    let line
    if (curr.default) {
      line = util.format('\ntoolbox.router.default = toolbox.%s;', curr.default)
    } else {
      let urlPattern = curr.urlPattern
      if (typeof urlPattern === 'string') {
        urlPattern = JSON.stringify(urlPattern)
      }

      if (!(urlPattern instanceof RegExp || typeof urlPattern === 'string')) {
        throw new Error('runtimeCaching.urlPattern must be a string or RegExp')
      }

      line = util.format(
        '\ntoolbox.router.%s(%s, %s, %s);',
        // Default to setting up a 'get' handler.
        curr.method || 'get',
        // urlPattern might be a String or a RegExp. sw-toolbox supports both.
        urlPattern,
        // If curr.handler is a string, then assume it's the name of one
        // of the built-in sw-toolbox strategies.
        // E.g. 'networkFirst' -> toolbox.networkFirst
        // If curr.handler is something else (like a function), then just
        // include its body inline.
        (typeof curr.handler === 'string' ? 'toolbox.' : '') + curr.handler,
        // Default to no options.
        JSON.stringify(curr.options)
      )
    }

    return prev + line
  }, '')
}

const releaseBranch = config.releaseBranch
const origin = url.parse(
  requestOrigins.forClientSideRendering[releaseBranch].api
)

const apiURLPrefix = `${origin.protocol}//${origin.hostname}(:${origin.port})?`
const hash = crypto
  .createHash('sha1')
  .update(JSON.stringify(webpackAssets))
  .digest('hex')
const cacheName = 'sw-precache-twreporter-' + hash
const staticFilesToCache = [
  webpackAssets.javascripts.main,
  webpackAssets.javascripts.manifest,
  ...webpackAssets.javascripts.vendors,
  ...webpackAssets.javascripts.chunks,
  ...webpackAssets.stylesheets,
  '/',
  '/sw-fallback-page',
]
const swFilePath = path.resolve(__dirname, '../sw.js')
const swTemplatePath = './service-worker.tmpl'

const fallback = '/sw-fallback-page'
const pagePatternToCache = [
  /^\/(a|topics|tags|category|categories)\//,
  /^\/$/,
  /^\/photography/,
]

const tmpl = fs.readFileSync(path.resolve(__dirname, swTemplatePath), 'utf8')
const swToolBoxCode = fs
  .readFileSync(require.resolve('sw-toolbox/sw-toolbox.js'), 'utf8')
  .replace('//# sourceMappingURL=sw-toolbox.js.map', '')
const param = {
  cacheName,
  staticFilesToCache: JSON.stringify(staticFilesToCache),
  fallbackPage: fallback,
  pagePatternToCache: JSON.stringify(
    pagePatternToCache.map(regex => {
      return regex.source
    })
  ),
  externalFunctions,
  swToolBoxCode: swToolBoxCode,
  runtimeCaching: generateRuntimeCaching([
    {
      urlPattern: new RegExp(apiURLPrefix + '/v2/posts'),
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'posts-cache',
          maxEntries: 50,
        },
      },
    },
    {
      urlPattern: new RegExp(apiURLPrefix + '/v2/topics'),
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'topics-cache',
          maxEntries: 10,
        },
      },
    },
    {
      urlPattern: new RegExp(apiURLPrefix + '/v2/index_page'),
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'index-page-cache',
        },
      },
    },
  ]),
}

const populatedTmpl = template(tmpl)(param)

fs.writeFileSync(swFilePath, populatedTmpl)
<|endoftext|>


<commit_before>const Settings = require('settings-sharelatex')
const rclient = require('@overleaf/redis-wrapper').createClient(
  Settings.redis.documentupdater
)
let keys = Settings.redis.documentupdater.key_schema
const async = require('async')
const RedisManager = require('./app/js/RedisManager')

const getKeysFromNode = function (node, pattern, callback) {
  let cursor = 0 // redis iterator
  const keySet = {} // use hash to avoid duplicate results
  // scan over all keys looking for pattern
  const doIteration = () =>
    node.scan(cursor, 'MATCH', pattern, 'COUNT', 1000, function(error, reply) {
      if (error) {
        return callback(error)
      }
      ;[cursor, keys] = reply
      console.log('SCAN', keys.length)
      for (const key of keys) {
        keySet[key] = true
      }
      if (cursor==='0') {
        // note redis returns string result not numeric
        return callback(null, Object.keys(keySet))
      } else {
        return doIteration()
      }
    })
  return doIteration()
}

const getKeys = function (pattern, callback) {
  const nodes = (typeof rclient.nodes === 'function'
    ? rclient.nodes('master')
    : undefined) || [rclient]
  console.log('GOT NODES', nodes.length)
  const doKeyLookupForNode = (node, cb) => getKeysFromNode(node, pattern, cb)
  return async.concatSeries(nodes, doKeyLookupForNode, callback)
}

const expireDocOps = (callback) =>
  // eslint-disable-next-line handle-callback-err
  getKeys(keys.docOps({ doc_id: '*' }), (error, keys) =>
    async.mapSeries(
      keys,
      function (key, cb) {
        console.log(`EXPIRE ${key} ${RedisManager.DOC_OPS_TTL}`)
        return rclient.expire(key, RedisManager.DOC_OPS_TTL, cb)
      },
      callback
    )
  )

setTimeout(
  () =>
    //  Give redis a chance to connect
    expireDocOps(function (error) {
      if (error) {
        throw error
      }
      return process.exit()
    }),
  1000
)
<commit_msg>Run format:fix<commit_after>const Settings = require('settings-sharelatex')
const rclient = require('@overleaf/redis-wrapper').createClient(
  Settings.redis.documentupdater
)
let keys = Settings.redis.documentupdater.key_schema
const async = require('async')
const RedisManager = require('./app/js/RedisManager')

const getKeysFromNode = function (node, pattern, callback) {
  let cursor = 0 // redis iterator
  const keySet = {} // use hash to avoid duplicate results
  // scan over all keys looking for pattern
  const doIteration = () =>
    node.scan(cursor, 'MATCH', pattern, 'COUNT', 1000, function (error, reply) {
      if (error) {
        return callback(error)
      }
      ;[cursor, keys] = reply
      console.log('SCAN', keys.length)
      for (const key of keys) {
        keySet[key] = true
      }
      if (cursor === '0') {
        // note redis returns string result not numeric
        return callback(null, Object.keys(keySet))
      } else {
        return doIteration()
      }
    })
  return doIteration()
}

const getKeys = function (pattern, callback) {
  const nodes = (typeof rclient.nodes === 'function'
    ? rclient.nodes('master')
    : undefined) || [rclient]
  console.log('GOT NODES', nodes.length)
  const doKeyLookupForNode = (node, cb) => getKeysFromNode(node, pattern, cb)
  return async.concatSeries(nodes, doKeyLookupForNode, callback)
}

const expireDocOps = (callback) =>
  // eslint-disable-next-line handle-callback-err
  getKeys(keys.docOps({ doc_id: '*' }), (error, keys) =>
    async.mapSeries(
      keys,
      function (key, cb) {
        console.log(`EXPIRE ${key} ${RedisManager.DOC_OPS_TTL}`)
        return rclient.expire(key, RedisManager.DOC_OPS_TTL, cb)
      },
      callback
    )
  )

setTimeout(
  () =>
    //  Give redis a chance to connect
    expireDocOps(function (error) {
      if (error) {
        throw error
      }
      return process.exit()
    }),
  1000
)
<|endoftext|>


<commit_before>'use strict';

/**
 * @file Defines the provider settings.
 *
 * Will set the path to Mongo, and applications id
 * Most of the configuration can be done using system environment variables.
 */

// Load environment variables from .env file
var dotenv = require('dotenv');
dotenv.load();

// node_env can either be "development" or "production"
var node_env = process.env.NODE_ENV || "development";
var default_port = 8000;
if(node_env === "production") {
  default_port = 80;
}

var mandatories = ['GMAIL_API_ID', 'GMAIL_API_SECRET', 'ANYFETCH_API_ID', 'ANYFETCH_API_SECRET'];
mandatories.forEach(function(mandatory) {
  if(!process.env[mandatory]) {
    console.log(mandatory + " missing, the provider may fail.");
  }
});

// Exports configuration
module.exports = {
  env: node_env,
  port: process.env.PORT || default_port,
  maxSize: process.env.MAX_SIZE || 50,

  mongoUrl: process.env.MONGO_URL || process.env.MONGOLAB_URI,
  redisUrl: process.env.REDIS_URL || process.env.REDISCLOUD_URL,

  maxConcurrency: process.env.GMAIL_MAX_CONCURRENCY || 1,

  googleId: process.env.GMAIL_API_ID,
  googleSecret: process.env.GMAIL_API_SECRET,

  appId: process.env.ANYFETCH_API_ID,
  appSecret: process.env.ANYFETCH_API_SECRET,

  providerUrl: process.env.PROVIDER_URL,

  testRefreshToken: process.env.GMAIL_TEST_REFRESH_TOKEN,
  testAccount: process.env.GMAIL_TEST_ACCOUNT_NAME,
  imapTimeout: process.env.IMAP_TIMEOUT || 20000
};
<commit_msg>Fix concurrency at 10<commit_after>'use strict';

/**
 * @file Defines the provider settings.
 *
 * Will set the path to Mongo, and applications id
 * Most of the configuration can be done using system environment variables.
 */

// Load environment variables from .env file
var dotenv = require('dotenv');
dotenv.load();

// node_env can either be "development" or "production"
var node_env = process.env.NODE_ENV || "development";
var default_port = 8000;
if(node_env === "production") {
  default_port = 80;
}

var mandatories = ['GMAIL_API_ID', 'GMAIL_API_SECRET', 'ANYFETCH_API_ID', 'ANYFETCH_API_SECRET'];
mandatories.forEach(function(mandatory) {
  if(!process.env[mandatory]) {
    console.log(mandatory + " missing, the provider may fail.");
  }
});

// Exports configuration
module.exports = {
  env: node_env,
  port: process.env.PORT || default_port,
  maxSize: process.env.MAX_SIZE || 50,

  mongoUrl: process.env.MONGO_URL || process.env.MONGOLAB_URI,
  redisUrl: process.env.REDIS_URL || process.env.REDISCLOUD_URL,

  maxConcurrency: process.env.GMAIL_MAX_CONCURRENCY || 10,

  googleId: process.env.GMAIL_API_ID,
  googleSecret: process.env.GMAIL_API_SECRET,

  appId: process.env.ANYFETCH_API_ID,
  appSecret: process.env.ANYFETCH_API_SECRET,

  providerUrl: process.env.PROVIDER_URL,

  testRefreshToken: process.env.GMAIL_TEST_REFRESH_TOKEN,
  testAccount: process.env.GMAIL_TEST_ACCOUNT_NAME,
  imapTimeout: process.env.IMAP_TIMEOUT || 20000
};
<|endoftext|>


<commit_before>/**
 * @file Defines the hydrater settings.
 */

// node_env can either be "development" or "production"
var nodeEnv = process.env.NODE_ENV || "development";
var defaultPort = 8000;

// Number of pdf instance to run simultaneously per cluster
var defaultConcurrency = 8;

if(nodeEnv === "production") {
  defaultPort = 80;
}

// Exports configuration
module.exports = {
  env: nodeEnv,
  port: process.env.PORT || defaultPort,
  concurrency: process.env.FILECLEANER_CONCURRENCY || defaultConcurrency,
  appName: process.env.APP_NAME || "filecleaner-hydrater",
  redisUrl: process.env.REDIS_URL,

  opbeat: {
    organizationId: process.env.OPBEAT_ORGANIZATION_ID,
    appId: process.env.OPBEAT_APP_ID,
    secretToken: process.env.OPBEAT_SECRET_TOKEN
  }
};
<commit_msg>Change env vars<commit_after>/**
 * @file Defines the hydrater settings.
 */

// node_env can either be "development" or "production"
var nodeEnv = process.env.NODE_ENV || "development";
var defaultPort = 8000;

// Number of pdf instance to run simultaneously per cluster
var defaultConcurrency = 8;

if(nodeEnv === "production") {
  defaultPort = 80;
}

// Exports configuration
module.exports = {
  env: nodeEnv,
  port: process.env.PORT || defaultPort,

  concurrency: process.env.CONCURRENCY || defaultConcurrency,
  tasksPerProcess: process.env.TASKS_PER_PROCESS,

  appName: process.env.APP_NAME || "filecleaner-hydrater",
  redisUrl: process.env.REDIS_URL,

  opbeat: {
    organizationId: process.env.OPBEAT_ORGANIZATION_ID,
    appId: process.env.OPBEAT_APP_ID,
    secretToken: process.env.OPBEAT_SECRET_TOKEN
  }
};
<|endoftext|>


<commit_before>define([],function() {

	/**
	 * Layout constructor
	 * @constructor
	 */
	function Layout() {
		this._nodes = null;
		this._linkMap = null;
		this._nodeMap = null;
		this._labelMap = null;
		this._duration = 250;
		this._easing = 'ease-in-out';
	}

	/**
	 * Gets/sets the duration of the layout animation
	 * @param duration - the duration of the layout animation in milliseconds.  (default = 250ms)
	 * @returns {Layout} if duration param is defined, {Layout._duration} otherwise
	 */
	Layout.prototype.duration = function(duration) {
		if (duration) {
			this._duration = duration;
		} else {
			return this._duration;
		}
		return this;
	};

	/**
	 * Gets/sets the easing of the layout animation
	 * @param easing - the easing of the layout animation in milliseconds.  (default = 'ease-in-out')
	 * @returns {Layout} if easing param is defined, {Layout._easing} otherwise
	 */
	Layout.prototype.easing = function(easing) {
		if (easing) {
			this._easing = easing;
		}	 else {
			return this._easing;
		}
		return this;
	};

	/**
	 * Gets/sets the nodes of the layout.   Set from the graph
	 * @param nodes - the set of nodes defined in the corresponding graph
	 * @returns {Layout} if nodes param is defined, {Layout._nodes} otherwise
	 */
	Layout.prototype.nodes = function(nodes) {
		if (nodes) {
			this._nodes = nodes;
		} else {
			return this._nodes;
		}
		return this;
	};

	/**
	 * Gets/sets the link map of the layout.   Set from the graph
	 * @param linkMap - a map from node index to a set of lines (path objects) that contain that node
	 * @returns {Layout} if linkMap param is defined, {Layout._linkMap} otherwise
	 */
	Layout.prototype.linkMap = function(linkMap) {
		if (linkMap) {
			this._linkMap = linkMap;
		} else {
			return this._linkMap;
		}
		return this;
	};

	/**
	 * Gets/sets the node map of the layout.   Set from the graph
	 * @param nodeMap - a map from node index to a circle (path object)
	 * @returns {Layout} if nodeMap param is defined, {Layout._nodeMap} otherwise
	 */
	Layout.prototype.nodeMap = function(nodeMap) {
		if (nodeMap) {
			this._nodeMap = nodeMap;
		} else {
			return this._nodeMap;
		}
		return this;
	};

	/**
	 * Gets/sets the label of the layout.   Set from the graph
	 * @param labelMap - a map from node index to a text object (path object)
	 * @returns {Layout} if labelMap param is defined, {Layout._labelMap} otherwise
	 */
	Layout.prototype.labelMap = function(labelMap) {
		if (labelMap) {
			this._labelMap = labelMap;
		} else {
			return this._labelMap;
		}
		return this;
	};

	/**
	 * Sets the position of a node and all attached links and labels without animation
	 * @param node - the node object being positioned
	 * @param x - the new x position for the node
	 * @param y - the new y position for the node
	 * @private
	 */
	Layout.prototype._setNodePositionImmediate = function(node,x,y) {
		this._setNodePosition(node,x,y,true);
	};

	/**
	 * Sets the position of a node by animating from it's old position to it's new one
	 * @param node - the node being repositioned
	 * @param x - the new x position of the node
	 * @param y - the new y position of the node
	 * @param bImmediate - if true, sets without animation.
	 * @private
	 */
	Layout.prototype._setNodePosition = function(node,x,y,bImmediate) {
		// Update the node render object
		var circle = this._nodeMap[node.index];
		if (bImmediate!==true) {
			circle.tweenAttr({
				x: x,
				y: y
			}, {
				duration: this._duration,
				easing: this._easing
			});
		} else {
			circle.x = x;
			circle.y = y;
		}

		// Update the label render object
		var label = this._labelMap[node.index];
		if (label) {
			var labelPos = this.layoutLabel(x,y,node.radius);
			if (bImmediate!==true) {
				label.tweenAttr(labelPos, {
					duration: this._duration,
					easing: this._easing
				});
			} else {
				for (var prop in labelPos) {
					if (labelPos.hasOwnProperty(prop)) {
						label[prop] = labelPos[prop];
					}
				}
			}
		}

		// Update the link render object
		var that = this;
		this._linkMap[node.index].forEach(function(link) {
			var linkObjKey = null;
			if (link.source.index === node.index) {
				linkObjKey = 'source';
			} else {
				linkObjKey = 'target';
			}
			if (bImmediate!==true) {
				link.tweenObj(linkObjKey, {
					x: x,
					y: y
				}, {
					duration: that._duration,
					easing: that._easing
				});
			} else {
				link[linkObjKey].x = x;
				link[linkObjKey].y = y;
			}
		});
	};

	/**
	 * Default layout routine.   Should be overriden by subclasses.
	 * @param w - the width of the canvas being rendered to
	 * @param h - the height of the canvas being rendered to
	 * @returns {Layout}
	 */
	Layout.prototype.layout = function(w,h) {
		var x = 0;
		var y = 0;
		var maxRadiusRow = 0;
		var that = this;
		this._nodes.forEach(function(node) {

			if (x === 0) {
				x += node.radius;
			}
			if (y === 0) {
				y += node.radius;
			}

			that._setNodePositionImmediate(node,x,y);

			maxRadiusRow = Math.max(maxRadiusRow,node.radius);

			x+= node.radius + 40;
			if (x > w) {
				x = 0;
				y += maxRadiusRow + 40;
				maxRadiusRow = 0;
			}
		});
		return this;
	};

	/**
	 * Sets the label position for a node
	 * @param nodeX - the x position of the node
	 * @param nodeY - the y position of the node
	 * @param radius - the radius of the node
	 * @returns {{x: x position of the label, y: y position of the label}}
	 */
	Layout.prototype.layoutLabel = function(nodeX,nodeY,radius) {
		return {
			x: nodeX + radius + 5,
			y: nodeY + radius + 5
		};
	};
	return Layout;
});<commit_msg>Make default layout vertical instead of horizontal<commit_after>define([],function() {

	/**
	 * Layout constructor
	 * @constructor
	 */
	function Layout() {
		this._nodes = null;
		this._linkMap = null;
		this._nodeMap = null;
		this._labelMap = null;
		this._duration = 250;
		this._easing = 'ease-in-out';
	}

	/**
	 * Gets/sets the duration of the layout animation
	 * @param duration - the duration of the layout animation in milliseconds.  (default = 250ms)
	 * @returns {Layout} if duration param is defined, {Layout._duration} otherwise
	 */
	Layout.prototype.duration = function(duration) {
		if (duration) {
			this._duration = duration;
		} else {
			return this._duration;
		}
		return this;
	};

	/**
	 * Gets/sets the easing of the layout animation
	 * @param easing - the easing of the layout animation in milliseconds.  (default = 'ease-in-out')
	 * @returns {Layout} if easing param is defined, {Layout._easing} otherwise
	 */
	Layout.prototype.easing = function(easing) {
		if (easing) {
			this._easing = easing;
		}	 else {
			return this._easing;
		}
		return this;
	};

	/**
	 * Gets/sets the nodes of the layout.   Set from the graph
	 * @param nodes - the set of nodes defined in the corresponding graph
	 * @returns {Layout} if nodes param is defined, {Layout._nodes} otherwise
	 */
	Layout.prototype.nodes = function(nodes) {
		if (nodes) {
			this._nodes = nodes;
		} else {
			return this._nodes;
		}
		return this;
	};

	/**
	 * Gets/sets the link map of the layout.   Set from the graph
	 * @param linkMap - a map from node index to a set of lines (path objects) that contain that node
	 * @returns {Layout} if linkMap param is defined, {Layout._linkMap} otherwise
	 */
	Layout.prototype.linkMap = function(linkMap) {
		if (linkMap) {
			this._linkMap = linkMap;
		} else {
			return this._linkMap;
		}
		return this;
	};

	/**
	 * Gets/sets the node map of the layout.   Set from the graph
	 * @param nodeMap - a map from node index to a circle (path object)
	 * @returns {Layout} if nodeMap param is defined, {Layout._nodeMap} otherwise
	 */
	Layout.prototype.nodeMap = function(nodeMap) {
		if (nodeMap) {
			this._nodeMap = nodeMap;
		} else {
			return this._nodeMap;
		}
		return this;
	};

	/**
	 * Gets/sets the label of the layout.   Set from the graph
	 * @param labelMap - a map from node index to a text object (path object)
	 * @returns {Layout} if labelMap param is defined, {Layout._labelMap} otherwise
	 */
	Layout.prototype.labelMap = function(labelMap) {
		if (labelMap) {
			this._labelMap = labelMap;
		} else {
			return this._labelMap;
		}
		return this;
	};

	/**
	 * Sets the position of a node and all attached links and labels without animation
	 * @param node - the node object being positioned
	 * @param x - the new x position for the node
	 * @param y - the new y position for the node
	 * @private
	 */
	Layout.prototype._setNodePositionImmediate = function(node,x,y) {
		this._setNodePosition(node,x,y,true);
	};

	/**
	 * Sets the position of a node by animating from it's old position to it's new one
	 * @param node - the node being repositioned
	 * @param x - the new x position of the node
	 * @param y - the new y position of the node
	 * @param bImmediate - if true, sets without animation.
	 * @private
	 */
	Layout.prototype._setNodePosition = function(node,x,y,bImmediate) {
		// Update the node render object
		var circle = this._nodeMap[node.index];
		if (bImmediate!==true) {
			circle.tweenAttr({
				x: x,
				y: y
			}, {
				duration: this._duration,
				easing: this._easing
			});
		} else {
			circle.x = x;
			circle.y = y;
		}

		// Update the label render object
		var label = this._labelMap[node.index];
		if (label) {
			var labelPos = this.layoutLabel(x,y,node.radius);
			if (bImmediate!==true) {
				label.tweenAttr(labelPos, {
					duration: this._duration,
					easing: this._easing
				});
			} else {
				for (var prop in labelPos) {
					if (labelPos.hasOwnProperty(prop)) {
						label[prop] = labelPos[prop];
					}
				}
			}
		}

		// Update the link render object
		var that = this;
		this._linkMap[node.index].forEach(function(link) {
			var linkObjKey = null;
			if (link.source.index === node.index) {
				linkObjKey = 'source';
			} else {
				linkObjKey = 'target';
			}
			if (bImmediate!==true) {
				link.tweenObj(linkObjKey, {
					x: x,
					y: y
				}, {
					duration: that._duration,
					easing: that._easing
				});
			} else {
				link[linkObjKey].x = x;
				link[linkObjKey].y = y;
			}
		});
	};

	/**
	 * Default layout routine.   Should be overriden by subclasses.
	 * @param w - the width of the canvas being rendered to
	 * @param h - the height of the canvas being rendered to
	 * @returns {Layout}
	 */
	Layout.prototype.layout = function(w,h) {
		var x = 0;
		var y = 0;
		var maxRadiusCol = 0;
		var that = this;
		this._nodes.forEach(function(node) {

			if (y === 0) {
				y += node.radius;
			}
			if (x === 0) {
				x += node.radius;
			}

			that._setNodePositionImmediate(node,x,y);

			maxRadiusCol = Math.max(maxRadiusCol,node.radius);

			y+= node.radius + 40;
			if (y > h) {
				y = 0;
				x += maxRadiusCol + 40;
				maxRadiusCol = 0;
			}
		});
		return this;
	};

	/**
	 * Sets the label position for a node
	 * @param nodeX - the x position of the node
	 * @param nodeY - the y position of the node
	 * @param radius - the radius of the node
	 * @returns {{x: x position of the label, y: y position of the label}}
	 */
	Layout.prototype.layoutLabel = function(nodeX,nodeY,radius) {
		return {
			x: nodeX + radius + 5,
			y: nodeY + radius + 5
		};
	};
	return Layout;
});<|endoftext|>


<commit_before>'use strict';

module.exports = function (req, res) {
    var timestamp = {
        unix: null,
        natural: null
    };

    var param = decodeURIComponent(req.url.substring(1));
    var num = Number(param);
    var re = /^([a-z]+) ([0-9]+), ([0-9]+)$/i;

    if ((num || num === 0) && Number.isSafeInteger(num)) {
        var date = new Date(num);
        var str = month[date.getUTCMonth()] + " " + date.getUTCDate() + ", " + date.getUTCFullYear();
        timestamp.unix = date.valueOf();
        timestamp.natural = str;
    } else if (re.test(param)) {
        var date = new Date(0);
        var array = re.exec(param);
        var monthVal = monthToInt(array[1]);
        if(monthVal !== -1) {
            date.setUTCFullYear(array[3], monthVal, array[2]);
            var str = month[date.getUTCMonth()] + " " + date.getUTCDate() + ", " + date.getUTCFullYear();

            timestamp.unix = date.valueOf();
            timestamp.natural = str;
        }
    };

    res.json(timestamp);
};

var month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

function monthToInt (str) {
    for(var i = 0; i < month.length; i++){
        if(str.toUpperCase() == month[i].toUpperCase()) {
            return i;
        }
    }
    return -1;
}<commit_msg>add dateToString function<commit_after>'use strict';

module.exports = function (req, res) {
    var timestamp = {
        unix: null,
        natural: null
    };

    var param = decodeURIComponent(req.url.substring(1));
    var num = Number(param);
    var re = /^([a-z]+) ([0-9]+), ([0-9]+)$/i;

    if ((num || num === 0) && Number.isSafeInteger(num)) {
        var date = new Date(num);

        timestamp.unix = date.valueOf();
        timestamp.natural = dateToString(date);
    } else if (re.test(param)) {
        var date = new Date(0);
        var array = re.exec(param);
        var monthVal = monthToInt(array[1]);

        if(monthVal !== -1) {
            date.setUTCFullYear(array[3], monthVal, array[2]);

            timestamp.unix = date.valueOf();
            timestamp.natural = dateToString(date);
        }
    }

    res.json(timestamp);
};

var month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

function monthToInt (str) {
    for(var i = 0; i < month.length; i++){
        if(str.toUpperCase() == month[i].toUpperCase()) {
            return i;
        }
    }
    return -1;
}

function dateToString(date) {
    return month[date.getUTCMonth()] + " " + date.getUTCDate() + ", " + date.getUTCFullYear();
}
<|endoftext|>


<commit_before>define(function(require, exports, module) {
  "use strict";

  var LocalStorageHelper = function() {
  }

  LocalStorageHelper.prototype = {
    prefix: 'justwriteitdown-',
    get: function(key) {
      return JSON.parse(localStorage.getItem(this.prefix + key));
    },
    set: function(key, value) {
      return localStorage.setItem(this.prefix + key, JSON.stringify(value));
    },
    delete: function(key) {
      return localStorage.removeItem(this.prefix + key);
    },
    getItemsByPrefix: function(key) {
      var reg = new RegExp('justwriteitdown-(' + key + '-.+)'),
          items = [],
          i,
          matches;

      for (i in localStorage) {

        matches = i.match(reg);
        if (!matches) {
          continue;
        }

        if (matches[1] !== undefined) {
          items.push(this.get(matches[1]));
        }
      }

      return items;
    }
  }

  module.exports = LocalStorageHelper;
});<commit_msg>fixed some missing semis<commit_after>define(function(require, exports, module) {
  "use strict";

  var LocalStorageHelper = function() {
  };

  LocalStorageHelper.prototype = {
    prefix: 'justwriteitdown-',
    get: function(key) {
      return JSON.parse(localStorage.getItem(this.prefix + key));
    },
    set: function(key, value) {
      return localStorage.setItem(this.prefix + key, JSON.stringify(value));
    },
    delete: function(key) {
      return localStorage.removeItem(this.prefix + key);
    },
    getItemsByPrefix: function(key) {
      var reg = new RegExp('justwriteitdown-(' + key + '-.+)'),
          items = [],
          i,
          matches;

      for (i in localStorage) {

        matches = i.match(reg);
        if (!matches) {
          continue;
        }

        if (matches[1] !== undefined) {
          items.push(this.get(matches[1]));
        }
      }

      return items;
    }
  };

  module.exports = LocalStorageHelper;
});<|endoftext|>