<commit_before>'use strict';

define((require) => {
	const { i18n, notifications, runtime } = require('webextension-polyfill');
	const { getPlatformName, isFullscreenMode } = require('util/util-browser');
	const Options = require('storage/options');

	const manifest = runtime.getManifest();
	const DEFAULT_OPTIONS_VALUES = {
		type: 'basic',
		iconUrl: runtime.getURL(manifest.icons['128']),
	};

	const defaultTrackArtUrl = runtime.getURL('/icons/cover_art_default.png');
	const unknownTrackArtUrl = runtime.getURL('icons/cover_art_unknown.png');

	/**
	 * Now playing notification delay in milliseconds.
	 */
	const NOW_PLAYING_NOTIFICATION_DELAY = 5000;

	/**
	 * Map of click listeners indexed by notification IDs.
	 * @type {Object}
	 */
	const clickListeners = {};

	let notificationTimeoutId = null;

	/**
	 * Check if notifications are available.
	 * Chrome on Mac does not show notification while in fullscreen mode.
	 * @return {Boolean} Check result
	 */
	async function isAvailable() {
		// @ifdef CHROME
		const platform = await getPlatformName();
		if (platform === 'mac') {
			return !await isFullscreenMode();
		}

		return true;
		// @endif
		/* @ifdef FIREFOX
		return true;
		/* @endif */
	}

	/**
	 * Check if notifications are allowed by user.
	 * @return {Boolean} Check result
	 */
	async function isAllowed() {
		return await Options.getOption(Options.USE_NOTIFICATIONS);
	}

	/**
	 * Set up listener for click on given notification.
	 * All clicks are handled internally and transparently passed to listeners, if any.
	 * Setting multiple listeners for single notification is not supported,
	 * the last set listener will overwrite any previous.
	 *
	 * @param {String} notificationId Notification ID
	 * @param {Function} callback Function that will be called on notification click
	 */
	function addOnClickedListener(notificationId, callback) {
		clickListeners[notificationId] = callback;
	}

	/**
	 * Remove onClicked listener for given notification.
	 * @param {String} notificationId Notification ID
	 */
	function removeOnClickedListener(notificationId) {
		if (clickListeners[notificationId]) {
			delete clickListeners[notificationId];
		}
	}

	/**
	 * Show notification.
	 * @param  {Object} options Notification options
	 * @param  {Function} onClicked Function that will be called on notification click
	 * @return {String} Notification ID
	 */
	async function showNotification(options, onClicked) {
		if (!await isAvailable()) {
			throw new Error('Notifications are not available');
		}

		if (typeof onClicked === 'function') {
			options.isClickable = true;
		}

		for (const key in DEFAULT_OPTIONS_VALUES) {
			if (options[key]) {
				continue;
			}

			const defaultValue = DEFAULT_OPTIONS_VALUES[key];
			options[key] = defaultValue;
		}

		let notificationId;
		try {
			notificationId = await notifications.create('', options);
		} catch (err) {
			// Use default track art and try again
			if (options.iconUrl === defaultTrackArtUrl) {
				throw err;
			}

			options.iconUrl = defaultTrackArtUrl;
			notificationId = await notifications.create('', options);
		}

		if (typeof onClicked === 'function') {
			addOnClickedListener(notificationId, onClicked);
		}

		return notificationId;
	}

	/**
	 * Show 'Now playing' notification.
	 * @param  {Object} song Copy of song instance
	 * @param  {Function} onClick Function that will be called on notification click
	 */
	async function showNowPlaying(song, onClick) {
		if (!await isAllowed()) {
			return;
		}

		const connectorLabel = song.metadata.label;
		const iconUrl = song.getTrackArt() || defaultTrackArtUrl;
		// @ifdef CHROME
		let message = song.getArtist();
		const title = song.getTrack();
		// @endif
		/* @ifdef FIREFOX
		let message = `${song.getTrack()}\n${song.getArtist()}`;
		let title = `Web Scrobbler \u2022 ${connectorLabel}`;
		/* @endif */

		const albumName = song.getAlbum();
		if (albumName) {
			message = `${message}\n${albumName}`;
		}

		const userPlayCount = song.metadata.userPlayCount;
		if (userPlayCount) {
			const userPlayCountStr = i18n.getMessage('infoYourScrobbles', userPlayCount);
			message = `${message}\n${userPlayCountStr}`;
		}

		const options = {
			iconUrl, title, message,

			// @ifdef CHROME
			silent: true,
			contextMessage: connectorLabel
			// @endif
		};

		clearNotificationTimeout();

		notificationTimeoutId = setTimeout(async() => {
			try {
				const notificationId = await showNotification(options, onClick);
				song.metadata.notificationId = notificationId;
			} catch (err) {
				console.warn(`Unable to show now playing notification: ${err.message}`);
			}
		}, NOW_PLAYING_NOTIFICATION_DELAY);
	}

	/**
	 * Remove now playing notification for given song.
	 * @param  {Object} song Song instance
	 */
	function clearNowPlaying(song) {
		clearNotificationTimeout();
		remove(song.metadata.notificationId);
	}

	/**
	 * Show error notification.
	 * @param  {String} message Notification message
	 * @param  {Function} onClick Function that will be called on notification click
	 */
	function showError(message, onClick = null) {
		const title = i18n.getMessage('notificationAuthError');
		const options = { title, message };
		showNotification(options, onClick);
	}

	/**
	 * Show error notification if user is unable to sign in to service.
	 * @param  {Object} scrobbler Scrobbler instance
	 * @param  {Function} onClicked Function that will be called on notification click
	 */
	function showSignInError(scrobbler, onClicked) {
		const errorMessage = i18n('notificationUnableSignIn', scrobbler.label);
		showError(errorMessage, onClicked);
	}

	/**
	 * Show notification if song is not recognized.
	 * @param  {Function} onClicked Function that will be called on notification click
	 */
	async function showSongNotRecognized(onClicked) {
		if (!await Options.getOption(Options.USE_UNRECOGNIZED_SONG_NOTIFICATIONS)) {
			return;
		}

		const options = {
			iconUrl: unknownTrackArtUrl,
			title: i18n.getMessage('notificationNotRecognized'),
			message: i18n.getMessage('notificationNotRecognizedText')
		};
		showNotification(options, onClicked);
	}

	/**
	 * Show auth notification.
	 * @param  {Function} onClicked Function that will be called on notification click
	 */
	async function showAuthNotification(onClicked) {
		const options = {
			title: i18n.getMessage('notificationConnectAccounts'),
			message: i18n.getMessage('notificationConnectAccountsText'),
		};

		await showNotification(options, onClicked);
	}

	/**
	 * Completely remove notification.
	 * Do nothing if ID does not match any existing notification.
	 *
	 * @param  {String} notificationId Notification ID
	 */
	function remove(notificationId) {
		if (notificationId) {
			notifications.clear(notificationId);
		}
	}

	function clearNotificationTimeout() {
		if (notificationTimeoutId) {
			clearTimeout(notificationTimeoutId);
			notificationTimeoutId = null;
		}
	}

	notifications.onClicked.addListener((notificationId) => {
		console.log(`Notification onClicked: ${notificationId}`);

		if (clickListeners[notificationId]) {
			clickListeners[notificationId](notificationId);
		}
	});
	notifications.onClosed.addListener((notificationId) => {
		removeOnClickedListener(notificationId);
	});

	return {
		clearNowPlaying,
		showAuthNotification,
		showError,
		showNowPlaying,
		showSignInError,
		showSongNotRecognized
	};
});
<commit_msg>Use `i18n` argument properly<commit_after>'use strict';

define((require) => {
	const { i18n, notifications, runtime } = require('webextension-polyfill');
	const { getPlatformName, isFullscreenMode } = require('util/util-browser');
	const Options = require('storage/options');

	const manifest = runtime.getManifest();
	const DEFAULT_OPTIONS_VALUES = {
		type: 'basic',
		iconUrl: runtime.getURL(manifest.icons['128']),
	};

	const defaultTrackArtUrl = runtime.getURL('/icons/cover_art_default.png');
	const unknownTrackArtUrl = runtime.getURL('icons/cover_art_unknown.png');

	/**
	 * Now playing notification delay in milliseconds.
	 */
	const NOW_PLAYING_NOTIFICATION_DELAY = 5000;

	/**
	 * Map of click listeners indexed by notification IDs.
	 * @type {Object}
	 */
	const clickListeners = {};

	let notificationTimeoutId = null;

	/**
	 * Check if notifications are available.
	 * Chrome on Mac does not show notification while in fullscreen mode.
	 * @return {Boolean} Check result
	 */
	async function isAvailable() {
		// @ifdef CHROME
		const platform = await getPlatformName();
		if (platform === 'mac') {
			return !await isFullscreenMode();
		}

		return true;
		// @endif
		/* @ifdef FIREFOX
		return true;
		/* @endif */
	}

	/**
	 * Check if notifications are allowed by user.
	 * @return {Boolean} Check result
	 */
	async function isAllowed() {
		return await Options.getOption(Options.USE_NOTIFICATIONS);
	}

	/**
	 * Set up listener for click on given notification.
	 * All clicks are handled internally and transparently passed to listeners, if any.
	 * Setting multiple listeners for single notification is not supported,
	 * the last set listener will overwrite any previous.
	 *
	 * @param {String} notificationId Notification ID
	 * @param {Function} callback Function that will be called on notification click
	 */
	function addOnClickedListener(notificationId, callback) {
		clickListeners[notificationId] = callback;
	}

	/**
	 * Remove onClicked listener for given notification.
	 * @param {String} notificationId Notification ID
	 */
	function removeOnClickedListener(notificationId) {
		if (clickListeners[notificationId]) {
			delete clickListeners[notificationId];
		}
	}

	/**
	 * Show notification.
	 * @param  {Object} options Notification options
	 * @param  {Function} onClicked Function that will be called on notification click
	 * @return {String} Notification ID
	 */
	async function showNotification(options, onClicked) {
		if (!await isAvailable()) {
			throw new Error('Notifications are not available');
		}

		if (typeof onClicked === 'function') {
			options.isClickable = true;
		}

		for (const key in DEFAULT_OPTIONS_VALUES) {
			if (options[key]) {
				continue;
			}

			const defaultValue = DEFAULT_OPTIONS_VALUES[key];
			options[key] = defaultValue;
		}

		let notificationId;
		try {
			notificationId = await notifications.create('', options);
		} catch (err) {
			// Use default track art and try again
			if (options.iconUrl === defaultTrackArtUrl) {
				throw err;
			}

			options.iconUrl = defaultTrackArtUrl;
			notificationId = await notifications.create('', options);
		}

		if (typeof onClicked === 'function') {
			addOnClickedListener(notificationId, onClicked);
		}

		return notificationId;
	}

	/**
	 * Show 'Now playing' notification.
	 * @param  {Object} song Copy of song instance
	 * @param  {Function} onClick Function that will be called on notification click
	 */
	async function showNowPlaying(song, onClick) {
		if (!await isAllowed()) {
			return;
		}

		const connectorLabel = song.metadata.label;
		const iconUrl = song.getTrackArt() || defaultTrackArtUrl;
		// @ifdef CHROME
		let message = song.getArtist();
		const title = song.getTrack();
		// @endif
		/* @ifdef FIREFOX
		let message = `${song.getTrack()}\n${song.getArtist()}`;
		let title = `Web Scrobbler \u2022 ${connectorLabel}`;
		/* @endif */

		const albumName = song.getAlbum();
		if (albumName) {
			message = `${message}\n${albumName}`;
		}

		const userPlayCount = song.metadata.userPlayCount;
		if (userPlayCount) {
			const userPlayCountStr = i18n.getMessage('infoYourScrobbles', [userPlayCount]);
			message = `${message}\n${userPlayCountStr}`;
		}

		const options = {
			iconUrl, title, message,

			// @ifdef CHROME
			silent: true,
			contextMessage: connectorLabel
			// @endif
		};

		clearNotificationTimeout();

		notificationTimeoutId = setTimeout(async() => {
			try {
				const notificationId = await showNotification(options, onClick);
				song.metadata.notificationId = notificationId;
			} catch (err) {
				console.warn(`Unable to show now playing notification: ${err.message}`);
			}
		}, NOW_PLAYING_NOTIFICATION_DELAY);
	}

	/**
	 * Remove now playing notification for given song.
	 * @param  {Object} song Song instance
	 */
	function clearNowPlaying(song) {
		clearNotificationTimeout();
		remove(song.metadata.notificationId);
	}

	/**
	 * Show error notification.
	 * @param  {String} message Notification message
	 * @param  {Function} onClick Function that will be called on notification click
	 */
	function showError(message, onClick = null) {
		const title = i18n.getMessage('notificationAuthError');
		const options = { title, message };
		showNotification(options, onClick);
	}

	/**
	 * Show error notification if user is unable to sign in to service.
	 * @param  {Object} scrobbler Scrobbler instance
	 * @param  {Function} onClicked Function that will be called on notification click
	 */
	function showSignInError(scrobbler, onClicked) {
		const errorMessage = i18n('notificationUnableSignIn', scrobbler.label);
		showError(errorMessage, onClicked);
	}

	/**
	 * Show notification if song is not recognized.
	 * @param  {Function} onClicked Function that will be called on notification click
	 */
	async function showSongNotRecognized(onClicked) {
		if (!await Options.getOption(Options.USE_UNRECOGNIZED_SONG_NOTIFICATIONS)) {
			return;
		}

		const options = {
			iconUrl: unknownTrackArtUrl,
			title: i18n.getMessage('notificationNotRecognized'),
			message: i18n.getMessage('notificationNotRecognizedText')
		};
		showNotification(options, onClicked);
	}

	/**
	 * Show auth notification.
	 * @param  {Function} onClicked Function that will be called on notification click
	 */
	async function showAuthNotification(onClicked) {
		const options = {
			title: i18n.getMessage('notificationConnectAccounts'),
			message: i18n.getMessage('notificationConnectAccountsText'),
		};

		await showNotification(options, onClicked);
	}

	/**
	 * Completely remove notification.
	 * Do nothing if ID does not match any existing notification.
	 *
	 * @param  {String} notificationId Notification ID
	 */
	function remove(notificationId) {
		if (notificationId) {
			notifications.clear(notificationId);
		}
	}

	function clearNotificationTimeout() {
		if (notificationTimeoutId) {
			clearTimeout(notificationTimeoutId);
			notificationTimeoutId = null;
		}
	}

	notifications.onClicked.addListener((notificationId) => {
		console.log(`Notification onClicked: ${notificationId}`);

		if (clickListeners[notificationId]) {
			clickListeners[notificationId](notificationId);
		}
	});
	notifications.onClosed.addListener((notificationId) => {
		removeOnClickedListener(notificationId);
	});

	return {
		clearNowPlaying,
		showAuthNotification,
		showError,
		showNowPlaying,
		showSignInError,
		showSongNotRecognized
	};
});
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import * as courseActions from '../../actions/course-actions';
import CourseForm from './course-form';

class ManageCoursePage extends React.Component {
    constructor(props, context) {
        super(props, context);

        this.state = {
            course: Object.assign({}, props.course),
            errors: {},
        };

        this.updateCourseState = this.updateCourseState.bind(this);
        this.saveCourse = this.saveCourse.bind(this);
    }

    updateCourseState(event) {
        const field = event.target.name;
        let course = this.state.course;
        course[field] = event.target.value;
        this.setState({course: course});
    }

    saveCourse(event) {
        event.preventDefault();
        this.props.actions.saveCourse(this.state.course);
        this.context.router.push('/courses');
    }

    render() {
        return (
            <CourseForm
                allAuthors={this.props.authors}
                onChange={this.updateCourseState}
                onSave={this.saveCourse}
                course={this.state.course}
                errors={this.state.errors}
            />
        );
    }
}

ManageCoursePage.propTypes = {
    course: PropTypes.object.isRequired,
    authors: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired,
}

//Pull in the React Router context so router is available on this.context.router.
ManageCoursePage.contextTypes = {
    router: PropTypes.object,
};

const getCourseById = (courses, id) => {
    const filteredCourses = courses.filter(course => course.id === id);

    return filteredCourses.length
        ? filteredCourses[0]
        : null;
}

function mapStateToProps(state, ownProps) {
    let course = {id: '', watchHref: '', title: '', authorId: '', length: '', category: ''};

    const courseId = ownProps.params.id; // from the path '/course/:id'

    if (courseId && state.courses.length) {
        course = getCourseById(state.courses, courseId);
    }

    const authorsFormattedForDropdown = state.authors.map(author => {
        return {
            value: author.id,
            text: `${author.firstName} ${author.lastName}`,
        };
    });

    return {
        course: course,
        authors: authorsFormattedForDropdown,
    }
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(courseActions, dispatch),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(ManageCoursePage);
<commit_msg>Update state via componentWillReceiveProps<commit_after>import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import * as courseActions from '../../actions/course-actions';
import CourseForm from './course-form';

class ManageCoursePage extends React.Component {
    constructor(props, context) {
        super(props, context);

        this.state = {
            course: Object.assign({}, props.course),
            errors: {},
        };

        this.updateCourseState = this.updateCourseState.bind(this);
        this.saveCourse = this.saveCourse.bind(this);
    }

    componentWillReceiveProps(nextProps) {
        if (this.props.course.id !== nextProps.course.id) {
            // Necessary to populate form when existing course is loaded directly.
            this.setState({course: Object.assign({}, nextProps.course)});
        }
    }

    updateCourseState(event) {
        const field = event.target.name;
        let course = this.state.course;
        course[field] = event.target.value;
        this.setState({course: course});
    }

    saveCourse(event) {
        event.preventDefault();
        this.props.actions.saveCourse(this.state.course);
        this.context.router.push('/courses');
    }

    render() {
        return (
            <CourseForm
                allAuthors={this.props.authors}
                onChange={this.updateCourseState}
                onSave={this.saveCourse}
                course={this.state.course}
                errors={this.state.errors}
            />
        );
    }
}

ManageCoursePage.propTypes = {
    course: PropTypes.object.isRequired,
    authors: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired,
}

//Pull in the React Router context so router is available on this.context.router.
ManageCoursePage.contextTypes = {
    router: PropTypes.object,
};

const getCourseById = (courses, id) => {
    const filteredCourses = courses.filter(course => course.id === id);

    return filteredCourses.length
        ? filteredCourses[0]
        : null;
}

function mapStateToProps(state, ownProps) {
    let course = {id: '', watchHref: '', title: '', authorId: '', length: '', category: ''};

    const courseId = ownProps.params.id; // from the path '/course/:id'

    if (courseId && state.courses.length) {
        course = getCourseById(state.courses, courseId);
    }

    const authorsFormattedForDropdown = state.authors.map(author => {
        return {
            value: author.id,
            text: `${author.firstName} ${author.lastName}`,
        };
    });

    return {
        course: course,
        authors: authorsFormattedForDropdown,
    }
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(courseActions, dispatch),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(ManageCoursePage);
<|endoftext|>


<commit_before>/*
 * @name Chain
 * @description One mass is attached to the mouse position and the other is attached the position of the other mass. The gravity in the environment pulls down on both.
 * Ported from the Processing Examples page.
 */
var s1, s2;
var gravity = 9.0;
var mass = 2.0;

function setup() {
  createCanvas(720, 400);
  fill(255, 126);
  // Inputs: x, y, mass, gravity
  s1 = new Spring2D(0.0, width/2, mass, gravity);
  s2 = new Spring2D(0.0, width/2, mass, gravity);
}

function draw() {
  background(0);
  s1.update(mouseX, mouseY);
  s1.display(mouseX, mouseY);
  s2.update(s1.x, s1.y);
  s2.display(s1.x, s1.y);
}

function Spring2D(xpos, ypos, m, g) {
  this.x = xpos;// The x- and y-coordinates
  this.y = ypos;
  this.vx = 0; // The x- and y-axis velocities
  this.vy = 0;
  this.mass = m;
  this.gravity = g;
  this.radius = 30;
  this.stiffness = 0.2;
  this.damping = 0.7;

  this.update = function(targetX, targetY) {
    var forceX = (targetX - this.x) * this.stiffness;
    var ax = forceX / this.mass;
    this.vx = this.damping * (this.vx + ax);
    this.x += this.vx;
    var forceY = (targetY - this.y) * this.stiffness;
    forceY += this.gravity;
    var ay = forceY / this.mass;
    this.vy = this.damping * (this.vy + ay);
    this.y += this.vy;
  }

  this.display = function(nx, ny) {
    noStroke();
    ellipse(this.x, this.y, this.radius*2, this.radius*2);
    stroke(255);
    line(this.x, this.y, nx, ny);
  }
}<commit_msg>add Spanish translation<commit_after>/*
 * @name Cadena
 * @description Una masa está unida a la posición del ratón y la otra está unida a la posición de la otra masa. La gravedad en el ambiente tira de ambas hacia abajo.
 * Puerto de un ejemplo original para Processing.
 */
var s1, s2;
var gravity = 9.0;
var mass = 2.0;

function setup() {
  createCanvas(720, 400);
  fill(255, 126);
  // Inputs: x, y, mass, gravity
  s1 = new Spring2D(0.0, width/2, mass, gravity);
  s2 = new Spring2D(0.0, width/2, mass, gravity);
}

function draw() {
  background(0);
  s1.update(mouseX, mouseY);
  s1.display(mouseX, mouseY);
  s2.update(s1.x, s1.y);
  s2.display(s1.x, s1.y);
}

function Spring2D(xpos, ypos, m, g) {
  this.x = xpos;// The x- and y-coordinates
  this.y = ypos;
  this.vx = 0; // The x- and y-axis velocities
  this.vy = 0;
  this.mass = m;
  this.gravity = g;
  this.radius = 30;
  this.stiffness = 0.2;
  this.damping = 0.7;

  this.update = function(targetX, targetY) {
    var forceX = (targetX - this.x) * this.stiffness;
    var ax = forceX / this.mass;
    this.vx = this.damping * (this.vx + ax);
    this.x += this.vx;
    var forceY = (targetY - this.y) * this.stiffness;
    forceY += this.gravity;
    var ay = forceY / this.mass;
    this.vy = this.damping * (this.vy + ay);
    this.y += this.vy;
  }

  this.display = function(nx, ny) {
    noStroke();
    ellipse(this.x, this.y, this.radius*2, this.radius*2);
    stroke(255);
    line(this.x, this.y, nx, ny);
  }
}<|endoftext|>


<commit_before>import React from 'react';
import ReactTooltip from 'react-tooltip';
import { sparqlConnect, sparqlCombine } from 'sparql-connect';
import OperationsBySeries from './operations-by-series';
import ProductsBySeries from '../products/products-by-series';
import NotFound from '../not-found'
import arrayToObject from '../../utils/array-to-object'
import operationTypesConnector from '../connectors/operation-types';
import periodicitiesConnector from '../connectors/periodicities'
import D, { getLang } from 'i18n'
import { tidyString } from 'utils/string-utils'
import 'css/style.css';

/**
  * Builds the query that retrieves the details on a given operation series.
  */
// OPTIONAL {<${series}> insee:casdAvailable ?casd} .
const queryBuilder = series => `
  PREFIX insee: <http://rdf.insee.fr/def/base#>
  PREFIX dcterms: <http://purl.org/dc/terms/>
  PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
  SELECT ?label ?altLabel ?abstract ?historyNote ?type ?periodicity
  FROM <http://rdf.insee.fr/graphes/operations>
  WHERE {
    <${series}> skos:prefLabel ?label .
    FILTER (lang(?label) = '${getLang()}') .
    OPTIONAL {<${series}> skos:altLabel ?altLabel} .
    OPTIONAL {<${series}> dcterms:abstract ?abstract .
    FILTER (lang(?abstract) = '${getLang()}')} .
    OPTIONAL {<${series}> skos:historyNote ?historyNote .
    FILTER (lang(?historyNote) = '${getLang()}')} .
    OPTIONAL {<${series}> dcterms:type ?type} .
    OPTIONAL {<${series}> dcterms:accrualPeriodicity ?periodicity}
  }
`;

const seriesDetailsConnector = sparqlConnect(queryBuilder, {
  queryName: 'seriesDetails',
  params: ['series'],
  singleResult: true
});

const connector = sparqlCombine(
  operationTypesConnector,
  periodicitiesConnector,
  seriesDetailsConnector
)

function SeriesDetails({ series, label, altLabel, abstract, historyNote,
  type, casd, periodicity, operationTypes, periodicities }) {

  const operationTypesObj = arrayToObject(operationTypes, 'type')
  const periodicitiesObj = arrayToObject(periodicities, 'periodicity')
  return (

{label}
        {/*(casd === 'true') &&

        */}

{altLabel}

      <ReactTooltip />

{tidyString(abstract)}

      {historyNote &&
{D.historyNote}
}

{tidyString(historyNote)}

      {type &&

        {operationTypesObj[type][getLang()]}

}
      {periodicity &&

        {periodicitiesObj[periodicity][getLang()]}

}

      <OperationsBySeries series={series} />
      <ProductsBySeries series={series} />

  );
}

export default connector(SeriesDetails, {
  error: ({ series }) => <NotFound
    message={D.seriesNotFound(series)} />
});
<commit_msg>Pull up pills into series details component<commit_after>import React from 'react';
import ReactTooltip from 'react-tooltip';
import { sparqlConnect, sparqlCombine } from 'sparql-connect';
import OperationsBySeries from './operations-by-series';
import ProductsBySeries from '../products/products-by-series';
import NotFound from '../not-found'
import arrayToObject from '../../utils/array-to-object'
import operationTypesConnector from '../connectors/operation-types';
import periodicitiesConnector from '../connectors/periodicities'
import D, { getLang } from 'i18n'
import { tidyString } from 'utils/string-utils'
import 'css/style.css';

/**
  * Builds the query that retrieves the details on a given operation series.
  */
// OPTIONAL {<${series}> insee:casdAvailable ?casd} .
const queryBuilder = series => `
  PREFIX insee: <http://rdf.insee.fr/def/base#>
  PREFIX dcterms: <http://purl.org/dc/terms/>
  PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
  SELECT ?label ?altLabel ?abstract ?historyNote ?type ?periodicity
  FROM <http://rdf.insee.fr/graphes/operations>
  WHERE {
    <${series}> skos:prefLabel ?label .
    FILTER (lang(?label) = '${getLang()}') .
    OPTIONAL {<${series}> skos:altLabel ?altLabel} .
    OPTIONAL {<${series}> dcterms:abstract ?abstract .
    FILTER (lang(?abstract) = '${getLang()}')} .
    OPTIONAL {<${series}> skos:historyNote ?historyNote .
    FILTER (lang(?historyNote) = '${getLang()}')} .
    OPTIONAL {<${series}> dcterms:type ?type} .
    OPTIONAL {<${series}> dcterms:accrualPeriodicity ?periodicity}
  }
`;

const seriesDetailsConnector = sparqlConnect(queryBuilder, {
  queryName: 'seriesDetails',
  params: ['series'],
  singleResult: true
});

const connector = sparqlCombine(
  operationTypesConnector,
  periodicitiesConnector,
  seriesDetailsConnector
)

function SeriesDetails({ series, label, altLabel, abstract, historyNote,
  type, casd, periodicity, operationTypes, periodicities }) {

  const operationTypesObj = arrayToObject(operationTypes, 'type')
  const periodicitiesObj = arrayToObject(periodicities, 'periodicity')
  return (

{label}
        {/*(casd === 'true') &&

        */}

{altLabel}

      {type &&

        {operationTypesObj[type][getLang()]}

}
      {periodicity &&

        {periodicitiesObj[periodicity][getLang()]}

}
      <ReactTooltip />

{tidyString(abstract)}

      {historyNote &&
{D.historyNote}
}

{tidyString(historyNote)}

      <OperationsBySeries series={series} />
      <ProductsBySeries series={series} />

  );
}

export default connector(SeriesDetails, {
  error: ({ series }) => <NotFound
    message={D.seriesNotFound(series)} />
});
<|endoftext|>


<commit_before>/*!
* Copyright (c) 2015 Carrot Creative
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

(function (win, doc) {

  function __() {

    var RegexpValue = /[\-+]?[\d]*\.?[\d]+/g
      , ParseWildcard = '{?}'
      , ParseWildcardRegexp = /\{\?\}/g;

    var Animation = function (component) {
      var tweens = []
        , points = component.points
        , current, next;
      for (var i=0; i<points.length; i++) {
        current = points[i];
        next = points[i+1];
        tweens.push(new Tween(component.property, current, next));
      }
      this.tweens = tweens;
    }

    Animation.prototype = {
      current: function (Y) {
        var tweens = this.tweens
          , len = tweens.length
          , tween
          , current;
        for (var i=0; i<len; i++) {
          tween = tweens[i];
          if (Y >= tween.fromY || (Y <= tween.fromY && i == 0)){
            current = tween.current(Y);
          }
        }
        return current;
      }
    }

    var Tweener = {};

    Tweener.default = function (fromValue, toValue) {
      this.fromValue = ParseValue(fromValue);
      this.toValue = ParseValue(toValue);
    }

    Tweener.default.prototype = {
      tween: function (pct) {
        var fromValue = this.fromValue
          , toValue = this.toValue;
        return CompileValues(fromValue, toValue, pct);
      }
    }

    var Tween = function (property, fromPoint, toPoint) {
      if (!toPoint) toPoint = fromPoint;
      this.tweener = new (Tweener[property] || Tweener.default)(fromPoint.value, toPoint.value);
      this.fromY = fromPoint.Y;
      this.toY = toPoint.Y;
    }

    Tween.prototype = {
      current: function (Y) {
        var pct = 0
          , fromY = this.fromY
          , toY = this.toY;
        if (Y >= fromY && Y <= toY) {
          pct = (Y - fromY) / (toY - fromY);
        } else if (Y > toY) {
          pct = 1;
        }
        return this.tweener.tween(pct);
      }
    }

    function ParseValue (value) {
      var nums = [];
      value = new String(value).replace(RegexpValue, function (num) {
        nums.push(parseFloat(num));
        return ParseWildcard;
      });
      return [value, nums]
    }

    function CompileValues (fromValue, toValue, pct) {
      var i = 0
        , fromNum
        , toNum;
      return fromValue[0].replace(ParseWildcardRegexp, function () {
        from = fromValue[1][i];
        to = toValue[1][i];
        i++;
        return (from + ((to - from) * pct));
      });
    }

    var Style = function (component) {
      this.points = component.points;
    }

    Style.prototype = {
      current: function (Y) {
        var points = this.points
          , current = new String();
        for (var i=0; i<points.length; i++) {
          point = points[i];
          if (Y >= point.Y) current = point.value;
        }
        return current;
      }
    }

    var Point = function (Y, value) {
      this.Y = Y;
      this.value = value;
    }

    var Collection = function (object) {
      object = object || {};
      this.points = [];
      for (var Y in object) {
        this.add(Y, object[Y]);
      }
    }

    Collection.prototype = {
      add: function (Y, value) {
        var points = this.points.slice(0)
          , point = new Point(parseInt(Y), value)
          , isAdded = false;
        for (var i=0; i<this.points.length; i++) {
          if (this.points[i].Y > point.Y) {
            points.splice(i, 0, point);
            isAdded = true;
          }
        }
        if (!isAdded) points.push(point);
        this.points = points;
        return this;
      },
      merge: function (at, collection) {
        var points = collection.points
          , value;
        for (var i=0; i<points.length; i++) {
          action = points[i];
          this.add((at + action.Y), action.value);
        }
        return this;
      }
    }

    var Action = function (Klass, property, points) {
      var points = this.points = (new Collection(points)).points;
      this.max = points[points.length - 1].Y;
      this.property = property;
      this.klass = new Klass(this);
    }

    Action.prototype = {
      current: function (Y) {
        return this.klass.current(Y);
      }
    }

    var Element = function (selector) {
      this.selector = selector;
      this.actions = {};
    }

    Element.prototype = {
      add: function (Y, action) {
        var property = action.property
          , collection;
        if (!(collection = this.actions[property])) collection = new Collection();
        collection.add(Y, action);
        this.actions[property] = collection;
        return this;
      },
      set: function (wY) {
        var $el = this.selector
          , actions = this.actions
          , collection, points
          , point, action, Y;
        if ($el.nodeName) {
          $el = [$el]
        } else if ('string' === typeof $el) {
          $el = doc.querySelectorAll($el);
        }
        for (var property in actions) {
          collection = actions[property];
          points = collection.points;
          for (var x=0; x<points.length; x++) {
            point = points[x];
            action = point.value;
            Y = (wY - point.Y);
            if ( (Y > 0) || (Y < 0 && x == 0) ) {
              for (var y=0; y<$el.length; y++) {
                $el[y].style[property] = action.current(Y);
              }
            }
          }
        }
        return this;
      }
    }

    var Storyboard = function () {
      this.elements = [];
      this.max = 0;
    }

    Storyboard.prototype = {
      add: function (Y, selector, action) {
        var elements = this.elements
          , element
          , max;
        for (var i=0; i<elements.length; i++) {
          if (elements[i].selector == selector) {
            element = elements[i];
            break;
          }
        }
        if (!element) {
          element = new Element(selector);
          elements.push(element);
        }
        if (action) {
          element.add(Y, action);
          max = Y + action.max;
          if (max > this.max) this.max = max;
        }
        this.elements = elements;
        return this;
      },
      merge: function (at, storyboard) {
        var elements = storyboard.elements
          , element, actions, collection
          , points, point;
        for (var x=0; x<elements.length; x++) {
          element = elements[x];
          actions = element.actions;
          for (var property in actions) {
            collection = actions[property];
            points = collection.points;
            for (var i=0; i<points.length; i++) {
              point = points[i];
              this.add((parseInt(at) + point.Y), element.selector, point.value);
            }
          }
        }
        return this;
      }
    }

    function SetElementsInStoryboardFunction (storyboard) {
      return function () {
        var wY = win.pageYOffset
          , elements = storyboard.elements
          , element;
        for (var i=0; i<elements.length; i++) {
          element = elements[i];
          element.set(wY);
        }
      }
    }

    function SetBodyMinHeightFunction (storyboard) {
      return function () {
        doc.body.style.minHeight = ((storyboard.max + win.innerHeight) + 'px');
      }
    }

    function AddEvent (roll, string, callback) {
      var events = string.split(' ')
        , ev;
      for (var i=0; i<events.length; i++) {
        ev = events[i];
        if (!roll.events[ev]) roll.events[ev] = [];
        roll.events[ev].push(callback);
        win.addEventListener(ev, callback);
      }
      callback();
    }

    function RemoveEvents (roll, string) {
      var events = string.split(' ')
        , ev, callbacks, callback;
      for (var x=0; x<events.length; x++) {
        ev = events[x];
        callbacks = roll.events[ev];
        for (var y=0; x<callbacks.length; x++) {
          callback = callbacks[y];
          win.removeEventListener(ev, callback);
        }
        roll.events[ev] = [];
      }
    }

    function RemoveAllEvents (roll) {
      for (var ev in roll.events) RemoveEvents(roll, ev);
      roll.events = {};
    }

    var Roll = function () {
      this.scenes = {};
      this.ats = {};
      this.events = {};
    }

    Roll.prototype = {
      add: function (name, scene) {
        if ('function' === typeof scene) {
          var fn = scene;
          scene = new Scene();
          fn(scene);
        }
        this.scenes[name] = scene;
        return this;
      },
      at: function (Y, name) {
        var ats = this.ats[Y] || [];
        ats.push(name);
        this.ats[Y] = ats;
        return this;
      },
      bind: function () {
        var storyboard = new Storyboard()
          , names
          , scene;
        for (var Y in this.ats) {
          names = this.ats[Y];
          for (var i=0; i<names.length; i++) {
            scene = this.scenes[names[i]];
            storyboard.merge(Y, scene.storyboard);
          }
        }
        AddEvent(this, 'scroll resize', SetElementsInStoryboardFunction(storyboard));
        AddEvent(this, 'resize', SetBodyMinHeightFunction(storyboard));
        return this;
      },
      unbind: function () {
        RemoveAllEvents(this);
        return this;
      }
    }

    var Scene = Roll.Scene = function () {
      this.storyboard = new Storyboard();
    }

    Scene.prototype = {
      animate: function ($el, property, points) {
        return this.action(Animation, $el, property, points);
      },
      style: function ($el, property, points) {
        return this.action(Style, $el, property, points);
      },
      action: function (Klass, $el, property, points) {
        var properties;
        if ('undefined' === typeof points) {
          properties = property;
        } else {
          (properties = {})[property] = points;
        }
        for (property in properties) {
          action = new Action(Klass, property, properties[property]);
          this.storyboard.add(0, $el, action);
        }
        return this;
      }
    }

    return Roll;

  }

  if ('function' === typeof define && define.amd) {
    define(__);
  } else {
    win.Roll = __();
  };

}(window, document));
<commit_msg>.remove(), .init() and fixes - .remove() erases all element values and unbinds. - .init() is the new .bind(): binds events and set up storyboard. - Set element styles in abstract function to make more compatible in the future.<commit_after>/*!
* Copyright (c) 2015 Carrot Creative
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

(function (win, doc) {

  function __() {

    var RegexpValue = /[\-+]?[\d]*\.?[\d]+/g
      , ParseWildcard = '{?}'
      , ParseWildcardRegexp = /\{\?\}/g;

    var Animation = function (component) {
      var tweens = []
        , points = component.points
        , current, next;
      for (var i=0; i<points.length; i++) {
        current = points[i];
        next = points[i+1];
        tweens.push(new Tween(component.property, current, next));
      }
      this.tweens = tweens;
    }

    Animation.prototype = {
      current: function (Y) {
        var tweens = this.tweens
          , len = tweens.length
          , tween
          , current;
        for (var i=0; i<len; i++) {
          tween = tweens[i];
          if (Y >= tween.fromY || (Y <= tween.fromY && i == 0)){
            current = tween.current(Y);
          }
        }
        return current;
      }
    }

    var Tweener = {};

    Tweener.default = function (fromValue, toValue) {
      this.fromValue = ParseValue(fromValue);
      this.toValue = ParseValue(toValue);
    }

    Tweener.default.prototype = {
      tween: function (pct) {
        var fromValue = this.fromValue
          , toValue = this.toValue;
        return CompileValues(fromValue, toValue, pct);
      }
    }

    var Tween = function (property, fromPoint, toPoint) {
      if (!toPoint) toPoint = fromPoint;
      this.tweener = new (Tweener[property] || Tweener.default)(fromPoint.value, toPoint.value);
      this.fromY = fromPoint.Y;
      this.toY = toPoint.Y;
    }

    Tween.prototype = {
      current: function (Y) {
        var pct = 0
          , fromY = this.fromY
          , toY = this.toY;
        if (Y >= fromY && Y <= toY) {
          pct = (Y - fromY) / (toY - fromY);
        } else if (Y > toY) {
          pct = 1;
        }
        return this.tweener.tween(pct);
      }
    }

    function ParseValue (value) {
      var nums = [];
      value = new String(value).replace(RegexpValue, function (num) {
        nums.push(parseFloat(num));
        return ParseWildcard;
      });
      return [value, nums]
    }

    function CompileValues (fromValue, toValue, pct) {
      var i = 0
        , fromNum
        , toNum;
      return fromValue[0].replace(ParseWildcardRegexp, function () {
        from = fromValue[1][i];
        to = toValue[1][i];
        i++;
        return (from + ((to - from) * pct));
      });
    }

    var Style = function (component) {
      this.points = component.points;
    }

    Style.prototype = {
      current: function (Y) {
        var points = this.points
          , current = new String();
        for (var i=0; i<points.length; i++) {
          point = points[i];
          if (Y >= point.Y) current = point.value;
        }
        return current;
      }
    }

    var Point = function (Y, value) {
      this.Y = Y;
      this.value = value;
    }

    var Collection = function (object) {
      object = object || {};
      this.points = [];
      for (var Y in object) {
        this.add(Y, object[Y]);
      }
    }

    Collection.prototype = {
      add: function (Y, value) {
        var points = this.points.slice(0)
          , point = new Point(parseInt(Y), value)
          , isAdded = false;
        for (var i=0; i<this.points.length; i++) {
          if (this.points[i].Y > point.Y) {
            points.splice(i, 0, point);
            isAdded = true;
          }
        }
        if (!isAdded) points.push(point);
        this.points = points;
        return this;
      },
      merge: function (at, collection) {
        var points = collection.points
          , value;
        for (var i=0; i<points.length; i++) {
          action = points[i];
          this.add((at + action.Y), action.value);
        }
        return this;
      }
    }

    var Action = function (Klass, property, points) {
      var points = this.points = (new Collection(points)).points;
      this.max = points[points.length - 1].Y;
      this.property = property;
      this.klass = new Klass(this);
    }

    Action.prototype = {
      current: function (Y) {
        return this.klass.current(Y);
      }
    }

    function SetElementStyle (object, property, value) {
      if (object instanceof NodeList || object instanceof Array) {
        for (var i=0; i<object.length; i++) SetElementStyle(object[i], property, value);
      } else {
        object.style[property] = value;
      }
    }

    var Element = function (selector) {
      this.selector = selector;
      this.actions = {};
    }

    Element.prototype = {
      $: function () {
        var $ = this.selector;
        if ($.nodeName) {
          $ = [$];
        } else if ('string' === typeof $) {
          $ = doc.querySelectorAll($);
        }
        return $;
      },
      add: function (Y, action) {
        var property = action.property
          , collection;
        if (!(collection = this.actions[property])) collection = new Collection();
        collection.add(Y, action);
        this.actions[property] = collection;
        return this;
      },
      set: function (wY) {
        var $ = this.$()
          , actions = this.actions
          , collection, points
          , point, action, Y;
        for (var property in actions) {
          collection = actions[property];
          points = collection.points;
          for (var x=0; x<points.length; x++) {
            point = points[x];
            action = point.value;
            Y = (wY - point.Y);
            if ( (Y > 0) || (Y < 0 && x == 0) ) {
              SetElementStyle($, property, action.current(Y));
            }
          }
        }
        return this;
      },
      unset: function () {
        var actions = this.actions
          , $ = this.$();
        for (var property in actions) {
          for (var i=0; i<$.length; i++) $[i].style[property] = '';
        }
        return this;
      }
    }

    var Storyboard = function () {
      this.elements = [];
      this.max = 0;
    }

    Storyboard.prototype = {
      add: function (Y, selector, action) {
        var elements = this.elements
          , element
          , max;
        for (var i=0; i<elements.length; i++) {
          if (elements[i].selector == selector) {
            element = elements[i];
            break;
          }
        }
        if (!element) {
          element = new Element(selector);
          elements.push(element);
        }
        if (action) {
          element.add(Y, action);
          max = Y + action.max;
          if (max > this.max) this.max = max;
        }
        this.elements = elements;
        return this;
      },
      merge: function (at, storyboard) {
        var elements = storyboard.elements
          , element, actions, collection
          , points, point;
        for (var x=0; x<elements.length; x++) {
          element = elements[x];
          actions = element.actions;
          for (var property in actions) {
            collection = actions[property];
            points = collection.points;
            for (var i=0; i<points.length; i++) {
              point = points[i];
              this.add((parseInt(at) + point.Y), element.selector, point.value);
            }
          }
        }
        return this;
      },
      set: function (Y) {
        var elements = this.elements
          , element;
        for (var i=0; i<elements.length; i++) {
          element = elements[i];
          element.set(Y);
        }
      },
      unset: function () {
        var elements = this.elements
          , element;
        for (var i=0; i<elements.length; i++) {
          element = elements[i];
          element.unset();
        }
      }
    }

    function SetStoryboardFunction (storyboard) {
      return function () {
        var wY = win.pageYOffset;
        storyboard.set(wY);
      }
    }

    function SetBodyMinHeightFunction (storyboard) {
      return function () {
        SetElementStyle(doc.body, 'minHeight', ((storyboard.max + win.innerHeight) + 'px'));
      }
    }

    function AddEvent (roll, string, callback) {
      var events = string.split(' ')
        , ev;
      for (var i=0; i<events.length; i++) {
        ev = events[i];
        if (!roll.events[ev]) roll.events[ev] = [];
        roll.events[ev].push(callback);
        win.addEventListener(ev, callback);
      }
      callback();
    }

    function RemoveEvents (roll, string) {
      var events = string.split(' ')
        , ev, callbacks, callback;
      for (var x=0; x<events.length; x++) {
        ev = events[x];
        callbacks = roll.events[ev];
        for (var y=0; x<callbacks.length; x++) {
          callback = callbacks[y];
          win.removeEventListener(ev, callback);
        }
        roll.events[ev] = [];
      }
    }

    function RemoveAllEvents (roll) {
      for (var ev in roll.events) RemoveEvents(roll, ev);
      roll.events = {};
    }

    var Roll = function () {
      this.scenes = {};
      this.ats = {};
      this.events = {};
    }

    Roll.prototype = {
      add: function (name, scene) {
        if ('function' === typeof scene) {
          var fn = scene;
          scene = new Scene();
          fn(scene);
        }
        this.scenes[name] = scene;
        return this;
      },
      at: function (Y, name) {
        var ats = this.ats[Y] || [];
        ats.push(name);
        this.ats[Y] = ats;
        return this;
      },
      init: function () {
        var storyboard, names, scene;
        storyboard = this.storyboard = new Storyboard();
        for (var Y in this.ats) {
          names = this.ats[Y];
          for (var i=0; i<names.length; i++) {
            scene = this.scenes[names[i]];
            storyboard.merge(Y, scene.storyboard);
          }
        }
        this.bind();
        return this;
      },
      remove: function () {
        var storyboard;
        if (storyboard = this.storyboard) {
          storyboard.unset();
          this.storyboard = null;
        }
        SetElementStyle(doc.body, 'minHeight', '');
        this.unbind();
        return this;
      },
      bind: function () {
        if (this.storyboard) {
          AddEvent(this, 'scroll resize', SetStoryboardFunction(this.storyboard));
          AddEvent(this, 'resize', SetBodyMinHeightFunction(this.storyboard));
        }
        return this;
      },
      unbind: function () {
        RemoveAllEvents(this);
        return this;
      }
    }

    var Scene = Roll.Scene = function () {
      this.storyboard = new Storyboard();
    }

    Scene.prototype = {
      animate: function ($el, property, points) {
        return this.action(Animation, $el, property, points);
      },
      style: function ($el, property, points) {
        return this.action(Style, $el, property, points);
      },
      action: function (Klass, $el, property, points) {
        var properties;
        if ('undefined' === typeof points) {
          properties = property;
        } else {
          (properties = {})[property] = points;
        }
        for (property in properties) {
          action = new Action(Klass, property, properties[property]);
          this.storyboard.add(0, $el, action);
        }
        return this;
      }
    }

    return Roll;

  }

  if ('function' === typeof define && define.amd) {
    define(__);
  } else {
    win.Roll = __();
  };

}(window, document));
<|endoftext|>


<commit_before>import mongoose from 'mongoose';

import User from './data/Models/User/UserSchema.es6';
import Hobby from './data/Models/Hobby/HobbySchema.es6';

mongoose.connect('mongodb://localhost/test');

let hobbyCycling = new Hobby({
  title:'cycling',
  description:'a painful sport',
  type:"hobby"
});

let hobbyHorses = new Hobby({
  title:'horses',
  description:'to get in one with an animal',
  type:"hobby"
});

let hobbyFlying = new Hobby({
  title:'flying',
  description:'man and machine in one',
  type:"hobby"
});

let hobbySleeping = new Hobby({
  title:'sleeping',
  description:'resting for whole day',
  type:"hobby"
});

let userMario = new User({
  name:"Mario",
  surname:"Castro",
  age:30,
  hobbies:[hobbyCycling, hobbyFlying],
  type:"user"
});

let userUla = new User({
  name:"Ula",
  surname:"Kornowska",
  age:26,
  hobbies:[hobbyHorses, hobbySleeping],
  type:"user"
});

let userRocco = new User({
  name:"Rocco",
  surname:"Artemisa",
  age:8,
  hobbies:[hobbySleeping],
  type:"user"
});

let userOla = new User({
  name:"Ola",
  surname:"SomePolish",
  age:2,
  hobbies:[hobbySleeping, hobbyHorses],
  friends:[userMario, userUla],
  type:"user"
});

userUla.friends = [userMario, userOla, userRocco];
userMario.friends = [userUla, userOla, userRocco];
userRocco.friends = [userMario, userUla];

if(true){
  hobbyCycling.save();
  hobbyFlying.save();
  hobbyHorses.save();
  hobbySleeping.save();

  userMario.save();
  userUla.save();
  userRocco.save();
  userOla.save();
}

if(false){
  User.update({_id:"55da2995e7f5581b3698f410"}, {age:26}, (err, res) => {
    console.log(err, res);
  });
}

if(false){
  User.find({}, (err, res) => {
    console.log(res[0].id);
  });
}<commit_msg>Population script anonymized<commit_after>import mongoose from 'mongoose';

import User from './data/Models/User/UserSchema.es6';
import Hobby from './data/Models/Hobby/HobbySchema.es6';

mongoose.connect('mongodb://localhost/test');

let hobbyCycling = new Hobby({
  title:'cycling',
  description:'a painful sport',
  type:"hobby"
});

let hobbyHorses = new Hobby({
  title:'horses',
  description:'to get in one with an animal',
  type:"hobby"
});

let hobbyFlying = new Hobby({
  title:'flying',
  description:'man and machine in one',
  type:"hobby"
});

let hobbySleeping = new Hobby({
  title:'sleeping',
  description:'resting for whole day',
  type:"hobby"
});

let userRichard = new User({
  name:"Richard",
  surname:"Stallman",
  age:30,
  hobbies:[hobbyCycling, hobbyFlying],
  type:"user"
});

let userDonald = new User({
  name:"Donald",
  surname:"Knuth",
  age:26,
  hobbies:[hobbyHorses, hobbySleeping],
  type:"user"
});

let userLinus = new User({
  name:"Linux",
  surname:"Torvalds",
  age:8,
  hobbies:[hobbySleeping],
  type:"user"
});

let userTim = new User({
  name:"Tim",
  surname:"Berners-Lee",
  age:2,
  hobbies:[hobbySleeping, hobbyHorses],
  friends:[userRichard, userDonald],
  type:"user"
});

userDonald.friends = [userRichard, userTim, userLinus];
userRichard.friends = [userDonald, userTim, userLinus];
userLinus.friends = [userRichard, userDonald];

if(true){
  hobbyCycling.save();
  hobbyFlying.save();
  hobbyHorses.save();
  hobbySleeping.save();

  userRichard.save();
  userDonald.save();
  userLinus.save();
  userTim.save();
}<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

const classNames = require('classnames');
const React = require('react');
const ReactDOM = require('react-dom');

// Shamelessly ripped off Modal.js.  There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
// pass in a custom control as the actual body.

module.exports = {
    ContextualMenuContainerId: "mx_ContextualMenu_Container",

    propTypes: {
        menuWidth: React.PropTypes.number,
        menuHeight: React.PropTypes.number,
        chevronOffset: React.PropTypes.number,
        menuColour: React.PropTypes.string,
        chevronFace: React.PropTypes.string, // top, bottom, left, right
    },

    getOrCreateContainer: function() {
        let container = document.getElementById(this.ContextualMenuContainerId);

        if (!container) {
            container = document.createElement("div");
            container.id = this.ContextualMenuContainerId;
            document.body.appendChild(container);
        }

        return container;
    },

    createMenu: function(Element, props) {
        const self = this;

        const closeMenu = function(...args) {
            ReactDOM.unmountComponentAtNode(self.getOrCreateContainer());

            if (props && props.onFinished) {
                props.onFinished.apply(null, args);
            }
        };

        const position = {};
        let chevronFace = null;

        if (props.top) {
            position.top = props.top;
        } else {
            position.bottom = props.bottom;
        }

        if (props.left) {
            position.left = props.left;
            chevronFace = 'left';
        } else {
            position.right = props.right;
            chevronFace = 'right';
        }

        const chevronOffset = {};
        if (props.chevronFace) {
            chevronFace = props.chevronFace;
        }
        if (chevronFace === 'top' || chevronFace === 'bottom') {
            chevronOffset.left = props.chevronOffset;
        } else {
            chevronOffset.top = props.chevronOffset;
        }

        // To override the default chevron colour, if it's been set
        let chevronCSS = "";
        if (props.menuColour) {
            chevronCSS = `
                .mx_ContextualMenu_chevron_left:after {
                    border-right-color: ${props.menuColour};
                }
                .mx_ContextualMenu_chevron_right:after {
                    border-left-color: ${props.menuColour};
                }
                .mx_ContextualMenu_chevron_top:after {
                    border-left-color: ${props.menuColour};
                }
                .mx_ContextualMenu_chevron_bottom:after {
                    border-left-color: ${props.menuColour};
                }
            `;
        }

        const chevron =

;
        const className = 'mx_ContextualMenu_wrapper';

        const menuClasses = classNames({
            'mx_ContextualMenu': true,
            'mx_ContextualMenu_left': chevronFace === 'left',
            'mx_ContextualMenu_right': chevronFace === 'right',
            'mx_ContextualMenu_top': chevronFace === 'top',
            'mx_ContextualMenu_bottom': chevronFace === 'bottom',
        });

        const menuStyle = {};
        if (props.menuWidth) {
            menuStyle.width = props.menuWidth;
        }

        if (props.menuHeight) {
            menuStyle.height = props.menuHeight;
        }

        if (props.menuColour) {
            menuStyle["backgroundColor"] = props.menuColour;
        }

        // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
        // property set here so you can't close the menu from a button click!
        const menu = (

                    { chevron }
                    <Element {...props} onFinished={closeMenu} />

        );

        ReactDOM.render(menu, this.getOrCreateContainer());

        return {close: closeMenu};
    },
};
<commit_msg>Close context menu on resize.<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

const classNames = require('classnames');
const React = require('react');
const ReactDOM = require('react-dom');

// Shamelessly ripped off Modal.js.  There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
// pass in a custom control as the actual body.

module.exports = {
    ContextualMenuContainerId: "mx_ContextualMenu_Container",

    propTypes: {
        menuWidth: React.PropTypes.number,
        menuHeight: React.PropTypes.number,
        chevronOffset: React.PropTypes.number,
        menuColour: React.PropTypes.string,
        chevronFace: React.PropTypes.string, // top, bottom, left, right
    },

    getOrCreateContainer: function() {
        let container = document.getElementById(this.ContextualMenuContainerId);

        if (!container) {
            container = document.createElement("div");
            container.id = this.ContextualMenuContainerId;
            document.body.appendChild(container);
        }

        return container;
    },

    createMenu: function(Element, props) {
        const self = this;

        const closeMenu = function(...args) {
            ReactDOM.unmountComponentAtNode(self.getOrCreateContainer());

            if (props && props.onFinished) {
                props.onFinished.apply(null, args);
            }
        };

        // Close the menu on window resize
        const windowResize = function() {
            closeMenu();
        };

        const position = {};
        let chevronFace = null;

        if (props.top) {
            position.top = props.top;
        } else {
            position.bottom = props.bottom;
        }

        if (props.left) {
            position.left = props.left;
            chevronFace = 'left';
        } else {
            position.right = props.right;
            chevronFace = 'right';
        }

        const chevronOffset = {};
        if (props.chevronFace) {
            chevronFace = props.chevronFace;
        }
        if (chevronFace === 'top' || chevronFace === 'bottom') {
            chevronOffset.left = props.chevronOffset;
        } else {
            chevronOffset.top = props.chevronOffset;
        }

        // To override the default chevron colour, if it's been set
        let chevronCSS = "";
        if (props.menuColour) {
            chevronCSS = `
                .mx_ContextualMenu_chevron_left:after {
                    border-right-color: ${props.menuColour};
                }
                .mx_ContextualMenu_chevron_right:after {
                    border-left-color: ${props.menuColour};
                }
                .mx_ContextualMenu_chevron_top:after {
                    border-left-color: ${props.menuColour};
                }
                .mx_ContextualMenu_chevron_bottom:after {
                    border-left-color: ${props.menuColour};
                }
            `;
        }

        const chevron =

;
        const className = 'mx_ContextualMenu_wrapper';

        const menuClasses = classNames({
            'mx_ContextualMenu': true,
            'mx_ContextualMenu_left': chevronFace === 'left',
            'mx_ContextualMenu_right': chevronFace === 'right',
            'mx_ContextualMenu_top': chevronFace === 'top',
            'mx_ContextualMenu_bottom': chevronFace === 'bottom',
        });

        const menuStyle = {};
        if (props.menuWidth) {
            menuStyle.width = props.menuWidth;
        }

        if (props.menuHeight) {
            menuStyle.height = props.menuHeight;
        }

        if (props.menuColour) {
            menuStyle["backgroundColor"] = props.menuColour;
        }

        // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
        // property set here so you can't close the menu from a button click!
        const menu = (

                    { chevron }
                    <Element {...props} onFinished={closeMenu} onResize={windowResize} />

        );

        ReactDOM.render(menu, this.getOrCreateContainer());

        return {close: closeMenu};
    },
};
<|endoftext|>


<commit_before>'use strict';

var timeouts = new Set();

function isthenable (obj) {
	return obj !== undefined && obj !== null && typeof obj === 'object' && 'then' in obj;
}

function delayloop (callback, time) {
	var args = Array.prototype.slice.call(arguments, 2);
	var timeout = setTimeout(delayed, time);

	function delayed () {
		// Cleanup now-expired timeout
		if (timeout) {
			timeouts.delete(timeout);
		}
		// Call function
		callback.apply(null, args);
	}
}

// TODO: more browser-specific checks?
var nextloop = (typeof setImmediate === 'function')
	? setImmediate
	: function (callback) {
		var args = [callback, 0];
		if (arguments.length > 1) {
			args.push.apply(args, Array.prototype.slice.call(arguments, 1));
		}
		return setTimeout.apply(null, args);
	};

function iterstep (iter, func, last, res, rej, time, skip) {
	var val;

	while (!last.done) {
		try {
			val = last.value;

			// Advance loop if not in progress
			if (!skip) {
				last = iter.next(val);
				if (last.done) {
					break;
				}
				val = last.value;

				// Check for promise
				if (isthenable(val)) {
					// Set loop to resume (skipping next()) once promise resolved and break; tack on rejector as catch handler
					return val.then(function (result) {
						return iterstep(iter, func, {value: result, done: last.done}, res, rej, time, true);
					}, rej);
				}
			}
			// Officially in progress
			skip = false;

			// Call function if given
			if (func !== undefined) {
				last.value = val = func(val);

				// Check for promise (again)
				if (isthenable(val)) {
					// Set loop to resume once promise resolved and break; tack on rejector as catch handler
					return val.then(function (result) {
						return iterstep(iter, func, {value: result, done: last.done}, res, rej, time);
					}, rej);
				}
			}

			if (time > 0) {
				// Schedule next iterator step after specified delay
				return delayloop(iterstep, time, iter, func, last, res, rej, time);
			}
			else if (time == 0) {
				// Schedule next iterator step for next event loop
				return nextloop(iterstep, iter, func, last, res, rej, time);
			}
			// else continue loop and get next value
		}
		catch (e) {
			// Reject original promise
			return rej(e);
		}
	};

	if (last.done) {
		return res(last.value);
	}
}

function iterwait (iterable, iterfunc, itertime) {
	// Callable sanity check
	if (iterfunc !== undefined && typeof iterfunc !== 'function') {
		throw new Error(`Paramter 'iterfunc' must be a function or undefined`);
	}

	if (isthenable(iterable)) {
		return iterable.then(function (iter) {
			return iterwait(iter, iterfunc);
		});
	}

	var iterator = iterable[Symbol.iterator]();
	var fakeval = {value: undefined, done: false};

	return new Promise(function (resolve, reject) {
		// Schedule stepper function
		if (itertime >= 0) {
			// Iteration job requested to be delayed per-iteration, so start on next event loop
			nextloop(iterstep, iterator, iterfunc, fakeval, resolve, reject, itertime);
		}
		else {
			// Begin actually-immediately
			iterstep(iterator, iterfunc, fakeval, resolve, reject, itertime);
		}
	});
}

iterwait.timeouts = timeouts;

module.exports = iterwait;
<commit_msg>Small tweak to iterwait() in delayloop()<commit_after>'use strict';

var timeouts = new Set();

function isthenable (obj) {
	return obj !== undefined && obj !== null && typeof obj === 'object' && 'then' in obj;
}

function delayloop (callback, time, args) {
	var timeout = setTimeout(delayed, time);

	function delayed () {
		// Cleanup now-expired timeout
		if (timeout) {
			timeouts.delete(timeout);
		}
		// Call function
		callback.apply(null, args);
	}
}

// TODO: more browser-specific checks?
var nextloop = (typeof setImmediate === 'function')
	? setImmediate
	: function (callback) {
		var args = [callback, 0];
		if (arguments.length > 1) {
			args.push.apply(args, Array.prototype.slice.call(arguments, 1));
		}
		return setTimeout.apply(null, args);
	};

function iterstep (iter, func, last, res, rej, time, skip) {
	var val;

	while (!last.done) {
		try {
			val = last.value;

			// Advance loop if not in progress
			if (!skip) {
				last = iter.next(val);
				if (last.done) {
					break;
				}
				val = last.value;

				// Check for promise
				if (isthenable(val)) {
					// Set loop to resume (skipping next()) once promise resolved and break; tack on rejector as catch handler
					return val.then(function (result) {
						return iterstep(iter, func, {value: result, done: last.done}, res, rej, time, true);
					}, rej);
				}
			}
			// Officially in progress
			skip = false;

			// Call function if given
			if (func !== undefined) {
				last.value = val = func(val);

				// Check for promise (again)
				if (isthenable(val)) {
					// Set loop to resume once promise resolved and break; tack on rejector as catch handler
					return val.then(function (result) {
						return iterstep(iter, func, {value: result, done: last.done}, res, rej, time);
					}, rej);
				}
			}

			if (time > 0) {
				// Schedule next iterator step after specified delay
				return delayloop(iterstep, time, [iter, func, last, res, rej, time]);
			}
			else if (time == 0) {
				// Schedule next iterator step for next event loop
				return nextloop(iterstep, iter, func, last, res, rej, time);
			}
			// else continue loop and get next value
		}
		catch (e) {
			// Reject original promise
			return rej(e);
		}
	};

	if (last.done) {
		return res(last.value);
	}
}

function iterwait (iterable, iterfunc, itertime) {
	// Callable sanity check
	if (iterfunc !== undefined && typeof iterfunc !== 'function') {
		throw new Error(`Paramter 'iterfunc' must be a function or undefined`);
	}

	if (isthenable(iterable)) {
		return iterable.then(function (iter) {
			return iterwait(iter, iterfunc);
		});
	}

	var iterator = iterable[Symbol.iterator]();
	var fakeval = {value: undefined, done: false};

	return new Promise(function (resolve, reject) {
		// Schedule stepper function
		if (itertime >= 0) {
			// Iteration job requested to be delayed per-iteration, so start on next event loop
			nextloop(iterstep, iterator, iterfunc, fakeval, resolve, reject, itertime);
		}
		else {
			// Begin actually-immediately
			iterstep(iterator, iterfunc, fakeval, resolve, reject, itertime);
		}
	});
}

iterwait.timeouts = timeouts;

module.exports = iterwait;
<|endoftext|>


<commit_before>var User = require('../models/user_model');
var jwt = require('jsonwebtoken');

module.exports = function(secret) {
  return function(req, res, next) {
    var token = req.headers.jwt || req.body.jwt;

    var decrypted;
    jwt.verify(token, secret, function(err, decoded) {
      if (err) return res.status(403).send('access denied');
      console.log(decoded.issuer);
    });
    process.nextTick(function() {
      console.log(decrypted);
      User.findOne({'_id': decrypted.issuer}, function(err, user) {
        if (err) return res.status(403).send('access denied');
        if (!user) return res.status(403).send('access denied');

        req.user = user;
        next();
      });
    });
  };
};
<commit_msg>erro fixes >> beer<commit_after>var User = require('../models/user_model');
var jwt = require('jsonwebtoken');

module.exports = function(secret) {
  return function(req, res, next) {
    var token = req.headers.jwt || req.body.jwt;

    var decrypted;
    jwt.verify(token, secret, function(err, decoded) {
      if (err) return res.status(403).send('access denied');
      console.log(decoded.issuer);
      decrypted = decoded;
    });
    process.nextTick(function() {
      console.log(decrypted);
      User.findOne({'_id': decrypted.issuer}, function(err, user) {
        if (err) return res.status(403).send('access denied');
        if (!user) return res.status(403).send('access denied');

        req.user = user;
        next();
      });
    });
  };
};
<|endoftext|>


<commit_before>// keystore.js
// ------------------------------------------------------------------
// Copyright 2018-2021 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.
//
/* jshint esversion:9, node:true, strict:implied */

const utility     = require('./utility.js'),
      common      = require('./common.js'),
      promiseWrap = require('./promiseWrap.js'),
      fs          = require('fs'),
      request     = require('request'),
      urljoin     = require('url-join'),
      sprintf     = require('sprintf-js').sprintf;

function Keystore(conn) {  this.conn = conn; }

Keystore.prototype.get = promiseWrap(function(options, cb) {
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores/:name
  if ( ! cb) { cb = options; options = {}; }
  let conn = this.conn,
      env = (options.environment) ? (options.environment.name || options.environment) : options.environment;
  if ( ! env)  {
    return cb({error:"missing environment"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    var name = options.name || options.keystore;
    requestOptions.url = (name)?
      urljoin(conn.urlBase, 'e', env, 'keystores', name) :
      urljoin(conn.urlBase, 'e', env, 'keystores');
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('GET %s', requestOptions.url));
    }
    request.get(requestOptions, common.callback(conn, [200], cb));
  });
});

Keystore.prototype.getAlias = promiseWrap(function(options, cb) {
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores/:name/aliases
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores/:name/aliases/:alias
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore;
  if ( ! env ) {
    return cb({error:"missing environment"});
  }
  if ( ! name ) {
    return cb({error:"missing keystore name"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    requestOptions.url = urljoin(conn.urlBase, 'e', env, 'keystores', name, 'aliases');
    if (options.alias) {
      requestOptions.url = urljoin(requestOptions.url, options.alias);
    }
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('GET %s', requestOptions.url));
    }
    request.get(requestOptions, common.callback(conn, [200], cb));
  });
});

Keystore.prototype.create = promiseWrap(function(options, cb) {
  // POST :mgmtserver/v1/o/:orgname/e/:env/keystores
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore;
  if ( ! env ) {
    return cb({error:"missing environment"});
  }
  if ( ! name ) {
    return cb({error:"missing keystore name"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    requestOptions.url = urljoin(conn.urlBase, 'e', env, 'keystores');
    requestOptions.headers['content-type'] = 'application/json';
    requestOptions.body = JSON.stringify({ name : name });
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('POST %s', requestOptions.url));
    }
    request.post(requestOptions, common.callback(conn, [200, 201], cb));
  });
});

Keystore.prototype.del = promiseWrap(function(options, cb) {
  // DELETE :mgmtserver/v1/o/:orgname/e/:env/keystores/:keystore
  // Authorization: :apigee-auth
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore;
  if ( ! env ) {
    return cb({error:"missing environment"});
  }
  if ( ! name ) {
    return cb({error:"missing keystore name"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    requestOptions.url = urljoin(conn.urlBase, 'e', env, 'keystores', name);
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('DELETE %s', requestOptions.url));
    }
    request.del(requestOptions, common.callback(conn, [200], cb));
  });
});

Keystore.prototype.importCert = promiseWrap(function(options, cb) {
  // POST :mgmtserver/v1/o/:orgname/e/:env/keystores/:keystore
  // Authorization: :apigee-auth
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore,
      certData = options.certificate || options.cert;
  if ( ! certData) {
    let certFile = options.certificateFile || options.certFile;
    if (certFile) {
      certData = fs.readFileSync(certFile, 'utf8');
    }
  }
  let keyData = options.key;
  if ( ! keyData) {
    if (options.keyFile) {
      keyData = fs.readFileSync(options.keyFile, 'utf8');
    }
  }
  if ( ! env ) {
    return cb(new Error("missing environment"));
  }
  if ( ! name ) {
    return cb(new Error("missing keystore name"));
  }
  if ( ! options.alias ) {
    return cb(new Error("missing alias name"));
  }
  if ( ! certData ) {
    return cb(new Error("missing certificate"));
  }

  common.insureFreshToken(conn, function(requestOptions) {
    let rando = Math.random().toString(36).slice(2),
        boundary = 'YYY' + rando;
    requestOptions.headers['content-type'] = sprintf('multipart/form-data; boundary="%s"', boundary);
    requestOptions.headers.Accept = 'application/json';
    requestOptions.url =
      urljoin(conn.urlBase, sprintf('e/%s/keystores/%s/aliases?alias=%s&format=keycertfile',
                                    env, name, options.alias));
    // build the multipart form body
    let bodyLines = [
          '--' + boundary,
          'Content-Disposition: form-data; name="certFile"; filename="file.cert"',
          'Content-Type: application/octet-stream\r\n',
          certData
        ];
    if (keyData) {
      bodyLines.push('--' + boundary);
      bodyLines.push('Content-Disposition: form-data; name="keyFile"; filename="file.key"');
      bodyLines.push('Content-Type: application/octet-stream\r\n');
      bodyLines.push( keyData );
      if (options.keyPassword) {
        bodyLines.push('--' + boundary);
        bodyLines.push('Content-Disposition: form-data; name="password"');
        bodyLines.push(options.keyPassword);
      }
    }
    bodyLines.push('--' + boundary + '\r\n');
    requestOptions.body = bodyLines.join('\r\n');
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('POST %s', requestOptions.url));
    }
    request.post(requestOptions, common.callback(conn, [201], cb));
  });
});

module.exports = Keystore;
<commit_msg>add support for gaambo in keystore.js<commit_after>// keystore.js
// ------------------------------------------------------------------
// Copyright 2018-2021 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.
//
/* jshint esversion:9, node:true, strict:implied */

const utility     = require('./utility.js'),
      common      = require('./common.js'),
      promiseWrap = require('./promiseWrap.js'),
      fs          = require('fs'),
      request     = require('request'),
      urljoin     = require('url-join'),
      sprintf     = require('sprintf-js').sprintf;

function Keystore(conn) {  this.conn = conn; }

Keystore.prototype.get = promiseWrap(function(options, cb) {
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores/:name
  if ( ! cb) { cb = options; options = {}; }
  let conn = this.conn,
      env = (options.environment) ? (options.environment.name || options.environment) : options.environment;
  if ( ! env)  {
    return cb({error:"missing environment"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    var name = options.name || options.keystore;
    requestOptions.url = (name)?
      urljoin(conn.urlBase, 'environments', env, 'keystores', name) :
      urljoin(conn.urlBase, 'environments', env, 'keystores');
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('GET %s', requestOptions.url));
    }
    request.get(requestOptions, common.callback(conn, [200], cb));
  });
});

Keystore.prototype.getAlias = promiseWrap(function(options, cb) {
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores/:name/aliases
  // GET :mgmtserver/v1/o/:orgname/e/:env/keystores/:name/aliases/:alias
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore;
  if ( ! env ) {
    return cb({error:"missing environment"});
  }
  if ( ! name ) {
    return cb({error:"missing keystore name"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    requestOptions.url = urljoin(conn.urlBase, 'environments', env, 'keystores', name, 'aliases');
    if (options.alias) {
      requestOptions.url = urljoin(requestOptions.url, options.alias);
    }
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('GET %s', requestOptions.url));
    }
    request.get(requestOptions, common.callback(conn, [200], cb));
  });
});

Keystore.prototype.create = promiseWrap(function(options, cb) {
  // POST :mgmtserver/v1/o/:orgname/e/:env/keystores
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore;
  if ( ! env ) {
    return cb({error:"missing environment"});
  }
  if ( ! name ) {
    return cb({error:"missing keystore name"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    requestOptions.url = urljoin(conn.urlBase, 'environments', env, 'keystores');
    requestOptions.headers['content-type'] = 'application/json';
    requestOptions.body = JSON.stringify({ name : name });
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('POST %s', requestOptions.url));
    }
    request.post(requestOptions, common.callback(conn, [200, 201], cb));
  });
});

Keystore.prototype.del = promiseWrap(function(options, cb) {
  // DELETE :mgmtserver/v1/o/:orgname/e/:env/keystores/:keystore
  // Authorization: :apigee-auth
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore;
  if ( ! env ) {
    return cb({error:"missing environment"});
  }
  if ( ! name ) {
    return cb({error:"missing keystore name"});
  }
  common.insureFreshToken(conn, function(requestOptions) {
    requestOptions.url = urljoin(conn.urlBase, 'environments', env, 'keystores', name);
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('DELETE %s', requestOptions.url));
    }
    request.del(requestOptions, common.callback(conn, [200], cb));
  });
});

Keystore.prototype.importCert = promiseWrap(function(options, cb) {
  // POST :mgmtserver/v1/o/:orgname/e/:env/keystores/:keystore
  // Authorization: :apigee-auth
  let conn = this.conn,
      env = options.environment.name || options.environment,
      name = options.name || options.keystore,
      certData = options.certificate || options.cert;
  if ( ! certData) {
    let certFile = options.certificateFile || options.certFile;
    if (certFile) {
      certData = fs.readFileSync(certFile, 'utf8');
    }
  }
  let keyData = options.key;
  if ( ! keyData) {
    if (options.keyFile) {
      keyData = fs.readFileSync(options.keyFile, 'utf8');
    }
  }
  if ( ! env ) {
    return cb(new Error("missing environment"));
  }
  if ( ! name ) {
    return cb(new Error("missing keystore name"));
  }
  if ( ! options.alias ) {
    return cb(new Error("missing alias name"));
  }
  if ( ! certData ) {
    return cb(new Error("missing certificate"));
  }

  common.insureFreshToken(conn, function(requestOptions) {
    let rando = Math.random().toString(36).slice(2),
        boundary = 'YYY' + rando;
    requestOptions.headers['content-type'] = sprintf('multipart/form-data; boundary="%s"', boundary);
    requestOptions.headers.Accept = 'application/json';
    requestOptions.url =
      urljoin(conn.urlBase, sprintf('environments/%s/keystores/%s/aliases?alias=%s&format=keycertfile',
                                    env, name, options.alias));
    // build the multipart form body
    let bodyLines = [
          '--' + boundary,
          'Content-Disposition: form-data; name="certFile"; filename="file.cert"',
          'Content-Type: application/octet-stream\r\n',
          certData
        ];
    if (keyData) {
      bodyLines.push('--' + boundary);
      bodyLines.push('Content-Disposition: form-data; name="keyFile"; filename="file.key"');
      bodyLines.push('Content-Type: application/octet-stream\r\n');
      bodyLines.push( keyData );
      if (options.keyPassword) {
        bodyLines.push('--' + boundary);
        bodyLines.push('Content-Disposition: form-data; name="password"');
        bodyLines.push(options.keyPassword);
      }
    }
    bodyLines.push('--' + boundary + '\r\n');
    requestOptions.body = bodyLines.join('\r\n');
    if (conn.verbosity>0) {
      utility.logWrite(sprintf('POST %s', requestOptions.url));
    }
    request.post(requestOptions, common.callback(conn, [200, 201], cb));
  });
});

module.exports = Keystore;
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import {
  getSubredditThreadComments,
  getFieldsOfSubredditThread,
  getSubredditThreadCommentCache,
  getSubredditThreadExpandedChildren,
  getSubredditThreadCardExpandedThumbnails,
} from '../selectors/main';
import { List, Map } from 'immutable';
import ThreadComment from '../components/thread-comment';
import FetchCommentsLink from '../components/fetch-comments-link';
import ThreadCard from '../components/thread-card';
import {
  fetchSubredditThreadMoreComments,
  fetchSubredditThreadMoreRootComments,
  toggleSubredditThreadCommentExpandChildren,
  toggleSubredditThreadCardExpandThumbnail,
  deleteSubredditThreadComment,
} from '../action-creators';
import { CHILDREN_EXPANDED, THUMBNAIL_EXPANDED } from '../constants';
import { complement } from 'ramda';

const SubredditThreadComments = ({
  thread,
  threadComments,
  params,
  subredditThreadCommentCache,
  subredditThreadExpandedChildren,
  subredditThreadCardExpandedThumbnails,
  dispatch,
}) => {
  const { subreddit } = params;

  const fetchMoreComments = (linkId, children) => (
    dispatch(fetchSubredditThreadMoreComments(
      subreddit, thread.get('id'), linkId, children
    ))
  );

  const shouldExpandChildren = (commentId) => (
    subredditThreadExpandedChildren.get(commentId, CHILDREN_EXPANDED)
  );

  const toggleExpandChildren = (commentId) => (
    dispatch(toggleSubredditThreadCommentExpandChildren(
      subreddit, thread.get('id'), commentId
    ))
  );

  const toggleExpandThumbnail = () => (
    dispatch(toggleSubredditThreadCardExpandThumbnail(
      subreddit, thread.get('id'),
    ))
  );

  const shouldExpandThumbnail = () => (
    subredditThreadCardExpandedThumbnails.get(thread.get('id'), THUMBNAIL_EXPANDED) &&
    ! thread.get('is_self')
  );

  const moreComment = threadComments.find(isMore);
  const normalComments = threadComments.filter(complement(isMore));

  return (

        <ThreadCard
          shouldExpandThumbnail={shouldExpandThumbnail}
          toggleExpandThumbnail={toggleExpandThumbnail}
          thread={thread}
          subreddit={subreddit} />
        {
          thread.get('is_self')
            ?
 { thread.get('selftext') }

            : null
        }

        {
          normalComments.map((comment, i) => (
            <ThreadComment
              comment={comment}
              cache={subredditThreadCommentCache}
              key={i}
              fetchMoreComments={fetchMoreComments}
              shouldExpandChildren={shouldExpandChildren}
              toggleExpandChildren={toggleExpandChildren}/>
          ))
        }
        {
          moreComment
            ? <FetchCommentsLink
                childCount={moreComment.getIn(['data', 'count'], 0)}
                fetchComments={() => (
                  dispatch(fetchSubredditThreadMoreRootComments(
                    subreddit,
                    thread.get('id'),
                    thread.get('name'),
                    moreComment.getIn(['data', 'children'], List()).join(',')
                  )),
                  dispatch(deleteSubredditThreadComment(
                    subreddit, thread.get('id'), moreComment.getIn(['data', 'id'])
                  ))
                )} />
            : null
        }

  );
};

const isMore = (comment) => comment.get('kind') === 'more';

SubredditThreadComments.propTypes = {
  params: PropTypes.shape({
    subreddit: PropTypes.string.isRequired,
  }).isRequired,
  thread: PropTypes.instanceOf(Map).isRequired,
  threadComments: PropTypes.instanceOf(List).isRequired,
  subredditThreadCommentCache: PropTypes.instanceOf(Map).isRequired,
  subredditThreadExpandedChildren: PropTypes.instanceOf(Map).isRequired,
  subredditThreadCardExpandedThumbnails: PropTypes.instanceOf(Map).isRequired,
  dispatch: PropTypes.func.isRequired,
};

export default connect(
  (state, { params: { subreddit, thread } }) => ({
    thread: getFieldsOfSubredditThread(state, subreddit, thread, ['id', 'title', 'author', 'name', 'selftext', 'url', 'score', 'is_self', 'num_comments', 'thumbnail', 'created_utc']),
    threadComments: getSubredditThreadComments(state, subreddit, thread),
    subredditThreadCommentCache: getSubredditThreadCommentCache(state, subreddit, thread),
    subredditThreadExpandedChildren: getSubredditThreadExpandedChildren(state, subreddit, thread),
    subredditThreadCardExpandedThumbnails: getSubredditThreadCardExpandedThumbnails(state, subreddit),
  })
)(SubredditThreadComments);
<commit_msg>feat(subreddit-thread-comments): Hide body box unless 'selftext' is truthy<commit_after>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import {
  getSubredditThreadComments,
  getFieldsOfSubredditThread,
  getSubredditThreadCommentCache,
  getSubredditThreadExpandedChildren,
  getSubredditThreadCardExpandedThumbnails,
} from '../selectors/main';
import { List, Map } from 'immutable';
import ThreadComment from '../components/thread-comment';
import FetchCommentsLink from '../components/fetch-comments-link';
import ThreadCard from '../components/thread-card';
import {
  fetchSubredditThreadMoreComments,
  fetchSubredditThreadMoreRootComments,
  toggleSubredditThreadCommentExpandChildren,
  toggleSubredditThreadCardExpandThumbnail,
  deleteSubredditThreadComment,
} from '../action-creators';
import { CHILDREN_EXPANDED, THUMBNAIL_EXPANDED } from '../constants';
import { complement } from 'ramda';

const SubredditThreadComments = ({
  thread,
  threadComments,
  params,
  subredditThreadCommentCache,
  subredditThreadExpandedChildren,
  subredditThreadCardExpandedThumbnails,
  dispatch,
}) => {
  const { subreddit } = params;

  const fetchMoreComments = (linkId, children) => (
    dispatch(fetchSubredditThreadMoreComments(
      subreddit, thread.get('id'), linkId, children
    ))
  );

  const shouldExpandChildren = (commentId) => (
    subredditThreadExpandedChildren.get(commentId, CHILDREN_EXPANDED)
  );

  const toggleExpandChildren = (commentId) => (
    dispatch(toggleSubredditThreadCommentExpandChildren(
      subreddit, thread.get('id'), commentId
    ))
  );

  const toggleExpandThumbnail = () => (
    dispatch(toggleSubredditThreadCardExpandThumbnail(
      subreddit, thread.get('id'),
    ))
  );

  const shouldExpandThumbnail = () => (
    subredditThreadCardExpandedThumbnails.get(thread.get('id'), THUMBNAIL_EXPANDED) &&
    ! thread.get('is_self')
  );

  const moreComment = threadComments.find(isMore);
  const normalComments = threadComments.filter(complement(isMore));

  return (

        <ThreadCard
          shouldExpandThumbnail={shouldExpandThumbnail}
          toggleExpandThumbnail={toggleExpandThumbnail}
          thread={thread}
          subreddit={subreddit} />
        {
          thread.get('is_self') && thread.get('selftext')
            ?
 { thread.get('selftext') }

            : null
        }

        {
          normalComments.map((comment, i) => (
            <ThreadComment
              comment={comment}
              cache={subredditThreadCommentCache}
              key={i}
              fetchMoreComments={fetchMoreComments}
              shouldExpandChildren={shouldExpandChildren}
              toggleExpandChildren={toggleExpandChildren}/>
          ))
        }
        {
          moreComment
            ? <FetchCommentsLink
                childCount={moreComment.getIn(['data', 'count'], 0)}
                fetchComments={() => (
                  dispatch(fetchSubredditThreadMoreRootComments(
                    subreddit,
                    thread.get('id'),
                    thread.get('name'),
                    moreComment.getIn(['data', 'children'], List()).join(',')
                  )),
                  dispatch(deleteSubredditThreadComment(
                    subreddit, thread.get('id'), moreComment.getIn(['data', 'id'])
                  ))
                )} />
            : null
        }

  );
};

const isMore = (comment) => comment.get('kind') === 'more';

SubredditThreadComments.propTypes = {
  params: PropTypes.shape({
    subreddit: PropTypes.string.isRequired,
  }).isRequired,
  thread: PropTypes.instanceOf(Map).isRequired,
  threadComments: PropTypes.instanceOf(List).isRequired,
  subredditThreadCommentCache: PropTypes.instanceOf(Map).isRequired,
  subredditThreadExpandedChildren: PropTypes.instanceOf(Map).isRequired,
  subredditThreadCardExpandedThumbnails: PropTypes.instanceOf(Map).isRequired,
  dispatch: PropTypes.func.isRequired,
};

export default connect(
  (state, { params: { subreddit, thread } }) => ({
    thread: getFieldsOfSubredditThread(state, subreddit, thread, [
      'id', 'title', 'author', 'name', 'selftext', 'url', 'score', 'is_self',
      'num_comments', 'thumbnail', 'created_utc',
    ]),
    threadComments: getSubredditThreadComments(state, subreddit, thread),
    subredditThreadCommentCache: getSubredditThreadCommentCache(state, subreddit, thread),
    subredditThreadExpandedChildren: getSubredditThreadExpandedChildren(state, subreddit, thread),
    subredditThreadCardExpandedThumbnails: getSubredditThreadCardExpandedThumbnails(state, subreddit),
  })
)(SubredditThreadComments);
<|endoftext|>