<commit_before>/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2014 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
(function() {

var ui = angular.module('axelor.ui');

DashboardCtrl.$inject = ['$scope', '$element'];
function DashboardCtrl($scope, $element) {

	var view = $scope._views['dashboard'];
	if (view.items) {
		$scope.$timeout(function () {
			$scope.parse(view);
		});
	} else {
		$scope.loadView('dashboard', view.name).success(function(fields, schema){
			$scope.parse(schema);
		});
	}

	$scope.applyLater(function(){
		if (view.deferred)
			view.deferred.resolve($scope);
	}, 0);

	$scope.show = function(promise) {
		$scope.updateRoute();
	};

	$scope.onShow = function() {

	};

	$scope.getContext = function() {
		return _.extend({}, $scope._context);
	};

	$scope.getRouteOptions = function() {
		return {
			mode: 'dashboard',
			args: []
		};
	};

	$scope.setRouteOptions = function(options) {
		if (!$scope.isNested) {
			$scope.updateRoute();
		}
	};

	$scope.parse = function(schema) {
		var items = schema.items || [];
		var rows = [[]];
		var last = _.last(rows);
		var lastCol = 0;

		items.forEach(function (item) {
			var span = item.colSpan || 6;

			if (lastCol + span > 12) {
				lastCol = 0;
				last = [];
				rows.push(last);
			}

			item.spanCss = {};
			item.spanCss['dashlet-cs' + span] = true;

			last.push(item);
			lastCol += span;
		});

		$scope.rows = rows;
	};
}

ui.directive('uiViewDashboard', ['$compile', function($compile) {

	return {
		scope: true,
		controller: DashboardCtrl,
		link: function(scope, element, attrs) {

		},
		replace: true,
		transclude: true,
		template:
		"
" +
			"
" +
				"
" +
					"

" +
				"
" +
			"
" +
		"
"
	};
}]);

DashletCtrl.$inject = ['$scope', '$element', 'MenuService', 'DataSource', 'ViewService'];
function DashletCtrl($scope, $element, MenuService, DataSource, ViewService) {

	var self = this;

	function init() {

		ViewCtrl.call(self, $scope, DataSource, ViewService);

		$scope.show = function() {

		};

		$scope.onShow = function() {

		};
	}

	function doLoad(dashlet) {

		var action = dashlet.action;
		if (!action) {
			return init();
		}

		MenuService.action(action).success(function(result){
			if (_.isEmpty(result.data)) {
				return;
			}
			var view = result.data[0].view;

			$scope._viewParams = view;
			$scope._viewAction = action;

			init();

			$scope.title = dashlet.title || view.title;
			$scope.parseDashlet(dashlet, view);
		});
	};

	var unwatch;
	unwatch = $scope.$watch('dashlet', function (dashlet) {
		if (dashlet) {
			doLoad(dashlet);
			unwatch();
		}
	});

	$scope.$on('on:attrs-change:refresh', function(e) {
		e.preventDefault();
		if ($scope.onRefresh) {
			$scope.onRefresh();
		}
	});
}

ui.directive('uiViewDashlet', ['$compile', function($compile){
	return {
		scope: true,
		controller: DashletCtrl,
		link: function(scope, element, attrs) {

			var body = element.find('.dashlet-body:first');

			scope.parseDashlet = _.once(function(dashlet, view) {

				var template = $('

');

				scope.noFilter = dashlet.canSearch != "true";

				template = $compile(template)(scope);
				body.append(template);

				element.removeClass('hidden');

				scope.show();
			});

			scope.onDashletToggle = function(event) {
				var e = $(event.target);
				e.toggleClass('fa-chevron-up fa-chevron-down');
				element.toggleClass('dashlet-minimized');
				if (e.hasClass('fa-chevron-up')) {
					axelor.$adjustSize();
				}
			};

			scope.doNext = function() {
				if (this.canNext()) this.onNext();
			};

			scope.doPrev = function() {
				if (this.canPrev()) this.onPrev();
			};
		},
		replace: true,
		template:
			"
" +
				"
" +
					"
{{title}}
" +
					"
" +
						"" +
					"
" +
					"
" +
						"{{pagerText()}}" +
						"" +
						"" +
					"
" +
				"
" +
				"

" +
			"
"
	};
}]);

})();<commit_msg>Fix dashlet filter issue<commit_after>/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2014 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
(function() {

var ui = angular.module('axelor.ui');

DashboardCtrl.$inject = ['$scope', '$element'];
function DashboardCtrl($scope, $element) {

	var view = $scope._views['dashboard'];
	if (view.items) {
		$scope.$timeout(function () {
			$scope.parse(view);
		});
	} else {
		$scope.loadView('dashboard', view.name).success(function(fields, schema){
			$scope.parse(schema);
		});
	}

	$scope.applyLater(function(){
		if (view.deferred)
			view.deferred.resolve($scope);
	}, 0);

	$scope.show = function(promise) {
		$scope.updateRoute();
	};

	$scope.onShow = function() {

	};

	$scope.getContext = function() {
		return _.extend({}, $scope._context);
	};

	$scope.getRouteOptions = function() {
		return {
			mode: 'dashboard',
			args: []
		};
	};

	$scope.setRouteOptions = function(options) {
		if (!$scope.isNested) {
			$scope.updateRoute();
		}
	};

	$scope.parse = function(schema) {
		var items = schema.items || [];
		var rows = [[]];
		var last = _.last(rows);
		var lastCol = 0;

		items.forEach(function (item) {
			var span = item.colSpan || 6;

			if (lastCol + span > 12) {
				lastCol = 0;
				last = [];
				rows.push(last);
			}

			item.spanCss = {};
			item.spanCss['dashlet-cs' + span] = true;

			last.push(item);
			lastCol += span;
		});

		$scope.rows = rows;
	};
}

ui.directive('uiViewDashboard', ['$compile', function($compile) {

	return {
		scope: true,
		controller: DashboardCtrl,
		link: function(scope, element, attrs) {

		},
		replace: true,
		transclude: true,
		template:
		"
" +
			"
" +
				"
" +
					"

" +
				"
" +
			"
" +
		"
"
	};
}]);

DashletCtrl.$inject = ['$scope', '$element', 'MenuService', 'DataSource', 'ViewService'];
function DashletCtrl($scope, $element, MenuService, DataSource, ViewService) {

	var self = this;

	function init() {

		ViewCtrl.call(self, $scope, DataSource, ViewService);

		$scope.show = function() {

		};

		$scope.onShow = function() {

		};
	}

	function doLoad(dashlet) {

		var action = dashlet.action;
		if (!action) {
			return init();
		}

		MenuService.action(action).success(function(result){
			if (_.isEmpty(result.data)) {
				return;
			}
			var view = result.data[0].view;

			$scope._viewParams = view;
			$scope._viewAction = action;

			init();

			$scope.title = dashlet.title || view.title;
			$scope.parseDashlet(dashlet, view);
		});
	};

	var unwatch;
	unwatch = $scope.$watch('dashlet', function (dashlet) {
		if (dashlet) {
			doLoad(dashlet);
			unwatch();
		}
	});

	$scope.$on('on:attrs-change:refresh', function(e) {
		e.preventDefault();
		if ($scope.onRefresh) {
			$scope.onRefresh();
		}
	});
}

ui.directive('uiViewDashlet', ['$compile', function($compile){
	return {
		scope: true,
		controller: DashletCtrl,
		link: function(scope, element, attrs) {

			var body = element.find('.dashlet-body:first');

			scope.parseDashlet = _.once(function(dashlet, view) {

				var template = $('

');

				scope.noFilter = !dashlet.canSearch;

				template = $compile(template)(scope);
				body.append(template);

				element.removeClass('hidden');

				scope.show();
			});

			scope.onDashletToggle = function(event) {
				var e = $(event.target);
				e.toggleClass('fa-chevron-up fa-chevron-down');
				element.toggleClass('dashlet-minimized');
				if (e.hasClass('fa-chevron-up')) {
					axelor.$adjustSize();
				}
			};

			scope.doNext = function() {
				if (this.canNext()) this.onNext();
			};

			scope.doPrev = function() {
				if (this.canPrev()) this.onPrev();
			};
		},
		replace: true,
		template:
			"
" +
				"
" +
					"
{{title}}
" +
					"
" +
						"" +
					"
" +
					"
" +
						"{{pagerText()}}" +
						"" +
						"" +
					"
" +
				"
" +
				"

" +
			"
"
	};
}]);

})();<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global $, jQuery, Handlebars, google*/

(function () {
    "use strict";

    // When included akvo-maps.js will query the page for elements with
    // class ".akvo_map". These elements should be generated by the maps
    // Django template tag. Each map element will have a div element and
    // a JavaScript literal with data which are used to create a map with
    // corresponding locations from the RSR API
    // There are currently three kinds of maps:
    //      "static" is used on the RSR home page where we want a world map with small markers
    //      "small" is used for the single object maps for projects and organisations
    //      "dynamic" are the large all-object maps for projects and organisations

    var addMap, addPin, populateMap, mapOptions, prepareNextRequest, getResourceUrl;

    // For each .akvo_map element on the page, read options
    // and kick of the creation of a new map
    $(document).ready(function () {
        $('.akvo_map').each(function () {
            var mapId = $(this).attr('id');
            addMap({
                mapId: mapId,
                mapElement: document.getElementById(mapId),
                mapOpts: window[mapId]
            });
        });
    });

    // Creates the map with options and makes the initial AJAX request
    addMap = function (map) {
        $(map.mapElement).gmap(mapOptions(map.mapOpts.type)).bind('init', function () {
            $.getJSON(getResourceUrl(map), function (data) {
                populateMap(map, data);
            });
        });
    };

    // Creates resource URLS based on map options
    getResourceUrl = function (map) {
        var opts, url, limit;
        opts = map.mapOpts;
        // call /api/v1/map_for_project/ or /api/v1/map_for_organisation/ resources
        //TODO: derive the host from the current page URL instead maybe?
        url = opts.host + 'api/v1/map_for_' + opts.resource + '/';
        //limit = 0 means all objects. If this becomes too heavy limit can be set to get the objects in multiple chunks
        limit = 0;
        // if object_id holds a value then that's the ID of the object we want to fetch
        if (opts.object_id) {
            url += opts.object_id + '/?format=jsonp&depth=1&callback=?';
        // otherwise we want all objects of the resource's type
        } else {
            url += '?format=jsonp&limit=' + limit + '&callback=?';
        }
        return url;
    };

    // Populates the map with data
    populateMap = function (map, data) {
        var objects, opts, pinTmpl, addOrganisationData, addProjectData;
        opts = map.mapOpts;

        // Since API resources that list multiple objects (projects or organisations) include
        // an objects array we need to add the single project or organisation to an array. This Since
        // we want to keep using the same logic for both cases
        if (opts.object_id === "") {
            objects = data.objects;
        } else {
            objects = [data];
        }

        pinTmpl = Handlebars.compile(
            '
' +
                '{{title}}' +
                '{{#if thumb}}' +
                    '
' +
                        '' +
                            '' +
                        '' +
                    '
' +
                '{{/if}}' +
                '
');

        // populate the location object with data from an Organisation model object
        addOrganisationData = function (object, location) {
            location.url = object.absolute_url;
            location.title = object.name;
            try {
                location.thumb = object.logo.thumbnails.map_thumb;
            } catch (e0) { location.thumb = ''; }
            return location;
        };

        // populate the location object with data from a Project model object
        addProjectData = function (object, location) {
            location.url = object.absolute_url;
            location.title = object.title;
            try {
                location.thumb = object.current_image.thumbnails.map_thumb;
            } catch (e1) { location.thumb = ''; }
            return location;
        };

        $.each(objects, function (i, object) {
            // for single objects show all locations
            if (opts.object_id) {
                $.each(object.locations, function (k, location) {
                    //TODO: extend this for additional resource types
                    if (opts.resource === 'organisation') {
                        location = addOrganisationData(object, location);
                    } else {
                        location = addProjectData(object, location);
                    }
                    addPin(map, location, pinTmpl);
                });
            // if we're displaying multiple objects we only show the primary locations
            } else {
                var location;
                location = object.primary_location;
                if (location) {
                    if (opts.resource === 'organisation') {
                        location = addOrganisationData(object, location);
                    } else {
                        location = addProjectData(object, location);
                    }
                    addPin(map, location, pinTmpl);
                }
            }
        });

        // If we are rendering multiple objects and there are more objects to
        // grab from the API
        if (isNaN(opts.object) && data.meta.next !== null) {
            prepareNextRequest(map, data.meta.next);
        }
    };

    // Add a single pin
    addPin = function (map, location, template) {
        var marker, opts;
        opts = map.mapOpts;
        marker = opts.host + 'rsr/media/core/img/';

        // get a custom marker if there is one, otherwise it's red for organisations and blue for projects
        if (opts.marker_icon) {
            marker = marker + opts.marker_icon;
        } else if (opts.resource === 'organisation') {
            marker = marker + 'redMarker.png';
        } else {
            marker = marker + 'blueMarker.png';
        }

        if (opts.type === 'static' || opts.type === 'small') {
            // shrink the marker for "static" maps
            if (opts.type === 'static') {
                marker = new google.maps.MarkerImage(marker, null, null, null, new google.maps.Size(10.5, 17));
            }
            $(map.mapElement).gmap('addMarker', {
                'position': new google.maps.LatLng(location.latitude, location.longitude),
                'clickable': false,
                'icon': marker,
                'bounds': true
            });
            // if the map is zoomed in a lot we zoom out a bit
            if ($(map.mapElement).gmap('get', 'map').getZoom() > 8) {
                $(map.mapElement).gmap('get', 'map').setZoom(8);
            }
        // "dynamic"
        } else {
            $(map.mapElement).gmap('addMarker', {
                'position': new google.maps.LatLng(location.latitude, location.longitude),
                'icon': marker,
                'bounds': true
            }).click(function () {
                $(map.mapElement).gmap('openInfoWindow', {
                    'content': template(location)
                }, this);
            });
        }
    };

    // Since we need to update the callback parameters we don't use the meta.next
    // but create a new resource url
    prepareNextRequest = function (map, resource) {
        var url = $.url(resource),
            urlTmpl = Handlebars.compile('{{host}}{{path}}?format=jsonp&depth=1&limit=' +
                '{{limit}}&offset={{offset}}&callback=?'),
            newUrl = urlTmpl({
                'host': url.attr('host'),
                'path': url.attr('path'),
                'limit': Number(url.param('limit')),
                'offset': Number(url.param('offset'))
            });
        $.getJSON(newUrl, function (data) {
            populateMap(map, data);
        });
    };

    mapOptions = function (mapType) {
        var options;
        // "static" and "small" are set to zoom 0 to begin with so that you see a world map until it has been populated
        // scroll wheel zoom is only enabled for the large "dynamic" maps
        if (mapType === 'static') {
            options = {
                'draggable': false,
                'mapTypeControl': false,
                'navigationControl': true,
                'scaleControl': false,
                'scrollwheel': false,
                'streetViewControl': false,
                'zoom': 0
            };
        } else if (mapType === 'small') {
            options = {
                'draggable': true,
                'mapTypeControl': false,
                'navigationControl': true,
                'scaleControl': true,
                'scrollwheel': false,
                'streetViewControl': false,
                'zoom': 0
            };
        } else {
            options = {
                'draggable': true,
                'mapTypeControl': true,
                'navigationControl': true,
                'scaleControl': true,
                'scrollwheel': true,
                'streetViewControl': false,
                'zoom': 2
            };
        }
        return options;
    };
}());
<commit_msg>Put back limit=100 for global maps<commit_after>/*jslint browser: true*/
/*global $, jQuery, Handlebars, google*/

(function () {
    "use strict";

    // When included akvo-maps.js will query the page for elements with
    // class ".akvo_map". These elements should be generated by the maps
    // Django template tag. Each map element will have a div element and
    // a JavaScript literal with data which are used to create a map with
    // corresponding locations from the RSR API
    // There are currently three kinds of maps:
    //      "static" is used on the RSR home page where we want a world map with small markers
    //      "small" is used for the single object maps for projects and organisations
    //      "dynamic" are the large all-object maps for projects and organisations

    var addMap, addPin, populateMap, mapOptions, prepareNextRequest, getResourceUrl;

    // For each .akvo_map element on the page, read options
    // and kick of the creation of a new map
    $(document).ready(function () {
        $('.akvo_map').each(function () {
            var mapId = $(this).attr('id');
            addMap({
                mapId: mapId,
                mapElement: document.getElementById(mapId),
                mapOpts: window[mapId]
            });
        });
    });

    // Creates the map with options and makes the initial AJAX request
    addMap = function (map) {
        $(map.mapElement).gmap(mapOptions(map.mapOpts.type)).bind('init', function () {
            $.getJSON(getResourceUrl(map), function (data) {
                populateMap(map, data);
            });
        });
    };

    // Creates resource URLS based on map options
    getResourceUrl = function (map) {
        var opts, url, limit;
        opts = map.mapOpts;
        // call /api/v1/map_for_project/ or /api/v1/map_for_organisation/ resources
        //TODO: derive the host from the current page URL instead maybe?
        url = opts.host + 'api/v1/map_for_' + opts.resource + '/';
        //limit = 0 means all objects. If this becomes too heavy limit can be set to get the objects in multiple chunks
        limit = 100;
        // if object_id holds a value then that's the ID of the object we want to fetch
        if (opts.object_id) {
            url += opts.object_id + '/?format=jsonp&depth=1&callback=?';
        // otherwise we want all objects of the resource's type
        } else {
            url += '?format=jsonp&limit=' + limit + '&callback=?';
        }
        return url;
    };

    // Populates the map with data
    populateMap = function (map, data) {
        var objects, opts, pinTmpl, addOrganisationData, addProjectData;
        opts = map.mapOpts;

        // Since API resources that list multiple objects (projects or organisations) include
        // an objects array we need to add the single project or organisation to an array. This Since
        // we want to keep using the same logic for both cases
        if (opts.object_id === "") {
            objects = data.objects;
        } else {
            objects = [data];
        }

        pinTmpl = Handlebars.compile(
            '
' +
                '{{title}}' +
                '{{#if thumb}}' +
                    '
' +
                        '' +
                            '' +
                        '' +
                    '
' +
                '{{/if}}' +
                '
');

        // populate the location object with data from an Organisation model object
        addOrganisationData = function (object, location) {
            location.url = object.absolute_url;
            location.title = object.name;
            try {
                location.thumb = object.logo.thumbnails.map_thumb;
            } catch (e0) { location.thumb = ''; }
            return location;
        };

        // populate the location object with data from a Project model object
        addProjectData = function (object, location) {
            location.url = object.absolute_url;
            location.title = object.title;
            try {
                location.thumb = object.current_image.thumbnails.map_thumb;
            } catch (e1) { location.thumb = ''; }
            return location;
        };

        $.each(objects, function (i, object) {
            // for single objects show all locations
            if (opts.object_id) {
                $.each(object.locations, function (k, location) {
                    //TODO: extend this for additional resource types
                    if (opts.resource === 'organisation') {
                        location = addOrganisationData(object, location);
                    } else {
                        location = addProjectData(object, location);
                    }
                    addPin(map, location, pinTmpl);
                });
            // if we're displaying multiple objects we only show the primary locations
            } else {
                var location;
                location = object.primary_location;
                if (location) {
                    if (opts.resource === 'organisation') {
                        location = addOrganisationData(object, location);
                    } else {
                        location = addProjectData(object, location);
                    }
                    addPin(map, location, pinTmpl);
                }
            }
        });

        // If we are rendering multiple objects and there are more objects to
        // grab from the API
        if (isNaN(opts.object) && data.meta.next !== null) {
            prepareNextRequest(map, data.meta.next);
        }
    };

    // Add a single pin
    addPin = function (map, location, template) {
        var marker, opts;
        opts = map.mapOpts;
        marker = opts.host + 'rsr/media/core/img/';

        // get a custom marker if there is one, otherwise it's red for organisations and blue for projects
        if (opts.marker_icon) {
            marker = marker + opts.marker_icon;
        } else if (opts.resource === 'organisation') {
            marker = marker + 'redMarker.png';
        } else {
            marker = marker + 'blueMarker.png';
        }

        if (opts.type === 'static' || opts.type === 'small') {
            // shrink the marker for "static" maps
            if (opts.type === 'static') {
                marker = new google.maps.MarkerImage(marker, null, null, null, new google.maps.Size(10.5, 17));
            }
            $(map.mapElement).gmap('addMarker', {
                'position': new google.maps.LatLng(location.latitude, location.longitude),
                'clickable': false,
                'icon': marker,
                'bounds': true
            });
            // if the map is zoomed in a lot we zoom out a bit
            if ($(map.mapElement).gmap('get', 'map').getZoom() > 8) {
                $(map.mapElement).gmap('get', 'map').setZoom(8);
            }
        // "dynamic"
        } else {
            $(map.mapElement).gmap('addMarker', {
                'position': new google.maps.LatLng(location.latitude, location.longitude),
                'icon': marker,
                'bounds': true
            }).click(function () {
                $(map.mapElement).gmap('openInfoWindow', {
                    'content': template(location)
                }, this);
            });
        }
    };

    // Since we need to update the callback parameters we don't use the meta.next
    // but create a new resource url
    prepareNextRequest = function (map, resource) {
        var url = $.url(resource),
            urlTmpl = Handlebars.compile('{{host}}{{path}}?format=jsonp&depth=1&limit=' +
                '{{limit}}&offset={{offset}}&callback=?'),
            newUrl = urlTmpl({
                'host': url.attr('host'),
                'path': url.attr('path'),
                'limit': Number(url.param('limit')),
                'offset': Number(url.param('offset'))
            });
        $.getJSON(newUrl, function (data) {
            populateMap(map, data);
        });
    };

    mapOptions = function (mapType) {
        var options;
        // "static" and "small" are set to zoom 0 to begin with so that you see a world map until it has been populated
        // scroll wheel zoom is only enabled for the large "dynamic" maps
        if (mapType === 'static') {
            options = {
                'draggable': false,
                'mapTypeControl': false,
                'navigationControl': true,
                'scaleControl': false,
                'scrollwheel': false,
                'streetViewControl': false,
                'zoom': 0
            };
        } else if (mapType === 'small') {
            options = {
                'draggable': true,
                'mapTypeControl': false,
                'navigationControl': true,
                'scaleControl': true,
                'scrollwheel': false,
                'streetViewControl': false,
                'zoom': 0
            };
        } else {
            options = {
                'draggable': true,
                'mapTypeControl': true,
                'navigationControl': true,
                'scaleControl': true,
                'scrollwheel': true,
                'streetViewControl': false,
                'zoom': 2
            };
        }
        return options;
    };
}());
<|endoftext|>


<commit_before>import ClusterDriver from 'shared/mixins/cluster-driver';
import Component from '@ember/component'
import { get, set, observer } from '@ember/object';
import layout from './template';
import { on } from '@ember/object/evented';

import {
  sizes,
  neuRegions,
} from 'ui/utils/azure-choices';

const VERSIONS = [
  {
    "value": "1.8.11"
  },
  {
    "value": "1.9.6"
  },
];

export default Component.extend(ClusterDriver, {
  layout,
  configField:  'azureKubernetesServiceConfig',

  zones:        neuRegions,
  versions:     VERSIONS,
  machineSizes: sizes,
  netMode: 'default',

  init() {
    this._super(...arguments);

    let config = get(this, 'cluster.azureKubernetesServiceConfig');

    if ( !config ) {

      config = this.get('globalStore').createRecord({
        agentPoolName:     "rancher",
        type:              'azureKubernetesServiceConfig',
        osDiskSizeGb:      100,
        adminUsername:     'azureuser',
        kubernetesVersion: '1.8.11',
        count:             3,
        agentVmSize:       'Standard_A2',
        location:          'eastus',
      });

      set(this, 'cluster.azureKubernetesServiceConfig', config);
    }
  },

  changeNetMode: on('init', observer('netMode', function() {

  })),
});
<commit_msg>remove unneeded observer<commit_after>import ClusterDriver from 'shared/mixins/cluster-driver';
import Component from '@ember/component'
import { get, set } from '@ember/object';
import layout from './template';
import { on } from '@ember/object/evented';

import {
  sizes,
  neuRegions,
} from 'ui/utils/azure-choices';

const VERSIONS = [
  {
    "value": "1.8.11"
  },
  {
    "value": "1.9.6"
  },
];

export default Component.extend(ClusterDriver, {
  layout,
  configField:  'azureKubernetesServiceConfig',

  zones:        neuRegions,
  versions:     VERSIONS,
  machineSizes: sizes,
  netMode:      'default',

  init() {
    this._super(...arguments);

    let config = get(this, 'cluster.azureKubernetesServiceConfig');

    if ( !config ) {

      config = this.get('globalStore').createRecord({
        agentPoolName:     "rancher",
        type:              'azureKubernetesServiceConfig',
        osDiskSizeGb:      100,
        adminUsername:     'azureuser',
        kubernetesVersion: '1.8.11',
        count:             3,
        agentVmSize:       'Standard_A2',
        location:          'eastus',
      });

      set(this, 'cluster.azureKubernetesServiceConfig', config);
    }
  },

});
<|endoftext|>


<commit_before>var search = document.querySelector('#query_ticket'),
	canOrder = document.querySelectorAll('.btn72'),
	trains = [];
function ticket(train, i) {
	// 硬座，二等座
	return train[i].parentNode.parentNode.querySelectorAll('td')[9].innerHTML
			|| parentNode.parentNode.querySelectorAll('td')[4].innerHTML;
}

(function timer(){
	setTimeout(function(){
		search.click();
		if(canOrder){
			// 对所有有硬座或者二等座的车就行抢票
			for (var i = 0; i < canOrder.length; i++) {
				if(ticket(canOrder, i) != ('无' && '-')) {
					trains[i] = canOrder[i];
					trains[i].innerHTML = trains[i].innerHTML == '有' ? 9999 : trains[i].innerHTML;
				}
			};
			trains.sort(function (a, b) {
				return a > b;
			});
			// 仅对票数最多的车次进行预订
			// console.log(trains[0]);
			trains[0].click();
		} else {
			timer();
		}
	}, 200)
})()<commit_msg>增加说明，在车票预订页面直接运行代码即可使用<commit_after>var search = document.querySelector('#query_ticket'),
	canOrder = document.querySelectorAll('.btn72'),
	trains = [],
	interval = 200;		// 默认200ms进行一次查询，可修改

function ticket(train, i) {
	// 1商务座 2特等座 3一等座 4二等座 5高级软卧 6软卧 7硬卧 8软座 9硬座 10无座
	// 此处为硬座或二等座, 可根据需求添加
	return train[i].parentNode.parentNode.querySelectorAll('td')[9].innerHTML
			|| parentNode.parentNode.querySelectorAll('td')[4].innerHTML;
}

(function timer(){
	setTimeout(function(){
		search.click();
		if(canOrder.length != 0){
			// 对所有有硬座或者二等座的车就行抢票
			for (var i = 0; i < canOrder.length; i++) {
				if(ticket(canOrder, i) != ('无' && '-')) {
					trains[i] = canOrder[i];
					trains[i].innerHTML = trains[i].innerHTML == '有' ? 9999 : trains[i].innerHTML;
				}
			};
			trains.sort(function (a, b) {
				return a > b;
			});
			// 仅对票数最多的车次进行预订
			// console.log(trains[0]);
			trains[0].click();
		} else {
			timer();
		}
	}, interval)
})()<|endoftext|>


<commit_before>'use strict';

{
  // Set focus

  document.body.setAttribute('tabindex', 0);
  document.body.focus();
  document.body.removeAttribute('tabindex');

  // DOM structure

  const layer = document.createElement('div');

  layer.setAttribute('id', 's8k-select-layer');

  layer.innerHTML = `

  `;

  document.body.appendChild(layer);

  const elements = {
    box: layer.querySelector('#s8k-select-box')
  };

  // Event handlers

  let selector = null;
  let target   = null;

  const stop = (event) => {
    event.stopPropagation();
    event.preventDefault();
  };

  const handlers = {
    mouseover: (event) => {
      if (selector === null) {
        target = event.target;

        let display = (target.currentStyle ? target.currentStyle : getComputedStyle(target, null)).display;

        while (display !== 'block') {
          target  = target.parentElement;
          display = (target.currentStyle ? target.currentStyle : getComputedStyle(target, null)).display;
        }

        const rect = target.getBoundingClientRect();

        elements.box.style.top  = (window.scrollY + rect.top)  + 'px';
        elements.box.style.left = (window.scrollX + rect.left) + 'px';

        elements.box.style.width  = rect.width  + 'px';
        elements.box.style.height = rect.height + 'px';
      }
    },
    click: (event) => {
      event.stopPropagation();
      event.preventDefault();

      if (selector === null) {
        selector = createSelector(target);

        layer.style.visibility = 'hidden';

        const rect = target.getBoundingClientRect();

        browser.runtime.sendMessage({
          action:   'selector:capture',
          selector: selector,
          rect:     {
            left:   Math.ceil(rect.left),
            top:    Math.ceil(rect.top),
            width:  Math.ceil(rect.width),
            height: Math.ceil(rect.height)
          }
        }).then(() => {
          layer.style.visibility = 'visible';
        });
      }
    },
    keypress: (event) => {
      if (event.key === 'Escape') {
        browser.runtime.sendMessage({action: 'selector:disable'});
      }
    },
    message: (message) => {
      if (typeof message === 'object') {
        if (message.action === 'selector:cancel') {
          selector = null;
        } else if (message.action === 'selector:disable') {
          document.body.removeChild(layer);

          document.body.removeEventListener('mouseover', handlers.mouseover);
          document.body.removeEventListener('click', handlers.click, true);
          document.body.removeEventListener('keypress', handlers.keypress, true);
          document.body.removeEventListener('dblclick', stop, true);

          browser.runtime.onMessage.removeListener(handlers.message);
        }
      }
    }
  }

  document.body.addEventListener('mouseover', handlers.mouseover);
  document.body.addEventListener('click', handlers.click, true);
  document.body.addEventListener('keypress', handlers.keypress, true);
  document.body.addEventListener('dblclick', stop, true);

  browser.runtime.onMessage.addListener(handlers.message);

  // Utils

  const createSelector = function (element, selectors = []) {
    const tag = element.tagName.toLowerCase();

    if (tag === 'img') {
      selectors.unshift(`${tag}[src="${element.getAttribute('src')}"]`);
    } else if (element.getAttribute('id') !== '') {
      selectors.unshift(`${tag}#${element.getAttribute('id')}`);
    } else {
      selectors.unshift(tag);

      if (element.parentElement !== null && element.getAttribute('id') === '') {
        const siblings = Array.prototype.filter.call(element.parentElement.children || [], function (item) {
          return (item.tagName === element.tagName);
        });

        if (siblings.length > 1) {
          selectors[0] += ':nth-of-type(' + (siblings.indexOf(element) + 1) + ')';
        }

        return createSelector(element.parentElement, selectors);
      };
    }

    return selectors.join(' > ');
  }
}
<commit_msg>Fix CSS selector generator<commit_after>'use strict';

{
  // Set focus

  document.body.setAttribute('tabindex', 0);
  document.body.focus();
  document.body.removeAttribute('tabindex');

  // DOM structure

  const layer = document.createElement('div');

  layer.setAttribute('id', 's8k-select-layer');

  layer.innerHTML = `

  `;

  document.body.appendChild(layer);

  const elements = {
    box: layer.querySelector('#s8k-select-box')
  };

  // Event handlers

  let selector = null;
  let target   = null;

  const stop = (event) => {
    event.stopPropagation();
    event.preventDefault();
  };

  const handlers = {
    mouseover: (event) => {
      if (selector === null) {
        target = event.target;

        let display = (target.currentStyle ? target.currentStyle : getComputedStyle(target, null)).display;

        while (display !== 'block') {
          target  = target.parentElement;
          display = (target.currentStyle ? target.currentStyle : getComputedStyle(target, null)).display;
        }

        const rect = target.getBoundingClientRect();

        elements.box.style.top  = (window.scrollY + rect.top)  + 'px';
        elements.box.style.left = (window.scrollX + rect.left) + 'px';

        elements.box.style.width  = rect.width  + 'px';
        elements.box.style.height = rect.height + 'px';
      }
    },
    click: (event) => {
      event.stopPropagation();
      event.preventDefault();

      if (selector === null) {
        selector = createSelector(target);

        layer.style.visibility = 'hidden';

        const rect = target.getBoundingClientRect();

        browser.runtime.sendMessage({
          action:   'selector:capture',
          selector: selector,
          rect:     {
            left:   Math.ceil(rect.left),
            top:    Math.ceil(rect.top),
            width:  Math.ceil(rect.width),
            height: Math.ceil(rect.height)
          }
        }).then(() => {
          layer.style.visibility = 'visible';
        });
      }
    },
    keypress: (event) => {
      if (event.key === 'Escape') {
        browser.runtime.sendMessage({action: 'selector:disable'});
      }
    },
    message: (message) => {
      if (typeof message === 'object') {
        if (message.action === 'selector:cancel') {
          selector = null;
        } else if (message.action === 'selector:disable') {
          document.body.removeChild(layer);

          document.body.removeEventListener('mouseover', handlers.mouseover);
          document.body.removeEventListener('click', handlers.click, true);
          document.body.removeEventListener('keypress', handlers.keypress, true);
          document.body.removeEventListener('dblclick', stop, true);

          browser.runtime.onMessage.removeListener(handlers.message);
        }
      }
    }
  }

  document.body.addEventListener('mouseover', handlers.mouseover);
  document.body.addEventListener('click', handlers.click, true);
  document.body.addEventListener('keypress', handlers.keypress, true);
  document.body.addEventListener('dblclick', stop, true);

  browser.runtime.onMessage.addListener(handlers.message);

  // Utils

  const createSelector = function (element, selectors = []) {
    const tag = element.tagName.toLowerCase();

    if (tag === 'img') {
      selectors.unshift(`${tag}[src="${element.getAttribute('src')}"]`);
    } else if (element.getAttribute('id') !== null) {
      selectors.unshift(`${tag}#${element.getAttribute('id')}`);
    } else {
      selectors.unshift(tag);

      if (element.parentElement !== null) {
        const siblings = Array.prototype.filter.call(element.parentElement.children || [], function (item) {
          return (item.tagName === element.tagName);
        });

        if (siblings.length > 1) {
          selectors[0] += ':nth-of-type(' + (siblings.indexOf(element) + 1) + ')';
        }

        return createSelector(element.parentElement, selectors);
      };
    }

    return selectors.join(' > ');
  }
}
<|endoftext|>


<commit_before>// Require what we need.
var Vue = require('vue');
var Example = require('./plugins/example');
var VueRouter = require('vue-router');
var VueResource = require('vue-resource');

// Use the example plugin
Vue.use(Example);
Vue.use(VueRouter);
Vue.use(VueResource);

/**
 * Vue root instance
 */
var App = Vue.extend({
    data() {
        return {};
    },
    ready() {
        // From example plugin
        this.$pluginSay();
    },
    components: {
        navigation: require('./components/nav')
    }
});

var Router = new VueRouter({
    history: true
});

Router.map(require('./router.js'));
Router.start(App, '#app');

<commit_msg>Cleaned up app.js<commit_after>var Vue = require('vue');

// Use the example plugin
Vue.use(require('./plugins/example'));
Vue.use(require('vue-router'));
Vue.use(require('vue-resource'));

/**
 * Vue root instance
 */
var App = Vue.extend({
    data() {
        return {};
    },
    ready() {
        // From example plugin
        this.$pluginSay();
    },
    components: {
        navigation: require('./components/nav')
    }
});

var Router = new VueRouter({history: true});
Router.map(require('./router.js'));
Router.start(App, '#app');

<|endoftext|>


<commit_before>/**
 * Run integration tests
 *
 * Uses the `waterline-adapter-tests` module to
 * run mocha tests against the appropriate version
 * of Waterline.  Only the interfaces explicitly
 * declared in this adapter's `package.json` file
 * are tested. (e.g. `queryable`, `semantic`, etc.)
 */

/**
 * Module dependencies
 */

var util = require('util');
var mocha = require('mocha');
var log = require('captains-log')();
var TestRunner = require('waterline-adapter-tests');
var Adapter = require('../../lib/adapter');

// Grab targeted interfaces from this adapter's `package.json` file:
var package = {},
  interfaces = [];
try {
  package = require('../../package.json');
  interfaces = package.waterlineAdapter.interfaces;
} catch (e) {
  throw new Error(
    '\n' +
    'Could not read supported interfaces from `waterlineAdapter.interfaces`' + '\n' +
    'in this adapter\'s `package.json` file ::' + '\n' +
    util.inspect(e)
  );
}

log.info('Testing `' + package.name + '`, a Sails/Waterline adapter.');
log.info('Running `waterline-adapter-tests` against ' + interfaces.length + ' interfaces...');
log.info('( ' + interfaces.join(', ') + ' )');
console.log();
log('Latest draft of Waterline adapter interface spec:');
log('http://links.sailsjs.org/docs/plugins/adapters/interfaces');
console.log();

/**
 * Integration Test Runner
 *
 * Uses the `waterline-adapter-tests` module to
 * run mocha tests against the specified interfaces
 * of the currently-implemented Waterline adapter API.
 */
new TestRunner({

  // Mocha opts
  mocha: {
    bail: true
  },

  // Load the adapter module.
  adapter: Adapter,

  // Default connection config to use.
  config: {
    host: 'localhost',
    database: 'sails-mongo',
    port: 6379,
    schema: true,
    poolSize: 1
  },

  // The set of adapter interfaces to test against.
  // (grabbed these from this adapter's package.json file above)
  interfaces: interfaces

  // Most databases implement 'semantic' and 'queryable'.
  //
  // As of Sails/Waterline v0.10, the 'associations' interface
  // is also available.  If you don't implement 'associations',
  // it will be polyfilled for you by Waterline core.  The core
  // implementation will always be used for cross-adapter / cross-connection
  // joins.
  //
  // In future versions of Sails/Waterline, 'queryable' may be also
  // be polyfilled by core.
  //
  // These polyfilled implementations can usually be further optimized at the
  // adapter level, since most databases provide optimizations for internal
  // operations.
  //
  // Full interface reference:
  // https://github.com/balderdashy/sails-docs/blob/master/adapter-specification.md
});
<commit_msg>Remove erroneous db config...<commit_after>/**
 * Run integration tests
 *
 * Uses the `waterline-adapter-tests` module to
 * run mocha tests against the appropriate version
 * of Waterline.  Only the interfaces explicitly
 * declared in this adapter's `package.json` file
 * are tested. (e.g. `queryable`, `semantic`, etc.)
 */

/**
 * Module dependencies
 */

var util = require('util');
var mocha = require('mocha');
var log = require('captains-log')();
var TestRunner = require('waterline-adapter-tests');
var Adapter = require('../../lib/adapter');

// Grab targeted interfaces from this adapter's `package.json` file:
var package = {},
  interfaces = [];
try {
  package = require('../../package.json');
  interfaces = package.waterlineAdapter.interfaces;
} catch (e) {
  throw new Error(
    '\n' +
    'Could not read supported interfaces from `waterlineAdapter.interfaces`' + '\n' +
    'in this adapter\'s `package.json` file ::' + '\n' +
    util.inspect(e)
  );
}

log.info('Testing `' + package.name + '`, a Sails/Waterline adapter.');
log.info('Running `waterline-adapter-tests` against ' + interfaces.length + ' interfaces...');
log.info('( ' + interfaces.join(', ') + ' )');
console.log();
log('Latest draft of Waterline adapter interface spec:');
log('http://links.sailsjs.org/docs/plugins/adapters/interfaces');
console.log();

/**
 * Integration Test Runner
 *
 * Uses the `waterline-adapter-tests` module to
 * run mocha tests against the specified interfaces
 * of the currently-implemented Waterline adapter API.
 */
new TestRunner({

  // Mocha opts
  mocha: {
    bail: true
  },

  // Load the adapter module.
  adapter: Adapter,

  // Default connection config to use.
  config: {
    host: 'localhost',
    port: 6379,
    schema: true,
    poolSize: 1
  },

  // The set of adapter interfaces to test against.
  // (grabbed these from this adapter's package.json file above)
  interfaces: interfaces,

  // Return non-zero code if any test failed
  failOnError: true

  // Most databases implement 'semantic' and 'queryable'.
  //
  // As of Sails/Waterline v0.10, the 'associations' interface
  // is also available.  If you don't implement 'associations',
  // it will be polyfilled for you by Waterline core.  The core
  // implementation will always be used for cross-adapter / cross-connection
  // joins.
  //
  // In future versions of Sails/Waterline, 'queryable' may be also
  // be polyfilled by core.
  //
  // These polyfilled implementations can usually be further optimized at the
  // adapter level, since most databases provide optimizations for internal
  // operations.
  //
  // Full interface reference:
  // https://github.com/balderdashy/sails-docs/blob/master/adapter-specification.md
});
<|endoftext|>


<commit_before>describe('Directive: photoupload', function() {

  // load the controller's module
  beforeEach(module('badgerApp'));
  beforeEach(module('ihammer.templates'));
  var $httpBackend;
  var $rootScope;
  var $compile;

  // Initialize the controller and a mock scope
  beforeEach(inject(function($injector) {
    $rootScope = $injector.get('$rootScope');
    $compile = $injector.get('$compile');
    $httpBackend = $injector.get('$httpBackend');

    $httpBackend.whenGET('/api/config').respond({
      awsConfig: {
        bucket: 'ihammer-dev'
      }
    });
    $httpBackend.flush();

    // Compile a piece of HTML containing the directive
    $compile("<photoupload></photoupload>")($rootScope);
    // fire all the watches, so the scope expression {{1 + 1}} will be evaluated
    $rootScope.$digest();

  }));

  afterEach(function() {
  });

  it('should get Policy for one file', function() {
    var file = new Blob(['<content>'], {
      type: 'image/jpeg'
    });
    file.name = 'abc.jpeg';
    var files = [file];
    $httpBackend.whenGET('/api/s3Policy?mimeType=' + files[0].type)
      .respond({
        s3Policy: 'base64Policy',
        s3Signature: 'signature',
        AWSAccessKeyId: 'config.accessKeyId'
      });

    $rootScope.onFileSelect(files);

    $httpBackend.whenPOST('https://ihammer-dev.s3.amazonaws.com/')
      .respond(201,
      '<?xml version="1.0" encoding="UTF-8"?>' +
      '<PostResponse>' +
      '<Location>https://ihammer-dev.s3.amazonaws.com/clubs%2Fimages%2Fpic+copy+3.jpg</Location>' +
      '<Bucket>ihammer-dev</Bucket>' +
      '<Key>clubs/images/pic copy 3.jpg</Key>' +
      '<ETag>"971d696d8ef20fbe43387c817f83dc52"</ETag>' +
      '</PostResponse>'
    );
    $httpBackend.flush();
  });

});
<commit_msg>Commenting out slow test.<commit_after>describe('Directive: photoupload', function() {

  // load the controller's module
  beforeEach(module('badgerApp'));
  beforeEach(module('ihammer.templates'));
  var $httpBackend;
  var $rootScope;
  var $compile;

  // Initialize the controller and a mock scope
  beforeEach(inject(function($injector) {
    $rootScope = $injector.get('$rootScope');
    $compile = $injector.get('$compile');
    $httpBackend = $injector.get('$httpBackend');

    $httpBackend.whenGET('/api/config').respond({
      awsConfig: {
        bucket: 'ihammer-dev'
      }
    });
    $httpBackend.flush();

    // Compile a piece of HTML containing the directive
    $compile("<photoupload></photoupload>")($rootScope);
    // fire all the watches, so the scope expression {{1 + 1}} will be evaluated
    $rootScope.$digest();

  }));

  afterEach(function() {
  });

  it('should get Policy for one file', function() {
    //var file = new Blob(['<content>'], {
    //  type: 'image/jpeg'
    //});
    //file.name = 'abc.jpeg';
    //var files = [file];
    //$httpBackend.whenGET('/api/s3Policy?mimeType=' + files[0].type)
    //  .respond({
    //    s3Policy: 'base64Policy',
    //    s3Signature: 'signature',
    //    AWSAccessKeyId: 'config.accessKeyId'
    //  });
    //
    //$rootScope.onFileSelect(files);
    //
    //$httpBackend.whenPOST('https://ihammer-dev.s3.amazonaws.com/')
    //  .respond(201,
    //  '<?xml version="1.0" encoding="UTF-8"?>' +
    //  '<PostResponse>' +
    //  '<Location>https://ihammer-dev.s3.amazonaws.com/clubs%2Fimages%2Fpic+copy+3.jpg</Location>' +
    //  '<Bucket>ihammer-dev</Bucket>' +
    //  '<Key>clubs/images/pic copy 3.jpg</Key>' +
    //  '<ETag>"971d696d8ef20fbe43387c817f83dc52"</ETag>' +
    //  '</PostResponse>'
    //);
    //$httpBackend.flush();
  });

});
<|endoftext|>


<commit_before>/**
 *  Copyright (C) 2021 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

const { isNumber, isString } = require('../../../utils/helper/typeCheck');
const Yup = require('yup');
const { types } = require('../../../utils/helper/yup');

const Group = {};

const objectEntryValidator = Yup.object().shape({
	account: types.strings.username.required(),
	model: types.id.required(),
	shared_ids: Yup.array().of(types.id).min(1).optional(),
	ifc_guids: Yup.array().of(Yup.string().length(22)).min(1).optional(),
}).test(
	'Object item check',
	'Can only contain either ifc_guids or shared_ids',
	(value) => (value.shared_ids && !value.ifc_guids) || (!value.shared_ids && value.ifc_guids),
);

const operators = {
	IS_EMPTY: 0,
	IS_NOT_EMPTY: 0,
	IS: 1,
	IS_NOT: 1,
	CONTAINS: 1,
	NOT_CONTAINS: 1,
	REGEX: 1,
	EQUALS: 1,
	NOT_EQUALS: 1,
	GT: 1,
	GTE: 1,
	LT: 1,
	LTE: 1,
	IN_RANGE: 2,
	NOT_IN_RANGE: 2,
};

const ruleParametersTypeCheck = (operator, values) => {
	switch (operator) {
	case 'IS':
	case 'IS_NOT':
	case 'CONTAINS':
	case 'NOT_CONTAINS':
	case 'REGEX':
		return values.every(isString);
	case 'EQUALS':
	case 'NOT_EQUALS':
	case 'GT':
	case 'GTE':
	case 'LT':
	case 'LTE':
		return values.every(isNumber);
	default:
		// range checks
		return values.length % 2 === 0 && values.every(isNumber);
	}
};

const numberOperator = (operator) => {
	switch (operator) {
	case 'EQUALS':
	case 'NOT_EQUALS':
	case 'GT':
	case 'GTE':
	case 'LT':
	case 'LTE':
	case 'IN_RANGE':
	case 'NOT_IN_RANGE':
		return true;
	default:
		return false;
	}
};

const ruleValidator = Yup.object().shape({
	field: Yup.string().required().min(1),
	operator: Yup.string().uppercase().oneOf(Object.keys(operators)).required(),
	values: Yup.array().when('operator', {
		is: numberOperator,
		then: Yup.array().of(Yup.number()).min(1).required(),
		otherwise: Yup.array().of(Yup.string().min(1)).optional(),
	}),
})
	.noUnknown()
	.transform((value) => {
		const nParams = operators[value.operator];
		const res = { ...value };
		if (nParams === 0) {
			delete res.values;
		}
		return res;
	})
	.test(
		'Rules validation', 'values field is not valid with the operator selected',
		(value) => {
			const nParams = operators[value.operator];
			const arrLength = (value.values || []).length;
			return (nParams === 0 && arrLength === 0)
				|| (nParams <= arrLength && ruleParametersTypeCheck(value.operator, value.values));
		},
	);

const schema = (group, strict = false) => {
	const rulesOrObjects = group.rules
		? { rules: Yup.array().of(ruleValidator).min(1).required() }
		: { objects: Yup.array().of(objectEntryValidator).min(1).required() };

	const output = Yup.object().shape({
		_id: types.id.required(),
		color: types.colorArr.required(),
		name: types.strings.title,
		author: types.strings.username.required(),
		createdAt: types.timestamp.required(),
		description: types.strings.longDescription.optional(),
		updatedAt: types.timestamp.optional().default(group.createdAt),
		updatedBy: types.strings.username.optional().default(group.author),
		...rulesOrObjects,

	}).strict(strict).noUnknown()
		.required()
		.test(
			'Group validation',
			'Should contains either rules or objects',
			(value) => (value.rules && !value.objects) || (!value.rules && value.objects),
		);

	return output;
};

Group.validateSchema = (group) => schema(group, true).validate(group);
Group.castSchema = (group) => schema(group).cast(group);

module.exports = Group;
<commit_msg>ISSUE #2862 smart groups export bug fix so that dates are always in integer format<commit_after>/**
 *  Copyright (C) 2021 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

const { isNumber, isString } = require('../../../utils/helper/typeCheck');
const Yup = require('yup');
const { types } = require('../../../utils/helper/yup');

const Group = {};

const objectEntryValidator = Yup.object().shape({
	account: types.strings.username.required(),
	model: types.id.required(),
	shared_ids: Yup.array().of(types.id).min(1).optional(),
	ifc_guids: Yup.array().of(Yup.string().length(22)).min(1).optional(),
}).test(
	'Object item check',
	'Can only contain either ifc_guids or shared_ids',
	(value) => (value.shared_ids && !value.ifc_guids) || (!value.shared_ids && value.ifc_guids),
);

const operators = {
	IS_EMPTY: 0,
	IS_NOT_EMPTY: 0,
	IS: 1,
	IS_NOT: 1,
	CONTAINS: 1,
	NOT_CONTAINS: 1,
	REGEX: 1,
	EQUALS: 1,
	NOT_EQUALS: 1,
	GT: 1,
	GTE: 1,
	LT: 1,
	LTE: 1,
	IN_RANGE: 2,
	NOT_IN_RANGE: 2,
};

const ruleParametersTypeCheck = (operator, values) => {
	switch (operator) {
	case 'IS':
	case 'IS_NOT':
	case 'CONTAINS':
	case 'NOT_CONTAINS':
	case 'REGEX':
		return values.every(isString);
	case 'EQUALS':
	case 'NOT_EQUALS':
	case 'GT':
	case 'GTE':
	case 'LT':
	case 'LTE':
		return values.every(isNumber);
	default:
		// range checks
		return values.length % 2 === 0 && values.every(isNumber);
	}
};

const numberOperator = (operator) => {
	switch (operator) {
	case 'EQUALS':
	case 'NOT_EQUALS':
	case 'GT':
	case 'GTE':
	case 'LT':
	case 'LTE':
	case 'IN_RANGE':
	case 'NOT_IN_RANGE':
		return true;
	default:
		return false;
	}
};

const ruleValidator = Yup.object().shape({
	field: Yup.string().required().min(1),
	operator: Yup.string().uppercase().oneOf(Object.keys(operators)).required(),
	values: Yup.array().when('operator', {
		is: numberOperator,
		then: Yup.array().of(Yup.number()).min(1).required(),
		otherwise: Yup.array().of(Yup.string().min(1)).optional(),
	}),
})
	.noUnknown()
	.transform((value) => {
		const nParams = operators[value.operator];
		const res = { ...value };
		if (nParams === 0) {
			delete res.values;
		}
		return res;
	})
	.test(
		'Rules validation', 'values field is not valid with the operator selected',
		(value) => {
			const nParams = operators[value.operator];
			const arrLength = (value.values || []).length;
			return (nParams === 0 && arrLength === 0)
				|| (nParams <= arrLength && ruleParametersTypeCheck(value.operator, value.values));
		},
	);

const schema = (group, strict = false) => {
	const rulesOrObjects = group.rules
		? { rules: Yup.array().of(ruleValidator).min(1).required() }
		: { objects: Yup.array().of(objectEntryValidator).min(1).required() };

	const output = Yup.object().shape({
		_id: types.id.required(),
		color: types.colorArr.required(),
		name: types.strings.title,
		author: types.strings.username.required(),
		createdAt: types.timestamp.required(),
		description: types.strings.longDescription.optional(),
		updatedAt: types.timestamp.optional().default(group.createdAt),
		updatedBy: types.strings.username.optional().default(group.author),
		...rulesOrObjects,

	}).strict(strict).noUnknown()
		.required()
		.test(
			'Group validation',
			'Should contains either rules or objects',
			(value) => (value.rules && !value.objects) || (!value.rules && value.objects),
		);

	return output;
};

Group.validateSchema = (group) => schema(group, true).validate(group);
Group.castSchema = (group) => {
	const castedSchema = schema(group).cast(group);

	if (typeof castedSchema.updatedAt !== 'number') {
		castedSchema.updatedAt = castedSchema.createdAt;
	}

	return castedSchema;
};
module.exports = Group;
<|endoftext|>


<commit_before>var _ = require("lodash");
var λ = require("contra");
var DB = require("./DB");
var getArg = require("./getArg");
var Future = require("fibers/future");
var modules = require("./modules");
var krl_stdlib = require("krl-stdlib");
var KRLClosure = require("./KRLClosure");
var SymbolTable = require("symbol-table");
var applyInFiber = require("./applyInFiber");
var EventEmitter = require("events");
var evalRuleInFiber = require("./evalRuleInFiber");
var selectRulesToEvalFuture = Future.wrap(require("./selectRulesToEval"));

module.exports = function(conf, callback){
  var db = Future.wrap(DB(conf.db));
  var compileAndLoadRuleset = conf.compileAndLoadRuleset;

  var rulesets = {};
  var salience_graph = {};

  var emitter = new EventEmitter();

  var mkCTX = function(ctx){
    ctx.db = db;
    ctx.getArg = getArg;
    ctx.engine = engine;
    ctx.modules = modules;
    ctx.KRLClosure = KRLClosure;
    ctx.emit = function(type, val, message){//for stdlib
      var info = {rid: ctx.rid};
      if(ctx.event){
        info.event = {
          eci: ctx.event.eci,
          eid: ctx.event.eid,
          domain: ctx.event.domain,
          type: ctx.event.type,
        };
      }
      emitter.emit(type, info, val, message);
    };
    ctx.callKRLstdlib = function(fn_name){
      var args = _.toArray(arguments);
      args[0] = ctx;
      return krl_stdlib[fn_name].apply(void 0, args);
    };
    return ctx;
  };

  var installRulesetInFiber = function(rs){
    rs.scope = SymbolTable();
    var ctx = mkCTX({
      scope: rs.scope
    });
    if(_.isFunction(rs.meta && rs.meta.configure)){
      rs.meta.configure(ctx);
    }
    if(_.isFunction(rs.global)){
      rs.global(ctx);
    }
    rs.modules_used = {};
    _.each(rs.meta && rs.meta.use, function(use){
      if(use.kind !== "module"){
        throw new Error("Unsupported 'use' kind: " + use.kind);
      }
      if(!_.has(rulesets, use.rid)){
        throw new Error("Dependant module not loaded: " + use.rid);
      }
      var dep_rs = rulesets[use.rid];
      var ctx = mkCTX({
        scope: SymbolTable()//or dep_rs.scope.push() ??? TODO
      });
      if(_.isFunction(dep_rs.meta && dep_rs.meta.configure)){
        dep_rs.meta.configure(ctx);
      }
      if(_.isFunction(use["with"])){
        use["with"](ctx);
      }
      if(_.isFunction(dep_rs.global)){
        dep_rs.global(ctx);
      }
      rs.modules_used[use.alias] = {
        rid: use.rid,
        scope: ctx.scope,
        provides: dep_rs.meta.provides
      };
    });
    _.each(rs.rules, function(rule){
      rule.rid = rs.rid;

      _.each(rule.select && rule.select.graph, function(g, domain){
        _.each(g, function(exprs, type){
          _.set(salience_graph, [domain, type, rule.rid, rule.name], true);
        });
      });
    });
    rulesets[rs.rid] = rs;
  };

  var installRuleset = function(rs, callback){
    applyInFiber(installRulesetInFiber, null, [rs], callback);
  };

  var getRulesetForRID = function(rid, callback){
    db.getEnableRuleset(rid, function(err, data){
      if(err) return callback(err);
      compileAndLoadRuleset({
        rid: rid,
        src: data.src,
        hash: data.hash
      }, function(err, rs){
        if(err){
          db.disableRuleset(rid, function(){
            callback(err);
          });
          return;
        }
        callback(void 0, rs);
      });
    });
  };

  var installRID = function(rid, callback){
    getRulesetForRID(rid, function(err, rs){
      if(err) return callback(err);
      installRuleset(rs, callback);
    });
  };

  var installAllEnableRulesets = function(callback){
    db.getAllEnableRulesets(function(err, rids){
      if(err)return callback(err);
      λ.map(rids, getRulesetForRID, function(err, rs_list){
        if(err)return callback(err);
        //TODO load in order of dependancies? or simply index all then install?
        λ.each(rs_list, installRuleset, callback);
      });
    });
  };

  var signalEventInFiber = function(event){
    event.timestamp = new Date();

    var ctx = mkCTX({
      event: event
    });

    ctx.emit("debug", "event recieved");

    ctx.pico = db.getPicoByECIFuture(event.eci).wait();
    if(!ctx.pico){
      throw new Error("Invalid eci: " + event.eci);
    }

    ctx.emit("debug", "pico selected");

    var rules = selectRulesToEvalFuture(ctx, salience_graph, rulesets).wait();
    var responses = _.map(rules, function(rule){

      ctx.emit("debug", "rule selected: " + rule.rid + " -> " + rule.name);

      ctx.rid = rule.rid;
      ctx.rule = rule;
      ctx.scope = rule.scope;
      if(_.has(rulesets, rule.rid)){
        ctx.modules_used = rulesets[rule.rid].modules_used;
      }

      return evalRuleInFiber(rule, ctx);
    });

    var res_by_type = _.groupBy(_.flattenDeep(_.values(responses)), "type");

    //TODO other types
    return {
      directives:  _.map(res_by_type.directive, function(d){
        return _.omit(d, "type");
      })
    };
  };

  var signalEvent = function(event, callback){
    applyInFiber(signalEventInFiber, void 0, [event], callback);
  };

  var runQuery = function(query, callback){
    db.getPicoByECI(query.eci, function(err, pico){
      if(err) return callback(err);
      if(!pico){
        return callback(new Error("Bad eci"));
      }
      if(!_.has(pico.ruleset, query.rid)){
        return callback(new Error("Pico does not have that rid"));
      }
      if(!_.has(rulesets, query.rid)){
        return callback(new Error("Not found: rid"));
      }
      var rs = rulesets[query.rid];
      var shares = _.get(rs, ["meta", "shares"]);
      if(!_.isArray(shares) || !_.includes(shares, query.name)){
        return callback(new Error("Not shared"));
      }
      if(!rs.scope.has(query.name)){
        //TODO throw -or- nil????
        return callback(new Error("Shared, but not defined: " + query.name));
      }

      ////////////////////////////////////////////////////////////////////////
      var ctx = mkCTX({
        rid: rs.rid,
        pico: pico,
        modules_used: rs.modules_used,
        scope: rs.scope
      });

      var val = ctx.scope.get(query.name);
      if(_.isFunction(val)){
        applyInFiber(val, null, [ctx, query.args], function(err, resp){
          if(err) return callback(err);
          callback(undefined, resp);
        });
      }else{
        callback(undefined, val);
      }
    });
  };

  var engine = Future.wrap({
    installRID: installRID,
    signalEvent: signalEvent
  });

  installAllEnableRulesets(function(err){
    if(err) return callback(err);
    callback(void 0, {
      db: db,
      emitter: emitter,
      isInstalled: function(rid){
        return _.has(rulesets, rid);
      },
      installRID: installRID,
      signalEvent: signalEvent,
      runQuery: runQuery
    });
  });
};
<commit_msg>runQueryInFiber<commit_after>var _ = require("lodash");
var λ = require("contra");
var DB = require("./DB");
var getArg = require("./getArg");
var Future = require("fibers/future");
var modules = require("./modules");
var krl_stdlib = require("krl-stdlib");
var KRLClosure = require("./KRLClosure");
var SymbolTable = require("symbol-table");
var applyInFiber = require("./applyInFiber");
var EventEmitter = require("events");
var evalRuleInFiber = require("./evalRuleInFiber");
var selectRulesToEvalFuture = Future.wrap(require("./selectRulesToEval"));

module.exports = function(conf, callback){
  var db = Future.wrap(DB(conf.db));
  var compileAndLoadRuleset = conf.compileAndLoadRuleset;

  var rulesets = {};
  var salience_graph = {};

  var emitter = new EventEmitter();

  var mkCTX = function(ctx){
    ctx.db = db;
    ctx.getArg = getArg;
    ctx.engine = engine;
    ctx.modules = modules;
    ctx.KRLClosure = KRLClosure;
    ctx.emit = function(type, val, message){//for stdlib
      var info = {rid: ctx.rid};
      if(ctx.event){
        info.event = {
          eci: ctx.event.eci,
          eid: ctx.event.eid,
          domain: ctx.event.domain,
          type: ctx.event.type,
        };
      }
      emitter.emit(type, info, val, message);
    };
    ctx.callKRLstdlib = function(fn_name){
      var args = _.toArray(arguments);
      args[0] = ctx;
      return krl_stdlib[fn_name].apply(void 0, args);
    };
    return ctx;
  };

  var installRulesetInFiber = function(rs){
    rs.scope = SymbolTable();
    var ctx = mkCTX({
      scope: rs.scope
    });
    if(_.isFunction(rs.meta && rs.meta.configure)){
      rs.meta.configure(ctx);
    }
    if(_.isFunction(rs.global)){
      rs.global(ctx);
    }
    rs.modules_used = {};
    _.each(rs.meta && rs.meta.use, function(use){
      if(use.kind !== "module"){
        throw new Error("Unsupported 'use' kind: " + use.kind);
      }
      if(!_.has(rulesets, use.rid)){
        throw new Error("Dependant module not loaded: " + use.rid);
      }
      var dep_rs = rulesets[use.rid];
      var ctx = mkCTX({
        scope: SymbolTable()//or dep_rs.scope.push() ??? TODO
      });
      if(_.isFunction(dep_rs.meta && dep_rs.meta.configure)){
        dep_rs.meta.configure(ctx);
      }
      if(_.isFunction(use["with"])){
        use["with"](ctx);
      }
      if(_.isFunction(dep_rs.global)){
        dep_rs.global(ctx);
      }
      rs.modules_used[use.alias] = {
        rid: use.rid,
        scope: ctx.scope,
        provides: dep_rs.meta.provides
      };
    });
    _.each(rs.rules, function(rule){
      rule.rid = rs.rid;

      _.each(rule.select && rule.select.graph, function(g, domain){
        _.each(g, function(exprs, type){
          _.set(salience_graph, [domain, type, rule.rid, rule.name], true);
        });
      });
    });
    rulesets[rs.rid] = rs;
  };

  var installRuleset = function(rs, callback){
    applyInFiber(installRulesetInFiber, null, [rs], callback);
  };

  var getRulesetForRID = function(rid, callback){
    db.getEnableRuleset(rid, function(err, data){
      if(err) return callback(err);
      compileAndLoadRuleset({
        rid: rid,
        src: data.src,
        hash: data.hash
      }, function(err, rs){
        if(err){
          db.disableRuleset(rid, function(){
            callback(err);
          });
          return;
        }
        callback(void 0, rs);
      });
    });
  };

  var installRID = function(rid, callback){
    getRulesetForRID(rid, function(err, rs){
      if(err) return callback(err);
      installRuleset(rs, callback);
    });
  };

  var installAllEnableRulesets = function(callback){
    db.getAllEnableRulesets(function(err, rids){
      if(err)return callback(err);
      λ.map(rids, getRulesetForRID, function(err, rs_list){
        if(err)return callback(err);
        //TODO load in order of dependancies? or simply index all then install?
        λ.each(rs_list, installRuleset, callback);
      });
    });
  };

  var signalEventInFiber = function(event){
    event.timestamp = new Date();

    var ctx = mkCTX({
      event: event
    });

    ctx.emit("debug", "event recieved");

    ctx.pico = db.getPicoByECIFuture(event.eci).wait();
    if(!ctx.pico){
      throw new Error("Invalid eci: " + event.eci);
    }

    ctx.emit("debug", "pico selected");

    var rules = selectRulesToEvalFuture(ctx, salience_graph, rulesets).wait();
    var responses = _.map(rules, function(rule){

      ctx.emit("debug", "rule selected: " + rule.rid + " -> " + rule.name);

      ctx.rid = rule.rid;
      ctx.rule = rule;
      ctx.scope = rule.scope;
      if(_.has(rulesets, rule.rid)){
        ctx.modules_used = rulesets[rule.rid].modules_used;
      }

      return evalRuleInFiber(rule, ctx);
    });

    var res_by_type = _.groupBy(_.flattenDeep(_.values(responses)), "type");

    //TODO other types
    return {
      directives:  _.map(res_by_type.directive, function(d){
        return _.omit(d, "type");
      })
    };
  };

  var signalEvent = function(event, callback){
    applyInFiber(signalEventInFiber, void 0, [event], callback);
  };

  var runQueryInFiber = function(ctx, query){
    ctx.pico = ctx.db.getPicoByECIFuture(query.eci).wait();
    if(!ctx.pico){
      throw new Error("Invalid eci: " + query.eci);
    }
    if(!_.has(ctx.pico.ruleset, query.rid)){
      throw new Error("Pico does not have that rid");
    }
    if(!_.has(rulesets, query.rid)){
      throw new Error("Not found: rid");
    }
    var rs = rulesets[query.rid];
    var shares = _.get(rs, ["meta", "shares"]);
    if(!_.isArray(shares) || !_.includes(shares, query.name)){
      throw new Error("Not shared");
    }
    if(!rs.scope.has(query.name)){
      throw new Error("Shared, but not defined: " + query.name);
    }

    ////////////////////////////////////////////////////////////////////////
    ctx.rid = rs.rid;
    ctx.modules_used = rs.modules_used;
    ctx.scope = rs.scope;
    var val = ctx.scope.get(query.name);
    if(_.isFunction(val)){
      return val(ctx, query.args);
    }
    return val;
  };

  var runQuery = function(query, callback){
    var ctx = mkCTX({});
    applyInFiber(runQueryInFiber, void 0, [ctx, query], callback);
  };

  var engine = Future.wrap({
    installRID: installRID,
    signalEvent: signalEvent
  });

  installAllEnableRulesets(function(err){
    if(err) return callback(err);
    callback(void 0, {
      db: db,
      emitter: emitter,
      isInstalled: function(rid){
        return _.has(rulesets, rid);
      },
      installRID: installRID,
      signalEvent: signalEvent,
      runQuery: runQuery
    });
  });
};
<|endoftext|>


<commit_before>const {Action, api} = require('actionhero');
const dal = require('@dal');
const fs = require('fs');
const path = require('path');

module.exports.GetTopViewedPublishedDatasetsAction = class GetTopViewedPublishedDatasetsAction extends Action {
    constructor() {
        super();
        this.name = 'getTopViewedPublishedDatasets';
        this.description = 'Returns the most viewed datasets';
        this.do_not_authenticate = true;
    }

    async run({response}) {
        const topViewedDatasets = await dal.tryCatch(async() => await api.mc.publishedDatasets.getTopViewedDatasets());
        response.data = topViewedDatasets ? topViewedDatasets : [];
    }
};

module.exports.GetRecentlyPublishedDatasetsAction = class GetRecentlyPublishedDatasetsAction extends Action {
    constructor() {
        super();
        this.name = 'getRecentlyPublishedDatasets';
        this.description = 'Returns most recently published datasets';
        this.do_not_authenticate = true;
    }

    async run({response}) {
        const recentlyPublishedDatasets = await dal.tryCatch(async() => await api.mc.publishedDatasets.getRecentlyPublishedDatasets());

        response.data = recentlyPublishedDatasets ? recentlyPublishedDatasets : [];
    }
};

module.exports.GetPublishedDatasetAction = class GetPublishedDatasetAction extends Action {
    constructor() {
        super();
        this.name = 'getPublishedDataset';
        this.description = 'Returns the published dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true
            }
        };
    }

    async run({response, params}) {
        const ds = await dal.tryCatch(async() => await api.mc.publishedDatasets.getDataset(params.dataset_id));
        if (!ds) {
            throw new Error(`No such dataset_id ${params.dataset_id}`);
        }
        response.data = ds;
    }
};

module.exports.GetPublishedDatasetsForTagAction = class GetPublishedDatasetsForTagAction extends Action {
    constructor() {
        super();
        this.name = 'getPublishedDatasetsForTag';
        this.description = 'Returns all published datasets associated with the tag';
        this.inputs = {
            tag_id: {
                required: true,
            }
        };
    }

    async run({response, params}) {
        const datasetsForTag = await dal.tryCatch(async() => await api.mc.publishedDatasets.getDatasetsForTag(params.tag_id));
        if (!datasetsForTag) {
            throw new Error(`No datasets for tag ${params.tag_id}`);
        }
        response.data = datasetsForTag;
    }
};

module.exports.GetPublishedDatasetProcessAction = class GetPublishedDatasetProcessAction extends Action {
    constructor() {
        super();
        this.name = 'getPublishedDatasetProcess';
        this.description = 'Returns the process in the published dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            },
            process_id: {
                required: true,
            }
        };
    }

    async run({response, params}) {
        const process = await dal.tryCatch(async() => await api.mc.publishedDatasets.getProcessForDataset(params.dataset_id, params.process_id));
        if (!process) {
            throw new Error(`No such process ${params.process_id} and/or dataset ${params.dataset_id}`);
        }
        response.data = process;
    }
};

module.exports.GetCommentsForPublishedDatasetAction = class GetCommentsForPublishedDatasetAction extends Action {
    constructor() {
        super();
        this.name = 'getCommentsForPublishedDataset';
        this.description = 'Returns the comments for the published dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            }
        };
    }

    async run({response, params}) {
        const comments = await dal.tryCatch(async() => await api.mc.publishedDatasets.getCommentsForDataset(params.dataset_id));
        if (comments == null) {
            throw new Error(`Unknown dataset ${params.dataset_id}`);
        }
        response.data = comments;
    }
};

module.exports.IncrementPublishedDatasetViewsAction = class IncrementPublishedDatasetViewsAction extends Action {
    constructor() {
        super();
        this.name = 'incrementPublishedDatasetViews';
        this.description = 'Increments the published datasets view count and returns dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            },

            user_id: {
                required: false,
            }
        };
    }

    async run({response, params, request}) {
        let userId = params.user_id ? params.user_id : request.remoteIP;
        const dataset = await dal.tryCatch(async() => await api.mc.publishedDatasets.incrementViewForDataset(params.dataset_id, userId));
        if (!dataset) {
            throw new Error(`Unable to update dataset ${params.dataset_id} view count`);
        }
        response.data = dataset;
    }
};

module.exports.UpdatePublishedDatasetUsefulCountAction = class UpdatePublishedDatasetUsefulCountAction extends Action {
    constructor() {
        super();
        this.name = 'updatePublishedDatasetUsefulCount';
        this.description = 'Increments or decrements the useful count for a public dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            },
            user_id: {
                required: true,
            },
            action: {
                required: true,
                validator: (param) => {
                    if (param !== 'add' && param !== 'delete') {
                        throw new Error(`action must be either 'add' or 'delete', ${param} not recognized`);
                    }
                }
            }
        };
    }

    async run({response, params}) {
        let ds;

        if (params.action === 'add') {
            ds = await dal.tryCatch(async() => await api.mc.publishedDatasets.markDatasetAsUseful(params.dataset_id, params.user_id));
        } else {
            // params.action === 'delete'
            ds = await dal.tryCatch(async() => await api.mc.publishedDatasets.unmarkDatasetAsUseful(params.dataset_id, params.user_id));
        }

        if (!ds) {
            throw new Error(`Unable to ${params.action === 'add' ? 'mark' : 'unmark'} dataset ${params.dataset_id} for user ${params.user_id}`);
        }

        response.data = ds;
    }
};

module.exports.GetPopularTagsForPublishedDatasetsAction = class GetPopularTagsForPublishedDatasetsAction extends Action {
    constructor() {
        super();
        this.name = 'getPopularTagsForPublishedDatasets';
        this.description = 'Gets the most popular tags for all published datasets';
        this.do_not_authenticate = true;
    }

    async run({response}) {
        const tags = await dal.tryCatch(async() => await api.mc.publishedDatasets.getMostPopularTagsForDatasets());
        if (!tags) {
            throw new Error(`Unable to retrieve most popular tags for published datasets`);
        }
        response.data = tags;
    }
};

module.exports.DownloadDatasetZipfileAction = class DownloadDatasetZipFileAction extends Action {
    constructor() {
        super();
        this.name = 'downloadDatasetZipfile';
        this.description = 'Returns the zipfile and updates the downloads count';
        this.inputs = {
            dataset_id: {
                required: true
            }
        };
    }

    async run(data) {
        const filepath = await dal.tryCatch(async() => await api.mc.publishedDatasets.updataDownloadCountAndReturnFilePath(data.params.dataset_id));
        if (!filepath) {
            throw new Error(`Unable to retrieve zip file for dataset ${data.params.dataset_id}`);
        }

        const filename = path.basename(filepath);
        let fstream = fs.createReadStream(filepath);
        data.connection.rawConnection.responseHeaders.push(['Content-Disposition', `attachment; filename=${filename}`]);
        api.mc.servers.servers.web.sendFile(data.connection, null, fstream, 'application/zip');
        data.toRender = false;
    }
};<commit_msg>Global replacement to use mc on api changed a reference it shouldn't have<commit_after>const {Action, api} = require('actionhero');
const dal = require('@dal');
const fs = require('fs');
const path = require('path');

module.exports.GetTopViewedPublishedDatasetsAction = class GetTopViewedPublishedDatasetsAction extends Action {
    constructor() {
        super();
        this.name = 'getTopViewedPublishedDatasets';
        this.description = 'Returns the most viewed datasets';
        this.do_not_authenticate = true;
    }

    async run({response}) {
        const topViewedDatasets = await dal.tryCatch(async() => await api.mc.publishedDatasets.getTopViewedDatasets());
        response.data = topViewedDatasets ? topViewedDatasets : [];
    }
};

module.exports.GetRecentlyPublishedDatasetsAction = class GetRecentlyPublishedDatasetsAction extends Action {
    constructor() {
        super();
        this.name = 'getRecentlyPublishedDatasets';
        this.description = 'Returns most recently published datasets';
        this.do_not_authenticate = true;
    }

    async run({response}) {
        const recentlyPublishedDatasets = await dal.tryCatch(async() => await api.mc.publishedDatasets.getRecentlyPublishedDatasets());

        response.data = recentlyPublishedDatasets ? recentlyPublishedDatasets : [];
    }
};

module.exports.GetPublishedDatasetAction = class GetPublishedDatasetAction extends Action {
    constructor() {
        super();
        this.name = 'getPublishedDataset';
        this.description = 'Returns the published dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true
            }
        };
    }

    async run({response, params}) {
        const ds = await dal.tryCatch(async() => await api.mc.publishedDatasets.getDataset(params.dataset_id));
        if (!ds) {
            throw new Error(`No such dataset_id ${params.dataset_id}`);
        }
        response.data = ds;
    }
};

module.exports.GetPublishedDatasetsForTagAction = class GetPublishedDatasetsForTagAction extends Action {
    constructor() {
        super();
        this.name = 'getPublishedDatasetsForTag';
        this.description = 'Returns all published datasets associated with the tag';
        this.inputs = {
            tag_id: {
                required: true,
            }
        };
    }

    async run({response, params}) {
        const datasetsForTag = await dal.tryCatch(async() => await api.mc.publishedDatasets.getDatasetsForTag(params.tag_id));
        if (!datasetsForTag) {
            throw new Error(`No datasets for tag ${params.tag_id}`);
        }
        response.data = datasetsForTag;
    }
};

module.exports.GetPublishedDatasetProcessAction = class GetPublishedDatasetProcessAction extends Action {
    constructor() {
        super();
        this.name = 'getPublishedDatasetProcess';
        this.description = 'Returns the process in the published dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            },
            process_id: {
                required: true,
            }
        };
    }

    async run({response, params}) {
        const process = await dal.tryCatch(async() => await api.mc.publishedDatasets.getProcessForDataset(params.dataset_id, params.process_id));
        if (!process) {
            throw new Error(`No such process ${params.process_id} and/or dataset ${params.dataset_id}`);
        }
        response.data = process;
    }
};

module.exports.GetCommentsForPublishedDatasetAction = class GetCommentsForPublishedDatasetAction extends Action {
    constructor() {
        super();
        this.name = 'getCommentsForPublishedDataset';
        this.description = 'Returns the comments for the published dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            }
        };
    }

    async run({response, params}) {
        const comments = await dal.tryCatch(async() => await api.mc.publishedDatasets.getCommentsForDataset(params.dataset_id));
        if (comments == null) {
            throw new Error(`Unknown dataset ${params.dataset_id}`);
        }
        response.data = comments;
    }
};

module.exports.IncrementPublishedDatasetViewsAction = class IncrementPublishedDatasetViewsAction extends Action {
    constructor() {
        super();
        this.name = 'incrementPublishedDatasetViews';
        this.description = 'Increments the published datasets view count and returns dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            },

            user_id: {
                required: false,
            }
        };
    }

    async run({response, params, request}) {
        let userId = params.user_id ? params.user_id : request.remoteIP;
        const dataset = await dal.tryCatch(async() => await api.mc.publishedDatasets.incrementViewForDataset(params.dataset_id, userId));
        if (!dataset) {
            throw new Error(`Unable to update dataset ${params.dataset_id} view count`);
        }
        response.data = dataset;
    }
};

module.exports.UpdatePublishedDatasetUsefulCountAction = class UpdatePublishedDatasetUsefulCountAction extends Action {
    constructor() {
        super();
        this.name = 'updatePublishedDatasetUsefulCount';
        this.description = 'Increments or decrements the useful count for a public dataset';
        this.do_not_authenticate = true;
        this.inputs = {
            dataset_id: {
                required: true,
            },
            user_id: {
                required: true,
            },
            action: {
                required: true,
                validator: (param) => {
                    if (param !== 'add' && param !== 'delete') {
                        throw new Error(`action must be either 'add' or 'delete', ${param} not recognized`);
                    }
                }
            }
        };
    }

    async run({response, params}) {
        let ds;

        if (params.action === 'add') {
            ds = await dal.tryCatch(async() => await api.mc.publishedDatasets.markDatasetAsUseful(params.dataset_id, params.user_id));
        } else {
            // params.action === 'delete'
            ds = await dal.tryCatch(async() => await api.mc.publishedDatasets.unmarkDatasetAsUseful(params.dataset_id, params.user_id));
        }

        if (!ds) {
            throw new Error(`Unable to ${params.action === 'add' ? 'mark' : 'unmark'} dataset ${params.dataset_id} for user ${params.user_id}`);
        }

        response.data = ds;
    }
};

module.exports.GetPopularTagsForPublishedDatasetsAction = class GetPopularTagsForPublishedDatasetsAction extends Action {
    constructor() {
        super();
        this.name = 'getPopularTagsForPublishedDatasets';
        this.description = 'Gets the most popular tags for all published datasets';
        this.do_not_authenticate = true;
    }

    async run({response}) {
        const tags = await dal.tryCatch(async() => await api.mc.publishedDatasets.getMostPopularTagsForDatasets());
        if (!tags) {
            throw new Error(`Unable to retrieve most popular tags for published datasets`);
        }
        response.data = tags;
    }
};

module.exports.DownloadDatasetZipfileAction = class DownloadDatasetZipFileAction extends Action {
    constructor() {
        super();
        this.name = 'downloadDatasetZipfile';
        this.description = 'Returns the zipfile and updates the downloads count';
        this.inputs = {
            dataset_id: {
                required: true
            }
        };
    }

    async run(data) {
        const filepath = await dal.tryCatch(async() => await api.mc.publishedDatasets.updataDownloadCountAndReturnFilePath(data.params.dataset_id));
        if (!filepath) {
            throw new Error(`Unable to retrieve zip file for dataset ${data.params.dataset_id}`);
        }

        const filename = path.basename(filepath);
        let fstream = fs.createReadStream(filepath);
        data.connection.rawConnection.responseHeaders.push(['Content-Disposition', `attachment; filename=${filename}`]);
        api.servers.servers.web.sendFile(data.connection, null, fstream, 'application/zip');
        data.toRender = false;
    }
};<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

var packageJson = require(__dirname + '/../package.json');
<commit_msg>started option parsing<commit_after>#!/usr/bin/env node
'use strict';

var packageJson = require(__dirname + '/../package.json');
var parseArgs = require('minimist');

var paramOptions = {
    boolean: [
        'version',
        'help'
    ],
    string: [
        'url'
    ],
    alias: {
        'v': 'version',
        'h': 'help',
        'u': 'url'
    },
    default: {
        version: false,
        help: false
    }
};

var argv = parseArgs(process.argv.slice(2), paramOptions);

if(argv.help === true) {
    showUsageHelp();
}

if(argv.version === true) {
    console.log('haste version: %s', packageJson.version);
    process.exit(0);
}

if(!argv.url) {
    showUsageHelp();
}

console.log("running...");
//console.dir(argv);

function showUsageHelp()
{
    console.log('Usage: haste [options]');
    console.log('   --help           Show this help');
    console.log('   --version        Show version number');
    console.log('   --url            Add a URL step to the test');
    process.exit(1);
}<|endoftext|>


<commit_before>/**
 * Create a JSONP request
 *
 * @param {String} url
 * @param {Object} options
 */

function ajaxJSONP(url, options) {
  var name = (name = /callback\=([A-Za-z0-9\-\.]+)/.exec(url)) ? name[1] : 'jsonp' + (+new Date())
    , elm = document.createElement('script');

  elm.onerror = function () {
    tire(elm).remove();
    try { delete window[name]; }
    catch (e) { window[name] = undefined; }
    if (tire.isFun(options.error)) options.error('abort');
  };

  window[name] = function (data) {
    tire(elm).remove();
    try { delete window[name]; }
    catch (e) { window[name] = undefined; }
    ajaxSuccess(data, null, options);
  };

  options.data = tire.param(options.data);
  elm.src = url.replace(/\=\?/, '=' + name);
  tire('head')[0].appendChild(elm);
}

/**
 * Ajax success. Check if the dataType is JSON and try to parse it or just return the response text/xml.
 *
 * @param {Object} data
 * @param {Object} xhr
 * @param {Object} options
 * @return {Object}
 */

function ajaxSuccess(data, xhr, options) {
  var res;
  if (xhr) {
    if ((options.dataType === 'json' || false) && (res = tire.parseJSON(xhr.responseText)) === null) res = xhr.responseText;
    if (options.dataType === 'xml') res = xhr.responseXML;
    res = res || xhr.responseText;
  }
  if (!res && data) res = data;
  if (tire.isFunction(options.success)) options.success(res);
}

tire.fn.extend({

  /**
   * Ajax method to create ajax request with XMLHTTPRequest (or ActiveXObject).
   * Supports JSONP, no cross domain yet.
   *
   * @param {String|Object} url
   * @param {Object|Function} options
   * @return {Object}
   */

  ajax: function (url, options) {
    options = options || {};

    if (tire.isObject(url)) {
      if (tire.isFunction(options)) {
        url.success = url.success || options;
      }
      options = url;
      url = options.url;
    }

    if (tire.isFunction(options)) options = { success: options };

    options.dataType = (options.dataType || '').toLowerCase();

    // won't do anything without a url
    if (!url) return;

    var self = this
      , method = (options.type || 'GET').toUpperCase()
      , params = options.data || null
      , jsonp = options.dataType === 'jsonp' || false
      , xhr
      , mime = { // support for script needed
          html: 'text/html',
          text: 'text/plain',
          xml: 'application/xml, text/xml',
          json: 'application/json'
      };

    if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // < IE 9
      xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }

    for (var k in mime) {
      if (url.indexOf('.' + k) !== -1 && !options.dataType) options.dataType = k;
    }

    // test for jsonp
    if (jsonp || /\=\?|callback\=/.test(url)) {
      if (/\=\?/.test(url)) url = (url + '&callback=?').replace(/[&?]{1,2}/, '?');
      ajaxJSONP(url, options);
      return this;
    }

    if (xhr) {
      xhr.queryString = params;
      xhr.open(method, url, true);
      xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');

      if ((mime = mime[options.dataType]) !== undefined) {
        xhr.setRequestHeader('Accept', mime);
        if (mime.indexOf(',') !== -1) mime = mime.split(',')[0];
        if (xhr.overrideMimeType) xhr.overrideMimeType(mime);
      }

      if (options.contentType || options.data && method !== 'GET') {
        xhr.setRequestHeader('Content-Type', (options.contentType || 'application/x-www-form-urlencoded'));
      }

      for (var key in options.headers) {
        if (options.headers.hasOwnProperty(key)) {
          xhr.setRequestHeader(key, options.headers[key]);
        }
      }

      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
            if (options.success !== undefined) {
              ajaxSuccess(null, xhr, options);
            }
          } else if (options.error !== undefined) {
            options.error(xhr, options);
          }
        }
      };

      xhr.send(tire.param(params));
    }

    return this;
  }
});

tire.extend({
  ajax: tire.fn.ajax,

  /**
   * Create a serialized representation of an array or object.
   *
   * @param {Array|Object} obj
   * @param {Obj} prefix
   * @return {String}
   */

  param: function (obj, prefix) {
    var str = [];
    this.each(obj, function (p, v) {
      var k = prefix ? prefix + '[' + p + ']' : p;
      str.push(tire.isObject(v) ? tire.param(v, k) : encodeURIComponent(k) + '=' + encodeURIComponent(v));
    });
    return str.join('&').replace('%20', '+');
  }
});<commit_msg>JSONP callback fix<commit_after>/**
 * Create a JSONP request
 *
 * @param {String} url
 * @param {Object} options
 */

function ajaxJSONP(url, options) {
  var name = (name = /callback\=([A-Za-z0-9\-\.]+)/.exec(url)) ? name[1] : 'jsonp' + (+new Date())
    , elm = document.createElement('script');

  elm.onerror = function () {
    tire(elm).remove();
    try { delete window[name]; }
    catch (e) { window[name] = undefined; }
    if (tire.isFun(options.error)) options.error('abort');
  };

  window[name] = function (data) {
    tire(elm).remove();
    try { delete window[name]; }
    catch (e) { window[name] = undefined; }
    ajaxSuccess(data, null, options);
  };

  options.data = tire.param(options.data);
  elm.src = url.replace(/\=\?/, '=' + name);
  tire('head')[0].appendChild(elm);
}

/**
 * Ajax success. Check if the dataType is JSON and try to parse it or just return the response text/xml.
 *
 * @param {Object} data
 * @param {Object} xhr
 * @param {Object} options
 * @return {Object}
 */

function ajaxSuccess(data, xhr, options) {
  var res;
  if (xhr) {
    if ((options.dataType === 'json' || false) && (res = tire.parseJSON(xhr.responseText)) === null) res = xhr.responseText;
    if (options.dataType === 'xml') res = xhr.responseXML;
    res = res || xhr.responseText;
  }
  if (!res && data) res = data;
  if (tire.isFunction(options.success)) options.success(res);
}

tire.fn.extend({

  /**
   * Ajax method to create ajax request with XMLHTTPRequest (or ActiveXObject).
   * Supports JSONP, no cross domain yet.
   *
   * @param {String|Object} url
   * @param {Object|Function} options
   * @return {Object}
   */

  ajax: function (url, options) {
    options = options || {};

    if (tire.isObject(url)) {
      if (tire.isFunction(options)) {
        url.success = url.success || options;
      }
      options = url;
      url = options.url;
    }

    if (tire.isFunction(options)) options = { success: options };

    options.dataType = (options.dataType || '').toLowerCase();

    // won't do anything without a url
    if (!url) return;

    var self = this
      , method = (options.type || 'GET').toUpperCase()
      , params = options.data || null
      , jsonp = options.dataType === 'jsonp' || false
      , xhr
      , mime = { // support for script needed
          html: 'text/html',
          text: 'text/plain',
          xml: 'application/xml, text/xml',
          json: 'application/json'
      };

    if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // < IE 9
      xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }

    for (var k in mime) {
      if (url.indexOf('.' + k) !== -1 && !options.dataType) options.dataType = k;
    }

    // test for jsonp
    if (jsonp || /\=\?|callback\=/.test(url)) {
      if (!/\=\?/.test(url)) url = (url + '&callback=?').replace(/[&?]{1,2}/, '?');
      ajaxJSONP(url, options);
      return this;
    }

    if (xhr) {
      xhr.queryString = params;
      xhr.open(method, url, true);
      xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');

      if ((mime = mime[options.dataType]) !== undefined) {
        xhr.setRequestHeader('Accept', mime);
        if (mime.indexOf(',') !== -1) mime = mime.split(',')[0];
        if (xhr.overrideMimeType) xhr.overrideMimeType(mime);
      }

      if (options.contentType || options.data && method !== 'GET') {
        xhr.setRequestHeader('Content-Type', (options.contentType || 'application/x-www-form-urlencoded'));
      }

      for (var key in options.headers) {
        if (options.headers.hasOwnProperty(key)) {
          xhr.setRequestHeader(key, options.headers[key]);
        }
      }

      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
            if (options.success !== undefined) {
              ajaxSuccess(null, xhr, options);
            }
          } else if (options.error !== undefined) {
            options.error(xhr, options);
          }
        }
      };

      xhr.send(tire.param(params));
    }

    return this;
  }
});

tire.extend({
  ajax: tire.fn.ajax,

  /**
   * Create a serialized representation of an array or object.
   *
   * @param {Array|Object} obj
   * @param {Obj} prefix
   * @return {String}
   */

  param: function (obj, prefix) {
    var str = [];
    this.each(obj, function (p, v) {
      var k = prefix ? prefix + '[' + p + ']' : p;
      str.push(tire.isObject(v) ? tire.param(v, k) : encodeURIComponent(k) + '=' + encodeURIComponent(v));
    });
    return str.join('&').replace('%20', '+');
  }
});<|endoftext|>