<commit_before>import React, { Component } from 'react';
import Relay from 'react-relay';
import PropTypes from 'prop-types';
import {
  FormattedMessage,
  FormattedHTMLMessage,
  FormattedDate,
  defineMessages,
  injectIntl,
  intlShape,
} from 'react-intl';
import TextField from 'material-ui/TextField';
import FlatButton from 'material-ui/FlatButton';
import { Card, CardActions, CardHeader, CardText } from 'material-ui/Card';
import IconButton from 'material-ui/IconButton';
import MDEdit from 'react-icons/lib/md/edit';
import AccountCard from './AccountCard';
import Annotations from './Annotations';
import PageTitle from '../PageTitle';
import Medias from '../media/Medias';
import MappedMessage from '../MappedMessage';
import Message from '../Message';
import Can from '../Can';
import CheckContext from '../../CheckContext';
import ContentColumn from '../layout/ContentColumn';
import ParsedText from '../ParsedText';

const messages = defineMessages({
  editError: {
    id: 'sourceComponent.editError',
    defaultMessage: 'Sorry, could not edit the source',
  },
  editSuccess: {
    id: 'sourceComponent.editSuccess',
    defaultMessage: 'Source information updated successfully!',
  },
});

class SourceComponent extends Component {

  constructor(props) {
    super(props);
    const source = this.props.source;
    this.state = {
      message: null,
      isEditing: false,
      submitDisabled: false,
      showTab: 'media',
    };
  }

  componentDidMount() {
    this.setContextSource();
  }

  componentDidUpdate() {
    this.setContextSource();
  }

  setContextSource() {
    // const context = new CheckContext(this);
    // const store = context.getContextStore();
    // const { team, project_id, source_id } = this.props.source;
    //
    // console.log('team');
    // console.log(team);
    // console.log('project_id');
    // console.log(project_id);
    // console.log('source_id');
    // console.log(source_id);
    //
    // const sourceUrl = `/${team.slug}/project/${project_id}/source/${source_id}`;
    //
    // if (!store.team || store.team.slug !== team.slug) {
    //   context.setContextStore({ team });
    //   // const path = `/${team.slug}`;
    //   store.history.push(sourceUrl);
    // }
  }

  showAnnotations() {
    this.setState({ showTab: 'annotation' });
  }

  showAccounts() {
    this.setState({ showTab: 'account' });
  }

  showMedias() {
    this.setState({ showTab: 'media' });
  }

  render() {
    const isProjectSource = !!this.props.source.source;
    const { source } = isProjectSource ? this.props.source : this.props;
    const isEditing = this.state.isEditing;

    return (
      <PageTitle prefix={source.name} skipTeam={false} team={source.team}>

          <Card className="source__profile source__profile--editing">
            <ContentColumn>
              <Message message={this.state.message} />

                    <div
                      className="source__avatar"
                      style={{ backgroundImage: `url(${source.image})` }}
                    />

                        {source.name}

                          {<ParsedText text={source.description} /> ||
                          <MappedMessage
                            msgObj={messages}
                            msgKey="verificationTeam"
                          />}

                    { isProjectSource ?

                        <FormattedHTMLMessage
                          id="sourceComponent.dateAdded" defaultMessage="Added {date} • Source of {number} links"
                          values={{
                            date: this.props.intl.formatDate(source.created_at, { year: 'numeric', month: 'short', day: '2-digit' }),
                            number: source.medias.edges.length,
                          }}
                        />

 : null
                      }

                  {/* Source editing not implemented yet
                    <Can
                      permissions={source.permissions}
                      permission="update Source"
                    >
                      <IconButton
                        className="source__edit-button"
                        tooltip={
                          <FormattedMessage
                            id="sourceComponent.editButton"
                            defaultMessage="Edit profile"
                          />
                        }
                        tooltipPosition="top-center"
                      >
                        <MDEdit />
                      </IconButton>
                    </Can>
                    */}

            </ContentColumn>
            { isProjectSource ?
              <CardActions className="source__tab-buttons">
                <FlatButton
                  label={<FormattedMessage id="sourceComponent.notes" defaultMessage="Notes" />}
                  className="source__tab-button-notes"
                  primary={this.state.showTab === 'annotation'}
                  onClick={this.showAnnotations.bind(this)}
                />
                <FlatButton
                  primary={this.state.showTab === 'media'}
                  label={<FormattedMessage id="sourceComponent.medias" defaultMessage="Media" />}
                  onClick={this.showMedias.bind(this)}
                />
                <FlatButton
                  primary={this.state.showTab === 'account'}
                  onClick={this.showAccounts.bind(this)}
                  label={<FormattedMessage id="sourceComponent.network" defaultMessage="Networks" />}
                />
              </CardActions> : <CardActions />
            }
          </Card>

          { this.state.showTab === 'annotation' ? <Annotations annotations={source.annotations.edges} annotated={source} annotatedType="Source" /> : null }
          <ContentColumn>
            { this.state.showTab === 'media' ? <Medias medias={source.medias.edges} /> : null }
            { this.state.showTab === 'account' ? source.accounts.edges.map(account => <AccountCard key={account.node.id} account={account.node} />) : null }
          </ContentColumn>

      </PageTitle>
    );
  }
}

SourceComponent.propTypes = {
  intl: intlShape.isRequired,
  source: PropTypes.object,
};

SourceComponent.contextTypes = {
  store: React.PropTypes.object,
};

export default injectIntl(SourceComponent);
<commit_msg>Fix copy for source with no added media links #5958<commit_after>import React, { Component } from 'react';
import Relay from 'react-relay';
import PropTypes from 'prop-types';
import {
  FormattedMessage,
  FormattedHTMLMessage,
  FormattedDate,
  defineMessages,
  injectIntl,
  intlShape,
} from 'react-intl';
import TextField from 'material-ui/TextField';
import FlatButton from 'material-ui/FlatButton';
import { Card, CardActions, CardHeader, CardText } from 'material-ui/Card';
import IconButton from 'material-ui/IconButton';
import MDEdit from 'react-icons/lib/md/edit';
import AccountCard from './AccountCard';
import Annotations from './Annotations';
import PageTitle from '../PageTitle';
import Medias from '../media/Medias';
import MappedMessage from '../MappedMessage';
import Message from '../Message';
import Can from '../Can';
import CheckContext from '../../CheckContext';
import ContentColumn from '../layout/ContentColumn';
import ParsedText from '../ParsedText';

const messages = defineMessages({
  editError: {
    id: 'sourceComponent.editError',
    defaultMessage: 'Sorry, could not edit the source',
  },
  editSuccess: {
    id: 'sourceComponent.editSuccess',
    defaultMessage: 'Source information updated successfully!',
  },
});

class SourceComponent extends Component {

  constructor(props) {
    super(props);
    const source = this.props.source;
    this.state = {
      message: null,
      isEditing: false,
      submitDisabled: false,
      showTab: 'media',
    };
  }

  componentDidMount() {
    this.setContextSource();
  }

  componentDidUpdate() {
    this.setContextSource();
  }

  setContextSource() {
    // const context = new CheckContext(this);
    // const store = context.getContextStore();
    // const { team, project_id, source_id } = this.props.source;
    //
    // console.log('team');
    // console.log(team);
    // console.log('project_id');
    // console.log(project_id);
    // console.log('source_id');
    // console.log(source_id);
    //
    // const sourceUrl = `/${team.slug}/project/${project_id}/source/${source_id}`;
    //
    // if (!store.team || store.team.slug !== team.slug) {
    //   context.setContextStore({ team });
    //   // const path = `/${team.slug}`;
    //   store.history.push(sourceUrl);
    // }
  }

  showAnnotations() {
    this.setState({ showTab: 'annotation' });
  }

  showAccounts() {
    this.setState({ showTab: 'account' });
  }

  showMedias() {
    this.setState({ showTab: 'media' });
  }

  render() {
    const isProjectSource = !!this.props.source.source;
    const { source } = isProjectSource ? this.props.source : this.props;
    const isEditing = this.state.isEditing;

    return (
      <PageTitle prefix={source.name} skipTeam={false} team={source.team}>

          <Card className="source__profile source__profile--editing">
            <ContentColumn>
              <Message message={this.state.message} />

                    <div
                      className="source__avatar"
                      style={{ backgroundImage: `url(${source.image})` }}
                    />

                        {source.name}

                          {<ParsedText text={source.description} /> ||
                          <MappedMessage
                            msgObj={messages}
                            msgKey="verificationTeam"
                          />}

                    { isProjectSource ?

                        <FormattedHTMLMessage
                          id="sourceComponent.dateAdded" defaultMessage="Added {date} • Source of {number} links"
                          values={{
                            date: this.props.intl.formatDate(source.created_at, { year: 'numeric', month: 'short', day: '2-digit' }),
                            number: source.medias.edges.length || '0',
                          }}
                        />

 : null
                      }

                  {/* Source editing not implemented yet
                    <Can
                      permissions={source.permissions}
                      permission="update Source"
                    >
                      <IconButton
                        className="source__edit-button"
                        tooltip={
                          <FormattedMessage
                            id="sourceComponent.editButton"
                            defaultMessage="Edit profile"
                          />
                        }
                        tooltipPosition="top-center"
                      >
                        <MDEdit />
                      </IconButton>
                    </Can>
                    */}

            </ContentColumn>
            { isProjectSource ?
              <CardActions className="source__tab-buttons">
                <FlatButton
                  label={<FormattedMessage id="sourceComponent.notes" defaultMessage="Notes" />}
                  className="source__tab-button-notes"
                  primary={this.state.showTab === 'annotation'}
                  onClick={this.showAnnotations.bind(this)}
                />
                <FlatButton
                  primary={this.state.showTab === 'media'}
                  label={<FormattedMessage id="sourceComponent.medias" defaultMessage="Media" />}
                  onClick={this.showMedias.bind(this)}
                />
                <FlatButton
                  primary={this.state.showTab === 'account'}
                  onClick={this.showAccounts.bind(this)}
                  label={<FormattedMessage id="sourceComponent.network" defaultMessage="Networks" />}
                />
              </CardActions> : <CardActions />
            }
          </Card>

          { this.state.showTab === 'annotation' ? <Annotations annotations={source.annotations.edges} annotated={source} annotatedType="Source" /> : null }
          <ContentColumn>
            { this.state.showTab === 'media' ? <Medias medias={source.medias.edges} /> : null }
            { this.state.showTab === 'account' ? source.accounts.edges.map(account => <AccountCard key={account.node.id} account={account.node} />) : null }
          </ContentColumn>

      </PageTitle>
    );
  }
}

SourceComponent.propTypes = {
  intl: intlShape.isRequired,
  source: PropTypes.object,
};

SourceComponent.contextTypes = {
  store: React.PropTypes.object,
};

export default injectIntl(SourceComponent);
<|endoftext|>


<commit_before>var client = require('box-view').createClient('your api token')

module.exports = function (callback) {
  // your code here
}
<commit_msg>fix bug in template for 03<commit_after>var client = require('box-view').createClient('your api token')

module.exports = function (name, callback) {
  // your code here
}
<|endoftext|>


<commit_before>'use strict';
/**
 * Concrete implementation of Plotter strategy for creating
 * stacked bar charts.
 * @implements {Plotter}
 */
class StackedBarPlotter {
  constructor() {
    /** @private @const {number} name_
     * The column in a datasource data referring to the
     * name of the associated data.
     */
    this.name_ = 0;
    /** @private @const {number} data_
     * The column in a datasource referring to the data.
     */
    this.data_ = 1;
    /**
     * @private @const {Array<string>} colors_
     * An array of hexcodes representing the available color
     * options for stacks in the plot.
     */
    this.colors_ = d3.schemeCategory10;
    /**
     * @private @const {Object}
     * Maps stack names to their colors, which are assigned
     * from the colors array.
     */
    this.colorForStack_ = {};
  }
  /**
   * Initalises the chart by computing the scales for the axes and
   * drawing them. It also applies the labels to the graph (axes and
   * graph titles).
   * @param {GraphData} graph GraphData instance containing the raw data.
   * @param {Object} chart Chart to draw to.
   * @param {Object} chartDimensions Size of the chart.
   * @param {Object} data The processed data.
   */
  initChart_(graph, chart, chartDimensions, data) {
    this.outerBandScale_ = this.createXAxisScale_(graph, chartDimensions);
    this.scaleForYAxis_ = this.createYAxisScale_(chartDimensions, data);
    this.xAxisGenerator_ = d3.axisBottom(this.outerBandScale_);
    this.yAxisGenerator_ = d3.axisLeft(this.scaleForYAxis_);
    // Note that the group for the xaxis which is transformed must be
    // wrapped in another group. This is to have a g element which
    // preserves the co-ordinate system of the chart, allowing a
    // clip path to be used based on the co-ordinate system of the chart
    // rather than the transformed system of the axis.
    chart.append('g')
        .attr('class', 'xaxis')
        .append('g')
        .call(this.xAxisGenerator_)
        .attr('transform', `translate(0, ${chartDimensions.height})`);
    this.yAxisDrawing_ = chart.append('g')
        .call(this.yAxisGenerator_);
    this.keys_ = graph.keys();
    // Each story is assigned a band by the createXAxisScale function
    // which maintains the positions in which each category of the chart
    // will be rendered. This further divides these bands into
    // sub-bands for each data source, so that different labels can be
    // grouped within the same category.
    this.innerBandScale_ = this.createInnerBandScale_(graph);
  }

  getBarCategories_(graph) {
    // Process data sources so that their data contains only their categories.
    const dataSources = graph.process(data => data.map(row => row[this.name_]));
    if (dataSources.length > 0) {
      return dataSources[0].data;
    }
    return [];
  }

  createXAxisScale_(graph, chartDimensions) {
    return d3.scaleBand()
        .domain(this.getBarCategories_(graph))
        .range([0, chartDimensions.width])
        .padding(0.2);
  }

  createYAxisScale_(chartDimensions, sources) {
    const getStackHeights =
        stackNames => stackNames.map(stack => stack[this.data_].height);
    const getBarHeight =
        story => this.sum_(getStackHeights(story[this.data_]));
    const maxHeight =
        bars => d3.max(bars.map(story => getBarHeight(story)));
    const maxHeightOfAllSources =
        d3.max(sources.map(({ data }) => maxHeight(data)));
    const defaultRange = 1;
    return d3.scaleLinear()
        .domain([Math.round(maxHeightOfAllSources) || defaultRange, 0]).nice()
        .range([0, chartDimensions.height]);
  }

  createInnerBandScale_() {
    return d3.scaleBand()
        .domain(this.keys_)
        .range([0, this.outerBandScale_.bandwidth()]);
  }

  /**
   * Attempts to compute the average of the given numbers but returns
   * 0 if the supplied array is empty.
   * @param {Array<number>} data
   * @returns {number}
   */
  avg_(data) {
    return this.sum_(data) / data.length || 0;
  }

  sum_(data) {
    if (!data.every(val => typeof val === 'number')) {
      throw new TypeError('Expected an array of numbers.');
    }
    return data.reduce((a, b) => a + b, 0);
  }

  getColorForStack_(name) {
    if (!(name in this.colorForStack_)) {
      const numColors = this.colors_.length;
      const numAssigned = Object.entries(this.colorForStack_).length;
      this.colorForStack_[name] = this.colors_[numAssigned % numColors];
    }
    return this.colorForStack_[name];
  }

  /**
   * Computes the start position and height of each stack for
   * the bar corresponing to the supplied data.
   * @param {Object} data The data for a single bar. Each key
   * corresponds to the label for the stack and the value that
   * key represents the values associated with that label.
   * For example:
   * {
   *  stackOne: [numbers...]
   *  stackTwo: [numbers...]
   * }
   * will compute the positions for a bar that has two stacks,
   * the height of each being the average of numbers...
   */
  stackLocations_(data) {
    const stackedAverages = [];
    let cumulativeAvg = 0;
    const compareStackNames = ([a], [b]) => a.localeCompare(b);
    const stacks = Object.entries(data).sort(compareStackNames);
    for (const [name, values] of stacks) {
      const average = this.avg_(values);
      const yValues = {
        start: cumulativeAvg,
        height: average,
      };
      cumulativeAvg += average;
      stackedAverages.push([name, yValues]);
    }
    return stackedAverages;
  }

  getNumericLabelForKey_(key) {
    return this.keys_.indexOf(key) + 1;
  }
  /**
   * Draws a stacked bar chart to the canvas. This expects the data
   * in graph to be formatted as a table, with the first column being categories
   * and the second being the corresponding values.
   * @param {GraphData} graph The data to be plotted.
   * @param {Object} chart d3 selection for the chart element to be drawn on.
   * @param {Object} legend d3 selection for the legend element for
   * additional information to be drawn on.
   * @param {Object} chartDimensions The margins, width and height
   * of the chart. This is useful for computing appropriates axis
   * scales and positioning elements.
   */
  plot(graph, chart, legend, chartDimensions) {
    const formatBars = bars =>
      bars.map(
          ([story, values]) => [story, this.stackLocations_(values)]);
    const bars = graph.process(formatBars);
    this.initChart_(graph, chart, chartDimensions, bars);
    bars.forEach(({ data, key }) => {
      data.forEach((bars) => {
        this.drawStackedBar_(chart, bars, chartDimensions, key, graph);
      });
    });
    if (bars.length > 0) {
      const bar = bars[0];
      const stacks = bar.data;
      if (stacks.length > 0) {
        const stackNames = stacks[0][this.data_].map(([name]) => name);
        this.drawLegendLabels_(legend, stackNames);
      }
    }
    const tickRotation = -30;
    d3.select('.xaxis')
        .attr('clip-path', 'url(#regionForXAxisTickText)');
    d3.selectAll('.xaxis text')
        .attr('text-anchor', 'end')
        .attr('font-size', 12)
        .attr('transform', `rotate(${tickRotation})`)
        .append('title')
        .text(text => text);
  }

  drawLegendLabels_(legend, stackNames) {
    stackNames.forEach((stackName, i) => {
      const boxSize = 10;
      const offset = `${i * 1}em`;
      legend.append('rect')
          .attr('fill', this.getColorForStack_(stackName))
          .attr('height', boxSize)
          .attr('width', boxSize)
          .attr('y', offset)
          .attr('x', 0);
      legend.append('text')
          .text(stackName)
          .attr('x', boxSize)
          .attr('y', offset)
          .attr('dy', boxSize)
          .attr('text-anchor', 'start');
    });
    this.keys_.forEach((key, i) => {
      const belowStackNames = `${stackNames.length + 1}em`;
      const offset = `${i}em`;
      legend.append('text')
          .text(`${this.getNumericLabelForKey_(key)}: ${key}`)
          .attr('y', belowStackNames)
          .attr('dy', offset)
          .append('title')
          .text(key);
    });
  }

  drawStackedBar_(selection, bars, chartDimensions, key, graph) {
    const barName = bars[this.name_];
    const stacks = bars[this.data_];
    const x = this.outerBandScale_(barName) + this.innerBandScale_(key);
    let totalHeight = 0;
    stacks.forEach(stack => {
      const positions = stack[this.data_];
      const height =
          chartDimensions.height - this.scaleForYAxis_(positions.height);
      selection.append('rect')
          .attr('x', x)
          .attr('y', this.scaleForYAxis_(positions.height + positions.start))
          .attr('width', this.innerBandScale_.bandwidth())
          .attr('height', height)
          .attr('fill', this.getColorForStack_(stack[this.name_]))
          .on('click', () =>
            graph.interactiveCallbackForCategory(stack[this.name_]))
          .on('mouseover', function() {
            d3.select(this).attr('opacity', 0.5);
          })
          .on('mouseout', function() {
            // Removes the opacity attribute.
            d3.select(this).attr('opacity', null);
          });
      totalHeight += positions.height;
    });
    const barMid = x + this.innerBandScale_.bandwidth() / 2;
    const padding = 5;
    selection.append('text')
        .text(this.getNumericLabelForKey_(key))
        .attr('fill', 'black')
        .attr('y', this.scaleForYAxis_(totalHeight) - padding)
        .attr('x', barMid)
        .append('title')
        .text(key);
  }
}
<commit_msg>Add title attribute to provide stack name on mouseover.<commit_after>'use strict';
/**
 * Concrete implementation of Plotter strategy for creating
 * stacked bar charts.
 * @implements {Plotter}
 */
class StackedBarPlotter {
  constructor() {
    /** @private @const {number} name_
     * The column in a datasource data referring to the
     * name of the associated data.
     */
    this.name_ = 0;
    /** @private @const {number} data_
     * The column in a datasource referring to the data.
     */
    this.data_ = 1;
    /**
     * @private @const {Array<string>} colors_
     * An array of hexcodes representing the available color
     * options for stacks in the plot.
     */
    this.colors_ = d3.schemeCategory10;
    /**
     * @private @const {Object}
     * Maps stack names to their colors, which are assigned
     * from the colors array.
     */
    this.colorForStack_ = {};
  }
  /**
   * Initalises the chart by computing the scales for the axes and
   * drawing them. It also applies the labels to the graph (axes and
   * graph titles).
   * @param {GraphData} graph GraphData instance containing the raw data.
   * @param {Object} chart Chart to draw to.
   * @param {Object} chartDimensions Size of the chart.
   * @param {Object} data The processed data.
   */
  initChart_(graph, chart, chartDimensions, data) {
    this.outerBandScale_ = this.createXAxisScale_(graph, chartDimensions);
    this.scaleForYAxis_ = this.createYAxisScale_(chartDimensions, data);
    this.xAxisGenerator_ = d3.axisBottom(this.outerBandScale_);
    this.yAxisGenerator_ = d3.axisLeft(this.scaleForYAxis_);
    // Note that the group for the xaxis which is transformed must be
    // wrapped in another group. This is to have a g element which
    // preserves the co-ordinate system of the chart, allowing a
    // clip path to be used based on the co-ordinate system of the chart
    // rather than the transformed system of the axis.
    chart.append('g')
        .attr('class', 'xaxis')
        .append('g')
        .call(this.xAxisGenerator_)
        .attr('transform', `translate(0, ${chartDimensions.height})`);
    this.yAxisDrawing_ = chart.append('g')
        .call(this.yAxisGenerator_);
    this.keys_ = graph.keys();
    // Each story is assigned a band by the createXAxisScale function
    // which maintains the positions in which each category of the chart
    // will be rendered. This further divides these bands into
    // sub-bands for each data source, so that different labels can be
    // grouped within the same category.
    this.innerBandScale_ = this.createInnerBandScale_(graph);
  }

  getBarCategories_(graph) {
    // Process data sources so that their data contains only their categories.
    const dataSources = graph.process(data => data.map(row => row[this.name_]));
    if (dataSources.length > 0) {
      return dataSources[0].data;
    }
    return [];
  }

  createXAxisScale_(graph, chartDimensions) {
    return d3.scaleBand()
        .domain(this.getBarCategories_(graph))
        .range([0, chartDimensions.width])
        .padding(0.2);
  }

  createYAxisScale_(chartDimensions, sources) {
    const getStackHeights =
        stackNames => stackNames.map(stack => stack[this.data_].height);
    const getBarHeight =
        story => this.sum_(getStackHeights(story[this.data_]));
    const maxHeight =
        bars => d3.max(bars.map(story => getBarHeight(story)));
    const maxHeightOfAllSources =
        d3.max(sources.map(({ data }) => maxHeight(data)));
    const defaultRange = 1;
    return d3.scaleLinear()
        .domain([Math.round(maxHeightOfAllSources) || defaultRange, 0]).nice()
        .range([0, chartDimensions.height]);
  }

  createInnerBandScale_() {
    return d3.scaleBand()
        .domain(this.keys_)
        .range([0, this.outerBandScale_.bandwidth()]);
  }

  /**
   * Attempts to compute the average of the given numbers but returns
   * 0 if the supplied array is empty.
   * @param {Array<number>} data
   * @returns {number}
   */
  avg_(data) {
    return this.sum_(data) / data.length || 0;
  }

  sum_(data) {
    if (!data.every(val => typeof val === 'number')) {
      throw new TypeError('Expected an array of numbers.');
    }
    return data.reduce((a, b) => a + b, 0);
  }

  getColorForStack_(name) {
    if (!(name in this.colorForStack_)) {
      const numColors = this.colors_.length;
      const numAssigned = Object.entries(this.colorForStack_).length;
      this.colorForStack_[name] = this.colors_[numAssigned % numColors];
    }
    return this.colorForStack_[name];
  }

  /**
   * Computes the start position and height of each stack for
   * the bar corresponing to the supplied data.
   * @param {Object} data The data for a single bar. Each key
   * corresponds to the label for the stack and the value that
   * key represents the values associated with that label.
   * For example:
   * {
   *  stackOne: [numbers...]
   *  stackTwo: [numbers...]
   * }
   * will compute the positions for a bar that has two stacks,
   * the height of each being the average of numbers...
   */
  stackLocations_(data) {
    const stackedAverages = [];
    let cumulativeAvg = 0;
    const compareStackNames = ([a], [b]) => a.localeCompare(b);
    const stacks = Object.entries(data).sort(compareStackNames);
    for (const [name, values] of stacks) {
      const average = this.avg_(values);
      const yValues = {
        start: cumulativeAvg,
        height: average,
      };
      cumulativeAvg += average;
      stackedAverages.push([name, yValues]);
    }
    return stackedAverages;
  }

  getNumericLabelForKey_(key) {
    return this.keys_.indexOf(key) + 1;
  }
  /**
   * Draws a stacked bar chart to the canvas. This expects the data
   * in graph to be formatted as a table, with the first column being categories
   * and the second being the corresponding values.
   * @param {GraphData} graph The data to be plotted.
   * @param {Object} chart d3 selection for the chart element to be drawn on.
   * @param {Object} legend d3 selection for the legend element for
   * additional information to be drawn on.
   * @param {Object} chartDimensions The margins, width and height
   * of the chart. This is useful for computing appropriates axis
   * scales and positioning elements.
   */
  plot(graph, chart, legend, chartDimensions) {
    const formatBars = bars =>
      bars.map(
          ([story, values]) => [story, this.stackLocations_(values)]);
    const bars = graph.process(formatBars);
    this.initChart_(graph, chart, chartDimensions, bars);
    bars.forEach(({ data, key }) => {
      data.forEach((bars) => {
        this.drawStackedBar_(chart, bars, chartDimensions, key, graph);
      });
    });
    if (bars.length > 0) {
      const bar = bars[0];
      const stacks = bar.data;
      if (stacks.length > 0) {
        const stackNames = stacks[0][this.data_].map(([name]) => name);
        this.drawLegendLabels_(legend, stackNames);
      }
    }
    const tickRotation = -30;
    d3.select('.xaxis')
        .attr('clip-path', 'url(#regionForXAxisTickText)');
    d3.selectAll('.xaxis text')
        .attr('text-anchor', 'end')
        .attr('font-size', 12)
        .attr('transform', `rotate(${tickRotation})`)
        .append('title')
        .text(text => text);
  }

  drawLegendLabels_(legend, stackNames) {
    stackNames.forEach((stackName, i) => {
      const boxSize = 10;
      const offset = `${i * 1}em`;
      legend.append('rect')
          .attr('fill', this.getColorForStack_(stackName))
          .attr('height', boxSize)
          .attr('width', boxSize)
          .attr('y', offset)
          .attr('x', 0);
      legend.append('text')
          .text(stackName)
          .attr('x', boxSize)
          .attr('y', offset)
          .attr('dy', boxSize)
          .attr('text-anchor', 'start');
    });
    this.keys_.forEach((key, i) => {
      const belowStackNames = `${stackNames.length + 1}em`;
      const offset = `${i}em`;
      legend.append('text')
          .text(`${this.getNumericLabelForKey_(key)}: ${key}`)
          .attr('y', belowStackNames)
          .attr('dy', offset)
          .append('title')
          .text(key);
    });
  }

  drawStackedBar_(selection, bars, chartDimensions, key, graph) {
    const barName = bars[this.name_];
    const stacks = bars[this.data_];
    const x = this.outerBandScale_(barName) + this.innerBandScale_(key);
    let totalHeight = 0;
    stacks.forEach(stack => {
      const positions = stack[this.data_];
      const height =
          chartDimensions.height - this.scaleForYAxis_(positions.height);
      selection.append('rect')
          .attr('x', x)
          .attr('y', this.scaleForYAxis_(positions.height + positions.start))
          .attr('width', this.innerBandScale_.bandwidth())
          .attr('height', height)
          .attr('fill', this.getColorForStack_(stack[this.name_]))
          .on('click', () =>
            graph.interactiveCallbackForCategory(stack[this.name_]))
          .on('mouseover', function() {
            d3.select(this).attr('opacity', 0.5);
          })
          .on('mouseout', function() {
            // Removes the opacity attribute.
            d3.select(this).attr('opacity', null);
          })
          .append('title')
          .text(stack[this.name_]);
      totalHeight += positions.height;
    });
    const barMid = x + this.innerBandScale_.bandwidth() / 2;
    const padding = 5;
    selection.append('text')
        .text(this.getNumericLabelForKey_(key))
        .attr('fill', 'black')
        .attr('y', this.scaleForYAxis_(totalHeight) - padding)
        .attr('x', barMid)
        .append('title')
        .text(key);
  }
}
<|endoftext|>


<commit_before>define(['app', 'underscore', '/app/views/forms/edit/edit.js', '/app/views/directives/help-directive.html.js', '/app/js/common.js',
 '/app/views/forms/edit/document-selector.html.js', '/app/views/forms/edit/warning-message-cna.html.js',
        '../view/view-authority.directive.js'
        ], function(app, _) {

    app.controller("editAuthority", ["$scope", "$http", "$filter", "Thesaurus", "$q", "$controller", "Enumerable", "$location", "IStorage", "commonjs",'searchService',
     function($scope, $http, $filter, Thesaurus, $q, $controller, Enumerable, $location, storage, commonjs,searchService) {
        $controller('editController', {
            $scope: $scope
        });

        $scope.getMeasures=[];
        $scope.path = $location.path();
        //$scope.documentUID = "NEW";

        _.extend($scope.options, {
            organizationTypes: function() {
                return $http.get("/api/v2013/thesaurus/domains/Organization%20Types/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            cbdSubjects: function() {
                return $http.get("/api/v2013/thesaurus/domains/CBD-SUBJECTS/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            jurisdictions: function() {
                return $q.all([
                    $http.get("/api/v2013/thesaurus/domains/D7BD5BDE-A6B9-4261-B788-16839CCC4F7E/terms", {
                        cache: true
                    }),
                    $http.get("/api/v2013/thesaurus/terms/5B6177DD-5E5E-434E-8CB7-D63D67D5EBED", {
                        cache: true
                    })
                ]).then(function(o) {
                    var jurisdictions = o[0].data;
                    jurisdictions.push(o[1].data);
                    return jurisdictions;
                });
            },
            absGeneticResourceTypes: function() {
                return $http.get("/api/v2013/thesaurus/domains/20945FA8-C24C-4AF6-B3D9-367592AFDF48/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            absGeneticResourceAreas: function() {
                return $http.get("/api/v2013/thesaurus/domains/545CD54C-CFF3-41E8-A003-FDD278426A3A/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            cpbFunctions: function() {
                return $http.get("/api/v2013/thesaurus/domains/Subject Areas/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            cpbOrganismTypes: function() {
                return $http.get("/api/v2013/thesaurus/domains/TypeOfOrganisms/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            absFunctions: function() {
                return $http.get("/api/v2013/thesaurus/domains/8102E184-E282-47F7-A49F-4C219B0EE235/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            keywords: function() {
                return $http.get("/api/v2013/thesaurus/domains/1A22EAAB-9BBC-4543-890E-DEF913F59E98/terms", {
                    cache: true
                }).then(function(o) {
                    return Thesaurus.buildTree(o.data);
                });
            },

        });

        //==================================
        $scope.showResponsibleforAllMsg = function() {

            //TODO: you need to gain access to the promise in order to do this correctly.a Otherwise the document won't be loaded when angular evaluated the ng-show.
            if (!$scope.document || (!$scope.document.absResponsibleForAll || !$scope.validationReport))
                return false;

            return Enumerable.from($scope.validationReport.errors).any(function(error) {
                return error.property == 'absResponsibleForAllNot';
            });
        };

        //==================================
        //
        //==================================
        $scope.getCleanDocument = function(document) {

            document = document || $scope.document;

            if (!document)
                return undefined;

            //document = angular.fromJson(angular.toJson(document));

            if (!document.picGranted) {
                document.consentInformation = undefined;
                document.consentDocuments = undefined;
            }

            if (!document.mutuallyAgreedTermsEstablished) {
                document.matInformation = undefined;
                document.matDocuments = undefined;
            }

            if (document.gisFiles && document.gisFiles.length === 0) {
                document.gisFiles = undefined;
            }

            if (document.amendedPermits && document.amendedPermits.length === 0) {
                document.amendedPermits = undefined;
            }

            if (!document.amendedPermits) {
                document.consentedAmendment = undefined;
                document.amendmentsDescription = undefined;
            }
            if (document.providersConfidential) {
                document.providers = undefined;
            }
            if (document.entitiesToWhomPICGrantedConfidential) {
                document.entitiesToWhomPICGranted = undefined;
            }
            if (document.geneticResourcesConfidential) {
                document.geneticResources = undefined;
                document.specimen = undefined;
                document.taxonomies = undefined;
                document.gisFiles = undefined;
                document.gisMapCenter = undefined;
            }
            if (document.absResponsibleForAll) {
                document.responsibilities = undefined;
                document.absJurisdiction = undefined;
                document.absJurisdictionName = undefined;
                document.absGeneticResourceTypes = undefined;
            }
            else{
                if(!$scope.showJurisdictionName())
                    document.absJurisdictionName = undefined;
            }

            if (/^\s*$/g.test(document.notes))
                document.notes = undefined;

            return document;
        };
        //==================================
        $scope.setDocument({
            libraries: [{
                identifier: "cbdLibrary:abs-ch"
            }]
        });

        //==================================
        $scope.showJurisdictionName = function() {

            if (!$scope.document || !$scope.document.absJurisdiction)
                return false;

            //var jurisdictions = $scope.document.absJurisdiction
            return _.intersection(_.pluck($scope.document.absJurisdiction, 'identifier'),
                                ['DEBB019D-8647-40EC-8AE5-10CA88572F6E', 'DEEEDB35-A34B-4755-BF77-D713017195E3', '5B6177DD-5E5E-434E-8CB7-D63D67D5EBED']).length > 0;
        }

    }]);
});
<commit_msg>revert changes on authority<commit_after>define(['app', 'underscore', '/app/views/forms/edit/edit.js', '/app/views/directives/help-directive.html.js', '/app/js/common.js',
 '/app/views/forms/edit/document-selector.html.js', '/app/views/forms/edit/warning-message-cna.html.js',
        '../view/view-authority.directive.js'
        ], function(app, _) {

    app.controller("editAuthority", ["$scope", "$http", "$filter", "Thesaurus", "$q", "$controller", "Enumerable", "$location", "IStorage", "commonjs",'searchService',
     function($scope, $http, $filter, Thesaurus, $q, $controller, Enumerable, $location, storage, commonjs,searchService) {
        $controller('editController', {
            $scope: $scope
        });

        $scope.getMeasures=[];
        $scope.path = $location.path();
        //$scope.documentUID = "NEW";

        _.extend($scope.options, {
            organizationTypes: function() {
                return $http.get("/api/v2013/thesaurus/domains/Organization%20Types/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            cbdSubjects: function() {
                return $http.get("/api/v2013/thesaurus/domains/CBD-SUBJECTS/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            jurisdictions: function() {
                return $q.all([
                    $http.get("/api/v2013/thesaurus/domains/D7BD5BDE-A6B9-4261-B788-16839CCC4F7E/terms", {
                        cache: true
                    }),
                    $http.get("/api/v2013/thesaurus/terms/5B6177DD-5E5E-434E-8CB7-D63D67D5EBED", {
                        cache: true
                    })
                ]).then(function(o) {
                    var jurisdictions = o[0].data;
                    jurisdictions.push(o[1].data);
                    return jurisdictions;
                });
            },
            absGeneticResourceTypes: function() {
                return $http.get("/api/v2013/thesaurus/domains/20945FA8-C24C-4AF6-B3D9-367592AFDF48/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            absGeneticResourceAreas: function() {
                return $http.get("/api/v2013/thesaurus/domains/545CD54C-CFF3-41E8-A003-FDD278426A3A/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            cpbFunctions: function() {
                return $http.get("/api/v2013/thesaurus/domains/Subject Areas/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            cpbOrganismTypes: function() {
                return $http.get("/api/v2013/thesaurus/domains/TypeOfOrganisms/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            absFunctions: function() {
                return $http.get("/api/v2013/thesaurus/domains/8102E184-E282-47F7-A49F-4C219B0EE235/terms", {
                    cache: true
                }).then(function(o) {
                    return o.data;
                });
            },
            keywords: function() {
                return $http.get("/api/v2013/thesaurus/domains/1A22EAAB-9BBC-4543-890E-DEF913F59E98/terms", {
                    cache: true
                }).then(function(o) {
                    return Thesaurus.buildTree(o.data);
                });
            },

        });

        //==================================
        $scope.showResponsibleforAllMsg = function() {

            //TODO: you need to gain access to the promise in order to do this correctly.a Otherwise the document won't be loaded when angular evaluated the ng-show.
            if (!$scope.document || (!$scope.document.absResponsibleForAll || !$scope.validationReport))
                return false;

            return Enumerable.from($scope.validationReport.errors).any(function(error) {
                return error.property == 'absResponsibleForAllNot';
            });
        };

        //==================================
        //
        //==================================
        $scope.getCleanDocument = function(document) {

            document = document || $scope.document;

            if (!document)
                return undefined;

            //document = angular.fromJson(angular.toJson(document));

            if (!document.consentGranted) {
                document.consentInformation = undefined;
                document.consentDocuments = undefined;
            }

            if (!document.mutuallyAgreedTermsInformation) {
                document.mutuallyAgreedTermsInformation = undefined;
                document.mutuallyAgreedTermsDocuments = undefined;
            }

            if (document.gisFiles && document.gisFiles.length === 0) {
                document.gisFiles = undefined;
            }

            if (document.amendedPermits && document.amendedPermits.length === 0) {
                document.amendedPermits = undefined;
            }

            if (!document.amendedPermits) {
                document.consentedAmendment = undefined;
                document.amendmentsDescription = undefined;
            }
            if (document.providerConfidential) {
                document.provider = undefined;
            }
            if (document.informedConsentConfidential) {
                document.informedConsents = undefined;
            }
            if (document.geneticResourcesConfidential) {
                document.geneticResources = undefined;
                document.specimen = undefined;
                document.taxonomy = undefined;
                document.gisFiles = undefined;
                document.gisMapCenter = undefined;
            }
            if (document.absResponsibleForAll) {
                document.responsibilities = undefined;
                document.absJurisdiction = undefined;
                document.absJurisdictionName = undefined;
                document.absGeneticResourceTypes = undefined;
            }
            else{
                if(!$scope.showJurisdictionName())
                    document.absJurisdictionName = undefined;
            }

            if (/^\s*$/g.test(document.notes))
                document.notes = undefined;

            return document;
        };
        //==================================
        $scope.setDocument({
            libraries: [{
                identifier: "cbdLibrary:abs-ch"
            }]
        });

        //==================================
        $scope.showJurisdictionName = function() {

            if (!$scope.document || !$scope.document.absJurisdiction)
                return false;

            //var jurisdictions = $scope.document.absJurisdiction
            return _.intersection(_.pluck($scope.document.absJurisdiction, 'identifier'),
                                ['DEBB019D-8647-40EC-8AE5-10CA88572F6E', 'DEEEDB35-A34B-4755-BF77-D713017195E3', '5B6177DD-5E5E-434E-8CB7-D63D67D5EBED']).length > 0;
        }

    }]);
});
<|endoftext|>


<commit_before>import { BlankConfig }        from './blank/config/stepway.blank.config';
import {editBlankControlComponent, EDIT_BLANK_CONTROL_COMPONENT} from './blank/editBlank/stepway.editBlank.component';
import editBlankModule  from './blank/editBlank/stepway.editBlankControl.module';

import { IpAdressConfig }     from './IpAdress/config/stepway.IpAdress.config';
import {editIpAdressControlComponent, EDIT_IP_ADRESS_COMPONENT} from './IpAdress/editIpAdress/stepway.editIpAdress.component';
import editIpAdressModule  from './IpAdress/editIpAdress/stepway.editIpAdress.module';

import { DateConfig }         from './Date/config/stepway.date.config';
import {editDateControlComponent, EDIT_DATE_COMPONENT} from './Date/editDate/stepway.editDate.component';
import editDateModule from './Date/editDate/stepway.editDate.module';

import { CheckBoxConfig }     from './CheckBox/config/stepway.checkbox.config';
import {editCheckBoxControlComponent, EDIT_CHECKBOX_COMPONENT} from './CheckBox/editCheckBox/stepway.editCheckBox.component';
import editCheckBoxModule from './CheckBox/editCheckBox/stepway.editCheckBox.module';

import { EmailConfig }        from './Email/config/stepway.email.config';
import {editEmailControlComponent, EDIT_EMAIL_COMPONENT} from './Email/editEmail/stepway.editEmail.component';
import editEmailControlModule from './Email/editEmail/stepway.editEmail.module';

import { BasicSelectConfig }  from './basicSelect/config/stepway.basicSelect.config';
import {editBasicSelectControlComponent, EDIT_BASIC_SELECT_COMPONENT} from './basicSelect/editBasicSelect/stepway.editbasicSelect.component';
import editbasicSelectModule  from './basicSelect/editBasicSelect/stepway.editBasicSelect.module';

import { GroupedSelectConfig }  from './groupedSelect/config/stepway.groupedSelect.config';
import {editGroupedSelectControlComponent, EDIT_GROUPED_SELECT_COMPONENT} from './groupedSelect/editgroupedSelect/stepway.editgroupedSelect.component';
import editGroupedSelectModule  from './groupedSelect/editGroupedSelect/stepway.editGroupedSelect.module';

import { HeaderConfig }  from './header/config/stepway.header.config';
import {editHeaderControlComponent, EDIT_HEADER_CONTROL_COMPONENT} from './header/editHeader/stepway.editHeaderSelect.component';
import editHeaderControl from 'header/editHeader/stepway.editHeaderSelect.module';

import { PasswordConfig }  from './password/config/stepway.password.config';
import {editPasswordControlComponent, EDIT_PASSWORD_CONTROL_COMPONENT} from './password/editPassword/stepway.editPassword.component';

import { RadioConfig }  from './radio/config/stepway.radio.config';
import {editRadioControlComponent, EDIT_RADIO_CONTROL_COMPONENT} from './radio/editRadio/stepway.editRadio.component';

import { RichTextEditorConfig }  from './richTextEditor/config/stepway.richTextEditor.config';
import {editRichTextEditorControlComponent, EDIT_RICH_TEXT_EDITOR_COMPONENT} from './richTextEditor/editRichTextEditor/stepway.editRichTextEditor.component';

import { SubTitleConfig }  from './subTitle/config/stepway.subTitle.config';
import {editSubTitleControlComponent, EDIT_SUBTITLE_CONTROL_COMPONENT} from './subTitle/editSubTitle/stepway.editSubTitle.component';
import editSubTitle from './subTitle/editSubTitle/stepway.editSubTitle.module';

import { TextAreaConfig }  from './textArea/config/stepway.textArea.config';
import {editTextareaControlComponent, EDIT_TEXTAREA_CONTROL_COMPONENT} from './textArea/editTextArea/stepway.editTextArea.component';
import editTextareaControlModule from './textArea/editTextArea/stepway.editTextArea.module';

// import TextInputModule

// controls configs
const configs = {
  IpAdressConfig,
  DateConfig,
  CheckBoxConfig,
  EmailConfig,
  BasicSelectConfig,
  BlankConfig,
  GroupedSelectConfig,
  HeaderConfig,
  PasswordConfig,
  RadioConfig,
  RichTextEditorConfig,
  SubTitleConfig,
  TextAreaConfig
};

// controls component (for edit control modal)
const controls = {
  editBlank: {
    name: EDIT_BLANK_CONTROL_COMPONENT,
    component: editBlankControlComponent,
    moduleName: editBlankModule.name
  },
  editIpAdress: {
    name:       EDIT_IP_ADRESS_COMPONENT,
    component:  editIpAdressControlComponent,
    moduleName: editIpAdressModule.name
  },
  editDate: {
    name:       EDIT_DATE_COMPONENT,
    component:  editDateControlComponent,
    moduleName: editDateModule.name
  },
  editBasicSelect: {
    name: EDIT_BASIC_SELECT_COMPONENT,
    component: editBasicSelectControlComponent,
    moduleName: editbasicSelectModule.name
  },
  editGroupedSelect: {
    name: EDIT_GROUPED_SELECT_COMPONENT,
    component: editGroupedSelectControlComponent,
    moduleName: editGroupedSelectModule.name
  },
  editCheckBox: {
    name: EDIT_CHECKBOX_COMPONENT,
    component: editCheckBoxControlComponent,
    moduleName: editCheckBoxModule.name
  },
  editEmail: {
    name: EDIT_EMAIL_COMPONENT,
    component: editEmailControlComponent,
    moduleName: editEmailControlModule
  },
  editHeader: {
    name: EDIT_HEADER_CONTROL_COMPONENT,
    component: editHeaderControlComponent,
    moduleName: editHeaderControl
  },
  editPassword: {
    name: EDIT_PASSWORD_CONTROL_COMPONENT,
    component: editPasswordControlComponent
  },
  editRadio: {
    name: EDIT_RADIO_CONTROL_COMPONENT,
    component: editRadioControlComponent
  },
  editRichTextEditor: {
    name: EDIT_RICH_TEXT_EDITOR_COMPONENT,
    component: editRichTextEditorControlComponent
  },
  editSubTitle: {
    name: EDIT_SUBTITLE_CONTROL_COMPONENT,
    component: editSubTitleControlComponent,
    moduleName: editSubTitle.name
  },
  editTextArea: {
    name: EDIT_TEXTAREA_CONTROL_COMPONENT,
    component: editTextareaControlComponent,
    moduleName: editTextareaControlModule.name
  }
};

export {
  configs,
  controls
};
<commit_msg>chore : refactor<commit_after>import { BlankConfig }        from './blank/config/stepway.blank.config';
import {editBlankControlComponent, EDIT_BLANK_CONTROL_COMPONENT} from './blank/editBlank/stepway.editBlank.component';
import editBlankModule  from './blank/editBlank/stepway.editBlankControl.module';

import { IpAdressConfig }     from './IpAdress/config/stepway.IpAdress.config';
import {editIpAdressControlComponent, EDIT_IP_ADRESS_COMPONENT} from './IpAdress/editIpAdress/stepway.editIpAdress.component';
import editIpAdressModule  from './IpAdress/editIpAdress/stepway.editIpAdress.module';

import { DateConfig }         from './Date/config/stepway.date.config';
import {editDateControlComponent, EDIT_DATE_COMPONENT} from './Date/editDate/stepway.editDate.component';
import editDateModule from './Date/editDate/stepway.editDate.module';

import { CheckBoxConfig }     from './CheckBox/config/stepway.checkbox.config';
import {editCheckBoxControlComponent, EDIT_CHECKBOX_COMPONENT} from './CheckBox/editCheckBox/stepway.editCheckBox.component';
import editCheckBoxModule from './CheckBox/editCheckBox/stepway.editCheckBox.module';

import { EmailConfig }        from './Email/config/stepway.email.config';
import {editEmailControlComponent, EDIT_EMAIL_COMPONENT} from './Email/editEmail/stepway.editEmail.component';
import editEmailControlModule from './Email/editEmail/stepway.editEmail.module';

import { BasicSelectConfig }  from './basicSelect/config/stepway.basicSelect.config';
import {editBasicSelectControlComponent, EDIT_BASIC_SELECT_COMPONENT} from './basicSelect/editBasicSelect/stepway.editbasicSelect.component';
import editbasicSelectModule  from './basicSelect/editBasicSelect/stepway.editBasicSelect.module';

import { GroupedSelectConfig }  from './groupedSelect/config/stepway.groupedSelect.config';
import {editGroupedSelectControlComponent, EDIT_GROUPED_SELECT_COMPONENT} from './groupedSelect/editgroupedSelect/stepway.editgroupedSelect.component';
import editGroupedSelectModule  from './groupedSelect/editGroupedSelect/stepway.editGroupedSelect.module';

import { HeaderConfig }  from './header/config/stepway.header.config';
import {editHeaderControlComponent, EDIT_HEADER_CONTROL_COMPONENT} from './header/editHeader/stepway.editHeaderSelect.component';
import editHeaderControl from 'header/editHeader/stepway.editHeaderSelect.module';

import { PasswordConfig }  from './password/config/stepway.password.config';
import {editPasswordControlComponent, EDIT_PASSWORD_CONTROL_COMPONENT} from './password/editPassword/stepway.editPassword.component';

import { RadioConfig }  from './radio/config/stepway.radio.config';
import {editRadioControlComponent, EDIT_RADIO_CONTROL_COMPONENT} from './radio/editRadio/stepway.editRadio.component';

import { RichTextEditorConfig }  from './richTextEditor/config/stepway.richTextEditor.config';
import {editRichTextEditorControlComponent, EDIT_RICH_TEXT_EDITOR_COMPONENT} from './richTextEditor/editRichTextEditor/stepway.editRichTextEditor.component';

import { SubTitleConfig }  from './subTitle/config/stepway.subTitle.config';
import {editSubTitleControlComponent, EDIT_SUBTITLE_CONTROL_COMPONENT} from './subTitle/editSubTitle/stepway.editSubTitle.component';
import editSubTitle from './subTitle/editSubTitle/stepway.editSubTitle.module';

import { TextAreaConfig }  from './textArea/config/stepway.textArea.config';
import {editTextareaControlComponent, EDIT_TEXTAREA_CONTROL_COMPONENT} from './textArea/editTextArea/stepway.editTextArea.component';
import editTextareaControlModule from './textArea/editTextArea/stepway.editTextArea.module';

import { TextInputConfig }  from './textInput/config/stepway.textInput.config';
import {editTextInputControlComponent, EDIT_TEXTINPUT_CONTROL_COMPONENT} from './textInput/editTextInput/stepway.editTextInput.component';
import editTextInputControlModule from './textInput/editTextInput/stepway.editTextInput.module';

// controls configs
const configs = {
  IpAdressConfig,
  DateConfig,
  CheckBoxConfig,
  EmailConfig,
  BasicSelectConfig,
  BlankConfig,
  GroupedSelectConfig,
  HeaderConfig,
  PasswordConfig,
  RadioConfig,
  RichTextEditorConfig,
  SubTitleConfig,
  TextAreaConfig,
  TextInputConfig
};

// controls component (for edit control modal)
const controls = {
  editBlank: {
    name: EDIT_BLANK_CONTROL_COMPONENT,
    component: editBlankControlComponent,
    moduleName: editBlankModule.name
  },
  editIpAdress: {
    name:       EDIT_IP_ADRESS_COMPONENT,
    component:  editIpAdressControlComponent,
    moduleName: editIpAdressModule.name
  },
  editDate: {
    name:       EDIT_DATE_COMPONENT,
    component:  editDateControlComponent,
    moduleName: editDateModule.name
  },
  editBasicSelect: {
    name: EDIT_BASIC_SELECT_COMPONENT,
    component: editBasicSelectControlComponent,
    moduleName: editbasicSelectModule.name
  },
  editGroupedSelect: {
    name: EDIT_GROUPED_SELECT_COMPONENT,
    component: editGroupedSelectControlComponent,
    moduleName: editGroupedSelectModule.name
  },
  editCheckBox: {
    name: EDIT_CHECKBOX_COMPONENT,
    component: editCheckBoxControlComponent,
    moduleName: editCheckBoxModule.name
  },
  editEmail: {
    name: EDIT_EMAIL_COMPONENT,
    component: editEmailControlComponent,
    moduleName: editEmailControlModule
  },
  editHeader: {
    name: EDIT_HEADER_CONTROL_COMPONENT,
    component: editHeaderControlComponent,
    moduleName: editHeaderControl
  },
  editPassword: {
    name: EDIT_PASSWORD_CONTROL_COMPONENT,
    component: editPasswordControlComponent
  },
  editRadio: {
    name: EDIT_RADIO_CONTROL_COMPONENT,
    component: editRadioControlComponent
  },
  editRichTextEditor: {
    name: EDIT_RICH_TEXT_EDITOR_COMPONENT,
    component: editRichTextEditorControlComponent
  },
  editSubTitle: {
    name: EDIT_SUBTITLE_CONTROL_COMPONENT,
    component: editSubTitleControlComponent,
    moduleName: editSubTitle.name
  },
  editTextArea: {
    name: EDIT_TEXTAREA_CONTROL_COMPONENT,
    component: editTextareaControlComponent,
    moduleName: editTextareaControlModule.name
  },
  editTextInput: {
    name: EDIT_TEXTINPUT_CONTROL_COMPONENT,
    component: editTextInputControlComponent,
    moduleName: editTextInputControlModule.name
  }
};

export {
  configs,
  controls
};
<|endoftext|>


<commit_before>/*
 * Thumbnail and image renderring
 */

var $ = require('jquery'),
	Backbone = require('backbone'),
	common = require('../../common/index'),
	main = require('../main'),
	options = require('../options');

var Hidamari = exports.Hidamari = {
	events: {
		'click >figure>figcaption>.imageSrc': 'revealThumbnail',
		'click >figure>a': 'imageClicked',
	},

	renderImage: function (model, image) {
		var $fig = this.$el.children('figure');
		// Remove image on mod deletion
		if (!image)
			$fig.remove();
		// Insert figure. Only used for articles
		else if (!$fig.length) {
			$(common.flatten(main.oneeSama.gazou(image, false)).join(''))
				.insertAfter(this.$el.children('header'));
			this.autoExpandImage();
		}
	},

	renderSpoiler: function(spoiler){
		this.model.get('image').spoiler = spoiler;
		this.renderThumbnail();
	},

	changeThumbnailStyle: function(model, type){
		if (!this.model.has('image'))
			return;
		// Shitty hack
		// TODO: remove all, when options model is rewritten
		main.oneeSama.thumbStyle = type;
		this.renderThumbnail(type == 'hide');
	},

	// Rerenders the entire thumbnail, which can pretty expensive in batch,
	// but good enough for now
	renderThumbnail: function(hide, contract){
		var $fig = this.$el.children('figure'),
			$a = $fig.children('a'),
			$img = $a.children('img, video');
		if (hide === undefined)
			hide = options.get('thumbs') == 'hide';
		if (hide){
			$fig.find('.imageSrc').text('[Show]');
			this.model.set({imageExpanded: false, thumbnailRevealed: false});
			return $img.remove();
		}
		// Don't replace expanded images, unless contracting
		if (this.model.get('imageExpanded') && !contract)
			return;
		var img = this.model.get('image');
		$fig.find('.imageSrc').text(img.src);
		$img = $(
			common.flatten(
				main.oneeSama.gazou_img(img, this.$el.is('section')
			).html).join('')
		);
		$a.remove();
		$img.appendTo($fig);
		this.model.set({imageExpanded: false, thumbnailRevealed: !hide});
	},

	toggleSpoiler: function(model, toggle){
		if (!this.model.has('image') || options.get('thumbs') == 'hide')
			return;
		main.oneeSama.spoilToggle = toggle;
		this.renderThumbnail();
	},

	// Toggle animated GIF thumbnails
	toggleAutogif: function(model, toggle){
		const img = this.model.get('image');
		if (!img || img.ext !== '.gif' || options.get('thumbs') == 'hide')
			return;
		main.oneeSama.autoGif = toggle;
		this.renderThumbnail();
	},

	// Reveal hidden thumbnail by clicking [Show]
	revealThumbnail: function(e){
		if (options.get('thumbs') != 'hide')
			return;
		e.preventDefault();
		var revealed = this.model.get('thumbnailRevealed');
		this.renderThumbnail(revealed);
		this.$el.children('figure').find('.imageSrc')
			.text(revealed ? '[Show]' : '[Hide]');
	},

	imageClicked: function(e){
		if (options.get('inlinefit') == 'none' || e.which != 1)
			return;
		e.preventDefault();
		this.toggleImageExpansion();
	},

	autoExpandImage: function(){
		var expand = massExpander.get('expand');
		if (expand)
			this.toggleImageExpansion(null, expand);
	},

	toggleImageExpansion: function(model, expand){
		var img = this.model.get('image');
		const fit = options.get('inlinefit');
		if (!img || fit == 'none')
			return;
		// Don't autoexpand webm/PDF/MP3 with Expand All enabled
		if (expand !== undefined
			&& (img.ext == '.webm'
			|| img.ext == '.pdf'
			|| img.ext == '.mp3'))
				return;
		if  (expand != false)
			expand = expand || this.model.get('imageExpanded') != true;
		if (expand)
			this.fitImage(img, fit);
		else
			this.renderThumbnail(options.get('thumbs') == 'hide', true);
	},

	fitImage: function(img, fit){
		// Open PDF in a new tab on click
		if (img.ext == '.pdf')
			return window.open(mediaURL + 'src/' + img.src, '_blank');
		// Audio controls are always the same height and do not need to be fitted
		if (img.ext == '.mp3')
			return this.renderAudio();
		var width = newWidth = img.dims[0],
			height = newHeight = img.dims[1];
		if (fit == 'full')
			return this.expandImage(width, height, img.ext);
		const both = fit == 'both',
			widthFlag = both || fit == 'width',
			heightFlag = both || fit == 'height',
			aspect = width / height,
			isArticle = this.$el.is('article');
		var fullWidth, fullHeight;
		if (widthFlag){
			var maxWidth = $(window).width() -
				// We have to go wider
				this.$el.closest('section')[0].getBoundingClientRect().left
					* (isArticle ? 1 : 2);
			if (isArticle)
				maxWidth -= this.$el.outerWidth() - this.$el.width() + 5;
			if (newWidth > maxWidth){
				newWidth = maxWidth;
				newHeight = newWidth / aspect;
				fullWidth = true;
			}
		}
		if (heightFlag){
			var maxHeight = $(window).height() - $('#banner').outerHeight();
			if (newHeight > maxHeight){
				newHeight = maxHeight;
				newWidth = newHeight * aspect;
				fullHeight = true;
			}
		}
		if (newWidth > 50 && newHeight > 50){
			width = newWidth;
			height = newHeight;
		}
		this.expandImage(width, height, img.ext, fullWidth && !fullHeight);
	},

	expandImage: function(width, height, ext, fullWidth){
		var $fig = this.$el.children('figure'),
			tag;
		if (ext == '.webm')
			tag = 'video';
		else
			tag = 'img';
		$fig.find('img, video').replaceWith($('<'+ tag +'/>', {
			src: $fig.find('.imageSrc').attr('href'),
			width: width,
			height: height,
			autoplay: true,
			loop: true,
			// Even wider
			'class': 'expanded'+ (fullWidth ? ' fullWidth' : ''),
		}));
		this.model.set('imageExpanded', true);
	},

	renderAudio: function() {
		$a = this.$el.children('figure').children('a');
		$('<audio/>', {
			src: $a.attr('href'),
			width: 300,
			height: '3em',
			autoplay: true,
			loop: true,
			controls: true
		})
			.appendTo($a);
		this.model.set('imageExpanded', true);
	}
};

var massExpander = exports.massExpander = new Backbone.Model({
	expand: false
});

$('#expandImages').click(function(e){
	e.preventDefault();
	const expand = massExpander.get('expand');
	$(e.target).text((expand ? 'Expand' : 'Contract')+' Images');
	massExpander.set('expand', !expand);
});
<commit_msg>Fix variable leaks<commit_after>/*
 * Thumbnail and image renderring
 */

var $ = require('jquery'),
	Backbone = require('backbone'),
	common = require('../../common/index'),
	main = require('../main'),
	options = require('../options');

var Hidamari = exports.Hidamari = {
	events: {
		'click >figure>figcaption>.imageSrc': 'revealThumbnail',
		'click >figure>a': 'imageClicked'
	},

	renderImage: function (model, image) {
		var $fig = this.$el.children('figure');
		// Remove image on mod deletion
		if (!image)
			$fig.remove();
		// Insert figure. Only used for articles
		else if (!$fig.length) {
			$(common.flatten(main.oneeSama.gazou(image, false)).join(''))
				.insertAfter(this.$el.children('header'));
			this.autoExpandImage();
		}
	},

	renderSpoiler: function(spoiler){
		this.model.get('image').spoiler = spoiler;
		this.renderThumbnail();
	},

	changeThumbnailStyle: function(model, type){
		if (!this.model.has('image'))
			return;
		// Shitty hack
		// TODO: remove all, when options model is rewritten
		main.oneeSama.thumbStyle = type;
		this.renderThumbnail(type == 'hide');
	},

	// Rerenders the entire thumbnail, which can pretty expensive in batch,
	// but good enough for now
	renderThumbnail: function(hide, contract){
		var $fig = this.$el.children('figure'),
			$a = $fig.children('a'),
			$img = $a.children('img, video');
		if (hide === undefined)
			hide = options.get('thumbs') == 'hide';
		if (hide){
			$fig.find('.imageSrc').text('[Show]');
			this.model.set({imageExpanded: false, thumbnailRevealed: false});
			return $img.remove();
		}
		// Don't replace expanded images, unless contracting
		if (this.model.get('imageExpanded') && !contract)
			return;
		var img = this.model.get('image');
		$fig.find('.imageSrc').text(img.src);
		$img = $(
			common.flatten(
				main.oneeSama.gazou_img(img, this.$el.is('section')
			).html).join('')
		);
		$a.remove();
		$img.appendTo($fig);
		this.model.set({imageExpanded: false, thumbnailRevealed: !hide});
	},

	toggleSpoiler: function(model, toggle){
		if (!this.model.has('image') || options.get('thumbs') == 'hide')
			return;
		main.oneeSama.spoilToggle = toggle;
		this.renderThumbnail();
	},

	// Toggle animated GIF thumbnails
	toggleAutogif: function(model, toggle){
		const img = this.model.get('image');
		if (!img || img.ext !== '.gif' || options.get('thumbs') == 'hide')
			return;
		main.oneeSama.autoGif = toggle;
		this.renderThumbnail();
	},

	// Reveal hidden thumbnail by clicking [Show]
	revealThumbnail: function(e){
		if (options.get('thumbs') != 'hide')
			return;
		e.preventDefault();
		var revealed = this.model.get('thumbnailRevealed');
		this.renderThumbnail(revealed);
		this.$el.children('figure').find('.imageSrc')
			.text(revealed ? '[Show]' : '[Hide]');
	},

	imageClicked: function(e){
		if (options.get('inlinefit') == 'none' || e.which != 1)
			return;
		e.preventDefault();
		this.toggleImageExpansion();
	},

	autoExpandImage: function(){
		var expand = massExpander.get('expand');
		if (expand)
			this.toggleImageExpansion(null, expand);
	},

	toggleImageExpansion: function(model, expand){
		var img = this.model.get('image');
		const fit = options.get('inlinefit');
		if (!img || fit == 'none')
			return;
		// Don't autoexpand webm/PDF/MP3 with Expand All enabled
		if (expand !== undefined
			&& (img.ext == '.webm'
			|| img.ext == '.pdf'
			|| img.ext == '.mp3'))
				return;
		if  (expand != false)
			expand = expand || this.model.get('imageExpanded') != true;
		if (expand)
			this.fitImage(img, fit);
		else
			this.renderThumbnail(options.get('thumbs') == 'hide', true);
	},

	fitImage: function(img, fit){
		// Open PDF in a new tab on click
		if (img.ext == '.pdf')
			return window.open(mediaURL + 'src/' + img.src, '_blank');
		// Audio controls are always the same height and do not need to be fitted
		if (img.ext == '.mp3')
			return this.renderAudio();
		var newWidth, newHeight,
			width = newWidth = img.dims[0],
			height = newHeight = img.dims[1];
		if (fit == 'full')
			return this.expandImage(width, height, img.ext);
		const both = fit == 'both',
			widthFlag = both || fit == 'width',
			heightFlag = both || fit == 'height',
			aspect = width / height,
			isArticle = this.$el.is('article');
		var fullWidth, fullHeight;
		if (widthFlag){
			var maxWidth = $(window).width() -
				// We have to go wider
				this.$el.closest('section')[0].getBoundingClientRect().left
					* (isArticle ? 1 : 2);
			if (isArticle)
				maxWidth -= this.$el.outerWidth() - this.$el.width() + 5;
			if (newWidth > maxWidth){
				newWidth = maxWidth;
				newHeight = newWidth / aspect;
				fullWidth = true;
			}
		}
		if (heightFlag){
			var maxHeight = $(window).height() - $('#banner').outerHeight();
			if (newHeight > maxHeight){
				newHeight = maxHeight;
				newWidth = newHeight * aspect;
				fullHeight = true;
			}
		}
		if (newWidth > 50 && newHeight > 50){
			width = newWidth;
			height = newHeight;
		}
		this.expandImage(width, height, img.ext, fullWidth && !fullHeight);
	},

	expandImage: function(width, height, ext, fullWidth){
		var $fig = this.$el.children('figure'),
			tag;
		if (ext == '.webm')
			tag = 'video';
		else
			tag = 'img';
		$fig.find('img, video').replaceWith($('<'+ tag +'/>', {
			src: $fig.find('.imageSrc').attr('href'),
			width: width,
			height: height,
			autoplay: true,
			loop: true,
			// Even wider
			'class': 'expanded'+ (fullWidth ? ' fullWidth' : '')
		}));
		this.model.set('imageExpanded', true);
	},

	renderAudio: function() {
		var $a = this.$el.children('figure').children('a');
		$('<audio/>', {
			src: $a.attr('href'),
			width: 300,
			height: '3em',
			autoplay: true,
			loop: true,
			controls: true
		})
			.appendTo($a);
		this.model.set('imageExpanded', true);
	}
};

var massExpander = exports.massExpander = new Backbone.Model({
	expand: false
});

$('#expandImages').click(function(e){
	e.preventDefault();
	const expand = massExpander.get('expand');
	$(e.target).text((expand ? 'Expand' : 'Contract')+' Images');
	massExpander.set('expand', !expand);
});
<|endoftext|>


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

(function(scope, testing) {

  var styleMethods = {
    getPropertyCSSValue: 1,
    getPropertyPriority: 1,
    getPropertyValue: 1,
    item: 1,
    removeProperty: 1,
    setProperty: 1,
  };

  // This patching method should be used for browsers that are unable to replace the browser's element.style property (Safari and iOS).
  // This patch has the disadvantage that reading style.cssProperty getters will return the animated value.
  // The correct way to interact with this patched style is to only use the style methods listed in styleMethods,
  // animated values will not leak into the return values of these methods.
  function patchInlineStyleForAnimation(element) {
    var style = element.style;
    var surrogateStyle = document.createElement('div').style;
    // Copy the inline style contents over to the surrogate.
    for (var i = 0; i < style.length; i++) {
      var property = style[i];
      surrogateStyle[property] = style[property];
    }
    var isAnimatedProperty = {};
    for (var method in styleMethods) {
      if (!(method in style))
        return;
      Object.defineProperty(style, method, {
        enumerable: true,
        configurable: true,
        value: (function(method, originalMethodFunction) {
          return function(property) {
            var result = surrogateStyle[method].apply(surrogateStyle, arguments);
            if (!isAnimatedProperty[property])
              originalMethodFunction.apply(style, arguments);
            return result;
          }
        })(method, style[method]),
      });
    }

    style._set = function(property, value) {
      style[property] = value;
      isAnimatedProperty[property] = true;
    };

    style._clear = function(property) {
      style[property] = surrogateStyle[property];
      delete isAnimatedProperty[property];
    };
  }

  function ensureStyleIsPatched(element) {
    if (element._webAnimationsPatchedStyle)
      return;
    patchInlineStyleForAnimation(element.style);
    // We must keep a handle on the patched style to prevent it from getting GC'd.
    element._webAnimationsPatchedStyle = element.style;
  }

  scope.apply = function(element, property, value) {
    ensureStyleIsPatched(element);
    element.style._set(property, value);
  };

  scope.clear = function(element, property) {
    if (element._webAnimationsPatchedStyle) {
      element.style._clear(property);
    }
  };

  testing.ensureStyleIsPatched = ensureStyleIsPatched;

})(webAnimations, testing);
<commit_msg>Fix parameter passing bug<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//     You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//     See the License for the specific language governing permissions and
// limitations under the License.

(function(scope, testing) {

  var styleMethods = {
    getPropertyCSSValue: 1,
    getPropertyPriority: 1,
    getPropertyValue: 1,
    item: 1,
    removeProperty: 1,
    setProperty: 1,
  };

  // This patching method should be used for browsers that are unable to replace the browser's element.style property (Safari and iOS).
  // This patch has the disadvantage that reading style.cssProperty getters will return the animated value.
  // The correct way to interact with this patched style is to only use the style methods listed in styleMethods,
  // animated values will not leak into the return values of these methods.
  function patchInlineStyleForAnimation(style) {
    var surrogateStyle = document.createElement('div').style;
    // Copy the inline style contents over to the surrogate.
    for (var i = 0; i < style.length; i++) {
      var property = style[i];
      surrogateStyle[property] = style[property];
    }
    var isAnimatedProperty = {};
    for (var method in styleMethods) {
      if (!(method in style))
        return;
      Object.defineProperty(style, method, {
        enumerable: true,
        configurable: true,
        value: (function(method, originalMethodFunction) {
          return function(property) {
            var result = surrogateStyle[method].apply(surrogateStyle, arguments);
            if (!isAnimatedProperty[property])
              originalMethodFunction.apply(style, arguments);
            return result;
          }
        })(method, style[method]),
      });
    }

    style._set = function(property, value) {
      style[property] = value;
      isAnimatedProperty[property] = true;
    };

    style._clear = function(property) {
      style[property] = surrogateStyle[property];
      delete isAnimatedProperty[property];
    };
  }

  function ensureStyleIsPatched(element) {
    if (element._webAnimationsPatchedStyle)
      return;
    patchInlineStyleForAnimation(element.style);
    // We must keep a handle on the patched style to prevent it from getting GC'd.
    element._webAnimationsPatchedStyle = element.style;
  }

  scope.apply = function(element, property, value) {
    ensureStyleIsPatched(element);
    element.style._set(property, value);
  };

  scope.clear = function(element, property) {
    if (element._webAnimationsPatchedStyle) {
      element.style._clear(property);
    }
  };

  testing.ensureStyleIsPatched = ensureStyleIsPatched;

})(webAnimations, testing);
<|endoftext|>


<commit_before>import {axios, log, isRoot} from 'store/utils'

export default {
  async init ({ rootState, commit, dispatch }) {
    if (!rootState.isConnected) {
      setTimeout(() => { dispatch('init') }, 10 * 1000)
      return
    }

    console.log('[INIT] Seasons')

    const now = new Date()
    const year = now.getFullYear()
    const month = now.getMonth() + 1
    let season

    if (month > 0 && month < 4) season = 'winter'
    else if (month > 3 && month < 7) season = 'spring'
    else if (month > 6 && month < 10) season = 'summer'
    else if (month > 9 && month < 13) season = 'fall'

    commit('setYear', year)
    commit('setSeason', season)

    dispatch('refresh')
  },
  async refresh ({state, commit, dispatch}) {
    log(`Refreshing Seasons...`)
    commit('refreshing', true)

    const { year, season } = state

    if (year >= 1917 && (year <= (new Date()).getYear() + 1901)) {
      const { data, status } = await axios.get('seasons.json', {
        params: { year, season }
      })

      if (status !== 200) {
        log('Could not refresh seasonal information.')
        setTimeout(() => { dispatch('refresh') }, 60 * 1000)
        commit('refreshing', false)
        return
      }

      commit('set', data)
      commit('refreshing', false)
      log('Seasons refreshed.')
    } else {
      commit('setInfoSnackbar', `Year must be between 1917 and ${(new Date()).getYear() + 1901}`, isRoot)
    }
  }
}
<commit_msg>Connectivity check should be done before each refresh not only at init<commit_after>import {axios, log, isRoot} from 'store/utils'

export default {
  async init ({ rootState, commit, dispatch }) {
    console.log('[INIT] Seasons')

    const now = new Date()
    const year = now.getFullYear()
    const month = now.getMonth() + 1
    let season

    if (month > 0 && month < 4) season = 'winter'
    else if (month > 3 && month < 7) season = 'spring'
    else if (month > 6 && month < 10) season = 'summer'
    else if (month > 9 && month < 13) season = 'fall'

    commit('setYear', year)
    commit('setSeason', season)

    dispatch('refresh')
  },
  async refresh ({ rootState, state, commit, dispatch }) {
    if (!rootState.isConnected) {
      log('Cancelling season update, user is offline.')
      setTimeout(() => { dispatch('refresh') }, 20 * 1000)
      return
    }

    commit('refreshing', true)

    const { year, season } = state

    if (year >= 1917 && (year <= (new Date()).getYear() + 1901)) {
      const { data, status } = await axios.get('seasons.json', {
        params: { year, season }
      })

      if (status !== 200) {
        log('Could not refresh seasonal information.')
        setTimeout(() => { dispatch('refresh') }, 60 * 1000)
        commit('refreshing', false)
        return
      }

      commit('set', data)
      commit('refreshing', false)
      log('Seasons refreshed.')
    } else {
      commit('setInfoSnackbar', `Year must be between 1917 and ${(new Date()).getYear() + 1901}`, isRoot)
    }
  }
}
<|endoftext|>


<commit_before>// TODO: transfer Save, Print, Close functions from older forms. *needs server access
app.service('$eea', ['$http', '$compile', function($http, $compile) {
    	return {
		test: function($scope) {
			return 'test' + $scope;
		},
		init: function($scope) {
			$scope.field = {};
			$scope.multipleIndex = 1;
			$scope.ValidationDisabled = false;
			$scope.selectedLanguage = "en";
			$scope.groups = groups;
		},
		group: {
			addRow: function(frm, group, $scope) {
				$scope.multipleIndex = $scope.groups[frm][group].length;
				var id = ++$scope.multipleIndex;
				$scope.groups[frm][group].push(id);
				setTimeout(function() {
					$scope.$apply();
					$('#group-area-' + $scope.multipleIndex + '-' + group).prepend($compile('
<button type="button"  title="{{\'deleterow\' | translate}}"class="deleterowbutton" ng-click="deleteRow(\'' + frm + '\', \'' + group + '\', ' + id + ')"></button>
')($scope));
				}, 10);
			},
			deleteRow: function(frm, group, id, $scope) {
				$scope.groups[frm][group][$scope.groups[frm][group].indexOf(id)] = -1;
				$("#group-area-" + id + "-" + group).html("");
			}
		},
		form: {
			save : function ($scope) {
				$("form.eeaform").each(function(index, form){
						console.log("Testing form - Valid:", $scope[form.name].$valid);
						//TODO: Maybe a DB status flag (same Table or Lookup for activity logging? or Status in main table and Activity Table for action/date/user logging)
						//(i.e. 0 created/saved, 1 edited (+dateedited? extra field), 2 commited - leave it "open" for future statuses). In order to be Commited it needs to be valid. It can be saved without all elements completed but not commited.
						if (!$scope[form.name].$valid) {
							$("#" + form.name + " .ng-invalid").first().focus();
						}
				});
			},
			submit : function (frm, test, $scope) {

				// for (var form in $scope.field) {
					// if (frm) {
						// if (frm.$name !== form) continue;
					// }

				if (test) return false;

				var frmObj = $scope.field[form];
				var postContent = '';
				for (var element in frmObj) {
					postContent += "&" + encodeURIComponent(element) + "=" + encodeURIComponent(frmObj[element]);
				}

				$http({
					method: 'POST',
					url: $("#" + form).attr("eea-action"),
					headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
					data: postContent
				}).then(
					function(response) {
						console.log("response", response.status);
					},
					function(error) {
						console.log("error", error.status);
					});

				// }

				return false;
			}
		}
	}
}]);<commit_msg>Adding Save Toolbar Component functionality<commit_after>// TODO: transfer Save, Print, Close functions from older forms. *needs server access
app.service('$eea', ['$http', '$compile', function($http, $compile) {
    	return {
		test: function($scope) {
			return 'test' + $scope;
		},
		init: function($scope) {
			$scope.field = {};
			$scope.multipleIndex = 1;
			$scope.ValidationDisabled = false;
			$scope.selectedLanguage = "en";
			$scope.groups = groups;
		},
		group: {
			addRow: function(frm, group, $scope) {
				$scope.multipleIndex = $scope.groups[frm][group].length;
				var id = ++$scope.multipleIndex;
				$scope.groups[frm][group].push(id);
				setTimeout(function() {
					$scope.$apply();
					$('#group-area-' + $scope.multipleIndex + '-' + group).prepend($compile('
<button type="button"  title="{{\'deleterow\' | translate}}"class="deleterowbutton" ng-click="deleteRow(\'' + frm + '\', \'' + group + '\', ' + id + ')"></button>
')($scope));
				}, 10);
			},
			deleteRow: function(frm, group, id, $scope) {
				$scope.groups[frm][group][$scope.groups[frm][group].indexOf(id)] = -1;
				$("#group-area-" + id + "-" + group).html("");
			}
		},
		form: {
			save : function ($scope) {
				$("form.eeaform").each(function(index, form){
						console.log("Testing form - Valid:", $scope[form.name].$valid);
						//TODO: Maybe a DB status flag (same Table or Lookup for activity logging? or Status in main table and Activity Table for action/date/user logging)
						//(i.e. 0 created/saved, 1 edited (+dateedited? extra field), 2 commited - leave it "open" for future statuses). In order to be Commited it needs to be valid. It can be saved without all elements completed but not commited.
						// Maybe an extra Commit button appearing in case server respond to last edit/save that data are accepted and checked.
						if (!$scope[form.name].$valid) {
							$("#" + form.name + " .ng-invalid").first().focus();
						}
				});
			},
			submit : function (frm, test, $scope) {

				// for (var form in $scope.field) {
					// if (frm) {
						// if (frm.$name !== form) continue;
					// }

				if (test) return false;

				var frmObj = $scope.field[form];
				var postContent = '';
				for (var element in frmObj) {
					postContent += "&" + encodeURIComponent(element) + "=" + encodeURIComponent(frmObj[element]);
				}

				$http({
					method: 'POST',
					url: $("#" + form).attr("eea-action"),
					headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
					data: postContent
				}).then(
					function(response) {
						console.log("response", response.status);
					},
					function(error) {
						console.log("error", error.status);
					});

				// }

				return false;
			}
		}
	}
}]);<|endoftext|>