<commit_before>import React from 'react'
import { Marker } from 'react-native-maps'
import platform from '../../util/Platforms'
import { Image, View } from 'react-native'
import DefaultText from '../DefaultText'
import Images from '@Assets/images'

const getClusterDetails = (pointCount, selected) => {
  var image
  var fontSize
  var marginTop
  var marginLeft
  switch (true) {
    case (pointCount > 99):
      image = selected ? Images.selectedOver99 : Images.clusterOver99
      marginTop = 5
      marginLeft = 14.5
      fontSize = 13
      break;
    case (pointCount > 9):
      image = selected ? Images.selectedOver9 : Images.clusterOver9
      marginTop = 3
      marginLeft = 13
      fontSize = 13
      break;
    default:
      image = selected ? Images.selectedCluster : Images.cluster
      marginTop = 7/3
      marginLeft = 12.5
      fontSize = 12
      break;
  }
  return {image, marginTop, marginLeft, fontSize}
}

const MapMarker = ({ coordinate, selected, onPress, pointCount }) => {
  if (pointCount) {
    const {image, marginTop, marginLeft, fontSize} = getClusterDetails(pointCount, selected)
    return <Marker
        coordinate={coordinate}
        onPress={onPress}
        key={coordinate.latitude + '-' + coordinate.longitude + '-' + Date.now()}
        anchor={platform.isIOS() ? null : { x: 0.5, y: 0.5 }}
        image={image}>
        <View collapsible={false}>
          <DefaultText style={{ color: 'white', fontSize, marginTop, marginLeft }}>
            {pointCount}
          </DefaultText>
        </View>
    </Marker>
  }

  const marker = selected ? Images.selectedTrader : Images.marker
  return <Marker
      coordinate={coordinate}
      onPress={onPress}
      anchor={platform.isIOS() ? null : { x: 0.5, y: 0.5 }}
      image={marker}/>
}

export default MapMarker
<commit_msg>added comment to explain weird workaround<commit_after>import React from 'react'
import { Marker } from 'react-native-maps'
import platform from '../../util/Platforms'
import { Image, View } from 'react-native'
import DefaultText from '../DefaultText'
import Images from '@Assets/images'

const getClusterDetails = (pointCount, selected) => {
  var image
  var fontSize
  var marginTop
  var marginLeft
  switch (true) {
    case (pointCount > 99):
      image = selected ? Images.selectedOver99 : Images.clusterOver99
      marginTop = 5
      marginLeft = 14.5
      fontSize = 13
      break;
    case (pointCount > 9):
      image = selected ? Images.selectedOver9 : Images.clusterOver9
      marginTop = 3
      marginLeft = 13
      fontSize = 13
      break;
    default:
      image = selected ? Images.selectedCluster : Images.cluster
      marginTop = 7/3
      marginLeft = 12.5
      fontSize = 12
      break;
  }
  return {image, marginTop, marginLeft, fontSize}
}

const MapMarker = ({ coordinate, selected, onPress, pointCount }) => {
  if (pointCount) {
    const {image, marginTop, marginLeft, fontSize} = getClusterDetails(pointCount, selected)
    // added Date.now into marker key to force update marker (fixes cluster text disappearing)
    return <Marker
        coordinate={coordinate}
        onPress={onPress}
        key={coordinate.latitude + '-' + coordinate.longitude + '-' + Date.now()}
        anchor={platform.isIOS() ? null : { x: 0.5, y: 0.5 }}
        image={image}>
        <View collapsible={false}>
          <DefaultText style={{ color: 'white', fontSize, marginTop, marginLeft }}>
            {pointCount}
          </DefaultText>
        </View>
    </Marker>
  }

  const marker = selected ? Images.selectedTrader : Images.marker
  return <Marker
      coordinate={coordinate}
      onPress={onPress}
      anchor={platform.isIOS() ? null : { x: 0.5, y: 0.5 }}
      image={marker}/>
}

export default MapMarker
<|endoftext|>


<commit_before>import React from 'react';
import Autosuggest from 'react-autosuggest';
import domOnlyProps from 'form/domOnlyProps';
import fieldIsInvalid from 'form/fieldIsInvalid';
import Icon from 'components/Icon';
import styles from './autocomplete.scss';

const MIN_QUERY_LENGTH = 2;

const NULL_VALUE = {};

const Autocomplete = React.createClass({
  getClassname (element, error) {
    return [
      styles[element || 'input'],
      styles[error ? 'invalid' : 'valid']
    ].join(' ');
  },

  handleFetchRequest (e) {
    // We handle the query length validation here as we don‘t want to do it in
    // the (throttled) typeahead search. If we did, the first input after
    // MIN_QUERY_LENGTH would be delayed.
    if (!e.value) {
      return this.props.clearSuggestions();
    }

    const query = e.value.trim().toLowerCase();

    if (query.length >= MIN_QUERY_LENGTH) {
      return this.props.typeaheadSearch(
        this.props.endpoint, query, this.props.suggestionsLimit
      );
    }
  },

  handleBlur () {
    const savedValue = this.props.helper.value &&
      this.props.suggestionFormatter(this.props.helper.value.data);

    // If the saved value in the redux-form matches the displayed value in the
    // auto-suggest input, we know that the user hasn‘t changed his choice.
    // If it did, we must reset both values as they aren‘t valid anymore.
    if (savedValue !== this.props.value) {
      this.props.updateSuggestionInputValue('');
      this.props.helper.onChange(this.props.nullValue || NULL_VALUE);
    }

    this.props.helper.onBlur();
  },

  handleChange (newValue) {
    // We have to manually update the displayed value in the auto-suggest.
    // This has nothing to do with the actual redux-form value.
    this.props.updateSuggestionInputValue(newValue);

    // If there is no more value, then we know the user has deleted his choice,
    // and we can update the redux-form store.
    if (!newValue) {
      this.props.helper.onChange(this.props.nullValue || NULL_VALUE);
    }
  },

  handleSelection (e, suggestion) {
    // Disable form submitting when selecting option with ENTER
    e.preventDefault();

    // Update redux-form store manually to reflect the selection
    this.props.helper.onChange(this.props.getFormValue(suggestion.suggestion) || this.props.nullValue || NULL_VALUE);
  },

  render () {
    const inputClass = this.props.inputModifier || 'input';
    const suggestionStyles = this.props.inputModifier ? styles['suggestion-thin'] : styles['suggestion-regular'];

    return (

        <Autosuggest
          theme={{
            containerOpen: styles.open,
            input: this.getClassname(inputClass, fieldIsInvalid(this.props.helper)),
            suggestionsList: styles.list,
            suggestion: suggestionStyles,
            suggestionFocused: styles.focused
          }}
          id={this.props.name}

          suggestions={this.props.suggestions}
          renderSuggestion={this.props.suggestionFormatter}
          getSuggestionValue={this.props.suggestionFormatter}

          onSuggestionsFetchRequested={(e) => (this.handleFetchRequest(e))}
          onSuggestionsClearRequested={this.props.clearSuggestions}
          onSuggestionSelected={(e, suggestion) => (
            this.handleSelection(e, suggestion)
          )}

          inputProps={{
            name: this.props.name,
            id: this.props.name,
            required: this.props.html.required,
            placeholder: this.props.html.placeholder,
            autoComplete: this.props.html.autocomplete || 'off',

            ...domOnlyProps(this.props.helper),

            value: this.props.value,
            onBlur: () => (this.handleBlur()),
            onChange: (e, { newValue }) => (this.handleChange(newValue))
          }}
        />

        {this.props.icon &&

            <Icon
              id={this.props.icon.id}
              inline
              fill={this.props.icon.fill}
            />

        }

    );
  }
});

export default Autocomplete;
<commit_msg>Added better TAB behavior for autocomplete component<commit_after>import React from 'react';
import Autosuggest from 'react-autosuggest';
import domOnlyProps from 'form/domOnlyProps';
import fieldIsInvalid from 'form/fieldIsInvalid';
import Icon from 'components/Icon';
import styles from './autocomplete.scss';

const MIN_QUERY_LENGTH = 2;

const NULL_VALUE = {};

const Autocomplete = React.createClass({
  getClassname (element, error) {
    return [
      styles[element || 'input'],
      styles[error ? 'invalid' : 'valid']
    ].join(' ');
  },

  handleFetchRequest (e) {
    // We handle the query length validation here as we don‘t want to do it in
    // the (throttled) typeahead search. If we did, the first input after
    // MIN_QUERY_LENGTH would be delayed.
    if (!e.value) {
      return this.props.clearSuggestions();
    }

    const query = e.value.trim().toLowerCase();

    if (query.length >= MIN_QUERY_LENGTH) {
      return this.props.typeaheadSearch(
        this.props.endpoint, query, this.props.suggestionsLimit
      );
    }
  },

  handleBlur (e, focusedSuggestion) {
    // If the user exits the input with a suggestion selected (which should only
    // happen on TAB out), we select that value and update the redux-form store.
    if (focusedSuggestion) {
      this.props.updateSuggestionInputValue(
        this.props.suggestionFormatter(focusedSuggestion)
      );

      this.props.helper.onChange(
        this.props.getFormValue(focusedSuggestion) ||
        this.props.nullValue || NULL_VALUE
      );
    } else {
      const savedValue = this.props.helper.value &&
        this.props.suggestionFormatter(this.props.helper.value.data);

      // If the saved value in the redux-form matches the displayed value in the
      // auto-suggest input, we know that the user hasn‘t changed his choice.
      // If it did, we must reset both values as they aren‘t valid anymore.
      if (savedValue !== this.props.value) {
        this.props.updateSuggestionInputValue('');
        this.props.helper.onChange(this.props.nullValue || NULL_VALUE);
      }
    }

    this.props.helper.onBlur();
  },

  handleChange (newValue) {
    // We have to manually update the displayed value in the auto-suggest.
    // This has nothing to do with the actual redux-form value.
    this.props.updateSuggestionInputValue(newValue);

    // If there is no more value, then we know the user has deleted his choice,
    // and we can update the redux-form store.
    if (!newValue) {
      this.props.helper.onChange(this.props.nullValue || NULL_VALUE);
    }
  },

  handleSelection (e, suggestion) {
    // Disable form submitting when selecting option with ENTER
    e.preventDefault();

    // Update redux-form store manually to reflect the selection
    this.props.helper.onChange(
      this.props.getFormValue(suggestion.suggestion) ||
      this.props.nullValue || NULL_VALUE
    );
  },

  render () {
    const inputClass = this.props.inputModifier || 'input';
    const suggestionStyles = this.props.inputModifier ? styles['suggestion-thin'] : styles['suggestion-regular'];

    return (

        <Autosuggest
          theme={{
            containerOpen: styles.open,
            input: this.getClassname(inputClass, fieldIsInvalid(this.props.helper)),
            suggestionsList: styles.list,
            suggestion: suggestionStyles,
            suggestionFocused: styles.focused
          }}
          id={this.props.name}

          suggestions={this.props.suggestions}
          renderSuggestion={this.props.suggestionFormatter}
          getSuggestionValue={this.props.suggestionFormatter}

          onSuggestionsFetchRequested={(e) => (this.handleFetchRequest(e))}
          onSuggestionsClearRequested={this.props.clearSuggestions}
          onSuggestionSelected={(e, suggestion) => (
            this.handleSelection(e, suggestion)
          )}

          inputProps={{
            name: this.props.name,
            id: this.props.name,
            required: this.props.html.required,
            placeholder: this.props.html.placeholder,
            autoComplete: this.props.html.autocomplete || 'off',

            ...domOnlyProps(this.props.helper),

            value: this.props.value,
            onBlur: (e, { focusedSuggestion }) =>
              (this.handleBlur(e, focusedSuggestion)),
            onChange: (e, { newValue }) =>
              (this.handleChange(newValue))
          }}
        />

        {this.props.icon &&

            <Icon
              id={this.props.icon.id}
              inline
              fill={this.props.icon.fill}
            />

        }

    );
  }
});

export default Autocomplete;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classNames from 'classnames';

const propTypes = {
  tagName: PropTypes.string,
  onClick: PropTypes.func.isRequired,
  onFocus: PropTypes.func,
  onBlur: PropTypes.func,
  className: PropTypes.string
};

const defaultProps = {
  tagName: 'div'
};

export default class ClickableComponent extends Component {
  constructor(props, context) {
    super(props, context);

    this.handleClick = this.handleClick.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
    this.handleKeypress = this.handleKeypress.bind(this);
  }

  handleKeypress(event) {
    // Support Space (32) or Enter (13) key operation to fire a click event
    if (event.which === 32 || event.which === 13) {
      event.preventDefault();
      this.handleClick(event);
    }
  }

  handleClick(event) {
    const { onClick } = this.props;
    onClick(event);
  }

  handleFocus(e) {
    document.addEventListener('keydown', this.handleKeypress);
    if (this.props.onFocus) {
      this.props.onFocus(e);
    }
  }

  handleBlur(e) {
    document.removeEventListener('keydown', this.handleKeypress);
    if (this.props.onBlur) {
      this.props.onBlur(e);
    }
  }

  render() {
    const Tag = this.props.tagName;
    const props = { ...this.props };
    delete props.tagName;
    delete props.className;
    return (
      <Tag
        className={classNames(this.props.className)}
        role="button"
        tabIndex="0"
        onClick={this.handleClick}
        onFocus={this.handleFocus}
        onBlur={this.handleBlur}
        {...props}
      />
    );
  }
}

ClickableComponent.propTypes = propTypes;
ClickableComponent.defaultProps = defaultProps;
ClickableComponent.displayName = 'ClickableComponent';
<commit_msg>added componentWillUnmount to click component<commit_after>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classNames from 'classnames';

const propTypes = {
  tagName: PropTypes.string,
  onClick: PropTypes.func.isRequired,
  onFocus: PropTypes.func,
  onBlur: PropTypes.func,
  className: PropTypes.string
};

const defaultProps = {
  tagName: 'div'
};

export default class ClickableComponent extends Component {
  constructor(props, context) {
    super(props, context);

    this.handleClick = this.handleClick.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
    this.handleKeypress = this.handleKeypress.bind(this);
  }

  handleKeypress(event) {
    // Support Space (32) or Enter (13) key operation to fire a click event
    if (event.which === 32 || event.which === 13) {
      event.preventDefault();
      this.handleClick(event);
    }
  }

  handleClick(event) {
    const { onClick } = this.props;
    onClick(event);
  }

  handleFocus(e) {
    document.addEventListener('keydown', this.handleKeypress);
    if (this.props.onFocus) {
      this.props.onFocus(e);
    }
  }

  handleBlur(e) {
    document.removeEventListener('keydown', this.handleKeypress);
    if (this.props.onBlur) {
      this.props.onBlur(e);
    }
  }

  componentWillUnmount(e) {
    this.handleBlur(e)
  }

  render() {
    const Tag = this.props.tagName;
    const props = { ...this.props };
    delete props.tagName;
    delete props.className;
    return (
      <Tag
        className={classNames(this.props.className)}
        role="button"
        tabIndex="0"
        onClick={this.handleClick}
        onFocus={this.handleFocus}
        onBlur={this.handleBlur}
        {...props}
      />
    );
  }
}

ClickableComponent.propTypes = propTypes;
ClickableComponent.defaultProps = defaultProps;
ClickableComponent.displayName = 'ClickableComponent';
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { push } from "redux-router"
import DataTables from 'material-ui-datatables'
import AbstractGraph from "../AbstractGraph"
import columnAccessor from "../../../utils/columnAccessor"
import CopyToClipboard from 'react-copy-to-clipboard'
import {Tooltip} from 'react-lightweight-tooltip'
import * as d3 from 'd3'

import tooltipStyle from './tooltipStyle'
import "./style.css"
import style from './style'
import {properties} from "./default.config"

import SearchBar from "../../SearchBar"

import {
    Actions as VFSActions,
} from '../../../features/redux/actions'

class Table extends AbstractGraph {

    constructor(props, context) {
        super(props, properties)

        this.handleSortOrderChange   = this.handleSortOrderChange.bind(this)
        this.handlePreviousPageClick = this.handlePreviousPageClick.bind(this)
        this.handleNextPageClick     = this.handleNextPageClick.bind(this)
        this.handleClick             = this.handleClick.bind(this)
        this.handleSearch            = this.handleSearch.bind(this)
        this.handleRowSelection      = this.handleRowSelection.bind(this)
        this.handleContextMenu       = this.handleContextMenu.bind(this)

        /**
        */
        this.currentPage = 1
        this.filterData = false
        this.selectedRows = {}
        this.htmlData = {}
        this.state = {
            selected: [],
            data: [],
            fontSize: style.defaultFontsize,
            contextMenu: null,
        }
    }

    componentWillMount() {
        this.initiate();
    }

    componentWillReceiveProps(nextProps) {
        if(this.props !== nextProps) {
            this.initiate();
        }
    }

    componentDidUpdate() {
        this.checkFontsize();
        const { contextMenu } = this.state;
        if (contextMenu) {
            this.openContextMenu();
        }
    }

    initiate() {
        let columns = this.getColumns();

        if (!columns)
            return;

        /*
         * On data change, resetting the paging and filtered data to 1 and false respectively.
         */
        this.resetFilters();

        this.filterData = this.props.data;
        this.setHeaderData(columns);
        this.updateData();
    }

    decrementFontSize() {
        this.setState({
            fontSize: this.state.fontSize - 1
        })
    }

    checkFontsize() {
        if(this.container.querySelector('table').clientWidth > this.container.clientWidth) {
            this.decrementFontSize();
        }
    }

    resetFilters() {
        this.currentPage = 1;
        this.selectedRows = {};
    }

    handleSearch(data) {
        this.resetFilters();

        this.filterData = data;
        this.updateData();
    }

    updateData() {
        const {
            limit,
        } = this.getConfiguredProperties();

        let offset = limit * (this.currentPage - 1);

        this.setState({
            data : this.filterData.slice(offset, offset + limit),
            selected: this.selectedRows[this.currentPage] ? this.selectedRows[this.currentPage]: []
        });
    }

    getColumns() {
        const {
            data,
            configuration,
        } = this.props;

        if (!data || !data.length)
            return;

        return configuration.data.columns;
    }

    getAccessor(columns) {
        return columns.map(columnAccessor);
    }

    getTooltipAccessor(columns) {
        return columns.map(column => {
            return column.tooltip ? columnAccessor(column.tooltip) : () => {}
        });
    }

    setHeaderData(columns) {
        this.headerData = columns.map(({column, label}, i) => ({
            key: column,
            label: label || column,
            sortable: true,
            columnText: label || column,
            columField: column,
            type:"text",
            style: {
              textIndent: '2px'
            }
           }
        ));
    }

    getHeaderData() {
        return this.headerData;
    }

    getTableData(columns) {
        const {
            highlight,
            highlightColor
        } = this.getConfiguredProperties();
        const accessors = this.getAccessor(columns);
        const tooltipAccessor = this.getTooltipAccessor(columns);

        return this.state.data.map((d, j) => {

            let data = {},
                highlighter = false;

            accessors.forEach((accessor, i) => {
                let originalData = accessor(d),
                    columnData   = originalData

                if(columns[i].tooltip) {
                    let fullText = tooltipAccessor[i](d, true);
                    columnData =

                            <Tooltip key={`tooltip_${j}_${i}`}
                              content={
                                [
                                  fullText,
                                  <CopyToClipboard text={fullText}><button title="copy" className="btn btn-link btn-xs fa fa-copy pointer text-white"></button></CopyToClipboard>,
                                ]
                              }
                              styles={tooltipStyle}>

                                 {columnData}

                            </Tooltip>

                }

                if(highlight && highlight.includes(columns[i].column) && originalData) {
                    highlighter = true
                }

                data[columns[i].column] = columnData;
            });

            if(highlighter)
               Object.keys(data).map( key => {
                return data[key] =
{data[key]}

            })

            return data
        })
    }

    handleSortOrderChange(column, order) {
        const keys = column.split(".");
        const value = (d) => keys.reduce((d, key) => d[key], d);

        this.filterData = this.filterData.sort(
          (a, b) => {
            return order === 'desc' ? value(b) > value(a) : value(a) > value(b);
          }
        );

        /**
         * Resetting the paging due to sorting
         */
        this.resetFilters();
        this.updateData();
    }

    handlePreviousPageClick() {
        --this.currentPage;
        this.updateData();
    }

    handleNextPageClick() {
        ++this.currentPage;
        this.updateData();
    }

    handleClick(key) {
        if(this.props.onMarkClick && this.state.data[key])
           this.props.onMarkClick(this.state.data[key]);
    }

    handleRowSelection(selectedRows) {
        const {
            multiSelectable
        } = this.getConfiguredProperties();

        if(!multiSelectable) {
            this.handleClick(...selectedRows)
        }
        this.selectedRows[this.currentPage] = selectedRows.slice();
        this.setState({
            selected: this.selectedRows[this.currentPage]
        })
        const { selectRow, location } = this.props;
        if (selectRow) {
            const selectedRows = this.getSelectedRows();
            const flow = selectedRows ? selectedRows[0] : {};
            selectRow(this.props.configuration.id, flow, location.query, location.pathname);
        }

    }

    handleContextMenu(event) {
        const {
            menu
        } = this.getConfiguredProperties();

        if (!menu) {
            return false;
        }
        event.preventDefault()
        const { clientX: x, clientY: y } = event;
        this.setState({ contextMenu: { x, y } });
        return true;
    }

    handleCloseContextMenu = () => {
        this.setState({ contextMenu: null });
        this.closeContextMenu();
    }

    closeContextMenu = () => {
        document.body.removeEventListener('click', this.handleCloseContextMenu);
        const node = document.getElementById('contextMenu');
        if (node) node.remove();
    }

    openContextMenu = () => {
        const { contextMenu: { x, y } } = this.state;
        const {
            menu
        } = this.getConfiguredProperties();

        this.closeContextMenu();
        document.body.addEventListener('click', this.handleCloseContextMenu);

        const node = document.createElement('ul');
        node.classList.add('contextMenu');
        node.id = 'contextMenu';
        node.style = `top: ${y}px; left: ${x}px; z-index: 100000;`;

        const { goTo, location: { query }, configuration: { id } } = this.props;
        query.id = id;

        menu.forEach((item) => {
            const { text, rootpath, params } = item;
            const pathname = `${process.env.PUBLIC_URL}/${rootpath}`
            const li = document.createElement('li');
            li.textContent = text;
            const queryParams = (params && Object.getOwnPropertyNames(params).length > 0) ?
                    Object.assign({}, query, params) : Object.assign({}, query);
            li.onclick = (e) => {
                // dispatch a push to the menu link
                goTo(pathname, queryParams);
            };
            node.append(li);
        });
        document.body.append(node);
    }

    getSelectedRows() {
        const {
            limit
        } = this.getConfiguredProperties();

        let selected = [];
        for(let page in this.selectedRows) {
            if(this.selectedRows.hasOwnProperty(page)) {
                this.selectedRows[page].forEach((index) => {
                    selected.push(this.filterData[(page - 1) * limit + index])
                })
            }
        }
        return selected;
    }

    renderSearchBarIfNeeded(showHeader) {
        const {
            searchBar
        } = this.getConfiguredProperties();

        if(searchBar === false || !showHeader)
           return;

        return (
          <SearchBar
            data={this.props.data}
            options={this.getHeaderData()}
            handleSearch={this.handleSearch}
            columns={this.getColumns()}
          />
        );
    }

    removeHighlighter(data) {
        const {
            highlight
        } = this.getConfiguredProperties();

        if(highlight) {
            this.state.selected.map( (key) => {
                if(highlight && data[key]) {
                    for (let i in data[key]) {
                        if (data[key].hasOwnProperty(i)) {
                            if(data[key][i].props.style)
                                data[key][i].props.style.background = ''
                        }
                    }
                }
            })
        }
        return data
    }

    render() {
        const {
            height,
            data
        } = this.props;

        const {
            limit,
            selectable,
            multiSelectable,
            showCheckboxes,
            hidePagination
        } = this.getConfiguredProperties();

        let tableData = this.getTableData(this.getColumns())

        // overrite style of highlighted selected row
        tableData = this.removeHighlighter(tableData)

        if(!tableData) {
            return "
No Data
";
        }

        let showHeader = (data.length <= limit && hidePagination !== false) ? false : true,
          tableHeight  = showHeader ? `${height - 100}px` : height

        return (

 { this.container = input; }}
                onContextMenu={this.handleContextMenu}
                >
                {this.renderSearchBarIfNeeded(showHeader)}
                <DataTables
                    columns={this.getHeaderData()}
                    data={tableData}
                    showHeaderToolbar={false}
                    showFooterToolbar={showHeader}
                    selectable={selectable}
                    multiSelectable={multiSelectable}
                    selectedRows={this.state.selected}
                    showCheckboxes={showCheckboxes}
                    showRowSizeControls={false}
                    onNextPageClick={this.handleNextPageClick}
                    onPreviousPageClick={this.handlePreviousPageClick}
                    onSortOrderChange={this.handleSortOrderChange}
                    onRowSelection={this.handleRowSelection}
                    page={this.currentPage}
                    count={this.filterData.length}
                    onCellClick={this.handleClick}
                    rowSize={limit}
                    tableStyle={style.table}
                    tableHeaderColumnStyle={Object.assign({}, style.headerColumn, {fontSize: this.state.fontSize})}
                    tableRowStyle={style.row}
                    tableRowColumnStyle={Object.assign({}, style.rowColumn, {fontSize: this.state.fontSize})}
                    tableBodyStyle={Object.assign({}, style.body, {height: tableHeight})}
                    footerToolbarStyle={style.footerToolbar}
                />

        );
    }
}

Table.propTypes = {
  configuration: React.PropTypes.object,
  response: React.PropTypes.object
};

const mapStateToProps = (state) => {
    return {
        location: state.router.location
    }
}

const actionCreators = (dispatch) => ({
    selectRow: (vssID, row, currentQueryParams, currentPath) => dispatch(VFSActions.selectRow(vssID, row, currentQueryParams, currentPath)),
    goTo: (link, queryParams) => {
        dispatch(push({pathname: link, query: queryParams}));
    }
});

export default connect ( mapStateToProps, actionCreators) (Table);
<commit_msg>Fix issue of hiding search bar<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { push } from "redux-router"
import DataTables from 'material-ui-datatables'
import AbstractGraph from "../AbstractGraph"
import columnAccessor from "../../../utils/columnAccessor"
import CopyToClipboard from 'react-copy-to-clipboard'
import {Tooltip} from 'react-lightweight-tooltip'
import * as d3 from 'd3'

import tooltipStyle from './tooltipStyle'
import "./style.css"
import style from './style'
import {properties} from "./default.config"

import SearchBar from "../../SearchBar"

import {
    Actions as VFSActions,
} from '../../../features/redux/actions'

class Table extends AbstractGraph {

    constructor(props, context) {
        super(props, properties)

        this.handleSortOrderChange   = this.handleSortOrderChange.bind(this)
        this.handlePreviousPageClick = this.handlePreviousPageClick.bind(this)
        this.handleNextPageClick     = this.handleNextPageClick.bind(this)
        this.handleClick             = this.handleClick.bind(this)
        this.handleSearch            = this.handleSearch.bind(this)
        this.handleRowSelection      = this.handleRowSelection.bind(this)
        this.handleContextMenu       = this.handleContextMenu.bind(this)

        /**
        */
        this.currentPage = 1
        this.filterData = false
        this.selectedRows = {}
        this.htmlData = {}
        this.state = {
            selected: [],
            data: [],
            fontSize: style.defaultFontsize,
            contextMenu: null,
        }
    }

    componentWillMount() {
        this.initiate();
    }

    componentWillReceiveProps(nextProps) {
        if(this.props !== nextProps) {
            this.initiate();
        }
    }

    componentDidUpdate() {
        this.checkFontsize();
        const { contextMenu } = this.state;
        if (contextMenu) {
            this.openContextMenu();
        }
    }

    initiate() {
        let columns = this.getColumns();

        if (!columns)
            return;

        /*
         * On data change, resetting the paging and filtered data to 1 and false respectively.
         */
        this.resetFilters();

        this.filterData = this.props.data;
        this.setHeaderData(columns);
        this.updateData();
    }

    decrementFontSize() {
        this.setState({
            fontSize: this.state.fontSize - 1
        })
    }

    checkFontsize() {
        if(this.container.querySelector('table').clientWidth > this.container.clientWidth) {
            this.decrementFontSize();
        }
    }

    resetFilters() {
        this.currentPage = 1;
        this.selectedRows = {};
    }

    handleSearch(data) {
        this.resetFilters();

        this.filterData = data;
        this.updateData();
    }

    updateData() {
        const {
            limit,
        } = this.getConfiguredProperties();

        let offset = limit * (this.currentPage - 1);

        this.setState({
            data : this.filterData.slice(offset, offset + limit),
            selected: this.selectedRows[this.currentPage] ? this.selectedRows[this.currentPage]: []
        });
    }

    getColumns() {
        const {
            data,
            configuration,
        } = this.props;

        if (!data || !data.length)
            return;

        return configuration.data.columns;
    }

    getAccessor(columns) {
        return columns.map(columnAccessor);
    }

    getTooltipAccessor(columns) {
        return columns.map(column => {
            return column.tooltip ? columnAccessor(column.tooltip) : () => {}
        });
    }

    setHeaderData(columns) {
        this.headerData = columns.map(({column, label}, i) => ({
            key: column,
            label: label || column,
            sortable: true,
            columnText: label || column,
            columField: column,
            type:"text",
            style: {
              textIndent: '2px'
            }
           }
        ));
    }

    getHeaderData() {
        return this.headerData;
    }

    getTableData(columns) {
        const {
            highlight,
            highlightColor
        } = this.getConfiguredProperties();
        const accessors = this.getAccessor(columns);
        const tooltipAccessor = this.getTooltipAccessor(columns);

        return this.state.data.map((d, j) => {

            let data = {},
                highlighter = false;

            accessors.forEach((accessor, i) => {
                let originalData = accessor(d),
                    columnData   = originalData

                if(columns[i].tooltip) {
                    let fullText = tooltipAccessor[i](d, true);
                    columnData =

                            <Tooltip key={`tooltip_${j}_${i}`}
                              content={
                                [
                                  fullText,
                                  <CopyToClipboard text={fullText ? fullText : ''}><button title="copy" className="btn btn-link btn-xs fa fa-copy pointer text-white"></button></CopyToClipboard>,
                                ]
                              }
                              styles={tooltipStyle}>

                                 {columnData}

                            </Tooltip>

                }

                if(highlight && highlight.includes(columns[i].column) && originalData) {
                    highlighter = true
                }

                data[columns[i].column] = columnData;
            });

            if(highlighter)
               Object.keys(data).map( key => {
                return data[key] =
{data[key]}

            })

            return data
        })
    }

    handleSortOrderChange(column, order) {
        const keys = column.split(".");
        const value = (d) => keys.reduce((d, key) => d[key], d);

        this.filterData = this.filterData.sort(
          (a, b) => {
            return order === 'desc' ? value(b) > value(a) : value(a) > value(b);
          }
        );

        /**
         * Resetting the paging due to sorting
         */
        this.resetFilters();
        this.updateData();
    }

    handlePreviousPageClick() {
        --this.currentPage;
        this.updateData();
    }

    handleNextPageClick() {
        ++this.currentPage;
        this.updateData();
    }

    handleClick(key) {
        if(this.props.onMarkClick && this.state.data[key])
           this.props.onMarkClick(this.state.data[key]);
    }

    handleRowSelection(selectedRows) {
        const {
            multiSelectable
        } = this.getConfiguredProperties();

        if(!multiSelectable) {
            this.handleClick(...selectedRows)
        }
        this.selectedRows[this.currentPage] = selectedRows.slice();
        this.setState({
            selected: this.selectedRows[this.currentPage]
        })
        const { selectRow, location } = this.props;
        if (selectRow) {
            const selectedRows = this.getSelectedRows();
            const flow = selectedRows ? selectedRows[0] : {};
            selectRow(this.props.configuration.id, flow, location.query, location.pathname);
        }

    }

    handleContextMenu(event) {
        const {
            menu
        } = this.getConfiguredProperties();

        if (!menu) {
            return false;
        }
        event.preventDefault()
        const { clientX: x, clientY: y } = event;
        this.setState({ contextMenu: { x, y } });
        return true;
    }

    handleCloseContextMenu = () => {
        this.setState({ contextMenu: null });
        this.closeContextMenu();
    }

    closeContextMenu = () => {
        document.body.removeEventListener('click', this.handleCloseContextMenu);
        const node = document.getElementById('contextMenu');
        if (node) node.remove();
    }

    openContextMenu = () => {
        const { contextMenu: { x, y } } = this.state;
        const {
            menu
        } = this.getConfiguredProperties();

        this.closeContextMenu();
        document.body.addEventListener('click', this.handleCloseContextMenu);

        const node = document.createElement('ul');
        node.classList.add('contextMenu');
        node.id = 'contextMenu';
        node.style = `top: ${y}px; left: ${x}px; z-index: 100000;`;

        const { goTo, location: { query }, configuration: { id } } = this.props;
        query.id = id;

        menu.forEach((item) => {
            const { text, rootpath, params } = item;
            const pathname = `${process.env.PUBLIC_URL}/${rootpath}`
            const li = document.createElement('li');
            li.textContent = text;
            const queryParams = (params && Object.getOwnPropertyNames(params).length > 0) ?
                    Object.assign({}, query, params) : Object.assign({}, query);
            li.onclick = (e) => {
                // dispatch a push to the menu link
                goTo(pathname, queryParams);
            };
            node.append(li);
        });
        document.body.append(node);
    }

    getSelectedRows() {
        const {
            limit
        } = this.getConfiguredProperties();

        let selected = [];
        for(let page in this.selectedRows) {
            if(this.selectedRows.hasOwnProperty(page)) {
                this.selectedRows[page].forEach((index) => {
                    selected.push(this.filterData[(page - 1) * limit + index])
                })
            }
        }
        return selected;
    }

    renderSearchBarIfNeeded(showHeader) {
        const {
            searchBar
        } = this.getConfiguredProperties();

        if(searchBar === false || !showHeader)
           return;

        return (
          <SearchBar
            data={this.props.data}
            options={this.getHeaderData()}
            handleSearch={this.handleSearch}
            columns={this.getColumns()}
          />
        );
    }

    removeHighlighter(data) {
        const {
            highlight
        } = this.getConfiguredProperties();

        if(highlight) {
            this.state.selected.map( (key) => {
                if(highlight && data[key]) {
                    for (let i in data[key]) {
                        if (data[key].hasOwnProperty(i)) {
                            if(data[key][i].props.style)
                                data[key][i].props.style.background = ''
                        }
                    }
                }
            })
        }
        return data
    }

    render() {
        const {
            height,
            data
        } = this.props;

        const {
            limit,
            selectable,
            multiSelectable,
            showCheckboxes,
            hidePagination
        } = this.getConfiguredProperties();

        let tableData = this.getTableData(this.getColumns())

        // overrite style of highlighted selected row
        tableData = this.removeHighlighter(tableData)

        if(!tableData) {
            return "
No Data
";
        }

        let showHeader = (data.length <= limit && hidePagination !== false) ? false : true,
          tableHeight  = showHeader ? `${height - 100}px` : height

        return (

 { this.container = input; }}
                onContextMenu={this.handleContextMenu}
                >
                {this.renderSearchBarIfNeeded(showHeader)}
                <DataTables
                    columns={this.getHeaderData()}
                    data={tableData}
                    showHeaderToolbar={false}
                    showFooterToolbar={showHeader}
                    selectable={selectable}
                    multiSelectable={multiSelectable}
                    selectedRows={this.state.selected}
                    showCheckboxes={showCheckboxes}
                    showRowSizeControls={false}
                    onNextPageClick={this.handleNextPageClick}
                    onPreviousPageClick={this.handlePreviousPageClick}
                    onSortOrderChange={this.handleSortOrderChange}
                    onRowSelection={this.handleRowSelection}
                    page={this.currentPage}
                    count={this.filterData.length}
                    onCellClick={this.handleClick}
                    rowSize={limit}
                    tableStyle={style.table}
                    tableHeaderColumnStyle={Object.assign({}, style.headerColumn, {fontSize: this.state.fontSize})}
                    tableRowStyle={style.row}
                    tableRowColumnStyle={Object.assign({}, style.rowColumn, {fontSize: this.state.fontSize})}
                    tableBodyStyle={Object.assign({}, style.body, {height: tableHeight})}
                    footerToolbarStyle={style.footerToolbar}
                />

        );
    }
}

Table.propTypes = {
  configuration: React.PropTypes.object,
  response: React.PropTypes.object
};

const mapStateToProps = (state) => {
    return {
        location: state.router.location
    }
}

const actionCreators = (dispatch) => ({
    selectRow: (vssID, row, currentQueryParams, currentPath) => dispatch(VFSActions.selectRow(vssID, row, currentQueryParams, currentPath)),
    goTo: (link, queryParams) => {
        dispatch(push({pathname: link, query: queryParams}));
    }
});

export default connect ( mapStateToProps, actionCreators) (Table);
<|endoftext|>


<commit_before>/**
 * Created by Yuicon on 2017/6/30.
 */
import React, {Component} from 'react';
import {Form, Icon, Input, Button, Modal, message} from 'antd';

const FormItem = Form.Item;
const createForm = Form.create;

@createForm()
export default class LoginDialog extends Component {

  constructor(props) {
    super(props);
    this.state = {
      loading: false,
    };
  }

  componentWillReceiveProps(nextProps) {
    console.log(nextProps);
    if (nextProps.auth.get('token') && this.props.visible) {
      this.props.onClose();
      message.success('登陆成功');
    } else if (nextProps.auth.get('error') && this.props.visible) {
      message.error(nextProps.auth.get('error'));
    }
    this.setState({loading: false});
  }

  handleSubmit = (e) => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.props.loginActions(values);
        this.setState({loading: true});
      }
    });
  };

  handleResetPassWord = () => {

  };

  handleRegister = () => {
    this.props.onRedirect();
  };

  render() {

    const {getFieldDecorator} = this.props.form;

    return (
      <Modal
        title="登录"
        width="26.5rem"
        visible={ this.props.visible }
        onCancel={ this.props.onClose }
        footer={null}
      >
        <Form onSubmit={this.handleSubmit} className="login-form">
          <FormItem>
            {getFieldDecorator('account', {
              rules: [{required: true, message: '请输入邮箱'}],
            })(
              <Input prefix={<Icon type="user" style={{fontSize: 13}}/>} placeholder="邮箱"/>
            )}
          </FormItem>
          <FormItem>
            {getFieldDecorator('password', {
              rules: [{required: true, message: '请输入密码'}],
            })(
              <Input prefix={<Icon type="lock" style={{fontSize: 13}}/>} type="password" placeholder="密码"/>
            )}
          </FormItem>
          <Form.Item>
            <Button style={{width: '100%'}} type="primary" onClick={this.handleSubmit} loading={this.state.loading}>
              登录
            </Button>
          </Form.Item>
          <Button type="text" onClick={this.handleRegister}>
            没有帐号？注册
          </Button>
          <Button style={{float: 'right'}} type="text" onClick={this.handleResetPassWord}>
            忘记密码
          </Button>
        </Form>
      </Modal>
    )
  }
}
<commit_msg>fix:登陆输入邮箱没有验证<commit_after>/**
 * Created by Yuicon on 2017/6/30.
 */
import React, {Component} from 'react';
import {Form, Icon, Input, Button, Modal, message} from 'antd';

const FormItem = Form.Item;
const createForm = Form.create;

@createForm()
export default class LoginDialog extends Component {

  constructor(props) {
    super(props);
    this.state = {
      loading: false,
    };
  }

  componentWillReceiveProps(nextProps) {
    console.log(nextProps);
    if (nextProps.auth.get('token') && this.props.visible) {
      this.props.onClose();
      message.success('登陆成功');
    } else if (nextProps.auth.get('error') && this.props.visible) {
      message.error(nextProps.auth.get('error'));
    }
    this.setState({loading: false});
  }

  handleSubmit = (e) => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.props.loginActions(values);
        this.setState({loading: true});
      }
    });
  };

  handleResetPassWord = () => {

  };

  handleRegister = () => {
    this.props.onRedirect();
  };

  render() {

    const {getFieldDecorator} = this.props.form;

    return (
      <Modal
        title="登录"
        width="26.5rem"
        visible={ this.props.visible }
        onCancel={ this.props.onClose }
        footer={null}
      >
        <Form onSubmit={this.handleSubmit} className="login-form">
          <FormItem>
            {getFieldDecorator('account', {
              rules: [{required: true, message: '请输入邮箱', type: 'email'}],
            })(
              <Input prefix={<Icon type="user" style={{fontSize: 13}}/>} placeholder="邮箱"/>
            )}
          </FormItem>
          <FormItem>
            {getFieldDecorator('password', {
              rules: [{required: true, message: '请输入密码'}],
            })(
              <Input prefix={<Icon type="lock" style={{fontSize: 13}}/>} type="password" placeholder="密码"/>
            )}
          </FormItem>
          <Form.Item>
            <Button style={{width: '100%'}} type="primary" onClick={this.handleSubmit} loading={this.state.loading}>
              登录
            </Button>
          </Form.Item>
          <Button type="text" onClick={this.handleRegister}>
            没有帐号？注册
          </Button>
          <Button style={{float: 'right'}} type="text" onClick={this.handleResetPassWord}>
            忘记密码
          </Button>
        </Form>
      </Modal>
    )
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import WebPullToRefresh from '../pull-to-refresh/wptr.1.1';

export default class ReactPullToRefresh extends Component {

  constructor(props) {
    super(props);
    this.state = {
      initialized: false
    };
    this.handleRefresh = this.handleRefresh.bind(this);
  }

  handleRefresh() {
    return new Promise((resolve, reject) => {
      this.props.onRefresh(resolve, reject);
    });
  }

  init() {
    if (!this.state.initialized) {
      WebPullToRefresh().init({
        contentEl: this.refs.refresh,
        ptrEl: this.refs.ptr,
        bodyEl: this.refs.body,
        distanceToRefresh: this.props.distanceToRefresh || undefined,
        loadingFunction: this.handleRefresh,
        resistance: this.props.resistance || undefined,
        hammerOptions: this.props.hammerOptions || undefined
      });
      this.setState({
        initialized: true
      });
    }
  }

  componentDidMount() {
    if (!this.props.disabled) {
      this.init();
    }
  }

  componentDidUpdate() {
    if (!this.props.disabled) {
      this.init();
    }
  }

  render() {
    const {
      children,
      disabled,
      distanceToRefresh,
      hammerOptions,
      icon,
      loading,
      onRefresh,
      resistance,
      ...rest
    } = this.props;

    if (disabled) {
      return (

          {children}

      );
    }

    return (

          {icon || }
          {loading ||

}

          {children}

    );
  }
}

ReactPullToRefresh.propTypes = {
  onRefresh: PropTypes.func.isRequired,
  icon: PropTypes.element,
  loading: PropTypes.element,
  disabled: PropTypes.bool,
  className: PropTypes.string,
  style: PropTypes.object,
  distanceToRefresh: PropTypes.number,
  resistance: PropTypes.number,
  hammerOptions: PropTypes.object
};
<commit_msg>Fix refs to use functions (#27)<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import WebPullToRefresh from '../pull-to-refresh/wptr.1.1';

export default class ReactPullToRefresh extends Component {

  constructor(props) {
    super(props);
    this.state = {
      initialized: false
    };
    this.handleRefresh = this.handleRefresh.bind(this);
  }

  handleRefresh() {
    return new Promise((resolve, reject) => {
      this.props.onRefresh(resolve, reject);
    });
  }

  init() {
    if (!this.state.initialized) {
      WebPullToRefresh().init({
        contentEl: this.refresh,
        ptrEl: this.ptr,
        bodyEl: this.body,
        distanceToRefresh: this.props.distanceToRefresh || undefined,
        loadingFunction: this.handleRefresh,
        resistance: this.props.resistance || undefined,
        hammerOptions: this.props.hammerOptions || undefined
      });
      this.setState({
        initialized: true
      });
    }
  }

  componentDidMount() {
    if (!this.props.disabled) {
      this.init();
    }
  }

  componentDidUpdate() {
    if (!this.props.disabled) {
      this.init();
    }
  }

  render() {
    const {
      children,
      disabled,
      distanceToRefresh,
      hammerOptions,
      icon,
      loading,
      onRefresh,
      resistance,
      ...rest
    } = this.props;

    if (disabled) {
      return (

          {children}

      );
    }

    return (

 { this.body = el; }} {...rest}>

 { this.ptr = el; }} className="ptr-element">
          {icon || }
          {loading ||

}

 { this.refresh = el; }} className="refresh-view">
          {children}

    );
  }
}

ReactPullToRefresh.propTypes = {
  onRefresh: PropTypes.func.isRequired,
  icon: PropTypes.element,
  loading: PropTypes.element,
  disabled: PropTypes.bool,
  className: PropTypes.string,
  style: PropTypes.object,
  distanceToRefresh: PropTypes.number,
  resistance: PropTypes.number,
  hammerOptions: PropTypes.object
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import * as T from "prop-types";
import './styles.scss';
import {cssClassName} from 'utils'
const cn = cssClassName('SE_HmqSearch')
import A_Container from 'A_Container'
import M_NoResults from 'M_NoResults'
import O_Search from 'O_Search'
import history from 'history'
import O_Transaction from 'O_Transaction'

class SE_HmqSearch extends Component {

  handleSubmit = (searchString) => {
    history.push('/hmq-explorer/search?searchTerm=' + searchString)
  }

  getResults(entities){
    return(
      entities.map( ({type, ...props}, i) => (
        <O_Transaction key={'key_' + i} {...props} type={type} up={i == 0}/>
      ))
    )
  }

  render() {
    const {request, show, entities} = this.props

    let result
    if(show){
      result = entities.length === 0 ?
        <M_NoResults request={request} />
        : this.getResults(entities)
    }
    return (

          <O_Search
            value={request}
            placeholder="Search TxHash or Address"
            focus
            handleSubmit={this.handleSubmit}
          />

        <A_Container type="section-long-text">

            {result}

        </A_Container>

    )
  }
}

SE_HmqSearch.propTypes = {
  entities: T.array.isRequired,
  request: T.string
};

SE_HmqSearch.defaultProps = {
}

export default SE_HmqSearch<commit_msg>[upd] content holders updated in tx search<commit_after>import React, { Component } from 'react';
import * as T from "prop-types";
import './styles.scss';
import {cssClassName} from 'utils'
const cn = cssClassName('SE_HmqSearch')
import A_Container from 'A_Container'
import M_NoResults from 'M_NoResults'
import O_Search from 'O_Search'
import history from 'history'
import O_Transaction from 'O_Transaction'

class SE_HmqSearch extends Component {

  handleSubmit = (searchString) => {
    history.push('/hmq-explorer/search?searchTerm=' + searchString)
  }

  getResults(entities){
    return(
      entities.map( ({type, ...props}, i) => (
        <O_Transaction key={'key_' + i} {...props} type={type} onTop={i === 0}/>
      ))
    )
  }

  render() {
    const {request, show, entities} = this.props;

    let result
    if(show){
      result = entities.length === 0 ?
        <M_NoResults request={request} />
        : this.getResults(entities)
    }
    return (

          <O_Search
            value={request}
            placeholder="Search TxHash or Address"
            focus
            handleSubmit={this.handleSubmit}
          />

        <A_Container type="section-long-text">

            {result}

        </A_Container>

    )
  }
}

SE_HmqSearch.propTypes = {
  entities: T.array.isRequired,
  request: T.string
};

SE_HmqSearch.defaultProps = {
}

export default SE_HmqSearch<|endoftext|>


<commit_before>/*
 * dbKoda - a modern, open source code editor, for MongoDB.
 * Copyright (C) 2017-2018 Southbank Software
 *
 * This file is part of dbKoda.
 *
 * dbKoda is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * dbKoda is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with dbKoda.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @Author: Wahaj Shamim <wahaj>
 * @Date:   2017-05-22T09:14:04+10:00
 * @Email:  wahaj@southbanksoftware.com
 * @Last modified by:   wahaj
 * @Last modified time: 2017-08-23T14:09:37+10:00
 */

import { featherClient } from '~/helpers/feathers';

 export const SyncService = {
   executeQuery: (query, shellId, profileId) => {
     console.log('Query:', query);
     if (shellId && profileId && shellId != '' && profileId != '') {
       const service = featherClient().service('/mongo-sync-execution');
       service.timeout = 60000;
       return new Promise((resolve, reject) => {
         service
           .update(profileId, {
             shellId,
             commands: query
           })
           .then((res) => {
             if (typeof res == 'string') {
               res = res.replace(/[\r\n\t]*/g, '');
               res = res.replace(/ObjectId\((\"\w*\")\)/g, '$1');
               res = res.replace(/(BinData\(\d\W)(\")([\w|\W]*?)(\")(\))/g, '"$1\\$2$3\\$4$5"');
               res = res.replace(/NumberLong\(\"?(\d*)\"?\)/g, '$1');
               res = res.replace(/Timestamp\((\d*)[\w|\W]*?\)/g, '$1');
               res = res.replace(/\bNaN\b/g, '"NaN"');
               console.log('Result: ', res);
               try {
                 const ejson = JSON.parse(res);
                 resolve(ejson);
               } catch (e) {
                 resolve(res);
               }
             } else {
               resolve(res);
             }
           })
           .catch((reason) => {
             console.log(
               'executeCommand:',
               'Handle rejected promise (' + reason + ') here.'
             );
             reject(reason);
           });
       });
     }
     return null;
   }
 };
<commit_msg><commit_after>/*
 * dbKoda - a modern, open source code editor, for MongoDB.
 * Copyright (C) 2017-2018 Southbank Software
 *
 * This file is part of dbKoda.
 *
 * dbKoda is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * dbKoda is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with dbKoda.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @Author: Wahaj Shamim <wahaj>
 * @Date:   2017-05-22T09:14:04+10:00
 * @Email:  wahaj@southbanksoftware.com
 * @Last modified by:   wahaj
 * @Last modified time: 2017-08-23T14:09:37+10:00
 */

import { featherClient } from '~/helpers/feathers';

 export const SyncService = {
   executeQuery: (query, shellId, profileId) => {
     console.log('Query:', query);
     if (shellId && profileId && shellId != '' && profileId != '') {
       const service = featherClient().service('/mongo-sync-execution');
       service.timeout = 60000;
       return new Promise((resolve, reject) => {
         service
           .update(profileId, {
             shellId,
             commands: query
           })
           .then((res) => {
             if (typeof res == 'string') {
               res = res.replace(/[\r\n\t]*/g, '');
               res = res.replace(/ObjectId\((\"\w*\")\)/g, '$1');
               res = res.replace(/(BinData\(\d*?\W)(\")(.*?)(\")(\))/g, '"$1\\$2$3\\$4$5"');
               res = res.replace(/NumberLong\(\"?(\d*)\"?\)/g, '$1');
               res = res.replace(/Timestamp\((\d*)[\w|\W]*?\)/g, '$1');
               res = res.replace(/\bNaN\b/g, '"NaN"');
               console.log('Result: ', res);
               try {
                 const ejson = JSON.parse(res);
                 resolve(ejson);
               } catch (e) {
                 resolve(res);
               }
             } else {
               resolve(res);
             }
           })
           .catch((reason) => {
             console.log(
               'executeCommand:',
               'Handle rejected promise (' + reason + ') here.'
             );
             reject(reason);
           });
       });
     }
     return null;
   }
 };
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router'
import classNames from 'classnames'
import Avatar from '../assets/Avatar'
import {
  ArrowIcon,
  ElloLogoType,
  PencilIcon,
  XIconLG,
} from '../assets/Icons'
import {
  active,
  after,
  before,
  css,
  hover,
  media,
  modifier,
  parent,
  select,
} from '../../styles/jss'
import * as s from '../../styles/jso'
import * as ENV from '../../../env'

// -------------------------------------

const layoutToolStyle = css(
  s.absolute,
  { top: 2, left: 145 },
  s.colorA,
)
export const NavbarLayoutTool = ({ icon, onClick }) => (
  <button className={layoutToolStyle} onClick={onClick} >
    {icon}
  </button>
)

NavbarLayoutTool.propTypes = {
  icon: PropTypes.node.isRequired,
  onClick: PropTypes.func.isRequired,
}

// -------------------------------------
const linkLabelStyle = css(
  s.relative,
  s.inlineBlock,
  parent('.NavbarLink.isActive >', s.colorBlack),
  parent('.NavbarLink:active >', s.colorBlack),
  parent('.no-touch .NavbarLink:hover >', s.colorBlack),
  parent('.NavbarLink.isSignUp.isActive >', s.colorWhite),
  parent('.NavbarLink.isSignUp:active >', s.colorWhite),
  parent('.no-touch .NavbarLink.isSignUp:hover >', s.colorWhite),
  select('.NavbarLink.isActive > &::after', s.fullWidth, s.bgcCurrentColor),
  select('.NavbarLink:active > &::after', s.fullWidth, s.bgcCurrentColor),
  select('.NavbarLink:hover > &::after', s.fullWidth, s.bgcCurrentColor),
  select('.NavbarLink.isNotificationsUnread > &::before',
    s.absolute,
    { top: 5, left: -5, width: 5, height: 5, content: '""', borderRadius: '50%' },
    s.bgcRed,
  ),
  select('.no-touch .NavbarLink.isNotificationsUnread:hover > > &::before',
    { left: -7, width: 7, height: 7 },
  ),
  after(
    s.absolute,
    { bottom: 8, left: 0, width: 0, height: 2, content: '""' },
    s.bgcTransparent,
    { transition: `width 0.2s ${s.ease}, background-color 0.2s ease` },
  ),
  parent('.NavbarLink.isSignUp', after(s.displayNone)),
  parent('.no-touch .NavbarLink.IconOnly:hover >', after({ transitionDelay: '0.6s' })),
)

// TODO: Move over styles from Icons
const linkStyle = css(
  s.relative,
  s.hv40,
  s.lh40,
  s.overflowHidden,
  s.fontSize14,
  s.colorA,
  s.nowrap,
  s.alignMiddle,
  { transition: `width 0.2s ${s.ease}, color 0.2s ease, background-color 0.2s ease` },
  before(s.hitarea),
  modifier('.isSignUp',
    { width: 80, borderRadius: 5, right: 0 },
    s.absolute,
    s.hv30,
    s.lh30,
    s.colorWhite,
    s.center,
    s.bgcGreen,
    active({ backgroundColor: '#00b100' }),
    hover({ backgroundColor: '#00b100' }),
    modifier('.isActive', { backgroundColor: '#00b100' }),
  ),
  select('[data-dragging-priority="noise"] &[href="/following"]', s.px10, s.bgcYellow),
  select('[data-dragging-priority="inactive"] &[href="/following"]', s.px10, s.bgcYellow),
  select('[data-dragging-priority="noise"] &.hasDragOver[href="/following"]', { backgroundColor: '#cfc' }),
  select('[data-dragging-priority="inactive"] &.hasDragOver[href="/following"]', { backgroundColor: '#cfc' }),
  select('.isLoggedOut &[href="/enter"]', s.absolute, s.m0, { top: 0, left: 'auto', right: 110 }),
  select('.NavbarLinks > & + &', s.ml30),
  media(s.maxBreak3,
    s.mt30,
    select('.isLoggedOut .NavbarLinks > & + &', { marginLeft: 18 }),
    select('.isLoggedIn &[href^="/notifications"]', s.absolute, s.m0, { top: -3, left: 55 }),
    select('.isLoggedIn &[href^="/search"]', s.absolute, s.m0, { top: -3, left: 100 }),
    select('.isLoggedOut &[href="/join"]', s.absolute, s.m0, { top: 0, left: 'auto', right: 0 }),
    select('.isLoggedOut &[href="/confirm"]', s.absolute, s.m0, { top: 0, left: 'auto', right: 0 }),
    select('.isLoggedOut &[href="/enter"]', { top: -5, right: 100 }),
  ),
  media(s.minBreak3, modifier('.isSignUp', s.hv40, s.lh40)),
)

const highlightingRules = {
  '/following': /^\/following/,
  '/creative-briefs': /(^\/creative-briefs$)|^\/creative-briefs(?:\/.*\.?.*)/,
  '/discover/subscribed': /^\/discover/,
}

export const NavbarLink = ({
  className = '',
  icon,
  label,
  onClick,
  onDragLeave,
  onDragOver,
  onDrop,
  pathname,
  to,
}) => {
  const klassNames = classNames(
    'NavbarLink',
    className,
    `${linkStyle}`,
    {
      isActive: highlightingRules[to] ? pathname.match(highlightingRules[to]) : pathname === to,
    },
  )
  return (
    <Link
      className={klassNames}
      onClick={onClick}
      onDragLeave={onDragLeave}
      onDragOver={onDragOver}
      onDrop={onDrop}
      to={to}
    >
      {icon || null}
      {label}
    </Link>
  )
}

NavbarLink.propTypes = {
  className: PropTypes.string.isRequired,
  icon: PropTypes.element,
  label: PropTypes.string.isRequired,
  onClick: PropTypes.func,
  onDragLeave: PropTypes.func,
  onDragOver: PropTypes.func,
  onDrop: PropTypes.func,
  pathname: PropTypes.string.isRequired,
  to: PropTypes.string.isRequired,
}
NavbarLink.defaultProps = {
  icon: null,
  onClick: null,
  onDragLeave: null,
  onDragOver: null,
  onDrop: null,
}

// -------------------------------------
const markStyle = css(
  { marginTop: -2 },
  s.relative,
  parent('.isLoggedIn', s.displayNone),
  parent('.isLoggedOut', s.inlineBlock),
  media(s.minBreak3,
    { marginTop: 2 },
    parent('.isLoggedIn', s.inlineBlock),
  ),
)

export const NavbarMark = ({ onClick }) => (
  <Link
    className={`NavbarMark ${markStyle}`}
    draggable
    onClick={onClick}
    to="/"
  >
    <ElloLogoType />
  </Link>
)

NavbarMark.propTypes = {
  onClick: PropTypes.func.isRequired,
}

// -------------------------------------

const moreButtonStyle = css(
  {
    borderRadius: '50%',
    transition: 'background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, opacity 0.4s ease',
  },
  s.absolute,
  s.bgcA,
  s.borderA,
  s.colorWhite,
  s.fontSize14,
  s.hv30,
  s.lh30,
  s.nowrap,
  s.wv30,
  s.zIndex3,
  parent('.isLoggedIn', { right: 90 }),
  parent('.isLoggedOut', s.displayNone),
  hover(s.color6),
  media(s.minBreak3,
    s.wv40, s.hv40, s.lh40,
    parent('.isLoggedIn', { right: 'auto', left: 80 }),
    parent('.isLoggedOut', s.inlineBlock, { left: 80 }),
    { width: 'auto', paddingRight: 20, paddingLeft: 15, borderRadius: 20 },
  ),
  media(s.minBreak4,
    parent('.isLoggedIn'),
    parent('.isLoggedOut', { left: 140 }),
  ),
)

const moreSpanStyle = css(
  s.displayNone,
  s.alignMiddle,
  { paddingLeft: 8 },
  media(s.minBreak3, s.inlineBlock),
)

export const NavbarMorePostsButton = ({ onClick }) =>
  (<button className={`NavbarMorePostsButton ${moreButtonStyle}`} onClick={onClick} >
    <ArrowIcon />
    New Posts
  </button>)
NavbarMorePostsButton.propTypes = {
  onClick: PropTypes.func.isRequired,
}

// -------------------------------------

const omniButtonStyle = css(
  s.absolute,
  { top: 0, right: 0, borderRadius: 5 },
  s.hv30,
  s.lh30,
  { paddingRight: 15, paddingLeft: 10 },
  s.fontSize14,
  s.colorWhite,
  s.bgcBlack,
  { transition: 'background-color 0.2s ease' },
  hover(s.bgc6),
  media(s.minBreak3,
    { width: 100 },
    s.hv40,
    s.lh40,
  ),
)

export const NavbarOmniButton = ({ onClick, onDragOver }) =>
  (<button className={`NavbarOmniButton ${omniButtonStyle}`} onClick={onClick} onDragOver={onDragOver}>
    <PencilIcon />
    Post
  </button>)

NavbarOmniButton.propTypes = {
  onClick: PropTypes.func.isRequired,
  onDragOver: PropTypes.func.isRequired,
}

// -------------------------------------

const profilePopStyle = css(
  s.absolute,
  { top: 0, left: 0 },
  s.zIndex4,
  s.transitionTransform,
  // wtf...?
  media(s.maxBreak3,
    select('.isProfileMenuActive ~ .Navbar .NavbarMain > *:not(.NavbarProfile)', s.displayNone),
  ),
  media(s.minBreak3,
    { top: 0, left: 'auto', right: 130 },
    s.zIndex3,
    hover(before(
      s.absolute,
      { top: 15, left: 0, width: 100, height: 30, content: '""' },
      { backgroundColor: 'rgba(0, 0, 0, 0)', transform: 'translateX(-100%)' },
    )),
    parent('.isOmnibarActive .Navbar >', s.absolute, { transform: 'translate3d(400px, 0, 0)' }),
  ),
)

const profileLinksStyle = css(
  s.absolute,
  s.zIndex2,
  { minWidth: 140 },
  s.py5,
  s.px10,
  s.overflowHidden,
  s.colorA,
  s.pointerNone,
  s.bgcWhite,
  s.borderA,
  { borderTop: 0 },
  s.opacity0,
  s.transitionOpacity,
  modifier('.isActive', s.pointerAuto, s.opacity1),
  media(s.maxBreak3, {
    top: -10,
    left: -10,
    width: '100vw',
    height: '100vh',
    padding: 0,
  }),
  media(s.minBreak3,
    {
      top: 40,
      right: 0,
      left: 'auto',
      maxWidth: 180,
    },
    parent('.no-touch .NavbarProfile:hover', s.pointerAuto, s.opacity1),
  ),
)

const profileLinkStyle = css(
  s.block,
  s.hv30,
  s.lh30,
  s.fontSize14,
  s.truncate,
  hover(s.colorBlack),
  media(s.maxBreak3,
    { height: 50, lineHeight: 50, textIndent: 10 },
    s.colorBlack,
    s.borderBottom,
  ),
)

const profileLinkSmallStyle = css(
  s.block,
  { height: 25, lineHeight: 25 },
  s.fontSize12,
  s.truncate,
  s.colorC,
  hover(s.colorBlack),
  media(s.maxBreak3,
    { textIndent: 10 },
    s.hv30,
    s.lh30,
    s.colorBlack,
  ),
)

const dividerStyle = css(
  { margin: '4px -10px', borderColor: '#ccc' },
  media(s.maxBreak3, { borderColor: 'transparent' }),
)

const closeButtonStyle = css(
  s.displayNone,
  s.absolute,
  { top: 5, right: 5 },
  media(s.maxBreak3, s.block),
)

export const NavbarProfile = ({
  artistInvitesInProfileMenu,
  avatar,
  isBrand,
  isProfileMenuActive,
  isStaff,
  onClickAvatar,
  onLogOut,
  username,
}, { onClickArtistInvites }) => {
  if (avatar && username) {
    return (
      <span className={`NavbarProfile ${profilePopStyle}`}>
        <Avatar sources={avatar} onClick={onClickAvatar} />
        <nav className={classNames(`${profileLinksStyle}`, { isActive: isProfileMenuActive })} >
          <Link className={profileLinkStyle} to={`/${username}`}>{`@${username}`}</Link>
          { artistInvitesInProfileMenu &&
            <Link className={profileLinkStyle} onClick={onClickArtistInvites} to="/creative-briefs">Creative Briefs</Link>
          }
          <Link className={profileLinkStyle} to={`/${username}/loves`}>Loves</Link>
          <Link className={profileLinkStyle} to="/invitations">Invite</Link>
          <Link className={profileLinkStyle} to="/settings">Settings</Link>
          {(isBrand || isStaff) &&
            Analytics
          }

          <a
            className={profileLinkSmallStyle}
            href={`${ENV.AUTH_DOMAIN}/wtf`}
            rel="noopener noreferrer"
            target="_blank"
          >
            Help

          <button className={profileLinkSmallStyle} onClick={onLogOut}>Logout</button>
          <button className={closeButtonStyle}>
            <XIconLG />
          </button>

    )
  }
  return (
    <span className={`NavbarProfile ${profilePopStyle}`}>
      <Avatar />

  )
}
NavbarProfile.propTypes = {
  artistInvitesInProfileMenu: PropTypes.bool.isRequired,
  avatar: PropTypes.object,
  isBrand: PropTypes.bool.isRequired,
  isStaff: PropTypes.bool.isRequired,
  isProfileMenuActive: PropTypes.bool.isRequired,
  onClickAvatar: PropTypes.func.isRequired,
  onLogOut: PropTypes.func.isRequired,
  username: PropTypes.string,
}
NavbarProfile.defaultProps = {
  avatar: null,
  username: null,
  innerWidth: null,
}
NavbarProfile.contextTypes = {
  onClickArtistInvites: PropTypes.func.isRequired,
}
<commit_msg>Make `NavbarLink` handle external links<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router'
import classNames from 'classnames'
import Avatar from '../assets/Avatar'
import {
  ArrowIcon,
  ElloLogoType,
  PencilIcon,
  XIconLG,
} from '../assets/Icons'
import {
  active,
  after,
  before,
  css,
  hover,
  media,
  modifier,
  parent,
  select,
} from '../../styles/jss'
import * as s from '../../styles/jso'
import * as ENV from '../../../env'

// -------------------------------------

const layoutToolStyle = css(
  s.absolute,
  { top: 2, left: 145 },
  s.colorA,
)
export const NavbarLayoutTool = ({ icon, onClick }) => (
  <button className={layoutToolStyle} onClick={onClick} >
    {icon}
  </button>
)

NavbarLayoutTool.propTypes = {
  icon: PropTypes.node.isRequired,
  onClick: PropTypes.func.isRequired,
}

// -------------------------------------
const linkLabelStyle = css(
  s.relative,
  s.inlineBlock,
  parent('.NavbarLink.isActive >', s.colorBlack),
  parent('.NavbarLink:active >', s.colorBlack),
  parent('.no-touch .NavbarLink:hover >', s.colorBlack),
  parent('.NavbarLink.isSignUp.isActive >', s.colorWhite),
  parent('.NavbarLink.isSignUp:active >', s.colorWhite),
  parent('.no-touch .NavbarLink.isSignUp:hover >', s.colorWhite),
  select('.NavbarLink.isActive > &::after', s.fullWidth, s.bgcCurrentColor),
  select('.NavbarLink:active > &::after', s.fullWidth, s.bgcCurrentColor),
  select('.NavbarLink:hover > &::after', s.fullWidth, s.bgcCurrentColor),
  select('.NavbarLink.isNotificationsUnread > &::before',
    s.absolute,
    { top: 5, left: -5, width: 5, height: 5, content: '""', borderRadius: '50%' },
    s.bgcRed,
  ),
  select('.no-touch .NavbarLink.isNotificationsUnread:hover > > &::before',
    { left: -7, width: 7, height: 7 },
  ),
  after(
    s.absolute,
    { bottom: 8, left: 0, width: 0, height: 2, content: '""' },
    s.bgcTransparent,
    { transition: `width 0.2s ${s.ease}, background-color 0.2s ease` },
  ),
  parent('.NavbarLink.isSignUp', after(s.displayNone)),
  parent('.no-touch .NavbarLink.IconOnly:hover >', after({ transitionDelay: '0.6s' })),
)

// TODO: Move over styles from Icons
const linkStyle = css(
  s.relative,
  s.hv40,
  s.lh40,
  s.overflowHidden,
  s.fontSize14,
  s.colorA,
  s.nowrap,
  s.alignMiddle,
  { transition: `width 0.2s ${s.ease}, color 0.2s ease, background-color 0.2s ease` },
  before(s.hitarea),
  modifier('.isSignUp',
    { width: 80, borderRadius: 5, right: 0 },
    s.absolute,
    s.hv30,
    s.lh30,
    s.colorWhite,
    s.center,
    s.bgcGreen,
    active({ backgroundColor: '#00b100' }),
    hover({ backgroundColor: '#00b100' }),
    modifier('.isActive', { backgroundColor: '#00b100' }),
  ),
  select('[data-dragging-priority="noise"] &[href="/following"]', s.px10, s.bgcYellow),
  select('[data-dragging-priority="inactive"] &[href="/following"]', s.px10, s.bgcYellow),
  select('[data-dragging-priority="noise"] &.hasDragOver[href="/following"]', { backgroundColor: '#cfc' }),
  select('[data-dragging-priority="inactive"] &.hasDragOver[href="/following"]', { backgroundColor: '#cfc' }),
  select('.isLoggedOut &[href="/enter"]', s.absolute, s.m0, { top: 0, left: 'auto', right: 110 }),
  select('.NavbarLinks > & + &', s.ml30),
  media(s.maxBreak3,
    s.mt30,
    select('.isLoggedOut .NavbarLinks > & + &', { marginLeft: 18 }),
    select('.isLoggedIn &[href^="/notifications"]', s.absolute, s.m0, { top: -3, left: 55 }),
    select('.isLoggedIn &[href^="/search"]', s.absolute, s.m0, { top: -3, left: 100 }),
    select('.isLoggedOut &[href="/join"]', s.absolute, s.m0, { top: 0, left: 'auto', right: 0 }),
    select('.isLoggedOut &[href="/confirm"]', s.absolute, s.m0, { top: 0, left: 'auto', right: 0 }),
    select('.isLoggedOut &[href="/enter"]', { top: -5, right: 100 }),
  ),
  media(s.minBreak3, modifier('.isSignUp', s.hv40, s.lh40)),
)

const highlightingRules = {
  '/following': /^\/following/,
  '/creative-briefs': /(^\/creative-briefs$)|^\/creative-briefs(?:\/.*\.?.*)/,
  '/discover/subscribed': /^\/discover/,
}

export const NavbarLink = ({
  className = '',
  external,
  icon,
  label,
  onClick,
  onDragLeave,
  onDragOver,
  onDrop,
  pathname,
  to,
}) => {
  const klassNames = classNames(
    'NavbarLink',
    className,
    `${linkStyle}`,
    {
      isActive: highlightingRules[to] ? pathname.match(highlightingRules[to]) : pathname === to,
    },
  )
  return external ?

      {icon || null}
      {label}
     :
    <Link
      className={klassNames}
      onClick={onClick}
      onDragLeave={onDragLeave}
      onDragOver={onDragOver}
      onDrop={onDrop}
      to={to}
    >
      {icon || null}
      {label}
    </Link>
}

NavbarLink.propTypes = {
  className: PropTypes.string.isRequired,
  icon: PropTypes.element,
  label: PropTypes.string.isRequired,
  onClick: PropTypes.func,
  onDragLeave: PropTypes.func,
  onDragOver: PropTypes.func,
  onDrop: PropTypes.func,
  pathname: PropTypes.string.isRequired,
  to: PropTypes.string.isRequired,
}
NavbarLink.defaultProps = {
  icon: null,
  onClick: null,
  onDragLeave: null,
  onDragOver: null,
  onDrop: null,
}

// -------------------------------------
const markStyle = css(
  { marginTop: -2 },
  s.relative,
  parent('.isLoggedIn', s.displayNone),
  parent('.isLoggedOut', s.inlineBlock),
  media(s.minBreak3,
    { marginTop: 2 },
    parent('.isLoggedIn', s.inlineBlock),
  ),
)

export const NavbarMark = ({ onClick }) => (
  <Link
    className={`NavbarMark ${markStyle}`}
    draggable
    onClick={onClick}
    to="/"
  >
    <ElloLogoType />
  </Link>
)

NavbarMark.propTypes = {
  onClick: PropTypes.func.isRequired,
}

// -------------------------------------

const moreButtonStyle = css(
  {
    borderRadius: '50%',
    transition: 'background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, opacity 0.4s ease',
  },
  s.absolute,
  s.bgcA,
  s.borderA,
  s.colorWhite,
  s.fontSize14,
  s.hv30,
  s.lh30,
  s.nowrap,
  s.wv30,
  s.zIndex3,
  parent('.isLoggedIn', { right: 90 }),
  parent('.isLoggedOut', s.displayNone),
  hover(s.color6),
  media(s.minBreak3,
    s.wv40, s.hv40, s.lh40,
    parent('.isLoggedIn', { right: 'auto', left: 80 }),
    parent('.isLoggedOut', s.inlineBlock, { left: 80 }),
    { width: 'auto', paddingRight: 20, paddingLeft: 15, borderRadius: 20 },
  ),
  media(s.minBreak4,
    parent('.isLoggedIn'),
    parent('.isLoggedOut', { left: 140 }),
  ),
)

const moreSpanStyle = css(
  s.displayNone,
  s.alignMiddle,
  { paddingLeft: 8 },
  media(s.minBreak3, s.inlineBlock),
)

export const NavbarMorePostsButton = ({ onClick }) =>
  (<button className={`NavbarMorePostsButton ${moreButtonStyle}`} onClick={onClick} >
    <ArrowIcon />
    New Posts
  </button>)
NavbarMorePostsButton.propTypes = {
  onClick: PropTypes.func.isRequired,
}

// -------------------------------------

const omniButtonStyle = css(
  s.absolute,
  { top: 0, right: 0, borderRadius: 5 },
  s.hv30,
  s.lh30,
  { paddingRight: 15, paddingLeft: 10 },
  s.fontSize14,
  s.colorWhite,
  s.bgcBlack,
  { transition: 'background-color 0.2s ease' },
  hover(s.bgc6),
  media(s.minBreak3,
    { width: 100 },
    s.hv40,
    s.lh40,
  ),
)

export const NavbarOmniButton = ({ onClick, onDragOver }) =>
  (<button className={`NavbarOmniButton ${omniButtonStyle}`} onClick={onClick} onDragOver={onDragOver}>
    <PencilIcon />
    Post
  </button>)

NavbarOmniButton.propTypes = {
  onClick: PropTypes.func.isRequired,
  onDragOver: PropTypes.func.isRequired,
}

// -------------------------------------

const profilePopStyle = css(
  s.absolute,
  { top: 0, left: 0 },
  s.zIndex4,
  s.transitionTransform,
  // wtf...?
  media(s.maxBreak3,
    select('.isProfileMenuActive ~ .Navbar .NavbarMain > *:not(.NavbarProfile)', s.displayNone),
  ),
  media(s.minBreak3,
    { top: 0, left: 'auto', right: 130 },
    s.zIndex3,
    hover(before(
      s.absolute,
      { top: 15, left: 0, width: 100, height: 30, content: '""' },
      { backgroundColor: 'rgba(0, 0, 0, 0)', transform: 'translateX(-100%)' },
    )),
    parent('.isOmnibarActive .Navbar >', s.absolute, { transform: 'translate3d(400px, 0, 0)' }),
  ),
)

const profileLinksStyle = css(
  s.absolute,
  s.zIndex2,
  { minWidth: 140 },
  s.py5,
  s.px10,
  s.overflowHidden,
  s.colorA,
  s.pointerNone,
  s.bgcWhite,
  s.borderA,
  { borderTop: 0 },
  s.opacity0,
  s.transitionOpacity,
  modifier('.isActive', s.pointerAuto, s.opacity1),
  media(s.maxBreak3, {
    top: -10,
    left: -10,
    width: '100vw',
    height: '100vh',
    padding: 0,
  }),
  media(s.minBreak3,
    {
      top: 40,
      right: 0,
      left: 'auto',
      maxWidth: 180,
    },
    parent('.no-touch .NavbarProfile:hover', s.pointerAuto, s.opacity1),
  ),
)

const profileLinkStyle = css(
  s.block,
  s.hv30,
  s.lh30,
  s.fontSize14,
  s.truncate,
  hover(s.colorBlack),
  media(s.maxBreak3,
    { height: 50, lineHeight: 50, textIndent: 10 },
    s.colorBlack,
    s.borderBottom,
  ),
)

const profileLinkSmallStyle = css(
  s.block,
  { height: 25, lineHeight: 25 },
  s.fontSize12,
  s.truncate,
  s.colorC,
  hover(s.colorBlack),
  media(s.maxBreak3,
    { textIndent: 10 },
    s.hv30,
    s.lh30,
    s.colorBlack,
  ),
)

const dividerStyle = css(
  { margin: '4px -10px', borderColor: '#ccc' },
  media(s.maxBreak3, { borderColor: 'transparent' }),
)

const closeButtonStyle = css(
  s.displayNone,
  s.absolute,
  { top: 5, right: 5 },
  media(s.maxBreak3, s.block),
)

export const NavbarProfile = ({
  artistInvitesInProfileMenu,
  avatar,
  isBrand,
  isProfileMenuActive,
  isStaff,
  onClickAvatar,
  onLogOut,
  username,
}, { onClickArtistInvites }) => {
  if (avatar && username) {
    return (
      <span className={`NavbarProfile ${profilePopStyle}`}>
        <Avatar sources={avatar} onClick={onClickAvatar} />
        <nav className={classNames(`${profileLinksStyle}`, { isActive: isProfileMenuActive })} >
          <Link className={profileLinkStyle} to={`/${username}`}>{`@${username}`}</Link>
          { artistInvitesInProfileMenu &&
            <Link className={profileLinkStyle} onClick={onClickArtistInvites} to="/creative-briefs">Creative Briefs</Link>
          }
          <Link className={profileLinkStyle} to={`/${username}/loves`}>Loves</Link>
          <Link className={profileLinkStyle} to="/invitations">Invite</Link>
          <Link className={profileLinkStyle} to="/settings">Settings</Link>
          {(isBrand || isStaff) &&
            Analytics
          }

          <a
            className={profileLinkSmallStyle}
            href={`${ENV.AUTH_DOMAIN}/wtf`}
            rel="noopener noreferrer"
            target="_blank"
          >
            Help

          <button className={profileLinkSmallStyle} onClick={onLogOut}>Logout</button>
          <button className={closeButtonStyle}>
            <XIconLG />
          </button>

    )
  }
  return (
    <span className={`NavbarProfile ${profilePopStyle}`}>
      <Avatar />

  )
}
NavbarProfile.propTypes = {
  artistInvitesInProfileMenu: PropTypes.bool.isRequired,
  avatar: PropTypes.object,
  isBrand: PropTypes.bool.isRequired,
  isStaff: PropTypes.bool.isRequired,
  isProfileMenuActive: PropTypes.bool.isRequired,
  onClickAvatar: PropTypes.func.isRequired,
  onLogOut: PropTypes.func.isRequired,
  username: PropTypes.string,
}
NavbarProfile.defaultProps = {
  avatar: null,
  username: null,
  innerWidth: null,
}
NavbarProfile.contextTypes = {
  onClickArtistInvites: PropTypes.func.isRequired,
}
<|endoftext|>