<commit_before>/**
 * Main Controller for the Search Manager.
 * Provides a search function with input a search query.
 */
(function () {

    var searchmodule = angular.module('pcApp.search.controllers', [
        'pcApp.search.services.search', 'pcApp.config', 'pcApp.references.services.reference'
    ]);

    var searchMainController = function ($scope, $location, searchclient, esFactory, API_CONF, Language, PolicyDomain, Individual, $routeParams, $timeout) {
        //Init Selectable number of items per page
        $scope.itemsPerPageChoices = [
            {
                id: 10,
                name: '10'
            }, {
                id: 20,
                name: '20'
            }, {
                id: 30,
                name: '30'
            }
        ];

        //Init Sort Options
        $scope.sortOptions = [
            {
                id: 'Relevance',
                name: 'Relevance'
            }, {
                id: 'Title',
                name: 'Title'
            }, {
                id: 'Date',
                name: 'Date Created'
            }, {
                id: 'CommentsDesc',
                name: 'Comments Desc.'
            }, {
                id: 'CommentsAsc',
                name: 'Comments Asc.'
            }
        ];

        var filters = {};
        var requestAggs = {};
        var facetsSelected = {};
        var aggregationData = {};
        $scope.facetCategories = [];

        var aggregations = {
            lang: {
                label: 'Language',
                field: ["language.id", "languageID"],
                order: 1,
                resolveLabel: function () {
                    var that = this;
                    Language.get({id: this.value}, function (response) {
                        that.label = response.title;
                    });
                },
                disable: true
            },
            policyDomains: {
                label: 'Policy Domains',
                field: ["policy_domains"],
                order: 1,
                resolveLabel: function () {
                    var that = this;
                    PolicyDomain.get({id: this.value}, function (response) {
                        that.label = response.title;
                    });
                }
            },
            location: {
                label: 'Location',
                field: ["spatial", "location"],
                order: 1,
                resolveLabel: function () {
                    var that = this;
                    Individual.get({id: this.value}, function (response) {
                        that.label = response.title;
                    });
                }
            },
            type: {
                label: 'Content type',
                field: ["_type"],
                order: 0,
                resolveLabel: function () {
                    switch (this.value) {
                        case "metric":
                            this.label = "Metrics";
                            break;
                        case "event":
                            this.label = "Events";
                            break;
                        case "indicator":
                            this.label = "Indicators";
                            break;
                        case "dataset":
                            this.label = "Datasets";
                            break;
                        case "fuzzymap":
                            this.label = "Causal Models";
                            break;
                        case "visualization":
                            this.label = "Visualizations";
                            break;
                        default:
                            this.label = this.value;
                            break;
                    }
                }
            },
            keyword: {
                label: 'Keyword',
                field: ["keywords"],
                size: 200,
                disable: true
            }
        };

        normalizeAggregationFilter = function () {
            var filters = [];
            angular.forEach(facetsSelected, function (values, facetCategory) {
                var terms = [];
                angular.forEach(values, function (val) {
                    var field = aggregations[facetCategory].field;
                    if (angular.isArray(field)) {
                        angular.forEach(field, function (fld) {
                            var term = {};
                            term[fld] = val;
                            terms.push({"term": term});
                        });
                    } else {
                        var term = {};
                        term[field] = bucket.value;
                        terms.push({"term": term});
                    }
                });
                if (terms.length > 0) {
                    filters.push({"bool": {"should": terms}});
                }
            });
            if (filters.length > 0)
                return {"bool": {"must": filters}};
            return {};
        };
        $scope.facetCategoryResults = function (name) {
            return 1;
            if ($scope.aggregationData[name])
                return $scope.aggregationData[name].length;
            return 0;
        };
        prepareAggregations = function () {
            if ($scope.facetCategories.length > 0)
                return;
            var request = {};
            angular.forEach(aggregations, function (aggregation, name) {
                if (aggregation.disable) return;
                $scope.facetCategories.push({
                    name: name,
                    label: aggregation.label,
                    order: aggregation.order,
                    results: 0,
                    buckets: {}
                });
                aggregations[name].index = $scope.facetCategories.length - 1;

                if (!angular.isArray(aggregation.field))
                    aggregations[name].field = [aggregation.field];

                var i = 0;
                angular.forEach(aggregation.field, function (fld) {
                    var obj = {};
                    obj.field = fld;
                    if (aggregation.size)
                        obj.size = aggregation.size;
                    var index = (aggregation.field.length > 1) ? name + '$' + (i++) : name;
                    request[index] = {
                        "terms": obj
                    };
                });
            });
            requestAggs = request;
        };

        normalizeAggregationResults = function (aggs) {
            //console.log(aggs);
            var buckets = {};
            angular.forEach(aggs, function (aggregation, key) {
                var resetCounters = true;
                if (_match = key.match(/(.*)\$(\d+)/i)) {
                    key = _match[1];
                    resetCounters = (_match[2] == 1);
                }
                if (!aggregations[key]) {
                    console.log(key + " was unexpected");
                    return;
                }
                var facetCategory = $scope.facetCategories[aggregations[key].index];
                if (resetCounters) {
                    facetCategory.results = 0;
                    facetCategory.buckets = {};
                }

                angular.forEach(aggregation.buckets, function (bucket) {
                    if (!facetCategory.buckets[bucket.key]) {
                        facetCategory.buckets[bucket.key] = {
                            value: bucket.key,
                            facetCategory: key,
                            label: '',
                            selected: false,
                            results: 0
                        };
                        if (angular.isFunction(aggregations[key].resolveLabel))
                            aggregations[key].resolveLabel.apply(facetCategory.buckets[bucket.key]); else
                            facetCategory.buckets[bucket.key].label = facetCategory.buckets[bucket.key].value;

                    }
                    if (facetsSelected[key] && (facetsSelected[key].indexOf(bucket.key) != -1 || facetsSelected[key].indexOf(""+bucket.key) != -1))
                        facetCategory.buckets[bucket.key].selected = true;
                    if (resetCounters)
                        facetCategory.buckets[bucket.key].results = 0;
                    facetCategory.buckets[bucket.key].results += bucket.doc_count;
                    facetCategory.results += bucket.doc_count;

                });
            });
            //console.log($scope.facetCategories);
        };

        $scope.facetChanged = function () {
            var bucket = this.bucket;
            if (!facetsSelected.hasOwnProperty(bucket.facetCategory))
                facetsSelected[bucket.facetCategory] = [];
            var idx = facetsSelected[bucket.facetCategory].indexOf(bucket.value);
            if (idx != -1 && !bucket.selected)
                facetsSelected[bucket.facetCategory].splice(idx, 1);
            if (idx == -1 && bucket.selected)
                facetsSelected[bucket.facetCategory].push(bucket.value);
            $location.search("_"+bucket.facetCategory, facetsSelected[bucket.facetCategory]);
            goSearch();
        };

        // Set Search Fire Event
        goSearch = function () {
            if ((typeof $scope.searchQuery == "undefined") || ($scope.searchQuery === "")) {
                searchText = "";
            } else {
                searchText = $scope.searchQuery;
            }
            //$scope.search(searchText);
        };

        //Define function that fires search when page changes
        $scope.pageChanged = function () {
            if (typeof $scope.totalItems === "undefined") {
                if ($routeParams.hasOwnProperty("page") && $scope.currentPage != $routeParams.page)
                    $scope.currentPage = $routeParams.page;
                return;
            }
            $location.search('page', $scope.currentPage);
            goSearch();
        };

        //Define function that fires search when Items Per Page selection box changes
        $scope.itemsPerPageChanged = function () {
            $scope.itemsperPage = $scope.selectedItemPerPage.id;
            $location.search('show', $scope.itemsperPage);
            goSearch();
        };

        //Define function that fires search when Sort By selection box changes
        $scope.sortItemsChanged = function () {
            $scope.sortByItem = $scope.selectedSortItem.id;
            $location.search('sort', $scope.sortByItem);
            goSearch();
        };

        //Define function that fires when Item Type is filtered (Metrics,Visualization, Events of Fuzzy Maps)
        $scope.filterSearchType = function (searchItemType) {
            $scope.searchItemType = searchItemType;
            switch (searchItemType) {
                case 'metric,visualization,event,fuzzymap':
                    $scope.searchItemTypeInfo = 'Search for metrics, visualizations, causal models, events, datasets, indicators';
                    $scope.searchItemTypeInfoDropDown = 'All';
                    break;
                case 'metric':
                    $scope.searchItemTypeInfo = 'Search for metrics';
                    $scope.searchItemTypeInfoDropDown = 'Metrics';
                    break;
                case 'visualization':
                    $scope.searchItemTypeInfo = 'Search for visualizations';
                    $scope.searchItemTypeInfoDropDown = 'Visualizations';
                    break;
                case 'event':
                    $scope.searchItemTypeInfo = 'Search for events';
                    $scope.searchItemTypeInfoDropDown = 'Events';
                    break;
                case 'fuzzymap':
                    $scope.searchItemTypeInfo = 'Search for causal models';
                    $scope.searchItemTypeInfoDropDown = 'Causal Models';
                    break;
                case 'dataset':
                    $scope.searchItemTypeInfo = 'Search for datasets';
                    $scope.searchItemTypeInfoDropDown = 'Datasets';
                    break;
                case 'indicator':
                    $scope.searchItemTypeInfo = 'Search for indicators';
                    $scope.searchItemTypeInfoDropDown = 'Indicators';
                    break;
                default:
                    $scope.searchItemTypeInfo = 'Search for metrics, visualizations, causal models, events, datasets, indicators';
            }
            //Perform search based on new Item Type
            //goSearch();
        };

        //Define Main search function
        $scope.search = function (searchQuery) {

            if (typeof searchQuery == 'undefined') {
                searchQuery = "";
            }
            $location.search('q', (searchQuery==="")?null:searchQuery);
            //Get current result item offset depending on current page
            itemOffset = ($scope.currentPage - 1) * $scope.itemsperPage;
            //Build Sort
            if ($scope.sortByItem == 'Relevance') {
                var sort = ["_score"];
            } else if ($scope.sortByItem == 'Title') {
                var sort = ["title.lower_case_sort"];
            } else if ($scope.sortByItem == 'CommentsDesc') {
                var sort = [{"commentsCount": {"order": "desc"}}];
            } else if ($scope.sortByItem == 'CommentsAsc') {
                var sort = [{"commentsCount": {"order": "asc"}}];
            } else {
                var sort = [
                    {"id": {"order": "desc"}}, "_score"
                ];
            }
            //Build query
            if (searchQuery != "") {
                var query = {
                    match: {
                        _all: searchQuery
                    }
                };
            } else {
                var query = {
                    match_all: {}
                };
            }
            var request = {
                index: API_CONF.ELASTIC_INDEX_NAME,
                type: $scope.searchItemType,
                body: {
                    size: $scope.itemsperPage,
                    from: itemOffset,
                    sort: sort,
                    query: query,
                    aggs: requestAggs
                }
            };
            var filters = normalizeAggregationFilter();
            if (!angular.equals({}, filters)) {
                //request.body.post_filter = filters;
                request.body.query = {
                    filtered: {
                        query: query,
                        filter: filters
                    }
                }
            }
            //Perform search through client and get a search Promise
            searchclient.search(request).then(function (resp) {
                //If search is successfull return results in searchResults objects
                $scope.searchResults = resp.hits.hits;
                $scope.searchResultsCount = resp.hits.total;
                $scope.totalItems = $scope.searchResultsCount;
                normalizeAggregationResults(resp.aggregations);
            }, function (err) {
                console.trace(err.message);
            });

        };

        $scope.init = function () {
            //Set Pagination defaults
            //Default value for how many pages to show in the page navigation control
            $scope.paginationSize = 5;
            //Default values for how many items per page
            $scope.itemsperPage = 10;
            //Default sort
            $scope.sortByItem = 'Relevance';
            //Default current page
            $scope.currentPage = $routeParams.page || 1;

            prepareAggregations();

            var type = $routeParams.type;
            if (type) {
                $scope.filterSearchType(type);
            } else {
                //Default search item type
                $scope.searchItemType = 'metric,visualization,event,fuzzymap,dataset,indicator';
                $scope.searchItemTypeInfo = 'Search for metrics, visualizations, causal models, events, datasets, indicators';
                $scope.searchItemTypeInfoDropDown = 'All';
            }

            //Default search query
            $scope.searchQuery = $routeParams.q || "";

            var sortBy = $routeParams.sort;
            angular.forEach($scope.sortOptions, function(option) {
                if (option.id === sortBy){
                    $scope.sortByItem = sortBy;
                    $scope.selectedSortItem = option;
                }
            });

            var showPerPage = $routeParams.show-0;
            angular.forEach($scope.itemsPerPageChoices, function(option) {
                if (option.id === showPerPage){
                    $scope.itemsperPage = showPerPage;
                    $scope.selectedItemPerPage = option;
                }
            });

            facetsSelected = {};
            angular.forEach(aggregations, function (aggregation, name) {
                var queryParam = "_"+name;
                if ($routeParams.hasOwnProperty(queryParam)) {
                    if (angular.isArray($routeParams[queryParam])) {
                        facetsSelected[name] = $routeParams[queryParam];
                    } else {
                        facetsSelected[name] = [];
                        facetsSelected[name].push($routeParams[queryParam]);
                    }
                }
            });

            //Search for first time
            $scope.search($scope.searchQuery);
        };
        $scope.$on('$routeUpdate', function(){
            $scope.init();
        });
        // runs once per controller instantiation
        $scope.init();
    };

    searchmodule.controller("searchMainController", searchMainController);

}());
<commit_msg>Fix persistent query facets bug<commit_after>/**
 * Main Controller for the Search Manager.
 * Provides a search function with input a search query.
 */
(function () {

    var searchmodule = angular.module('pcApp.search.controllers', [
        'pcApp.search.services.search', 'pcApp.config', 'pcApp.references.services.reference'
    ]);

    var searchMainController = function ($scope, $location, searchclient, esFactory, API_CONF, Language, PolicyDomain, Individual, $routeParams, $timeout) {
        //Init Selectable number of items per page
        $scope.itemsPerPageChoices = [
            {
                id: 10,
                name: '10'
            }, {
                id: 20,
                name: '20'
            }, {
                id: 30,
                name: '30'
            }
        ];

        //Init Sort Options
        $scope.sortOptions = [
            {
                id: 'Relevance',
                name: 'Relevance'
            }, {
                id: 'Title',
                name: 'Title'
            }, {
                id: 'Date',
                name: 'Date Created'
            }, {
                id: 'CommentsDesc',
                name: 'Comments Desc.'
            }, {
                id: 'CommentsAsc',
                name: 'Comments Asc.'
            }
        ];

        var filters = {};
        var requestAggs = {};
        var facetsSelected = {};
        var aggregationData = {};
        $scope.facetCategories = [];

        var aggregations = {
            lang: {
                label: 'Language',
                field: ["language.id", "languageID"],
                order: 1,
                resolveLabel: function () {
                    var that = this;
                    Language.get({id: this.value}, function (response) {
                        that.label = response.title;
                    });
                },
                disable: true
            },
            policyDomains: {
                label: 'Policy Domains',
                field: ["policy_domains"],
                order: 1,
                resolveLabel: function () {
                    var that = this;
                    PolicyDomain.get({id: this.value}, function (response) {
                        that.label = response.title;
                    });
                }
            },
            location: {
                label: 'Location',
                field: ["spatial", "location"],
                order: 1,
                resolveLabel: function () {
                    var that = this;
                    Individual.get({id: this.value}, function (response) {
                        that.label = response.title;
                    });
                }
            },
            type: {
                label: 'Content type',
                field: ["_type"],
                order: 0,
                resolveLabel: function () {
                    switch (this.value) {
                        case "metric":
                            this.label = "Metrics";
                            break;
                        case "event":
                            this.label = "Events";
                            break;
                        case "indicator":
                            this.label = "Indicators";
                            break;
                        case "dataset":
                            this.label = "Datasets";
                            break;
                        case "fuzzymap":
                            this.label = "Causal Models";
                            break;
                        case "visualization":
                            this.label = "Visualizations";
                            break;
                        default:
                            this.label = this.value;
                            break;
                    }
                }
            },
            keyword: {
                label: 'Keyword',
                field: ["keywords"],
                size: 200,
                disable: true
            }
        };

        normalizeAggregationFilter = function () {
            var filters = [];
            angular.forEach(facetsSelected, function (values, facetCategory) {
                var terms = [];
                angular.forEach(values, function (val) {
                    var field = aggregations[facetCategory].field;
                    if (angular.isArray(field)) {
                        angular.forEach(field, function (fld) {
                            var term = {};
                            term[fld] = val;
                            terms.push({"term": term});
                        });
                    } else {
                        var term = {};
                        term[field] = bucket.value;
                        terms.push({"term": term});
                    }
                });
                if (terms.length > 0) {
                    filters.push({"bool": {"should": terms}});
                }
            });
            if (filters.length > 0)
                return {"bool": {"must": filters}};
            return {};
        };
        $scope.facetCategoryResults = function (name) {
            return 1;
            if ($scope.aggregationData[name])
                return $scope.aggregationData[name].length;
            return 0;
        };
        prepareAggregations = function () {
            if ($scope.facetCategories.length > 0)
                return;
            var request = {};
            angular.forEach(aggregations, function (aggregation, name) {
                if (aggregation.disable) return;
                $scope.facetCategories.push({
                    name: name,
                    label: aggregation.label,
                    order: aggregation.order,
                    results: 0,
                    buckets: {}
                });
                aggregations[name].index = $scope.facetCategories.length - 1;

                if (!angular.isArray(aggregation.field))
                    aggregations[name].field = [aggregation.field];

                var i = 0;
                angular.forEach(aggregation.field, function (fld) {
                    var obj = {};
                    obj.field = fld;
                    if (aggregation.size)
                        obj.size = aggregation.size;
                    var index = (aggregation.field.length > 1) ? name + '$' + (i++) : name;
                    request[index] = {
                        "terms": obj
                    };
                });
            });
            requestAggs = request;
        };

        normalizeAggregationResults = function (aggs) {
            //console.log(aggs);
            var buckets = {};
            angular.forEach(aggs, function (aggregation, key) {
                var resetCounters = true;
                if (_match = key.match(/(.*)\$(\d+)/i)) {
                    key = _match[1];
                    resetCounters = (_match[2] == 1);
                }
                if (!aggregations[key]) {
                    console.log(key + " was unexpected");
                    return;
                }
                var facetCategory = $scope.facetCategories[aggregations[key].index];
                if (resetCounters) {
                    facetCategory.results = 0;
                    facetCategory.buckets = {};
                }

                angular.forEach(aggregation.buckets, function (bucket) {
                    if (!facetCategory.buckets[bucket.key]) {
                        facetCategory.buckets[bucket.key] = {
                            value: bucket.key,
                            facetCategory: key,
                            label: '',
                            selected: false,
                            results: 0
                        };
                        if (angular.isFunction(aggregations[key].resolveLabel))
                            aggregations[key].resolveLabel.apply(facetCategory.buckets[bucket.key]); else
                            facetCategory.buckets[bucket.key].label = facetCategory.buckets[bucket.key].value;

                    }
                    if (facetsSelected[key] && (facetsSelected[key].indexOf(bucket.key) != -1 || facetsSelected[key].indexOf(""+bucket.key) != -1))
                        facetCategory.buckets[bucket.key].selected = true;
                    if (resetCounters)
                        facetCategory.buckets[bucket.key].results = 0;
                    facetCategory.buckets[bucket.key].results += bucket.doc_count;
                    facetCategory.results += bucket.doc_count;

                });
            });
            //console.log($scope.facetCategories);
        };

        $scope.facetChanged = function () {
            var bucket = this.bucket;
            if (!facetsSelected.hasOwnProperty(bucket.facetCategory))
                facetsSelected[bucket.facetCategory] = [];
            var idx = facetsSelected[bucket.facetCategory].indexOf(bucket.value);
            if (idx == -1)
                idx = facetsSelected[bucket.facetCategory].indexOf(""+bucket.value);
            if (idx != -1 && !bucket.selected)
                facetsSelected[bucket.facetCategory].splice(idx, 1);
            if (idx == -1 && bucket.selected)
                facetsSelected[bucket.facetCategory].push(bucket.value);
            $location.search("_"+bucket.facetCategory, facetsSelected[bucket.facetCategory]);
            goSearch();
        };

        // Set Search Fire Event
        goSearch = function () {
            if ((typeof $scope.searchQuery == "undefined") || ($scope.searchQuery === "")) {
                searchText = "";
            } else {
                searchText = $scope.searchQuery;
            }
            //$scope.search(searchText);
        };

        //Define function that fires search when page changes
        $scope.pageChanged = function () {
            if (typeof $scope.totalItems === "undefined") {
                if ($routeParams.hasOwnProperty("page") && $scope.currentPage != $routeParams.page)
                    $scope.currentPage = $routeParams.page;
                return;
            }
            $location.search('page', $scope.currentPage);
            goSearch();
        };

        //Define function that fires search when Items Per Page selection box changes
        $scope.itemsPerPageChanged = function () {
            $scope.itemsperPage = $scope.selectedItemPerPage.id;
            $location.search('show', $scope.itemsperPage);
            goSearch();
        };

        //Define function that fires search when Sort By selection box changes
        $scope.sortItemsChanged = function () {
            $scope.sortByItem = $scope.selectedSortItem.id;
            $location.search('sort', $scope.sortByItem);
            goSearch();
        };

        //Define function that fires when Item Type is filtered (Metrics,Visualization, Events of Fuzzy Maps)
        $scope.filterSearchType = function (searchItemType) {
            $scope.searchItemType = searchItemType;
            switch (searchItemType) {
                case 'metric,visualization,event,fuzzymap':
                    $scope.searchItemTypeInfo = 'Search for metrics, visualizations, causal models, events, datasets, indicators';
                    $scope.searchItemTypeInfoDropDown = 'All';
                    break;
                case 'metric':
                    $scope.searchItemTypeInfo = 'Search for metrics';
                    $scope.searchItemTypeInfoDropDown = 'Metrics';
                    break;
                case 'visualization':
                    $scope.searchItemTypeInfo = 'Search for visualizations';
                    $scope.searchItemTypeInfoDropDown = 'Visualizations';
                    break;
                case 'event':
                    $scope.searchItemTypeInfo = 'Search for events';
                    $scope.searchItemTypeInfoDropDown = 'Events';
                    break;
                case 'fuzzymap':
                    $scope.searchItemTypeInfo = 'Search for causal models';
                    $scope.searchItemTypeInfoDropDown = 'Causal Models';
                    break;
                case 'dataset':
                    $scope.searchItemTypeInfo = 'Search for datasets';
                    $scope.searchItemTypeInfoDropDown = 'Datasets';
                    break;
                case 'indicator':
                    $scope.searchItemTypeInfo = 'Search for indicators';
                    $scope.searchItemTypeInfoDropDown = 'Indicators';
                    break;
                default:
                    $scope.searchItemTypeInfo = 'Search for metrics, visualizations, causal models, events, datasets, indicators';
            }
            //Perform search based on new Item Type
            //goSearch();
        };

        //Define Main search function
        $scope.search = function (searchQuery) {

            if (typeof searchQuery == 'undefined') {
                searchQuery = "";
            }
            $location.search('q', (searchQuery==="")?null:searchQuery);
            //Get current result item offset depending on current page
            itemOffset = ($scope.currentPage - 1) * $scope.itemsperPage;
            //Build Sort
            if ($scope.sortByItem == 'Relevance') {
                var sort = ["_score"];
            } else if ($scope.sortByItem == 'Title') {
                var sort = ["title.lower_case_sort"];
            } else if ($scope.sortByItem == 'CommentsDesc') {
                var sort = [{"commentsCount": {"order": "desc"}}];
            } else if ($scope.sortByItem == 'CommentsAsc') {
                var sort = [{"commentsCount": {"order": "asc"}}];
            } else {
                var sort = [
                    {"id": {"order": "desc"}}, "_score"
                ];
            }
            //Build query
            if (searchQuery != "") {
                var query = {
                    match: {
                        _all: searchQuery
                    }
                };
            } else {
                var query = {
                    match_all: {}
                };
            }
            var request = {
                index: API_CONF.ELASTIC_INDEX_NAME,
                type: $scope.searchItemType,
                body: {
                    size: $scope.itemsperPage,
                    from: itemOffset,
                    sort: sort,
                    query: query,
                    aggs: requestAggs
                }
            };
            var filters = normalizeAggregationFilter();
            if (!angular.equals({}, filters)) {
                //request.body.post_filter = filters;
                request.body.query = {
                    filtered: {
                        query: query,
                        filter: filters
                    }
                }
            }
            //Perform search through client and get a search Promise
            searchclient.search(request).then(function (resp) {
                //If search is successfull return results in searchResults objects
                $scope.searchResults = resp.hits.hits;
                $scope.searchResultsCount = resp.hits.total;
                $scope.totalItems = $scope.searchResultsCount;
                normalizeAggregationResults(resp.aggregations);
            }, function (err) {
                console.trace(err.message);
            });

        };

        $scope.init = function () {
            //Set Pagination defaults
            //Default value for how many pages to show in the page navigation control
            $scope.paginationSize = 5;
            //Default values for how many items per page
            $scope.itemsperPage = 10;
            //Default sort
            $scope.sortByItem = 'Relevance';
            //Default current page
            $scope.currentPage = $routeParams.page || 1;

            prepareAggregations();

            var type = $routeParams.type;
            if (type) {
                $scope.filterSearchType(type);
            } else {
                //Default search item type
                $scope.searchItemType = 'metric,visualization,event,fuzzymap,dataset,indicator';
                $scope.searchItemTypeInfo = 'Search for metrics, visualizations, causal models, events, datasets, indicators';
                $scope.searchItemTypeInfoDropDown = 'All';
            }

            //Default search query
            $scope.searchQuery = $routeParams.q || "";

            var sortBy = $routeParams.sort;
            angular.forEach($scope.sortOptions, function(option) {
                if (option.id === sortBy){
                    $scope.sortByItem = sortBy;
                    $scope.selectedSortItem = option;
                }
            });

            var showPerPage = $routeParams.show-0;
            angular.forEach($scope.itemsPerPageChoices, function(option) {
                if (option.id === showPerPage){
                    $scope.itemsperPage = showPerPage;
                    $scope.selectedItemPerPage = option;
                }
            });

            facetsSelected = {};
            angular.forEach(aggregations, function (aggregation, name) {
                var queryParam = "_"+name;
                if ($routeParams.hasOwnProperty(queryParam)) {
                    if (angular.isArray($routeParams[queryParam])) {
                        facetsSelected[name] = $routeParams[queryParam];
                    } else {
                        facetsSelected[name] = [];
                        facetsSelected[name].push($routeParams[queryParam]);
                    }
                }
            });

            //Search for first time
            $scope.search($scope.searchQuery);
        };
        $scope.$on('$routeUpdate', function(){
            $scope.init();
        });
        // runs once per controller instantiation
        $scope.init();
    };

    searchmodule.controller("searchMainController", searchMainController);

}());
<|endoftext|>


<commit_before>import React from 'react'
import { Link } from 'react-router-dom'
import { linkForResource } from '../../routes'
import { toHumanizedAge } from '../../converters'

let kinds = {
  Deployment: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Replicas:', (status.availableReplicas ? status.availableReplicas + ' available, ': '') +
          (status.readyReplicas ? status.readyReplicas + ' ready, ':'') +
          (status.updatedReplicas ? status.updatedReplicas + ' updated, ':'') +
          (status.unavailableReplicas ? status.unavailableReplicas + ' unavailable, ':'') +
          (status.replicas || 0) + ' desired'],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Update Strategy:', spec.strategy.type],
      ]
    },
  },
  DaemonSet: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Instances',`${status.desiredNumberScheduled || 0} desired, ${status.currentNumberScheduled} scheduled,
          ${status.numberAvailable} available, ${status.numberReady} ready,
          ${status.updatedNumberScheduled} updated, ${status.numberMisscheduled} misscheduled`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Selector', `${spec.selector.matchLabels ? Object.entries(spec.selector.matchLabels).map(e=>e[0]+'='+e[1]).join(', '): ''}`],
        ['Update Strategy', spec.updateStrategy.type],
      ]
    },
  },
  StatefulSet: {
    getData: ({status, spec, metadata}) => {
      return [
        ['Replicas',`${status.replicas || 0} current, ${spec.replicas || 0} desired`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  ReplicaSet: {
    getData: ({status, spec, metadata}) => {
      return [
        ['Replicas',`${status.availableReplicas} available, ${status.readyReplicas} ready, ${status.fullyLabeledReplicas} labeled, ${status.replicas} total`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Label Selector', spec.selector.matchLabels],
      ]
    },
  },
  ReplicationController: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Replicas',`${status.availableReplicas} available, ${status.readyReplicas} ready,  ${status.fullyLabeledReplicas} labeled, ${status.replicas} total`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  CronJob: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Schedule:', spec.schedule],
        ['Concurrency Policy:', spec.concurrencyPolicy],
        ['Suspend', spec.suspend],
        // ['Starting Deadline Seconds:', spec.startingDeadlineSeconds || '<unset>'],
        ['Selector:', (spec.selector && spec.selector.matchLabels) || '<none>'],
        ['Parallelism:', spec.parallelism || '<unset>'],
        ['Last Schedule Time:', status.lastScheduleTime],
        //Completions:			<unset> // => need to get details of owned Jobs for this...
      ]
    },
  },
  Job: {
    getData: ({status, spec, metadata}) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Selector:', (spec.selector && spec.selector.matchLabels) || '<none>'],
        ['Parallelism:', spec.parallelism],
        ['Completions:', spec.completions],
        ['Start Time:', status.startTime],
      ]
    }
  },
  Pod: {
    getData: ({status, spec, metadata }) => {
      return [
      ]
    },
  },
  Service: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Type:', spec.type],
        ['IP:', spec.clusterIP],
        ['Port:', spec.ports[0].port],
        ['NodePort:', spec.ports[0].nodePort || 'n/a'],
        ['Session Affinity:', spec.sessionAffinity],
      ]
    },
  },
  Endpoints: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  Ingress: {
    getData: ({status, spec, metadata }) => {
      let lbs = []
      if (status.loadBalancer.ingress && status.loadBalancer.ingress.length) {
        for (let ig of status.loadBalancer.ingress) {
          if (ig.hostname) {
            lbs.push(ig.hostname)
          } else if (ig.ip) {
            lbs.push(ig.ip)
          }
        }
      }
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Rules:', spec.rules],
        ['Load Balancers:', lbs.length > 0 ? lbs.join(', ') : '< none >'],
      ]
    },
  },
  ConfigMap: {
    getData: (resource) => {
      return [
        ['Created:', `${resource.metadata.creationTimestamp} (${toHumanizedAge(resource.metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  Secret: {
    getData: (resource) => {
      return [
        ['Created:', `${resource.metadata.creationTimestamp} (${toHumanizedAge(resource.metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  PersistentVolume: {
    getData: ({status, spec, metadata }) => {
      return [
          ['Status:', status.phase],
          ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
          ['Claim:', spec.claimRef ?
            <Link to={linkForResource(`PersistentVolumeClaim/${spec.claimRef.namespace}/${spec.claimRef.name}`)}>
              {spec.claimRef.namespace + '/' + spec.claimRef.name}
            </Link>: null
          ],
          ['Reclaim Policy:', spec.persistentVolumeReclaimPolicy],
          ['Access Modes:', `${spec.accessModes.join(', ')}`],
          ['Capacity:', spec.capacity.storage],
        ]
    },
  },
  PersistentVolumeClaim: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Status:', status.phase],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Volume:', spec.volumeName],
        ['Capacity:', `${status.phase === 'Bound' ? status.capacity.storage : 0} bound / ${spec.resources.requests.storage} requested`],
        ['Access Modes:', `${spec.accessModes.join(', ')}`],
      ]
    },
  },
  Node: {
    getData: (resource) => {
      let data = []
      for (let addr of resource.status.addresses) {
        data.push([addr.type, addr.address])
      }
      data.push(["CPU", resource.status.allocatable.cpu])
      data.push(["Mem", resource.status.allocatable.memory])
      data.push(["OS", resource.status.nodeInfo.operatingSystem])
      data.push(["OS Image", resource.status.nodeInfo.osImage])
      data.push(["Kernel Version", resource.status.nodeInfo.kernelVersion])
      data.push(["Architecture", resource.status.nodeInfo.architecture])
      data.push(["Container Runtime", resource.status.nodeInfo.containerRuntimeVersion])
      data.push(["KubeProxy Version", resource.status.nodeInfo.kubeProxyVersion])
      data.push(["Kubelet Version", resource.status.nodeInfo.kubeletVersion])
      data.push(["Boot ID", resource.status.nodeInfo.bootID])
      data.push(["Machine ID", resource.status.nodeInfo.machineID])
      data.push(["System UUID", resource.status.nodeInfo.systemUUID])
      return data
    },
  },
  ServiceAccount: {
    getData: (resource) => {
      return [
        ['Created:', `${resource.metadata.creationTimestamp} (${toHumanizedAge(resource.metadata.creationTimestamp)} ago)`],
        ['Secrets:', `${resource.secrets ? resource.secrets.map((s)=> s.name).join(', ') : ''}`],
      ]
    },
  },
  ComponentStatus: {
  },
  Namespace: {
  },
  ResourceQuota: {
  },
  Role: {
  },
  RoleBinding: {
  },
  ClusterRole: {
  },
  ClusterRoleBinding: {
  },
  NetworkPolicy: {
  },
}

export default kinds<commit_msg>add details to statefulsets<commit_after>import React from 'react'
import { Link } from 'react-router-dom'
import { linkForResource } from '../../routes'
import { toHumanizedAge } from '../../converters'

let kinds = {
  Deployment: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Replicas:', (status.availableReplicas ? status.availableReplicas + ' available, ': '') +
          (status.readyReplicas ? status.readyReplicas + ' ready, ':'') +
          (status.updatedReplicas ? status.updatedReplicas + ' updated, ':'') +
          (status.unavailableReplicas ? status.unavailableReplicas + ' unavailable, ':'') +
          (status.replicas || 0) + ' desired'],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Update Strategy:', spec.strategy.type],
      ]
    },
  },
  DaemonSet: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Instances',`${status.desiredNumberScheduled || 0} desired, ${status.currentNumberScheduled} scheduled,
          ${status.numberAvailable} available, ${status.numberReady} ready,
          ${status.updatedNumberScheduled} updated, ${status.numberMisscheduled} misscheduled`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Selector', `${spec.selector.matchLabels ? Object.entries(spec.selector.matchLabels).map(e=>e[0]+'='+e[1]).join(', '): ''}`],
        ['Update Strategy', spec.updateStrategy.type],
      ]
    },
  },
  StatefulSet: {
    getData: ({status, spec, metadata}) => {
      return [
        ['Selector', `${spec.selector.matchLabels ? Object.entries(spec.selector.matchLabels).map(e=>e[0]+'='+e[1]).join(', '): ''}`],
        ['Replicas',`${status.replicas || 0} current, ${spec.replicas || 0} desired`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Update Strategy', spec.updateStrategy.type],
      ]
    },
  },
  ReplicaSet: {
    getData: ({status, spec, metadata}) => {
      return [
        ['Replicas',`${status.availableReplicas} available, ${status.readyReplicas} ready, ${status.fullyLabeledReplicas} labeled, ${status.replicas} total`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Label Selector', spec.selector.matchLabels],
      ]
    },
  },
  ReplicationController: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Replicas',`${status.availableReplicas} available, ${status.readyReplicas} ready,  ${status.fullyLabeledReplicas} labeled, ${status.replicas} total`],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  CronJob: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Schedule:', spec.schedule],
        ['Concurrency Policy:', spec.concurrencyPolicy],
        ['Suspend', spec.suspend],
        // ['Starting Deadline Seconds:', spec.startingDeadlineSeconds || '<unset>'],
        ['Selector:', (spec.selector && spec.selector.matchLabels) || '<none>'],
        ['Parallelism:', spec.parallelism || '<unset>'],
        ['Last Schedule Time:', status.lastScheduleTime],
        //Completions:			<unset> // => need to get details of owned Jobs for this...
      ]
    },
  },
  Job: {
    getData: ({status, spec, metadata}) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Selector:', (spec.selector && spec.selector.matchLabels) || '<none>'],
        ['Parallelism:', spec.parallelism],
        ['Completions:', spec.completions],
        ['Start Time:', status.startTime],
      ]
    }
  },
  Pod: {
    getData: ({status, spec, metadata }) => {
      return [
      ]
    },
  },
  Service: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Type:', spec.type],
        ['IP:', spec.clusterIP],
        ['Port:', spec.ports[0].port],
        ['NodePort:', spec.ports[0].nodePort || 'n/a'],
        ['Session Affinity:', spec.sessionAffinity],
      ]
    },
  },
  Endpoints: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  Ingress: {
    getData: ({status, spec, metadata }) => {
      let lbs = []
      if (status.loadBalancer.ingress && status.loadBalancer.ingress.length) {
        for (let ig of status.loadBalancer.ingress) {
          if (ig.hostname) {
            lbs.push(ig.hostname)
          } else if (ig.ip) {
            lbs.push(ig.ip)
          }
        }
      }
      return [
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Rules:', spec.rules],
        ['Load Balancers:', lbs.length > 0 ? lbs.join(', ') : '< none >'],
      ]
    },
  },
  ConfigMap: {
    getData: (resource) => {
      return [
        ['Created:', `${resource.metadata.creationTimestamp} (${toHumanizedAge(resource.metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  Secret: {
    getData: (resource) => {
      return [
        ['Created:', `${resource.metadata.creationTimestamp} (${toHumanizedAge(resource.metadata.creationTimestamp)} ago)`],
      ]
    },
  },
  PersistentVolume: {
    getData: ({status, spec, metadata }) => {
      return [
          ['Status:', status.phase],
          ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
          ['Claim:', spec.claimRef ?
            <Link to={linkForResource(`PersistentVolumeClaim/${spec.claimRef.namespace}/${spec.claimRef.name}`)}>
              {spec.claimRef.namespace + '/' + spec.claimRef.name}
            </Link>: null
          ],
          ['Reclaim Policy:', spec.persistentVolumeReclaimPolicy],
          ['Access Modes:', `${spec.accessModes.join(', ')}`],
          ['Capacity:', spec.capacity.storage],
        ]
    },
  },
  PersistentVolumeClaim: {
    getData: ({status, spec, metadata }) => {
      return [
        ['Status:', status.phase],
        ['Created:', `${metadata.creationTimestamp} (${toHumanizedAge(metadata.creationTimestamp)} ago)`],
        ['Volume:', spec.volumeName],
        ['Capacity:', `${status.phase === 'Bound' ? status.capacity.storage : 0} bound / ${spec.resources.requests.storage} requested`],
        ['Access Modes:', `${spec.accessModes.join(', ')}`],
      ]
    },
  },
  Node: {
    getData: (resource) => {
      let data = []
      for (let addr of resource.status.addresses) {
        data.push([addr.type, addr.address])
      }
      data.push(["CPU", resource.status.allocatable.cpu])
      data.push(["Mem", resource.status.allocatable.memory])
      data.push(["OS", resource.status.nodeInfo.operatingSystem])
      data.push(["OS Image", resource.status.nodeInfo.osImage])
      data.push(["Kernel Version", resource.status.nodeInfo.kernelVersion])
      data.push(["Architecture", resource.status.nodeInfo.architecture])
      data.push(["Container Runtime", resource.status.nodeInfo.containerRuntimeVersion])
      data.push(["KubeProxy Version", resource.status.nodeInfo.kubeProxyVersion])
      data.push(["Kubelet Version", resource.status.nodeInfo.kubeletVersion])
      data.push(["Boot ID", resource.status.nodeInfo.bootID])
      data.push(["Machine ID", resource.status.nodeInfo.machineID])
      data.push(["System UUID", resource.status.nodeInfo.systemUUID])
      return data
    },
  },
  ServiceAccount: {
    getData: (resource) => {
      return [
        ['Created:', `${resource.metadata.creationTimestamp} (${toHumanizedAge(resource.metadata.creationTimestamp)} ago)`],
        ['Secrets:', `${resource.secrets ? resource.secrets.map((s)=> s.name).join(', ') : ''}`],
      ]
    },
  },
  ComponentStatus: {
  },
  Namespace: {
  },
  ResourceQuota: {
  },
  Role: {
  },
  RoleBinding: {
  },
  ClusterRole: {
  },
  ClusterRoleBinding: {
  },
  NetworkPolicy: {
  },
}

export default kinds<|endoftext|>


<commit_before>module.exports = function(req, res, next) {
	if (req.session.user) {
		return next();
	}
	return res.forbidden('You are not permitted to perform this action.');
};
<commit_msg>redirect to login if not logged in<commit_after>module.exports = function(req, res, next) {
	if (req.session.user) {
		return next();
	}
	return res.redirect('/login', 403);
};
<|endoftext|>


<commit_before>function()
{
  window.open(
    'http://www.emendapp.com?url='+location.href+'&v=2&original='+
      encodeURIComponent(
        window.getSelection ? window.getSelection() :
        document.getSelection ? document.getSelection() :
        document.selection ? document.selection.createRange().text :
        ''
      ),
    '_blank');
}
<commit_msg>updated bookmarklet version<commit_after>function()
{
  window.open(
    'http://www.emendapp.com?url='+location.href+'&v=3&original='+
      encodeURIComponent(
        window.getSelection ? window.getSelection() :
        document.getSelection ? document.getSelection() :
        document.selection ? document.selection.createRange().text :
        ''
      ),
    '_blank');
}
<|endoftext|>


<commit_before>google.load("visualization", "1", {packages: ["corechart"]});
google.setOnLoadCallback(drawSeriesChart);

function drawSeriesChart() {
    var nodes = document.getElementsByClassName("wp-bubble-graph");
    var len = nodes.length;
    var charts = {};
    var values = {};
    var selectX = {};
    var selectY = {};
    var selectColor = {};
    var graphDivs = {};
    counter = 0;

    for (var i = 0; i < len; i++) {
        // Extract the node and all its properties
        var masterDiv = nodes[i];
        var id = nodes[i].getAttribute("id");
        if (id === null) {
            counter++;
            id = "bubble-graph-" + counter;
            nodes[i].id = id;
        }
        var channelname = nodes[i].getAttribute("data-channel");
        var xColumn = nodes[i].getAttribute("data-x-column");
        var yColumn = nodes[i].getAttribute("data-y-column");
        var colorColumn = nodes[i].getAttribute("data-color-column");
        var readOnly = "true";

        // Prepare html
        var tableDiv = document.createElement("div");
        tableDiv.style.display = "table";
        tableDiv.style.height = "100%";
        tableDiv.style.width = "100%";
        masterDiv.appendChild(tableDiv);

        var columnsDiv = document.createElement("div");
        columnsDiv.style.display = "table-row";
        tableDiv.appendChild(columnsDiv);
        var columnsP = document.createElement("p");
        columnsDiv.appendChild(columnsP);
        columnsP.appendChild(document.createTextNode("X: "));
        selectX[i] = document.createElement("select");
        selectX[i].id = id + "-select-x";
        columnsP.appendChild(selectX[i]);
        columnsP.appendChild(document.createTextNode(" Y: "));
        selectY[i] = document.createElement("select");
        selectY[i].id = id + "-select-y";
        columnsP.appendChild(selectY[i]);
        columnsP.appendChild(document.createTextNode(" Color: "));
        selectColor[i] = document.createElement("select");
        selectColor[i].id = id + "-select-color";
        columnsP.appendChild(selectColor[i]);

        var graphDiv = document.createElement("div");
        graphDiv.style.display = "table-row";
        graphDiv.style.height = "100%";
        tableDiv.appendChild(graphDiv);
        graphDivs[i] = graphDiv;

        // Helper functions
        var populateSelect = function (select, list) {
            var currentSelection = null;
            if (select.selectedIndex !== -1) {
                currentSelection = select.options[select.selectedIndex].text;
            }
            for (nElement = 0; nElement < list.length; nElement++) {
                if (nElement < select.options.length) {
                    select.options[nElement].text = list[nElement];
                } else {
                    var option = document.createElement("option");
                    option.text = list[nElement];
                    select.add(option, select[nElement]);
                }
                if (select[nElement].text === currentSelection) {
                    select.selectedIndex = nElement;
                }
            }
            if (select.options.length > list.length) {
                for (nElement = select.options.length - 1; nElement >= list.length; nElement--) {
                    select.remove(nElement);
                }
            }
        };

        var fixSelection = function (selectX, selectY, selectColor, vtable) {
            var finalX = -1;
            var finalY = -1;
            var finalColor = -1;
            for (var col = 0; col < vtable.columnTypes.length; col++) {
                switch (vtable.columnTypes[col]) {
                    case "String":
                        if (finalColor === -1) {
                            finalColor = col;
                        }
                        break;
                    case "double":
                    case "float":
                    case "long":
                    case "int":
                    case "short":
                    case "byte":
                        if (finalX === -1) {
                            finalX = col;
                        } else if (finalY === -1) {
                            finalY = col;
                        } else if (finalColor === -1) {
                            finalColor = col;
                        }
                        break;
                    default:
                        break;
                }
            }
            if (finalX !== -1) {
                selectX.selectedIndex = finalX;
            }
            if (finalY !== -1) {
                selectY.selectedIndex = finalY;
            }
            if (finalColor !== -1) {
                selectColor.selectedIndex = finalColor;
            }
        }

        var processValue = function (channel, nNode) {
            var value = values[channel.getId()];
            populateSelect(selectX[nNode], value.columnNames);
            populateSelect(selectY[nNode], value.columnNames);
            populateSelect(selectColor[nNode], value.columnNames);
            //alert(selectX[nNode].selectedIndex + " " + selectY[nNode].selectedIndex + " " + selectColor[nNode].selectedIndex);
            if (selectX[nNode].selectedIndex === 0 &&
                    selectY[nNode].selectedIndex === 0 &&
                    selectColor[nNode].selectedIndex === 0) {
                fixSelection(selectX[nNode], selectY[nNode], selectColor[nNode], value)
            }
            var xId = selectX[nNode].selectedIndex;
            var yId = selectY[nNode].selectedIndex;
            var colorId = selectColor[nNode].selectedIndex;
            var dataArray = [];
            dataArray[0] = ['ID', selectX[nNode].options[xId].text, selectY[nNode].options[yId].text, selectColor[nNode].options[colorId].text];
            var nPoints = value.columnValues[xId].length;
            for (var i=0; i < nPoints; i++) {
                dataArray[i+1] = ['', value.columnValues[xId][i], value.columnValues[yId][i], value.columnValues[colorId][i]];
            }
            var data = google.visualization.arrayToDataTable(dataArray);

            var options = {
                hAxis: {title: selectX[nNode].options[xId].text},
                vAxis: {title: selectY[nNode].options[yId].text},
                bubble: {textStyle: {fontSize: 11}},
                sizeAxis: {minValue: 0,  maxSize: 10}
            };

            charts[channel.getId()].draw(data, options);
        };

        var addError = function (message, channel, nNode) {
            google.visualization.errors.addError(graphDivs[nNode],
                message, "", {'removable': true});
        };

        var createCallback = function (nNode) {

            return function (evt, channel) {
                switch (evt.type) {
                    case "connection": //connection state changed
                        channel.readOnly = !evt.writeConnected;
                        break;
                    case "value": //value changed
                        values[channel.getId()] = evt.value;
                        processValue(channel, nNode);
                        break;
                    case "error": //error happened
                        addError(evt.error, channel, nNode);
                        break;
                    case "writePermission":	// write permission changed.
                        break;
                    case "writeCompleted": // write finished.
                        break;
                    default:
                        break;
                }
            };

        };

        var channel = wp.subscribeChannel(channelname, createCallback(i), readOnly);

        var data = google.visualization.arrayToDataTable([
            ['ID', 'X', 'Y', 'Color', 'Size'],
            ['', 0, 0, '', 0]
        ]);

        var options = {
            title: 'Waiting for data',
            hAxis: {title: ''},
            vAxis: {title: ''},
            bubble: {textStyle: {fontSize: 11}}
        };

        populateSelect(selectX[i], [xColumn]);
        populateSelect(selectY[i], [yColumn]);
        populateSelect(selectColor[i], [colorColumn]);

        var chart = new google.visualization.BubbleChart(graphDiv);
        chart.draw(data, options);

        charts[channel.getId()] = chart;

        var createOnClick = function (theChannel, nNode) {
            return function () {
                processValue(theChannel, nNode);
            };
        };

        selectX[i].onclick = createOnClick(channel, i);
        selectY[i].onclick = createOnClick(channel, i);
        selectColor[i].onclick = createOnClick(channel, i);
    }
}
<commit_msg>web-pods: bubble graph should handle empty table more gracefully<commit_after>google.load("visualization", "1", {packages: ["corechart"]});
google.setOnLoadCallback(drawSeriesChart);

function drawSeriesChart() {
    var nodes = document.getElementsByClassName("wp-bubble-graph");
    var len = nodes.length;
    var charts = {};
    var values = {};
    var selectX = {};
    var selectY = {};
    var selectColor = {};
    var graphDivs = {};
    counter = 0;

    for (var i = 0; i < len; i++) {
        // Extract the node and all its properties
        var masterDiv = nodes[i];
        var id = nodes[i].getAttribute("id");
        if (id === null) {
            counter++;
            id = "bubble-graph-" + counter;
            nodes[i].id = id;
        }
        var channelname = nodes[i].getAttribute("data-channel");
        var xColumn = nodes[i].getAttribute("data-x-column");
        var yColumn = nodes[i].getAttribute("data-y-column");
        var colorColumn = nodes[i].getAttribute("data-color-column");
        var readOnly = "true";

        // Prepare html
        var tableDiv = document.createElement("div");
        tableDiv.style.display = "table";
        tableDiv.style.height = "100%";
        tableDiv.style.width = "100%";
        masterDiv.appendChild(tableDiv);

        var columnsDiv = document.createElement("div");
        columnsDiv.style.display = "table-row";
        tableDiv.appendChild(columnsDiv);
        var columnsP = document.createElement("p");
        columnsDiv.appendChild(columnsP);
        columnsP.appendChild(document.createTextNode("X: "));
        selectX[i] = document.createElement("select");
        selectX[i].id = id + "-select-x";
        columnsP.appendChild(selectX[i]);
        columnsP.appendChild(document.createTextNode(" Y: "));
        selectY[i] = document.createElement("select");
        selectY[i].id = id + "-select-y";
        columnsP.appendChild(selectY[i]);
        columnsP.appendChild(document.createTextNode(" Color: "));
        selectColor[i] = document.createElement("select");
        selectColor[i].id = id + "-select-color";
        columnsP.appendChild(selectColor[i]);

        var graphDiv = document.createElement("div");
        graphDiv.style.display = "table-row";
        graphDiv.style.height = "100%";
        tableDiv.appendChild(graphDiv);
        graphDivs[i] = graphDiv;

        // Helper functions
        var populateSelect = function (select, list) {
            var currentSelection = null;
            if (select.selectedIndex !== -1) {
                currentSelection = select.options[select.selectedIndex].text;
            }
            for (nElement = 0; nElement < list.length; nElement++) {
                if (nElement < select.options.length) {
                    select.options[nElement].text = list[nElement];
                } else {
                    var option = document.createElement("option");
                    option.text = list[nElement];
                    select.add(option, select[nElement]);
                }
                if (select[nElement].text === currentSelection) {
                    select.selectedIndex = nElement;
                }
            }
            if (select.options.length > list.length) {
                for (nElement = select.options.length - 1; nElement >= list.length; nElement--) {
                    select.remove(nElement);
                }
            }
        };

        var fixSelection = function (selectX, selectY, selectColor, vtable) {
            var finalX = -1;
            var finalY = -1;
            var finalColor = -1;
            for (var col = 0; col < vtable.columnTypes.length; col++) {
                switch (vtable.columnTypes[col]) {
                    case "String":
                        if (finalColor === -1) {
                            finalColor = col;
                        }
                        break;
                    case "double":
                    case "float":
                    case "long":
                    case "int":
                    case "short":
                    case "byte":
                        if (finalX === -1) {
                            finalX = col;
                        } else if (finalY === -1) {
                            finalY = col;
                        } else if (finalColor === -1) {
                            finalColor = col;
                        }
                        break;
                    default:
                        break;
                }
            }
            if (finalX !== -1) {
                selectX.selectedIndex = finalX;
            }
            if (finalY !== -1) {
                selectY.selectedIndex = finalY;
            }
            if (finalColor !== -1) {
                selectColor.selectedIndex = finalColor;
            }
        }

        var processValue = function (channel, nNode) {
            var value = values[channel.getId()];
            populateSelect(selectX[nNode], value.columnNames);
            populateSelect(selectY[nNode], value.columnNames);
            populateSelect(selectColor[nNode], value.columnNames);
            //alert(selectX[nNode].selectedIndex + " " + selectY[nNode].selectedIndex + " " + selectColor[nNode].selectedIndex);
            if (selectX[nNode].selectedIndex === 0 &&
                    selectY[nNode].selectedIndex === 0 &&
                    selectColor[nNode].selectedIndex === 0) {
                fixSelection(selectX[nNode], selectY[nNode], selectColor[nNode], value)
            }
            var xId = selectX[nNode].selectedIndex;
            var yId = selectY[nNode].selectedIndex;
            var colorId = selectColor[nNode].selectedIndex;
            var dataArray = [];
            dataArray[0] = ['ID', selectX[nNode].options[xId].text, selectY[nNode].options[yId].text, selectColor[nNode].options[colorId].text];
            var nPoints = value.columnValues[xId].length;
            if (nPoints > 0) {
                for (var i=0; i < nPoints; i++) {
                    dataArray[i+1] = ['', value.columnValues[xId][i], value.columnValues[yId][i], value.columnValues[colorId][i]];
                }
                var data = google.visualization.arrayToDataTable(dataArray);

                var options = {
                    hAxis: {title: selectX[nNode].options[xId].text},
                    vAxis: {title: selectY[nNode].options[yId].text},
                    bubble: {textStyle: {fontSize: 11}},
                    sizeAxis: {minValue: 0,  maxSize: 10}
                };
            } else {

                var data = google.visualization.arrayToDataTable([
                    ['ID', 'X', 'Y', 'Color', 'Size'],
                    ['', 0, 0, '', 0]
                ]);

                var options = {
                    title: 'Empty table',
                    hAxis: {title: ''},
                    vAxis: {title: ''},
                    bubble: {textStyle: {fontSize: 11}}
                };
            }

            charts[channel.getId()].draw(data, options);
        };

        var addError = function (message, channel, nNode) {
            google.visualization.errors.addError(graphDivs[nNode],
                message, "", {'removable': true});
        };

        var createCallback = function (nNode) {

            return function (evt, channel) {
                switch (evt.type) {
                    case "connection": //connection state changed
                        channel.readOnly = !evt.writeConnected;
                        break;
                    case "value": //value changed
                        values[channel.getId()] = evt.value;
                        processValue(channel, nNode);
                        break;
                    case "error": //error happened
                        addError(evt.error, channel, nNode);
                        break;
                    case "writePermission":	// write permission changed.
                        break;
                    case "writeCompleted": // write finished.
                        break;
                    default:
                        break;
                }
            };

        };

        var channel = wp.subscribeChannel(channelname, createCallback(i), readOnly);

        var data = google.visualization.arrayToDataTable([
            ['ID', 'X', 'Y', 'Color', 'Size'],
            ['', 0, 0, '', 0]
        ]);

        var options = {
            title: 'Waiting for data',
            hAxis: {title: ''},
            vAxis: {title: ''},
            bubble: {textStyle: {fontSize: 11}}
        };

        populateSelect(selectX[i], [xColumn]);
        populateSelect(selectY[i], [yColumn]);
        populateSelect(selectColor[i], [colorColumn]);

        var chart = new google.visualization.BubbleChart(graphDiv);
        chart.draw(data, options);

        charts[channel.getId()] = chart;

        var createOnClick = function (theChannel, nNode) {
            return function () {
                processValue(theChannel, nNode);
            };
        };

        selectX[i].onclick = createOnClick(channel, i);
        selectY[i].onclick = createOnClick(channel, i);
        selectColor[i].onclick = createOnClick(channel, i);
    }
}
<|endoftext|>


<commit_before>wwt.controllers.controller('colorpickerController',
  ['$scope', function ($scope) {
  var cp = $scope.colorpicker;

  var setMouse = function(e){
    if (!$scope.mouse){
      $scope.mouse = e;
    }
    $(window).off('mousemove',setMouse)
  }
  $(window).on('mousemove',setMouse);
  $scope.previewColor = 'rgba(0,0,0,0)';
  $scope.rgb = [0,0,0];
  $scope.opacity = 100;
  $scope.init = function(){
    var e = $scope.mouse || wwt.lastmouseContext;
    $('body.wwt-webclient-wrapper .colorpicker-modal.wwt-modal .modal-dialog').css({marginTop:e.pageY,marginLeft:e.pageX});
    console.log(wwt.lastmouseContext,$scope.mouse);
    var bar = $('.cross-fader.color-picker a.btn').css('left', 100);
    var slider = new wwt.Move({
      el: bar,
      bounds: {
        x: [-200,  0],
        y: [0, 0]
      },
      onstart: function () {
        bar.addClass('moving');
      },
      onmove: function (args) {
        $scope.opacity = this.css.left / 100;
        //$('img#colorhex').css('opacity', bar.css.left/100);
        $scope.setColor();
      },
      oncomplete: function () {
        bar.removeClass('moving');
      }
    });
    $scope.pickColor();
  }

  $scope.pickColor = function(event){
    var c;
    if (event) {
      c = cp.getColorFromClick(event);
    }
    else{
      c = cp.color;
      /*if (c.name === ''){
        c.r = 255;
        c.b = 255;
        c.g = 255;
      }*/
      if (!c.a){
        c.a = 255;//????
      }
      $scope.opacity =Math.round(cp.color.a/255);
    }
    $scope.rgb = [c.r,c.g,c.b];
    $scope.setColor();
  };

  $scope.setColor = function(){
    $scope.$applyAsync(function(){
      $scope.previewColor = 'rgba('+ $scope.rgb.join(',') + ',' + $scope.opacity +')';
    });

  }

  $scope.commitColor = function(){
    cp.color.a = Math.min(255,Math.max(0,Math.round($scope.opacity*255)));
    var rgb = $scope.rgb;
    cp.color.r = rgb[0];
    cp.color.g = rgb[1];
    cp.color.b = rgb[2];
    cp.color.name='custom';
    cp.pickColor({});
    $scope.$hide();
  }

  setTimeout($scope.init,500);
  }]);
<commit_msg>added sticky colors, histogram close button<commit_after>wwt.controllers.controller('colorpickerController',
  ['$scope', function ($scope) {
  var cp = $scope.colorpicker;

  var setMouse = function(e){
    if (!$scope.mouse){
      $scope.mouse = e;
    }
    $(window).off('mousemove',setMouse)
  }
  $(window).on('mousemove',setMouse);
  $scope.previewColor = 'rgba(0,0,0,0)';
  $scope.rgb = [0,0,0];
  $scope.opacity = 100;
  $scope.init = function(){
    var e = $scope.mouse || wwt.lastmouseContext;
    $('body.wwt-webclient-wrapper .colorpicker-modal.wwt-modal .modal-dialog').css({marginTop:e.pageY,marginLeft:e.pageX});
    console.log(wwt.lastmouseContext,$scope.mouse);
    var bar = $('.cross-fader.color-picker a.btn').css('left', 100);
    var slider = new wwt.Move({
      el: bar,
      bounds: {
        x: [-200,  0],
        y: [0, 0]
      },
      onstart: function () {
        bar.addClass('moving');
      },
      onmove: function (args) {
        $scope.opacity = this.css.left / 100;
        //$('img#colorhex').css('opacity', bar.css.left/100);
        $scope.setColor();
      },
      oncomplete: function () {
        bar.removeClass('moving');
      }
    });
    $scope.pickColor();
  }

  $scope.pickColor = function(event){
    var c;
    if (event) {
      c = cp.getColorFromClick(event);
    }
    else{
      c = cp.color;
      /*if (c.name === ''){
        c.r = 255;
        c.b = 255;
        c.g = 255;
      }*/
      if (!c.a){
        c.a = 255;//????
      }
      $scope.opacity = cp.color.a/255;
    }
    $scope.rgb = [c.r,c.g,c.b];
    $scope.setColor();
  };

  $scope.setColor = function(){
    $scope.$applyAsync(function(){
      $scope.previewColor = 'rgba('+ $scope.rgb.join(',') + ',' + $scope.opacity +')';
    });

  }

  $scope.commitColor = function(){
    cp.color.a = Math.min(255,Math.max(0,Math.round($scope.opacity*255)));
    var rgb = $scope.rgb;
    cp.color.r = rgb[0];
    cp.color.g = rgb[1];
    cp.color.b = rgb[2];
    cp.color.name='custom';
    cp.pickColor({});
    $scope.$hide();
  }

  setTimeout($scope.init,500);
  }]);
<|endoftext|>


<commit_before>import { countTotal } from '../../../lib/util/knex'
import addTermToQueryBuilder from './addTermToQueryBuilder'

export default function (opts) {
  const { communities, network } = opts
  return User.query(function (qb) {
    qb.limit(opts.limit || 1000)
    qb.offset(opts.offset || 0)
    qb.where('users.active', '=', true)

    if (opts.sort === 'join') {
      if (!communities || communities.length !== 1) {
        throw new Error('When sorting by join date, you must specify exactly one community.')
      }
      qb.orderBy('communities_users.created_at', 'desc')
      qb.groupBy(['users.id', 'communities_users.created_at'])
    } else {
      qb.orderBy(opts.sort || 'name', 'asc')

      // prevent duplicates due to the joins
      qb.groupBy('users.id')
    }

    countTotal(qb, 'users', opts.totalColumnName)

    if (communities) {
      qb.join('communities_users', 'communities_users.user_id', 'users.id')
      qb.whereIn('communities_users.community_id', opts.communities)
      qb.where('communities_users.active', true)
    }

    if (network) {
      qb.distinct()
      qb.where({'communities.network_id': network})
      qb.join('communities_users', 'users.id', 'communities_users.user_id')
      qb.join('communities', 'communities.id', 'communities_users.community_id')
    }

    if (opts.autocomplete) {
      addTermToQueryBuilder(opts.autocomplete, qb, {
        columns: ['users.name']
      })
    }

    if (opts.term) {
      qb.leftJoin('tags_users', 'tags_users.user_id', 'users.id')
      qb.leftJoin('tags', 'tags.id', 'tags_users.tag_id')
      addTermToQueryBuilder(opts.term, qb, {
        columns: ['users.name', 'users.bio', 'tags.name']
      })
    }

    if (opts.start_time && opts.end_time) {
      qb.whereRaw('users.created_at between ? and ?', [opts.start_time, opts.end_time])
    }

    if (opts.exclude) {
      qb.whereNotIn('id', opts.exclude)
    }
  })
}
<commit_msg>update Search.forUsers to work with skills<commit_after>import { countTotal } from '../../../lib/util/knex'
import addTermToQueryBuilder from './addTermToQueryBuilder'

export default function (opts) {
  const { communities, network } = opts
  return User.query(function (qb) {
    qb.limit(opts.limit || 1000)
    qb.offset(opts.offset || 0)
    qb.where('users.active', '=', true)

    if (opts.sort === 'join') {
      if (!communities || communities.length !== 1) {
        throw new Error('When sorting by join date, you must specify exactly one community.')
      }
      qb.orderBy('communities_users.created_at', 'desc')
      qb.groupBy(['users.id', 'communities_users.created_at'])
    } else {
      qb.orderBy(opts.sort || 'name', 'asc')

      // prevent duplicates due to the joins
      qb.groupBy('users.id')
    }

    countTotal(qb, 'users', opts.totalColumnName)

    if (communities) {
      qb.join('communities_users', 'communities_users.user_id', 'users.id')
      qb.whereIn('communities_users.community_id', opts.communities)
      qb.where('communities_users.active', true)
    }

    if (network) {
      qb.distinct()
      qb.where({'communities.network_id': network})
      qb.join('communities_users', 'users.id', 'communities_users.user_id')
      qb.join('communities', 'communities.id', 'communities_users.community_id')
    }

    if (opts.autocomplete) {
      addTermToQueryBuilder(opts.autocomplete, qb, {
        columns: ['users.name']
      })
    }

    if (opts.term) {
      qb.leftJoin('skills_users', 'skills_users.user_id', 'users.id')
      qb.leftJoin('skills', 'skills.id', 'skills_users.skill_id')
      addTermToQueryBuilder(opts.term, qb, {
        columns: ['users.name', 'users.bio', 'skills.name']
      })
    }

    if (opts.start_time && opts.end_time) {
      qb.whereRaw('users.created_at between ? and ?', [opts.start_time, opts.end_time])
    }

    if (opts.exclude) {
      qb.whereNotIn('id', opts.exclude)
    }
  })
}
<|endoftext|>


<commit_before>const sinonChai = require('sinon-chai')
const chai = require('chai')
chai.use(sinonChai)
chai.should()
const expect = chai.expect
const serverTest = require('../test/utils/server')
const nock = require('nock')

describe('Etudiant API', function () {
  const server = serverTest()
  const api = server.api
  const validIne = 'fakeIne'
  const invalidIne = 'invalidIne'
  const apiKey = 'georges-moustaki'
  const fakeResponseData = {
    ine: '0102014544Z',
    nomFamille: 'GARCIA',
    prenom: 'CEDRIC',
    inscriptions: [
      {
        dateDebutInscription: '2019-11-20',
        dateFinInscription: '2020-11-20',
        statut: 'admis',
        etablissement: {
          uai: '0731499H',
          codePostal: '73381',
          codeCommune: '73051',
          codeRegion: '084'
        }
      },
      {
        dateDebutInscription: '2019-11-20',
        dateFinInscription: '2020-08-31',
        statut: 'admis',
        etablissement: {
          uai: '0691774D',
          codePostal: null,
          codeCommune: null,
          codeRegion: null
        }
      }
    ]
  }

  this.beforeEach(() => {
    nock('http://sup.data/api/rest.php')
      .get('/ping')
      .reply(200, 'pong')

    nock('http://sup.data/api/rest.php', {
      reqHeader: {
        'X-API-KEY': apiKey
      }
    })
      .get('/etudiantParIne')
      .query({
        INE: validIne
      })
      .reply(200, fakeResponseData)

    nock('http://sup.data/api/rest.php', {
      reqHeader: {
        'X-API-KEY': apiKey
      }
    })
      .get('/etudiantParIne')
      .query({
        INE: invalidIne
      })
      .reply(404, {
        message: 'rest_student_not_found',
        uid: '5e25cc78797ca_0000',
        details: 'rest_student_not_found'
      })
  })

  describe('Ping', () => {
    it('replies a 200', () => {
      return api()
        .get('/api/etudiant/ping')
        .expect(200)
    })
  })

  describe('Student search endpoint', () => {
    it('replies a 200 for a valid ine', (done) => {
      api()
        .get(`/api/etudiant?ine=${validIne}`)
        .set('Accept', '*/*')
        .set('X-User-Id', 'test')
        .set('X-User-Name', 'test')
        .set('X-User-Scopes', 'mesri_statut_etudiant')
        .expect(200)
        .end((req, res) => {
          expect(res.body).to.deep.equal(fakeResponseData)
          done()
        })
    })

    it('replies a 404 for an invalid ine', () => {
      return api()
        .get(`/api/etudiant?ine=${invalidIne}`)
        .set('Accept', '*/*')
        .set('X-User-Id', 'test')
        .set('X-User-Name', 'test')
        .set('X-User-Scopes', 'mesri_statut_etudiant')
        .expect(404)
    })

    it('hides the out-of-scope data', (done) => {
      api()
        .get(`/api/etudiant?ine=${validIne}`)
        .set('Accept', '*/*')
        .set('X-User-Id', 'test')
        .set('X-User-Name', 'test')
        .set('X-User-Scopes', 'dgfip_avis_imposition')
        .expect(200)
        .end((req, res) => {
          expect(res.body).to.deep.equal({})
          done()
        })
    })
  })
})
<commit_msg>:art: Simplify test syntax<commit_after>const serverTest = require('../test/utils/server')
const nock = require('nock')

describe('Etudiant API', function () {
  const server = serverTest()
  const api = server.api
  const validIne = 'fakeIne'
  const invalidIne = 'invalidIne'
  const apiKey = 'georges-moustaki'
  const fakeResponseData = {
    ine: '0102014544Z',
    nomFamille: 'GARCIA',
    prenom: 'CEDRIC',
    inscriptions: [
      {
        dateDebutInscription: '2019-11-20',
        dateFinInscription: '2020-11-20',
        statut: 'admis',
        etablissement: {
          uai: '0731499H',
          codePostal: '73381',
          codeCommune: '73051',
          codeRegion: '084'
        }
      },
      {
        dateDebutInscription: '2019-11-20',
        dateFinInscription: '2020-08-31',
        statut: 'admis',
        etablissement: {
          uai: '0691774D',
          codePostal: null,
          codeCommune: null,
          codeRegion: null
        }
      }
    ]
  }

  this.beforeEach(() => {
    nock('http://sup.data/api/rest.php')
      .get('/ping')
      .reply(200, 'pong')

    nock('http://sup.data/api/rest.php', {
      reqHeader: {
        'X-API-KEY': apiKey
      }
    })
      .get('/etudiantParIne')
      .query({
        INE: validIne
      })
      .reply(200, fakeResponseData)

    nock('http://sup.data/api/rest.php', {
      reqHeader: {
        'X-API-KEY': apiKey
      }
    })
      .get('/etudiantParIne')
      .query({
        INE: invalidIne
      })
      .reply(404, {
        message: 'rest_student_not_found',
        uid: '5e25cc78797ca_0000',
        details: 'rest_student_not_found'
      })
  })

  describe('Ping', () => {
    it('replies a 200', () => {
      return api()
        .get('/api/etudiant/ping')
        .expect(200)
    })
  })

  describe('Student search endpoint', () => {
    it('replies a 200 for a valid ine', () => {
      return api()
        .get(`/api/etudiant?ine=${validIne}`)
        .set('Accept', '*/*')
        .set('X-User-Id', 'test')
        .set('X-User-Name', 'test')
        .set('X-User-Scopes', 'mesri_statut_etudiant')
        .expect(200)
        .expect(fakeResponseData)
    })

    it('replies a 404 for an invalid ine', () => {
      return api()
        .get(`/api/etudiant?ine=${invalidIne}`)
        .set('Accept', '*/*')
        .set('X-User-Id', 'test')
        .set('X-User-Name', 'test')
        .set('X-User-Scopes', 'mesri_statut_etudiant')
        .expect(404)
    })

    it('hides the out-of-scope data', () => {
      return api()
        .get(`/api/etudiant?ine=${validIne}`)
        .set('Accept', '*/*')
        .set('X-User-Id', 'test')
        .set('X-User-Name', 'test')
        .set('X-User-Scopes', 'dgfip_avis_imposition')
        .expect(200)
        .expect({})
    })
  })
})
<|endoftext|>


<commit_before>import { Map, List } from 'immutable';
import * as _ from 'lodash';
import appPackage from '../package.json';
import { getPromotions, filterPromotions } from '../utils/marketingUtils';
import stores from '../../mocks/stores';

const productPropertiesMap = Map({
  prod_id: ['code'],
  prod_name: ['name'],
  prod_brand: ['brand', 'name'],
  prod_category: ['mainCategoryName'],
  prod_univers: ['mainCategoryRooms', '0'],
  prod_price: ['price', 'selling', 'gross'],
  prod_avail_online: ['vendible'],
  prod_avail_store: ['isClickCollectProduct'],
  prod_gamma: ['gamma'],
  prod_sconto: ['price', 'selling', 'discount']
});

const buildCommonLayer = (product) => {
  const commonPropertiesLayer = productPropertiesMap.reduce((acc, property, key) => {
    const productProperty = product.hasIn(property) ? product.getIn(property) : '';
    return acc.set(key, List().push(productProperty));
  }, Map({}));

  const normalizedCommonPropertiesLayer = normalizeProperties(commonPropertiesLayer);
  return normalizedCommonPropertiesLayer;
};

const normalizeProperties = (layer) => {
  let obj = layer;
  obj = obj.set('prod_sconto', normalizeSconto(obj.get('prod_sconto')));
  obj = obj.set('prod_avail_online', normalizeAvail(obj.get('prod_avail_online')));
  obj = obj.set('prod_avail_store', normalizeAvail(obj.get('prod_avail_store')));
  obj = obj.set('prod_price', normalizePrice(obj.get('prod_price')));
  return obj;
};

const normalizeSconto = (value = Map({})) => {
  const sconto = value.get(0);
  return List().push(sconto !== '' ? Math.round(sconto * 10).toString() : sconto);
};

const normalizePrice = (value = Map({})) => {
  const price = value.get(0);
  return List().push(price !== '' ? price.toFixed(2) : '');
};

const normalizeAvail = (field = List()) => List().push(field.get(0) ? '1' : '0');

const isProductNew = (product) => {
  const marketingAttributes = product.get('marketingAttributes');
  const loyaltyProgram = product.get('loyaltyProgram');

  if (marketingAttributes && loyaltyProgram) {
    const promotions = getPromotions(marketingAttributes, loyaltyProgram);
    const filteredPromotions = filterPromotions(promotions);
    const isNew = filteredPromotions
                  .reduce((acc, promotion) => promotion.get('code') === 'NOVITA', false);

    const prodNew = isNew ? '1' : '0';
    return Map({ prod_new: List().push(prodNew) });
  }
};

const getVariant = (product) => {
  const masterProductCode = product.get('masterProductCode');
  const list = List();
  let layer = Map({});

  if (masterProductCode) {
    const code = product.get('code');
    layer = layer.set('prod_variant', list.push(`${code}_${masterProductCode}`));
  } else {
    layer = layer.set('prod_variant', list.push('master'));
  }
  return layer;
};

const getGiftPoints = (product) => {
  const giftPoints = product.getIn(['loyaltyProgram', 'type']);
  const list = List();
  let layer = Map({});

  if (giftPoints && giftPoints === 'ADDITIONAL_POINTS') {
    const points = list.push(Math.round(product.getIn('loyaltyProgram', 'value') * 10));
    layer = layer.set('prod_puntiomaggio', points);
  }
  return layer;
};

const getIdeapiuPoints = (product) => {
  const ideapiuPoints = product.getIn(['loyaltyProgram', 'type']);
  const list = List();
  let layer = Map({});

  if (ideapiuPoints && ideapiuPoints === 'DISCOUNT') {
    const points = list.push(Math.round(product.getIn('prod_idepiu', 'value') * 10));
    layer = layer.set('prod_idepiu', points);
  }
  return layer;
};

const getBundle = (product) => {
  const isBundle = product.getIn(['bundleInformation', 'isBundle']);
  const list = List();
  let layer = Map({ prod_bundle: list.push('0') });

  if (isBundle) {
    layer = layer.set('prod_bundle', list.push('1'));
  }
  return layer;
};

const getProdList = (product, path) => {
  const mainCategory = product.get('mainCategory');
  const mainCategoryName = product.get('mainCategoryName');
  return `${path[0]} > ${mainCategoryName}/${mainCategory}`;
};

const customizer = (objValue, srcValue) => {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
};

const buildNavigationStore = (storeCode = null) => {
  let storeName = '';

  if (storeCode) {
    stores.forEach(store => {
      if (store.storeCode === storeCode) {
        storeName = store.storeName;
      }
    });
  }

  return Map({ navigation_store: storeName });
};

// ---------------------   EXPORTED FUNCTIONS ------------------->

const buildPageName = (path = []) => {
  let pageName = path;
  const splitChar = '/';

  if (!_.isEmpty(path)) {
    const trimSlash = _.trimStart(pageName, splitChar);
    pageName = _.split(trimSlash, splitChar);
  }
  return pageName;
};

const buildProductLayer = (product = {}, action = 'detail') => {
  let productLayer = Map({});

  if (!_.isEmpty(product)) {
    const commonProperties = buildCommonLayer(product);
    const newProductProperty = isProductNew(product);
    const variantProperty = getVariant(product);
    const giftPoints = getGiftPoints(product);
    const ideapiuPoints = getIdeapiuPoints(product);
    const isBundle = getBundle(product);
    const prodAction = Map({ prod_action: action });

    productLayer = productLayer.merge(
      commonProperties,
      newProductProperty,
      variantProperty,
      giftPoints,
      ideapiuPoints,
      isBundle,
      prodAction
    );
    return productLayer;
  }
};

const buildRelatedProductsLayer = (products = Map({}), path = []) => {
  let prodPositionCount = 0;

  if (products.size) {
    const listOfProductsLayer = products.map((product) => {
      const prodPosition = List().push(prodPositionCount += 1);
      const prodListList = List().push(getProdList(product, path));

      let productLayer = buildCommonLayer(product);
      // add additional properties to productLayer
      productLayer = productLayer.set('prod_position', prodPosition);
      productLayer = productLayer.set('prod_list', prodListList);
      return productLayer;
    });

    const mergedlistOfProductsLayer = listOfProductsLayer.reduce((acc, productLayer) => {
      const mergedValues = _.mergeWith(acc.toJS(), productLayer.toJS(), customizer);
      return Map(mergedValues);
    });

    const normalizeFinalLayer = mergedlistOfProductsLayer
                                .mapKeys(key => _.replace(key, 'prod', 'imp'));

    return normalizeFinalLayer;
  }
};

const buildReleaseVersion = (worldName = '') => `${_.snakeCase(worldName)}_${appPackage.version}`;

export {
  buildPageName,
  buildProductLayer,
  buildRelatedProductsLayer,
  buildNavigationStore,
  buildReleaseVersion
};

<commit_msg>add store code to navigation_store<commit_after>import { Map, List } from 'immutable';
import * as _ from 'lodash';
import appPackage from '../package.json';
import { getPromotions, filterPromotions } from '../utils/marketingUtils';
import stores from '../../mocks/stores';

const productPropertiesMap = Map({
  prod_id: ['code'],
  prod_name: ['name'],
  prod_brand: ['brand', 'name'],
  prod_category: ['mainCategoryName'],
  prod_univers: ['mainCategoryRooms', '0'],
  prod_price: ['price', 'selling', 'gross'],
  prod_avail_online: ['vendible'],
  prod_avail_store: ['isClickCollectProduct'],
  prod_gamma: ['gamma'],
  prod_sconto: ['price', 'selling', 'discount']
});

const buildCommonLayer = (product) => {
  const commonPropertiesLayer = productPropertiesMap.reduce((acc, property, key) => {
    const productProperty = product.hasIn(property) ? product.getIn(property) : '';
    return acc.set(key, List().push(productProperty));
  }, Map({}));

  const normalizedCommonPropertiesLayer = normalizeProperties(commonPropertiesLayer);
  return normalizedCommonPropertiesLayer;
};

const normalizeProperties = (layer) => {
  let obj = layer;
  obj = obj.set('prod_sconto', normalizeSconto(obj.get('prod_sconto')));
  obj = obj.set('prod_avail_online', normalizeAvail(obj.get('prod_avail_online')));
  obj = obj.set('prod_avail_store', normalizeAvail(obj.get('prod_avail_store')));
  obj = obj.set('prod_price', normalizePrice(obj.get('prod_price')));
  return obj;
};

const normalizeSconto = (value = Map({})) => {
  const sconto = value.get(0);
  return List().push(sconto !== '' ? Math.round(sconto * 10).toString() : sconto);
};

const normalizePrice = (value = Map({})) => {
  const price = value.get(0);
  return List().push(price !== '' ? price.toFixed(2) : '');
};

const normalizeAvail = (field = List()) => List().push(field.get(0) ? '1' : '0');

const isProductNew = (product) => {
  const marketingAttributes = product.get('marketingAttributes');
  const loyaltyProgram = product.get('loyaltyProgram');

  if (marketingAttributes && loyaltyProgram) {
    const promotions = getPromotions(marketingAttributes, loyaltyProgram);
    const filteredPromotions = filterPromotions(promotions);
    const isNew = filteredPromotions
                  .reduce((acc, promotion) => promotion.get('code') === 'NOVITA', false);

    const prodNew = isNew ? '1' : '0';
    return Map({ prod_new: List().push(prodNew) });
  }
};

const getVariant = (product) => {
  const masterProductCode = product.get('masterProductCode');
  const list = List();
  let layer = Map({});

  if (masterProductCode) {
    const code = product.get('code');
    layer = layer.set('prod_variant', list.push(`${code}_${masterProductCode}`));
  } else {
    layer = layer.set('prod_variant', list.push('master'));
  }
  return layer;
};

const getGiftPoints = (product) => {
  const giftPoints = product.getIn(['loyaltyProgram', 'type']);
  const list = List();
  let layer = Map({});

  if (giftPoints && giftPoints === 'ADDITIONAL_POINTS') {
    const points = list.push(Math.round(product.getIn('loyaltyProgram', 'value') * 10));
    layer = layer.set('prod_puntiomaggio', points);
  }
  return layer;
};

const getIdeapiuPoints = (product) => {
  const ideapiuPoints = product.getIn(['loyaltyProgram', 'type']);
  const list = List();
  let layer = Map({});

  if (ideapiuPoints && ideapiuPoints === 'DISCOUNT') {
    const points = list.push(Math.round(product.getIn('prod_idepiu', 'value') * 10));
    layer = layer.set('prod_idepiu', points);
  }
  return layer;
};

const getBundle = (product) => {
  const isBundle = product.getIn(['bundleInformation', 'isBundle']);
  const list = List();
  let layer = Map({ prod_bundle: list.push('0') });

  if (isBundle) {
    layer = layer.set('prod_bundle', list.push('1'));
  }
  return layer;
};

const getProdList = (product, path) => {
  const mainCategory = product.get('mainCategory');
  const mainCategoryName = product.get('mainCategoryName');
  return `${path[0]} > ${mainCategoryName}/${mainCategory}`;
};

const customizer = (objValue, srcValue) => {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
};

const buildNavigationStore = (storeCode = null) => {
  let storeName = '';

  if (storeCode) {
    stores.forEach(store => {
      if (store.storeCode === storeCode) {
        storeName = `${storeCode} - ${store.storeName}`;
      }
    });
  }

  return Map({ navigation_store: storeName });
};

// ---------------------   EXPORTED FUNCTIONS ------------------->

const buildPageName = (path = []) => {
  let pageName = path;
  const splitChar = '/';

  if (!_.isEmpty(path)) {
    const trimSlash = _.trimStart(pageName, splitChar);
    pageName = _.split(trimSlash, splitChar);
  }
  return pageName;
};

const buildProductLayer = (product = {}, action = 'detail') => {
  let productLayer = Map({});

  if (!_.isEmpty(product)) {
    const commonProperties = buildCommonLayer(product);
    const newProductProperty = isProductNew(product);
    const variantProperty = getVariant(product);
    const giftPoints = getGiftPoints(product);
    const ideapiuPoints = getIdeapiuPoints(product);
    const isBundle = getBundle(product);
    const prodAction = Map({ prod_action: action });

    productLayer = productLayer.merge(
      commonProperties,
      newProductProperty,
      variantProperty,
      giftPoints,
      ideapiuPoints,
      isBundle,
      prodAction
    );
    return productLayer;
  }
};

const buildRelatedProductsLayer = (products = Map({}), path = []) => {
  let prodPositionCount = 0;

  if (products.size) {
    const listOfProductsLayer = products.map((product) => {
      const prodPosition = List().push(prodPositionCount += 1);
      const prodListList = List().push(getProdList(product, path));

      let productLayer = buildCommonLayer(product);
      // add additional properties to productLayer
      productLayer = productLayer.set('prod_position', prodPosition);
      productLayer = productLayer.set('prod_list', prodListList);
      return productLayer;
    });

    const mergedlistOfProductsLayer = listOfProductsLayer.reduce((acc, productLayer) => {
      const mergedValues = _.mergeWith(acc.toJS(), productLayer.toJS(), customizer);
      return Map(mergedValues);
    });

    const normalizeFinalLayer = mergedlistOfProductsLayer
                                .mapKeys(key => _.replace(key, 'prod', 'imp'));

    return normalizeFinalLayer;
  }
};

const buildReleaseVersion = (worldName = '') => `${_.snakeCase(worldName)}_${appPackage.version}`;

export {
  buildPageName,
  buildProductLayer,
  buildRelatedProductsLayer,
  buildNavigationStore,
  buildReleaseVersion
};

<|endoftext|>