<commit_before>define(["dojo", "."], function(dojo, dijit) {
	// module:
	//		dijit/_Container
	// summary:
	//		TODOC

dojo.declare("dijit._Container",
	null,
	{
		// summary:
		//		Mixin for widgets that contain a set of widget children.
		// description:
		//		Use this mixin for widgets that needs to know about and
		//		keep track of their widget children. Suitable for widgets like BorderContainer
		//		and TabContainer which contain (only) a set of child widgets.
		//
		//		It's not suitable for widgets like ContentPane
		//		which contains mixed HTML (plain DOM nodes in addition to widgets),
		//		and where contained widgets are not necessarily directly below
		//		this.containerNode.   In that case calls like addChild(node, position)
		//		wouldn't make sense.

		// isContainer: [protected] Boolean
		//		Indicates that this widget acts as a "parent" to the descendant widgets.
		//		When the parent is started it will call startup() on the child widgets.
		//		See also `isLayoutContainer`.
		isContainer: true,

		buildRendering: function(){
			this.inherited(arguments);
			if(!this.containerNode){
				// all widgets with descendants must set containerNode
	 				this.containerNode = this.domNode;
			}
		},

		addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
			// summary:
			//		Makes the given widget a child of this widget.
			// description:
			//		Inserts specified child widget's dom node as a child of this widget's
			//		container node, and possibly does other processing (such as layout).

			var refNode = this.containerNode;
			if(insertIndex && typeof insertIndex == "number"){
				var children = this.getChildren();
				if(children && children.length >= insertIndex){
					refNode = children[insertIndex-1].domNode;
					insertIndex = "after";
				}
			}
			dojo.place(widget.domNode, refNode, insertIndex);

			// If I've been started but the child widget hasn't been started,
			// start it now.  Make sure to do this after widget has been
			// inserted into the DOM tree, so it can see that it's being controlled by me,
			// so it doesn't try to size itself.
			if(this._started && !widget._started){
				widget.startup();
			}
		},

		removeChild: function(/*Widget or int*/ widget){
			// summary:
			//		Removes the passed widget instance from this widget but does
			//		not destroy it.  You can also pass in an integer indicating
			//		the index within the container to remove

			if(typeof widget == "number"){
				widget = this.getChildren()[widget];
			}

			if(widget){
				var node = widget.domNode;
				if(node && node.parentNode){
					node.parentNode.removeChild(node); // detach but don't destroy
				}
			}
		},

		hasChildren: function(){
			// summary:
			//		Returns true if widget has children, i.e. if this.containerNode contains something.
			return this.getChildren().length > 0;	// Boolean
		},

		destroyDescendants: function(/*Boolean*/ preserveDom){
			// summary:
			//      Destroys all the widgets inside this.containerNode,
			//      but not this widget itself
			dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); });
		},

		_getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
			// summary:
			//		Get the next or previous widget sibling of child
			// dir:
			//		if 1, get the next sibling
			//		if -1, get the previous sibling
			// tags:
			//      private
			var node = child.domNode,
				which = (dir>0 ? "nextSibling" : "previousSibling");
			do{
				node = node[which];
			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
			return node && dijit.byNode(node);	// dijit._Widget
		},

		getIndexOfChild: function(/*dijit._Widget*/ child){
			// summary:
			//		Gets the index of the child in this container or -1 if not found
			return dojo.indexOf(this.getChildren(), child);	// int
		},

		startup: function(){
			// summary:
			//		Called after all the widgets have been instantiated and their
			//		dom nodes have been inserted somewhere under dojo.doc.body.
			//
			//		Widgets should override this method to do any initialization
			//		dependent on other widgets existing, and then call
			//		this superclass method to finish things off.
			//
			//		startup() in subclasses shouldn't do anything
			//		size related because the size of the widget hasn't been set yet.

			if(this._started){ return; }

			// Startup all children of this widget
			dojo.forEach(this.getChildren(), function(child){ child.startup(); });

			this.inherited(arguments);
		}
	}
);

return dijit._Container;
});
<commit_msg>comment / spacing fixes, sort of refs #12672 !strict.<commit_after>define(["dojo", "."], function(dojo, dijit){
	// module:
	//		dijit/_Container
	// summary:
	//		Mixin for widgets that contain a set of widget children.

	dojo.declare("dijit._Container", null, {
		// summary:
		//		Mixin for widgets that contain a set of widget children.
		// description:
		//		Use this mixin for widgets that needs to know about and
		//		keep track of their widget children. Suitable for widgets like BorderContainer
		//		and TabContainer which contain (only) a set of child widgets.
		//
		//		It's not suitable for widgets like ContentPane
		//		which contains mixed HTML (plain DOM nodes in addition to widgets),
		//		and where contained widgets are not necessarily directly below
		//		this.containerNode.   In that case calls like addChild(node, position)
		//		wouldn't make sense.

		// isContainer: [protected] Boolean
		//		Indicates that this widget acts as a "parent" to the descendant widgets.
		//		When the parent is started it will call startup() on the child widgets.
		//		See also `isLayoutContainer`.
		isContainer: true,

		buildRendering: function(){
			this.inherited(arguments);
			if(!this.containerNode){
				// all widgets with descendants must set containerNode
	 				this.containerNode = this.domNode;
			}
		},

		addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
			// summary:
			//		Makes the given widget a child of this widget.
			// description:
			//		Inserts specified child widget's dom node as a child of this widget's
			//		container node, and possibly does other processing (such as layout).

			var refNode = this.containerNode;
			if(insertIndex && typeof insertIndex == "number"){
				var children = this.getChildren();
				if(children && children.length >= insertIndex){
					refNode = children[insertIndex-1].domNode;
					insertIndex = "after";
				}
			}
			dojo.place(widget.domNode, refNode, insertIndex);

			// If I've been started but the child widget hasn't been started,
			// start it now.  Make sure to do this after widget has been
			// inserted into the DOM tree, so it can see that it's being controlled by me,
			// so it doesn't try to size itself.
			if(this._started && !widget._started){
				widget.startup();
			}
		},

		removeChild: function(/*Widget|int*/ widget){
			// summary:
			//		Removes the passed widget instance from this widget but does
			//		not destroy it.  You can also pass in an integer indicating
			//		the index within the container to remove

			if(typeof widget == "number"){
				widget = this.getChildren()[widget];
			}

			if(widget){
				var node = widget.domNode;
				if(node && node.parentNode){
					node.parentNode.removeChild(node); // detach but don't destroy
				}
			}
		},

		hasChildren: function(){
			// summary:
			//		Returns true if widget has children, i.e. if this.containerNode contains something.
			return this.getChildren().length > 0;	// Boolean
		},

		destroyDescendants: function(/*Boolean*/ preserveDom){
			// summary:
			//      Destroys all the widgets inside this.containerNode,
			//      but not this widget itself
			dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); });
		},

		_getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
			// summary:
			//		Get the next or previous widget sibling of child
			// dir:
			//		if 1, get the next sibling
			//		if -1, get the previous sibling
			// tags:
			//      private
			var node = child.domNode,
				which = (dir>0 ? "nextSibling" : "previousSibling");
			do{
				node = node[which];
			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
			return node && dijit.byNode(node);	// dijit._Widget
		},

		getIndexOfChild: function(/*dijit._Widget*/ child){
			// summary:
			//		Gets the index of the child in this container or -1 if not found
			return dojo.indexOf(this.getChildren(), child);	// int
		},

		startup: function(){
			// summary:
			//		Called after all the widgets have been instantiated and their
			//		dom nodes have been inserted somewhere under dojo.doc.body.
			//
			//		Widgets should override this method to do any initialization
			//		dependent on other widgets existing, and then call
			//		this superclass method to finish things off.
			//
			//		startup() in subclasses shouldn't do anything
			//		size related because the size of the widget hasn't been set yet.

			if(this._started){ return; }

			// Startup all children of this widget
			dojo.forEach(this.getChildren(), function(child){ child.startup(); });

			this.inherited(arguments);
		}
	});

	return dijit._Container;
});
<|endoftext|>


<commit_before>'use strict';

angular.module('csyywx')
	.controller('BalanceCtrl', function($scope, $stateParams, AccountApi, userConfig, balanceService, $filter) {
		var queryType = 0;
		switch($stateParams.type) {
			case 'accumulative':
				$scope.title = '累计收益';
				$scope.balance = balanceService.balance.totalIncome;
				break;
			case 'total':
				$scope.title = '总资产';
				queryType = 1;
				$scope.balance = balanceService.balance.total;
				break;
			case 'regular':
				$scope.title = '定期资产';
				queryType = 2;
				$scope.balance = balanceService.balance.regular;
				break;
			case 'demand':
				$scope.title = '活期资产';
				queryType = 3;
				$scope.balance = balanceService.balance.demand;
				break;
		}

		if(queryType) {
			AccountApi.getBalanceDetail({
				sessionId: userConfig.getSessionId(),
				queryType: queryType
			}).success(function(data) {
				if(+data.flag === 1) {
					$scope.items = data.data.assetList.map(function(obj) {
						var status;
						switch(+obj.status) {
							case 1:
								status = '转活期';
								break;
							case 2:
								status = '提现';
								break;
							case 3:
								status = '转定期';
								break;
							default:
								status = '买入';
						}

						return {
							date: $filter('date')(new Date(obj.investDate), 'yyyy-MM-dd'),
							desc: obj.termDesc,
							amount: obj.investAmount,
							status: status
						};
					});
				}
			});
		} else {
			AccountApi.getLatestIncome({sessionId: userConfig.getSessionId()})
				.success(function(data) {
					if(+data.flag === 1) {
						$scope.items = data.data.interestList.map(function(obj) {
							return {
								date: obj.interestDate,
								amount: obj.actualInterest
							}
						})
					}
				})
		}

	})<commit_msg>set status to success for demand balance detail<commit_after>'use strict';

angular.module('csyywx')
	.controller('BalanceCtrl', function($scope, $stateParams, AccountApi, userConfig, balanceService, $filter) {
		var queryType = 0;
		switch($stateParams.type) {
			case 'accumulative':
				$scope.title = '累计收益';
				$scope.balance = balanceService.balance.totalIncome;
				break;
			case 'total':
				$scope.title = '总资产';
				queryType = 1;
				$scope.balance = balanceService.balance.total;
				break;
			case 'regular':
				$scope.title = '定期资产';
				queryType = 2;
				$scope.balance = balanceService.balance.regular;
				break;
			case 'demand':
				$scope.title = '活期资产';
				queryType = 3;
				$scope.balance = balanceService.balance.demand;
				break;
		}

		if(queryType) {
			AccountApi.getBalanceDetail({
				sessionId: userConfig.getSessionId(),
				queryType: queryType
			}).success(function(data) {
				if(+data.flag === 1) {
					$scope.items = data.data.assetList.map(function(obj) {
						var status;
						switch(+obj.status) {
							case 1:
								status = '转活期';
								break;
							case 2:
								status = '提现';
								break;
							case 3:
								status = '转定期';
								break;
							default:
								status = '买入';
						}

						if(+queryType === 3) {
							status = '成功';
						}

						return {
							date: $filter('date')(new Date(obj.investDate), 'yyyy-MM-dd'),
							desc: obj.termDesc,
							amount: obj.investAmount,
							status: status
						};
					});
				}
			});
		} else {
			AccountApi.getLatestIncome({sessionId: userConfig.getSessionId()})
				.success(function(data) {
					if(+data.flag === 1) {
						$scope.items = data.data.interestList.map(function(obj) {
							return {
								date: obj.interestDate,
								amount: obj.actualInterest
							}
						})
					}
				})
		}

	})<|endoftext|>


<commit_before>((app) => {
    'use strict'
    app.component("vibe", {
        templateUrl: 'js/components/vibe/vibe.html',
        controller: ['ngMeta', 'JsonService', 'MapsService', '$http', 'WordpressService', '$stateParams', function(ngMeta, JsonService, MapsService, $http, WordpressService, $stateParams) {
            angular.extend(this, {
                $onInit() {
                    WordpressService.getPostById($stateParams.id).then((res)=> {
                        this.vibe = res.data;
                        $( "#post-content" ).html($(res.data.content.rendered));
                        this.tagsName = [];
                        var lat;
                        var lng;
                        var coordinates;
                        var indices = [];
                        var string = res.data.content.rendered.substring(res.data.content.rendered.length - 45,res.data.content.rendered.length)
                        for(var i=0;i<string.length;i++) {
                            if (string[i] === "|") indices.push(i);
                        }
                        coordinates = string.substring(indices[0]+1, indices[1]).split(';');

                        MapsService.createMapWithMarker(coordinates);

                        res.data.tags.forEach((el)=> {
                                WordpressService.getTagById(el).then((response) => {
                                    this.tagsName.push(response.data.name)
                            });
                        })
                        var base_url = "http://korea.vibesharing.com/#!/vibes/"
                        console.log(res.data.better_featured_image.source_url)
                        ngMeta.setTitle('Vibesharing |'+ res.data.title.rendered);
                        ngMeta.setTag('author', 'Hadrien Buret');
                        ngMeta.setTag('description', res.data.content.rendered.substring(0,121));
                        ngMeta.setTag('type', 'article');
                        ngMeta.setTag('image', res.data.better_featured_image.source_url);
                        ngMeta.setTag('og:image:width',res.data.better_featured_image.media_details.width);
                        ngMeta.setTag('og:image:height',res.data.better_featured_image.media_details.height)
                        ngMeta.setTag('url', base_url.concat(res.data.id));
                    })
                    ngMeta.setTitle('Vibesharing | Travel for People and culture by bike on Budget');
                    ngMeta.setTag('author', 'Hadrien Buret');
                    ngMeta.setTag('description', 'Vibesharing is a travel blog where you will find articles, maps and other tips on how to travel in Asia and South-Korea by bike on a budget.');
                    ngMeta.setTag('type', 'website');
                    ngMeta.setTag('image', 'https://s3.eu-central-1.amazonaws.com/vibesharing-static/vibesharing_home_page_meta.png');
                    ngMeta.setTag('url', 'http://korea.vibesharing.com/#!');

                }
            })
        }]
    })
})(angular.module('app.vibe'))
<commit_msg>try fix on<commit_after>((app) => {
    'use strict'
    app.component("vibe", {
        templateUrl: 'js/components/vibe/vibe.html',
        controller: ['ngMeta', 'JsonService', 'MapsService', '$http', 'WordpressService', '$stateParams', function(ngMeta, JsonService, MapsService, $http, WordpressService, $stateParams) {
            angular.extend(this, {
                $onInit() {
                    WordpressService.getPostById($stateParams.id).then((res)=> {
                        var base_url = "http://korea.vibesharing.com/#!/vibes/"
                        console.log(res.data.better_featured_image.source_url)
                        ngMeta.setTitle('Vibesharing |'+ res.data.title.rendered);
                        ngMeta.setTag('author', 'Hadrien Buret');
                        ngMeta.setTag('description', res.data.content.rendered.substring(0,121));
                        ngMeta.setTag('type', 'article');
                        ngMeta.setTag('image', res.data.better_featured_image.source_url);
                        ngMeta.setTag('og:image:width',res.data.better_featured_image.media_details.width);
                        ngMeta.setTag('og:image:height',res.data.better_featured_image.media_details.height)
                        ngMeta.setTag('url', base_url.concat(res.data.id));

                        this.vibe = res.data;
                        $( "#post-content" ).html($(res.data.content.rendered));
                        this.tagsName = [];
                        var lat;
                        var lng;
                        var coordinates;
                        var indices = [];
                        var string = res.data.content.rendered.substring(res.data.content.rendered.length - 45,res.data.content.rendered.length)
                        for(var i=0;i<string.length;i++) {
                            if (string[i] === "|") indices.push(i);
                        }
                        coordinates = string.substring(indices[0]+1, indices[1]).split(';');

                        MapsService.createMapWithMarker(coordinates);

                        res.data.tags.forEach((el)=> {
                                WordpressService.getTagById(el).then((response) => {
                                    this.tagsName.push(response.data.name)
                            });
                        })
                    })
                }
            })
        }]
    })
})(angular.module('app.vibe'))
<|endoftext|>


<commit_before>const _ = require('lodash'),
    nql = require('@nexes/nql'),
    debug = require('ghost-ignition').debug('services:url:generator'),
    localUtils = require('./utils'),
    // @TODO: merge with filter plugin
    EXPANSIONS = [{
        key: 'author',
        replacement: 'authors.slug'
    }, {
        key: 'tags',
        replacement: 'tags.slug'
    }, {
        key: 'tag',
        replacement: 'tags.slug'
    }, {
        key: 'authors',
        replacement: 'authors.slug'
    }];

class UrlGenerator {
    constructor(router, queue, resources, urls, position) {
        this.router = router;
        this.queue = queue;
        this.urls = urls;
        this.resources = resources;
        this.uid = position;

        debug('constructor', this.toString());

        // CASE: routers can define custom filters, but not required.
        if (this.router.getFilter()) {
            this.filter = this.router.getFilter();
            this.nql = nql(this.filter, {expansions: EXPANSIONS});
            debug('filter', this.filter);
        }

        this._listeners();
    }

    _listeners() {
        /**
         * @NOTE: currently only used if the permalink setting changes and it's used for this url generator.
         * @TODO: remove in Ghost 2.0
         */
        this.router.addListener('updated', () => {
            const myResources = this.urls.getByGeneratorId(this.uid);

            myResources.forEach((object) => {
                this.urls.removeResourceId(object.resource.data.id);
                object.resource.release();
                this._try(object.resource);
            });
        });

        /**
         * Listen on two events:
         *
         * - init: bootstrap or url reset
         * - added: resource was added
         */
        this.queue.register({
            event: 'init',
            tolerance: 100
        }, this._onInit.bind(this));

        // @TODO: listen on added event per type (post optimisation)
        this.queue.register({
            event: 'added'
        }, this._onAdded.bind(this));
    }

    _onInit() {
        debug('_onInit', this.router.getResourceType());

        // @NOTE: get the resources of my type e.g. posts.
        const resources = this.resources.getAllByType(this.router.getResourceType());

        debug(resources.length);

        _.each(resources, (resource) => {
            this._try(resource);
        });
    }

    _onAdded(event) {
        debug('onAdded', this.toString());

        // CASE: you are type "pages", but the incoming type is "users"
        if (event.type !== this.router.getResourceType()) {
            return;
        }

        const resource = this.resources.getByIdAndType(event.type, event.id);

        this._try(resource);
    }

    _try(resource) {
        /**
         * CASE: another url generator has taken this resource already.
         *
         * We have to remember that, because each url generator can generate a different url
         * for a resource. So we can't directly check `this.urls.getUrl(url)`.
         */
        if (resource.isReserved()) {
            return false;
        }

        const url = this._generateUrl(resource);

        // CASE 1: route has no custom filter, it will own the resource for sure
        // CASE 2: find out if my filter matches the resource
        if (!this.filter) {
            this.urls.add({
                url: url,
                generatorId: this.uid,
                resource: resource
            });

            resource.reserve();
            this._resourceListeners(resource);
            return true;
        } else if (this.nql.queryJSON(resource.data)) {
            this.urls.add({
                url: url,
                generatorId: this.uid,
                resource: resource
            });

            resource.reserve();
            this._resourceListeners(resource);
            return true;
        } else {
            return false;
        }
    }

    /**
     * We currently generate relative urls without subdirectory.
     */
    _generateUrl(resource) {
        const permalink = this.router.getPermalinks().getValue();
        return localUtils.replacePermalink(permalink, resource.data);
    }

    /**
     * I want to know if my resources changes.
     * Register events of resource.
     *
     * If the owned resource get's updated, we simply release/free the resource and push it back to the queue.
     * This is the easiest, less error prone implementation.
     *
     * Imagine you have two collections: `featured:true` and `page:false`.
     * If a published post status get's featured and you have not explicitly defined `featured:false`, we wouldn't
     * be able to figure out if this resource still belongs to me, because the filter still matches.
     */
    _resourceListeners(resource) {
        const onUpdate = (updatedResource) => {
            // 1. remove old resource
            this.urls.removeResourceId(updatedResource.data.id);

            // 2. free resource, the url <-> resource connection no longer exists
            updatedResource.release();

            // 3. post has the change to get owned from a different collection again
            debug('put back in queue', updatedResource.data.id);

            this.queue.start({
                event: 'added',
                action: 'added:' + resource.data.id,
                eventData: {
                    id: resource.data.id,
                    type: this.router.getResourceType()
                }
            });
        };

        const onRemoved = (removedResource) => {
            this.urls.removeResourceId(removedResource.data.id);
            removedResource.release();
        };

        resource.removeAllListeners();
        resource.addListener('updated', onUpdate.bind(this));
        resource.addListener('removed', onRemoved.bind(this));
    }

    hasId(id) {
        const existingUrl = this.urls.getByResourceId(id);

        if (existingUrl && existingUrl.generatorId === this.uid) {
            return true;
        }

        return false;
    }

    getUrls() {
        return this.urls.getByGeneratorId(this.uid);
    }

    toString() {
        return this.router.toString();
    }
}

module.exports = UrlGenerator;
<commit_msg>🐛 Fixed filtering by primary_tag or primary_author in routes.yaml<commit_after>const _ = require('lodash'),
    nql = require('@nexes/nql'),
    debug = require('ghost-ignition').debug('services:url:generator'),
    localUtils = require('./utils'),
    // @TODO: merge with filter plugin
    EXPANSIONS = [{
        key: 'author',
        replacement: 'authors.slug'
    }, {
        key: 'tags',
        replacement: 'tags.slug'
    }, {
        key: 'tag',
        replacement: 'tags.slug'
    }, {
        key: 'authors',
        replacement: 'authors.slug'
    }, {
        key: 'primary_tag',
        replacement: 'primary_tag.slug'
    }, {
        key: 'primary_author',
        replacement: 'primary_author.slug'
    }];

class UrlGenerator {
    constructor(router, queue, resources, urls, position) {
        this.router = router;
        this.queue = queue;
        this.urls = urls;
        this.resources = resources;
        this.uid = position;

        debug('constructor', this.toString());

        // CASE: routers can define custom filters, but not required.
        if (this.router.getFilter()) {
            this.filter = this.router.getFilter();
            this.nql = nql(this.filter, {expansions: EXPANSIONS});
            debug('filter', this.filter);
        }

        this._listeners();
    }

    _listeners() {
        /**
         * @NOTE: currently only used if the permalink setting changes and it's used for this url generator.
         * @TODO: remove in Ghost 2.0
         */
        this.router.addListener('updated', () => {
            const myResources = this.urls.getByGeneratorId(this.uid);

            myResources.forEach((object) => {
                this.urls.removeResourceId(object.resource.data.id);
                object.resource.release();
                this._try(object.resource);
            });
        });

        /**
         * Listen on two events:
         *
         * - init: bootstrap or url reset
         * - added: resource was added
         */
        this.queue.register({
            event: 'init',
            tolerance: 100
        }, this._onInit.bind(this));

        // @TODO: listen on added event per type (post optimisation)
        this.queue.register({
            event: 'added'
        }, this._onAdded.bind(this));
    }

    _onInit() {
        debug('_onInit', this.router.getResourceType());

        // @NOTE: get the resources of my type e.g. posts.
        const resources = this.resources.getAllByType(this.router.getResourceType());

        debug(resources.length);

        _.each(resources, (resource) => {
            this._try(resource);
        });
    }

    _onAdded(event) {
        debug('onAdded', this.toString());

        // CASE: you are type "pages", but the incoming type is "users"
        if (event.type !== this.router.getResourceType()) {
            return;
        }

        const resource = this.resources.getByIdAndType(event.type, event.id);

        this._try(resource);
    }

    _try(resource) {
        /**
         * CASE: another url generator has taken this resource already.
         *
         * We have to remember that, because each url generator can generate a different url
         * for a resource. So we can't directly check `this.urls.getUrl(url)`.
         */
        if (resource.isReserved()) {
            return false;
        }

        const url = this._generateUrl(resource);

        // CASE 1: route has no custom filter, it will own the resource for sure
        // CASE 2: find out if my filter matches the resource
        if (!this.filter) {
            this.urls.add({
                url: url,
                generatorId: this.uid,
                resource: resource
            });

            resource.reserve();
            this._resourceListeners(resource);
            return true;
        } else if (this.nql.queryJSON(resource.data)) {
            this.urls.add({
                url: url,
                generatorId: this.uid,
                resource: resource
            });

            resource.reserve();
            this._resourceListeners(resource);
            return true;
        } else {
            return false;
        }
    }

    /**
     * We currently generate relative urls without subdirectory.
     */
    _generateUrl(resource) {
        const permalink = this.router.getPermalinks().getValue();
        return localUtils.replacePermalink(permalink, resource.data);
    }

    /**
     * I want to know if my resources changes.
     * Register events of resource.
     *
     * If the owned resource get's updated, we simply release/free the resource and push it back to the queue.
     * This is the easiest, less error prone implementation.
     *
     * Imagine you have two collections: `featured:true` and `page:false`.
     * If a published post status get's featured and you have not explicitly defined `featured:false`, we wouldn't
     * be able to figure out if this resource still belongs to me, because the filter still matches.
     */
    _resourceListeners(resource) {
        const onUpdate = (updatedResource) => {
            // 1. remove old resource
            this.urls.removeResourceId(updatedResource.data.id);

            // 2. free resource, the url <-> resource connection no longer exists
            updatedResource.release();

            // 3. post has the change to get owned from a different collection again
            debug('put back in queue', updatedResource.data.id);

            this.queue.start({
                event: 'added',
                action: 'added:' + resource.data.id,
                eventData: {
                    id: resource.data.id,
                    type: this.router.getResourceType()
                }
            });
        };

        const onRemoved = (removedResource) => {
            this.urls.removeResourceId(removedResource.data.id);
            removedResource.release();
        };

        resource.removeAllListeners();
        resource.addListener('updated', onUpdate.bind(this));
        resource.addListener('removed', onRemoved.bind(this));
    }

    hasId(id) {
        const existingUrl = this.urls.getByResourceId(id);

        if (existingUrl && existingUrl.generatorId === this.uid) {
            return true;
        }

        return false;
    }

    getUrls() {
        return this.urls.getByGeneratorId(this.uid);
    }

    toString() {
        return this.router.toString();
    }
}

module.exports = UrlGenerator;
<|endoftext|>


<commit_before><commit_msg>Add all supported languages to translation list<commit_after><|endoftext|>


<commit_before>define(["pat-tooltip", "pat-inject"], function(pattern, inject) {
    var utils = {
        createTooltip: function(c) {
            var cfg = c || {};
            return $("", {
                "id":   cfg.id || "tooltip",
                "href": cfg.href || "#anchor",
                "title": cfg.title || "tooltip title attribute",
                "data-pat-tooltip": "" || cfg.data,
                "class": "pat-tooltip"
            }).appendTo($("div#lab"));
        },

        removeTooltip: function removeTooltip() {
            var $el = $("a#tooltip");
            $el.remove();
        },

        createTooltipSource: function() {
            return $(""+
                    "<stong>Local content")
                .appendTo($("div#lab"));
        },

        click: {
            type: "click",
            preventDefault: function () {}
        }
    };

    describe("pat-tooltip", function () {
        beforeEach(function() {
            $("
", {id: "lab"}).appendTo(document.body);
        });

        afterEach(function() {
            $("#lab").remove();
        });

        describe("A Tooltip", function () {

            it("will be closed when a form with class .close-panel is submitted", function () {
                runs(function () {
                    var $div = $("
", {id: "content"});
                    var $form = $("<form/>", {"class": "close-panel"});
                    $div.appendTo(document.body);
                    $form.appendTo($div[0]);
                    utils.createTooltip({
                        data: "source: content",
                        href: "#content"
                    });
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(pattern, "hide").andCallThrough();
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(document).on("submit", function (ev) { ev.preventDefault(); });
                    $("form.close-panel").submit();
                    expect(pattern.hide).toHaveBeenCalled();
                    $("div#content").remove();
                });
            });

            it("will NOT be closed when a form WITHOUT class .close-panel is submitted", function () {
                runs(function () {
                    var $div = $("
", {id: "content"});
                    var $form = $("<form/>");
                    $div.appendTo(document.body);
                    $form.appendTo($div[0]);
                    utils.createTooltip({
                        data: "source: content",
                        href: "#content"
                    });
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(pattern, "hide").andCallThrough();
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(document).on("submit", function (ev) { ev.preventDefault(); });
                    $("#content form").submit();
                    expect(pattern.hide).not.toHaveBeenCalled();
                    $("div#content").remove();
                });
            });

            it("gets a .close-panel element when closing=close-button", function () {
                utils.createTooltip({
                    data: "closing: close-button",
                    href: "/tests/content.html#content"
                });
                var $el = $("a#tooltip");
                pattern.init($el);
                $el.trigger(utils.click);
                expect($(".close-panel").length).toBeTruthy();
            });

            it("is closed when one clicks on a .close-panel element", function () {
                runs(function () {
                    utils.createTooltip({
                        data: "trigger: click; closing: close-button",
                        href: "/tests/content.html#content"
                    });
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(pattern, "hide").andCallThrough();
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(".close-panel").click();
                    expect(pattern.hide).toHaveBeenCalled();
                });
            });

            it("is NOT closed when an injection happens", function () {
                    runs(function () {
                        utils.createTooltip({
                            data: "trigger: click; closing: auto",
                            href: "/tests/content.html#content"
                        });
                        var $el = $("a#tooltip");
                        spyOn(pattern, "show").andCallThrough();
                        spyOn(pattern, "hide").andCallThrough();
                        pattern.init($el);
                        $el.trigger(utils.click);
                        expect(pattern.show).toHaveBeenCalled();
                    });
                    waits(100); // hide events get registered 50 ms after show
                    runs(function () {
                        var $el = $("a#tooltip");
                        var $container = $el.data("patterns.tooltip.container");
                        $container.trigger("patterns-inject-triggered");
                        expect(pattern.hide).not.toHaveBeenCalled();
                    });
            });
        });

        describe("When a tooltip is clicked", function () {
            describe("if the tootip is a hyperlink", function () {
                beforeEach(function() {
                    utils.createTooltip();
                });
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("the default click action is prevented", function () {
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(utils.click, "preventDefault");
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                    expect(utils.click.preventDefault).toHaveBeenCalled();
                });
            });

            describe("if the 'source' parameter is 'title'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will show the contents of the 'title' attribute", function () {
                    utils.createTooltip({data: "source: title"});
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    var title = $el.attr("title");
                    pattern.init($el);
                    // The 'title' attr gets removed, otherwise the browser's
                    // tooltip will appear
                    expect($el.attr("title")).toBeFalsy();

                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                    var $container = $el.data("patterns.tooltip.container");
                    expect($container.text()).toBe(title);
                });
            });

            describe("if the 'source' parameter is 'ajax'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will fetch its contents via ajax", function () {
                    utils.createTooltip({data: "source: auto", href: "/tests/content.html#content"});
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(inject, "execute"); //.andCallThrough();
                    pattern.init($el);
                    runs(function () {
                        $el.trigger(utils.click);
                    });
                    waits(200);
                    runs(function () {
                        expect(pattern.show).toHaveBeenCalled();
                        expect(inject.execute).toHaveBeenCalled();
                        /* XXX: The ajax call works fine in the browser but not
                         * via PhantomJS. Will have to debug later.
                         *
                        var $container = $el.data("patterns.tooltip.container");
                        // Content is fetched from ./tests/content.html#content
                        expect($container.text()).toBe(
                            "External content fetched via an HTTP request.");
                        */
                    });
                });
            });

            describe("if the 'source' parameter is 'content'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will clone a DOM element from the page", function () {
                    utils.createTooltip({data: "source: content", href: "#tooltip-source"});
                    utils.createTooltipSource();
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                    var $container = $el.data("patterns.tooltip.container");
                    expect($container.text()).toBe("Local content");
                });
            });

            describe("if the 'source' parameter is 'auto'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will revert to 'ajax' if 'href' points to an external URL", function () {
                    utils.createTooltip({data: "source: auto", href: "/tests/content.html#content"});
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    var options = $el.data("patterns.tooltip");
                    expect(options.source).toBe("ajax");
                });
                it("will revert to 'content' if 'href' points to a document fragment", function () {
                    utils.createTooltipSource();
                    utils.createTooltip({data: "source: auto", href: "#tooltip-source"});
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    var options = $el.data("patterns.tooltip");
                    expect(options.source).toBe("content");
                });
            });
        });

        describe("A tooltip that opens on click and contains another tooltip trigger", function () {
            beforeEach(function() {
                utils.createTooltip({
                    data: "trigger: click; source: content",
                    href: "#tooltip-content"
                });
                $("
", {
                    "id":   "tooltip-content"
                }).appendTo($("div#lab"));
                $("", {
                    "id":   "nested-tooltip",
                    "href": "#nested-tooltip-content",
                    "title": "nested tooltip title attribute",
                    "data-pat-tooltip": "trigger: click; source: content",
                    "class": "pat-tooltip"
                }).appendTo($("div#tooltip-content"));
            });
            afterEach(function() {
                utils.removeTooltip();
            });
            it("will not close if the contained trigger is clicked", function () {
                runs(function () {
                    spyOn(pattern, "show").andCallThrough();
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    pattern.init($("a#nested-tooltip"));
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(".tooltip-container a#nested-tooltip").trigger(utils.click);
                    expect($(".tooltip-container a#nested-tooltip").css("visibility")).toBe("visible");
                });
            });
        });
    });
});
// jshint indent: 4, browser: true, jquery: true, quotmark: double
<commit_msg>Add a wait statement to fix heisenbug in browser.<commit_after>define(["pat-tooltip", "pat-inject"], function(pattern, inject) {
    var utils = {
        createTooltip: function(c) {
            var cfg = c || {};
            return $("", {
                "id":   cfg.id || "tooltip",
                "href": cfg.href || "#anchor",
                "title": cfg.title || "tooltip title attribute",
                "data-pat-tooltip": "" || cfg.data,
                "class": "pat-tooltip"
            }).appendTo($("div#lab"));
        },

        removeTooltip: function removeTooltip() {
            var $el = $("a#tooltip");
            $el.remove();
        },

        createTooltipSource: function() {
            return $(""+
                    "<stong>Local content")
                .appendTo($("div#lab"));
        },

        click: {
            type: "click",
            preventDefault: function () {}
        }
    };

    describe("pat-tooltip", function () {
        beforeEach(function() {
            $("
", {id: "lab"}).appendTo(document.body);
        });

        afterEach(function() {
            $("#lab").remove();
        });

        describe("A Tooltip", function () {

            it("will be closed when a form with class .close-panel is submitted", function () {
                runs(function () {
                    var $div = $("
", {id: "content"});
                    var $form = $("<form/>", {"class": "close-panel"});
                    $div.appendTo(document.body);
                    $form.appendTo($div[0]);
                    utils.createTooltip({
                        data: "source: content",
                        href: "#content"
                    });
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(pattern, "hide").andCallThrough();
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(document).on("submit", function (ev) { ev.preventDefault(); });
                    $("form.close-panel").submit();
                    expect(pattern.hide).toHaveBeenCalled();
                    $("div#content").remove();
                });
            });

            it("will NOT be closed when a form WITHOUT class .close-panel is submitted", function () {
                runs(function () {
                    var $div = $("
", {id: "content"});
                    var $form = $("<form/>");
                    $div.appendTo(document.body);
                    $form.appendTo($div[0]);
                    utils.createTooltip({
                        data: "source: content",
                        href: "#content"
                    });
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(pattern, "hide").andCallThrough();
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(document).on("submit", function (ev) { ev.preventDefault(); });
                    $("#content form").submit();
                    expect(pattern.hide).not.toHaveBeenCalled();
                    $("div#content").remove();
                });
            });

            it("gets a .close-panel element when closing=close-button", function () {
                utils.createTooltip({
                    data: "closing: close-button",
                    href: "/tests/content.html#content"
                });
                var $el = $("a#tooltip");
                pattern.init($el);
                $el.trigger(utils.click);
                expect($(".close-panel").length).toBeTruthy();
            });

            it("is closed when one clicks on a .close-panel element", function () {
                runs(function () {
                    utils.createTooltip({
                        data: "trigger: click; closing: close-button",
                        href: "/tests/content.html#content"
                    });
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(pattern, "hide").andCallThrough();
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(".close-panel").click();
                    expect(pattern.hide).toHaveBeenCalled();
                });
            });

            it("is NOT closed when an injection happens", function () {
                    runs(function () {
                        utils.createTooltip({
                            data: "trigger: click; closing: auto",
                            href: "/tests/content.html#content"
                        });
                        var $el = $("a#tooltip");
                        spyOn(pattern, "show").andCallThrough();
                        spyOn(pattern, "hide").andCallThrough();
                        pattern.init($el);
                        $el.trigger(utils.click);
                        expect(pattern.show).toHaveBeenCalled();
                    });
                    waits(100); // hide events get registered 50 ms after show
                    runs(function () {
                        var $el = $("a#tooltip");
                        var $container = $el.data("patterns.tooltip.container");
                        $container.trigger("patterns-inject-triggered");
                    });
                    waits(100); // hide events get registered 50 ms after show
                    runs(function () {
                        expect(pattern.hide).not.toHaveBeenCalled();
                    });
            });
        });

        describe("When a tooltip is clicked", function () {
            describe("if the tootip is a hyperlink", function () {
                beforeEach(function() {
                    utils.createTooltip();
                });
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("the default click action is prevented", function () {
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(utils.click, "preventDefault");
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                    expect(utils.click.preventDefault).toHaveBeenCalled();
                });
            });

            describe("if the 'source' parameter is 'title'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will show the contents of the 'title' attribute", function () {
                    utils.createTooltip({data: "source: title"});
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    var title = $el.attr("title");
                    pattern.init($el);
                    // The 'title' attr gets removed, otherwise the browser's
                    // tooltip will appear
                    expect($el.attr("title")).toBeFalsy();

                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                    var $container = $el.data("patterns.tooltip.container");
                    expect($container.text()).toBe(title);
                });
            });

            describe("if the 'source' parameter is 'ajax'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will fetch its contents via ajax", function () {
                    utils.createTooltip({data: "source: auto", href: "/tests/content.html#content"});
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    spyOn(inject, "execute"); //.andCallThrough();
                    pattern.init($el);
                    runs(function () {
                        $el.trigger(utils.click);
                    });
                    waits(200);
                    runs(function () {
                        expect(pattern.show).toHaveBeenCalled();
                        expect(inject.execute).toHaveBeenCalled();
                        /* XXX: The ajax call works fine in the browser but not
                         * via PhantomJS. Will have to debug later.
                         *
                        var $container = $el.data("patterns.tooltip.container");
                        // Content is fetched from ./tests/content.html#content
                        expect($container.text()).toBe(
                            "External content fetched via an HTTP request.");
                        */
                    });
                });
            });

            describe("if the 'source' parameter is 'content'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will clone a DOM element from the page", function () {
                    utils.createTooltip({data: "source: content", href: "#tooltip-source"});
                    utils.createTooltipSource();
                    var $el = $("a#tooltip");
                    spyOn(pattern, "show").andCallThrough();
                    pattern.init($el);
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                    var $container = $el.data("patterns.tooltip.container");
                    expect($container.text()).toBe("Local content");
                });
            });

            describe("if the 'source' parameter is 'auto'", function () {
                afterEach(function() {
                    utils.removeTooltip();
                });
                it("will revert to 'ajax' if 'href' points to an external URL", function () {
                    utils.createTooltip({data: "source: auto", href: "/tests/content.html#content"});
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    var options = $el.data("patterns.tooltip");
                    expect(options.source).toBe("ajax");
                });
                it("will revert to 'content' if 'href' points to a document fragment", function () {
                    utils.createTooltipSource();
                    utils.createTooltip({data: "source: auto", href: "#tooltip-source"});
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    var options = $el.data("patterns.tooltip");
                    expect(options.source).toBe("content");
                });
            });
        });

        describe("A tooltip that opens on click and contains another tooltip trigger", function () {
            beforeEach(function() {
                utils.createTooltip({
                    data: "trigger: click; source: content",
                    href: "#tooltip-content"
                });
                $("
", {
                    "id":   "tooltip-content"
                }).appendTo($("div#lab"));
                $("", {
                    "id":   "nested-tooltip",
                    "href": "#nested-tooltip-content",
                    "title": "nested tooltip title attribute",
                    "data-pat-tooltip": "trigger: click; source: content",
                    "class": "pat-tooltip"
                }).appendTo($("div#tooltip-content"));
            });
            afterEach(function() {
                utils.removeTooltip();
            });
            it("will not close if the contained trigger is clicked", function () {
                runs(function () {
                    spyOn(pattern, "show").andCallThrough();
                    var $el = $("a#tooltip");
                    pattern.init($el);
                    pattern.init($("a#nested-tooltip"));
                    $el.trigger(utils.click);
                    expect(pattern.show).toHaveBeenCalled();
                });
                waits(100); // hide events get registered 50 ms after show
                runs(function () {
                    $(".tooltip-container a#nested-tooltip").trigger(utils.click);
                    expect($(".tooltip-container a#nested-tooltip").css("visibility")).toBe("visible");
                });
            });
        });
    });
});
// jshint indent: 4, browser: true, jquery: true, quotmark: double
<|endoftext|>


<commit_before>import update from 'immutability-helper';
import {
  FETCH_ALL_CONSORTIA_QUERY,
} from './functions';

export const compIOProp = {
  props: ({ data: { fetchComputation } }) => ({
    compIO: fetchComputation ? fetchComputation[0] : null,
  }),
  options: ({ computationId }) => ({ variables: { computationIds: [computationId] } }),
};

export const getDocumentByParam = (param, prop, query) => ({
  props: ({ data }) => ({
    [prop]: data[query],
  }),
  options: ({ params }) => ({ variables: { [param]: params[param] } }),
});

export const consortiaMembershipProp = (name) => {
  return {
    props: ({ mutate }) => ({
      [name]: consortiumId => mutate({
        variables: { consortiumId },
        update: (store, { data }) => {
          const consQuery = store.readQuery({ query: FETCH_ALL_CONSORTIA_QUERY });
          const index = consQuery.fetchAllConsortia
            .findIndex(con => con.id === data[name].id);
          if (index > -1) {
            consQuery.fetchAllConsortia[index].members = data[name].members;
          }
          store.writeQuery({ query: FETCH_ALL_CONSORTIA_QUERY, data: consQuery });
        },
      }),
    }),
  };
};

export const getAllAndSubProp = (document, listProp, query, subProp, subscription, filter) => ({
  options: (props) => {
    const opts = { fetchPolicy: 'cache-and-network' };

    if (filter && filter === 'userId' && props.auth.user.id) {
      opts.variables = { [filter]: props.auth.user.id };
    }

    return opts;
  },
  props: props => ({
    [listProp]: props.data[query],
    [subProp]: () => {
      const variables = {};
      if (filter && filter === 'userId' && props.ownProps.auth.user.id) {
        variables.userId = props.ownProps.auth.user.id;
      }

      return props.data.subscribeToMore({
        document,
        updateQuery: (prevResult, { subscriptionData: { data } }) => {
          const index =
            prevResult[query].findIndex(c => c.id === data[subscription].id);

          if (data[subscription].delete) {
            return {
              [query]: prevResult[query].filter(obj => obj.id !== data[subscription].id),
            };
          } else if (index !== -1) {
            return {
              [query]: update(prevResult[query], {
                $splice: [
                  [index, 1, data[subscription]],
                ],
              }),
            };
          }

          return {
            [query]: [...prevResult[query], data[subscription]],
          };
        },
      });
    },
  }),
});

export const getSelectAndSubProp = (activeProp, document, objId, subProp, subscription, query) => ({
  options: (props) => {
    let theId = null;

    if (props[objId]) {
      theId = props[objId];
    } else if (props.params[objId]) {
      theId = props.params[objId];
    }

    return {
      fetchPolicy: 'cache-and-network',
      variables: { [objId]: theId },
    };
  },
  props: props => ({
    [activeProp]: props.data[query],
    [subProp]: theId =>
      props.data.subscribeToMore({
        document,
        variables: { [objId]: theId },
        updateQuery: (prevResult, { subscriptionData: { data } }) => {
          if (data[subscription].delete) {
            return { [query]: null };
          }

          return { [query]: data[subscription] };
        },
      }),
  }),
});

export const pipelinesProp = {
  props: ({ data: { fetchAllPipelines } }) => ({
    pipelines: fetchAllPipelines,
  }),
};

export const resultsProp = {
  props: ({ data: { fetchAllResults } }) => ({
    results: fetchAllResults,
  }),
};

export const removeDocFromTableProp = (docId, mutation, query, dataQuery) => {
  return {
    props: ({ mutate }) => ({
      [mutation]: theId => mutate({
        variables: { [docId]: theId },
        update: (store, { data }) => {
          const d = store.readQuery({ query });
          const index = d[dataQuery].findIndex(con => con.id === data[mutation].id);
          if (index > -1) {
            d[dataQuery].splice(index, 1);
          }
          store.writeQuery({ query, data: d });
        },
      }),
    }),
  };
};

export const saveDocumentProp = (funcName, objVar) => {
  return {
    props: ({ mutate }) => ({
      [funcName]: obj => mutate({
        variables: { [objVar]: obj },
      }),
    }),
  };
};

export const userRolesProp = (name) => {
  return {
    props: ({ ownProps, mutate }) => ({
      [name]: (userId, table, doc, role) => mutate({
        variables: { userId, table, doc, role },
      })
      .then(({ data: { [name]: { permissions } } }) => {
        return ownProps.updateUserPerms(permissions);
      }),
    }),
  };
};
<commit_msg>missing variables param added to allSub<commit_after>import update from 'immutability-helper';
import {
  FETCH_ALL_CONSORTIA_QUERY,
} from './functions';

export const compIOProp = {
  props: ({ data: { fetchComputation } }) => ({
    compIO: fetchComputation ? fetchComputation[0] : null,
  }),
  options: ({ computationId }) => ({ variables: { computationIds: [computationId] } }),
};

export const getDocumentByParam = (param, prop, query) => ({
  props: ({ data }) => ({
    [prop]: data[query],
  }),
  options: ({ params }) => ({ variables: { [param]: params[param] } }),
});

export const consortiaMembershipProp = (name) => {
  return {
    props: ({ mutate }) => ({
      [name]: consortiumId => mutate({
        variables: { consortiumId },
        update: (store, { data }) => {
          const consQuery = store.readQuery({ query: FETCH_ALL_CONSORTIA_QUERY });
          const index = consQuery.fetchAllConsortia
            .findIndex(con => con.id === data[name].id);
          if (index > -1) {
            consQuery.fetchAllConsortia[index].members = data[name].members;
          }
          store.writeQuery({ query: FETCH_ALL_CONSORTIA_QUERY, data: consQuery });
        },
      }),
    }),
  };
};

export const getAllAndSubProp = (document, listProp, query, subProp, subscription, filter) => ({
  options: (props) => {
    const opts = { fetchPolicy: 'cache-and-network' };

    if (filter && filter === 'userId' && props.auth.user.id) {
      opts.variables = { [filter]: props.auth.user.id };
    }

    return opts;
  },
  props: props => ({
    [listProp]: props.data[query],
    [subProp]: () => {
      const variables = {};
      if (filter && filter === 'userId' && props.ownProps.auth.user.id) {
        variables.userId = props.ownProps.auth.user.id;
      }

      return props.data.subscribeToMore({
        document,
        variables,
        updateQuery: (prevResult, { subscriptionData: { data } }) => {
          const index =
            prevResult[query].findIndex(c => c.id === data[subscription].id);

          if (data[subscription].delete) {
            return {
              [query]: prevResult[query].filter(obj => obj.id !== data[subscription].id),
            };
          } else if (index !== -1) {
            return {
              [query]: update(prevResult[query], {
                $splice: [
                  [index, 1, data[subscription]],
                ],
              }),
            };
          }

          return {
            [query]: [...prevResult[query], data[subscription]],
          };
        },
      });
    },
  }),
});

export const getSelectAndSubProp = (activeProp, document, objId, subProp, subscription, query) => ({
  options: (props) => {
    let theId = null;

    if (props[objId]) {
      theId = props[objId];
    } else if (props.params[objId]) {
      theId = props.params[objId];
    }

    return {
      fetchPolicy: 'cache-and-network',
      variables: { [objId]: theId },
    };
  },
  props: props => ({
    [activeProp]: props.data[query],
    [subProp]: theId =>
      props.data.subscribeToMore({
        document,
        variables: { [objId]: theId },
        updateQuery: (prevResult, { subscriptionData: { data } }) => {
          if (data[subscription].delete) {
            return { [query]: null };
          }

          return { [query]: data[subscription] };
        },
      }),
  }),
});

export const pipelinesProp = {
  props: ({ data: { fetchAllPipelines } }) => ({
    pipelines: fetchAllPipelines,
  }),
};

export const resultsProp = {
  props: ({ data: { fetchAllResults } }) => ({
    results: fetchAllResults,
  }),
};

export const removeDocFromTableProp = (docId, mutation, query, dataQuery) => {
  return {
    props: ({ mutate }) => ({
      [mutation]: theId => mutate({
        variables: { [docId]: theId },
        update: (store, { data }) => {
          const d = store.readQuery({ query });
          const index = d[dataQuery].findIndex(con => con.id === data[mutation].id);
          if (index > -1) {
            d[dataQuery].splice(index, 1);
          }
          store.writeQuery({ query, data: d });
        },
      }),
    }),
  };
};

export const saveDocumentProp = (funcName, objVar) => {
  return {
    props: ({ mutate }) => ({
      [funcName]: obj => mutate({
        variables: { [objVar]: obj },
      }),
    }),
  };
};

export const userRolesProp = (name) => {
  return {
    props: ({ ownProps, mutate }) => ({
      [name]: (userId, table, doc, role) => mutate({
        variables: { userId, table, doc, role },
      })
      .then(({ data: { [name]: { permissions } } }) => {
        return ownProps.updateUserPerms(permissions);
      }),
    }),
  };
};
<|endoftext|>


<commit_before>// Wraps Tizen's module "Alarm".

define(['Ti/_/lang', 'Tizen/_/Alarm/AlarmRelative', 'Tizen/_/Alarm/AlarmAbsolute', 'Ti/_/Evented'], function(lang, AlarmRelative, AlarmAbsolute, Evented) {

	var Alarm = lang.mixProps(require.mix({}, Evented), {

		add: function(alarm /*Alarm*/, applicationId /*ApplicationId*/, appControl /*ApplicationControl*/) {
			// Tizen distinguishes between undefined appControl (this gives an error) and missing appControl.
			var args = [
				alarm._obj,
				applicationId
			];
			(typeof appControl !== 'undefined') && args.push(appControl._obj);
			tizen.alarm.add.apply(tizen.alarm, args);
		},

		remove: function(id /*AlarmId*/) {
			tizen.alarm.remove(id);
		},

		removeAll: function() {
			tizen.alarm.removeAll();
		},

		getAlarm: function(id /*AlarmId*/) {
			return this._wrap(tizen.alarm.get(id));
		},

		getAll: function() {
			var objects = tizen.alarm.getAll(),
				i = 0,
				objectsCount = objects.length,
				result = [];

			for (; i < objectsCount; i++) {
				result.push(this._wrap(objects[i]));
			}
			return result;
		},

		_wrap: function(object) {
			// Wrap the object (create a Titanium wrapped object out of a native Tizen object).

			var result;

			if (object.toString() === '[object AlarmRelative]') {
				result = new AlarmRelative(void 0, object);
			}
			else if (object.toString() === '[object AlarmAbsolute]') {
				result = new AlarmAbsolute(void 0, object);
			} else {
				throw new Error('Object of unknown type');
			}

			return result;
		},

		createAlarmRelative: function(args) {
			return new AlarmRelative(args);
		},

		createAlarmAbsolute: function(args) {
			return new AlarmAbsolute(args);
		},

		constants: {
			PERIOD_MINUTE: 60, //unsigned long long
			PERIOD_HOUR: 3600, //unsigned long long
			PERIOD_DAY: 86400, //unsigned long long
			PERIOD_WEEK: 604800 //unsigned long long
		}

	}, true);

	return Alarm;
});
<commit_msg>fixed bug in function add<commit_after>// Wraps Tizen's module "Alarm".

define(['Ti/_/lang', 'Tizen/_/Alarm/AlarmRelative', 'Tizen/_/Alarm/AlarmAbsolute', 'Ti/_/Evented'], function(lang, AlarmRelative, AlarmAbsolute, Evented) {

	var Alarm = lang.mixProps(require.mix({}, Evented), {

		add: function(alarm /*Alarm*/, applicationId /*ApplicationId*/, appControl /*ApplicationControl*/) {
			// Tizen distinguishes between undefined appControl (this gives an error) and missing appControl.
			var args = [
				alarm._obj,
				applicationId
			];
			(typeof appControl !== 'undefined') && args.push((appControl && appControl._obj) || appControl);
			tizen.alarm.add.apply(tizen.alarm, args);
		},

		remove: function(id /*AlarmId*/) {
			tizen.alarm.remove(id);
		},

		removeAll: function() {
			tizen.alarm.removeAll();
		},

		getAlarm: function(id /*AlarmId*/) {
			return this._wrap(tizen.alarm.get(id));
		},

		getAll: function() {
			var objects = tizen.alarm.getAll(),
				i = 0,
				objectsCount = objects.length,
				result = [];

			for (; i < objectsCount; i++) {
				result.push(this._wrap(objects[i]));
			}
			return result;
		},

		_wrap: function(object) {
			// Wrap the object (create a Titanium wrapped object out of a native Tizen object).

			var result;

			if (object.toString() === '[object AlarmRelative]') {
				result = new AlarmRelative(void 0, object);
			}
			else if (object.toString() === '[object AlarmAbsolute]') {
				result = new AlarmAbsolute(void 0, object);
			} else {
				throw new Error('Object of unknown type');
			}

			return result;
		},

		createAlarmRelative: function(args) {
			return new AlarmRelative(args);
		},

		createAlarmAbsolute: function(args) {
			return new AlarmAbsolute(args);
		},

		constants: {
			PERIOD_MINUTE: 60, //unsigned long long
			PERIOD_HOUR: 3600, //unsigned long long
			PERIOD_DAY: 86400, //unsigned long long
			PERIOD_WEEK: 604800 //unsigned long long
		}

	}, true);

	return Alarm;
});
<|endoftext|>


<commit_before>D.modules.menu=function(require){'use strict'

// Generic menu for a browser or NW.js
// There's an alternative implementation for NW.js in ../init-nw.js
// For the concrete content in the menu, see prefs.js
var prefs=require('./prefs'),cmds=require('./cmds').cmds
if(D.el){
  var renderMenu=function(x,groups){
    if(!x)return
    if(x['']==='-')return new D.el.MenuItem({type:'separator'})
    var h={label:x[''].replace(/_/g,'&')}
    if(x.group){
      h.type='checkbox';h.checked=!!x.checked
      h.click=function(){groups[x.group].forEach(function(y){y.checked=y===mi});x.action&&x.action()}
    }else if(x.checkBoxPref){
      h.type='checkbox';h.checked=!!x.checkBoxPref()
      if(x.action)h.click=function(){x.action(mi.checked)}
      x.checkBoxPref(function(v){mi.checked=!!v})
    }else{
      h.click=x.action
    }
    if(x.items){h.submenu=new D.el.Menu;x.items.forEach(function(y){h.submenu.append(renderMenu(y,groups))})}
    var mi=new D.el.MenuItem(h);x.group&&(groups[x.group]=groups[x.group]||[]).push(mi);return mi
  }
  D.installMenu=function(x){
    var groups={},m=new D.el.Menu
    x.forEach(function(y){m.append(renderMenu(y,groups))})
    D.el.Menu.setApplicationMenu(m)
  }
}else{
  D.installMenu=function(arg){
    // DOM structure:
    // ┌.menu───────────────────────────────────────────┐
    // │┌div.m-sub────────────────────────────────┐     │
    // ││            ┌div.m-box──────────────────┐│     │
    // ││┌a.m-opener┐│┌a─────┐┌a─────┐┌div.m-sub┐││     │
    // │││┌span┐    │││┌span┐││┌span┐││         │││     │
    // ││││File│    ││││Open││││Save│││   ...   │││ ... │
    // │││└────┘    │││└────┘││└────┘││         │││     │
    // ││└──────────┘│└──────┘└──────┘└─────────┘││     │
    // ││            └───────────────────────────┘│     │
    // │└─────────────────────────────────────────┘     │
    // └────────────────────────────────────────────────┘
    // Top-level ".m-opener"-s also have class ".m-top"
    function render(x){
      if(!x)return
      if(x['']==='-')return $('
')
      var acc,name=x[''].replace(/_(.)/g,function(_,k){return acc||k==='_'?k:''+(acc=k)+''}) // acc:access key
      var $a=$(''+name+'')
      x.cmd&&$a.append('')
      if(x.group){
        $a.addClass('m-group-'+x.group).toggleClass('m-checked',!!x.checked).on('mousedown mouseup click',function(e){
          $(this).closest('.menu').find('.m-group-'+x.group).removeClass('m-checked');$(this).addClass('m-checked')
          mFocus(null);x.action&&x.action();return!1
        })
      }else if(x.checkBoxPref){
        x.checkBoxPref(function(v){$a.toggleClass('m-checked',!!v)})
        $a.toggleClass('m-checked',!!x.checkBoxPref()).on('mousedown mouseup click',function(e){
          mFocus(null);x.action&&x.action($(this).hasClass('m-checked'));return!1
        })
      }else{
        x.action&&$a.on('mousedown mouseup click',function(e){mFocus(null);x.action();return!1})
      }
      if(!x.items)return $a
      var $b=$('
')
      return $('
').append($a.addClass('m-opener'),$b.append.apply($b,x.items.map(render)))
    }
    var $o // original focused element
    function mFocus(anchor){
      $m.find('.m-open').removeClass('m-open');if(!anchor){$o&&$o.focus();$o=null;return}
      $o||($o=$(':focus'));var $a=$(anchor);$a.parentsUntil('.menu').addClass('m-open')
      $a.is('.m-top')?$a.closest('.m-sub').find('a').eq(1).focus():$a.focus()
    }
    function leftRight(d,$e){ // d: +1 or -1, $e: target element
      if(d>0&&$e.is('.m-opener')){
        mFocus($e.next('.m-box').find('a').first())
      }else if(d<0&&!$e.is('.m-opener')&&$e.parents('.m-sub').length>1){
        mFocus($e.closest('.m-sub').find('.m-opener').first())
      }else{
        var $t=$m.children(),n=$t.length,i=$e.parentsUntil('.menu').last().index();mFocus($t.eq((i+d+n)%n).find('a').eq(1))
      }
      return!1
    }
    function upDown(d,$e){ // d: +1 or -1, $e: target element
      if($e.is('.m-top')){
        mFocus($e.parent().find(':not(hr)').eq(1))
      }else{
        var $s=$e.closest('.m-box').children(':not(hr)'),i=$s.index($e),n=$s.length,$f=$s.eq((i+d+n)%n)
        mFocus($f.is('a')?$f:$f.find('a').first())
      }
      return!1
    }
    var $m=$('
').prependTo('body').empty().addClass('menu').append(arg.map(render))
    $m.find('>.m-sub>.m-opener').addClass('m-top')
    $m.on('mouseover','a',function(){$(this).closest('.menu').children().is('.m-open')&&mFocus(this)})
      .on('mousedown click','a',function(e){
        mFocus($(this).parentsUntil('.menu').last().is('.m-open')&&e.type==='mousedown'?null:this);return!1
      })
      .keydown(function(e){
        switch(CodeMirror.keyNames[e.which]){
          case'Left' :leftRight(-1,$(e.target));break
          case'Right':leftRight( 1,$(e.target));break
          case'Up'   :upDown   (-1,$(e.target));break
          case'Down' :upDown   ( 1,$(e.target));break
          case'Esc':case'F10':mFocus(null);return!1
        }
      })
    $(document).mousedown(function(e){$(e.target).closest('.menu').length||mFocus(null)})
    updMenuShcs(prefs.keys())
  }
}
function updMenuShcs(h){
  var k={};for(var i=0;i<cmds.length;i++){var c=cmds[i][0],d=cmds[i][2];k[c]=(h[c]||d)[0]} // c:code, d:defaults
  $('.m-shortcut').each(function(){$(this).text(k[$(this).data('cmd')]||'')})
}
prefs.keys(updMenuShcs)

}
<commit_msg>menu only in main window (not in editors and 3500⌶)<commit_after>D.modules.menu=function(require){'use strict'

// Generic menu for a browser or NW.js
// There's an alternative implementation for NW.js in ../init-nw.js
// For the concrete content in the menu, see prefs.js
var prefs=require('./prefs'),cmds=require('./cmds').cmds
if(D.el){
  var renderMenu=function(x,groups){
    if(!x)return
    if(x['']==='-')return new D.el.MenuItem({type:'separator'})
    var h={label:x[''].replace(/_/g,'&')}
    if(x.group){
      h.type='checkbox';h.checked=!!x.checked
      h.click=function(){groups[x.group].forEach(function(y){y.checked=y===mi});x.action&&x.action()}
    }else if(x.checkBoxPref){
      h.type='checkbox';h.checked=!!x.checkBoxPref()
      if(x.action)h.click=function(){x.action(mi.checked)}
      x.checkBoxPref(function(v){mi.checked=!!v})
    }else{
      h.click=x.action
    }
    if(x.items){h.submenu=new D.el.Menu;x.items.forEach(function(y){h.submenu.append(renderMenu(y,groups))})}
    var mi=new D.el.MenuItem(h);x.group&&(groups[x.group]=groups[x.group]||[]).push(mi);return mi
  }
  D.installMenu=function(x){
    var groups={},m=new D.el.Menu
    x.forEach(function(y){m.append(renderMenu(y,groups))})
    D.elw.setMenu(m)
  }
}else{
  D.installMenu=function(arg){
    // DOM structure:
    // ┌.menu───────────────────────────────────────────┐
    // │┌div.m-sub────────────────────────────────┐     │
    // ││            ┌div.m-box──────────────────┐│     │
    // ││┌a.m-opener┐│┌a─────┐┌a─────┐┌div.m-sub┐││     │
    // │││┌span┐    │││┌span┐││┌span┐││         │││     │
    // ││││File│    ││││Open││││Save│││   ...   │││ ... │
    // │││└────┘    │││└────┘││└────┘││         │││     │
    // ││└──────────┘│└──────┘└──────┘└─────────┘││     │
    // ││            └───────────────────────────┘│     │
    // │└─────────────────────────────────────────┘     │
    // └────────────────────────────────────────────────┘
    // Top-level ".m-opener"-s also have class ".m-top"
    function render(x){
      if(!x)return
      if(x['']==='-')return $('
')
      var acc,name=x[''].replace(/_(.)/g,function(_,k){return acc||k==='_'?k:''+(acc=k)+''}) // acc:access key
      var $a=$(''+name+'')
      x.cmd&&$a.append('')
      if(x.group){
        $a.addClass('m-group-'+x.group).toggleClass('m-checked',!!x.checked).on('mousedown mouseup click',function(e){
          $(this).closest('.menu').find('.m-group-'+x.group).removeClass('m-checked');$(this).addClass('m-checked')
          mFocus(null);x.action&&x.action();return!1
        })
      }else if(x.checkBoxPref){
        x.checkBoxPref(function(v){$a.toggleClass('m-checked',!!v)})
        $a.toggleClass('m-checked',!!x.checkBoxPref()).on('mousedown mouseup click',function(e){
          mFocus(null);x.action&&x.action($(this).hasClass('m-checked'));return!1
        })
      }else{
        x.action&&$a.on('mousedown mouseup click',function(e){mFocus(null);x.action();return!1})
      }
      if(!x.items)return $a
      var $b=$('
')
      return $('
').append($a.addClass('m-opener'),$b.append.apply($b,x.items.map(render)))
    }
    var $o // original focused element
    function mFocus(anchor){
      $m.find('.m-open').removeClass('m-open');if(!anchor){$o&&$o.focus();$o=null;return}
      $o||($o=$(':focus'));var $a=$(anchor);$a.parentsUntil('.menu').addClass('m-open')
      $a.is('.m-top')?$a.closest('.m-sub').find('a').eq(1).focus():$a.focus()
    }
    function leftRight(d,$e){ // d: +1 or -1, $e: target element
      if(d>0&&$e.is('.m-opener')){
        mFocus($e.next('.m-box').find('a').first())
      }else if(d<0&&!$e.is('.m-opener')&&$e.parents('.m-sub').length>1){
        mFocus($e.closest('.m-sub').find('.m-opener').first())
      }else{
        var $t=$m.children(),n=$t.length,i=$e.parentsUntil('.menu').last().index();mFocus($t.eq((i+d+n)%n).find('a').eq(1))
      }
      return!1
    }
    function upDown(d,$e){ // d: +1 or -1, $e: target element
      if($e.is('.m-top')){
        mFocus($e.parent().find(':not(hr)').eq(1))
      }else{
        var $s=$e.closest('.m-box').children(':not(hr)'),i=$s.index($e),n=$s.length,$f=$s.eq((i+d+n)%n)
        mFocus($f.is('a')?$f:$f.find('a').first())
      }
      return!1
    }
    var $m=$('
').prependTo('body').empty().addClass('menu').append(arg.map(render))
    $m.find('>.m-sub>.m-opener').addClass('m-top')
    $m.on('mouseover','a',function(){$(this).closest('.menu').children().is('.m-open')&&mFocus(this)})
      .on('mousedown click','a',function(e){
        mFocus($(this).parentsUntil('.menu').last().is('.m-open')&&e.type==='mousedown'?null:this);return!1
      })
      .keydown(function(e){
        switch(CodeMirror.keyNames[e.which]){
          case'Left' :leftRight(-1,$(e.target));break
          case'Right':leftRight( 1,$(e.target));break
          case'Up'   :upDown   (-1,$(e.target));break
          case'Down' :upDown   ( 1,$(e.target));break
          case'Esc':case'F10':mFocus(null);return!1
        }
      })
    $(document).mousedown(function(e){$(e.target).closest('.menu').length||mFocus(null)})
    updMenuShcs(prefs.keys())
  }
}
function updMenuShcs(h){
  var k={};for(var i=0;i<cmds.length;i++){var c=cmds[i][0],d=cmds[i][2];k[c]=(h[c]||d)[0]} // c:code, d:defaults
  $('.m-shortcut').each(function(){$(this).text(k[$(this).data('cmd')]||'')})
}
prefs.keys(updMenuShcs)

}
<|endoftext|>


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

/**
 * Choose the source URL of the smallest available size image wider than
 * minWidth, according to the device pixel ratio.
 *
 * @param {number} minWidth The minimum width of the thumbnail to return.
 * @param {*} resource Image resource object.
 * @return {string} Source URL of the smallest available size image.
 */
function getThumbnailUrl(minWidth, resource) {
  const getOrientation = (obj) => {
    if (obj.width / obj.height > 1) {
      return Orientation.LANDSCAPE;
    } else if (obj.width / obj.height < 1) {
      return Orientation.PORTRAIT;
    }
    return Orientation.SQUARE;
  };

  const Orientation = {
    PORTRAIT: 'portrait',
    LANDSCAPE: 'landscape',
    SQUARE: 'square',
  };

  if (resource.sizes) {
    // The thumbnail is a square cropped image, we don't want that.
    const sizesWithoutThumbnail = {
      ...resource.sizes,
    };
    delete sizesWithoutThumbnail.thumbnail;

    const smallestValidImage = Object.values(sizesWithoutThumbnail)
      .sort((s1, s2) => s1.width - s2.width)
      .filter((s) => getOrientation(s) === getOrientation(resource))
      .find((s) => s.width >= minWidth * window.devicePixelRatio);
    if (smallestValidImage) {
      return smallestValidImage.source_url;
    }
  }
  return resource.src;
}

export default getThumbnailUrl;
<commit_msg>Removed the deletion of thumbnail url, this should be handled by my orientation check<commit_after>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Choose the source URL of the smallest available size image wider than
 * minWidth, according to the device pixel ratio.
 *
 * @param {number} minWidth The minimum width of the thumbnail to return.
 * @param {*} resource Image resource object.
 * @return {string} Source URL of the smallest available size image.
 */
function getThumbnailUrl(minWidth, resource) {
  const getOrientation = (obj) => {
    if (obj.width / obj.height > 1) {
      return Orientation.LANDSCAPE;
    } else if (obj.width / obj.height < 1) {
      return Orientation.PORTRAIT;
    }
    return Orientation.SQUARE;
  };

  const Orientation = {
    PORTRAIT: 'portrait',
    LANDSCAPE: 'landscape',
    SQUARE: 'square',
  };

  if (resource.sizes) {
    const smallestValidImage = Object.values(resource.sizes)
      .sort((s1, s2) => s1.width - s2.width)
      .filter((s) => getOrientation(s) === getOrientation(resource))
      .find((s) => s.width >= minWidth * window.devicePixelRatio);
    if (smallestValidImage) {
      return smallestValidImage.source_url;
    }
  }
  return resource.src;
}

export default getThumbnailUrl;
<|endoftext|>


<commit_before>
PurrJS = {};

 /*
	 modal
 */
PurrJS.modal = function(title, msg, icon, duration, position) {

	var width  = 400;
	var height = 300;

	var padding = 0;

	var farRight = air.Screen.mainScreen.bounds.right;
	var farTop   = air.Screen.mainScreen.bounds.top;

	var winX = farRight - width - padding;
	var winY = 0 + padding + 20;

	var opts = new air.NativeWindowInitOptions();
	opts.transparent = true;
	opts.type = air.NativeWindowType.UTILITY;
	opts.systemChrome = air.NativeWindowSystemChrome.NONE;
	opts.resizable = false;
	opts.minimizable = false;
	opts.maximizable = false;

	var winBounds = new air.Rectangle(winX, winY, width, height);
	var notifyLoader = air.HTMLLoader.createRootWindow(true, opts, false, winBounds);
	notifyLoader.load(new air.URLRequest("app:/html/modal.html"));
	notifyLoader.alpha = 0.6;

	 // air.Introspector.Console.info(notifyLoader);

	 // notifyLoader.window.document.getElementById('container').innerHTML = msg;

	fadeIn();
	var fadeOutTimeout = setTimeout(fadeOut, 8000);

	function fadeIn() {

		notifyLoader.alpha = 0;

		// start
		opacityUp();

		function opacityUp() {
			notifyLoader.alpha += 0.1;
			if (notifyLoader.alpha < 1) {
				setTimeout(opacityUp, 30); // do again
			}
		}

	}

	function fadeOut() {
		notifyLoader.alpha = 1;

		clearTimeout(fadeOutTimeout);

		// start
		opacityDown();

		function opacityDown() {
			notifyLoader.alpha -= 0.1;
			if (notifyLoader.alpha > 0 && opacityDown) {
				setTimeout(opacityDown, 30); // do again
			} else {
				notifyLoader.window.nativeWindow.close();
				notifyLoader = null;
			}
		}

	}

};

/*
   notify
*/
PurrJS.notify = function(opts) {
	opts = sch.defaults({
		'title':   'opts.title',
		'message': 'opts.message',
		'icon':    'opts.icon',
		'duration':6000, // in ms
		'position':'topRight',
		'height':  160,
		'width':   300,
		'padding': 0,
		'data':    null,
		'template':null,
		'onClick' :null,
		'onHover' :null
	}, opts);

	/*
	  Size of window
	*/
	var width  = opts.width;
	var height = opts.height;

	/*
	  padding from screen edges
	*/
	var padding = opts.padding;

	/*
	  get dimensions
	*/
	var farRight  = air.Screen.mainScreen.visibleBounds.right;
	var farTop    = air.Screen.mainScreen.visibleBounds.top;
	var farLeft   = air.Screen.mainScreen.visibleBounds.left;
	var farBottom = air.Screen.mainScreen.visibleBounds.bottom;

	/*
	  Calculate position
	*/
	var winX, winY;
	switch (opts.position) {
		case 'topLeft':
			winX = farLeft + padding;
			winY = farTop + padding + 0;
			break;

		case 'bottomLeft':
			winX = farLeft + padding;
			winY = farBottom - height - padding - 0;
			break;

		case 'bottomRight':
			winX = farRight - width - padding;
			winY = farBottom - height - padding - 0;
			break;

		default:
			winX = farRight - width - padding;
			winY = farTop + padding + 0;
			break;
	}
	sch.dump(winX+"x"+winY);
	/*
	  Create window
	*/
	var winopts = new air.NativeWindowInitOptions();
	winopts.transparent = true;
	winopts.type = air.NativeWindowType.LIGHTWEIGHT;
	winopts.systemChrome = air.NativeWindowSystemChrome.NONE;
	winopts.resizable = false;
	winopts.minimizable = false;
	winopts.maximizable = false;

	var winBounds = new air.Rectangle(winX, winY, width, height);

	// window is initially not visible to keep it from stealing focus
	var notifyLoader = air.HTMLLoader.createRootWindow(false, winopts, false, winBounds);

	notifyLoader.paintsDefaultBackground = false;
	notifyLoader.alpha = 1; // make the loader object transparent
	notifyLoader.stage.nativeWindow.alwaysInFront = true; // make the notify window a non-blocking modal

	/*
		bind notifyLoader.window.opener to this window
	*/
	notifyLoader.addEventListener(air.Event.HTML_DOM_INITIALIZE, function(){
		notifyLoader.window.opener = window;
	});

	var notify_url = "html/notify.html?json="+encodeURIComponent(sch.enJSON(opts));

	notifyLoader.load(new air.URLRequest(notify_url));

};<commit_msg>NYI'd methods we need to fix for Titanium<commit_after>
PurrJS = {};

 /*
	 modal
 */
PurrJS.modal = function(title, msg, icon, duration, position) {

	console.log('PurrJS.modal NYI');
	return;

	var width  = 400;
	var height = 300;

	var padding = 0;

	var farRight = air.Screen.mainScreen.bounds.right;
	var farTop   = air.Screen.mainScreen.bounds.top;

	var winX = farRight - width - padding;
	var winY = 0 + padding + 20;

	var opts = new air.NativeWindowInitOptions();
	opts.transparent = true;
	opts.type = air.NativeWindowType.UTILITY;
	opts.systemChrome = air.NativeWindowSystemChrome.NONE;
	opts.resizable = false;
	opts.minimizable = false;
	opts.maximizable = false;

	var winBounds = new air.Rectangle(winX, winY, width, height);
	var notifyLoader = air.HTMLLoader.createRootWindow(true, opts, false, winBounds);
	notifyLoader.load(new air.URLRequest("app:/html/modal.html"));
	notifyLoader.alpha = 0.6;

	 // air.Introspector.Console.info(notifyLoader);

	 // notifyLoader.window.document.getElementById('container').innerHTML = msg;

	fadeIn();
	var fadeOutTimeout = setTimeout(fadeOut, 8000);

	function fadeIn() {

		notifyLoader.alpha = 0;

		// start
		opacityUp();

		function opacityUp() {
			notifyLoader.alpha += 0.1;
			if (notifyLoader.alpha < 1) {
				setTimeout(opacityUp, 30); // do again
			}
		}

	}

	function fadeOut() {
		notifyLoader.alpha = 1;

		clearTimeout(fadeOutTimeout);

		// start
		opacityDown();

		function opacityDown() {
			notifyLoader.alpha -= 0.1;
			if (notifyLoader.alpha > 0 && opacityDown) {
				setTimeout(opacityDown, 30); // do again
			} else {
				notifyLoader.window.nativeWindow.close();
				notifyLoader = null;
			}
		}

	}

};

/*
   notify
*/
PurrJS.notify = function(opts) {

	console.log('PurrJS.notify NYI');
	return;

	opts = sch.defaults({
		'title':   'opts.title',
		'message': 'opts.message',
		'icon':    'opts.icon',
		'duration':6000, // in ms
		'position':'topRight',
		'height':  160,
		'width':   300,
		'padding': 0,
		'data':    null,
		'template':null,
		'onClick' :null,
		'onHover' :null
	}, opts);

	/*
	  Size of window
	*/
	var width  = opts.width;
	var height = opts.height;

	/*
	  padding from screen edges
	*/
	var padding = opts.padding;

	/*
	  get dimensions
	*/
	var farRight  = air.Screen.mainScreen.visibleBounds.right;
	var farTop    = air.Screen.mainScreen.visibleBounds.top;
	var farLeft   = air.Screen.mainScreen.visibleBounds.left;
	var farBottom = air.Screen.mainScreen.visibleBounds.bottom;

	/*
	  Calculate position
	*/
	var winX, winY;
	switch (opts.position) {
		case 'topLeft':
			winX = farLeft + padding;
			winY = farTop + padding + 0;
			break;

		case 'bottomLeft':
			winX = farLeft + padding;
			winY = farBottom - height - padding - 0;
			break;

		case 'bottomRight':
			winX = farRight - width - padding;
			winY = farBottom - height - padding - 0;
			break;

		default:
			winX = farRight - width - padding;
			winY = farTop + padding + 0;
			break;
	}
	sch.dump(winX+"x"+winY);
	/*
	  Create window
	*/
	var winopts = new air.NativeWindowInitOptions();
	winopts.transparent = true;
	winopts.type = air.NativeWindowType.LIGHTWEIGHT;
	winopts.systemChrome = air.NativeWindowSystemChrome.NONE;
	winopts.resizable = false;
	winopts.minimizable = false;
	winopts.maximizable = false;

	var winBounds = new air.Rectangle(winX, winY, width, height);

	// window is initially not visible to keep it from stealing focus
	var notifyLoader = air.HTMLLoader.createRootWindow(false, winopts, false, winBounds);

	notifyLoader.paintsDefaultBackground = false;
	notifyLoader.alpha = 1; // make the loader object transparent
	notifyLoader.stage.nativeWindow.alwaysInFront = true; // make the notify window a non-blocking modal

	/*
		bind notifyLoader.window.opener to this window
	*/
	notifyLoader.addEventListener(air.Event.HTML_DOM_INITIALIZE, function(){
		notifyLoader.window.opener = window;
	});

	var notify_url = "html/notify.html?json="+encodeURIComponent(sch.enJSON(opts));

	notifyLoader.load(new air.URLRequest(notify_url));

};<|endoftext|>