<commit_before>function MarkdownConverter(markdownRenderer) {

    marked.setOptions({
        renderer: markdownRenderer,
        gfm: true,
        tables: true,
        breaks: true,
        pedantic: false,
        sanitize: false,
        smartLists: true,
        smartypants: false
    });

    this.convert = function(markdownTextarea, convertedTextarea) {
        var markdownText = markdownTextarea.value;
        var convertedText = marked(markdownText);

        if (convertedText.charAt(0) === '\n') {
            convertedText = convertedText.substring(1);
        }

        convertedTextarea.value = convertedText;
    };
};

var Util = new (function() {

    function indentOrUnindentSelectedLines(indent, markdownTextarea) {
        var selectionStart = markdownTextarea.selectionStart;
        var selectionEnd = markdownTextarea.selectionEnd;
        var firstLineIndex = markdownTextarea.value.substring(0, selectionStart).lastIndexOf('\n') + 1;

        if (firstLineIndex === -1) {
            firstLineIndex = 0;
        }

        var stringBeforeSelection = markdownTextarea.value.substring(0, firstLineIndex);
        var stringAfterSelection = markdownTextarea.value.substring(selectionEnd);
        var changedLines;
        var newSelectionIndex;

        if (indent) {
            newSelectionIndex = selectionStart + 4;
            changedLines = '    ' + markdownTextarea.value.substring(firstLineIndex, selectionEnd)
                    .replace(/\n/g, '\n    ');
        } else {
            var textToUnindent = markdownTextarea.value.substring(firstLineIndex, markdownTextarea.selectionEnd);
            newSelectionIndex = selectionStart + (textToUnindent.startsWith('    ') ? -4 : 0);
            changedLines = textToUnindent.replace(/^    /, '')
                    .replace(/\n    /g, '\n');
        }

        markdownTextarea.value = stringBeforeSelection + changedLines + stringAfterSelection;
        markdownTextarea.focus();
        markdownTextarea.selectionStart = newSelectionIndex;
        markdownTextarea.selectionEnd = markdownTextarea.value.lastIndexOf(stringAfterSelection);
    }

    this.indentSelectedLines = function(markdownTextarea) {
        indentOrUnindentSelectedLines(true, markdownTextarea);
    };

    this.unindentSelectedLines = function(markdownTextarea) {
        indentOrUnindentSelectedLines(false, markdownTextarea);
    };

    this.unescapeXML = function(text) {
        // split and join are used instead of replace since replace does not replace all occurences. For more
        // details see: http://stackoverflow.com/questions/1144783/how-to-replace-all-occurrences-of-a-string-in-javascript#1145525
        return text.split('<').join('<')
                .split('>').join('>')
                .split('"').join('"')
                .split(''').join("'")
                .split('&').join('&');
    };
})();
<commit_msg>Add license header to markdown-converter-util.js<commit_after>/**
 *    Copyright (c) 2000-2016 Liferay, Inc. All rights reserved.
 *
 *    This library is free software; you can redistribute it and/or modify it under
 *    the terms of the GNU Lesser General Public License as published by the Free
 *    Software Foundation; either version 2.1 of the License, or (at your option)
 *    any later version.
 *
 *    This library is distributed in the hope that it will be useful, but WITHOUT
 *    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *    FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 *    details.
 **/

function MarkdownConverter(markdownRenderer) {

    marked.setOptions({
        renderer: markdownRenderer,
        gfm: true,
        tables: true,
        breaks: true,
        pedantic: false,
        sanitize: false,
        smartLists: true,
        smartypants: false
    });

    this.convert = function(markdownTextarea, convertedTextarea) {
        var markdownText = markdownTextarea.value;
        var convertedText = marked(markdownText);

        if (convertedText.charAt(0) === '\n') {
            convertedText = convertedText.substring(1);
        }

        convertedTextarea.value = convertedText;
    };
};

var Util = new (function() {

    function indentOrUnindentSelectedLines(indent, markdownTextarea) {
        var selectionStart = markdownTextarea.selectionStart;
        var selectionEnd = markdownTextarea.selectionEnd;
        var firstLineIndex = markdownTextarea.value.substring(0, selectionStart).lastIndexOf('\n') + 1;

        if (firstLineIndex === -1) {
            firstLineIndex = 0;
        }

        var stringBeforeSelection = markdownTextarea.value.substring(0, firstLineIndex);
        var stringAfterSelection = markdownTextarea.value.substring(selectionEnd);
        var changedLines;
        var newSelectionIndex;

        if (indent) {
            newSelectionIndex = selectionStart + 4;
            changedLines = '    ' + markdownTextarea.value.substring(firstLineIndex, selectionEnd)
                    .replace(/\n/g, '\n    ');
        } else {
            var textToUnindent = markdownTextarea.value.substring(firstLineIndex, markdownTextarea.selectionEnd);
            newSelectionIndex = selectionStart + (textToUnindent.startsWith('    ') ? -4 : 0);
            changedLines = textToUnindent.replace(/^    /, '')
                    .replace(/\n    /g, '\n');
        }

        markdownTextarea.value = stringBeforeSelection + changedLines + stringAfterSelection;
        markdownTextarea.focus();
        markdownTextarea.selectionStart = newSelectionIndex;
        markdownTextarea.selectionEnd = markdownTextarea.value.lastIndexOf(stringAfterSelection);
    }

    this.indentSelectedLines = function(markdownTextarea) {
        indentOrUnindentSelectedLines(true, markdownTextarea);
    };

    this.unindentSelectedLines = function(markdownTextarea) {
        indentOrUnindentSelectedLines(false, markdownTextarea);
    };

    this.unescapeXML = function(text) {
        // split and join are used instead of replace since replace does not replace all occurences. For more
        // details see: http://stackoverflow.com/questions/1144783/how-to-replace-all-occurrences-of-a-string-in-javascript#1145525
        return text.split('<').join('<')
                .split('>').join('>')
                .split('"').join('"')
                .split(''').join("'")
                .split('&').join('&');
    };
})();
<|endoftext|>


<commit_before>/*
 Copyright 2014 matrix.org

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

'use strict';

angular.module('RecentsController', ['matrixService', 'eventHandlerService'])
.controller('RecentsController', ['$scope', 'matrixService', 'eventHandlerService', 'eventStreamService',
                               function($scope,  matrixService, eventHandlerService, eventStreamService) {
    $scope.rooms = {};

    // $scope of the parent where the recents component is included can override this value
    // in order to highlight a specific room in the list
    $scope.recentsSelectedRoomID;

    $scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) {
        var config = matrixService.config();
        if (event.state_key === config.user_id && event.content.membership === "invite") {
            console.log("Invited to room " + event.room_id);
            // FIXME push membership to top level key to match /im/sync
            event.membership = event.content.membership;
            // FIXME bodge a nicer name than the room ID for this invite.
            event.room_display_name = event.user_id + "'s room";
            $scope.rooms[event.room_id] = event;
        }
    });

    var refresh = function() {
        // List all rooms joined or been invited to
        matrixService.rooms(1, false).then(
            function(response) {
                var data = matrixService.assignRoomAliases(response.data.rooms);
                for (var i=0; i<data.length; i++) {
                    $scope.rooms[data[i].room_id] = data[i];

                    // Create a shortcut for the last message of this room
                    if (data[i].messages && data[i].messages.chunk && data[i].messages.chunk[0]) {
                        $scope.rooms[data[i].room_id].lastMsg = data[i].messages.chunk[0];
                    }
                }

                var presence = response.data.presence;
                for (var i = 0; i < presence.length; ++i) {
                    eventHandlerService.handleEvent(presence[i], false);
                }
            },
            function(error) {
                $scope.feedback = "Failure: " + error.data;
            }
        );
    };

    $scope.onInit = function() {
        refresh();
    };

}]);

<commit_msg>Wired the recents list with the stream events for realtime update<commit_after>/*
 Copyright 2014 matrix.org

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

'use strict';

angular.module('RecentsController', ['matrixService', 'eventHandlerService'])
.controller('RecentsController', ['$scope', 'matrixService', 'eventHandlerService', 'eventStreamService',
                               function($scope,  matrixService, eventHandlerService, eventStreamService) {
    $scope.rooms = {};

    // $scope of the parent where the recents component is included can override this value
    // in order to highlight a specific room in the list
    $scope.recentsSelectedRoomID;

    // Refresh the list on matrix invitation and message event
    $scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) {
        refresh();
    });
    $scope.$on(eventHandlerService.MSG_EVENT, function(ngEvent, event, isLive) {
        refresh();
    });

    var refresh = function() {
        // List all rooms joined or been invited to
        // TODO: This is a pity that event-stream-service.js makes the same call
        // We should be able to reuse event-stream-service.js fetched data
        matrixService.rooms(1, false).then(
            function(response) {
                // Reset data
                $scope.rooms = {};

                var data = matrixService.assignRoomAliases(response.data.rooms);
                for (var i=0; i<data.length; i++) {
                    $scope.rooms[data[i].room_id] = data[i];

                    // Create a shortcut for the last message of this room
                    if (data[i].messages && data[i].messages.chunk && data[i].messages.chunk[0]) {
                        $scope.rooms[data[i].room_id].lastMsg = data[i].messages.chunk[0];
                    }
                }

                var presence = response.data.presence;
                for (var i = 0; i < presence.length; ++i) {
                    eventHandlerService.handleEvent(presence[i], false);
                }
            },
            function(error) {
                $scope.feedback = "Failure: " + error.data;
            }
        );
    };

    $scope.onInit = function() {
        refresh();
    };

}]);

<|endoftext|>


<commit_before>const locales_hr = {
    nested: {
        lang: 'Croatian'
    },
    "Awaiting Payment...": "Čeka se uplata...",
    "Pay with": "Plati sa",
    "Contact and Refund Email": "E-mail za kontakt i povrat sredstava",
    "Contact_Body": "Molimo upišite Vašu e-mail adresu. Kontaktirati ćemo Vas ako nastane problem s uplatom",
    "Your email": "Vaš e-mail",
    "Continue": "Dalje",
    "Please enter a valid email address": "Molimo unesite ispravnu e-mail adresu",
    "Order Amount": "Količina",
    "Network Cost": "Mrežni trošak",
    "Already Paid": "Već plačeno",
    "Due": "Rok",
    // Tabs
    "Scan": "Skeniraj",
    "Copy": "Kopiraj",
    "Conversion": "Pretvori",
    // Scan tab
    "Open in wallet": "Otvori u novčaniku",
    // Copy tab
    "CompletePay_Body": "Kako bi završili uplatu pošaljite {{btcDue}} {{cryptoCode}} na navedenu adresu",
    "Amount": "Iznos",
    "Address": "Adresa",
    "Copied": "Kopirano",
    // Conversion tab
    "ConversionTab_BodyTop": "Možete platiti {{btcDue}} {{cryptoCode}} pomoću altcoina koje prodavač ne podržava.",
    "ConversionTab_BodyDesc": "Ovu usluga pruža treća strana. Vodite računa da nemamo kontroli nad načinom kako će Vam davatelji usluge prosljediti sredstva. Vodite računa da je račun plaćen tek kada su primljena sredstva na {{cryptoCode}} Blockchainu.",
    "Shapeshift_Button_Text": "Plati s Altcoinovima",
    "ConversionTab_Lightning": "Ne postoji treća strana koja bi konvertirala Lightning Network uplate.",
    // Invoice expired
    "Invoice expiring soon...": "Račun uskoro istiće...",
    "Invoice expired": "Račun je istekao",
    "What happened?": "Što se dogodilo",
    "InvoiceExpired_Body_1": "Račun je istekao i nije više valjan. Račun vrijedi samo {{maxTimeMinutes}} minuta.  \
Možete se vratiti na {{storeName}}, gdje možete ponovo inicirati plačanje.",
    "InvoiceExpired_Body_2": "Ukoliko ste pokušali poslati uplatu, ista nije registrirana na Blockchainu. Nismo još zaprimili Vašu uplatu.",
    "InvoiceExpired_Body_3": "Ukoliko poslana sredstva na budu potvrđena na Blockchainu, sredstva će biti ponovo dostupna u Vašem novčaniku.",
    "Invoice ID": "Broj računa",
    "Order ID": "Broj narudžbe",
    "Return to StoreName": "Vrati se na {{storeName}}",
    // Invoice paid
    "This invoice has been paid": "Račun je plačen",
    // Invoice archived
    "This invoice has been archived": "Račun je arhiviran.",
    "Archived_Body": "Kontaktirajte dučan za detalje oko naruđbe ili pomoć."
};
<commit_msg>Update hr.js<commit_after>const locales_hr = {
    nested: {
        lang: 'Croatian'
    },
    "Awaiting Payment...": "Čeka se uplata...",
    "Pay with": "Plati sa",
    "Contact and Refund Email": "E-mail za kontakt i povrat sredstava",
    "Contact_Body": "Molimo upišite Vašu e-mail adresu. Kontaktirat ćemo Vas ukoliko bude potrebe.",
    "Your email": "Vaš e-mail",
    "Continue": "Dalje",
    "Please enter a valid email address": "Molimo unesite ispravnu e-mail adresu",
    "Order Amount": "Količina",
    "Network Cost": "Mrežni trošak",
    "Already Paid": "Već plaćeno",
    "Due": "Rok",
    // Tabs
    "Scan": "Skeniraj",
    "Copy": "Kopiraj",
    "Conversion": "Pretvori",
    // Scan tab
    "Open in wallet": "Otvori u novčaniku",
    // Copy tab
    "CompletePay_Body": "Kako bi završili uplatu pošaljite {{btcDue}} {{cryptoCode}} na navedenu adresu",
    "Amount": "Iznos",
    "Address": "Adresa",
    "Copied": "Kopirano",
    // Conversion tab
    "ConversionTab_BodyTop": "Možete platiti {{btcDue}} {{cryptoCode}} pomoću altcoina koje prodavač ne podržava.",
    "ConversionTab_BodyDesc": "Ovu usluga pruža treća strana. Vodite računa da nemamo kontroli nad načinom kako će Vam davatelji usluge proslijediti sredstva. Vodite računa da je račun plaćen tek kada su primljena sredstva na {{cryptoCode}} Blockchainu.",
    "Shapeshift_Button_Text": "Plati s Alt-coinovima",
    "ConversionTab_Lightning": "Ne postoji treća strana koja bi konvertirala Lightning Network uplate.",
    // Invoice expired
    "Invoice expiring soon...": "Račun uskoro ističe...",
    "Invoice expired": "Račun je istekao",
    "What happened?": "Što se dogodilo",
    "InvoiceExpired_Body_1": "Račun je istekao i nije više valjan. Račun vrijedi samo {{maxTimeMinutes}} minuta.  \
Možete se vratiti na {{storeName}}, gdje možete ponovo inicirati plaćanje.",
    "InvoiceExpired_Body_2": "Ako ste pokušali poslati uplatu, ista nije registrirana na Blockchainu. Nismo još zaprimili Vašu uplatu.",
    "InvoiceExpired_Body_3": "Ako poslana sredstva na budu potvrđena na Blockchainu, sredstva će biti ponovo dostupna u Vašem novčaniku.",
    "Invoice ID": "Broj računa",
    "Order ID": "Broj narudžbe",
    "Return to StoreName": "Vrati se na {{storeName}}",
    // Invoice paid
    "This invoice has been paid": "Račun je plaćen",
    // Invoice archived
    "This invoice has been archived": "Račun je arhiviran.",
    "Archived_Body": "Kontaktirajte dućan za detalje oko narudžbe ili pomoć."
};
<|endoftext|>


<commit_before>/*global
 define
 */
/*jslint
 browser: true,
 white: true
 */
define([
    'jquery',
    'bluebird',
    'kb/common/html',
    'kb/widget/adapters/objectWidget',
    'kb/widget/widgetSet',
    'kb/service/utils',
    'kb/service/client/workspace'
],
    function ($, Promise, html, widgetAdapter, WidgetSet, apiUtils, Workspace) {
        'use strict';

        function renderBSPanel(config) {
            var div = html.tag('div');
            return div({class: 'panel panel-default'}, [
                div({class: 'panel-heading'}, [
                    div({class: 'panel-title'}, config.title)
                ]),
                div({class: 'panel-body'}, [
                    config.content
                ])
            ]);
        }

        function widget(config) {
            var mount, container, runtime = config.runtime,
                widgetSet = WidgetSet.make({runtime: runtime}),
                rendered;

            function getObjectInfo(params) {
                return Promise.try(function () {
                    var workspaceId = params.workspaceId,
                        objectId = params.objectId,
                        objectVersion = params.objectVersion;

                    if (workspaceId === undefined) {
                        throw new Error('Workspace id or name is required');
                    }
                    if (objectId === undefined) {
                        throw new Error('Object id or name is required');
                    }

                    var objectRef = apiUtils.makeWorkspaceObjectRef(workspaceId, objectId, objectVersion),
                        workspaceClient = new Workspace(runtime.getConfig('services.workspace.url'), {
                            token: runtime.service('session').getAuthToken()
                        });

                    return workspaceClient.get_object_info_new({
                        objects: [{ref: objectRef}],
                        ignoreErrors: 1
                    })
                        .then(function (objectList) {
                            if (objectList.length === 0) {
                                throw new Error('Object not found: ' + objectRef);
                            }
                            if (objectList.length > 1) {
                                throw new Error('Too many objects found: ' + objectRef + ', ' + objectList.length);
                            }
                            return apiUtils.object_info_to_object(objectList[0]);
                        });
                })
            }

            function renderPanel() {
                var div = html.tag('div'),
                    panel = div({class: 'kbase-view kbase-dataview-view container-fluid', 'data-kbase-view': 'dataview'}, [
                        div({class: 'row'}, [
                            div({class: 'col-sm-12'}, [
                                renderBSPanel({
                                    title: 'Data Provenance and Reference Network',
                                    icon: 'sitemap',
                                    content: div({id: widgetSet.addWidget('kb_dataview_provenance')})
                                })
                            ])
                        ])
                    ]);
                return({
                    title: 'Dataview',
                    content: panel
                });
            }

            function init(config) {
                return Promise.try(function () {
                    rendered = renderPanel();
                    return widgetSet.init(config);
                });
            }

            function attach(node) {
                return Promise.try(function () {
                    mount = node;
                    container = document.createElement('div');
                    mount.appendChild(container);
                    container.innerHTML = rendered.content;
                    return widgetSet.attach(node);
                });
            }

            function start(params) {
                return Promise.try(function () {
                    return getObjectInfo(params)
                        .then(function (objectInfo) {
                            params.objectInfo = objectInfo;

                            runtime.send('ui', 'setTitle', 'Data Provenance and Reference Network for ' + objectInfo.name);

                            return widgetSet.start(params);
                        });
                });
            }

            function run(params) {
                return Promise.try(function () {
                    return widgetSet.run(params);
                });
            }
            function stop() {
                return Promise.try(function () {
                    return widgetSet.stop();
                });
            }
            function detach() {
                return Promise.try(function () {
                    return widgetSet.detach();
                });
            }

            return {
                init: init,
                attach: attach,
                start: start,
                run: run,
                stop: stop,
                detach: detach
            };
        }

        return {
            make: function (config) {
                return widget(config);
            }
        };
    });<commit_msg>fix detection of ws object not found<commit_after>/*global
 define
 */
/*jslint
 browser: true,
 white: true
 */
define([
    'jquery',
    'bluebird',
    'kb/common/html',
    'kb/widget/adapters/objectWidget',
    'kb/widget/widgetSet',
    'kb/service/utils',
    'kb/service/client/workspace'
],
    function ($, Promise, html, widgetAdapter, WidgetSet, apiUtils, Workspace) {
        'use strict';

        function renderBSPanel(config) {
            var div = html.tag('div');
            return div({class: 'panel panel-default'}, [
                div({class: 'panel-heading'}, [
                    div({class: 'panel-title'}, config.title)
                ]),
                div({class: 'panel-body'}, [
                    config.content
                ])
            ]);
        }

        function widget(config) {
            var mount, container, runtime = config.runtime,
                widgetSet = WidgetSet.make({runtime: runtime}),
                rendered;

            function getObjectInfo(params) {
                return Promise.try(function () {
                    var workspaceId = params.workspaceId,
                        objectId = params.objectId,
                        objectVersion = params.objectVersion;

                    if (workspaceId === undefined) {
                        throw new Error('Workspace id or name is required');
                    }
                    if (objectId === undefined) {
                        throw new Error('Object id or name is required');
                    }

                    var objectRef = apiUtils.makeWorkspaceObjectRef(workspaceId, objectId, objectVersion),
                        workspaceClient = new Workspace(runtime.getConfig('services.workspace.url'), {
                            token: runtime.service('session').getAuthToken()
                        });

                    return workspaceClient.get_object_info_new({
                        objects: [{ref: objectRef}],
                        ignoreErrors: 1
                    })
                        .then(function (objectList) {
                            if (objectList[0] === null) {
                                throw new Error('Object not found: ' + objectRef);
                            }
                            return apiUtils.object_info_to_object(objectList[0]);
                        });
                })
            }

            function renderPanel() {
                var div = html.tag('div'),
                    panel = div({class: 'kbase-view kbase-dataview-view container-fluid', 'data-kbase-view': 'dataview'}, [
                        div({class: 'row'}, [
                            div({class: 'col-sm-12'}, [
                                renderBSPanel({
                                    title: 'Data Provenance and Reference Network',
                                    icon: 'sitemap',
                                    content: div({id: widgetSet.addWidget('kb_dataview_provenance')})
                                })
                            ])
                        ])
                    ]);
                return({
                    title: 'Dataview',
                    content: panel
                });
            }

            function init(config) {
                return Promise.try(function () {
                    rendered = renderPanel();
                    return widgetSet.init(config);
                });
            }

            function attach(node) {
                return Promise.try(function () {
                    mount = node;
                    container = document.createElement('div');
                    mount.appendChild(container);
                    container.innerHTML = rendered.content;
                    return widgetSet.attach(node);
                });
            }

            function start(params) {
                return Promise.try(function () {
                    return getObjectInfo(params)
                        .then(function (objectInfo) {
                            params.objectInfo = objectInfo;

                            runtime.send('ui', 'setTitle', 'Data Provenance and Reference Network for ' + objectInfo.name);

                            return widgetSet.start(params);
                        });
                });
            }

            function run(params) {
                return Promise.try(function () {
                    return widgetSet.run(params);
                });
            }
            function stop() {
                return Promise.try(function () {
                    return widgetSet.stop();
                });
            }
            function detach() {
                return Promise.try(function () {
                    return widgetSet.detach();
                });
            }

            return {
                init: init,
                attach: attach,
                start: start,
                run: run,
                stop: stop,
                detach: detach
            };
        }

        return {
            make: function (config) {
                return widget(config);
            }
        };
    });<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Peter Kuma

 * 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.
 */

var FileShack = new Class({
    Implements: Options,

    options: {
        updateInterval: 2000
    },

    initialize: function(options) {
        var this_ = this;

        this.setOptions(options);
        this.lastUpdate = undefined;

        this.items = new Collection();
        this.items.addEvent('add', function(view) {
            $('list').insertBefore(view.el, $('list').firstChild);
        });

        // Bootstrap items from JSON embedded in index.html.
        this.bootstrap($('bootstrap').get('text'))

        var dropbox = $('dropbox');
        var dropboxInput = $('dropbox-input');

        // Drag & Drop.
        if (typeof dropbox.addEventListener != 'undefined' &&
            typeof dropbox.ondrop != 'undefined' &&
            typeof File != 'undefined')
        {
            // Register Drag & Drop events.
            dropbox.addEventListener("dragenter", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("dragover", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("drop", function(e) {
                e.preventDefault();
                if (e.dataTransfer.files)
                    Array.each(e.dataTransfer.files, function(f) { this_.upload(f); });
            }, false);
        } else {
            // Switch dropbox text, drag & drop is not supported.
            $('dropbox-text').setStyle('display', 'none');
            $('dropbox-text-nodragndrop').setStyle('display', 'block');
        }

        var clickDelegated = false;
        dropboxInput.onclick = function(e) {
            clickDelegated = true;
            if (e && e.stopPropagation) e.stopPropagation();
        };

        if (Browser.ie && Browser.version <= 7) {
            this.fallback();
        } else {
            // Delegate click on dropbox to the hidden input file element.
            dropbox.addEvent('click', function() {
                if (typeof File != 'undefined') {
                    dropboxInput.click();
                    window.setTimeout(function() { if (!clickDelegated) this_.fallback(); }, 100);
                } else { // Fallback to upload by the iframe hack (IE).
                    this_.uploadIFrame();
                }
            });
        }

        dropboxInput.addEvent('change', function() {
            this_.upload(dropbox);
            dropbox.reset();
        });

        //window.setInterval(function() { this_.update() }, this.options.updateInterval);
        window.uuid = uuid();
        //this.update();
    },

    bootstrap: function(json) {
        var this_ = this;
        items = JSON.decode(json);
        Array.each(items, function(item) {
            var view = new ItemView(new Item());
            view.model.update(item);
            this_.items.add(view);
        });
    },

    fallback: function() {
        var this_ = this;
        // Show the file upload input form.
        $('dropbox-text').setStyle('display', 'none');
        $('dropbox-text-nodragndrop').setStyle('display', 'none');
        $('dropbox-file').setStyle('visibility', 'visible');
    },

    update: function() {
        var xhr = new XMLHttpRequest();

        if (this.lastUpdate) xhr.open('GET', 'update/' + this.lastUpdate + '/');
        else xhr.open('GET', 'update/');

        var this_ = this;
        xhr.onreadystatechange = function(e) {
            if (this.readyState == 4) {
                json = JSON.decode(this.responseText);
                this_.removeStaleItems(json.item_ids);
                Array.each(json.items, function(item) {
                    if (this_.items.get(item.id)) { // Existing item.
                        // Do not update pending items.
                        if (this_.items.get(item.id).model.type != 'pending')
                            this_.items.get(item.id).model.update(item);
                    } else { // New item.
                        var view = new ItemView(new Item());
                        view.model.update(item);
                        this_.items.add(view);
                    }
                });
                this.lastUpdate = json.time;
            }
        };
        xhr.send();
    },

    upload: function(data) {
        var this_ = this;
        // If input[type="file"].files is supported, upload per parts.
        if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement &&
            data.file && data.file.files)
        {
            Array.each(data.file.files, function(file) { this_.upload(file); });
            return null;
        }

        // Determine name and size of the file.
        if (typeof File != 'undefined' && data instanceof File) {
            // Older browsers.
            if (data.fileName) var name = data.fileName;
            if (data.fileSize) var size = data.fileSize;
            // Newer browsers.
            if (data.name) var name = data.name;
            if (data.size) var size = data.size;
        } else if (data.file) {
            var name = basename(data.file.value);
        } else {
            var name = '';
            var size = 0;
        }

        // Is there a stale item with the same size and name?
        var i = this.items.find(function(i) {
            if (!(i.model.type == 'stale' || i.model.type == 'pending' && i.isError()))
                return false;
            if (i.model.size_total != size) return false;
            if (i.model.name == name) return true;
            var n = i.model.name;
            // Django appends _#no to duplicate file names, account for that.
            if (n.contains('_')) {
                var index = n.lastIndexOf('_');
                var first = n.substring(0, index);
                var second = n.substring(index);
                n = first + second.substring(second.indexOf('.'));
            }
            if (n == name) return true;
            return false;
        });

        // If this is a File, ask the user about resume.
        if (i && typeof File != 'undefined' && data instanceof File) {
            var c = confirm('A stale file with the same name and size has been found.\nDo you want to resume uploading?');
            if (c) {
                item = i;
                item.clearError();
            }
        }

        if (!item) {
            var item = new ItemView(new Item({
                type: 'pending',
                'name': name,
                size: 0,
                size_total: size,
                status: 'UPLOADING'
            }));
            this.items.add(item);
        }

        if (ITEM_SIZE_LIMIT > 0 && size > ITEM_SIZE_LIMIT) {
            item.onError({
                label: ITEM_SIZE_LIMIT_ERROR_LABEL,
                message: ITEM_SIZE_LIMIT_ERROR_MESSAGE
	    });
            return null;
        }

        if (typeof File != 'undefined' && data instanceof File && typeof FileReader != 'undefined') {
            var reader = new FileReader()
            reader.onload = function(e) { item.model.upload(e.target.result); };
            reader.readAsBinaryString(data);
        } else if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement && typeof FormData != 'undefined') {
            item.model.upload(new FormData(data));
        } else if (typeof File != 'undefined' && data instanceof File && typeof FormData != 'undefined') {
            var formData = new FormData();
            formData.append('file', data);
            item.model.upload(formData);
        } else if (typeof File != 'undefined' && data instanceof File) {
            item.model.upload(data.getAsBinary());
        } else {
            data.submit();
        }

        return item;
    },

    uploadIFrame: function() {
        var this_ = this;
        var iframe = $('iframe');
        var form = iframe.contentDocument.forms[0];

        form.file.onchange = function() {
            var item = this_.upload(form);
            iframe.onload = function() {
                var responseText = iframe.contentDocument.body.innerHTML;
                iframe.onload = null;
                iframe.src = iframe.src;
                try {
		    var response = JSON.decode(responseText);
		} catch(e) {
		    item.onError({
			label: 'Upload failed',
			message: 'The server responded with an invalid message',
			details: responseText
		    });
                    return;
		}
                item.model.update(response.item);
                if (response.status != 'success') {
                    item.onError({
			label: response.error_label,
			message: response.error_message,
                        details: response.details
                    });
                    return;
                }
                item.model.set('type', 'complete');
                item.model.update(response.item);
            };
        };
        form.file.click();
    },

    removeStaleItems: function(validIds) {
        Object.each(this.items.all(), function(item) {
            if (item.model.type != 'pending' && !validIds.contains(item.model.id))
                item.model.remove();
        });
    }
});

document.addEvent('domready', function() {
    var fs = new FileShack();
});

<commit_msg>fileshack.js: Fix this.lastUpdate in update().<commit_after>/*
 * Copyright (c) 2012 Peter Kuma

 * 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.
 */

var FileShack = new Class({
    Implements: Options,

    options: {
        updateInterval: 2000
    },

    initialize: function(options) {
        var this_ = this;

        this.setOptions(options);
        this.lastUpdate = undefined;

        this.items = new Collection();
        this.items.addEvent('add', function(view) {
            $('list').insertBefore(view.el, $('list').firstChild);
        });

        // Bootstrap items from JSON embedded in index.html.
        this.bootstrap($('bootstrap').get('text'))

        var dropbox = $('dropbox');
        var dropboxInput = $('dropbox-input');

        // Drag & Drop.
        if (typeof dropbox.addEventListener != 'undefined' &&
            typeof dropbox.ondrop != 'undefined' &&
            typeof File != 'undefined')
        {
            // Register Drag & Drop events.
            dropbox.addEventListener("dragenter", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("dragover", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("drop", function(e) {
                e.preventDefault();
                if (e.dataTransfer.files)
                    Array.each(e.dataTransfer.files, function(f) { this_.upload(f); });
            }, false);
        } else {
            // Switch dropbox text, drag & drop is not supported.
            $('dropbox-text').setStyle('display', 'none');
            $('dropbox-text-nodragndrop').setStyle('display', 'block');
        }

        var clickDelegated = false;
        dropboxInput.onclick = function(e) {
            clickDelegated = true;
            if (e && e.stopPropagation) e.stopPropagation();
        };

        if (Browser.ie && Browser.version <= 7) {
            this.fallback();
        } else {
            // Delegate click on dropbox to the hidden input file element.
            dropbox.addEvent('click', function() {
                if (typeof File != 'undefined') {
                    dropboxInput.click();
                    window.setTimeout(function() { if (!clickDelegated) this_.fallback(); }, 100);
                } else { // Fallback to upload by the iframe hack (IE).
                    this_.uploadIFrame();
                }
            });
        }

        dropboxInput.addEvent('change', function() {
            this_.upload(dropbox);
            dropbox.reset();
        });

        //window.setInterval(function() { this_.update() }, this.options.updateInterval);
        window.uuid = uuid();
        //this.update();
    },

    bootstrap: function(json) {
        var this_ = this;
        items = JSON.decode(json);
        Array.each(items, function(item) {
            var view = new ItemView(new Item());
            view.model.update(item);
            this_.items.add(view);
        });
    },

    fallback: function() {
        var this_ = this;
        // Show the file upload input form.
        $('dropbox-text').setStyle('display', 'none');
        $('dropbox-text-nodragndrop').setStyle('display', 'none');
        $('dropbox-file').setStyle('visibility', 'visible');
    },

    update: function() {
	var this_ = this;
        var xhr = new XMLHttpRequest();

        if (this.lastUpdate) xhr.open('GET', 'update/' + this.lastUpdate + '/');
        else xhr.open('GET', 'update/');

        var this_ = this;
        xhr.onreadystatechange = function(e) {
            if (this.readyState == 4) {
                json = JSON.decode(this.responseText);
                this_.removeStaleItems(json.item_ids);
                Array.each(json.items, function(item) {
                    if (this_.items.get(item.id)) { // Existing item.
                        // Do not update pending items.
                        if (this_.items.get(item.id).model.type != 'pending')
                            this_.items.get(item.id).model.update(item);
                    } else { // New item.
                        var view = new ItemView(new Item());
                        view.model.update(item);
                        this_.items.add(view);
                    }
                });
                this_.lastUpdate = json.time;
            }
        };
        xhr.send();
    },

    upload: function(data) {
        var this_ = this;
        // If input[type="file"].files is supported, upload per parts.
        if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement &&
            data.file && data.file.files)
        {
            Array.each(data.file.files, function(file) { this_.upload(file); });
            return null;
        }

        // Determine name and size of the file.
        if (typeof File != 'undefined' && data instanceof File) {
            // Older browsers.
            if (data.fileName) var name = data.fileName;
            if (data.fileSize) var size = data.fileSize;
            // Newer browsers.
            if (data.name) var name = data.name;
            if (data.size) var size = data.size;
        } else if (data.file) {
            var name = basename(data.file.value);
        } else {
            var name = '';
            var size = 0;
        }

        // Is there a stale item with the same size and name?
        var i = this.items.find(function(i) {
            if (!(i.model.type == 'stale' || i.model.type == 'pending' && i.isError()))
                return false;
            if (i.model.size_total != size) return false;
            if (i.model.name == name) return true;
            var n = i.model.name;
            // Django appends _#no to duplicate file names, account for that.
            if (n.contains('_')) {
                var index = n.lastIndexOf('_');
                var first = n.substring(0, index);
                var second = n.substring(index);
                n = first + second.substring(second.indexOf('.'));
            }
            if (n == name) return true;
            return false;
        });

        // If this is a File, ask the user about resume.
        if (i && typeof File != 'undefined' && data instanceof File) {
            var c = confirm('A stale file with the same name and size has been found.\nDo you want to resume uploading?');
            if (c) {
                item = i;
                item.clearError();
            }
        }

        if (!item) {
            var item = new ItemView(new Item({
                type: 'pending',
                'name': name,
                size: 0,
                size_total: size,
                status: 'UPLOADING'
            }));
            this.items.add(item);
        }

        if (ITEM_SIZE_LIMIT > 0 && size > ITEM_SIZE_LIMIT) {
            item.onError({
                label: ITEM_SIZE_LIMIT_ERROR_LABEL,
                message: ITEM_SIZE_LIMIT_ERROR_MESSAGE
	    });
            return null;
        }

        if (typeof File != 'undefined' && data instanceof File && typeof FileReader != 'undefined') {
            var reader = new FileReader()
            reader.onload = function(e) { item.model.upload(e.target.result); };
            reader.readAsBinaryString(data);
        } else if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement && typeof FormData != 'undefined') {
            item.model.upload(new FormData(data));
        } else if (typeof File != 'undefined' && data instanceof File && typeof FormData != 'undefined') {
            var formData = new FormData();
            formData.append('file', data);
            item.model.upload(formData);
        } else if (typeof File != 'undefined' && data instanceof File) {
            item.model.upload(data.getAsBinary());
        } else {
            data.submit();
        }

        return item;
    },

    uploadIFrame: function() {
        var this_ = this;
        var iframe = $('iframe');
        var form = iframe.contentDocument.forms[0];

        form.file.onchange = function() {
            var item = this_.upload(form);
            iframe.onload = function() {
                var responseText = iframe.contentDocument.body.innerHTML;
                iframe.onload = null;
                iframe.src = iframe.src;
                try {
		    var response = JSON.decode(responseText);
		} catch(e) {
		    item.onError({
			label: 'Upload failed',
			message: 'The server responded with an invalid message',
			details: responseText
		    });
                    return;
		}
                item.model.update(response.item);
                if (response.status != 'success') {
                    item.onError({
			label: response.error_label,
			message: response.error_message,
                        details: response.details
                    });
                    return;
                }
                item.model.set('type', 'complete');
                item.model.update(response.item);
            };
        };
        form.file.click();
    },

    removeStaleItems: function(validIds) {
        Object.each(this.items.all(), function(item) {
            if (item.model.type != 'pending' && !validIds.contains(item.model.id))
                item.model.remove();
        });
    }
});

document.addEvent('domready', function() {
    var fs = new FileShack();
});

<|endoftext|>


<commit_before>/* global require, describe, it */
'use strict';

var expect = require('chai').expect;
var request = require('request');

var url = function(path) {
  return 'http://localhost:8000' + path;
};

describe("MongoDB", function() {
  it("is there a server running", function(next) {
    var MongoClient = require('mongodb').MongoClient;
    MongoClient.connect('mongodb://127.0.0.1:27017/brainstormer', function(err, db) {
      expect(err).to.equal(null);
      next();
    });
  });
});

describe('GET /', function() {
  it('responds', function(done){
    request(url('/'), function(error, res) {
      expect(res.statusCode).to.equal(200);
      done();
    });
  });
});

describe('GET /index.html', function() {
  it('responds', function(done){
    request(url('/index.html'), function(error, res) {
      expect(res.headers['content-type'].indexOf('html')).to.not.equal(-1);
      done();
    });
  });
});

describe('GET /no-such-file.html', function() {
  it('responds', function(done){
    request(url('/no-such-file.html'), function(error, res) {
      expect(res.statusCode).to.equal(404);
      done();
    });
  });
});
<commit_msg>(test) Add test for joining a room in sockets.<commit_after>/* global require, describe, it */
'use strict';

var expect = require('chai').expect;
var request = require('request');
var io = require('socket.io-client');

var url = function(path) {
  return 'http://localhost:8000' + path;
};

var options ={
  transports: ['websocket'],
  'force new connection': true
};

describe("MongoDB", function() {
  it("is there a server running", function(next) {
    var MongoClient = require('mongodb').MongoClient;
    MongoClient.connect('mongodb://127.0.0.1:27017/brainstormer', function(err, db) {
      expect(err).to.equal(null);
      next();
    });
  });
});

describe('GET /', function() {
  it('responds', function(done){
    request(url('/'), function(error, res) {
      expect(res.statusCode).to.equal(200);
      done();
    });
  });
});

describe('GET /index.html', function() {
  it('responds', function(done){
    request(url('/index.html'), function(error, res) {
      expect(res.headers['content-type'].indexOf('html')).to.not.equal(-1);
      done();
    });
  });
});

describe('GET /no-such-file.html', function() {
  it('responds', function(done){
    request(url('/no-such-file.html'), function(error, res) {
      expect(res.statusCode).to.equal(404);
      done();
    });
  });
});

describe('Socket connection', function() {
  it('can connect to a room', function(done){

    var client1 = io.connect(url(''), options);
    var client2 = io.connect(url(''), options);
    var room = "test room";
    var comment = "this is a test";

    client1.on('comment-change', function(data){
      expect(data).to.equal(comment);
      client1.disconnect();
      client2.disconnect();
      done();
    });

    // client1.on('connect', function(){
    //   client1.emit('join', 'mockRoom');
    //   var client2 = io.connect(url(''), options);
    //   client2.on('connect', function(){
    //     client2.emit('join', 'mockRoom');
    //     client2.emit('comment-change', 'some....comments', 'mockRoom');
    //   })
    // })

    client1.emit('join', room);
    client2.emit('join', room);
    client2.emit('comment-change', comment, room);

  });

});<|endoftext|>


<commit_before>import React from 'react';
import { Doughnut as DoughnutChart } from 'react-chartjs-2';

import SpellLink from 'common/SpellLink';
import SPELLS from 'common/SPELLS';
import { formatPercentage } from 'common/format';

import StatisticsListBox, { STATISTIC_ORDER } from 'interface/others/StatisticsListBox';
import STATISTIC_CATEGORY from 'interface/others/STATISTIC_CATEGORY';
import StatisticListBoxItem from 'interface/others/StatisticListBoxItem';

import Analyzer from 'parser/core/Analyzer';
import calculateEffectiveHealing from 'parser/core/calculateEffectiveHealing';

import CooldownThroughputTracker from '../features/FeedingTracker';

const UNLEASH_LIFE_HEALING_INCREASE = 0.45;
const BUFFER_MS = 200;
const UNLEASH_LIFE_DURATION = 10000;
const debug = false;

const CHART_SIZE = 75;

/**
 * Unleash Life:
 * Unleashes elemental forces of Life, healing a friendly target and increasing the effect of the Shaman's next direct heal.
 */

class UnleashLife extends Analyzer {
  static dependencies = {
    cooldownThroughputTracker: CooldownThroughputTracker,
  };
  healing = 0;
  healingBuff = {
    [SPELLS.RIPTIDE.id]: {
      healing: 0,
      castAmount: 0,
      playersActive: [],
    },
    [SPELLS.CHAIN_HEAL.id]: {
      healing: 0,
      castAmount: 0,
    },
    [SPELLS.HEALING_WAVE.id]: {
      healing: 0,
      castAmount: 0,
    },
    [SPELLS.HEALING_SURGE_RESTORATION.id]: {
      healing: 0,
      castAmount: 0,
    },
  };

  unleashLifeCasts = 0;
  unleashLifeRemaining = false;
  unleashLifeHealRemaining = 0;

  buffedChainHealTimestamp = null;
  lastUnleashLifeTimestamp = null;

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTalent(SPELLS.UNLEASH_LIFE_TALENT.id);
  }

  on_byPlayer_heal(event) {
    const spellId = event.ability.guid;

    if (spellId === SPELLS.UNLEASH_LIFE_TALENT.id) {
      this.unleashLifeHealRemaining = 1;
      this.lastUnleashLifeTimestamp = event.timestamp;
      this.healing += event.amount + (event.absorbed || 0);
    }

    if (this.unleashLifeHealRemaining > 0 && (this.lastUnleashLifeTimestamp + UNLEASH_LIFE_DURATION) <= event.timestamp) {
      debug && console.log("Heal Timed out", event.timestamp);
      this.unleashLifeHealRemaining = 0;
    }

    // Riptide HoT handling, ticks on whoever its active
    if (spellId === SPELLS.RIPTIDE.id && this.healingBuff[spellId].playersActive.includes(event.targetID)) {
      if (event.tick) {
        this.healingBuff[spellId].healing += calculateEffectiveHealing(event, UNLEASH_LIFE_HEALING_INCREASE);

        // Initial Riptide Heal without Unleash Life
        // casting an unbuffed Riptide on a target that already has a buffed Riptide, will completely negate the buff, so we remove that person
      } else if (!event.tick && !this.unleashLifeHealRemaining) {
        this.healingBuff[spellId].playersActive.splice(this.healingBuff[spellId].playersActive.indexOf(event.targetID), 1);
      }
    }

    // These 3 heals only have 1 event and are handled easily
    if (this.unleashLifeHealRemaining > 0 && ((spellId === SPELLS.HEALING_WAVE.id) || (spellId === SPELLS.HEALING_SURGE_RESTORATION.id) || (spellId === SPELLS.RIPTIDE.id && !event.tick))) {
      this.healingBuff[spellId].healing += calculateEffectiveHealing(event, UNLEASH_LIFE_HEALING_INCREASE);
      this.unleashLifeHealRemaining = 0;
      debug && console.log("Heal:", spellId);

      // I had to move the HoT application to the heal event as the buffapply event had too many false positives
      if (spellId === SPELLS.RIPTIDE.id) {
        this.healingBuff[spellId].playersActive.push(event.targetID);
        debug && console.log("HoT Applied:", spellId, event.targetID);
      }

      // Chain heal has up to 4 events, setting the variable to -1 to indicate that there might be more events coming
    } else if (spellId === SPELLS.CHAIN_HEAL.id && (this.unleashLifeHealRemaining > 0 || (this.unleashLifeHealRemaining < 0 && this.buffedChainHealTimestamp + BUFFER_MS > event.timestamp))) {
      this.healingBuff[spellId].healing += calculateEffectiveHealing(event, UNLEASH_LIFE_HEALING_INCREASE);
      this.unleashLifeHealRemaining = -1;
      this.buffedChainHealTimestamp = event.timestamp;
      debug && console.log("Heal:", spellId);
    }
  }

  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;

    if (spellId === SPELLS.UNLEASH_LIFE_TALENT.id) {
      this.unleashLifeCasts += 1;
      this.unleashLifeRemaining = true;
      this.lastUnleashLifeTimestamp = event.timestamp;
      debug && console.log("New Unleash", event.timestamp);
    }

    if (this.unleashLifeRemaining && (this.lastUnleashLifeTimestamp + UNLEASH_LIFE_DURATION) <= event.timestamp) {
      this.unleashLifeRemaining = false;
      debug && console.log("Cast Timed out", event.timestamp);
      return;
    }

    if (this.unleashLifeRemaining) {
      if (this.healingBuff[spellId]) {
        this.healingBuff[spellId].castAmount += 1;
        this.unleashLifeRemaining = false;
        debug && console.log("Cast:", spellId);
      }
    }
  }

  on_byPlayer_removebuff(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.RIPTIDE.id) {
      return;
    }

    if (!this.healingBuff[spellId].playersActive.includes(event.targetID)) {
      return;
    }

    this.healingBuff[spellId].playersActive.splice(this.healingBuff[spellId].playersActive.indexOf(event.targetID), 1);
  }

  on_feed_heal(event) {
    // rework
  }

  get totalBuffedHealing() {
    return Object.values(this.healingBuff).reduce((sum, spell) => sum + spell.healing, 0);
  }

  get totalUses() {
    return Object.values(this.healingBuff).reduce((sum, spell) => sum + spell.castAmount, 0);
  }

  legend(items, total) {
    const numItems = items.length;
    return items.map(({ color, label, tooltip, value, spellId }, index) => {
      label = tooltip ? (
        <dfn data-tip={tooltip}>{label}</dfn>
      ) : label;
      label = spellId ? (
        <SpellLink id={spellId} icon={false}>{label}</SpellLink>
      ) : label;
      return (

            {label}

            <dfn data-tip={value}>
              {formatPercentage(value / total, 0)}%
            </dfn>

      );
    });
  }
  chart(items) {
    return (
      <DoughnutChart
        data={{
          datasets: [{
            data: items.map(item => item.value),
            backgroundColor: items.map(item => item.color),
            borderColor: '#000000',
            borderWidth: 0,
          }],
          labels: items.map(item => item.label),
        }}
        options={{
          legend: {
            display: false,
          },
          tooltips: {
            bodyFontSize: 8,
          },
          cutoutPercentage: 45,
          animation: false,
          responsive: false,
        }}
        width={CHART_SIZE}
        height={CHART_SIZE}
      />
    );
  }

  unleashLifeCastRatioChart() {
    const unusedUL = this.unleashLifeCasts - this.totalUses;

    const items = [
      {
        color: SPELLS.CHAIN_HEAL.color,
        label: 'Chain Heal',
        spellId: SPELLS.CHAIN_HEAL.id,
        value: this.healingBuff[SPELLS.CHAIN_HEAL.id].castAmount,
      },
      {
        color: SPELLS.HEALING_WAVE.color,
        label: 'Healing Wave',
        spellId: SPELLS.HEALING_WAVE.id,
        value: this.healingBuff[SPELLS.HEALING_WAVE.id].castAmount,
      },
      {
        color: SPELLS.HEALING_SURGE_RESTORATION.color,
        label: 'Healing Surge',
        spellId: SPELLS.HEALING_SURGE_RESTORATION.id,
        value: this.healingBuff[SPELLS.HEALING_SURGE_RESTORATION.id].castAmount,
      },
      {
        color: SPELLS.RIPTIDE.color,
        label: 'Riptide',
        spellId: SPELLS.RIPTIDE.id,
        value: this.healingBuff[SPELLS.RIPTIDE.id].castAmount,
      },
      {
        color: '#CC3D20',
        label: 'Unused Buffs',
        tooltip: `The amount of Unleash Life buffs you did not use out of the total available. You cast ${this.unleashLifeCasts} Unleash Lifes, of which you used ${this.totalUses}.`,
        value: unusedUL,
      },
    ];

    return (

          {this.chart(items)}

          {this.legend(items, this.totalUses)}

    );
  }

  statistic() {
    return (
      <StatisticsListBox
        title={<SpellLink id={SPELLS.UNLEASH_LIFE_TALENT.id} /> usage}
        containerProps={{ className: 'col-lg-3 col-md-4 col-sm-6 col-xs-12' }}
        category={STATISTIC_CATEGORY.TALENTS}
        position={STATISTIC_ORDER.OPTIONAL(15)}
      >
        {this.unleashLifeCastRatioChart()}
      </StatisticsListBox>
    );
  }

  subStatistic() {
    const feeding = this.cooldownThroughputTracker.getIndirectHealing(SPELLS.UNLEASH_LIFE_TALENT.id);
    return (
      <StatisticListBoxItem
        title={<SpellLink id={SPELLS.UNLEASH_LIFE_TALENT.id} />}
        value={`${formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.healing + this.totalBuffedHealing + feeding))} %`}
        valueTooltip={`${formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.healing + feeding))}% from Unleash Life and ${formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.totalBuffedHealing))}% from the healing buff.`}
      />
    );
  }

}

export default UnleashLife;

<commit_msg>I'm quite sure I unchecked this files changes<commit_after>import React from 'react';
import { Doughnut as DoughnutChart } from 'react-chartjs-2';

import SpellLink from 'common/SpellLink';
import SPELLS from 'common/SPELLS';
import { formatPercentage } from 'common/format';

import StatisticsListBox, { STATISTIC_ORDER } from 'interface/others/StatisticsListBox';
import STATISTIC_CATEGORY from 'interface/others/STATISTIC_CATEGORY';
import StatisticListBoxItem from 'interface/others/StatisticListBoxItem';

import Analyzer from 'parser/core/Analyzer';
import calculateEffectiveHealing from 'parser/core/calculateEffectiveHealing';

import CooldownThroughputTracker from '../features/CooldownThroughputTracker';

const UNLEASH_LIFE_HEALING_INCREASE = 0.45;
const BUFFER_MS = 200;
const UNLEASH_LIFE_DURATION = 10000;
const debug = false;

const CHART_SIZE = 75;

/**
 * Unleash Life:
 * Unleashes elemental forces of Life, healing a friendly target and increasing the effect of the Shaman's next direct heal.
 */

class UnleashLife extends Analyzer {
  static dependencies = {
    cooldownThroughputTracker: CooldownThroughputTracker,
  };
  healing = 0;
  healingBuff = {
    [SPELLS.RIPTIDE.id]: {
      healing: 0,
      castAmount: 0,
      playersActive: [],
    },
    [SPELLS.CHAIN_HEAL.id]: {
      healing: 0,
      castAmount: 0,
    },
    [SPELLS.HEALING_WAVE.id]: {
      healing: 0,
      castAmount: 0,
    },
    [SPELLS.HEALING_SURGE_RESTORATION.id]: {
      healing: 0,
      castAmount: 0,
    },
  };

  unleashLifeCasts = 0;
  unleashLifeRemaining = false;
  unleashLifeHealRemaining = 0;

  buffedChainHealTimestamp = null;
  lastUnleashLifeTimestamp = null;

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTalent(SPELLS.UNLEASH_LIFE_TALENT.id);
  }

  on_byPlayer_heal(event) {
    const spellId = event.ability.guid;

    if (spellId === SPELLS.UNLEASH_LIFE_TALENT.id) {
      this.unleashLifeHealRemaining = 1;
      this.lastUnleashLifeTimestamp = event.timestamp;
      this.healing += event.amount + (event.absorbed || 0);
    }

    if (this.unleashLifeHealRemaining > 0 && (this.lastUnleashLifeTimestamp + UNLEASH_LIFE_DURATION) <= event.timestamp) {
      debug && console.log("Heal Timed out", event.timestamp);
      this.unleashLifeHealRemaining = 0;
    }

    // Riptide HoT handling, ticks on whoever its active
    if (spellId === SPELLS.RIPTIDE.id && this.healingBuff[spellId].playersActive.includes(event.targetID)) {
      if (event.tick) {
        this.healingBuff[spellId].healing += calculateEffectiveHealing(event, UNLEASH_LIFE_HEALING_INCREASE);

        // Initial Riptide Heal without Unleash Life
        // casting an unbuffed Riptide on a target that already has a buffed Riptide, will completely negate the buff, so we remove that person
      } else if (!event.tick && !this.unleashLifeHealRemaining) {
        this.healingBuff[spellId].playersActive.splice(this.healingBuff[spellId].playersActive.indexOf(event.targetID), 1);
      }
    }

    // These 3 heals only have 1 event and are handled easily
    if (this.unleashLifeHealRemaining > 0 && ((spellId === SPELLS.HEALING_WAVE.id) || (spellId === SPELLS.HEALING_SURGE_RESTORATION.id) || (spellId === SPELLS.RIPTIDE.id && !event.tick))) {
      this.healingBuff[spellId].healing += calculateEffectiveHealing(event, UNLEASH_LIFE_HEALING_INCREASE);
      this.unleashLifeHealRemaining = 0;
      debug && console.log("Heal:", spellId);

      // I had to move the HoT application to the heal event as the buffapply event had too many false positives
      if (spellId === SPELLS.RIPTIDE.id) {
        this.healingBuff[spellId].playersActive.push(event.targetID);
        debug && console.log("HoT Applied:", spellId, event.targetID);
      }

      // Chain heal has up to 4 events, setting the variable to -1 to indicate that there might be more events coming
    } else if (spellId === SPELLS.CHAIN_HEAL.id && (this.unleashLifeHealRemaining > 0 || (this.unleashLifeHealRemaining < 0 && this.buffedChainHealTimestamp + BUFFER_MS > event.timestamp))) {
      this.healingBuff[spellId].healing += calculateEffectiveHealing(event, UNLEASH_LIFE_HEALING_INCREASE);
      this.unleashLifeHealRemaining = -1;
      this.buffedChainHealTimestamp = event.timestamp;
      debug && console.log("Heal:", spellId);
    }
  }

  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;

    if (spellId === SPELLS.UNLEASH_LIFE_TALENT.id) {
      this.unleashLifeCasts += 1;
      this.unleashLifeRemaining = true;
      this.lastUnleashLifeTimestamp = event.timestamp;
      debug && console.log("New Unleash", event.timestamp);
    }

    if (this.unleashLifeRemaining && (this.lastUnleashLifeTimestamp + UNLEASH_LIFE_DURATION) <= event.timestamp) {
      this.unleashLifeRemaining = false;
      debug && console.log("Cast Timed out", event.timestamp);
      return;
    }

    if (this.unleashLifeRemaining) {
      if (this.healingBuff[spellId]) {
        this.healingBuff[spellId].castAmount += 1;
        this.unleashLifeRemaining = false;
        debug && console.log("Cast:", spellId);
      }
    }
  }

  on_byPlayer_removebuff(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.RIPTIDE.id) {
      return;
    }

    if (!this.healingBuff[spellId].playersActive.includes(event.targetID)) {
      return;
    }

    this.healingBuff[spellId].playersActive.splice(this.healingBuff[spellId].playersActive.indexOf(event.targetID), 1);
  }

  on_feed_heal(event) {
    // rework
  }

  get totalBuffedHealing() {
    return Object.values(this.healingBuff).reduce((sum, spell) => sum + spell.healing, 0);
  }

  get totalUses() {
    return Object.values(this.healingBuff).reduce((sum, spell) => sum + spell.castAmount, 0);
  }

  legend(items, total) {
    const numItems = items.length;
    return items.map(({ color, label, tooltip, value, spellId }, index) => {
      label = tooltip ? (
        <dfn data-tip={tooltip}>{label}</dfn>
      ) : label;
      label = spellId ? (
        <SpellLink id={spellId} icon={false}>{label}</SpellLink>
      ) : label;
      return (

            {label}

            <dfn data-tip={value}>
              {formatPercentage(value / total, 0)}%
            </dfn>

      );
    });
  }
  chart(items) {
    return (
      <DoughnutChart
        data={{
          datasets: [{
            data: items.map(item => item.value),
            backgroundColor: items.map(item => item.color),
            borderColor: '#000000',
            borderWidth: 0,
          }],
          labels: items.map(item => item.label),
        }}
        options={{
          legend: {
            display: false,
          },
          tooltips: {
            bodyFontSize: 8,
          },
          cutoutPercentage: 45,
          animation: false,
          responsive: false,
        }}
        width={CHART_SIZE}
        height={CHART_SIZE}
      />
    );
  }

  unleashLifeCastRatioChart() {
    const unusedUL = this.unleashLifeCasts - this.totalUses;

    const items = [
      {
        color: SPELLS.CHAIN_HEAL.color,
        label: 'Chain Heal',
        spellId: SPELLS.CHAIN_HEAL.id,
        value: this.healingBuff[SPELLS.CHAIN_HEAL.id].castAmount,
      },
      {
        color: SPELLS.HEALING_WAVE.color,
        label: 'Healing Wave',
        spellId: SPELLS.HEALING_WAVE.id,
        value: this.healingBuff[SPELLS.HEALING_WAVE.id].castAmount,
      },
      {
        color: SPELLS.HEALING_SURGE_RESTORATION.color,
        label: 'Healing Surge',
        spellId: SPELLS.HEALING_SURGE_RESTORATION.id,
        value: this.healingBuff[SPELLS.HEALING_SURGE_RESTORATION.id].castAmount,
      },
      {
        color: SPELLS.RIPTIDE.color,
        label: 'Riptide',
        spellId: SPELLS.RIPTIDE.id,
        value: this.healingBuff[SPELLS.RIPTIDE.id].castAmount,
      },
      {
        color: '#CC3D20',
        label: 'Unused Buffs',
        tooltip: `The amount of Unleash Life buffs you did not use out of the total available. You cast ${this.unleashLifeCasts} Unleash Lifes, of which you used ${this.totalUses}.`,
        value: unusedUL,
      },
    ];

    return (

          {this.chart(items)}

          {this.legend(items, this.totalUses)}

    );
  }

  statistic() {
    return (
      <StatisticsListBox
        title={<SpellLink id={SPELLS.UNLEASH_LIFE_TALENT.id} /> usage}
        containerProps={{ className: 'col-lg-3 col-md-4 col-sm-6 col-xs-12' }}
        category={STATISTIC_CATEGORY.TALENTS}
        position={STATISTIC_ORDER.OPTIONAL(15)}
      >
        {this.unleashLifeCastRatioChart()}
      </StatisticsListBox>
    );
  }

  subStatistic() {
    const feeding = this.cooldownThroughputTracker.getIndirectHealing(SPELLS.UNLEASH_LIFE_TALENT.id);
    return (
      <StatisticListBoxItem
        title={<SpellLink id={SPELLS.UNLEASH_LIFE_TALENT.id} />}
        value={`${formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.healing + this.totalBuffedHealing + feeding))} %`}
        valueTooltip={`${formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.healing + feeding))}% from Unleash Life and ${formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.totalBuffedHealing))}% from the healing buff.`}
      />
    );
  }

}

export default UnleashLife;

<|endoftext|>


<commit_before>/* global CloudCmd */
/* global Util */
/* global DOM */
/* global CloudFunc */
/* global rendy */
/* global spero */

(function(CloudCmd, Util, DOM, CloudFunc, rendy) {
    'use strict';

    CloudCmd.Operation = OperationProto;

    function OperationProto(operation, data) {
        var Name        = 'Operation',
            Loaded,
            copyFn      = DOM.RESTful.cp,
            moveFn      = DOM.RESTful.mv,
            Images      = DOM.Images,
            Dialog      = DOM.Dialog,

            Operation   = this;

        function init() {
            Images.show.load();

            Util.exec.series([
                function(callback) {
                    var Files = DOM.Files;

                    Files.get('config', function(error, config) {
                        if (error)
                            alert(error);
                        else if (config.progressOfCopying)
                            load(function() {
                                create(callback);
                            });
                        else
                            callback();
                    });
                },
                function() {
                    Loaded = true;
                    Operation.show(operation, data);
                }
            ]);
        }

        function create(callback) {
            spero(function() {
                var parse   = function(fn) {
                    return function(data, callback) {
                        var progress = function(value) {
                                Images.setProgress(value);
                            },

                            end     = function() {
                                callback();
                                spero.removeListener('progress', progress);
                                spero.removeListener('end', end);
                            },

                            error   = function(data) {
                                var msg = data + '\n Continue?',
                                    is = confirm(msg);

                                if (is)
                                    spero.continue();
                                else
                                    spero.abort();
                            };

                        Images.show('top');

                        fn(data.from, data.to, data.names);

                        spero.on('progress', progress);
                        spero.on('end', end);
                        spero.on('error', error);
                    };
                };

                spero.on('connect', function() {
                    copyFn      = parse(spero.copy);
                });

                spero.on('disconnect', function() {
                    copyFn      = DOM.RESTful.cp;
                });

                Util.exec(callback);
            });
        }

        this.hide   = function() {
            CloudCmd.View.hide();
        };

        this.show = function(operation, data) {
            if (Loaded)
                switch(operation) {
                case 'copy':
                    this.copy(data);
                    break;

                case 'move':
                    this.move(data);
                    break;
                }
        };

        this.copy = function(data) {
            processFiles(data, copyFn, message('Copy'));
        };

        this.move = function(data) {
            processFiles(data, moveFn, message('Rename/Move'));
        };

        /*
         * process files (copy or move)
         * @param data
         * @param operation
         */
        function processFiles(data, operation, message) {
             var name, files,
                CurrentInfo = DOM.CurrentInfo,
                panel,
                shouldAsk,
                sameName,
                ok,
                tmpl        = '"{{ name }}" already exist. Overwrite?',

                from        = '',
                to          = '',

                names       = [];

            if (data) {
                from        = data.from;
                to          = data.to;
                names       = data.names;
                panel       = CurrentInfo.panel;
            } else {
                from        = CurrentInfo.dirPath;
                to          = DOM.getNotCurrentDirPath();
                names       = DOM.getSelectedNames();
                data        = {};
                shouldAsk   = true;
                panel       = CurrentInfo.panelPassive;
            }

            if (!names.length)
                names.push(DOM.getCurrentName());

            name    = names[0];

            sameName    = !!DOM.getCurrentByName(name, panel);

            if (name === '..') {
                Dialog.alert('No files selected!');
            } else {
                if (shouldAsk)
                    to = message(to, names);

                ok = from !== to && to;

                if (ok && shouldAsk && sameName)
                    ok = Dialog.confirm(rendy(tmpl, {
                        name: name
                    }));

                if (ok) {
                    Images.show.load('top');

                    files   = {
                        from    : from,
                        to      : to,
                        names   : names
                    };

                    operation(files, function() {
                        var path            = CloudFunc.rmLastSlash(from);

                        DOM.Storage.remove(path, function() {
                            var panel           = CurrentInfo.panel,
                                panelPassive    = CurrentInfo.panelPassive,
                                setCurrent      = function() {
                                    var current;

                                    if (!name)
                                        name = data.names[0];

                                    current = DOM.getCurrentByName(name);
                                    DOM.setCurrentFile(current);
                                };

                            if (!CurrentInfo.isOnePanel)
                                CloudCmd.refresh(panelPassive, {noCurrent: true}, function() {});

                            CloudCmd.refresh(panel, setCurrent);
                        });
                    });
                }
            }
        }

        function message(msg) {
            return function(to, names) {
                var ret,
                    n       = names.length,
                    name    = names[0];

                msg += ' ';

                if (names.length > 1)
                    msg     += n + ' file(s)';
                else
                    msg     += '"' + name + '"';

                msg         += ' to';

                ret = Dialog.prompt(msg, to);

                return ret;
            };
        }

        function load(callback) {
            DOM.load.js('/spero/spero.js', function(error) {
                if (error) {
                    Dialog.alert(error.message);
                } else {
                    Loaded = true;
                    Util.timeEnd(Name + ' load');
                    Util.exec(callback);
                }
            });

            Util.time(Name + ' load');
        }

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc, rendy);
<commit_msg>chore(operation) rm " "<commit_after>/* global CloudCmd */
/* global Util */
/* global DOM */
/* global CloudFunc */
/* global rendy */
/* global spero */

(function(CloudCmd, Util, DOM, CloudFunc, rendy) {
    'use strict';

    CloudCmd.Operation = OperationProto;

    function OperationProto(operation, data) {
        var Name        = 'Operation',
            Loaded,
            copyFn      = DOM.RESTful.cp,
            moveFn      = DOM.RESTful.mv,
            Images      = DOM.Images,
            Dialog      = DOM.Dialog,

            Operation   = this;

        function init() {
            Images.show.load();

            Util.exec.series([
                function(callback) {
                    var Files = DOM.Files;

                    Files.get('config', function(error, config) {
                        if (error)
                            alert(error);
                        else if (config.progressOfCopying)
                            load(function() {
                                create(callback);
                            });
                        else
                            callback();
                    });
                },
                function() {
                    Loaded = true;
                    Operation.show(operation, data);
                }
            ]);
        }

        function create(callback) {
            spero(function() {
                var parse   = function(fn) {
                    return function(data, callback) {
                        var progress = function(value) {
                                Images.setProgress(value);
                            },

                            end     = function() {
                                callback();
                                spero.removeListener('progress', progress);
                                spero.removeListener('end', end);
                            },

                            error   = function(data) {
                                var msg = data + '\n Continue?',
                                    is = confirm(msg);

                                if (is)
                                    spero.continue();
                                else
                                    spero.abort();
                            };

                        Images.show('top');

                        fn(data.from, data.to, data.names);

                        spero.on('progress', progress);
                        spero.on('end', end);
                        spero.on('error', error);
                    };
                };

                spero.on('connect', function() {
                    copyFn      = parse(spero.copy);
                });

                spero.on('disconnect', function() {
                    copyFn      = DOM.RESTful.cp;
                });

                Util.exec(callback);
            });
        }

        this.hide   = function() {
            CloudCmd.View.hide();
        };

        this.show = function(operation, data) {
            if (Loaded)
                switch(operation) {
                case 'copy':
                    this.copy(data);
                    break;

                case 'move':
                    this.move(data);
                    break;
                }
        };

        this.copy = function(data) {
            processFiles(data, copyFn, message('Copy'));
        };

        this.move = function(data) {
            processFiles(data, moveFn, message('Rename/Move'));
        };

        /*
         * process files (copy or move)
         * @param data
         * @param operation
         */
        function processFiles(data, operation, message) {
             var name, files,
                CurrentInfo = DOM.CurrentInfo,
                panel,
                shouldAsk,
                sameName,
                ok,
                tmpl        = '"{{ name }}" already exist. Overwrite?',

                from        = '',
                to          = '',

                names       = [];

            if (data) {
                from        = data.from;
                to          = data.to;
                names       = data.names;
                panel       = CurrentInfo.panel;
            } else {
                from        = CurrentInfo.dirPath;
                to          = DOM.getNotCurrentDirPath();
                names       = DOM.getSelectedNames();
                data        = {};
                shouldAsk   = true;
                panel       = CurrentInfo.panelPassive;
            }

            if (!names.length)
                names.push(DOM.getCurrentName());

            name    = names[0];

            sameName    = !!DOM.getCurrentByName(name, panel);

            if (name === '..') {
                Dialog.alert('No files selected!');
            } else {
                if (shouldAsk)
                    to = message(to, names);

                ok = from !== to && to;

                if (ok && shouldAsk && sameName)
                    ok = Dialog.confirm(rendy(tmpl, {
                        name: name
                    }));

                if (ok) {
                    Images.show.load('top');

                    files   = {
                        from    : from,
                        to      : to,
                        names   : names
                    };

                    operation(files, function() {
                        var path            = CloudFunc.rmLastSlash(from);

                        DOM.Storage.remove(path, function() {
                            var panel           = CurrentInfo.panel,
                                panelPassive    = CurrentInfo.panelPassive,
                                setCurrent      = function() {
                                    var current;

                                    if (!name)
                                        name = data.names[0];

                                    current = DOM.getCurrentByName(name);
                                    DOM.setCurrentFile(current);
                                };

                            if (!CurrentInfo.isOnePanel)
                                CloudCmd.refresh(panelPassive, {noCurrent: true}, function() {});

                            CloudCmd.refresh(panel, setCurrent);
                        });
                    });
                }
            }
        }

        function message(msg) {
            return function(to, names) {
                var ret,
                    n       = names.length,
                    name    = names[0];

                msg += ' ';

                if (names.length > 1)
                    msg     += n + ' file(s)';
                else
                    msg     += '"' + name + '"';

                msg         += ' to';

                ret = Dialog.prompt(msg, to);

                return ret;
            };
        }

        function load(callback) {
            DOM.load.js('/spero/spero.js', function(error) {
                if (error) {
                    Dialog.alert(error.message);
                } else {
                    Loaded = true;
                    Util.timeEnd(Name + ' load');
                    Util.exec(callback);
                }
            });

            Util.time(Name + ' load');
        }

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc, rendy);
<|endoftext|>


<commit_before>
module.exports = script_langs;

var newErrorLogs = require('./tools.js').servErrorLogs;
var genRegExp = require('./tools.js').genRegExp;
var file_proxy = require('./file-prox.js');
var modscript = require('./modscript.js');
var yaml = require('js-yaml');
var URL = require('url');

function script_langs(url, req, res, options) {
	var u
	, langsFor = options.for
	, log = newErrorLogs()
	, prx = true
	, file_index = -1
	, files
	, langs
	, mdurl
	, LNG = {}
	, file
	, modID
	;

	var langsFor = (function() {
		var m = [];

		if (typeof langsFor === 'string') {
			langsFor.split(',').forEach(function(v) {
				if (v = String(v).trim()) {
					if (m.indexOf('v') === -1) {
						m.push(v);
					};
				};
			});
		};

		if (m.length < 1) m.push('en')
		return m;
	})();

	var xreq = {
		X_Forwarded_For: req.X_Forwarded_For || null,

		headers: {
			'user-agent': (req.headers||false)['user-agent'],
			'authorization': (req.headers||false)['authorization']
		}
	};

	var regz = genRegExp(['str1', 'str2', 'comment_mu', 'comment_mi', 'regx'], 'g');
    var buffer = [];

	var xres = {
		writeHead: function(status) {
			prx = status === 200;
		},

		write: function(chunk) {
			if (prx) buffer.push(chunk);
		},

		end: function() {
			var code = buffer.join(''), lang, x;
			buffer.length = 0;

            var m = code.match(regz) || false;
			var l = m.length, i = 0, x;

			var autokey = file.moduleJSON.autokey;
			if (!options.autokey || typeof autokey !== 'string') {
				autokey = false;
			};

			var lang_old = langs[modID] || false;
			var lang_new = LNG[modID] || {};

			for(; i < l; i++)  {
				x = m[i];

				if (x.charCodeAt(0) !== 34) continue;

				try {
					x = JSON.parse(x)
				} catch (e) {
					//console.log('ups JSON.parse(lang)');
					continue;
				};

                if (!x || !x.trim()) continue;

                if (!lang_old[x]) {
					if (options.all == 'unicode' &&  !/[^\x00-\xff]/i.test(x) ) {
						continue;
					};

					if (options.all == 'ru' &&  !/[аА-яЯёЁ]/i.test(x) ) {
						continue;
					};
				};

				if (lang_new[x]) continue
				LNG[modID] = lang_new;

                var oldx = lang_old[x] || false;
                var newx = lang_new[x] = {};

                langsFor.forEach(function(lang) {
                    var value = oldx[lang];

                    if (autokey && typeof value === 'string') {
                        if (value[0] === '.') {
                            value = autokey + value;
                        };
                    };

                    newx[lang] = value != null ? value : null;
                });
			};

			if (!options.pure && typeof lang_old === 'object') { // ишем протухшие значения
				for(x in lang_old) {
					console.log(modID, x)
					if (lang_old[x] && !lang_new[x]) {
						(lang_new[x] = lang_old[x]).deleted = true;
					};
				};
			};

			next();
		}
	};

	modscript(log, req, url
		, function(status, code, _files, _styles, _langs, _mdurl) {
			if (status !== true) {
				res.writeHead(404, {
					'content-type': 'application/x-javascript; charset=UTF-8'
				});

				res.end(log());
				return;
			};

			res.writeHead(200, {
				'content-type': 'application/x-javascript; charset=UTF-8'
			});

			files = _files;
			langs = _langs;
			mdurl = _mdurl;

			next();
		}
	);

	function next() {
		var i;

		do {
			i = ++file_index;

			if (i >= files.length || !files.length) {
				complite();
				return;
			};

			file = files[i];

		} while(!file);

		if (typeof file !== 'object') {
			complite();
			return;
		};

		if (!options.all && !langs[file.moduleID]) {
			return next();
		};

		if (file.js_inc) {
			return next();
		};

		var u
		, shead = ''
		, sfoot = ''
		, url = file.src
		, q = URL.parse(url)
		;

		modID = file.moduleID;

		if (q.protocol === 'http:' || q.protocol === 'https:') {
			if (!q.host || !/.\.[a-zA-Z]{2,7}$/.test(q.hostname) || /^\.|\.\.|[^\w\-\.]/.test(q.hostname)) {
				// res.write('\n\n/* ------ BAD: ' + url + ' */\n');
				log('error', 'bad host: ' + url );
				return next();
			};
		} else {
			if (q.protocol !== 'file:') {
				// res.write('\n\n/* ------ BAD: ' + url + ' */\n');
				log('error', 'bad protocol: ' + url );
				return next();
			};
		};

		file_proxy(url, xreq, xres, false, shead, sfoot);
	};

	function complite() {
		var r = {}, i, x;

		for (i in LNG) {
			if (typeof mdurl[i] === 'string') {
				r[xDelHost(mdurl[i])] = LNG[i];
				//r[mdurl[i]] = LNG[i];
			};
		};

		if (options.yaml) {
			res.write(yaml.safeDump(r, {indent: options.yaml}));
		} else {
			res.write(JSON.stringify(r, null, "\t"));
		};

		res.end();
	};

	var xStartHost = req.xStartHost;
	function xDelHost(x) {
		x = x + '';
		return xStartHost && x.substr(0, xStartHost.length) === xStartHost
			? x.substr(xStartHost.length)
			: x
		;
	};

};

<commit_msg>* при формирования списка переводов отображаются удаленные тексты<commit_after>
module.exports = script_langs;

var newErrorLogs = require('./tools.js').servErrorLogs;
var genRegExp = require('./tools.js').genRegExp;
var file_proxy = require('./file-prox.js');
var modscript = require('./modscript.js');
var yaml = require('js-yaml');
var URL = require('url');

function script_langs(url, req, res, options) {
	var u
	, langsFor = options.for
	, log = newErrorLogs()
	, prx = true
	, file_index = -1
	, files
	, langs
	, mdurl
	, LNG = {}
	, file
	, modID
	;

	var langsFor = (function() {
		var m = [];

		if (typeof langsFor === 'string') {
			langsFor.split(',').forEach(function(v) {
				if (v = String(v).trim()) {
					if (m.indexOf('v') === -1) {
						m.push(v);
					};
				};
			});
		};

		if (m.length < 1) m.push('en')
		return m;
	})();

	var xreq = {
		X_Forwarded_For: req.X_Forwarded_For || null,

		headers: {
			'user-agent': (req.headers||false)['user-agent'],
			'authorization': (req.headers||false)['authorization']
		}
	};

	var regz = genRegExp(['str1', 'str2', 'comment_mu', 'comment_mi', 'regx'], 'g');
    var buffer = [];

	var xres = {
		writeHead: function(status) {
			prx = status === 200;
		},

		write: function(chunk) {
			if (prx) buffer.push(chunk);
		},

		end: function() {
			var code = buffer.join(''), lang, x;
			buffer.length = 0;

            var m = code.match(regz) || false;
			var l = m.length, i = 0, x;

			var autokey = file.moduleJSON.autokey;
			if (!options.autokey || typeof autokey !== 'string') {
				autokey = false;
			};

			var lang_old = langs[modID] || false;
			var lang_new = LNG[modID] || {};

			for(; i < l; i++)  {
				x = m[i];

				if (x.charCodeAt(0) !== 34) continue;

				try {
					x = JSON.parse(x)
				} catch (e) {
					//console.log('ups JSON.parse(lang)');
					continue;
				};

                if (!x || !x.trim()) continue;

                if (!lang_old[x]) {
					if (options.all == 'unicode' &&  !/[^\x00-\xff]/i.test(x) ) {
						continue;
					};

					if (options.all == 'ru' &&  !/[аА-яЯёЁ]/i.test(x) ) {
						continue;
					};
				};

				if (lang_new[x]) continue
				LNG[modID] = lang_new;

                var oldx = lang_old[x] || false;
                var newx = lang_new[x] = {};

                langsFor.forEach(function(lang) {
                    var value = oldx[lang];

                    if (autokey && typeof value === 'string') {
                        if (value[0] === '.') {
                            value = autokey + value;
                        };
                    };

                    newx[lang] = value != null ? value : null;
                });
			};

			if (!options.pure && typeof lang_old === 'object') { // ишем протухшие значения
				for(x in lang_old) {
					if (lang_old[x] && !lang_new[x]) {
						(lang_new[x] = lang_old[x]).deleted = true;
					};
				};
			};

			next();
		}
	};

	modscript(log, req, url
		, function(status, code, _files, _styles, _langs, _mdurl) {
			if (status !== true) {
				res.writeHead(404, {
					'content-type': 'application/x-javascript; charset=UTF-8'
				});

				res.end(log());
				return;
			};

			res.writeHead(200, {
				'content-type': 'application/x-javascript; charset=UTF-8'
			});

			files = _files;
			langs = _langs;
			mdurl = _mdurl;

			next();
		}
	);

	function next() {
		var i;

		do {
			i = ++file_index;

			if (i >= files.length || !files.length) {
				complite();
				return;
			};

			file = files[i];

		} while(!file);

		if (typeof file !== 'object') {
			complite();
			return;
		};

		if (!options.all && !langs[file.moduleID]) {
			return next();
		};

		if (file.js_inc) {
			return next();
		};

		var u
		, shead = ''
		, sfoot = ''
		, url = file.src
		, q = URL.parse(url)
		;

		modID = file.moduleID;

		if (q.protocol === 'http:' || q.protocol === 'https:') {
			if (!q.host || !/.\.[a-zA-Z]{2,7}$/.test(q.hostname) || /^\.|\.\.|[^\w\-\.]/.test(q.hostname)) {
				// res.write('\n\n/* ------ BAD: ' + url + ' */\n');
				log('error', 'bad host: ' + url );
				return next();
			};
		} else {
			if (q.protocol !== 'file:') {
				// res.write('\n\n/* ------ BAD: ' + url + ' */\n');
				log('error', 'bad protocol: ' + url );
				return next();
			};
		};

		file_proxy(url, xreq, xres, false, shead, sfoot);
	};

	function complite() {
		var r = {}, i, x;

		for (i in LNG) {
			if (typeof mdurl[i] === 'string') {
				r[xDelHost(mdurl[i])] = LNG[i];
				//r[mdurl[i]] = LNG[i];
			};
		};

		if (options.yaml) {
			res.write(yaml.safeDump(r, {indent: options.yaml}));
		} else {
			res.write(JSON.stringify(r, null, "\t"));
		};

		res.end();
	};

	var xStartHost = req.xStartHost;
	function xDelHost(x) {
		x = x + '';
		return xStartHost && x.substr(0, xStartHost.length) === xStartHost
			? x.substr(xStartHost.length)
			: x
		;
	};

};

<|endoftext|>


<commit_before>var store = require('../shared/Store.js');

module.exports = async function (context, req) {
    try {
        // store.verifyApiKey(context)
        // store.verifyToken(context)

        context.res = { status: 200, body: '' };
    } catch (err) {
        context.log.error('error:', err);
        context.res = { status: 400, body: `error: '${err.message}'` };
    }
}<commit_msg>Reenable check<commit_after>var store = require('../shared/Store.js');

module.exports = async function (context, req) {
    try {
        store.verifyApiKey(context)
        store.verifyToken(context)

        context.res = { status: 200, body: '' };
    } catch (err) {
        context.log.error('error:', err);
        context.res = { status: 400, body: `error: '${err.message}'` };
    }
}<|endoftext|>


<commit_before>function newMsg(msg){
	switch(msg._type){
		case "newMsg":
			insertMessage(msg._args[0],msg._args[1]);
			break;
		case "newUser":
			$('#users').append('
'+msg._args[0]+'
');
			break;
	}
}

<commit_msg>lista de users na mensagem "newUser"<commit_after>function newMsg(msg){
	switch(msg._type){
		case "newMsg":
			insertMessage(msg._args[0],msg._args[1]);
			break;
		case "newUser":
			jQuery.each(msg._args, function() {
				$('#users').append('
'+this+'
');
			});
			break;
	}
}

<|endoftext|>


<commit_before>angular.module('App.ServerRoutes', [])

.factory('ServerRoutes', function(){
  //return an object of the routes
  return {
  	//change the routes once our server is deployed.
    sendContent: 'http://votallyserve.azurewebsites.net/receivers/sendContent',
    getPending: 'http://votallyserve.azurewebsites.net/pending/getPending',
    sendVote: 'http://votallyserve.azurewebsites.net/pending/sendVote',
    getResults: 'http://votallyserve.azurewebsites.net/results/getResults',
    getReceivers: 'http://votallyserve.azurewebsites.net/receivers/getContacts',
    postContent: 'http://votallyserve.azurewebsites.net/receivers/sendContent',
    checkUpdates: 'http://votallyserve.azurewebsites.net/home/checkUpdates',
    checkFriendRequest: 'http://votallyserve.azurewebsites.net/friends/checkRequest',
    requestFriend: 'http://votallyserve.azurewebsites.net/friends/requestFriend',
    confirmFriend: 'http://votallyserve.azurewebsites.net/friends/confirmFriend',
    declineFriend: 'http://votallyserve.azurewebsites.net/friends/declineFriend'
  };
});
<commit_msg>(refactor) remove serverRoutes.sendcontent<commit_after>angular.module('App.ServerRoutes', [])

.factory('ServerRoutes', function(){
  //return an object of the routes
  return {
  	//change the routes once our server is deployed.
    getPending: 'http://votallyserve.azurewebsites.net/pending/getPending',
    sendVote: 'http://votallyserve.azurewebsites.net/pending/sendVote',
    getResults: 'http://votallyserve.azurewebsites.net/results/getResults',
    getReceivers: 'http://votallyserve.azurewebsites.net/receivers/getContacts',
    postContent: 'http://votallyserve.azurewebsites.net/receivers/sendContent',
    checkUpdates: 'http://votallyserve.azurewebsites.net/home/checkUpdates',
    checkFriendRequest: 'http://votallyserve.azurewebsites.net/friends/checkRequest',
    requestFriend: 'http://votallyserve.azurewebsites.net/friends/requestFriend',
    confirmFriend: 'http://votallyserve.azurewebsites.net/friends/confirmFriend',
    declineFriend: 'http://votallyserve.azurewebsites.net/friends/declineFriend'
  };
});
<|endoftext|>