<commit_before>"use strict";

//*------------------------------------------------------------------*

var React = require('react');
var ReactDOM = require('react-dom');

var $ = require('jquery');

var URI = require('urijs');

//*------------------------------------------------------------------*

var DifferentialFacetsTree = require('./DifferentialFacetsTree.jsx');
var DifferentialResults = require('./DifferentialResults.jsx');

//*------------------------------------------------------------------*

/**
 * @param {Object} options
 * @param {string} options.facetsContainer - id of the facets container, i.e. a <div> id
 * @param {string} options.resultsContainer - id of the results container, i.e. a <div> id
 * @param {string} options.identifier
 * @param {string} options.queryType - "gene", "geneSet"
 * @param {string} options.species
 * @param {string} options.atlasHost
 */
module.exports = function (options) {

    var facetsElement = document.getElementById(options.facetsContainer),
        resultsElement = document.getElementById(options.resultsContainer),
        host = options.atlasHost ? options.atlasHost : window.location.host;

    var query = {
        geneQuery : options.identifier,
        queryType : options.queryType,
        select    : {}
    };

    var differentialFacetsPath = "";
    var differentialResultsPath = "";
    switch (query.queryType) {
        case "gene":
            differentialFacetsPath = "gxa/json/genes/" + query.geneQuery + "/differentialFacets";
            differentialResultsPath = "gxa/json/genes/" + query.geneQuery + "/differentialResults";
            break;
        case "geneSet":
            differentialFacetsPath = "gxa/json/genesets/" + query.geneQuery + "/differentialFacets" + (options.species ? "&organism=" + options.species : "");
            differentialResultsPath = "gxa/json/genesets/" + query.geneQuery + "/differentialResults" + (options.species ? "&organism=" + options.species : "");
            break;
        default:
            differentialFacetsPath =
                "gxa/json/query/differentialFacets?geneQuery=" + query.geneQuery +
                "&organism=" + options.species;
            differentialResultsPath =
                "gxa/json/query/differentialResults?geneQuery=" + query.geneQuery +
                "&organism=" + options.species;
            break;
    }

    var facetsTreeData,
        resultsData;
    $.ajaxSetup({ traditional:true });
    $.ajax({
        url: new URI({protocol: URI(window.location).protocol(), hostname: host, path: differentialFacetsPath}).toString(),
        dataType: "json",
        success: function(response) {
            facetsTreeData = response;
            if (options.species) {
                for (var i = 0 ; i < facetsTreeData.species.length ; i++) {
                    if (facetsTreeData.species[i].name === options.species) {
                        addSelection(query.select, "species", options.species);
                    }
                }
            }
            if (Object.keys(query.select).length === 0) {
                parseSelectedFacetsFromLocation();
            }
            pushQueryIntoBrowserHistory(true);

            $.ajax({
                url: new URI({protocol: URI(window.location).protocol(), hostname: host, path: differentialResultsPath}).toString(),
                dataType: "json",
                success: function(response) {
                    resultsData = response;

                    filterAndRenderResults();
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log("ERROR");
                    console.log("Status: " + textStatus);
                    console.log("Error thrown: " + errorThrown);
                }
            });
        },
        error: function(jqXHR, textStatus, errorThrown) {
            console.log("ERROR");
            console.log("Status: " + textStatus);
            console.log("Error thrown: " + errorThrown);
        }
    });

    /**
     * Parse the `ds` search field in the URL and assign it to the `query` object
     */
    function parseSelectedFacetsFromLocation() {
        var currentURL = new URI(window.location);
        var selectString = currentURL.search(true)["ds"];
        query.select = selectString ? JSON.parse(selectString) : {};
    }

    function setChecked(checked, facet, facetItem) {
        if (checked) {
            addSelection(query.select, facet, facetItem);
        } else {
            removeSelection(query.select, facet, facetItem);
        }
        pushQueryIntoBrowserHistory(false);
        filterAndRenderResults();
    }

    function addSelection(select, facet, facetItem) {
        if (!select[facet]) {
            select[facet] = {};
        }
        select[facet][facetItem] = true;
    }

    function removeSelection(select, facet, facetItem) {
        select[facet][facetItem] = false;
    }

    /**
     * Stringify the `query` object, assign it to the `ds` search field in the URL and store it in the History
     * @param {boolean} replace - use `replaceState` instead of `pushState`
     */
    function pushQueryIntoBrowserHistory(replace) {
        var newURL = new URI(window.location).search(function(data) {
            data.ds = JSON.stringify(query.select);
        });

        if (replace) {
            history.replaceState(null, "", newURL);
        } else {
            history.pushState(null, "", newURL);
        }
    }

    function filterResults(query) {
        return resultsData.results.filter(function(result) {
            for (var facetName in query) {
                if (query.hasOwnProperty(facetName)) {

                    var hasCheckedItemsInThisFacet = false;
                    var facetMatch = false;

                    for (var facetItem in query[facetName]) {
                        if (query[facetName].hasOwnProperty(facetItem)) {

                            if (query[facetName][facetItem]) {
                                hasCheckedItemsInThisFacet = true;

                                if (result[facetName].constructor === Array) {
                                    facetMatch = facetMatch || result[facetName].indexOf(facetItem) != -1;
                                }
                                else {
                                    facetMatch = facetMatch || result[facetName] === facetItem;
                                }
                            }

                        }
                    }

                    if (hasCheckedItemsInThisFacet && !facetMatch) {
                        return false;
                    }
                }
            }

            return true;
        });

    }

    function filterAndRenderResults() {

        var filteredResults = filterResults (query.select);

        var disabledCheckedFacets = {};
        var disabledUncheckedFacets = {};

        var selectedFacets = [];
        for (var facet in query.select) {
            var itemFacet = query.select[facet];
            for (var item in itemFacet) {
                if (itemFacet[item]) {
                    selectedFacets.push(item);
                }
            }
        }

        var notSelectedFacets = {};
        for (var facet in facetsTreeData) {
            var facetItems = facetsTreeData[facet];
            var unSelectedFacets = [];
            for (var item in facetItems) {
                var facetItem = facetItems[item];
                if (selectedFacets.indexOf(facetItem.name) === -1) {
                    unSelectedFacets.push(facetItem);
                }
            }
            notSelectedFacets[facet] = unSelectedFacets;
        }

        for (var facet in notSelectedFacets) {
            var facetNotExistsValue = [];
            var _query = query.select;

            for (var item in notSelectedFacets[facet]) {
                var facetItem = notSelectedFacets[facet][item];

                if (_query.hasOwnProperty(facet)) {
                    _query[facet][facetItem.name] = true;
                } else {
                    var _item = {};
                    _item[facetItem.name] = true;
                    _query[facet] = _item;
                }

                var queryResults = filterResults(_query);
                if (queryResults.length === 0 || queryResults.length === filteredResults.length) {
                    facetNotExistsValue.push(facetItem.name);
                }
                _query[facet][facetItem.name] = false; // once calculated, leave it as it was
            }

            if (facetNotExistsValue.length > 0) {
                disabledUncheckedFacets[facet] = facetNotExistsValue;
            }
        }

        for (var facet in disabledUncheckedFacets) {
            var facetValue = [];

            for (var item in disabledUncheckedFacets[facet]) {
                var existsFacet = true;
                var existMultiValueFacet = false;

                for (var index in filteredResults) {
                    var filtered = filteredResults[index];
                    var facetResults = filtered[facet];

                    if (facet === "factors" && facetResults.length > 1 ) {
                        if (facetResults.indexOf(disabledUncheckedFacets[facet][item].toString()) === -1) {
                            existsFacet = false;
                        } else {
                            existMultiValueFacet = true;
                        }

                    } else if (disabledUncheckedFacets[facet][item].toString() !== facetResults.toString()) {
                        existsFacet = false;
                    }
                }

                //All the results contain the same item
                if (existsFacet) {
                    facetValue.push(disabledUncheckedFacets[facet][item]);
                }

                //If all the results don't contain the same facet but the factor multiValue exists in more than one result
                if (!existsFacet && existMultiValueFacet) {
                    disabledUncheckedFacets[facet].splice(item, 1);
                }
            }

            //FacetValue contains all the items that are present in the results for a facet
            if (facetValue.length > 0) {
                disabledCheckedFacets[facet] = facetValue;
            }
        }

        ReactDOM.render(
            React.createElement(
                DifferentialFacetsTree, {facets: facetsTreeData, checkedFacets: query.select, setChecked: setChecked,
                    disabledCheckedFacets: disabledCheckedFacets, disabledUncheckedFacets: disabledUncheckedFacets}
            ),
            facetsElement
        );

        ReactDOM.render(
            React.createElement(
                DifferentialResults,
                {results: filteredResults.slice(0, 1000), maxDownLevel: resultsData.maxDownLevel,
                    minDownLevel: resultsData.minDownLevel, minUpLevel: resultsData.minUpLevel,
                    maxUpLevel: resultsData.maxUpLevel, host: host}
            ),
            resultsElement
        );
    }
};
<commit_msg>Build differential queries with species properly<commit_after>"use strict";

//*------------------------------------------------------------------*

var React = require('react');
var ReactDOM = require('react-dom');

var $ = require('jquery');

var URI = require('urijs');

//*------------------------------------------------------------------*

var DifferentialFacetsTree = require('./DifferentialFacetsTree.jsx');
var DifferentialResults = require('./DifferentialResults.jsx');

//*------------------------------------------------------------------*

/**
 * @param {Object} options
 * @param {string} options.facetsContainer - id of the facets container, i.e. a <div> id
 * @param {string} options.resultsContainer - id of the results container, i.e. a <div> id
 * @param {string} options.identifier
 * @param {string} options.queryType - "gene", "geneSet"
 * @param {string} options.species
 * @param {string} options.atlasHost
 */
module.exports = function (options) {

    var facetsElement = document.getElementById(options.facetsContainer),
        resultsElement = document.getElementById(options.resultsContainer),
        host = options.atlasHost ? options.atlasHost : window.location.host;

    var query = {
        geneQuery : options.identifier,
        queryType : options.queryType,
        select    : {}
    };

    var differentialFacetsPath = "";
    var differentialResultsPath = "";
    switch (query.queryType) {
        case "gene":
            differentialFacetsPath = "gxa/json/genes/" + query.geneQuery + "/differentialFacets";
            differentialResultsPath = "gxa/json/genes/" + query.geneQuery + "/differentialResults";
            break;
        case "geneSet":
            differentialFacetsPath = "gxa/json/genesets/" + query.geneQuery + "/differentialFacets" + (options.species ? "?organism=" + options.species : "");
            differentialResultsPath = "gxa/json/genesets/" + query.geneQuery + "/differentialResults" + (options.species ? "?organism=" + options.species : "");
            break;
        default:
            differentialFacetsPath =
                "gxa/json/query/differentialFacets?geneQuery=" + query.geneQuery +
                (options.species ? "?organism=" + options.species : "");
            differentialResultsPath =
                "gxa/json/query/differentialResults?geneQuery=" + query.geneQuery +
                (options.species ? "?organism=" + options.species : "");
            break;
    }

    var facetsTreeData,
        resultsData;
    $.ajaxSetup({ traditional:true });
    $.ajax({
        url: new URI({protocol: URI(window.location).protocol(), hostname: host, path: differentialFacetsPath}).toString(),
        dataType: "json",
        success: function(response) {
            facetsTreeData = response;
            if (options.species) {
                for (var i = 0 ; i < facetsTreeData.species.length ; i++) {
                    if (facetsTreeData.species[i].name === options.species) {
                        addSelection(query.select, "species", options.species);
                    }
                }
            }
            if (Object.keys(query.select).length === 0) {
                parseSelectedFacetsFromLocation();
            }
            pushQueryIntoBrowserHistory(true);

            $.ajax({
                url: new URI({protocol: URI(window.location).protocol(), hostname: host, path: differentialResultsPath}).toString(),
                dataType: "json",
                success: function(response) {
                    resultsData = response;

                    filterAndRenderResults();
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log("ERROR");
                    console.log("Status: " + textStatus);
                    console.log("Error thrown: " + errorThrown);
                }
            });
        },
        error: function(jqXHR, textStatus, errorThrown) {
            console.log("ERROR");
            console.log("Status: " + textStatus);
            console.log("Error thrown: " + errorThrown);
        }
    });

    /**
     * Parse the `ds` search field in the URL and assign it to the `query` object
     */
    function parseSelectedFacetsFromLocation() {
        var currentURL = new URI(window.location);
        var selectString = currentURL.search(true)["ds"];
        query.select = selectString ? JSON.parse(selectString) : {};
    }

    function setChecked(checked, facet, facetItem) {
        if (checked) {
            addSelection(query.select, facet, facetItem);
        } else {
            removeSelection(query.select, facet, facetItem);
        }
        pushQueryIntoBrowserHistory(false);
        filterAndRenderResults();
    }

    function addSelection(select, facet, facetItem) {
        if (!select[facet]) {
            select[facet] = {};
        }
        select[facet][facetItem] = true;
    }

    function removeSelection(select, facet, facetItem) {
        select[facet][facetItem] = false;
    }

    /**
     * Stringify the `query` object, assign it to the `ds` search field in the URL and store it in the History
     * @param {boolean} replace - use `replaceState` instead of `pushState`
     */
    function pushQueryIntoBrowserHistory(replace) {
        var newURL = new URI(window.location).search(function(data) {
            data.ds = JSON.stringify(query.select);
        });

        if (replace) {
            history.replaceState(null, "", newURL);
        } else {
            history.pushState(null, "", newURL);
        }
    }

    function filterResults(query) {
        return resultsData.results.filter(function(result) {
            for (var facetName in query) {
                if (query.hasOwnProperty(facetName)) {

                    var hasCheckedItemsInThisFacet = false;
                    var facetMatch = false;

                    for (var facetItem in query[facetName]) {
                        if (query[facetName].hasOwnProperty(facetItem)) {

                            if (query[facetName][facetItem]) {
                                hasCheckedItemsInThisFacet = true;

                                if (result[facetName].constructor === Array) {
                                    facetMatch = facetMatch || result[facetName].indexOf(facetItem) != -1;
                                }
                                else {
                                    facetMatch = facetMatch || result[facetName] === facetItem;
                                }
                            }

                        }
                    }

                    if (hasCheckedItemsInThisFacet && !facetMatch) {
                        return false;
                    }
                }
            }

            return true;
        });

    }

    function filterAndRenderResults() {

        var filteredResults = filterResults (query.select);

        var disabledCheckedFacets = {};
        var disabledUncheckedFacets = {};

        var selectedFacets = [];
        for (var facet in query.select) {
            var itemFacet = query.select[facet];
            for (var item in itemFacet) {
                if (itemFacet[item]) {
                    selectedFacets.push(item);
                }
            }
        }

        var notSelectedFacets = {};
        for (var facet in facetsTreeData) {
            var facetItems = facetsTreeData[facet];
            var unSelectedFacets = [];
            for (var item in facetItems) {
                var facetItem = facetItems[item];
                if (selectedFacets.indexOf(facetItem.name) === -1) {
                    unSelectedFacets.push(facetItem);
                }
            }
            notSelectedFacets[facet] = unSelectedFacets;
        }

        for (var facet in notSelectedFacets) {
            var facetNotExistsValue = [];
            var _query = query.select;

            for (var item in notSelectedFacets[facet]) {
                var facetItem = notSelectedFacets[facet][item];

                if (_query.hasOwnProperty(facet)) {
                    _query[facet][facetItem.name] = true;
                } else {
                    var _item = {};
                    _item[facetItem.name] = true;
                    _query[facet] = _item;
                }

                var queryResults = filterResults(_query);
                if (queryResults.length === 0 || queryResults.length === filteredResults.length) {
                    facetNotExistsValue.push(facetItem.name);
                }
                _query[facet][facetItem.name] = false; // once calculated, leave it as it was
            }

            if (facetNotExistsValue.length > 0) {
                disabledUncheckedFacets[facet] = facetNotExistsValue;
            }
        }

        for (var facet in disabledUncheckedFacets) {
            var facetValue = [];

            for (var item in disabledUncheckedFacets[facet]) {
                var existsFacet = true;
                var existMultiValueFacet = false;

                for (var index in filteredResults) {
                    var filtered = filteredResults[index];
                    var facetResults = filtered[facet];

                    if (facet === "factors" && facetResults.length > 1 ) {
                        if (facetResults.indexOf(disabledUncheckedFacets[facet][item].toString()) === -1) {
                            existsFacet = false;
                        } else {
                            existMultiValueFacet = true;
                        }

                    } else if (disabledUncheckedFacets[facet][item].toString() !== facetResults.toString()) {
                        existsFacet = false;
                    }
                }

                //All the results contain the same item
                if (existsFacet) {
                    facetValue.push(disabledUncheckedFacets[facet][item]);
                }

                //If all the results don't contain the same facet but the factor multiValue exists in more than one result
                if (!existsFacet && existMultiValueFacet) {
                    disabledUncheckedFacets[facet].splice(item, 1);
                }
            }

            //FacetValue contains all the items that are present in the results for a facet
            if (facetValue.length > 0) {
                disabledCheckedFacets[facet] = facetValue;
            }
        }

        ReactDOM.render(
            React.createElement(
                DifferentialFacetsTree, {facets: facetsTreeData, checkedFacets: query.select, setChecked: setChecked,
                    disabledCheckedFacets: disabledCheckedFacets, disabledUncheckedFacets: disabledUncheckedFacets}
            ),
            facetsElement
        );

        ReactDOM.render(
            React.createElement(
                DifferentialResults,
                {results: filteredResults.slice(0, 1000), maxDownLevel: resultsData.maxDownLevel,
                    minDownLevel: resultsData.minDownLevel, minUpLevel: resultsData.minUpLevel,
                    maxUpLevel: resultsData.maxUpLevel, host: host}
            ),
            resultsElement
        );
    }
};
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*globals $, jQuery, angular, TypiCMS, alertify, top, window, console*/

(function (angular) {

    'use strict';

    angular.module('typicms').controller('FilesController', ['$http', '$scope', '$rootScope', '$location', '$attrs', function ($http, $scope, $rootScope, $location, $attrs) {

        $scope.url = $attrs.url;

        /**
         * Empty object that will contain checked items.
         */
        $scope.checked = {
            models: []
        };

        $scope.path = null;

        $scope.model = {};

        $scope.folder = {id: ''};
        if (sessionStorage.getItem('folder')) {
            $scope.folder = JSON.parse(sessionStorage.getItem('folder'));
        }
        if ($scope.folder.id) {
            $scope.url += '?folder_id=' + $scope.folder.id;
        }

        if (TypiCMS.content_locale == null) {
            TypiCMS.content_locale = TypiCMS.locale;
        }
        $scope.TypiCMS = TypiCMS;

        $http.get($scope.url).then(function (response) {
                $scope.models = response.data.models;
                $scope.model.models = response.data.models;
                $scope.path = response.data.path;
                //copy the references (you could clone ie angular.copy but then have to go through a dirty checking for the matches)
                $scope.displayedModels = [].concat($scope.models);
            }, function (error) {
                console.log(error);
            });

        $scope.$on('filesAdded', function (event, models) {
            $scope.model.models = models;
        });

        $scope.sortableOptions = {
            animation: 100,
            onSort: function (evt){
                $http({
                    method: 'POST',
                    url: '/admin/files/sort',
                    data: evt.models
                }).then(function successCallback(response) {
                }, function errorCallback(response) {
                    alertify.error('Error ' + response.status + ' ' + response.statusText);
                });
            }
        };

        $scope.dropped = function(draggedModels, droppedModel) {

            let ids = [];
            draggedModels.forEach(function (model) {
                ids.push(model.id);
            });

            if (droppedModel.type !== 'f' || ids.indexOf(droppedModel.id) !== -1) {
                return;
            }

            for (var i = draggedModels.length - 1; i >= 0; i--) {
                let draggedModel = draggedModels[i];
                var index = $scope.models.indexOf(draggedModel);
                $scope.models.splice(index, 1);
            }

            let data = {
                folder_id: droppedModel.id
            }

            $http.patch('/admin/files/'+ids.join(), data).then(function (response) {
            }, function (reason) {
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

            $scope.checked.models = [];

        }

        /**
         * Create a new folder.
         */
        $scope.newFolder = function(folderId) {
            let name = window.prompt('What is the name of the new folder?');
            if (!name) {
                return;
            }
            let data = {
                folder_id: folderId,
                type: 'f',
                name: name,
                description: {},
                alt_attribute: {},
            }

            $http.post('/admin/files', data).then(function (response) {
                $scope.models.push(response.data.model);
            }, function (reason) {
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });
        }

        /**
         * Select an item.
         */
        $scope.check = function (model, $event) {
            $event.stopPropagation();
            let indexOfLastCheckedItem = $scope.models.indexOf($scope.checked.models[$scope.checked.models.length-1]);
            let index = $scope.checked.models.indexOf(model);
            if (!($event.ctrlKey || $event.metaKey || $event.shiftKey)) {
                $scope.checked.models = [];
            }
            if (index !== -1 && ($event.metaKey || $event.ctrlKey)) {
                $scope.checked.models.splice(index, 1);
            } else if ($scope.checked.models.indexOf(model) === -1) {
                $scope.checked.models.push(model);
            }
            if (index === -1) {
                if ($event.shiftKey) {
                    let currentItemIndex = $scope.models.indexOf(model);
                    $scope.models.forEach(function (model, index) {
                        if (currentItemIndex > indexOfLastCheckedItem) {
                            if (indexOfLastCheckedItem === -1) {
                                if (index <= currentItemIndex) {
                                    $scope.checked.models.push(model);
                                }
                            }
                            if (indexOfLastCheckedItem !== -1) {
                                if (index > indexOfLastCheckedItem && index < currentItemIndex) {
                                    if ($scope.checked.models.indexOf(model) === -1) {
                                        $scope.checked.models.push(model);
                                    }
                                }
                            }
                        }
                        if (currentItemIndex < indexOfLastCheckedItem) {
                            if (indexOfLastCheckedItem !== -1) {
                                if (index < indexOfLastCheckedItem && index > currentItemIndex) {
                                    if ($scope.checked.models.indexOf(model) === -1) {
                                        $scope.checked.models.push(model);
                                    }
                                }
                            }
                        }
                    });
                }
            }
        };

        /**
         * Uncheck all items
         */
        $scope.unCheckAll = function (model) {
            $scope.checked.models = [];
        };

        /**
         * Put items in parent folder
         */
        $scope.moveToParentFolder = function () {

            var ids = [],
                models = $scope.checked.models,
                number = models.length;

            if ($scope.checked.models.length > $scope.deleteLimit) {
                alertify.error('Too much elements (max ' + $scope.deleteLimit + ' items.)');
                return false;
            }

            models.forEach(function (model) {
                ids.push(model.id);
                var index = $scope.models.indexOf(model);
                $scope.models.splice(index, 1);
            });

            $scope.checked.models = [];

            $scope.loading = true;

            let data = {
                folder_id: $scope.path[$scope.path.length-2].id
            }

            $http.patch('/admin/files/'+ids.join(), data).then(function (response) {
                $scope.loading = false;
                if (response.data.number < number) {
                    alertify.error((number - response.data.number) + ' items could not be moved.');
                }
                if (response.data.number > 0) {
                    alertify.success(response.data.number + ' items moved.');
                }
            }, function (reason) {
                $scope.loading = false;
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        };

        /**
         * Remove a file attached to a model
         */
        $scope.remove = function (model) {
            var segments = $location.absUrl().split('?')[0].split('/').reverse(),
                modelId = segments[1],
                module = segments[2],
                index = $scope.model.models.indexOf(model);

            $scope.model.models.splice(index, 1);
            $scope.loading = true;

            $http.patch('/admin/' + module + '/' + modelId, {remove: model.id}).then(function (response) {
                $scope.loading = false;
            }, function (reason) {
                $scope.loading = false;
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        };

        /**
         * Delete checked items
         */
        $scope.deleteChecked = function () {

            var ids = [],
                models = $scope.checked.models,
                number = models.length;

            if ($scope.checked.models.length > $scope.deleteLimit) {
                alertify.error('Impossible to delete more than ' + $scope.deleteLimit + ' items in one go.');
                return false;
            }
            if (!window.confirm('Are you sure you want to delete ' + number + ' items?')) {
                return false;
            }

            models.forEach(function (model) {
                ids.push(model.id);
            });

            $scope.loading = true;

            $http.delete('/admin/files/'+ids.join()).then(function (response) {
                $scope.loading = false;
                if (response.data.number == 0) {
                    alertify.error(response.data.message);
                } else if (response.data.number < number) {
                    alertify.error((number - response.data.number) + ' items could not be deleted.');
                }
                if (response.data.number == number) {
                    alertify.success(response.data.number + ' items deleted.');
                    models.forEach(function (model) {
                        var index = $scope.models.indexOf(model);
                        $scope.models.splice(index, 1);
                    });
                    $scope.checked.models = [];
                }
            }, function (reason) {
                $scope.loading = false;
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        };

        /**
         * Add selected items to model
         */
        $scope.addSelectedFiles = function () {
            var ids = [],
                models = $scope.checked.models,
                data = {},
                segments = $location.absUrl().split('?')[0].split('/').reverse(),
                modelId = segments[1],
                module = segments[2];

            if (models.length === 0) {
                $('html, body').removeClass('noscroll');
                $('#filepicker').removeClass('filepicker-modal-open');
                return;
            }

            models.forEach(function (model) {
                ids.push(model.id);
            });
            data.files = ids;

            $http.patch('/admin/' + module + '/' + modelId, data).then(function (response) {

                $scope.checked.models = [];

                $rootScope.$broadcast('filesAdded', response.data.models);
                $('html, body').removeClass('noscroll');
                $('#filepicker').removeClass('filepicker-modal-open');

                if (response.data.number == 0) {
                    alertify.error(response.data.message);
                } else {
                    alertify.success(response.data.message);
                }

            }, function (reason) {
                console.log(reason);
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        }

        /**
         * Handle a double click on a file or folder.
         */
        $scope.handle = function (model) {
            if (model.type === 'f') {
                $http.get('/admin/files?folder_id='+model.id).then(function (response) {
                        $scope.models = response.data.models;
                        $scope.path = response.data.path;
                        //copy the references (you could clone ie angular.copy but then have to go through a dirty checking for the matches)
                        $scope.displayedModels = [].concat($scope.models);
                    }, function (error) {
                        console.log(error);
                    });
                sessionStorage.setItem('folder', JSON.stringify(model));
                $scope.folder = model;
                $scope.checked.models = [];
            } else {
                var CKEditorCleanUpFuncNum = $('#filepicker').data('CKEditorCleanUpFuncNum'),
                    CKEditorFuncNum = $('#filepicker').data('CKEditorFuncNum');
                if (!!CKEditorFuncNum || !!CKEditorCleanUpFuncNum) {
                    parent.CKEDITOR.tools.callFunction(CKEditorFuncNum, '/storage/files/' + model.name);
                    parent.CKEDITOR.tools.callFunction(CKEditorCleanUpFuncNum);
                } else {
                    $rootScope.$broadcast('fileAdded', model);
                    $('html, body').removeClass('noscroll');
                    $('#filepicker').removeClass('filepicker-modal-open');
                }
            }
        };

        /**
         * Add selected item
         */
        $scope.addSelectedFile = function () {
            $rootScope.$broadcast('fileAdded', $scope.checked.models[0]);
            $('html, body').removeClass('noscroll');
            $('#filepicker').removeClass('filepicker-modal-open');
        }

    }]);

}(angular));
<commit_msg>indentation<commit_after>/*jslint browser: true*/
/*globals $, jQuery, angular, TypiCMS, alertify, top, window, console*/

(function (angular) {

    'use strict';

    angular.module('typicms').controller('FilesController', ['$http', '$scope', '$rootScope', '$location', '$attrs', function ($http, $scope, $rootScope, $location, $attrs) {

        $scope.url = $attrs.url;

        /**
         * Empty object that will contain checked items.
         */
        $scope.checked = {
            models: []
        };

        $scope.path = null;

        $scope.model = {};

        $scope.folder = {id: ''};
        if (sessionStorage.getItem('folder')) {
            $scope.folder = JSON.parse(sessionStorage.getItem('folder'));
        }
        if ($scope.folder.id) {
            $scope.url += '?folder_id=' + $scope.folder.id;
        }

        if (TypiCMS.content_locale == null) {
            TypiCMS.content_locale = TypiCMS.locale;
        }
        $scope.TypiCMS = TypiCMS;

        $http.get($scope.url).then(function (response) {
            $scope.models = response.data.models;
            $scope.model.models = response.data.models;
            $scope.path = response.data.path;
            //copy the references (you could clone ie angular.copy but then have to go through a dirty checking for the matches)
            $scope.displayedModels = [].concat($scope.models);
        }, function (error) {
            console.log(error);
        });

        $scope.$on('filesAdded', function (event, models) {
            $scope.model.models = models;
        });

        $scope.sortableOptions = {
            animation: 100,
            onSort: function (evt){
                $http({
                    method: 'POST',
                    url: '/admin/files/sort',
                    data: evt.models
                }).then(function successCallback(response) {
                }, function errorCallback(response) {
                    alertify.error('Error ' + response.status + ' ' + response.statusText);
                });
            }
        };

        $scope.dropped = function(draggedModels, droppedModel) {

            let ids = [];
            draggedModels.forEach(function (model) {
                ids.push(model.id);
            });

            if (droppedModel.type !== 'f' || ids.indexOf(droppedModel.id) !== -1) {
                return;
            }

            for (var i = draggedModels.length - 1; i >= 0; i--) {
                let draggedModel = draggedModels[i];
                var index = $scope.models.indexOf(draggedModel);
                $scope.models.splice(index, 1);
            }

            let data = {
                folder_id: droppedModel.id
            }

            $http.patch('/admin/files/'+ids.join(), data).then(function (response) {
            }, function (reason) {
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

            $scope.checked.models = [];

        }

        /**
         * Create a new folder.
         */
        $scope.newFolder = function(folderId) {
            let name = window.prompt('What is the name of the new folder?');
            if (!name) {
                return;
            }
            let data = {
                folder_id: folderId,
                type: 'f',
                name: name,
                description: {},
                alt_attribute: {},
            }

            $http.post('/admin/files', data).then(function (response) {
                $scope.models.push(response.data.model);
            }, function (reason) {
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });
        }

        /**
         * Select an item.
         */
        $scope.check = function (model, $event) {
            $event.stopPropagation();
            let indexOfLastCheckedItem = $scope.models.indexOf($scope.checked.models[$scope.checked.models.length-1]);
            let index = $scope.checked.models.indexOf(model);
            if (!($event.ctrlKey || $event.metaKey || $event.shiftKey)) {
                $scope.checked.models = [];
            }
            if (index !== -1 && ($event.metaKey || $event.ctrlKey)) {
                $scope.checked.models.splice(index, 1);
            } else if ($scope.checked.models.indexOf(model) === -1) {
                $scope.checked.models.push(model);
            }
            if (index === -1) {
                if ($event.shiftKey) {
                    let currentItemIndex = $scope.models.indexOf(model);
                    $scope.models.forEach(function (model, index) {
                        if (currentItemIndex > indexOfLastCheckedItem) {
                            if (indexOfLastCheckedItem === -1) {
                                if (index <= currentItemIndex) {
                                    $scope.checked.models.push(model);
                                }
                            }
                            if (indexOfLastCheckedItem !== -1) {
                                if (index > indexOfLastCheckedItem && index < currentItemIndex) {
                                    if ($scope.checked.models.indexOf(model) === -1) {
                                        $scope.checked.models.push(model);
                                    }
                                }
                            }
                        }
                        if (currentItemIndex < indexOfLastCheckedItem) {
                            if (indexOfLastCheckedItem !== -1) {
                                if (index < indexOfLastCheckedItem && index > currentItemIndex) {
                                    if ($scope.checked.models.indexOf(model) === -1) {
                                        $scope.checked.models.push(model);
                                    }
                                }
                            }
                        }
                    });
                }
            }
        };

        /**
         * Uncheck all items
         */
        $scope.unCheckAll = function (model) {
            $scope.checked.models = [];
        };

        /**
         * Put items in parent folder
         */
        $scope.moveToParentFolder = function () {

            var ids = [],
                models = $scope.checked.models,
                number = models.length;

            if ($scope.checked.models.length > $scope.deleteLimit) {
                alertify.error('Too much elements (max ' + $scope.deleteLimit + ' items.)');
                return false;
            }

            models.forEach(function (model) {
                ids.push(model.id);
                var index = $scope.models.indexOf(model);
                $scope.models.splice(index, 1);
            });

            $scope.checked.models = [];

            $scope.loading = true;

            let data = {
                folder_id: $scope.path[$scope.path.length-2].id
            }

            $http.patch('/admin/files/'+ids.join(), data).then(function (response) {
                $scope.loading = false;
                if (response.data.number < number) {
                    alertify.error((number - response.data.number) + ' items could not be moved.');
                }
                if (response.data.number > 0) {
                    alertify.success(response.data.number + ' items moved.');
                }
            }, function (reason) {
                $scope.loading = false;
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        };

        /**
         * Remove a file attached to a model
         */
        $scope.remove = function (model) {
            var segments = $location.absUrl().split('?')[0].split('/').reverse(),
                modelId = segments[1],
                module = segments[2],
                index = $scope.model.models.indexOf(model);

            $scope.model.models.splice(index, 1);
            $scope.loading = true;

            $http.patch('/admin/' + module + '/' + modelId, {remove: model.id}).then(function (response) {
                $scope.loading = false;
            }, function (reason) {
                $scope.loading = false;
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        };

        /**
         * Delete checked items
         */
        $scope.deleteChecked = function () {

            var ids = [],
                models = $scope.checked.models,
                number = models.length;

            if ($scope.checked.models.length > $scope.deleteLimit) {
                alertify.error('Impossible to delete more than ' + $scope.deleteLimit + ' items in one go.');
                return false;
            }
            if (!window.confirm('Are you sure you want to delete ' + number + ' items?')) {
                return false;
            }

            models.forEach(function (model) {
                ids.push(model.id);
            });

            $scope.loading = true;

            $http.delete('/admin/files/'+ids.join()).then(function (response) {
                $scope.loading = false;
                if (response.data.number == 0) {
                    alertify.error(response.data.message);
                } else if (response.data.number < number) {
                    alertify.error((number - response.data.number) + ' items could not be deleted.');
                }
                if (response.data.number == number) {
                    alertify.success(response.data.number + ' items deleted.');
                    models.forEach(function (model) {
                        var index = $scope.models.indexOf(model);
                        $scope.models.splice(index, 1);
                    });
                    $scope.checked.models = [];
                }
            }, function (reason) {
                $scope.loading = false;
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        };

        /**
         * Add selected items to model
         */
        $scope.addSelectedFiles = function () {
            var ids = [],
                models = $scope.checked.models,
                data = {},
                segments = $location.absUrl().split('?')[0].split('/').reverse(),
                modelId = segments[1],
                module = segments[2];

            if (models.length === 0) {
                $('html, body').removeClass('noscroll');
                $('#filepicker').removeClass('filepicker-modal-open');
                return;
            }

            models.forEach(function (model) {
                ids.push(model.id);
            });
            data.files = ids;

            $http.patch('/admin/' + module + '/' + modelId, data).then(function (response) {

                $scope.checked.models = [];

                $rootScope.$broadcast('filesAdded', response.data.models);
                $('html, body').removeClass('noscroll');
                $('#filepicker').removeClass('filepicker-modal-open');

                if (response.data.number == 0) {
                    alertify.error(response.data.message);
                } else {
                    alertify.success(response.data.message);
                }

            }, function (reason) {
                console.log(reason);
                alertify.error('Error ' + reason.status + ' ' + reason.statusText);
            });

        }

        /**
         * Handle a double click on a file or folder.
         */
        $scope.handle = function (model) {
            if (model.type === 'f') {
                $http.get('/admin/files?folder_id='+model.id).then(function (response) {
                        $scope.models = response.data.models;
                        $scope.path = response.data.path;
                        //copy the references (you could clone ie angular.copy but then have to go through a dirty checking for the matches)
                        $scope.displayedModels = [].concat($scope.models);
                    }, function (error) {
                        console.log(error);
                    });
                sessionStorage.setItem('folder', JSON.stringify(model));
                $scope.folder = model;
                $scope.checked.models = [];
            } else {
                var CKEditorCleanUpFuncNum = $('#filepicker').data('CKEditorCleanUpFuncNum'),
                    CKEditorFuncNum = $('#filepicker').data('CKEditorFuncNum');
                if (!!CKEditorFuncNum || !!CKEditorCleanUpFuncNum) {
                    parent.CKEDITOR.tools.callFunction(CKEditorFuncNum, '/storage/files/' + model.name);
                    parent.CKEDITOR.tools.callFunction(CKEditorCleanUpFuncNum);
                } else {
                    $rootScope.$broadcast('fileAdded', model);
                    $('html, body').removeClass('noscroll');
                    $('#filepicker').removeClass('filepicker-modal-open');
                }
            }
        };

        /**
         * Add selected item
         */
        $scope.addSelectedFile = function () {
            $rootScope.$broadcast('fileAdded', $scope.checked.models[0]);
            $('html, body').removeClass('noscroll');
            $('#filepicker').removeClass('filepicker-modal-open');
        }

    }]);

}(angular));
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import serializeError from 'serialize-error'
import getStudentInfo from '../../../../helpers/import-student'
import convertStudent from '../../../../helpers/convert-imported-student'
import DOMify from 'react-domify'

export default class SISImportScreen extends Component {
	static propTypes = {};

	state = {
		loggedIn: null,
		checkingLogin: true,
		data: {},
		error: null,
	};

	componentWillMount() {
		getStudentInfo()
			.then(data => {
				console.log(data)
				console.log(convertStudent(data))
				this.setState({loggedIn: true, checkingLogin: false, student: convertStudent(data)})
			})
			.catch(err => {
				console.error(err)
				this.setState({loggedIn: false, checkingLogin: false, error: serializeError(err)})
			})
	}

	render() {
		return

Import from the SIS

				{this.state.checkingLogin
					? 'Checking login…'
					: this.state.loggedIn
						? 'Logged in!'
						: 'Not logged in.'}

			{this.state.error ?
{JSON.stringify(this.state.error)}
 : null}

			<DOMify value={this.state.student} />

	}
}
<commit_msg>add some nifty buttons<commit_after>import React, {Component, PropTypes} from 'react'
import serializeError from 'serialize-error'
import Button from '../../../../components/button'
import getStudentInfo, {checkIfLoggedIn} from '../../../../helpers/import-student'
import convertStudent from '../../../../helpers/convert-imported-student'
import DOMify from 'react-domify'
import { push } from 'react-router-redux'
import { initStudent } from '../../../../redux/students/actions/init-student'
import {connect} from 'react-redux'

export default class SISImportScreen extends Component {
	static propTypes = {
		dispatch: PropTypes.func.isRequired, // redux
	};

	state = {
		loggedIn: null,
		checkingLogin: true,
		data: {},
		error: null,
	};

	componentWillMount() {
		checkIfLoggedIn()
			.then(() => this.setState({loggedIn: true, checkingLogin: false}))
			.catch(err => {
				console.error(err)
				this.setState({loggedIn: false, checkingLogin: false, error: serializeError(err)})
			})
	}

	handleImportData = () => {
		getStudentInfo()
			.then(data => {
				console.log(data)
				this.setState({student: convertStudent(data)})
			})
			.catch(err => {
				console.error(err)
				this.setState({error: serializeError(err)})
			})
	};

	handleCreateStudent = () => {
		let action = initStudent(this.state.student)
		this.props.dispatch(action)
		this.props.dispatch(push(`/s/${action.payload.id}`))
	};

	render() {
		return

Import from the SIS

				{this.state.checkingLogin
					? 'Checking login…'
					: this.state.loggedIn
						? 'Logged in!'
						: 'Not logged in.'}

			{this.state.error ?
{JSON.stringify(this.state.error)}
 : null}

			{this.state.student ? <DOMify value={this.state.student} /> : null}

				<Button
					disabled={!this.state.loggedIn}
					onClick={this.handleImportData}
				>
					Import Student
				</Button>
				{this.state.student
					? <Button onClick={this.handleCreateStudent}>Let's go!</Button>
					: null}

	}
}

let mapDispatch = dispatch => ({dispatch})

export default connect(undefined, mapDispatch)(SISImportScreen)
<|endoftext|>


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

define(function(require) {
  /*
    DEPENDENCIES
   */
  var Locale = require('utils/locale');
  var BaseDialog = require('utils/dialogs/dialog');
  var TemplateHTML = require('hbs!./disk-resize/html');
  var Sunstone = require('sunstone');
  var Tips = require('utils/tips');
  var RangeSlider = require('utils/range-slider');
  var Humanize = require('utils/humanize');

  /*
    CONSTANTS
   */

  var DIALOG_ID = require('./disk-resize/dialogId');
  var TAB_ID = require('../tabId');

  /*
    CONSTRUCTOR
   */

  function Dialog() {
    this.dialogId = DIALOG_ID;

    BaseDialog.call(this);
  }

  Dialog.DIALOG_ID = DIALOG_ID;
  Dialog.prototype = Object.create(BaseDialog.prototype);
  Dialog.prototype.constructor = Dialog;
  Dialog.prototype.html = _html;
  Dialog.prototype.onShow = _onShow;
  Dialog.prototype.setup = _setup;
  Dialog.prototype.setParams = _setParams;

  return Dialog;

  /*
    FUNCTION DEFINITIONS
   */

  function _html() {
    return TemplateHTML({
      'dialogId': this.dialogId
    });

  }function convertCostNumber(number){
    if(number >= 1000000){
      number = (number/1000000).toFixed(2)
      return number.toString()+"M";
    }
    else if(number >= 1000){
      number = (number/1000).toFixed(2)
      return number.toString()+"K";
    }
    else if (number >= 0 && number < 1000)
      return number.toFixed(2);
    else
      return number;
  }

  function _setup(context) {
    var that = this;
    Tips.setup(context);
    $( ".diskSlider", context).html(RangeSlider.html({
        min: that.diskSize,
        max: Humanize.sizeToMB("1024GB")*1024,
        initial: that.diskSize,
        name: "resize",
        max_value: ""
    }));
    $( ".uinput-slider-val",context).prop('type', 'text');
    $( ".uinput-slider-val",context).val(Humanize.size($( ".uinput-slider",context).val()));

    $( ".uinput-slider", context).on("input", function(){
      $( ".uinput-slider-val",context).val(Humanize.size($( ".uinput-slider",context).val()));
      var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*that.diskCost;
      if(isNaN(cost)){
        cost = 0;
      }
      document.getElementById("new_cost_resize").textContent =  Locale.tr("Cost")+": "+ convertCostNumber(cost);
    });

    $( ".uinput-slider-val", context).on("change", function(){
      $( ".uinput-slider",context).val(Humanize.sizeToMB(($( ".uinput-slider-val",context).val()).toString())*1024);
      var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*that.diskCost;
      if(isNaN(cost)){
        cost = 0;
      }
      document.getElementById("new_cost_resize").textContent =  Locale.tr("Cost")+": "+ convertCostNumber(cost);
    });

    var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*this.diskCost;
    if(isNaN(cost)){
        cost = 0;
    }
    document.getElementById("new_cost_resize").textContent =  Locale.tr("Cost")+": "+ convertCostNumber(cost);

    $('#' + DIALOG_ID + 'Form', context).submit(function() {
      var new_size = $( ".uinput-slider-val",context).val();
      new_size = Math.round(parseInt(new_size) / 1024);
      new_size = new_size.toString();
      var obj = {
        "vm_id": that.element.ID,
        "disk_id" : that.diskId,
        "new_size": new_size
      };

      Sunstone.runAction('VM.disk_resize', that.element.ID, obj);

      Sunstone.getDialog(DIALOG_ID).hide();
      Sunstone.getDialog(DIALOG_ID).reset();
      return false;
    });

    return false;
  }

  function _onShow(context) {
    this.setNames( {tabId: TAB_ID} );
    $("#disk_id", context).val(this.diskId);
    $("#resize_disk", context).focus();
    return false;
  }

  /**
   * @param {object} params
   *        - params.element : VM element
   *        - params.diskId : Disk ID to save as
   *        - params.snapshotId : Disk snapshot ID to save as. Can be undefined
   */
  function _setParams(params) {
    this.element = params.element;
    this.diskId = params.diskId;
    this.diskSize = params.diskSize;
    this.diskCost = params.diskCost;
  }
});
<commit_msg>B #1671: Can't resize VM disk - [one.vm.diskresize] (#1722)<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

define(function(require) {
  /*
    DEPENDENCIES
   */
  var Locale = require('utils/locale');
  var BaseDialog = require('utils/dialogs/dialog');
  var TemplateHTML = require('hbs!./disk-resize/html');
  var Sunstone = require('sunstone');
  var Tips = require('utils/tips');
  var RangeSlider = require('utils/range-slider');
  var Humanize = require('utils/humanize');

  /*
    CONSTANTS
   */

  var DIALOG_ID = require('./disk-resize/dialogId');
  var TAB_ID = require('../tabId');

  /*
    CONSTRUCTOR
   */

  function Dialog() {
    this.dialogId = DIALOG_ID;

    BaseDialog.call(this);
  }

  Dialog.DIALOG_ID = DIALOG_ID;
  Dialog.prototype = Object.create(BaseDialog.prototype);
  Dialog.prototype.constructor = Dialog;
  Dialog.prototype.html = _html;
  Dialog.prototype.onShow = _onShow;
  Dialog.prototype.setup = _setup;
  Dialog.prototype.setParams = _setParams;

  return Dialog;

  /*
    FUNCTION DEFINITIONS
   */

  function _html() {
    return TemplateHTML({
      'dialogId': this.dialogId
    });

  }function convertCostNumber(number){
    if(number >= 1000000){
      number = (number/1000000).toFixed(2)
      return number.toString()+"M";
    }
    else if(number >= 1000){
      number = (number/1000).toFixed(2)
      return number.toString()+"K";
    }
    else if (number >= 0 && number < 1000)
      return number.toFixed(2);
    else
      return number;
  }

  function _setup(context) {
    var that = this;
    Tips.setup(context);
    $( ".diskSlider", context).html(RangeSlider.html({
        min: that.diskSize,
        max: Humanize.sizeToMB("1024GB")*1024,
        initial: that.diskSize,
        name: "resize",
        max_value: ""
    }));
    $( ".uinput-slider-val",context).prop('type', 'text');
    $( ".uinput-slider-val",context).val(Humanize.size($( ".uinput-slider",context).val()));

    $( ".uinput-slider", context).on("input", function(){
      $( ".uinput-slider-val",context).val(Humanize.size($( ".uinput-slider",context).val()));
      var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*that.diskCost;
      if(isNaN(cost)){
        cost = 0;
      }
      document.getElementById("new_cost_resize").textContent =  Locale.tr("Cost")+": "+ convertCostNumber(cost);
    });

    $( ".uinput-slider-val", context).on("change", function(){
      $( ".uinput-slider",context).val(Humanize.sizeToMB(($( ".uinput-slider-val",context).val()).toString())*1024);
      var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*that.diskCost;
      if(isNaN(cost)){
        cost = 0;
      }
      document.getElementById("new_cost_resize").textContent =  Locale.tr("Cost")+": "+ convertCostNumber(cost);
    });

    var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*this.diskCost;
    if(isNaN(cost)){
        cost = 0;
    }
    document.getElementById("new_cost_resize").textContent =  Locale.tr("Cost")+": "+ convertCostNumber(cost);

    $('#' + DIALOG_ID + 'Form', context).submit(function() {
      var new_size = Humanize.sizeToMB($( ".uinput-slider-val",context).val());
      new_size = new_size.toString();
      var obj = {
        "vm_id": that.element.ID,
        "disk_id" : that.diskId,
        "new_size": new_size
      };

      Sunstone.runAction('VM.disk_resize', that.element.ID, obj);

      Sunstone.getDialog(DIALOG_ID).hide();
      Sunstone.getDialog(DIALOG_ID).reset();
      return false;
    });

    return false;
  }

  function _onShow(context) {
    this.setNames( {tabId: TAB_ID} );
    $("#disk_id", context).val(this.diskId);
    $("#resize_disk", context).focus();
    return false;
  }

  /**
   * @param {object} params
   *        - params.element : VM element
   *        - params.diskId : Disk ID to save as
   *        - params.snapshotId : Disk snapshot ID to save as. Can be undefined
   */
  function _setParams(params) {
    this.element = params.element;
    this.diskId = params.diskId;
    this.diskSize = params.diskSize;
    this.diskCost = params.diskCost;
  }
});
<|endoftext|>


<commit_before>import {Button} from 'widget/button'
import {ButtonGroup} from './buttonGroup'
import {ScrollableList} from 'widget/list'
import {Subject, delay} from 'rxjs'
import {compose} from 'compose'
import {connect} from 'store'
import {selectFrom} from 'stateUtils'
import FloatingBox from 'widget/floatingBox'
import Icon from 'widget/icon'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './buttonSelect.module.css'
import withSubscriptions from 'subscription'

const SELECTION_DELAY_MS = 350

const mapStateToProps = state => ({
    dimensions: selectFrom(state, 'dimensions') || []
})

class ButtonSelect extends React.Component {
    input = React.createRef()
    list = React.createRef()
    select$ = new Subject()
    state = {
        showOptions: false,
        flattenedOptions: [],
        selectedOption: null,
        selected: false
    }

    constructor() {
        super()
        this.handleBlur = this.handleBlur.bind(this)
    }

    render() {
        const {className} = this.props
        const {showOptions} = this.state
        return (

                {this.renderButton()}
                {showOptions ? this.renderOptions() : null}

        )
    }

    renderButton() {
        const {onClick} = this.props
        return onClick
            ? this.renderMultiButton()
            : this.renderSingleButton()
    }

    renderSingleButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onMouseOver, onMouseOut} = this.props
        return (
            <Button
                ref={this.input}
                chromeless={chromeless}
                shape={shape}
                look={look}
                icon={icon}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}
                width={width}
                onClick={() => this.toggleOptions()}
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}
                disabled={disabled}
                label={this.getLabel()}
                tail={
                    <Icon name={this.getChevronIcon()}/>
                }
            />
        )
    }

    renderMultiButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onClick, onMouseOver, onMouseOut} = this.props
        return (
            <ButtonGroup
                ref={this.input}
                spacing='tight'
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}
            >
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={icon}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={e => onClick && onClick(e)}
                    disabled={disabled}
                    label={this.getLabel()}
                />
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={this.getChevronIcon()}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={() => this.toggleOptions()}
                    disabled={disabled}
                />
            </ButtonGroup>
        )
    }

    getLabel() {
        const {label} = this.props
        const {selectedOption} = this.state
        return (selectedOption && selectedOption.buttonLabel) || label
    }

    getChevronIcon() {
        const {placement} = this.props
        return placement === 'above' ? 'chevron-up' : 'chevron-down'
    }

    renderOptions() {
        const {placement, optionsClassName, optionTooltipPlacement} = this.props
        const {flattenedOptions, selectedOption, selected} = this.state
        return (
            <FloatingBox
                element={this.input.current}
                placement={placement}
                alignment='left'
                onBlur={this.handleBlur}>
                <ScrollableList
                    ref={this.list}
                    className={optionsClassName || styles.options}
                    options={flattenedOptions}
                    selectedOption={selectedOption}
                    onSelect={option => this.select$.next(option)}
                    onCancel={() => this.hideOptions()}
                    autoCenter={!selected}
                    tooltipPlacement={optionTooltipPlacement}
                    air='more'
                    keyboard
                />
            </FloatingBox>
        )
    }

    toggleOptions() {
        const {showOptions} = this.state
        showOptions
            ? this.hideOptions()
            : this.showOptions()
    }

    showOptions() {
        this.setState({showOptions: true})
    }

    hideOptions() {
        this.setState({showOptions: false, selectedOption: null})
    }

    setSelectedOption(selectedOption) {
        this.updateState({
            selectedOption,
            selected: true
        })
    }

    updateState(state, callback) {
        const updatedState = (prevState, state) =>
            _.isEqual(_.pick(prevState, _.keys(state)), state) ? null : state
        this.setState(
            prevState =>
                updatedState(prevState, _.isFunction(state) ? state(prevState) : state),
            callback
        )
    }

    handleSelect() {
        const {input, onSelect, addSubscription} = this.props
        addSubscription(
            this.select$.subscribe(
                option => {
                    this.setSelectedOption(option)
                    input && input.set(option.value)
                    onSelect && onSelect(option)
                }
            ),
            this.select$.pipe(
                delay(SELECTION_DELAY_MS)
            ).subscribe(
                () => this.setState({selected: false}, this.hideOptions)
            )
        )
    }

    handleBlur(e) {
        const isInputClick = e => this.input.current && this.input.current.contains(e.target)
        const isListClick = e => this.list.current && this.list.current.contains && this.list.current.contains(e.target)
        if (!isInputClick(e) && !isListClick(e)) {
            this.hideOptions()
        }
    }

    componentDidMount() {
        this.handleSelect()
    }

    static getDerivedStateFromProps(props, state) {
        const {input} = props
        const {flattenedOptions} = state
        return input
            ? {
                selectedOption: _.find(flattenedOptions, option => option.value === input.value)
            }
            : null
    }

    componentDidUpdate() {
        this.updateOptions()
    }

    updateOptions() {
        const {options} = this.props
        const getFlattenedOptions = options =>
            _.flatten(
                options.map(option =>
                    option.options
                        ? [{..._.omit(option, 'options'), group: true}, ...option.options]
                        : option
                )
            )
        this.updateState({
            flattenedOptions: getFlattenedOptions(options)
        })
    }
}

export default compose(
    ButtonSelect,
    withSubscriptions(),
    connect(mapStateToProps)
)

ButtonSelect.propTypes = {
    options: PropTypes.any.isRequired,
    chromeless: PropTypes.any,
    className: PropTypes.string,
    disabled: PropTypes.any,
    icon: PropTypes.string,
    input: PropTypes.any,
    label: PropTypes.any,
    look: PropTypes.string,
    optionsClassName: PropTypes.string,
    optionTooltipPlacement: PropTypes.string,
    placement: PropTypes.oneOf(['above', 'below']),
    shape: PropTypes.string,
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    width: PropTypes.string,
    onClick: PropTypes.func,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func,
    onSelect: PropTypes.func
}

ButtonSelect.defaultProps = {
    placement: 'below'
}
<commit_msg>Allowed ButtonSelect to use option label as label.<commit_after>import {Button} from 'widget/button'
import {ButtonGroup} from './buttonGroup'
import {ScrollableList} from 'widget/list'
import {Subject, delay} from 'rxjs'
import {compose} from 'compose'
import {connect} from 'store'
import {selectFrom} from 'stateUtils'
import FloatingBox from 'widget/floatingBox'
import Icon from 'widget/icon'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './buttonSelect.module.css'
import withSubscriptions from 'subscription'

const SELECTION_DELAY_MS = 350

const mapStateToProps = state => ({
    dimensions: selectFrom(state, 'dimensions') || []
})

class ButtonSelect extends React.Component {
    input = React.createRef()
    list = React.createRef()
    select$ = new Subject()
    state = {
        showOptions: false,
        flattenedOptions: [],
        selectedOption: null,
        selected: false
    }

    constructor() {
        super()
        this.handleBlur = this.handleBlur.bind(this)
    }

    render() {
        const {className} = this.props
        const {showOptions} = this.state
        return (

                {this.renderButton()}
                {showOptions ? this.renderOptions() : null}

        )
    }

    renderButton() {
        const {onClick} = this.props
        return onClick
            ? this.renderMultiButton()
            : this.renderSingleButton()
    }

    renderSingleButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onMouseOver, onMouseOut} = this.props
        return (
            <Button
                ref={this.input}
                chromeless={chromeless}
                shape={shape}
                look={look}
                icon={icon}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}
                width={width}
                onClick={() => this.toggleOptions()}
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}
                disabled={disabled}
                label={this.getLabel()}
                tail={
                    <Icon name={this.getChevronIcon()}/>
                }
            />
        )
    }

    renderMultiButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onClick, onMouseOver, onMouseOut} = this.props
        return (
            <ButtonGroup
                ref={this.input}
                spacing='tight'
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}
            >
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={icon}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={e => onClick && onClick(e)}
                    disabled={disabled}
                    label={this.getLabel()}
                />
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={this.getChevronIcon()}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={() => this.toggleOptions()}
                    disabled={disabled}
                />
            </ButtonGroup>
        )
    }

    getLabel() {
        const {label} = this.props
        const {selectedOption} = this.state
        return (selectedOption && (selectedOption.buttonLabel || selectedOption.label)) || label
    }

    getChevronIcon() {
        const {placement} = this.props
        return placement === 'above' ? 'chevron-up' : 'chevron-down'
    }

    renderOptions() {
        const {placement, optionsClassName, optionTooltipPlacement} = this.props
        const {flattenedOptions, selectedOption, selected} = this.state
        return (
            <FloatingBox
                element={this.input.current}
                placement={placement}
                alignment='left'
                onBlur={this.handleBlur}>
                <ScrollableList
                    ref={this.list}
                    className={optionsClassName || styles.options}
                    options={flattenedOptions}
                    selectedOption={selectedOption}
                    onSelect={option => this.select$.next(option)}
                    onCancel={() => this.hideOptions()}
                    autoCenter={!selected}
                    tooltipPlacement={optionTooltipPlacement}
                    air='more'
                    keyboard
                />
            </FloatingBox>
        )
    }

    toggleOptions() {
        const {showOptions} = this.state
        showOptions
            ? this.hideOptions()
            : this.showOptions()
    }

    showOptions() {
        this.setState({showOptions: true})
    }

    hideOptions() {
        this.setState({showOptions: false, selectedOption: null})
    }

    setSelectedOption(selectedOption) {
        this.updateState({
            selectedOption,
            selected: true
        })
    }

    updateState(state, callback) {
        const updatedState = (prevState, state) =>
            _.isEqual(_.pick(prevState, _.keys(state)), state) ? null : state
        this.setState(
            prevState =>
                updatedState(prevState, _.isFunction(state) ? state(prevState) : state),
            callback
        )
    }

    handleSelect() {
        const {input, onSelect, addSubscription} = this.props
        addSubscription(
            this.select$.subscribe(
                option => {
                    this.setSelectedOption(option)
                    input && input.set(option.value)
                    onSelect && onSelect(option)
                }
            ),
            this.select$.pipe(
                delay(SELECTION_DELAY_MS)
            ).subscribe(
                () => this.setState({selected: false}, this.hideOptions)
            )
        )
    }

    handleBlur(e) {
        const isInputClick = e => this.input.current && this.input.current.contains(e.target)
        const isListClick = e => this.list.current && this.list.current.contains && this.list.current.contains(e.target)
        if (!isInputClick(e) && !isListClick(e)) {
            this.hideOptions()
        }
    }

    componentDidMount() {
        this.handleSelect()
    }

    static getDerivedStateFromProps(props, state) {
        const {input} = props
        const {flattenedOptions} = state
        return input
            ? {
                selectedOption: _.find(flattenedOptions, option => option.value === input.value)
            }
            : null
    }

    componentDidUpdate() {
        this.updateOptions()
    }

    updateOptions() {
        const {options} = this.props
        const getFlattenedOptions = options =>
            _.flatten(
                options.map(option =>
                    option.options
                        ? [{..._.omit(option, 'options'), group: true}, ...option.options]
                        : option
                )
            )
        this.updateState({
            flattenedOptions: getFlattenedOptions(options)
        })
    }
}

export default compose(
    ButtonSelect,
    withSubscriptions(),
    connect(mapStateToProps)
)

ButtonSelect.propTypes = {
    options: PropTypes.any.isRequired,
    chromeless: PropTypes.any,
    className: PropTypes.string,
    disabled: PropTypes.any,
    icon: PropTypes.string,
    input: PropTypes.any,
    label: PropTypes.any,
    look: PropTypes.string,
    optionsClassName: PropTypes.string,
    optionTooltipPlacement: PropTypes.string,
    placement: PropTypes.oneOf(['above', 'below']),
    shape: PropTypes.string,
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    width: PropTypes.string,
    onClick: PropTypes.func,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func,
    onSelect: PropTypes.func
}

ButtonSelect.defaultProps = {
    placement: 'below'
}
<|endoftext|>


<commit_before>
import { config } from '../config';
import { loadScript } from '../lib';
import { BUTTON_JS_URL } from './constants';
import { logDebug, logError } from './log';
import { eachElement } from './util';

let buttonJS;

function loadButtonJS() {

    if (buttonJS) {
        return buttonJS;
    }

    logDebug(`buttonjs_load`);

    buttonJS = loadScript(BUTTON_JS_URL);

    return buttonJS.then(result => {
        logDebug(`buttonjs_load_success`);
        return result;
    }).catch(err => {
        logError(`buttonjs_load_error`, { error: err.stack || err.toString() });
        throw err;
    });
}

function renderButton(id, container, options, label) {

    let buttonDom = window.paypal.button.create(id, {
        lc:    options.locale || `${config.locale.lang}_${config.locale.country}`,
        color: options.color  || 'gold',
        shape: options.shape  || 'pill',
        size:  options.size   || 'small'
    }, {
        label: label || 'checkout',
        type: 'button'
    });

    container.appendChild(buttonDom.el);

    return buttonDom.el.childNodes[0];
}

export function renderButtons(id, options) {

    return loadButtonJS().then(() => {

        let buttons = [];

        if (options.container) {

            let labels = [];

            if (typeof options.type === 'string') {
                labels.push(options.type);
            } else if (options.type instanceof Array) {
                labels = options.type;
            }

            eachElement(options.container, (container, i) => {
                buttons.push({
                    el: renderButton(id, container, options, labels[i]),
                    click: options.click,
                    condition: options.condition
                });
            });
        }

        if (options.buttons instanceof Array) {
            options.buttons.forEach(button => {
                if (button) {
                    button.click = button.click || options.click;
                    eachElement(button.container, container => {
                        buttons.push({
                            el: renderButton(id, container, button, button.type),
                            click: button.click || options.click,
                            condition: button.condition || options.condition
                        });
                    });
                }
            });
        }

        return buttons;
    });
}
<commit_msg>Add logging for button render type<commit_after>
import { config } from '../config';
import { loadScript } from '../lib';
import { BUTTON_JS_URL } from './constants';
import { logDebug, logError } from './log';
import { eachElement } from './util';

let buttonJS;

function loadButtonJS() {

    if (buttonJS) {
        return buttonJS;
    }

    logDebug(`buttonjs_load`);

    buttonJS = loadScript(BUTTON_JS_URL);

    return buttonJS.then(result => {
        logDebug(`buttonjs_load_success`);
        return result;
    }).catch(err => {
        logError(`buttonjs_load_error`, { error: err.stack || err.toString() });
        throw err;
    });
}

function renderButton(id, container, options, label) {

    let lc    = options.locale || `${config.locale.lang}_${config.locale.country}`;
    let color = options.color  || 'gold';
    let shape = options.shape  || 'pill';
    let size  = options.size   || 'small';

    let type = 'button';
    label = label || 'checkout';

    logDebug(`render_button_lc_${lc}`);
    logDebug(`render_button_color_${color}`);
    logDebug(`render_button_shape_${shape}`);
    logDebug(`render_button_size_${size}`);
    logDebug(`render_button_label_${label}`);

    let buttonDom = window.paypal.button.create(id, { lc, color, shape, size }, { type, label });
    container.appendChild(buttonDom.el);
    return buttonDom.el.childNodes[0];
}

export function renderButtons(id, options) {

    return loadButtonJS().then(() => {

        let buttons = [];

        if (options.container) {

            let labels = [];

            if (typeof options.type === 'string') {
                labels.push(options.type);
            } else if (options.type instanceof Array) {
                labels = options.type;
            }

            eachElement(options.container, (container, i) => {
                buttons.push({
                    el: renderButton(id, container, options, labels[i]),
                    click: options.click,
                    condition: options.condition
                });
            });
        }

        if (options.buttons instanceof Array) {
            options.buttons.forEach(button => {
                if (button) {
                    button.click = button.click || options.click;
                    eachElement(button.container, container => {
                        buttons.push({
                            el: renderButton(id, container, button, button.type),
                            click: button.click || options.click,
                            condition: button.condition || options.condition
                        });
                    });
                }
            });
        }

        return buttons;
    });
}
<|endoftext|>


<commit_before>// @flow

import type {
  EncodedHttpRequest,
  Id,
  QueryStringParams,
  RequestData,
} from 'phenyl-interfaces'

/**
 *
 */
export default function decodeRequest(request: EncodedHttpRequest): [RequestData, ?Id] {
  let reqData: RequestData
  const sessionId = request.headers.Authorization || null
  switch (request.method) {
    case 'GET':
      reqData = decodeGETRequest(request)
      break

    case 'POST':
      reqData = decodePOSTRequest(request)
      break

    case 'PUT':
      reqData = decodePUTRequest(request)
      break

    case 'DELETE':
      reqData = decodeDELETERequest(request)
      break
  }
  // $FlowIssue(reqData-is-always-initialized)
  return [reqData, sessionId]
}

function decodeGETRequest(request: EncodedHttpRequest): RequestData {
  const {
    path,
    qsParams,
  } = request

  const paths = path.split('/') // path[0] must be an empty string.

  if (qsParams == null || Object.keys(qsParams).length === 0) {
    return {
      method: 'get',
      payload: { entityName: paths[1], id: paths[2] }
    }
  }
  const methodName = paths[2]

  if (!methodName) {
    return {
      method: 'runCustomQuery',
      payload: decodeQsParams(qsParams)
    }
  }

  if (methodName === 'find') {
    return {
      method: 'find',
      payload: decodeQsParams(qsParams)
    }
  }

  if (methodName === 'findOne') {
    return {
      method: 'findOne',
      payload: decodeQsParams(qsParams)
    }
  }

  if (methodName === 'getByIds') {
    return {
      method: 'getByIds',
      payload: decodeQsParams(qsParams)
    }
  }
  throw new Error(`Could not decode the given GET request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodePOSTRequest(request: EncodedHttpRequest): RequestData {
  const {
    headers,
    path,
    body
  } = request

  if (!body) {
    throw new Error(`Request body is empty in the given POST request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
  }

  if (headers['X-Phenyl-Custom']) {
    return {
      method: 'runCustomCommand',
      payload: decodeBody(body),
    }
  }

  if (path === '/login') {
    return {
      method: 'login',
      payload: decodeBody(body),
    }
  }

  if (path === '/logout') {
    return {
      method: 'logout',
      payload: decodeBody(body),
    }
  }
  const paths = path.split('/')
  const methodName = paths[2]

  if (methodName === 'insert') {
    return {
      method: 'insert',
      payload: decodeBody(body),
    }
  }

  if (methodName === 'insertAndGet') {
    return {
      method: 'insertAndGet',
      payload: decodeBody(body),
    }
  }
  if (methodName === 'insertAndGetMulti') {
    return {
      method: 'insertAndGetMulti',
      payload: decodeBody(body),
    }
  }
  throw new Error(`Could not decode the given POST request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodePUTRequest(request: EncodedHttpRequest): RequestData {
  const {
    path,
    body
  } = request

  if (!body) {
    throw new Error(`Request body is empty in the given PUT request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
  }

  const paths = path.split('/')
  const methodName = paths[2]
  if (methodName === 'update') {
    return {
      method: 'update',
      payload: decodeBody(body),
    }
  }

  if (methodName === 'updateAndGet') {
    return {
      method: 'updateAndGet',
      payload: decodeBody(body),
    }
  }
  if (methodName === 'updateAndFetch') {
    return {
      method: 'updateAndFetch',
      payload: decodeBody(body),
    }
  }
  throw new Error(`Could not decode the given PUT request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodeDELETERequest(request: EncodedHttpRequest): RequestData {
  const {
    path,
    qsParams,
  } = request

  const paths = path.split('/')

  // multi deletion
  if (paths[2] === 'delete' && qsParams) {
    return {
      method: 'delete',
      payload: decodeQsParams(qsParams),
    }
  }

  if (paths[1] && paths[2]) {
    // single deletion
    return {
      method: 'delete',
      payload: {
        entityName: paths[1],
        id: paths[2],
      }
    }
  }
  throw new Error(`Could not decode the given DELETE request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodeBody(body: string): any { // return "any" type for suppressing flow error
  return JSON.parse(body)
}

function decodeQsParams(qsParams: QueryStringParams): any { // return "any" type for suppressing flow error
  return JSON.parse(qsParams.d)
}
<commit_msg>[phenyl-http-rules] throw error when unknown HTTP method is given<commit_after>// @flow

import type {
  EncodedHttpRequest,
  Id,
  QueryStringParams,
  RequestData,
} from 'phenyl-interfaces'

/**
 *
 */
export default function decodeRequest(request: EncodedHttpRequest): [RequestData, ?Id] {
  let reqData: RequestData
  const sessionId = request.headers.Authorization || null
  switch (request.method) {
    case 'GET':
      reqData = decodeGETRequest(request)
      break

    case 'POST':
      reqData = decodePOSTRequest(request)
      break

    case 'PUT':
      reqData = decodePUTRequest(request)
      break

    case 'DELETE':
      reqData = decodeDELETERequest(request)
      break
    default:
      throw new Error(`Could not handle HTTP method: ${request.method}. Only GET|POST|PUT|DELETE are allowed.`)
  }
  return [reqData, sessionId]
}

function decodeGETRequest(request: EncodedHttpRequest): RequestData {
  const {
    path,
    qsParams,
  } = request

  const paths = path.split('/') // path[0] must be an empty string.

  if (qsParams == null || Object.keys(qsParams).length === 0) {
    return {
      method: 'get',
      payload: { entityName: paths[1], id: paths[2] }
    }
  }
  const methodName = paths[2]

  if (!methodName) {
    return {
      method: 'runCustomQuery',
      payload: decodeQsParams(qsParams)
    }
  }

  if (methodName === 'find') {
    return {
      method: 'find',
      payload: decodeQsParams(qsParams)
    }
  }

  if (methodName === 'findOne') {
    return {
      method: 'findOne',
      payload: decodeQsParams(qsParams)
    }
  }

  if (methodName === 'getByIds') {
    return {
      method: 'getByIds',
      payload: decodeQsParams(qsParams)
    }
  }
  throw new Error(`Could not decode the given GET request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodePOSTRequest(request: EncodedHttpRequest): RequestData {
  const {
    headers,
    path,
    body
  } = request

  if (!body) {
    throw new Error(`Request body is empty in the given POST request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
  }

  if (headers['X-Phenyl-Custom']) {
    return {
      method: 'runCustomCommand',
      payload: decodeBody(body),
    }
  }

  if (path === '/login') {
    return {
      method: 'login',
      payload: decodeBody(body),
    }
  }

  if (path === '/logout') {
    return {
      method: 'logout',
      payload: decodeBody(body),
    }
  }
  const paths = path.split('/')
  const methodName = paths[2]

  if (methodName === 'insert') {
    return {
      method: 'insert',
      payload: decodeBody(body),
    }
  }

  if (methodName === 'insertAndGet') {
    return {
      method: 'insertAndGet',
      payload: decodeBody(body),
    }
  }
  if (methodName === 'insertAndGetMulti') {
    return {
      method: 'insertAndGetMulti',
      payload: decodeBody(body),
    }
  }
  throw new Error(`Could not decode the given POST request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodePUTRequest(request: EncodedHttpRequest): RequestData {
  const {
    path,
    body
  } = request

  if (!body) {
    throw new Error(`Request body is empty in the given PUT request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
  }

  const paths = path.split('/')
  const methodName = paths[2]
  if (methodName === 'update') {
    return {
      method: 'update',
      payload: decodeBody(body),
    }
  }

  if (methodName === 'updateAndGet') {
    return {
      method: 'updateAndGet',
      payload: decodeBody(body),
    }
  }
  if (methodName === 'updateAndFetch') {
    return {
      method: 'updateAndFetch',
      payload: decodeBody(body),
    }
  }
  throw new Error(`Could not decode the given PUT request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodeDELETERequest(request: EncodedHttpRequest): RequestData {
  const {
    path,
    qsParams,
  } = request

  const paths = path.split('/')

  // multi deletion
  if (paths[2] === 'delete' && qsParams) {
    return {
      method: 'delete',
      payload: decodeQsParams(qsParams),
    }
  }

  if (paths[1] && paths[2]) {
    // single deletion
    return {
      method: 'delete',
      payload: {
        entityName: paths[1],
        id: paths[2],
      }
    }
  }
  throw new Error(`Could not decode the given DELETE request. Request = \n${JSON.stringify(request, null, 2)}\n\n`)
}

function decodeBody(body: string): any { // return "any" type for suppressing flow error
  return JSON.parse(body)
}

function decodeQsParams(qsParams: QueryStringParams): any { // return "any" type for suppressing flow error
  return JSON.parse(qsParams.d)
}
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare",
	"dojo/dom-construct",
	"dijit/_WidgetBase",
	"dijit/form/_FormValueMixin",
	"dijit/form/_TextBoxMixin"
], function(declare, domConstruct, WidgetBase, FormValueMixin, TextBoxMixin){

	return declare("dojox.mobile.TextBox",[WidgetBase, FormValueMixin, TextBoxMixin],{
		// summary:
		//		A non-templated base class for textbox form inputs

		baseClass: "mblTextBox",

		// Override automatic assigning type --> node, it causes exception on IE8.
		// Instead, type must be specified as this.type when the node is created, as part of the original DOM
		_setTypeAttr: null,

		// Map widget attributes to DOMNode attributes.
		_setPlaceHolderAttr: function(/*String*/value){
			value = this._cv ? this._cv(value) : value;
			this.textbox.setAttribute("placeholder", value);
		},

		buildRendering: function(){
			if(!this.srcNodeRef){
				this.srcNodeRef = domConstruct.create("input", {"type":this.type});
			}
			this.inherited(arguments);
			this.textbox = this.focusNode = this.domNode;
		},

		postCreate: function(){
			this.inherited(arguments);
			this.connect(this.textbox, "onmouseup", function(){ this._mouseIsDown = false; });
			this.connect(this.textbox, "onmousedown", function(){ this._mouseIsDown = true; });
			this.connect(this.textbox, "onfocus", function(e){
				this._onFocus(this._mouseIsDown ? "mouse" : e);
				this._mouseIsDown = false;
			});
			this.connect(this.textbox, "onblur", "_onBlur");
		}
	});
});
<commit_msg>Fixes #16154.  Set widget placeHolder value as well as textbox attribute. Refs #15354.<commit_after>define([
	"dojo/_base/declare",
	"dojo/dom-construct",
	"dijit/_WidgetBase",
	"dijit/form/_FormValueMixin",
	"dijit/form/_TextBoxMixin"
], function(declare, domConstruct, WidgetBase, FormValueMixin, TextBoxMixin){

	return declare("dojox.mobile.TextBox",[WidgetBase, FormValueMixin, TextBoxMixin],{
		// summary:
		//		A non-templated base class for textbox form inputs

		baseClass: "mblTextBox",

		// Override automatic assigning type --> node, it causes exception on IE8.
		// Instead, type must be specified as this.type when the node is created, as part of the original DOM
		_setTypeAttr: null,

		// Map widget attributes to DOMNode attributes.
		_setPlaceHolderAttr: function(/*String*/value){
			value = this._cv ? this._cv(value) : value;
			this._set("placeHolder", value);
			this.textbox.setAttribute("placeholder", value);
		},

		buildRendering: function(){
			if(!this.srcNodeRef){
				this.srcNodeRef = domConstruct.create("input", {"type":this.type});
			}
			this.inherited(arguments);
			this.textbox = this.focusNode = this.domNode;
		},

		postCreate: function(){
			this.inherited(arguments);
			this.connect(this.textbox, "onmouseup", function(){ this._mouseIsDown = false; });
			this.connect(this.textbox, "onmousedown", function(){ this._mouseIsDown = true; });
			this.connect(this.textbox, "onfocus", function(e){
				this._onFocus(this._mouseIsDown ? "mouse" : e);
				this._mouseIsDown = false;
			});
			this.connect(this.textbox, "onblur", "_onBlur");
		}
	});
});
<|endoftext|>