<commit_before>/*
 * Copyright 2015-2016 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {html, LitElement} from "lit";
import VariantUtils from "../variant-utils.js";
import ClinicalAnalysisManager from "../../clinical/clinical-analysis-manager.js";
import LitUtils from "../../commons/utils/lit-utils.js";
import NotificationUtils from "../../commons/utils/notification-utils.js";
import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js";
import UtilsNew from "../../../core/utilsNew.js";
import "./variant-interpreter-browser-toolbar.js";
import "./variant-interpreter-grid.js";
import "./variant-interpreter-detail.js";
import "../variant-browser-filter.js";
import "../../commons/tool-header.js";
import "../../commons/opencga-active-filters.js";

class VariantInterpreterBrowserTemplate extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            clinicalAnalysis: {
                type: Object
            },
            query: {
                type: Object
            },
            opencgaSession: {
                type: Object
            },
            cellbaseClient: {
                type: Object
            },
            toolId: {
                type: String
            },
            settings: {
                type: Object
            },
            config: {
                type: Object
            }
        };
    }

    _init() {
        this._prefix = UtilsNew.randomString(8);

        this.variant = null;
        this.query = {};
        this.savedVariants = [];
        this.notSavedVariantIds = 0;
        this.removedVariantIds = 0;

        this.currentQueryBeforeSaveEvent = null;

        this._config = {};
    }

    connectedCallback() {
        super.connectedCallback();

        this.clinicalAnalysisManager = new ClinicalAnalysisManager(this, this.clinicalAnalysis, this.opencgaSession);
    }

    update(changedProperties) {
        if (changedProperties.has("clinicalAnalysis")) {
            this.clinicalAnalysisObserver();
        }
        if (changedProperties.has("query")) {
            this.queryObserver();
        }
        if (changedProperties.has("opencgaSession")) {
            this.clinicalAnalysisManager = new ClinicalAnalysisManager(this, this.clinicalAnalysis, this.opencgaSession);
        }
        if (changedProperties.has("settings")) {
            this.settingsObserver();
        }
        if (changedProperties.has("config")) {
            this._config = {...this.config};
        }
        super.update(changedProperties);
    }

    settingsObserver() {
        if (!this.clinicalAnalysis) {
            return;
        }
        // merge filters
        this._config = {...this.config};

        // filter list, canned filters, detail tabs
        if (this.settings?.menu) {
            this._config.filter = UtilsNew.mergeFiltersAndDetails(this._config?.filter, this.settings);
        }

        if (this.settings?.table) {
            this._config.filter.result.grid = {...this._config.filter.result.grid, ...this.settings.table};
        }

        if (this.settings?.table?.toolbar) {
            this._config.filter.result.grid.toolbar = {...this._config.filter.result.grid.toolbar, ...this.settings.table.toolbar};
        }

        // Check for user configuration
        if (this.toolId && this.opencgaSession.user?.configs?.IVA?.[this.toolId]?.grid) {
            this._config.filter.result.grid = {
                ...this._config.filter.result.grid,
                ...this.opencgaSession.user.configs.IVA[this.toolId].grid,
            };
        }
    }

    clinicalAnalysisObserver() {
        // Init saved variants with the primary findings of the main interpretation
        if (this.clinicalAnalysis?.interpretation?.primaryFindings?.length) {
            this.savedVariants = this.clinicalAnalysis?.interpretation?.primaryFindings?.map(v => v.id);
        }
        this.settingsObserver();

        // When refreshing AFTER saving variants we set the same query as before refreshing, check 'onSaveVariants'
        if (this.currentQueryBeforeSaveEvent) {
            this.query = {...this.currentQueryBeforeSaveEvent};
            this.currentQueryBeforeEvent = null;
        }
    }

    queryObserver() {
        if (this.opencgaSession && this.query) {
            this.preparedQuery = {study: this.opencgaSession.study.fqn, ...this.query};
            this.executedQuery = {study: this.opencgaSession.study.fqn, ...this.query};
        }
        this.requestUpdate();
    }

    onSelectVariant(e) {
        this.variantId = e.detail.id;
        this.variant = e.detail.row;
        this.requestUpdate();
    }

    onCheckVariant(e) {
        const rows = Array.isArray(e.detail.row) ? e.detail.row : [e.detail.row];
        rows.forEach(row => {
            if (e.detail.checked) {
                this.clinicalAnalysisManager.addVariant(row);
            } else {
                this.clinicalAnalysisManager.removeVariant(row);
            }
        });
    }

    onUpdateVariant(e) {
        const rows = Array.isArray(e.detail.row) ? e.detail.row : [e.detail.row];
        rows.forEach(row => {
            this.clinicalAnalysisManager.updateSingleVariant(row);
        });
        this.requestUpdate();
    }

    onFilterVariants(e) {
        const lockedFields = [...this._config?.filter?.activeFilters?.lockedFields.map(key => key.id), "study"];
        const variantIds = e.detail.variants.map(v => v.id);
        this.executedQuery = {...UtilsNew.filterKeys(this.executedQuery, lockedFields), id: variantIds.join(",")};
        this.preparedQuery = {...this.executedQuery};
        this.requestUpdate();
    }

    onResetVariants(e) {
        this.clinicalAnalysisManager.reset();

        this.preparedQuery = {...this.preparedQuery};
        this.executedQuery = {...this.executedQuery};
        delete this.preparedQuery.id;
        delete this.executedQuery.id;

        this.clinicalAnalysis = {...this.clinicalAnalysis};
    }

    onSaveVariants(e) {
        // We save current query so we can execute the same query after refreshing, check 'clinicaAnalysisObserver'
        this.currentQueryBeforeSaveEvent = this.query;

        const comment = e.detail.comment;
        this.clinicalAnalysisManager.updateInterpretation(comment, () => {
            LitUtils.dispatchCustomEvent(this, "clinicalAnalysisUpdate", null, {
                clinicalAnalysis: this.clinicalAnalysis,
            }, null, {bubbles: true, composed: true});
        });
    }

    onVariantFilterChange(e) {
        this.preparedQuery = e.detail.query;
        this.requestUpdate();
    }

    onVariantFilterSearch(e) {
        this.preparedQuery = e.detail.query;
        this.executedQuery = e.detail.query;
        this.query = {...e.detail.query}; // We need to update the internal query to propagate to filters
        this.requestUpdate();
    }

    onActiveFilterChange(e) {
        VariantUtils.validateQuery(e.detail);
        this.query = {...e.detail};
        this.requestUpdate();
    }

    onActiveFilterClear() {
        const _query = {
            study: this.opencgaSession.study.fqn,
            sample: this._sampleQuery
        };

        // Check if panelLock is enabled
        if (this.clinicalAnalysis.panelLock) {
            _query.panel = this.query.panel;
            _query.panelIntersection = true;
        }

        this.query = _query;
        this.requestUpdate();
    }

    async onGridConfigSave(e) {
        const newGridConfig = {...e.detail.value};

        // Remove highlights and copies configuration from new config
        delete newGridConfig.highlights;
        // delete newConfig.copies;

        // Update user configuration
        try {
            await OpencgaCatalogUtils.updateGridConfig(this.opencgaSession, this.toolId, newGridConfig);
            this.settingsObserver();
            this.requestUpdate();

            NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, {
                message: "Configuration saved",
            });
        } catch (error) {
            NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error);
        }
    }

    render() {
        // Check Project exists
        if (!this.opencgaSession?.study) {
            return html`

No project available to browse. Please login to continue

            `;
        }

        return html`

            ${this._config.showTitle ? html`
                <tool-header
                    title="${this.clinicalAnalysis ? `${this._config.title} (${this.clinicalAnalysis.id})` : this._config.title}"
                    icon="${this._config.icon}">
                </tool-header>
            ` : null}

                    <variant-browser-filter
                        .opencgaSession="${this.opencgaSession}"
                        .query="${this.query}"
                        .clinicalAnalysis="${this.clinicalAnalysis}"
                        .cellbaseClient="${this.cellbaseClient}"
                        .populationFrequencies="${POPULATION_FREQUENCIES}"
                        .consequenceTypes="${SAMPLE_STATS_CONSEQUENCE_TYPES}"
                        .config="${this._config.filter}"
                        @queryChange="${this.onVariantFilterChange}"
                        @querySearch="${this.onVariantFilterSearch}">
                    </variant-browser-filter>

                        ${OpencgaCatalogUtils.checkPermissions(this.opencgaSession.study, this.opencgaSession.user.id, "WRITE_CLINICAL_ANALYSIS") ?
                            html`
                                <variant-interpreter-browser-toolbar
                                    .clinicalAnalysis="${this.clinicalAnalysis}"
                                    .state="${this.clinicalAnalysisManager.state}"
                                    @filterVariants="${this.onFilterVariants}"
                                    @resetVariants="${this.onResetVariants}"
                                    @saveInterpretation="${this.onSaveVariants}">
                                </variant-interpreter-browser-toolbar>
                            ` : null
                        }

                            <opencga-active-filters
                                resource="VARIANT"
                                .opencgaSession="${this.opencgaSession}"
                                .clinicalAnalysis="${this.clinicalAnalysis}"
                                .defaultStudy="${this.opencgaSession.study.fqn}"
                                .query="${this.preparedQuery}"
                                .executedQuery="${this.executedQuery}"
                                .filters="${this._config.filter.activeFilters.filters}"
                                .alias="${this._config.activeFilterAlias}"
                                .genotypeSamples="${this.genotypeSamples}"
                                .modeInheritance="${this.modeInheritance}"
                                .config="${this._config.filter.activeFilters}"
                                @activeFilterChange="${this.onActiveFilterChange}"
                                @activeFilterClear="${this.onActiveFilterClear}">
                            </opencga-active-filters>

                                ${!this._config.filter.result.grid.isRearrangement ? html`
                                    <variant-interpreter-grid
                                        .opencgaSession="${this.opencgaSession}"
                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                        .query="${this.executedQuery}"
                                        .review="${true}"
                                        .config="${this._config.filter.result.grid}"
                                        @selectrow="${this.onSelectVariant}"
                                        @updaterow="${this.onUpdateVariant}"
                                        @checkrow="${this.onCheckVariant}"
                                        @gridconfigsave="${this.onGridConfigSave}">
                                    </variant-interpreter-grid>` : html`
                                    <variant-interpreter-rearrangement-grid
                                        .opencgaSession="${this.opencgaSession}"
                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                        .query="${this.executedQuery}"
                                        .review="${true}"
                                        .config="${this._config.filter.result.grid}"
                                        @selectrow="${this.onSelectVariant}"
                                        @updaterow="${this.onUpdateVariant}"
                                        @checkrow="${this.onCheckVariant}">
                                    </variant-interpreter-rearrangement-grid>`
                                }

                                <variant-interpreter-detail
                                    .opencgaSession="${this.opencgaSession}"
                                    .clinicalAnalysis="${this.clinicalAnalysis}"
                                    .variant="${this.variant}"
                                    .cellbaseClient="${this.cellbaseClient}"
                                    .config=${this._config.filter.detail}>
                                </variant-interpreter-detail>

        `;
    }

}

customElements.define("variant-interpreter-browser-template", VariantInterpreterBrowserTemplate);
<commit_msg>wc: fix displaying pre-configured example filters in interpreter browser (#381)<commit_after>/*
 * Copyright 2015-2016 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {html, LitElement} from "lit";
import VariantUtils from "../variant-utils.js";
import ClinicalAnalysisManager from "../../clinical/clinical-analysis-manager.js";
import LitUtils from "../../commons/utils/lit-utils.js";
import NotificationUtils from "../../commons/utils/notification-utils.js";
import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js";
import UtilsNew from "../../../core/utilsNew.js";
import "./variant-interpreter-browser-toolbar.js";
import "./variant-interpreter-grid.js";
import "./variant-interpreter-detail.js";
import "../variant-browser-filter.js";
import "../../commons/tool-header.js";
import "../../commons/opencga-active-filters.js";

class VariantInterpreterBrowserTemplate extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            clinicalAnalysis: {
                type: Object
            },
            query: {
                type: Object
            },
            opencgaSession: {
                type: Object
            },
            cellbaseClient: {
                type: Object
            },
            toolId: {
                type: String
            },
            settings: {
                type: Object
            },
            config: {
                type: Object
            }
        };
    }

    _init() {
        this._prefix = UtilsNew.randomString(8);

        this.variant = null;
        this.query = {};
        this.savedVariants = [];
        this.notSavedVariantIds = 0;
        this.removedVariantIds = 0;

        this.currentQueryBeforeSaveEvent = null;

        this._config = {};
    }

    connectedCallback() {
        super.connectedCallback();

        this.clinicalAnalysisManager = new ClinicalAnalysisManager(this, this.clinicalAnalysis, this.opencgaSession);
    }

    update(changedProperties) {
        if (changedProperties.has("clinicalAnalysis")) {
            this.clinicalAnalysisObserver();
        }

        if (changedProperties.has("query")) {
            this.queryObserver();
        }

        if (changedProperties.has("opencgaSession")) {
            this.clinicalAnalysisManager = new ClinicalAnalysisManager(this, this.clinicalAnalysis, this.opencgaSession);
        }

        if (changedProperties.has("settings") || changedProperties.has("config")) {
            this.settingsObserver();
        }

        super.update(changedProperties);
    }

    settingsObserver() {
        if (!this.clinicalAnalysis) {
            return;
        }
        // merge filters
        this._config = {...this.config};

        // filter list, canned filters, detail tabs
        if (this.settings?.menu) {
            this._config.filter = UtilsNew.mergeFiltersAndDetails(this._config?.filter, this.settings);
        }

        if (this.settings?.table) {
            this._config.filter.result.grid = {...this._config.filter.result.grid, ...this.settings.table};
        }

        if (this.settings?.table?.toolbar) {
            this._config.filter.result.grid.toolbar = {...this._config.filter.result.grid.toolbar, ...this.settings.table.toolbar};
        }

        // Check for user configuration
        if (this.toolId && this.opencgaSession.user?.configs?.IVA?.[this.toolId]?.grid) {
            this._config.filter.result.grid = {
                ...this._config.filter.result.grid,
                ...this.opencgaSession.user.configs.IVA[this.toolId].grid,
            };
        }
    }

    clinicalAnalysisObserver() {
        // Init saved variants with the primary findings of the main interpretation
        if (this.clinicalAnalysis?.interpretation?.primaryFindings?.length) {
            this.savedVariants = this.clinicalAnalysis?.interpretation?.primaryFindings?.map(v => v.id);
        }
        this.settingsObserver();

        // When refreshing AFTER saving variants we set the same query as before refreshing, check 'onSaveVariants'
        if (this.currentQueryBeforeSaveEvent) {
            this.query = {...this.currentQueryBeforeSaveEvent};
            this.currentQueryBeforeEvent = null;
        }
    }

    queryObserver() {
        if (this.opencgaSession && this.query) {
            this.preparedQuery = {study: this.opencgaSession.study.fqn, ...this.query};
            this.executedQuery = {study: this.opencgaSession.study.fqn, ...this.query};
        }
        this.requestUpdate();
    }

    onSelectVariant(e) {
        this.variantId = e.detail.id;
        this.variant = e.detail.row;
        this.requestUpdate();
    }

    onCheckVariant(e) {
        const rows = Array.isArray(e.detail.row) ? e.detail.row : [e.detail.row];
        rows.forEach(row => {
            if (e.detail.checked) {
                this.clinicalAnalysisManager.addVariant(row);
            } else {
                this.clinicalAnalysisManager.removeVariant(row);
            }
        });
    }

    onUpdateVariant(e) {
        const rows = Array.isArray(e.detail.row) ? e.detail.row : [e.detail.row];
        rows.forEach(row => {
            this.clinicalAnalysisManager.updateSingleVariant(row);
        });
        this.requestUpdate();
    }

    onFilterVariants(e) {
        const lockedFields = [...this._config?.filter?.activeFilters?.lockedFields.map(key => key.id), "study"];
        const variantIds = e.detail.variants.map(v => v.id);
        this.executedQuery = {...UtilsNew.filterKeys(this.executedQuery, lockedFields), id: variantIds.join(",")};
        this.preparedQuery = {...this.executedQuery};
        this.requestUpdate();
    }

    onResetVariants(e) {
        this.clinicalAnalysisManager.reset();

        this.preparedQuery = {...this.preparedQuery};
        this.executedQuery = {...this.executedQuery};
        delete this.preparedQuery.id;
        delete this.executedQuery.id;

        this.clinicalAnalysis = {...this.clinicalAnalysis};
    }

    onSaveVariants(e) {
        // We save current query so we can execute the same query after refreshing, check 'clinicaAnalysisObserver'
        this.currentQueryBeforeSaveEvent = this.query;

        const comment = e.detail.comment;
        this.clinicalAnalysisManager.updateInterpretation(comment, () => {
            LitUtils.dispatchCustomEvent(this, "clinicalAnalysisUpdate", null, {
                clinicalAnalysis: this.clinicalAnalysis,
            }, null, {bubbles: true, composed: true});
        });
    }

    onVariantFilterChange(e) {
        this.preparedQuery = e.detail.query;
        this.requestUpdate();
    }

    onVariantFilterSearch(e) {
        this.preparedQuery = e.detail.query;
        this.executedQuery = e.detail.query;
        this.query = {...e.detail.query}; // We need to update the internal query to propagate to filters
        this.requestUpdate();
    }

    onActiveFilterChange(e) {
        VariantUtils.validateQuery(e.detail);
        this.query = {...e.detail};
        this.requestUpdate();
    }

    onActiveFilterClear() {
        const _query = {
            study: this.opencgaSession.study.fqn,
            sample: this._sampleQuery
        };

        // Check if panelLock is enabled
        if (this.clinicalAnalysis.panelLock) {
            _query.panel = this.query.panel;
            _query.panelIntersection = true;
        }

        this.query = _query;
        this.requestUpdate();
    }

    async onGridConfigSave(e) {
        const newGridConfig = {...e.detail.value};

        // Remove highlights and copies configuration from new config
        delete newGridConfig.highlights;
        // delete newConfig.copies;

        // Update user configuration
        try {
            await OpencgaCatalogUtils.updateGridConfig(this.opencgaSession, this.toolId, newGridConfig);
            this.settingsObserver();
            this.requestUpdate();

            NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, {
                message: "Configuration saved",
            });
        } catch (error) {
            NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error);
        }
    }

    render() {
        // Check Project exists
        if (!this.opencgaSession?.study) {
            return html`

No project available to browse. Please login to continue

            `;
        }

        return html`

            ${this._config.showTitle ? html`
                <tool-header
                    title="${this.clinicalAnalysis ? `${this._config.title} (${this.clinicalAnalysis.id})` : this._config.title}"
                    icon="${this._config.icon}">
                </tool-header>
            ` : null}

                    <variant-browser-filter
                        .opencgaSession="${this.opencgaSession}"
                        .query="${this.query}"
                        .clinicalAnalysis="${this.clinicalAnalysis}"
                        .cellbaseClient="${this.cellbaseClient}"
                        .populationFrequencies="${POPULATION_FREQUENCIES}"
                        .consequenceTypes="${SAMPLE_STATS_CONSEQUENCE_TYPES}"
                        .config="${this._config.filter}"
                        @queryChange="${this.onVariantFilterChange}"
                        @querySearch="${this.onVariantFilterSearch}">
                    </variant-browser-filter>

                        ${OpencgaCatalogUtils.checkPermissions(this.opencgaSession.study, this.opencgaSession.user.id, "WRITE_CLINICAL_ANALYSIS") ?
                            html`
                                <variant-interpreter-browser-toolbar
                                    .clinicalAnalysis="${this.clinicalAnalysis}"
                                    .state="${this.clinicalAnalysisManager.state}"
                                    @filterVariants="${this.onFilterVariants}"
                                    @resetVariants="${this.onResetVariants}"
                                    @saveInterpretation="${this.onSaveVariants}">
                                </variant-interpreter-browser-toolbar>
                            ` : null
                        }

                            <opencga-active-filters
                                resource="VARIANT"
                                .opencgaSession="${this.opencgaSession}"
                                .clinicalAnalysis="${this.clinicalAnalysis}"
                                .defaultStudy="${this.opencgaSession.study.fqn}"
                                .query="${this.preparedQuery}"
                                .executedQuery="${this.executedQuery}"
                                .filters="${this._config.filter.examples}"
                                .alias="${this._config.activeFilterAlias}"
                                .genotypeSamples="${this.genotypeSamples}"
                                .modeInheritance="${this.modeInheritance}"
                                .config="${this._config.filter.activeFilters}"
                                @activeFilterChange="${this.onActiveFilterChange}"
                                @activeFilterClear="${this.onActiveFilterClear}">
                            </opencga-active-filters>

                                ${!this._config.filter.result.grid.isRearrangement ? html`
                                    <variant-interpreter-grid
                                        .opencgaSession="${this.opencgaSession}"
                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                        .query="${this.executedQuery}"
                                        .review="${true}"
                                        .config="${this._config.filter.result.grid}"
                                        @selectrow="${this.onSelectVariant}"
                                        @updaterow="${this.onUpdateVariant}"
                                        @checkrow="${this.onCheckVariant}"
                                        @gridconfigsave="${this.onGridConfigSave}">
                                    </variant-interpreter-grid>` : html`
                                    <variant-interpreter-rearrangement-grid
                                        .opencgaSession="${this.opencgaSession}"
                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                        .query="${this.executedQuery}"
                                        .review="${true}"
                                        .config="${this._config.filter.result.grid}"
                                        @selectrow="${this.onSelectVariant}"
                                        @updaterow="${this.onUpdateVariant}"
                                        @checkrow="${this.onCheckVariant}">
                                    </variant-interpreter-rearrangement-grid>`
                                }

                                <variant-interpreter-detail
                                    .opencgaSession="${this.opencgaSession}"
                                    .clinicalAnalysis="${this.clinicalAnalysis}"
                                    .variant="${this.variant}"
                                    .cellbaseClient="${this.cellbaseClient}"
                                    .config=${this._config.filter.detail}>
                                </variant-interpreter-detail>

        `;
    }

}

customElements.define("variant-interpreter-browser-template", VariantInterpreterBrowserTemplate);
<|endoftext|>


<commit_before>$(window).load(function() {
    if(!window.markdown_init){
        window.markdown_init = true;
        $('div.markdown_edit').each(function(){
            var $container = $(this);
            var $textarea = $('textarea', $container);
            var $preview = $('a.markdown_preview', $container);
            var $edit = $('a.markdown_edit', $container);
            var $help = $('a.markdown_help', $container);
            var $preview_area = $('div.markdown_preview', $container);
            var $help_area = $('div.markdown_help', $container);
            $preview.click(function(evt){
                evt.preventDefault();
                $.post('/nf/markdown_to_html', {
                    markdown:$textarea.val(),
                    project:$('input.markdown_project', $container).val(),
                    app:$('input.markdown_app', $container).val()
                },
                function(resp){
                    $preview_area.html(resp);
                    $preview_area.show();
                    $textarea.hide();
                    $preview.hide();
                    $edit.show();
                });
            });
            $edit.click(function(evt){
                evt.preventDefault();
                $preview_area.hide();
                $textarea.show();
                $preview.show();
                $edit.hide();
            });
            $help.click(function(evt){
                evt.preventDefault();
                $help_area.lightbox_me();
            });
            $('.close', $help_area).bind('click', function() {
                $help_area.hide();
            });
        });
    }
});<commit_msg>[#1478] Fix problem with MD preview (CSRF failure)<commit_after>$(window).load(function() {
    if(!window.markdown_init){
        window.markdown_init = true;
        $('div.markdown_edit').each(function(){
            var $container = $(this);
            var $textarea = $('textarea', $container);
            var $preview = $('a.markdown_preview', $container);
            var $edit = $('a.markdown_edit', $container);
            var $help = $('a.markdown_help', $container);
            var $preview_area = $('div.markdown_preview', $container);
            var $help_area = $('div.markdown_help', $container);
            $preview.click(function(evt){
                evt.preventDefault();
                var cval = $.cookie('_session_id');
                $.post('/nf/markdown_to_html', {
                    markdown:$textarea.val(),
                    project:$('input.markdown_project', $container).val(),
                    app:$('input.markdown_app', $container).val(),
                    _session_id:cval
                },
                function(resp){
                    $preview_area.html(resp);
                    $preview_area.show();
                    $textarea.hide();
                    $preview.hide();
                    $edit.show();
                });
            });
            $edit.click(function(evt){
                evt.preventDefault();
                $preview_area.hide();
                $textarea.show();
                $preview.show();
                $edit.hide();
            });
            $help.click(function(evt){
                evt.preventDefault();
                $help_area.lightbox_me();
            });
            $('.close', $help_area).bind('click', function() {
                $help_area.hide();
            });
        });
    }
});<|endoftext|>


<commit_before>/**
 * Shopware 5
 * Copyright (c) shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * 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.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 *
 * @category   Shopware
 * @package    Customer
 * @subpackage Detail
 * @version    $Id$
 * @author shopware AG
 */

//{namespace name=backend/performance/main}

/**
 * Categories fieldSet
 */
//{block name="backend/performance/view/tabs/settings/fields/categories"}
Ext.define('Shopware.apps.Performance.view.tabs.settings.fields.Categories', {
    /**
     * Define that the base field set is an extension of the "Base" fieldSet
     * @string
     */
    extend:'Shopware.apps.Performance.view.tabs.settings.fields.Base',

    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     * @string
     */
    alias:'widget.performance-tabs-settings-categories',

    /**
     * Description of the fieldSet
     */
    caption: '{s name=tabs/settings/categories/title}Categories{/s}',

    /**
     * Component event method which is fired when the component
     * is initials. The component is initials when the user
     * want to create a new customer or edit an existing customer
     * @return void
     */
    initComponent:function () {
        var me = this;

        me.items = me.getItems();
        me.callParent(arguments);

    },

    getItems: function() {
        var me = this;

        return [
            {
                xtype: 'fieldset',
                defaults: me.defaults,
                title: '{s name=fieldset/information}Information{/s}',
                items: [
                    me.createDescriptionContainer("{s name=fieldset/categories/info}Hier können Sie Einstellungen vornehmen, die die Performance der Produkt-Listings betreffen.{/s}")]
            },
            {
                xtype: 'fieldset',
                title: '{s name=fieldset/configuration}Configuration{/s}',
                items: [
                    {
                        xtype: 'performance-multi-request-button',
                        event: 'category',
                        title: '{s name=fieldset/categories/repair}Rebuild cagtegory tree{/s}'
                    },
                    {
                        fieldLabel: '{s name=fieldset/categories/text/moveBatchModeEnabled}Move categories in batch-mode{/s}',
                        helpText: '',
                        name: 'categories[moveBatchModeEnabled]',
                        xtype: 'checkbox',
                        uncheckedValue: false,
                        inputValue: true,
                        labelWidth: 300
                    }
                ]
            }, {
                xtype: 'fieldset',
                defaults: me.defaults,
                title: '{s name=fieldset/listings}Listings{/s}',
                items: [{
                    fieldLabel: 'Default listing sorting',
                    helpText: '',
                    name: 'categories[defaultListingSorting]',
                    xtype: 'combo',
                    valueField: 'id',
                    value: 1,
                    editable: false,
                    displayField: 'name',
                    store: Ext.create('Shopware.apps.Performance.store.ListingSorting').load()
                }, {
                    name: 'categories[articlesperpage]',
                    fieldLabel: '{s name=fieldset/categories/text/perPage}Articles per page{/s}',
                    helpText: '{s name=fieldset/categories/help/perPage}How many articles should be shown per page?{/s}',

                    xtype: 'numberfield',
                    minValue: 1
                }]
            }
        ];
    }

});
//{/block}
<commit_msg>SW-9854 - added missing snippet to js file<commit_after>/**
 * Shopware 5
 * Copyright (c) shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * 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.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 *
 * @category   Shopware
 * @package    Customer
 * @subpackage Detail
 * @version    $Id$
 * @author shopware AG
 */

//{namespace name=backend/performance/main}

/**
 * Categories fieldSet
 */
//{block name="backend/performance/view/tabs/settings/fields/categories"}
Ext.define('Shopware.apps.Performance.view.tabs.settings.fields.Categories', {
    /**
     * Define that the base field set is an extension of the "Base" fieldSet
     * @string
     */
    extend:'Shopware.apps.Performance.view.tabs.settings.fields.Base',

    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     * @string
     */
    alias:'widget.performance-tabs-settings-categories',

    /**
     * Description of the fieldSet
     */
    caption: '{s name=tabs/settings/categories/title}Categories{/s}',

    /**
     * Component event method which is fired when the component
     * is initials. The component is initials when the user
     * want to create a new customer or edit an existing customer
     * @return void
     */
    initComponent:function () {
        var me = this;

        me.items = me.getItems();
        me.callParent(arguments);

    },

    getItems: function() {
        var me = this;

        return [
            {
                xtype: 'fieldset',
                defaults: me.defaults,
                title: '{s name=fieldset/information}Information{/s}',
                items: [
                    me.createDescriptionContainer("{s name=fieldset/categories/info}Hier können Sie Einstellungen vornehmen, die die Performance der Produkt-Listings betreffen.{/s}")]
            },
            {
                xtype: 'fieldset',
                title: '{s name=fieldset/configuration}Configuration{/s}',
                items: [
                    {
                        xtype: 'performance-multi-request-button',
                        event: 'category',
                        title: '{s name=fieldset/categories/repair}Rebuild cagtegory tree{/s}'
                    },
                    {
                        fieldLabel: '{s name=fieldset/categories/text/moveBatchModeEnabled}Move categories in batch-mode{/s}',
                        helpText: '',
                        name: 'categories[moveBatchModeEnabled]',
                        xtype: 'checkbox',
                        uncheckedValue: false,
                        inputValue: true,
                        labelWidth: 300
                    }
                ]
            }, {
                xtype: 'fieldset',
                defaults: me.defaults,
                title: '{s name=fieldset/listings}Listings{/s}',
                items: [{
                    fieldLabel: '{s name=fieldset/categories/text/sort}Default listing sorting{/s}',
                    helpText: '',
                    name: 'categories[defaultListingSorting]',
                    xtype: 'combo',
                    valueField: 'id',
                    value: 1,
                    editable: false,
                    displayField: 'name',
                    store: Ext.create('Shopware.apps.Performance.store.ListingSorting').load()
                }, {
                    name: 'categories[articlesperpage]',
                    fieldLabel: '{s name=fieldset/categories/text/perPage}Articles per page{/s}',
                    helpText: '{s name=fieldset/categories/help/perPage}How many articles should be shown per page?{/s}',

                    xtype: 'numberfield',
                    minValue: 1
                }]
            }
        ];
    }

});
//{/block}
<|endoftext|>


<commit_before>$(function() {
  var parent = $('#reprocess');

  $('form', parent).on('submit', function(event) {
    event.preventDefault();
    var crash_id = parent.data('crash-id');

    // make sure previous result flash messages are hidden
    $('.reprocessing-success', parent).hide();
    $('.reprocessing-error', parent).hide();

    // disable the submit button
    $('form button', parent).prop('disabled', true);

    // show a waiting message
    $('.waiting', parent).show();

    $.post('/api/Reprocessing/', { crash_ids: crash_id })
      .done(function() {
        $('.reprocessing-success', parent).show();
      })
      .error(function(jqXHR) {
        $('.reprocessing-error .status', parent).text(jqXHR.status);
        $('.reprocessing-error pre', parent).text(jqXHR.responseText);
        $('.reprocessing-error', parent).show();
      })
      .complete(function() {
        $('.waiting', parent).hide();
        $('form button', parent).prop('disabled', false);
      });
  });
});
<commit_msg>fix bug 1467412: updated crash reprocessing jQuery notation<commit_after>$(function() {
  var parent = $('#reprocess');

  $('form', parent).on('submit', function(event) {
    event.preventDefault();
    var crash_id = parent.data('crash-id');

    // make sure previous result flash messages are hidden
    $('.reprocessing-success', parent).hide();
    $('.reprocessing-error', parent).hide();

    // disable the submit button
    $('form button', parent).prop('disabled', true);

    // show a waiting message
    $('.waiting', parent).show();

    $.post('/api/Reprocessing/', { crash_ids: crash_id })
      .done(function() {
        $('.reprocessing-success', parent).show();
      })
      .fail(function(jqXHR) {
        $('.reprocessing-error .status', parent).text(jqXHR.status);
        $('.reprocessing-error pre', parent).text(jqXHR.responseText);
        $('.reprocessing-error', parent).show();
      })
      .always(function() {
        $('.waiting', parent).hide();
        $('form button', parent).prop('disabled', false);
      });
  });
});
<|endoftext|>


<commit_before><commit_msg>Delete maps_lib.js<commit_after><|endoftext|>


<commit_before>'use strict';

let angular = require('angular');

// TODO: Clean this up on the backend - this is a mess
module.exports = angular.module('spinnaker.core.pipeline.stage.canary.transformer', [
  require('../../../../utils/lodash.js'),
])
  .service('canaryStageTransformer', function($log, _) {

    // adds "canary" or "baseline" to the deploy stage name when converting it to a task
    function getDeployTaskName(stage) {
      if (stage.context.freeFormDetails) {
        var nameParts = stage.name.split(' ');
        if (_.endsWith(stage.context.freeFormDetails, 'canary')) {
          nameParts.splice(1, 0, 'canary');
        } else {
          nameParts.splice(1, 0, 'baseline');
        }
        return nameParts.join(' ');
      }
      return stage.name;
    }

    function getException (stage) {
      if (stage.context) {
        if (stage.context.exception && stage.context.exception.details.errors.length) {
          return stage.context.exception.details.errors.join(', ');
        }
        if (stage.context['kato.tasks'] && stage.context['kato.tasks'].length) {
          var lastTask = stage.context['kato.tasks'][stage.context['kato.tasks'].length-1];
          return lastTask.exception ? lastTask.exception.message : null;
        }
      }
      return null;
    }

    function buildCanaryDeploymentsFromClusterPairs(stage) {
      return _.map(stage.context.clusterPairs, function (pair) {
        var name = function (cluster) {
          var parts = [cluster.application];
          if (cluster.stack) {
            parts.push(cluster.stack);
          } else if (cluster.freeFormDetails) {
            parts.push('');
          }
          if (cluster.freeFormDetails) {
            parts.push(cluster.freeFormDetails);
          }
          return parts.join('-');
        };
        var region = function (cluster) {
          return _.first(_.keys(cluster.availabilityZones));
        };
        return {
          canaryCluster: {
            accountName: pair.canary.account,
            imageId: null,
            buildId: null,
            name: name(pair.canary),
            region: region(pair.canary),
            type: 'aws',
          },
          baselineCluster: {
            accountName: pair.baseline.account,
            imageId: pair.baseline.amiName,
            buildId: pair.baseline.buildUrl,
            name: name(pair.baseline),
            region: region(pair.baseline),
            type: 'aws',
          }
        };
      });
    }

    function extractBuild(cluster) {
      cluster.build = cluster.build || {};
      if (cluster.buildId) {
        var parts = cluster.buildId.split('/');
        parts.pop();
        cluster.build.url = cluster.buildId;
        cluster.build.number = parts.pop();
      } else {
        cluster.build.url = '#';
        cluster.build.number = 'n/a';
      }
    }

    function createSyntheticCanaryDeploymentStage(stage, deployment, status, deployParent, deploymentEndTime, canaryDeploymentId, execution) {
      return {
        parentStageId: stage.id,
        syntheticStageOwner: 'STAGE_AFTER',
        id: stage.id + '-' + deployment.id,
        type: 'canaryDeployment',
        name: deployment.canaryCluster.region,
        status: status,
        startTime: deployParent.startTime,
        endTime: deploymentEndTime,
        context: {
          commits: deployment.commits,
          canaryDeploymentId: canaryDeploymentId,
          application: stage.context.canary.application || execution.application,
          canaryCluster: deployment.canaryCluster,
          baselineCluster: deployment.baselineCluster,
          canaryResult: deployment.canaryResult,
          status: {
            reportUrl: deployment.canaryResult.canaryReportURL,
            score: deployment.canaryResult.score,
            result: deployment.canaryResult.result,
            duration: deployment.canaryResult.timeDuration,
            health: deployment.health ? deployment.health.health : '',
          }
        }
      };
    }

    this.transform = function(application, execution) {
      var syntheticStagesToAdd = [];
      execution.stages.forEach(function(stage) {
        if (stage.type === 'canary') {

          stage.exceptions = [];

          var deployParent = _.find(execution.stages, {
            type: 'deployCanary',
            context: {
              canaryStageId: stage.id,
            }
          });
          if (!deployParent) {
            $log.warn('No deployment parent found for canary stage in execution:', execution.id);
            return;
          }
          var monitorStage = _.find(execution.stages, {
            type: 'monitorCanary',
            context: {
              canaryStageId: stage.id,
            }
          });

          var deployStages = _.filter(execution.stages, {
            type: 'deploy',
            parentStageId: deployParent.id,
          });

          if (getException(monitorStage)) {
            stage.exceptions.push('Monitor Canary failure: ' + getException(monitorStage));
          }
          deployStages.forEach((deployStage) => {
            if (getException(deployStage)) {
              stage.exceptions.push(deployStage.name + ': ' + getException(deployStage));
            }
          });

          stage.context.canary = monitorStage.context.canary || deployParent.context.canary || stage.context.canary;
          if (!stage.context.canary.canaryDeployments) {
            stage.context.canary.canaryDeployments = buildCanaryDeploymentsFromClusterPairs(stage);
          }
          var status = monitorStage.status === 'CANCELED' || _.some(deployStages, { status: 'CANCELED' }) ? 'CANCELED' : 'UNKNOWN';
          if (_.some(deployStages, { status: 'RUNNING' })) {
            status = 'RUNNING';
          }
          if (_.some(deployStages, { status: 'TERMINAL' })) {
            status = 'TERMINAL';
          }
          var canaryStatus = stage.context.canary.status;
          if (canaryStatus && status !== 'CANCELED') {
            if (canaryStatus.status === 'LAUNCHED' || monitorStage.status === 'RUNNING') {
              status = 'RUNNING';
            }
            if (canaryStatus.complete) {
              status = 'COMPLETED';
            }
            if (canaryStatus.status === 'DISABLED') {
              status = 'DISABLED';
            }
            if (canaryStatus.status === 'FAILED') {
              status = 'FAILED';
            }
            if (canaryStatus.status === 'TERMINATED') {
              status = 'TERMINATED';
            }
            canaryStatus.status = status;
          } else {
            stage.context.canary.status = { status: status };
          }
          stage.status = status;

          var tasks = _.map(deployStages, function(deployStage) {
            var region = _.first(_.keys(deployStage.context.availabilityZones));
            return {
              id: deployStage.id,
              region: region,
              name: getDeployTaskName(deployStage),
              startTime: deployStage.startTime,
              endTime: deployStage.endTime,
              status: deployStage.status,
              commits: deployStage.context.commits
            };
          });

          tasks.push({
            id: monitorStage.id,
            name: monitorStage.name,
            startTime: monitorStage.startTime,
            endTime: monitorStage.endTime,
            status: monitorStage.status,
          });

          stage.tasks = tasks;

          stage.context.canary.canaryDeployments.forEach(function(deployment, deploymentIdx) {

            deployment.id = deployment.id || deploymentIdx;

            var deployedClusterPair = _.find(monitorStage.context.deployedClusterPairs, {
              baselineCluster: {
                accountName: deployment.baselineCluster.accountName,
                name: deployment.baselineCluster.name,
                region: deployment.baselineCluster.region,
              },
              canaryCluster: {
                accountName: deployment.canaryCluster.accountName,
                name: deployment.canaryCluster.name,
                region: deployment.canaryCluster.region,
              }
            });

            var deploymentEndTime = null;
            var monitorTask = _.find(monitorStage.tasks, { name: 'monitorCanary' });
            if (monitorTask) {
              deploymentEndTime = monitorTask.endTime;
            }

            extractBuild(deployment.baselineCluster);
            extractBuild(deployment.canaryCluster);

            deployment.canaryResult = deployment.canaryAnalysisResult || {};
            deployment.canaryCluster = deployment.canaryCluster || {};

            var foundTask = _.find(stage.tasks, function(task) {
              return task.region === deployment.baselineCluster.region && task.commits !== undefined && task.commits.length > 0;
            });
            if(foundTask !== undefined && foundTask.commits !== undefined) {
              deployment.commits = foundTask.commits;
            }

            if (deployedClusterPair) {
              var canaryServerGroup = _.find(application.serverGroups, {
                name: deployedClusterPair.canaryCluster.serverGroup,
                account: deployedClusterPair.canaryCluster.accountName,
                region: deployedClusterPair.canaryCluster.region
              });
              if (canaryServerGroup) {
                deployment.canaryCluster.capacity = canaryServerGroup.instances.length;
              } else {
                deployment.canaryCluster.capacity = 'n/a';
              }

              var baselineServerGroup = _.find(application.serverGroups, {
                name: deployedClusterPair.baselineCluster.serverGroup,
                account: deployedClusterPair.baselineCluster.accountName,
                region: deployedClusterPair.baselineCluster.region
              });
              if (baselineServerGroup) {
                deployment.baselineCluster.capacity = baselineServerGroup.instances.length;
              } else {
                deployment.baselineCluster.capacity = 'n/a';
              }
            } else {
              deployment.baselineCluster.capacity = 'n/a';
              deployment.canaryCluster.capacity = 'n/a';
            }

            var canaryDeploymentId = deployment.canaryAnalysisResult ? deployment.canaryAnalysisResult.canaryDeploymentId : null;
            syntheticStagesToAdd.push(createSyntheticCanaryDeploymentStage(stage, deployment, status, deployParent, deploymentEndTime, canaryDeploymentId, execution));
          });
          execution.stages = execution.stages.filter((stage) => deployStages.indexOf(stage) === -1);
        }
      });
      execution.stages = execution.stages.concat(syntheticStagesToAdd);
    };
  }).name;
<commit_msg>remove duplicate canary exceptions<commit_after>'use strict';

let angular = require('angular');

// TODO: Clean this up on the backend - this is a mess
module.exports = angular.module('spinnaker.core.pipeline.stage.canary.transformer', [
  require('../../../../utils/lodash.js'),
])
  .service('canaryStageTransformer', function($log, _) {

    // adds "canary" or "baseline" to the deploy stage name when converting it to a task
    function getDeployTaskName(stage) {
      if (stage.context.freeFormDetails) {
        var nameParts = stage.name.split(' ');
        if (_.endsWith(stage.context.freeFormDetails, 'canary')) {
          nameParts.splice(1, 0, 'canary');
        } else {
          nameParts.splice(1, 0, 'baseline');
        }
        return nameParts.join(' ');
      }
      return stage.name;
    }

    function getException (stage) {
      if (stage.context) {
        if (stage.context.exception && stage.context.exception.details.errors.length) {
          return stage.context.exception.details.errors.join(', ');
        }
        if (stage.context['kato.tasks'] && stage.context['kato.tasks'].length) {
          var lastTask = stage.context['kato.tasks'][stage.context['kato.tasks'].length-1];
          return lastTask.exception ? lastTask.exception.message : null;
        }
      }
      return null;
    }

    function buildCanaryDeploymentsFromClusterPairs(stage) {
      return _.map(stage.context.clusterPairs, function (pair) {
        var name = function (cluster) {
          var parts = [cluster.application];
          if (cluster.stack) {
            parts.push(cluster.stack);
          } else if (cluster.freeFormDetails) {
            parts.push('');
          }
          if (cluster.freeFormDetails) {
            parts.push(cluster.freeFormDetails);
          }
          return parts.join('-');
        };
        var region = function (cluster) {
          return _.first(_.keys(cluster.availabilityZones));
        };
        return {
          canaryCluster: {
            accountName: pair.canary.account,
            imageId: null,
            buildId: null,
            name: name(pair.canary),
            region: region(pair.canary),
            type: 'aws',
          },
          baselineCluster: {
            accountName: pair.baseline.account,
            imageId: pair.baseline.amiName,
            buildId: pair.baseline.buildUrl,
            name: name(pair.baseline),
            region: region(pair.baseline),
            type: 'aws',
          }
        };
      });
    }

    function extractBuild(cluster) {
      cluster.build = cluster.build || {};
      if (cluster.buildId) {
        var parts = cluster.buildId.split('/');
        parts.pop();
        cluster.build.url = cluster.buildId;
        cluster.build.number = parts.pop();
      } else {
        cluster.build.url = '#';
        cluster.build.number = 'n/a';
      }
    }

    function createSyntheticCanaryDeploymentStage(stage, deployment, status, deployParent, deploymentEndTime, canaryDeploymentId, execution) {
      return {
        parentStageId: stage.id,
        syntheticStageOwner: 'STAGE_AFTER',
        id: stage.id + '-' + deployment.id,
        type: 'canaryDeployment',
        name: deployment.canaryCluster.region,
        status: status,
        startTime: deployParent.startTime,
        endTime: deploymentEndTime,
        context: {
          commits: deployment.commits,
          canaryDeploymentId: canaryDeploymentId,
          application: stage.context.canary.application || execution.application,
          canaryCluster: deployment.canaryCluster,
          baselineCluster: deployment.baselineCluster,
          canaryResult: deployment.canaryResult,
          status: {
            reportUrl: deployment.canaryResult.canaryReportURL,
            score: deployment.canaryResult.score,
            result: deployment.canaryResult.result,
            duration: deployment.canaryResult.timeDuration,
            health: deployment.health ? deployment.health.health : '',
          }
        }
      };
    }

    this.transform = function(application, execution) {
      var syntheticStagesToAdd = [];
      execution.stages.forEach(function(stage) {
        if (stage.type === 'canary') {

          stage.exceptions = [];

          var deployParent = _.find(execution.stages, {
            type: 'deployCanary',
            context: {
              canaryStageId: stage.id,
            }
          });
          if (!deployParent) {
            $log.warn('No deployment parent found for canary stage in execution:', execution.id);
            return;
          }
          var monitorStage = _.find(execution.stages, {
            type: 'monitorCanary',
            context: {
              canaryStageId: stage.id,
            }
          });

          var deployStages = _.filter(execution.stages, {
            type: 'deploy',
            parentStageId: deployParent.id,
          });

          if (getException(monitorStage)) {
            stage.exceptions.push('Monitor Canary failure: ' + getException(monitorStage));
          }
          deployStages.forEach((deployStage) => {
            if (getException(deployStage)) {
              stage.exceptions.push(deployStage.name + ': ' + getException(deployStage));
            }
          });

          stage.exceptions = _.uniq(stage.exceptions);

          stage.context.canary = monitorStage.context.canary || deployParent.context.canary || stage.context.canary;
          if (!stage.context.canary.canaryDeployments) {
            stage.context.canary.canaryDeployments = buildCanaryDeploymentsFromClusterPairs(stage);
          }
          var status = monitorStage.status === 'CANCELED' || _.some(deployStages, { status: 'CANCELED' }) ? 'CANCELED' : 'UNKNOWN';
          if (_.some(deployStages, { status: 'RUNNING' })) {
            status = 'RUNNING';
          }
          if (_.some(deployStages, { status: 'TERMINAL' })) {
            status = 'TERMINAL';
          }
          var canaryStatus = stage.context.canary.status;
          if (canaryStatus && status !== 'CANCELED') {
            if (canaryStatus.status === 'LAUNCHED' || monitorStage.status === 'RUNNING') {
              status = 'RUNNING';
            }
            if (canaryStatus.complete) {
              status = 'COMPLETED';
            }
            if (canaryStatus.status === 'DISABLED') {
              status = 'DISABLED';
            }
            if (canaryStatus.status === 'FAILED') {
              status = 'FAILED';
            }
            if (canaryStatus.status === 'TERMINATED') {
              status = 'TERMINATED';
            }
            canaryStatus.status = status;
          } else {
            stage.context.canary.status = { status: status };
          }
          stage.status = status;

          var tasks = _.map(deployStages, function(deployStage) {
            var region = _.first(_.keys(deployStage.context.availabilityZones));
            return {
              id: deployStage.id,
              region: region,
              name: getDeployTaskName(deployStage),
              startTime: deployStage.startTime,
              endTime: deployStage.endTime,
              status: deployStage.status,
              commits: deployStage.context.commits
            };
          });

          tasks.push({
            id: monitorStage.id,
            name: monitorStage.name,
            startTime: monitorStage.startTime,
            endTime: monitorStage.endTime,
            status: monitorStage.status,
          });

          stage.tasks = tasks;

          stage.context.canary.canaryDeployments.forEach(function(deployment, deploymentIdx) {

            deployment.id = deployment.id || deploymentIdx;

            var deployedClusterPair = _.find(monitorStage.context.deployedClusterPairs, {
              baselineCluster: {
                accountName: deployment.baselineCluster.accountName,
                name: deployment.baselineCluster.name,
                region: deployment.baselineCluster.region,
              },
              canaryCluster: {
                accountName: deployment.canaryCluster.accountName,
                name: deployment.canaryCluster.name,
                region: deployment.canaryCluster.region,
              }
            });

            var deploymentEndTime = null;
            var monitorTask = _.find(monitorStage.tasks, { name: 'monitorCanary' });
            if (monitorTask) {
              deploymentEndTime = monitorTask.endTime;
            }

            extractBuild(deployment.baselineCluster);
            extractBuild(deployment.canaryCluster);

            deployment.canaryResult = deployment.canaryAnalysisResult || {};
            deployment.canaryCluster = deployment.canaryCluster || {};

            var foundTask = _.find(stage.tasks, function(task) {
              return task.region === deployment.baselineCluster.region && task.commits !== undefined && task.commits.length > 0;
            });
            if(foundTask !== undefined && foundTask.commits !== undefined) {
              deployment.commits = foundTask.commits;
            }

            if (deployedClusterPair) {
              var canaryServerGroup = _.find(application.serverGroups, {
                name: deployedClusterPair.canaryCluster.serverGroup,
                account: deployedClusterPair.canaryCluster.accountName,
                region: deployedClusterPair.canaryCluster.region
              });
              if (canaryServerGroup) {
                deployment.canaryCluster.capacity = canaryServerGroup.instances.length;
              } else {
                deployment.canaryCluster.capacity = 'n/a';
              }

              var baselineServerGroup = _.find(application.serverGroups, {
                name: deployedClusterPair.baselineCluster.serverGroup,
                account: deployedClusterPair.baselineCluster.accountName,
                region: deployedClusterPair.baselineCluster.region
              });
              if (baselineServerGroup) {
                deployment.baselineCluster.capacity = baselineServerGroup.instances.length;
              } else {
                deployment.baselineCluster.capacity = 'n/a';
              }
            } else {
              deployment.baselineCluster.capacity = 'n/a';
              deployment.canaryCluster.capacity = 'n/a';
            }

            var canaryDeploymentId = deployment.canaryAnalysisResult ? deployment.canaryAnalysisResult.canaryDeploymentId : null;
            syntheticStagesToAdd.push(createSyntheticCanaryDeploymentStage(stage, deployment, status, deployParent, deploymentEndTime, canaryDeploymentId, execution));
          });
          execution.stages = execution.stages.filter((stage) => deployStages.indexOf(stage) === -1);
        }
      });
      execution.stages = execution.stages.concat(syntheticStagesToAdd);
    };
  }).name;
<|endoftext|>


<commit_before>/* jshint node: true */

//************************************************************
//  live_lecture.controller.js                              //
//  Active Learning 2110                                    //
//                                                          //
//  Created by Jeremy Carter on 04/02/17.                   //
//  Copyright © 2016 Jeremy Carter. All rights reserved.    //
//                                                          //
//  Date        Name        Description                     //
//  -------     ---------   --------------                  //
//  02Apr17     J. Carter  Initial Design                   //
//                                                          //
//************************************************************

var app = angular.module('app');

app.controller('Instructor.Live.Lecture.Controller', function($scope, $localStorage, $state, $stateParams, $rootScope, RESTService, SocketService, ngNotify) {

    $scope.selectedQuestion = "";
    $scope.time = 60;
    $scope.timeMax = 60;
    $scope.timerEnabled = false;
    $scope.end_time = 0;
    $rootScope.$stateParams = $stateParams;
    $scope.course = $localStorage.courses[$stateParams.selectedCourse];
    updateLectureInfo();

    $scope.$on("$destroy", function() {
        console.log('killing live lecture');
        SocketService.StopLecture($scope.lecture.lecture_id);
    });

    $rootScope.$on('updated_user_total', function(evt, total) {
        console.log('new total: ' + total);
        $scope.$apply(function() {
            $scope.options.scales.yAxes[0].ticks.max = total + 5;
        });
    });

    $rootScope.$on('new_answer', function(evnt, answer) {
        var choices = $scope.choices.map(function(choice) {
            return choice.text;
        });
        var indx = choices.indexOf(answer);
        $scope.data[0][indx]++;
    });

    RESTService.GetLectureInfo({
        lecture_id: $scope.lecture.lecture_id,
        course_id: $scope.course._id
    }, function(info) {
        if (!info.success) {
            ngNotify.set('Could not fetch lecture info', 'error');
            return;
        }
        $scope.lecture = $scope.course.lectures[$stateParams.selectedLecture];
    });

    function updateLectureInfo() {
        $scope.lecture = $scope.course.lectures[$stateParams.selectedLecture];
        $scope.questions = $scope.lecture.questions;
    }

    $scope.labels = [];
    $scope.data = [];

    $scope.datasetOverride = [
        {
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 2
        }
      ];
    $scope.options = {
        scales: {
            xAxes: [{
                gridLines: {
                    display: false,
                },
                barPercentage: 0.4,
                ticks: {
                    fontSize: 16,
                    fontStyle: "bold"
                }
            }],
            yAxes: [{
                    id: 'y-axis-1',
                    type: 'linear',
                    display: true,
                    position: 'left',
                    ticks: {
                        max: 10,
                        fontSize: 16,
                        fontStyle: "bold",
                        suggestedMin: 0,
                        scaleSteps : 1,
                        beginAtZero: true // minimum value will be 0.
                    }
            }
          ]
        }
    };

    $scope.add10Seconds = function() {
        if ($scope.time + 10 > $scope.timeMax) {
            $scope.timeMax = $scope.time + 10;
        }
        $scope.end_time.setSeconds($scope.end_time.getSeconds() + 10);
        SocketService.ChangeTime({
            lecture_id: $scope.lecture.lecture_id,
            time: $scope.end_time,
            timeMax: $scope.timeMax
        });
    };
    $scope.remove10Seconds = function() {
        if ($scope.time < 0) {
            $scope.time = 0;
        }
        $scope.end_time.setSeconds($scope.end_time.getSeconds() - 10);
        SocketService.ChangeTime({
            lecture_id: $scope.lecture.lecture_id,
            time: $scope.end_time
        });
    };
    $scope.startQuestion = function() {
        RESTService.GetQuestionDetails($scope.selectedQuestion, function(info) {
            if (!info.success) {
                ngNotify.set("Failed to fetch question details", 'error');
                return;
            }
            $scope.labels = [];
            $scope.data = [];
            var newData = [];
            $scope.choices = info.choices;
            for (var i in info.choices) {
                var correct = info.choices[i].answer ? " ✓" : " ✘";
                $scope.labels.push((parseInt(i) + 1).toString() + correct);
                newData.push(0);
            }
            $scope.data.push(newData);
            $scope.timerEnabled = true;
            $scope.$broadcast('timer-set-countdown-seconds', $scope.time);
            var t = new Date();
            t.setSeconds(t.getSeconds() + $scope.time);
            $scope.end_time = t;
            SocketService.StartQuestion({
                lecture_id: $scope.lecture.lecture_id,
                question_id: $scope.selectedQuestion,
                max_time: $scope.timeMax,
                end_time: t
            });
            $scope.$broadcast('timer-start');
        });
    };

    $scope.$on('timer-tick', function(event, data) {
        var myTime = new Date();
        $scope.time = Math.round(($scope.end_time.getTime() - myTime.getTime()) / 1000);
        if ($scope.time <= 0) {
            $scope.$broadcast('timer-stop');
            $scope.selectedQuestion = "";
            $scope.time = 60;
            $scope.timeMax = 60;
            $scope.timerEnabled = false;
            $scope.end_time = 0;
            SocketService.EndQuestion();
        } else {
            $scope.timerEnabled = true;
        }
    });
});
<commit_msg>slight update.<commit_after>/* jshint node: true */

//************************************************************
//  live_lecture.controller.js                              //
//  Active Learning 2110                                    //
//                                                          //
//  Created by Jeremy Carter on 04/02/17.                   //
//  Copyright © 2016 Jeremy Carter. All rights reserved.    //
//                                                          //
//  Date        Name        Description                     //
//  -------     ---------   --------------                  //
//  02Apr17     J. Carter  Initial Design                   //
//                                                          //
//************************************************************

var app = angular.module('app');

app.controller('Instructor.Live.Lecture.Controller', function($scope, $localStorage, $state, $stateParams, $rootScope, RESTService, SocketService, ngNotify) {

    $scope.selectedQuestion = "";
    $scope.time = 60;
    $scope.timeMax = 60;
    $scope.timerEnabled = false;
    $scope.end_time = 0;
    $rootScope.$stateParams = $stateParams;
    $scope.course = $localStorage.courses[$stateParams.selectedCourse];
    updateLectureInfo();

    $scope.$on("$destroy", function() {
        console.log('killing live lecture');
        SocketService.StopLecture($scope.lecture.lecture_id);
    });

    $rootScope.$on('updated_user_total', function(evt, total) {
        console.log('new total: ' + total);
        var cur = $scope.options.scales.yAxes[0].ticks.max;
        if (total > cur - 5) {
            $scope.$apply(function() {
                $scope.options.scales.yAxes[0].ticks.max = total + 5;
            });
        }
    });

    $rootScope.$on('new_answer', function(evnt, answer) {
        var choices = $scope.choices.map(function(choice) {
            return choice.text;
        });
        var indx = choices.indexOf(answer);
        $scope.data[0][indx]++;
    });

    RESTService.GetLectureInfo({
        lecture_id: $scope.lecture.lecture_id,
        course_id: $scope.course._id
    }, function(info) {
        if (!info.success) {
            ngNotify.set('Could not fetch lecture info', 'error');
            return;
        }
        $scope.lecture = $scope.course.lectures[$stateParams.selectedLecture];
    });

    function updateLectureInfo() {
        $scope.lecture = $scope.course.lectures[$stateParams.selectedLecture];
        $scope.questions = $scope.lecture.questions;
    }

    $scope.labels = [];
    $scope.data = [];

    $scope.datasetOverride = [
        {
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 2
        }
      ];
    $scope.options = {
        scales: {
            xAxes: [{
                gridLines: {
                    display: false,
                },
                barPercentage: 0.4,
                ticks: {
                    fontSize: 16,
                    fontStyle: "bold"
                }
            }],
            yAxes: [{
                    id: 'y-axis-1',
                    type: 'linear',
                    display: true,
                    position: 'left',
                    ticks: {
                        max: 10,
                        fontSize: 16,
                        fontStyle: "bold",
                        suggestedMin: 0,
                        scaleSteps : 1,
                        beginAtZero: true // minimum value will be 0.
                    }
            }
          ]
        }
    };

    $scope.add10Seconds = function() {
        if ($scope.time + 10 > $scope.timeMax) {
            $scope.timeMax = $scope.time + 10;
        }
        $scope.end_time.setSeconds($scope.end_time.getSeconds() + 10);
        SocketService.ChangeTime({
            lecture_id: $scope.lecture.lecture_id,
            time: $scope.end_time,
            timeMax: $scope.timeMax
        });
    };
    $scope.remove10Seconds = function() {
        if ($scope.time < 0) {
            $scope.time = 0;
        }
        $scope.end_time.setSeconds($scope.end_time.getSeconds() - 10);
        SocketService.ChangeTime({
            lecture_id: $scope.lecture.lecture_id,
            time: $scope.end_time
        });
    };
    $scope.startQuestion = function() {
        RESTService.GetQuestionDetails($scope.selectedQuestion, function(info) {
            if (!info.success) {
                ngNotify.set("Failed to fetch question details", 'error');
                return;
            }
            $scope.labels = [];
            $scope.data = [];
            var newData = [];
            $scope.choices = info.choices;
            for (var i in info.choices) {
                var correct = info.choices[i].answer ? " ✓" : " ✘";
                $scope.labels.push((parseInt(i) + 1).toString() + correct);
                newData.push(0);
            }
            $scope.data.push(newData);
            $scope.timerEnabled = true;
            $scope.$broadcast('timer-set-countdown-seconds', $scope.time);
            var t = new Date();
            t.setSeconds(t.getSeconds() + $scope.time);
            $scope.end_time = t;
            SocketService.StartQuestion({
                lecture_id: $scope.lecture.lecture_id,
                question_id: $scope.selectedQuestion,
                max_time: $scope.timeMax,
                end_time: t
            });
            $scope.$broadcast('timer-start');
        });
    };

    $scope.$on('timer-tick', function(event, data) {
        var myTime = new Date();
        $scope.time = Math.round(($scope.end_time.getTime() - myTime.getTime()) / 1000);
        if ($scope.time <= 0) {
            $scope.$broadcast('timer-stop');
            $scope.selectedQuestion = "";
            $scope.time = 60;
            $scope.timeMax = 60;
            $scope.timerEnabled = false;
            $scope.end_time = 0;
            SocketService.EndQuestion();
        } else {
            $scope.timerEnabled = true;
        }
    });
});
<|endoftext|>