<commit_before>/* @flow */

import React, { Component, PropTypes } from 'react';
import ReactNative from 'react-native';
import shallowCompare from 'react-addons-shallow-compare';
import ImageChooser from 'react-native-image-chooser';
import { v4 } from 'node-uuid';
import Icon from '../Core/Icon';
import GrowingTextInput from '../Core/GrowingTextInput';
import TouchFeedback from '../Core/TouchFeedback';
import ChatSuggestionsContainer from '../../containers/ChatSuggestionsContainer';
import ImageUploadContainer from '../../containers/ImageUploadContainer';
import ImageUploadChat from '../ImageUpload/ImageUploadChat';
import Colors from '../../../Colors';
import type { Text } from '../../../../lib/schemaTypes';

const {
	StyleSheet,
	View,
	PixelRatio,
} = ReactNative;

const styles = StyleSheet.create({
	container: {
		flexDirection: 'row',
		alignItems: 'stretch',
		backgroundColor: Colors.white,
		borderColor: Colors.underlay,
		borderTopWidth: 1 / PixelRatio.get(),
		elevation: 4,
	},
	inputContainer: {
		flex: 1,
		paddingHorizontal: 16,
	},
	input: {
		paddingVertical: 8,
		margin: 0,
		backgroundColor: 'transparent',
		color: Colors.black,
		fontSize: 14,
		lineHeight: 21,
	},
	iconContainer: {
		alignItems: 'center',
		justifyContent: 'center',
	},
	icon: {
		color: Colors.fadedBlack,
		margin: 17,
	},
});

type Props = {
	room: string;
	thread: string;
	user: string;
	sendMessage: Function;
}

type State = {
	nextId: string;
	text: string;
	query: ?string;
	cursor: number;
	photo: ?{
		uri: string;
		size: number;
		name: string;
		height: number;
		width: number;
	};
}

export default class ChatInput extends Component<void, Props, State> {
	static propTypes = {
		room: PropTypes.string.isRequired,
		thread: PropTypes.string.isRequired,
		user: PropTypes.string.isRequired,
		sendMessage: PropTypes.func.isRequired,
	};

	state: State = {
		nextId: v4(),
		text: '',
		query: null, // set to empty string when typing starts to render the component which makes query for texts
		photo: null,
		cursor: -1,
	};

	shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
		return shallowCompare(this, nextProps, nextState);
	}

	setQuotedText: Function = (text: Text) => {
		this._computeAndSetText({
			replyTo: text.creator,
			quotedText: text.body,
		});
	};

	setReplyTo: Function = (text: Text) => {
		this._computeAndSetText({
			replyTo: text.creator,
		});
	};

	_input: Object;

	_sendMessage = () => {
		const {
			room,
			thread,
			user,
		} = this.props;

		this.props.sendMessage({
			body: this.state.text,
			room,
			thread,
			user,
		});

		this.setState({
			text: '',
		});
	};

	_handleUploadImage = async () => {
		try {
			this.setState({
				photo: null,
			});

			const photo = await ImageChooser.pickImage();

			this.setState({
				photo,
			});
		} catch (e) {
			// Do nothing
		}
	};

	_handleUploadFinish = (result: { url: ?string; thumbnail: ?string; }) => {
		const {
			room,
			thread,
			user,
		} = this.props;
		const {
			photo,
		} = this.state;

		if (!result.url || !photo) {
			return;
		}

		const { height, width, name } = photo;
		const aspectRatio = height / width;

		this.props.sendMessage({
			id: this.state.nextId,
			room,
			thread,
			user,
			body: `${photo.name}: ${result.url}`,
			meta: {
				photo: {
					height,
					width,
					title: name,
					url: result.url,
					thumbnail_height: Math.min(480, width) * aspectRatio,
					thumbnail_width: Math.min(480, width),
					thumbnail_url: result.thumbnail,
					type: 'photo',
				},
			},
		});

		setTimeout(() => this._handleUploadClose(), 500);
	};

	_handleUploadClose = () => {
		this.setState({
			nextId: v4(),
			photo: null,
		});
	};

	_handleSuggestionSelect = (user: { id: string }) => {
		const {
			text,
			cursor,
		} = this.state;

		let message;

		if (cursor === -1) {
			message = text + ' @' + user.id + ' ';
		} else {
			let beginning = text.slice(0, cursor);
			beginning = beginning.slice(0, beginning.lastIndexOf('@'));
			message = beginning + '@' + user.id + ' ' + text.slice(cursor);
		}

		this.setState({
			text: message,
			query: '',
		});
	};

	_handleChangeText = (text: string) => {
		this.setState({
			text,
		});
	};

	_handleChangeSelection = (e: any) => {
		const { selection } = e.nativeEvent;

		if (selection && selection.start === selection.end) {
			const text = this.state.text.substring(0, selection.start);

			// match when there's a @ towards the end of the text
			// e.g. - '@', 'hey @', 'hey @s'
			if (/(\s+@|^@)[a-z0-9]?[^@^\s]*$/.test(text)) {
				const query = text.substring(text.lastIndexOf('@'));
				this.setState({
					cursor: selection.start,
					query,
				});
				return;
			}
		}

		this.setState({
			cursor: -1,
			query: '',
		});
	};

	_computeAndSetText = (opts: { quotedText?: string; replyTo?: string;}) => {
		const quotedText = opts.quotedText ? opts.quotedText.replace(/\n/g, ' ') : null;

		let newValue = this.state.text;

		if (quotedText) {
			if (newValue) {
				newValue += '\n\n';
			}

			newValue += '> ' + (opts.replyTo ? '@' + opts.replyTo + ' - ' : '') + quotedText + '\n\n';
		} else if (opts.replyTo) {
			if (newValue) {
				newValue += ' ';
			}

			newValue += `@${opts.replyTo} `;
		}

		this.setState({
			text: newValue,
		}, () => this._input.focusKeyboard());
	};

	render() {
		return (
			<View {...this.props}>
				{typeof this.state.query === 'string' ?
					<ChatSuggestionsContainer
						user={this.props.user}
						thread={this.props.thread}
						prefix={this.state.query}
						style={styles.suggestions}
						onSelect={this._handleSuggestionSelect}
					/> : null
				}

				<View style={styles.container}>
					<GrowingTextInput
						ref={c => (this._input = c)}
						value={this.state.text}
						onChangeText={this._handleChangeText}
						onSelectionChange={this._handleChangeSelection}
						underlineColorAndroid='transparent'
						placeholder='Write a message…'
						autoCapitalize='sentences'
						numberOfLines={7}
						style={styles.inputContainer}
						inputStyle={styles.input}
					/>

					<TouchFeedback
						borderless
						onPress={this.state.text ? this._sendMessage : this._handleUploadImage}
					>
						<View style={styles.iconContainer}>
							<Icon
								name={this.state.text ? 'send' : 'image'}
								style={styles.icon}
								size={24}
							/>
						</View>
					</TouchFeedback>
				</View>

				{this.state.photo ?
					<ImageUploadContainer
						component={ImageUploadChat}
						photo={this.state.photo}
						onUploadClose={this._handleUploadClose}
						onUploadFinish={this._handleUploadFinish}
						uploadOptions={{
							uploadType: 'content',
							generateThumb: true,
							textId: this.state.nextId,
						}}
					/> : null
				}
			</View>
		);
	}
}
<commit_msg>minor change<commit_after>/* @flow */

import React, { Component, PropTypes } from 'react';
import ReactNative from 'react-native';
import shallowCompare from 'react-addons-shallow-compare';
import ImageChooser from 'react-native-image-chooser';
import { v4 } from 'node-uuid';
import Icon from '../Core/Icon';
import GrowingTextInput from '../Core/GrowingTextInput';
import TouchFeedback from '../Core/TouchFeedback';
import ChatSuggestionsContainer from '../../containers/ChatSuggestionsContainer';
import ImageUploadContainer from '../../containers/ImageUploadContainer';
import ImageUploadChat from '../ImageUpload/ImageUploadChat';
import Colors from '../../../Colors';
import type { Text } from '../../../../lib/schemaTypes';

const {
	StyleSheet,
	View,
	PixelRatio,
} = ReactNative;

const styles = StyleSheet.create({
	container: {
		flexDirection: 'row',
		alignItems: 'stretch',
		backgroundColor: Colors.white,
		borderColor: Colors.underlay,
		borderTopWidth: 1 / PixelRatio.get(),
		elevation: 4,
	},
	inputContainer: {
		flex: 1,
		paddingHorizontal: 16,
	},
	input: {
		paddingVertical: 8,
		margin: 0,
		backgroundColor: 'transparent',
		color: Colors.black,
		fontSize: 14,
		lineHeight: 21,
	},
	iconContainer: {
		alignItems: 'center',
		justifyContent: 'center',
	},
	icon: {
		color: Colors.fadedBlack,
		margin: 17,
	},
});

type Props = {
	room: string;
	thread: string;
	user: string;
	sendMessage: Function;
}

type State = {
	nextId: string;
	text: string;
	query: ?string;
	cursor: number;
	photo: ?{
		uri: string;
		size: number;
		name: string;
		height: number;
		width: number;
	};
}

export default class ChatInput extends Component<void, Props, State> {
	static propTypes = {
		room: PropTypes.string.isRequired,
		thread: PropTypes.string.isRequired,
		user: PropTypes.string.isRequired,
		sendMessage: PropTypes.func.isRequired,
	};

	state: State = {
		nextId: v4(),
		text: '',
		query: null, // set to empty string when typing starts to render the component which makes query for texts
		photo: null,
		cursor: -1,
	};

	shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
		return shallowCompare(this, nextProps, nextState);
	}

	setQuotedText: Function = (text: Text) => {
		this._computeAndSetText({
			replyTo: text.creator,
			quotedText: text.body,
		});
	};

	setReplyTo: Function = (text: Text) => {
		this._computeAndSetText({
			replyTo: text.creator,
		});
	};

	_input: Object;

	_sendMessage = () => {
		const {
			room,
			thread,
			user,
		} = this.props;

		this.props.sendMessage({
			body: this.state.text,
			room,
			thread,
			user,
		});

		this.setState({
			text: '',
		});
	};

	_handleUploadImage = async () => {
		try {
			this.setState({
				photo: null,
			});

			const photo = await ImageChooser.pickImage();

			this.setState({
				photo,
			});
		} catch (e) {
			// Do nothing
		}
	};

	_handleUploadFinish = (result: { url: ?string; thumbnail: ?string; }) => {
		const {
			room,
			thread,
			user,
		} = this.props;
		const {
			photo,
		} = this.state;

		if (!result.url || !photo) {
			return;
		}

		const { height, width, name } = photo;
		const aspectRatio = height / width;

		this.props.sendMessage({
			id: this.state.nextId,
			room,
			thread,
			user,
			body: `${photo.name}: ${result.url}`,
			meta: {
				photo: {
					height,
					width,
					title: name,
					url: result.url,
					thumbnail_height: Math.min(480, width) * aspectRatio,
					thumbnail_width: Math.min(480, width),
					thumbnail_url: result.thumbnail,
					type: 'photo',
				},
			},
		});

		setTimeout(() => this._handleUploadClose(), 500);
	};

	_handleUploadClose = () => {
		this.setState({
			nextId: v4(),
			photo: null,
		});
	};

	_handleSuggestionSelect = (user: { id: string }) => {
		const {
			text,
			cursor,
		} = this.state;

		let message;

		if (cursor === -1) {
			message = text + ' @' + user.id + ' ';
		} else {
			let beginning = text.slice(0, cursor);
			beginning = beginning.slice(0, beginning.lastIndexOf('@'));
			message = beginning + '@' + user.id + ' ' + text.slice(cursor);
		}

		this.setState({
			text: message,
			query: '',
		});
	};

	_handleChangeText = (text: string) => {
		this.setState({
			text,
		});
	};

	_handleChangeSelection = (e: any) => {
		const { selection } = e.nativeEvent;

		if (selection && selection.start === selection.end) {
			const text = this.state.text.substring(0, selection.start);

			// match when there's a @ towards the end of the text
			// e.g. - '@', 'hey @', 'hey @s'
			if (/(\s+@|^@)[a-z0-9]?[^@^\s]*$/.test(text)) {
				const query = text.substring(text.lastIndexOf('@'));
				this.setState({
					cursor: selection.start,
					query,
				});
				return;
			}
		}

		this.setState({
			cursor: -1,
			query: '',
		});
	};

	_computeAndSetText = (opts: { quotedText?: string; replyTo?: string;}) => {
		const quotedText = opts.quotedText ? opts.quotedText.replace(/\n/g, ' ') : null;

		let newValue = this.state.text;

		if (quotedText) {
			if (newValue) {
				newValue += '\n\n';
			}

			newValue += '> ' + (opts.replyTo ? '@' + opts.replyTo + ' - ' : '') + quotedText + '\n\n';
		} else if (opts.replyTo) {
			if (newValue) {
				newValue += ' ';
			}

			newValue += `@${opts.replyTo} `;
		}

		this.setState({
			text: newValue,
		}, () => this._input.focusKeyboard());
	};

	render() {
		return (
			<View {...this.props}>
				{typeof this.state.query === 'string' ?
					<ChatSuggestionsContainer
						user={this.props.user}
						thread={this.props.thread}
						prefix={this.state.query}
						style={styles.suggestions}
						onSelect={this._handleSuggestionSelect}
					/> : null
				}

				<View style={styles.container}>
					<GrowingTextInput
						ref={c => (this._input = c)}
						value={this.state.text}
						onChangeText={this._handleChangeText}
						onSelectionChange={this._handleChangeSelection}
						underlineColorAndroid='transparent'
						placeholder='Write a message…'
						autoCapitalize='sentences'
						numberOfLines={7}
						style={styles.inputContainer}
						inputStyle={styles.input}
					/>

					<TouchFeedback
						borderless
						onPress={this.state.text ? this._sendMessage : this._handleUploadImage}
					>
						<View style={styles.iconContainer}>
							<Icon
								name={this.state.text ? 'send' : 'image'}
								style={styles.icon}
								size={24}
							/>
						</View>
					</TouchFeedback>
				</View>

				{this.state.photo ?
					<ImageUploadContainer
						component={ImageUploadChat}
						photo={this.state.photo}
						onUploadClose={this._handleUploadClose}
						onUploadFinish={this._handleUploadFinish}
						uploadOptions={{
							uploadType: 'content',
							generateThumb: true,
							textId: this.state.nextId,
						}}
					/> : null
				}
			</View>
		);
	}
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var utils = require('../lib/utils');

// module.exports = {
//   randomMove,
//   getDirection,
//   isVisible,
//   canKill,
//   safeRandomMove,
//   fastGetDirection,
//   turn,
//   getDistance
// };

utils.canKillSafe = (currentPlayerState = {}, enemiesStates = []) => {
    return enemiesStates.some((enemyObject) => {
        return (enemyObject.isAlive && enemyObject.ammo > 0 && utils.isVisible(currentPlayerState.position, enemyObject.position, currentPlayerState.direction));
    });
};

var gridSize, topLeft, topRight, bottomLeft, bottomRight, lastIndex, corners;
var init = function(gameEnvironment) {
    gridSize = gameEnvironment.gridSize;
    lastIndex = gridSize - 1;
    topLeft = [0, 0];
    topRight = [0, lastIndex];
    bottomLeft = [lastIndex, 0];
    bottomRight = [lastIndex, lastIndex];
    corners = [topLeft, topRight, bottomLeft, bottomRight];
};

var eql = function(pos1, pos2) {
    return pos1[0] == pos2[0] && pos1[1] == pos2[1];
}

module.exports = function() {
    var goToClosestAmmo = function(playerState, enemiesStates, gameEnvironment) {
        var closestAmmo = _.sortBy(gameEnvironment.ammoPosition, function(ammoPosition) {
            return utils.getDistance(playerState.position, ammoPosition);
        })[0];

        var direction = utils.getDirection(playerState.position, closestAmmo);
        if (playerState.direction != direction) {
            return direction;
        }

        return 'move';
    };

    var getNextPosition = function(playerState) {
        switch (playerState.direction) {
            case 'north':
                return [playerState[0], playerState[1] + 1];
            case 'west':
                return [playerState[0] - 1, playerState[1]];
            case 'south':
                return [playerState[0], playerState[1] - 1];
            case 'east':
                return [playerState[0] + 1, playerState[1]];
        }
    };

    var getWillBeKilled = function(playerState, enemiesStates) {
        var nextPosition = getNextPosition(playerState);

        return _.some(enemiesStates, function(enemyState) {
            return utils.canKillSafe(enemyState, [{
                direction: playerState.direction,
                position: nextPosition
            }]);
        });
    };

    var getClosestCorner = function(playerState, gameEnvironment) {
        var gridSize = gameEnvironment.gridSize;
        var corners = [
            [0, 0],
            [0, gridSize - 1],
            [gridSize - 1, gridSize - 1],
            [gridSize - 1, 0]
        ];

        var minDis = null;
        var closestCorner = null;

        for (var i in corners) {
            var corner = corners[i];
            var distance = utils.getDistance(playerState.position, corner);
            if (distance < minDis || minDis == null) {
                minDis = distance;
                closestCorner = corner;
            }
        }

        var direction = utils.getDirection(playerState.position, closestCorner);
        if (playerState.direction == direction) {
            return 'move';
        }

        return direction;
    };

    var atCorner = function(playerState, gameEnvironment) {
        var gridSize = gameEnvironment.gridSize;
        var corners = [
            [0, 0],
            [0, gridSize - 1],
            [gridSize - 1, gridSize - 1],
            [gridSize - 1, 0]
        ];

        return _.some(corners, function(corner) {
            return playerState.position[0] == corner[0] && playerState.position[1] == corner[1];
        });
    };

    var comeAtMeBro = function(playerState, gameEnvironment) {
        if (eql(playerState.position, topLeft)) {
            return playerState.direction == 'south' ? 'east' : 'south';
        } else if (eql(playerState.position, topRight)) {
            return playerState.direction == 'south' ? 'west' : 'south';
        } else if (eql(playerState.position, bottomLeft)) {
            return playerState.direction == 'north' ? 'east' : 'north';
        } else if (eql(playerState.position, bottomRight)) {
            return playerState.direction == 'north' ? 'west' : 'north';
        }

        throw "not at corner";
    };

    return {
        info: {
            name: 'will3',
            style: 1 // one of the 6 styles (0 to 5)
        },

        ai: function(playerState, enemiesStates, gameEnvironment) {
            init(gameEnvironment);

            if (utils.canKill(playerState, enemiesStates) && playerState.ammo > 0) {
                return 'shoot';
            }

            var canMove = !getWillBeKilled(playerState, enemiesStates);

            if (!canMove) {
                return utils.randomMove();
            }

            var move = utils.randomMove();
            if (playerState.ammo == 0 && gameEnvironment.ammoPosition.length > 0) {
                return goToClosestAmmo(playerState, enemiesStates, gameEnvironment);
            }

            if (!atCorner(playerState, gameEnvironment)) {
                return getClosestCorner(playerState, gameEnvironment);
            }

            return comeAtMeBro(playerState, gameEnvironment);
        }
    }
}();<commit_msg>will3<commit_after>var _ = require('lodash');
var utils = require('../lib/utils');

// module.exports = {
//   randomMove,
//   getDirection,
//   isVisible,
//   canKill,
//   safeRandomMove,
//   fastGetDirection,
//   turn,
//   getDistance
// };

utils.canKillSafe = (currentPlayerState = {}, enemiesStates = []) => {
    return enemiesStates.some((enemyObject) => {
        return (enemyObject.isAlive && enemyObject.ammo > 0 && utils.isVisible(currentPlayerState.position, enemyObject.position, currentPlayerState.direction));
    });
};

var getDirectionVertical = (start = [], end = []) => {
    start = start || [];
    end = end || [];

    var diffVertical = Math.abs(start[0] - end[0]);
    var diffHorizontal = Math.abs(start[1] - end[1]);

    if (diffVertical != 0) {
        return (start[0] - end[0] > 0) ? 'north' : 'south';
    }
    return (start[1] - end[1] > 0) ? 'west' : 'east';
};

var gridSize, topLeft, topRight, bottomLeft, bottomRight, lastIndex, corners;
var init = function(gameEnvironment) {
    gridSize = gameEnvironment.gridSize;
    lastIndex = gridSize - 1;
    topLeft = [0, 0];
    topRight = [0, lastIndex];
    bottomLeft = [lastIndex, 0];
    bottomRight = [lastIndex, lastIndex];
    corners = [topLeft, topRight, bottomLeft, bottomRight];
};

var eql = function(pos1, pos2) {
    return pos1[0] == pos2[0] && pos1[1] == pos2[1];
}

module.exports = function() {
    var goToClosestAmmo = function(playerState, enemiesStates, gameEnvironment) {
        var closestAmmo = _.sortBy(gameEnvironment.ammoPosition, function(ammoPosition) {
            return utils.getDistance(playerState.position, ammoPosition);
        })[0];

        var direction = getDirectionVertical(playerState.position, closestAmmo);
        if (playerState.direction != direction) {
            return direction;
        }

        return 'move';
    };

    var getNextPosition = function(playerState) {
        switch (playerState.direction) {
            case 'north':
                return [playerState[0], playerState[1] + 1];
            case 'west':
                return [playerState[0] - 1, playerState[1]];
            case 'south':
                return [playerState[0], playerState[1] - 1];
            case 'east':
                return [playerState[0] + 1, playerState[1]];
        }
    };

    var getWillBeKilled = function(playerState, enemiesStates) {
        var nextPosition = getNextPosition(playerState);

        return _.some(enemiesStates, function(enemyState) {
            return utils.canKillSafe(enemyState, [{
                direction: playerState.direction,
                position: nextPosition
            }]);
        });
    };

    var getClosestCorner = function(playerState, gameEnvironment) {
        var gridSize = gameEnvironment.gridSize;
        var corners = [
            [0, 0],
            [0, gridSize - 1],
            [gridSize - 1, gridSize - 1],
            [gridSize - 1, 0]
        ];

        var minDis = null;
        var closestCorner = null;

        for (var i in corners) {
            var corner = corners[i];
            var distance = getDirectionVertical(playerState.position, corner);
            if (distance < minDis || minDis == null) {
                minDis = distance;
                closestCorner = corner;
            }
        }

        var direction = getDirectionVertical(playerState.position, closestCorner);
        if (playerState.direction == direction) {
            return 'move';
        }

        return direction;
    };

    var atCorner = function(playerState, gameEnvironment) {
        var gridSize = gameEnvironment.gridSize;
        var corners = [
            [0, 0],
            [0, gridSize - 1],
            [gridSize - 1, gridSize - 1],
            [gridSize - 1, 0]
        ];

        return _.some(corners, function(corner) {
            return playerState.position[0] == corner[0] && playerState.position[1] == corner[1];
        });
    };

    var comeAtMeBro = function(playerState, gameEnvironment) {
        if (eql(playerState.position, topLeft)) {
            return playerState.direction == 'south' ? 'east' : 'south';
        } else if (eql(playerState.position, topRight)) {
            return playerState.direction == 'south' ? 'west' : 'south';
        } else if (eql(playerState.position, bottomLeft)) {
            return playerState.direction == 'north' ? 'east' : 'north';
        } else if (eql(playerState.position, bottomRight)) {
            return playerState.direction == 'north' ? 'west' : 'north';
        }

        throw "not at corner";
    };

    return {
        info: {
            name: 'will3',
            style: 1 // one of the 6 styles (0 to 5)
        },

        ai: function(playerState, enemiesStates, gameEnvironment) {
            init(gameEnvironment);

            if (utils.canKill(playerState, enemiesStates) && playerState.ammo > 0) {
                return 'shoot';
            }

            var canMove = !getWillBeKilled(playerState, enemiesStates);

            if (!canMove) {
                return 'north';
            }

            var move = utils.randomMove();
            if (playerState.ammo == 0 && gameEnvironment.ammoPosition.length > 0) {
                return goToClosestAmmo(playerState, enemiesStates, gameEnvironment);
            }

            if (enemiesStates.length == 1) {
                return utils.randomMove();
            }

            if (!atCorner(playerState, gameEnvironment)) {
                return getClosestCorner(playerState, gameEnvironment);
            }

            return comeAtMeBro(playerState, gameEnvironment);
        }
    }
}();<|endoftext|>


<commit_before>/*
 * Copyright 2015-2016 OpenCB
 *
 * 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.
 */

import {LitElement, html} from "lit";
import UtilsNew from "../../core/utilsNew.js";

export default class SimpleChart extends LitElement {

    constructor() {
        super();
        this.#init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            active: {
                type: Boolean
            },
            type: {
                type: String
            },
            title: {
                type: String
            },
            subtitle: {
                type: String
            },
            data: {
                type: Object
            },
            xAxisTitle: {
                type: String
            },
            yAxisTitle: {
                type: String
            },
            showButtons: {
                type: Boolean
            },
            config: {
                // This is must be a valid Highcharts configuration object
                type: Object
            }
        };
    }

    #init() {
        this._prefix = UtilsNew.randomString(8);

        // Initially we set the default config, this will be overridden if 'config' is passed
        this._config = this.getDefaultConfig();
        this.type = "column";
    }

    connectedCallback() {
        super.connectedCallback();

        this._config = {...this.getDefaultConfig(), ...this.config};
    }

    updated(changedProperties) {
        if (changedProperties.has("config")) {
            this._config = {...this.getDefaultConfig(), ...this.config};
        }

        if (changedProperties.has("type") || changedProperties.has("data") || changedProperties.has("config")) {
            if (this.type && this.data) {
                switch (this.type) {
                    case "column":
                        this.renderColumnChart();
                        break;
                    case "bar":
                        this.renderBarChart();
                        break;
                    case "pie":
                        this.renderPieChart();
                        break;
                    default:
                        throw new Error("Chart type not supported");
                }
            }
        }
    }

    renderColumnChart() {
        Highcharts.chart(this._prefix + "chart", {
            chart: {
                type: "column",
                ...this._config.chart
            },
            title: {
                text: this.title,
                ...this._config.title
            },
            subtitle: {
                text: this.subtitle,
                ...this._config.subtitle
            },
            xAxis: {
                title: {
                    text: this.xAxisTitle || ""
                },
                label: {
                    enabled: true
                },
                crosshair: true,
                ...this._config.xAxis
            },
            yAxis: {
                title: {
                    text: this.yAxisTitle || ""
                },
                min: 0,
                ...this._config.yAxis
            },
            plotOptions: {
                column: {
                    pointPadding: 0.2,
                    borderWidth: 0
                },
                ...this._config.plotOptions
            },
            series: Object.entries(this.data).map(([name, data]) => ({
                name: name,
                // TODO Proper fix after facet-result-view refactor.
                // Most of the variant stats are Maps with a single datapoint, in other cases we need an array (facets)
                data: Array.isArray(data) ? data : [data],
            })),
            credits: {
                enabled: false
            },
        });
    }

    renderBarChart() {
        Highcharts.chart(this._prefix + "chart", {
            chart: {
                type: "bar",
                ...this._config.chart,
            },
            title: {
                text: this.title,
                ...this._config.title,
            },
            subtitle: {
                text: this.subtitle,
                ...this._config.subtitle,
            },
            xAxis: {
                title: {
                    text: this.xAxisTitle || "",
                },
                label: {
                    enabled: true,
                },
                crosshair: true,
                // categories: Object.keys(this.data).map(elem => elem),
                ...this._config.xAxis,
            },
            yAxis: {
                title: {
                    text: this.yAxisTitle || "",
                },
                min: 0,
                ...this._config.yAxis,
            },
            plotOptions: {
                column: {
                    pointPadding: 0.2,
                    borderWidth: 0,
                },
                ...this._config.plotOptions,
            },
            series: Object.entries(this.data).map(([name, data]) => ({
                name: name,
                // TODO Proper fix after facet-result-view refactor.
                // Most of the variant stats are Maps with a single datapoint, in other cases we need an array (facets)
                data: Array.isArray(data) ? data : [data],
            })),
            credits: {
                enabled: false,
            },
        });
    }

    renderPieChart() {
        Highcharts.chart(this._prefix + "chart", {
            chart: {
                type: "pie",
                plotBackgroundColor: null,
                plotBorderWidth: null,
                plotShadow: false,
            },
            title: {
                text: this.title,
                ...this._config.title,
            },
            subtitle: {
                text: this.subtitle,
                ...this._config.subtitle,
            },
            accessibility: {
                point: {
                    valueSuffix: "%",
                },
            },
            plotOptions: {
                pie: {
                    allowPointSelect: true,
                    cursor: "pointer",
                    dataLabels: {
                        enabled: false,
                    },
                    showInLegend: true,
                },
                ...this._config.plotOptions,
            },
            series: [
                {
                    data: Object.entries(this.data).map(([name, data]) => ({name: name, y: data})),
                }
            ],
            credits: {
                enabled: false,
            },
        });
    }

    getDefaultConfig() {
        return {
            chart: {
                backgroundColor: {
                    // linearGradient: [0, 0, 500, 500],
                    stops: [
                        [0, "rgb(255, 255, 255)"],
                        [1, "rgb(240, 240, 255)"]
                    ]
                },
                borderWidth: 0,
                // plotBackgroundColor: "rgba(255, 255, 255, .9)",
                plotShadow: true,
                plotBorderWidth: 1
            },
        };
    }

    render() {
        return html`

        `;
    }

}

customElements.define("simple-chart", SimpleChart);
<commit_msg>wc: minor fixes in simple-chart component<commit_after>/*
 * Copyright 2015-2016 OpenCB
 *
 * 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.
 */

import {LitElement, html} from "lit";
import UtilsNew from "../../core/utilsNew.js";

export default class SimpleChart extends LitElement {

    constructor() {
        super();
        this.#init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            active: {
                type: Boolean,
            },
            type: {
                type: String,
            },
            title: {
                type: String,
            },
            subtitle: {
                type: String,
            },
            data: {
                type: Object,
            },
            xAxisTitle: {
                type: String,
            },
            yAxisTitle: {
                type: String,
            },
            showButtons: {
                type: Boolean,
            },
            config: {
                // This must be a valid Highcharts configuration object
                type: Object,
            },
        };
    }

    #init() {
        this._prefix = UtilsNew.randomString(8);

        // Initially we set the default config, this will be overridden if 'config' is passed
        this._config = this.getDefaultConfig();
        this.type = "column";
    }

    updated(changedProperties) {
        if (changedProperties.has("config")) {
            this._config = {
                ...this.getDefaultConfig(),
                ...this.config,
            };
        }

        if (changedProperties.has("type") || changedProperties.has("data") || changedProperties.has("config")) {
            if (this.type && this.data) {
                switch (this.type) {
                    case "column":
                        this.renderColumnChart();
                        break;
                    case "bar":
                        this.renderBarChart();
                        break;
                    case "pie":
                        this.renderPieChart();
                        break;
                    default:
                        throw new Error("Chart type not supported");
                }
            }
        }
    }

    renderColumnChart() {
        Highcharts.chart(this._prefix + "chart", {
            chart: {
                type: "column",
                ...this._config.chart
            },
            title: {
                text: this.title,
                ...this._config.title
            },
            subtitle: {
                text: this.subtitle,
                ...this._config.subtitle
            },
            xAxis: {
                title: {
                    text: this.xAxisTitle || ""
                },
                label: {
                    enabled: true
                },
                crosshair: true,
                ...this._config.xAxis
            },
            yAxis: {
                title: {
                    text: this.yAxisTitle || ""
                },
                min: 0,
                ...this._config.yAxis
            },
            plotOptions: {
                column: {
                    pointPadding: 0.2,
                    borderWidth: 0
                },
                ...this._config.plotOptions
            },
            series: Object.entries(this.data).map(([name, data]) => ({
                name: name,
                // TODO Proper fix after facet-result-view refactor.
                // Most of the variant stats are Maps with a single datapoint, in other cases we need an array (facets)
                data: Array.isArray(data) ? data : [data],
            })),
            credits: {
                enabled: false
            },
        });
    }

    renderBarChart() {
        Highcharts.chart(this._prefix + "chart", {
            chart: {
                type: "bar",
                ...this._config.chart,
            },
            title: {
                text: this.title,
                ...this._config.title,
            },
            subtitle: {
                text: this.subtitle,
                ...this._config.subtitle,
            },
            xAxis: {
                title: {
                    text: this.xAxisTitle || "",
                },
                label: {
                    enabled: true,
                },
                crosshair: true,
                // categories: Object.keys(this.data).map(elem => elem),
                ...this._config.xAxis,
            },
            yAxis: {
                title: {
                    text: this.yAxisTitle || "",
                },
                min: 0,
                ...this._config.yAxis,
            },
            plotOptions: {
                column: {
                    pointPadding: 0.2,
                    borderWidth: 0,
                },
                ...this._config.plotOptions,
            },
            series: Object.entries(this.data).map(([name, data]) => ({
                name: name,
                // TODO Proper fix after facet-result-view refactor.
                // Most of the variant stats are Maps with a single datapoint, in other cases we need an array (facets)
                data: Array.isArray(data) ? data : [data],
            })),
            credits: {
                enabled: false,
            },
        });
    }

    renderPieChart() {
        Highcharts.chart(this._prefix + "chart", {
            chart: {
                type: "pie",
                plotBackgroundColor: null,
                plotBorderWidth: null,
                plotShadow: false,
            },
            title: {
                text: this.title,
                ...this._config.title,
            },
            subtitle: {
                text: this.subtitle,
                ...this._config.subtitle,
            },
            accessibility: {
                point: {
                    valueSuffix: "%",
                },
            },
            plotOptions: {
                pie: {
                    allowPointSelect: true,
                    cursor: "pointer",
                    dataLabels: {
                        enabled: false,
                    },
                    showInLegend: true,
                },
                ...this._config.plotOptions,
            },
            series: [
                {
                    data: Object.entries(this.data).map(([name, data]) => ({name: name, y: data})),
                }
            ],
            credits: {
                enabled: false,
            },
        });
    }

    getDefaultConfig() {
        return {
            chart: {
                backgroundColor: {
                    // linearGradient: [0, 0, 500, 500],
                    stops: [
                        [0, "rgb(255, 255, 255)"],
                        [1, "rgb(240, 240, 255)"]
                    ]
                },
                borderWidth: 0,
                // plotBackgroundColor: "rgba(255, 255, 255, .9)",
                plotShadow: true,
                plotBorderWidth: 1
            },
        };
    }

    render() {
        return html`

        `;
    }

}

customElements.define("simple-chart", SimpleChart);
<|endoftext|>


<commit_before>/**
 * Parses the attributes an element has and sets the corresponding attributes.
 * @returns {Function}
 */
module.exports = (function () {
	var attributeParser = {},
	// Style
		DEPRECATED = "deprecated",
		EXTERNAL = "external",
		DATATYPE = "datatype",
		OBJECT = "object",
		RDF = "rdf",
		ANONYMOUS = "anonymous",
	// Representations
		FUNCTIONAL = "functional",
		INVERSE_FUNCTIONAL = "inverse functional",
		TRANSITIVE = "transitive",
		SYMMETRIC = "symmetric",
	// Attribute groups
	    VISUAL_ATTRIBUTE_GROUPS = [
		    [DEPRECATED, EXTERNAL, DATATYPE, OBJECT, RDF],
		    [ANONYMOUS]
	    ];

	/**
	 * Parses and sets the attributes of a class.
	 * @param clazz
	 */
	attributeParser.parseClassAttributes = function (clazz) {
		if (!(clazz.attributes() instanceof Array)) {
			return;
		}

		parseVisualAttributes(clazz);
		parseClassIndications(clazz);
	};

	function parseVisualAttributes(element) {
		VISUAL_ATTRIBUTE_GROUPS.forEach(function (attributeGroup) {
			setVisualAttributeOfGroup(element, attributeGroup);
		});
	}

	function setVisualAttributeOfGroup(element, group) {
		var i, l, attribute;

		for (i = 0, l = group.length; i < l; i++) {
			attribute = group[i];
			if (element.attributes().indexOf(attribute) >= 0) {
				element.visualAttributes().push(attribute);

				// Just a single attribute is possible
				break;
			}
		}
	}

	function parseClassIndications(clazz) {
		var indications = [DEPRECATED, EXTERNAL],
			i, l, indication;

		for (i = 0, l = indications.length; i < l; i++) {
			indication = indications[i];

			if (clazz.attributes().indexOf(indication) >= 0) {
				clazz.indications().push(indication);
			}
		}
	}

	/**
	 * Parses and sets the attributes of a property.
	 * @param property
	 */
	attributeParser.parsePropertyAttributes = function (property) {
		if (!(property.attributes() instanceof Array)) {
			return;
		}

		parseVisualAttributes(property);
		parsePropertyIndications(property);
	};

	function parsePropertyIndications(property) {
		var indications = [FUNCTIONAL, INVERSE_FUNCTIONAL, SYMMETRIC, TRANSITIVE],
			i, l, indication;

		for (i = 0, l = indications.length; i < l; i++) {
			indication = indications[i];

			if (property.attributes().indexOf(indication) >= 0) {
				property.indications().push(indication);
			}
		}
	}

	return function () {
		// Return a function to keep module interfaces consistent
		return attributeParser;
	};
})();
<commit_msg>Support more property axioms<commit_after>/**
 * Parses the attributes an element has and sets the corresponding attributes.
 * @returns {Function}
 */
module.exports = (function () {
	var attributeParser = {},
	// Style
		ANONYMOUS = "anonymous",
		DATATYPE = "datatype",
		DEPRECATED = "deprecated",
		EXTERNAL = "external",
		OBJECT = "object",
		RDF = "rdf",
	// Representations
		ASYMMETRIC = "asymmetric",
		FUNCTIONAL = "functional",
		INVERSE_FUNCTIONAL = "inverse functional",
		IRREFLEXIVE = "irreflexive",
		REFLEXIVE = "reflexive",
		SYMMETRIC = "symmetric",
		TRANSITIVE = "transitive",
	// Attribute groups
		VISUAL_ATTRIBUTE_GROUPS = [
			[DEPRECATED, EXTERNAL, DATATYPE, OBJECT, RDF],
			[ANONYMOUS]
		],
		CLASS_INDICATIONS = [DEPRECATED, EXTERNAL],
		PROPERTY_INDICATIONS = [ASYMMETRIC, FUNCTIONAL, INVERSE_FUNCTIONAL, IRREFLEXIVE, REFLEXIVE, SYMMETRIC,
		                        TRANSITIVE];

	/**
	 * Parses and sets the attributes of a class.
	 * @param clazz
	 */
	attributeParser.parseClassAttributes = function (clazz) {
		if (!(clazz.attributes() instanceof Array)) {
			return;
		}

		parseVisualAttributes(clazz);
		parseClassIndications(clazz);
	};

	function parseVisualAttributes(element) {
		VISUAL_ATTRIBUTE_GROUPS.forEach(function (attributeGroup) {
			setVisualAttributeOfGroup(element, attributeGroup);
		});
	}

	function setVisualAttributeOfGroup(element, group) {
		var i, l, attribute;

		for (i = 0, l = group.length; i < l; i++) {
			attribute = group[i];
			if (element.attributes().indexOf(attribute) >= 0) {
				element.visualAttributes().push(attribute);

				// Just a single attribute is possible
				break;
			}
		}
	}

	function parseClassIndications(clazz) {
		var i, l, indication;

		for (i = 0, l = CLASS_INDICATIONS.length; i < l; i++) {
			indication = CLASS_INDICATIONS[i];

			if (clazz.attributes().indexOf(indication) >= 0) {
				clazz.indications().push(indication);
			}
		}
	}

	/**
	 * Parses and sets the attributes of a property.
	 * @param property
	 */
	attributeParser.parsePropertyAttributes = function (property) {
		if (!(property.attributes() instanceof Array)) {
			return;
		}

		parseVisualAttributes(property);
		parsePropertyIndications(property);
	};

	function parsePropertyIndications(property) {
		var i, l, indication;

		for (i = 0, l = PROPERTY_INDICATIONS.length; i < l; i++) {
			indication = PROPERTY_INDICATIONS[i];

			if (property.attributes().indexOf(indication) >= 0) {
				property.indications().push(indication);
			}
		}
	}

	return function () {
		// Return a function to keep module interfaces consistent
		return attributeParser;
	};
})();
<|endoftext|>


<commit_before>// @flow

import {type Config} from 'cli-engine-config'
import Command, {Topic} from 'cli-engine-command'
import type Output from 'cli-engine-command/lib/output'
import Plugin from './plugin'
import LinkedPlugins from './linked'
import UserPlugins from './user'
import BuiltinPlugins from './builtin'
import CorePlugins from './core'
import uniqby from 'lodash.uniqby'
import Cache, {type CachedCommand, type CachedTopic} from './cache'
import Namespaces from '../namespaces'
import Lock from '../lock'

export default class Plugins {
  builtin: BuiltinPlugins
  linked: LinkedPlugins
  user: UserPlugins
  core: CorePlugins
  plugins: Plugin[]
  cache: Cache
  out: Output
  lock: Lock
  loaded: boolean
  config: Config

  constructor (output: Output) {
    this.out = output
    this.config = output.config
    this.cache = new Cache(output)

    this.builtin = new BuiltinPlugins(this)
    this.linked = new LinkedPlugins(this)
    this.user = new UserPlugins(this)
    this.core = new CorePlugins(this)
    this.lock = new Lock(this.out)
  }

  async load () {
    if (this.loaded) return
    this.plugins = await this.cache.fetchManagers(
      this.builtin,
      this.linked,
      this.user,
      this.core
    )
    this.loaded = true
  }

  get commands (): CachedCommand[] {
    let commands = []
    for (let plugin of this.plugins) {
      try {
        commands = commands.concat(plugin.commands)
      } catch (err) {
        this.out.warn(err, `error reading plugin ${plugin.name}`)
      }
    }
    return commands
  }

  async list () {
    await this.load()
    return this.plugins
  }

  isPluginInstalled (name: string): boolean {
    return !!this.plugins.find(p => p.name === name)
  }

  async findPluginWithCommand (cmd: string): Promise<?Plugin> {
    for (let plugin of await this.list()) {
      if (await plugin.findCommand(cmd)) return plugin
    }
  }

  async findCommand (cmd: string): Promise<?Class<Command<*>>> {
    for (let plugin of this.plugins) {
      if (plugin.namespace) {
        let split = cmd.split(':')
        if (plugin.namespace !== split[0]) return
        cmd = split.slice(1, split.length).join(':')
      }
      let c = await plugin.findCommand(cmd)
      if (c) return c
    }
  }

  async commandsForTopic (topic: string): Promise<Class<Command<*>>[]> {
    let commands = this.plugins.reduce((t, p) => {
      try {
        return t.concat(p.commands
          .filter(c => c.topic === topic)
          .map(c => (p.findCommand(c.id): any)))
      } catch (err) {
        this.out.warn(err, `error reading plugin ${p.name}`)
        return t
      }
    }, [])
    commands = await Promise.all(commands)
    return uniqby(commands, 'id')
  }

  async findTopic (cmd: string): Promise<?Class<Topic>> {
    if (!cmd) return
    for (let plugin of this.plugins) {
      if (plugin.namespace) {
        let split = cmd.split(':')
        if (plugin.namespace !== split[0]) return
        cmd = split.slice(1, split.length).join(':')
      }
      let t = await plugin.findTopic(cmd)
      if (t) return t
    }
  }

  findNamespaced (namespace: string): Array<Plugin> {
    return this.plugins.filter(p => p.namespace === namespace)
  }

  async install (name: string, tag: string = 'latest') {
    let downgrade = await this.lock.upgrade()

    await this.load()
    if (this.plugins.find(p => p.name === name && p.tag === tag)) throw new Error(`Plugin ${name} is already installed`)

    let path = await this.user.install(name, tag)
    this.clearCache(path)
    await downgrade()
  }

  async update () {
    if (this.user.list().length === 0) return
    this.out.action.start(`${this.config.name}: Updating plugins`)
    let downgrade = await this.lock.upgrade()
    await this.user.update()
    this.clearCache(...(await this.user.list()).map(p => p.path))
    await downgrade()
  }

  async uninstall (name: string) {
    await this.load()
    let plugin = this.plugins.filter(p => ['user', 'link'].includes(p.type)).find(p => p.name === name)
    if (!plugin) throw new Error(`${name} is not installed`)
    let downgrade = await this.lock.upgrade()
    switch (plugin.type) {
      case 'user': {
        if (!this.config.debug) this.out.action.start(`Uninstalling plugin ${name}`)
        await this.user.remove(name)
        break
      }
      case 'link': {
        if (!this.config.debug) this.out.action.start(`Unlinking plugin ${name}`)
        this.linked.remove(plugin.path)
        break
      }
    }
    this.clearCache(plugin.path)
    await downgrade()
    this.out.action.stop()
  }

  addPackageToPJSON (name: string, version: string = '*') {
    this.user.addPackageToPJSON(name, version)
  }

  async addLinkedPlugin (p: string) {
    let downgrade = await this.lock.upgrade()

    await this.load()
    let name = this.linked.checkLinked(p)

    if (this.plugins.find(p => p.type === 'user' && p.name === name)) {
      throw new Error(`${name} is already installed.\nUninstall with ${this.out.color.cmd(this.config.bin + ' plugins:uninstall ' + name)}`)
    }

    Namespaces.throwErrorIfNotPermitted(p, this.config)

    await this.linked.add(p)
    this.clearCache(p)
    await downgrade()
  }

  clearCache (...paths: string[]) {
    this.cache.deletePlugin(...paths)
  }

  get topics (): CachedTopic[] {
    return uniqby(this.plugins.reduce((t, p) => {
      const topics = p.topics.map(t => {
        if (p.namespace) return Object.assign(t, {topic: `${p.namespace}:${t.topic}`})
        return t
      })
      return t.concat(topics)
    }, []), 'topic')
  }
}
<commit_msg>let ns pass as cmd id (#249)<commit_after>// @flow

import {type Config} from 'cli-engine-config'
import Command, {Topic} from 'cli-engine-command'
import type Output from 'cli-engine-command/lib/output'
import Plugin from './plugin'
import LinkedPlugins from './linked'
import UserPlugins from './user'
import BuiltinPlugins from './builtin'
import CorePlugins from './core'
import uniqby from 'lodash.uniqby'
import Cache, {type CachedCommand, type CachedTopic} from './cache'
import Namespaces from '../namespaces'
import Lock from '../lock'

export default class Plugins {
  builtin: BuiltinPlugins
  linked: LinkedPlugins
  user: UserPlugins
  core: CorePlugins
  plugins: Plugin[]
  cache: Cache
  out: Output
  lock: Lock
  loaded: boolean
  config: Config

  constructor (output: Output) {
    this.out = output
    this.config = output.config
    this.cache = new Cache(output)

    this.builtin = new BuiltinPlugins(this)
    this.linked = new LinkedPlugins(this)
    this.user = new UserPlugins(this)
    this.core = new CorePlugins(this)
    this.lock = new Lock(this.out)
  }

  async load () {
    if (this.loaded) return
    this.plugins = await this.cache.fetchManagers(
      this.builtin,
      this.linked,
      this.user,
      this.core
    )
    this.loaded = true
  }

  get commands (): CachedCommand[] {
    let commands = []
    for (let plugin of this.plugins) {
      try {
        commands = commands.concat(plugin.commands)
      } catch (err) {
        this.out.warn(err, `error reading plugin ${plugin.name}`)
      }
    }
    return commands
  }

  async list () {
    await this.load()
    return this.plugins
  }

  isPluginInstalled (name: string): boolean {
    return !!this.plugins.find(p => p.name === name)
  }

  async findPluginWithCommand (cmd: string): Promise<?Plugin> {
    for (let plugin of await this.list()) {
      if (await plugin.findCommand(cmd)) return plugin
    }
  }

  async findCommand (cmd: string): Promise<?Class<Command<*>>> {
    for (let plugin of this.plugins) {
      let nsCmd
      if (plugin.namespace) {
        let split = cmd.split(':')
        if (plugin.namespace !== split[0]) return
        nsCmd = split.slice(1, split.length).join(':')
      }
      let c = await plugin.findCommand(nsCmd || cmd)
      if (c) return c
    }
  }

  async commandsForTopic (topic: string): Promise<Class<Command<*>>[]> {
    let commands = this.plugins.reduce((t, p) => {
      try {
        return t.concat(p.commands
          .filter(c => c.topic === topic)
          .map(c => (p.findCommand(c.id): any)))
      } catch (err) {
        this.out.warn(err, `error reading plugin ${p.name}`)
        return t
      }
    }, [])
    commands = await Promise.all(commands)
    return uniqby(commands, 'id')
  }

  async findTopic (cmd: string): Promise<?Class<Topic>> {
    if (!cmd) return
    for (let plugin of this.plugins) {
      let nsCmd
      if (plugin.namespace) {
        let split = cmd.split(':')
        if (plugin.namespace !== split[0]) return
        nsCmd = split.slice(1, split.length).join(':')
      }
      let t = await plugin.findTopic(nsCmd || cmd)
      if (t) return t
    }
  }

  findNamespaced (namespace: string): Array<Plugin> {
    return this.plugins.filter(p => p.namespace === namespace)
  }

  async install (name: string, tag: string = 'latest') {
    let downgrade = await this.lock.upgrade()

    await this.load()
    if (this.plugins.find(p => p.name === name && p.tag === tag)) throw new Error(`Plugin ${name} is already installed`)

    let path = await this.user.install(name, tag)
    this.clearCache(path)
    await downgrade()
  }

  async update () {
    if (this.user.list().length === 0) return
    this.out.action.start(`${this.config.name}: Updating plugins`)
    let downgrade = await this.lock.upgrade()
    await this.user.update()
    this.clearCache(...(await this.user.list()).map(p => p.path))
    await downgrade()
  }

  async uninstall (name: string) {
    await this.load()
    let plugin = this.plugins.filter(p => ['user', 'link'].includes(p.type)).find(p => p.name === name)
    if (!plugin) throw new Error(`${name} is not installed`)
    let downgrade = await this.lock.upgrade()
    switch (plugin.type) {
      case 'user': {
        if (!this.config.debug) this.out.action.start(`Uninstalling plugin ${name}`)
        await this.user.remove(name)
        break
      }
      case 'link': {
        if (!this.config.debug) this.out.action.start(`Unlinking plugin ${name}`)
        this.linked.remove(plugin.path)
        break
      }
    }
    this.clearCache(plugin.path)
    await downgrade()
    this.out.action.stop()
  }

  addPackageToPJSON (name: string, version: string = '*') {
    this.user.addPackageToPJSON(name, version)
  }

  async addLinkedPlugin (p: string) {
    let downgrade = await this.lock.upgrade()

    await this.load()
    let name = this.linked.checkLinked(p)

    if (this.plugins.find(p => p.type === 'user' && p.name === name)) {
      throw new Error(`${name} is already installed.\nUninstall with ${this.out.color.cmd(this.config.bin + ' plugins:uninstall ' + name)}`)
    }

    Namespaces.throwErrorIfNotPermitted(p, this.config)

    await this.linked.add(p)
    this.clearCache(p)
    await downgrade()
  }

  clearCache (...paths: string[]) {
    this.cache.deletePlugin(...paths)
  }

  get topics (): CachedTopic[] {
    return uniqby(this.plugins.reduce((t, p) => {
      const topics = p.topics.map(t => {
        if (p.namespace) return Object.assign(t, {topic: `${p.namespace}:${t.topic}`})
        return t
      })
      return t.concat(topics)
    }, []), 'topic')
  }
}
<|endoftext|>


<commit_before>var po = org.polymaps;

var loaded_tiles = 0;
var load_target = 0;

var map = po.map()
	.container(document.getElementById("map").appendChild(po.svg("svg")))
	.center({lat: 50, lon: 10})
	.zoomRange([2, 7])
	.zoom(5)
	.add(po.interact());

var geoJson_layer = (po.geoJson()
	.url("http://127.0.0.1:8080/vector_test/{Z}/{X}/{Y}.geojson") //Remember to use the ip adress rather than localhost to avoid XDomain trouble
	.on("load", po.stylist()
		.title(function(d) { return d.properties.NAME + ": " + d.properties.UN + " UN"; })
	)

	.on("load", load)
	.on("move", loadedMap)
);

map.add(geoJson_layer);

map.add(po.compass()
	.pan("none"));

var layer_container = document.getElementById("org.polymaps.1").parentNode;

function load(e) {
	for (var i = 0; i < e.features.length; i++) {
		var feature = e.features[i].data, d = feature.properties.UN;
		//console.log (feature.properties.NAME + " NR: " + d);
		e.features[i].element.setAttribute("class", "country"); //Could probably be done better
		e.features[i].element.setAttribute("fill", "blue");
		e.features[i].element.setAttribute("UN_code", d);
	}

	loaded_tiles++;
	if (loaded_tiles == load_target) {
		console.log("load target reached");
		loaded_tiles = 0;
		ConcatenateTiles ();

	}
}

//TODO: Make a more robust load-finished detection
function loadedMap(e) {

	console.log("Added " + e.added);
	console.log("Removed " + e.removed);

	if (e.added != 0) {
		load_target = e.added - e.removed;
		loaded_tiles = 0;
	}
}

function ConcatenateTiles () {

	var tiles = layer_container.lastChild.children;
	var tile;
	var segment;
	var offsets;
	var id;

	var completedFeatures = new Array();
	var tileSegments;

	for (var i = 0; i < tiles.length; i++) {

	//console.log ("tile");
	tile = tiles[i];

	//Preprare the tile for larger features
	tile.removeAttribute ("clip-path");

	offsets_dest = FindTileOffset (tile);
		for (var j = 0; j < tile.children.length; j++) {
			segment = tile.children[j]
			//console.log ("fragments");
			//console.log (segment.getAttributeNS(null,"UN_code"));

			//Getting the unique ID
			id = segment.getAttribute("UN_code");

			if (id in oc(completedFeatures)) continue;

			tileSegments = [segment];

			for (var k = i+1; k < tiles.length; k++) {
				for (var l = 0; l < tiles[k].children.length; l++) {
					if (tiles[k].children[l].getAttribute("UN_code") == id) {
						tileSegments.push (tiles[k].children[l]);
					}
				}
			}

			for (var m = 1; m <tileSegments.length; m++) {
				CombineSegments (segment, tileSegments[m], offsets_dest);
				tileSegments[m].parentNode.removeChild (tileSegments[m]);
			}

			segment.setAttribute("fill", "lightblue");
			completedFeatures.push (id);
		}
	}
}

<commit_msg>Much improved concat trigger, needs more work<commit_after>var po = org.polymaps;

var tiles_added = 0;
var tiles_loaded = 0;

var map = po.map()
	.container(document.getElementById("map").appendChild(po.svg("svg")))
	.center({lat: 50, lon: 10})
	.zoomRange([2, 7])
	.zoom(5)
	.add(po.interact());

var geoJson_layer = (po.geoJson()
	.url("http://127.0.0.1:8080/vector_test/{Z}/{X}/{Y}.geojson") //Remember to use the ip adress rather than localhost to avoid XDomain trouble
	.on("load", po.stylist()
		.title(function(d) { return d.properties.NAME + ": " + d.properties.UN + " UN"; })
	)

	.on("load", load)
	.on("added_tile", tileAdded)
);

map.add(geoJson_layer);

map.add(po.compass()
	.pan("none"));

var layer_container = document.getElementById("org.polymaps.1").parentNode;

function tileAdded (e) {
	tiles_added++;
}

function CheckTileCount () {
	if (tiles_added == tiles_loaded) ConcatenateTiles ();
}

function load(e) {
	for (var i = 0; i < e.features.length; i++) {
		var feature = e.features[i].data, d = feature.properties.UN;
		//console.log (feature.properties.NAME + " NR: " + d);
		e.features[i].element.setAttribute("class", "country"); //Could probably be done better
		e.features[i].element.setAttribute("fill", "blue");
		e.features[i].element.setAttribute("UN_code", d);
	}
  	tiles_loaded++;
  	CheckTileCount ();
}

function ConcatenateTiles () {

	var tiles = layer_container.lastChild.children;
	var tile;
	var segment;
	var offsets;
	var id;

	var completedFeatures = new Array();
	var tileSegments;

	for (var i = 0; i < tiles.length; i++) {

	//console.log ("tile");
	tile = tiles[i];

	//Preprare the tile for larger features
	tile.removeAttribute ("clip-path");

	offsets_dest = FindTileOffset (tile);
		for (var j = 0; j < tile.children.length; j++) {
			segment = tile.children[j]
			//console.log ("fragments");
			//console.log (segment.getAttributeNS(null,"UN_code"));

			//Getting the unique ID
			id = segment.getAttribute("UN_code");

			if (id in oc(completedFeatures)) continue;

			tileSegments = [segment];

			for (var k = i+1; k < tiles.length; k++) {
				for (var l = 0; l < tiles[k].children.length; l++) {
					if (tiles[k].children[l].getAttribute("UN_code") == id) {
						tileSegments.push (tiles[k].children[l]);
					}
				}
			}

			for (var m = 1; m <tileSegments.length; m++) {
				CombineSegments (segment, tileSegments[m], offsets_dest);
				tileSegments[m].parentNode.removeChild (tileSegments[m]);
			}

			segment.setAttribute("fill", "lightblue");
			completedFeatures.push (id);
		}
	}
}

<|endoftext|>


<commit_before>module.exports = function (req) {

    return [
        {
            "id": "785a9b14-a9b8-457b-a851-803d3cd1a93e",
            "name": "SABU",
            "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/sabu.jpg",
            "datetime": new Date(),
            "twitter": true,
            "facebook": true,
            "instagram": true
        },
        {
            "id": "122c1de2-4b4f-49b9-9faa-d07b30f79990",
            "name": "MATTER - EATER LAD",
            "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/matter-eater-lad.jpg",
            "datetime": new Date(),
            "twitter": true,
            "facebook": true,
            "instagram": true
        },
        {
            "id": "088b384f-6eec-4a35-be8d-d251557b1fef",
            "name": "ARM FALL OFF BOY",
            "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/arm-fall-off-boy.jpg",
            "datetime": new Date(),
            "twitter": true,
            "facebook": true,
            "instagram": true
        },
        {
            "id": "4792d5d3-dec4-42d7-b188-5e9d34a216cf",
            "name": "BOUNCING BOY",
            "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/bouncing-boy.jpg",
            "datetime": new Date(),
            "twitter": true,
            "facebook": true,
            "instagram": true
        },
        {
            "id": "d7b9e9a7-1e0c-4c3b-b73a-8f670ec4f6b1",
            "name": "SUPERDUPONT",
            "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/superdupont.jpg",
            "datetime": new Date(),
            "twitter": true,
            "facebook": true,
            "instagram": true
        },
    ];
};<commit_msg>response<commit_after>module.exports = function (context, req) {

    context.res = {
        status: 200,
        body: [
            {
                "id": "785a9b14-a9b8-457b-a851-803d3cd1a93e",
                "name": "SABU",
                "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/sabu.jpg",
                "datetime": new Date(),
                "twitter": true,
                "facebook": true,
                "instagram": true
            },
            {
                "id": "122c1de2-4b4f-49b9-9faa-d07b30f79990",
                "name": "MATTER - EATER LAD",
                "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/matter-eater-lad.jpg",
                "datetime": new Date(),
                "twitter": true,
                "facebook": true,
                "instagram": true
            },
            {
                "id": "088b384f-6eec-4a35-be8d-d251557b1fef",
                "name": "ARM FALL OFF BOY",
                "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/arm-fall-off-boy.jpg",
                "datetime": new Date(),
                "twitter": true,
                "facebook": true,
                "instagram": true
            },
            {
                "id": "4792d5d3-dec4-42d7-b188-5e9d34a216cf",
                "name": "BOUNCING BOY",
                "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/bouncing-boy.jpg",
                "datetime": new Date(),
                "twitter": true,
                "facebook": true,
                "instagram": true
            },
            {
                "id": "d7b9e9a7-1e0c-4c3b-b73a-8f670ec4f6b1",
                "name": "SUPERDUPONT",
                "picture": "http://www.weirdworm.com/img/misc/10-weird-superheroes/superdupont.jpg",
                "datetime": new Date(),
                "twitter": true,
                "facebook": true,
                "instagram": true
            },
        ]
    };

    context.done();
};<|endoftext|>


<commit_before>/**
 * Main Node file
 */
var exec = require('child_process').exec,
	watcher = require('./modules/watcher'),
	livereloader = require('./modules/livereloader'),
	utils = require('./modules/utils'),
	http = require('http'),
	waitingTheServer = true,
	INTEGRATION_TEST = global.INTEGRATION_TEST || false,
	PORT = normalizePort(process.env.STYLEGUIDE_PORT || process.env.PORT || '9241');

function waitTheServer() {
	if(waitingTheServer) {
		http.get({
			host: '127.0.0.1',
			port: PORT,
			path: '/'
		}, function(res) {
			console.log(res.statusCode);
			if(res.statusCode == 200) {
				if (!INTEGRATION_TEST) exec('echo "Done! Enjoy!" && echo "PROGRESS:100" && open "http://localhost:' + PORT + '"', utils.puts);
				if (INTEGRATION_TEST) INTEGRATION_TEST.run(PORT);
				waitingTheServer = false;

				// Files watcher
				watcher.start();
			}
			res.emit('end');
			waitTheServer();
		}).on('error', function(e) {
			// Nothing
			waitingTheServer = true;
			console.log('problem with request: ' + e.message);
			waitTheServer();
		});
	}
}

console.log('Running watch.js');

// Livereload server
livereloader.start();

// Initialize Harp
exec('cd ' + utils.basePath + '&& harp server --port ' + PORT, utils.puts);
if (!INTEGRATION_TEST) exec('echo "Starting Server on port ' + PORT + '.." && echo "PROGRESS:94"', utils.puts);
waitTheServer();

// From Express
function normalizePort(val) {
	var port = parseInt(val, 10);

	if (isNaN(port)) {
		// named pipe
		return val;
	}

	if (port >= 0) {
		// port number
		return port;
	}

	return false;
}
<commit_msg>Testing Travis for browser testing..<commit_after>/**
 * Main Node file
 */
var exec = require('child_process').exec,
	watcher = require('./modules/watcher'),
	livereloader = require('./modules/livereloader'),
	utils = require('./modules/utils'),
	http = require('http'),
	waitingTheServer = true,
	INTEGRATION_TEST = global.INTEGRATION_TEST || false,
	PORT = normalizePort(process.env.STYLEGUIDE_PORT || process.env.PORT || '9241');

function waitTheServer() {
	if(waitingTheServer) {
		http.get({
			host: '127.0.0.1',
			port: PORT,
			path: '/'
		}, function(res) {
			console.log(res.statusCode);
			if(res.statusCode == 200) {
				if (!INTEGRATION_TEST) exec('echo "Done! Enjoy!" && echo "PROGRESS:100" && open "http://localhost:' + PORT + '"', utils.puts);
				if (INTEGRATION_TEST) INTEGRATION_TEST.run(PORT);
				waitingTheServer = false;

				// Files watcher
				watcher.start();
			}
			res.emit('end');
			waitTheServer();
		}).on('error', function(e) {
			// Nothing
			waitingTheServer = true;
			console.log('problem with request: ', JSON.stringify(e));
			waitTheServer();
		});
	}
}

console.log('Running watch.js');

// Livereload server
livereloader.start();

// Initialize Harp
exec('cd ' + utils.basePath + '&& harp server --port ' + PORT, function(a,b) {
	console.log(a, b);
});
if (!INTEGRATION_TEST) exec('echo "Starting Server on port ' + PORT + '.." && echo "PROGRESS:94"', utils.puts);
waitTheServer();

// From Express
function normalizePort(val) {
	var port = parseInt(val, 10);

	if (isNaN(port)) {
		// named pipe
		return val;
	}

	if (port >= 0) {
		// port number
		return port;
	}

	return false;
}
<|endoftext|>


<commit_before>import actions from './actions';
import './marketplace';
import './provider';
import rancherNodesService from './rancher-nodes-service';
import rancherClusterNodes from './rancher-cluster-nodes';

export default module => {
  module.service('rancherNodesService', rancherNodesService);
  module.component('rancherClusterNodes', rancherClusterNodes);
  module.config(actionsConfig);
  module.config(tabsConfig);
};

// @ngInject
function actionsConfig(ActionConfigurationProvider) {
  ActionConfigurationProvider.register('Rancher.Node', actions);
}

// @ngInject
function tabsConfig(ResourceTabsConfigurationProvider, DEFAULT_RESOURCE_TABS) {
  ResourceTabsConfigurationProvider.register('Rancher.Cluster', {
    order: [
      'nodes',
      ...DEFAULT_RESOURCE_TABS.order,
    ],
    options: angular.merge({}, DEFAULT_RESOURCE_TABS.options, {
      snapshots: {
        heading: gettext('Nodes'),
        component: 'rancherClusterNodes'
      },
    })
  });
}
<commit_msg>Fix typo.<commit_after>import actions from './actions';
import './marketplace';
import './provider';
import rancherNodesService from './rancher-nodes-service';
import rancherClusterNodes from './rancher-cluster-nodes';

export default module => {
  module.service('rancherNodesService', rancherNodesService);
  module.component('rancherClusterNodes', rancherClusterNodes);
  module.config(actionsConfig);
  module.config(tabsConfig);
};

// @ngInject
function actionsConfig(ActionConfigurationProvider) {
  ActionConfigurationProvider.register('Rancher.Node', actions);
}

// @ngInject
function tabsConfig(ResourceTabsConfigurationProvider, DEFAULT_RESOURCE_TABS) {
  ResourceTabsConfigurationProvider.register('Rancher.Cluster', {
    order: [
      'nodes',
      ...DEFAULT_RESOURCE_TABS.order,
    ],
    options: angular.merge({}, DEFAULT_RESOURCE_TABS.options, {
      nodes: {
        heading: gettext('Nodes'),
        component: 'rancherClusterNodes'
      },
    })
  });
}
<|endoftext|>


<commit_before>import { combineReducers } from 'redux'
import { routeReducer } from 'redux-simple-router'
import { debug } from '../util/logging'
import { appendUniq } from './util'
import { contains, uniq, filter } from 'lodash'
import postEdits from './postEdits'
import postsByQuery from './postsByQuery'
import posts from './posts'
import projectsByQuery from './projectsByQuery'
import projects from './projects'
import projectEdits from './projectEdits'
import communities from './communities'
import { UPDATE_PATH } from 'redux-simple-router'

import {
  CANCEL_TYPEAHEAD,
  CREATE_COMMENT,
  CREATE_POST,
  FETCH_COMMENTS,
  FETCH_CURRENT_USER,
  FETCH_PEOPLE,
  FETCH_PERSON,
  FETCH_POSTS,
  FETCH_PROJECTS,
  LOGIN,
  LOGOUT,
  NAVIGATE,
  SET_LOGIN_ERROR,
  TOGGLE_MAIN_MENU,
  TYPEAHEAD,
  UPDATE_POST,
  UPLOAD_IMAGE,
  UPDATE_USER_SETTINGS,
  UPDATE_USER_SETTINGS_PENDING,
  LEAVE_COMMUNITY,
  LEAVE_COMMUNITY_PENDING
} from '../actions'

export default combineReducers({
  mainMenuOpened: (state = false, action) => {
    let { error, type } = action
    if (error) return state

    switch (type) {
      case TOGGLE_MAIN_MENU:
        return !state
      case NAVIGATE:
      case UPDATE_PATH:
        return false
    }

    return state
  },

  errors: (state = {}, action) => {
    let { error, type, payload, meta } = action
    if (!error) return state

    return {...state, [type]: {error, payload, meta}}
  },

  routing: (state = {path: '/'}, action) => {
    if (action.error) return state

    switch (action.type) {
      case LOGOUT:
        return {path: '/login'}
      case NAVIGATE:
        return {path: action.payload}
      default:
        return routeReducer(state, action)
    }
  },

  login: (state = {}, action) => {
    let { type, payload, error } = action
    switch (type) {
      case LOGIN:
        if (error) return {error: payload.message}
        return {success: true}
      case SET_LOGIN_ERROR:
        if (!payload) return {success: true}
        return {error: payload}
    }
    return state
  },

  people: (state = {}, action) => {
    let { type, error, payload, meta } = action
    if (error) {
      switch (type) {
        case UPDATE_USER_SETTINGS:
          return {
            ...state,
            current: {...state.current, ...meta.prevProps}
          }
        case LEAVE_COMMUNITY:
          return {
            ...state,
            current: {...state.current, ...meta.prevProps}
          }
        default:
          return state
      }
    }

    // the cases where there isn't a payload
    switch (type) {
      case LOGOUT:
        let currentUser = state.current
        if (!currentUser) return state

        debug('un-caching person:', currentUser.id)
        return {
          ...state,
          current: null,
          [currentUser.id]: null
        }
      case UPDATE_USER_SETTINGS_PENDING:
        return {
          ...state,
          current: {...state.current, ...meta.params}
        }
      case LEAVE_COMMUNITY_PENDING:
        let memberships = filter(state.current.memberships, m => m.community_id !== meta.communityId)
        return {
          ...state,
          current: {...state.current, ...{memberships: memberships}}
        }
    }

    if (!payload) return state

    switch (type) {
      case FETCH_PERSON:
        debug('caching person:', payload.id)
        return {
          ...state,
          [payload.id]: payload
        }
      case LOGIN:
      case FETCH_CURRENT_USER:
        debug('caching person:', payload.id)
        return {
          ...state,
          [payload.id]: payload,
          current: payload
        }
      case FETCH_PEOPLE:
        let people = payload.people.reduce((m, p) => {
          m[p.id] = p
          return m
        }, {})
        return {...state, ...people}
      case UPDATE_USER_SETTINGS:
        debug('UPDATE USER SETTINGS: ', meta)
        return {
          ...state,
          current: {...state.current, ...payload}
        }
    }

    return state
  },

  totalPostsByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_POSTS:
        return {...state, [meta.cache.id]: payload.posts_total}
    }
    return state
  },

  communities,
  posts,
  postsByQuery,
  postEdits,
  projects,
  projectsByQuery,
  projectEdits,

  pending: (state = {}, action) => {
    let { type } = action

    let toggle = targetType => {
      if (type === targetType) return {...state, [targetType]: false}
      if (type === targetType + '_PENDING') return {...state, [targetType]: true}
    }

    return toggle(FETCH_POSTS) ||
      toggle(FETCH_PEOPLE) ||
      toggle(UPLOAD_IMAGE) ||
      toggle(CREATE_POST) ||
      toggle(UPDATE_POST) ||
      toggle(FETCH_PROJECTS) ||
      state
  },

  commentsByPost: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_COMMENTS:
        if (meta.subject === 'post') {
          return appendUniq(state, meta.id, payload)
        }
        break
      case CREATE_COMMENT:
        return appendUniq(state, meta.id, [payload])
    }

    return state
  },

  typeaheadMatches: (state = {}, action) => {
    let { error, type } = action
    if (error || !contains([TYPEAHEAD, CANCEL_TYPEAHEAD], type)) return state

    let { payload, meta: { id } } = action
    switch (type) {
      case TYPEAHEAD:
        return {...state, [id]: payload}
      case CANCEL_TYPEAHEAD:
        return {...state, [id]: []}
    }

    return state
  },

  peopleByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_PEOPLE:
        let { cache } = meta
        return {
          ...state,
          [cache.id]: uniq((state[cache.id] || []).concat(payload.people.map(p => p.id)))
        }
    }
    return state
  },

  totalPeopleByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_PEOPLE:
        return {...state, [meta.cache.id]: Number(payload.people_total)}
    }
    return state
  },

  totalProjectsByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_PROJECTS:
        return {...state, [meta.cache.id]: Number(payload.projects_total)}
    }
    return state
  }
})
<commit_msg>remove debug log<commit_after>import { combineReducers } from 'redux'
import { routeReducer } from 'redux-simple-router'
import { debug } from '../util/logging'
import { appendUniq } from './util'
import { contains, uniq, filter } from 'lodash'
import postEdits from './postEdits'
import postsByQuery from './postsByQuery'
import posts from './posts'
import projectsByQuery from './projectsByQuery'
import projects from './projects'
import projectEdits from './projectEdits'
import communities from './communities'
import { UPDATE_PATH } from 'redux-simple-router'

import {
  CANCEL_TYPEAHEAD,
  CREATE_COMMENT,
  CREATE_POST,
  FETCH_COMMENTS,
  FETCH_CURRENT_USER,
  FETCH_PEOPLE,
  FETCH_PERSON,
  FETCH_POSTS,
  FETCH_PROJECTS,
  LOGIN,
  LOGOUT,
  NAVIGATE,
  SET_LOGIN_ERROR,
  TOGGLE_MAIN_MENU,
  TYPEAHEAD,
  UPDATE_POST,
  UPLOAD_IMAGE,
  UPDATE_USER_SETTINGS,
  UPDATE_USER_SETTINGS_PENDING,
  LEAVE_COMMUNITY,
  LEAVE_COMMUNITY_PENDING
} from '../actions'

export default combineReducers({
  mainMenuOpened: (state = false, action) => {
    let { error, type } = action
    if (error) return state

    switch (type) {
      case TOGGLE_MAIN_MENU:
        return !state
      case NAVIGATE:
      case UPDATE_PATH:
        return false
    }

    return state
  },

  errors: (state = {}, action) => {
    let { error, type, payload, meta } = action
    if (!error) return state

    return {...state, [type]: {error, payload, meta}}
  },

  routing: (state = {path: '/'}, action) => {
    if (action.error) return state

    switch (action.type) {
      case LOGOUT:
        return {path: '/login'}
      case NAVIGATE:
        return {path: action.payload}
      default:
        return routeReducer(state, action)
    }
  },

  login: (state = {}, action) => {
    let { type, payload, error } = action
    switch (type) {
      case LOGIN:
        if (error) return {error: payload.message}
        return {success: true}
      case SET_LOGIN_ERROR:
        if (!payload) return {success: true}
        return {error: payload}
    }
    return state
  },

  people: (state = {}, action) => {
    let { type, error, payload, meta } = action
    if (error) {
      switch (type) {
        case UPDATE_USER_SETTINGS:
          return {
            ...state,
            current: {...state.current, ...meta.prevProps}
          }
        case LEAVE_COMMUNITY:
          return {
            ...state,
            current: {...state.current, ...meta.prevProps}
          }
        default:
          return state
      }
    }

    // the cases where there isn't a payload
    switch (type) {
      case LOGOUT:
        let currentUser = state.current
        if (!currentUser) return state

        debug('un-caching person:', currentUser.id)
        return {
          ...state,
          current: null,
          [currentUser.id]: null
        }
      case UPDATE_USER_SETTINGS_PENDING:
        return {
          ...state,
          current: {...state.current, ...meta.params}
        }
      case LEAVE_COMMUNITY_PENDING:
        let memberships = filter(state.current.memberships, m => m.community_id !== meta.communityId)
        return {
          ...state,
          current: {...state.current, ...{memberships: memberships}}
        }
    }

    if (!payload) return state

    switch (type) {
      case FETCH_PERSON:
        debug('caching person:', payload.id)
        return {
          ...state,
          [payload.id]: payload
        }
      case LOGIN:
      case FETCH_CURRENT_USER:
        debug('caching person:', payload.id)
        return {
          ...state,
          [payload.id]: payload,
          current: payload
        }
      case FETCH_PEOPLE:
        let people = payload.people.reduce((m, p) => {
          m[p.id] = p
          return m
        }, {})
        return {...state, ...people}
      case UPDATE_USER_SETTINGS:
        return {
          ...state,
          current: {...state.current, ...payload}
        }
    }

    return state
  },

  totalPostsByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_POSTS:
        return {...state, [meta.cache.id]: payload.posts_total}
    }
    return state
  },

  communities,
  posts,
  postsByQuery,
  postEdits,
  projects,
  projectsByQuery,
  projectEdits,

  pending: (state = {}, action) => {
    let { type } = action

    let toggle = targetType => {
      if (type === targetType) return {...state, [targetType]: false}
      if (type === targetType + '_PENDING') return {...state, [targetType]: true}
    }

    return toggle(FETCH_POSTS) ||
      toggle(FETCH_PEOPLE) ||
      toggle(UPLOAD_IMAGE) ||
      toggle(CREATE_POST) ||
      toggle(UPDATE_POST) ||
      toggle(FETCH_PROJECTS) ||
      state
  },

  commentsByPost: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_COMMENTS:
        if (meta.subject === 'post') {
          return appendUniq(state, meta.id, payload)
        }
        break
      case CREATE_COMMENT:
        return appendUniq(state, meta.id, [payload])
    }

    return state
  },

  typeaheadMatches: (state = {}, action) => {
    let { error, type } = action
    if (error || !contains([TYPEAHEAD, CANCEL_TYPEAHEAD], type)) return state

    let { payload, meta: { id } } = action
    switch (type) {
      case TYPEAHEAD:
        return {...state, [id]: payload}
      case CANCEL_TYPEAHEAD:
        return {...state, [id]: []}
    }

    return state
  },

  peopleByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_PEOPLE:
        let { cache } = meta
        return {
          ...state,
          [cache.id]: uniq((state[cache.id] || []).concat(payload.people.map(p => p.id)))
        }
    }
    return state
  },

  totalPeopleByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_PEOPLE:
        return {...state, [meta.cache.id]: Number(payload.people_total)}
    }
    return state
  },

  totalProjectsByQuery: (state = {}, action) => {
    if (action.error) return state

    let { type, payload, meta } = action
    switch (type) {
      case FETCH_PROJECTS:
        return {...state, [meta.cache.id]: Number(payload.projects_total)}
    }
    return state
  }
})
<|endoftext|>


<commit_before>// Set up your root reducer here...
 import { combineReducers } from 'redux';
 export default combineReducers;<commit_msg>combine app reducers<commit_after> import {combineReducers} from 'redux';
 import books from './bookReducers';

 export default combineReducers({
   books: books,
 });
<|endoftext|>


<commit_before>import { combineReducers } from 'redux';
import GuessesReducer from './guessesReducer';
import AnswerReducer from './answerReducer';
import { reducer as formReducer } from 'redux-form';

const rootReducer = combineReducers({
  guesses: GuessesReducer,

  form: formReducer,
});

export default rootReducer;
<commit_msg>Remove answer reducer<commit_after>import { combineReducers } from 'redux';
import GuessesReducer from './guessesReducer';

import { reducer as formReducer } from 'redux-form';

const rootReducer = combineReducers({
  guesses: GuessesReducer,

  form: formReducer,
});

export default rootReducer;
<|endoftext|>


<commit_before>const initialState = {
  testField: 'hello hello hello',
  userList :
  [{
    name: 'Tristan',
    index: 0
  },{
    name: 'Ali',
    index: 1
  },{
    name: 'Jim-boo',
    index: 2
  }]
}

const user = (state = {}, action) => {
  switch (action.type) {
    case 'ADD_USER':
      return {
        name: action.name,
        index: action.index
      }

    default:
      return state;
  }
}

const users = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_USER':
      return {
        ...state,
        userList: [
          ...state.userList,
          user(undefined, action)
        ]
      }

    default:
      return state;
  }
}

export default users;
<commit_msg>rename user in initial state<commit_after>const initialState = {
  testField: 'hello hello hello',
  userList :
  [{
    name: 'Tristan',
    index: 0
  },{
    name: 'Ali',
    index: 1
  },{
    name: 'Snoopy',
    index: 2
  }]
}

const user = (state = {}, action) => {
  switch (action.type) {
    case 'ADD_USER':
      return {
        name: action.name,
        index: action.index
      }

    default:
      return state;
  }
}

const users = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_USER':
      return {
        ...state,
        userList: [
          ...state.userList,
          user(undefined, action)
        ]
      }

    default:
      return state;
  }
}

export default users;
<|endoftext|>


<commit_before>/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

type GraphiQLData = {
  query: ?string,
  variables: ?{[name: string]: mixed},
  operationName: ?string,
  result?: mixed
};

// Current latest version of GraphiQL.
const GRAPHIQL_VERSION = '0.7.1';

// Ensures string values are save to be used within a <script> tag.
function safeSerialize(data) {
  return data ? JSON.stringify(data).replace(/\//g, '\\/') : 'undefined';
}

/**
 * When express-graphql receives a request which does not Accept JSON, but does
 * Accept HTML, it may present GraphiQL, the in-browser GraphQL explorer IDE.
 *
 * When shown, it will be pre-populated with the result of having executed the
 * requested query.
 */
export function renderGraphiQL(data: GraphiQLData): string {
  const queryString = data.query;
  const variablesString =
    data.variables ? JSON.stringify(data.variables, null, 2) : null;
  const resultString =
    data.result ? JSON.stringify(data.result, null, 2) : null;
  const operationName = data.operationName;

  /* eslint-disable max-len */
  return `<!--
The request to this GraphQL server provided the header "Accept: text/html"
and as a result has been presented GraphiQL - an in-browser IDE for
exploring GraphQL.

If you wish to receive JSON, provide the header "Accept: application/json" or
add "&raw" to the end of the URL within a browser.
-->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>GraphiQL</title>
  <meta name="robots" content="noindex" />
  <style>
    html, body {
      height: 100%;
      margin: 0;
      overflow: hidden;
      width: 100%;
    }
  </style>
  <link href="//cdn.jsdelivr.net/graphiql/${GRAPHIQL_VERSION}/graphiql.css" rel="stylesheet" />
  <script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
  <script src="//cdn.jsdelivr.net/react/15.0.0/react.min.js"></script>
  <script src="//cdn.jsdelivr.net/react/15.0.0/react-dom.min.js"></script>
  <script src="//cdn.jsdelivr.net/graphiql/${GRAPHIQL_VERSION}/graphiql.min.js"></script>
</head>
<body>
  <script>
    // Collect the URL parameters
    var parameters = {};
    window.location.search.substr(1).split('&').forEach(function (entry) {
      var eq = entry.indexOf('=');
      if (eq >= 0) {
        parameters[decodeURIComponent(entry.slice(0, eq))] =
          decodeURIComponent(entry.slice(eq + 1));
      }
    });

    // Produce a Location query string from a parameter object.
    function locationQuery(params) {
      return '?' + Object.keys(params).map(function (key) {
        return encodeURIComponent(key) + '=' +
          encodeURIComponent(params[key]);
      }).join('&');
    }

    // Derive a fetch URL from the current URL, sans the GraphQL parameters.
    var graphqlParamNames = {
      query: true,
      variables: true,
      operationName: true
    };

    var otherParams = {};
    for (var k in parameters) {
      if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
        otherParams[k] = parameters[k];
      }
    }
    var fetchURL = locationQuery(otherParams);

    // Defines a GraphQL fetcher using the fetch API.
    function graphQLFetcher(graphQLParams) {
      return fetch(fetchURL, {
        method: 'post',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(graphQLParams),
        credentials: 'include',
      }).then(function (response) {
        return response.text();
      }).then(function (responseBody) {
        try {
          return JSON.parse(responseBody);
        } catch (error) {
          return responseBody;
        }
      });
    }

    // When the query and variables string is edited, update the URL bar so
    // that it can be easily shared.
    function onEditQuery(newQuery) {
      parameters.query = newQuery;
      updateURL();
    }

    function onEditVariables(newVariables) {
      parameters.variables = newVariables;
      updateURL();
    }

    function onEditOperationName(newOperationName) {
      parameters.operationName = newOperationName;
      updateURL();
    }

    function updateURL() {
      history.replaceState(null, null, locationQuery(parameters));
    }

    // Render <GraphiQL /> into the body.
    ReactDOM.render(
      React.createElement(GraphiQL, {
        fetcher: graphQLFetcher,
        onEditQuery: onEditQuery,
        onEditVariables: onEditVariables,
        onEditOperationName: onEditOperationName,
        query: ${safeSerialize(queryString)},
        response: ${safeSerialize(resultString)},
        variables: ${safeSerialize(variablesString)},
        operationName: ${safeSerialize(operationName)},
      }),
      document.body
    );
  </script>
</body>
</html>`;
}
<commit_msg>Update graphiql to use latest react<commit_after>/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

type GraphiQLData = {
  query: ?string,
  variables: ?{[name: string]: mixed},
  operationName: ?string,
  result?: mixed
};

// Current latest version of GraphiQL.
const GRAPHIQL_VERSION = '0.7.1';

// Ensures string values are save to be used within a <script> tag.
function safeSerialize(data) {
  return data ? JSON.stringify(data).replace(/\//g, '\\/') : 'undefined';
}

/**
 * When express-graphql receives a request which does not Accept JSON, but does
 * Accept HTML, it may present GraphiQL, the in-browser GraphQL explorer IDE.
 *
 * When shown, it will be pre-populated with the result of having executed the
 * requested query.
 */
export function renderGraphiQL(data: GraphiQLData): string {
  const queryString = data.query;
  const variablesString =
    data.variables ? JSON.stringify(data.variables, null, 2) : null;
  const resultString =
    data.result ? JSON.stringify(data.result, null, 2) : null;
  const operationName = data.operationName;

  /* eslint-disable max-len */
  return `<!--
The request to this GraphQL server provided the header "Accept: text/html"
and as a result has been presented GraphiQL - an in-browser IDE for
exploring GraphQL.

If you wish to receive JSON, provide the header "Accept: application/json" or
add "&raw" to the end of the URL within a browser.
-->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>GraphiQL</title>
  <meta name="robots" content="noindex" />
  <style>
    html, body {
      height: 100%;
      margin: 0;
      overflow: hidden;
      width: 100%;
    }
  </style>
  <link href="//cdn.jsdelivr.net/graphiql/${GRAPHIQL_VERSION}/graphiql.css" rel="stylesheet" />
  <script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
  <script src="//cdn.jsdelivr.net/react/15.3.2/react.min.js"></script>
  <script src="//cdn.jsdelivr.net/react/15.3.2/react-dom.min.js"></script>
  <script src="//cdn.jsdelivr.net/graphiql/${GRAPHIQL_VERSION}/graphiql.min.js"></script>
</head>
<body>
  <script>
    // Collect the URL parameters
    var parameters = {};
    window.location.search.substr(1).split('&').forEach(function (entry) {
      var eq = entry.indexOf('=');
      if (eq >= 0) {
        parameters[decodeURIComponent(entry.slice(0, eq))] =
          decodeURIComponent(entry.slice(eq + 1));
      }
    });

    // Produce a Location query string from a parameter object.
    function locationQuery(params) {
      return '?' + Object.keys(params).map(function (key) {
        return encodeURIComponent(key) + '=' +
          encodeURIComponent(params[key]);
      }).join('&');
    }

    // Derive a fetch URL from the current URL, sans the GraphQL parameters.
    var graphqlParamNames = {
      query: true,
      variables: true,
      operationName: true
    };

    var otherParams = {};
    for (var k in parameters) {
      if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
        otherParams[k] = parameters[k];
      }
    }
    var fetchURL = locationQuery(otherParams);

    // Defines a GraphQL fetcher using the fetch API.
    function graphQLFetcher(graphQLParams) {
      return fetch(fetchURL, {
        method: 'post',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(graphQLParams),
        credentials: 'include',
      }).then(function (response) {
        return response.text();
      }).then(function (responseBody) {
        try {
          return JSON.parse(responseBody);
        } catch (error) {
          return responseBody;
        }
      });
    }

    // When the query and variables string is edited, update the URL bar so
    // that it can be easily shared.
    function onEditQuery(newQuery) {
      parameters.query = newQuery;
      updateURL();
    }

    function onEditVariables(newVariables) {
      parameters.variables = newVariables;
      updateURL();
    }

    function onEditOperationName(newOperationName) {
      parameters.operationName = newOperationName;
      updateURL();
    }

    function updateURL() {
      history.replaceState(null, null, locationQuery(parameters));
    }

    // Render <GraphiQL /> into the body.
    ReactDOM.render(
      React.createElement(GraphiQL, {
        fetcher: graphQLFetcher,
        onEditQuery: onEditQuery,
        onEditVariables: onEditVariables,
        onEditOperationName: onEditOperationName,
        query: ${safeSerialize(queryString)},
        response: ${safeSerialize(resultString)},
        variables: ${safeSerialize(variablesString)},
        operationName: ${safeSerialize(operationName)},
      }),
      document.body
    );
  </script>
</body>
</html>`;
}
<|endoftext|>