<commit_before>import $ from 'jquery';
import * as _ from 'lodash';
import * as d3 from 'd3';

import clinicalTimelineExports from './timeline-lib';

const SAMPLE_ID_ALIASES = [
    'SAMPLE_ID',
    'SPECIMEN_REFERENCE_NUMBER',
    'SpecimenReferenceNumber',
];

// TODO: these are some styling hacks for genie. Need to figure out how to add
// proper support for this in the library (or the future reactified library)
function addMoreGenieTimelineStylingHacks() {
    $("circle[id^='timelineItem_2']").attr('stroke', 'gray');
    $("circle[id^='timelineItem_2']").attr('stroke-width', '0.5px');
    $("circle[id^='timelineItem_2']").attr('r', '4.5');
    $("circle[id^='timelineItem_3']").attr('stroke', 'gray');
    $("circle[id^='timelineItem_3']").attr('stroke-width', '0.5px');
    $("circle[id^='timelineItem_3']").attr('r', '4.5');
    $("circle[id^='timelineItem_4']").attr('stroke', 'gray');
    $("circle[id^='timelineItem_4']").attr('stroke-width', '0.5px');
    $("circle[id^='timelineItem_4']").attr('r', '4.5');
}

function plotCaseLabelsInTimeline(
    timelineClasses,
    caseIds,
    clinicalDataMap,
    caseMetaData
) {
    var fillColorAndLabelForCase = function(circle, caseId) {
        var label = caseMetaData.label[caseId];
        var color = caseMetaData.color[caseId];
        circle.select('circle').attr('fill', color);
        circle
            .append('text')
            .attr('y', 4)
            .attr('r', 6)
            .attr('text-anchor', 'middle')
            .attr('font-size', 10)
            .attr('fill', 'white')
            .text(label);
    };

    for (var i = 0; i < caseIds.length; i++) {
        var caseId = caseIds[i];
        var clinicalData = clinicalDataMap[caseId];
        var compareAgainstIds = [caseId];

        var OtherSampleId = clinicalData['OTHER_SAMPLE_ID'];
        if (OtherSampleId) {
            compareAgainstIds = compareAgainstIds.concat(OtherSampleId);
        }
        timelineClasses.forEach(timelineRow => {
            var circle = d3.selectAll(timelineRow).filter(function(x) {
                if (x.tooltip_tables.length === 1) {
                    var specRefNum = x.tooltip_tables[0].filter(function(x) {
                        return SAMPLE_ID_ALIASES.includes(x[0]);
                    })[0];
                    if (specRefNum) {
                        return compareAgainstIds.indexOf(specRefNum[1]) !== -1;
                    }
                }
                return undefined;
            });
            if (circle[0][0]) {
                var g = document.createElementNS(
                    'http://www.w3.org/2000/svg',
                    'g'
                );
                if (circle.attr('cx') !== null && circle.attr('cy') !== null) {
                    $(g).attr(
                        'transform',
                        'translate(' +
                            circle.attr('cx') +
                            ',' +
                            circle.attr('cy') +
                            ')'
                    );
                }
                $(circle[0]).removeAttr('cx');
                $(circle[0]).removeAttr('cy');
                $(circle[0]).removeAttr('style');
                $(circle[0]).qtip('destroy');
                $(circle[0]).unbind('mouseover mouseout');
                $(circle[0]).wrap(g);
                g = $(circle[0]).parent();
                g.prop('__data__', $(circle[0]).prop('__data__'));
                fillColorAndLabelForCase(d3.select(g.get(0)), caseId);
                window.pvTimeline.addDataPointTooltip(g);
            }
        });
    }
}

export function buildTimeline(
    params,
    caseIds,
    patientInfo,
    clinicalDataMap,
    caseMetaData,
    data,
    width
) {
    if (data.length === 0) return;

    var timeData = clinicalTimelineExports.clinicalTimelineParser(data);
    if (timeData.length === 0) return;

    // TODO: remove this, special dev configuration for genie_bpc* studies
    var isGenieBpcStudy = window.location.href.includes('genie_bpc');
    if (isGenieBpcStudy) {
        // color based on state (need to rename Status to Med Onc Assessment)
        var statusGenieData = _.find(
            timeData,
            item =>
                item.label === 'Status' || item.label == 'Med Onc Assessment'
        );
        if (statusGenieData) {
            statusGenieData.label = 'Med Onc Assessment';
            statusGenieData.times.forEach(time => {
                var state = _.find(
                    time.tooltip_tables[0],
                    row => row[0] === 'STATUS'
                )[1].toLowerCase();
                if (state.includes('indeter')) {
                    time['color'] = 'white';
                } else if (state.includes('stable')) {
                    time['color'] = 'gainsboro';
                } else if (state.includes('mixed')) {
                    time['color'] = 'goldenrod';
                } else if (state.includes('improving')) {
                    time['color'] = 'rgb(44, 160, 44)';
                } else if (state.includes('worsening')) {
                    time['color'] = 'rgb(214, 39, 40)';
                }
            });
        }
        // same for imaging
        var imagingGenieData = _.find(
            timeData,
            item => item.label === 'Imaging'
        );
        if (imagingGenieData) {
            imagingGenieData.times.forEach(time => {
                var imageOverall = _.find(
                    time.tooltip_tables[0],
                    row => row[0] === 'IMAGE_OVERALL'
                );
                imageOverall = imageOverall
                    ? imageOverall[1].toLowerCase()
                    : 'indeterminate';
                if (
                    imageOverall.includes('indeter') ||
                    imageOverall.includes('does not mention')
                ) {
                    time['color'] = 'white';
                } else if (imageOverall.includes('stable')) {
                    time['color'] = 'gainsboro';
                } else if (imageOverall.includes('mixed')) {
                    time['color'] = 'goldenrod';
                } else if (imageOverall.includes('improving')) {
                    time['color'] = 'rgb(44, 160, 44)';
                } else if (imageOverall.includes('worsening')) {
                    time['color'] = 'rgb(214, 39, 40)';
                }
            });
        }
    }

    // order specimens by svg label number
    var specimen = _.find(timeData, item => item.label === 'Specimen');
    if (specimen) {
        specimen.times = _.sortBy(specimen.times, function(x) {
            var sortOrder = Infinity;

            var specRefNum = _.filter(x.tooltip_tables[0], function(x) {
                return SAMPLE_ID_ALIASES.includes(x[0]);
            });
            if (specRefNum) {
                if (specRefNum.length > 1) {
                    console.warn(
                        'More than 1 specimen reference number found in tooltip table'
                    );
                } else if (specRefNum.length === 1) {
                    sortOrder = caseIds.indexOf(specRefNum[0][1]);
                    if (sortOrder === -1) {
                        sortOrder = Infinity;
                    }
                }
            }
            return sortOrder;
        });
    }

    // add DECEASED point to Status track using data from .*OS_MONTHS$ if
    // .*OS_STATUS$ is DECEASED
    //
    // TODO: we might want to remove this entirely. For now we only remove it
    // for a test study where we have curated the DECEASED points in data rather
    // than computing it on the frontend. That might have to be the future way
    // of doing things
    var isMskImpactJuneTestStudy = window.location.href.includes(
        'mskimpact_test_june'
    );
    if (!isMskImpactJuneTestStudy) {
        var i;
        var prefixes;
        prefixes = Object.keys(patientInfo)
            .filter(function(x) {
                // find all keys postfixed with "OS_STATUS"
                return /OS_STATUS$/.test(x);
            })
            .map(function(x) {
                // get the prefixes
                return x.substr(0, x.length - 'OS_STATUS'.length);
            });

        for (i = 0; i < prefixes.length; i++) {
            var prefix = prefixes[i];
            if (
                patientInfo[prefix + 'OS_STATUS'] === 'DECEASED' &&
                prefix + 'OS_MONTHS' in patientInfo
            ) {
                var days = Math.round(
                    parseFloat(patientInfo[prefix + 'OS_MONTHS']) * 30.4
                );
                var timePoint = {
                    starting_time: days,
                    ending_time: days,
                    display: 'circle',
                    color: '#000',
                    tooltip_tables: [
                        [['START_DATE', days], ['STATUS', 'DECEASED']],
                    ],
                };

                var trackData = timeData.filter(function(x) {
                    return x.label === 'Status';
                })[0];

                if (trackData) {
                    trackData.times = trackData.times.concat(timePoint);
                } else {
                    timeData = timeData.concat({
                        label: 'Status',
                        times: [timePoint],
                    });
                }
                // Add timepoint only once in case of multiple prefixes
                break;
            }
        }
    }

    window.pvTimeline = clinicalTimelineExports
        .clinicalTimeline()
        .width(width)
        .data(timeData)
        .divId('#timeline')
        .setTimepointsDisplay('Imaging', 'square')
        .orderTracks([
            'Specimen',
            'Surgery',
            'Med Onc Assessment',
            'Status',
            'Diagnostics',
            'Diagnostic',
            'Imaging',
            'Lab_test',
            'Treatment',
        ])
        .splitByClinicalAttributes('Lab_test', 'TEST');
    var splitData = window.pvTimeline.data();
    // Get TEST names that have a RESULT field in their clinical
    // tooltip table. We assume the RESULT field contains
    // integer/float values that can be used to size the dots on the
    // timeline by
    var testsWithResults = splitData
        .filter(function(x) {
            return (
                x.parent_track === 'Lab_test' &&
                _.every(
                    x.times.map(function(t) {
                        return (
                            t.tooltip_tables.length === 1 &&
                            t.tooltip_tables[0].filter(function(a) {
                                return a[0] === 'RESULT';
                            }).length > 0
                        );
                    })
                )
            );
        })
        .map(function(x) {
            return x.label;
        });
    // Scale dot size on timepoint by RESULT field
    testsWithResults.forEach(function(test) {
        window.pvTimeline = window.pvTimeline.sizeByClinicalAttribute(
            test,
            'RESULT'
        );
    });
    if (isGenieBpcStudy) {
        window.pvTimeline = window.pvTimeline
            .orderTracks([
                'Sample acquisition',
                'Sequencing',
                'Surgery',
                'Med Onc Assessment',
                'Status',
                'Diagnostics',
                'Diagnostic',
                'Imaging',
                'Lab_test',
                'Treatment',
            ])
            .setTimepointsDisplay('Imaging', 'circle')
            .splitByClinicalAttributes('Treatment', ['TREATMENT_TYPE', 'AGENT'])
            .enableTrackTooltips(false)
            .plugins([
                {
                    obj: new clinicalTimelineExports.trimClinicalTimeline(
                        'Trim Timeline'
                    ),
                    enabled: true,
                },
            ])
            .addPostTimelineHook(addMoreGenieTimelineStylingHacks.bind(this));
    } else {
        window.pvTimeline = window.pvTimeline
            .splitByClinicalAttributes('Treatment', [
                'TREATMENT_TYPE',
                'SUBTYPE',
                'AGENT',
            ])
            .splitByClinicalAttributes('Diagnosis', ['SUBTYPE'])
            .collapseAll()
            .enableTrackTooltips(false)
            .plugins([
                {
                    obj: new clinicalTimelineExports.trimClinicalTimeline(
                        'Trim Timeline'
                    ),
                    enabled: true,
                },
            ]);
    }
    // find tracks that have a SAMPLE_ID in their tooltip, so we can replace
    // them with the sample label icon (i.e. the circle with 1/2/3 in it)
    var tracksContainingSamples = window.pvTimeline
        .data()
        .reduce(function(previous, currentTrack, i) {
            if (
                currentTrack.times.length > 0 &&
                _.every(
                    currentTrack.times.map(function(t) {
                        return (
                            t.tooltip_tables.length > 0 &&
                            _.every(
                                t.tooltip_tables.map(
                                    table =>
                                        table.filter(function(a) {
                                            return SAMPLE_ID_ALIASES.includes(
                                                a[0]
                                            );
                                        }).length > 0
                                )
                            )
                        );
                    })
                )
            ) {
                return _.concat(previous, [
                    {
                        label: currentTrack.label,
                        index: i,
                        className: `.timelineSeries_${i}`,
                    },
                ]);
            } else {
                return previous;
            }
        }, []);
    // replace tracks with number labels
    if (tracksContainingSamples && tracksContainingSamples.length > 0) {
        tracksContainingSamples.forEach(t => {
            window.pvTimeline.toggleTrackCollapse(t.label);
        });
        window.pvTimeline.addPostTimelineHook(
            plotCaseLabelsInTimeline.bind(
                this,
                tracksContainingSamples.map(t => t.className),
                caseIds,
                clinicalDataMap,
                caseMetaData
            )
        );
    }
    window.pvTimeline();
    $('#timeline-container').show();

    // $.post("http://www.cbioportal.org/clinical_timeline_data.json",
    //     params,
    //
    //     , "json"
    // );
}
<commit_msg>update OS_STATUS in legacy.js<commit_after>import $ from 'jquery';
import * as _ from 'lodash';
import * as d3 from 'd3';

import clinicalTimelineExports from './timeline-lib';

const SAMPLE_ID_ALIASES = [
    'SAMPLE_ID',
    'SPECIMEN_REFERENCE_NUMBER',
    'SpecimenReferenceNumber',
];

// TODO: these are some styling hacks for genie. Need to figure out how to add
// proper support for this in the library (or the future reactified library)
function addMoreGenieTimelineStylingHacks() {
    $("circle[id^='timelineItem_2']").attr('stroke', 'gray');
    $("circle[id^='timelineItem_2']").attr('stroke-width', '0.5px');
    $("circle[id^='timelineItem_2']").attr('r', '4.5');
    $("circle[id^='timelineItem_3']").attr('stroke', 'gray');
    $("circle[id^='timelineItem_3']").attr('stroke-width', '0.5px');
    $("circle[id^='timelineItem_3']").attr('r', '4.5');
    $("circle[id^='timelineItem_4']").attr('stroke', 'gray');
    $("circle[id^='timelineItem_4']").attr('stroke-width', '0.5px');
    $("circle[id^='timelineItem_4']").attr('r', '4.5');
}

function plotCaseLabelsInTimeline(
    timelineClasses,
    caseIds,
    clinicalDataMap,
    caseMetaData
) {
    var fillColorAndLabelForCase = function(circle, caseId) {
        var label = caseMetaData.label[caseId];
        var color = caseMetaData.color[caseId];
        circle.select('circle').attr('fill', color);
        circle
            .append('text')
            .attr('y', 4)
            .attr('r', 6)
            .attr('text-anchor', 'middle')
            .attr('font-size', 10)
            .attr('fill', 'white')
            .text(label);
    };

    for (var i = 0; i < caseIds.length; i++) {
        var caseId = caseIds[i];
        var clinicalData = clinicalDataMap[caseId];
        var compareAgainstIds = [caseId];

        var OtherSampleId = clinicalData['OTHER_SAMPLE_ID'];
        if (OtherSampleId) {
            compareAgainstIds = compareAgainstIds.concat(OtherSampleId);
        }
        timelineClasses.forEach(timelineRow => {
            var circle = d3.selectAll(timelineRow).filter(function(x) {
                if (x.tooltip_tables.length === 1) {
                    var specRefNum = x.tooltip_tables[0].filter(function(x) {
                        return SAMPLE_ID_ALIASES.includes(x[0]);
                    })[0];
                    if (specRefNum) {
                        return compareAgainstIds.indexOf(specRefNum[1]) !== -1;
                    }
                }
                return undefined;
            });
            if (circle[0][0]) {
                var g = document.createElementNS(
                    'http://www.w3.org/2000/svg',
                    'g'
                );
                if (circle.attr('cx') !== null && circle.attr('cy') !== null) {
                    $(g).attr(
                        'transform',
                        'translate(' +
                            circle.attr('cx') +
                            ',' +
                            circle.attr('cy') +
                            ')'
                    );
                }
                $(circle[0]).removeAttr('cx');
                $(circle[0]).removeAttr('cy');
                $(circle[0]).removeAttr('style');
                $(circle[0]).qtip('destroy');
                $(circle[0]).unbind('mouseover mouseout');
                $(circle[0]).wrap(g);
                g = $(circle[0]).parent();
                g.prop('__data__', $(circle[0]).prop('__data__'));
                fillColorAndLabelForCase(d3.select(g.get(0)), caseId);
                window.pvTimeline.addDataPointTooltip(g);
            }
        });
    }
}

export function buildTimeline(
    params,
    caseIds,
    patientInfo,
    clinicalDataMap,
    caseMetaData,
    data,
    width
) {
    if (data.length === 0) return;

    var timeData = clinicalTimelineExports.clinicalTimelineParser(data);
    if (timeData.length === 0) return;

    // TODO: remove this, special dev configuration for genie_bpc* studies
    var isGenieBpcStudy = window.location.href.includes('genie_bpc');
    if (isGenieBpcStudy) {
        // color based on state (need to rename Status to Med Onc Assessment)
        var statusGenieData = _.find(
            timeData,
            item =>
                item.label === 'Status' || item.label == 'Med Onc Assessment'
        );
        if (statusGenieData) {
            statusGenieData.label = 'Med Onc Assessment';
            statusGenieData.times.forEach(time => {
                var state = _.find(
                    time.tooltip_tables[0],
                    row => row[0] === 'STATUS'
                )[1].toLowerCase();
                if (state.includes('indeter')) {
                    time['color'] = 'white';
                } else if (state.includes('stable')) {
                    time['color'] = 'gainsboro';
                } else if (state.includes('mixed')) {
                    time['color'] = 'goldenrod';
                } else if (state.includes('improving')) {
                    time['color'] = 'rgb(44, 160, 44)';
                } else if (state.includes('worsening')) {
                    time['color'] = 'rgb(214, 39, 40)';
                }
            });
        }
        // same for imaging
        var imagingGenieData = _.find(
            timeData,
            item => item.label === 'Imaging'
        );
        if (imagingGenieData) {
            imagingGenieData.times.forEach(time => {
                var imageOverall = _.find(
                    time.tooltip_tables[0],
                    row => row[0] === 'IMAGE_OVERALL'
                );
                imageOverall = imageOverall
                    ? imageOverall[1].toLowerCase()
                    : 'indeterminate';
                if (
                    imageOverall.includes('indeter') ||
                    imageOverall.includes('does not mention')
                ) {
                    time['color'] = 'white';
                } else if (imageOverall.includes('stable')) {
                    time['color'] = 'gainsboro';
                } else if (imageOverall.includes('mixed')) {
                    time['color'] = 'goldenrod';
                } else if (imageOverall.includes('improving')) {
                    time['color'] = 'rgb(44, 160, 44)';
                } else if (imageOverall.includes('worsening')) {
                    time['color'] = 'rgb(214, 39, 40)';
                }
            });
        }
    }

    // order specimens by svg label number
    var specimen = _.find(timeData, item => item.label === 'Specimen');
    if (specimen) {
        specimen.times = _.sortBy(specimen.times, function(x) {
            var sortOrder = Infinity;

            var specRefNum = _.filter(x.tooltip_tables[0], function(x) {
                return SAMPLE_ID_ALIASES.includes(x[0]);
            });
            if (specRefNum) {
                if (specRefNum.length > 1) {
                    console.warn(
                        'More than 1 specimen reference number found in tooltip table'
                    );
                } else if (specRefNum.length === 1) {
                    sortOrder = caseIds.indexOf(specRefNum[0][1]);
                    if (sortOrder === -1) {
                        sortOrder = Infinity;
                    }
                }
            }
            return sortOrder;
        });
    }

    // add DECEASED point to Status track using data from .*OS_MONTHS$ if
    // .*OS_STATUS$ is DECEASED
    //
    // TODO: we might want to remove this entirely. For now we only remove it
    // for a test study where we have curated the DECEASED points in data rather
    // than computing it on the frontend. That might have to be the future way
    // of doing things
    var isMskImpactJuneTestStudy = window.location.href.includes(
        'mskimpact_test_june'
    );
    if (!isMskImpactJuneTestStudy) {
        var i;
        var prefixes;
        prefixes = Object.keys(patientInfo)
            .filter(function(x) {
                // find all keys postfixed with "OS_STATUS"
                return /OS_STATUS$/.test(x);
            })
            .map(function(x) {
                // get the prefixes
                return x.substr(0, x.length - 'OS_STATUS'.length);
            });

        for (i = 0; i < prefixes.length; i++) {
            var prefix = prefixes[i];
            if (
                patientInfo[prefix + 'OS_STATUS'] === '1:DECEASED' &&
                prefix + 'OS_MONTHS' in patientInfo
            ) {
                var days = Math.round(
                    parseFloat(patientInfo[prefix + 'OS_MONTHS']) * 30.4
                );
                var timePoint = {
                    starting_time: days,
                    ending_time: days,
                    display: 'circle',
                    color: '#000',
                    tooltip_tables: [
                        [['START_DATE', days], ['STATUS', 'DECEASED']],
                    ],
                };

                var trackData = timeData.filter(function(x) {
                    return x.label === 'Status';
                })[0];

                if (trackData) {
                    trackData.times = trackData.times.concat(timePoint);
                } else {
                    timeData = timeData.concat({
                        label: 'Status',
                        times: [timePoint],
                    });
                }
                // Add timepoint only once in case of multiple prefixes
                break;
            }
        }
    }

    window.pvTimeline = clinicalTimelineExports
        .clinicalTimeline()
        .width(width)
        .data(timeData)
        .divId('#timeline')
        .setTimepointsDisplay('Imaging', 'square')
        .orderTracks([
            'Specimen',
            'Surgery',
            'Med Onc Assessment',
            'Status',
            'Diagnostics',
            'Diagnostic',
            'Imaging',
            'Lab_test',
            'Treatment',
        ])
        .splitByClinicalAttributes('Lab_test', 'TEST');
    var splitData = window.pvTimeline.data();
    // Get TEST names that have a RESULT field in their clinical
    // tooltip table. We assume the RESULT field contains
    // integer/float values that can be used to size the dots on the
    // timeline by
    var testsWithResults = splitData
        .filter(function(x) {
            return (
                x.parent_track === 'Lab_test' &&
                _.every(
                    x.times.map(function(t) {
                        return (
                            t.tooltip_tables.length === 1 &&
                            t.tooltip_tables[0].filter(function(a) {
                                return a[0] === 'RESULT';
                            }).length > 0
                        );
                    })
                )
            );
        })
        .map(function(x) {
            return x.label;
        });
    // Scale dot size on timepoint by RESULT field
    testsWithResults.forEach(function(test) {
        window.pvTimeline = window.pvTimeline.sizeByClinicalAttribute(
            test,
            'RESULT'
        );
    });
    if (isGenieBpcStudy) {
        window.pvTimeline = window.pvTimeline
            .orderTracks([
                'Sample acquisition',
                'Sequencing',
                'Surgery',
                'Med Onc Assessment',
                'Status',
                'Diagnostics',
                'Diagnostic',
                'Imaging',
                'Lab_test',
                'Treatment',
            ])
            .setTimepointsDisplay('Imaging', 'circle')
            .splitByClinicalAttributes('Treatment', ['TREATMENT_TYPE', 'AGENT'])
            .enableTrackTooltips(false)
            .plugins([
                {
                    obj: new clinicalTimelineExports.trimClinicalTimeline(
                        'Trim Timeline'
                    ),
                    enabled: true,
                },
            ])
            .addPostTimelineHook(addMoreGenieTimelineStylingHacks.bind(this));
    } else {
        window.pvTimeline = window.pvTimeline
            .splitByClinicalAttributes('Treatment', [
                'TREATMENT_TYPE',
                'SUBTYPE',
                'AGENT',
            ])
            .splitByClinicalAttributes('Diagnosis', ['SUBTYPE'])
            .collapseAll()
            .enableTrackTooltips(false)
            .plugins([
                {
                    obj: new clinicalTimelineExports.trimClinicalTimeline(
                        'Trim Timeline'
                    ),
                    enabled: true,
                },
            ]);
    }
    // find tracks that have a SAMPLE_ID in their tooltip, so we can replace
    // them with the sample label icon (i.e. the circle with 1/2/3 in it)
    var tracksContainingSamples = window.pvTimeline
        .data()
        .reduce(function(previous, currentTrack, i) {
            if (
                currentTrack.times.length > 0 &&
                _.every(
                    currentTrack.times.map(function(t) {
                        return (
                            t.tooltip_tables.length > 0 &&
                            _.every(
                                t.tooltip_tables.map(
                                    table =>
                                        table.filter(function(a) {
                                            return SAMPLE_ID_ALIASES.includes(
                                                a[0]
                                            );
                                        }).length > 0
                                )
                            )
                        );
                    })
                )
            ) {
                return _.concat(previous, [
                    {
                        label: currentTrack.label,
                        index: i,
                        className: `.timelineSeries_${i}`,
                    },
                ]);
            } else {
                return previous;
            }
        }, []);
    // replace tracks with number labels
    if (tracksContainingSamples && tracksContainingSamples.length > 0) {
        tracksContainingSamples.forEach(t => {
            window.pvTimeline.toggleTrackCollapse(t.label);
        });
        window.pvTimeline.addPostTimelineHook(
            plotCaseLabelsInTimeline.bind(
                this,
                tracksContainingSamples.map(t => t.className),
                caseIds,
                clinicalDataMap,
                caseMetaData
            )
        );
    }
    window.pvTimeline();
    $('#timeline-container').show();

    // $.post("http://www.cbioportal.org/clinical_timeline_data.json",
    //     params,
    //
    //     , "json"
    // );
}
<|endoftext|>


<commit_before>(function() {
/** Policy generation script. Will retrieve CSP directive URIs from the DOM. */
'use strict';

(function() {
    /** Delete this <script> element from DOM (first script on page). */
    var this_element = document.getElementsByTagName('script')[0];
    this_element.parentNode.removeChild(this_element);
})();

// shortcut functions
var $ = {
    empty: function(value) {
        if (value === null || value === undefined ||
            (value.constructor === Array && !value.length) || !value) {
            return true;
        }
        return false;
    },
    /*
    toAbsoluteURI: function(uri) {
        var a = document.createElement('a');
        a.href = uri;
        return a.href;
    },*/
};

// Array functions
var $a = {
    forEach: function(array, callback) {
        /** Calls forEach on arrays and array-like objects. */
        Array.prototype.forEach.call(array, callback);
    },
    in: function(array, value) {
        /** Checks if value can be found in array. */
        return Array.prototype.indexOf.call(array, value) > -1;
    },
};

// Object functions
var $o = {
    forEach: function(object, callback) {
        for (var key in object) {
            if ($o.in(object, key)) {
                callback(key, object[key]);
            }
        }
    },
    in: function(object, key) {
        /** Returns if an key exists in the object. */
        return Object.prototype.hasOwnProperty.call(object, key);
    },
};

// String functions
var $s = {
    startsWith: function(str, startstr) {
        return str.slice(0, startstr.length) === startstr;
    },
};

$.Map = function(values) {
    /** Maps keys to values without the shenanigans of JavaScript. */
    this.values = values || {};
    this.length = Object.keys(this.values).length;
};
$.Map.prototype.add = function(key, value) {
    this.values[key] = value;
    this.length++;
};
$.Map.prototype.foreach = function(cb) {
    for (var key in this.values) {
        if (this.has_key(key)) {
            cb(key, this.values[key]);
        }
    }
};
$.Map.prototype.get = function(key) {
    return this.values[key];
};
$.Map.prototype.get_object = function() {
    return this.values;
};
$.Map.prototype.has_key = function(key) {
    return Object.prototype.hasOwnProperty.call(this.values, key);
};
$.Map.prototype.setdefault = function(key, default_val) {
    default_val = default_val || null;
    if (!this.has_key(key)) {
        this.values[key] = default_val;
        this.length++;
    }
    return this.values[key];
};
$.Map.prototype.valueOf = function() {
    var internal = {};
    this.foreach(function(key, value) {
        internal[key] = value.valueOf();
    });
    return internal;
};

$.Set = function(values) {
    var values = values || [];
    this.values = {};
    for (var i = 0; i < values.length; i++) {
        this.values[values[i]] = true;
    }
};
$.Set.prototype.add = function(value) {
    /** Adds a new element or a list of elements to the Set. */
    if ($.empty(value)) {
        return false;
    }
    if (value.constructor === Array) {
        for (var i = 0; i < value.length; i++) {
            this.add(value[i]);
        }
    } else {
        this.values[value] = true;
    }
};
$.Set.prototype.get_array = function() {
    return Object.keys(this.values);
};
$.Set.prototype.valueOf = function() {
    return this.get_array();
};

// Network functions
var $n = {
    get: function(url, callback) {
        (new $n.Request(url, callback)).get();
    },
    post: function(url, data, callback) {
        /** POSTS to the URL and url-encodes the data object. */
        var components = [];
        $o.forEach(data, function(key, value) {
            components.push(window.encodeURIComponent(key) + '=' +
                            window.encodeURIComponent(value));
        });
        (new $n.Request(url, callback)).post(components.join('&'));
    },
};
$n.Request = function(url, callback) {
    callback = callback || function () {};
    this.url = url;
    this.xhr = new XMLHttpRequest();
    this.xhr.addEventListener('readystatechange', function() {
        if (this.readyState === 4) {
            callback(this.responseText);
        }
    });
};
$n.Request.prototype.get = function() {
    this.xhr.open('GET', this.url);
    this.xhr.send();
};
$n.Request.prototype.post = function(data) {
    data = data || '';
    this.xhr.open('POST', this.url);
    this.xhr.send(data);
};

// variable definitions
//var self_uri = location.protocol + '//' + location.hostname +
//               (location.port ? ':' + location.port : '') + '/';

// will contain a Map of Node types we want to visit
var visit = null;

/** Contains all functions used to extract sources. **/
(function() {
    var sanitizeUri = function(uri) {
        /** Detects data: URIs and just returns data: in that case */
        if ($.empty(uri) || !$s.startsWith(uri, 'data:')) {
            return uri;
        }
        // oh, it's a data URI
        return 'data:';
    };

    var getSrc = function(e) {
        return sanitizeUri(e.src);
    };
    var getBackgroundImage = function(e) {
        /** Retrieve all background image URIs. */
        var bg = window.getComputedStyle(e, false).backgroundImage;
        var match = bg.match(/url\('?([^)]*[^']+)'?\)/);
        return (match) ? sanitizeUri(match[1]) : null;
    };
    var getIcon = function(e) {
        return (e.rel === 'icon') ? sanitizeUri(e.href) : null;
    };

    // remembers all stylesheets (prevent crawling rules a second time)
    var styles = [];
    var appendStyle = function(stylesheet, newStyles) {
        /** If a stylesheet was found this will check if its new and recurse. */
        // unfortunately we cannot know if we already visited an inline style
        var uri = sanitizeUri(stylesheet.href);
        if (!$a.in(styles, uri)) {
            // don't add to styles list if inline
            if (!$.empty(uri)) {
                newStyles.push(uri);
                styles.push(uri);
            }
            for (var i = 0; i < stylesheet.rules.length; i++) {
                // @import rules are always on top so break if no import
                if (stylesheet.rules[i].constructor !== CSSImportRule) {
                    break;
                }
                // recurse into stylesheet (could contain more @imports)
                appendStyle(stylesheet.rules[i].styleSheet, newStyles);
            }
        }
    };
    var checkStyles = function(e) {
        /** Checks for new stylesheets in document.styleSheets. */
        var newStyles = [];
        $a.forEach(document.styleSheets, function(stylesheet) {
            appendStyle(stylesheet, newStyles);
        });
        return newStyles;
    };

    visit = {
        '*': {'img-src': getBackgroundImage},
        'IMG': {'img-src': getSrc},
        'LINK': {'img-src': getIcon, 'style-src': checkStyles},
        'SCRIPT': {'script-src': getSrc},
        'STYLE': {'style-src': checkStyles},
    };
})();

window.addEventListener('load', function() {
    var inferRules = function(nodes) {
        /** Infers CSP rules from given nodes with the visit list. */
        var sources = new $.Map();
        var node = null;
        var store_in_sources = function(directive, func) {
            var uri = func(node);
            if (!$.empty(uri)) {
                sources.setdefault(directive, new $.Set()).add(uri);
            }
        };
        for (var i = 0; i < nodes.length; i++) {
            if (nodes[i].tagName) {
                node = nodes[i];
                $o.forEach(visit['*'], store_in_sources);
                if ($o.in(visit, node.tagName)) {
                    $o.forEach(visit[node.tagName], store_in_sources);
                }
            }
        }
        return sources;
    };

    var uri = location.pathname + location.search;
    var processNodes = function(nodes) {
        /** Retrieves policy rules from nodes and POSTs to backend. */
        var rules = inferRules(nodes);
        if ($.empty(rules)) {
            // don't POST empty JSON response
            return;
        }
        var rules = JSON.stringify(rules.valueOf());
        console.log(rules);
        $n.post('{{ report_uri }}', {'uri': uri, 'sources': rules});
    };

    // visit all nodes at load one time
    processNodes(document.getElementsByTagName('*'));

    // register an observer for future changes (tree mod and attributes)
    var observer = new MutationObserver(function(mutations) {
        $a.forEach(mutations, function(mutation) {
            var nodes = (mutation.type === 'childList') ? mutation.addedNodes :
                                                          [mutation.target];
            processNodes(nodes);
        });
    });
    observer.observe(document.body.parentNode,
                     {subtree: true, childList: true, attributes: true});
});

})();<commit_msg>Getting rid of $.Map and $.Set.<commit_after>(function() {
/** Policy generation script. Will retrieve CSP directive URIs from the DOM. */
'use strict';

(function() {
    /** Delete this <script> element from DOM (first script on page). */
    var this_element = document.getElementsByTagName('script')[0];
    this_element.parentNode.removeChild(this_element);
})();

// shortcut functions
var $ = {
    empty: function(value) {
        /** Sane emptiness check. $.empty([]) == true, $.empty({}) == true */
        if (value === null || value === undefined ||
            (value.constructor !== Boolean &&
             ((value.constructor === Array && !value.length) ||
              (value.constructor === Object &&
               value.toString() == '[object Object]' &&
               !Object.keys(value).length) || !value))) {
            return true;
        }
        return false;
    },
    /*
    toAbsoluteURI: function(uri) {
        var a = document.createElement('a');
        a.href = uri;
        return a.href;
    },*/
};

// Array functions
var $a = {
    add: function(array, value) {
        /** If value, adds to array, if array adds all values to array. */
        if (value.constructor === Array) {
            for (var i = 0; i < value.length; i++) {
                array.push(value[i]);
            }
        } else {
            array.push(value);
        }
    },
    forEach: function(array, callback) {
        /** Calls forEach on arrays and array-like objects. */
        Array.prototype.forEach.call(array, callback);
    },
    in: function(array, value) {
        /** Checks if value can be found in array. */
        return Array.prototype.indexOf.call(array, value) > -1;
    },
};

// Object functions
var $o = {
    forEach: function(object, callback) {
        for (var key in object) {
            if ($o.in(object, key)) {
                callback(key, object[key]);
            }
        }
    },
    in: function(object, key) {
        /** Returns if an key exists in the object. */
        return Object.prototype.hasOwnProperty.call(object, key);
    },
    setDefault: function(object, key, default_val) {
        /** Returns a object key and sets it if it does not exist, yet. */
        default_val = default_val || null;
        if (!$o.in(object, key)) {
            object[key] = default_val;
        }
        return object[key];
    },
};

// String functions
var $s = {
    startsWith: function(str, startstr) {
        return str.slice(0, startstr.length) === startstr;
    },
};

// Network functions
var $n = {
    get: function(url, callback) {
        (new $n.Request(url, callback)).get();
    },
    post: function(url, data, callback) {
        /** POSTS to the URL and url-encodes the data object. */
        var components = [];
        $o.forEach(data, function(key, value) {
            components.push(window.encodeURIComponent(key) + '=' +
                            window.encodeURIComponent(value));
        });
        (new $n.Request(url, callback)).post(components.join('&'));
    },
};
$n.Request = function(url, callback) {
    callback = callback || function () {};
    this.url = url;
    this.xhr = new XMLHttpRequest();
    this.xhr.addEventListener('readystatechange', function() {
        if (this.readyState === 4) {
            callback(this.responseText);
        }
    });
};
$n.Request.prototype.get = function() {
    this.xhr.open('GET', this.url);
    this.xhr.send();
};
$n.Request.prototype.post = function(data) {
    data = data || '';
    this.xhr.open('POST', this.url);
    this.xhr.send(data);
};

// variable definitions
//var self_uri = location.protocol + '//' + location.hostname +
//               (location.port ? ':' + location.port : '') + '/';

// will contain a Map of Node types we want to visit
var visit = null;

/** Contains all functions used to extract sources. **/
(function() {
    var sanitizeUri = function(uri) {
        /** Detects data: URIs and just returns data: in that case */
        if ($.empty(uri) || !$s.startsWith(uri, 'data:')) {
            return uri;
        }
        return 'data:';
    };

    var getSrc = function(e) {
        return sanitizeUri(e.src);
    };
    var getBackgroundImage = function(e) {
        /** Retrieve all background image URIs. */
        var bg = window.getComputedStyle(e, false).backgroundImage;
        var match = bg.match(/url\('?([^)]*[^']+)'?\)/);
        return (match) ? sanitizeUri(match[1]) : null;
    };
    var getIcon = function(e) {
        return (e.rel === 'icon') ? sanitizeUri(e.href) : null;
    };

    // remembers all stylesheets (prevent crawling rules a second time)
    var styles = [];
    var appendStyle = function(stylesheet, newStyles) {
        /** If a stylesheet was found this will check if its new and recurse. */
        // unfortunately we cannot know if we already visited an inline style
        var uri = sanitizeUri(stylesheet.href);
        if (!$a.in(styles, uri)) {
            // don't add to styles list if inline
            if (!$.empty(uri)) {
                newStyles.push(uri);
                styles.push(uri);
            }
            for (var i = 0; i < stylesheet.rules.length; i++) {
                // @import rules are always on top so break if no import
                if (stylesheet.rules[i].constructor !== CSSImportRule) {
                    break;
                }
                // recurse into stylesheet (could contain more @imports)
                appendStyle(stylesheet.rules[i].styleSheet, newStyles);
            }
        }
    };
    var checkStyles = function(e) {
        /** Checks for new stylesheets in document.styleSheets. */
        var newStyles = [];
        $a.forEach(document.styleSheets, function(stylesheet) {
            appendStyle(stylesheet, newStyles);
        });
        return newStyles;
    };

    visit = {
        '*': {'img-src': getBackgroundImage},
        'IMG': {'img-src': getSrc},
        'LINK': {'img-src': getIcon, 'style-src': checkStyles},
        'SCRIPT': {'script-src': getSrc},
        'STYLE': {'style-src': checkStyles},
    };
})();

window.addEventListener('load', function() {
    var inferRules = function(nodes) {
        /** Infers CSP rules from given nodes with the visit list. */
        var rules = {};
        var node = null;
        var store_in_sources = function(directive, func) {
            var uri = func(node);
            if (!$.empty(uri)) {
                var list = $o.setDefault(rules, directive, []);
                if (!$a.in(list, uri)) {
                    $a.add(list, uri);
                }
            }
        };
        for (var i = 0; i < nodes.length; i++) {
            if (nodes[i].tagName) {
                node = nodes[i];
                $o.forEach(visit['*'], store_in_sources);
                if ($o.in(visit, node.tagName)) {
                    $o.forEach(visit[node.tagName], store_in_sources);
                }
            }
        }
        return rules;
    };

    var uri = location.pathname + location.search;
    var processNodes = function(nodes) {
        /** Retrieves policy rules from nodes and POSTs to backend. */
        var rules = inferRules(nodes);
        if ($.empty(rules)) {
            // don't POST empty JSON response
            return;
        }
        var rules = JSON.stringify(rules.valueOf());
        console.log(rules);
        $n.post('{{ report_uri }}', {'uri': uri, 'sources': rules});
    };

    // visit all nodes at load one time
    processNodes(document.getElementsByTagName('*'));

    // register an observer for future changes (tree mod and attributes)
    var observer = new MutationObserver(function(mutations) {
        $a.forEach(mutations, function(mutation) {
            var nodes = (mutation.type === 'childList') ? mutation.addedNodes :
                                                          [mutation.target];
            processNodes(nodes);
        });
    });
    observer.observe(document.body.parentNode,
                     {subtree: true, childList: true, attributes: true});
});

})();<|endoftext|>


<commit_before>var Trace = require('./trace')

var eventPairs = [
  ['domainLookupStart', 'domainLookupEnd', 'DNS lookup'],
  ['connectStart', 'connectEnd', 'Connect'],
  ['requestStart', 'responseStart', 'Sending and waiting for first byte'],
  ['responseStart', 'responseEnd', 'Downloading'],
  ['domLoading', 'domInteractive', 'Fetching, parsing and sync. execution'],
  ['domContentLoadedEventStart', 'domContentLoadedEventEnd', '"DOMContentLoaded" event handling'],
  ['loadEventStart', 'loadEventEnd', '"load" event handling']
]

module.exports = function captureHardNavigation (transaction) {
  if (transaction.isHardNavigation && window.performance && window.performance.timing) {
    var baseTime = window.performance.timing.navigationStart
    var timings = window.performance.timing

    transaction._rootTrace._start = transaction._start = 0
    transaction.type = 'page-load'
    var traceThreshold = 5 * 60 * 1000 // 5 minutes
    for (var i = 0; i < eventPairs.length; i++) {
      // var transactionStart = eventPairs[0]
      var start = timings[eventPairs[i][0]]
      var end = timings[eventPairs[i][1]]
      if (start && end && end - start !== 0) {
        var trace = new Trace(transaction, eventPairs[i][2], 'hard-navigation.browser-timing')
        trace._start = timings[eventPairs[i][0]] - baseTime
        trace.ended = true
        trace.setParent(transaction._rootTrace)
        trace.end()
        trace._end = timings[eventPairs[i][1]] - baseTime
        trace.calcDiff()
        var d = trace.duration()
        if (d > traceThreshold || d < 0) {
          transaction.traces.splice(transaction.traces.indexOf(trace), 1)
        }
      }
    }

    if (window.performance.getEntriesByType) {
      var entries = window.performance.getEntriesByType('resource')
      for (i = 0; i < entries.length; i++) {
        var entry = entries[i]
        if (entry.initiatorType && entry.initiatorType === 'xmlhttprequest') {
          continue
        } else {
          var kind = 'resource'
          if (entry.initiatorType) {
            kind += '.' + entry.initiatorType
          }

          trace = new Trace(transaction, entry.name, kind)
          trace._start = entry.startTime
          trace.ended = true
          trace.setParent(transaction._rootTrace)
          trace.end()
          trace._end = entry.responseEnd
          trace.calcDiff()
        }
      }
    }

    transaction._adjustStartToEarliestTrace()
    transaction._adjustEndToLatestTrace()
  }
  return 0
}
<commit_msg>fix(captureHardNavigation): filter out late traces<commit_after>var Trace = require('./trace')

var eventPairs = [
  ['domainLookupStart', 'domainLookupEnd', 'DNS lookup'],
  ['connectStart', 'connectEnd', 'Connect'],
  ['requestStart', 'responseStart', 'Sending and waiting for first byte'],
  ['responseStart', 'responseEnd', 'Downloading'],
  ['domLoading', 'domInteractive', 'Fetching, parsing and sync. execution'],
  ['domContentLoadedEventStart', 'domContentLoadedEventEnd', '"DOMContentLoaded" event handling'],
  ['loadEventStart', 'loadEventEnd', '"load" event handling']
]

var traceThreshold = 5 * 60 * 1000 // 5 minutes
function isValidTrace (transaction, trace) {
  var d = trace.duration()
  return (d < traceThreshold && d > 0 && trace._start <= transaction._rootTrace._end && trace._end <= transaction._rootTrace._end)
}

module.exports = function captureHardNavigation (transaction) {
  if (transaction.isHardNavigation && window.performance && window.performance.timing) {
    var baseTime = window.performance.timing.navigationStart
    var timings = window.performance.timing

    transaction._rootTrace._start = transaction._start = 0
    transaction.type = 'page-load'
    for (var i = 0; i < eventPairs.length; i++) {
      // var transactionStart = eventPairs[0]
      var start = timings[eventPairs[i][0]]
      var end = timings[eventPairs[i][1]]
      if (start && end && end - start !== 0) {
        var trace = new Trace(transaction, eventPairs[i][2], 'hard-navigation.browser-timing')
        trace._start = timings[eventPairs[i][0]] - baseTime
        trace.ended = true
        trace.setParent(transaction._rootTrace)
        trace.end()
        trace._end = timings[eventPairs[i][1]] - baseTime
        trace.calcDiff()
        if (!isValidTrace(transaction, trace)) {
          transaction.traces.splice(transaction.traces.indexOf(trace), 1)
        }
      }
    }

    if (window.performance.getEntriesByType) {
      var entries = window.performance.getEntriesByType('resource')
      for (i = 0; i < entries.length; i++) {
        var entry = entries[i]
        if (entry.initiatorType && entry.initiatorType === 'xmlhttprequest') {
          continue
        } else {
          var kind = 'resource'
          if (entry.initiatorType) {
            kind += '.' + entry.initiatorType
          }

          trace = new Trace(transaction, entry.name, kind)
          trace._start = entry.startTime
          trace.ended = true
          trace.setParent(transaction._rootTrace)
          trace.end()
          trace._end = entry.responseEnd
          trace.calcDiff()
          if (!isValidTrace(transaction, trace)) {
            transaction.traces.splice(transaction.traces.indexOf(trace), 1)
          }
        }
      }
    }

    transaction._adjustStartToEarliestTrace()
    transaction._adjustEndToLatestTrace()
  }
  return 0
}
<|endoftext|>


<commit_before>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

export default
    angular.module('CompletedJobsDefinition', ['sanitizeFilter'])
    .value( 'CompletedJobsList', {
        // These tooltip fields are consumed to build disabled related tabs tooltips in the form > add view
        awToolTip: 'Please save and run a job to view',
        dataPlacement: 'top',
        name: 'completed_jobs',
        basePath: 'job_templates/:id/jobs/?or__status=successful&or__status=failed&or__status=error&or__status=canceled',
        iterator: 'completed_job',
        editTitle: 'Completed Jobs',
        index: false,
        hover: true,
        well: false,
        emptyListText: 'No completed jobs',

        fields: {
            status: {
                label: '',
                searchLabel: 'Status',
                columnClass: 'List-staticColumn--smallStatus',
                awToolTip: "{{ completed_job.status_tip }}",
                awTipPlacement: "right",
                dataTitle: "{{ completed_job.status_popover_title }}",
                icon: 'icon-job-{{ completed_job.status }}',
                iconOnly: true,
                ngClick:"viewJobDetails(completed_job)",
                searchable: true,
                searchType: 'select',
                nosort: true,
                searchOptions: [
                    { label: "Success", value: "successful" },
                    { label: "Error", value: "error" },
                    { label: "Failed", value: "failed" },
                    { label: "Canceled", value: "canceled" }
                ]
            },
            id: {
                label: 'ID',
                ngClick:"viewJobDetails(completed_job)",
                searchType: 'int',
                columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent',
                awToolTip: "{{ completed_job.status_tip }}",
                dataPlacement: 'top'
            },
            name: {
                label: 'Name',
                columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6',
                ngClick: "viewJobDetails(completed_job)",
                defaultSearchField: true,
                awToolTip: "{{ completed_job.name | sanitize }}",
                dataPlacement: 'top'
            },
            type: {
                label: 'Type',
                ngBind: 'completed_job.type_label',
                link: false,
                columnClass: "col-lg-2 col-md-2 hidden-sm hidden-xs",
                searchable: true,
                searchType: 'select',
                searchOptions: []    // populated via GetChoices() in controller
            },
            finished: {
                label: 'Finished',
                noLink: true,
                searchable: false,
                filter: "longDate",
                columnClass: "col-lg-3 col-md-3 col-sm-3 hidden-xs",
                key: true,
                desc: true
            },
            failed: {
                label: 'Job failed?',
                searchSingleValue: true,
                searchType: 'boolean',
                searchValue: 'true',
                searchOnly: true,
                nosort: true
            }
        },

        actions: { },

        fieldActions: {

            columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',

            submit: {
                icon: 'icon-rocket',
                mode: 'all',
                ngClick: 'relaunchJob($event, completed_job.id)',
                awToolTip: 'Relaunch using the same parameters',
                dataPlacement: 'top',
                ngHide: "completed_job.type == 'system_job' "
            },
            "delete": {
                mode: 'all',
                ngClick: 'deleteJob(completed_job.id)',
                awToolTip: 'Delete the job',
                dataPlacement: 'top'
            }
        }
    });
<commit_msg>Made type and name not searchable on the job templates completed jobs list<commit_after>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

export default
    angular.module('CompletedJobsDefinition', ['sanitizeFilter'])
    .value( 'CompletedJobsList', {
        // These tooltip fields are consumed to build disabled related tabs tooltips in the form > add view
        awToolTip: 'Please save and run a job to view',
        dataPlacement: 'top',
        name: 'completed_jobs',
        basePath: 'job_templates/:id/jobs/?or__status=successful&or__status=failed&or__status=error&or__status=canceled',
        iterator: 'completed_job',
        editTitle: 'Completed Jobs',
        index: false,
        hover: true,
        well: false,
        emptyListText: 'No completed jobs',

        fields: {
            status: {
                label: '',
                searchLabel: 'Status',
                columnClass: 'List-staticColumn--smallStatus',
                awToolTip: "{{ completed_job.status_tip }}",
                awTipPlacement: "right",
                dataTitle: "{{ completed_job.status_popover_title }}",
                icon: 'icon-job-{{ completed_job.status }}',
                iconOnly: true,
                ngClick:"viewJobDetails(completed_job)",
                searchable: true,
                searchType: 'select',
                defaultSearchField: true,
                nosort: true,
                searchOptions: [
                    { label: "Success", value: "successful" },
                    { label: "Error", value: "error" },
                    { label: "Failed", value: "failed" },
                    { label: "Canceled", value: "canceled" }
                ]
            },
            id: {
                label: 'ID',
                ngClick:"viewJobDetails(completed_job)",
                searchType: 'int',
                columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent',
                awToolTip: "{{ completed_job.status_tip }}",
                dataPlacement: 'top'
            },
            name: {
                label: 'Name',
                columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6',
                searchable: false,
                ngClick: "viewJobDetails(completed_job)",
                awToolTip: "{{ completed_job.name | sanitize }}",
                dataPlacement: 'top'
            },
            type: {
                label: 'Type',
                ngBind: 'completed_job.type_label',
                link: false,
                columnClass: "col-lg-2 col-md-2 hidden-sm hidden-xs",
                searchable: false,
                searchType: 'select',
                searchOptions: []    // populated via GetChoices() in controller
            },
            finished: {
                label: 'Finished',
                noLink: true,
                searchable: false,
                filter: "longDate",
                columnClass: "col-lg-3 col-md-3 col-sm-3 hidden-xs",
                key: true,
                desc: true
            },
            failed: {
                label: 'Job failed?',
                searchSingleValue: true,
                searchType: 'boolean',
                searchValue: 'true',
                searchOnly: true,
                nosort: true
            }
        },

        actions: { },

        fieldActions: {

            columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',

            submit: {
                icon: 'icon-rocket',
                mode: 'all',
                ngClick: 'relaunchJob($event, completed_job.id)',
                awToolTip: 'Relaunch using the same parameters',
                dataPlacement: 'top',
                ngHide: "completed_job.type == 'system_job' "
            },
            "delete": {
                mode: 'all',
                ngClick: 'deleteJob(completed_job.id)',
                awToolTip: 'Delete the job',
                dataPlacement: 'top'
            }
        }
    });
<|endoftext|>


<commit_before>const defaultPrefs = Object.freeze([

	{
		'name': 'setunlimitedlinks',
		// 'title': 'Show as many comments as possible on a page',
		'title': 'A lehető legtöbb hozzászólás mutatása',
		'type': 'bool',
		'value': true,
		'group': 'comments'
	},

	{
		'name': 'replacenewcommenttext',
		// 'title': 'Replace the "új" text of new comments to a better searchable one',
		'title': 'Olvasatlan hozzászólásoknál az "új" szöveg lecserélése valami jobban kereshetőre',
		'type': 'bool',
		'value': true,
		'group': 'comments',
		'requiredBy': ['newcommenttext']
	},

	{
		'name': 'newcommenttext',
		// 'title': 'The text to show instead of \"új\"',
		'title': 'Szöveg az új hozzászólásokban "új" helyett',
		'type': 'string',
		'value': '[new]',
		'group': 'comments'
	},

	{
		'name': 'filtertrolls',
		// 'title': 'Enable trollfilter',
		'title': 'Trollszűrő engedélyezése',
		'type': 'bool',
		'value': true,
		'group': 'comments',
		'requiredBy': ['edittrolls']
	},

	{
		'name': 'edittrolls',
		// 'title': 'Edit trolls',
		'title': 'Trollok szerkesztése',
		'label': 'Click to edit trolls',
		'type': 'control',
		'group': 'comments'
	},

	{
		'name': 'trolls',
		// 'title': 'List of trolls',
		'title': 'Trollok listája',
		'type': 'array',
		'value': [],
		'hidden': true,
		'group': 'comments'
	},

	{
		'name': 'huppercolor',
		// 'title': 'Default color of highlighted user\'s comment header',
		'title': 'Kiemelt felhasználók alapértelmezett színe',
		'type': 'color',
		'value': '#B5D7BE',
		'group': 'comments'
	},

	{
		'name': 'edithighlightusers',
		// 'title': 'Edit highlighted users',
		'title': 'Kiemelt felhasználók szerkesztése',
		'label': 'Click to edit highlighted users',
		'type': 'control',
		'group': 'comments'
	},

	{
		'name': 'highlightusers',
		// 'title': 'Highlight comments of the users',
		'title': 'Kiemelt felhasználók listája',
		'type': 'array',
		'value': [
			{name: 'username', color: '#fff999'},
			{name: 'username2', color: '#999fff'}
		],
		'hidden': true,
		'group': 'comments'
	},

	{
		'name': 'hidetaxonomy',
		// 'title': 'Hidden article types',
		'title': 'Rejtett sikkek listája',
		'type': 'array',
		'value': [],
		'hidden': true,
		'group': 'articles'
	},

	{
		'name': 'edithidetaxonomy',
		// 'title': 'Edit hidden article types',
		'title': 'Rejtett cikkek szerkesztése',
		'type': 'control',
		'group': 'articles'
	},

	{
		'name': 'blocks',
		// 'title': 'Block settings',
		'title': 'Block beállítások',
		'type': 'array',
		'value': [],
		'hidden': true,
		'group': 'blocks'
	},
	{
		'name': 'parseblocks',
		// 'title': 'Parse blocks',
		'title': 'Blokkokhoz tartozó funkciók engedélyezése',
		'type': 'bool',
		'value': true,
		'group': 'blocks'

	},

	{
		'name': 'style_wider_sidebar',
		// 'title': 'Width of sidebars',
		'title': 'Oldalsó oszlopok szélessége',
		'type': 'integer',
		'value': 0,
		'group': 'styles'
	},

	{
		'name': 'style_min_fontsize',
		// 'title': 'Minimum font size',
		'title': 'Minimum betűméret',
		'type': 'integer',
		'value': 0,
		'group': 'styles'
	},

	{
		'name': 'style_accessibility',
		// 'title': 'Load accessibility styles',
		'title': 'Használatot segítő stílusok betöltése',
		'type': 'bool',
		'value': true,
		'group': 'styles'
	},

	{
		'name': 'style_hide_left_sidebar',
		// 'title': 'Hide left sidebar',
		'title': 'Bal oldali oszlop elrejtése',
		'type': 'bool',
		'value': false,
		'group': 'styles'
	},

	{
		'name': 'style_hide_right_sidebar',
		// 'title': 'Hide right sidebar',
		'title': 'Jobb oldali oszlop elrejtése',
		'type': 'bool',
		'value': false,
		'group': 'styles'
	},

	{
		'name': 'hideboringcomments',
		// 'title': 'Hide boring comments',
		'title': 'Unalmas hozzászólások elrejtése',
		'type': 'bool',
		'value': true,
		'group': 'comments',
		'requiredBy': ['boringcommentcontents']
	},

	{
		'name': 'boringcommentcontents',
		// 'title': 'Regular expression to identify boring comments',
		'title': 'Reguláris kifejezés az unalmas hozzászólások megtalálásához',
		'type': 'string',
		'value': '^([-_.]|[-+]1|sub|subscribe)$',
		'group': 'comments'
	},

	{
		'name': 'alwaysshownewcomments',
		'title': 'Olvasatlan hozzászlások mindig jelenjenek meg',
		'type': 'bool',
		'value': false,
		'group': 'comments'
	},

	{
		'name': 'validateForms',
		'title': 'Hozzászólások formai ellenőrzése beküldés előtt',
		'type': 'bool',
		'value': true,
		'group': 'content_creation'
	},

	{
		'name': 'logenabled',
		// 'title': 'Regular expression to identify boring comments',
		'title': 'Logolás engedélyezése',
		'type': 'bool',
		'value': false,
		'hidden': true,
		'group': null
	}
]);

export default defaultPrefs;
<commit_msg>fix(options) Typo fix hozzászlások -> hozzászólások (#31)<commit_after>const defaultPrefs = Object.freeze([

	{
		'name': 'setunlimitedlinks',
		// 'title': 'Show as many comments as possible on a page',
		'title': 'A lehető legtöbb hozzászólás mutatása',
		'type': 'bool',
		'value': true,
		'group': 'comments'
	},

	{
		'name': 'replacenewcommenttext',
		// 'title': 'Replace the "új" text of new comments to a better searchable one',
		'title': 'Olvasatlan hozzászólásoknál az "új" szöveg lecserélése valami jobban kereshetőre',
		'type': 'bool',
		'value': true,
		'group': 'comments',
		'requiredBy': ['newcommenttext']
	},

	{
		'name': 'newcommenttext',
		// 'title': 'The text to show instead of \"új\"',
		'title': 'Szöveg az új hozzászólásokban "új" helyett',
		'type': 'string',
		'value': '[new]',
		'group': 'comments'
	},

	{
		'name': 'filtertrolls',
		// 'title': 'Enable trollfilter',
		'title': 'Trollszűrő engedélyezése',
		'type': 'bool',
		'value': true,
		'group': 'comments',
		'requiredBy': ['edittrolls']
	},

	{
		'name': 'edittrolls',
		// 'title': 'Edit trolls',
		'title': 'Trollok szerkesztése',
		'label': 'Click to edit trolls',
		'type': 'control',
		'group': 'comments'
	},

	{
		'name': 'trolls',
		// 'title': 'List of trolls',
		'title': 'Trollok listája',
		'type': 'array',
		'value': [],
		'hidden': true,
		'group': 'comments'
	},

	{
		'name': 'huppercolor',
		// 'title': 'Default color of highlighted user\'s comment header',
		'title': 'Kiemelt felhasználók alapértelmezett színe',
		'type': 'color',
		'value': '#B5D7BE',
		'group': 'comments'
	},

	{
		'name': 'edithighlightusers',
		// 'title': 'Edit highlighted users',
		'title': 'Kiemelt felhasználók szerkesztése',
		'label': 'Click to edit highlighted users',
		'type': 'control',
		'group': 'comments'
	},

	{
		'name': 'highlightusers',
		// 'title': 'Highlight comments of the users',
		'title': 'Kiemelt felhasználók listája',
		'type': 'array',
		'value': [
			{name: 'username', color: '#fff999'},
			{name: 'username2', color: '#999fff'}
		],
		'hidden': true,
		'group': 'comments'
	},

	{
		'name': 'hidetaxonomy',
		// 'title': 'Hidden article types',
		'title': 'Rejtett sikkek listája',
		'type': 'array',
		'value': [],
		'hidden': true,
		'group': 'articles'
	},

	{
		'name': 'edithidetaxonomy',
		// 'title': 'Edit hidden article types',
		'title': 'Rejtett cikkek szerkesztése',
		'type': 'control',
		'group': 'articles'
	},

	{
		'name': 'blocks',
		// 'title': 'Block settings',
		'title': 'Block beállítások',
		'type': 'array',
		'value': [],
		'hidden': true,
		'group': 'blocks'
	},
	{
		'name': 'parseblocks',
		// 'title': 'Parse blocks',
		'title': 'Blokkokhoz tartozó funkciók engedélyezése',
		'type': 'bool',
		'value': true,
		'group': 'blocks'

	},

	{
		'name': 'style_wider_sidebar',
		// 'title': 'Width of sidebars',
		'title': 'Oldalsó oszlopok szélessége',
		'type': 'integer',
		'value': 0,
		'group': 'styles'
	},

	{
		'name': 'style_min_fontsize',
		// 'title': 'Minimum font size',
		'title': 'Minimum betűméret',
		'type': 'integer',
		'value': 0,
		'group': 'styles'
	},

	{
		'name': 'style_accessibility',
		// 'title': 'Load accessibility styles',
		'title': 'Használatot segítő stílusok betöltése',
		'type': 'bool',
		'value': true,
		'group': 'styles'
	},

	{
		'name': 'style_hide_left_sidebar',
		// 'title': 'Hide left sidebar',
		'title': 'Bal oldali oszlop elrejtése',
		'type': 'bool',
		'value': false,
		'group': 'styles'
	},

	{
		'name': 'style_hide_right_sidebar',
		// 'title': 'Hide right sidebar',
		'title': 'Jobb oldali oszlop elrejtése',
		'type': 'bool',
		'value': false,
		'group': 'styles'
	},

	{
		'name': 'hideboringcomments',
		// 'title': 'Hide boring comments',
		'title': 'Unalmas hozzászólások elrejtése',
		'type': 'bool',
		'value': true,
		'group': 'comments',
		'requiredBy': ['boringcommentcontents']
	},

	{
		'name': 'boringcommentcontents',
		// 'title': 'Regular expression to identify boring comments',
		'title': 'Reguláris kifejezés az unalmas hozzászólások megtalálásához',
		'type': 'string',
		'value': '^([-_.]|[-+]1|sub|subscribe)$',
		'group': 'comments'
	},

	{
		'name': 'alwaysshownewcomments',
		'title': 'Olvasatlan hozzászólások mindig jelenjenek meg',
		'type': 'bool',
		'value': false,
		'group': 'comments'
	},

	{
		'name': 'validateForms',
		'title': 'Hozzászólások formai ellenőrzése beküldés előtt',
		'type': 'bool',
		'value': true,
		'group': 'content_creation'
	},

	{
		'name': 'logenabled',
		// 'title': 'Regular expression to identify boring comments',
		'title': 'Logolás engedélyezése',
		'type': 'bool',
		'value': false,
		'hidden': true,
		'group': null
	}
]);

export default defaultPrefs;
<|endoftext|>


<commit_before>(function () {

    /**
     * The default state core singleton for {@link SceneJS.Lights} nodes
     */
    var defaultCore = {
        type: "lights",
        stateId: SceneJS._baseStateId++,
        hash: null,
        empty: false,
        lights: [
            {
                mode: "ambient",
                color: [0.7, 0.7, 0.8 ],
                diffuse: true,
                specular: false
            },
            {
                mode: "dir",
                color: [1.0, 1.0, 1.0 ],
                diffuse: true,
                specular: true,
                dir: [-0.5, -0.5, -1.0 ],
                space: "view"
            },
            {
                mode: "dir",
                color: [1.0, 1.0, 1.0 ],
                diffuse: false,
                specular: true,
                dir: [1.0, -0.9, -0.7 ],
                space: "view"
            }
        ]
    };

    makeHash(defaultCore);

    function makeHash(core) {
        if (core.lights && core.lights.length > 0) {
            var lights = core.lights;
            var parts = [];
            var light;
            for (var i = 0, len = lights.length; i < len; i++) {
                light = lights[i];
                parts.push(light.mode);
                if (light.specular) {
                    parts.push("s");
                }
                if (light.diffuse) {
                    parts.push("d");
                }
                parts.push((light.space == "world") ? "w" : "v");
            }
            core.hash = parts.join("");

        } else {
            core.hash = "";
        }
    }

    var coreStack = [];
    var stackLen = 0;

    SceneJS_events.addListener(
        SceneJS_events.SCENE_COMPILING,
        function (params) {
            params.engine.display.lights = defaultCore;
            stackLen = 0;
        });

    /**
     * @class Scene graph node which defines light sources to illuminate the {@link SceneJS.Geometry}s within its subgraph
     * @extends SceneJS.Node
     */
    SceneJS.Lights = SceneJS_NodeFactory.createNodeType("lights");

    SceneJS.Lights.prototype._init = function (params) {

        if (this._core.useCount == 1) { // This node defines the resource

            var lights = params.lights;

            if (!lights) {
                throw SceneJS_error.fatalError(
                    SceneJS.errors.NODE_CONFIG_EXPECTED,
                    "lights node attribute missing : 'lights'");
            }

            this._core.lights = this._core.lights || [];

            for (var i = 0, len = lights.length; i < len; i++) {
                this._initLight(i, lights[i]);
            }
        }
    };

    SceneJS.Lights.prototype._initLight = function (index, cfg) {

        var light = [];
        this._core.lights[index] = light;

        var mode = cfg.mode || "dir";
        if (mode != "dir" && mode != "point" && mode != "ambient") {
            throw SceneJS_error.fatalError(
                SceneJS.errors.ILLEGAL_NODE_CONFIG,
                "Light mode not supported - should be 'dir' or 'point' or 'ambient'");
        }

        var pos = cfg.pos;
        var dir = cfg.dir;

        var color = cfg.color;
        light.color = [
                color.r != undefined ? color.r : 1.0,
                color.g != undefined ? color.g : 1.0,
                color.b != undefined ? color.b : 1.0
        ];

        // Ambient lights hardwired to contribute to diffuse lighting
        light.mode = mode;
        light.diffuse = (mode == "ambient") ? true : ((cfg.diffuse != undefined) ? cfg.diffuse : true);
        light.specular = (mode == "ambient") ? false : ((cfg.specular != undefined) ? cfg.specular : true);
        light.pos = cfg.pos ? [ pos.x || 0, pos.y || 0, pos.z || 0 ] : [0, 0, 0];
        light.dir = cfg.dir ? [dir.x || 0, dir.y || 0, dir.z || 0] : [0, 0, 1];
        light.attenuation = [
                cfg.constantAttenuation != undefined ? cfg.constantAttenuation : 0.0,
                cfg.linearAttenuation || 0.0,
                cfg.quadraticAttenuation || 0.0
        ];

        var space = cfg.space;

        if (!space) {

            space = "world";

        } else if (space != "view" && space != "world") {

            throw SceneJS_error.fatalError(
                SceneJS.errors.ILLEGAL_NODE_CONFIG,
                    "lights node invalid value for property 'space': '" + space + "' - should be 'view' or 'world'");
        }

        light.space = space;

        this._core.hash = null;
    };

    SceneJS.Lights.prototype.setLights = function (lights) {
        var indexNum;
        for (var index in lights) {
            if (lights.hasOwnProperty(index)) {
                if (index != undefined || index != null) {
                    indexNum = parseInt(index);
                    if (indexNum < 0 || indexNum >= this._core.lights.length) {
                        throw SceneJS_error.fatalError(
                            SceneJS.errors.ILLEGAL_NODE_CONFIG,
                                "Invalid argument to set 'lights': index out of range (" + this._core.lights.length + " lights defined)");
                    }
                    this._setLight(indexNum, lights[index] || {});
                }
            }
        }
        this._engine.branchDirty(this); // Schedule recompilation of this subgraph
    };

    SceneJS.Lights.prototype._setLight = function (index, cfg) {

        var light = this._core.lights[index];

        // Impact of light update
        var imageDirty = false; // Redraw display list?
        var branchDirty = false; // Recompile scene branch?

        if (cfg.mode && cfg.mode != light.mode) {
            var mode = cfg.mode;
            if (mode != "dir" && mode != "point" && mode != "ambient") {
                throw SceneJS_error.fatalError(
                    SceneJS.errors.ILLEGAL_NODE_CONFIG,
                    "Light mode not supported - should be 'dir' or 'point' or 'ambient'");
            }
            light.mode = mode;
            light.diffuse = (mode == "ambient") ? true : ((cfg.diffuse != undefined) ? cfg.diffuse : true);
            light.specular = (mode == "ambient") ? false : ((cfg.specular != undefined) ? cfg.specular : true);
            branchDirty = true;
        }

        if (cfg.color) {
            var color = cfg.color;
            light.color = [
                    color.r != undefined ? color.r : 1.0,
                    color.g != undefined ? color.g : 1.0,
                    color.b != undefined ? color.b : 1.0
            ];
            imageDirty = true;
        }

        var pos = cfg.pos;
        if (pos) {
            light.pos = [ pos.x || 0, pos.y || 0, pos.z || 0 ];
            imageDirty = true;
        }

        var dir = cfg.dir;
        if (dir) {
            light.dir = [dir.x || 0, dir.y || 0, dir.z || 0];
            imageDirty = true;
        }

        if (cfg.constantAttenuation != undefined) {
            light.attenuation[0] = cfg.constantAttenuation;
            imageDirty = true;
        }
        if (cfg.linearAttenuation != undefined) {
            light.attenuation[1] = cfg.linearAttenuation;
            imageDirty = true;
        }
        if (cfg.quadraticAttenuation != undefined) {
            light.attenuation[2] = cfg.quadraticAttenuation;
            imageDirty = true;
        }

        if (cfg.space && cfg.space != light.space) {
            var space = cfg.space;
            if (space != "view" && space != "world") {
                throw SceneJS_error.fatalError(
                    SceneJS.errors.ILLEGAL_NODE_CONFIG,
                        "lights node invalid value for property 'space': '" + space + "' - should be 'view' or 'world'");
            }
            light.space = space;
            this._core.hash = null;
            branchDirty = true;
        }

        if (cfg.specular != undefined && cfg.specular != light.specular) {
            light.specular = cfg.specular;
            branchDirty = true;
        }
        if (cfg.diffuse != undefined && cfg.diffuse != light.diffuse) {
            light.diffuse = cfg.diffuse;
            branchDirty = true;
        }

        if (branchDirty) {
            this._engine.branchDirty(this); // Schedule recompilation of this subgraph
        } else if (imageDirty) {
            this._engine.display.imageDirty = true;
        }

        this._core.hash = null;
    };

    SceneJS.Lights.prototype._compile = function (ctx) {

        if (!this._core.hash) {
            makeHash(this._core);
        }

        this._engine.display.lights = coreStack[stackLen++] = this._core;
        this._compileNodes(ctx);
        this._engine.display.lights = (--stackLen > 0) ? coreStack[stackLen - 1] : defaultCore;
    };

})();<commit_msg>Lights represented by objects (instead of empty arrays)<commit_after>(function () {

    /**
     * The default state core singleton for {@link SceneJS.Lights} nodes
     */
    var defaultCore = {
        type: "lights",
        stateId: SceneJS._baseStateId++,
        hash: null,
        empty: false,
        lights: [
            {
                mode: "ambient",
                color: [0.7, 0.7, 0.8 ],
                diffuse: true,
                specular: false
            },
            {
                mode: "dir",
                color: [1.0, 1.0, 1.0 ],
                diffuse: true,
                specular: true,
                dir: [-0.5, -0.5, -1.0 ],
                space: "view"
            },
            {
                mode: "dir",
                color: [1.0, 1.0, 1.0 ],
                diffuse: false,
                specular: true,
                dir: [1.0, -0.9, -0.7 ],
                space: "view"
            }
        ]
    };

    makeHash(defaultCore);

    function makeHash(core) {
        if (core.lights && core.lights.length > 0) {
            var lights = core.lights;
            var parts = [];
            var light;
            for (var i = 0, len = lights.length; i < len; i++) {
                light = lights[i];
                parts.push(light.mode);
                if (light.specular) {
                    parts.push("s");
                }
                if (light.diffuse) {
                    parts.push("d");
                }
                parts.push((light.space == "world") ? "w" : "v");
            }
            core.hash = parts.join("");

        } else {
            core.hash = "";
        }
    }

    var coreStack = [];
    var stackLen = 0;

    SceneJS_events.addListener(
        SceneJS_events.SCENE_COMPILING,
        function (params) {
            params.engine.display.lights = defaultCore;
            stackLen = 0;
        });

    /**
     * @class Scene graph node which defines light sources to illuminate the {@link SceneJS.Geometry}s within its subgraph
     * @extends SceneJS.Node
     */
    SceneJS.Lights = SceneJS_NodeFactory.createNodeType("lights");

    SceneJS.Lights.prototype._init = function (params) {

        if (this._core.useCount == 1) { // This node defines the resource

            var lights = params.lights;

            if (!lights) {
                throw SceneJS_error.fatalError(
                    SceneJS.errors.NODE_CONFIG_EXPECTED,
                    "lights node attribute missing : 'lights'");
            }

            this._core.lights = this._core.lights || [];

            for (var i = 0, len = lights.length; i < len; i++) {
                this._initLight(i, lights[i]);
            }
        }
    };

    SceneJS.Lights.prototype._initLight = function (index, cfg) {

        var light = {};
        this._core.lights[index] = light;

        var mode = cfg.mode || "dir";
        if (mode != "dir" && mode != "point" && mode != "ambient") {
            throw SceneJS_error.fatalError(
                SceneJS.errors.ILLEGAL_NODE_CONFIG,
                "Light mode not supported - should be 'dir' or 'point' or 'ambient'");
        }

        var pos = cfg.pos;
        var dir = cfg.dir;

        var color = cfg.color;
        light.color = [
                color.r != undefined ? color.r : 1.0,
                color.g != undefined ? color.g : 1.0,
                color.b != undefined ? color.b : 1.0
        ];

        // Ambient lights hardwired to contribute to diffuse lighting
        light.mode = mode;
        light.diffuse = (mode == "ambient") ? true : ((cfg.diffuse != undefined) ? cfg.diffuse : true);
        light.specular = (mode == "ambient") ? false : ((cfg.specular != undefined) ? cfg.specular : true);
        light.pos = cfg.pos ? [ pos.x || 0, pos.y || 0, pos.z || 0 ] : [0, 0, 0];
        light.dir = cfg.dir ? [dir.x || 0, dir.y || 0, dir.z || 0] : [0, 0, 1];
        light.attenuation = [
                cfg.constantAttenuation != undefined ? cfg.constantAttenuation : 0.0,
                cfg.linearAttenuation || 0.0,
                cfg.quadraticAttenuation || 0.0
        ];

        var space = cfg.space;

        if (!space) {

            space = "world";

        } else if (space != "view" && space != "world") {

            throw SceneJS_error.fatalError(
                SceneJS.errors.ILLEGAL_NODE_CONFIG,
                    "lights node invalid value for property 'space': '" + space + "' - should be 'view' or 'world'");
        }

        light.space = space;

        this._core.hash = null;
    };

    SceneJS.Lights.prototype.setLights = function (lights) {
        var indexNum;
        for (var index in lights) {
            if (lights.hasOwnProperty(index)) {
                if (index != undefined || index != null) {
                    indexNum = parseInt(index);
                    if (indexNum < 0 || indexNum >= this._core.lights.length) {
                        throw SceneJS_error.fatalError(
                            SceneJS.errors.ILLEGAL_NODE_CONFIG,
                                "Invalid argument to set 'lights': index out of range (" + this._core.lights.length + " lights defined)");
                    }
                    this._setLight(indexNum, lights[index] || {});
                }
            }
        }
        this._engine.branchDirty(this); // Schedule recompilation of this subgraph
    };

    SceneJS.Lights.prototype._setLight = function (index, cfg) {

        var light = this._core.lights[index];

        // Impact of light update
        var imageDirty = false; // Redraw display list?
        var branchDirty = false; // Recompile scene branch?

        if (cfg.mode && cfg.mode != light.mode) {
            var mode = cfg.mode;
            if (mode != "dir" && mode != "point" && mode != "ambient") {
                throw SceneJS_error.fatalError(
                    SceneJS.errors.ILLEGAL_NODE_CONFIG,
                    "Light mode not supported - should be 'dir' or 'point' or 'ambient'");
            }
            light.mode = mode;
            light.diffuse = (mode == "ambient") ? true : ((cfg.diffuse != undefined) ? cfg.diffuse : true);
            light.specular = (mode == "ambient") ? false : ((cfg.specular != undefined) ? cfg.specular : true);
            branchDirty = true;
        }

        if (cfg.color) {
            var color = cfg.color;
            light.color = [
                    color.r != undefined ? color.r : 1.0,
                    color.g != undefined ? color.g : 1.0,
                    color.b != undefined ? color.b : 1.0
            ];
            imageDirty = true;
        }

        var pos = cfg.pos;
        if (pos) {
            light.pos = [ pos.x || 0, pos.y || 0, pos.z || 0 ];
            imageDirty = true;
        }

        var dir = cfg.dir;
        if (dir) {
            light.dir = [dir.x || 0, dir.y || 0, dir.z || 0];
            imageDirty = true;
        }

        if (cfg.constantAttenuation != undefined) {
            light.attenuation[0] = cfg.constantAttenuation;
            imageDirty = true;
        }
        if (cfg.linearAttenuation != undefined) {
            light.attenuation[1] = cfg.linearAttenuation;
            imageDirty = true;
        }
        if (cfg.quadraticAttenuation != undefined) {
            light.attenuation[2] = cfg.quadraticAttenuation;
            imageDirty = true;
        }

        if (cfg.space && cfg.space != light.space) {
            var space = cfg.space;
            if (space != "view" && space != "world") {
                throw SceneJS_error.fatalError(
                    SceneJS.errors.ILLEGAL_NODE_CONFIG,
                        "lights node invalid value for property 'space': '" + space + "' - should be 'view' or 'world'");
            }
            light.space = space;
            this._core.hash = null;
            branchDirty = true;
        }

        if (cfg.specular != undefined && cfg.specular != light.specular) {
            light.specular = cfg.specular;
            branchDirty = true;
        }
        if (cfg.diffuse != undefined && cfg.diffuse != light.diffuse) {
            light.diffuse = cfg.diffuse;
            branchDirty = true;
        }

        if (branchDirty) {
            this._engine.branchDirty(this); // Schedule recompilation of this subgraph
        } else if (imageDirty) {
            this._engine.display.imageDirty = true;
        }

        this._core.hash = null;
    };

    SceneJS.Lights.prototype._compile = function (ctx) {

        if (!this._core.hash) {
            makeHash(this._core);
        }

        this._engine.display.lights = coreStack[stackLen++] = this._core;
        this._compileNodes(ctx);
        this._engine.display.lights = (--stackLen > 0) ? coreStack[stackLen - 1] : defaultCore;
    };

})();<|endoftext|>


<commit_before>import isEqual from './is-equal.js';

export default ({ client, useCallback, useEffect, useRef, useState }) => ({
  context: _context,
  query: _query
}) => {
  const [context, setContext] = useState(_context);
  const [data, setData] = useState(client.cacheExecute({ query: _query }));
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [query, setQuery] = useState(_query);
  const executeId = useRef(0);

  useEffect(() => {
    if (!isEqual(query, _query)) setQuery(_query);
  }, [query, _query]);

  useEffect(() => {
    if (!isEqual(context, _context)) setContext(_context);
  }, [context, _context]);

  const execute = useCallback(async () => {
    const id = ++executeId.current;
    setError(null);
    setIsLoading(true);
    let error;
    try {
      await client.execute({ context, query });
    } catch (er) {
      error = er;
    }
    if (id !== executeId.current) return;

    if (error) setError(error);
    setIsLoading(false);
  }, [context, query]);

  useEffect(() => {
    execute();
  }, [execute]);

  useEffect(() => client.watch({ onChange: setData, query }), [query]);

  return { data, error, isLoading, execute };
};
<commit_msg>Update setState<commit_after>import isEqual from './is-equal.js';

export default ({ client, useCallback, useEffect, useRef, useState }) => ({
  context: _context,
  query: _query
}) => {
  const [context, setContext] = useState(_context);
  const [data, setData] = useState(client.cacheExecute({ query: _query }));
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [query, setQuery] = useState(_query);
  const executeId = useRef(0);

  useEffect(() => {
    if (!isEqual(query, _query)) setQuery(_query);
  }, [query, _query]);

  useEffect(() => {
    if (!isEqual(context, _context)) setContext(_context);
  }, [context, _context]);

  const execute = useCallback(async () => {
    const id = ++executeId.current;
    setError(null);
    setIsLoading(true);
    let error = null;
    try {
      await client.execute({ context, query });
    } catch (er) {
      error = er;
    }
    if (id !== executeId.current) return;

    setError(error);
    setIsLoading(false);
  }, [context, query]);

  useEffect(() => {
    execute();
  }, [execute]);

  useEffect(() => client.watch({ onChange: setData, query }), [query]);

  return { data, error, isLoading, execute };
};
<|endoftext|>


<commit_before>/*
 * Movable Type DataAPI SDK for JavaScript v1
 * Copyright (c) 2013 Six Apart, Ltd.
 * This program is distributed under the terms of the MIT license.
 *
 * Includes jQuery JavaScript Library to serialize a HTMLFormElement
 * http://jquery.com/
 * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 */

;(function(window, undefined) {

"use strict";
<commit_msg>Insert the project URL to script header.<commit_after>/*
 * Movable Type DataAPI SDK for JavaScript v1
 * https://github.com/movabletype/mt-data-api-sdk-js
 * Copyright (c) 2013 Six Apart, Ltd.
 * This program is distributed under the terms of the MIT license.
 *
 * Includes jQuery JavaScript Library to serialize a HTMLFormElement
 * http://jquery.com/
 * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 */

;(function(window, undefined) {

"use strict";
<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2019  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('15.4.0');
		this.setClientTag('node:19-07-30');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2019  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('15.4.0');
		this.setClientTag('node:19-07-31');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2020  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('16.12.0');
		this.setClientTag('node:20-11-25');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2020  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('16.12.0');
		this.setClientTag('node:20-11-26');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>