<commit_before>import React from 'react';

import Rx from 'rx';
import fromHistory from '../lib/Rx.History.js';
Rx.Observable.fromHistory = fromHistory;

// External Dependencies
import marked from 'marked';

marked.setOptions({
  gfm: true
});

// Actions
import { Page } from '../actions/Page';
import { Command } from '../actions/Command';

export default React.createClass({
  handlers: {},

  componentWillMount: function () {
    // Listen reactively to history changes
    this.handlers.history = Rx.Observable.fromHistory(this.props.history)
      .pluck("pathname")
      .map( path => path[0] === "/" ? path.slice(1) : path )
      .filter( path => path.length > 0 )
      .distinctUntilChanged()
      .debounce(150)
      .subscribe( this.search );
  },

  getInitialState: function () {
    return {body: ""};
  },

  render: function () {
    let markup = marked(this.state.body);
    return (

    );
  },

  error: function (err) {
    this.display( " # " + err);
  },

  search: function (cmd) {
    Command
      .search(cmd)
      .subscribe(this.fetch, this.error);
  },

  fetch: function (cmd) {
    Page
      .get(cmd)
      .subscribe(this.display, this.error);
  },

  display: function (page) {
    this.setState({ body: page });
  }

});
<commit_msg>Handler for welcome page<commit_after>import React from 'react';

import Rx from 'rx';
import fromHistory from '../lib/Rx.History.js';
Rx.Observable.fromHistory = fromHistory;

// External Dependencies
import marked from 'marked';

marked.setOptions({
  gfm: true
});

// Actions
import { Page } from '../actions/Page';
import { Command } from '../actions/Command';

export default React.createClass({
  handlers: {},

  componentWillMount: function () {
    // Listen reactively to history changes
    this.handlers.history = Rx.Observable.fromHistory(this.props.history)
      .pluck("pathname")
      .map( path => path[0] === "/" ? path.slice(1) : path )
      .filter( path => path.length > 0 )
      .distinctUntilChanged()
      .debounce(200)
      .subscribe( this.search );

    this.handlers.history = Rx.Observable.fromHistory(this.props.history)
      .pluck("pathname")
      .map( path => path[0] === "/" ? path.slice(1) : path )
      .filter( path => path.length === 0 )
      .distinctUntilChanged()
      .debounce(200)
      .subscribe( this.emptyPage );
  },

  getInitialState: function () {
    return {body: ""};
  },

  render: function () {
    let markup = marked(this.state.body);
    return (

    );
  },

  emptyPage: function () {
    this.display( " # Welcome " );
  },

  error: function (err) {
    this.display( " # " + err);
  },

  search: function (cmd) {
    Command
      .search(cmd)
      .subscribe(this.fetch, this.error);
  },

  fetch: function (cmd) {
    Page
      .get(cmd)
      .subscribe(this.display, this.error);
  },

  display: function (page) {
    this.setState({ body: page });
  }

});
<|endoftext|>


<commit_before>import React, { Component } from "react"
import { translate }        from "react-i18next";
import { FontAwesomeIcon }  from '@fortawesome/react-fontawesome'
import PropTypes            from "prop-types"
import styled               from "styled-components";
import { initialize }       from "redux-form";

import V                    from "../constants/PanelView"
import ResultList           from "./pure/ResultList"
import SubscribeToBbox      from "./pure/SubscribeToBbox"
import Ratings              from "./pure/Ratings"
import EntryDetails         from "./pure/EntryDetails"
import EntryForm            from "./EntryForm"
import RatingForm           from "./pure/RatingForm"
import CommentForm          from "./pure/CommentForm"
import Message              from "./pure/Message"
import SidebarFooter        from "./pure/SidebarFooter"
import CityList             from "./pure/CityList"
import { EDIT, RATING }     from "../constants/Form"
import Actions              from "../Actions"
import STYLE                from "./styling/Variables"
import { IDS }              from "../constants/Categories"
import NavButton            from "./pure/NavButton";
import SearchBar            from "./SearchBar"
import ScrollableDiv        from "./pure/ScrollableDiv";

const converDateToTimestamp = (date) => {
    var dateObj = new window.Date(date);
    var result = dateObj.getTime();
    if (result > 99999999999) {
        result = Math.trunc(result / 1000) - (dateObj.getTimezoneOffset() * 60)
    }
    return result;
}

class Sidebar extends Component {

  entryContent = null;

  shouldComponentUpdate(nextProps) {
    if( !nextProps.view.showLeftPanel ) return false
    if( !this.props.view.showLeftPanel && nextProps.view.showLeftPanel ) return true
    if( nextProps.view.left !== this.props.view.left ) return true
    if( nextProps.view.left === this.props.view.left === V.ENTRY && nextProps.search.highlight === this.props.search.highlight ) return false
    // if( nextProps.view.left === V.RESULT
    // && Object.keys(nextProps.search.entryResults).join() ===
    // Object.keys(this.props.search.entryResults).join()
    // && Object.keys(nextProps.search.invisible).join() ===
    // Object.keys(this.props.search.invisible).join()
    // && Object.keys(nextProps.search.eventResults).join() ===
    // Object.keys(this.props.search.eventResults).join()
    // && Object.keys(nextProps.search.eventsWithoutPlace).join() ===
    // Object.keys(this.props.search.eventsWithoutPlace).join()
    // ) return false
    return true
  }

  render(){
    const { view, search, user, server, resultEntries, entries,
      ratings, dispatch, map, form, t, showAddEntryButton,
      showSearchBar, onTagClick, tagsClickable } = this.props;
    const { waiting_for_search_results } = view;
    const { explainRatingContext, selectedContext } = view;
    const invisibleEntries = search.invisible
      .filter(e => entries[e.id])
      .map(e => entries[e.id])
      .concat(search.eventsWithoutPlace);

    const entry = entries[search.current] || null;
    const isEventForEdit = entry && entry.categories && entry.categories.length > 0 && entry.categories[0] === IDS.EVENT;

    const fixedTagsStr = search.fixedTags.map(tag => `#${tag}`).join(' ')

    var content;
    switch (view.left) {
      case V.RESULT:
        content = (
          <ResultWrapper className="result">
            <ResultList
              waiting={ waiting_for_search_results }
              entries={ resultEntries }
              ratings={ ratings }
              highlight={ search.highlight}
              moreEntriesAvailable={ search.moreEntriesAvailable }
              onMoreEntriesClick={ () => { return dispatch(Actions.showAllEntries()); }}
              dispatch={dispatch}
            />
            {
              (search.cities.length > 0) ?

                  <GroupHeader>
                    { t("search-results.cities") }
                  </GroupHeader>
                  <CityList
                    cities={ search.cities.slice(0, 5) }
                    onClick={ city => {
                      dispatch(Actions.setCenter({
                        lat: city.lat,
                        lng: city.lon
                      }));
                      return dispatch(Actions.setSearchText(''));
                    }}
                    selectedColor="rgba(0,0,0,0)"
                  />

                : ""
            }
            {
              (invisibleEntries && invisibleEntries.length) ?

                  <GroupHeader>
                    { t("search-results.results-out-of-bbox") }
                  </GroupHeader>
                  <ResultList
                    entries={ invisibleEntries }
                    ratings={ ratings }
                    highlight={ search.highlight }
                    onClick={ (id,center) => { return dispatch(Actions.setCurrentEntry(id, center)); }}
                    onMouseEnter={ id => { return dispatch(Actions.highlight(id)); }}
                    onMouseLeave={ id => { return dispatch(Actions.highlight()); }}
                    dispatch={ dispatch }
                    waiting={ waiting_for_search_results }
                    moreEntriesAvailable={ search.moreEntriesAvailable }
                    onMoreEntriesClick={ () => { return dispatch(Actions.showAllEntries()); }}
                  />

                : ""
            }
          </ResultWrapper>
        );
        break;

      case V.ENTRY:
        if (!entry) {
          content = (<Message iconClass={ "spinner" } message={ t("loading-message") } />)
        } else {

          const onBack = () => {
            dispatch(Actions.setCurrentEntry(null, null));
            dispatch(Actions.showSearchResults());
            dispatch(Actions.setCenterInUrl(map.center));
            // dispatch(Actions.restoreSearch());
          };

          const onEdit = () => {
            dispatch(Actions.editCurrentEntry());
          };

          const isEvent = entry.categories && entry.categories.length > 0 && entry.categories[0] === IDS.EVENT;
          content = (
            <ScrollableEntryDetailsWrapper id="ScrollableEntryDetailsWrapper">
              <EntryDetails
                entry={ entry }
                isEvent={ isEvent }
                onTag={ onTagClick }
                tagsClickable={ tagsClickable }
                onEdit={ onEdit }
                onBack={ onBack }
              />
              { !isEvent ?
                <Ratings
                  id="Ratings"
                  entry={ entry }
                  ratings={ (entry ? entry.ratings || [] : []).map(id => {
                    return ratings[id];
                  })}
                  onRate={ id => { return dispatch(Actions.showNewRating(id)); }}
                  onComment={ context => { return dispatch(Actions.showNewComment(context)); }}
                />
              : ''}
              <SidebarFooter
                isEvent={isEvent}
                changed = {entry.created}
                version = {entry.version}
                title = {entry.title}
              />
            </ScrollableEntryDetailsWrapper>
          );
        }
        break;

      case V.EDIT:
      case V.NEW:
        content = (
          <EntryForm
            isEdit={ form[EDIT.id] ? form[EDIT.id].kvm_flag_id : null }
            isEvent={ isEventForEdit }
            formSyncErrors={ form[EDIT.id].syncErrors }
            formSubmitFailed = { form[EDIT.id].submitFailed }
            formStartEndDate={ { startDate: entry ? (entry.start * 1000) : null, endDate: entry ? (entry.end * 1000) : null } }
            license={ entries[search.current] ? entries[search.current].license : null }
            dispatch={ dispatch }
            onSubmit={ data => {
              var dataToSend = {
                title: data.title,
                description: data.description,
                tags: data.tags ? data.tags.split(',') : null,
                organizer: data.organizer,
                homepage: data.homepage,
                telephone: data.telephone,
                opening_hours: data.opening_hours,
                lat: Number(data.lat),
                lng: Number(data.lng),
                street: data.street,
                city: data.city,
                country: data.country,
                state: data.state,
                email: data.email,
                zip: data.zip,
                version: ((form[EDIT.id] ? form[EDIT.id].values ? form[EDIT.id].values.version : null : null) || 0) + 1,
                categories: [data.category],
                image_url: data.image_url,
                image_link_url: data.image_link_url,
                end: data.end && converDateToTimestamp(data.end),
                start: data.start && converDateToTimestamp(data.start)
              };
              if (form[EDIT.id]) {
                dataToSend.id = form[EDIT.id].kvm_flag_id;
              }
              return dispatch(Actions.saveEntry(dataToSend));
            }}
          />
        );
        break;

      case V.NEW_RATING:
        var kvm_flag_id = form[RATING.id] ? form[RATING.id].kvm_flag_id : null;
        var ref;
        content = (
          <RatingForm
            ref={ 'rating' }
            entryid={ kvm_flag_id }
            entryTitle={
              form[RATING.id]
                ? entries[form[RATING.id].kvm_flag_id]
                  ? entries[form[RATING.id].kvm_flag_id].title
                  : null
                : null
            }
            onSubmit={ data => {
              return dispatch(Actions.createRating({
                entry: form[RATING.id] ? form[RATING.id].kvm_flag_id : null,
                title: data.title,
                context: data.context,
                value: data.value,
                comment: data.comment,
                source: data.source
              }));
            }}
            onCancel={ () => {
              dispatch(initialize(RATING.id, {}, RATING.fields));
              dispatch(Actions.cancelRating());
            }}
            contextToExplain={ explainRatingContext }
            selectedContext={ selectedContext }
            changeContext={ ratingContext => { return dispatch(Actions.explainRatingContext(ratingContext)); }}
          />
        );
        break;

      case V.NEW_COMMENT:
        var kvm_flag_id = form[RATING.id] ? form[RATING.id].kvm_flag_id : null;
        var ref;
        let payload = form.comment.kvm_flag_id;
        content = (
          <CommentForm
            entryId={ payload.entryId }
            entryTitle={ payload.entryTitle }
            onSubmit={ data => {
              return dispatch(Actions.createRating({
                entry: payload.entryId,
                title: data.title,
                context: payload.ratingContext,
                value: data.value,
                comment: data.comment,
                source: data.source
              }));
            }}
            onCancel={ () => {
              dispatch(initialize(RATING.id, {}, RATING.fields));
              dispatch(Actions.cancelRating());
            }}
            ratingContext={ payload.ratingContext }
            ratingList={ payload.ratingList }
          />
        );
        break;

      case V.WAIT:
        content = (
          <Message
            iconClass={ "spinner" }
            message={ t("loading-message") }
            onCancel={ () => { return dispatch(Actions.cancelWait()); }}
          />
        );
        break;

      case V.IO_ERROR:
        content = (
          <Message
            iconClass={ "exclamation-triangle" }
            message={ t("io-error.message") }
          />
        );
        break;

      case V.SUBSCRIBE_TO_BBOX:
        content = (
          <SubscribeToBbox
            subscriptionExists={ user.subscriptionExists }
            dispatch={ dispatch }
            bbox={ map.bbox }
            username={ user.username }
            mapCenter={ map.center }
          />
        );
        break;

      default:
        content =

    }

    return(
      <SidebarComponent>
        {
          showSearchBar
          ?

            <SearchBar
                searchText={search.text.startsWith(fixedTagsStr) ? search.text.substr(fixedTagsStr.length).trimStart() : search.text}
                fixedTagsStr={fixedTagsStr}
                categories={search.categories}
                type="integrated"
                disabled={view.left === V.EDIT || view.left === V.NEW}
                toggleCat={ c => {
                  if(search.categories.includes(c)){
                    dispatch(Actions.disableSearchCategory(c));
                  } else {
                    dispatch(Actions.enableSearchCategory(c));
                  }
                  return dispatch(Actions.search());
                }}
              onChange={txt => {
                  txt = txt ? `${fixedTagsStr}${txt}`: fixedTagsStr

                  dispatch(Actions.setSearchText(txt));
                  return dispatch(Actions.search());
                }}
                onEscape={ () => {
                  return dispatch(Actions.setSearchText(''));
                }}
                onEnter={ () => {}}      // currently not used, TODO
                loading={ server.loadingSearch }
              />

          : ""
        }
        {
          content
        }
        {
          (view.left === V.RESULT) && showAddEntryButton
          ? <AddEntryButton>
              <NavButton
                key = "back"
                classname = "pure-u-1"
                icon = "plus"
                text = {t("resultlist.addEntry")}
                onClick = {() => {
                  dispatch(Actions.showNewEntry());
                }}
              />
            </AddEntryButton>
          : ""
        }
      </SidebarComponent>
    );
  }
}

const ScrollableEntryDetailsWrapper = styled(ScrollableDiv)`
  height: 100%;
  display: flex;
  flex-direction: column;
`

const SidebarComponent = styled.div`
  display: flex;
  flex-direction: column;
  height: 100%;
`

Sidebar.propTypes = {
  view:           PropTypes.object.isRequired,
  search:         PropTypes.object.isRequired,
  map:            PropTypes.object.isRequired,
  user:           PropTypes.object,
  form:           PropTypes.object,
  resultEntries:  PropTypes.array,
  entries:        PropTypes.object.isRequired,
  ratings:        PropTypes.object,
  dispatch:       PropTypes.func,
  t:              PropTypes.func.isRequired
}

export default Sidebar

const GroupHeader = styled.div `
  border-top: 3px solid ${STYLE.lightGray};
  padding: 0.5em 1em 0.5em 1em;
  margin: 0;
  background: #eaeaea;
  color: #666;
`

const AddEntryButton = styled.nav`
  z-index: 10;
  padding: 0;
  margin: 0;
  background: ${STYLE.coal};
  text-align: center;
  bottom: 0;
  li {
    cursor: pointer;
    box-sizing: border-box;
    font-weight: normal;
    padding: 0.3em;
    font-size: 1.2em;
    border: none;
    color: ${STYLE.lightGray};
    background: transparent;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    &:hover {
      color: #fff;
      border-bottom: 4px solid #fff;
    }
    i {
      margin-right: 0.5em;
    }
  }
`;

const ResultWrapper = styled(ScrollableDiv)`
  background: #f7f7f7;
   /* city list only for sidebar, not landing page TODO: where to put this? */
  .city-list ul {
    background: #f7f7f7;
    li {
      padding: 0.2em;
      padding-left: 0.7em;
      padding-right: 0.7em;
      line-height: 0.9;
      border-left: 5px solid transparent;
      &:hover {
        background: #fff;
        border-left: 5px solid ${STYLE.darkGray};
        div.chevron {
          color: ${STYLE.darkGray};
        }
      }
      span {
        &.state {
          color: #555;
        }
        &.country {
          color: #888;
        }
        &.prefix {
          color: #888;
        }
      }
    }
  }
`<commit_msg>fix: add space between fixedTags and the actual search term<commit_after>import React, { Component } from "react"
import { translate }        from "react-i18next";
import { FontAwesomeIcon }  from '@fortawesome/react-fontawesome'
import PropTypes            from "prop-types"
import styled               from "styled-components";
import { initialize }       from "redux-form";

import V                    from "../constants/PanelView"
import ResultList           from "./pure/ResultList"
import SubscribeToBbox      from "./pure/SubscribeToBbox"
import Ratings              from "./pure/Ratings"
import EntryDetails         from "./pure/EntryDetails"
import EntryForm            from "./EntryForm"
import RatingForm           from "./pure/RatingForm"
import CommentForm          from "./pure/CommentForm"
import Message              from "./pure/Message"
import SidebarFooter        from "./pure/SidebarFooter"
import CityList             from "./pure/CityList"
import { EDIT, RATING }     from "../constants/Form"
import Actions              from "../Actions"
import STYLE                from "./styling/Variables"
import { IDS }              from "../constants/Categories"
import NavButton            from "./pure/NavButton";
import SearchBar            from "./SearchBar"
import ScrollableDiv        from "./pure/ScrollableDiv";

const converDateToTimestamp = (date) => {
    var dateObj = new window.Date(date);
    var result = dateObj.getTime();
    if (result > 99999999999) {
        result = Math.trunc(result / 1000) - (dateObj.getTimezoneOffset() * 60)
    }
    return result;
}

class Sidebar extends Component {

  entryContent = null;

  shouldComponentUpdate(nextProps) {
    if( !nextProps.view.showLeftPanel ) return false
    if( !this.props.view.showLeftPanel && nextProps.view.showLeftPanel ) return true
    if( nextProps.view.left !== this.props.view.left ) return true
    if( nextProps.view.left === this.props.view.left === V.ENTRY && nextProps.search.highlight === this.props.search.highlight ) return false
    // if( nextProps.view.left === V.RESULT
    // && Object.keys(nextProps.search.entryResults).join() ===
    // Object.keys(this.props.search.entryResults).join()
    // && Object.keys(nextProps.search.invisible).join() ===
    // Object.keys(this.props.search.invisible).join()
    // && Object.keys(nextProps.search.eventResults).join() ===
    // Object.keys(this.props.search.eventResults).join()
    // && Object.keys(nextProps.search.eventsWithoutPlace).join() ===
    // Object.keys(this.props.search.eventsWithoutPlace).join()
    // ) return false
    return true
  }

  render(){
    const { view, search, user, server, resultEntries, entries,
      ratings, dispatch, map, form, t, showAddEntryButton,
      showSearchBar, onTagClick, tagsClickable } = this.props;
    const { waiting_for_search_results } = view;
    const { explainRatingContext, selectedContext } = view;
    const invisibleEntries = search.invisible
      .filter(e => entries[e.id])
      .map(e => entries[e.id])
      .concat(search.eventsWithoutPlace);

    const entry = entries[search.current] || null;
    const isEventForEdit = entry && entry.categories && entry.categories.length > 0 && entry.categories[0] === IDS.EVENT;

    const fixedTagsStr = search.fixedTags.map(tag => `#${tag}`).join(' ')

    var content;
    switch (view.left) {
      case V.RESULT:
        content = (
          <ResultWrapper className="result">
            <ResultList
              waiting={ waiting_for_search_results }
              entries={ resultEntries }
              ratings={ ratings }
              highlight={ search.highlight}
              moreEntriesAvailable={ search.moreEntriesAvailable }
              onMoreEntriesClick={ () => { return dispatch(Actions.showAllEntries()); }}
              dispatch={dispatch}
            />
            {
              (search.cities.length > 0) ?

                  <GroupHeader>
                    { t("search-results.cities") }
                  </GroupHeader>
                  <CityList
                    cities={ search.cities.slice(0, 5) }
                    onClick={ city => {
                      dispatch(Actions.setCenter({
                        lat: city.lat,
                        lng: city.lon
                      }));
                      return dispatch(Actions.setSearchText(''));
                    }}
                    selectedColor="rgba(0,0,0,0)"
                  />

                : ""
            }
            {
              (invisibleEntries && invisibleEntries.length) ?

                  <GroupHeader>
                    { t("search-results.results-out-of-bbox") }
                  </GroupHeader>
                  <ResultList
                    entries={ invisibleEntries }
                    ratings={ ratings }
                    highlight={ search.highlight }
                    onClick={ (id,center) => { return dispatch(Actions.setCurrentEntry(id, center)); }}
                    onMouseEnter={ id => { return dispatch(Actions.highlight(id)); }}
                    onMouseLeave={ id => { return dispatch(Actions.highlight()); }}
                    dispatch={ dispatch }
                    waiting={ waiting_for_search_results }
                    moreEntriesAvailable={ search.moreEntriesAvailable }
                    onMoreEntriesClick={ () => { return dispatch(Actions.showAllEntries()); }}
                  />

                : ""
            }
          </ResultWrapper>
        );
        break;

      case V.ENTRY:
        if (!entry) {
          content = (<Message iconClass={ "spinner" } message={ t("loading-message") } />)
        } else {

          const onBack = () => {
            dispatch(Actions.setCurrentEntry(null, null));
            dispatch(Actions.showSearchResults());
            dispatch(Actions.setCenterInUrl(map.center));
            // dispatch(Actions.restoreSearch());
          };

          const onEdit = () => {
            dispatch(Actions.editCurrentEntry());
          };

          const isEvent = entry.categories && entry.categories.length > 0 && entry.categories[0] === IDS.EVENT;
          content = (
            <ScrollableEntryDetailsWrapper id="ScrollableEntryDetailsWrapper">
              <EntryDetails
                entry={ entry }
                isEvent={ isEvent }
                onTag={ onTagClick }
                tagsClickable={ tagsClickable }
                onEdit={ onEdit }
                onBack={ onBack }
              />
              { !isEvent ?
                <Ratings
                  id="Ratings"
                  entry={ entry }
                  ratings={ (entry ? entry.ratings || [] : []).map(id => {
                    return ratings[id];
                  })}
                  onRate={ id => { return dispatch(Actions.showNewRating(id)); }}
                  onComment={ context => { return dispatch(Actions.showNewComment(context)); }}
                />
              : ''}
              <SidebarFooter
                isEvent={isEvent}
                changed = {entry.created}
                version = {entry.version}
                title = {entry.title}
              />
            </ScrollableEntryDetailsWrapper>
          );
        }
        break;

      case V.EDIT:
      case V.NEW:
        content = (
          <EntryForm
            isEdit={ form[EDIT.id] ? form[EDIT.id].kvm_flag_id : null }
            isEvent={ isEventForEdit }
            formSyncErrors={ form[EDIT.id].syncErrors }
            formSubmitFailed = { form[EDIT.id].submitFailed }
            formStartEndDate={ { startDate: entry ? (entry.start * 1000) : null, endDate: entry ? (entry.end * 1000) : null } }
            license={ entries[search.current] ? entries[search.current].license : null }
            dispatch={ dispatch }
            onSubmit={ data => {
              var dataToSend = {
                title: data.title,
                description: data.description,
                tags: data.tags ? data.tags.split(',') : null,
                organizer: data.organizer,
                homepage: data.homepage,
                telephone: data.telephone,
                opening_hours: data.opening_hours,
                lat: Number(data.lat),
                lng: Number(data.lng),
                street: data.street,
                city: data.city,
                country: data.country,
                state: data.state,
                email: data.email,
                zip: data.zip,
                version: ((form[EDIT.id] ? form[EDIT.id].values ? form[EDIT.id].values.version : null : null) || 0) + 1,
                categories: [data.category],
                image_url: data.image_url,
                image_link_url: data.image_link_url,
                end: data.end && converDateToTimestamp(data.end),
                start: data.start && converDateToTimestamp(data.start)
              };
              if (form[EDIT.id]) {
                dataToSend.id = form[EDIT.id].kvm_flag_id;
              }
              return dispatch(Actions.saveEntry(dataToSend));
            }}
          />
        );
        break;

      case V.NEW_RATING:
        var kvm_flag_id = form[RATING.id] ? form[RATING.id].kvm_flag_id : null;
        var ref;
        content = (
          <RatingForm
            ref={ 'rating' }
            entryid={ kvm_flag_id }
            entryTitle={
              form[RATING.id]
                ? entries[form[RATING.id].kvm_flag_id]
                  ? entries[form[RATING.id].kvm_flag_id].title
                  : null
                : null
            }
            onSubmit={ data => {
              return dispatch(Actions.createRating({
                entry: form[RATING.id] ? form[RATING.id].kvm_flag_id : null,
                title: data.title,
                context: data.context,
                value: data.value,
                comment: data.comment,
                source: data.source
              }));
            }}
            onCancel={ () => {
              dispatch(initialize(RATING.id, {}, RATING.fields));
              dispatch(Actions.cancelRating());
            }}
            contextToExplain={ explainRatingContext }
            selectedContext={ selectedContext }
            changeContext={ ratingContext => { return dispatch(Actions.explainRatingContext(ratingContext)); }}
          />
        );
        break;

      case V.NEW_COMMENT:
        var kvm_flag_id = form[RATING.id] ? form[RATING.id].kvm_flag_id : null;
        var ref;
        let payload = form.comment.kvm_flag_id;
        content = (
          <CommentForm
            entryId={ payload.entryId }
            entryTitle={ payload.entryTitle }
            onSubmit={ data => {
              return dispatch(Actions.createRating({
                entry: payload.entryId,
                title: data.title,
                context: payload.ratingContext,
                value: data.value,
                comment: data.comment,
                source: data.source
              }));
            }}
            onCancel={ () => {
              dispatch(initialize(RATING.id, {}, RATING.fields));
              dispatch(Actions.cancelRating());
            }}
            ratingContext={ payload.ratingContext }
            ratingList={ payload.ratingList }
          />
        );
        break;

      case V.WAIT:
        content = (
          <Message
            iconClass={ "spinner" }
            message={ t("loading-message") }
            onCancel={ () => { return dispatch(Actions.cancelWait()); }}
          />
        );
        break;

      case V.IO_ERROR:
        content = (
          <Message
            iconClass={ "exclamation-triangle" }
            message={ t("io-error.message") }
          />
        );
        break;

      case V.SUBSCRIBE_TO_BBOX:
        content = (
          <SubscribeToBbox
            subscriptionExists={ user.subscriptionExists }
            dispatch={ dispatch }
            bbox={ map.bbox }
            username={ user.username }
            mapCenter={ map.center }
          />
        );
        break;

      default:
        content =

    }

    return(
      <SidebarComponent>
        {
          showSearchBar
          ?

            <SearchBar
                searchText={search.text.startsWith(fixedTagsStr) ? search.text.substr(fixedTagsStr.length).trimStart() : search.text}
                fixedTagsStr={fixedTagsStr}
                categories={search.categories}
                type="integrated"
                disabled={view.left === V.EDIT || view.left === V.NEW}
                toggleCat={ c => {
                  if(search.categories.includes(c)){
                    dispatch(Actions.disableSearchCategory(c));
                  } else {
                    dispatch(Actions.enableSearchCategory(c));
                  }
                  return dispatch(Actions.search());
                }}
              onChange={txt => {
                  txt = txt ? `${fixedTagsStr} ${txt}`: fixedTagsStr

                  dispatch(Actions.setSearchText(txt));
                  return dispatch(Actions.search());
                }}
                onEscape={ () => {
                  return dispatch(Actions.setSearchText(''));
                }}
                onEnter={ () => {}}      // currently not used, TODO
                loading={ server.loadingSearch }
              />

          : ""
        }
        {
          content
        }
        {
          (view.left === V.RESULT) && showAddEntryButton
          ? <AddEntryButton>
              <NavButton
                key = "back"
                classname = "pure-u-1"
                icon = "plus"
                text = {t("resultlist.addEntry")}
                onClick = {() => {
                  dispatch(Actions.showNewEntry());
                }}
              />
            </AddEntryButton>
          : ""
        }
      </SidebarComponent>
    );
  }
}

const ScrollableEntryDetailsWrapper = styled(ScrollableDiv)`
  height: 100%;
  display: flex;
  flex-direction: column;
`

const SidebarComponent = styled.div`
  display: flex;
  flex-direction: column;
  height: 100%;
`

Sidebar.propTypes = {
  view:           PropTypes.object.isRequired,
  search:         PropTypes.object.isRequired,
  map:            PropTypes.object.isRequired,
  user:           PropTypes.object,
  form:           PropTypes.object,
  resultEntries:  PropTypes.array,
  entries:        PropTypes.object.isRequired,
  ratings:        PropTypes.object,
  dispatch:       PropTypes.func,
  t:              PropTypes.func.isRequired
}

export default Sidebar

const GroupHeader = styled.div `
  border-top: 3px solid ${STYLE.lightGray};
  padding: 0.5em 1em 0.5em 1em;
  margin: 0;
  background: #eaeaea;
  color: #666;
`

const AddEntryButton = styled.nav`
  z-index: 10;
  padding: 0;
  margin: 0;
  background: ${STYLE.coal};
  text-align: center;
  bottom: 0;
  li {
    cursor: pointer;
    box-sizing: border-box;
    font-weight: normal;
    padding: 0.3em;
    font-size: 1.2em;
    border: none;
    color: ${STYLE.lightGray};
    background: transparent;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    &:hover {
      color: #fff;
      border-bottom: 4px solid #fff;
    }
    i {
      margin-right: 0.5em;
    }
  }
`;

const ResultWrapper = styled(ScrollableDiv)`
  background: #f7f7f7;
   /* city list only for sidebar, not landing page TODO: where to put this? */
  .city-list ul {
    background: #f7f7f7;
    li {
      padding: 0.2em;
      padding-left: 0.7em;
      padding-right: 0.7em;
      line-height: 0.9;
      border-left: 5px solid transparent;
      &:hover {
        background: #fff;
        border-left: 5px solid ${STYLE.darkGray};
        div.chevron {
          color: ${STYLE.darkGray};
        }
      }
      span {
        &.state {
          color: #555;
        }
        &.country {
          color: #888;
        }
        &.prefix {
          color: #888;
        }
      }
    }
  }
`<|endoftext|>


<commit_before>/*
 * Copyright 2012-present, Polis Technology Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights for non-commercial use can be found in the PATENTS file
 * in the same directory.
 */

import React from "react";
import { connect } from "react-redux";
import { populateUserStore } from "../actions";

import Radium from "radium";
import _ from "lodash";
// import {Link} from "react-router";
import StarsSpinner from "./framework/stars-spinner";
// import Awesome from "react-fontawesome";
import Sidebar from "react-sidebar";
import SidebarContentConversation from "./sidebar-content-conversation";
import SidebarContentHome from "./sidebar-content-home";
import MaterialTitlePanel from "./material-title-panel";
import Trial from "./framework/trial-banner";
import Flex from "./framework/flex";

const styles = {
  container: {
    backgroundColor: "rgb(240,240,247)",
    height: "100%",
    margin: 0
  }
};

@connect((state) => {
  return state.user;
})
@Radium
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sidebarOpen: false
      // sidebarDocked: true,
    };
  }
  static propTypes = {
    /* react */
    dispatch: React.PropTypes.func,
    params: React.PropTypes.object,
    /* component api */
    error: React.PropTypes.object,
    loading: React.PropTypes.bool,
    user: React.PropTypes.object,
    routes: React.PropTypes.array,
    isLoggedIn: React.PropTypes.bool,
    // foo: React.PropTypes.string
  }
  static defaultProps = {
    // foo: "bar"
  }

  loadUserData() {
    this.props.dispatch(populateUserStore());
  }

  componentWillMount() {
    this.loadUserData();
    let mql = window.matchMedia(`(min-width: 800px)`);
    mql.addListener(this.mediaQueryChanged.bind(this));
    this.setState({mql: mql, docked: mql.matches});
    this.checkForAuth(this.props);
  }

  componentWillReceiveProps(nextProps) {
    this.checkForAuth(nextProps);
  }

  checkForAuth(props) {
    if (!_.isUndefined(props.isLoggedIn)) {
      if (!props.isLoggedIn && (props.status === 401 || props.status === 403)) {
        window.location = "/signin" + this.props.location.pathname;
      }
    }
  }

  componentDidMount() {
    this.mediaQueryChanged();
  }

  initIntercom() {
    if (!this.intercomInitialized) {
      const user = this.props.user;
      if (user) {
        if (!window.Intercom && user && user.uid) {
          window.initIntercom();
        }
        if (user.email) {
          /*eslint-disable */
          /* jshint ignore:start */
          Intercom("boot", {
            app_id: "nb5hla8s",
            created_at: Date.now(),
            user_id: user.uid
          });
          /* jshint ignore:end */
          /*eslint-enable */
        }
        this.intercomInitialized = true;
      }
    }
  }

  updateIntercomSettings() {
    this.initIntercom();
    const user = this.props.user;
    window.intercomOptions = {
      app_id: "nb5hla8s",
      widget: {
        activator: "#IntercomDefaultWidget"
      }
    };
    if (user && user.uid) {
      intercomOptions.user_id = user.uid + "";
    }
    if (user && user.email) {
      intercomOptions.email = user.email;
    }
    if (user && user.created) {
      intercomOptions.created_at = user.created / 1000 >> 0;
    }

  }

  componentDidUpdate() {
    this.updateIntercomSettings();
  }

  componentWillUnmount() {
    this.state.mql.removeListener(this.mediaQueryChanged.bind(this));
  }

  mediaQueryChanged() {
    this.setState({sidebarDocked: this.state.mql.matches});
  }

  onSetSidebarOpen(open) {
    this.setState({sidebarOpen: open});
  }

  handleMenuButtonClick() {
    this.setState({sidebarOpen: !this.state.sidebarOpen});
  }
  getTitleFromRoute() {
    /* ugly, but... is what it is for now */
    let title = "Admin Dashboard"; /* in leiu of default */

    if (this.props.routes[1] && this.props.routes[1].path === "integrate") {
      title = "Integrate";
    } else if (this.props.routes[1] && !this.props.routes[1].path) {
      title = "My Conversations";
    } else if (this.props.routes[1] && this.props.routes[1].path === "other-conversations") {
      title = "Conversations I Participated In";
    } else if (this.props.routes[1] && this.props.routes[1].path === "account") {
      title = "Account Management";
    } else if (this.props.routes[2] && this.props.routes[2].path === "comments") {
      title = "Moderate Comments";
    } else if (this.props.routes[2] && !this.props.routes[2].path) {
      title = "Configure Conversation";
    } else if (this.props.routes[2] && this.props.routes[2].path === "participants") {
      title = "Moderate Participants";
    } else if (this.props.routes[2] && this.props.routes[2].path === "stats") {
      title = "Conversation Statistics";
    } else if (this.props.routes[2] && this.props.routes[2].path === "export") {
      title = "Data Export";
    } else if (this.props.routes[2] && this.props.routes[2].path === "share") {
      title = "Share & Embed";
    } else if (this.props.routes[2] && this.props.routes[2].path === "live") {
      title = "See Conversation Live";
    } else if (this.props.routes[2] && this.props.routes[2].path === "summary") {
      title = "Summary";
    }

    return title;
  }
  onSidebarItemClicked() {
    this.setState({sidebarOpen: false});
  }

  renderConsole() {
    return (
      <Sidebar
        sidebar={
          this.props.params.conversation_id ?
            <SidebarContentConversation
              {...this.props}
              conversation_id={this.props.params.conversation_id}
              onSidebarItemClicked={ this.onSidebarItemClicked.bind(this) }/> :
            <SidebarContentHome
              {...this.props}
              onSidebarItemClicked={ this.onSidebarItemClicked.bind(this) } />
          }
          open={ this.state.sidebarOpen }
          docked={ this.state.sidebarDocked }

          onSetOpen={ this.onSetSidebarOpen.bind(this) }>
          <MaterialTitlePanel
            handleHamburgerClick={this.handleMenuButtonClick.bind(this)}
            showHamburger={this.state.sidebarDocked}
            name={this.props.user.hname}
            title={this.getTitleFromRoute()}>
            {
              /*trial condition*/ true ?
              <Trial title={"You have x days remaining on your trial. *Upgrade*"}/> :
                ""
              }

                { this.props.children }

            </MaterialTitlePanel>
      </Sidebar>
    )
  }
  renderSpinner() {
    return (
      <Flex styleOverrides={{height: "100%"}}>
        {"Loading pol.is..."}
      </Flex>
    )
    // return (
    //   <StarsSpinner
    //     text={""}
    //     nodeColor={ "rgb(150,150,150)" }
    //     count={ Math.floor(window.innerWidth / 10) }
    //     width={ window.innerWidth }
    //     height={ window.innerHeight }
    //     radius={ 1.5 }
    //     lineWidth={ 1 }/>
    // )
  }
  render() {
    return (

        {
          !this.props.isLoggedIn ? this.renderSpinner() : this.renderConsole()
        }

    );
  }
}

export default App;
<commit_msg>fix !isLoggedIn redirect test<commit_after>/*
 * Copyright 2012-present, Polis Technology Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights for non-commercial use can be found in the PATENTS file
 * in the same directory.
 */

import React from "react";
import { connect } from "react-redux";
import { populateUserStore } from "../actions";

import Radium from "radium";
import _ from "lodash";
// import {Link} from "react-router";
import StarsSpinner from "./framework/stars-spinner";
// import Awesome from "react-fontawesome";
import Sidebar from "react-sidebar";
import SidebarContentConversation from "./sidebar-content-conversation";
import SidebarContentHome from "./sidebar-content-home";
import MaterialTitlePanel from "./material-title-panel";
import Trial from "./framework/trial-banner";
import Flex from "./framework/flex";

const styles = {
  container: {
    backgroundColor: "rgb(240,240,247)",
    height: "100%",
    margin: 0
  }
};

@connect((state) => {
  return state.user;
})
@Radium
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sidebarOpen: false
      // sidebarDocked: true,
    };
  }
  static propTypes = {
    /* react */
    dispatch: React.PropTypes.func,
    params: React.PropTypes.object,
    /* component api */
    error: React.PropTypes.object,
    loading: React.PropTypes.bool,
    user: React.PropTypes.object,
    routes: React.PropTypes.array,
    isLoggedIn: React.PropTypes.bool,
    // foo: React.PropTypes.string
  }
  static defaultProps = {
    // foo: "bar"
  }

  loadUserData() {
    this.props.dispatch(populateUserStore());
  }

  componentWillMount() {
    this.loadUserData();
    let mql = window.matchMedia(`(min-width: 800px)`);
    mql.addListener(this.mediaQueryChanged.bind(this));
    this.setState({mql: mql, docked: mql.matches});
    this.checkForAuth(this.props);
  }

  componentWillReceiveProps(nextProps) {
    this.checkForAuth(nextProps);
  }

  checkForAuth(props) {
    if (!_.isUndefined(props.isLoggedIn)) {

      var shouldRedirect = props.error ?
        (props.status === 401 || props.status === 403) :
        !props.isLoggedIn;

      if (shouldRedirect) {
        window.location = "/signin" + this.props.location.pathname;
      }
    }
  }

  componentDidMount() {
    this.mediaQueryChanged();
  }

  initIntercom() {
    if (!this.intercomInitialized) {
      const user = this.props.user;
      if (user) {
        if (!window.Intercom && user && user.uid) {
          window.initIntercom();
        }
        if (user.email) {
          /*eslint-disable */
          /* jshint ignore:start */
          Intercom("boot", {
            app_id: "nb5hla8s",
            created_at: Date.now(),
            user_id: user.uid
          });
          /* jshint ignore:end */
          /*eslint-enable */
        }
        this.intercomInitialized = true;
      }
    }
  }

  updateIntercomSettings() {
    this.initIntercom();
    const user = this.props.user;
    window.intercomOptions = {
      app_id: "nb5hla8s",
      widget: {
        activator: "#IntercomDefaultWidget"
      }
    };
    if (user && user.uid) {
      intercomOptions.user_id = user.uid + "";
    }
    if (user && user.email) {
      intercomOptions.email = user.email;
    }
    if (user && user.created) {
      intercomOptions.created_at = user.created / 1000 >> 0;
    }

  }

  componentDidUpdate() {
    this.updateIntercomSettings();
  }

  componentWillUnmount() {
    this.state.mql.removeListener(this.mediaQueryChanged.bind(this));
  }

  mediaQueryChanged() {
    this.setState({sidebarDocked: this.state.mql.matches});
  }

  onSetSidebarOpen(open) {
    this.setState({sidebarOpen: open});
  }

  handleMenuButtonClick() {
    this.setState({sidebarOpen: !this.state.sidebarOpen});
  }
  getTitleFromRoute() {
    /* ugly, but... is what it is for now */
    let title = "Admin Dashboard"; /* in leiu of default */

    if (this.props.routes[1] && this.props.routes[1].path === "integrate") {
      title = "Integrate";
    } else if (this.props.routes[1] && !this.props.routes[1].path) {
      title = "My Conversations";
    } else if (this.props.routes[1] && this.props.routes[1].path === "other-conversations") {
      title = "Conversations I Participated In";
    } else if (this.props.routes[1] && this.props.routes[1].path === "account") {
      title = "Account Management";
    } else if (this.props.routes[2] && this.props.routes[2].path === "comments") {
      title = "Moderate Comments";
    } else if (this.props.routes[2] && !this.props.routes[2].path) {
      title = "Configure Conversation";
    } else if (this.props.routes[2] && this.props.routes[2].path === "participants") {
      title = "Moderate Participants";
    } else if (this.props.routes[2] && this.props.routes[2].path === "stats") {
      title = "Conversation Statistics";
    } else if (this.props.routes[2] && this.props.routes[2].path === "export") {
      title = "Data Export";
    } else if (this.props.routes[2] && this.props.routes[2].path === "share") {
      title = "Share & Embed";
    } else if (this.props.routes[2] && this.props.routes[2].path === "live") {
      title = "See Conversation Live";
    } else if (this.props.routes[2] && this.props.routes[2].path === "summary") {
      title = "Summary";
    }

    return title;
  }
  onSidebarItemClicked() {
    this.setState({sidebarOpen: false});
  }

  renderConsole() {
    return (
      <Sidebar
        sidebar={
          this.props.params.conversation_id ?
            <SidebarContentConversation
              {...this.props}
              conversation_id={this.props.params.conversation_id}
              onSidebarItemClicked={ this.onSidebarItemClicked.bind(this) }/> :
            <SidebarContentHome
              {...this.props}
              onSidebarItemClicked={ this.onSidebarItemClicked.bind(this) } />
          }
          open={ this.state.sidebarOpen }
          docked={ this.state.sidebarDocked }

          onSetOpen={ this.onSetSidebarOpen.bind(this) }>
          <MaterialTitlePanel
            handleHamburgerClick={this.handleMenuButtonClick.bind(this)}
            showHamburger={this.state.sidebarDocked}
            name={this.props.user.hname}
            title={this.getTitleFromRoute()}>
            {
              /*trial condition*/ true ?
              <Trial title={"You have x days remaining on your trial. *Upgrade*"}/> :
                ""
              }

                { this.props.children }

            </MaterialTitlePanel>
      </Sidebar>
    )
  }
  renderSpinner() {
    return (
      <Flex styleOverrides={{height: "100%"}}>
        {"Loading pol.is..."}
      </Flex>
    )
    // return (
    //   <StarsSpinner
    //     text={""}
    //     nodeColor={ "rgb(150,150,150)" }
    //     count={ Math.floor(window.innerWidth / 10) }
    //     width={ window.innerWidth }
    //     height={ window.innerHeight }
    //     radius={ 1.5 }
    //     lineWidth={ 1 }/>
    // )
  }
  render() {
    return (

        {
          !this.props.isLoggedIn ? this.renderSpinner() : this.renderConsole()
        }

    );
  }
}

export default App;
<|endoftext|>


<commit_before>export const mocks = ['nodeId', 'componentName']

export function isPage () {
  return !this.ownerId
}

export function initRelation (detail) {
  this.dispatch('__l', detail)
}
<commit_msg>feat(qa-light): mock _componentId<commit_after>export const mocks = ['nodeId', 'componentName', '_componentId']

export function isPage () {
  return !this.ownerId
}

export function initRelation (detail) {
  this.dispatch('__l', detail)
}
<|endoftext|>


<commit_before>/* @flow */

import { isDef, isUndef, extend, toNumber } from 'shared/util'

function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
  if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
    return
  }
  let key, cur
  const elm: any = vnode.elm
  const oldProps = oldVnode.data.domProps || {}
  let props = vnode.data.domProps || {}
  // clone observed objects, as the user probably wants to mutate it
  if (isDef(props.__ob__)) {
    props = vnode.data.domProps = extend({}, props)
  }

  for (key in oldProps) {
    if (isUndef(props[key])) {
      elm[key] = ''
    }
  }
  for (key in props) {
    cur = props[key]
    // ignore children if the node has textContent or innerHTML,
    // as these will throw away existing DOM nodes and cause removal errors
    // on subsequent patches (#3360)
    if (key === 'textContent' || key === 'innerHTML') {
      if (vnode.children) vnode.children.length = 0
      if (cur === oldProps[key]) continue
    }

    if (key === 'value') {
      // store value as _value as well since
      // non-string values will be stringified
      elm._value = cur
      // avoid resetting cursor position when value is the same
      const strCur = isUndef(cur) ? '' : String(cur)
      if (shouldUpdateValue(elm, vnode, strCur)) {
        elm.value = strCur
      }
    } else {
      elm[key] = cur
    }
  }
}

// check platforms/web/util/attrs.js acceptValue
type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;

function shouldUpdateValue (
  elm: acceptValueElm,
  vnode: VNodeWithData,
  checkVal: string
): boolean {
  return (!elm.composing && (
    vnode.tag === 'option' ||
    isDirty(elm, checkVal) ||
    isInputChanged(elm, checkVal)
  ))
}

function isDirty (elm: acceptValueElm, checkVal: string): boolean {
  // return true when textbox (.number and .trim) loses focus and its value is
  // not equal to the updated value
  return document.activeElement !== elm && elm.value !== checkVal
}

function isInputChanged (elm: any, newVal: string): boolean {
  const value = elm.value
  const modifiers = elm._vModifiers // injected by v-model runtime
  if (isDef(modifiers) && modifiers.number) {
    return toNumber(value) !== toNumber(newVal)
  }
  if (isDef(modifiers) && modifiers.trim) {
    return value.trim() !== newVal.trim()
  }
  return value !== newVal
}

export default {
  create: updateDOMProps,
  update: updateDOMProps
}
<commit_msg>fix: work around IE/Edge bug when accessing document.activeElement from iframe<commit_after>/* @flow */

import { isDef, isUndef, extend, toNumber } from 'shared/util'

function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
  if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
    return
  }
  let key, cur
  const elm: any = vnode.elm
  const oldProps = oldVnode.data.domProps || {}
  let props = vnode.data.domProps || {}
  // clone observed objects, as the user probably wants to mutate it
  if (isDef(props.__ob__)) {
    props = vnode.data.domProps = extend({}, props)
  }

  for (key in oldProps) {
    if (isUndef(props[key])) {
      elm[key] = ''
    }
  }
  for (key in props) {
    cur = props[key]
    // ignore children if the node has textContent or innerHTML,
    // as these will throw away existing DOM nodes and cause removal errors
    // on subsequent patches (#3360)
    if (key === 'textContent' || key === 'innerHTML') {
      if (vnode.children) vnode.children.length = 0
      if (cur === oldProps[key]) continue
    }

    if (key === 'value') {
      // store value as _value as well since
      // non-string values will be stringified
      elm._value = cur
      // avoid resetting cursor position when value is the same
      const strCur = isUndef(cur) ? '' : String(cur)
      if (shouldUpdateValue(elm, vnode, strCur)) {
        elm.value = strCur
      }
    } else {
      elm[key] = cur
    }
  }
}

// check platforms/web/util/attrs.js acceptValue
type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;

function shouldUpdateValue (
  elm: acceptValueElm,
  vnode: VNodeWithData,
  checkVal: string
): boolean {
  return (!elm.composing && (
    vnode.tag === 'option' ||
    isDirty(elm, checkVal) ||
    isInputChanged(elm, checkVal)
  ))
}

function isDirty (elm: acceptValueElm, checkVal: string): boolean {
  // return true when textbox (.number and .trim) loses focus and its value is
  // not equal to the updated value
  let notInFocus = true
  // #6157
  // work around IE bug when accessing document.activeElement in an iframe
  try { notInFocus = document.activeElement !== elm } catch (e) {}
  return notInFocus && elm.value !== checkVal
}

function isInputChanged (elm: any, newVal: string): boolean {
  const value = elm.value
  const modifiers = elm._vModifiers // injected by v-model runtime
  if (isDef(modifiers) && modifiers.number) {
    return toNumber(value) !== toNumber(newVal)
  }
  if (isDef(modifiers) && modifiers.trim) {
    return value.trim() !== newVal.trim()
  }
  return value !== newVal
}

export default {
  create: updateDOMProps,
  update: updateDOMProps
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import ReactDOM from 'react-dom';
// 图片相关信息
import imageDatas from '../data/imageDatas.json';

// 引入 ECharts 主模块
// import echarts from 'echarts/lib/echarts';
// import  'echarts/lib/chart/bar';
// import  'echarts/lib/chart/line';
// import 'echarts/lib/component/tooltip';
// import 'echarts/lib/component/title';
// import 'echarts/lib/component/markLine';
// import 'echarts/lib/component/legend';

import '../scss/index.scss';

// 获取区间内的一个随机值
function getRangeRandom(low, high) {
    return Math.ceil(Math.random() * (high - low) + low);
}

// 将图片信息转为图片URL路径信息
function genImageURL (imageDatasArr) {
    let singleImageData;
    for (let i = 0; i < imageDatasArr.length; i++) {
        singleImageData = imageDatasArr[i];
        singleImageData.imageURL = require('../images/' + singleImageData.fileName);
        imageDatasArr[i] = singleImageData;
    }
    return imageDatasArr;
};

// 单个图片组件
class ImgFigure extends Component {
    render () {
        let styleObj = {};
        //  如果props属性中指定了这张图片的位置，则使用
        if (this.props.arrange) {
            styleObj = this.props.arrange.pos;
        }
        return (

{this.props.data.desc}

        )
    }
}

class Gallery extends Component {
    constructor (props) {
        super(props);
        this.state = {
            imgsArrangeArr: [
                // {
                    // pos: {
                    //     left: '0',
                    //     top: '0'
                    // }
                // }
            ]
        };
        this.constant = {
            centerPos: {
                left: 0,
                right: 0
            },
            // 水平方向取值范围
            hPosRange: {
                leftSecX: [0, 0],
                rightSecX: [0, 0],
                y: [0, 0]
            },
            // 垂直方向取值范围
            vPosRange: {
                x: [0, 0],
                topY: [0, 0]
            }
        }
    };

    // 重新布局所有图片 centerIndex指定居中哪个图片
    rearrange (centerIndex) {
        // let imgsArrangeArr = this.state.imgsArrangeArr,
        let imgsArrangeArr = [],
        data = genImageURL(imageDatas);
        // 如果当前没对象，则初始化
        for (let i = 0; i < data.length; i++) {
            if (!this.state.imgsArrangeArr[i]) {
                imgsArrangeArr.push({
                    pos: {
                        left: 0,
                        top: 0
                    }
                })
            } else {
                imgsArrangeArr.push(this.state.imgsArrangeArr[i])
            }
        }
        console.log('初始化图片数组imgsArrangeArr:')
        console.log(imgsArrangeArr)
        let constant = this.constant,
            centerPos = constant.centerPos,
            hPosRange = constant.hPosRange,
            vPosRange = constant.vPosRange,
            hPosRangeLeftSecX = hPosRange.leftSecX,
            hPosRangeRightSecX = hPosRange.rightSecX,
            hPosRangeY = hPosRange.y,
            vPosRangeTopY = vPosRange.topY,
            vPosRangeX = vPosRange.x,
            imgsArrangeTopArr = [],
            topImgNum = Math.floor(Math.random() * 2), // 取一个或者不取
            topImgSpliceIndex = 0,
            imgsArrangeCenterArr = imgsArrangeArr.splice(centerIndex, 1);

        console.log(imgsArrangeArr)
        console.log(imgsArrangeCenterArr)

        // 首先居中centerIndex的图片
        imgsArrangeCenterArr[0].pos = centerPos;
        console.log('中心图片:');
        console.log(imgsArrangeCenterArr);
        // 取出要布局上侧的图片的状态信息
        topImgSpliceIndex = Math.ceil(Math.random() * (imgsArrangeArr.length - topImgNum));
        imgsArrangeTopArr = imgsArrangeArr.splice(topImgSpliceIndex, topImgNum);

        // 布局上侧图片
        imgsArrangeTopArr.forEach((value, index) => {
            imgsArrangeTopArr[index] = {
                pos: {
                    top: getRangeRandom(vPosRangeTopY[0], vPosRangeTopY[1]),
                    left: getRangeRandom(vPosRangeX[0], vPosRangeX[1])
                }
            }
        })
        console.log('顶部有' + topImgNum + '张图片:');
        console.log(imgsArrangeTopArr)

        // 布局左右两侧的图片
        for(let i = 0, j = imgsArrangeArr.length, k = j / 2; i < j; i++) {
            let hPosRangeLORX = null;
            if (i < k) {
                // 前半部分布局左边，后半部分布局右边
                hPosRangeLORX = hPosRangeLeftSecX;
            } else {
                hPosRangeLORX = hPosRangeRightSecX;
            }

            imgsArrangeArr[i].pos = {
                top: getRangeRandom(hPosRangeY[0], hPosRangeY[1]),
                left: getRangeRandom(hPosRangeLORX[0], hPosRangeLORX[1])
            }

        }

        if (imgsArrangeTopArr && imgsArrangeTopArr[0]) {
            imgsArrangeTopArr.splice(topImgSpliceIndex, 0, imgsArrangeTopArr[0])
        }

        console.log(imgsArrangeArr)
        imgsArrangeArr.splice(centerIndex, 0, imgsArrangeCenterArr[0])
        this.setState({
            imgsArrangeArr: imgsArrangeArr
        })
    };

    componentDidMount () {
        // 组件加载以后，为每张图片计算其位置的范围,
        // 获取stage的节点，不能在render中和render之前使用ReactDOM.findDOMNode

        // scrollWidth实际宽度，不包含滚动条, 会随着内容的宽度变大
        // clientWidth可视区域的宽度，不包含滚动条，会随对象显示大小而改变
        // offestWidth整体的宽度，包含滚动条，会随对象显示大小而改变
        let stageDom = ReactDOM.findDOMNode(this.refs.stage),
            stageW = stageDom.scrollWidth, // 宽
            stageH = stageDom.scrollHeight, // 高
            halfStageW = Math.ceil(stageW / 2), // 一半宽
            halfStageH = Math.ceil(stageH / 2); // 一半高

        // 获取单个imgFigure的大小
        let imgFigureDom = ReactDOM.findDOMNode(this.refs.imgFigure0),
            imgW = imgFigureDom.scrollWidth,
            imgH = imgFigureDom.scrollHeight,
            halfImgW = Math.ceil(imgW / 2),
            halfImgH = Math.ceil(imgH / 2);

        this.constant = {
            // 计算中心图片的位置点
            centerPos: {
                left: halfStageW - halfImgW,
                top: halfStageH - halfImgH
            },
            // 计算水平方向位置
            hPosRange: {
                leftSecX: [halfImgW, halfStageW - halfImgW * 3],
                rightSecX: [halfStageW + halfImgW, stageW - halfImgW],
                y: [-halfImgH, stageH - halfImgH]
            },
            // 计算垂直方向位置
            vPosRange: {
                topY: [-halfImgH, halfStageH - halfImgW * 3],
                x: [halfStageW - imgW, halfImgW]
            }
        }

        // 随机生成一个0-10的整数在最中间展示
        const randomNum = Math.floor(Math.random() * 11);
        console.log(randomNum)
        this.rearrange(randomNum);
    };

    render () {
        let controllerUnits = [],
            imgFigures = [],
            data = genImageURL(imageDatas);
        // 将单个图片插入到数组中,再将数组imgFigures放入section中
        data.forEach((value, index) => {
            imgFigures.push(
                <ImgFigure
                    data={value}
                    key={'imgFigure'+index}
                    ref={'imgFigure'+index}
                    arrange={this.state.imgsArrangeArr[index]}
                />
            )
        })

        return (

                    {imgFigures}

                    {controllerUnits}

        )
    }
}

export default Gallery;

// 左分区 0 - ImgFigure.width/2 < x < stage.width/2 - ImgFigure.width/2*3
//       0 - ImgFigure.height/2 < y < stage.height - ImgFigure.height/2
// 右分区 stage.width/2 + ImgFigure.width/2 < x < stage.width - ImgFigure.width/2
//       0 - ImgFigure.height/2 < y < stage.height - ImgFigure.height/2
// 上分区 stage.width/2 - ImgFigure.width < x < stage.width/2
//       0 - ImgFigure.height/2 < y < stage.height - ImgFigure.height/2*3
<commit_msg>1.0 gallery is finished<commit_after>import React, {Component} from 'react';
import ReactDOM from 'react-dom';
// 图片相关信息
import imageDatas from '../data/imageDatas.json';

// 引入 ECharts 主模块
// import echarts from 'echarts/lib/echarts';
// import  'echarts/lib/chart/bar';
// import  'echarts/lib/chart/line';
// import 'echarts/lib/component/tooltip';
// import 'echarts/lib/component/title';
// import 'echarts/lib/component/markLine';
// import 'echarts/lib/component/legend';

import '../scss/index.scss';

// 获取区间内的一个随机值
function getRangeRandom(low, high) {
    return Math.ceil(Math.random() * (high - low) + low);
}

// 将图片信息转为图片URL路径信息
function genImageURL (imageDatasArr) {
    let singleImageData;
    for (let i = 0; i < imageDatasArr.length; i++) {
        singleImageData = imageDatasArr[i];
        singleImageData.imageURL = require('../images/' + singleImageData.fileName);
        imageDatasArr[i] = singleImageData;
    }
    return imageDatasArr;
};

// 单个图片组件
class ImgFigure extends Component {
    render () {
        let styleObj = {};
        //  如果props属性中指定了这张图片的位置，则使用
        if (this.props.arrange) {
            styleObj = this.props.arrange.pos;
        }
        return (

{this.props.data.desc}

        )
    }
}

class Gallery extends Component {
    constructor (props) {
        super(props);
        this.state = {
            imgsArrangeArr: [
                // {
                    // pos: {
                    //     left: '0',
                    //     top: '0'
                    // }
                // }
            ]
        };
        this.constant = {
            centerPos: {
                left: 0,
                right: 0
            },
            // 水平方向取值范围
            hPosRange: {
                leftSecX: [0, 0],
                rightSecX: [0, 0],
                y: [0, 0]
            },
            // 垂直方向取值范围
            vPosRange: {
                x: [0, 0],
                topY: [0, 0]
            }
        }
    };

    // 重新布局所有图片 centerIndex指定居中哪个图片
    rearrange (centerIndex) {
        // let imgsArrangeArr = this.state.imgsArrangeArr,
        let imgsArrangeArr = [],
        data = genImageURL(imageDatas);
        // 如果当前没对象，则初始化
        for (let i = 0; i < data.length; i++) {
            if (!this.state.imgsArrangeArr[i]) {
                imgsArrangeArr.push({
                    pos: {
                        left: 0,
                        top: 0
                    }
                })
            } else {
                imgsArrangeArr.push(this.state.imgsArrangeArr[i])
            }
        }
        console.log('初始化图片数组imgsArrangeArr:')
        console.log(imgsArrangeArr)
        let constant = this.constant,
            centerPos = constant.centerPos,
            hPosRange = constant.hPosRange,
            vPosRange = constant.vPosRange,
            hPosRangeLeftSecX = hPosRange.leftSecX,
            hPosRangeRightSecX = hPosRange.rightSecX,
            hPosRangeY = hPosRange.y,
            vPosRangeTopY = vPosRange.topY,
            vPosRangeX = vPosRange.x,
            imgsArrangeTopArr = [],
            topImgNum = Math.floor(Math.random() * 2), // 取一个或者不取
            topImgSpliceIndex = 0,
            imgsArrangeCenterArr = imgsArrangeArr.splice(centerIndex, 1);

        console.log(imgsArrangeArr)
        console.log(imgsArrangeCenterArr)

        // 首先居中centerIndex的图片
        imgsArrangeCenterArr[0].pos = centerPos;
        console.log('中心图片:');
        console.log(imgsArrangeCenterArr);
        // 取出要布局上侧的图片的状态信息
        topImgSpliceIndex = Math.ceil(Math.random() * (imgsArrangeArr.length - topImgNum));
        imgsArrangeTopArr = imgsArrangeArr.splice(topImgSpliceIndex, topImgNum);

        // 布局上侧图片
        imgsArrangeTopArr.forEach((value, index) => {
            imgsArrangeTopArr[index] = {
                pos: {
                    top: getRangeRandom(vPosRangeTopY[0], vPosRangeTopY[1]),
                    left: getRangeRandom(vPosRangeX[0], vPosRangeX[1])
                }
            }
        })
        console.log('顶部有' + topImgNum + '张图片:');
        console.log(imgsArrangeTopArr)

        // 布局左右两侧的图片
        for(let i = 0, j = imgsArrangeArr.length, k = j / 2; i < j; i++) {
            let hPosRangeLORX = null;
            if (i < k) {
                // 前半部分布局左边，后半部分布局右边
                hPosRangeLORX = hPosRangeLeftSecX;
            } else {
                hPosRangeLORX = hPosRangeRightSecX;
            }

            imgsArrangeArr[i].pos = {
                top: getRangeRandom(hPosRangeY[0], hPosRangeY[1]),
                left: getRangeRandom(hPosRangeLORX[0], hPosRangeLORX[1])
            }

        }

        // 把取出来的顶部图片放回imgsArrangeArr数组中
        if (imgsArrangeTopArr && imgsArrangeTopArr[0]) {
            imgsArrangeArr.splice(topImgSpliceIndex, 0, imgsArrangeTopArr[0])
        }

        imgsArrangeArr.splice(centerIndex, 0, imgsArrangeCenterArr[0]);
        this.setState({
            imgsArrangeArr: imgsArrangeArr
        })
    };

    componentDidMount () {
        // 组件加载以后，为每张图片计算其位置的范围,
        // 获取stage的节点，不能在render中和render之前使用ReactDOM.findDOMNode

        // scrollWidth实际宽度，不包含滚动条, 会随着内容的宽度变大
        // clientWidth可视区域的宽度，不包含滚动条，会随对象显示大小而改变
        // offestWidth整体的宽度，包含滚动条，会随对象显示大小而改变
        let stageDom = ReactDOM.findDOMNode(this.refs.stage),
            stageW = stageDom.scrollWidth, // 宽
            stageH = stageDom.scrollHeight, // 高
            halfStageW = Math.ceil(stageW / 2), // 一半宽
            halfStageH = Math.ceil(stageH / 2); // 一半高

        // 获取单个imgFigure的大小
        let imgFigureDom = ReactDOM.findDOMNode(this.refs.imgFigure0),
            imgW = imgFigureDom.scrollWidth,
            imgH = imgFigureDom.scrollHeight,
            halfImgW = Math.ceil(imgW / 2),
            halfImgH = Math.ceil(imgH / 2);

        this.constant = {
            // 计算中心图片的位置点
            centerPos: {
                left: halfStageW - halfImgW,
                top: halfStageH - halfImgH
            },
            // 计算左右两侧图片排布位置的取值范围
            hPosRange: {
                leftSecX: [-halfImgW, halfStageW - halfImgW * 3],
                rightSecX: [halfStageW + halfImgW, stageW - halfImgW],
                y: [-halfImgH, stageH - halfImgH]
            },
            // 计算上侧图片排布位置的取值范围
            vPosRange: {
                topY: [-halfImgH, halfStageH - halfImgH * 3],
                x: [halfStageW - imgW, halfStageW]
            }
        }

        // 随机生成一个0-16的整数在最中间展示
        const randomNum = Math.floor(Math.random() * 16);
        this.rearrange(randomNum);
    };

    render () {
        let controllerUnits = [],
            imgFigures = [],
            data = genImageURL(imageDatas);
        // 将单个图片插入到数组中,再将数组imgFigures放入section中
        data.forEach((value, index) => {
            imgFigures.push(
                <ImgFigure
                    data={value}
                    key={'imgFigure'+index}
                    ref={'imgFigure'+index}
                    arrange={this.state.imgsArrangeArr[index]}
                />
            )
        })

        return (

                    {imgFigures}

                    {controllerUnits}

        )
    }
}

export default Gallery;

// 左分区 0 - ImgFigure.width/2 < x < stage.width/2 - ImgFigure.width/2*3
//       0 - ImgFigure.height/2 < y < stage.height - ImgFigure.height/2
// 右分区 stage.width/2 + ImgFigure.width/2 < x < stage.width - ImgFigure.width/2
//       0 - ImgFigure.height/2 < y < stage.height - ImgFigure.height/2
// 上分区 stage.width/2 - ImgFigure.width < x < stage.width/2
//       0 - ImgFigure.height/2 < y < stage.height - ImgFigure.height/2*3
<|endoftext|>


<commit_before>import React from 'react'
import Tabs, {Tab} from 'material-ui/Tabs'
import {MuiThemeProvider} from 'material-ui/styles'
import Card from 'material-ui/Card'
import theme from './theme'
import {Link} from "react-static";

class NavBar extends React.Component {
  constructor (props) {
    super(props)
    this.home =
    this.resume = <Link to='/resume'/>
    this.blog = <Link to='/blog'/>
    this.about = <Link to='/about'/>
    this.pageList = ['', '/', '/resume', '/blog', '/about']
    this.state = {
      selection: this.pageList.indexOf('/'+window.location.pathname.split('/')[1]),
    }
  }
  handleChange = (event, value) => {
    this.setState({selection: value})
  }
  render () {
    return (
      <MuiThemeProvider theme={theme}>
        <div
          style={{position: 'fixed', width: '100%'}}
        >
          <Card
            raised
            className='top-bar'
            style={{maxWidth: '960px', margin: '0 auto'}}
          >
            <Tabs
              centered
              value={this.state.selection}
              indicatorColor="grey"
              onChange={this.handleChange}
            >
              <Tab label="Tanay PrabhuDesai" disabled />
              <Tab to="/" label={<Link to='/'>Home</Link>} onClick={this.home.onClick} />
              <Tab to="/resume" label={<Link to='/resume'>Résumé</Link>} onClick={this.resume.onClick} />
              <Tab to="/blog" label={<Link to='/blog'>Blog</Link>} onClick={this.blog.onClick} />
              <Tab to="/about" label={<Link to='/about'>About</Link>} onClick={this.about.onClick} />
            </Tabs>
          </Card>
        </div>
      </MuiThemeProvider>
    )
  }
}
export default NavBar
<commit_msg>Add redirect links to the nav bar<commit_after>import React from 'react'
import Tabs, {Tab} from 'material-ui/Tabs'
import {MuiThemeProvider} from 'material-ui/styles'
import Card from 'material-ui/Card'
import theme from './theme'
import {Redirect} from "react-static";

class NavBar extends React.Component {
  constructor (props) {
    super(props)
    this.pageList = ['', '/', '/resume', '/blog', '/about']
    this.state = {
      selection: this.pageList.indexOf('/'+window.location.pathname.split('/')[1]),
      buttonClicked: false,
    }
  }
  handleChange = (event, value) => {
    this.setState({selection: value, buttonClicked: true})
  }
  render () {
    var redirect = null;
    if (this.state.buttonClicked) {
      console.log('LINK ' + this.state.selection);
      redirect = <Redirect push to={this.pageList[this.state.selection]} />
    }
    this.state.buttonClicked = false;
    return (
      <MuiThemeProvider theme={theme}>
        {redirect}
        <div
          style={{position: 'fixed', width: '100%'}}
        >
          <Card
            raised
            className='top-bar'
            style={{maxWidth: '960px', margin: '0 auto'}}
          >
            <Tabs
              centered
              value={this.state.selection}
              indicatorColor="grey"
              onChange={this.handleChange}
            >
              <Tab label="Tanay PrabhuDesai" disabled />
              <Tab to="/" label='Home' onClick={()=>this.state.selection='/'} />
              <Tab to="/resume" label='Résumé' onClick={()=>this.state.selection='/resume'} />
              <Tab to="/blog" label='Blog' onClick={()=>this.state.selection='/blog'} />
              <Tab to="/about" label='About' onClick={()=>this.state.selection='/about'} />
            </Tabs>
          </Card>
        </div>
      </MuiThemeProvider>
    )
  }
}
export default NavBar
<|endoftext|>


<commit_before>import React from 'react'
import '../assets/stylesheets/application.css';
import { Link } from 'react-router-dom'
import { defaultState } from '../utils/constants'
import { setFlatFileContentToState } from '../utils/utils';
import { getOldState } from '../utils/utils'
import { StepNavigation } from './Common/StepNavigation'
import { NAVIGATION_STEPS } from '../utils/constants'
const { CROWDSALE_CONTRACT, TOKEN_SETUP, CROWDSALE_SETUP, PUBLISH, CROWDSALE_PAGE } = NAVIGATION_STEPS

export class stepOne extends React.Component {
  constructor(props) {
    super(props);
    let oldState = getOldState(props, defaultState)
    this.state = Object.assign({}, oldState)
  }

  getStandardCrowdsaleAssets (state) {
    const contractName = "CrowdsaleStandard";
    let srcC, binC
    setFlatFileContentToState("./contracts/" + contractName + "_flat.sol", (content) => srcC = content);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.bin", (_bin) => binC = _bin);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.abi", (_abi) => this.addContractsToState(srcC, binC, _abi, "crowdsale", state));

    const tokenName = "CrowdsaleStandardToken";
    let srcT, binT
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.sol", (content) => srcT = content);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.bin", (_bin) => binT = _bin);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.abi", (_abi) => this.addContractsToState(srcT, binT, _abi, "token", state));
  }

  getWhiteListWithCapCrowdsaleAssets (state) {
    const contractName = "CrowdsaleWhiteListWithCap";
    let srcC, binC
    setFlatFileContentToState("./contracts/" + contractName + "_flat.sol", (content) => srcC = content);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.bin", (_bin) => binC = _bin);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.abi", (_abi) => this.addContractsToState(srcC, binC, _abi, "crowdsale", state));

    const tokenName = "CrowdsaleWhiteListWithCapToken";
    let srcT, binT
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.sol", (content) => srcT = content);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.bin", (_bin) => binT = _bin);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.abi", (_abi) => this.addContractsToState(srcT, binT, _abi, "token", state));

    const pricingStrategyName = "CrowdsaleWhiteListWithCapPricingStrategy";
    let srcP, binP
    setFlatFileContentToState("./contracts/" + pricingStrategyName + "_flat.sol", (content) => srcP = content);
    setFlatFileContentToState("./contracts/" + pricingStrategyName + "_flat.bin", (_bin) => binP = _bin);
    setFlatFileContentToState("./contracts/" + pricingStrategyName + "_flat.abi", (_abi) => this.addContractsToState(srcP, binP, _abi, "pricingStrategy", state));

    const tokenTransferProxyName = "TokenTransferProxy";
    let srcTTP, binTTP
    setFlatFileContentToState("./contracts/" + tokenTransferProxyName + "_flat.sol", (content) => srcTTP = content);
    setFlatFileContentToState("./contracts/" + tokenTransferProxyName + "_flat.bin", (_bin) => binTTP = _bin);
    setFlatFileContentToState("./contracts/" + tokenTransferProxyName + "_flat.abi", (_abi) => this.addContractsToState(srcTTP, binTTP, _abi, "tokenTransferProxy", state));

    const multiSigName = "MultiSig";
    let srcM, binM
    setFlatFileContentToState("./contracts/" + multiSigName + "_flat.sol", (content) => srcM = content);
    setFlatFileContentToState("./contracts/" + multiSigName + "_flat.bin", (_bin) => binM = _bin);
    setFlatFileContentToState("./contracts/" + multiSigName + "_flat.abi", (_abi) => this.addContractsToState(srcM, binM, _abi, "multisig", state));

    const finalizeAgentName = "FinalizeAgent";
    let srcF, binF
    setFlatFileContentToState("./contracts/" + finalizeAgentName + "_flat.sol", (content) => srcF = content);
    setFlatFileContentToState("./contracts/" + finalizeAgentName + "_flat.bin", (_bin) => binF = _bin);
    setFlatFileContentToState("./contracts/" + finalizeAgentName + "_flat.abi", (_abi) => this.addContractsToState(srcF, binF, _abi, "finalizeAgent", state));
  }

  componentDidMount() {
    let newState = { ...this.state }
    newState.contractType = this.state.contractTypes.standard
    this.getStandardCrowdsaleAssets(newState);
  }

  addContractsToState (src, bin, abi, contract, state) {
    //let newState = Object.assign({}, state)
    state.contracts[contract] = {
      src,
      bin,
      abi: JSON.parse(abi),
      addr: (contract=="crowdsale" || contract=="pricingStrategy" || contract=="finalizeAgent")?[]:"",
      abiConstructor: (contract=="crowdsale" || contract=="pricingStrategy" || contract=="finalizeAgent")?[]:""
    }
    this.setState(state)
  }

  contractTypeSelected(e) {
    let newState = { ...this.state }
    newState.contractType = e.currentTarget.id;
    console.log(e.currentTarget.id);
    switch (e.currentTarget.id) {
      case this.state.contractTypes.standard: {
        this.getStandardCrowdsaleAssets(newState);
      } break;
      case this.state.contractTypes.whitelistwithcap: {
        this.getWhiteListWithCapCrowdsaleAssets(newState);
      } break;
      default:
        break;
    }
  }

  render() {
    return (

       <StepNavigation activeStep={CROWDSALE_CONTRACT}/>

Crowdsale Contract

              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
              in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

              <input
                type="radio"
                checked={this.state.contractType === this.state.contractTypes.standard}
                name="contract-type"
                id={this.state.contractTypes.standard}
                onChange={(e) => this.contractTypeSelected(e)}
              />
              Standard

                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

              <input
                type="radio"
                checked={this.state.contractType === this.state.contractTypes.whitelistwithcap}
                name="contract-type"
                id={this.state.contractTypes.whitelistwithcap}
                onChange={(e) => this.contractTypeSelected(e)}
              />
              Whitelist with Cap

                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

              <input
                type="radio"
                disabled
                checked={this.state.contractType === this.state.contractTypes.capped}
                name="contract-type"
                id={this.state.contractTypes.whitelistwithcap}
                onChange={(e) => this.contractTypeSelected(e)}
              />
              Capped

                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

          <Link to={{ pathname: '/2', query: { state: this.state } }}>Continue</Link>

    )}
}<commit_msg>Fix bug in loading step one<commit_after>import React from 'react'
import '../assets/stylesheets/application.css';
import { Link } from 'react-router-dom'
import { defaultState } from '../utils/constants'
import { setFlatFileContentToState } from '../utils/utils';
import { getOldState } from '../utils/utils'
import { StepNavigation } from './Common/StepNavigation'
import { NAVIGATION_STEPS } from '../utils/constants'
const { CROWDSALE_CONTRACT, TOKEN_SETUP, CROWDSALE_SETUP, PUBLISH, CROWDSALE_PAGE } = NAVIGATION_STEPS

export class stepOne extends React.Component {
  constructor(props) {
    super(props);
    let oldState = getOldState(props, defaultState)
    this.state = Object.assign({}, oldState)
  }

  getStandardCrowdsaleAssets (state) {
    const contractName = "CrowdsaleStandard";
    let srcC, binC
    setFlatFileContentToState("./contracts/" + contractName + "_flat.sol", (content) => srcC = content);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.bin", (_bin) => binC = _bin);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.abi", (_abi) => this.addContractsToState(srcC, binC, _abi, "crowdsale", state));

    const tokenName = "CrowdsaleStandardToken";
    let srcT, binT
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.sol", (content) => srcT = content);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.bin", (_bin) => binT = _bin);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.abi", (_abi) => this.addContractsToState(srcT, binT, _abi, "token", state));
  }

  getWhiteListWithCapCrowdsaleAssets (state) {
    const contractName = "CrowdsaleWhiteListWithCap";
    let srcC, binC
    setFlatFileContentToState("./contracts/" + contractName + "_flat.sol", (content) => srcC = content);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.bin", (_bin) => binC = _bin);
    setFlatFileContentToState("./contracts/" + contractName + "_flat.abi", (_abi) => this.addContractsToState(srcC, binC, _abi, "crowdsale", state));

    const tokenName = "CrowdsaleWhiteListWithCapToken";
    let srcT, binT
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.sol", (content) => srcT = content);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.bin", (_bin) => binT = _bin);
    setFlatFileContentToState("./contracts/" + tokenName + "_flat.abi", (_abi) => this.addContractsToState(srcT, binT, _abi, "token", state));

    const pricingStrategyName = "CrowdsaleWhiteListWithCapPricingStrategy";
    let srcP, binP
    setFlatFileContentToState("./contracts/" + pricingStrategyName + "_flat.sol", (content) => srcP = content);
    setFlatFileContentToState("./contracts/" + pricingStrategyName + "_flat.bin", (_bin) => binP = _bin);
    setFlatFileContentToState("./contracts/" + pricingStrategyName + "_flat.abi", (_abi) => this.addContractsToState(srcP, binP, _abi, "pricingStrategy", state));

    const tokenTransferProxyName = "TokenTransferProxy";
    let srcTTP, binTTP
    setFlatFileContentToState("./contracts/" + tokenTransferProxyName + "_flat.sol", (content) => srcTTP = content);
    setFlatFileContentToState("./contracts/" + tokenTransferProxyName + "_flat.bin", (_bin) => binTTP = _bin);
    setFlatFileContentToState("./contracts/" + tokenTransferProxyName + "_flat.abi", (_abi) => this.addContractsToState(srcTTP, binTTP, _abi, "tokenTransferProxy", state));

    const multiSigName = "MultiSig";
    let srcM, binM
    setFlatFileContentToState("./contracts/" + multiSigName + "_flat.sol", (content) => srcM = content);
    setFlatFileContentToState("./contracts/" + multiSigName + "_flat.bin", (_bin) => binM = _bin);
    setFlatFileContentToState("./contracts/" + multiSigName + "_flat.abi", (_abi) => this.addContractsToState(srcM, binM, _abi, "multisig", state));

    const finalizeAgentName = "FinalizeAgent";
    let srcF, binF
    setFlatFileContentToState("./contracts/" + finalizeAgentName + "_flat.sol", (content) => srcF = content);
    setFlatFileContentToState("./contracts/" + finalizeAgentName + "_flat.bin", (_bin) => binF = _bin);
    setFlatFileContentToState("./contracts/" + finalizeAgentName + "_flat.abi", (_abi) => this.addContractsToState(srcF, binF, _abi, "finalizeAgent", state));
  }

  componentDidMount() {
    let newState = { ...this.state }
    newState.contractType = this.state.contractTypes.standard
    this.getStandardCrowdsaleAssets(newState);
  }

  addContractsToState (src, bin, abi, contract, state) {
    //let newState = Object.assign({}, state)
    state.contracts[contract] = {
      src,
      bin,
      abi: JSON.parse(JSON.stringify(abi)),
      addr: (contract=="crowdsale" || contract=="pricingStrategy" || contract=="finalizeAgent")?[]:"",
      abiConstructor: (contract=="crowdsale" || contract=="pricingStrategy" || contract=="finalizeAgent")?[]:""
    }
    this.setState(state)
  }

  contractTypeSelected(e) {
    let newState = { ...this.state }
    newState.contractType = e.currentTarget.id;
    console.log(e.currentTarget.id);
    switch (e.currentTarget.id) {
      case this.state.contractTypes.standard: {
        this.getStandardCrowdsaleAssets(newState);
      } break;
      case this.state.contractTypes.whitelistwithcap: {
        this.getWhiteListWithCapCrowdsaleAssets(newState);
      } break;
      default:
        break;
    }
  }

  render() {
    return (

       <StepNavigation activeStep={CROWDSALE_CONTRACT}/>

Crowdsale Contract

              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
              in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

              <input
                type="radio"
                checked={this.state.contractType === this.state.contractTypes.standard}
                name="contract-type"
                id={this.state.contractTypes.standard}
                onChange={(e) => this.contractTypeSelected(e)}
              />
              Standard

                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

              <input
                type="radio"
                checked={this.state.contractType === this.state.contractTypes.whitelistwithcap}
                name="contract-type"
                id={this.state.contractTypes.whitelistwithcap}
                onChange={(e) => this.contractTypeSelected(e)}
              />
              Whitelist with Cap

                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

              <input
                type="radio"
                disabled
                checked={this.state.contractType === this.state.contractTypes.capped}
                name="contract-type"
                id={this.state.contractTypes.whitelistwithcap}
                onChange={(e) => this.contractTypeSelected(e)}
              />
              Capped

                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

          <Link to={{ pathname: '/2', query: { state: this.state } }}>Continue</Link>

    )}
}
<|endoftext|>


<commit_before>let valids = {
  required: {
    valid(value) {
      return value !== null && value !== undefined && new String(value).length > 0;
    },
    message: '不能为空'
  },
  maxLen(value, configValue) {
    let result = value !== null && value !== undefined && new String(value).length <= configValue;
    return result === true ? true : `文字长度不能大于${configValue}个字`;
  },
  minLen(value, configValue) {
    let result = value !== null && value !== undefined && new String(value).length >= configValue;
    return result === true ? true : `文字长度不能小于${configValue}个字`;
  },
  max(value, configValue) {
    let result = value !== null && value !== undefined && new Number(value) <= configValue;
    return result === true ? true : `不能大于${configValue}`;
  },
  min(value, configValue) {
    let result = value !== null && value !== undefined && new Number(value) >= configValue;
    return result === true ? true : `不能小于${configValue}`;
  }
};
module.exports = valids;
<commit_msg>fix: 字段超出长度文字修改<commit_after>let valids = {
  required: {
    valid(value) {
      return value !== null && value !== undefined && new String(value).length > 0;
    },
    message: '不能为空'
  },
  maxLen(value, configValue) {
    let result = value !== null && value !== undefined && new String(value).length <= configValue;
    return result === true ? true : `文字长度不能超过${configValue}个字`;
  },
  minLen(value, configValue) {
    let result = value !== null && value !== undefined && new String(value).length >= configValue;
    return result === true ? true : `文字长度不能少于${configValue}个字`;
  },
  max(value, configValue) {
    let result = value !== null && value !== undefined && new Number(value) <= configValue;
    return result === true ? true : `不能大于${configValue}`;
  },
  min(value, configValue) {
    let result = value !== null && value !== undefined && new Number(value) >= configValue;
    return result === true ? true : `不能小于${configValue}`;
  }
};
module.exports = valids;
<|endoftext|>


<commit_before>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2020 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Class = require('../../../utils/Class');
var GetFastValue = require('../../../utils/object/GetFastValue');
var MultiPipeline = require('./MultiPipeline');
var ShaderSourceFS = require('../shaders/Single-frag.js');
var ShaderSourceVS = require('../shaders/Single-vert.js');
var WebGLPipeline = require('../WebGLPipeline');

/**
 * @classdesc
 * The Single Pipeline is a special version of the Multi Pipeline that only ever
 * uses one texture, bound to texture unit zero. Although not as efficient as the
 * Multi Pipeline, it provides an easier way to create custom pipelines that only require
 * a single bound texture.
 *
 * Prior to Phaser v3.50 this pipeline didn't exist, but could be compared to the old `TextureTintPipeline`.
 *
 * The fragment shader it uses can be found in `shaders/src/Single.frag`.
 * The vertex shader it uses can be found in `shaders/src/Single.vert`.
 *
 * The default shader attributes for this pipeline are:
 *
 * `inPosition` (vec2, offset 0)
 * `inTexCoord` (vec2, offset 8)
 * `inTexId` (float, offset 16) - this value is always zero in the Single Pipeline
 * `inTintEffect` (float, offset 20)
 * `inTint` (vec4, offset 24, normalized)
 *
 * The default shader uniforms for this pipeline are:
 *
 * `uProjectionMatrix` (mat4)
 * `uMainSampler` (sampler2D)
 *
 * @class SinglePipeline
 * @extends Phaser.Renderer.WebGL.Pipelines.MultiPipeline
 * @memberof Phaser.Renderer.WebGL.Pipelines
 * @constructor
 * @since 3.50.0
 *
 * @param {Phaser.Types.Renderer.WebGL.WebGLPipelineConfig} config - The configuration options for this pipeline.
 */
var SinglePipeline = new Class({

    Extends: MultiPipeline,

    initialize:

    function SinglePipeline (config)
    {
        config.fragShader = GetFastValue(config, 'fragShader', ShaderSourceFS),
        config.vertShader = GetFastValue(config, 'vertShader', ShaderSourceVS),
        config.forceZero = true;

        MultiPipeline.call(this, config);
    },

    boot: function ()
    {
        WebGLPipeline.prototype.boot.call(this);

        this.set1i('uMainSampler', 0);
    }

});

module.exports = SinglePipeline;
<commit_msg>Correct sampler ID<commit_after>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2020 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Class = require('../../../utils/Class');
var GetFastValue = require('../../../utils/object/GetFastValue');
var MultiPipeline = require('./MultiPipeline');
var ShaderSourceFS = require('../shaders/Single-frag.js');
var ShaderSourceVS = require('../shaders/Single-vert.js');
var WebGLPipeline = require('../WebGLPipeline');

/**
 * @classdesc
 * The Single Pipeline is a special version of the Multi Pipeline that only ever
 * uses one texture, bound to texture unit zero. Although not as efficient as the
 * Multi Pipeline, it provides an easier way to create custom pipelines that only require
 * a single bound texture.
 *
 * Prior to Phaser v3.50 this pipeline didn't exist, but could be compared to the old `TextureTintPipeline`.
 *
 * The fragment shader it uses can be found in `shaders/src/Single.frag`.
 * The vertex shader it uses can be found in `shaders/src/Single.vert`.
 *
 * The default shader attributes for this pipeline are:
 *
 * `inPosition` (vec2, offset 0)
 * `inTexCoord` (vec2, offset 8)
 * `inTexId` (float, offset 16) - this value is always zero in the Single Pipeline
 * `inTintEffect` (float, offset 20)
 * `inTint` (vec4, offset 24, normalized)
 *
 * The default shader uniforms for this pipeline are:
 *
 * `uProjectionMatrix` (mat4)
 * `uMainSampler` (sampler2D)
 *
 * @class SinglePipeline
 * @extends Phaser.Renderer.WebGL.Pipelines.MultiPipeline
 * @memberof Phaser.Renderer.WebGL.Pipelines
 * @constructor
 * @since 3.50.0
 *
 * @param {Phaser.Types.Renderer.WebGL.WebGLPipelineConfig} config - The configuration options for this pipeline.
 */
var SinglePipeline = new Class({

    Extends: MultiPipeline,

    initialize:

    function SinglePipeline (config)
    {
        config.fragShader = GetFastValue(config, 'fragShader', ShaderSourceFS),
        config.vertShader = GetFastValue(config, 'vertShader', ShaderSourceVS),
        config.forceZero = true;

        MultiPipeline.call(this, config);
    },

    boot: function ()
    {
        WebGLPipeline.prototype.boot.call(this);

        this.set1i('uMainSampler', 1);
    }

});

module.exports = SinglePipeline;
<|endoftext|>