<commit_before>import {call, put, fork, select, takeLatest, take, all} from 'redux-saga/effects'
import {form} from 'tocco-util'
import _reduce from 'lodash/reduce'
import * as actions from './actions'
import {fetchForm, searchFormTransformer} from '../../util/api/forms'
import {getPreselectedValues} from '../../util/searchForm'
import {fetchEntities, searchFilterTransformer} from '../../util/api/entities'

import {SET_INITIALIZED as LIST_SET_INITIALIZED} from '../entityList/actions'
import {
  actions as formActions,
  getFormValues
} from 'redux-form'
import * as formActionTypes from 'redux-form/es/actionTypes'

import _forOwn from 'lodash/forOwn'

import {validateSearchFields} from '../../util/searchFormValidation'
import {getSearchInputsForRequest} from '../../util/searchInputs'

export const inputSelector = state => state.input
export const searchFormSelector = state => state.searchForm
export const entityListSelector = state => state.entityList
export const searchValuesSelector = getFormValues('searchForm')

const FORM_ID = 'searchForm'

export default function* sagas() {
  yield all([
    fork(takeLatest, actions.INITIALIZE, initialize),
    fork(takeLatest, actions.LOAD_SEARCH_FILTERS, loadSearchFilters),
    fork(takeLatest, formActionTypes.CHANGE, submitSearchFrom),
    fork(takeLatest, actions.SUBMIT_SEARCH_FORM, submitSearchFrom),
    fork(takeLatest, actions.RESET_SEARCH, resetSearch),
    fork(takeLatest, actions.ADVANCED_SEARCH_UPDATE, advancedSearchUpdate)
  ])
}

export function* initialize({payload: {searchFormVisible}}) {
  const {searchFormName, initialized} = yield select(searchFormSelector)
  if (!initialized) {
    const formDefinition = searchFormVisible ? yield call(loadSearchForm, searchFormName) : null
    yield call(setInitialFormValues, searchFormVisible, formDefinition)
    yield put(actions.setInitialized())
  }
}

export function* setInitialFormValues(searchFormVisible, formDefinition) {
  const {preselectedSearchFields, parent} = yield select(inputSelector)
  const {model} = yield call(getEntityModel)

  let formValues = preselectedSearchFields
    ? yield call(getPreselectedValues, preselectedSearchFields, model, null, searchFormVisible)
    : {}

  if (parent && !formValues.hasOwnProperty(parent.reverseRelationName)) {
    formValues[parent.reverseRelationName] = parent.key
  }

  if (searchFormVisible && formDefinition) {
    const fieldDefinitions = yield call(form.getFieldDefinitions, formDefinition)
    const fromDefaultValues = yield call(form.getDefaultValues, fieldDefinitions)
    formValues = {...fromDefaultValues, ...formValues}
  }

  const transformedFromValues = yield call(transformFieldNames, formValues)

  yield put(formActions.initialize(FORM_ID, transformedFromValues))
  yield put(actions.setValuesInitialized(true))
}

export function* transformFieldNames(formValues) {
  return _reduce(formValues, (acc, val, key) => (
    {...acc, [form.transformFieldName(key)]: val}
  ), {})
}

export function* submitSearchFrom() {
  yield put(formActions.startSubmit(FORM_ID))
  const values = yield select(getFormValues(FORM_ID))
  const {formDefinition} = yield select(searchFormSelector)
  const errors = yield call(validateSearchFields, values, formDefinition)
  yield put(formActions.stopSubmit(FORM_ID, errors))

  if (Object.keys(errors).length === 0) {
    yield put(actions.executeSearch())
  }
}

export function* loadSearchForm(searchFormName) {
  const formDefinition = yield call(fetchForm, searchFormName, searchFormTransformer)
  if (formDefinition) {
    yield put(actions.setFormDefinition(formDefinition))
  } else {
    yield put(actions.setShowFullTextSearchForm(true))
  }
  return formDefinition
}

export function* getEntityModel() {
  let entityList = yield select(entityListSelector)
  if (!entityList.initialized) {
    yield take(LIST_SET_INITIALIZED)
  }

  entityList = yield select(entityListSelector)

  return entityList.entityModel
}

export function* loadSearchFilters({payload}) {
  const {model, group} = payload
  const {searchFilter} = yield select(searchFormSelector)
  if (!searchFilter) {
    const params = {
      searchInputs: {
        entity: model,
        ...(group ? {'relSearch_filter_group.unique_id': group} : {})
      },
      fields: ['unique_id']
    }

    const json = yield call(fetchEntities, 'Search_filter', params)
    const entities = yield call(searchFilterTransformer, json)
    yield put(actions.setSearchFilter(entities))
  }

  return searchFilter
}

export function* resetSearch() {
  yield put(formActions.reset('searchForm'))
  yield call(submitSearchFrom)
}

const getFilterArray = v => {
  if (Array.isArray(v)) {
    return v.map(e => e.uniqueId)
  } else {
    return [v.uniqueId]
  }
}

export function* getSearchInputs() {
  const {valuesInitialized} = yield select(searchFormSelector)

  if (!valuesInitialized) {
    yield take(actions.SET_VALUES_INITIALIZED)
  }

  const searchInputs = yield select(searchValuesSelector)
  const {entityModel} = yield select(entityListSelector)

  const searchInputsRenamed = {}
  _forOwn(searchInputs, (value, key) => {
    if (key === 'searchFilter' && value) {
      searchInputsRenamed._filter = getFilterArray(value)
    } else if (key === 'txtFulltext') {
      searchInputsRenamed._search = value
    } else {
      searchInputsRenamed[form.transformFieldNameBack(key)] = value
    }
  })
  return yield call(getSearchInputsForRequest, searchInputsRenamed, entityModel)
}

export function* advancedSearchUpdate({payload: {field, ids}}) {
  yield put(formActions.change(FORM_ID, form.transformFieldName(field), ids))
}
<commit_msg>fix(entity-list): fix search input parent<commit_after>import {call, put, fork, select, takeLatest, take, all} from 'redux-saga/effects'
import {form} from 'tocco-util'
import _reduce from 'lodash/reduce'
import * as actions from './actions'
import {fetchForm, searchFormTransformer} from '../../util/api/forms'
import {getPreselectedValues} from '../../util/searchForm'
import {fetchEntities, searchFilterTransformer} from '../../util/api/entities'

import {SET_INITIALIZED as LIST_SET_INITIALIZED} from '../entityList/actions'
import {
  actions as formActions,
  getFormValues
} from 'redux-form'
import * as formActionTypes from 'redux-form/es/actionTypes'

import _forOwn from 'lodash/forOwn'

import {validateSearchFields} from '../../util/searchFormValidation'
import {getSearchInputsForRequest} from '../../util/searchInputs'

export const inputSelector = state => state.input
export const searchFormSelector = state => state.searchForm
export const entityListSelector = state => state.entityList
export const searchValuesSelector = getFormValues('searchForm')

const FORM_ID = 'searchForm'

export default function* sagas() {
  yield all([
    fork(takeLatest, actions.INITIALIZE, initialize),
    fork(takeLatest, actions.LOAD_SEARCH_FILTERS, loadSearchFilters),
    fork(takeLatest, formActionTypes.CHANGE, submitSearchFrom),
    fork(takeLatest, actions.SUBMIT_SEARCH_FORM, submitSearchFrom),
    fork(takeLatest, actions.RESET_SEARCH, resetSearch),
    fork(takeLatest, actions.ADVANCED_SEARCH_UPDATE, advancedSearchUpdate)
  ])
}

export function* initialize({payload: {searchFormVisible}}) {
  const {searchFormName, initialized} = yield select(searchFormSelector)
  if (!initialized) {
    const formDefinition = searchFormVisible ? yield call(loadSearchForm, searchFormName) : null
    yield call(setInitialFormValues, searchFormVisible, formDefinition)
    yield put(actions.setInitialized())
  }
}

export function* setInitialFormValues(searchFormVisible, formDefinition) {
  const {preselectedSearchFields, parent} = yield select(inputSelector)
  const {model} = yield call(getEntityModel)

  let formValues = preselectedSearchFields
    ? yield call(getPreselectedValues, preselectedSearchFields, model, null, searchFormVisible)
    : {}

  if (parent && !formValues.hasOwnProperty(parent.reverseRelationName)) {
    formValues[parent.reverseRelationName] = {key: parent.key}
  }

  if (searchFormVisible && formDefinition) {
    const fieldDefinitions = yield call(form.getFieldDefinitions, formDefinition)
    const fromDefaultValues = yield call(form.getDefaultValues, fieldDefinitions)
    formValues = {...fromDefaultValues, ...formValues}
  }

  const transformedFromValues = yield call(transformFieldNames, formValues)

  yield put(formActions.initialize(FORM_ID, transformedFromValues))
  yield put(actions.setValuesInitialized(true))
}

export function* transformFieldNames(formValues) {
  return _reduce(formValues, (acc, val, key) => (
    {...acc, [form.transformFieldName(key)]: val}
  ), {})
}

export function* submitSearchFrom() {
  yield put(formActions.startSubmit(FORM_ID))
  const values = yield select(getFormValues(FORM_ID))
  const {formDefinition} = yield select(searchFormSelector)
  const errors = yield call(validateSearchFields, values, formDefinition)
  yield put(formActions.stopSubmit(FORM_ID, errors))

  if (Object.keys(errors).length === 0) {
    yield put(actions.executeSearch())
  }
}

export function* loadSearchForm(searchFormName) {
  const formDefinition = yield call(fetchForm, searchFormName, searchFormTransformer)
  if (formDefinition) {
    yield put(actions.setFormDefinition(formDefinition))
  } else {
    yield put(actions.setShowFullTextSearchForm(true))
  }
  return formDefinition
}

export function* getEntityModel() {
  let entityList = yield select(entityListSelector)
  if (!entityList.initialized) {
    yield take(LIST_SET_INITIALIZED)
  }

  entityList = yield select(entityListSelector)

  return entityList.entityModel
}

export function* loadSearchFilters({payload}) {
  const {model, group} = payload
  const {searchFilter} = yield select(searchFormSelector)
  if (!searchFilter) {
    const params = {
      searchInputs: {
        entity: model,
        ...(group ? {'relSearch_filter_group.unique_id': group} : {})
      },
      fields: ['unique_id']
    }

    const json = yield call(fetchEntities, 'Search_filter', params)
    const entities = yield call(searchFilterTransformer, json)
    yield put(actions.setSearchFilter(entities))
  }

  return searchFilter
}

export function* resetSearch() {
  yield put(formActions.reset('searchForm'))
  yield call(submitSearchFrom)
}

const getFilterArray = v => {
  if (Array.isArray(v)) {
    return v.map(e => e.uniqueId)
  } else {
    return [v.uniqueId]
  }
}

export function* getSearchInputs() {
  const {valuesInitialized} = yield select(searchFormSelector)

  if (!valuesInitialized) {
    yield take(actions.SET_VALUES_INITIALIZED)
  }

  const searchInputs = yield select(searchValuesSelector)
  const {entityModel} = yield select(entityListSelector)

  const searchInputsRenamed = {}
  _forOwn(searchInputs, (value, key) => {
    if (key === 'searchFilter' && value) {
      searchInputsRenamed._filter = getFilterArray(value)
    } else if (key === 'txtFulltext') {
      searchInputsRenamed._search = value
    } else {
      searchInputsRenamed[form.transformFieldNameBack(key)] = value
    }
  })
  return yield call(getSearchInputsForRequest, searchInputsRenamed, entityModel)
}

export function* advancedSearchUpdate({payload: {field, ids}}) {
  yield put(formActions.change(FORM_ID, form.transformFieldName(field), ids))
}
<|endoftext|>


<commit_before>import {call, put, fork, select, takeLatest, take, all} from 'redux-saga/effects'
import {form} from 'tocco-util'
import _reduce from 'lodash/reduce'
import * as actions from './actions'
import {fetchForm, searchFormTransformer} from '../../util/api/forms'
import {getPreselectedValues} from '../../util/searchForm'
import {fetchEntities, searchFilterTransformer} from '../../util/api/entities'

import {SET_INITIALIZED as LIST_SET_INITIALIZED} from '../entityList/actions'
import {
  actions as formActions,
  getFormValues
} from 'redux-form'
import * as formActionTypes from 'redux-form/es/actionTypes'

import _forOwn from 'lodash/forOwn'

import {validateSearchFields} from '../../util/searchFormValidation'
import {getSearchInputsForRequest} from '../../util/searchInputs'

export const inputSelector = state => state.input
export const searchFormSelector = state => state.searchForm
export const entityListSelector = state => state.entityList
export const searchValuesSelector = getFormValues('searchForm')

const FORM_ID = 'searchForm'

export default function* sagas() {
  yield all([
    fork(takeLatest, actions.INITIALIZE, initialize),
    fork(takeLatest, actions.LOAD_SEARCH_FILTERS, loadSearchFilters),
    fork(takeLatest, formActionTypes.CHANGE, submitSearchFrom),
    fork(takeLatest, actions.SUBMIT_SEARCH_FORM, submitSearchFrom),
    fork(takeLatest, actions.RESET_SEARCH, resetSearch),
    fork(takeLatest, actions.ADVANCED_SEARCH_UPDATE, advancedSearchUpdate)
  ])
}

export function* initialize({payload: {searchFormVisible}}) {
  const {searchFormName, initialized} = yield select(searchFormSelector)
  if (!initialized) {
    const formDefinition = searchFormVisible ? yield call(loadSearchForm, searchFormName) : null
    yield call(setInitialFormValues, searchFormVisible, formDefinition)
    yield put(actions.setInitialized())
  }
}

export function* setInitialFormValues(searchFormVisible, formDefinition) {
  const {preselectedSearchFields, parent} = yield select(inputSelector)
  const {model} = yield call(getEntityModel)

  let formValues = preselectedSearchFields
    ? yield call(getPreselectedValues, preselectedSearchFields, model, null, searchFormVisible)
    : {}

  if (parent && !formValues.hasOwnProperty(parent.reverseRelationName)) {
    formValues[parent.reverseRelationName] = parent.key
  }

  if (searchFormVisible && formDefinition) {
    const fieldDefinitions = yield call(form.getFieldDefinitions, formDefinition)
    const fromDefaultValues = yield call(form.getDefaultValues, fieldDefinitions)
    formValues = {...fromDefaultValues, ...formValues}
  }

  const transformedFromValues = yield call(transformFieldNames, formValues)

  yield put(formActions.initialize(FORM_ID, transformedFromValues))
  yield put(actions.setValuesInitialized(true))
}

export function* transformFieldNames(formValues) {
  return _reduce(formValues, (acc, val, key) => (
    {...acc, [form.transformFieldName(key)]: val}
  ), {})
}

export function* submitSearchFrom() {
  yield put(formActions.startSubmit(FORM_ID))
  const values = yield select(getFormValues(FORM_ID))
  const {formDefinition} = yield select(searchFormSelector)
  const errors = yield call(validateSearchFields, values, formDefinition)
  yield put(formActions.stopSubmit(FORM_ID, errors))

  if (Object.keys(errors).length === 0) {
    yield put(actions.executeSearch())
  }
}

export function* loadSearchForm(searchFormName) {
  const formDefinition = yield call(fetchForm, searchFormName, searchFormTransformer)
  if (formDefinition !== null) {
    yield put(actions.setFormDefinition(formDefinition))
  } else {
    yield put(actions.setShowFullTextSearchForm(true))
  }
  return formDefinition
}

export function* getEntityModel() {
  let entityList = yield select(entityListSelector)
  if (!entityList.initialized) {
    yield take(LIST_SET_INITIALIZED)
  }

  entityList = yield select(entityListSelector)

  return entityList.entityModel
}

export function* loadSearchFilters({payload}) {
  const {model, group} = payload
  const {searchFilter} = yield select(searchFormSelector)
  if (!searchFilter) {
    const params = {
      searchInputs: {
        entity: model,
        ...(group ? {'relSearch_filter_group.unique_id': group} : {})
      },
      fields: ['unique_id']
    }

    const json = yield call(fetchEntities, 'Search_filter', params)
    const entities = yield call(searchFilterTransformer, json)
    yield put(actions.setSearchFilter(entities))
  }

  return searchFilter
}

export function* resetSearch() {
  yield put(formActions.reset('searchForm'))
  yield call(submitSearchFrom)
}

const getFilterArray = v => {
  if (Array.isArray(v)) {
    return v.map(e => e.uniqueId)
  } else {
    return [v.uniqueId]
  }
}

export function* getSearchInputs() {
  const {valuesInitialized} = yield select(searchFormSelector)

  if (!valuesInitialized) {
    yield take(actions.SET_VALUES_INITIALIZED)
  }

  const searchInputs = yield select(searchValuesSelector)
  const {entityModel} = yield select(entityListSelector)

  const searchInputsRenamed = {}
  _forOwn(searchInputs, (value, key) => {
    if (key === 'searchFilter' && value) {
      searchInputsRenamed._filter = getFilterArray(value)
    } else if (key === 'txtFulltext') {
      searchInputsRenamed._search = value
    } else {
      searchInputsRenamed[form.transformFieldNameBack(key)] = value
    }
  })
  return yield call(getSearchInputsForRequest, searchInputsRenamed, entityModel)
}

export function* advancedSearchUpdate({payload: {field, ids}}) {
  yield put(formActions.change(FORM_ID, form.transformFieldName(field), ids))
}
<commit_msg>refactor(entity-list): check formDefinition for undefined<commit_after>import {call, put, fork, select, takeLatest, take, all} from 'redux-saga/effects'
import {form} from 'tocco-util'
import _reduce from 'lodash/reduce'
import * as actions from './actions'
import {fetchForm, searchFormTransformer} from '../../util/api/forms'
import {getPreselectedValues} from '../../util/searchForm'
import {fetchEntities, searchFilterTransformer} from '../../util/api/entities'

import {SET_INITIALIZED as LIST_SET_INITIALIZED} from '../entityList/actions'
import {
  actions as formActions,
  getFormValues
} from 'redux-form'
import * as formActionTypes from 'redux-form/es/actionTypes'

import _forOwn from 'lodash/forOwn'

import {validateSearchFields} from '../../util/searchFormValidation'
import {getSearchInputsForRequest} from '../../util/searchInputs'

export const inputSelector = state => state.input
export const searchFormSelector = state => state.searchForm
export const entityListSelector = state => state.entityList
export const searchValuesSelector = getFormValues('searchForm')

const FORM_ID = 'searchForm'

export default function* sagas() {
  yield all([
    fork(takeLatest, actions.INITIALIZE, initialize),
    fork(takeLatest, actions.LOAD_SEARCH_FILTERS, loadSearchFilters),
    fork(takeLatest, formActionTypes.CHANGE, submitSearchFrom),
    fork(takeLatest, actions.SUBMIT_SEARCH_FORM, submitSearchFrom),
    fork(takeLatest, actions.RESET_SEARCH, resetSearch),
    fork(takeLatest, actions.ADVANCED_SEARCH_UPDATE, advancedSearchUpdate)
  ])
}

export function* initialize({payload: {searchFormVisible}}) {
  const {searchFormName, initialized} = yield select(searchFormSelector)
  if (!initialized) {
    const formDefinition = searchFormVisible ? yield call(loadSearchForm, searchFormName) : null
    yield call(setInitialFormValues, searchFormVisible, formDefinition)
    yield put(actions.setInitialized())
  }
}

export function* setInitialFormValues(searchFormVisible, formDefinition) {
  const {preselectedSearchFields, parent} = yield select(inputSelector)
  const {model} = yield call(getEntityModel)

  let formValues = preselectedSearchFields
    ? yield call(getPreselectedValues, preselectedSearchFields, model, null, searchFormVisible)
    : {}

  if (parent && !formValues.hasOwnProperty(parent.reverseRelationName)) {
    formValues[parent.reverseRelationName] = parent.key
  }

  if (searchFormVisible && formDefinition) {
    const fieldDefinitions = yield call(form.getFieldDefinitions, formDefinition)
    const fromDefaultValues = yield call(form.getDefaultValues, fieldDefinitions)
    formValues = {...fromDefaultValues, ...formValues}
  }

  const transformedFromValues = yield call(transformFieldNames, formValues)

  yield put(formActions.initialize(FORM_ID, transformedFromValues))
  yield put(actions.setValuesInitialized(true))
}

export function* transformFieldNames(formValues) {
  return _reduce(formValues, (acc, val, key) => (
    {...acc, [form.transformFieldName(key)]: val}
  ), {})
}

export function* submitSearchFrom() {
  yield put(formActions.startSubmit(FORM_ID))
  const values = yield select(getFormValues(FORM_ID))
  const {formDefinition} = yield select(searchFormSelector)
  const errors = yield call(validateSearchFields, values, formDefinition)
  yield put(formActions.stopSubmit(FORM_ID, errors))

  if (Object.keys(errors).length === 0) {
    yield put(actions.executeSearch())
  }
}

export function* loadSearchForm(searchFormName) {
  const formDefinition = yield call(fetchForm, searchFormName, searchFormTransformer)
  if (formDefinition) {
    yield put(actions.setFormDefinition(formDefinition))
  } else {
    yield put(actions.setShowFullTextSearchForm(true))
  }
  return formDefinition
}

export function* getEntityModel() {
  let entityList = yield select(entityListSelector)
  if (!entityList.initialized) {
    yield take(LIST_SET_INITIALIZED)
  }

  entityList = yield select(entityListSelector)

  return entityList.entityModel
}

export function* loadSearchFilters({payload}) {
  const {model, group} = payload
  const {searchFilter} = yield select(searchFormSelector)
  if (!searchFilter) {
    const params = {
      searchInputs: {
        entity: model,
        ...(group ? {'relSearch_filter_group.unique_id': group} : {})
      },
      fields: ['unique_id']
    }

    const json = yield call(fetchEntities, 'Search_filter', params)
    const entities = yield call(searchFilterTransformer, json)
    yield put(actions.setSearchFilter(entities))
  }

  return searchFilter
}

export function* resetSearch() {
  yield put(formActions.reset('searchForm'))
  yield call(submitSearchFrom)
}

const getFilterArray = v => {
  if (Array.isArray(v)) {
    return v.map(e => e.uniqueId)
  } else {
    return [v.uniqueId]
  }
}

export function* getSearchInputs() {
  const {valuesInitialized} = yield select(searchFormSelector)

  if (!valuesInitialized) {
    yield take(actions.SET_VALUES_INITIALIZED)
  }

  const searchInputs = yield select(searchValuesSelector)
  const {entityModel} = yield select(entityListSelector)

  const searchInputsRenamed = {}
  _forOwn(searchInputs, (value, key) => {
    if (key === 'searchFilter' && value) {
      searchInputsRenamed._filter = getFilterArray(value)
    } else if (key === 'txtFulltext') {
      searchInputsRenamed._search = value
    } else {
      searchInputsRenamed[form.transformFieldNameBack(key)] = value
    }
  })
  return yield call(getSearchInputsForRequest, searchInputsRenamed, entityModel)
}

export function* advancedSearchUpdate({payload: {field, ids}}) {
  yield put(formActions.change(FORM_ID, form.transformFieldName(field), ids))
}
<|endoftext|>


<commit_before>import React from 'react'
import { storiesOf } from '@storybook/react'
import Button from 'fyndiq-component-button'
import { Message, Wrapper, addMessage } from 'fyndiq-component-message'
import { Error, Truck, Warning } from 'fyndiq-icons'

storiesOf('Message', module)
  .addWithInfo('default', () => <Message>Content</Message>)
  .addWithInfo('color themes', () => (

        <Message icon={<Truck />}>Type info</Message>

        <Message icon={<Truck />} type="confirm">
          Type confirm
        </Message>

        <Message icon={<Warning />} type="warn">
          Type warn
        </Message>

        <Message icon={<Error />} type="error">
          Type error
        </Message>

  ))
  .addWithInfo('action', () => (

      <Wrapper />
      <Button
        onClick={() =>
          addMessage(
            <Message icon={<Truck />} type="confirm">
              Type confirm {Math.random()}
            </Message>,
          )
        }
      >
        Show message
      </Button>

  ))
<commit_msg>:notebook: Improve Message storybook demo<commit_after>import React from 'react'
import { storiesOf } from '@storybook/react'
import Button, { Wrapper as ButtonWrapper } from 'fyndiq-component-button'
import { Message, Wrapper, addMessage } from 'fyndiq-component-message'
import { Star, Error, Truck, Warning, Checkmark } from 'fyndiq-icons'

storiesOf('Message', module)
  .addWithInfo('default', () => <Message>Content</Message>)
  .addWithInfo('color themes', () => (

        <Message icon={<Truck />}>Type info</Message>

        <Message icon={<Checkmark />} type="confirm">
          Type confirm
        </Message>

        <Message icon={<Warning />} type="warn">
          Type warn
        </Message>

        <Message icon={<Error />} type="error">
          Type error
        </Message>

  ))
  .addWithInfo('addMessage utility', () => (
    <React.Fragment>
      <Wrapper />
      <Button
        onClick={() =>
          addMessage(
            <Message icon={<Checkmark />} type="confirm">
              The message has been successfully shown
            </Message>,
          )
        }
      >
        Show message
      </Button>
    </React.Fragment>
  ))
  .addWithInfo('custom timeout', () => (
    <React.Fragment>
      <Wrapper />
      <ButtonWrapper>
        <Button
          onClick={() =>
            addMessage(
              <Message icon={<Warning />} type="warn" timeout={1000}>
                I don't stay very long
              </Message>,
            )
          }
        >
          Show 1s message
        </Button>
        <Button
          onClick={() =>
            addMessage(
              <Message timeout={10000}>You OK if I stay a bit long?</Message>,
            )
          }
        >
          Show 10s message
        </Button>
      </ButtonWrapper>
    </React.Fragment>
  ))
<|endoftext|>


<commit_before>import * as d3 from 'd3';
import _ from 'lodash';
import { t } from '../../util/locale';
import { d3combobox } from '../../lib/d3.combobox.js';
import { services } from '../../services/index';
import {
    utilGetSetValue,
    utilNoAuto,
    utilRebind
} from '../../util';

export {
    uiFieldCombo as uiFieldMultiCombo,
    uiFieldCombo as uiFieldNetworkCombo,
    uiFieldCombo as uiFieldSemiCombo,
    uiFieldCombo as uiFieldTypeCombo
};

export function uiFieldCombo(field, context) {
    var dispatch = d3.dispatch('change'),
        nominatim = services.geocoder,
        taginfo = services.taginfo,
        isMulti = (field.type === 'multiCombo'),
        isNetwork = (field.type === 'networkCombo'),
        isSemi = (field.type === 'semiCombo'),
        optstrings = field.strings && field.strings.options,
        optarray = field.options,
        snake_case = (field.snake_case || (field.snake_case === undefined)),
        combobox = d3combobox().minItems(isMulti || isSemi ? 1 : 2),
        comboData = [],
        multiData = [],
        container,
        input,
        entity,
        country;

    // ensure multiCombo field.key ends with a ':'
    if (isMulti && field.key.match(/:$/) === null) {
        field.key += ':';
    }

    function snake(s) {
        return s.replace(/\s+/g, '_');
    }

    function unsnake(s) {
        return s.replace(/_+/g, ' ');
    }

    function clean(s) {
        return s.split(';')
            .map(function(s) { return s.trim(); })
            .join(';');
    }

    // returns the tag value for a display value
    // (for multiCombo, dval should be the key suffix, not the entire key)
    function tagValue(dval) {
        dval = clean(dval || '');

        if (optstrings) {
            var match = _.find(comboData, function(o) {
                return o.key && clean(o.value) === dval;
            });
            if (match) {
                return match.key;
            }
        }

        if (field.type === 'typeCombo' && !dval) {
            return 'yes';
        }

        return (snake_case ? snake(dval) : dval) || undefined;
    }

    // returns the display value for a tag value
    // (for multiCombo, tval should be the key suffix, not the entire key)
    function displayValue(tval) {
        tval = tval || '';

        if (optstrings) {
            var match = _.find(comboData, function(o) { return o.key === tval && o.value; });
            if (match) {
                return match.value;
            }
        }

        if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
            return '';
        }

        return snake_case ? unsnake(tval) : tval;
    }

    function objectDifference(a, b) {
        return _.reject(a, function(d1) {
            return _.some(b, function(d2) { return d1.value === d2.value; });
        });
    }

    function initCombo(selection, attachTo) {
        if (optstrings) {
            selection.attr('readonly', 'readonly');
            selection.call(combobox, attachTo);
            setStaticValues(setPlaceholder);

        } else if (optarray) {
            selection.call(combobox, attachTo);
            setStaticValues(setPlaceholder);

        } else if (taginfo) {
            selection.call(combobox.fetcher(setTaginfoValues), attachTo);
            setTaginfoValues('', setPlaceholder);
        }
    }

    function setStaticValues(callback) {
        if (!(optstrings || optarray)) return;

        if (optstrings) {
            comboData = Object.keys(optstrings).map(function(k) {
                var v = field.t('options.' + k, { 'default': optstrings[k] });
                return {
                    key: k,
                    value: v,
                    title: v
                };
            });

        } else if (optarray) {
            comboData = optarray.map(function(k) {
                var v = snake_case ? unsnake(k) : k;
                return {
                    key: k,
                    value: v,
                    title: v
                };
            });
        }

        combobox.data(objectDifference(comboData, multiData));
        if (callback) callback(comboData);
    }

    function setTaginfoValues(q, callback) {
        var fn = isMulti ? 'multikeys' : 'values';
        var query = (isMulti ? field.key : '') + q;
        var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
        if (hasCountryPrefix) {
            query = country + ':';
        }

        taginfo[fn]({
            debounce: (q !== ''),
            key: field.key,
            geometry: context.geometry(entity.id),
            query: query
        }, function(err, data) {
            if (err) return;
            if (hasCountryPrefix) {
                data = _.filter(data, function(d) {
                    return d.value.toLowerCase().indexOf(country + ':') === 0;
                });
            }

            comboData = _.map(data, function(d) {
                var k = d.value;
                if (isMulti) k = k.replace(field.key, '');
                var v = snake_case ? unsnake(k) : k;
                return {
                    key: k,
                    value: v,
                    title: isMulti ? v : d.title
                };
            });

            comboData = objectDifference(comboData, multiData);
            if (callback) callback(comboData);
        });
    }

    function setPlaceholder(d) {
        var ph;
        if (isMulti || isSemi) {
            ph = field.placeholder() || t('inspector.add');
        } else {
            var vals = _.map(d, 'value').filter(function(s) { return s.length < 20; }),
                placeholders = vals.length > 1 ? vals : _.map(d, 'key');
            ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
        }

        container.selectAll('input')
            .attr('placeholder', ph + '…');
    }

    function change() {
        var val = tagValue(utilGetSetValue(input)),
            t = {};

        if (isMulti || isSemi) {
            if (!val) return;
            container.classed('active', false);
            utilGetSetValue(input, '');
            if (isMulti) {
                field.keys.push(field.key + val);
                t[field.key + val] = 'yes';
            } else if (isSemi) {
                var arr = multiData.map(function(d) { return d.key; });
                arr.push(val);
                t[field.key] = _.compact(_.uniq(arr)).join(';');
            }
            window.setTimeout(function() { input.node().focus(); }, 10);

        } else {
            t[field.key] = val;
        }

        dispatch.call('change', this, t);
    }

    function removeMultikey(d) {
        d3.event.stopPropagation();
        var t = {};
        if (isMulti) {
            t[d.key] = undefined;
        } else if (isSemi) {
            var arr = multiData.map(function(md) { return md.key; });
            arr = _.compact(_.uniq(_.without(arr, d.key)));
            t[field.key] = arr.length ? arr.join(';') : undefined;
        }
        dispatch.call('change', this, t);
    }

    function combo(selection) {
        if (isMulti || isSemi) {
            container = selection.selectAll('ul').data([0]);

            container = container.enter()
                .append('ul')
                .attr('class', 'form-field-multicombo')
                .on('click', function() {
                    window.setTimeout(function() { input.node().focus(); }, 10);
                })
                .merge(container);

        } else {
            container = selection;
        }

        input = container.selectAll('input')
            .data([0]);

        input = input.enter()
            .append('input')
            .attr('type', 'text')
            .attr('id', 'preset-input-' + field.id)
            .call(utilNoAuto)
            .call(initCombo, selection)
            .merge(input);

        if (isNetwork && nominatim && entity) {
            var center = entity.extent(context.graph()).center();
            nominatim.countryCode(center, function (err, code) {
                country = code;
            });
        }

        input
            .on('change', change)
            .on('blur', change);

        if (isMulti || isSemi) {
            combobox
                .on('accept', function() {
                    input.node().blur();
                    input.node().focus();
                });

            input
                .on('focus', function() { container.classed('active', true); });
        }
    }

    combo.tags = function(tags) {
        if (isMulti || isSemi) {
            multiData = [];

            if (isMulti) {
                // Build multiData array containing keys already set..
                Object.keys(tags).forEach(function(key) {
                    if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;

                    var suffix = key.substring(field.key.length);
                    multiData.push({
                        key: key,
                        value: displayValue(suffix)
                    });
                });

                // Set keys for form-field modified (needed for undo and reset buttons)..
                field.keys = _.map(multiData, 'key');

            } else if (isSemi) {
                var arr = _.compact(_.uniq((tags[field.key] || '').split(';')));
                multiData = arr.map(function(key) {
                    return {
                        key: key,
                        value: displayValue(key)
                    };
                });
            }

            // Exclude existing multikeys from combo options..
            var available = objectDifference(comboData, multiData);
            combobox.data(available);

            // Hide 'Add' button if this field uses fixed set of
            // translateable optstrings and they're all currently used..
            container.selectAll('.combobox-input, .combobox-caret')
                .classed('hide', optstrings && !available.length);

            // Render chips
            var chips = container.selectAll('.chips')
                .data(multiData);

            chips.exit()
                .remove();

            var enter = chips.enter()
                .insert('li', 'input')
                .attr('class', 'chips');

            enter.append('span');
            enter.append('a');

            chips = chips.merge(enter);

            chips.select('span')
                .text(function(d) { return d.value; });

            chips.select('a')
                .on('click', removeMultikey)
                .attr('class', 'remove')
                .text('×');

        } else {
            utilGetSetValue(input, displayValue(tags[field.key]));
        }
    };

    combo.focus = function() {
        input.node().focus();
    };

    combo.entity = function(_) {
        if (!arguments.length) return entity;
        entity = _;
        return combo;
    };

    return utilRebind(combo, dispatch, 'on');
}
<commit_msg>Make sure multiData array is updated when item is removed<commit_after>import * as d3 from 'd3';
import _ from 'lodash';
import { t } from '../../util/locale';
import { d3combobox } from '../../lib/d3.combobox.js';
import { services } from '../../services/index';
import {
    utilGetSetValue,
    utilNoAuto,
    utilRebind
} from '../../util';

export {
    uiFieldCombo as uiFieldMultiCombo,
    uiFieldCombo as uiFieldNetworkCombo,
    uiFieldCombo as uiFieldSemiCombo,
    uiFieldCombo as uiFieldTypeCombo
};

export function uiFieldCombo(field, context) {
    var dispatch = d3.dispatch('change'),
        nominatim = services.geocoder,
        taginfo = services.taginfo,
        isMulti = (field.type === 'multiCombo'),
        isNetwork = (field.type === 'networkCombo'),
        isSemi = (field.type === 'semiCombo'),
        optstrings = field.strings && field.strings.options,
        optarray = field.options,
        snake_case = (field.snake_case || (field.snake_case === undefined)),
        combobox = d3combobox().minItems(isMulti || isSemi ? 1 : 2),
        comboData = [],
        multiData = [],
        container,
        input,
        entity,
        country;

    // ensure multiCombo field.key ends with a ':'
    if (isMulti && field.key.match(/:$/) === null) {
        field.key += ':';
    }

    function snake(s) {
        return s.replace(/\s+/g, '_');
    }

    function unsnake(s) {
        return s.replace(/_+/g, ' ');
    }

    function clean(s) {
        return s.split(';')
            .map(function(s) { return s.trim(); })
            .join(';');
    }

    // returns the tag value for a display value
    // (for multiCombo, dval should be the key suffix, not the entire key)
    function tagValue(dval) {
        dval = clean(dval || '');

        if (optstrings) {
            var match = _.find(comboData, function(o) {
                return o.key && clean(o.value) === dval;
            });
            if (match) {
                return match.key;
            }
        }

        if (field.type === 'typeCombo' && !dval) {
            return 'yes';
        }

        return (snake_case ? snake(dval) : dval) || undefined;
    }

    // returns the display value for a tag value
    // (for multiCombo, tval should be the key suffix, not the entire key)
    function displayValue(tval) {
        tval = tval || '';

        if (optstrings) {
            var match = _.find(comboData, function(o) { return o.key === tval && o.value; });
            if (match) {
                return match.value;
            }
        }

        if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
            return '';
        }

        return snake_case ? unsnake(tval) : tval;
    }

    function objectDifference(a, b) {
        return _.reject(a, function(d1) {
            return _.some(b, function(d2) { return d1.value === d2.value; });
        });
    }

    function initCombo(selection, attachTo) {
        if (optstrings) {
            selection.attr('readonly', 'readonly');
            selection.call(combobox, attachTo);
            setStaticValues(setPlaceholder);

        } else if (optarray) {
            selection.call(combobox, attachTo);
            setStaticValues(setPlaceholder);

        } else if (taginfo) {
            selection.call(combobox.fetcher(setTaginfoValues), attachTo);
            setTaginfoValues('', setPlaceholder);
        }
    }

    function setStaticValues(callback) {
        if (!(optstrings || optarray)) return;

        if (optstrings) {
            comboData = Object.keys(optstrings).map(function(k) {
                var v = field.t('options.' + k, { 'default': optstrings[k] });
                return {
                    key: k,
                    value: v,
                    title: v
                };
            });

        } else if (optarray) {
            comboData = optarray.map(function(k) {
                var v = snake_case ? unsnake(k) : k;
                return {
                    key: k,
                    value: v,
                    title: v
                };
            });
        }

        combobox.data(objectDifference(comboData, multiData));
        if (callback) callback(comboData);
    }

    function setTaginfoValues(q, callback) {
        var fn = isMulti ? 'multikeys' : 'values';
        var query = (isMulti ? field.key : '') + q;
        var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
        if (hasCountryPrefix) {
            query = country + ':';
        }

        taginfo[fn]({
            debounce: (q !== ''),
            key: field.key,
            geometry: context.geometry(entity.id),
            query: query
        }, function(err, data) {
            if (err) return;
            if (hasCountryPrefix) {
                data = _.filter(data, function(d) {
                    return d.value.toLowerCase().indexOf(country + ':') === 0;
                });
            }

            comboData = _.map(data, function(d) {
                var k = d.value;
                if (isMulti) k = k.replace(field.key, '');
                var v = snake_case ? unsnake(k) : k;
                return {
                    key: k,
                    value: v,
                    title: isMulti ? v : d.title
                };
            });

            comboData = objectDifference(comboData, multiData);
            if (callback) callback(comboData);
        });
    }

    function setPlaceholder(d) {
        var ph;
        if (isMulti || isSemi) {
            ph = field.placeholder() || t('inspector.add');
        } else {
            var vals = _.map(d, 'value').filter(function(s) { return s.length < 20; }),
                placeholders = vals.length > 1 ? vals : _.map(d, 'key');
            ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
        }

        container.selectAll('input')
            .attr('placeholder', ph + '…');
    }

    function change() {
        var val = tagValue(utilGetSetValue(input)),
            t = {};

        if (isMulti || isSemi) {
            if (!val) return;
            container.classed('active', false);
            utilGetSetValue(input, '');
            if (isMulti) {
                field.keys.push(field.key + val);
                t[field.key + val] = 'yes';
            } else if (isSemi) {
                var arr = multiData.map(function(d) { return d.key; });
                arr.push(val);
                t[field.key] = _.compact(_.uniq(arr)).join(';');
            }
            window.setTimeout(function() { input.node().focus(); }, 10);

        } else {
            t[field.key] = val;
        }

        dispatch.call('change', this, t);
    }

    function removeMultikey(d) {
        d3.event.stopPropagation();
        var t = {};
        if (isMulti) {
            t[d.key] = undefined;
        } else if (isSemi) {
            _.remove(multiData, function(md) { return md.key === d.key; });
            var arr = multiData.map(function(md) { return md.key; });
            arr = _.compact(_.uniq(arr));
            t[field.key] = arr.length ? arr.join(';') : undefined;
        }
        dispatch.call('change', this, t);
    }

    function combo(selection) {
        if (isMulti || isSemi) {
            container = selection.selectAll('ul').data([0]);

            container = container.enter()
                .append('ul')
                .attr('class', 'form-field-multicombo')
                .on('click', function() {
                    window.setTimeout(function() { input.node().focus(); }, 10);
                })
                .merge(container);

        } else {
            container = selection;
        }

        input = container.selectAll('input')
            .data([0]);

        input = input.enter()
            .append('input')
            .attr('type', 'text')
            .attr('id', 'preset-input-' + field.id)
            .call(utilNoAuto)
            .call(initCombo, selection)
            .merge(input);

        if (isNetwork && nominatim && entity) {
            var center = entity.extent(context.graph()).center();
            nominatim.countryCode(center, function (err, code) {
                country = code;
            });
        }

        input
            .on('change', change)
            .on('blur', change);

        if (isMulti || isSemi) {
            combobox
                .on('accept', function() {
                    input.node().blur();
                    input.node().focus();
                });

            input
                .on('focus', function() { container.classed('active', true); });
        }
    }

    combo.tags = function(tags) {
        if (isMulti || isSemi) {
            multiData = [];

            if (isMulti) {
                // Build multiData array containing keys already set..
                Object.keys(tags).forEach(function(key) {
                    if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;

                    var suffix = key.substring(field.key.length);
                    multiData.push({
                        key: key,
                        value: displayValue(suffix)
                    });
                });

                // Set keys for form-field modified (needed for undo and reset buttons)..
                field.keys = _.map(multiData, 'key');

            } else if (isSemi) {
                var arr = _.compact(_.uniq((tags[field.key] || '').split(';')));
                multiData = arr.map(function(key) {
                    return {
                        key: key,
                        value: displayValue(key)
                    };
                });
            }

            // Exclude existing multikeys from combo options..
            var available = objectDifference(comboData, multiData);
            combobox.data(available);

            // Hide 'Add' button if this field uses fixed set of
            // translateable optstrings and they're all currently used..
            container.selectAll('.combobox-input, .combobox-caret')
                .classed('hide', optstrings && !available.length);

            // Render chips
            var chips = container.selectAll('.chips')
                .data(multiData);

            chips.exit()
                .remove();

            var enter = chips.enter()
                .insert('li', 'input')
                .attr('class', 'chips');

            enter.append('span');
            enter.append('a');

            chips = chips.merge(enter);

            chips.select('span')
                .text(function(d) { return d.value; });

            chips.select('a')
                .on('click', removeMultikey)
                .attr('class', 'remove')
                .text('×');

        } else {
            utilGetSetValue(input, displayValue(tags[field.key]));
        }
    };

    combo.focus = function() {
        input.node().focus();
    };

    combo.entity = function(_) {
        if (!arguments.length) return entity;
        entity = _;
        return combo;
    };

    return utilRebind(combo, dispatch, 'on');
}
<|endoftext|>


<commit_before>'use strict'

const path = require('path')
const os = require('os')
const fs = require('fs')

const projectRoot = path.join(__dirname, '..')
const appPackage = require(path.join(projectRoot, 'app', 'package.json'))

function getDistPath() {
  return path.join(
    projectRoot,
    'dist',
    `${getExecutableName()}-${process.platform}-x64`
  )
}

function getExecutableName() {
  const suffix = process.env.NODE_ENV === 'development' ? '-dev' : ''

  return process.platform === 'win32'
    ? `${getWindowsIdentifierName()}${suffix}`
    : getProductName()
}

function getProductName() {
  const productName = appPackage.productName
  return process.env.NODE_ENV === 'development'
    ? `${productName}-dev`
    : productName
}

function getCompanyName() {
  return appPackage.companyName
}

function getVersion() {
  return appPackage.version
}

function getOSXZipName() {
  const productName = getProductName()
  return `${productName}-macos.zip`
}

function getOSXZipPath() {
  return path.join(getDistPath(), '..', getOSXZipName())
}

function getWindowsInstallerName() {
  const productName = getExecutableName()
  return `${productName}Setup.msi`
}

function getWindowsInstallerPath() {
  return path.join(getDistPath(), '..', 'installer', getWindowsInstallerName())
}

function getWindowsStandaloneName() {
  const productName = getExecutableName()
  return `${productName}Setup.exe`
}

function getWindowsStandalonePath() {
  return path.join(getDistPath(), '..', 'installer', getWindowsStandaloneName())
}

function getWindowsFullNugetPackageName() {
  return `${getWindowsIdentifierName()}-${getVersion()}-full.nupkg`
}

function getWindowsFullNugetPackagePath() {
  return path.join(
    getDistPath(),
    '..',
    'installer',
    getWindowsFullNugetPackageName()
  )
}

function getWindowsDeltaNugetPackageName() {
  return `${getWindowsIdentifierName()}-${getVersion()}-delta.nupkg`
}

function getWindowsDeltaNugetPackagePath() {
  return path.join(
    getDistPath(),
    '..',
    'installer',
    getWindowsDeltaNugetPackageName()
  )
}

function getBundleID() {
  return appPackage.bundleID
}

function getUserDataPath() {
  if (process.platform === 'win32') {
    return path.join(process.env.APPDATA, getExecutableName())
  } else if (process.platform === 'darwin') {
    const home = os.homedir()
    return path.join(home, 'Library', 'Application Support', getProductName())
  } else if (process.platform === 'linux') {
    if (process.env.XDG_CONFIG_HOME) {
      return path.join(process.env.XDG_CONFIG_HOME, getProductName())
    }
    const home = os.homedir()
    return path.join(home, '.config', getProductName())
  } else {
    console.error(
      `I dunno how to resolve the user data path for ${process.platform} ${process.arch} :(`
    )
    process.exit(1)
  }
}

function getWindowsIdentifierName() {
  return 'Kactus'
}

function getBundleSizes() {
  const rendererStats = fs.statSync(
    path.join(projectRoot, 'out', 'renderer.js')
  )
  const mainStats = fs.statSync(path.join(projectRoot, 'out', 'main.js'))
  return { rendererSize: rendererStats.size, mainSize: mainStats.size }
}

function getReleaseBranchName() {
  let branchName
  if (process.platform === 'darwin') {
    branchName = process.env.CIRCLE_BRANCH || process.env.TRAVIS_BRANCH
  } else if (process.platform === 'win32') {
    branchName = process.env.APPVEYOR_REPO_BRANCH
  }

  return branchName || ''
}

function getReleaseChannel() {
  // Branch name format: __release-CHANNEL-DEPLOY_ID
  const pieces = getReleaseBranchName().split('-')
  if (pieces.length < 3 || pieces[0] !== '__release') {
    return process.env.NODE_ENV || 'development'
  }

  return pieces[1]
}

function getReleaseSHA() {
  // Branch name format: __release-CHANNEL-DEPLOY_ID
  const pieces = getReleaseBranchName().split('-')
  if (pieces.length < 3 || pieces[0] !== '__release') {
    return null
  }

  return pieces[2]
}

function getUpdatesURL() {
  return `https://kactus-autoupdater.herokuapp.com/update/osx/${getVersion()}`
}

function shouldMakeDelta() {
  // Only production and beta channels include deltas. Test releases aren't
  // necessarily sequential so deltas wouldn't make sense.
  const channelsWithDeltas = ['production', 'beta']
  return channelsWithDeltas.indexOf(getReleaseChannel()) > -1
}

/**
 * Attempt to dereference the given ref without requiring a Git environment
 * to be present. Note that this method will not be able to dereference packed
 * refs but should suffice for simple refs like 'HEAD'.
 *
 * Will throw an error for unborn HEAD.
 *
 * @param {string} gitDir The path to the Git repository's .git directory
 * @param {string} ref    A qualified git ref such as 'HEAD' or 'refs/heads/master'
 */
function revParse(gitDir, ref) {
  const refPath = path.join(gitDir, ref)
  const refContents = fs.readFileSync(refPath)
  const refRe = /^([a-f0-9]{40})|(?:ref: (refs\/.*))$/m
  const refMatch = refRe.exec(refContents)

  if (!refMatch) {
    throw new Error(
      `Could not de-reference HEAD to SHA, invalid ref in ${refPath}: ${refContents}`
    )
  }

  return refMatch[1] || revParse(gitDir, refMatch[2])
}

function getSHA() {
  // CircleCI does some funny stuff where HEAD points to an packed ref, but
  // luckily it gives us the SHA we want in the environment.
  const circleSHA = process.env.CIRCLE_SHA1 || process.env.TRAVIS_COMMIT
  if (circleSHA) {
    return circleSHA
  }

  return revParse(path.resolve(__dirname, '../.git'), 'HEAD')
}

module.exports = {
  getDistPath,
  getProductName,
  getCompanyName,
  getVersion,
  getOSXZipName,
  getOSXZipPath,
  getWindowsInstallerName,
  getWindowsInstallerPath,
  getWindowsStandaloneName,
  getWindowsStandalonePath,
  getWindowsFullNugetPackageName,
  getWindowsFullNugetPackagePath,
  getBundleID,
  getUserDataPath,
  getWindowsIdentifierName,
  getBundleSizes,
  getReleaseChannel,
  getReleaseSHA,
  getUpdatesURL,
  getWindowsDeltaNugetPackageName,
  getWindowsDeltaNugetPackagePath,
  shouldMakeDelta,
  getReleaseBranchName,
  getExecutableName,
  getSHA,
}
<commit_msg>log branch name<commit_after>'use strict'

const path = require('path')
const os = require('os')
const fs = require('fs')

const projectRoot = path.join(__dirname, '..')
const appPackage = require(path.join(projectRoot, 'app', 'package.json'))

function getDistPath() {
  return path.join(
    projectRoot,
    'dist',
    `${getExecutableName()}-${process.platform}-x64`
  )
}

function getExecutableName() {
  const suffix = process.env.NODE_ENV === 'development' ? '-dev' : ''

  return process.platform === 'win32'
    ? `${getWindowsIdentifierName()}${suffix}`
    : getProductName()
}

function getProductName() {
  const productName = appPackage.productName
  return process.env.NODE_ENV === 'development'
    ? `${productName}-dev`
    : productName
}

function getCompanyName() {
  return appPackage.companyName
}

function getVersion() {
  return appPackage.version
}

function getOSXZipName() {
  const productName = getProductName()
  return `${productName}-macos.zip`
}

function getOSXZipPath() {
  return path.join(getDistPath(), '..', getOSXZipName())
}

function getWindowsInstallerName() {
  const productName = getExecutableName()
  return `${productName}Setup.msi`
}

function getWindowsInstallerPath() {
  return path.join(getDistPath(), '..', 'installer', getWindowsInstallerName())
}

function getWindowsStandaloneName() {
  const productName = getExecutableName()
  return `${productName}Setup.exe`
}

function getWindowsStandalonePath() {
  return path.join(getDistPath(), '..', 'installer', getWindowsStandaloneName())
}

function getWindowsFullNugetPackageName() {
  return `${getWindowsIdentifierName()}-${getVersion()}-full.nupkg`
}

function getWindowsFullNugetPackagePath() {
  return path.join(
    getDistPath(),
    '..',
    'installer',
    getWindowsFullNugetPackageName()
  )
}

function getWindowsDeltaNugetPackageName() {
  return `${getWindowsIdentifierName()}-${getVersion()}-delta.nupkg`
}

function getWindowsDeltaNugetPackagePath() {
  return path.join(
    getDistPath(),
    '..',
    'installer',
    getWindowsDeltaNugetPackageName()
  )
}

function getBundleID() {
  return appPackage.bundleID
}

function getUserDataPath() {
  if (process.platform === 'win32') {
    return path.join(process.env.APPDATA, getExecutableName())
  } else if (process.platform === 'darwin') {
    const home = os.homedir()
    return path.join(home, 'Library', 'Application Support', getProductName())
  } else if (process.platform === 'linux') {
    if (process.env.XDG_CONFIG_HOME) {
      return path.join(process.env.XDG_CONFIG_HOME, getProductName())
    }
    const home = os.homedir()
    return path.join(home, '.config', getProductName())
  } else {
    console.error(
      `I dunno how to resolve the user data path for ${process.platform} ${process.arch} :(`
    )
    process.exit(1)
  }
}

function getWindowsIdentifierName() {
  return 'Kactus'
}

function getBundleSizes() {
  const rendererStats = fs.statSync(
    path.join(projectRoot, 'out', 'renderer.js')
  )
  const mainStats = fs.statSync(path.join(projectRoot, 'out', 'main.js'))
  return { rendererSize: rendererStats.size, mainSize: mainStats.size }
}

function getReleaseBranchName() {
  let branchName
  if (process.platform === 'darwin') {
    branchName = process.env.CIRCLE_BRANCH || process.env.TRAVIS_BRANCH
  } else if (process.platform === 'win32') {
    branchName = process.env.APPVEYOR_REPO_BRANCH
  }

  console.log(branchName)

  return branchName || ''
}

function getReleaseChannel() {
  // Branch name format: __release-CHANNEL-DEPLOY_ID
  const pieces = getReleaseBranchName().split('-')
  if (pieces.length < 3 || pieces[0] !== '__release') {
    return process.env.NODE_ENV || 'development'
  }

  return pieces[1]
}

function getReleaseSHA() {
  // Branch name format: __release-CHANNEL-DEPLOY_ID
  const pieces = getReleaseBranchName().split('-')
  if (pieces.length < 3 || pieces[0] !== '__release') {
    return null
  }

  return pieces[2]
}

function getUpdatesURL() {
  return `https://kactus-autoupdater.herokuapp.com/update/osx/${getVersion()}`
}

function shouldMakeDelta() {
  // Only production and beta channels include deltas. Test releases aren't
  // necessarily sequential so deltas wouldn't make sense.
  const channelsWithDeltas = ['production', 'beta']
  return channelsWithDeltas.indexOf(getReleaseChannel()) > -1
}

/**
 * Attempt to dereference the given ref without requiring a Git environment
 * to be present. Note that this method will not be able to dereference packed
 * refs but should suffice for simple refs like 'HEAD'.
 *
 * Will throw an error for unborn HEAD.
 *
 * @param {string} gitDir The path to the Git repository's .git directory
 * @param {string} ref    A qualified git ref such as 'HEAD' or 'refs/heads/master'
 */
function revParse(gitDir, ref) {
  const refPath = path.join(gitDir, ref)
  const refContents = fs.readFileSync(refPath)
  const refRe = /^([a-f0-9]{40})|(?:ref: (refs\/.*))$/m
  const refMatch = refRe.exec(refContents)

  if (!refMatch) {
    throw new Error(
      `Could not de-reference HEAD to SHA, invalid ref in ${refPath}: ${refContents}`
    )
  }

  return refMatch[1] || revParse(gitDir, refMatch[2])
}

function getSHA() {
  // CircleCI does some funny stuff where HEAD points to an packed ref, but
  // luckily it gives us the SHA we want in the environment.
  const circleSHA = process.env.CIRCLE_SHA1 || process.env.TRAVIS_COMMIT
  if (circleSHA) {
    return circleSHA
  }

  return revParse(path.resolve(__dirname, '../.git'), 'HEAD')
}

module.exports = {
  getDistPath,
  getProductName,
  getCompanyName,
  getVersion,
  getOSXZipName,
  getOSXZipPath,
  getWindowsInstallerName,
  getWindowsInstallerPath,
  getWindowsStandaloneName,
  getWindowsStandalonePath,
  getWindowsFullNugetPackageName,
  getWindowsFullNugetPackagePath,
  getBundleID,
  getUserDataPath,
  getWindowsIdentifierName,
  getBundleSizes,
  getReleaseChannel,
  getReleaseSHA,
  getUpdatesURL,
  getWindowsDeltaNugetPackageName,
  getWindowsDeltaNugetPackagePath,
  shouldMakeDelta,
  getReleaseBranchName,
  getExecutableName,
  getSHA,
}
<|endoftext|>


<commit_before>
var Timeline = {
    init: function() {
        $('#bottom .timeline').mousedown(function(event) {
            Timeline.manualUpdate(event);
        });
        $('#bottom .timeline .slider .knob').mousedown(function(event) {
            Timeline.startDrag(event);
        });
        $(window).mouseup(function(event) {
            Timeline.stopDrag(event);
        });
        $(window).mousemove(function(event) {
            Timeline.onDrag(event);
        });
    },
    isDragging: false,
    updateHandle: null,
    startDrag: function(event) {
        Timeline.isDragging = true;
    },
    stopDrag: function(event) {
        if (Timeline.isDragging) {
            Timeline.stop();
            Timeline.isDragging = false;
            Timeline.manualUpdate(event);
            Timeline.start();
        }
    },
    onDrag: function(event) {
        if (!Timeline.isDragging) {
            return;
        }
        Timeline.manualUpdate(event);
    },
	start: function() {
		if (!Player.assertPlayerLoaded()) {
			return;
		}

		$('#bottom .timeline .knob').show();
		Timeline.updateHandle = setInterval(Timeline.update, 100);
	},
    manualUpdate: function(event) {
        if (!Player.assertPlayerLoaded()) {
			return;
		}

        var maxWidth = $('#bottom .timeline').width(),
            mouseX = event.pageX - $('#bottom .timeline .slider').offset().left,
            pos = null,
            len = Player._player.getDuration();

        if (mouseX < 0) {
            mouseX = 0;
        }
        if (mouseX > maxWidth) {
            mouseX = maxWidth;
        }
        pos = mouseX / maxWidth * len;

        $('#bottom .timeline-wrapper .position').html(Math.round(pos/60)+':' + ((Math.round(pos%60) <10) ? '0' : '') + Math.round(pos%60));
        $('#bottom .timeline-wrapper .length').html(Math.round(len/60)+':' + ((Math.round(len%60) <10) ? '0' : '') + Math.round(len%60));
		$('#bottom .timeline-wrapper .slider').width(pos/len*$('#bottom .timeline').width());

        if (!Timeline.isDragging) {
            var wasMuted = Player._player.isMuted();
            Player._player.mute();

            Player._player.seekTo(pos, true);
            if (!wasMuted) {
                Player._player.unMute();
            }
        }
    },
	update: function(percent) {
		if (!Player.assertPlayerLoaded()) {
			clearInterval(Timeline.updateHandle);
			return;
		}
        if (Timeline.isDragging) {
            return;
        }
        var pos = Player._player.getCurrentTime(),
            len = Player._player.getDuration();

		$('#bottom .timeline-wrapper .position').html(Math.round(pos/60)+':' + ((Math.round(pos%60) <10) ? '0' : '') + Math.round(pos%60));
        $('#bottom .timeline-wrapper .length').html(Math.round(len/60)+':' + ((Math.round(len%60) <10) ? '0' : '') + Math.round(len%60));
		$('#bottom .timeline-wrapper .slider').width(pos/len*$('#bottom .timeline').width());
	},

	stop: function() {
		if (Timeline.updateHandle) {
			clearInterval(Timeline.updateHandle);
			Timeline.updateHandle = null;
		}
	},
};
<commit_msg>Fixed timeline NaN bug<commit_after>
var Timeline = {
    init: function() {
        $('#bottom .timeline').mousedown(function(event) {
            Timeline.manualUpdate(event);
        });
        $('#bottom .timeline .slider .knob').mousedown(function(event) {
            Timeline.startDrag(event);
        });
        $(window).mouseup(function(event) {
            Timeline.stopDrag(event);
        });
        $(window).mousemove(function(event) {
            Timeline.onDrag(event);
        });
    },
    isDragging: false,
    updateHandle: null,
    startDrag: function(event) {
        Timeline.isDragging = true;
    },
    stopDrag: function(event) {
        if (Timeline.isDragging) {
            Timeline.stop();
            Timeline.isDragging = false;
            Timeline.manualUpdate(event);
            Timeline.start();
        }
    },
    onDrag: function(event) {
        if (!Timeline.isDragging) {
            return;
        }
        Timeline.manualUpdate(event);
    },
	start: function() {
		if (!Player.assertPlayerLoaded()) {
			return;
		}

		$('#bottom .timeline .knob').show();
		Timeline.updateHandle = setInterval(Timeline.update, 100);
	},
    manualUpdate: function(event) {
        if (!Player.assertPlayerLoaded()) {
			return;
		}

        var maxWidth = $('#bottom .timeline').width(),
            mouseX = event.pageX - $('#bottom .timeline .slider').offset().left,
            pos = null,
            len = Player._player.getDuration();

        if (mouseX < 0) {
            mouseX = 0;
        }
        if (mouseX > maxWidth) {
            mouseX = maxWidth;
        }
        pos = mouseX / maxWidth * len;

        $('#bottom .timeline-wrapper .position').html(Math.round(pos/60)+':' + ((Math.round(pos%60) <10) ? '0' : '') + Math.round(pos%60));
        $('#bottom .timeline-wrapper .length').html(Math.round(len/60)+':' + ((Math.round(len%60) <10) ? '0' : '') + Math.round(len%60));
		$('#bottom .timeline-wrapper .slider').width(pos/len*$('#bottom .timeline').width());

        if (!Timeline.isDragging) {
            var wasMuted = Player._player.isMuted();
            Player._player.mute();

            Player._player.seekTo(pos, true);
            if (!wasMuted) {
                Player._player.unMute();
            }
        }
    },
	update: function(percent) {
		if (!Player.assertPlayerLoaded()) {
			clearInterval(Timeline.updateHandle);
			return;
		}
        if (Timeline.isDragging) {
            return;
        }
        var pos = Player._player.getCurrentTime(),
            len = Player._player.getDuration();

        if (pos && len) {
            $('#bottom .timeline-wrapper .position').html(Math.round(pos/60)+':' + ((Math.round(pos%60) <10) ? '0' : '') + Math.round(pos%60));
            $('#bottom .timeline-wrapper .length').html(Math.round(len/60)+':' + ((Math.round(len%60) <10) ? '0' : '') + Math.round(len%60));
            $('#bottom .timeline-wrapper .slider').width(pos/len*$('#bottom .timeline').width());
        } else {
            $('#bottom .timeline-wrapper .position').html('0:00');
            $('#bottom .timeline-wrapper .length').html('0:00');
            $('#bottom .timeline-wrapper .slider').width(0);
        }
	},

	stop: function() {
		if (Timeline.updateHandle) {
			clearInterval(Timeline.updateHandle);
			Timeline.updateHandle = null;
		}
	},
};
<|endoftext|>


<commit_before>/******************************************************************************
 * Author: Frank Derry Wanye
 * Date: 11 Mar 2017
 * Loads example output from file and displays it in given text box.
 *****************************************************************************/

/**
 * Send ajax request to given URL, place result in given div
 */
var sendRequest = function(url, div) {
    div.innerHTML = "Waiting for a response from Terry...";

    var request = new XMLHttpRequest();

    request.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var response = request.responseText;
            var outputs = response.split("\n");
            console.log("Received input of length " + outputs.length);
            var i = 0;
            while (i < outputs.length) {
                if (outputs[i].indexOf('fuck') >= 0 || outputs[i].length == 0) {
                    outputs.splice(i, 1);
                } else {
                    i++;
                }
            }
            console.log("After filtering, input length was " + outputs.length);
            var index = Math.floor(Math.random() * outputs.length);
            div.innerHTML = outputs[index];
        }
    };

    request.open("GET", url, true);
    request.send();

};

/**
 * Assign functionality to buttons
 */
document.addEventListener("readystatechange", function() {

    if (document.readyState === "interactive") {

        console.log("Document is interactive.");

        //=====================================================================

        console.log("Setting up variables.");

        var sentenceDiv = document.getElementById("sentences");
        var sentenceButton = sentenceDiv.getElementsByClassName("button")[0];
        var sentenceBox = sentenceDiv.getElementsByClassName("container")[0];

        var paragraphDiv = document.getElementById("paragraphs");
        var paragraphButton = paragraphDiv.getElementsByClassName("button")[0];
        var paragraphBox = paragraphDiv.getElementsByClassName("container")[0];

        var storyDiv = document.getElementById("stories");
        var storyButton = storyDiv.getElementsByClassName("button")[0];
        var storyBox = storyDiv.getElementsByClassName("container")[0];

        //=====================================================================

        console.log("Adding button functionality.")

        sentenceButton.onclick = function() {
            console.log("Sentence requested.");
            sendRequest("/results/f_sentences.txt", sentenceBox);
        };

        paragraphButton.onclick = function() {
            console.log("Paragraph requested.");
            sendRequest("/results/f_paragraphs.txt", paragraphBox);
        };

        storyButton.onclick = function() {
            console.log("Story requested.");
            sendRequest("/results/f_stories.txt", storyBox);
        };

    }

});
<commit_msg>Fixed bug<commit_after>/******************************************************************************
 * Author: Frank Derry Wanye
 * Date: 11 Mar 2017
 * Loads example output from file and displays it in given text box.
 *****************************************************************************/

/**
 * Send ajax request to given URL, place result in given div
 */
var sendRequest = function(url, div) {
    div.innerHTML = "Waiting for a response from Terry...";

    var request = new XMLHttpRequest();

    request.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var response = request.responseText;
            var outputs = response.split("\n");
            console.log("Received input of length " + outputs.length);
            var i = 0;
            while (i < outputs.length) {
                if (outputs[i].indexOf('fuck') >= 0 || outputs[i].length == 0) {
                    outputs.splice(i, 1);
                } else {
                    i++;
                }
            }
            console.log("After filtering, input length was " + outputs.length);
            var index = Math.floor(Math.random() * outputs.length);
            div.innerHTML = outputs[index];
        }
    };

    request.open("GET", url, true);
    request.send();

};

/**
 * Assign functionality to buttons
 */
document.addEventListener("readystatechange", function() {

    if (document.readyState === "interactive") {

        console.log("Document is interactive.");

        //=====================================================================

        console.log("Setting up variables.");

        var sentenceDiv = document.getElementById("sentences");
        var sentenceButton = sentenceDiv.getElementsByClassName("button")[0];
        var sentenceBox = sentenceDiv.getElementsByClassName("container")[0];

        var paragraphDiv = document.getElementById("paragraphs");
        var paragraphButton = paragraphDiv.getElementsByClassName("button")[0];
        var paragraphBox = paragraphDiv.getElementsByClassName("container")[0];

        var storyDiv = document.getElementById("stories");
        var storyButton = storyDiv.getElementsByClassName("button")[0];
        var storyBox = storyDiv.getElementsByClassName("container")[0];

        //=====================================================================

        console.log("Adding button functionality.")

        sentenceButton.onclick = function() {
            console.log("Sentence requested.");
            sendRequest("./results/f_sentences.txt", sentenceBox);
        };

        paragraphButton.onclick = function() {
            console.log("Paragraph requested.");
            sendRequest("./results/f_paragraphs.txt", paragraphBox);
        };

        storyButton.onclick = function() {
            console.log("Story requested.");
            sendRequest("./results/f_stories.txt", storyBox);
        };

    }

});
<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Fancy script to deploy to GitHub Pages
 * ======================================
 *
 * Sample usage
 * ------------
 *
 * % node ./scripts/gh-pages
 * gh-pages -d dist -r git@github.com:MozVR/vr-markup.git
 *
 * % node ./scripts/gh-pages cvan
 * gh-pages -d dist -r git@github.com:cvan/vr-markup.git
 *
 * % node ./scripts/gh-pages git@github.com:dmarcos/vr-markup.git
 * gh-pages -d dist -r git@github.com:dmarcos/vr-markup.git
 *
 */

var spawn = require('child_process').spawn;

var ghpages = require('gh-pages');
var path = require('path');

var repo = {
  username: 'MozVR',
  name: 'vr-markup'
};

var arg = process.argv[2];
if (arg) {
  if (arg.indexOf(':') === -1) {
    repo.username = arg;
  } else {
    repo.url = arg;
    var usernameMatches = arg.match(':(.+)/');
    if (usernameMatches) {
      repo.username = usernameMatches[1];
    }
  }
}

if (!repo.url) {
  repo.url = 'git@github.com:' + repo.username + '/' + repo.name + '.git';
}

repo.ghPagesUrl = 'https://' + repo.username + '.github.io/' + repo.name + '/';

console.log('Publishing to', repo.url);

ghpages.clean();  // Wipe out the checkout from scratch every time in case we change repos.
ghpages.publish(path.join(process.cwd(), 'gh-pages'), {
  repo: repo.url,
  dotfiles: true,
  logger: function (message) {
    console.log(message);
  }
}, function () {
  console.log('Published');
  console.log(repo.ghPagesUrl);
  spawn('open', [repo.ghPagesUrl]);
});
<commit_msg>deploy to `aframe-core` GitHub Pages since remote name changed (issue #289)<commit_after>#!/usr/bin/env node

/**
 * Fancy script to deploy to GitHub Pages
 * ======================================
 *
 * Sample usage
 * ------------
 *
 * % node ./scripts/gh-pages
 * gh-pages -d dist -r git@github.com:MozVR/aframe-core.git
 *
 * % node ./scripts/gh-pages cvan
 * gh-pages -d dist -r git@github.com:cvan/aframe-core.git
 *
 * % node ./scripts/gh-pages git@github.com:dmarcos/aframe-core.git
 * gh-pages -d dist -r git@github.com:dmarcos/aframe-core.git
 *
 */

var spawn = require('child_process').spawn;

var ghpages = require('gh-pages');
var path = require('path');

var repo = {
  username: 'MozVR',
  name: 'aframe-core'
};

var arg = process.argv[2];
if (arg) {
  if (arg.indexOf(':') === -1) {
    repo.username = arg;
  } else {
    repo.url = arg;
    var usernameMatches = arg.match(':(.+)/');
    if (usernameMatches) {
      repo.username = usernameMatches[1];
    }
  }
}

if (!repo.url) {
  repo.url = 'git@github.com:' + repo.username + '/' + repo.name + '.git';
}

repo.ghPagesUrl = 'https://' + repo.username + '.github.io/' + repo.name + '/';

console.log('Publishing to', repo.url);

ghpages.clean();  // Wipe out the checkout from scratch every time in case we change repos.
ghpages.publish(path.join(process.cwd(), 'gh-pages'), {
  repo: repo.url,
  dotfiles: true,
  logger: function (message) {
    console.log(message);
  }
}, function () {
  console.log('Published');
  console.log(repo.ghPagesUrl);
  spawn('open', [repo.ghPagesUrl]);
});
<|endoftext|>


<commit_before>(function () {
    var stripe_key = '';
    var payment_minimum = 100; // Let's make the minimum $1.00 for now

    var previous_amount = 'amount-twenty-five';
    var current_amount = 'amount-twenty-five';
    var amountClick = function() {
        // Remove existing checks.
        $('.target-amount').removeClass('checked');
        // Add current check.
        $(this).addClass('checked');
        // Declare new amount.
        var new_amount;
        new_amount = this.id;
        // If different, update the previous and current.
        if ( new_amount != current_amount ) {
            previous_amount = current_amount;
            current_amount = new_amount;
        }
    }
    var amountBlur = function() {
        // If NOT valid OR empty.
        if (
            !this.validity.valid ||
            this.value == ''
        ) {
            // Remove existing checks.
            $('.target-amount').removeClass('checked');
            // Use the old amount.
            current_amount = previous_amount;
            // Set the old amount as checked.
            $('#' + current_amount).addClass('checked');
        }
    }
    // Listen for Clicking on Amounts
    $('.target-amount').click(amountClick);
    // Check Custom Amounts on Blur
    $('#amount-custom').blur(amountBlur);

    $('#download').click(function(){
        console.log('Pay ' + current_amount);
        payment_amount = $('#' + current_amount).val() * 100;
        console.log('Starting payment for ' + payment_amount);
        if (payment_amount < payment_minimum) {
            open_download_overlay();
        } else {
            do_stripe_payment(payment_amount);
        }
    });

    function do_stripe_payment (amount) {
        StripeCheckout.open({
            key: stripe_key,
            token: function (token) {
                console.log(token);
                process_payment(amount, token);
                open_download_overlay();
            },
            name: 'elementary LLC.',
            description: 'elementary OS download',
            amount: amount
        });
    }

    function process_payment (amount, token) {
        payment_http = new XMLHttpRequest();
        payment_http.open('POST','./backend/payment.php',true);
        payment_http.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        payment_http.send('amount=' + amount + '&token=' + token.id);
    }

    function open_download_overlay () {
        console.log('Open the download overlay!');
        $('.open-modal').leanModal({
            // Add this class to download buttons to make them close it.
            closeButton: '.close-modal',
        });
        $('.open-modal').click();
    }

    // Get the stripe key from the server
    key_http = new XMLHttpRequest();
    key_http.open('GET','./backend/payment.php',true);
    key_http.onreadystatechange = function() {
        if (key_http.readyState == 4 && key_http.status == 200) {
            stripe_key = key_http.responseText;
            console.log('Stripe key is: ' + stripe_key);
        }
    }
    key_http.send();

    console.log('Loaded homepage.js');
})();<commit_msg>Adds dowload events<commit_after>(function () {
    var stripe_key = '';
    var payment_minimum = 100; // Let's make the minimum $1.00 for now

    var previous_amount = 'amount-twenty-five';
    var current_amount = 'amount-twenty-five';
    var amountClick = function() {
        // Remove existing checks.
        $('.target-amount').removeClass('checked');
        // Add current check.
        $(this).addClass('checked');
        // Declare new amount.
        var new_amount;
        new_amount = this.id;
        // If different, update the previous and current.
        if ( new_amount != current_amount ) {
            previous_amount = current_amount;
            current_amount = new_amount;
        }
    }
    var amountBlur = function() {
        // If NOT valid OR empty.
        if (
            !this.validity.valid ||
            this.value == ''
        ) {
            // Remove existing checks.
            $('.target-amount').removeClass('checked');
            // Use the old amount.
            current_amount = previous_amount;
            // Set the old amount as checked.
            $('#' + current_amount).addClass('checked');
        }
    }
    // Listen for Clicking on Amounts
    $('.target-amount').click(amountClick);
    // Check Custom Amounts on Blur
    $('#amount-custom').blur(amountBlur);

    $('#download').click(function(){
        console.log('Pay ' + current_amount);
        payment_amount = $('#' + current_amount).val() * 100;
        console.log('Starting payment for ' + payment_amount);
        if (payment_amount < payment_minimum) {
            open_download_overlay();
        } else {
            do_stripe_payment(payment_amount);
        }
    });

    function do_stripe_payment (amount) {
        StripeCheckout.open({
            key: stripe_key,
            token: function (token) {
                console.log(token);
                process_payment(amount, token);
                open_download_overlay();
            },
            name: 'elementary LLC.',
            description: 'elementary OS download',
            amount: amount
        });
    }

    function process_payment (amount, token) {
        payment_http = new XMLHttpRequest();
        payment_http.open('POST','./backend/payment.php',true);
        payment_http.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        payment_http.send('amount=' + amount + '&token=' + token.id);
    }

    function open_download_overlay () {
        console.log('Open the download overlay!');
        $('.open-modal').leanModal({
            // Add this class to download buttons to make them close it.
            closeButton: '.close-modal',
        });
        $('.open-modal').click();
    }

    function detect_os() {
        var ua = window.navigator.userAgent;
        if (ua.indexOf('Android') >= 0) {
            return 'Android';
        }
        if (ua.indexOf('Mac OS X') >= 0 && ua.indexOf('Mobile') >= 0) {
            return 'iOS';
        }
        if (ua.indexOf('Windows') >= 0) {
            return 'Windows';
        }
        if (ua.indexOf('Mac_PowerPC') >= 0 || ua.indexOf('Macintosh') >= 0) {
            return 'OS X';
        }
        if (ua.indexOf('Linux') >= 0) {
            return 'Linux';
        }
        return 'Other';
    }

    if (window.ga) {
        var download_links = $('#download-modal .actions').find('a');
        var links_data = [
            { arch: '32-bit', method: 'HTTP' },
            { arch: '32-bit', method: 'Magnet' },
            { arch: '64-bit', method: 'HTTP' },
            { arch: '64-bit', method: 'Magnet' }
        ];

        for (var i = 0; i < links_data.length; i++) {
            (function (data, link) {
                $(link).click(function () {
                    ga('send', 'event', 'Freya Beta Download (Architecture)', 'Homepage', data.arch);
                    ga('send', 'event', 'Freya Beta Download (Method)', 'Homepage', data.method);
                    ga('send', 'event', 'Freya Beta Download (OS)', 'Homepage', detect_os());
                });
            })(links_data[i], download_links[i]);
        }
    }

    // Get the stripe key from the server
    key_http = new XMLHttpRequest();
    key_http.open('GET','./backend/payment.php',true);
    key_http.onreadystatechange = function() {
        if (key_http.readyState == 4 && key_http.status == 200) {
            stripe_key = key_http.responseText;
            console.log('Stripe key is: ' + stripe_key);
        }
    }
    key_http.send();

    console.log('Loaded homepage.js');
})();<|endoftext|>


<commit_before>import React from 'react'
import ReactDOM from 'react-dom'

import {ScriptCache} from './lib/ScriptCache'
import GoogleApi from './lib/GoogleApi'

const defaultMapConfig = {}
const defaultCreateCache = (options) => {
    options = options || {};
    const apiKey = options.apiKey;
    const libraries = options.libraries || ['places'];
    const version = options.version || '3.29';
    const language = options.language || 'en';

    return ScriptCache({
        google: GoogleApi({
            apiKey: apiKey,
            language: language,
            libraries: libraries,
            version: version
        })
    });
};

export const wrapper = (options) => (WrappedComponent) => {
    const apiKey = options.apiKey;
    const libraries = options.libraries || ['places'];
    const version = options.version || '3';
    const createCache = options.createCache || defaultCreateCache;

    class Wrapper extends React.Component {
        constructor(props, context) {
            super(props, context);

            this.scriptCache = createCache(options);
            this.scriptCache.google.onLoad(this.onLoad.bind(this))

            this.state = {
                loaded: false,
                map: null,
                google: null
            }
        }

        onLoad(err, tag) {
            this._gapi = window.google;

            this.setState({loaded: true, google: this._gapi})
        }

        render() {
            const props = Object.assign({}, this.props, {
                loaded: this.state.loaded,
                google: window.google
            });

            return (

                    <WrappedComponent {...props}/>

            )
        }
    }

    return Wrapper;
}

export default wrapper;
<commit_msg>remove not used variable<commit_after>import React from 'react'
import ReactDOM from 'react-dom'

import {ScriptCache} from './lib/ScriptCache'
import GoogleApi from './lib/GoogleApi'

const defaultMapConfig = {}
const defaultCreateCache = (options) => {
    options = options || {};
    const apiKey = options.apiKey;
    const libraries = options.libraries || ['places'];
    const version = options.version || '3.29';
    const language = options.language || 'en';

    return ScriptCache({
        google: GoogleApi({
            apiKey: apiKey,
            language: language,
            libraries: libraries,
            version: version
        })
    });
};

export const wrapper = (options) => (WrappedComponent) => {
    const createCache = options.createCache || defaultCreateCache;

    class Wrapper extends React.Component {
        constructor(props, context) {
            super(props, context);

            this.scriptCache = createCache(options);
            this.scriptCache.google.onLoad(this.onLoad.bind(this))

            this.state = {
                loaded: false,
                map: null,
                google: null
            }
        }

        onLoad(err, tag) {
            this._gapi = window.google;

            this.setState({loaded: true, google: this._gapi})
        }

        render() {
            const props = Object.assign({}, this.props, {
                loaded: this.state.loaded,
                google: window.google
            });

            return (

                    <WrappedComponent {...props}/>

            )
        }
    }

    return Wrapper;
}

export default wrapper;
<|endoftext|>


<commit_before>define([
           'dojo/_base/declare',
           'dojo/dom-construct',

           'dijit/Toolbar',
           'dijit/form/Button',
           'JBrowse/Util',
           'JBrowse/has'
       ],
       function( declare, dom, Toolbar, Button, Util, has ) {

return declare(null,
{

    constructor: function( args ) {

        this.width       = args.width || 78;
        this.htmlMaxRows = args.htmlMaxRows || 15;
        this.track = args.track;
        this.canSaveFiles = args.track &&  args.track._canSaveFiles && args.track._canSaveFiles();

	// hook point
	if (typeof this.initData === 'function')
		this.initData(args);
    },
    renderHTML: function( region, seq, parent ) {
        var thisB = this;
        var text = this.renderText( region, seq );
        var lineCount = text.match( /\n/g ).length + 1;
        var container = dom.create('div', { className: 'fastaView' }, parent );

        if( this.canSaveFiles ) {
            var toolbar = new Toolbar().placeAt( container );
            var thisB = this;

	    // hook point
	if (typeof thisB.addButtons === 'function')
            thisB.addButtons(region, seq, toolbar);

            toolbar.addChild( new Button(
                                  { iconClass: 'dijitIconSave',
                                    label: 'FASTA',
                                    title: 'save as FASTA',
                                    disabled: ! has('save-generated-files'),
                                    onClick: function() {
                                        thisB.track._fileDownload(
                                            { format: 'FASTA',
                                              filename: Util.assembleLocString(region)+'.fasta',
                                              data: text
                                            });
                                    }
                                  }));
        }

        var textArea = dom.create('textarea', {
                        className: 'fasta',
                        cols: this.width,
                        rows: Math.min( lineCount, this.htmlMaxRows ),
                        readonly: true
                    }, container );
        var c = 0;
        textArea.innerHTML = text.replace(/\n/g, function() { return c++ ? '' : "\n"; });
        return container;
    },
    renderText: function( region, seq ) {
        return '>' + region.ref
            + ' '+Util.assembleLocString(region)
            + ( region.type ? ' class='+region.type : '' )
            + ' length='+(region.end - region.start)
            + "\n"
            + this._wrap( seq, this.width );
    },
    _wrap: function( string, length ) {
        length = length || this.width;
        return string.replace( new RegExp('(.{'+length+'})','g'), "$1\n" );
    }
});
});
<commit_msg>tweak allows jblast to use the module, arbitrary region handling.<commit_after>define([
           'dojo/_base/declare',
           'dojo/dom-construct',

           'dijit/Toolbar',
           'dijit/form/Button',
           'JBrowse/Util',
           'JBrowse/has'
       ],
       function( declare, dom, Toolbar, Button, Util, has ) {

return declare(null,
{

    constructor: function( args ) {

        if (typeof args === 'undefined') {
            this.width = 78;
            return;
        };

        this.width       = args.width || 78;
        this.htmlMaxRows = args.htmlMaxRows || 15;
        this.track = args.track;
        this.canSaveFiles = args.track &&  args.track._canSaveFiles && args.track._canSaveFiles();

	// hook point
	if (typeof this.initData === 'function')
		this.initData(args);
    },
    renderHTML: function( region, seq, parent ) {
        var thisB = this;
        var text = this.renderText( region, seq );
        var lineCount = text.match( /\n/g ).length + 1;
        var container = dom.create('div', { className: 'fastaView' }, parent );

        if( this.canSaveFiles ) {
            var toolbar = new Toolbar().placeAt( container );
            var thisB = this;

	    // hook point
	if (typeof thisB.addButtons === 'function')
            thisB.addButtons(region, seq, toolbar);

            toolbar.addChild( new Button(
                                  { iconClass: 'dijitIconSave',
                                    label: 'FASTA',
                                    title: 'save as FASTA',
                                    disabled: ! has('save-generated-files'),
                                    onClick: function() {
                                        thisB.track._fileDownload(
                                            { format: 'FASTA',
                                              filename: Util.assembleLocString(region)+'.fasta',
                                              data: text
                                            });
                                    }
                                  }));
        }

        var textArea = dom.create('textarea', {
                        className: 'fasta',
                        cols: this.width,
                        rows: Math.min( lineCount, this.htmlMaxRows ),
                        readonly: true
                    }, container );
        var c = 0;
        textArea.innerHTML = text.replace(/\n/g, function() { return c++ ? '' : "\n"; });
        return container;
    },
    renderText: function( region, seq ) {
        console.log('renderText');
        return '>' + region.ref
            + ' '+Util.assembleLocString(region)
            + ( region.type ? ' class='+region.type : '' )
            + ' length='+(region.end - region.start)
            + "\n"
            + this._wrap( seq, this.width );
    },
    _wrap: function( string, length ) {
        length = length || this.width;
        return string.replace( new RegExp('(.{'+length+'})','g'), "$1\n" );
    }
});
});
<|endoftext|>


<commit_before>const corePath = require('path')
const fs = require('fs')
const junk = require('junk')
const once = require('once')
const parallel = require('run-parallel')

// TODO: When Node 10 support is dropped, replace this with Array.prototype.flat
function flat (arr1) {
  return arr1.reduce(
    (acc, val) => Array.isArray(val)
      ? acc.concat(flat(val))
      : acc.concat(val),
    []
  )
}

function notHidden (file) {
  return file[0] !== '.'
}

function traversePath (path, fn, cb) {
  fs.stat(path, (err, stats) => {
    if (err) return cb(err)
    if (stats.isDirectory()) {
      fs.readdir(path, (err, entries) => {
        if (err) return cb(err)
        parallel(entries.filter(notHidden).filter(junk.not).map(entry => cb => {
          traversePath(corePath.join(path, entry), fn, cb)
        }), cb)
      })
    } else if (stats.isFile()) {
      fn(path, cb)
    }
    // Ignore other types (not a file or directory)
  })
}

/**
 * Convert a file path to a lazy readable stream.
 * @param  {string} path
 * @return {function}
 */
function getFilePathStream (path) {
  return () => fs.createReadStream(path)
}

function getFiles (path, keepRoot, cb) {
  traversePath(path, getFileInfo, (err, files) => {
    if (err) return cb(err)

    if (Array.isArray(files)) files = flat(files)
    else files = [files]

    path = corePath.normalize(path)
    if (keepRoot) {
      path = path.slice(0, path.lastIndexOf(corePath.sep) + 1)
    }
    if (path[path.length - 1] !== corePath.sep) path += corePath.sep

    files.forEach(file => {
      file.getStream = getFilePathStream(file.path)
      file.path = file.path.replace(path, '').split(corePath.sep)
    })

    cb(null, files)
  })
}

function getFileInfo (path, cb) {
  cb = once(cb)
  fs.stat(path, (err, stat) => {
    if (err) return cb(err)
    const info = {
      length: stat.size,
      path
    }
    cb(null, info)
  })
}

module.exports = getFiles
<commit_msg>fix: remove flat pollyfill in get-files<commit_after>const corePath = require('path')
const fs = require('fs')
const junk = require('junk')
const once = require('once')
const parallel = require('run-parallel')

function notHidden (file) {
  return file[0] !== '.'
}

function traversePath (path, fn, cb) {
  fs.stat(path, (err, stats) => {
    if (err) return cb(err)
    if (stats.isDirectory()) {
      fs.readdir(path, (err, entries) => {
        if (err) return cb(err)
        parallel(entries.filter(notHidden).filter(junk.not).map(entry => cb => {
          traversePath(corePath.join(path, entry), fn, cb)
        }), cb)
      })
    } else if (stats.isFile()) {
      fn(path, cb)
    }
    // Ignore other types (not a file or directory)
  })
}

/**
 * Convert a file path to a lazy readable stream.
 * @param  {string} path
 * @return {function}
 */
function getFilePathStream (path) {
  return () => fs.createReadStream(path)
}

function getFiles (path, keepRoot, cb) {
  traversePath(path, getFileInfo, (err, files) => {
    if (err) return cb(err)

    if (Array.isArray(files)) files = files.flat()
    else files = [files]

    path = corePath.normalize(path)
    if (keepRoot) {
      path = path.slice(0, path.lastIndexOf(corePath.sep) + 1)
    }
    if (path[path.length - 1] !== corePath.sep) path += corePath.sep

    files.forEach(file => {
      file.getStream = getFilePathStream(file.path)
      file.path = file.path.replace(path, '').split(corePath.sep)
    })

    cb(null, files)
  })
}

function getFileInfo (path, cb) {
  cb = once(cb)
  fs.stat(path, (err, stat) => {
    if (err) return cb(err)
    const info = {
      length: stat.size,
      path
    }
    cb(null, info)
  })
}

module.exports = getFiles
<|endoftext|>


<commit_before>
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true }] */

const eventManager = {
  eventList: new Map(),

    /**
     * Bind event
     *
     * @param event
     * @param callback
     * @param context
     * @returns {eventManager.on}
     */
  on(event, callback, context = null) {
    this.eventList.has(event) || this.eventList.set(event, []);

    this.eventList.get(event).push({
      callback,
      context: context || this
    });

    return this;
  },

    /**
     * Unbind events
     * Strict comparison voluntary omitted to check both null and undefined
     *
     * @param event
     * @param callback
     * @returns {boolean}
     */
  off(event = null, callback = null) {
    if (event != null && callback == null) {
      return this.eventList.delete(event);
    } else if (event != null && callback != null) {
      const listeners = this.eventList.get(event);

      this.eventList.set(event, listeners.filter(el =>
                !(el.callback === callback || el.callback.toString() === callback.toString())
            ));
      listeners.length > 0 || this.eventList.delete(event);

      return true;
    } else if (event === null && callback === null) {
      this.eventList.clear();
      return true;
    }
    return false;
  },
    /**
     * @param event
     * @param callback
     * @param context
     * @returns {eventManager.once}
     */
  once(event, callback, context) {
    this.on(event, callback, context);
    const listener = this.eventList.get(event);
    const idx = listener.length - 1;
    listener[idx].once = true;
    return this;
  },
    /**
     * @param event
     * @param args
     * @returns {boolean}
     */
  emit(event, ...args) {
    if (!this.eventList.has(event)) {
      console.warn(`<${event}> Event is not registered. Did you forgot to bind the event ?`);
      return false;
    }
    const listeners = this.eventList.get(event);

    this.eventList.set(event, listeners.filter(listener => {
      listener.callback.call(listener.context, ...args);
      return !listener.once;
    }));

    return true;
  }
};

export default eventManager;
<commit_msg>Rename of Utils folder<commit_after><|endoftext|>