<commit_before>const CBA = {

    DEBUG: true,

    getUUID: () => {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
            const r = Math.random() * 16 | 0;
            const v = c === 'x' ? r : (r & (0x3 | 0x8));
            return v.toString(16);
        });
    },

    collectComponents: () => {
        const object = new FormData();

        $('input.component, textarea.component, select').each(function() {
            const id = $(this).attr('id');

            if ($(this).attr('type') == 'file') {
                for (const file of $(this)[0].files) {
                    object.append(id, file);
                }
            } else if ($(this).attr('type') == 'checkbox') {
                if ($(this).is(':checked')) {
                    const value = $(this).val();
                    const name = $(this).attr('name');
                    object.append(`${name}[]`, value);
                }
            } else if ($(this).attr('type') == 'radio') {
                if ($(this).is(':checked')) {
                    const value = $(this).val();
                    const name = $(this).attr('name');
                    object.append(name, value);
                }
            } else if ($(this).is('select')) {
                if ($(this).attr('multiple')) {
                    for (const value of $(this).val()) {
                        object.append(`${id}[]`, value);
                    }
                } else {
                    object.append(id, $(this).val());
                }
            } else {
                let value = $(this).val();
                // jquery doesn't post empty lists
                if (value == false) {
                    value = '';
                }
                object.append(id, value);
            }
        });
        return object;
    },

    replaceHTML: result => {
        for (const html of result) {
            if ($(html[0]).hasClass('render')) {
                $(html[0]).replaceWith(html[1]);
            } else {
                $(html[0]).parents('.render:first').replaceWith(html[1]);
            }
        }
    },

    addMessages: messages => {
        for (const message of messages) {
            const id = CBA.getUUID();
            $('#messages').append(`<div class="ui large ${message.type} message" id="message-${id}">${message.text}</div>`);
            setTimeout(() => {
                $(`#message-${id}`).fadeOut(500, function() {
                    $(this).remove();
                });
            },
            3000);
        }
    },

    defaultAjaxAction: (element, event, handler) => {
        const data = CBA.collectComponents();
        try {
            data.append('source_id', event.originalEvent.dataTransfer.getData('text'));
        } catch (e) {}

        const elementId = element.attr('id');
        const componentId = element.attr('cid') || elementId;
        const componentValue = element.attr('component-value') || componentId;
        data.append('handler', handler);
        data.append('element_id', elementId);
        data.append('component_id', componentId);
        data.append('component_value', componentValue);
        data.append('csrfmiddlewaretoken', $('input[name=csrfmiddlewaretoken]').attr('value'));

        if (CBA.DEBUG) {
            console.log(data);
        }

        $.ajax({
            url: '',
            type: 'POST',
            data,
            processData: false,
            contentType: false,
            success: result => {
                CBA.replaceHTML(result.html);
                CBA.addMessages(result.messages);
            },
        });
    },

    defaultJSAction: (element, event, handler) => {
        const fn = CBA[handler];
        fn(element);
    },

    handleEvent: (element, event) => {
        const handlerString = element.attr(`${event.type}_handler`);
        const handler = handlerString.split(':');
        if (handler[0] === 'server') {
            CBA.defaultAjaxAction(element, event, handler[1]);
        } else if (handler[0] === 'client') {
            CBA.defaultJSAction(element, event, handler[1]);
        }
    },
};

// Register Events
$(() => {
    $('body').on('click', '.click', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    $('body').on('change', '.change', function(event) {
        // Unfortunately semantic-ui wraps the original select with a div and
        // copy its classes to this.
        let element = $(this);
        if ($(this).hasClass('dropdown')) {
            element = $(this).children('select:first');
        }
        CBA.handleEvent(element, event);
        return false;
    });

    $('body').on('mouseover', '.mouseover', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    $('body').on('mouseout', '.mouseout', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    $('body').on('keyup', '.keyup', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    // DnD: Stores id of the draggable component for later use
    $('body').on('dragstart', '.draggable', function(event) {
        event.originalEvent.dataTransfer.setData('text', event.target.id);
    });

    // DnD: handles drop event
    $('body').on('drop', '.droppable', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    // DnD: Allows drop
    $('body').on('dragover', '.droppable', function(event) {
        return false;
    });

    // Table Component: selects row if clicked.
    $('body').on('click', 'tr', function(event) {
        $(this).siblings('tr').removeClass('selected');
        $(this).addClass('selected');
    });

    // FileInput Component: toggles checkbox when the image is clicked.
    $('body').on('click', '.file-input img', function(event) {
        const checkbox = $(this).siblings('.checkbox').children('input');
        checkbox.prop('checked', !checkbox.prop('checked'));
    });
});
<commit_msg>Fix defaultJSAction<commit_after>const CBA = {

    DEBUG: true,

    getUUID: () => {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
            const r = Math.random() * 16 | 0;
            const v = c === 'x' ? r : (r & (0x3 | 0x8));
            return v.toString(16);
        });
    },

    collectComponents: () => {
        const object = new FormData();

        $('input.component, textarea.component, select').each(function() {
            const id = $(this).attr('id');

            if ($(this).attr('type') == 'file') {
                for (const file of $(this)[0].files) {
                    object.append(id, file);
                }
            } else if ($(this).attr('type') == 'checkbox') {
                if ($(this).is(':checked')) {
                    const value = $(this).val();
                    const name = $(this).attr('name');
                    object.append(`${name}[]`, value);
                }
            } else if ($(this).attr('type') == 'radio') {
                if ($(this).is(':checked')) {
                    const value = $(this).val();
                    const name = $(this).attr('name');
                    object.append(name, value);
                }
            } else if ($(this).is('select')) {
                if ($(this).attr('multiple')) {
                    for (const value of $(this).val()) {
                        object.append(`${id}[]`, value);
                    }
                } else {
                    object.append(id, $(this).val());
                }
            } else {
                let value = $(this).val();
                // jquery doesn't post empty lists
                if (value == false) {
                    value = '';
                }
                object.append(id, value);
            }
        });
        return object;
    },

    replaceHTML: result => {
        for (const html of result) {
            if ($(html[0]).hasClass('render')) {
                $(html[0]).replaceWith(html[1]);
            } else {
                $(html[0]).parents('.render:first').replaceWith(html[1]);
            }
        }
    },

    addMessages: messages => {
        for (const message of messages) {
            const id = CBA.getUUID();
            $('#messages').append(`<div class="ui large ${message.type} message" id="message-${id}">${message.text}</div>`);
            setTimeout(() => {
                $(`#message-${id}`).fadeOut(500, function() {
                    $(this).remove();
                });
            },
            3000);
        }
    },

    defaultAjaxAction: (element, event, handler) => {
        const data = CBA.collectComponents();
        try {
            data.append('source_id', event.originalEvent.dataTransfer.getData('text'));
        } catch (e) {}

        const elementId = element.attr('id');
        const componentId = element.attr('cid') || elementId;
        const componentValue = element.attr('component-value') || componentId;
        data.append('handler', handler);
        data.append('element_id', elementId);
        data.append('component_id', componentId);
        data.append('component_value', componentValue);
        data.append('csrfmiddlewaretoken', $('input[name=csrfmiddlewaretoken]').attr('value'));

        if (CBA.DEBUG) {
            console.log(data);
        }

        $.ajax({
            url: '',
            type: 'POST',
            data,
            processData: false,
            contentType: false,
            success: result => {
                CBA.replaceHTML(result.html);
                CBA.addMessages(result.messages);
            },
        });
    },

    defaultJSAction: (element, event, handler) => {
        const fn = window[handler];
        fn(element);
    },

    handleEvent: (element, event) => {
        const handlerString = element.attr(`${event.type}_handler`);
        const handler = handlerString.split(':');
        if (handler[0] === 'server') {
            CBA.defaultAjaxAction(element, event, handler[1]);
        } else if (handler[0] === 'client') {
            CBA.defaultJSAction(element, event, handler[1]);
        }
    },
};

// Register Events
$(() => {
    $('body').on('click', '.click', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    $('body').on('change', '.change', function(event) {
        // Unfortunately semantic-ui wraps the original select with a div and
        // copy its classes to this.
        let element = $(this);
        if ($(this).hasClass('dropdown')) {
            element = $(this).children('select:first');
        }
        CBA.handleEvent(element, event);
        return false;
    });

    $('body').on('mouseover', '.mouseover', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    $('body').on('mouseout', '.mouseout', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    $('body').on('keyup', '.keyup', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    // DnD: Stores id of the draggable component for later use
    $('body').on('dragstart', '.draggable', function(event) {
        event.originalEvent.dataTransfer.setData('text', event.target.id);
    });

    // DnD: handles drop event
    $('body').on('drop', '.droppable', function(event) {
        CBA.handleEvent($(this), event);
        return false;
    });

    // DnD: Allows drop
    $('body').on('dragover', '.droppable', function(event) {
        return false;
    });

    // Table Component: selects row if clicked.
    $('body').on('click', 'tr', function(event) {
        $(this).siblings('tr').removeClass('selected');
        $(this).addClass('selected');
    });

    // FileInput Component: toggles checkbox when the image is clicked.
    $('body').on('click', '.file-input img', function(event) {
        const checkbox = $(this).siblings('.checkbox').children('input');
        checkbox.prop('checked', !checkbox.prop('checked'));
    });
});
<|endoftext|>


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

import Tab from 'src/Tab';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import Toaster from 'src/Toaster';
import IconButton from 'src/IconButton';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Tab.json';

import 'scss/containers/app/modules/layout/TabExamples.scss';

class TabExamples extends Component {

    constructor(props) {

        super(props);

        this.state = {
            tabs: this.generateTabs(20),
            toasts: []
        };

    }

    activeHandler = tab => {

        const {toasts} = this.state;

        toasts.push({
            type: Toaster.Type.INFO,
            message: `${tab.value} Activated`
        });

        this.setState({
            toasts
        });

    };

    toastPopHandler = () => {
        this.setState({
            toasts: []
        });
    };

    generateTabs = length => {
        return Array.from({length}, (item, index) => ({
            id: index + 1,
            value: `Tab ${index + 1}`,
            renderer:
Tab {index + 1}

        }));
    };

    addTab = () => {

        const {tabs} = this.state,
            index = tabs.length + 1;

        tabs.push({
            id: index,
            value: `Tab ${index}`,
            renderer:
Tab {index}

        });

        this.setState({
            tabs
        });

    };

    handleScrollLeftButtonMouseDown = () => {
        console.log('scroll left button mouse down');
    };

    handleScrollRightButtonMouseDown = () => {
        console.log('scroll right button mouse down');
    };

    render() {

        const {tabs, toasts} = this.state;

        return (

Tabs

                    Tabs
                    make it easy to explore and switch between different views or functional aspects
                    of an app or to browse categorized data sets.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="Full Width Tabs Example"/>

                                    A simple example of Tabs. The third tab demonstrates the onActive property of Tab.

                                <Tab tabs={[{
                                    value: 'Tab 1',
                                    renderer:
Tab 1

                                }, {
                                    value: 'Tab 2',
                                    renderer:
Tab 2

                                }, {
                                    value: 'Tab 3',
                                    renderer:
onActive
,
                                    onActive: this.activeHandler
                                }, {
                                    value: 'Tab 4',
                                    disabled: true
                                }]}
                                     activatedIndex={1}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Tabs Example"/>

                                    Tabs use full container width by default.Set the isTabFullWidth property to false
                                    for partial width.

                                <Tab tabs={tabs}
                                     isTabFullWidth={false}
                                     isAnimated={false}
                                     draggable={true}
                                     idProp="id"
                                     tabsChildren={
                                         <IconButton className="tab-button customized-tab-button"
                                                     iconCls="fas fa-plus"
                                                     onClick={this.addTab}/>
                                     }
                                     onScrollLeftButtonMouseDown={this.handleScrollLeftButtonMouseDown}
                                     onScrollRightButtonMouseDown={this.handleScrollRightButtonMouseDown}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Tabs Example"/>

                                    Tabs without icons by default.Set the iconCls property for left icons.

                                <Tab tabs={[{
                                    value: 'Bicycle',
                                    iconCls: 'fas fa-bicycle',
                                    renderer:
Bicycle

                                }, {
                                    value: 'Taxi',
                                    iconCls: 'fas fa-taxi',
                                    renderer:
Taxi

                                }, {
                                    value: 'Plane',
                                    iconCls: 'fas fa-plane',
                                    renderer:
Plane

                                }, {
                                    value: 'Rocket',
                                    iconCls: 'fas fa-rocket',
                                    renderer:
Rocket

                                }]}
                                     isTabFullWidth={false}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Draggable"/>

                                    Tabs without icons by default.Set the iconCls property for left icons.

                                <Tab tabs={[{
                                    value: 'Bicycle',
                                    iconCls: 'fas fa-bicycle',
                                    renderer:
Bicycle

                                }, {
                                    value: 'Taxi',
                                    iconCls: 'fas fa-taxi',
                                    renderer:
Taxi

                                }, {
                                    value: 'Plane',
                                    iconCls: 'fas fa-plane',
                                    renderer:
Plane

                                }, {
                                    value: 'Rocket',
                                    iconCls: 'fas fa-rocket',
                                    renderer:
Rocket

                                }]}
                                     isTabFullWidth={false}
                                     isAnimated={false}
                                     draggable={true}/>

                </Widget>

                <Toaster toasts={toasts}
                         onToastPop={this.toastPopHandler}/>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
}

export default TabExamples;
<commit_msg>update TabExamples<commit_after>import React, {Component} from 'react';

import Tab from 'src/Tab';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import Toaster from 'src/Toaster';
import IconButton from 'src/IconButton';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Tab.json';

import 'scss/containers/app/modules/layout/TabExamples.scss';

class TabExamples extends Component {

    constructor(props) {

        super(props);

        this.state = {
            tabs: this.generateTabs(20),
            toasts: []
        };

    }

    activeHandler = tab => {

        const {toasts} = this.state;

        toasts.push({
            type: Toaster.Type.INFO,
            message: `${tab.value} Activated`
        });

        this.setState({
            toasts
        });

    };

    toastPopHandler = () => {
        this.setState({
            toasts: []
        });
    };

    generateTabs = length => {
        return Array.from({length}, (item, index) => ({
            id: index + 1,
            value: `Tab ${index + 1}`,
            tabContentRenderer:
Tab {index + 1}

        }));
    };

    addTab = () => {

        const {tabs} = this.state,
            index = tabs.length + 1;

        tabs.push({
            id: index,
            value: `Tab ${index}`,
            tabContentRenderer:
Tab {index}

        });

        this.setState({
            tabs
        });

    };

    handleScrollLeftButtonMouseDown = () => {
        console.log('scroll left button mouse down');
    };

    handleScrollRightButtonMouseDown = () => {
        console.log('scroll right button mouse down');
    };

    render() {

        const {tabs, toasts} = this.state;

        return (

Tabs

                    Tabs
                    make it easy to explore and switch between different views or functional aspects
                    of an app or to browse categorized data sets.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="Full Width Tabs Example"/>

                                    A simple example of Tabs. The third tab demonstrates the onActive property of Tab.

                                <Tab tabs={[{
                                    value: 'Tab 1',
                                    tabContentRenderer:
Tab 1

                                }, {
                                    value: 'Tab 2',
                                    tabContentRenderer:
Tab 2

                                }, {
                                    value: 'Tab 3',
                                    tabContentRenderer:
onActive
,
                                    onActive: this.activeHandler
                                }, {
                                    value: 'Tab 4',
                                    disabled: true
                                }]}
                                     activatedIndex={1}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Tabs Example"/>

                                    Tabs use full container width by default.Set the isTabFullWidth property to false
                                    for partial width.

                                <Tab tabs={tabs}
                                     isTabFullWidth={false}
                                     isAnimated={false}
                                     draggable={true}
                                     idProp="id"
                                     tabsChildren={
                                         <IconButton className="tab-button customized-tab-button"
                                                     iconCls="fas fa-plus"
                                                     onClick={this.addTab}/>
                                     }
                                     onScrollLeftButtonMouseDown={this.handleScrollLeftButtonMouseDown}
                                     onScrollRightButtonMouseDown={this.handleScrollRightButtonMouseDown}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Tabs Example"/>

                                    Tabs without icons by default.Set the iconCls property for left icons.

                                <Tab tabs={[{
                                    value: 'Bicycle',
                                    iconCls: 'fas fa-bicycle',
                                    tabContentRenderer:
Bicycle

                                }, {
                                    value: 'Taxi',
                                    iconCls: 'fas fa-taxi',
                                    tabContentRenderer:
Taxi

                                }, {
                                    value: 'Plane',
                                    iconCls: 'fas fa-plane',
                                    tabContentRenderer:
Plane

                                }, {
                                    value: 'Rocket',
                                    iconCls: 'fas fa-rocket',
                                    tabContentRenderer:
Rocket

                                }]}
                                     isTabFullWidth={false}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Draggable"/>

                                    Tabs without icons by default.Set the iconCls property for left icons.

                                <Tab tabs={[{
                                    value: 'Bicycle',
                                    iconCls: 'fas fa-bicycle',
                                    tabContentRenderer:
Bicycle

                                }, {
                                    value: 'Taxi',
                                    iconCls: 'fas fa-taxi',
                                    tabContentRenderer:
Taxi

                                }, {
                                    value: 'Plane',
                                    iconCls: 'fas fa-plane',
                                    tabContentRenderer:
Plane

                                }, {
                                    value: 'Rocket',
                                    iconCls: 'fas fa-rocket',
                                    tabContentRenderer:
Rocket

                                }]}
                                     isTabFullWidth={false}
                                     isAnimated={false}
                                     draggable={true}/>

                </Widget>

                <Toaster toasts={toasts}
                         onToastPop={this.toastPopHandler}/>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
}

export default TabExamples;
<|endoftext|>


<commit_before>function JiraAPI (baseUrl, apiExtension, username, password, jql) {

    var ACTIVE_REQUESTS = 0;

    var apiDefaults = {
        type: 'GET',
        url : baseUrl + apiExtension,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Basic ' + btoa(username + ':' + password)
        },
        responseType: 'json',
        data: ''
    };

    return {
        login : login,
        getIssue : getIssue,
        getIssues: getIssues,
        getIssueWorklog : getIssueWorklog,
        updateWorklog : updateWorklog
    };

    function login() {
        var url = '/user?username=' + username;
        var options = {
            headers: {
                'Authorization': 'Basic ' + btoa(username + ':' + password)
            }
        }
        return ajaxWrapper(url, options);
    };

    function getIssue (id) {
        return ajaxWrapper('/issue/' + id);
    }

    function getIssues () {
        return ajaxWrapper('/search?jql=' + jql);
    }

    function getIssueWorklog (id) {
        return ajaxWrapper('/issue/' + id + '/worklog');
    }

    function updateWorklog (id, timeSpent, date) {
        var url = '/issue/' + id + '/worklog';
        var options = {
            type: 'POST',
            data: JSON.stringify({
                "started": date.toISOString().replace('Z', '+0530'), // TODO: Quick fix - Problems with the timezone, investigate
                "timeSpent": timeSpent
            })
        }
        return ajaxWrapper(url, options);
    }

    function ajaxWrapper (urlExtension, optionsOverrides) {

        // merge default and override options
        var options = extend(apiDefaults, optionsOverrides || {});

        // concat url
        options.url += urlExtension;

        // return promise
        return new Promise(function(resolve, reject) {

            var req = new XMLHttpRequest();

            // open request
            req.open(options.type, options.url, true);

            // set response type (json)
            req.responseType = options.responseType;

            // on load logic
            req.onload = function() {

                // consider all statuses between 200 and 400 successful
                if (req.status >= 200 && req.status < 400) {
                    resolve(req.response);
                }
                // all other ones are considered to be errors
                else {
                    //reject(req.response, req.status, req.statusText);
                    reject({
                        response: req.response,
                        status: req.status,
                        statusText: req.statusText
                    });
                }

                // keep the count of active XMLHttpRequest objects
                if (!(--ACTIVE_REQUESTS)) {

                    //if it's 0 dispatch a global event
                    dispatchEvent('jiraStop', document);
                }

            };

            // Unpredicted error
            req.onerror = function() {
                reject({
                    response: undefined,
                    status: undefined,
                    statusText: 'Unknown Error'
                });
                dispatchEvent('jiraError', document);
            };

            // set all headers
            for(header in options.headers){
                req.setRequestHeader(header, options.headers[header]);
            }

            // send the request
            req.send(options.data);

            // increment the count of active XMLHttpRequest objects
            if (ACTIVE_REQUESTS++ === 0 ) {

                // if it's the first one in the queue, dispatch a global event
                dispatchEvent('jiraStart', document);
            }

        });

    }

    /*
        Helper functions
    */
    // Event dispatcher
    function dispatchEvent (name, element) {
        var event = new Event(name);
        element.dispatchEvent(event);
    }

    // Simple extend function
    function extend (target, overrides) {

        // new empty object
        var extended = Object.create(target);

        // copy all properties from default
        Object.keys(target).map(function (prop) {
            extended[prop] = target[prop];
        });

        // iterate through overrides
        Object.keys(overrides).map(function (prop) {

            // if the attribute is an object, extend it too
            if(typeof overrides[prop] === 'object'){
                extended[prop] = extend(extended[prop], overrides[prop]);
            }
            // otherwise just assign value to the extended object
            else{
                extended[prop] = overrides[prop];
            }
        });

        return extended;

    };

}
<commit_msg>reset +5.30 timezone offset to +00.00<commit_after>function JiraAPI (baseUrl, apiExtension, username, password, jql) {

    var ACTIVE_REQUESTS = 0;

    var apiDefaults = {
        type: 'GET',
        url : baseUrl + apiExtension,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Basic ' + btoa(username + ':' + password)
        },
        responseType: 'json',
        data: ''
    };

    return {
        login : login,
        getIssue : getIssue,
        getIssues: getIssues,
        getIssueWorklog : getIssueWorklog,
        updateWorklog : updateWorklog
    };

    function login() {
        var url = '/user?username=' + username;
        var options = {
            headers: {
                'Authorization': 'Basic ' + btoa(username + ':' + password)
            }
        }
        return ajaxWrapper(url, options);
    };

    function getIssue (id) {
        return ajaxWrapper('/issue/' + id);
    }

    function getIssues () {
        return ajaxWrapper('/search?jql=' + jql);
    }

    function getIssueWorklog (id) {
        return ajaxWrapper('/issue/' + id + '/worklog');
    }

    function updateWorklog (id, timeSpent, date) {
        var url = '/issue/' + id + '/worklog';
        var options = {
            type: 'POST',
            data: JSON.stringify({
                "started": date.toISOString().replace('Z', '+0000'), // TODO: Quick fix - Problems with the timezone, investigate
                "timeSpent": timeSpent
            })
        }
        return ajaxWrapper(url, options);
    }

    function ajaxWrapper (urlExtension, optionsOverrides) {

        // merge default and override options
        var options = extend(apiDefaults, optionsOverrides || {});

        // concat url
        options.url += urlExtension;

        // return promise
        return new Promise(function(resolve, reject) {

            var req = new XMLHttpRequest();

            // open request
            req.open(options.type, options.url, true);

            // set response type (json)
            req.responseType = options.responseType;

            // on load logic
            req.onload = function() {

                // consider all statuses between 200 and 400 successful
                if (req.status >= 200 && req.status < 400) {
                    resolve(req.response);
                }
                // all other ones are considered to be errors
                else {
                    //reject(req.response, req.status, req.statusText);
                    reject({
                        response: req.response,
                        status: req.status,
                        statusText: req.statusText
                    });
                }

                // keep the count of active XMLHttpRequest objects
                if (!(--ACTIVE_REQUESTS)) {

                    //if it's 0 dispatch a global event
                    dispatchEvent('jiraStop', document);
                }

            };

            // Unpredicted error
            req.onerror = function() {
                reject({
                    response: undefined,
                    status: undefined,
                    statusText: 'Unknown Error'
                });
                dispatchEvent('jiraError', document);
            };

            // set all headers
            for(header in options.headers){
                req.setRequestHeader(header, options.headers[header]);
            }

            // send the request
            req.send(options.data);

            // increment the count of active XMLHttpRequest objects
            if (ACTIVE_REQUESTS++ === 0 ) {

                // if it's the first one in the queue, dispatch a global event
                dispatchEvent('jiraStart', document);
            }

        });

    }

    /*
        Helper functions
    */
    // Event dispatcher
    function dispatchEvent (name, element) {
        var event = new Event(name);
        element.dispatchEvent(event);
    }

    // Simple extend function
    function extend (target, overrides) {

        // new empty object
        var extended = Object.create(target);

        // copy all properties from default
        Object.keys(target).map(function (prop) {
            extended[prop] = target[prop];
        });

        // iterate through overrides
        Object.keys(overrides).map(function (prop) {

            // if the attribute is an object, extend it too
            if(typeof overrides[prop] === 'object'){
                extended[prop] = extend(extended[prop], overrides[prop]);
            }
            // otherwise just assign value to the extended object
            else{
                extended[prop] = overrides[prop];
            }
        });

        return extended;

    };

}
<|endoftext|>


<commit_before>var expect = buster.assertions.expect;

buster.spec.expose();

describe("EnglishParser", function () {
  before(function () {
    this.ep = new EnglishParser();
  });

  describe("#getWords", function () {
    before(function () {
      this.words = ["foo", "bar", "baz"];
    });

    it("splits words regardless of spaces", function () {
      expect(this.ep.getWords("foo   \tbar   baz  ")).toEqual(this.words);
    });

    it("does not count a hyphen twice", function () {
      expect(this.ep.getWords("foo-bar")).toEqual(["foo-bar"]);
    });
  });

  it("determines the number of words", function () {
    expect(this.ep.getNumberWords("foo bar baz")).toEqual(3);
  });

  describe("#getSentences", function () {
    before(function () {
      this.ary = ["Foo", "Bar"];
    });

    it("splits sentences ending in periods", function () {
      expect(this.ep.getSentences("Foo. Bar.")).toEqual(this.ary);
    });

    it("splits sentences ending in question marks", function () {
      expect(this.ep.getSentences("Foo? Bar?")).toEqual(this.ary);
    });

    it("splits sentences ending in exclamation points", function () {
      expect(this.ep.getSentences("Foo! Bar.")).toEqual(this.ary);
    });

    it("handles one sentence", function () {
      expect(this.ep.getSentences("Foo!")).toEqual(["Foo"]);
    });

    it("handles repeated punctuation marks", function () {
      expect(this.ep.getSentences("Foo!!?!?!?! Bar?!?!?")).toEqual(this.ary);
    });

    it("returns an empty array when given null", function () {
      expect(this.ep.getSentences(null)).toEqual([]);
    });

    it("returns an empty array when given an empty string", function () {
      expect(this.ep.getSentences("")).toEqual([]);
    });
  });

  it("determines the number of sentences", function () {
    var text = "See Spot run! See Spot play!";
    expect(this.ep.getNumberSentences(text)).toEqual(2);
  });

  describe("#getNumberSyllables", function () {
    before(function () {
      this.f = this.ep.getNumberSyllables;
    });

    it("counts one character as one syllable", function () {
      expect(this.ep.getNumberSyllables("a")).toEqual(1);
    });

    it("counts two characters as one syllable", function () {
      expect(this.ep.getNumberSyllables("ab")).toEqual(1);
    });

    it("counts three characters as one syllable", function () {
      expect(this.ep.getNumberSyllables("abc")).toEqual(1);
    });

    it("counts two syllables in 'ruby'", function () {
      expect(this.ep.getNumberSyllables("ruby")).toEqual(2);
    });

    it("counts two syllables in 'races'", function () {
      expect(this.ep.getNumberSyllables("races")).toEqual(2);
    });

    it("counts three syllables in 'discomfit'", function () {
      expect(this.ep.getNumberSyllables("discomfit")).toEqual(3);
    });

    it("counts two syllables in 'handle'", function () {
      expect(this.ep.getNumberSyllables("handle")).toEqual(2);
    });

    it("counts two syllables in 'themselves'", function () {
      expect(this.ep.getNumberSyllables("themselves")).toEqual(2);
    });

    it("handles hypens", function () {
      expect(this.ep.getNumberSyllables("Jon-Michael")).toEqual(3);
    });
  });

  describe("#getNumberSyllablesInText", function () {
    it("returns 3 for 3 simple words", function () {
      var r = this.ep.getNumberSyllablesInText("foo bar baz");
      expect(r).toEqual(3);
    });
  });

  describe(".getGradeLevel", function () {
    it("handles harder sentences", function () {
      var text = "The Australian platypus is seemingly a hybrid of a mammal "
               + "and reptilian creature.";
      expect(EnglishParser.getGradeLevel(text)).toBeGreaterThan(11.0);
    });
  });

  describe(".getRoundedGradeLevel", function () {
    it("handles harder sentences", function () {
      var text = "The Australian platypus is seemingly a hybrid of a mammal "
               + "and reptilian creature.";
      expect(EnglishParser.getRoundedGradeLevel(text)).toEqual(11);
    });
  });
});
<commit_msg>Make JSLint happy (indentation)<commit_after>/*global buster: true, describe: true, it: true, before: true,
  EnglishParser: true*/

"use strict";
var expect = buster.assertions.expect;

buster.spec.expose();

describe("EnglishParser", function () {
    before(function () {
        this.ep = new EnglishParser();
    });

    describe("#getWords", function () {
        before(function () {
            this.words = ["foo", "bar", "baz"];
        });

        it("splits words regardless of spaces", function () {
            expect(this.ep.getWords("foo   \tbar   baz  ")).toEqual(this.words);
        });

        it("does not count a hyphen twice", function () {
            expect(this.ep.getWords("foo-bar")).toEqual(["foo-bar"]);
        });
    });

    it("determines the number of words", function () {
        expect(this.ep.getNumberWords("foo bar baz")).toEqual(3);
    });

    describe("#getSentences", function () {
        before(function () {
            this.ary = ["Foo", "Bar"];
        });

        it("splits sentences ending in periods", function () {
            expect(this.ep.getSentences("Foo. Bar.")).toEqual(this.ary);
        });

        it("splits sentences ending in question marks", function () {
            expect(this.ep.getSentences("Foo? Bar?")).toEqual(this.ary);
        });

        it("splits sentences ending in exclamation points", function () {
            expect(this.ep.getSentences("Foo! Bar.")).toEqual(this.ary);
        });

        it("handles one sentence", function () {
            expect(this.ep.getSentences("Foo!")).toEqual(["Foo"]);
        });

        it("handles repeated punctuation marks", function () {
            expect(this.ep.getSentences("Foo!!?!?!?! Bar?!?!?")).toEqual(this.ary);
        });

        it("returns an empty array when given null", function () {
            expect(this.ep.getSentences(null)).toEqual([]);
        });

        it("returns an empty array when given an empty string", function () {
            expect(this.ep.getSentences("")).toEqual([]);
        });
    });

    it("determines the number of sentences", function () {
        var text = "See Spot run! See Spot play!";
        expect(this.ep.getNumberSentences(text)).toEqual(2);
    });

    describe("#getNumberSyllables", function () {
        before(function () {
            this.f = this.ep.getNumberSyllables;
        });

        it("counts one character as one syllable", function () {
            expect(this.ep.getNumberSyllables("a")).toEqual(1);
        });

        it("counts two characters as one syllable", function () {
            expect(this.ep.getNumberSyllables("ab")).toEqual(1);
        });

        it("counts three characters as one syllable", function () {
            expect(this.ep.getNumberSyllables("abc")).toEqual(1);
        });

        it("counts two syllables in 'ruby'", function () {
            expect(this.ep.getNumberSyllables("ruby")).toEqual(2);
        });

        it("counts two syllables in 'races'", function () {
            expect(this.ep.getNumberSyllables("races")).toEqual(2);
        });

        it("counts three syllables in 'discomfit'", function () {
            expect(this.ep.getNumberSyllables("discomfit")).toEqual(3);
        });

        it("counts two syllables in 'handle'", function () {
            expect(this.ep.getNumberSyllables("handle")).toEqual(2);
        });

        it("counts two syllables in 'themselves'", function () {
            expect(this.ep.getNumberSyllables("themselves")).toEqual(2);
        });

        it("handles hypens", function () {
            expect(this.ep.getNumberSyllables("Jon-Michael")).toEqual(3);
        });
    });

    describe("#getNumberSyllablesInText", function () {
        it("returns 3 for 3 simple words", function () {
            var r = this.ep.getNumberSyllablesInText("foo bar baz");
            expect(r).toEqual(3);
        });
    });

    describe(".getGradeLevel", function () {
        it("handles harder sentences", function () {
            var text = "The Australian platypus is seemingly a hybrid of a mammal "
                     + "and reptilian creature.";
            expect(EnglishParser.getGradeLevel(text)).toBeGreaterThan(11.0);
        });
    });

    describe(".getRoundedGradeLevel", function () {
        it("handles harder sentences", function () {
            var text = "The Australian platypus is seemingly a hybrid of a mammal "
                     + "and reptilian creature.";
            expect(EnglishParser.getRoundedGradeLevel(text)).toEqual(11);
        });
    });
});
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Print component
 * Creates a AttributeList component
 * @author Roy Braam
 */
Ext.define ("viewer.components.Search",{
    extend: "viewer.components.Component",
    form: null,
    searchResult: null,
    results: null,
    margin: "0 5 0 0",
    autosuggestStore:null,
    searchField:null,
    resultPanelId: '',
    defaultFormHeight: MobileManager.isMobile() ? 100 : 90,
    searchRequestId: 0,
    config:{
        title: null,
        iconUrl: null,
        tooltip: null,
        searchconfigs: null,
        formHeight:null,
        label: "",
        //not yet configurable:
        zoomBoxSize: 200,
        typeZoomBoxSize: null,
        typeLabel:null
    },
    constructor: function (conf){
        if (conf.typeZoomBoxSize===undefined){
            conf.typeZoomBoxSize={
                Street: 200,
                MunicipalitySubdivision: 2000,
                Municipality: 5000,
                CountrySubdivision: 25000
            }
        }
        if (conf.typeLabel===undefined){
            conf.typeLabel={
                Street: 'Straat',
                MunicipalitySubdivision: 'Plaats',
                Municipality: 'Gemeente',
                CountrySubdivision: 'Provincie'
            }
        }
        viewer.components.Search.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        this.renderButton();
        this.loadWindow();
        return this;
    },
    renderButton: function() {
        var me = this;
        viewer.components.Search.superclass.renderButton.call(this,{
            text: me.title,
            icon: me.iconUrl,
            tooltip: me.tooltip,
            label: me.label,
            handler: function() {
                me.popup.show();
            }
        });
    },
    loadWindow : function(){
        var me = this;
        this.form = Ext.create("Ext.form.Panel",{
            frame: false,
            height: this.formHeight || this.defaultFormHeight,
            items: this.getFormItems(),
            border: 0,
            style: {
                padding: '0px 10px 0px 10px'
            }
        });
        this.resultPanelId = Ext.id();
        this.mainContainer = Ext.create('Ext.container.Container', {
            id: this.name + 'Container',
            width: '100%',
            height: '100%',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            style: {
                backgroundColor: 'White'
            },
            renderTo: this.getContentDiv(),
            items: [
                this.form, {
                    id: this.name + 'ContentPanel',
                    xtype: "container",
                    autoScroll: true,
                    width: '100%',
                    flex: 1,
                    html: '

'
                }, {
                    id: this.name + 'ClosingPanel',
                    xtype: "container",
                    width: '100%',
                    height: MobileManager.isMobile() ? 45 : 25,
                    style: {
                        marginTop: '10px',
                        marginRight: '5px'
                    },
                    layout: {
                        type:'hbox',
                        pack:'end'
                    },
                    items: [
                        {xtype: 'button', text: 'Sluiten', componentCls: 'mobileLarge', handler: function() {
                            me.popup.hide();
                        }}
                    ]
                }
            ]
        });
        this.form.getChildByElement("cancel"+ this.name).setVisible(false);
    },
    getFormItems: function(){
        var me = this;
        var itemList = new Array();
        if(this.searchconfigs ){
            if(this.searchconfigs.length === 1){
                itemList.push({
                    xtype: 'label',
                    text: 'Zoek op: '+ this.searchconfigs[0].name
                });
            }else if (this.searchconfigs.length > 1 ){
                var configs = Ext.create('Ext.data.Store', {
                    fields: ['id', 'name', 'url'],
                    data : this.searchconfigs
                });
                itemList.push({
                    xtype: "flamingocombobox",
                    fieldLabel: 'Zoek op',
                    store: configs,
                    queryMode: 'local',
                    displayField: 'name',
                    valueField: 'id',
                    anchor: '100%',
                    emptyText:'Maak uw keuze',
                    id: 'searchName' + this.name,
                    listeners:{
                        change:{
                            fn: function(combo, newValue){
                                this.searchConfigChanged(newValue);
                            },
                            scope:this
                        }
                    }
                });
            }
            if (this.searchconfigs.length> 0){
                this.autosuggestStore = Ext.create(Ext.data.Store,  {
                    autoLoad: false,
                    model: 'Doc',
                    proxy: {
                        type: 'ajax',
                        url: actionBeans["autosuggest"],
                        reader: {
                            type: 'json',
                            root: 'response.docs'
                        }
                    }
                });
                this.searchField = Ext.create( Ext.form.field.ComboBox,{
                    name: 'searchfield',
                    hideTrigger: true,
                    anchor: '100%',
                    triggerAction: 'query',
                    queryParam: "searchText",
                    displayField: "suggestion",
                    queryMode: this.searchconfigs.length === 1 && this.searchconfigs[0].type === "solr" ? "remote" : "local",
                    id: 'searchfield' + this.name,
                    minChars: 2,
                    listeners: {
                        specialkey: function(field, e){
                            if (e.getKey() === e.ENTER) {
                                me.search();
                            }
                        }
                    },
                    store:this.autosuggestStore
                });
                itemList.push(this.searchField);

                itemList.push({
                    xtype: 'button',
                    text: 'Zoeken',
                    componentCls: 'mobileLarge',
                    margin: this.margin,
                    listeners: {
                        click:{
                            scope: this,
                            fn: this.search
                        }
                    }
                });
            }
        }
        itemList.push({
            xtype: 'button',
            text: 'Zoekactie afbreken',
            margin: this.margin,
            componentCls: 'mobileLarge',
            name: 'cancel',
            id: 'cancel'+ this.name,
            listeners: {
                click:{
                    scope: this,
                    fn: this.cancel
                }
            }
        });
        return itemList;
    },
    hideWindow : function(){
        this.popup.hide();
    },
    search : function(){
        this.searchRequestId++;
        if(this.results !== null){
            this.results.destroy();
        }
        var searchText = this.form.getChildByElement("searchfield" + this.name).getValue();
        var searchName = '';
        if(this.searchconfigs.length === 1){
            searchName = this.searchconfigs[0].id;
        }else{
            searchName = this.form.getChildByElement("searchName" + this.name).getValue();
        }

        if(searchName !== null && searchText !== ""){
            var requestPath=  contextPath+"/action/search";
           var requestParams = {};

            requestParams["searchText"]= searchText;
            requestParams["searchName"]= searchName;
            requestParams["appId"]= appId;
            requestParams["componentName"]= this.name;
            requestParams["searchRequestId"]= this.searchRequestId;
            var me = this;
            me.mainContainer.setLoading({
                msg: 'Bezig met zoeken'
            });
            Ext.Ajax.request({
                url: requestPath,
                params: requestParams,
                success: function ( result, request ) {
                    var response = Ext.JSON.decode(result.responseText);
                    me.searchResult = response.results;
                    if (response.error){
                        Ext.MessageBox.alert("Foutmelding", response.error);
                    }
                    if (me.searchRequestId===response.request.searchRequestId){
                        me.showSearchResults();
                    }
                    me.mainContainer.setLoading(false);
                },
                failure: function(result, request) {
                    var response = Ext.JSON.decode(result.responseText);
                    Ext.MessageBox.alert("Foutmelding", response.error);
                    me.mainContainer.setLoading(false);
                }
            });
            this.form.getChildByElement("cancel"+ this.name).setVisible(true);
        } else {
            Ext.MessageBox.alert("Foutmelding", "Alle velden dienen ingevult te worden.");
            // search request is not complete
        }
    },
    showSearchResults : function(){
        var html = "";
        if(this.searchResult.length <= 0){
            html = "
Er zijn geen resultaten gevonden.
";
        }
        var me = this;
        this.form.getChildByElement("cancel"+ this.name).setVisible(false);
        var buttonList = new Array();
        for ( var i = 0 ; i < this.searchResult.length ; i ++){
            var result = this.searchResult[i];
            var typeLabel = this.typeLabel[result.type];

            buttonList.push({
                text: result.label + (typeLabel!==undefined ? " ("+typeLabel+")" : ""),
                xtype: 'button',
                margin: '10px 10px 0px 10px',
                componentCls: 'mobileLarge',
                tooltip: 'Zoom naar locatie',
                id: "searchButton_"+i,
                listeners: {
                    click:{
                        scope: me,
                        fn: function(button,e,eOpts){
                            //get index
                            var loc = this.searchResult[button.id.split("_")[1]].location;
                            var type = this.searchResult[button.id.split("_")[1]].type;
                            me.handleSearchResult(loc,type);
                        }
                    }
                }
            });
        }

        me.results = Ext.create('Ext.form.Panel', {
            title: 'Resultaten:',
            renderTo: this.resultPanelId,
            html: html,
            height: '100%',
            autoScroll: true,
            style: {
                padding: '0px 0px 10px 0px'
            },
            items: buttonList
        });

    },
    cancel : function(){
        this.form.getChildByElement("searchfield"+ this.name).setValue("");
        this.form.getChildByElement("searchName"+ this.name).setValue("");
        this.form.getChildByElement("cancel"+ this.name).setVisible(false);
        this.results.destroy();
    },
    handleSearchResult : function(location,type){
        var newExtent = new Object();
        var zoomBoxSize=this.getZoomBoxSize()/2;
        if (this.typeZoomBoxSize && this.typeZoomBoxSize[type]){
            zoomBoxSize=this.typeZoomBoxSize[type];
        }
        newExtent.minx=location.x-zoomBoxSize;
        newExtent.miny=location.y-zoomBoxSize;
        newExtent.maxx=location.x+zoomBoxSize;
        newExtent.maxy=location.y+zoomBoxSize;
        this.viewerController.mapComponent.getMap().zoomToExtent(newExtent);
        this.viewerController.mapComponent.getMap().removeMarker("searchmarker");
        this.viewerController.mapComponent.getMap().setMarker("searchmarker",location.x,location.y,"marker");
        this.popup.hide();
    },
    getExtComponents: function() {
        var c = [ this.mainContainer.getId(), this.form.getId() ];
        if(this.results) c.push(this.results.getId());
        return c;
    },
    searchConfigChanged: function(searchConfig){
        for(var i = 0 ; i < this.searchconfigs.length ;i++){
            var config = this.searchconfigs[i];
            if(config.id === searchConfig){
                if(config.type === "solr"){
                    this.searchField.queryMode = "remote";
                }else{
                    this.searchField.queryMode = "local";
                    this.searchField.getStore().removeAll();
                }
                break;
            }
        }
    }
});

 Ext.define('Doc', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'suggestion', type: 'string'}
        ]
    });
    Ext.define('Response', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'numFound', type: 'int'},
            {name: 'start', type: 'int'},
            {name: 'maxScore', type: 'float'},
            {name: 'docs', type: 'Doc'}
        ]
    });
<commit_msg>Searchrequestid comparator not checking for type. Fixes not showing results.<commit_after>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Print component
 * Creates a AttributeList component
 * @author Roy Braam
 */
Ext.define ("viewer.components.Search",{
    extend: "viewer.components.Component",
    form: null,
    searchResult: null,
    results: null,
    margin: "0 5 0 0",
    autosuggestStore:null,
    searchField:null,
    resultPanelId: '',
    defaultFormHeight: MobileManager.isMobile() ? 100 : 90,
    searchRequestId: 0,
    config:{
        title: null,
        iconUrl: null,
        tooltip: null,
        searchconfigs: null,
        formHeight:null,
        label: "",
        //not yet configurable:
        zoomBoxSize: 200,
        typeZoomBoxSize: null,
        typeLabel:null
    },
    constructor: function (conf){
        if (conf.typeZoomBoxSize===undefined){
            conf.typeZoomBoxSize={
                Street: 200,
                MunicipalitySubdivision: 2000,
                Municipality: 5000,
                CountrySubdivision: 25000
            }
        }
        if (conf.typeLabel===undefined){
            conf.typeLabel={
                Street: 'Straat',
                MunicipalitySubdivision: 'Plaats',
                Municipality: 'Gemeente',
                CountrySubdivision: 'Provincie'
            }
        }
        viewer.components.Search.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        this.renderButton();
        this.loadWindow();
        return this;
    },
    renderButton: function() {
        var me = this;
        viewer.components.Search.superclass.renderButton.call(this,{
            text: me.title,
            icon: me.iconUrl,
            tooltip: me.tooltip,
            label: me.label,
            handler: function() {
                me.popup.show();
            }
        });
    },
    loadWindow : function(){
        var me = this;
        this.form = Ext.create("Ext.form.Panel",{
            frame: false,
            height: this.formHeight || this.defaultFormHeight,
            items: this.getFormItems(),
            border: 0,
            style: {
                padding: '0px 10px 0px 10px'
            }
        });
        this.resultPanelId = Ext.id();
        this.mainContainer = Ext.create('Ext.container.Container', {
            id: this.name + 'Container',
            width: '100%',
            height: '100%',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            style: {
                backgroundColor: 'White'
            },
            renderTo: this.getContentDiv(),
            items: [
                this.form, {
                    id: this.name + 'ContentPanel',
                    xtype: "container",
                    autoScroll: true,
                    width: '100%',
                    flex: 1,
                    html: '

'
                }, {
                    id: this.name + 'ClosingPanel',
                    xtype: "container",
                    width: '100%',
                    height: MobileManager.isMobile() ? 45 : 25,
                    style: {
                        marginTop: '10px',
                        marginRight: '5px'
                    },
                    layout: {
                        type:'hbox',
                        pack:'end'
                    },
                    items: [
                        {xtype: 'button', text: 'Sluiten', componentCls: 'mobileLarge', handler: function() {
                            me.popup.hide();
                        }}
                    ]
                }
            ]
        });
        this.form.getChildByElement("cancel"+ this.name).setVisible(false);
    },
    getFormItems: function(){
        var me = this;
        var itemList = new Array();
        if(this.searchconfigs ){
            if(this.searchconfigs.length === 1){
                itemList.push({
                    xtype: 'label',
                    text: 'Zoek op: '+ this.searchconfigs[0].name
                });
            }else if (this.searchconfigs.length > 1 ){
                var configs = Ext.create('Ext.data.Store', {
                    fields: ['id', 'name', 'url'],
                    data : this.searchconfigs
                });
                itemList.push({
                    xtype: "flamingocombobox",
                    fieldLabel: 'Zoek op',
                    store: configs,
                    queryMode: 'local',
                    displayField: 'name',
                    valueField: 'id',
                    anchor: '100%',
                    emptyText:'Maak uw keuze',
                    id: 'searchName' + this.name,
                    listeners:{
                        change:{
                            fn: function(combo, newValue){
                                this.searchConfigChanged(newValue);
                            },
                            scope:this
                        }
                    }
                });
            }
            if (this.searchconfigs.length> 0){
                this.autosuggestStore = Ext.create(Ext.data.Store,  {

                    autoLoad: false,
                    model: 'Doc',
                    proxy: {
                        type: 'ajax',
                        url: actionBeans["autosuggest"],
                        reader: {
                            type: 'json',
                            root: 'response.docs'
                        }
                    }
                });
                this.searchField = Ext.create( Ext.form.field.ComboBox,{
                    name: 'searchfield',
                    hideTrigger: true,
                    anchor: '100%',
                    triggerAction: 'query',
                    queryParam: "searchText",
                    displayField: "suggestion",
                    queryMode: this.searchconfigs.length === 1 && this.searchconfigs[0].type === "solr" ? "remote" : "local",
                    id: 'searchfield' + this.name,
                    minChars: 2,
                    listeners: {
                        specialkey: function(field, e){
                            if (e.getKey() === e.ENTER) {
                                me.search();
                            }
                        }
                    },
                    store:this.autosuggestStore
                });
                itemList.push(this.searchField);

                itemList.push({
                    xtype: 'button',
                    text: 'Zoeken',
                    componentCls: 'mobileLarge',
                    margin: this.margin,
                    listeners: {
                        click:{
                            scope: this,
                            fn: this.search
                        }
                    }
                });
            }
        }
        itemList.push({
            xtype: 'button',
            text: 'Zoekactie afbreken',
            margin: this.margin,
            componentCls: 'mobileLarge',
            name: 'cancel',
            id: 'cancel'+ this.name,
            listeners: {
                click:{
                    scope: this,
                    fn: this.cancel
                }
            }
        });
        return itemList;
    },
    hideWindow : function(){
        this.popup.hide();
    },
    search : function(){
        this.searchRequestId++;
        if(this.results != null){
            this.results.destroy();
        }
        var searchText = this.form.getChildByElement("searchfield" + this.name).getValue();
        var searchName = '';
        if(this.searchconfigs.length === 1){
            searchName = this.searchconfigs[0].id;
        }else{
            searchName = this.form.getChildByElement("searchName" + this.name).getValue();
        }

        if(searchName !== null && searchText !== ""){
            var requestPath=  contextPath+"/action/search";
           var requestParams = {};

            requestParams["searchText"]= searchText;
            requestParams["searchName"]= searchName;
            requestParams["appId"]= appId;
            requestParams["componentName"]= this.name;
            requestParams["searchRequestId"]= this.searchRequestId;
            var me = this;
            me.mainContainer.setLoading({
                msg: 'Bezig met zoeken'
            });
            Ext.Ajax.request({
                url: requestPath,
                params: requestParams,
                success: function ( result, request ) {
                    var response = Ext.JSON.decode(result.responseText);
                    me.searchResult = response.results;
                    if (response.error){
                        Ext.MessageBox.alert("Foutmelding", response.error);
                    }
                    if (me.searchRequestId==response.request.searchRequestId){
                        me.showSearchResults();
                    }
                    me.mainContainer.setLoading(false);
                },
                failure: function(result, request) {
                    var response = Ext.JSON.decode(result.responseText);
                    Ext.MessageBox.alert("Foutmelding", response.error);
                    me.mainContainer.setLoading(false);
                }
            });
            this.form.getChildByElement("cancel"+ this.name).setVisible(true);
        } else {
            Ext.MessageBox.alert("Foutmelding", "Alle velden dienen ingevult te worden.");
            // search request is not complete
        }
    },
    showSearchResults : function(){
        var html = "";
        if(this.searchResult.length <= 0){
            html = "
Er zijn geen resultaten gevonden.
";
        }
        var me = this;
        this.form.getChildByElement("cancel"+ this.name).setVisible(false);
        var buttonList = new Array();
        for ( var i = 0 ; i < this.searchResult.length ; i ++){
            var result = this.searchResult[i];
            var typeLabel = this.typeLabel[result.type];

            buttonList.push({
                text: result.label + (typeLabel!==undefined ? " ("+typeLabel+")" : ""),
                xtype: 'button',
                margin: '10px 10px 0px 10px',
                componentCls: 'mobileLarge',
                tooltip: 'Zoom naar locatie',
                id: "searchButton_"+i,
                listeners: {
                    click:{
                        scope: me,
                        fn: function(button,e,eOpts){
                            //get index
                            var loc = this.searchResult[button.id.split("_")[1]].location;
                            var type = this.searchResult[button.id.split("_")[1]].type;
                            me.handleSearchResult(loc,type);
                        }
                    }
                }
            });
        }

        me.results = Ext.create('Ext.form.Panel', {
            title: 'Resultaten:',
            renderTo: this.resultPanelId,
            html: html,
            height: '100%',
            autoScroll: true,
            style: {
                padding: '0px 0px 10px 0px'
            },
            items: buttonList
        });

    },
    cancel : function(){
        this.form.getChildByElement("searchfield"+ this.name).setValue("");
        this.form.getChildByElement("searchName"+ this.name).setValue("");
        this.form.getChildByElement("cancel"+ this.name).setVisible(false);
        this.results.destroy();
    },
    handleSearchResult : function(location,type){
        var newExtent = new Object();
        var zoomBoxSize=this.getZoomBoxSize()/2;
        if (this.typeZoomBoxSize && this.typeZoomBoxSize[type]){
            zoomBoxSize=this.typeZoomBoxSize[type];
        }
        newExtent.minx=location.x-zoomBoxSize;
        newExtent.miny=location.y-zoomBoxSize;
        newExtent.maxx=location.x+zoomBoxSize;
        newExtent.maxy=location.y+zoomBoxSize;
        this.viewerController.mapComponent.getMap().zoomToExtent(newExtent);
        this.viewerController.mapComponent.getMap().removeMarker("searchmarker");
        this.viewerController.mapComponent.getMap().setMarker("searchmarker",location.x,location.y,"marker");
        this.popup.hide();
    },
    getExtComponents: function() {
        var c = [ this.mainContainer.getId(), this.form.getId() ];
        if(this.results) c.push(this.results.getId());
        return c;
    },
    searchConfigChanged: function(searchConfig){
        for(var i = 0 ; i < this.searchconfigs.length ;i++){
            var config = this.searchconfigs[i];
            if(config.id === searchConfig){
                if(config.type === "solr"){
                    this.searchField.queryMode = "remote";
                    var proxy = this.searchField.getStore().getProxy();
                    var params = proxy.extraParams;
                    params["searchName"]=searchConfig;
                     params["appId"]=appId;
                     params["componentName"]=this.name;

                }else{
                    this.searchField.queryMode = "local";
                    this.searchField.getStore().removeAll();
                }
                break;
            }
        }
    }
});

 Ext.define('Doc', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'suggestion', type: 'string'}
        ]
    });
    Ext.define('Response', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'numFound', type: 'int'},
            {name: 'start', type: 'int'},
            {name: 'maxScore', type: 'float'},
            {name: 'docs', type: 'Doc'}
        ]
    });
<|endoftext|>


<commit_before>var Transaction = require('./transaction')
var request = require('../lib/transport')
var logger = require('../lib/logger')

var Instrumentation = function () {
  this._queue = []
  this.scheduler = setInterval(this._dispatch.bind(this), 5000)
}

Instrumentation.prototype.add = function (transaction) {
  this._queue.push(transaction)
}

Instrumentation.prototype.startTransaction = function (name, type) {
  return new Transaction(this, name, type)
}

Instrumentation.prototype._flush = function () {
  this._queue = []
}

Instrumentation.prototype._dispatch = function () {
  logger.log('Instrumentation.scheduler._dispatch', this._queue.length)

  if (!this._queue.length) {
    return
  }

  var transactions = this._formatTransactions()
  var flush = this._flush.bind(this)

  request.sendTransaction(transactions).then(flush, flush)
}

Instrumentation.prototype._formatTransactions = function () {
  var transactions = groupTransactions(this._queue)

  var traces = [].concat.apply([], this._queue.map(function (trans) {
    return trans.traces
  }))

  var groupedTraces = groupTraces(traces)
  var groupedTracesTimings = getRawGroupedTracesTimings(traces, groupedTraces)

  return {
    transactions: transactions,
    traces: {
      groups: groupedTraces,
      raw: groupedTracesTimings
    }
  }
}

function groupTransactions (transactions) {
  var groups = grouper(transactions, transactionGroupingKey)

  return Object.keys(groups).map(function (key) {
    var trans = groups[key][0]
    var durations = groups[key].map(function (trans) {
      return trans.duration()
    })
    return {
      transaction: trans.name,
      result: trans.result,
      kind: trans.type,
      timestamp: groupingTs(trans._startStamp).toISOString(),
      durations: durations
    }
  })
}

function getRawGroupedTracesTimings (traces, groupedTraces) {
  var getTraceGroupIndex = function (col, item) {
    var index = 0
    var targetGroup = traceGroupingKey(item)

    col.forEach(function (item, i) {
      if (item._group === targetGroup) {
        index = i
      }
    })

    return index
  }

  var groupedByTransaction = grouper(traces, function (trace) {
    return trace.transaction.name
  })

  return Object.keys(groupedByTransaction).map(function (key) {
    var traces = groupedByTransaction[key]
    var transaction = traces[0].transaction

    var data = [transaction.duration()]

    traces.forEach(function (trace) {
      var groupIndex = getTraceGroupIndex(groupedTraces, trace)
      data.push([groupIndex, trace._start - transaction._start, trace.duration()])
    })

    return data
  })
}

function groupTraces (traces) {
  var groupedByMinute = grouper(traces, traceGroupingKey)

  return Object.keys(groupedByMinute).map(function (key) {
    var trace = groupedByMinute[key][0]

    var startTime = trace._start
    if (trace.transaction) {
      startTime = startTime - trace.transaction._start
    } else {
      startTime = 0
    }

    return {
      transaction: trace.transaction.name,
      signature: trace.signature,
      kind: trace.type,
      timestamp: trace._startStamp.toISOString(),
      parents: trace.ancestors(),
      extra: {
        _frames: trace.frames
      },
      _group: key
    }
  }).sort(function (a, b) {
    return a.start_time - b.start_time
  })
}

function grouper (arr, func) {
  var groups = {}

  arr.forEach(function (obj) {
    var key = func(obj)
    if (key in groups) {
      groups[key].push(obj)
    } else {
      groups[key] = [obj]
    }

    obj._traceGroup = key
  })

  return groups
}

function groupingTs (ts) {
  return new Date(ts.getFullYear(), ts.getMonth(), ts.getDate(), ts.getHours(), ts.getMinutes())
}

function transactionGroupingKey (trans) {
  return [
    groupingTs(trans._startStamp).getTime(),
    trans.name,
    trans.result,
    trans.type
  ].join('-')
}

function traceGroupingKey (trace) {
  var ancestors = trace.ancestors().map(function (trace) {
    return trace.signature
  }).join(',')

  return [
    groupingTs(trace._startStamp).getTime(),
    trace.transaction.name,
    ancestors,
    trace.signature,
    trace.type
  ].join('-')
}

module.exports = Instrumentation
<commit_msg>Use transaction name + transaction start as grouping keys<commit_after>var Transaction = require('./transaction')
var request = require('../lib/transport')
var logger = require('../lib/logger')

var Instrumentation = function () {
  this._queue = []
  this.scheduler = setInterval(this._dispatch.bind(this), 5000)
}

Instrumentation.prototype.add = function (transaction) {
  this._queue.push(transaction)
}

Instrumentation.prototype.startTransaction = function (name, type) {
  return new Transaction(this, name, type)
}

Instrumentation.prototype._flush = function () {
  this._queue = []
}

Instrumentation.prototype._dispatch = function () {
  logger.log('Instrumentation.scheduler._dispatch', this._queue.length)

  if (!this._queue.length) {
    return
  }

  var transactions = this._formatTransactions()
  var flush = this._flush.bind(this)

  request.sendTransaction(transactions).then(flush, flush)
}

Instrumentation.prototype._formatTransactions = function () {
  var transactions = groupTransactions(this._queue)

  var traces = [].concat.apply([], this._queue.map(function (trans) {
    return trans.traces
  }))

  var groupedTraces = groupTraces(traces)
  var groupedTracesTimings = getRawGroupedTracesTimings(traces, groupedTraces)

  return {
    transactions: transactions,
    traces: {
      groups: groupedTraces,
      raw: groupedTracesTimings
    }
  }
}

function groupTransactions (transactions) {
  var groups = grouper(transactions, transactionGroupingKey)

  return Object.keys(groups).map(function (key) {
    var trans = groups[key][0]
    var durations = groups[key].map(function (trans) {
      return trans.duration()
    })
    return {
      transaction: trans.name,
      result: trans.result,
      kind: trans.type,
      timestamp: groupingTs(trans._startStamp).toISOString(),
      durations: durations
    }
  })
}

function getRawGroupedTracesTimings (traces, groupedTraces) {
  var getTraceGroupIndex = function (col, item) {
    var index = 0
    var targetGroup = traceGroupingKey(item)

    col.forEach(function (item, i) {
      if (item._group === targetGroup) {
        index = i
      }
    })

    return index
  }

  var groupedByTransaction = grouper(traces, function (trace) {
    return trace.transaction.name + '|' + trace.transaction._start
  })

  return Object.keys(groupedByTransaction).map(function (key) {
    var traces = groupedByTransaction[key]
    var transaction = traces[0].transaction

    var data = [transaction.duration()]

    traces.forEach(function (trace) {
      var groupIndex = getTraceGroupIndex(groupedTraces, trace)
      data.push([groupIndex, trace._start - transaction._start, trace.duration()])
    })

    return data
  })
}

function groupTraces (traces) {
  var groupedByMinute = grouper(traces, traceGroupingKey)

  return Object.keys(groupedByMinute).map(function (key) {
    var trace = groupedByMinute[key][0]

    var startTime = trace._start
    if (trace.transaction) {
      startTime = startTime - trace.transaction._start
    } else {
      startTime = 0
    }

    return {
      transaction: trace.transaction.name,
      signature: trace.signature,
      kind: trace.type,
      timestamp: trace._startStamp.toISOString(),
      parents: trace.ancestors(),
      extra: {
        _frames: trace.frames
      },
      _group: key
    }
  }).sort(function (a, b) {
    return a.start_time - b.start_time
  })
}

function grouper (arr, func) {
  var groups = {}

  arr.forEach(function (obj) {
    var key = func(obj)
    if (key in groups) {
      groups[key].push(obj)
    } else {
      groups[key] = [obj]
    }

    obj._traceGroup = key
  })

  return groups
}

function groupingTs (ts) {
  return new Date(ts.getFullYear(), ts.getMonth(), ts.getDate(), ts.getHours(), ts.getMinutes())
}

function transactionGroupingKey (trans) {
  return [
    groupingTs(trans._startStamp).getTime(),
    trans.name,
    trans.result,
    trans.type
  ].join('-')
}

function traceGroupingKey (trace) {
  var ancestors = trace.ancestors().map(function (trace) {
    return trace.signature
  }).join(',')

  return [
    groupingTs(trace._startStamp).getTime(),
    trace.transaction.name,
    ancestors,
    trace.signature,
    trace.type
  ].join('-')
}

module.exports = Instrumentation
<|endoftext|>


<commit_before>import { DNAComponent } from './dna-component.js';
import {
    dashToCamel,
    getDescriptor,
    wrapDescriptorGet,
    wrapDescriptorSet,
} from './dna-helper.js';

/**
 * Simple Custom Component for properties initialization via attributes.
 * @class DNAPropertiesComponent
 * @extends DNAComponent
 *
 * @example
 * my-component.js
 * ```js
 * import { DNAPropertiesComponent } from 'dna/component';
 * export class MyComponent extends DNAPropertiesComponent {
 *   get properties() {
 *     return ['name'];
 *   }
 * }
 * ```
 * app.js
 * ```js
 * import { Register } from 'dna/component';
 * import { MyComponent } from './components/my-component/my-component.js';
 * var MyElement = Register('my-component', { prototype: MyComponent });
 * var temp = document.createElement('div');
 * temp.innerHTML = '<my-component name="Albert"></my-component>';
 * var element = temp.firstChild;
 * console.log(element.name); // logs "Albert"
 * ```
 */
export class DNAPropertiesComponent extends DNAComponent {
    /**
     * Fires when an the element is registered.
     */
    static onRegister() {
        let propertiesToWatch = this.properties || [];
        propertiesToWatch.forEach((prop) => {
            let descriptor = getDescriptor(this.prototype, prop) || {};
            Object.defineProperty(this.prototype, prop, {
                configurable: true,
                get: wrapDescriptorGet(prop, descriptor),
                set: wrapDescriptorSet(prop, descriptor),
            });
        });
    }
    /**
     * On `created` callback, apply attributes to properties.
     */
    createdCallback() {
        super.createdCallback();
        let attributes = Array.prototype.slice.call(this.attributes || [], 0);
        let properties = this.constructor.properties || [];
        for (let i = 0, len = attributes.length; i < len; i++) {
            let attr = attributes[i];
            let key = dashToCamel(attr.name);
            if (properties.indexOf(key) !== -1) {
                let value = attr.value;
                this.removeAttribute(attr.name);
                if (value === '') {
                    this[key] = true;
                } else {
                    try {
                        this[key] = JSON.parse(value);
                    } catch (ex) {
                        this[key] = value;
                    }
                }
            }
        }
    }
}
<commit_msg>fix: do not use constructor property to retrieve component's properties<commit_after>import { DNAComponent } from './dna-component.js';
import {
    dashToCamel,
    getDescriptor,
    wrapDescriptorGet,
    wrapDescriptorSet,
} from './dna-helper.js';

const PROPERTIES_CACHE = {};

/**
 * Simple Custom Component for properties initialization via attributes.
 * @class DNAPropertiesComponent
 * @extends DNAComponent
 *
 * @example
 * my-component.js
 * ```js
 * import { DNAPropertiesComponent } from 'dna/component';
 * export class MyComponent extends DNAPropertiesComponent {
 *   get properties() {
 *     return ['name'];
 *   }
 * }
 * ```
 * app.js
 * ```js
 * import { Register } from 'dna/component';
 * import { MyComponent } from './components/my-component/my-component.js';
 * var MyElement = Register('my-component', { prototype: MyComponent });
 * var temp = document.createElement('div');
 * temp.innerHTML = '<my-component name="Albert"></my-component>';
 * var element = temp.firstChild;
 * console.log(element.name); // logs "Albert"
 * ```
 */
export class DNAPropertiesComponent extends DNAComponent {
    /**
     * Fires when an the element is registered.
     * @param {String} id The element definition name.
     */
    static onRegister(is) {
        let propertiesToWatch = this.properties || [];
        PROPERTIES_CACHE[is] = propertiesToWatch;
        propertiesToWatch.forEach((prop) => {
            let descriptor = getDescriptor(this.prototype, prop) || {};
            Object.defineProperty(this.prototype, prop, {
                configurable: true,
                get: wrapDescriptorGet(prop, descriptor),
                set: wrapDescriptorSet(prop, descriptor),
            });
        });
    }
    /**
     * On `created` callback, apply attributes to properties.
     */
    createdCallback() {
        super.createdCallback();
        let attributes = Array.prototype.slice.call(this.attributes || [], 0);
        let properties = PROPERTIES_CACHE[this.is] || [];
        for (let i = 0, len = attributes.length; i < len; i++) {
            let attr = attributes[i];
            let key = dashToCamel(attr.name);
            if (properties.indexOf(key) !== -1) {
                let value = attr.value;
                this.removeAttribute(attr.name);
                if (value === '') {
                    this[key] = true;
                } else {
                    try {
                        this[key] = JSON.parse(value);
                    } catch (ex) {
                        this[key] = value;
                    }
                }
            }
        }
    }
}
<|endoftext|>