<commit_before>import FormBuilderPropTypes from '../../FormBuilderPropTypes'
import PropTypes from 'prop-types'
import React from 'react'
import {FormBuilderInput} from '../../FormBuilderInput'
import InvalidValue from '../InvalidValue'
import MemberValue from '../../Member'

import styles from './styles/Field.css'
import {resolveTypeName} from '../../utils/resolveType'

// This component renders a single type in an object type. It emits onChange events telling the owner about the name of the type
// that changed. This gives the owner an opportunity to use the same event handler function for all of its fields
export default class Field extends React.Component {

  static propTypes = {
    field: FormBuilderPropTypes.field.isRequired,
    validation: PropTypes.shape(FormBuilderPropTypes.validation),
    value: PropTypes.any,
    onChange: PropTypes.func,
    onEnter: PropTypes.func,
    level: PropTypes.number,
    hasFocus: PropTypes.bool
  };

  static defaultProps = {
    validation: {messages: [], fields: {}},
    onEnter() {}
  };

  handleChange = event => {
    const {field, onChange} = this.props
    if (!field.type.readOnly) {
      onChange(event, field)
    }
  }

  handleEnter = event => {
    const {field, onEnter} = this.props
    onEnter(event, field)
  }

  render() {
    const {value, field, level, validation, hasFocus} = this.props

    if (typeof value !== 'undefined') {
      const expectedType = field.type.name
      const actualType = resolveTypeName(value)

      // todo: we should consider removing this, and not allow aliasing native types
      // + ensure custom object types always gets annotated with _type
      const isCompatible = actualType === field.type.jsonType

      if (expectedType !== actualType && !isCompatible) {
        return (
          <InvalidValue
            value={value}
            onChange={this.handleChange}
            validTypes={[field.type.name]}
            actualType={actualType}
          />
        )
      }
    }

    return (

        <MemberValue path={field.name}>
          <FormBuilderInput
            value={value}
            type={field.type}
            validation={validation}
            onChange={this.handleChange}
            onEnter={this.handleEnter}
            level={level}
            hasFocus={hasFocus}
          />
        </MemberValue>

    )
  }
}
<commit_msg>[form-builder] Wrap InvalidValue in fieldset<commit_after>import FormBuilderPropTypes from '../../FormBuilderPropTypes'
import PropTypes from 'prop-types'
import React from 'react'
import {FormBuilderInput} from '../../FormBuilderInput'
import InvalidValue from '../InvalidValue'
import MemberValue from '../../Member'

import styles from './styles/Field.css'
import {resolveTypeName} from '../../utils/resolveType'
import Fieldset from 'part:@sanity/components/fieldsets/default'

// This component renders a single type in an object type. It emits onChange events telling the owner about the name of the type
// that changed. This gives the owner an opportunity to use the same event handler function for all of its fields
export default class Field extends React.Component {

  static propTypes = {
    field: FormBuilderPropTypes.field.isRequired,
    validation: PropTypes.shape(FormBuilderPropTypes.validation),
    value: PropTypes.any,
    onChange: PropTypes.func,
    onEnter: PropTypes.func,
    level: PropTypes.number,
    hasFocus: PropTypes.bool
  };

  static defaultProps = {
    validation: {messages: [], fields: {}},
    onEnter() {}
  };

  handleChange = event => {
    const {field, onChange} = this.props
    if (!field.type.readOnly) {
      onChange(event, field)
    }
  }

  handleEnter = event => {
    const {field, onEnter} = this.props
    onEnter(event, field)
  }

  render() {
    const {value, field, level, validation, hasFocus} = this.props

    if (typeof value !== 'undefined') {
      const expectedType = field.type.name
      const actualType = resolveTypeName(value)

      // todo: we should consider removing this, and not allow aliasing native types
      // + ensure custom object types always gets annotated with _type
      const isCompatible = actualType === field.type.jsonType

      if (expectedType !== actualType && !isCompatible) {
        return (
          <Fieldset legend={field.type.title} level={level}>
            <InvalidValue
              value={value}
              onChange={this.handleChange}
              validTypes={[field.type.name]}
              actualType={actualType}
            />
          </Fieldset>
        )
      }
    }

    return (

        <MemberValue path={field.name}>
          <FormBuilderInput
            value={value}
            type={field.type}
            validation={validation}
            onChange={this.handleChange}
            onEnter={this.handleEnter}
            level={level}
            hasFocus={hasFocus}
          />
        </MemberValue>

    )
  }
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const webpack = require('atool-build/lib/webpack');
const getConfig = require('./get-config');
const resolvePlugins = require('./resolve-plugins');
const bishengLib = path.join(__dirname, '..');
const bishengLibLoaders = path.join(bishengLib, 'loaders');

module.exports = function updateWebpackConfig(webpackConfig, configFile, isBuild) {
  const config = getConfig(configFile);

  /* eslint-disable no-param-reassign */
  webpackConfig.entry = {};
  if (isBuild) {
    webpackConfig.output.path = config.output;
  }
  webpackConfig.output.publicPath = isBuild ? config.root : '/';
  webpackConfig.module.loaders.push({
    test(filename) {
      return filename === path.join(bishengLib, 'utils', 'data.js') ||
        filename === path.join(bishengLib, 'utils', 'ssr-data.js');
    },
    loader: `${path.join(bishengLibLoaders, 'bisheng-data-loader')}` +
      `?config=${configFile}&isBuild=${isBuild}`,
  });

  webpackConfig.module.loaders.push({
    test: /\.md$/,
    exclude: /node_modules/,
    loaders: [
      `${path.join(bishengLibLoaders, 'markdown-loader')}` +
        `?config=${configFile}&isBuild=${isBuild}`,
    ],
  });
  /* eslint-enable no-param-reassign */

  const pluginsConfig = resolvePlugins(config.plugins, 'config');
  pluginsConfig.forEach((pluginConfig) => {
    require(pluginConfig[0])(pluginConfig[1]).webpackConfig(webpackConfig, webpack);
  });

  const customizedWebpackConfig = config.webpackConfig(webpackConfig, webpack);

  const entryPath = path.join(bishengLib, '..', 'tmp', 'entry.' + config.entryName + '.js');
  if (customizedWebpackConfig.entry[config.entryName]) {
    throw new Error('Should not set `webpackConfig.entry.' + config.entryName + '`!');
  }
  customizedWebpackConfig.entry[config.entryName] = entryPath;
  return customizedWebpackConfig;
};
<commit_msg>feat: remove plugin/config<commit_after>'use strict';

const path = require('path');
const webpack = require('atool-build/lib/webpack');
const getConfig = require('./get-config');
const bishengLib = path.join(__dirname, '..');
const bishengLibLoaders = path.join(bishengLib, 'loaders');

module.exports = function updateWebpackConfig(webpackConfig, configFile, isBuild) {
  const config = getConfig(configFile);

  /* eslint-disable no-param-reassign */
  webpackConfig.entry = {};
  if (isBuild) {
    webpackConfig.output.path = config.output;
  }
  webpackConfig.output.publicPath = isBuild ? config.root : '/';
  webpackConfig.module.loaders.push({
    test(filename) {
      return filename === path.join(bishengLib, 'utils', 'data.js') ||
        filename === path.join(bishengLib, 'utils', 'ssr-data.js');
    },
    loader: `${path.join(bishengLibLoaders, 'bisheng-data-loader')}` +
      `?config=${configFile}&isBuild=${isBuild}`,
  });

  webpackConfig.module.loaders.push({
    test: /\.md$/,
    exclude: /node_modules/,
    loaders: [
      `${path.join(bishengLibLoaders, 'markdown-loader')}` +
        `?config=${configFile}&isBuild=${isBuild}`,
    ],
  });
  /* eslint-enable no-param-reassign */

  const customizedWebpackConfig = config.webpackConfig(webpackConfig, webpack);

  const entryPath = path.join(bishengLib, '..', 'tmp', 'entry.' + config.entryName + '.js');
  if (customizedWebpackConfig.entry[config.entryName]) {
    throw new Error('Should not set `webpackConfig.entry.' + config.entryName + '`!');
  }
  customizedWebpackConfig.entry[config.entryName] = entryPath;
  return customizedWebpackConfig;
};
<|endoftext|>


<commit_before>import React from "react-native";
import EvilIcons from "react-native-vector-icons/EvilIcons";
import Colors from "../../Colors.json";
import AppText from "./AppText";
import AppTextInput from "./AppTextInput";
import StatusbarContainer from "./StatusbarContainer";
import AppbarSecondary from "./AppbarSecondary";
import AppbarTouchable from "./AppbarTouchable";
import AppbarIcon from "./AppbarIcon";
import GrowingTextInput from "./GrowingTextInput";
import TouchFeedback from "./TouchFeedback";
import Icon from "./Icon";
import UserIconContainer from "../containers/UserIconContainer";
import ImageUploadContainer from "../containers/ImageUploadContainer";
import Banner from "./Banner";
import ImageUploadDiscussion from "./ImageUploadDiscussion";
import ImageChooser from "../modules/ImageChooser";
import textUtils from "../lib/text-utils";

const {
	AsyncStorage,
	TouchableOpacity,
	StyleSheet,
	NavigationActions,
	ScrollView,
	View
} = React;

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: Colors.white
	},
	scene: {
		paddingHorizontal: 8,
		paddingVertical: 16
	},
	threadTitle: {
		fontWeight: "bold",
		fontSize: 20,
		lineHeight: 30
	},
	threadSummary: {
		fontSize: 16,
		lineHeight: 24,
		marginVertical: 8
	},
	icon: {
		color: Colors.fadedBlack
	},
	disabled: {
		opacity: 0.5
	},
	userIcon: {
		margin: 12
	},
	entry: {
		paddingVertical: 4,
		paddingHorizontal: 12
	},
	uploadButtonIcon: {
		color: Colors.fadedBlack,
		marginHorizontal: 16,
		marginVertical: 14
	},
	uploadButtonIconActive: {
		color: Colors.info
	},
	footer: {
		flexDirection: "row",
		justifyContent: "space-between",
		borderTopColor: Colors.separator,
		borderTopWidth: 1
	},
	postButton: {
		backgroundColor: Colors.info,
		margin: 6,
		width: 100,
		borderRadius: 3
	},
	postButtonInner: {
		paddingVertical: 10,
		paddingHorizontal: 16
	},
	postButtonText: {
		color: Colors.white,
		fontWeight: "bold",
		textAlign: "center"
	},
	socialItem: {
		flexDirection: "row",
		alignItems: "center"
	},
	socialIconContainer: {
		height: 24,
		width: 24,
		marginHorizontal: 12,
		marginVertical: 8,
		alignItems: "center",
		justifyContent: "center",
		backgroundColor: Colors.grey,
		borderRadius: 2
	},
	socialIconContainerSelected: {
		backgroundColor: Colors.facebook
	},
	socialIcon: {
		fontSize: 24,
		borderRadius: 12,
		color: Colors.white
	},
	socialTextSelected: {
		color: Colors.facebook,
		fontWeight: "bold"
	},
	socialTip: {
		margin: 12,
		fontSize: 12,
		color: Colors.grey
	}
});

const FACEBOOK_SHARE_CHECKED_KEY = "start_discussion_facebook_share_checked";

export default class StartDiscussionButton extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			title: "",
			text: "",
			imageData: null,
			uploadResult: null,
			status: null,
			error: null,
			shareOnFacebook: false
		};
	}

	componentDidMount() {
		this._setShareCheckbox();
	}

	_handleSharePress = () => {
		requestAnimationFrame(async () => {
			let shareOnFacebook = !this.state.shareOnFacebook;

			if (shareOnFacebook) {
				try {
					await this.props.requestFacebookPermissions();
				} catch (err) {
					shareOnFacebook = false;
				}
			}

			this.setState({
				shareOnFacebook
			});

			AsyncStorage.setItem(FACEBOOK_SHARE_CHECKED_KEY, JSON.stringify(shareOnFacebook));
		});
	};

	_setShareCheckbox = async () => {
		let shareOnFacebook;

		try {
			const isEnabled = JSON.parse(await AsyncStorage.getItem(FACEBOOK_SHARE_CHECKED_KEY));

			if (isEnabled) {
				const granted = await this.props.isFacebookPermissionGranted();

				shareOnFacebook = granted;
			} else {
				shareOnFacebook = false;
			}
		} catch (err) {
			shareOnFacebook = false;
		}

		this.setState({
			shareOnFacebook
		});
	};

	_handleLoading = () => {
		this.setState({
			status: "loading"
		});
	};

	_handlePosted = thread => {
		this.props.onNavigation(new NavigationActions.Push({
			name: "chat",
			props: {
				thread: thread.id,
				room: this.props.room
			}
		}));
	};

	_handleError = message => {
		this.setState({
			error: message,
			status: null
		});
	};

	_postDiscussion = async () => {
		const FAIL_MESSAGE = "An error occurred while posting";
		const SHORT_TITLE_MESSAGE = "Title needs be at least 2 words";
		const LONG_TITLE_MESSAGE = "Title needs be less than 10 words";
		const NO_TITLE_MESSAGE = "Enter a title in 2 to 10 words";
		const NO_SUMMARY_MESSAGE = "Enter a short summary";

		if (!this.state.title) {
			this._handleError(NO_TITLE_MESSAGE);
			return;
		}

		const words = this.state.title.trim().split(/\s+/);

		if (words.length < 2) {
			this._handleError(SHORT_TITLE_MESSAGE);
			return;
		} else if (words.length > 10) {
			this._handleError(LONG_TITLE_MESSAGE);
			return;
		}

		if (this.state.uploadResult) {
			const result = this.state.uploadResult;
			const { height, width, name } = this.state.imageData;
			const aspectRatio = height / width;

			try {
				this._handleLoading();

				const thread = await this.props.postDiscussion({
					title: this.state.title,
					text: textUtils.getTextFromMetadata({
						type: "photo",
						title: name,
						url: result.originalUrl,
						height,
						width,
						thumbnail_height: Math.min(480, width) * aspectRatio,
						thumbnail_width: Math.min(480, width),
						thumbnail_url: result.thumbnailUrl
					}),
					thread: result.textId,
					image: result.thumbnailUrl
				}, this.state.shareOnFacebook);

				this._handlePosted(thread);
			} catch (e) {
				this._handleError(FAIL_MESSAGE);
			}
		} else if (this.state.text) {
			try {
				this._handleLoading();

				const thread = await this.props.postDiscussion({
					title: this.state.title,
					text: this.state.text
				}, this.state.shareOnFacebook);

				this._handlePosted(thread);
			} catch (e) {
				this._handleError(FAIL_MESSAGE);
			}
		} else {
			this._handleError(NO_SUMMARY_MESSAGE);
		}
	};

	_handlePress = () => {
		if (this.state.status === "loading") {
			return;
		}

		this._postDiscussion();
	};

	_handleChangeTitle = title => {
		this.setState({
			title,
			error: null
		});
	};

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

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

			const imageData = await ImageChooser.pickImage();

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

	_handleUploadFinish = result => {
		this.setState({
			uploadResult: result,
			error: null
		});
	};

	_handleUploadClose = () => {
		this.setState({
			imageData: null,
			uploadResult: null,
			error: null
		});
	};

	render() {
		const isLoading = this.state.status === "loading";
		const isDisabled = !(this.state.title && (this.state.text || this.state.uploadResult) && !isLoading);

		return (
			<StatusbarContainer style={styles.container}>
				<AppbarSecondary>
					<AppbarTouchable type="secondary" onPress={this.props.dismiss}>
						<AppbarIcon name="close" style={styles.icon} />
					</AppbarTouchable>

					<UserIconContainer style={styles.userIcon} size={30} />
				</AppbarSecondary>

				<Banner text={this.state.error} type="error" />

				<ScrollView style={styles.scene} keyboardShouldPersistTaps>
					<AppTextInput
						autoFocus
						value={this.state.title}
						onChangeText={this._handleChangeTitle}
						placeholder="Write a discussion title"
						autoCapitalize="sentences"
						style={[ styles.threadTitle, styles.entry ]}
						underlineColorAndroid="transparent"
					/>

					{this.state.imageData ?
						<ImageUploadContainer
							component={ImageUploadDiscussion}
							imageData={this.state.imageData}
							onUploadClose={this._handleUploadClose}
							onUploadFinish={this._handleUploadFinish}
							autoStart
						/> :
						<GrowingTextInput
							numberOfLines={5}
							value={this.state.text}
							onChangeText={this._handleChangeText}
							placeholder="And a short summary"
							autoCapitalize="sentences"
							initialHeight={29}
							maxHeight={124}
							style={[ styles.threadSummary, styles.entry ]}
							underlineColorAndroid="transparent"
						/>
					}

					<TouchableOpacity onPress={this._handleSharePress}>
						<View style={styles.socialItem}>
							<View style={[ styles.socialIconContainer, this.state.shareOnFacebook ? styles.socialIconContainerSelected : null ]}>
								<EvilIcons name="sc-facebook" style={styles.socialIcon} />
							</View>
							<AppText style={[ styles.socialText, this.state.shareOnFacebook ? styles.socialTextSelected : null ]}>
								{this.state.shareOnFacebook ?
									"This will appear on your timeline" :
									"Tap to share this with your friends"
								}
							</AppText>
						</View>
					</TouchableOpacity>
					<AppText style={styles.socialTip}>Tip: Sharing improves your discussion’s reach</AppText>
				</ScrollView>
				<View style={styles.footer}>
					<TouchFeedback
						borderless
						onPress={this._handleUploadImage}
					>
						<View style={styles.uploadButton}>
							<Icon
								name="image"
								style={[ styles.uploadButtonIcon, this.state.imageData ? styles.uploadButtonIconActive : null ]}
								size={24}
							/>
						</View>
					</TouchFeedback>
					<View style={[ styles.postButton, isDisabled ? styles.disabled : null ]}>
						{isDisabled ?
							<View style={styles.postButtonInner}>
								<AppText style={styles.postButtonText}>{isLoading ? "Posting…" : "Post"}</AppText>
							</View> :
							<TouchFeedback onPress={this._handlePress}>
								<View style={styles.postButtonInner}>
									<AppText style={styles.postButtonText}>Post</AppText>
								</View>
							</TouchFeedback>
						}
					</View>
				</View>
			</StatusbarContainer>
		);
	}
}

StartDiscussionButton.propTypes = {
	room: React.PropTypes.string.isRequired,
	dismiss: React.PropTypes.func.isRequired,
	postDiscussion: React.PropTypes.func.isRequired,
	requestFacebookPermissions: React.PropTypes.func.isRequired,
	isFacebookPermissionGranted: React.PropTypes.func.isRequired,
	onNavigation: React.PropTypes.func.isRequired
};
<commit_msg>Rework post to Facebook button<commit_after>import React from "react-native";
import EvilIcons from "react-native-vector-icons/EvilIcons";
import Colors from "../../Colors.json";
import AppText from "./AppText";
import AppTextInput from "./AppTextInput";
import StatusbarContainer from "./StatusbarContainer";
import AppbarSecondary from "./AppbarSecondary";
import AppbarTouchable from "./AppbarTouchable";
import AppbarIcon from "./AppbarIcon";
import GrowingTextInput from "./GrowingTextInput";
import TouchFeedback from "./TouchFeedback";
import Icon from "./Icon";
import UserIconContainer from "../containers/UserIconContainer";
import ImageUploadContainer from "../containers/ImageUploadContainer";
import Banner from "./Banner";
import ImageUploadDiscussion from "./ImageUploadDiscussion";
import ImageChooser from "../modules/ImageChooser";
import textUtils from "../lib/text-utils";

const {
	AsyncStorage,
	TouchableOpacity,
	StyleSheet,
	NavigationActions,
	ScrollView,
	View
} = React;

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: Colors.white
	},
	scene: {
		paddingHorizontal: 8,
		paddingVertical: 16
	},
	threadTitle: {
		fontWeight: "bold",
		fontSize: 20,
		lineHeight: 30
	},
	threadSummary: {
		fontSize: 16,
		lineHeight: 24,
		marginVertical: 8
	},
	icon: {
		color: Colors.fadedBlack
	},
	disabled: {
		opacity: 0.5
	},
	userIcon: {
		margin: 12
	},
	entry: {
		paddingVertical: 4,
		paddingHorizontal: 12
	},
	uploadButtonIcon: {
		color: Colors.fadedBlack,
		marginHorizontal: 16,
		marginVertical: 14
	},
	uploadButtonIconActive: {
		color: Colors.info
	},
	footer: {
		flexDirection: "row",
		justifyContent: "space-between",
		borderTopColor: Colors.separator,
		borderTopWidth: 1
	},
	postButton: {
		backgroundColor: Colors.info,
		margin: 6,
		width: 100,
		borderRadius: 3
	},
	postButtonInner: {
		paddingVertical: 10,
		paddingHorizontal: 16
	},
	postButtonText: {
		color: Colors.white,
		fontWeight: "bold",
		textAlign: "center"
	},
	socialItem: {
		flexDirection: "row",
		alignItems: "center",
		margin: 12
	},
	socialIconContainer: {
		height: 28,
		width: 28,
		alignItems: "center",
		justifyContent: "center",
		backgroundColor: Colors.grey,
		borderRadius: 2
	},
	socialIconContainerSelected: {
		backgroundColor: Colors.facebook
	},
	socialIcon: {
		fontSize: 28,
		color: Colors.white
	},
	socialTextContainer: {
		marginHorizontal: 12,
		color: Colors.fadedBlack,
		bottom: -3
	},
	socialTextSelected: {
		color: Colors.facebook,
		fontWeight: "bold"
	},
	socialLabel: {
		fontSize: 12,
		lineHeight: 18,
	},
	socialTip: {
		fontSize: 10,
		lineHeight: 15,
		opacity: 0.5,
		fontWeight: "normal"
	}
});

const FACEBOOK_SHARE_CHECKED_KEY = "start_discussion_facebook_share_checked";

export default class StartDiscussionButton extends React.Component {
	state = {
		title: "",
		text: "",
		imageData: null,
		uploadResult: null,
		status: null,
		error: null,
		shareOnFacebook: false
	};

	componentDidMount() {
		this._setShareCheckbox();
	}

	_handleSharePress = () => {
		requestAnimationFrame(async () => {
			let shareOnFacebook = !this.state.shareOnFacebook;

			if (shareOnFacebook) {
				try {
					await this.props.requestFacebookPermissions();
				} catch (err) {
					shareOnFacebook = false;
				}
			}

			this.setState({
				shareOnFacebook
			});

			AsyncStorage.setItem(FACEBOOK_SHARE_CHECKED_KEY, JSON.stringify(shareOnFacebook));
		});
	};

	_setShareCheckbox = async () => {
		let shareOnFacebook;

		try {
			const isEnabled = JSON.parse(await AsyncStorage.getItem(FACEBOOK_SHARE_CHECKED_KEY));

			if (isEnabled) {
				const granted = await this.props.isFacebookPermissionGranted();

				shareOnFacebook = granted;
			} else {
				shareOnFacebook = false;
			}
		} catch (err) {
			shareOnFacebook = false;
		}

		this.setState({
			shareOnFacebook
		});
	};

	_handleLoading = () => {
		this.setState({
			status: "loading"
		});
	};

	_handlePosted = thread => {
		this.props.onNavigation(new NavigationActions.Push({
			name: "chat",
			props: {
				thread: thread.id,
				room: this.props.room
			}
		}));
	};

	_handleError = message => {
		this.setState({
			error: message,
			status: null
		});
	};

	_postDiscussion = async () => {
		const FAIL_MESSAGE = "An error occurred while posting";
		const SHORT_TITLE_MESSAGE = "Title needs be at least 2 words";
		const LONG_TITLE_MESSAGE = "Title needs be less than 10 words";
		const NO_TITLE_MESSAGE = "Enter a title in 2 to 10 words";
		const NO_SUMMARY_MESSAGE = "Enter a short summary";

		if (!this.state.title) {
			this._handleError(NO_TITLE_MESSAGE);
			return;
		}

		const words = this.state.title.trim().split(/\s+/);

		if (words.length < 2) {
			this._handleError(SHORT_TITLE_MESSAGE);
			return;
		} else if (words.length > 10) {
			this._handleError(LONG_TITLE_MESSAGE);
			return;
		}

		if (this.state.uploadResult) {
			const result = this.state.uploadResult;
			const { height, width, name } = this.state.imageData;
			const aspectRatio = height / width;

			try {
				this._handleLoading();

				const thread = await this.props.postDiscussion({
					title: this.state.title,
					text: textUtils.getTextFromMetadata({
						type: "photo",
						title: name,
						url: result.originalUrl,
						height,
						width,
						thumbnail_height: Math.min(480, width) * aspectRatio,
						thumbnail_width: Math.min(480, width),
						thumbnail_url: result.thumbnailUrl
					}),
					thread: result.textId,
					image: result.thumbnailUrl
				}, this.state.shareOnFacebook);

				this._handlePosted(thread);
			} catch (e) {
				this._handleError(FAIL_MESSAGE);
			}
		} else if (this.state.text) {
			try {
				this._handleLoading();

				const thread = await this.props.postDiscussion({
					title: this.state.title,
					text: this.state.text
				}, this.state.shareOnFacebook);

				this._handlePosted(thread);
			} catch (e) {
				this._handleError(FAIL_MESSAGE);
			}
		} else {
			this._handleError(NO_SUMMARY_MESSAGE);
		}
	};

	_handlePress = () => {
		if (this.state.status === "loading") {
			return;
		}

		this._postDiscussion();
	};

	_handleChangeTitle = title => {
		this.setState({
			title,
			error: null
		});
	};

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

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

			const imageData = await ImageChooser.pickImage();

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

	_handleUploadFinish = result => {
		this.setState({
			uploadResult: result,
			error: null
		});
	};

	_handleUploadClose = () => {
		this.setState({
			imageData: null,
			uploadResult: null,
			error: null
		});
	};

	render() {
		const isLoading = this.state.status === "loading";
		const isDisabled = !(this.state.title && (this.state.text || this.state.uploadResult) && !isLoading);

		return (
			<StatusbarContainer style={styles.container}>
				<AppbarSecondary>
					<AppbarTouchable type="secondary" onPress={this.props.dismiss}>
						<AppbarIcon name="close" style={styles.icon} />
					</AppbarTouchable>

					<UserIconContainer style={styles.userIcon} size={30} />
				</AppbarSecondary>

				<Banner text={this.state.error} type="error" />

				<ScrollView style={styles.scene} keyboardShouldPersistTaps>
					<AppTextInput
						autoFocus
						value={this.state.title}
						onChangeText={this._handleChangeTitle}
						placeholder="Write a discussion title"
						autoCapitalize="sentences"
						style={[ styles.threadTitle, styles.entry ]}
						underlineColorAndroid="transparent"
					/>

					{this.state.imageData ?
						<ImageUploadContainer
							component={ImageUploadDiscussion}
							imageData={this.state.imageData}
							onUploadClose={this._handleUploadClose}
							onUploadFinish={this._handleUploadFinish}
							autoStart
						/> :
						<GrowingTextInput
							numberOfLines={5}
							value={this.state.text}
							onChangeText={this._handleChangeText}
							placeholder="And a short summary"
							autoCapitalize="sentences"
							initialHeight={29}
							maxHeight={124}
							style={[ styles.threadSummary, styles.entry ]}
							underlineColorAndroid="transparent"
						/>
					}

					<TouchableOpacity onPress={this._handleSharePress}>
						<View style={styles.socialItem}>
							<View style={[ styles.socialIconContainer, this.state.shareOnFacebook ? styles.socialIconContainerSelected : null ]}>
								<EvilIcons name="sc-facebook" style={styles.socialIcon} />
							</View>
							<AppText style={[ styles.socialTextContainer, this.state.shareOnFacebook ? styles.socialTextSelected : null ]}>
								<AppText style={styles.socialLabel}>
									{this.state.shareOnFacebook ?
										"This will appear on your timeline\n" :
										"Tap to share this with your friends\n"
									}
								</AppText>
								<AppText style={styles.socialTip}>Tip: Sharing improves your discussion’s reach</AppText>
							</AppText>
						</View>
					</TouchableOpacity>
				</ScrollView>
				<View style={styles.footer}>
					<TouchFeedback
						borderless
						onPress={this._handleUploadImage}
					>
						<View style={styles.uploadButton}>
							<Icon
								name="image"
								style={[ styles.uploadButtonIcon, this.state.imageData ? styles.uploadButtonIconActive : null ]}
								size={24}
							/>
						</View>
					</TouchFeedback>
					<View style={[ styles.postButton, isDisabled ? styles.disabled : null ]}>
						{isDisabled ?
							<View style={styles.postButtonInner}>
								<AppText style={styles.postButtonText}>{isLoading ? "Posting…" : "Post"}</AppText>
							</View> :
							<TouchFeedback onPress={this._handlePress}>
								<View style={styles.postButtonInner}>
									<AppText style={styles.postButtonText}>Post</AppText>
								</View>
							</TouchFeedback>
						}
					</View>
				</View>
			</StatusbarContainer>
		);
	}
}

StartDiscussionButton.propTypes = {
	room: React.PropTypes.string.isRequired,
	dismiss: React.PropTypes.func.isRequired,
	postDiscussion: React.PropTypes.func.isRequired,
	requestFacebookPermissions: React.PropTypes.func.isRequired,
	isFacebookPermissionGranted: React.PropTypes.func.isRequired,
	onNavigation: React.PropTypes.func.isRequired
};
<|endoftext|>


<commit_before>import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import {
  boolean, text, number, select
} from '@storybook/addon-knobs';
import { Store, State } from '@sambego/storybook-state';
import Form from '../form';
import { dlsThemeSelector, classicThemeSelector } from '../../../../.storybook/theme-selectors';
import OptionsHelper from '../../../utils/helpers/options-helper';
import { Checkbox, CheckboxGroup } from '.';
import { info, notes, infoValidations } from './documentation';
import getDocGenInfo from '../../../utils/helpers/docgen-info';
import Text from '../../../utils/helpers/text';
import AutoFocus from '../../../utils/helpers/auto-focus';
import guid from '../../../utils/helpers/guid';

Checkbox.__docgenInfo = getDocGenInfo(
  require('./docgenInfo.json'),
  /checkbox\.component(?!spec)/
);

function testValidator(value, props) {
  return new Promise((resolve, reject) => {
    if (['required', 'mandatory'].indexOf(value) !== -1 && !props.checked) {
      reject(new Error('This checkbox is required!'));
    } else if (props.name === 'checkbox-group' && value === '0') {
      reject(new Error('This checkbox is required!'));
    } else {
      resolve();
    }
  });
}

function testWarning(value, props) {
  return new Promise((resolve, reject) => {
    if (['warning', 'alert'].indexOf(value) !== -1 && !props.checked) {
      reject(new Error('Show warning!'));
    } else if (props.name === 'checkbox-group' && value === '1') {
      reject(new Error('Show warning!'));
    } else {
      resolve();
    }
  });
}

function testInfo(value, props) {
  return new Promise((resolve, reject) => {
    if (['info', 'example'].indexOf(value) !== -1 && !props.checked) {
      reject(new Error('Show this information'));
    } else if (props.name === 'checkbox-group' && value === '2') {
      reject(new Error('Show this information'));
    } else {
      resolve();
    }
  });
}

const checkboxes = {
  default: {}, required: {}, warning: {}, info: {}, optional: {}, one: {}, two: {}, three: {}
};
const checkboxKeys = Object.keys(checkboxes);

checkboxKeys.forEach((id) => {
  checkboxes[id] = {
    store: new Store({
      checked: false,
      forceUpdateTriggerToggle: false
    })
  };
});
const formCheckbox = checkboxKeys.filter(name => ['required', 'warning', 'info', 'optional'].indexOf(name) !== -1);
const groupCheckbox = checkboxKeys.filter(name => ['one', 'two', 'three'].indexOf(name) !== -1);

const groupStore = new Store({
  value: '0',
  mandatory: false,
  alert: false,
  example: false,
  one: false,
  two: false,
  three: false
});

const previous = {
  key: guid(),
  autoFocus: false
};

function defaultKnobs(type) {
  const knobGroup = `Checkbox_${type}`;
  const nameWithGroup = (name) => {
    return (type === 'default') ? name : `${Text.titleCase(type)} ${name}`;
  };
  const label = `${text(nameWithGroup('label'), 'Example Checkbox', knobGroup)} (${type})`;
  const autoFocus = boolean(nameWithGroup('autoFocus'), false, knobGroup);
  const key = AutoFocus.getKey(autoFocus, previous);

  return ({
    key,
    disabled: boolean(nameWithGroup('disabled'), false, knobGroup),
    fieldHelp: text(nameWithGroup('fieldHelp'), 'This text provides help for the input.', knobGroup),
    fieldHelpInline: boolean(nameWithGroup('fieldHelpInline'), false, knobGroup),
    reverse: boolean(nameWithGroup('reverse'), false, knobGroup),
    autoFocus,
    label,
    labelHelp: text(nameWithGroup('labelHelp'), 'This text provides more information for the label.', knobGroup),
    onBlur: action('onBlur'),
    inputWidth: number(nameWithGroup('inputWidth'), 0, {
      range: true,
      min: 0,
      max: 100,
      step: 1
    }, knobGroup),
    labelWidth: number(nameWithGroup('labelWidth'), 0, {
      range: true,
      min: 0,
      max: 100,
      step: 1
    }, knobGroup),
    labelAlign: select(
      nameWithGroup('labelAlign'),
      OptionsHelper.alignBinary,
      OptionsHelper.alignBinary[0],
      knobGroup
    ),
    size: select(nameWithGroup('size'), OptionsHelper.sizesBinary, 'small', knobGroup),
    value: text(nameWithGroup('value'), type, knobGroup)
  });
}

function makeStory(name, themeSelector, component) {
  const metadata = {
    themeSelector,
    info: {
      text: name.search('validations') !== -1 ? infoValidations : info,
      propTablesExclude: [State],
      excludedPropTypes: ['children']
    },
    notes: { markdown: notes },
    knobs: { escapeHTML: false }
  };

  return [name, component, metadata];
}

function handleChange(ev, id) {
  const { checked } = ev.target;

  checkboxes[id].store.set({
    checked,
    forceUpdateTriggerToggle: !checked
  });

  action('change')(`checked: ${checked}`);
}

function handleGroupChange(ev, id) {
  const { checked } = ev.target;
  const count = Number(groupStore.get('value'));
  const value = checked ? count + 1 : count - 1;

  groupStore.set({
    value: value.toString(),
    [id]: checked,
    forceUpdateTriggerToggle: checked
  });
}

function handleSubmit(ev) {
  ev.preventDefault();
  action('submit')();
}

const checkboxComponent = () => {
  return (
    <State store={ checkboxes.default.store }>
      <Checkbox
        onChange={ ev => handleChange(ev, 'default') }
        { ...defaultKnobs('default') }
      />
    </State>
  );
};

const checkboxComponentAutoFocus = () => {
  boolean('autoFocus', true, 'Checkbox default');
  return checkboxComponent();
};

const checkboxGroupComponent = () => (

In Form

    <Form onSubmit={ handleSubmit }>
      {formCheckbox.map(type => (
        <State store={ checkboxes[type].store } key={ `check-state-${type}` }>
          <Checkbox
            id='checkbox'
            key={ `checkbox-input-${type}` }
            validations={ testValidator }
            warnings={ testWarning }
            info={ testInfo }
            onChange={ ev => handleChange(ev, type) }
            name={ `my-checkbox-${type}` }
            unblockValidation
            { ...defaultKnobs(type) }
          />
        </State>
      ))}
    </Form>

In Group

    <State store={ groupStore }>
      {state => [
        <CheckboxGroup
          key='checkbox-group'
          name='checkbox-group'
          groupName='checkbox-group'
          label={ text('label', 'What would you choose?', 'group') }
          labelHelp={ text('labelHelp', 'Some helpful information', 'group') }
          validations={ testValidator }
          warnings={ testWarning }
          info={ testInfo }
          value={ state.value }
        >
          {groupCheckbox.map(id => (
            <Checkbox
              checked={ state[id] }
              name={ `checkbox-input-${id}` }
              key={ `checkbox-input-${id}` }
              onChange={ ev => handleGroupChange(ev, id) }
              labelHelp={ text(`${Text.titleCase(id)} labelHelp`, '', `Checkbox ${id}`) }
              { ...defaultKnobs(id) }
            />
          ))}
        </CheckboxGroup>
      ]}
    </State>

);

storiesOf('Experimental/Checkbox', module)
  .add(...makeStory('default', dlsThemeSelector, checkboxComponent))
  .add(...makeStory('classic', classicThemeSelector, checkboxComponent))
  .add(...makeStory('validations', dlsThemeSelector, checkboxGroupComponent))
  .add(...makeStory('validations classic', classicThemeSelector, checkboxGroupComponent))
  .add(...makeStory('autoFocus', dlsThemeSelector, checkboxComponentAutoFocus));
<commit_msg>chore(checkbox): updated naming of knobs for default story<commit_after>import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import {
  boolean, text, number, select
} from '@storybook/addon-knobs';
import { Store, State } from '@sambego/storybook-state';
import Form from '../form';
import { dlsThemeSelector, classicThemeSelector } from '../../../../.storybook/theme-selectors';
import OptionsHelper from '../../../utils/helpers/options-helper';
import { Checkbox, CheckboxGroup } from '.';
import { info, notes, infoValidations } from './documentation';
import getDocGenInfo from '../../../utils/helpers/docgen-info';
import AutoFocus from '../../../utils/helpers/auto-focus';
import guid from '../../../utils/helpers/guid';

Checkbox.__docgenInfo = getDocGenInfo(
  require('./docgenInfo.json'),
  /checkbox\.component(?!spec)/
);

function testValidator(value, props) {
  return new Promise((resolve, reject) => {
    if (['required', 'mandatory'].indexOf(value) !== -1 && !props.checked) {
      reject(new Error('This checkbox is required!'));
    } else if (props.name === 'checkbox-group' && value === '0') {
      reject(new Error('This checkbox is required!'));
    } else {
      resolve();
    }
  });
}

function testWarning(value, props) {
  return new Promise((resolve, reject) => {
    if (['warning', 'alert'].indexOf(value) !== -1 && !props.checked) {
      reject(new Error('Show warning!'));
    } else if (props.name === 'checkbox-group' && value === '1') {
      reject(new Error('Show warning!'));
    } else {
      resolve();
    }
  });
}

function testInfo(value, props) {
  return new Promise((resolve, reject) => {
    if (['info', 'example'].indexOf(value) !== -1 && !props.checked) {
      reject(new Error('Show this information'));
    } else if (props.name === 'checkbox-group' && value === '2') {
      reject(new Error('Show this information'));
    } else {
      resolve();
    }
  });
}

const checkboxes = {
  default: {}, required: {}, warning: {}, info: {}, optional: {}, one: {}, two: {}, three: {}
};
const checkboxKeys = Object.keys(checkboxes);

checkboxKeys.forEach((id) => {
  checkboxes[id] = {
    store: new Store({
      checked: false,
      forceUpdateTriggerToggle: false
    })
  };
});
const formCheckbox = checkboxKeys.filter(name => ['required', 'warning', 'info', 'optional'].indexOf(name) !== -1);
const groupCheckbox = checkboxKeys.filter(name => ['one', 'two', 'three'].indexOf(name) !== -1);

const groupStore = new Store({
  value: '0',
  mandatory: false,
  alert: false,
  example: false,
  one: false,
  two: false,
  three: false
});

const previous = {
  key: guid(),
  autoFocus: false
};

function defaultKnobs(type) {
  let theType = '';
  if (type === undefined) {
    theType = 'default';
  } else {
    theType = type;
  }
  const label = `${text('label', 'Example Checkbox', type)} (${theType})`;
  const autoFocus = boolean('autoFocus', false, type);
  const key = AutoFocus.getKey(autoFocus, previous);

  return ({
    key,
    disabled: boolean('disabled', false, type),
    fieldHelp: text('fieldHelp', 'This text provides help for the input.', type),
    fieldHelpInline: boolean('fieldHelpInline', false, type),
    reverse: boolean('reverse', false, type),
    autoFocus,
    label,
    labelHelp: text('labelHelp', 'This text provides more information for the label.', type),
    onBlur: action('onBlur'),
    inputWidth: number('inputWidth', 0, {
      range: true,
      min: 0,
      max: 100,
      step: 1
    }, type),
    labelWidth: number('labelWidth', 0, {
      range: true,
      min: 0,
      max: 100,
      step: 1
    }, type),
    labelAlign: select(
      'labelAlign',
      OptionsHelper.alignBinary,
      OptionsHelper.alignBinary[0],
      type
    ),
    size: select('size', OptionsHelper.sizesBinary, 'small', type),
    value: text('value', type, type)
  });
}

function makeStory(name, themeSelector, component) {
  const metadata = {
    themeSelector,
    info: {
      text: name.search('validations') !== -1 ? infoValidations : info,
      propTablesExclude: [State],
      excludedPropTypes: ['children']
    },
    notes: { markdown: notes },
    knobs: { escapeHTML: false }
  };

  return [name, component, metadata];
}

function handleChange(ev, id) {
  const { checked } = ev.target;

  checkboxes[id].store.set({
    checked,
    forceUpdateTriggerToggle: !checked
  });

  action('change')(`checked: ${checked}`);
}

function handleGroupChange(ev, id) {
  const { checked } = ev.target;
  const count = Number(groupStore.get('value'));
  const value = checked ? count + 1 : count - 1;

  groupStore.set({
    value: value.toString(),
    [id]: checked,
    forceUpdateTriggerToggle: checked
  });
}

function handleSubmit(ev) {
  ev.preventDefault();
  action('submit')();
}

const checkboxComponent = () => {
  return (
    <State store={ checkboxes.default.store }>
      <Checkbox
        onChange={ ev => handleChange(ev, 'default') }
        { ...defaultKnobs() }
      />
    </State>
  );
};

const checkboxComponentAutoFocus = () => {
  boolean('autoFocus', true, 'Checkbox default');
  return checkboxComponent();
};

const checkboxGroupComponent = () => (

In Form

    <Form onSubmit={ handleSubmit }>
      {formCheckbox.map(type => (
        <State store={ checkboxes[type].store } key={ `check-state-${type}` }>
          <Checkbox
            id='checkbox'
            key={ `checkbox-input-${type}` }
            validations={ testValidator }
            warnings={ testWarning }
            info={ testInfo }
            onChange={ ev => handleChange(ev, type) }
            name={ `my-checkbox-${type}` }
            unblockValidation
            { ...defaultKnobs(type) }
          />
        </State>
      ))}
    </Form>

In Group

    <State store={ groupStore }>
      {state => [
        <CheckboxGroup
          key='checkbox-group'
          name='checkbox-group'
          groupName='checkbox-group'
          label={ text('label', 'What would you choose?', 'group') }
          labelHelp={ text('labelHelp', 'Some helpful information', 'group') }
          validations={ testValidator }
          warnings={ testWarning }
          info={ testInfo }
          value={ state.value }
        >
          {groupCheckbox.map(id => (
            <Checkbox
              checked={ state[id] }
              name={ `checkbox-input-${id}` }
              key={ `checkbox-input-${id}` }
              onChange={ ev => handleGroupChange(ev, id) }
              { ...defaultKnobs(id) }
            />
          ))}
        </CheckboxGroup>
      ]}
    </State>

);

storiesOf('Experimental/Checkbox', module)
  .add(...makeStory('default', dlsThemeSelector, checkboxComponent))
  .add(...makeStory('classic', classicThemeSelector, checkboxComponent))
  .add(...makeStory('validations', dlsThemeSelector, checkboxGroupComponent))
  .add(...makeStory('validations classic', classicThemeSelector, checkboxGroupComponent))
  .add(...makeStory('autoFocus', dlsThemeSelector, checkboxComponentAutoFocus));
<|endoftext|>


<commit_before>define([
   "dojo/_base/declare",
   "dojo/when",
   "dojo/topic",
   "dojo/on",
   "dojo/_base/lang",
   "dojo/dom-construct",
   "dojo/dom-style",
   "dojo/dom-attr",
   "dojo/aspect",

   "dijit/_WidgetBase",
   "dijit/Dialog",
   "dijit/_OnDijitClickMixin",
   "dijit/focus",
   "dijit/form/Button",
   "dijit/layout/BorderContainer",
   "dijit/_Container",
   "dijit/layout/_ContentPaneResizeMixin",
   "dijit/_TemplatedMixin",
   "dijit/_WidgetsInTemplateMixin",

   'dgrid/List',
   'dgrid/OnDemandList',
   "dgrid/Selection",
   "dgrid/Keyboard",
   "dgrid/util/mouse",
   "dgrid/extensions/DijitRegistry",
   'put-selector/put',

   "hotplate/hotDojoSubmit/defaultSubmit",
   "hotplate/hotDojoWidgets/BusyButton",
   "hotplate/hotDojoWidgets/ConfirmDialog",

   ], function(
     declare
     , when
     , topic
     , on
     , lang
     , domConstruct
     , domStyle
     , domAttr
     , aspect

     , _WidgetBase
     , Dialog
     , _OnDijitClickMixin
     , focusUtil
     , Button
     , BorderContainer
     , _Container
     , _ContentPaneResizeMixin
     , _TemplatedMixin
     , _WidgetsInTemplateMixin

     , List
     , OnDemandList
     , Selection
     , Keyboard
     , mouse
     , DijitRegistry
     , put

     , ds
     , BusyButton
     , ConfirmDialog

 ){

    return declare( [ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, _ContentPaneResizeMixin ] , {

      templateString: '
\n' +
                      '
\n'+
                      '
\n'+
                      '\n'+
                      '\n'+
                      '\n'+
                      '

Pick

\n' +
                      '

\n' +
                      '
\n'+
                      '
\n'+
                      '

\n'+
                      '
\n'+
                      '
\n'+
                      '
\n'+
                      '\n'+
                      '',

      widgetsInTemplate: true,
      // Store
      storeName: '',
      store: null,
      renderRow: function( o ){ return "renderRow not defined"; } ,

      selectedId: null,
      listWidget: null,

      constructor: function( params ){
        // this.store = stores( params.storeName, params.storeFields );
      },

      // Proxy method for listwidget.row()
      row: function( p ){
        return this.listWidget.row( p );
      },

      postCreate: function(){

        var self = S = this;
        this.inherited(arguments);

        put( self.domNode, '.dgrid-select' );

        var ListConstructor = declare( [ OnDemandList, Selection, Keyboard, DijitRegistry ], {
          renderRow: self.renderRow,
        } );

        // Make a listWidget
        self.listWidget = new ListConstructor( { store: this.store }, self.listWidgetNode );

        // A record was selected beforehand: load it up
        if( this.selectedId !== null ){
          self.label.innerHTML = "Loading...";

          when( self.store.get( self.selectedId ) ).then(
            function( res ) {
              self.label.innerHTML = '';
              put( self.label, self.renderRow( res ) );
            },
            function( err ){
              self.label.innerHTML = 'Error loading item!';
              connectUp();
            }
          );
        } else {
          connectUp();
        }

        function connectUp(){

        }

      },

      resize: function(){
        this.listWidget.resize();

        this.inherited(arguments);
      },

      destroy: function(){
        this.listWidget.destroy();

        this.inherited(arguments);
      },

      startup: function(){
        this.inherited(arguments);
      },

    });

});

<commit_msg>Another attempt<commit_after>define([
   "dojo/_base/declare",
   "dojo/when",
   "dojo/topic",
   "dojo/on",
   "dojo/_base/lang",
   "dojo/dom-construct",
   "dojo/dom-style",
   "dojo/dom-attr",
   "dojo/aspect",

   "dijit/_WidgetBase",
   "dijit/Dialog",
   "dijit/_OnDijitClickMixin",
   "dijit/focus",
   "dijit/form/Button",
   "dijit/layout/BorderContainer",
   "dijit/_Container",
   "dijit/layout/_ContentPaneResizeMixin",
   "dijit/_TemplatedMixin",
   "dijit/_WidgetsInTemplateMixin",

   'dgrid/List',
   'dgrid/OnDemandList',
   "dgrid/Selection",
   "dgrid/Keyboard",
   "dgrid/util/mouse",
   "dgrid/extensions/DijitRegistry",
   'put-selector/put',

   "hotplate/hotDojoSubmit/defaultSubmit",
   "hotplate/hotDojoWidgets/BusyButton",
   "hotplate/hotDojoWidgets/ConfirmDialog",

   ], function(
     declare
     , when
     , topic
     , on
     , lang
     , domConstruct
     , domStyle
     , domAttr
     , aspect

     , _WidgetBase
     , Dialog
     , _OnDijitClickMixin
     , focusUtil
     , Button
     , BorderContainer
     , _Container
     , _ContentPaneResizeMixin
     , _TemplatedMixin
     , _WidgetsInTemplateMixin

     , List
     , OnDemandList
     , Selection
     , Keyboard
     , mouse
     , DijitRegistry
     , put

     , ds
     , BusyButton
     , ConfirmDialog

 ){

    return declare( [ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, _ContentPaneResizeMixin ] , {

      templateString: '
\n' +
                      '
\n'+
                      '
\n'+
                      '\n'+
                      '\n'+
                      '\n'+
                      '

Pick

\n' +
                      '

\n' +
                      '
\n'+
                      '
\n'+
                      '

\n'+
                      '
\n'+
                      '
\n'+
                      '
\n'+
                      '\n'+
                      '',

      widgetsInTemplate: true,
      // Store
      storeName: '',
      store: null,
      renderRow: function( o ){ return "renderRow not defined"; } ,

      selectedId: null,
      listWidget: null,

      constructor: function( params ){
        // this.store = stores( params.storeName, params.storeFields );
      },

      // Proxy method for listwidget.row()
      row: function( p ){
        return this.listWidget.row( p );
      },

      postCreate: function(){

        var self = S = this;
        this.inherited(arguments);

        put( self.domNode, '.dgrid-select' );

        var ListConstructor = declare( [ OnDemandList, Selection, Keyboard, DijitRegistry ], {
          renderRow: self.renderRow,
        } );

        // Make a listWidget
        self.listWidget = new ListConstructor( { store: this.store }, self.listWidgetNode );

        // A record was selected beforehand: load it up
        if( this.selectedId !== null ){
          self.label.innerHTML = "Loading...";

          when( self.store.get( self.selectedId ) ).then(
            function( res ) {
              self.label.innerHTML = '';
              put( self.label, self.renderRow( res ) );
            },
            function( err ){
              self.label.innerHTML = 'Error loading item!';
              connectUp();
            }
          );
        } else {
          connectUp();
        }

        function connectUp(){

        }

      },

      resize: function(){
        this.listWidget.resize();

        this.inherited(arguments);
      },

      destroy: function(){
        this.listWidget.destroy();

        this.inherited(arguments);
      },

      startup: function(){
        this.inherited(arguments);
      },

    });

});

<|endoftext|>


<commit_before>import path from 'path';

import formConfig from 'applications/caregivers/config/form';
import manifest from 'applications/caregivers/manifest.json';
import testForm from 'platform/testing/e2e/cypress/support/form-tester';
import featureToggles from './fixtures/mocks/feature-toggles.json';
import mockUpload from './fixtures/mocks/mock-upload.json';
import { createTestConfig } from 'platform/testing/e2e/cypress/support/form-tester/utilities';
import {
  veteranSignatureContent,
  primaryCaregiverContent,
  secondaryCaregiverContent,
  veteranLabel,
  primaryLabel,
  secondaryOneLabel,
  secondaryTwoLabel,
  representativeLabel,
  representativeSignatureContent,
} from 'applications/caregivers/definitions/content';

export const mockVeteranSignatureContent = [
  'I certify that I give consent to the individual(s) named in this application to perform personal care services for me upon being approved as Primary and/or Secondary Family Caregivers in the Program of Comprehensive Assistance for Family Caregivers.',
];
export const mockRepresentativeSignatureContent = [
  'Signed by the Veteran’s legal representative on behalf of the Veteran.',
  'I certify that I give consent to the individual(s) named in this application to perform personal care services for me (or if the Veteran’s Representative, the Veteran) upon being approved as a Primary and/or Secondary Family Caregiver(s) in the Program of Comprehensive Assistance for Family Caregivers.',
];
export const mockPrimaryCaregiverContent = [
  'I certify that I am at least 18 years of age.',
  'I certify that either: (1) I am a member of the Veteran\u2019s family (including a parent, spouse, a son or daughter, a step-family member, or an extended family member) OR (2) I am not a member of the Veteran\u2019s family, and I reside with the Veteran full-time or will do so upon designation as the Veteran\u2019s Primary Family Caregiver.',
  'I agree to perform personal care services as the Primary Family Caregiver for the Veteran named on this application.',
  'I understand that the Veteran or the Veteran\u2019s surrogate may request my discharge from the Program of Comprehensive Assistance for Family Caregivers (PCAFC) at any time and that my designation as a Primary Family Caregiver may be revoked or I may be discharged from PCAFC by the Secretary of Veterans Affairs (or designee) as set forth in 38 CFR 71.45.',
  'I understand that participation in the PCAFC does not create an employment relationship between me and the Department of Veterans Affairs.',
];
export const mockSecondaryCaregiverContent = [
  'I certify that I am at least 18 years of age.',
  'I certify that either: (1) I am a member of the Veteran\u2019s family (including a parent, spouse, a son or daughter, a step-family member, or an extended family member) OR (2) I am not a member of the Veteran\u2019s family, and I reside with the Veteran full-time or will do so upon designation as the Veteran\u2019s Secondary Family Caregiver.',
  'I agree to perform personal care services as the Secondary Family Caregiver for the Veteran named on this application.',
  'I understand that the Veteran or the Veteran\u2019s surrogate may request my discharge from the Program of Comprehensive Assistance for Family Caregivers (PCAFC) at any time and that my designation as a Secondary Family Caregiver may be revoked or I may be discharged from PCAFC by the Secretary of Veterans Affairs (or designee) as set forth in 38 CFR 71.45.',
  'I understand that participation in the PCAFC does not create an employment relationship between me and the Department of Veterans Affairs.',
];

const checkContent = (partyLabel, content, mockContent) => {
  content.forEach((contentItem, idx) => {
    cy.get(`[data-testid="${partyLabel}"]`)
      .contains(contentItem, { matchCase: true })
      .should(signatureParagraph =>
        expect(signatureParagraph[0].innerText).to.eq(mockContent[idx]),
      );
  });
};

const signAsParty = (partyLabel, signature) => {
  cy.findByTestId(partyLabel)
    .find('input')
    .first()
    .type(signature);

  cy.findByTestId(partyLabel)
    .find('[type="checkbox"]')
    .check();
};

const testSecondaryTwo = createTestConfig(
  {
    dataPrefix: 'data',
    dataSets: [
      'requiredOnly',
      'secondaryOneOnly',
      'oneSecondaryCaregivers',
      'twoSecondaryCaregivers',
      'signAsRepresentativeNoRep',
      'signAsRepresentativeNo',
    ],
    fixtures: {
      data: path.join(__dirname, 'fixtures', 'data'),
      mocks: path.join(__dirname, 'fixtures', 'mocks'),
    },

    setupPerTest: () => {
      cy.server();
      cy.intercept('GET', '/v0/feature_toggles?*', featureToggles);
      cy.intercept('POST', 'v0/form1010cg/attachments', mockUpload);
    },
    pageHooks: {
      introduction: () => {
        // Hit the start button
        cy.findAllByText(/start/i, { selector: 'a' })
          .first()
          .click();
      },
      'review-and-submit': () => {
        cy.get('@testKey').then(testKey => {
          switch (testKey) {
            case 'secondaryOneOnly':
              // Check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // check secondary caregiver content && sign
              checkContent(
                secondaryOneLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryOneLabel, 'George Geef Goofus');

              break;
            case 'oneSecondaryCaregivers':
              // check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // Check primary caregiver content && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');

              // Check secondaryOne caregiver content && sign
              checkContent(
                secondaryOneLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryOneLabel, 'George Geef Goofus');

              break;
            case 'twoSecondaryCaregivers':
              // check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // Check primary caregiver content && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');

              // Check secondaryOne caregiver content && sign
              checkContent(
                secondaryOneLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryOneLabel, 'George Geef Goofus');

              // Check secondaryTwo caregiver content && sign
              checkContent(
                secondaryTwoLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryTwoLabel, 'Donald Duck');
              break;
            case 'signAsRepresentativeYes':
            case 'signAsRepresentativeNoRep':
              // check veteran content && sign as representative
              checkContent(
                representativeLabel,
                representativeSignatureContent,
                mockRepresentativeSignatureContent,
              );
              signAsParty(representativeLabel, 'Mini Mouse');

              // Check primary caregiver && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');
              break;
            default:
              // check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // Check primary caregiver && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');
              break;
          }
        });
        // sign signature as veteran

        cy.route({
          method: 'POST',
          url: '/v0/caregivers_assistance_claims',
          status: 200,
          response: {
            body: {
              data: {
                id: '',
                type: 'form1010cg_submissions',
                attributes: {
                  confirmationNumber: 'aB935000000F3VnCAK',
                  submittedAt: '2020-08-06T19:18:11+00:00',
                },
              },
            },
          },
        });
      },
    },
  },
  manifest,
  formConfig,
);

testForm(testSecondaryTwo);
<commit_msg>feat(1010cg): Add cypress test case file upload (#17242)<commit_after>import path from 'path';

import formConfig from 'applications/caregivers/config/form';
import manifest from 'applications/caregivers/manifest.json';
import testForm from 'platform/testing/e2e/cypress/support/form-tester';
import featureToggles from './fixtures/mocks/feature-toggles.json';
import mockUpload from './fixtures/mocks/mock-upload.json';
import { createTestConfig } from 'platform/testing/e2e/cypress/support/form-tester/utilities';
import {
  veteranSignatureContent,
  primaryCaregiverContent,
  secondaryCaregiverContent,
  veteranLabel,
  primaryLabel,
  secondaryOneLabel,
  secondaryTwoLabel,
  representativeLabel,
  representativeSignatureContent,
} from 'applications/caregivers/definitions/content';

export const mockVeteranSignatureContent = [
  'I certify that I give consent to the individual(s) named in this application to perform personal care services for me upon being approved as Primary and/or Secondary Family Caregivers in the Program of Comprehensive Assistance for Family Caregivers.',
];
export const mockRepresentativeSignatureContent = [
  'Signed by the Veteran’s legal representative on behalf of the Veteran.',
  'I certify that I give consent to the individual(s) named in this application to perform personal care services for me (or if the Veteran’s Representative, the Veteran) upon being approved as a Primary and/or Secondary Family Caregiver(s) in the Program of Comprehensive Assistance for Family Caregivers.',
];
export const mockPrimaryCaregiverContent = [
  'I certify that I am at least 18 years of age.',
  'I certify that either: (1) I am a member of the Veteran\u2019s family (including a parent, spouse, a son or daughter, a step-family member, or an extended family member) OR (2) I am not a member of the Veteran\u2019s family, and I reside with the Veteran full-time or will do so upon designation as the Veteran\u2019s Primary Family Caregiver.',
  'I agree to perform personal care services as the Primary Family Caregiver for the Veteran named on this application.',
  'I understand that the Veteran or the Veteran\u2019s surrogate may request my discharge from the Program of Comprehensive Assistance for Family Caregivers (PCAFC) at any time and that my designation as a Primary Family Caregiver may be revoked or I may be discharged from PCAFC by the Secretary of Veterans Affairs (or designee) as set forth in 38 CFR 71.45.',
  'I understand that participation in the PCAFC does not create an employment relationship between me and the Department of Veterans Affairs.',
];
export const mockSecondaryCaregiverContent = [
  'I certify that I am at least 18 years of age.',
  'I certify that either: (1) I am a member of the Veteran\u2019s family (including a parent, spouse, a son or daughter, a step-family member, or an extended family member) OR (2) I am not a member of the Veteran\u2019s family, and I reside with the Veteran full-time or will do so upon designation as the Veteran\u2019s Secondary Family Caregiver.',
  'I agree to perform personal care services as the Secondary Family Caregiver for the Veteran named on this application.',
  'I understand that the Veteran or the Veteran\u2019s surrogate may request my discharge from the Program of Comprehensive Assistance for Family Caregivers (PCAFC) at any time and that my designation as a Secondary Family Caregiver may be revoked or I may be discharged from PCAFC by the Secretary of Veterans Affairs (or designee) as set forth in 38 CFR 71.45.',
  'I understand that participation in the PCAFC does not create an employment relationship between me and the Department of Veterans Affairs.',
];

const checkContent = (partyLabel, content, mockContent) => {
  content.forEach((contentItem, idx) => {
    cy.get(`[data-testid="${partyLabel}"]`)
      .contains(contentItem, { matchCase: true })
      .should(signatureParagraph =>
        expect(signatureParagraph[0].innerText).to.eq(mockContent[idx]),
      );
  });
};

const signAsParty = (partyLabel, signature) => {
  cy.findByTestId(partyLabel)
    .find('input')
    .first()
    .type(signature);

  cy.findByTestId(partyLabel)
    .find('[type="checkbox"]')
    .check();
};

const testSecondaryTwo = createTestConfig(
  {
    dataPrefix: 'data',
    dataSets: [
      'requiredOnly',
      'secondaryOneOnly',
      'oneSecondaryCaregivers',
      'twoSecondaryCaregivers',
      'signAsRepresentativeNoRep',
      'signAsRepresentativeNo',
      'signAsRepresentativeYes',
    ],
    fixtures: {
      data: path.join(__dirname, 'fixtures', 'data'),
      mocks: path.join(__dirname, 'fixtures', 'mocks'),
    },

    setupPerTest: () => {
      cy.server();
      cy.intercept('GET', '/v0/feature_toggles?*', featureToggles);
      cy.intercept('POST', 'v0/form1010cg/attachments', mockUpload);
    },
    pageHooks: {
      introduction: () => {
        // Hit the start button
        cy.findAllByText(/start/i, { selector: 'a' })
          .first()
          .click();
      },
      'review-and-submit': () => {
        cy.get('@testKey').then(testKey => {
          switch (testKey) {
            case 'secondaryOneOnly':
              // Check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // check secondary caregiver content && sign
              checkContent(
                secondaryOneLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryOneLabel, 'George Geef Goofus');

              break;
            case 'oneSecondaryCaregivers':
              // check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // Check primary caregiver content && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');

              // Check secondaryOne caregiver content && sign
              checkContent(
                secondaryOneLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryOneLabel, 'George Geef Goofus');

              break;
            case 'twoSecondaryCaregivers':
              // check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // Check primary caregiver content && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');

              // Check secondaryOne caregiver content && sign
              checkContent(
                secondaryOneLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryOneLabel, 'George Geef Goofus');

              // Check secondaryTwo caregiver content && sign
              checkContent(
                secondaryTwoLabel,
                secondaryCaregiverContent,
                mockSecondaryCaregiverContent,
              );
              signAsParty(secondaryTwoLabel, 'Donald Duck');
              break;
            case 'signAsRepresentativeYes':
            case 'signAsRepresentativeNoRep':
              // check veteran content && sign as representative
              checkContent(
                representativeLabel,
                representativeSignatureContent,
                mockRepresentativeSignatureContent,
              );
              signAsParty(representativeLabel, 'Mini Mouse');

              // Check primary caregiver && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');
              break;
            default:
              // check veteran content && sign
              checkContent(
                veteranLabel,
                veteranSignatureContent,
                mockVeteranSignatureContent,
              );
              signAsParty(veteranLabel, 'Micky Mouse');

              // Check primary caregiver && sign
              checkContent(
                primaryLabel,
                primaryCaregiverContent,
                mockPrimaryCaregiverContent,
              );
              signAsParty(primaryLabel, 'Mini Mouse');
              break;
          }
        });
        // sign signature as veteran

        cy.route({
          method: 'POST',
          url: '/v0/caregivers_assistance_claims',
          status: 200,
          response: {
            body: {
              data: {
                id: '',
                type: 'form1010cg_submissions',
                attributes: {
                  confirmationNumber: 'aB935000000F3VnCAK',
                  submittedAt: '2020-08-06T19:18:11+00:00',
                },
              },
            },
          },
        });
      },
    },
  },
  manifest,
  formConfig,
);

testForm(testSecondaryTwo);
<|endoftext|>


<commit_before>/**
 * Shopware 4.0
 * Copyright © 2012 shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 *
 * @category   Shopware
 * @package    Article
 * @subpackage Detail
 * @copyright  Copyright (c) 2012, shopware AG (http://www.shopware.de)
 * @version    $Id$
 * @author shopware AG
 */

/**
 * Shopware UI - Article detail page
 * The properties component contains the grid panel for the article properties.
 * The grid supports a multi selection over a grid combo box element.
 * On top of the grid, a combo box displayed where the user can select a property group.
 * After the selection of a property group, the group options will be displayed in the grid.
 */
//{namespace name=backend/article/view/main}
//{block name="backend/article/view/detail/properties"}
Ext.define('Shopware.apps.Article.view.detail.Properties', {
    /**
     * Define that the billing field set is an extension of the Ext.form.FieldSet
     * @string
     */
    extend:'Ext.form.FieldSet',
    /**
     * The Ext.container.Container.layout for the fieldset's immediate child items.
     * @object
     */
    layout: 'anchor',
    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     * @string
     */
    alias:'widget.article-properties-field-set',
    /**
     * Set css class for this component
     * @string
     */
    cls: Ext.baseCSSPrefix + 'article-properties-field-set',
    /**
     * Contains all snippets for the view component
     * @object
     */
    snippets:{
        title:'{s name=detail/properties/title}Properties{/s}',
        notice:'{s name=detail/properties/notice}To configure an article property, please select a suitable property group via the selection box. Hereafter, a grid with all property values will be displayed. To change the values as well, you can click on the second grid column and modify the value via combo box (multiple selection possible).{/s}',
        property:'{s name=detail/properties/property}Select property{/s}',
        name:'{s name=detail/properties/name_column}Property{/s}',
        value:'{s name=detail/properties/value_column}Values{/s}',
        empty:'{s name=empty}Please select...{/s}'
    },
    /**
     * Contains the field set defaults.
     */
    defaults: {
        labelWidth: 155,
        anchor: '100%'
    },

    /**
	 * The initComponent template method is an important initialization step for a Component.
     * It is intended to be implemented by each subclass of Ext.Component to provide any needed constructor logic.
     * The initComponent method of the class being created is called first,
     * with each initComponent method up the hierarchy to Ext.Component being called thereafter.
     * This makes it easy to implement and, if needed, override the constructor logic of the Component at any step in the hierarchy.
     * The initComponent method must contain a call to callParent in order to ensure that the parent class' initComponent method is also called.
	 *
	 * @return void
	 */
    initComponent:function () {
        var me = this,
            mainWindow = me.subApp.articleWindow;

        mainWindow.on('storesLoaded', me.onStoresLoaded, me);
        me.title = me.snippets.title;
        me.items = me.createElements();
        me.callParent(arguments);
    },

    /**
     * Creates the elements for the properties field set.
     * @return Array
     */
    createElements: function () {
        var me = this;

        var notice = Ext.create('Ext.container.Container', {
            html: me.snippets.notice,
            style: 'font-style: italic; color: #999; margin: 0 0 8px 0; font-size: 11px;'
        });

        me.propertyGrid = me.createPropertyGrid();

        me.propertyCombo = Ext.create('Ext.form.field.ComboBox', {
            name: 'filterGroupId',
            labelWidth: 155,
            forceSelection: false,
            queryMode: 'local',
            valueField: 'id',
            displayField: 'name',
            emptyText: me.snippets.empty,
            fieldLabel: me.snippets.property
        });

        return [ notice, me.propertyCombo, me.propertyGrid ];
    },

    /**
     * Creates the grid panel for the article properties.
     * @return Ext.grid.Panel
     */
    createPropertyGrid: function() {
        var me = this, store = null;

        return me.propertyGrid = Ext.create('Ext.grid.Panel', {
            height: 255,
            name: 'property-grid',
            cls: Ext.baseCSSPrefix + 'free-standing-grid ' + Ext.baseCSSPrefix + 'article-properties-grid',
            title: '{s name=detail/property/title}Properties{/s}',
            plugins: [{
                ptype: 'cellediting',
                clicksToEdit: 1,
                cls: Ext.baseCSSPrefix + 'article-properties-grid-editor'
            }],
            selType: 'cellmodel',
            columns: [
                {
                    header: me.snippets.name,
                    dataIndex: 'name',
                    editor: {
                        xtype: 'textfield',
                        readOnly: true
                    },
                    width: 150
                } , {
                    header: me.snippets.value,
                    dataIndex: 'value',
                    flex: 1,
                    renderer: me.getValueRenderer,
                    editor: me.getValueEditor()
                }
            ]
        });
    },

    getValueEditor: function() {
        var me = this;
        return me.valueEditor =  Ext.create('Ext.ux.form.field.BoxSelect', {
            store: me.valueStore,
            multiSelect: true,
            forceSelection: false,
            createNewOnEnter: true,
            createNewOnBlur: true,
            delimiter: ', ',
            typeAhead: true,
            displayField: 'value',
            valueField: 'id',
            queryMode: 'remote',
            cls: Ext.baseCSSPrefix + 'article-properties-box-selection'
        });
    },

    getValueRenderer: function(values, metadata, record, rowIndex, colIndex) {
        var me = this,
            column = me.columns[colIndex],
            result = [];
        if(!column.editor && !column._editor) {
            return value;
        }
        if(!column._editor) {
            column._editor = column.editor;
        }

        var editor = column._editor,
            store = editor.store || me.valueStore;

        Ext.each(values, function(value, key) {
            var map = store.getById(value);
            result[result.length] = map ? map.get(editor.displayField) : value;
        });

        return result.join(', ');
    },

    onStoresLoaded: function(article, stores) {
        var me = this, propertyStore = stores['properties'];
        me.article = article;
        me.store = Ext.data.StoreManager.lookup('Property');
        me.valueStore = Ext.data.StoreManager.lookup('PropertyValue');

        me.propertyCombo.bindStore(propertyStore);
        me.propertyGrid.reconfigure(me.store);
        me.valueEditor.bindStore(me.valueStore);
    }
});
//{/block}
<commit_msg>SW-7922 fine tuning poperty combobox settings<commit_after>/**
 * Shopware 4.0
 * Copyright © 2012 shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 *
 * @category   Shopware
 * @package    Article
 * @subpackage Detail
 * @copyright  Copyright (c) 2012, shopware AG (http://www.shopware.de)
 * @version    $Id$
 * @author shopware AG
 */

/**
 * Shopware UI - Article detail page
 * The properties component contains the grid panel for the article properties.
 * The grid supports a multi selection over a grid combo box element.
 * On top of the grid, a combo box displayed where the user can select a property group.
 * After the selection of a property group, the group options will be displayed in the grid.
 */
//{namespace name=backend/article/view/main}
//{block name="backend/article/view/detail/properties"}
Ext.define('Shopware.apps.Article.view.detail.Properties', {
    /**
     * Define that the billing field set is an extension of the Ext.form.FieldSet
     * @string
     */
    extend:'Ext.form.FieldSet',
    /**
     * The Ext.container.Container.layout for the fieldset's immediate child items.
     * @object
     */
    layout: 'anchor',
    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     * @string
     */
    alias:'widget.article-properties-field-set',
    /**
     * Set css class for this component
     * @string
     */
    cls: Ext.baseCSSPrefix + 'article-properties-field-set',
    /**
     * Contains all snippets for the view component
     * @object
     */
    snippets:{
        title:'{s name=detail/properties/title}Properties{/s}',
        notice:'{s name=detail/properties/notice}To configure an article property, please select a suitable property group via the selection box. Hereafter, a grid with all property values will be displayed. To change the values as well, you can click on the second grid column and modify the value via combo box (multiple selection possible).{/s}',
        property:'{s name=detail/properties/property}Select property{/s}',
        name:'{s name=detail/properties/name_column}Property{/s}',
        value:'{s name=detail/properties/value_column}Values{/s}',
        empty:'{s name=empty}Please select...{/s}'
    },
    /**
     * Contains the field set defaults.
     */
    defaults: {
        labelWidth: 155,
        anchor: '100%'
    },

    /**
	 * The initComponent template method is an important initialization step for a Component.
     * It is intended to be implemented by each subclass of Ext.Component to provide any needed constructor logic.
     * The initComponent method of the class being created is called first,
     * with each initComponent method up the hierarchy to Ext.Component being called thereafter.
     * This makes it easy to implement and, if needed, override the constructor logic of the Component at any step in the hierarchy.
     * The initComponent method must contain a call to callParent in order to ensure that the parent class' initComponent method is also called.
	 *
	 * @return void
	 */
    initComponent:function () {
        var me = this,
            mainWindow = me.subApp.articleWindow;

        mainWindow.on('storesLoaded', me.onStoresLoaded, me);
        me.title = me.snippets.title;
        me.items = me.createElements();
        me.callParent(arguments);
    },

    /**
     * Creates the elements for the properties field set.
     * @return Array
     */
    createElements: function () {
        var me = this;

        var notice = Ext.create('Ext.container.Container', {
            html: me.snippets.notice,
            style: 'font-style: italic; color: #999; margin: 0 0 8px 0; font-size: 11px;'
        });

        me.propertyGrid = me.createPropertyGrid();

        me.propertyCombo = Ext.create('Ext.form.field.ComboBox', {
            name: 'filterGroupId',
            labelWidth: 155,
            forceSelection: false,
            queryMode: 'local',
            valueField: 'id',
            displayField: 'name',
            emptyText: me.snippets.empty,
            fieldLabel: me.snippets.property
        });

        return [ notice, me.propertyCombo, me.propertyGrid ];
    },

    /**
     * Creates the grid panel for the article properties.
     * @return Ext.grid.Panel
     */
    createPropertyGrid: function() {
        var me = this, store = null;

        return me.propertyGrid = Ext.create('Ext.grid.Panel', {
            height: 255,
            name: 'property-grid',
            cls: Ext.baseCSSPrefix + 'free-standing-grid ' + Ext.baseCSSPrefix + 'article-properties-grid',
            title: '{s name=detail/property/title}Properties{/s}',
            plugins: [{
                ptype: 'cellediting',
                clicksToEdit: 1,
                cls: Ext.baseCSSPrefix + 'article-properties-grid-editor'
            }],
            selType: 'cellmodel',
            columns: [
                {
                    header: me.snippets.name,
                    dataIndex: 'name',
                    editor: {
                        xtype: 'textfield',
                        readOnly: true
                    },
                    width: 150
                } , {
                    header: me.snippets.value,
                    dataIndex: 'value',
                    flex: 1,
                    renderer: me.getValueRenderer,
                    editor: me.getValueEditor()
                }
            ]
        });
    },

    getValueEditor: function() {
        var me = this;
        return me.valueEditor =  Ext.create('Ext.ux.form.field.BoxSelect', {
            store: me.valueStore,
            multiSelect: true,
            forceSelection: false,
            createNewOnEnter: true,
            createNewOnBlur: true,
            delimiter: ', ',
            typeAhead: true,
            displayField: 'value',
            valueField: 'id',
            queryMode: 'remote',
            minChars: 2,
            queryDelay: 750,
            cls: Ext.baseCSSPrefix + 'article-properties-box-selection'
        });
    },

    getValueRenderer: function(values, metadata, record, rowIndex, colIndex) {
        var me = this,
            column = me.columns[colIndex],
            result = [];
        if(!column.editor && !column._editor) {
            return value;
        }
        if(!column._editor) {
            column._editor = column.editor;
        }

        var editor = column._editor,
            store = editor.store || me.valueStore;

        Ext.each(values, function(value, key) {
            var map = store.getById(value);
            result[result.length] = map ? map.get(editor.displayField) : value;
        });

        return result.join(', ');
    },

    onStoresLoaded: function(article, stores) {
        var me = this, propertyStore = stores['properties'];
        me.article = article;
        me.store = Ext.data.StoreManager.lookup('Property');
        me.valueStore = Ext.data.StoreManager.lookup('PropertyValue');

        me.propertyCombo.bindStore(propertyStore);
        me.propertyGrid.reconfigure(me.store);
        me.valueEditor.bindStore(me.valueStore);
    }
});
//{/block}
<|endoftext|>


<commit_before>(function () {
  'use strict';

  angular
    .module('app')
    .constant('Config', {
      sendEmailUrl: 'https://sunnymead-sciencecat.c9users.io/sendEmail'
    });

})();<commit_msg>update config<commit_after>(function () {
  'use strict';

  angular
    .module('app')
    .constant('Config', {
      sendEmailUrl: 'https://sunnymead-staging.herokuapp.com/sendEmail'
    });

})();<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
**/

// Controller for result page
App.Controllers.controller('ResultDetailCtrl', ['$rootScope', '$scope', '$http', '$stateParams',
function($rootScope, $scope, $http, $stateParams) {

	// Grab all figures
	$scope.result = $stateParams.resultId;

	$http.jsonp($rootScope.baseURL + '/getResults//' + $scope.result + '?callback=JSON_CALLBACK')
	.success(function(data) {
	  if (data.length < 1){
		$scope.figures = null;
		$scope.alertMessage = "No results found.";
		$scope.alertClass = "alert alert-danger";
	  } else {
		$scope.figures = data;
	  }
	});

}]);
<commit_msg>CLIMATE-333 - Update ResultDetailCtrl endpoints and result handling<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
**/

// Controller for result page
App.Controllers.controller('ResultDetailCtrl', ['$rootScope', '$scope', '$http', '$stateParams',
function($rootScope, $scope, $http, $stateParams) {
	$scope.result = $stateParams.resultId;

	$http.jsonp($rootScope.baseURL + '/dir/results/' + $scope.result + '?callback=JSON_CALLBACK')
	.success(function(data) {
		data = data['listing'];

		if (data.length < 1) {
			$scope.figures = null;
			$scope.alertMessage = "No results found.";
			$scope.alertClass = "alert alert-danger";
		} else {
			$scope.figures = data;
		}
	});

}]);
<|endoftext|>


<commit_before><commit_msg>test-commit<commit_after>var AddMyBag = angular.module("mohApp", ['ngRoute']);<|endoftext|>


<commit_before>import Creature from '../Creature.js';
import Strategies from '../strategies/Strategies.js';

import Weapon from '../../weapons/Weapon.js';
import DamageTypes from '../../DamageTypes.js';

class ImpSlingshot extends Weapon {
    getRange() {
        return 3;
    }

    getDamage() {
        return 2;
    }

    getDamageType() {
        return DamageTypes.RANGED_PHYSICAL;
    }
}

export default class SlingshotImp extends Creature {
    /**
      * @class SlingshotImp
      * @description Basic ranged enemy. Stands in place an shoots enemies
      */
    constructor() {
        super();
        this.setStrategy(new Strategies.CompositeStrategy(
            new Strategies.ChaseStrategy(),
            new Strategies.FleeStrategy(),
            new Strategies.IdleStrategy()
        ));
    }

    getMeleeWeapon() {
        return null;
    }

    getRangedWeapon() {
        return new ImpSlingshot();
    }

    getBaseHP() {
        return 3;
    }

    getSpeed() {
        return 550;
    }
}
<commit_msg>Made Imp use same sling as player<commit_after>import Creature from '../Creature.js';
import Strategies from '../strategies/Strategies.js';

import Sling from '../../weapons/Sling.js';

export default class SlingshotImp extends Creature {
    /**
      * @class SlingshotImp
      * @description Basic ranged enemy.
      */
    constructor() {
        super();
        this.addItem(new Sling());
        this.setStrategy(new Strategies.CompositeStrategy(
            new Strategies.ChaseStrategy(),
            new Strategies.FleeStrategy(),
            new Strategies.IdleStrategy()
        ));
    }

    getBaseHP() {
        return 3;
    }

    getSpeed() {
        return 550;
    }
}
<|endoftext|>


<commit_before>app.config(["$locationProvider", function($locationProvider) {
	$locationProvider.html5Mode(true);
}]);

app.config(["$routeProvider", function($routeProvider) {
	$routeProvider
		.when("/subreddits", {
			controller: "SubredditListController",
			templateUrl: "/dev-partials/subreddit-list.html"
		})
		.when("/r/:subredditId/comments/:threadId/:title?", {
			controller: "ThreadDetailController",
			templateUrl: "/dev-partials/thread-detail.html"
		})
		.when("/r/:subredditIds/:section?", {
			controller: "ThreadListController",
			templateUrl: "/dev-partials/thread-list.html"
		})
		.when("/:subredditIds?", {
			controller: "ThreadListController",
			templateUrl: "/dev-partials/thread-list.html"
		})
		.otherwise({
			redirectTo: "/"
		});
}]);

app.config(["threadProcessorProvider", function(threadProcessor) {
	threadProcessor.setImgurClientId("2cf931a0831396f");
	threadProcessor.setMaxThreadsToProcessSimultaneously(3);
}]);
<commit_msg>Changed threadProcessor.setMaxThreadsToProcessSimultaneously from 3 to 2 to reduce loading time for images with a large filesize.<commit_after>app.config(["$locationProvider", function($locationProvider) {
	$locationProvider.html5Mode(true);
}]);

app.config(["$routeProvider", function($routeProvider) {
	$routeProvider
		.when("/subreddits", {
			controller: "SubredditListController",
			templateUrl: "/dev-partials/subreddit-list.html"
		})
		.when("/r/:subredditId/comments/:threadId/:title?", {
			controller: "ThreadDetailController",
			templateUrl: "/dev-partials/thread-detail.html"
		})
		.when("/r/:subredditIds/:section?", {
			controller: "ThreadListController",
			templateUrl: "/dev-partials/thread-list.html"
		})
		.when("/:subredditIds?", {
			controller: "ThreadListController",
			templateUrl: "/dev-partials/thread-list.html"
		})
		.otherwise({
			redirectTo: "/"
		});
}]);

app.config(["threadProcessorProvider", function(threadProcessor) {
	threadProcessor.setImgurClientId("2cf931a0831396f");
	threadProcessor.setMaxThreadsToProcessSimultaneously(2);
}]);
<|endoftext|>