<commit_before>// Copyright The Workers Ltd. 2012 (theworkers.net)
// @author Ross Cairns
// @notes  Not suitable for heavy usage (i.e. particles) as produces
//         many object with in turn will cause big
//         garbage collections delays
(function () {

    var root = this;
    var W = root.W || {};
    if (typeof module !== 'undefined' && module.exports) {
        module.exports = W;
        root.W = W;
    } else {
        root.W = W;
    }

    W.DisplayViewMixin = {
        version : 1,
        setPosition : function (x, y) { // or setXY(array) or setXY({x:y:})
            if (typeof x === "[object Array]") {
                this.x(x[0]);
                this.y(y[1]);
            } else if (typeof x === "number") {
                this.x(x);
                this.y(y);
            } else {
                this.x(x.x);
                this.y(x.y);
            }
            return this;
        },
        setSize : function (width, height) { // or setSize(Array) or setSize({width:height}) or setSize(DOMElement)
            if (!!width.tagName) {
                this.width($(width).width());
                this.height($(width).height());
            } else if (typeof width === "number") {
                this.width(width);
                this.height(height);
            } else if (typeof width === "array") {
                this.width(width[0]);
                this.height(width[1]);
            } else if (typeof(width) == 'function') {
                this.width(width());
                this.height(height());
            } else {
                var obj = width;
                this.width(typeof(obj.width) == 'function' ? obj.width() : obj.width);
                this.height(typeof(obj.height) == 'function' ? obj.height() : obj.height);
            }
            return this;
        },
        x : function (x) {
            if (arguments.length > 0) { this._x = x; }
            if (typeof this._x === "undefined") { this._x = 0; }
            return this._x;
        },
        y : function (y) {
            if (arguments.length > 0) { this._y = y; }
            if (typeof this._y === "undefined") { this._y = 0; }
            return this._y;
        },
        width : function (width)  {
            if (arguments.length > 0) { this._width = width; }
            if (typeof this._width === "undefined") { this._width = 0; }
            return this._width;
        },
        height : function (height) {
            if (arguments.length > 0) { this._height = height; }
            if (typeof this._height === "undefined") { this._height = 0; }
            return this._height;
        }
    };

}());

<commit_msg>fixed issue with no $<commit_after>// Copyright The Workers Ltd. 2012 (theworkers.net)
// @author Ross Cairns
// @notes  Not suitable for heavy usage (i.e. particles) as produces
//         many object with in turn will cause big
//         garbage collections delays
(function () {

    var root = this;
    var W = root.W || {};
    if (typeof module !== 'undefined' && module.exports) {
        module.exports = W;
        root.W = W;
    } else {
        root.W = W;
    }

    W.DisplayViewMixin = {
        version : 1,
        setPosition : function (x, y) { // or setXY(array) or setXY({x:y:})
            if (typeof x === "[object Array]") {
                this.x(x[0]);
                this.y(y[1]);
            } else if (typeof x === "number") {
                this.x(x);
                this.y(y);
            } else {
                this.x(x.x);
                this.y(x.y);
            }
            return this;
        },
        setSize : function (width, height) { // or setSize(Array) or setSize({width:height}) or setSize(DOMElement)
            if (!!width.tagName && typeof jQuery === 'function') {
                this.width(jQuery(width).width());
                this.height(jQuery(width).height());
            } else if (!!width.tagName) {
                this.width = width.width;
                this.height = width.height;
            } else if (typeof width === "number") {
                this.width(width);
                this.height(height);
            } else if (typeof width === "array") {
                this.width(width[0]);
                this.height(width[1]);
            } else if (typeof(width) == 'function') {
                this.width(width());
                this.height(height());
            } else {
                var obj = width;
                this.width(typeof(obj.width) == 'function' ? obj.width() : obj.width);
                this.height(typeof(obj.height) == 'function' ? obj.height() : obj.height);
            }
            return this;
        },
        x : function (x) {
            if (arguments.length > 0) { this._x = x; }
            if (typeof this._x === "undefined") { this._x = 0; }
            return this._x;
        },
        y : function (y) {
            if (arguments.length > 0) { this._y = y; }
            if (typeof this._y === "undefined") { this._y = 0; }
            return this._y;
        },
        width : function (width)  {
            if (arguments.length > 0) { this._width = width; }
            if (typeof this._width === "undefined") { this._width = 0; }
            return this._width;
        },
        height : function (height) {
            if (arguments.length > 0) { this._height = height; }
            if (typeof this._height === "undefined") { this._height = 0; }
            return this._height;
        }
    };

}());

<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc service
 * @name oncokbApp.mainUtils
 * @description
 * # mainUtils
 * Service in the oncokbApp.
 */
angular.module('oncokbApp')
    .factory('mainUtils', function(OncoKB, _, storage, $q, DatabaseConnector, $rootScope) {
        var isoforms = {};
        var oncogeneTSG = {};

        /**
         * Create new Gene document
         * @param {string} hugoSymbol Gene Hugo Symbol
         * @param {string} parentFolderId The folder where to put new document
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
         */
        function createGene(hugoSymbol, parentFolderId) {
            var deferred = $q.defer();
            if (_.isString(hugoSymbol)) {
                storage.requireAuth().then(function() {
                    console.log('Creating gene ', hugoSymbol);
                    storage.createDocument(hugoSymbol, parentFolderId)
                        .then(function(result) {
                            if (result && result.error) {
                                console.error('\tError when creating document.');
                                deferred.reject(result);
                            } else {
                                storage.getRealtimeDocument(result.id)
                                    .then(function(file) {
                                        var model = file.getModel();
                                        var gene = model.getRoot().get('gene');
                                        if (!gene) {
                                            gene = model.create('Gene');
                                            gene.name.setText(hugoSymbol);
                                            model.getRoot().set('gene', gene);
                                        }
                                        if (!model.getRoot().get('vus')) {
                                            var vus = model.createList();
                                            model.getRoot().set('vus', vus);
                                        }
                                        if (!model.getRoot().get('queue')) {
                                            var queue = model.createList();
                                            model.getRoot().set('queue', queue);
                                        }
                                        $q.all([getIsoform(hugoSymbol),
                                            getOncogeneTSG(hugoSymbol)])
                                            .then(function(result) {
                                                if (_.isArray(result)) {
                                                    var isoform = result[0];
                                                    var geneType = result[1];
                                                    if (isoform && isoform.error) {
                                                        console.error('\tError when getting isoforms.');
                                                    } else if (isoform && isoform.gene_name) {
                                                        var isoformModel = createIsoform(model, isoform);
                                                        gene.transcripts.push(isoformModel);
                                                    } else {
                                                        console.error('\tNo isoform found!!');
                                                    }

                                                    if (geneType && geneType.error) {
                                                        console.error('\tError when getting gene type.');
                                                    } else if (geneType && geneType.classification) {
                                                        var type = '';
                                                        var key = '';
                                                        switch (geneType.classification) {
                                                        case 'TSG':
                                                            type = 'Tumor Suppressor';
                                                            key = 'TSG';
                                                            break;
                                                        case 'Oncogene':
                                                            type = 'Oncogene';
                                                            key = 'OCG';
                                                            break;
                                                        default:
                                                            type = '';
                                                            break;
                                                        }
                                                        if (type) {
                                                            gene.type.set(key, type);
                                                        }
                                                    } else {
                                                        console.log('\tNo gene type found.');
                                                    }
                                                }
                                                deferred.resolve();
                                            }, function(error) {
                                                console.error('Failed to load isoform/geneType', error);
                                            });
                                    });
                            }
                        });
                });
            }
            return deferred.promise;
        }

        /**
         * Create Google realtime mutation
         * @param {object} model Google realtime gene model
         * @param {string} mutationName mutation name.
         * Could be multiple, separated by comma.
         * @return {OncoKB.Mutation} OncoKB.Mutation
         */
        function createMutation(model, mutationName) {
            if (_.isString(mutationName)) {
                mutationName = _.filter(mutationName
                    .trim().split(','), function(item) {
                    return _.isString(item);
                }).join(',');
                var mutation = model.create(OncoKB.Mutation);
                mutation.name.setText(mutationName);
                mutation.oncogenic_eStatus.set('obsolete', 'false');
                mutation.shortSummary_eStatus.set('obsolete', 'false');
                return mutation;
            }
            return null;
        }

        /**
         * Create OncoKB Tumor, it is list of Cancer Type
         * @param {object} model Google Realtime document gene model
         * @return {OncoKB.Tumor} OncoKB.Tumor
         */
        function createTumorType(model) {
            var tumorType = model.create(OncoKB.Tumor);
            for (var i = 0; i < 4; i++) {
                var __ti = model.create(OncoKB.TI);
                var __status = i < 2 ? 1 : 0; // 1: Standard, 0: Investigational
                var __type = i % 2 === 0 ? 1 : 0; // 1: sensitivity, 0: resistance
                var __name = (__status ? 'Standard' : 'Investigational') + ' implications for ' + (__type ? 'sensitivity' : 'resistance') + ' to therapy';

                __ti.types.set('status', __status.toString());
                __ti.types.set('type', __type.toString());
                __ti.name.setText(__name);
                tumorType.TI.push(__ti);
            }
            return tumorType;
        }

        /**
         * Create single OncoTree cancer type
         * @param {object} model Google Realtime document gene model
         * @param {string} cancerType OncoTree main type name
         * @param {string} subtype OncoTree subtype name
         * @param {stirng} oncoTreeCode Subtype code
         * @return {OncoKB.CancerType} OncoKB.CancerType
         */
        function createCancerType(model, cancerType, subtype, oncoTreeCode) {
            if (_.isString(cancerType)) {
                var newCancerType = model.create(OncoKB.CancerType);
                newCancerType.cancerType.setText(cancerType);
                if (_.isString(oncoTreeCode)) {
                    newCancerType.oncoTreeCode.setText(oncoTreeCode);
                }
                if (_.isString(subtype)) {
                    newCancerType.subtype.setText(subtype);
                }
                newCancerType.cancerType_eStatus.set('obsolete', 'false');
                newCancerType.subtype_eStatus.set('obsolete', 'false');
                newCancerType.oncoTreeCode_eStatus.set('obsolete', 'false');
                return newCancerType;
            }
            return null;
        }

        /**
         * Create new treatment object
         * @param {object} model Google realtime document
         * @param {string} treatmentName New treatment name
         * @return {OncoKB.Treatment} OncoKB.Treatment
         */
        function createTreatment(model, treatmentName) {
            if (_.isString(treatmentName) && treatmentName) {
                var treatment = model.create(OncoKB.Treatment);
                treatment.name.setText(treatmentName.trim());
                treatment.type.setText('Therapy');
                return treatment;
            }
            return null;
        }

        /**
         * Create Google Realtime isoform model
         * @param {object} model Google realtime document
         * @param {object} isoform gene isofom info
         * @return {*} return OncoKB.Isoform
         */
        function createIsoform(model, isoform) {
            if (_.isObject(isoform) && model) {
                var Isoform = model.create(OncoKB.ISOForm);
                if (isoform.isoform_override) {
                    Isoform.isoform_override.setText(isoform.isoform_override);
                }
                if (isoform.gene_name) {
                    Isoform.gene_name.setText(isoform.gene_name);
                }
                if (isoform.dmp_refseq_id) {
                    Isoform.dmp_refseq_id.setText(isoform.dmp_refseq_id);
                }
                if (isoform.ccds_id) {
                    Isoform.ccds_id.setText(isoform.ccds_id);
                }
                return Isoform;
            }
            return null;
        }

        /**
         * Output cancer type name, either subtype or cancerType
         * @param {array} cancerTypes List of cancer types
         * @return {string} TumorType name
         */
        function getCancerTypesName(cancerTypes) {
            if (!cancerTypes) {
                return null;
            }
            var list = [];
            cancerTypes.asArray().forEach(function(cancerType) {
                if (cancerType.subtype.length > 0) {
                    var str = cancerType.subtype.getText();
                    list.push(str);
                } else if (cancerType.cancerType.length > 0) {
                    list.push(cancerType.cancerType.getText());
                }
            });
            return list.join(', ');
        }

        /**
         * Check whether searched mainType in cancerTypes
         * @param {array} cancerTypes array of cancer types
         * @param {string} mainType searched main type
         * @return {boolean} whether exist
         */
        function containMainType(cancerTypes, mainType) {
            if (!cancerTypes || !mainType) {
                return null;
            }
            mainType = mainType.toLowerCase().trim();
            cancerTypes.asArray().forEach(function(cancerType) {
                if (cancerType.cancerType && cancerType.cancerType.text.toLowerCase().indexOf(mainType) !== -1) {
                    return true;
                }
            });
            return false;
        }

        /**
         * Output last reviewed cancer type name, either subtype or cancerType
         * @param {array} cancerTypes array of cancer types
         * @return {string} TumorType name
         */
        function getLastReviewedCancerTypesName(cancerTypes) {
            var list = [];
            if (_.isArray(cancerTypes)) {
                cancerTypes.forEach(function(cancerType) {
                    if (cancerType.subtype) {
                        var str = cancerType.subtype;
                        list.push(str);
                    } else if (cancerType.cancerType) {
                        list.push(cancerType.cancerType);
                    }
                });
            }
            return list.join(', ');
        }

        /**
         * Util to find isoform info by giving hugo symbol
         * @param {string} hugoSymbol Gene Hugo Symbol
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
         */
        function getIsoform(hugoSymbol) {
            var deferred = $q.defer();
            if (Object.keys(isoforms).length === 0) {
                $q.all([DatabaseConnector.getIsoforms(), DatabaseConnector.getIsoforms('msk')])
                    .then(function(result) {
                        if (_.isArray(result)) {
                            var allGenes = [];
                            _.each(result, function(item) {
                                if (_.isArray(item)) {
                                    allGenes = allGenes.concat(item);
                                }
                            });
                            _.each(allGenes, function(item) {
                                if (_.isObject(item) &&
                                    _.isString(item.gene_name)) {
                                    isoforms[item.gene_name] = item;
                                }
                            });
                        }
                        deferred.resolve(isoforms[hugoSymbol]);
                    }, function() {
                        deferred.reject();
                    });
            } else {
                deferred.resolve(isoforms[hugoSymbol]);
            }
            return deferred.promise;
        }

        /**
         * Util to find gene type by giving hugo symbol
         * @param {string} hugoSymbol Gene Hugo Symbol
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
         */
        function getOncogeneTSG(hugoSymbol) {
            var deferred = $q.defer();
            if (Object.keys(oncogeneTSG).length === 0) {
                DatabaseConnector.getOncogeneTSG(hugoSymbol)
                    .then(function(result) {
                        if (_.isArray(result)) {
                            _.each(result, function(item) {
                                if (_.isObject(item) &&
                                    _.isString(item.gene)) {
                                    oncogeneTSG[item.gene] = item;
                                }
                            });
                        }
                        deferred.resolve(oncogeneTSG[hugoSymbol]);
                    }, function() {
                        deferred.reject();
                    });
            } else {
                deferred.resolve(oncogeneTSG[hugoSymbol]);
            }
            return deferred.promise;
        }

        /**
         * Util to send email systematically
         * @param {string} sendTo The recipient
         * @param {string} subject The email subject
         * @param {string} content The email content
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
        * */
        function sendEmail(sendTo, subject, content) {
            var deferred = $q.defer();
            var param = {sendTo: sendTo, subject: subject, content: content};
            DatabaseConnector.sendEmail(
                param,
                function(result) {
                    deferred.resolve(result);
                },
                function(result) {
                    deferred.reject(result);
                }
            );
            return deferred.promise;
        }

        /*
         *  Check if item needs to be reviewed or not
         *  @param {collaborative string object} uuid The uuid object for the item needs to be checked
         * */
        function needReview(uuid) {
            if (uuid) {
                uuid = uuid.getText();
                if ($rootScope.geneMetaData.get(uuid) && $rootScope.geneMetaData.get(uuid).get('review')) {
                    return true;
                }
            }
            return false;
        }

        /**
         * Check whether user is developer
         * @param {string} userName The user name
         * @return {boolean} whether user is developer
         */
        function developerCheck(userName) {
            if (!userName) {
                return false;
            }
            var developers = ['Hongxin Zhang', 'Jianjiong Gao', 'Jiaojiao Wang'];
            if (developers.indexOf(userName) !== -1) {
                return true;
            }
            return false;
        }

        return {
            getCancerTypesName: getCancerTypesName,
            containMainType: containMainType,
            createGene: createGene,
            createMutation: createMutation,
            createTumorType: createTumorType,
            createCancerType: createCancerType,
            createTreatment: createTreatment,
            getIsoform: getIsoform,
            getOncogeneTSG: getOncogeneTSG,
            getLastReviewedCancerTypesName: getLastReviewedCancerTypesName,
            sendEmail: sendEmail,
            needReview: needReview,
            developerCheck: developerCheck
        };
    });
<commit_msg>create history model when create new doc<commit_after>'use strict';

/**
 * @ngdoc service
 * @name oncokbApp.mainUtils
 * @description
 * # mainUtils
 * Service in the oncokbApp.
 */
angular.module('oncokbApp')
    .factory('mainUtils', function(OncoKB, _, storage, $q, DatabaseConnector, $rootScope) {
        var isoforms = {};
        var oncogeneTSG = {};

        /**
         * Create new Gene document
         * @param {string} hugoSymbol Gene Hugo Symbol
         * @param {string} parentFolderId The folder where to put new document
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
         */
        function createGene(hugoSymbol, parentFolderId) {
            var deferred = $q.defer();
            if (_.isString(hugoSymbol)) {
                storage.requireAuth().then(function() {
                    console.log('Creating gene ', hugoSymbol);
                    storage.createDocument(hugoSymbol, parentFolderId)
                        .then(function(result) {
                            if (result && result.error) {
                                console.error('\tError when creating document.');
                                deferred.reject(result);
                            } else {
                                storage.getRealtimeDocument(result.id)
                                    .then(function(file) {
                                        var model = file.getModel();
                                        var gene = model.getRoot().get('gene');
                                        if (!gene) {
                                            gene = model.create('Gene');
                                            gene.name.setText(hugoSymbol);
                                            model.getRoot().set('gene', gene);
                                        }
                                        if (!model.getRoot().get('vus')) {
                                            var vus = model.createList();
                                            model.getRoot().set('vus', vus);
                                        }
                                        if (!model.getRoot().get('history')) {
                                            var history = model.createMap();
                                            model.getRoot().set('history', history);
                                        }
                                        if (!model.getRoot().get('queue')) {
                                            var queue = model.createList();
                                            model.getRoot().set('queue', queue);
                                        }
                                        $q.all([getIsoform(hugoSymbol),
                                            getOncogeneTSG(hugoSymbol)])
                                            .then(function(result) {
                                                if (_.isArray(result)) {
                                                    var isoform = result[0];
                                                    var geneType = result[1];
                                                    if (isoform && isoform.error) {
                                                        console.error('\tError when getting isoforms.');
                                                    } else if (isoform && isoform.gene_name) {
                                                        var isoformModel = createIsoform(model, isoform);
                                                        gene.transcripts.push(isoformModel);
                                                    } else {
                                                        console.error('\tNo isoform found!!');
                                                    }

                                                    if (geneType && geneType.error) {
                                                        console.error('\tError when getting gene type.');
                                                    } else if (geneType && geneType.classification) {
                                                        var type = '';
                                                        var key = '';
                                                        switch (geneType.classification) {
                                                        case 'TSG':
                                                            type = 'Tumor Suppressor';
                                                            key = 'TSG';
                                                            break;
                                                        case 'Oncogene':
                                                            type = 'Oncogene';
                                                            key = 'OCG';
                                                            break;
                                                        default:
                                                            type = '';
                                                            break;
                                                        }
                                                        if (type) {
                                                            gene.type.set(key, type);
                                                        }
                                                    } else {
                                                        console.log('\tNo gene type found.');
                                                    }
                                                }
                                                deferred.resolve();
                                            }, function(error) {
                                                console.error('Failed to load isoform/geneType', error);
                                            });
                                    });
                            }
                        });
                });
            }
            return deferred.promise;
        }

        /**
         * Create Google realtime mutation
         * @param {object} model Google realtime gene model
         * @param {string} mutationName mutation name.
         * Could be multiple, separated by comma.
         * @return {OncoKB.Mutation} OncoKB.Mutation
         */
        function createMutation(model, mutationName) {
            if (_.isString(mutationName)) {
                mutationName = _.filter(mutationName
                    .trim().split(','), function(item) {
                    return _.isString(item);
                }).join(',');
                var mutation = model.create(OncoKB.Mutation);
                mutation.name.setText(mutationName);
                mutation.oncogenic_eStatus.set('obsolete', 'false');
                mutation.shortSummary_eStatus.set('obsolete', 'false');
                return mutation;
            }
            return null;
        }

        /**
         * Create OncoKB Tumor, it is list of Cancer Type
         * @param {object} model Google Realtime document gene model
         * @return {OncoKB.Tumor} OncoKB.Tumor
         */
        function createTumorType(model) {
            var tumorType = model.create(OncoKB.Tumor);
            for (var i = 0; i < 4; i++) {
                var __ti = model.create(OncoKB.TI);
                var __status = i < 2 ? 1 : 0; // 1: Standard, 0: Investigational
                var __type = i % 2 === 0 ? 1 : 0; // 1: sensitivity, 0: resistance
                var __name = (__status ? 'Standard' : 'Investigational') + ' implications for ' + (__type ? 'sensitivity' : 'resistance') + ' to therapy';

                __ti.types.set('status', __status.toString());
                __ti.types.set('type', __type.toString());
                __ti.name.setText(__name);
                tumorType.TI.push(__ti);
            }
            return tumorType;
        }

        /**
         * Create single OncoTree cancer type
         * @param {object} model Google Realtime document gene model
         * @param {string} cancerType OncoTree main type name
         * @param {string} subtype OncoTree subtype name
         * @param {stirng} oncoTreeCode Subtype code
         * @return {OncoKB.CancerType} OncoKB.CancerType
         */
        function createCancerType(model, cancerType, subtype, oncoTreeCode) {
            if (_.isString(cancerType)) {
                var newCancerType = model.create(OncoKB.CancerType);
                newCancerType.cancerType.setText(cancerType);
                if (_.isString(oncoTreeCode)) {
                    newCancerType.oncoTreeCode.setText(oncoTreeCode);
                }
                if (_.isString(subtype)) {
                    newCancerType.subtype.setText(subtype);
                }
                newCancerType.cancerType_eStatus.set('obsolete', 'false');
                newCancerType.subtype_eStatus.set('obsolete', 'false');
                newCancerType.oncoTreeCode_eStatus.set('obsolete', 'false');
                return newCancerType;
            }
            return null;
        }

        /**
         * Create new treatment object
         * @param {object} model Google realtime document
         * @param {string} treatmentName New treatment name
         * @return {OncoKB.Treatment} OncoKB.Treatment
         */
        function createTreatment(model, treatmentName) {
            if (_.isString(treatmentName) && treatmentName) {
                var treatment = model.create(OncoKB.Treatment);
                treatment.name.setText(treatmentName.trim());
                treatment.type.setText('Therapy');
                return treatment;
            }
            return null;
        }

        /**
         * Create Google Realtime isoform model
         * @param {object} model Google realtime document
         * @param {object} isoform gene isofom info
         * @return {*} return OncoKB.Isoform
         */
        function createIsoform(model, isoform) {
            if (_.isObject(isoform) && model) {
                var Isoform = model.create(OncoKB.ISOForm);
                if (isoform.isoform_override) {
                    Isoform.isoform_override.setText(isoform.isoform_override);
                }
                if (isoform.gene_name) {
                    Isoform.gene_name.setText(isoform.gene_name);
                }
                if (isoform.dmp_refseq_id) {
                    Isoform.dmp_refseq_id.setText(isoform.dmp_refseq_id);
                }
                if (isoform.ccds_id) {
                    Isoform.ccds_id.setText(isoform.ccds_id);
                }
                return Isoform;
            }
            return null;
        }

        /**
         * Output cancer type name, either subtype or cancerType
         * @param {array} cancerTypes List of cancer types
         * @return {string} TumorType name
         */
        function getCancerTypesName(cancerTypes) {
            if (!cancerTypes) {
                return null;
            }
            var list = [];
            cancerTypes.asArray().forEach(function(cancerType) {
                if (cancerType.subtype.length > 0) {
                    var str = cancerType.subtype.getText();
                    list.push(str);
                } else if (cancerType.cancerType.length > 0) {
                    list.push(cancerType.cancerType.getText());
                }
            });
            return list.join(', ');
        }

        /**
         * Check whether searched mainType in cancerTypes
         * @param {array} cancerTypes array of cancer types
         * @param {string} mainType searched main type
         * @return {boolean} whether exist
         */
        function containMainType(cancerTypes, mainType) {
            if (!cancerTypes || !mainType) {
                return null;
            }
            mainType = mainType.toLowerCase().trim();
            cancerTypes.asArray().forEach(function(cancerType) {
                if (cancerType.cancerType && cancerType.cancerType.text.toLowerCase().indexOf(mainType) !== -1) {
                    return true;
                }
            });
            return false;
        }

        /**
         * Output last reviewed cancer type name, either subtype or cancerType
         * @param {array} cancerTypes array of cancer types
         * @return {string} TumorType name
         */
        function getLastReviewedCancerTypesName(cancerTypes) {
            var list = [];
            if (_.isArray(cancerTypes)) {
                cancerTypes.forEach(function(cancerType) {
                    if (cancerType.subtype) {
                        var str = cancerType.subtype;
                        list.push(str);
                    } else if (cancerType.cancerType) {
                        list.push(cancerType.cancerType);
                    }
                });
            }
            return list.join(', ');
        }

        /**
         * Util to find isoform info by giving hugo symbol
         * @param {string} hugoSymbol Gene Hugo Symbol
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
         */
        function getIsoform(hugoSymbol) {
            var deferred = $q.defer();
            if (Object.keys(isoforms).length === 0) {
                $q.all([DatabaseConnector.getIsoforms(), DatabaseConnector.getIsoforms('msk')])
                    .then(function(result) {
                        if (_.isArray(result)) {
                            var allGenes = [];
                            _.each(result, function(item) {
                                if (_.isArray(item)) {
                                    allGenes = allGenes.concat(item);
                                }
                            });
                            _.each(allGenes, function(item) {
                                if (_.isObject(item) &&
                                    _.isString(item.gene_name)) {
                                    isoforms[item.gene_name] = item;
                                }
                            });
                        }
                        deferred.resolve(isoforms[hugoSymbol]);
                    }, function() {
                        deferred.reject();
                    });
            } else {
                deferred.resolve(isoforms[hugoSymbol]);
            }
            return deferred.promise;
        }

        /**
         * Util to find gene type by giving hugo symbol
         * @param {string} hugoSymbol Gene Hugo Symbol
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
         */
        function getOncogeneTSG(hugoSymbol) {
            var deferred = $q.defer();
            if (Object.keys(oncogeneTSG).length === 0) {
                DatabaseConnector.getOncogeneTSG(hugoSymbol)
                    .then(function(result) {
                        if (_.isArray(result)) {
                            _.each(result, function(item) {
                                if (_.isObject(item) &&
                                    _.isString(item.gene)) {
                                    oncogeneTSG[item.gene] = item;
                                }
                            });
                        }
                        deferred.resolve(oncogeneTSG[hugoSymbol]);
                    }, function() {
                        deferred.reject();
                    });
            } else {
                deferred.resolve(oncogeneTSG[hugoSymbol]);
            }
            return deferred.promise;
        }

        /**
         * Util to send email systematically
         * @param {string} sendTo The recipient
         * @param {string} subject The email subject
         * @param {string} content The email content
         * @return {*|h.promise|promise|r.promise|d.promise} Promise
        * */
        function sendEmail(sendTo, subject, content) {
            var deferred = $q.defer();
            var param = {sendTo: sendTo, subject: subject, content: content};
            DatabaseConnector.sendEmail(
                param,
                function(result) {
                    deferred.resolve(result);
                },
                function(result) {
                    deferred.reject(result);
                }
            );
            return deferred.promise;
        }

        /*
         *  Check if item needs to be reviewed or not
         *  @param {collaborative string object} uuid The uuid object for the item needs to be checked
         * */
        function needReview(uuid) {
            if (uuid) {
                uuid = uuid.getText();
                if ($rootScope.geneMetaData.get(uuid) && $rootScope.geneMetaData.get(uuid).get('review')) {
                    return true;
                }
            }
            return false;
        }

        /**
         * Check whether user is developer
         * @param {string} userName The user name
         * @return {boolean} whether user is developer
         */
        function developerCheck(userName) {
            if (!userName) {
                return false;
            }
            var developers = ['Hongxin Zhang', 'Jianjiong Gao', 'Jiaojiao Wang'];
            if (developers.indexOf(userName) !== -1) {
                return true;
            }
            return false;
        }

        return {
            getCancerTypesName: getCancerTypesName,
            containMainType: containMainType,
            createGene: createGene,
            createMutation: createMutation,
            createTumorType: createTumorType,
            createCancerType: createCancerType,
            createTreatment: createTreatment,
            getIsoform: getIsoform,
            getOncogeneTSG: getOncogeneTSG,
            getLastReviewedCancerTypesName: getLastReviewedCancerTypesName,
            sendEmail: sendEmail,
            needReview: needReview,
            developerCheck: developerCheck
        };
    });
<|endoftext|>


<commit_before>import {
  props,
  define,
  hasNativeShadowDomSupport,
  containsTagName,
} from '@bolt/core/utils';
import { withLitHtml, html } from '@bolt/core/renderers/renderer-lit-html';
import { ifDefined } from 'lit-html/directives/if-defined';
import extName from 'ext-name';

// Use 'dedupe' version instead of 'bind' to help merge initial classes with those defined here
import classNames from 'classnames/dedupe';

import imageStyles from './image.scss';

import schema from '../image.schema.yml';

import './_image-lazy-sizes';

let cx = classNames.bind(imageStyles);

@define
class BoltImage extends withLitHtml() {
  static is = 'bolt-image';

  static props = {
    src: props.string,
    alt: props.string,
    noLazy: props.boolean,
    srcset: props.string,
    sizes: props.string,
    ratio: props.string,
    placeholderColor: props.string,
    placeholderImage: props.string,
    zoom: props.boolean,
    cover: props.boolean,
  };

  // https://github.com/WebReflection/document-register-element#upgrading-the-constructor-context
  constructor(self) {
    self = super(self);
    self.useShadow = hasNativeShadowDomSupport;
    self.schema = this.getModifiedSchema(schema);
    return self;
  }

  getModifiedSchema(schema) {
    var modifiedSchema = schema;

    // Remove "lazyload" and "useAspectRatio" from schema, does not apply to web component.
    for (let property in modifiedSchema.properties) {
      if (property === 'lazyload' || property === 'useAspectRatio') {
        delete modifiedSchema.properties[property];
      }
    }

    return modifiedSchema;
  }

  lazyloadImage(image) {
    if (!this.isLoaded) {
      // Note: This immediately unveils the image. Add intersection observer?
      lazySizes.loader.unveil(image);
      this.isLoaded = true;
    }
  }

  connecting() {
    // IE fires this twice, only let it remove children once
    if (!this._wasInitiallyRendered) {
      super.connecting && super.connecting();

      const image = this.querySelector('.c-bolt-image__image');
      this.initialClasses = image ? [].slice.call(image.classList) : [];

      while (this.firstChild) {
        this.removeChild(this.firstChild);
      }
    }
  }

  rendered() {
    super.rendered && super.rendered();

    const lazyImage = this.shadowRoot
      ? this.shadowRoot.querySelector('.js-lazyload')
      : this.querySelector('.js-lazyload');

    if (lazyImage) {
      // check if placeholder image has loaded; lazySizes will only unveil an image that is "complete"
      if (lazyImage.complete) {
        this.lazyloadImage(lazyImage);
      } else {
        lazyImage.onload = () => {
          this.lazyloadImage(lazyImage);
        };
      }
    }
  }

  render() {
    // validate the original prop data passed along -- returns back the validated data w/ added default values
    const {
      src,
      alt,
      noLazy,
      srcset,
      sizes,
      ratio,
      placeholderColor,
      placeholderImage,
      zoom,
      cover,
    } = this.validateProps(this.props);

    // negate and rename variables for readability
    const lazyload = !noLazy;

    // use ratio by default, still depends upon aspect-ratio being passed in
    let useRatio = true;
    let ratioW, ratioH;

    if (ratio === 'none') {
      useRatio = false;
    } else {
      if (ratio === 'auto') {
        // TODO: automatically get image dimensions
      } else if (ratio.includes('/')) {
        const ratioArr = ratio.split('/');
        ratioW = ratioArr[0];
        ratioH = ratioArr[1];
      }
    }

    const _isJpg = src && extName(src)[0].ext === 'jpg';
    const _canUseRatio = ratioW > 0 && ratioH > 0 && useRatio && !cover;
    // Only JPGs allowed, PNGs can have transparency and may not look right layered over placeholder
    const _canUsePlaceholder = (_canUseRatio || cover) && _isJpg;

    const classes = cx(...this.initialClasses, 'c-bolt-image__image', {
      'c-bolt-image__lazyload': lazyload,
      'c-bolt-image__lazyload--fade': lazyload,
      'c-bolt-image__lazyload--blur': lazyload && _isJpg,
      'js-lazyload': lazyload,
      'c-bolt-image--cover': cover,
    });

    const imageElement = () => {
      if (src || srcset) {
        return html`
          <img
            class="${classes}"
            src="${lazyload ? placeholderImage : src}"
            alt="${ifDefined(alt ? alt : undefined)}"
            srcset="${ifDefined(
              !lazyload || this.isLoaded ? srcset || src : undefined,
            )}"
            data-srcset="${ifDefined(lazyload ? srcset || src : undefined)}"
            sizes="${ifDefined(!lazyload || this.isLoaded ? sizes : undefined)}"
            data-sizes="${ifDefined(lazyload ? sizes : undefined)}"
            data-zoom="${ifDefined(zoom ? src : undefined)}"
          />
        `;
      }
    };

    const placeholderImageElement = () => {
      if (_canUsePlaceholder) {
        return html`
          <img
            class="${cx(
              ...this.initialClasses,
              'c-bolt-image__image-placeholder',
              {
                'c-bolt-image__image': false,
                'c-bolt-image__lazyload': false,
                'c-bolt-image__lazyload--fade': false,
                'c-bolt-image__lazyload--blur': false,
                'js-lazyload': false,
                'c-bolt-image--cover': cover,
              },
            )}"
            src="${placeholderImage}"
            alt="${ifDefined(alt ? alt : undefined)}"
          />
        `;
      }
    };

    // Include <noscript> for server-side rendered components
    const fallbackImageElement = () => {
      // this.isSSR is undefined at the moment, placeholder for future server-side rendering
      if (lazyload && src && this.isSSR) {
        return html`
          <noscript>
            <img
              class="${cx('c-bolt-image__image', {
                'c-bolt-image--cover': cover,
              })}"
              src="${src}"
              alt="${ifDefined(alt ? alt : undefined)}"
              srcset="${ifDefined(!lazyload ? srcset || src : undefined)}"
              data-srcset="${ifDefined(lazyload ? srcset || src : undefined)}"
            />
          </noscript>
        `;
      }
    };

    const imageTemplate = html`
      ${placeholderImageElement()} ${imageElement()} ${fallbackImageElement()}
    `;

    const ratioTemplate = children => {
      return html`
        <bolt-ratio ratio="${ratioW * 1}/${ratioH * 1}">
          ${children}
        </bolt-ratio>
      `;
    };

    if (_canUsePlaceholder && placeholderColor) {
      this.style.backgroundColor = placeholderColor;
    }

    let renderedImage;

    if (_canUseRatio) {
      renderedImage = ratioTemplate(imageTemplate);
    } else {
      renderedImage = imageTemplate;
    }

    return html`
      ${this.addStyles([imageStyles])} ${renderedImage}
    `;
  }
}

export { BoltImage };
<commit_msg>refactor: remove unused 'containsTagName' import<commit_after>import { props, define, hasNativeShadowDomSupport } from '@bolt/core/utils';
import { withLitHtml, html } from '@bolt/core/renderers/renderer-lit-html';
import { ifDefined } from 'lit-html/directives/if-defined';
import extName from 'ext-name';

// Use 'dedupe' version instead of 'bind' to help merge initial classes with those defined here
import classNames from 'classnames/dedupe';

import imageStyles from './image.scss';

import schema from '../image.schema.yml';

import './_image-lazy-sizes';

let cx = classNames.bind(imageStyles);

@define
class BoltImage extends withLitHtml() {
  static is = 'bolt-image';

  static props = {
    src: props.string,
    alt: props.string,
    noLazy: props.boolean,
    srcset: props.string,
    sizes: props.string,
    ratio: props.string,
    placeholderColor: props.string,
    placeholderImage: props.string,
    zoom: props.boolean,
    cover: props.boolean,
  };

  // https://github.com/WebReflection/document-register-element#upgrading-the-constructor-context
  constructor(self) {
    self = super(self);
    self.useShadow = hasNativeShadowDomSupport;
    self.schema = this.getModifiedSchema(schema);
    return self;
  }

  getModifiedSchema(schema) {
    var modifiedSchema = schema;

    // Remove "lazyload" and "useAspectRatio" from schema, does not apply to web component.
    for (let property in modifiedSchema.properties) {
      if (property === 'lazyload' || property === 'useAspectRatio') {
        delete modifiedSchema.properties[property];
      }
    }

    return modifiedSchema;
  }

  lazyloadImage(image) {
    if (!this.isLoaded) {
      // Note: This immediately unveils the image. Add intersection observer?
      lazySizes.loader.unveil(image);
      this.isLoaded = true;
    }
  }

  connecting() {
    // IE fires this twice, only let it remove children once
    if (!this._wasInitiallyRendered) {
      super.connecting && super.connecting();

      const image = this.querySelector('.c-bolt-image__image');
      this.initialClasses = image ? [].slice.call(image.classList) : [];

      while (this.firstChild) {
        this.removeChild(this.firstChild);
      }
    }
  }

  rendered() {
    super.rendered && super.rendered();

    const lazyImage = this.shadowRoot
      ? this.shadowRoot.querySelector('.js-lazyload')
      : this.querySelector('.js-lazyload');

    if (lazyImage) {
      // check if placeholder image has loaded; lazySizes will only unveil an image that is "complete"
      if (lazyImage.complete) {
        this.lazyloadImage(lazyImage);
      } else {
        lazyImage.onload = () => {
          this.lazyloadImage(lazyImage);
        };
      }
    }
  }

  render() {
    // validate the original prop data passed along -- returns back the validated data w/ added default values
    const {
      src,
      alt,
      noLazy,
      srcset,
      sizes,
      ratio,
      placeholderColor,
      placeholderImage,
      zoom,
      cover,
    } = this.validateProps(this.props);

    // negate and rename variables for readability
    const lazyload = !noLazy;

    // use ratio by default, still depends upon aspect-ratio being passed in
    let useRatio = true;
    let ratioW, ratioH;

    if (ratio === 'none') {
      useRatio = false;
    } else {
      if (ratio === 'auto') {
        // TODO: automatically get image dimensions
      } else if (ratio.includes('/')) {
        const ratioArr = ratio.split('/');
        ratioW = ratioArr[0];
        ratioH = ratioArr[1];
      }
    }

    const _isJpg = src && extName(src)[0].ext === 'jpg';
    const _canUseRatio = ratioW > 0 && ratioH > 0 && useRatio && !cover;
    // Only JPGs allowed, PNGs can have transparency and may not look right layered over placeholder
    const _canUsePlaceholder = (_canUseRatio || cover) && _isJpg;

    const classes = cx(...this.initialClasses, 'c-bolt-image__image', {
      'c-bolt-image__lazyload': lazyload,
      'c-bolt-image__lazyload--fade': lazyload,
      'c-bolt-image__lazyload--blur': lazyload && _isJpg,
      'js-lazyload': lazyload,
      'c-bolt-image--cover': cover,
    });

    const imageElement = () => {
      if (src || srcset) {
        return html`
          <img
            class="${classes}"
            src="${lazyload ? placeholderImage : src}"
            alt="${ifDefined(alt ? alt : undefined)}"
            srcset="${ifDefined(
              !lazyload || this.isLoaded ? srcset || src : undefined,
            )}"
            data-srcset="${ifDefined(lazyload ? srcset || src : undefined)}"
            sizes="${ifDefined(!lazyload || this.isLoaded ? sizes : undefined)}"
            data-sizes="${ifDefined(lazyload ? sizes : undefined)}"
            data-zoom="${ifDefined(zoom ? src : undefined)}"
          />
        `;
      }
    };

    const placeholderImageElement = () => {
      if (_canUsePlaceholder) {
        return html`
          <img
            class="${cx(
              ...this.initialClasses,
              'c-bolt-image__image-placeholder',
              {
                'c-bolt-image__image': false,
                'c-bolt-image__lazyload': false,
                'c-bolt-image__lazyload--fade': false,
                'c-bolt-image__lazyload--blur': false,
                'js-lazyload': false,
                'c-bolt-image--cover': cover,
              },
            )}"
            src="${placeholderImage}"
            alt="${ifDefined(alt ? alt : undefined)}"
          />
        `;
      }
    };

    // Include <noscript> for server-side rendered components
    const fallbackImageElement = () => {
      // this.isSSR is undefined at the moment, placeholder for future server-side rendering
      if (lazyload && src && this.isSSR) {
        return html`
          <noscript>
            <img
              class="${cx('c-bolt-image__image', {
                'c-bolt-image--cover': cover,
              })}"
              src="${src}"
              alt="${ifDefined(alt ? alt : undefined)}"
              srcset="${ifDefined(!lazyload ? srcset || src : undefined)}"
              data-srcset="${ifDefined(lazyload ? srcset || src : undefined)}"
            />
          </noscript>
        `;
      }
    };

    const imageTemplate = html`
      ${placeholderImageElement()} ${imageElement()} ${fallbackImageElement()}
    `;

    const ratioTemplate = children => {
      return html`
        <bolt-ratio ratio="${ratioW * 1}/${ratioH * 1}">
          ${children}
        </bolt-ratio>
      `;
    };

    if (_canUsePlaceholder && placeholderColor) {
      this.style.backgroundColor = placeholderColor;
    }

    let renderedImage;

    if (_canUseRatio) {
      renderedImage = ratioTemplate(imageTemplate);
    } else {
      renderedImage = imageTemplate;
    }

    return html`
      ${this.addStyles([imageStyles])} ${renderedImage}
    `;
  }
}

export { BoltImage };
<|endoftext|>


<commit_before>// @flow

/* eslint consistent-this: ["error", "view"] */

import type {Node} from 'react';
import React, {Component} from 'react';
import Dialog from '@material-ui/core/Dialog';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import style from './style.scss';

const theme = createMuiTheme({
    overrides: {
        MuiPaper: {
            // Name of the component ⚛ / style sheet
            root: {
                // Name of the rule
                // Some CSS
                boxShadow: 'none !important',
                backgroundColor: 'transparent !important'
            }
        }
    }
});

type StateType = void;
type PropsType = {|
    +isOpen: boolean
|};

export default class Spinner extends Component<PropsType, StateType> {
    props: PropsType;
    state: StateType;

    render(): Node {
        const view = this;
        const {props} = view;

        return (
            <MuiThemeProvider theme={theme}>
                <Dialog
                    open={props.isOpen}
                    keepMounted
                    aria-labelledby="alert-dialog-slide-title"
                    aria-describedby="alert-dialog-slide-description"
                >

                </Dialog>
            </MuiThemeProvider>
        );
    }
}
<commit_msg>update<commit_after>// @flow

/* eslint consistent-this: ["error", "view"] */

import type {Node} from 'react';
import React, {Component} from 'react';
import Dialog from '@material-ui/core/Dialog';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import style from './style.scss';

const theme = createMuiTheme({
    typography: {
        useNextVariants: true
    },
    overrides: {
        MuiPaper: {
            // Name of the component ⚛ / style sheet
            root: {
                // Name of the rule
                // Some CSS
                boxShadow: 'none !important',
                backgroundColor: 'transparent !important'
            }
        }
    }
});

type StateType = void;
type PropsType = {|
    +isOpen: boolean
|};

export default class Spinner extends Component<PropsType, StateType> {
    props: PropsType;
    state: StateType;

    render(): Node {
        const view = this;
        const {props} = view;

        return (
            <MuiThemeProvider theme={theme}>
                <Dialog
                    open={props.isOpen}
                    keepMounted
                    aria-labelledby="alert-dialog-slide-title"
                    aria-describedby="alert-dialog-slide-description"
                >

                </Dialog>
            </MuiThemeProvider>
        );
    }
}
<|endoftext|>


<commit_before>/* $This file is distributed under the terms of the license in /doc/license.txt$ */

var browseByVClass = {
    // Initial page setup
    onLoad: function() {
        this.mergeFromTemplate();
        this.initObjects();
        this.bindEventListeners();
    },

    // Add variables from menupage template
    mergeFromTemplate: function() {
        $.extend(this, menupageData);
    },

    // Create references to frequently used elements for convenience
    initObjects: function() {
        this.vgraphVClasses = $('#vgraph-classes');
        this.vgraphVClassLinks = $('#vgraph-classes li a');
        this.browseVClasses = $('#browse-classes');
        this.browseVClassLinks = $('#browse-classes li a');
        this.alphaIndex = $('#alpha-browse-individuals');
        this.alphaIndexLinks = $('#alpha-browse-individuals li a');
        this.paginationNav = $('nav.pagination');
        this.paginationLinks = $('nav.pagination li a');
        this.individualsInVClass = $('#individuals-in-class ul');
        this.individualsContainer = $('#individuals-in-class');
    },

    // Event listeners. Called on page load
    bindEventListeners: function() {
        // Listeners for vClass switching
        this.vgraphVClassLinks.click(function() {
            uri = $(this).attr('data-uri');
            browseByVClass.getIndividuals(uri);
        });

        this.browseVClassLinks.click(function() {
            uri = $(this).attr('data-uri');
            browseByVClass.getIndividuals(uri);
            return false;
        });

        // Listener for alpha switching
        this.alphaIndexLinks.click(function() {
            uri = $('#browse-classes li a.selected').attr('data-uri');
            alpha = $(this).attr('data-alpha');
            // alpha = $(this).text().substring(0, 1);
            browseByVClass.getIndividuals(uri, alpha);
            return false;
        });

        // Call the pagination listener
        this.paginationListener();
    },

    // Listener for page switching -- separate from the rest because it needs to be callable
    paginationListener: function() {
        $('nav.pagination li a').click(function() {
            uri = $('#browse-classes li a.selected').attr('data-uri');
            alpha = $('#alpha-browse-individuals li a.selected').attr('data-alpha');
            page = $(this).attr('class').substring(4,5);
            browseByVClass.getIndividuals(uri, alpha, page);
            return false;
        });
    },

    // Load individuals for default class as specified by menupage template
    defaultVClass: function() {
        if ( this.defaultBrowseVClassURI != "false" ) {
            this.getIndividuals(this.defaultBrowseVClassUri);
        }
    },

    // Where all the magic happens -- gonna fetch me some individuals
    getIndividuals: function(vclassUri, alpha, page) {
        url = this.dataServiceUrl + encodeURIComponent(vclassUri);
        if ( alpha && alpha != "all") {
            url += '&alpha=' + alpha;
        }
        if ( page ) {
            url += '&page=' + page;
        } else {
            page = 1;
        }

        // First wipe currently displayed individuals and existing pagination
        this.individualsInVClass.empty();
        $('nav.pagination').remove();

        $.getJSON(url, function(results) {
            // Check to see if we're dealing with pagination
            if ( results.pages.length ) {
                pages = results.pages;

                pagination = '';
                pagination += '
page
';
                pagination += '
';
                $.each(pages, function(i, item) {
                    anchorOpen = '';
                    anchorClose = '';

                    pagination += '
';
                    pagination += anchorOpen;
                    pagination += pages[i].text;
                    pagination += anchorClose;
                    pagination += '
';
                })
                pagination += '
';

                // Add the pagination above and below the list of individuals and call the listener
                browseByVClass.individualsContainer.prepend(pagination);
                browseByVClass.individualsContainer.append(pagination);
                browseByVClass.paginationListener();
            }

            $.each(results.individuals, function(i, item) {
                label = results.individuals[i].label;
                moniker = results.individuals[i].moniker;
                vclassName = results.individuals[i].vclassName;
                uri = results.individuals[i].URI;
                profileUrl = results.individuals[i].profileUrl;
                if ( results.individuals[i].thumbUrl ) {
                    image = browseByVClass.baseUrl + results.individuals[i].thumbUrl;
                }
                // Build the content of each list item, piecing together each component
                listItem = '
';
                if ( typeof results.individuals[i].thumbUrl !== "undefined" ) {
                    listItem += '
';
                } else {
                    listItem += '
';
                }
                listItem += ''+ label +'
';
                // Include the moniker only if it's not empty and not equal to the VClass name
                if ( moniker != vclassName && moniker != "" ) {
                    listItem += ''+ moniker +'';
                }
                listItem += '
';
                browseByVClass.individualsInVClass.append(listItem);
            })

            // Set selected class, alpha and page
            browseByVClass.selectedVClass(results.vclass.URI);
            browseByVClass.selectedAlpha(alpha);
        });
    },

    // Toggle the active class so it's clear which is selected
    selectedVClass: function(vclassUri) {
        // Remove active class on all vClasses
        $('#browse-classes li a.selected').removeClass('selected');

        // Add active class for requested vClass
        $('#browse-classes li a[data-uri="'+ vclassUri +'"]').addClass('selected');
    },

    // Toggle the active letter so it's clear which is selected
    selectedAlpha: function(alpha) {
        // if no alpha argument sent, assume all
        if ( alpha == null ) {
            alpha = "all";
        }
        // Remove active class on all letters
        $('#alpha-browse-individuals li a.selected').removeClass('selected');

        // Add active class for requested alpha
        $('#alpha-browse-individuals li a[data-alpha="'+ alpha +'"]').addClass('selected');
    }
};

$(document).ready(function() {
    browseByVClass.onLoad();
    browseByVClass.defaultVClass();
});<commit_msg>NIHVIVO-1948 Pulled pagination out into its own function so it can be called by the default file and any product extension. Also introduced scrolling to getIndividuals(). Not sure if we'll keep this.<commit_after>/* $This file is distributed under the terms of the license in /doc/license.txt$ */

var browseByVClass = {
    // Initial page setup
    onLoad: function() {
        this.mergeFromTemplate();
        this.initObjects();
        this.bindEventListeners();
    },

    // Add variables from menupage template
    mergeFromTemplate: function() {
        $.extend(this, menupageData);
    },

    // Create references to frequently used elements for convenience
    initObjects: function() {
        this.vgraphVClasses = $('#vgraph-classes');
        this.vgraphVClassLinks = $('#vgraph-classes li a');
        this.browseVClasses = $('#browse-classes');
        this.browseVClassLinks = $('#browse-classes li a');
        this.alphaIndex = $('#alpha-browse-individuals');
        this.alphaIndexLinks = $('#alpha-browse-individuals li a');
        this.paginationNav = $('nav.pagination');
        this.paginationLinks = $('nav.pagination li a');
        this.individualsInVClass = $('#individuals-in-class ul');
        this.individualsContainer = $('#individuals-in-class');
    },

    // Event listeners. Called on page load
    bindEventListeners: function() {
        // Listeners for vClass switching
        this.vgraphVClassLinks.click(function() {
            uri = $(this).attr('data-uri');
            browseByVClass.getIndividuals(uri);
        });

        this.browseVClassLinks.click(function() {
            uri = $(this).attr('data-uri');
            browseByVClass.getIndividuals(uri);
            return false;
        });

        // Listener for alpha switching
        this.alphaIndexLinks.click(function() {
            uri = $('#browse-classes li a.selected').attr('data-uri');
            alpha = $(this).attr('data-alpha');
            // alpha = $(this).text().substring(0, 1);
            browseByVClass.getIndividuals(uri, alpha);
            return false;
        });

        // Call the pagination listener
        this.paginationListener();
    },

    // Listener for page switching -- separate from the rest because it needs to be callable
    paginationListener: function() {
        $('nav.pagination li a').click(function() {
            uri = $('#browse-classes li a.selected').attr('data-uri');
            alpha = $('#alpha-browse-individuals li a.selected').attr('data-alpha');
            page = $(this).attr('class').substring(4,5);
            browseByVClass.getIndividuals(uri, alpha, page);
            return false;
        });
    },

    // Load individuals for default class as specified by menupage template
    defaultVClass: function() {
        if ( this.defaultBrowseVClassURI != "false" ) {
            this.getIndividuals(this.defaultBrowseVClassUri, "all", 1, false);
        }
    },

    // Where all the magic happens -- gonna fetch me some individuals
    getIndividuals: function(vclassUri, alpha, page, scroll) {
        url = this.dataServiceUrl + encodeURIComponent(vclassUri);
        if ( alpha && alpha != "all") {
            url += '&alpha=' + alpha;
        }
        if ( page ) {
            url += '&page=' + page;
        } else {
            page = 1;
        }
        if ( typeof scroll === "undefined" ) {
            scroll = true;
        }

        // First wipe currently displayed individuals and existing pagination
        this.individualsInVClass.empty();
        $('nav.pagination').remove();

        $.getJSON(url, function(results) {
            // Check to see if we're dealing with pagination
            if ( results.pages.length ) {
                pages = results.pages;
                browseByVClass.pagination(pages, page);
            }

            $.each(results.individuals, function(i, item) {
                label = results.individuals[i].label;
                moniker = results.individuals[i].moniker;
                vclassName = results.individuals[i].vclassName;
                uri = results.individuals[i].URI;
                profileUrl = results.individuals[i].profileUrl;
                if ( results.individuals[i].thumbUrl ) {
                    image = browseByVClass.baseUrl + results.individuals[i].thumbUrl;
                }
                // Build the content of each list item, piecing together each component
                listItem = '
';
                if ( typeof results.individuals[i].thumbUrl !== "undefined" ) {
                    listItem += '
';
                } else {
                    listItem += '
';
                }
                listItem += ''+ label +'
';
                // Include the moniker only if it's not empty and not equal to the VClass name
                if ( moniker != vclassName && moniker != "" ) {
                    listItem += ''+ moniker +'';
                }
                listItem += '
';
                browseByVClass.individualsInVClass.append(listItem);
            })

            // Set selected class, alpha and page
            browseByVClass.selectedVClass(results.vclass.URI);
            browseByVClass.selectedAlpha(alpha);

            // Scroll to the top of the browse section unless told otherwise
            if ( scroll != false ) {
                $.scrollTo('#browse-by', 500);
            }
        });
    },

    // Print out the pagination nav if called
    pagination: function(pages, page) {
        pagination = '';
        pagination += '
page
';
        pagination += '
';
        $.each(pages, function(i, item) {
            anchorOpen = '';
            anchorClose = '';

            pagination += '
';
            pagination += anchorOpen;
            pagination += pages[i].text;
            pagination += anchorClose;
            pagination += '
';
        })
        pagination += '
';

        // Add the pagination above and below the list of individuals and call the listener
        browseByVClass.individualsContainer.prepend(pagination);
        browseByVClass.individualsContainer.append(pagination);
        browseByVClass.paginationListener();
    },

    // Toggle the active class so it's clear which is selected
    selectedVClass: function(vclassUri) {
        // Remove active class on all vClasses
        $('#browse-classes li a.selected').removeClass('selected');

        // Add active class for requested vClass
        $('#browse-classes li a[data-uri="'+ vclassUri +'"]').addClass('selected');
    },

    // Toggle the active letter so it's clear which is selected
    selectedAlpha: function(alpha) {
        // if no alpha argument sent, assume all
        if ( alpha == null ) {
            alpha = "all";
        }
        // Remove active class on all letters
        $('#alpha-browse-individuals li a.selected').removeClass('selected');

        // Add active class for requested alpha
        $('#alpha-browse-individuals li a[data-alpha="'+ alpha +'"]').addClass('selected');
    }
};

$(document).ready(function() {
    browseByVClass.onLoad();
    browseByVClass.defaultVClass();
});<|endoftext|>


<commit_before>H5.GridViewHelper = (function (Height, Math, add) {
    "use strict";

    function GridViewHelper(stage, device, xTilesCount, yTilesCount, topOffset, bottomOffset) {
        this.stage = stage;
        this.device = device;
        this.xTiles = xTilesCount;
        this.yTiles = yTilesCount;
        this.topOffset = topOffset;
        this.bottomOffset = bottomOffset;

        this.baseScale = 1;
    }

    GridViewHelper.prototype.getEdgeLengthFn = function () {
        return (function (self) {
            return function (width, height) {
                return self.__edgeLength(height);
            }
        })(this);
    };

    GridViewHelper.prototype.getCoordinates = function (x, y) {

        var length = this.__edgeLength(this.device.height);
        return {
            u: Math.floor((x - this.__xOffset(this.device.width, length) + length / 2) / length),
            v: Math.floor((y - this.__getTopOffset(this.device.height)) / length)
        };
    };

    GridViewHelper.prototype.getCoordinatesWithScale = function (x, y, scale) {

        var length = this.__edgeLength(this.device.height);
        var u = Math.floor((x - this.__xOffset(this.device.width, length) + length / 2) / length);
        var v = Math.floor((y - this.__getTopOffset(this.device.height)) / length);

        function isHit(x, y, cornerX, endX, cornerY, endY) {
            return x > cornerX && x < endX && y > cornerY && y < endY;
        }

        var position = this.getPosition(u, v);
        var lengthHalfScaled = Math.floor(length / 2 * scale);

        if (isHit(x, y, position.x - lengthHalfScaled, position.x + lengthHalfScaled, position.y - lengthHalfScaled,
                position.y + lengthHalfScaled)) {

            return {
                u: u,
                v: v
            };
        }

        return false;
    };

    GridViewHelper.prototype.getPosition = function (u, v) {
        return {
            x: this.__getX(u)(this.device.width, this.device.height),
            y: this.__getY(v)(this.device.height)
        };
    };

    GridViewHelper.prototype.create = function (u, v, name, defaultTileHeight, xOffset, yOffset, dependencies) {
        return this.createBackground(u, v, name, 5, defaultTileHeight, xOffset, yOffset, dependencies);
    };

    GridViewHelper.prototype.createBackground = function (u, v, name, zIndex, defaultTileHeight, xOffset, yOffset,
        dependencies) {
        var drawable = this.stage.createImage(name);
        if (xOffset && yOffset) {
            drawable.setPosition(add(this.__getX(u), xOffset), add(this.__getY(v), yOffset), dependencies);
        } else if (xOffset) {
            drawable.setPosition(add(this.__getX(u), xOffset), this.__getY(v), dependencies);
        } else if (yOffset) {
            drawable.setPosition(this.__getX(u), add(this.__getY(v), yOffset), dependencies);
        } else {
            drawable.setPosition(this.__getX(u), this.__getY(v), dependencies);
        }
        if (zIndex !== 3)
            drawable.setZIndex(zIndex);
        if (defaultTileHeight) {
            var scaleFactor = drawable.data.height / defaultTileHeight;
            drawable.scale = this.__calcBaseScale(drawable.getHeight()) * scaleFactor;
        } else {
            drawable.scale = this.__calcBaseScale(drawable.getHeight());
        }

        return drawable;
    };

    GridViewHelper.prototype.__calcBaseScale = function (drawableHeight) {
        var length = this.__edgeLength(this.device.height);
        return length / drawableHeight;
    };

    GridViewHelper.prototype.createRect = function (u, v, color) {
        var self = this;

        function getWidth(width, height) {
            return self.__edgeLength(height) - 1;
        }

        function getHeight(height) {
            return self.__edgeLength(height) - 1;
        }

        return this.stage.createRectangle(true).setPosition(this.__getX(u), this.__getY(v)).setWidth(getWidth)
            .setHeight(getHeight).setColor(color);
    };

    GridViewHelper.prototype.createRectBackground = function (u, v, color, zIndex) {
        return this.createRect(u, v, color).setZIndex(zIndex);
    };

    GridViewHelper.prototype.move = function (drawable, u, v, speed, callback, xOffset, yOffset, dependencies) {
        if (xOffset && yOffset)
            return drawable.moveTo(add(this.__getX(u), xOffset), add(this.__getY(v), yOffset), dependencies)
                .setDuration(speed).setCallback(callback);
        if (xOffset)
            return drawable.moveTo(add(this.__getX(u), xOffset), this.__getY(v), dependencies).setDuration(speed)
                .setCallback(callback);
        if (yOffset)
            return drawable.moveTo(this.__getX(u), add(this.__getY(v), yOffset), dependencies).setDuration(speed)
                .setCallback(callback);
        return drawable.moveTo(this.__getX(u), this.__getY(v), dependencies).setDuration(speed).setCallback(callback);
    };

    GridViewHelper.prototype.setPosition = function (drawable, u, v, dependencies) {
        return drawable.setPosition(this.__getX(u), this.__getY(v), dependencies);
    };

    GridViewHelper.prototype.__edgeLength = function (height) {
        if (this.bottomOffset) {
            return Height.get(this.yTiles)(height - (this.__getTopOffset(height) + this.bottomOffset(height)));
        } else {
            return Height.get(this.yTiles)(height - this.__getTopOffset(height));
        }
    };

    GridViewHelper.prototype.__xOffset = function (width, length) {
        return Math.floor(width / 2 - length * this.xTiles / 2 + length / 2);
    };

    GridViewHelper.prototype.__getX = function (u) {
        var self = this;
        return function (width, height) {
            var length = self.__edgeLength(height);
            var start = self.__xOffset(width, length);
            return start + u * length;
        };
    };

    GridViewHelper.prototype.__getY = function (v) {
        var self = this;
        return function (height) {
            var length = self.__edgeLength(height);
            return v * length + Math.floor(length / 2) + self.__getTopOffset(height);
        };
    };

    GridViewHelper.prototype.__getTopOffset = function (height) {
        return this.topOffset(height);
    };

    GridViewHelper.prototype.getBaseScale = function () {
        return this.baseScale;
    };

    return GridViewHelper;
})(H5.Height, Math, H5.add);<commit_msg>make top offset optional #core<commit_after>H5.GridViewHelper = (function (Height, Math, add) {
    "use strict";

    function GridViewHelper(stage, device, xTilesCount, yTilesCount, topOffset, bottomOffset) {
        this.stage = stage;
        this.device = device;
        this.xTiles = xTilesCount;
        this.yTiles = yTilesCount;
        this.topOffset = topOffset;
        this.bottomOffset = bottomOffset;

        this.baseScale = 1;
    }

    GridViewHelper.prototype.getEdgeLengthFn = function () {
        return (function (self) {
            return function (width, height) {
                return self.__edgeLength(height);
            }
        })(this);
    };

    GridViewHelper.prototype.getCoordinates = function (x, y) {

        var length = this.__edgeLength(this.device.height);
        return {
            u: Math.floor((x - this.__xOffset(this.device.width, length) + length / 2) / length),
            v: Math.floor((y - this.__getTopOffset(this.device.height)) / length)
        };
    };

    GridViewHelper.prototype.getCoordinatesWithScale = function (x, y, scale) {

        var length = this.__edgeLength(this.device.height);
        var u = Math.floor((x - this.__xOffset(this.device.width, length) + length / 2) / length);
        var v = Math.floor((y - this.__getTopOffset(this.device.height)) / length);

        function isHit(x, y, cornerX, endX, cornerY, endY) {
            return x > cornerX && x < endX && y > cornerY && y < endY;
        }

        var position = this.getPosition(u, v);
        var lengthHalfScaled = Math.floor(length / 2 * scale);

        if (isHit(x, y, position.x - lengthHalfScaled, position.x + lengthHalfScaled, position.y - lengthHalfScaled,
                position.y + lengthHalfScaled)) {

            return {
                u: u,
                v: v
            };
        }

        return false;
    };

    GridViewHelper.prototype.getPosition = function (u, v) {
        return {
            x: this.__getX(u)(this.device.width, this.device.height),
            y: this.__getY(v)(this.device.height)
        };
    };

    GridViewHelper.prototype.create = function (u, v, name, defaultTileHeight, xOffset, yOffset, dependencies) {
        return this.createBackground(u, v, name, 5, defaultTileHeight, xOffset, yOffset, dependencies);
    };

    GridViewHelper.prototype.createBackground = function (u, v, name, zIndex, defaultTileHeight, xOffset, yOffset,
        dependencies) {
        var drawable = this.stage.createImage(name);
        if (xOffset && yOffset) {
            drawable.setPosition(add(this.__getX(u), xOffset), add(this.__getY(v), yOffset), dependencies);
        } else if (xOffset) {
            drawable.setPosition(add(this.__getX(u), xOffset), this.__getY(v), dependencies);
        } else if (yOffset) {
            drawable.setPosition(this.__getX(u), add(this.__getY(v), yOffset), dependencies);
        } else {
            drawable.setPosition(this.__getX(u), this.__getY(v), dependencies);
        }
        if (zIndex !== 3) drawable.setZIndex(zIndex);
        if (defaultTileHeight) {
            var scaleFactor = drawable.data.height / defaultTileHeight;
            drawable.scale = this.__calcBaseScale(drawable.getHeight()) * scaleFactor;
        } else {
            drawable.scale = this.__calcBaseScale(drawable.getHeight());
        }

        return drawable;
    };

    GridViewHelper.prototype.__calcBaseScale = function (drawableHeight) {
        var length = this.__edgeLength(this.device.height);
        return length / drawableHeight;
    };

    GridViewHelper.prototype.createRect = function (u, v, color) {
        var self = this;

        function getWidth(width, height) {
            return self.__edgeLength(height) - 1;
        }

        function getHeight(height) {
            return self.__edgeLength(height) - 1;
        }

        return this.stage.createRectangle(true).setPosition(this.__getX(u), this.__getY(v)).setWidth(getWidth)
            .setHeight(getHeight).setColor(color);
    };

    GridViewHelper.prototype.createRectBackground = function (u, v, color, zIndex) {
        return this.createRect(u, v, color).setZIndex(zIndex);
    };

    GridViewHelper.prototype.move = function (drawable, u, v, speed, callback, xOffset, yOffset, dependencies) {
        if (xOffset && yOffset)
            return drawable.moveTo(add(this.__getX(u), xOffset), add(this.__getY(v), yOffset), dependencies)
                .setDuration(speed).setCallback(callback);
        if (xOffset)
            return drawable.moveTo(add(this.__getX(u), xOffset), this.__getY(v), dependencies).setDuration(speed)
                .setCallback(callback);
        if (yOffset)
            return drawable.moveTo(this.__getX(u), add(this.__getY(v), yOffset), dependencies).setDuration(speed)
                .setCallback(callback);
        return drawable.moveTo(this.__getX(u), this.__getY(v), dependencies).setDuration(speed).setCallback(callback);
    };

    GridViewHelper.prototype.setPosition = function (drawable, u, v, dependencies) {
        return drawable.setPosition(this.__getX(u), this.__getY(v), dependencies);
    };

    GridViewHelper.prototype.__edgeLength = function (height) {
        if (this.bottomOffset) {
            return Height.get(this.yTiles)(height - (this.__getTopOffset(height) + this.bottomOffset(height)));
        } else {
            return Height.get(this.yTiles)(height - this.__getTopOffset(height));
        }
    };

    GridViewHelper.prototype.__xOffset = function (width, length) {
        return Math.floor(width / 2 - length * this.xTiles / 2 + length / 2);
    };

    GridViewHelper.prototype.__getX = function (u) {
        var self = this;
        return function (width, height) {
            var length = self.__edgeLength(height);
            var start = self.__xOffset(width, length);
            return start + u * length;
        };
    };

    GridViewHelper.prototype.__getY = function (v) {
        var self = this;
        return function (height) {
            var length = self.__edgeLength(height);
            return v * length + Math.floor(length / 2) + self.__getTopOffset(height);
        };
    };

    GridViewHelper.prototype.__getTopOffset = function (height) {
        if (this.topOffset)
            return this.topOffset(height);
        return 0;
    };

    GridViewHelper.prototype.getBaseScale = function () {
        return this.baseScale;
    };

    return GridViewHelper;
})(H5.Height, Math, H5.add);<|endoftext|>


<commit_before>/**
 * Tag Manager Setup Form component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';

/**
 * WordPress dependencies
 */
import { Fragment, useEffect, useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { STORE_NAME, FORM_SETUP, EDIT_SCOPE } from '../../datastore/constants';
import { STORE_NAME as MODULES_ANALYTICS } from '../../../analytics/datastore/constants';
import { STORE_NAME as CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants';
import { STORE_NAME as CORE_USER } from '../../../../googlesitekit/datastore/user/constants';
import { STORE_NAME as CORE_MODULES } from '../../../../googlesitekit/modules/datastore/constants';
import { isPermissionScopeError } from '../../../../googlesitekit/datastore/user/utils/is-permission-scope-error';
import {
	AccountSelect,
	AMPContainerSelect,
	WebContainerSelect,
} from '../common';
import StoreErrorNotice from '../../../../components/StoreErrorNotice';
import Button from '../../../../components/button';
import Link from '../../../../components/link';
import SetupFormInstructions from './SetupFormInstructions';
const { useSelect, useDispatch } = Data;

export default function SetupForm( { finishSetup, setIsNavigating } ) {
	const canSubmitChanges = useSelect( ( select ) => select( STORE_NAME ).canSubmitChanges() );
	const singleAnalyticsPropertyID = useSelect( ( select ) => select( STORE_NAME ).getSingleAnalyticsPropertyID() );
	const analyticsModuleActive = useSelect( ( select ) => select( CORE_MODULES ).isModuleActive( 'analytics' ) );
	const hasEditScope = useSelect( ( select ) => select( CORE_USER ).hasScope( EDIT_SCOPE ) );
	const analyticsModuleReauthURL = useSelect( ( select ) => select( MODULES_ANALYTICS ).getAdminReauthURL() );
	// Only select the initial autosubmit + submitMode once from form state which will already be set if a snapshot was restored.
	const initialAutoSubmit = useSelect( ( select ) => select( CORE_FORMS ).getValue( FORM_SETUP, 'autoSubmit' ), [] );
	const initialSubmitMode = useSelect( ( select ) => select( CORE_FORMS ).getValue( FORM_SETUP, 'submitMode' ), [] );

	const { setValues } = useDispatch( CORE_FORMS );
	const { activateModule } = useDispatch( CORE_MODULES );
	const { submitChanges, receiveError } = useDispatch( STORE_NAME );
	const dispatchAnalytics = useDispatch( MODULES_ANALYTICS );
	const submitForm = useCallback( async ( { submitMode } = {} ) => {
		// We'll use form state to persist the chosen submit choice
		// in order to preserve support for auto-submit.
		setValues( FORM_SETUP, { submitMode } );

		const { error } = await submitChanges();

		if ( isPermissionScopeError( error ) ) {
			setValues( FORM_SETUP, { autoSubmit: true } );
		} else if ( ! error ) {
			setValues( FORM_SETUP, { autoSubmit: false } );
			// If the property ID is set in GTM and Analytics is active,
			// we disable the snippet output via Analyics to prevent duplicate measurement.
			if ( singleAnalyticsPropertyID && analyticsModuleActive ) {
				dispatchAnalytics.setUseSnippet( false );
				const saveAnalyticsSettings = await dispatchAnalytics.saveSettings();
				if ( saveAnalyticsSettings.error ) {
					receiveError( saveAnalyticsSettings.error );
					return;
				}
			}
			// If submitting with Analytics setup, and Analytics is not active,
			// activate it, and navigate to its reauth/setup URL to proceed with its setup.
			if ( submitMode === 'with_analytics_setup' && ! analyticsModuleActive ) {
				setIsNavigating( true );
				const activateAnalytics = await activateModule( 'analytics' );
				if ( activateAnalytics.error ) {
					receiveError( activateAnalytics.error );
					return;
				}
				global.location.assign( analyticsModuleReauthURL );
				// Don't call finishSetup as this navigates to a different location.
				return;
			}
			finishSetup();
		}
	}, [ finishSetup, dispatchAnalytics, singleAnalyticsPropertyID, analyticsModuleActive, analyticsModuleReauthURL, receiveError ] );

	// If the user lands back on this component with autoSubmit and the edit scope,
	// resubmit the form.
	useEffect( () => {
		if ( initialAutoSubmit && hasEditScope ) {
			submitForm( { submitMode: initialSubmitMode } );
		}
	}, [ hasEditScope, initialAutoSubmit, submitForm, initialSubmitMode ] );

	const isSetupWithAnalytics = !! ( singleAnalyticsPropertyID && ! analyticsModuleActive );

	// Form submit behavior now varies based on which button is clicked.
	// Only the main buttons will trigger the form submit so here we only handle the default action.
	const onSubmit = useCallback( ( event ) => {
		event.preventDefault();
		const submitMode = isSetupWithAnalytics ? 'with_analytics_setup' : '';
		submitForm( { submitMode } );
	}, [ submitForm, isSetupWithAnalytics ] );
	// Click handler for secondary option when setting up with option to include Analytics.
	const onSetupWithoutAnalytics = useCallback( () => submitForm(), [ submitForm ] );

	return (
		<form
			className="googlesitekit-tagmanager-setup__form"
			onSubmit={ onSubmit }
		>
			<StoreErrorNotice storeName={ STORE_NAME } />
			<SetupFormInstructions />

				<AccountSelect />

				<WebContainerSelect />

				<AMPContainerSelect />

				{ isSetupWithAnalytics && (
					<Fragment>
						<Button disabled={ ! canSubmitChanges }>
							{ __( 'Continue to Analytics setup', 'google-site-kit' ) }
						</Button>
						{ /*
						This "link" below will be rendered as a <button> but should not
						trigger a form submit when clicked, hence the `type="button"`.
						*/ }
						<Link
							className="googlesitekit-setup-module__sub-action"
							type="button"
							onClick={ onSetupWithoutAnalytics }
							disabled={ ! canSubmitChanges }
							inherit
						>
							{ __( 'Complete setup without Analytics', 'google-site-kit' ) }
						</Link>
					</Fragment>
				) }
				{ ! isSetupWithAnalytics && (
					<Button disabled={ ! canSubmitChanges }>
						{ __( 'Confirm & Continue', 'google-site-kit' ) }
					</Button>
				) }

		</form>
	);
}

SetupForm.propTypes = {
	finishSetup: PropTypes.func,
	setIsNavigating: PropTypes.func,
};
<commit_msg>Update comment for clarity regarding GTM.<commit_after>/**
 * Tag Manager Setup Form component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';

/**
 * WordPress dependencies
 */
import { Fragment, useEffect, useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { STORE_NAME, FORM_SETUP, EDIT_SCOPE } from '../../datastore/constants';
import { STORE_NAME as MODULES_ANALYTICS } from '../../../analytics/datastore/constants';
import { STORE_NAME as CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants';
import { STORE_NAME as CORE_USER } from '../../../../googlesitekit/datastore/user/constants';
import { STORE_NAME as CORE_MODULES } from '../../../../googlesitekit/modules/datastore/constants';
import { isPermissionScopeError } from '../../../../googlesitekit/datastore/user/utils/is-permission-scope-error';
import {
	AccountSelect,
	AMPContainerSelect,
	WebContainerSelect,
} from '../common';
import StoreErrorNotice from '../../../../components/StoreErrorNotice';
import Button from '../../../../components/button';
import Link from '../../../../components/link';
import SetupFormInstructions from './SetupFormInstructions';
const { useSelect, useDispatch } = Data;

export default function SetupForm( { finishSetup, setIsNavigating } ) {
	const canSubmitChanges = useSelect( ( select ) => select( STORE_NAME ).canSubmitChanges() );
	const singleAnalyticsPropertyID = useSelect( ( select ) => select( STORE_NAME ).getSingleAnalyticsPropertyID() );
	const analyticsModuleActive = useSelect( ( select ) => select( CORE_MODULES ).isModuleActive( 'analytics' ) );
	const hasEditScope = useSelect( ( select ) => select( CORE_USER ).hasScope( EDIT_SCOPE ) );
	const analyticsModuleReauthURL = useSelect( ( select ) => select( MODULES_ANALYTICS ).getAdminReauthURL() );
	// Only select the initial autosubmit + submitMode once from form state which will already be set if a snapshot was restored.
	const initialAutoSubmit = useSelect( ( select ) => select( CORE_FORMS ).getValue( FORM_SETUP, 'autoSubmit' ), [] );
	const initialSubmitMode = useSelect( ( select ) => select( CORE_FORMS ).getValue( FORM_SETUP, 'submitMode' ), [] );

	const { setValues } = useDispatch( CORE_FORMS );
	const { activateModule } = useDispatch( CORE_MODULES );
	const { submitChanges, receiveError } = useDispatch( STORE_NAME );
	const dispatchAnalytics = useDispatch( MODULES_ANALYTICS );
	const submitForm = useCallback( async ( { submitMode } = {} ) => {
		// We'll use form state to persist the chosen submit choice
		// in order to preserve support for auto-submit.
		setValues( FORM_SETUP, { submitMode } );

		const { error } = await submitChanges();

		if ( isPermissionScopeError( error ) ) {
			setValues( FORM_SETUP, { autoSubmit: true } );
		} else if ( ! error ) {
			setValues( FORM_SETUP, { autoSubmit: false } );
			// If a singular property ID is set in the container(s) and Analytics is active,
			// we disable the snippet output via Analyics to prevent duplicate measurement.
			if ( singleAnalyticsPropertyID && analyticsModuleActive ) {
				dispatchAnalytics.setUseSnippet( false );
				const saveAnalyticsSettings = await dispatchAnalytics.saveSettings();
				if ( saveAnalyticsSettings.error ) {
					receiveError( saveAnalyticsSettings.error );
					return;
				}
			}
			// If submitting with Analytics setup, and Analytics is not active,
			// activate it, and navigate to its reauth/setup URL to proceed with its setup.
			if ( submitMode === 'with_analytics_setup' && ! analyticsModuleActive ) {
				setIsNavigating( true );
				const activateAnalytics = await activateModule( 'analytics' );
				if ( activateAnalytics.error ) {
					receiveError( activateAnalytics.error );
					return;
				}
				global.location.assign( analyticsModuleReauthURL );
				// Don't call finishSetup as this navigates to a different location.
				return;
			}
			finishSetup();
		}
	}, [ finishSetup, dispatchAnalytics, singleAnalyticsPropertyID, analyticsModuleActive, analyticsModuleReauthURL, receiveError ] );

	// If the user lands back on this component with autoSubmit and the edit scope,
	// resubmit the form.
	useEffect( () => {
		if ( initialAutoSubmit && hasEditScope ) {
			submitForm( { submitMode: initialSubmitMode } );
		}
	}, [ hasEditScope, initialAutoSubmit, submitForm, initialSubmitMode ] );

	const isSetupWithAnalytics = !! ( singleAnalyticsPropertyID && ! analyticsModuleActive );

	// Form submit behavior now varies based on which button is clicked.
	// Only the main buttons will trigger the form submit so here we only handle the default action.
	const onSubmit = useCallback( ( event ) => {
		event.preventDefault();
		const submitMode = isSetupWithAnalytics ? 'with_analytics_setup' : '';
		submitForm( { submitMode } );
	}, [ submitForm, isSetupWithAnalytics ] );
	// Click handler for secondary option when setting up with option to include Analytics.
	const onSetupWithoutAnalytics = useCallback( () => submitForm(), [ submitForm ] );

	return (
		<form
			className="googlesitekit-tagmanager-setup__form"
			onSubmit={ onSubmit }
		>
			<StoreErrorNotice storeName={ STORE_NAME } />
			<SetupFormInstructions />

				<AccountSelect />

				<WebContainerSelect />

				<AMPContainerSelect />

				{ isSetupWithAnalytics && (
					<Fragment>
						<Button disabled={ ! canSubmitChanges }>
							{ __( 'Continue to Analytics setup', 'google-site-kit' ) }
						</Button>
						{ /*
						This "link" below will be rendered as a <button> but should not
						trigger a form submit when clicked, hence the `type="button"`.
						*/ }
						<Link
							className="googlesitekit-setup-module__sub-action"
							type="button"
							onClick={ onSetupWithoutAnalytics }
							disabled={ ! canSubmitChanges }
							inherit
						>
							{ __( 'Complete setup without Analytics', 'google-site-kit' ) }
						</Link>
					</Fragment>
				) }
				{ ! isSetupWithAnalytics && (
					<Button disabled={ ! canSubmitChanges }>
						{ __( 'Confirm & Continue', 'google-site-kit' ) }
					</Button>
				) }

		</form>
	);
}

SetupForm.propTypes = {
	finishSetup: PropTypes.func,
	setIsNavigating: PropTypes.func,
};
<|endoftext|>