<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

;(function() {
    'use strict';

    // handle errors
    var errorArray = [];
    var newsletterErrors = document.getElementById('newsletter-errors');
    function err(e) {
        var errorList = document.createElement('ul');

        if(errorArray.length) {
            for (var i = 0; i < errorArray.length; i++) {
                var item = document.createElement('li');
                item.appendChild(document.createTextNode(errorArray[i]));
                errorList.appendChild(item);
            }
        } else {
            subscribe(false, true);
        }

        newsletterErrors.appendChild(errorList);
        newsletterErrors.style.display = 'block';
    }

    /* HTML5 "required" validation feedback is not cross-browser compatible
     * so we have to roll our own.
     * Add .invalid class to :invalid elements; remove on submit.
     */
    function validate(form) {

        var already_invalid = form.querySelectorAll('.invalid');
        for (var i = 0; i < already_invalid.length; ++i) {
            var element = already_invalid[i];
            element.className = element.className.replace(/ *invalid/g, '');
        }
        var invalid = form.querySelectorAll('input:invalid');
        for (i = 0; i < invalid.length; ++i) {
            invalid[i].parentNode.parentNode.className += ' invalid';
        }
        if (invalid.length > 0) {
            err(new Error('Please complete the form below.'));
            return false;
        }
        return true;
    }

    // XHR subscribe; handle errors; display thanks message on success.
    function subscribe(evt, skipXHR) {
        if(skipXHR) {
            return true;
        }
        evt.preventDefault();
        evt.stopPropagation();

        // new submission, clear old errors
        errorArray = [];
        newsletterErrors.style.display = 'none';
        while (newsletterErrors.firstChild) newsletterErrors.removeChild(newsletterErrors.firstChild);

        var form = document.getElementById('newsletter-signup');
        if (!validate(form)) {
            return false;
        }

        var fmt = document.getElementById('fmt').value;
        var email = document.getElementById('newsletter-email').value;
        var newsletter = document.querySelector('input[name="newsletters"]:checked') ? document.querySelector('input[name="newsletters"]:checked').value : '';
        var privacy = document.querySelector('input[name="privacy"]:checked') ? '&privacy=true' : '';
        var thanks = document.getElementById('newsletter-thanks');
        var params = 'email=' + encodeURIComponent(email) +
                     '&newsletters=' + newsletter +
                     privacy +
                     '&fmt=' + fmt;

        var xhr = new XMLHttpRequest();

        xhr.onload = function(r) {
            if (r.target.status >= 200 && r.target.status < 300) {
                var response = r.target.response;
                if (response.success === true) {
                    form.style.display = 'none';
                    thanks.style.display = 'block';
                    if(window.vs.analytics) {
                        window.vs.analytics.trackEvent({ category: 'signup', action: 'newsletter', label: String(newsletter) });
                    }
                }
                else {
                    if(response.errors) {
                        for (var i = 0; i < response.errors.length; i++) {
                            errorArray.push(response.errors[i]);
                        }
                    }
                    err(new Error());
                }
            }
            else {
                err(new Error());
                if(window.vs.analytics) {
                    window.vs.analytics.trackEvent({ category: 'Error', action: 'XMLHttpRequest', label: String(r.target.status) });
                }
            }
        };

        xhr.onerror = function(e) {
            err(e);
        };

        var url = form.getAttribute('action');

        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
        xhr.timeout = 5000;
        xhr.ontimeout = err;
        xhr.responseType = 'json';
        xhr.send(params);

        return false;
    }

    var newsletterForm = document.getElementById('newsletter-signup');
    if(newsletterForm){
        newsletterForm.addEventListener('submit', subscribe, false);
    }
})();
<commit_msg>Revert "Resubmit without XHR if problem contacting server."<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

;(function() {
    'use strict';

    // handle errors
    var errorArray = [];
    var newsletterErrors = document.getElementById('newsletter-errors');
    function err(e) {
        var errorList = document.createElement('ul');

        if(errorArray.length) {
            for (var i = 0; i < errorArray.length; i++) {
                var item = document.createElement('li');
                item.appendChild(document.createTextNode(errorArray[i]));
                errorList.appendChild(item);
            }
        } else {
            var item = document.createElement('li');
            item.appendChild(document.createTextNode('An error occurred contacting the server. Please try again later.'));
            errorList.appendChild(item);
        }

        newsletterErrors.appendChild(errorList);
        newsletterErrors.style.display = 'block';
    }

    /* HTML5 "required" validation feedback is not cross-browser compatible
     * so we have to roll our own.
     * Add .invalid class to :invalid elements; remove on submit.
     */
    function validate(form) {

        var already_invalid = form.querySelectorAll('.invalid');
        for (var i = 0; i < already_invalid.length; ++i) {
            var element = already_invalid[i];
            element.className = element.className.replace(/ *invalid/g, '');
        }
        var invalid = form.querySelectorAll('input:invalid');
        for (i = 0; i < invalid.length; ++i) {
            invalid[i].parentNode.parentNode.className += ' invalid';
        }
        if (invalid.length > 0) {
            err(new Error('Please complete the form below.'));
            return false;
        }
        return true;
    }

    // XHR subscribe; handle errors; display thanks message on success.
    function subscribe(evt) {
        evt.preventDefault();
        evt.stopPropagation();

        // new submission, clear old errors
        errorArray = [];
        newsletterErrors.style.display = 'none';
        while (newsletterErrors.firstChild) newsletterErrors.removeChild(newsletterErrors.firstChild);

        var form = document.getElementById('newsletter-signup');
        if (!validate(form)) {
            return false;
        }

        var fmt = document.getElementById('fmt').value;
        var email = document.getElementById('newsletter-email').value;
        var newsletter = document.querySelector('input[name="newsletters"]:checked') ? document.querySelector('input[name="newsletters"]:checked').value : '';
        var privacy = document.querySelector('input[name="privacy"]:checked') ? '&privacy=true' : '';
        var thanks = document.getElementById('newsletter-thanks');
        var params = 'email=' + encodeURIComponent(email) +
                     '&newsletters=' + newsletter +
                     privacy +
                     '&fmt=' + fmt;

        var xhr = new XMLHttpRequest();

        xhr.onload = function(r) {
            if (r.target.status >= 200 && r.target.status < 300) {
                var response = r.target.response;
                if (response.success === true) {
                    form.style.display = 'none';
                    thanks.style.display = 'block';
                    if(window.vs.analytics) {
                        window.vs.analytics.trackEvent({ category: 'signup', action: 'newsletter', label: String(newsletter) });
                    }
                }
                else {
                    if(response.errors) {
                        for (var i = 0; i < response.errors.length; i++) {
                            errorArray.push(response.errors[i]);
                        }
                    }
                    err(new Error());
                }
            }
            else {
                err(new Error());
                if(window.vs.analytics) {
                    window.vs.analytics.trackEvent({ category: 'Error', action: 'XMLHttpRequest', label: String(r.target.status) });
                }
            }
        };

        xhr.onerror = function(e) {
            err(e);
        };

        var url = form.getAttribute('action');

        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
        xhr.timeout = 5000;
        xhr.ontimeout = err;
        xhr.responseType = 'json';
        xhr.send(params);

        return false;
    }

    var newsletterForm = document.getElementById('newsletter-signup');
    if(newsletterForm){
        newsletterForm.addEventListener('submit', subscribe, false);
    }
})();
<|endoftext|>


<commit_before>/* eslint-disable max-len */

import path from 'path';

import config from 'config';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin';
import webpackIsomorphicToolsConfig from './webpack-isomorphic-tools-config';
import webpack from 'webpack';

import SriStatsPlugin from 'sri-stats-webpack-plugin';

import { getClientConfig } from 'core/utils';

const clientConfig = getClientConfig(config);

const appName = config.get('appName');
const appsBuildList = appName ? [appName] : config.get('validAppNames');

const entryPoints = {};
for (const app of appsBuildList) {
  entryPoints[app] = `src/${app}/client`;
}

export default {
  devtool: 'source-map',
  context: path.resolve(__dirname),
  progress: true,
  entry: entryPoints,
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]-[chunkhash].js',
    chunkFilename: '[name]-[chunkhash].js',
    publicPath: config.has('staticHost') ? `${config.get('staticHost')}/` : '/',
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
      }, {
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract('style', 'css?importLoaders=2&sourceMap!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true'),
      }, {
        test: /\.svg$/,
        loader: 'url?limit=10000&mimetype=image/svg+xml',
      }, {
        test: /\.jpg$/,
        loader: 'url?limit=10000&mimetype=image/jpeg',
      }, {
        test: /\.webm$/,
        loader: 'url?limit=10000&mimetype=video/webm',
      }, {
        test: /\.mp4$/,
        loader: 'url?limit=10000&mimetype=video/mp4',
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({
      CLIENT_CONFIG: JSON.stringify(clientConfig),
      'process.env.NODE_ENV': JSON.stringify('production'),
    }),
    // Replaces server config module with the subset clientConfig object.
    new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'),
    // Substitutes client only config.
    new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'),
    // Use the browser's window for window.
    new webpack.NormalModuleReplacementPlugin(/core\/window/, 'core/browserWindow.js'),
    // This allow us to exclude locales for other apps being built.
    new webpack.ContextReplacementPlugin(
      /locale$/,
      new RegExp(`^\\.\\/.*?\\/${appName}\\.json$`)
    ),
    new ExtractTextPlugin('[name]-[chunkhash].css', {allChunks: true}),
    new SriStatsPlugin({
      algorithm: 'sha512',
      write: true,
      saveAs: path.join(__dirname, 'dist/sri.json'),
    }),
    // optimizations
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        drop_console: true,
      },
    }),
    new WebpackIsomorphicToolsPlugin(webpackIsomorphicToolsConfig),
  ],
  resolve: {
    alias: {
      'normalize.css': 'normalize.css/normalize.css',
    },
    root: [
      path.resolve(__dirname),
    ],
    modulesDirectories: ['node_modules', 'src'],
    extensions: ['', '.js', '.jsx'],
  },
};
<commit_msg>Use contenthash for CSS<commit_after>/* eslint-disable max-len */

import path from 'path';

import config from 'config';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin';
import webpackIsomorphicToolsConfig from './webpack-isomorphic-tools-config';
import webpack from 'webpack';

import SriStatsPlugin from 'sri-stats-webpack-plugin';

import { getClientConfig } from 'core/utils';

const clientConfig = getClientConfig(config);

const appName = config.get('appName');
const appsBuildList = appName ? [appName] : config.get('validAppNames');

const entryPoints = {};
for (const app of appsBuildList) {
  entryPoints[app] = `src/${app}/client`;
}

export default {
  devtool: 'source-map',
  context: path.resolve(__dirname),
  progress: true,
  entry: entryPoints,
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]-[chunkhash].js',
    chunkFilename: '[name]-[chunkhash].js',
    publicPath: config.has('staticHost') ? `${config.get('staticHost')}/` : '/',
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
      }, {
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract('style', 'css?importLoaders=2&sourceMap!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true'),
      }, {
        test: /\.svg$/,
        loader: 'url?limit=10000&mimetype=image/svg+xml',
      }, {
        test: /\.jpg$/,
        loader: 'url?limit=10000&mimetype=image/jpeg',
      }, {
        test: /\.webm$/,
        loader: 'url?limit=10000&mimetype=video/webm',
      }, {
        test: /\.mp4$/,
        loader: 'url?limit=10000&mimetype=video/mp4',
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({
      CLIENT_CONFIG: JSON.stringify(clientConfig),
      'process.env.NODE_ENV': JSON.stringify('production'),
    }),
    // Replaces server config module with the subset clientConfig object.
    new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'),
    // Substitutes client only config.
    new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'),
    // Use the browser's window for window.
    new webpack.NormalModuleReplacementPlugin(/core\/window/, 'core/browserWindow.js'),
    // This allow us to exclude locales for other apps being built.
    new webpack.ContextReplacementPlugin(
      /locale$/,
      new RegExp(`^\\.\\/.*?\\/${appName}\\.json$`)
    ),
    new ExtractTextPlugin('[name]-[contenthash].css', {allChunks: true}),
    new SriStatsPlugin({
      algorithm: 'sha512',
      write: true,
      saveAs: path.join(__dirname, 'dist/sri.json'),
    }),
    // optimizations
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        drop_console: true,
      },
    }),
    new WebpackIsomorphicToolsPlugin(webpackIsomorphicToolsConfig),
  ],
  resolve: {
    alias: {
      'normalize.css': 'normalize.css/normalize.css',
    },
    root: [
      path.resolve(__dirname),
    ],
    modulesDirectories: ['node_modules', 'src'],
    extensions: ['', '.js', '.jsx'],
  },
};
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { reduxForm, Field, propTypes, formValueSelector } from 'redux-form';
import { Grid, Row, Col } from 'react-flexbox-grid/lib';
import withIntlForm from '../../common/hocs/IntlForm';
import AppButton from '../../common/AppButton';
import withHelp from '../../common/hocs/HelpfulContainer';
import CopyAllComponent from '../../common/CopyAllComponent';
import SourceCollectionsMediaForm from '../../common/form/SourceCollectionsMediaForm';
import MediaPickerDialog from '../../common/mediaPicker/MediaPickerDialog';
import QueryHelpDialog from '../../common/help/QueryHelpDialog';
import MediaHelpDialog from '../../common/help/MediaHelpDialog';
import SavedSearchControls from './SavedSearchControls';
import { emptyString, validDate } from '../../../lib/formValidators';
import { isStartDateAfterEndDate, isValidSolrDate } from '../../../lib/dateUtil';
import { KEYWORD, MEDIA, DATES } from '../../../lib/explorerUtil';
import messages from '../../../resources/messages';

const formSelector = formValueSelector('queryForm');

const localMessages = {
  mainTitle: { id: 'explorer.queryBuilder.maintitle', defaultMessage: 'Create Query' },
  addButton: { id: 'explorer.queryBuilder.saveAll', defaultMessage: 'Search' },
  feedback: { id: 'explorer.queryBuilder.feedback', defaultMessage: 'We saved your new source' },
  query: { id: 'explorer.queryBuilder.query', defaultMessage: 'Enter search terms' },
  queryDesc: { id: 'explorer.queryBuilder.query.desc', defaultMessage: 'Media Cloud will return stories that match your search query. We use standard boolean search syntax.' },
  selectSandC: { id: 'explorer.queryBuilder.selectSAndC', defaultMessage: 'Select your media' },
  selectSandCDesc: { id: 'explorer.queryBuilder.selectSAndCDesc', defaultMessage: 'Choose individual sources or collections to be searched. Our system includes collections for a large range of countries, in multiple languages.' },
  selectSandCDescLink: { id: 'explorer.queryBuilder.selectSAndCDescLink', defaultMessage: 'Learn more about choosing media.' },
  SandC: { id: 'explorer.queryBuilder.sAndC', defaultMessage: 'Media' },
  color: { id: 'explorer.queryBuilder.color', defaultMessage: 'Choose a color' },
  dates: { id: 'explorer.queryBuilder.dates', defaultMessage: 'Enter dates' },
  datesDesc: { id: 'explorer.queryBuilder.datesDesc', defaultMessage: 'Our database goes back to 2011, however the start date for different sources and collections can vary. Click on a source or collecton to learn more about when we added it.' },
  dateTo: { id: 'explorer.queryBuilder.dateTo', defaultMessage: 'to' },
  queryHelpTitle: { id: 'explorer.queryBuilder.queryHelp.title', defaultMessage: 'Building Query Strings' },
  queryHelpContent: { id: 'explorer.queryBuilder.queryHelp.content', defaultMessage: '
You can write boolean queries to search against out database. To search for a single word, just enter that word:
gender
You can also use boolean and phrase searches like this:
"gender equality" OR "gender equity"' },
  saveSearch: { id: 'explorer.queryBuilder.saveQueries', defaultMessage: 'Save Search...' },
  queryStringError: { id: 'explorer.queryBuilder.queryStringError', defaultMessage: 'Your {name} query is missing keywords.' },
  startDateWarning: { id: 'explorer.queryBuilder.warning.startDate', defaultMessage: 'Start Date must be before End Date' },
  invalidDateWarning: { id: 'explorer.queryBuilder.warning.invalidDate', defaultMessage: 'Use the YYYY-MM-DD format' },
  noMediaSpecified: { id: 'explorer.queryBuilder.warning.noMediaSpecified', defaultMessage: 'No media selected' },
  copyQueryKeywordTitle: { id: 'explorer.queryform.copyQueryQ', defaultMessage: 'Copy Query Keywords' },
  copyQueryDatesTitle: { id: 'explorer.queryform.copyQueryDates', defaultMessage: 'Copy Query Dates' },
  copyQueryMediaTitle: { id: 'explorer.queryform.copyQueryMedia', defaultMessage: 'Copy Query Media' },
  copyQueryKeywordMsg: { id: 'explorer.queryform.title.copyQueryQ', defaultMessage: 'Are you sure you want to copy these keywords to all your queries? This will replace the keyword for all your queries.' },
  copyQueryDatesMsg: { id: 'explorer.queryform.title.copyQueryDates', defaultMessage: 'Are you sure you want to copy these dates to all your queries? This will replace the dates for all your queries.' },
  copyQueryMediaMsg: { id: 'explorer.queryform.title.copyQueryMedia', defaultMessage: 'Are you sure you want to copy these media to all your queries? This will replace the media for all your queries.' },
};

class QueryForm extends React.Component {
  state = { // do not focus on primary textfield if we have a dialog open
    childDialogOpen: false,
  }

  setQueryFormChildDialogOpen = () => {
    this.setState(prevState => ({ childDialogOpen: !prevState.childDialogOpen }));
  }

  render() {
    const { initialValues, mediaUpdates, onWillSearch, isEditable, selected, buttonLabel, onMediaDelete, onDateChange, handleLoadSearches, handleDeleteSearch, handleLoadSelectedSearch, savedSearches, searchNickname, handleSaveSearch,
      submitting, handleSubmit, onSave, onMediaChange, renderTextField, renderTextFieldWithFocus, handleCopyAll } = this.props;
    const { formatMessage } = this.props.intl;
    const updatedMedia = formSelector(this.state, 'media');
    const cleanedInitialValues = initialValues ? { ...initialValues } : {};
    if (cleanedInitialValues.disabled === undefined) {
      cleanedInitialValues.disabled = false;
    }
    cleanedInitialValues.media = [ // merge intial sources and collections into one list for display with `renderFields`
      ...initialValues.sources,
      ...initialValues.collections,
    ];
    selected.media = [ // merge sources and collections into one list for display with `renderFields`
      ...selected.sources,
      ...selected.collections,
    ];
    const currentQ = selected.q;
    let mediaPicker = null;
    let mediaLabel = formatMessage(localMessages.SandC);
    if (isEditable) {
      mediaPicker = (
        <MediaPickerDialog
          initMedia={selected.media ? selected.media : cleanedInitialValues.media}
          onConfirmSelection={selections => onMediaChange(selections)}
          setQueryFormChildDialogOpen={this.setQueryFormChildDialogOpen}
        />
      );
      mediaLabel = formatMessage(localMessages.selectSandC);
    }
    if (!selected) { return null; }
    return (
      <form className="app-form query-form" name="queryForm" onSubmit={handleSubmit(onSave)}>

          <Grid>
            <Row>
              <Col lg={4}>

                    1
                    <CopyAllComponent
                      label={formatMessage(localMessages.query)}
                      title={formatMessage(localMessages.copyQueryKeywordTitle)}
                      msg={formatMessage(localMessages.copyQueryKeywordMsg)}
                      onOk={() => handleCopyAll(KEYWORD)}
                    />

                  <Field
                    className="query-field"
                    name="q"
                    type="text"
                    value={currentQ}
                    multiline
                    rows={3}
                    rowsMax={4}
                    fullWidth
                    onChange={this.focusSelect}
                    component={renderTextFieldWithFocus}
                  />

                  <FormattedMessage {...localMessages.queryDesc} />

                  <QueryHelpDialog trigger={formatMessage(messages.queryHelpLink)} />

              </Col>
              <Col lg={4}>

                    2
                    <CopyAllComponent
                      label={mediaLabel}
                      title={formatMessage(localMessages.copyQueryMediaTitle)}
                      msg={formatMessage(localMessages.copyQueryMediaMsg)}
                      onOk={() => handleCopyAll(MEDIA)}
                    />

                  <SourceCollectionsMediaForm
                    className="query-field"
                    form="queryForm"
                    destroyOnUnmount={false}
                    onDelete={onMediaDelete}
                    initialValues={cleanedInitialValues.media}
                    allowRemoval={isEditable}
                    name="media"
                    title="title"
                    intro="intro"
                  />
                  {mediaPicker}

                    <FormattedMessage {...localMessages.selectSandCDesc} />

                    <MediaHelpDialog trigger={formatMessage(localMessages.selectSandCDescLink)} />

              </Col>
              <Col lg={4}>

                  3
                  <CopyAllComponent
                    label={formatMessage(localMessages.dates)}
                    title={formatMessage(localMessages.copyQueryDatesTitle)}
                    msg={formatMessage(localMessages.copyQueryDatesMsg)}
                    onOk={() => handleCopyAll(DATES)}
                  />

                  <Field
                    className="query-field start-date-wrapper"
                    maxLength="12"
                    name="startDate"
                    type="inline"
                    component={renderTextField}
                    disableunderline="true"
                    disabled={!isEditable}
                    onChange={onDateChange}
                  />

<FormattedMessage {...localMessages.dateTo} />

                  <Field
                    className="query-field end-date-wrapper"
                    maxLength="12"
                    name="endDate"
                    type="inline"
                    component={renderTextField}
                    disableunderline="true"
                    disabled={!isEditable}
                    onChange={onDateChange}
                  />

<FormattedMessage {...localMessages.datesDesc} />

              </Col>
            </Row>
          </Grid>

          <Grid>
            <Row>
              <Col lg={6} />
              <Col lg={6}>

                  <SavedSearchControls
                    searchNickname={searchNickname}
                    savedSearches={savedSearches}
                    handleLoadSearches={handleLoadSearches}
                    handleLoadSelectedSearch={handleLoadSelectedSearch}
                    handleSaveSearch={l => handleSaveSearch(l)}
                    handleDeleteSearch={handleDeleteSearch}
                    submitting={submitting}
                    setQueryFormChildDialogOpen={this.setQueryFormChildDialogOpen}
                  />
                  <AppButton
                    type="submit"
                    label={buttonLabel}
                    disabled={mediaUpdates && mediaUpdates.length === 0 || submitting}
                    onClick={onWillSearch}
                    primary
                  />

              </Col>
            </Row>
          </Grid>

      </form>
    );
  }
}

QueryForm.propTypes = {
  // from context
  intl: PropTypes.object.isRequired,
  renderTextField: PropTypes.func.isRequired,
  renderSelect: PropTypes.func.isRequired,
  renderTextFieldWithFocus: PropTypes.func.isRequired,
  searchNickname: PropTypes.string.isRequired,
  savedSearches: PropTypes.array,

  // from parent
  selected: PropTypes.object.isRequired,
  onSave: PropTypes.func.isRequired,
  onColorChange: PropTypes.func,
  onMediaChange: PropTypes.func,
  buttonLabel: PropTypes.string.isRequired,
  initialValues: PropTypes.object,
  onWillSearch: PropTypes.func,
  handleLoadSearches: PropTypes.func.isRequired,
  handleLoadSelectedSearch: PropTypes.func.isRequired,
  handleSaveSearch: PropTypes.func.isRequired,
  handleDeleteSearch: PropTypes.func.isRequired,
  handleCopyAll: PropTypes.func.isRequired,
  onMediaDelete: PropTypes.func.isRequired,
  onDateChange: PropTypes.func.isRequired,
  // from form healper
  updateQuery: PropTypes.func,
  handleSubmit: PropTypes.func,
  pristine: PropTypes.bool.isRequired,
  submitting: PropTypes.bool.isRequired,
  isEditable: PropTypes.bool.isRequired,
  focusRequested: PropTypes.func.isRequired,
  mediaUpdates: PropTypes.object,
};

const mapStateToProps = state => ({
  mediaUpdates: formSelector(state, 'media'),
});

function validate(values, props) {
  const { formatMessage } = props.intl;
  const errors = {};
  if (emptyString(values.q)) {
    const errString = formatMessage(localMessages.queryStringError, { name: values.label });
    errors.q = { _error: errString };
  }
  if (!validDate(values.startDate) || !isValidSolrDate(values.startDate)) {
    errors.startDate = { _error: formatMessage(localMessages.invalidDateWarning) };
  }
  if (!validDate(values.endDate) || !isValidSolrDate(values.endDate)) {
    errors.endDate = { _error: formatMessage(localMessages.invalidDateWarning) };
  }
  if (validDate(values.startDate) && validDate(values.endDate) && isStartDateAfterEndDate(values.startDate, values.endDate)) {
    errors.startDate = { _error: formatMessage(localMessages.startDateWarning) };
  }
  if ((!values.collections || !values.collections.length)
    && (!values.sources || !values.sources.length)
    && (!values.media || !values.media.length)) {
    errors.media = { _error: formatMessage(localMessages.noMediaSpecified) };
  }
  return errors;
}

function warn(values, props) {
  const { formatMessage } = props.intl;
  const warnings = {};
  if ((!values.collections || !values.collections.length)
    && (!values.sources || !values.sources.length)
    && (!values.media || !values.media.length)) {
    warnings.media = { _warning: formatMessage(localMessages.noMediaSpecified) };
  }
  return warnings;
}

export default
withIntlForm(
  withHelp(localMessages.queryHelpTitle, localMessages.queryHelpContent)(
    reduxForm({ propTypes, validate, warn })(
      connect(mapStateToProps, null)(
        QueryForm
      ),
    ),
  ),
);
<commit_msg>#1260 eval queries and current query to invalidate Search button<commit_after>import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { reduxForm, Field, propTypes, formValueSelector } from 'redux-form';
import { Grid, Row, Col } from 'react-flexbox-grid/lib';
import withIntlForm from '../../common/hocs/IntlForm';
import AppButton from '../../common/AppButton';
import withHelp from '../../common/hocs/HelpfulContainer';
import CopyAllComponent from '../../common/CopyAllComponent';
import SourceCollectionsMediaForm from '../../common/form/SourceCollectionsMediaForm';
import MediaPickerDialog from '../../common/mediaPicker/MediaPickerDialog';
import QueryHelpDialog from '../../common/help/QueryHelpDialog';
import MediaHelpDialog from '../../common/help/MediaHelpDialog';
import SavedSearchControls from './SavedSearchControls';
import { emptyString, validDate } from '../../../lib/formValidators';
import { isStartDateAfterEndDate, isValidSolrDate } from '../../../lib/dateUtil';
import { KEYWORD, MEDIA, DATES } from '../../../lib/explorerUtil';
import messages from '../../../resources/messages';

const formSelector = formValueSelector('queryForm');

const localMessages = {
  mainTitle: { id: 'explorer.queryBuilder.maintitle', defaultMessage: 'Create Query' },
  addButton: { id: 'explorer.queryBuilder.saveAll', defaultMessage: 'Search' },
  feedback: { id: 'explorer.queryBuilder.feedback', defaultMessage: 'We saved your new source' },
  query: { id: 'explorer.queryBuilder.query', defaultMessage: 'Enter search terms' },
  queryDesc: { id: 'explorer.queryBuilder.query.desc', defaultMessage: 'Media Cloud will return stories that match your search query. We use standard boolean search syntax.' },
  selectSandC: { id: 'explorer.queryBuilder.selectSAndC', defaultMessage: 'Select your media' },
  selectSandCDesc: { id: 'explorer.queryBuilder.selectSAndCDesc', defaultMessage: 'Choose individual sources or collections to be searched. Our system includes collections for a large range of countries, in multiple languages.' },
  selectSandCDescLink: { id: 'explorer.queryBuilder.selectSAndCDescLink', defaultMessage: 'Learn more about choosing media.' },
  SandC: { id: 'explorer.queryBuilder.sAndC', defaultMessage: 'Media' },
  color: { id: 'explorer.queryBuilder.color', defaultMessage: 'Choose a color' },
  dates: { id: 'explorer.queryBuilder.dates', defaultMessage: 'Enter dates' },
  datesDesc: { id: 'explorer.queryBuilder.datesDesc', defaultMessage: 'Our database goes back to 2011, however the start date for different sources and collections can vary. Click on a source or collecton to learn more about when we added it.' },
  dateTo: { id: 'explorer.queryBuilder.dateTo', defaultMessage: 'to' },
  queryHelpTitle: { id: 'explorer.queryBuilder.queryHelp.title', defaultMessage: 'Building Query Strings' },
  queryHelpContent: { id: 'explorer.queryBuilder.queryHelp.content', defaultMessage: '
You can write boolean queries to search against out database. To search for a single word, just enter that word:
gender
You can also use boolean and phrase searches like this:
"gender equality" OR "gender equity"' },
  saveSearch: { id: 'explorer.queryBuilder.saveQueries', defaultMessage: 'Save Search...' },
  queryStringError: { id: 'explorer.queryBuilder.queryStringError', defaultMessage: 'Your {name} query is missing keywords.' },
  startDateWarning: { id: 'explorer.queryBuilder.warning.startDate', defaultMessage: 'Start Date must be before End Date' },
  invalidDateWarning: { id: 'explorer.queryBuilder.warning.invalidDate', defaultMessage: 'Use the YYYY-MM-DD format' },
  noMediaSpecified: { id: 'explorer.queryBuilder.warning.noMediaSpecified', defaultMessage: 'No media selected' },
  copyQueryKeywordTitle: { id: 'explorer.queryform.copyQueryQ', defaultMessage: 'Copy Query Keywords' },
  copyQueryDatesTitle: { id: 'explorer.queryform.copyQueryDates', defaultMessage: 'Copy Query Dates' },
  copyQueryMediaTitle: { id: 'explorer.queryform.copyQueryMedia', defaultMessage: 'Copy Query Media' },
  copyQueryKeywordMsg: { id: 'explorer.queryform.title.copyQueryQ', defaultMessage: 'Are you sure you want to copy these keywords to all your queries? This will replace the keyword for all your queries.' },
  copyQueryDatesMsg: { id: 'explorer.queryform.title.copyQueryDates', defaultMessage: 'Are you sure you want to copy these dates to all your queries? This will replace the dates for all your queries.' },
  copyQueryMediaMsg: { id: 'explorer.queryform.title.copyQueryMedia', defaultMessage: 'Are you sure you want to copy these media to all your queries? This will replace the media for all your queries.' },
};

class QueryForm extends React.Component {
  state = { // do not focus on primary textfield if we have a dialog open
    childDialogOpen: false,
  }

  setQueryFormChildDialogOpen = () => {
    this.setState(prevState => ({ childDialogOpen: !prevState.childDialogOpen }));
  }

  evalAllQueriesForValidMedia = () => {
    const { queries, mediaUpdates } = this.props;
    const anyQueriesNoMedia = queries.filter(q => (q.index !== mediaUpdates.index) && q.media && q.media.length === 0).length; // if any query is missing media
    const thisCurrentQueryFormNoMedia = mediaUpdates && (mediaUpdates.media === undefined || mediaUpdates.media.length === 0) && mediaUpdates.sources.length === 0 && mediaUpdates.collections.length === 0;
    return anyQueriesNoMedia || thisCurrentQueryFormNoMedia;
  }

  render() {
    const { initialValues, onWillSearch, isEditable, selected, buttonLabel, onMediaDelete, onDateChange, handleLoadSearches, handleDeleteSearch, handleLoadSelectedSearch, savedSearches, searchNickname, handleSaveSearch,
      submitting, handleSubmit, onSave, onMediaChange, renderTextField, renderTextFieldWithFocus, handleCopyAll } = this.props;
    const { formatMessage } = this.props.intl;
    const cleanedInitialValues = initialValues ? { ...initialValues } : {};
    if (cleanedInitialValues.disabled === undefined) {
      cleanedInitialValues.disabled = false;
    }
    cleanedInitialValues.media = [ // merge intial sources and collections into one list for display with `renderFields`
      ...initialValues.sources,
      ...initialValues.collections,
    ];
    selected.media = [ // merge sources and collections into one list for display with `renderFields`
      ...selected.sources,
      ...selected.collections,
    ];
    const currentQ = selected.q;
    let mediaPicker = null;
    let mediaLabel = formatMessage(localMessages.SandC);
    if (isEditable) {
      mediaPicker = (
        <MediaPickerDialog
          initMedia={selected.media ? selected.media : cleanedInitialValues.media}
          onConfirmSelection={selections => onMediaChange(selections)}
          setQueryFormChildDialogOpen={this.setQueryFormChildDialogOpen}
        />
      );
      mediaLabel = formatMessage(localMessages.selectSandC);
    }
    const queriesMissingMedia = this.evalAllQueriesForValidMedia();
    if (!selected) { return null; }
    return (
      <form className="app-form query-form" name="queryForm" onSubmit={handleSubmit(onSave)}>

          <Grid>
            <Row>
              <Col lg={4}>

                    1
                    <CopyAllComponent
                      label={formatMessage(localMessages.query)}
                      title={formatMessage(localMessages.copyQueryKeywordTitle)}
                      msg={formatMessage(localMessages.copyQueryKeywordMsg)}
                      onOk={() => handleCopyAll(KEYWORD)}
                    />

                  <Field
                    className="query-field"
                    name="q"
                    type="text"
                    value={currentQ}
                    multiline
                    rows={3}
                    rowsMax={4}
                    fullWidth
                    onChange={this.focusSelect}
                    component={renderTextFieldWithFocus}
                  />

                  <FormattedMessage {...localMessages.queryDesc} />

                  <QueryHelpDialog trigger={formatMessage(messages.queryHelpLink)} />

              </Col>
              <Col lg={4}>

                    2
                    <CopyAllComponent
                      label={mediaLabel}
                      title={formatMessage(localMessages.copyQueryMediaTitle)}
                      msg={formatMessage(localMessages.copyQueryMediaMsg)}
                      onOk={() => handleCopyAll(MEDIA)}
                    />

                  <SourceCollectionsMediaForm
                    className="query-field"
                    form="queryForm"
                    destroyOnUnmount={false}
                    onDelete={onMediaDelete}
                    initialValues={cleanedInitialValues.media}
                    allowRemoval={isEditable}
                    name="media"
                    title="title"
                    intro="intro"
                  />
                  {mediaPicker}

                    <FormattedMessage {...localMessages.selectSandCDesc} />

                    <MediaHelpDialog trigger={formatMessage(localMessages.selectSandCDescLink)} />

              </Col>
              <Col lg={4}>

                  3
                  <CopyAllComponent
                    label={formatMessage(localMessages.dates)}
                    title={formatMessage(localMessages.copyQueryDatesTitle)}
                    msg={formatMessage(localMessages.copyQueryDatesMsg)}
                    onOk={() => handleCopyAll(DATES)}
                  />

                  <Field
                    className="query-field start-date-wrapper"
                    maxLength="12"
                    name="startDate"
                    type="inline"
                    component={renderTextField}
                    disableunderline="true"
                    disabled={!isEditable}
                    onChange={onDateChange}
                  />

<FormattedMessage {...localMessages.dateTo} />

                  <Field
                    className="query-field end-date-wrapper"
                    maxLength="12"
                    name="endDate"
                    type="inline"
                    component={renderTextField}
                    disableunderline="true"
                    disabled={!isEditable}
                    onChange={onDateChange}
                  />

<FormattedMessage {...localMessages.datesDesc} />

              </Col>
            </Row>
          </Grid>

          <Grid>
            <Row>
              <Col lg={6} />
              <Col lg={6}>

                  <SavedSearchControls
                    searchNickname={searchNickname}
                    savedSearches={savedSearches}
                    handleLoadSearches={handleLoadSearches}
                    handleLoadSelectedSearch={handleLoadSelectedSearch}
                    handleSaveSearch={l => handleSaveSearch(l)}
                    handleDeleteSearch={handleDeleteSearch}
                    submitting={submitting}
                    setQueryFormChildDialogOpen={this.setQueryFormChildDialogOpen}
                  />
                  <AppButton
                    type="submit"
                    label={buttonLabel}
                    disabled={queriesMissingMedia || submitting}
                    onClick={onWillSearch}
                    primary
                  />

              </Col>
            </Row>
          </Grid>

      </form>
    );
  }
}

QueryForm.propTypes = {
  // from context
  intl: PropTypes.object.isRequired,
  renderTextField: PropTypes.func.isRequired,
  renderSelect: PropTypes.func.isRequired,
  renderTextFieldWithFocus: PropTypes.func.isRequired,
  searchNickname: PropTypes.string.isRequired,
  savedSearches: PropTypes.array,

  // from parent
  selected: PropTypes.object.isRequired,
  onSave: PropTypes.func.isRequired,
  onColorChange: PropTypes.func,
  onMediaChange: PropTypes.func,
  buttonLabel: PropTypes.string.isRequired,
  initialValues: PropTypes.object,
  onWillSearch: PropTypes.func,
  handleLoadSearches: PropTypes.func.isRequired,
  handleLoadSelectedSearch: PropTypes.func.isRequired,
  handleSaveSearch: PropTypes.func.isRequired,
  handleDeleteSearch: PropTypes.func.isRequired,
  handleCopyAll: PropTypes.func.isRequired,
  onMediaDelete: PropTypes.func.isRequired,
  onDateChange: PropTypes.func.isRequired,
  // from state
  queries: PropTypes.array,
  // from form helper
  updateQuery: PropTypes.func,
  handleSubmit: PropTypes.func,
  pristine: PropTypes.bool.isRequired,
  submitting: PropTypes.bool.isRequired,
  isEditable: PropTypes.bool.isRequired,
  focusRequested: PropTypes.func.isRequired,
  mediaUpdates: PropTypes.object,
};

const mapStateToProps = state => ({
  mediaUpdates: formSelector(state, 'index', 'media', 'sources', 'collections'),
  queries: state.explorer.queries.queries ? state.explorer.queries.queries : null,
});

function validate(values, props) {
  const { formatMessage } = props.intl;
  const errors = {};
  if (emptyString(values.q)) {
    const errString = formatMessage(localMessages.queryStringError, { name: values.label });
    errors.q = { _error: errString };
  }
  if (!validDate(values.startDate) || !isValidSolrDate(values.startDate)) {
    errors.startDate = { _error: formatMessage(localMessages.invalidDateWarning) };
  }
  if (!validDate(values.endDate) || !isValidSolrDate(values.endDate)) {
    errors.endDate = { _error: formatMessage(localMessages.invalidDateWarning) };
  }
  if (validDate(values.startDate) && validDate(values.endDate) && isStartDateAfterEndDate(values.startDate, values.endDate)) {
    errors.startDate = { _error: formatMessage(localMessages.startDateWarning) };
  }
  if ((!values.collections || !values.collections.length)
    && (!values.sources || !values.sources.length)
    && (!values.media || !values.media.length)) {
    errors.media = { _error: formatMessage(localMessages.noMediaSpecified) };
  }
  return errors;
}

function warn(values, props) {
  const { formatMessage } = props.intl;
  const warnings = {};
  if ((!values.collections || !values.collections.length)
    && (!values.sources || !values.sources.length)
    && (!values.media || !values.media.length)) {
    warnings.media = { _warning: formatMessage(localMessages.noMediaSpecified) };
  }
  return warnings;
}

export default
withIntlForm(
  withHelp(localMessages.queryHelpTitle, localMessages.queryHelpContent)(
    reduxForm({ propTypes, validate, warn })(
      connect(mapStateToProps, null)(
        QueryForm
      ),
    ),
  ),
);
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var webpack = require('webpack');
var del = require('del');

class CleanPlugin {
  constructor(options) {
    this.options = options;
  }

  apply () {
    del.sync(this.options.files);
  }
}

module.exports = {
  entry: './app/index',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'app.min.js',
    publicPath: '/'
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new CleanPlugin({
      files: ['dist/*']
    }),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false,
        screw_ie8: true
      }
    }),
    new webpack.DefinePlugin({
      'process.env':{
        'NODE_ENV': JSON.stringify('production')
      }
    })
  ],
  module: {
    loaders: [{
      test: /\.js?$/,
      loader: 'babel',
      include: path.join(__dirname, 'app'),
      query: {
        plugins: [
          ['transform-object-assign']
        ]
      }
    }]
  }
};
<commit_msg>add -loader<commit_after>'use strict';

var path = require('path');
var webpack = require('webpack');
var del = require('del');

class CleanPlugin {
  constructor(options) {
    this.options = options;
  }

  apply () {
    del.sync(this.options.files);
  }
}

module.exports = {
  entry: './app/index',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'app.min.js',
    publicPath: '/'
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new CleanPlugin({
      files: ['dist/*']
    }),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false,
        screw_ie8: true
      }
    }),
    new webpack.DefinePlugin({
      'process.env':{
        'NODE_ENV': JSON.stringify('production')
      }
    })
  ],
  module: {
    loaders: [{
      test: /\.js?$/,
      loader: 'babel-loader',
      include: path.join(__dirname, 'app'),
      query: {
        plugins: [
          ['transform-object-assign']
        ]
      }
    }]
  }
};
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import styled from 'styled-components'
import Divider from 'material-ui/Divider';
import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import FlatButton from 'material-ui/FlatButton';
import {Tabs, Tab} from 'material-ui/Tabs';
import Slider from 'material-ui/Slider';
import {Grid, Row, Col} from 'react-flexbox-grid';
import {IconLink, Link, FileHeader, TitleSection, FileDetailTitle, FileDetailTitleBlock} from 'components'
import Scrollspy from 'react-scrollspy';
import {palette} from 'styled-theme';

const Wrapper = styled.div `
  .fx{
    /*position: fixed;*/
  }
  .menu-scrollspy{
    padding: 5px;
      li{
        padding: 8px 0px;
      }
      a{
          font-size: 14px;
          color: ${palette('grayscale', 6)} !important;
          &:hover{
              color: ${palette('primary', 0)} !important;
          }
      }
     .is-current{
      color: ${palette('primary', 0)} !important;
      a{
        color: ${palette('primary', 0)} !important;
      }
    }
  }
`

class FileDetail extends React.Component {

  constructor(props) {
    super(props);
  }

  getFeeding() {
    try {
      return this.props.complete.feedingApprovedInUse.feeding.feedingUnstructured;
    } catch (err) {
      return 'Sin información';
    }
  }

  render() {
    return (
      <Wrapper>
        <Row>
          <Col lg={3} xs={12}>
            <Paper className="menu-scrollspy">
              <Scrollspy items={['section-1', 'section-2', 'section-3']} currentClassName="is-current">

                  Historia natural

                  Dinámica población y Amenazas

              </Scrollspy>
            </Paper>

          </Col>

          <Col lg={9} xs={12}>
            <Row>

              <Col xs={12} lg={12}>
                <FileDetailTitleBlock text='Historia Natural'/>
                <Paper zDepth={1} className="paper-padding-3 t100 align-justify color-text">
                  <FileDetailTitle text="Alimentación" />
                  {this.getFeeding()}
                </Paper>
                <Paper zDepth={1} className="paper-padding-3 t100 align-justify color-text">
                  <FileDetailTitle text="Alimentación" />
                  {this.getFeeding()}
                </Paper>
              </Col>
            </Row>

          </Col>
        </Row>
      </Wrapper>
    )
  }
}

export default FileDetail;
<commit_msg>blocks in FileDetail<commit_after>import React, {PropTypes} from 'react'
import styled from 'styled-components'
import Divider from 'material-ui/Divider';
import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import FlatButton from 'material-ui/FlatButton';
import {Tabs, Tab} from 'material-ui/Tabs';
import Slider from 'material-ui/Slider';
import {Grid, Row, Col} from 'react-flexbox-grid';
import {
  IconLink,
  Link,
  FileHeader,
  TitleSection,
  FileDetailTitle,
  FileDetailTitleBlock
} from 'components'
import Scrollspy from 'react-scrollspy';
import {palette} from 'styled-theme';
import ArrowDropDown from 'material-ui/svg-icons/navigation/arrow-drop-down';

const Wrapper = styled.div `
  .fx{
    /*position: fixed;*/
  }
  .menu-scrollspy{
    padding: 5px;
      li{
        padding: 8px 0px;
      }
      a{
          font-size: 14px;
          color: ${palette('grayscale', 6)} !important;
          &:hover{
              color: ${palette('primary', 0)} !important;
          }
      }
     .is-current{
      color: ${palette('primary', 0)} !important;
      a{
        color: ${palette('primary', 0)} !important;
      }
    }
  }
  .viewMore{
    text-align: right;
    margin-top: 10px;
    button{
      padding: 5px 25px;
      border:none;
      font-weight: bold;
      color: ${palette('grayscale', 5)};
      background: ${palette('grayscale', 1)};
      cursor: pointer;
      svg{
        vertical-align: middle;
      }
    }
  }
  .spacing{
    margin-bottom: 20px;
  }
  .paragraph{
    line-height: 1.8;
  }
`

class FileDetail extends React.Component {

  constructor(props) {
    super(props);
  }

  getFeeding() {
    try {
      return this.props.complete.feedingApprovedInUse.feeding.feedingUnstructured;
    } catch (err) {
      return 'Sin información';
    }
  }

  render() {
    return (
      <Wrapper>
        <Row>
          <Col lg={3} xs={12}>
            <Paper className="menu-scrollspy">
              <Scrollspy items={['section-1', 'section-2', 'section-3']} currentClassName="is-current">

                  Historia natural

                  Dinámica población y Amenazas

              </Scrollspy>
            </Paper>

          </Col>

          <Col lg={9} xs={12}>
            <Row>
              <Col xs={12} lg={12}>
                <FileDetailTitleBlock text='Historia Natural' id="section-1"/>
                <Paper zDepth={1} className="paper-padding-3 t100 align-justify color-text">
                  <FileDetailTitle text="Alimentación"/>

                    {this.getFeeding()}

                    <button>VER MÁS
                      <ArrowDropDown/>
                    </button>

                </Paper>
              </Col>
            </Row>

          </Col>
        </Row>
      </Wrapper>
    )
  }
}

export default FileDetail;
<|endoftext|>


<commit_before>/* eslint-disable */
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  context: __dirname + '/src',
  entry: {
    app: './index.js',
    vendor: [
      'react',
      'react-dom',
      'preact',
      'preact-compat',
      'preact-helmet'
    ]
  },
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js'
  },

  resolve: {
    alias: {
      'react': 'preact-compat/dist/preact-compat',
      'react-dom': 'preact-compat/dist/preact-compat'
  },
    extensions: ['.js', '.jsx', '.json', '.css']
  },
  module: {
    loaders: [
      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ["babel-loader"] },
      { test: /\.eot/, loader: 'url-loader?mimetype=application/vnd.ms-fontobject' },
      { test: /\.ttf/, loader: 'url-loader?mimetype=application/x-font-ttf' },
      { test: /\.woff/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.woff2/, loader: 'url-loader?mimetype=application/font-woff2' },
      { test: /\.svg$/, loader: "svg-loader?limit=10000&mimetype=image/svg+xml" },
      { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
      { test: /\.(jpe?g|png)$/i, loaders: [
            'file-loader?hash=sha512&digest=hex',
            'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false'
        ] },
      { test: /manifest.json$/, loader: 'file-loader?name=manifest.json!web-app-manifest-loader' },
      {
        test: /\.js$/,
        exclude: [/node_modules/],
        loader: 'babel-loader',
        query: {
          presets: ["es2015", "react", "stage-0"],
          plugins: [
              ["transform-decorators-legacy"],
              ["transform-runtime"]
            ]
          }
      },
    ]
  },

  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js' }),
    new webpack.LoaderOptionsPlugin({
       minimize: true,
       debug: false
     }),
    new HtmlWebpackPlugin({
      title: 'Bare Minimum',
      filename: 'index.html',
      template: './index.html',
      inject: true
    }),
    new webpack.optimize.AggressiveMergingPlugin(),
    new ExtractTextPlugin("styles.css"),
    new webpack.DefinePlugin({
    'process.env': {
      'NODE_ENV': JSON.stringify('production')
      }
    }),
    new FaviconsWebpackPlugin({
      logo: './assets/Bm144.png',
      icons: {
       android: false,
       appleIcon: false,
       appleStartup: false,
       coast: false,
       favicons: true,
       firefox: false,
       opengraph: false,
       twitter: false,
       yandex: false,
       windows: false
     }
   }),
   new SWPrecacheWebpackPlugin(
      {
        cacheId: 'bareminimum',
        filename: 'bareminimumSW.js',
        maximumFileSizeToCacheInBytes: 4194304,
        minify: true,
        runtimeCaching: [
          {
            urlPattern: /grade-calculator/,
            handler: 'cacheFirst',
          },
          {
            urlPattern: /damage-calculator/,
            handler: 'cacheFirst',
          },
          {
            urlPattern: /weighted-grade-calculator/,
            handler: 'cacheFirst',
          },
          {
            urlPattern: /gpa-calculator/,
            handler: 'cacheFirst',
          },
      ],
      }
    ),
    new CopyWebpackPlugin([
      { from: '../_redirects' },
    ])
  ]
}
<commit_msg>Tries something<commit_after>/* eslint-disable */
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  context: __dirname + '/src',
  entry: {
    app: './index.js',
    vendor: [
      'react',
      'react-dom',
      'preact',
      'preact-compat',
      'preact-helmet'
    ]
  },
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js'
  },

  resolve: {
    alias: {
      'react': 'preact-compat/dist/preact-compat',
      'react-dom': 'preact-compat/dist/preact-compat'
  },
    extensions: ['.js', '.jsx', '.json', '.css']
  },
  module: {
    loaders: [
      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ["babel-loader"] },
      { test: /\.eot/, loader: 'url-loader?mimetype=application/vnd.ms-fontobject' },
      { test: /\.ttf/, loader: 'url-loader?mimetype=application/x-font-ttf' },
      { test: /\.woff/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.woff2/, loader: 'url-loader?mimetype=application/font-woff2' },
      { test: /\.svg$/, loader: "svg-loader?limit=10000&mimetype=image/svg+xml" },
      { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
      { test: /\.(jpe?g|png)$/i, loaders: [
            'file-loader?hash=sha512&digest=hex',
            'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false'
        ] },
      { test: /manifest.json$/, loader: 'file-loader?name=manifest.json!web-app-manifest-loader' },
      {
        test: /\.js$/,
        exclude: [/node_modules/],
        loader: 'babel-loader',
        query: {
          presets: ["es2015", "react", "stage-0"],
          plugins: [
              ["transform-decorators-legacy"],
              ["transform-runtime"]
            ]
          }
      },
    ]
  },

  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js' }),
    new webpack.LoaderOptionsPlugin({
       minimize: true,
       debug: false
     }),
    new HtmlWebpackPlugin({
      title: 'Bare Minimum',
      filename: 'index.html',
      template: './index.html',
      inject: true
    }),
    new webpack.optimize.AggressiveMergingPlugin(),
    new ExtractTextPlugin("styles.css"),
    new webpack.DefinePlugin({
    'process.env': {
      'NODE_ENV': JSON.stringify('production')
      }
    }),
    new FaviconsWebpackPlugin({
      logo: './assets/Bm144.png',
      icons: {
       android: false,
       appleIcon: false,
       appleStartup: false,
       coast: false,
       favicons: true,
       firefox: false,
       opengraph: false,
       twitter: false,
       yandex: false,
       windows: false
     }
   }),
   new SWPrecacheWebpackPlugin(
      {
        cacheId: 'bareminimum',
        filename: 'bareminimumSW.js',
        maximumFileSizeToCacheInBytes: 4194304,
        minify: true,
      }
    ),
    new CopyWebpackPlugin([
      { from: '../_redirects' },
    ])
  ]
}
<|endoftext|>


<commit_before>export const ALERT_BANNER_ACTIVE = true

// https://github.com/hashicorp/web-components/tree/master/packages/alert-banner
export default {
  tag: 'June 8-11',
  url: 'https://hashiconf.com/europe/?utm_source=DocsBanner',
  text: 'HashiConf Europe is happening now. Join all sessions live June 8 & 9.',
  linkText: 'Join Now',
  // Set the `expirationDate prop with a datetime string (e.g. `2020-01-31T12:00:00-07:00`)
  // if you'd like the component to stop showing at or after a certain date
  expirationDate: `2021-06-12T12:00:00-07:00`,
}
<commit_msg>website: update alert banner (#11074)<commit_after>export const ALERT_BANNER_ACTIVE = true

// https://github.com/hashicorp/web-components/tree/master/packages/alert-banner
export default {
  tag: 'Thank you',
  url: 'https://hashiconf.com/europe',
  text: 'HashiConf Europe is a wrap. Watch this year’s sessions on-demand.',
  linkText: 'Watch Now',
  // Set the `expirationDate prop with a datetime string (e.g. `2020-01-31T12:00:00-07:00`)
  // if you'd like the component to stop showing at or after a certain date
  expirationDate: `2021-06-20T12:00:00-07:00`,
}
<|endoftext|>


<commit_before>export const ALERT_BANNER_ACTIVE = true

// https://github.com/hashicorp/web-components/tree/master/packages/alert-banner
export default {
  tag: 'New',
  url: 'https://cloud.hashicorp.com/products/packer ',
  text:
    'HCP Packer offers automation and security workflows for Packer, and is now generally available.',
  linkText: 'Sign up for free',
  // Set the expirationDate prop with a datetime string (e.g. '2020-01-31T12:00:00-07:00')
  // if you'd like the component to stop showing at or after a certain date
  // expirationDate: '2021-12-17T23:00:00-07:00',
}
<commit_msg>Add expiration date to banner<commit_after>export const ALERT_BANNER_ACTIVE = true

// https://github.com/hashicorp/web-components/tree/master/packages/alert-banner
export default {
  tag: 'New',
  url: 'https://cloud.hashicorp.com/products/packer ',
  text:
    'HCP Packer offers automation and security workflows for Packer, and is now generally available.',
  linkText: 'Sign up for free',
  // Set the expirationDate prop with a datetime string (e.g. '2020-01-31T12:00:00-07:00')
  // if you'd like the component to stop showing at or after a certain date
  expirationDate: '2022-04-07T23:00:00-07:00',
}
<|endoftext|>


<commit_before>const path = require('path');

module.exports = {
  title: 'DiceBear Avatars',
  tagline: 'Avatars is an avatar placeholder library for designers and developers. ',
  url: 'https://avatars.dicebear.com',
  baseUrl: '/',
  onBrokenLinks: 'throw',
  favicon: 'img/favicon.ico',
  organizationName: 'DiceBear', // Usually your GitHub org/user name.
  projectName: 'avatars', // Usually your repo name.
  themeConfig: {
    sidebarCollapsible: false,
    colorMode: {
      defaultMode: 'light',
      disableSwitch: true,
      respectPrefersColorScheme: false,
    },
    navbar: {
      title: 'DiceBear Avatars',
      logo: {
        alt: 'DiceBear Avatars',
        src: 'img/favicon.svg',
      },
      items: [
        {
          to: 'docs',
          activeBasePath: 'docs',
          label: 'Docs',
          position: 'left',
        },
        {
          to: 'styles',
          activeBasePath: 'styles',
          label: 'Styles',
          position: 'left',
        },
        {
          to: 'integrations/serverless',
          activeBasePath: 'integrations',
          label: 'Integrations',
          position: 'left',
        },
        {
          href: 'https://github.com/DiceBear/avatars',
          label: 'GitHub',
          position: 'right',
        },
      ],
    },
    footer: {
      style: 'light',
      links: [
        {
          title: 'Community',
          items: [
            {
              label: 'GitHub',
              href: 'https://github.com/DiceBear/avatars',
            },
            {
              label: 'Status',
              href: 'https://dicebear.betteruptime.com/',
            },
            {
              label: 'Twitter',
              href: 'https://twitter.com/flomavali',
            },
          ],
        },
        {
          title: 'More',
          items: [
            {
              label: 'Frequently Asked Questions',
              to: '/faq',
            },
          ],
        },
        {
          title: 'Legal',
          items: [
            {
              label: 'Privacy Policy',
              to: '/legal/privacy-policy',
            },
            {
              label: 'Legal Notice / Impressum',
              to: '/legal/legal-notice',
            },
          ],
        },
      ],
      copyright: `Documentation realized with <a href="https://v2.docusaurus.io/">docusaurus</a>, <a href="https://getbootstrap.com/">bootstrap</a> and <a href="https://octicons.github.com/">octicons</a>.`,
    },
  },
  presets: [
    [
      '@docusaurus/preset-classic',
      {
        docs: {
          sidebarPath: require.resolve('./sidebars.js'),
          // Please change this to your repo.
          editUrl: 'https://github.com/DiceBear/avatars/edit/v4/docs/',
          routeBasePath: '/',
        },
        theme: {
          customCss: require.resolve('./src/css/index.scss'),
        },
      },
    ],
  ],
  plugins: ['docusaurus-plugin-sass', path.resolve(__dirname, 'src/plugins/buffer-plugin')],
};
<commit_msg>Fix: Website edit path<commit_after>const path = require('path');

module.exports = {
  title: 'DiceBear Avatars',
  tagline: 'Avatars is an avatar placeholder library for designers and developers. ',
  url: 'https://avatars.dicebear.com',
  baseUrl: '/',
  onBrokenLinks: 'throw',
  favicon: 'img/favicon.ico',
  organizationName: 'DiceBear', // Usually your GitHub org/user name.
  projectName: 'avatars', // Usually your repo name.
  themeConfig: {
    sidebarCollapsible: false,
    colorMode: {
      defaultMode: 'light',
      disableSwitch: true,
      respectPrefersColorScheme: false,
    },
    navbar: {
      title: 'DiceBear Avatars',
      logo: {
        alt: 'DiceBear Avatars',
        src: 'img/favicon.svg',
      },
      items: [
        {
          to: 'docs',
          activeBasePath: 'docs',
          label: 'Docs',
          position: 'left',
        },
        {
          to: 'styles',
          activeBasePath: 'styles',
          label: 'Styles',
          position: 'left',
        },
        {
          to: 'integrations/serverless',
          activeBasePath: 'integrations',
          label: 'Integrations',
          position: 'left',
        },
        {
          href: 'https://github.com/DiceBear/avatars',
          label: 'GitHub',
          position: 'right',
        },
      ],
    },
    footer: {
      style: 'light',
      links: [
        {
          title: 'Community',
          items: [
            {
              label: 'GitHub',
              href: 'https://github.com/DiceBear/avatars',
            },
            {
              label: 'Status',
              href: 'https://dicebear.betteruptime.com/',
            },
            {
              label: 'Twitter',
              href: 'https://twitter.com/flomavali',
            },
          ],
        },
        {
          title: 'More',
          items: [
            {
              label: 'Frequently Asked Questions',
              to: '/faq',
            },
          ],
        },
        {
          title: 'Legal',
          items: [
            {
              label: 'Privacy Policy',
              to: '/legal/privacy-policy',
            },
            {
              label: 'Legal Notice / Impressum',
              to: '/legal/legal-notice',
            },
          ],
        },
      ],
      copyright: `Documentation realized with <a href="https://v2.docusaurus.io/">docusaurus</a>, <a href="https://getbootstrap.com/">bootstrap</a> and <a href="https://octicons.github.com/">octicons</a>.`,
    },
  },
  presets: [
    [
      '@docusaurus/preset-classic',
      {
        docs: {
          sidebarPath: require.resolve('./sidebars.js'),
          // Please change this to your repo.
          editUrl: 'https://github.com/DiceBear/avatars/edit/v4/website/',
          routeBasePath: '/',
        },
        theme: {
          customCss: require.resolve('./src/css/index.scss'),
        },
      },
    ],
  ],
  plugins: ['docusaurus-plugin-sass', path.resolve(__dirname, 'src/plugins/buffer-plugin')],
};
<|endoftext|>


<commit_before>var table;
var socket = io.connect('http://' + document.domain + ':' + location.port);
var uuid;
var running = false;

$('#codeform').on('submit', function(d) { d.preventDefault(); });

function submitCode() {
    var form = $('#codeform');

    $('#errorconsoletab').css('font-weight', 'normal');
    $('#errors').html('');
    $('#output').html('')

    socket.emit('submit', {
        code: $('#code').val(),
        inputs: $('#inputs').val(),
        debug: $('#debug').val(),
        version: $('#version').data('version'),
        uid: uuid
    });

    running = true;

    $('#run').text('Kill');
}

// When the server acknowledges that we are connected it will issue
// us an ID which we can use to get updates
socket.on('connection', function(data) {
    uuid = data.session_id;
});

$('#explain').on('click', function(d) {
    var code = $('#code').val();
    var version = $('#version').data('version');

    // Do not submit the form unless there is code
    if ( code == '' ) {
        return;
    }

    $('#modal-explain').text('Parsing...');

    // Going to get the explanation and post it in a balloon
    $('#explainmodal').modal();

    $.ajax({
        url: '/explain',
        method: 'GET',
        data:{
            code: code,
            version: version
        },
        success: function(resp) {
            alltext = '';
            resp['data'].forEach(function (item) {
                alltext = alltext + item.value
            });
            $('#modal-explain').text(alltext);
        }
    });
});

function getlink() {

    var data = {
        'code': $('#code').val(),
        'inputs': $('#inputs').val(),
        'version': $('#version').data('version')};

    var link = $.param(data);

    // Now sanitize for SE
    return link.replace(/[!'()*]/g, function(ch) {
        return '%' + ch.charCodeAt(0).toString(16);
    });
}

socket.on('killed', function(data) {
    $('#run').text('Run');
    running = false;
});

socket.on('complete', function(msg) {
    $('#run').text('Run');
    running = false;
});

$('#run').on('click', function() {
    if ( running ) {
        socket.emit('kill', {uid: uuid});
    } else {
        submitCode();
    }
});

socket.on('status', function(data) {
    var output = $('#output');
    var errors = $('#errors');

    // Clear the output
    output.text('');

    if ( data['session'] == uuid ) {
        data['data'].forEach(function(item) {
            switch ( item.type ) {
                case 'image':

                    // Remove any previous images (simulates drawnow)
                    var thumb = $('.thumb');

                    if ( thumb.length ){
                        $(thumb).find('.imshow').attr('src', item.value);
                    } else {
                        val = '
';
                        output.append(val);
                        $('.thumb').on('click', function(e) {
                            var url = $(this).find('.imshow').attr('src');
                            $('#imagepreview').attr('src', url);
                            var img = $('#imagepreview').get(0);

                            $('#dimensions').text(img.naturalHeight + ' x ' + img.naturalWidth);
                            $('#imagemodal').modal('show');
                        });
                    }

                    break;
                case 'stderr':
                    errors.append(item.value + '\n');
                    $('#errorconsoletab').css('font-weight', 'bold');
                    break;
                default:
                    $('#output').append(item.value);
            }
        });
    }
});

function refreshHelp() {
    table.ajax.url('help/' + $('#version').data('version')).load();
}

$('.version').on('click', function(e) {
    $('#version').text(e.target.text).data('version', $(e.target).data('version'));
    refreshHelp();
    e.preventDefault();
});

$('#save').on('click', function(e) {
    link = '?' + getlink();
    history.pushState({'Title': '', 'Url': link}, '', link);
    e.preventDefault();
});

// When the image preview dialog is closed, reset the share link
$('#imagemodal').on('hidden.bs.modal', function () {
    $('#share').removeClass('flip-side-2').addClass('flip-side-1');
    $('#sharelink').removeClass('flip-side-1');
});

// Be sure that we place the CSRF token in all AJAX request headers
$.ajaxSetup({
    // Add a header containing the CSRF token if needed
    beforeSend: function(xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken",
                $('meta[name=csrf-token]').attr('content'));
        }
    }
});

$('#share').on('click', function(e){
    // Display loading while we upload to imgur and get the link
    $('#imgurlink').val('Loading...').css('color', '');

    // Flip over to the link to prevent the user from clicking share again
    $('#share').addClass('flip-side-2');
    $('#sharelink').addClass('flip-side-1');

    $.post({
        url: '/share',
        data: {'data': $('.thumb').find('.imshow').attr('src')},
        success: function(resp){
            // Paste the link into the input box and highlight it
            $('#imgurlink').val(resp.link)
                .prop('disabled', false)
                .css('color', 'black')
                .select();
        },
        error: function(resp){
            // Some unspecified error happened (could be CSRF or others)
            $('#imgurlink').val('SERVER ERROR')
                .css('color', 'red');
        }
    });
});

table = $('#documentation').DataTable({
    paging: false,
    ordering: false,
    info: false,
    ajax: 'help/' + $('#version').data('version'),
    stripe: true,
    scrollY: '80vh',
    scrollX: false,
    scrollCollapse: true,
    order: [[ 0, "asc"]],
    columns: [
        {
            data: 'source',
            orderable: true
        },
        {
            data: null,
            orderable: false,
            render: function(data) {
                output = '' + data.brief + '';
                if ( data.arguments ){
                    output = output + '\n' + data.arguments;
                }
                return output + '\n' + data.description;
            }
        }]
});

function countChar(val) {
    var count = val.value.length;

    if ( count == 1 ) {
        $('#charcount').text('(' + count + ' character)');
    } else {
        $('#charcount').text('(' + count + ' characters)');
    }
}
<commit_msg>Makes socket connection work with https<commit_after>var table;
var socket = io.connect(window.location.protocol + '//' + document.domain + ':' + location.port);
var uuid;
var running = false;

$('#codeform').on('submit', function(d) { d.preventDefault(); });

function submitCode() {
    var form = $('#codeform');

    $('#errorconsoletab').css('font-weight', 'normal');
    $('#errors').html('');
    $('#output').html('')

    socket.emit('submit', {
        code: $('#code').val(),
        inputs: $('#inputs').val(),
        debug: $('#debug').val(),
        version: $('#version').data('version'),
        uid: uuid
    });

    running = true;

    $('#run').text('Kill');
}

// When the server acknowledges that we are connected it will issue
// us an ID which we can use to get updates
socket.on('connection', function(data) {
    uuid = data.session_id;
});

$('#explain').on('click', function(d) {
    var code = $('#code').val();
    var version = $('#version').data('version');

    // Do not submit the form unless there is code
    if ( code == '' ) {
        return;
    }

    $('#modal-explain').text('Parsing...');

    // Going to get the explanation and post it in a balloon
    $('#explainmodal').modal();

    $.ajax({
        url: '/explain',
        method: 'GET',
        data:{
            code: code,
            version: version
        },
        success: function(resp) {
            alltext = '';
            resp['data'].forEach(function (item) {
                alltext = alltext + item.value
            });
            $('#modal-explain').text(alltext);
        }
    });
});

function getlink() {

    var data = {
        'code': $('#code').val(),
        'inputs': $('#inputs').val(),
        'version': $('#version').data('version')};

    var link = $.param(data);

    // Now sanitize for SE
    return link.replace(/[!'()*]/g, function(ch) {
        return '%' + ch.charCodeAt(0).toString(16);
    });
}

socket.on('killed', function(data) {
    $('#run').text('Run');
    running = false;
});

socket.on('complete', function(msg) {
    $('#run').text('Run');
    running = false;
});

$('#run').on('click', function() {
    if ( running ) {
        socket.emit('kill', {uid: uuid});
    } else {
        submitCode();
    }
});

socket.on('status', function(data) {
    var output = $('#output');
    var errors = $('#errors');

    // Clear the output
    output.text('');

    if ( data['session'] == uuid ) {
        data['data'].forEach(function(item) {
            switch ( item.type ) {
                case 'image':

                    // Remove any previous images (simulates drawnow)
                    var thumb = $('.thumb');

                    if ( thumb.length ){
                        $(thumb).find('.imshow').attr('src', item.value);
                    } else {
                        val = '
';
                        output.append(val);
                        $('.thumb').on('click', function(e) {
                            var url = $(this).find('.imshow').attr('src');
                            $('#imagepreview').attr('src', url);
                            var img = $('#imagepreview').get(0);

                            $('#dimensions').text(img.naturalHeight + ' x ' + img.naturalWidth);
                            $('#imagemodal').modal('show');
                        });
                    }

                    break;
                case 'stderr':
                    errors.append(item.value + '\n');
                    $('#errorconsoletab').css('font-weight', 'bold');
                    break;
                default:
                    $('#output').append(item.value);
            }
        });
    }
});

function refreshHelp() {
    table.ajax.url('help/' + $('#version').data('version')).load();
}

$('.version').on('click', function(e) {
    $('#version').text(e.target.text).data('version', $(e.target).data('version'));
    refreshHelp();
    e.preventDefault();
});

$('#save').on('click', function(e) {
    link = '?' + getlink();
    history.pushState({'Title': '', 'Url': link}, '', link);
    e.preventDefault();
});

// When the image preview dialog is closed, reset the share link
$('#imagemodal').on('hidden.bs.modal', function () {
    $('#share').removeClass('flip-side-2').addClass('flip-side-1');
    $('#sharelink').removeClass('flip-side-1');
});

// Be sure that we place the CSRF token in all AJAX request headers
$.ajaxSetup({
    // Add a header containing the CSRF token if needed
    beforeSend: function(xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken",
                $('meta[name=csrf-token]').attr('content'));
        }
    }
});

$('#share').on('click', function(e){
    // Display loading while we upload to imgur and get the link
    $('#imgurlink').val('Loading...').css('color', '');

    // Flip over to the link to prevent the user from clicking share again
    $('#share').addClass('flip-side-2');
    $('#sharelink').addClass('flip-side-1');

    $.post({
        url: '/share',
        data: {'data': $('.thumb').find('.imshow').attr('src')},
        success: function(resp){
            // Paste the link into the input box and highlight it
            $('#imgurlink').val(resp.link)
                .prop('disabled', false)
                .css('color', 'black')
                .select();
        },
        error: function(resp){
            // Some unspecified error happened (could be CSRF or others)
            $('#imgurlink').val('SERVER ERROR')
                .css('color', 'red');
        }
    });
});

table = $('#documentation').DataTable({
    paging: false,
    ordering: false,
    info: false,
    ajax: 'help/' + $('#version').data('version'),
    stripe: true,
    scrollY: '80vh',
    scrollX: false,
    scrollCollapse: true,
    order: [[ 0, "asc"]],
    columns: [
        {
            data: 'source',
            orderable: true
        },
        {
            data: null,
            orderable: false,
            render: function(data) {
                output = '' + data.brief + '';
                if ( data.arguments ){
                    output = output + '\n' + data.arguments;
                }
                return output + '\n' + data.description;
            }
        }]
});

function countChar(val) {
    var count = val.value.length;

    if ( count == 1 ) {
        $('#charcount').text('(' + count + ' character)');
    } else {
        $('#charcount').text('(' + count + ' characters)');
    }
}
<|endoftext|>


<commit_before>L.Control.Sidebar = L.Control.extend({

    includes: L.Mixin.Events,

    options: {
        closeButton: true,
        position: 'left',
        autoPan: true,
    },

    initialize: function (placeholder, options) {
        L.setOptions(this, options);

        // Find content container
        var content = this._contentContainer = L.DomUtil.get(placeholder);

        // Remove the content container from its original parent
        content.parentNode.removeChild(content);

        var l = 'leaflet-';

        // Create sidebar container
        var container = this._container =
            L.DomUtil.create('div', l + 'sidebar ' + this.options.position);

        // Style and attach content container
        L.DomUtil.addClass(content, l + 'control');
        container.appendChild(content);

        // Create close button and attach it if configured
        if (this.options.closeButton) {
            var close = this._closeButton =
                L.DomUtil.create('a', 'close', container);
            close.innerHTML = '×';
        }
    },

    addTo: function (map) {
        var container = this._container;
        var content = this._contentContainer;

        // Attach event to close button
        if (this.options.closeButton) {
            var close = this._closeButton;

            L.DomEvent.on(close, 'click', this.hide, this);
        }

        L.DomEvent
            .on(container, 'transitionend',
                this._handleTransitionEvent, this)
            .on(container, 'webkitTransitionEnd',
                this._handleTransitionEvent, this);

        // Attach sidebar container to controls container
        var controlContainer = map._controlContainer;
        controlContainer.insertBefore(container, controlContainer.firstChild);

        this._map = map;

        // Make sure we don't drag the map when we interact with the content
        var stop = L.DomEvent.stopPropagation;
        var fakeStop = L.DomEvent._fakeStop || stop;
        L.DomEvent
            .on(content, 'contextmenu', stop)
            .on(content, 'click', fakeStop)
            .on(content, 'mousedown', stop)
            .on(content, 'touchstart', stop)
            .on(content, 'dblclick', fakeStop)
            .on(content, 'mousewheel', stop)
            .on(content, 'MozMousePixelScroll', stop);

        return this;
    },

    removeFrom: function (map) {
        //if the control is visible, hide it before removing it.
        this.hide();

        var content = this._contentContainer;

        // Remove sidebar container from controls container
        var controlContainer = map._controlContainer;
        controlContainer.removeChild(this._container);

        //disassociate the map object
        this._map = null;

        // Unregister events to prevent memory leak
        var stop = L.DomEvent.stopPropagation;
        var fakeStop = L.DomEvent._fakeStop || stop;
        L.DomEvent
            .off(content, 'contextmenu', stop)
            .off(content, 'click', fakeStop)
            .off(content, 'mousedown', stop)
            .off(content, 'touchstart', stop)
            .off(content, 'dblclick', fakeStop)
            .off(content, 'mousewheel', stop)
            .off(content, 'MozMousePixelScroll', stop);

        L.DomEvent
            .off(container, 'transitionend',
                this._handleTransitionEvent, this)
            .off(container, 'webkitTransitionEnd',
                this._handleTransitionEvent, this);

        if (this._closeButton && this._close) {
            var close = this._closeButton;

            L.DomEvent.off(close, 'click', this.hide, this);
        }

        return this;
    },

    isVisible: function () {
        return L.DomUtil.hasClass(this._container, 'visible');
    },

    show: function () {
        if (!this.isVisible()) {
            L.DomUtil.addClass(this._container, 'visible');
            if (this.options.autoPan) {
                this._map.panBy([-this.getOffset() / 2, 0], {
                    duration: 0.5
                });
            }
            this.fire('show');
        }
    },

    hide: function (e) {
        if (this.isVisible()) {
            L.DomUtil.removeClass(this._container, 'visible');
            if (this.options.autoPan) {
                this._map.panBy([this.getOffset() / 2, 0], {
                    duration: 0.5
                });
            }
            this.fire('hide');
        }
        if(e) {
            L.DomEvent.stopPropagation(e);
        }
    },

    toggle: function () {
        if (this.isVisible()) {
            this.hide();
        } else {
            this.show();
        }
    },

    getContainer: function () {
        return this._contentContainer;
    },

    getCloseButton: function () {
        return this._closeButton;
    },

    setContent: function (content) {
        this.getContainer().innerHTML = content;
        return this;
    },

    getOffset: function () {
        if (this.options.position === 'right') {
            return -this._container.offsetWidth;
        } else {
            return this._container.offsetWidth;
        }
    },

    _handleTransitionEvent: function (e) {
        if (e.propertyName == 'left' || e.propertyName == 'right')
            this.fire(this.isVisible() ? 'shown' : 'hidden');
    }
});

L.control.sidebar = function (placeholder, options) {
    return new L.Control.Sidebar(placeholder, options);
};
<commit_msg>accept HTML DOM element object as content<commit_after>L.Control.Sidebar = L.Control.extend({

    includes: L.Mixin.Events,

    options: {
        closeButton: true,
        position: 'left',
        autoPan: true,
    },

    initialize: function (placeholder, options) {
        L.setOptions(this, options);

        // Find content container
        var content = this._contentContainer = L.DomUtil.get(placeholder);

        // Remove the content container from its original parent
        content.parentNode.removeChild(content);

        var l = 'leaflet-';

        // Create sidebar container
        var container = this._container =
            L.DomUtil.create('div', l + 'sidebar ' + this.options.position);

        // Style and attach content container
        L.DomUtil.addClass(content, l + 'control');
        container.appendChild(content);

        // Create close button and attach it if configured
        if (this.options.closeButton) {
            var close = this._closeButton =
                L.DomUtil.create('a', 'close', container);
            close.innerHTML = '×';
        }
    },

    addTo: function (map) {
        var container = this._container;
        var content = this._contentContainer;

        // Attach event to close button
        if (this.options.closeButton) {
            var close = this._closeButton;

            L.DomEvent.on(close, 'click', this.hide, this);
        }

        L.DomEvent
            .on(container, 'transitionend',
                this._handleTransitionEvent, this)
            .on(container, 'webkitTransitionEnd',
                this._handleTransitionEvent, this);

        // Attach sidebar container to controls container
        var controlContainer = map._controlContainer;
        controlContainer.insertBefore(container, controlContainer.firstChild);

        this._map = map;

        // Make sure we don't drag the map when we interact with the content
        var stop = L.DomEvent.stopPropagation;
        var fakeStop = L.DomEvent._fakeStop || stop;
        L.DomEvent
            .on(content, 'contextmenu', stop)
            .on(content, 'click', fakeStop)
            .on(content, 'mousedown', stop)
            .on(content, 'touchstart', stop)
            .on(content, 'dblclick', fakeStop)
            .on(content, 'mousewheel', stop)
            .on(content, 'MozMousePixelScroll', stop);

        return this;
    },

    removeFrom: function (map) {
        //if the control is visible, hide it before removing it.
        this.hide();

        var content = this._contentContainer;

        // Remove sidebar container from controls container
        var controlContainer = map._controlContainer;
        controlContainer.removeChild(this._container);

        //disassociate the map object
        this._map = null;

        // Unregister events to prevent memory leak
        var stop = L.DomEvent.stopPropagation;
        var fakeStop = L.DomEvent._fakeStop || stop;
        L.DomEvent
            .off(content, 'contextmenu', stop)
            .off(content, 'click', fakeStop)
            .off(content, 'mousedown', stop)
            .off(content, 'touchstart', stop)
            .off(content, 'dblclick', fakeStop)
            .off(content, 'mousewheel', stop)
            .off(content, 'MozMousePixelScroll', stop);

        L.DomEvent
            .off(container, 'transitionend',
                this._handleTransitionEvent, this)
            .off(container, 'webkitTransitionEnd',
                this._handleTransitionEvent, this);

        if (this._closeButton && this._close) {
            var close = this._closeButton;

            L.DomEvent.off(close, 'click', this.hide, this);
        }

        return this;
    },

    isVisible: function () {
        return L.DomUtil.hasClass(this._container, 'visible');
    },

    show: function () {
        if (!this.isVisible()) {
            L.DomUtil.addClass(this._container, 'visible');
            if (this.options.autoPan) {
                this._map.panBy([-this.getOffset() / 2, 0], {
                    duration: 0.5
                });
            }
            this.fire('show');
        }
    },

    hide: function (e) {
        if (this.isVisible()) {
            L.DomUtil.removeClass(this._container, 'visible');
            if (this.options.autoPan) {
                this._map.panBy([this.getOffset() / 2, 0], {
                    duration: 0.5
                });
            }
            this.fire('hide');
        }
        if(e) {
            L.DomEvent.stopPropagation(e);
        }
    },

    toggle: function () {
        if (this.isVisible()) {
            this.hide();
        } else {
            this.show();
        }
    },

    getContainer: function () {
        return this._contentContainer;
    },

    getCloseButton: function () {
        return this._closeButton;
    },

    setContent: function (content) {
        if (typeof content === 'string') {
            this.getContainer().innerHTML = content;
        } else {
            this._content = content;
        }

        this.update();

        return this;
    },

    getOffset: function () {
        if (this.options.position === 'right') {
            return -this._container.offsetWidth;
        } else {
            return this._container.offsetWidth;
        }
    },

    _handleTransitionEvent: function (e) {
        if (e.propertyName == 'left' || e.propertyName == 'right')
            this.fire(this.isVisible() ? 'shown' : 'hidden');
    }
});

L.control.sidebar = function (placeholder, options) {
    return new L.Control.Sidebar(placeholder, options);
};
<|endoftext|>


<commit_before>"use strict";

// Blank the document so the 404 page doesn't show up visibly.
document.documentElement.style.display = 'none';

// Can't use DOMContentLoaded, calling document.write or document.close inside it from
// inside an extension causes a crash.
window.addEventListener("load", function() {
    function resolveUrl(name) {
        if (!chrome || !chrome.extension)
            return name;
        return chrome.extension.getURL(name);
    }

    var title = document.querySelector("title");
    title.textContent = "Chromium Code Review";
    document.write(
        "<!DOCTYPE html>" +
        "<meta name=viewport content='initial-scale=1, maximum-scale=1, user-scalable=no'>" +
        "<script src='" + resolveUrl("bower_components/platform/platform.js") + "'></script>" +
        "<script>EXTENSION_URL = '" + resolveUrl("") + "';</script>" +
        "<link rel='import' href='" + resolveUrl("ui/components/cr-app.html") + "'>" +
        "<link rel='stylesheet' href='" + resolveUrl("ui/style.css") + "'>" +
        "<cr-app></cr-app>"
    );
    document.close();
    document.head.appendChild(title);
    document.documentElement.style.display = '';
});
<commit_msg>Add a comment for the title hack.<commit_after>"use strict";

// Blank the document so the 404 page doesn't show up visibly.
document.documentElement.style.display = 'none';

// Can't use DOMContentLoaded, calling document.write or document.close inside it from
// inside an extension causes a crash.
window.addEventListener("load", function() {
    function resolveUrl(name) {
        if (!chrome || !chrome.extension)
            return name;
        return chrome.extension.getURL(name);
    }

    // FIXME: Work around http://crbug.com/411111 where the title won't dynamically
    // update anymore in Chrome 37 unless we reuse the same <title> element.
    var title = document.querySelector("title");
    title.textContent = "Chromium Code Review";
    document.write(
        "<!DOCTYPE html>" +
        "<meta name=viewport content='initial-scale=1, maximum-scale=1, user-scalable=no'>" +
        "<script src='" + resolveUrl("bower_components/platform/platform.js") + "'></script>" +
        "<script>EXTENSION_URL = '" + resolveUrl("") + "';</script>" +
        "<link rel='import' href='" + resolveUrl("ui/components/cr-app.html") + "'>" +
        "<link rel='stylesheet' href='" + resolveUrl("ui/style.css") + "'>" +
        "<cr-app></cr-app>"
    );
    document.close();
    document.head.appendChild(title);
    document.documentElement.style.display = '';
});
<|endoftext|>