<commit_before>// ---------------------------------------
// Build a mapacache.xml file from
// a WMS capabilies xml file
// (Synchronous request)
// --------------------------------------------
// Parameters
//  - capabilitiesFile : xml capabilities
//  - urlRequestCapa : WMS getCapabilities request
//  - projectName : name of the project
// --------------------------------------------
buildMapcacheXmlFromContent = (function(capabilitiesXmlContent, urlRequestCapa, projectName) {
    var parser = new ol.parser.ogc.WMSCapabilities(), capabilitiesXmlContent;
    capabilitiesXmlContent = parser.read(capabilitiesXmlContent);

    var layers = capabilitiesXmlContent.capability.layers;

    var project = projectName;
    var mapcache = '';
    var tileset = '';
    var source = '';
    var concat = '&';
    var idx = urlRequestCapa.indexOf('?');
    if (idx == -1) {
        concat = '?';
    }

    mapcache = '<?xml version="1.0" encoding="UTF-8"?>\n';
    mapcache += '<mapcache>\n';
    mapcache += '  <metadata>\n';
    mapcache += '    <title>Mapcache service for url: ' + urlRequestCapa + '</title>\n';
    mapcache += '    <abstract>Render map services for url: ' + urlRequestCapa + '</abstract>\n';
    mapcache += '  </metadata>\n\n';

    // Cache: Disk
    mapcache += '  <cache name="disk" type="disk">\n';
    mapcache += '    <base>/tmp/' + project + '</base>\n';
    mapcache += '    <symlink_blank/>\n';
    mapcache += '  </cache>\n\n';

    // Cache: template
    mapcache += '  <cache name="tmpl" type="disk">\n';
    mapcache += '    <base>/tmp' + project + '</base>\n';
    mapcache += '    <template>/tmp/' + project + '/template/{tileset}#{grid}#{dim}/{z}/{x}/{y}.{ext}</template>\n';
    mapcache += '  </cache>\n\n';

    // Cache: sqlite
    mapcache += '  <cache name="sqlite" type="sqlite3">\n';
    mapcache += '    <dbfile>/tmp/' + project + '/sqlitetiles.db</dbfile>\n';
    mapcache += '    <pragma name="key">value</pragma>\n';
    mapcache += '  </cache>\n\n';

    // Cache: MbTiles
    mapcache += '  <cache name="mbtiles" type="mbtiles">\n';
    mapcache += '    <dbfile>/tmp/' + project + '/' + project + '.mbtiles</dbfile>\n';
    mapcache += '  </cache>\n\n';

    // Format: png
    mapcache += '  <format name="PNGQ_FAST" type ="PNG">\n';
    mapcache += '    <compression>fast</compression>\n';
    mapcache += '    <colors>256</colors>\n';
    mapcache += '  </format>\n\n';

    // Format: jpeg
    mapcache += '  <format name="JPEG_75" type ="JPEG">\n';
    mapcache += '    <quality>75</quality>\n';
    mapcache += '    <photometric>RGB</photometric>\n';
    mapcache += '  </format>\n\n';

    // Format: png
    mapcache += '  <format name="PNG_BEST" type ="PNG">\n';
    mapcache += '    <compression>best</compression>\n';
    mapcache += '  </format>\n\n';

    // Format: mixed
    mapcache += '  <format name="mixed" type="MIXED">\n';
    mapcache += '    <transparent>PNG_BEST</transparent>\n';
    mapcache += '    <opaque>JPEG</opaque>\n';
    mapcache += '  </format>\n\n';

    for (var l = 0; l < layers.length; ++l) {
        layer = layers[l];

        console.log('Layer:' + layer.name);
        console.log('\tAvailable elevations: ' + layer.dimensions.elevation.values);
        console.log('\tAvailable times: ' + layer.dimensions.time.values);

        var arrayTab = layer.styles;
        for (var s = 0; s < arrayTab.length; ++s) {
            style = arrayTab[s];

            tileset = layer.name + '_' + style.name;
            source = 'SOURCE_' + layer.name + '_' + style.name;

            mapcache += '  <!-- Source for layer: ' + layer.name + ', style: ' + style.name + ' -->\n';
            mapcache += '  <source name="' + source + '" type="wms">\n';
            mapcache += '    <http>\n';
            mapcache += '      <url>' + urlRequestCapa + '</url>\n';
            mapcache += '    </http>\n';
            mapcache += '    <getmap>\n';
            mapcache += '      <params>\n';
            mapcache += '        <FORMAT>image/png</FORMAT>\n';
            mapcache += '        <LAYERS>' + layer.name + '</LAYERS>\n';
            mapcache += '        <STYLES>' + style.name + '</STYLES>\n';
            mapcache += '      </params>\n';
            mapcache += '    </getmap>\n';
            mapcache += '  </source>\n\n';

            mapcache += '  <!-- Tileset for layer: ' + layer.name + ', style: ' + style.name + ' -->\n';
            mapcache += '  <tileset name="' + tileset + '">\n';
            mapcache += '    <source>' + source + '</source>\n';
            mapcache += '    <dimensions>\n';
            mapcache += '      <dimension type="regex" name="elevation" default="-1">.*</dimension>\n';
            mapcache += '      <dimension type="regex" name="time" default="2000-01-00T00:00:00Z">.*</dimension>\n';
            mapcache += '    </dimensions>\n';
            mapcache += '    <cache>disk</cache>\n';
            mapcache += '    <format>PNG</format>\n';

            // TODO : create grid for each srs
            //var projs = layer.srs;
            //for (var p = 0; p < projs.length; ++p) {
            //    proj = projs[p];
            //    mapcache += '    <grid>' + proj + '</grid>\n';
            //}

            mapcache += '    <grid>WGS84</grid>\n';
            mapcache += '    <grid>GoogleMapsCompatible</grid>\n';
            mapcache += '    <metatile>5 5</metatile>\n';
            mapcache += '    <metabuffer>10</metabuffer>\n';
            mapcache += '  </tileset>\n\n';

        }
    }

    // Services: wms
    mapcache += '  <service type="wms" enabled="true">\n';
    for (var l = 0; l < layers.length; ++l) {
        layer = layers[l];
        var arrayTab = layer.styles;
        for (var s = 0; s < arrayTab.length; ++s) {
            style = arrayTab[s];
            tileset = layer.name + '_' + style.name;
            source = 'SOURCE_' + layer.name + '_' + style.name;
            mapcache += '    <forwarding_rule name="RULE' + tileset + '"&gt\n';
            mapcache += '      <param name="SERVICE" type="values">WMS</param&gt\n';
            mapcache += '      <param name="LAYERS" type="values">' + layer.name + '</param&gt\n';
            mapcache += '      <param name="STYLES" type="values">' + style.name + '</param&gt\n';
            mapcache += '      <http&gt\n';
            mapcache += '        <url>' + urlRequestCapa + concat + 'LAYERS=' + tileset + '</url&gt\n';
            mapcache += '      </http&gt\n';
            mapcache += '    </forwarding_rule&gt\n';

        }
    }
    mapcache += '    <full_wms>assemble</full_wms&gt\n';
    mapcache += '    <resample_mode>bilinear</resample_mode&gt\n';
    mapcache += '    <format>JPEG_75</format&gt\n';
    mapcache += '    <maxsize>4096</maxsize&gt\n';
    mapcache += '  </service&gt\n\n';

    // Services: wmts, tms, gmaps, ve, demo
    mapcache += '  <service type="wmts" enabled="true"/>\n';
    mapcache += '  <service type="tms" enabled="true"/>\n';
    mapcache += '  <service type="kml" enabled="true"/>\n';
    mapcache += '  <service type="gmaps" enabled="true"/>\n';
    mapcache += '  <service type="ve" enabled="true"/>\n';
    mapcache += '  <service type="demo" enabled="true"/>\n\n';

    // General parameters
    mapcache += '  <errors>report</errors>\n';
    mapcache += '  <lock_dir>/tmp/' + project + '</lock_dir>\n';
    mapcache += '  <threaded_fetching>true</threaded_fetching>\n';
    mapcache += '  <log_level>debug</log_level>\n';
    mapcache += '  <auto_reload>true&lt/auto_reload> \n';

    mapcache += '</mapcache>\n';

    return mapcache;
});

// ---------------------------------------
// Build a mapacache.xml file from
// a WMS capabilies xml file
// (Synchronous request)
// --------------------------------------------
// Parameters
//  - capabilitiesFile : xml capabilities
//  - urlRequestCapa : WMS getCapabilities request
//  - projectName : name of the project
// --------------------------------------------
buildMapcacheXml = (function(capabilitiesFile, urlRequestCapa, projectName) {
    var mapcache = 'null';
    var xhr = new XMLHttpRequest();
    xhr.open('GET', capabilitiesFile, false);
    xhr.setRequestHeader('Content-Type', 'text/xml');
    xhr.send(null);

    if (xhr.status == 200) {
        mapcache = buildMapcacheFromXml(result, urlRequestCapa, projectName);
    }
    return mapcache;
});

<commit_msg>correction for missing elevation<commit_after>// ---------------------------------------
// Build a mapacache.xml file from
// a WMS capabilies xml file
// (Synchronous request)
// --------------------------------------------
// Parameters
//  - capabilitiesFile : xml capabilities
//  - urlRequestCapa : WMS getCapabilities request
//  - projectName : name of the project
// --------------------------------------------
buildMapcacheXmlFromContent = (function(capabilitiesXmlContent, urlRequestCapa, projectName) {
    var parser = new ol.parser.ogc.WMSCapabilities(), capabilitiesXmlContent;
    capabilitiesXmlContent = parser.read(capabilitiesXmlContent);

    var layers = capabilitiesXmlContent.capability.layers;

    var project = projectName;
    var mapcache = '';
    var tileset = '';
    var source = '';
    var concat = '&';
    var idx = urlRequestCapa.indexOf('?');
    if (idx == -1) {
        concat = '?';
    }

    mapcache = '<?xml version="1.0" encoding="UTF-8"?>\n';
    mapcache += '<mapcache>\n';
    mapcache += '  <metadata>\n';
    mapcache += '    <title>Mapcache service for url: ' + urlRequestCapa + '</title>\n';
    mapcache += '    <abstract>Render map services for url: ' + urlRequestCapa + '</abstract>\n';
    mapcache += '  </metadata>\n\n';

    // Cache: Disk
    mapcache += '  <cache name="disk" type="disk">\n';
    mapcache += '    <base>/tmp/' + project + '</base>\n';
    mapcache += '    <symlink_blank/>\n';
    mapcache += '  </cache>\n\n';

    // Cache: template
    mapcache += '  <cache name="tmpl" type="disk">\n';
    mapcache += '    <base>/tmp' + project + '</base>\n';
    mapcache += '    <template>/tmp/' + project + '/template/{tileset}#{grid}#{dim}/{z}/{x}/{y}.{ext}</template>\n';
    mapcache += '  </cache>\n\n';

    // Cache: sqlite
    mapcache += '  <cache name="sqlite" type="sqlite3">\n';
    mapcache += '    <dbfile>/tmp/' + project + '/sqlitetiles.db</dbfile>\n';
    mapcache += '    <pragma name="key">value</pragma>\n';
    mapcache += '  </cache>\n\n';

    // Cache: MbTiles
    mapcache += '  <cache name="mbtiles" type="mbtiles">\n';
    mapcache += '    <dbfile>/tmp/' + project + '/' + project + '.mbtiles</dbfile>\n';
    mapcache += '  </cache>\n\n';

    // Format: png
    mapcache += '  <format name="PNGQ_FAST" type ="PNG">\n';
    mapcache += '    <compression>fast</compression>\n';
    mapcache += '    <colors>256</colors>\n';
    mapcache += '  </format>\n\n';

    // Format: jpeg
    mapcache += '  <format name="JPEG_75" type ="JPEG">\n';
    mapcache += '    <quality>75</quality>\n';
    mapcache += '    <photometric>RGB</photometric>\n';
    mapcache += '  </format>\n\n';

    // Format: png
    mapcache += '  <format name="PNG_BEST" type ="PNG">\n';
    mapcache += '    <compression>best</compression>\n';
    mapcache += '  </format>\n\n';

    // Format: mixed
    mapcache += '  <format name="mixed" type="MIXED">\n';
    mapcache += '    <transparent>PNG_BEST</transparent>\n';
    mapcache += '    <opaque>JPEG</opaque>\n';
    mapcache += '  </format>\n\n';

    for (var l = 0; l < layers.length; ++l) {
        layer = layers[l];

        console.log('Layer:' + layer.name);
        //console.log('\tAvailable elevations: ' + layer.dimensions.elevation.values);
        console.log('\tAvailable times: ' + layer.dimensions.time.values);

        var arrayTab = layer.styles;
        for (var s = 0; s < arrayTab.length; ++s) {
            style = arrayTab[s];

            tileset = layer.name + '_' + style.name;
            source = 'SOURCE_' + layer.name + '_' + style.name;

            mapcache += '  <!-- Source for layer: ' + layer.name + ', style: ' + style.name + ' -->\n';
            mapcache += '  <source name="' + source + '" type="wms">\n';
            mapcache += '    <http>\n';
            mapcache += '      <url>' + urlRequestCapa + '</url>\n';
            mapcache += '    </http>\n';
            mapcache += '    <getmap>\n';
            mapcache += '      <params>\n';
            mapcache += '        <FORMAT>image/png</FORMAT>\n';
            mapcache += '        <LAYERS>' + layer.name + '</LAYERS>\n';
            mapcache += '        <STYLES>' + style.name + '</STYLES>\n';
            mapcache += '      </params>\n';
            mapcache += '    </getmap>\n';
            mapcache += '  </source>\n\n';

            mapcache += '  <!-- Tileset for layer: ' + layer.name + ', style: ' + style.name + ' -->\n';
            mapcache += '  <tileset name="' + tileset + '">\n';
            mapcache += '    <source>' + source + '</source>\n';
            mapcache += '    <dimensions>\n';
            mapcache += '      <dimension type="regex" name="elevation" default="-1">.*</dimension>\n';
            mapcache += '      <dimension type="regex" name="time" default="2000-01-00T00:00:00Z">.*</dimension>\n';
            mapcache += '    </dimensions>\n';
            mapcache += '    <cache>disk</cache>\n';
            mapcache += '    <format>PNG</format>\n';

            // TODO : create grid for each srs
            //var projs = layer.srs;
            //for (var p = 0; p < projs.length; ++p) {
            //    proj = projs[p];
            //    mapcache += '    <grid>' + proj + '</grid>\n';
            //}

            mapcache += '    <grid>WGS84</grid>\n';
            mapcache += '    <grid>GoogleMapsCompatible</grid>\n';
            mapcache += '    <metatile>5 5</metatile>\n';
            mapcache += '    <metabuffer>10</metabuffer>\n';
            mapcache += '  </tileset>\n\n';

        }
    }

    // Services: wms
    mapcache += '  <service type="wms" enabled="true">\n';
    for (var l = 0; l < layers.length; ++l) {
        layer = layers[l];
        var arrayTab = layer.styles;
        for (var s = 0; s < arrayTab.length; ++s) {
            style = arrayTab[s];
            tileset = layer.name + '_' + style.name;
            source = 'SOURCE_' + layer.name + '_' + style.name;
            mapcache += '    <forwarding_rule name="RULE' + tileset + '"&gt\n';
            mapcache += '      <param name="SERVICE" type="values">WMS</param&gt\n';
            mapcache += '      <param name="LAYERS" type="values">' + layer.name + '</param&gt\n';
            mapcache += '      <param name="STYLES" type="values">' + style.name + '</param&gt\n';
            mapcache += '      <http&gt\n';
            mapcache += '        <url>' + urlRequestCapa + concat + 'LAYERS=' + tileset + '</url&gt\n';
            mapcache += '      </http&gt\n';
            mapcache += '    </forwarding_rule&gt\n';

        }
    }
    mapcache += '    <full_wms>assemble</full_wms&gt\n';
    mapcache += '    <resample_mode>bilinear</resample_mode&gt\n';
    mapcache += '    <format>JPEG_75</format&gt\n';
    mapcache += '    <maxsize>4096</maxsize&gt\n';
    mapcache += '  </service&gt\n\n';

    // Services: wmts, tms, gmaps, ve, demo
    mapcache += '  <service type="wmts" enabled="true"/>\n';
    mapcache += '  <service type="tms" enabled="true"/>\n';
    mapcache += '  <service type="kml" enabled="true"/>\n';
    mapcache += '  <service type="gmaps" enabled="true"/>\n';
    mapcache += '  <service type="ve" enabled="true"/>\n';
    mapcache += '  <service type="demo" enabled="true"/>\n\n';

    // General parameters
    mapcache += '  <errors>report</errors>\n';
    mapcache += '  <lock_dir>/tmp/' + project + '</lock_dir>\n';
    mapcache += '  <threaded_fetching>true</threaded_fetching>\n';
    mapcache += '  <log_level>debug</log_level>\n';
    mapcache += '  <auto_reload>true&lt/auto_reload> \n';

    mapcache += '</mapcache>\n';

    return mapcache;
});

// ---------------------------------------
// Build a mapacache.xml file from
// a WMS capabilies xml file
// (Synchronous request)
// --------------------------------------------
// Parameters
//  - capabilitiesFile : xml capabilities
//  - urlRequestCapa : WMS getCapabilities request
//  - projectName : name of the project
// --------------------------------------------
buildMapcacheXml = (function(capabilitiesFile, urlRequestCapa, projectName) {
    var mapcache = 'null';
    var xhr = new XMLHttpRequest();
    xhr.open('GET', capabilitiesFile, false);
    xhr.setRequestHeader('Content-Type', 'text/xml');
    xhr.send(null);

    if (xhr.status == 200) {
        mapcache = buildMapcacheFromXml(result, urlRequestCapa, projectName);
    }
    return mapcache;
});

<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'
import { connect } from 'react-redux'

import WebView from './WebView'
import Button from '../Button'
import BrowserTabUrlField from './BrowserTabUrlField'
import SideBar from './sidebar/SideBar'
import SplitPane from 'react-split-pane'
import BrowserTabWebentityNameField from './BrowserTabWebentityNameField'
import PageHypheHome from './PageHypheHome'

import { intlShape } from 'react-intl'

import { PAGE_HYPHE_HOME } from '../../constants'

import { showError, hideError } from '../../actions/browser'
import {
  setTabUrl, setTabStatus, setTabTitle, setTabIcon,
  openTab, closeTab
} from '../../actions/tabs'
import {
  declarePage, setTabWebentity, setWebentityHomepage, setWebentityName, createWebentity,
  setAdjustWebentity, saveAdjustedWebentity, showAdjustWebentity, hideAdjustWebentity
} from '../../actions/webentities'

import networkErrors from '@naholyr/chromium-net-errors'
import { getSearchUrl } from '../../utils/search-web'

class TabContent extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      disableBack: true,
      disableForward: true
    }
    this.doNotRedirectToSearchOnNextDNSError = false // internal property, should never trigger update
    this.navigationActions = {} // Mutated by WebView
  }

  updateTabStatus (event, info) {
    const { id, setTabStatus, setTabTitle, setTabUrl, setTabIcon, openTab, closeTab,
      showError, declarePage, setTabWebentity, serverUrl, corpusId } = this.props

    if (this.navigationActions.canGoBack && this.navigationActions.canGoForward) {
      this.setState({
        disableBack: !this.navigationActions.canGoBack(),
        disableForward: !this.navigationActions.canGoForward()
      })
    }

    switch (event) {
    case 'start':
      this.doNotRedirectToSearchOnNextDNSError = false
      setTabStatus({ loading: true, url: info }, id)
      setTabWebentity(id, null)
      break
    case 'stop':
      this.doNotRedirectToSearchOnNextDNSError = false
      setTabStatus({ loading: false, url: info }, id)
      setTabUrl(info, id)
      declarePage(serverUrl, corpusId, info, id)
      break
    case 'title':
      setTabTitle(info, id)
      break
    case 'favicon':
      setTabIcon(info, id)
      break
    case 'open': // link in new tab
      openTab(info)
      break
    case 'close': // from context menu
      closeTab(id)
      break
    case 'error': {
      const err = networkErrors.createByCode(info.errorCode)
      if (err.name === 'NameNotResolvedError') {
        if (this.doNotRedirectToSearchOnNextDNSError) {
          this.doNotRedirectToSearchOnNextDNSError = false
        } else {
          // DNS error: let's search instead
          const term = info.pageURL.replace(/^.+:\/\//, '')
          this.doNotRedirectToSearchOnNextDNSError = true
          setTabUrl(getSearchUrl(term), id)
          // Main page triggered the error, it's important
          showError({ messageId: 'error.dns-error-search', fatal: false, icon: 'attention', timeout: 3000 })
        }
      } else {
        if (info.pageURL === info.validatedURL) {
          // Main page triggered the error, it's important
          showError({ messageId: 'error.network-error', messageValues: { error: err.message }, fatal: false, icon: 'attention', timeout: 10000 })
          setTabStatus({ loading: false, url: info.pageURL, error: info }, id)
        }
      }
      // Anyway, log to console
      if (process.env.NODE_ENV === 'development') {
        console.debug(info) // eslint-disable-line no-console
        console.error(err) // eslint-disable-line no-console
      }
      break
    }
    default:
      break
    }
  }

  saveAdjustChanges () {
    const { saveAdjustedWebentity, hideAdjustWebentity, serverUrl, corpusId, webentity, adjusting, hideError, showError, id } = this.props

    saveAdjustedWebentity(serverUrl, corpusId, webentity, adjusting, id)
      .then(() => {
        hideError()
        hideAdjustWebentity(webentity.id)
      })
      .catch((err) => {
        showError({ messageId: 'error.save-webentity', messageValues: { error: err.message }, fatal: false })
      })
  }

  renderHomeButton () {
    const { adjusting, setAdjustWebentity, webentity, setTabUrl, url, id } = this.props
    const { formatMessage } = this.context.intl

    if (adjusting) {
      return <Button size="large" icon="home" title={ formatMessage({ id: 'set-homepage' }, { url: url }) }
        disabled={ !webentity }
        onClick={ () => setAdjustWebentity(webentity.id, { homepage: url }) } />
    } else if (webentity && webentity.homepage) {
      return <Button size="large" icon="home" title={ formatMessage({ id: 'goto-homepage' }, { url: webentity.homepage }) }
        disabled={ !webentity || webentity.homepage === url }
        onClick={ () => setTabUrl(webentity.homepage, id) } />
    } else {
      return <Button size="large" icon="home" title={ formatMessage({ id: 'no-homepage' }) }
        disabled={ true }
        onClick={ () => {} } />
    }
  }

  renderAdjustButton () {
    const { adjusting, showAdjustWebentity, hideAdjustWebentity, webentity } = this.props
    const { formatMessage } = this.context.intl

    if (adjusting) {
      return [
        <Button key="cancel-adjust" size="large" icon="cancel" title={ formatMessage({ id: 'cancel' }) }
          onClick={ () => hideAdjustWebentity(webentity.id) } />,
        <Button key="apply-adjust" size="large" icon="check" title={ formatMessage({ id: adjusting.crawl ? 'save-and-crawl' : 'save' }) }
          onClick={ () => { this.saveAdjustChanges() } } />
      ]
    } else {
      return <Button size="large" icon="pencil" title={ formatMessage({ id: 'adjust' }) } disabled={ !this.props.webentity }
        onClick={ () => showAdjustWebentity(webentity.id) } />
    }
  }

  renderToolbar () {
    const { id, url, loading, webentity, setTabUrl, adjusting, setAdjustWebentity } = this.props
    const { formatMessage } = this.context.intl

    const ready = url === PAGE_HYPHE_HOME || (!loading && !!webentity)

    return (

              <Button title={ formatMessage({ id: 'browse-back' }) } size="large" icon="left-open" disabled={ !!adjusting || this.state.disableBack }
                onClick={ () => this.navigationActions.back() } />
              <Button title={ formatMessage({ id: 'browse-forward' }) } size="large" icon="right-open" disabled={ !!adjusting || this.state.disableForward }
                onClick={ () => this.navigationActions.forward() } />
              <Button title={ formatMessage({ id: 'browse-reload' }) } size="large" icon="ccw" disabled={ !!adjusting }
                onClick={ () => this.navigationActions.reload() } />

              <BrowserTabUrlField
                loading={ !ready }
                initialUrl={ url === PAGE_HYPHE_HOME ? '' : url }
                lruPrefixes={ webentity && webentity.lru_prefixes }
                onSubmit={ (url) => setTabUrl(url, id) }
                prefixSelector={ !!adjusting }
                onSelectPrefix={ (url, modified) => setAdjustWebentity(webentity.id, { prefix: modified ? url : null }) } />

              { this.renderHomeButton () }
              <BrowserTabWebentityNameField
                initialValue={ webentity && webentity.name }
                disabled={ url === PAGE_HYPHE_HOME }
                editable={ !!adjusting }
                onChange={ (name) => setAdjustWebentity(webentity.id, { name }) } />
              { this.renderAdjustButton() }

    )
  }

  renderSplitPane () {
    const { id, url, webentity, setTabUrl, serverUrl, corpusId } = this.props

    return (
      <SplitPane split="vertical" minSize="130" defaultSize="200">
        { webentity ? <SideBar webentity={ webentity } serverUrl={ serverUrl } corpusId={ corpusId } /> :  }
        { url === PAGE_HYPHE_HOME
          ? <PageHypheHome onSubmit={ (url) => setTabUrl(url, id) } />
          : <WebView id={ id } url={ url }
            onStatusUpdate={ (e, i) => this.updateTabStatus(e, i) }
            onNavigationActionsReady={ (actions) => Object.assign(this.navigationActions, actions) } />
        }
      </SplitPane>
    )
  }

  render () {
    const { active, id } = this.props

    return (

        { this.renderToolbar() }
        { this.renderSplitPane() }

    )
  }
}

TabContent.propTypes = {
  id: PropTypes.string.isRequired, // Tab's id (≠ webentity.id)

  active: PropTypes.bool.isRequired,
  url: PropTypes.string.isRequired,
  loading: PropTypes.bool.isRequired,
  serverUrl: PropTypes.string.isRequired,
  corpusId: PropTypes.string.isRequired,
  webentity: PropTypes.object,
  adjusting: PropTypes.object,

  showError: PropTypes.func.isRequired,
  hideError: PropTypes.func.isRequired,

  setTabUrl: PropTypes.func.isRequired,
  setTabStatus: PropTypes.func.isRequired,
  setTabTitle: PropTypes.func.isRequired,
  setTabIcon: PropTypes.func.isRequired,
  openTab: PropTypes.func.isRequired,
  closeTab: PropTypes.func.isRequired,

  declarePage: PropTypes.func.isRequired,
  setTabWebentity: PropTypes.func.isRequired,
  setWebentityHomepage: PropTypes.func.isRequired,
  setWebentityName: PropTypes.func.isRequired,
  createWebentity: PropTypes.func.isRequired,
  saveAdjustedWebentity: PropTypes.func.isRequired,
  setAdjustWebentity: PropTypes.func.isRequired,
  showAdjustWebentity: PropTypes.func.isRequired,
  hideAdjustWebentity: PropTypes.func.isRequired
}

const mapStateToProps = ({ corpora, servers, tabs, webentities }, { id }) => {
  const tab = tabs.tabs.find((tab) => tab.id === id)
  const webentity = webentities.webentities[webentities.tabs[id]]
  return {
    id,
    active: id === tabs.activeTab,
    url: tab.url,
    loading: tab.loading || false,
    serverUrl: servers.selected.url,
    corpusId: corpora.selected.corpus_id,
    webentity: webentity,
    adjusting: webentity && webentities.adjustments[webentity.id]
  }
}

const mapDispatchToProps = {
  showError, hideError,
  setTabUrl, setTabStatus, setTabTitle, setTabIcon, openTab , closeTab,
  declarePage, setTabWebentity, setWebentityHomepage, setWebentityName, createWebentity,
  setAdjustWebentity, showAdjustWebentity, hideAdjustWebentity, saveAdjustedWebentity
}

TabContent.contextTypes = {
  intl: intlShape
}

export default connect(mapStateToProps, mapDispatchToProps)(TabContent)
<commit_msg>fix(url): do not declare page on load error<commit_after>import React, { PropTypes } from 'react'
import { connect } from 'react-redux'

import WebView from './WebView'
import Button from '../Button'
import BrowserTabUrlField from './BrowserTabUrlField'
import SideBar from './sidebar/SideBar'
import SplitPane from 'react-split-pane'
import BrowserTabWebentityNameField from './BrowserTabWebentityNameField'
import PageHypheHome from './PageHypheHome'

import { intlShape } from 'react-intl'

import { PAGE_HYPHE_HOME } from '../../constants'

import { showError, hideError } from '../../actions/browser'
import {
  setTabUrl, setTabStatus, setTabTitle, setTabIcon,
  openTab, closeTab
} from '../../actions/tabs'
import {
  declarePage, setTabWebentity, setWebentityHomepage, setWebentityName, createWebentity,
  setAdjustWebentity, saveAdjustedWebentity, showAdjustWebentity, hideAdjustWebentity
} from '../../actions/webentities'

import networkErrors from '@naholyr/chromium-net-errors'
import { getSearchUrl } from '../../utils/search-web'

class TabContent extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      disableBack: true,
      disableForward: true
    }
    this.doNotRedirectToSearchOnNextDNSError = false // internal property, should never trigger update
    this.doNotDeclarePageOnStop = false // idem
    this.navigationActions = {} // Mutated by WebView
  }

  updateTabStatus (event, info) {
    const { id, setTabStatus, setTabTitle, setTabUrl, setTabIcon, openTab, closeTab,
      showError, declarePage, setTabWebentity, serverUrl, corpusId } = this.props

    if (this.navigationActions.canGoBack && this.navigationActions.canGoForward) {
      this.setState({
        disableBack: !this.navigationActions.canGoBack(),
        disableForward: !this.navigationActions.canGoForward()
      })
    }

    switch (event) {
    case 'start':
      setTabStatus({ loading: true, url: info }, id)
      setTabWebentity(id, null)
      break
    case 'stop':
      setTabStatus({ loading: false, url: info }, id)
      if (!this.doNotDeclarePageOnStop) {
        setTabUrl(info, id)
        declarePage(serverUrl, corpusId, info, id)
      } else {
        this.doNotDeclarePageOnStop = false
      }
      break
    case 'title':
      setTabTitle(info, id)
      break
    case 'favicon':
      setTabIcon(info, id)
      break
    case 'open': // link in new tab
      openTab(info)
      break
    case 'close': // from context menu
      closeTab(id)
      break
    case 'error': {
      const err = networkErrors.createByCode(info.errorCode)
      if (err.name === 'NameNotResolvedError' && !this.doNotRedirectToSearchOnNextDNSError) {
        // DNS error: let's search instead
        this.doNotDeclarePageOnStop = true
        this.doNotRedirectToSearchOnNextDNSError = true
        const term = info.pageURL.replace(/^.+:\/\/(.+?)\/?$/, '$1')
        setTabUrl(getSearchUrl(term), id)
        // Still show a dedicated error messag
        showError({ messageId: 'error.dns-error-search', fatal: false, icon: 'attention', timeout: 3000 })
      } else if (info.pageURL === info.validatedURL) {
        // Main page triggered the error, it's important
        this.doNotDeclarePageOnStop = true
        showError({ messageId: 'error.network-error', messageValues: { error: err.message }, fatal: false, icon: 'attention', timeout: 10000 })
        setTabStatus({ loading: false, url: info.pageURL, error: info }, id)
      }
      // Anyway, log to console
      if (process.env.NODE_ENV === 'development') {
        console.debug(info) // eslint-disable-line no-console
        console.error(err) // eslint-disable-line no-console
      }
      break
    }
    default:
      break
    }
  }

  saveAdjustChanges () {
    const { saveAdjustedWebentity, hideAdjustWebentity, serverUrl, corpusId, webentity, adjusting, hideError, showError, id } = this.props

    saveAdjustedWebentity(serverUrl, corpusId, webentity, adjusting, id)
      .then(() => {
        hideError()
        hideAdjustWebentity(webentity.id)
      })
      .catch((err) => {
        showError({ messageId: 'error.save-webentity', messageValues: { error: err.message }, fatal: false })
      })
  }

  renderHomeButton () {
    const { adjusting, setAdjustWebentity, webentity, setTabUrl, url, id } = this.props
    const { formatMessage } = this.context.intl

    if (adjusting) {
      return <Button size="large" icon="home" title={ formatMessage({ id: 'set-homepage' }, { url: url }) }
        disabled={ !webentity }
        onClick={ () => setAdjustWebentity(webentity.id, { homepage: url }) } />
    } else if (webentity && webentity.homepage) {
      return <Button size="large" icon="home" title={ formatMessage({ id: 'goto-homepage' }, { url: webentity.homepage }) }
        disabled={ !webentity || webentity.homepage === url }
        onClick={ () => setTabUrl(webentity.homepage, id) } />
    } else {
      return <Button size="large" icon="home" title={ formatMessage({ id: 'no-homepage' }) }
        disabled={ true }
        onClick={ () => {} } />
    }
  }

  renderAdjustButton () {
    const { adjusting, showAdjustWebentity, hideAdjustWebentity, webentity } = this.props
    const { formatMessage } = this.context.intl

    if (adjusting) {
      return [
        <Button key="cancel-adjust" size="large" icon="cancel" title={ formatMessage({ id: 'cancel' }) }
          onClick={ () => hideAdjustWebentity(webentity.id) } />,
        <Button key="apply-adjust" size="large" icon="check" title={ formatMessage({ id: adjusting.crawl ? 'save-and-crawl' : 'save' }) }
          onClick={ () => { this.saveAdjustChanges() } } />
      ]
    } else {
      return <Button size="large" icon="pencil" title={ formatMessage({ id: 'adjust' }) } disabled={ !this.props.webentity }
        onClick={ () => showAdjustWebentity(webentity.id) } />
    }
  }

  renderToolbar () {
    const { id, url, loading, webentity, setTabUrl, adjusting, setAdjustWebentity } = this.props
    const { formatMessage } = this.context.intl

    const ready = url === PAGE_HYPHE_HOME || (!loading && !!webentity)

    return (

              <Button title={ formatMessage({ id: 'browse-back' }) } size="large" icon="left-open" disabled={ !!adjusting || this.state.disableBack }
                onClick={ () => this.navigationActions.back() } />
              <Button title={ formatMessage({ id: 'browse-forward' }) } size="large" icon="right-open" disabled={ !!adjusting || this.state.disableForward }
                onClick={ () => this.navigationActions.forward() } />
              <Button title={ formatMessage({ id: 'browse-reload' }) } size="large" icon="ccw" disabled={ !!adjusting }
                onClick={ () => this.navigationActions.reload() } />

              <BrowserTabUrlField
                loading={ !ready }
                initialUrl={ url === PAGE_HYPHE_HOME ? '' : url }
                lruPrefixes={ webentity && webentity.lru_prefixes }
                onSubmit={ (url) => setTabUrl(url, id) }
                prefixSelector={ !!adjusting }
                onSelectPrefix={ (url, modified) => setAdjustWebentity(webentity.id, { prefix: modified ? url : null }) } />

              { this.renderHomeButton () }
              <BrowserTabWebentityNameField
                initialValue={ webentity && webentity.name }
                disabled={ url === PAGE_HYPHE_HOME }
                editable={ !!adjusting }
                onChange={ (name) => setAdjustWebentity(webentity.id, { name }) } />
              { this.renderAdjustButton() }

    )
  }

  renderSplitPane () {
    const { id, url, webentity, setTabUrl, serverUrl, corpusId } = this.props

    return (
      <SplitPane split="vertical" minSize="130" defaultSize="200">
        { webentity ? <SideBar webentity={ webentity } serverUrl={ serverUrl } corpusId={ corpusId } /> :  }
        { url === PAGE_HYPHE_HOME
          ? <PageHypheHome onSubmit={ (url) => setTabUrl(url, id) } />
          : <WebView id={ id } url={ url }
            onStatusUpdate={ (e, i) => this.updateTabStatus(e, i) }
            onNavigationActionsReady={ (actions) => Object.assign(this.navigationActions, actions) } />
        }
      </SplitPane>
    )
  }

  render () {
    const { active, id } = this.props

    return (

        { this.renderToolbar() }
        { this.renderSplitPane() }

    )
  }
}

TabContent.propTypes = {
  id: PropTypes.string.isRequired, // Tab's id (≠ webentity.id)

  active: PropTypes.bool.isRequired,
  url: PropTypes.string.isRequired,
  loading: PropTypes.bool.isRequired,
  serverUrl: PropTypes.string.isRequired,
  corpusId: PropTypes.string.isRequired,
  webentity: PropTypes.object,
  adjusting: PropTypes.object,

  showError: PropTypes.func.isRequired,
  hideError: PropTypes.func.isRequired,

  setTabUrl: PropTypes.func.isRequired,
  setTabStatus: PropTypes.func.isRequired,
  setTabTitle: PropTypes.func.isRequired,
  setTabIcon: PropTypes.func.isRequired,
  openTab: PropTypes.func.isRequired,
  closeTab: PropTypes.func.isRequired,

  declarePage: PropTypes.func.isRequired,
  setTabWebentity: PropTypes.func.isRequired,
  setWebentityHomepage: PropTypes.func.isRequired,
  setWebentityName: PropTypes.func.isRequired,
  createWebentity: PropTypes.func.isRequired,
  saveAdjustedWebentity: PropTypes.func.isRequired,
  setAdjustWebentity: PropTypes.func.isRequired,
  showAdjustWebentity: PropTypes.func.isRequired,
  hideAdjustWebentity: PropTypes.func.isRequired
}

const mapStateToProps = ({ corpora, servers, tabs, webentities }, { id }) => {
  const tab = tabs.tabs.find((tab) => tab.id === id)
  const webentity = webentities.webentities[webentities.tabs[id]]
  return {
    id,
    active: id === tabs.activeTab,
    url: tab.url,
    loading: tab.loading || false,
    serverUrl: servers.selected.url,
    corpusId: corpora.selected.corpus_id,
    webentity: webentity,
    adjusting: webentity && webentities.adjustments[webentity.id]
  }
}

const mapDispatchToProps = {
  showError, hideError,
  setTabUrl, setTabStatus, setTabTitle, setTabIcon, openTab , closeTab,
  declarePage, setTabWebentity, setWebentityHomepage, setWebentityName, createWebentity,
  setAdjustWebentity, showAdjustWebentity, hideAdjustWebentity, saveAdjustedWebentity
}

TabContent.contextTypes = {
  intl: intlShape
}

export default connect(mapStateToProps, mapDispatchToProps)(TabContent)
<|endoftext|>


<commit_before>export default [
    {
        "code": "AR",
        "languages": [
            {
                "code": "es-AR",
                "name": "Argentinian Spanish"
            }
        ],
        "name": "Argentina"
    },
    {
        "code": "AT",
        "languages": [
            {
                "code": "de-AT",
                "name": "Deutsch"
            }
        ],
        "name": "Austria"
    },
    {
        "code": "BE",
        "languages": [
            {
                "code": "nl-BE",
                "name": "Dutch"
            }
        ],
        "name": "Belgium"
    },
    {
        "code": "BR",
        "languages": [
            {
                "code": "pt-BR",
                "name": "Portuguese"
            }
        ],
        "name": "Brazil"
    },
    {
        "code": "CA",
        "languages": [
            {
                "code": "en-CA",
                "name": "English"
            },
            {
                "code": "fr-CA",
                "name": "French"
            }
        ],
        "name": "Canada"
    },
    {
        "code": "CL",
        "languages": [
            {
                "code": "es-CL",
                "name": "Spanish"
            }
        ],
        "name": "Chile"
    },
    {
        "code": "CN",
        "languages": [
            {
                "code": "zh-CN",
                "name": "Chinese (simplified)"
            }
        ],
        "name": "China"
    },
    {
        "code": "CR",
        "languages": [
            {
                "code": "hr-CR",
                "name": "Croatian"
            }
        ],
        "name": "Croatia"
    },
    {
        "code": "CZ",
        "languages": [
            {
                "code": "cs-CZ",
                "name": "Czech"
            }
        ],
        "name": "Czech Republic"
    },
    {
        "code": "DK",
        "languages": [
            {
                "code": "da-DK",
                "name": "Danish"
            }
        ],
        "name": "Denmark"
    },
    {
        "code": "EE",
        "languages": [
            {
                "code": "et-EE",
                "name": "Estonian"
            }
        ],
        "name": "Estonia"
    },
    {
        "code": "ET",
        "languages": [
            {
                "code": "am-ET",
                "name": "Amharic"
            }
        ],
        "name": "Ethiopia"
    },
    {
        "code": "FI",
        "languages": [
            {
                "code": "fi-FI",
                "name": "Finnish"
            }
        ],
        "name": "Finland"
    },
    {
        "code": "FR",
        "languages": [
            {
                "code": "fr-FR",
                "name": "French"
            }
        ],
        "name": "France"
    },
    {
        "code": "DE",
        "languages": [
            {
                "code": "de-DE",
                "name": "German"
            }
        ],
        "name": "Germany"
    },
    {
        "code": "GR",
        "languages": [
            {
                "code": "el-GR",
                "name": "Greek"
            }
        ],
        "name": "Greece"
    },
    {
        "code": "HK",
        "languages": [
            {
                "code": "code",
                "name": "Hong Kong Chinese"
            }
        ],
        "name": "Hong Kong"
    },
    {
        "code": "HU",
        "languages": [
            {
                "code": "hu-HU",
                "name": "Hungarian"
            }
        ],
        "name": "Hungary"
    },
    {
        "code": "IS",
        "languages": [
            {
                "code": "is-IS",
                "name": "Icelandic"
            }
        ],
        "name": "Iceland"
    },
    {
        "code": "IN",
        "languages": [
            {
                "code": "en-IN",
                "name": "English"
            },
            {
                "code": "mr-IN",
                "name": "Marathi"
            },
            {
                "code": "hi-IN",
                "name": "Hindi"
            }
        ],
        "name": "India"
    },
    {
        "code": "IL",
        "languages": [
            {
                "code": "he-IL",
                "name": "Hebrew"
            }
        ],
        "name": "Israel"
    },
    {
        "code": "IT",
        "languages": [
            {
                "code": "it-IT",
                "name": "Italian"
            }
        ],
        "name": "Italy"
    },
    {
        "code": "JP",
        "languages": [
            {
                "code": "ja-JP",
                "name": "Japanese"
            }
        ],
        "name": "Japan"
    },
    {
        "code": "JO",
        "languages": [
            {
                "code": "ar-JO",
                "name": "Arabic"
            }
        ],
        "name": "Jordan"
    },
    {
        "code": "LV",
        "languages": [
            {
                "code": "lv-LV",
                "name": "Latvian"
            }
        ],
        "name": "Latvia"
    },
    {
        "code": "LT",
        "languages": [
            {
                "code": "lt-LT",
                "name": "Lithuanian"
            }
        ],
        "name": "Lithuania"
    },
    {
        "code": "MK",
        "languages": [
            {
                "code": "mk-MK",
                "name": "Macedonian"
            }
        ],
        "name": "Macedonia"
    },
    {
        "code": "MY",
        "languages": [
            {
                "code": "ms-MY",
                "name": "Malay"
            }
        ],
        "name": "Malaysia"
    },
    {
        "code": "MX",
        "languages": [
            {
                "code": "es-mx",
                "name": "Spanish"
            }
        ],
        "name": "Mexico"
    },
    {
        "code": "NL",
        "languages": [
            {
                "code": "nl-NL",
                "name": "Dutch"
            }
        ],
        "name": "Netherlands"
    },
    {
        "code": "NZ",
        "languages": [
            {
                "code": "en-NZ",
                "name": "New Zealand English"
            }
        ],
        "name": "New Zealand"
    },
    {
        "code": "NO",
        "languages": [
            {
                "code": "no-NO",
                "name": "Norwegian"
            }
        ],
        "name": "Norway"
    },
    {
        "code": "PK",
        "languages": [
            {
                "code": "ur-PK",
                "name": "Urdu"
            }
        ],
        "name": "Pakistan"
    },
    {
        "code": "PS",
        "languages": [
            {
                "code": "ar-PS",
                "name": "Arabic"
            }
        ],
        "name": "Palestine"
    },
    {
        "code": "PE",
        "languages": [
            {
                "code": "es-PE",
                "name": "Español"
            }
        ],
        "name": "Peru"
    },
    {
        "code": "PH",
        "languages": [
            {
                "code": "en-PH",
                "name": "English"
            }
        ],
        "name": "Philippines"
    },
    {
        "code": "PL",
        "languages": [
            {
                "code": "pl-PL",
                "name": "Polish"
            }
        ],
        "name": "Poland"
    },
    {
        "code": "PT",
        "languages": [
            {
                "code": "pt-PT",
                "name": "Portugese"
            }
        ],
        "name": "Portugal"
    },
    {
        "code": "RO",
        "languages": [
            {
                "code": "ro-RO",
                "name": "Romanian"
            }
        ],
        "name": "Romania"
    },
    {
        "code": "RU",
        "languages": [
            {
                "code": "ru-RU",
                "name": "Russian"
            }
        ],
        "name": "Russia"
    },
    {
        "code": "SN",
        "languages": [
            {
                "code": "fr-SN",
                "name": "French"
            }
        ],
        "name": "Senegal"
    },
    {
        "code": "RS",
        "languages": [
            {
                "code": "sr-SP",
                "name": "Serbian"
            }
        ],
        "name": "Serbia"
    },
    {
        "code": "SG",
        "languages": [
            {
                "code": "en-SG",
                "name": "English"
            }
        ],
        "name": "Singapore"
    },
    {
        "code": "SK",
        "languages": [
            {
                "code": "sk-SK",
                "name": "Slovak"
            }
        ],
        "name": "Slovakia"
    },
    {
        "code": "SI",
        "languages": [
            {
                "code": "sl-SI",
                "name": "Slovenian"
            }
        ],
        "name": "Slovenia"
    },
    {
        "code": "KR",
        "languages": [
            {
                "code": "ko-KR",
                "name": "Korean"
            }
        ],
        "name": "South Korea"
    },
    {
        "code": "ES",
        "languages": [
            {
                "code": "ca-ES",
                "name": "Catalan"
            },
            {
                "code": "es-es",
                "name": "Spanish"
            }
        ],
        "name": "Spain"
    },
    {
        "code": "SE",
        "languages": [
            {
                "code": "sv-SE",
                "name": "Swedish"
            }
        ],
        "name": "Sweden"
    },
    {
        "code": "CH",
        "languages": [
            {
                "code": "fr-CH",
                "name": "French"
            },
            {
                "code": "de-CH",
                "name": "Deutsch"
            }
        ],
        "name": "Switzerland"
    },
    {
        "code": "TR",
        "languages": [
            {
                "code": "tr-TR",
                "name": "Turkish"
            }
        ],
        "name": "Turkey"
    },
    {
        "code": "UG",
        "languages": [
            {
                "code": "en-UG",
                "name": "English"
            },
            {
                "code": "lg-UG",
                "name": "Luganda"
            },
            {
                "code": "rk-UG",
                "name": "Runyankore"
            }
        ],
        "name": "Uganda"
    },
    {
        "code": "UA",
        "languages": [
            {
                "code": "uk-UA",
                "name": "Ukrainian"
            },
            {
                "code": "ru-UA",
                "name": "Russian"
            }
        ],
        "name": "Ukraine"
    },
    {
        "code": "AE",
        "languages": [
            {
                "code": "en-AE",
                "name": "English"
            },
            {
                "code": "ar-AE",
                "name": "Arabic"
            }
        ],
        "name": "United Arab Emirates"
    },
    {
        "code": "GB",
        "languages": [
            {
                "code": "en-GB",
                "name": "English"
            }
        ],
        "name": "United Kingdom"
    },
    {
        "code": "US",
        "languages": [
            {
                "code": "en-US",
                "name": "English"
            }
        ],
        "name": "USA"
    }
];
<commit_msg>Add country code next to language<commit_after>export default [
    {
        "code": "AR",
        "languages": [
            {
                "code": "es-AR",
                "name": "Argentinian Spanish"
            }
        ],
        "name": "Argentina"
    },
    {
        "code": "AT",
        "languages": [
            {
                "code": "de-AT",
                "name": "Deutsch (AT)"
            }
        ],
        "name": "Austria"
    },
    {
        "code": "BE",
        "languages": [
            {
                "code": "nl-BE",
                "name": "Dutch (BE)"
            }
        ],
        "name": "Belgium"
    },
    {
        "code": "BR",
        "languages": [
            {
                "code": "pt-BR",
                "name": "Portuguese (BR)"
            }
        ],
        "name": "Brazil"
    },
    {
        "code": "CA",
        "languages": [
            {
                "code": "en-CA",
                "name": "English (CA)"
            },
            {
                "code": "fr-CA",
                "name": "French (CA)"
            }
        ],
        "name": "Canada"
    },
    {
        "code": "CL",
        "languages": [
            {
                "code": "es-CL",
                "name": "Spanish (CL)"
            }
        ],
        "name": "Chile"
    },
    {
        "code": "CN",
        "languages": [
            {
                "code": "zh-CN",
                "name": "Chinese (simplified)"
            }
        ],
        "name": "China"
    },
    {
        "code": "CR",
        "languages": [
            {
                "code": "hr-CR",
                "name": "Croatian"
            }
        ],
        "name": "Croatia"
    },
    {
        "code": "CZ",
        "languages": [
            {
                "code": "cs-CZ",
                "name": "Czech"
            }
        ],
        "name": "Czech Republic"
    },
    {
        "code": "DK",
        "languages": [
            {
                "code": "da-DK",
                "name": "Danish"
            }
        ],
        "name": "Denmark"
    },
    {
        "code": "EE",
        "languages": [
            {
                "code": "et-EE",
                "name": "Estonian"
            }
        ],
        "name": "Estonia"
    },
    {
        "code": "ET",
        "languages": [
            {
                "code": "am-ET",
                "name": "Amharic"
            }
        ],
        "name": "Ethiopia"
    },
    {
        "code": "FI",
        "languages": [
            {
                "code": "fi-FI",
                "name": "Finnish"
            }
        ],
        "name": "Finland"
    },
    {
        "code": "FR",
        "languages": [
            {
                "code": "fr-FR",
                "name": "French (FR)"
            }
        ],
        "name": "France"
    },
    {
        "code": "DE",
        "languages": [
            {
                "code": "de-DE",
                "name": "German"
            }
        ],
        "name": "Germany"
    },
    {
        "code": "GR",
        "languages": [
            {
                "code": "el-GR",
                "name": "Greek"
            }
        ],
        "name": "Greece"
    },
    {
        "code": "HK",
        "languages": [
            {
                "code": "code",
                "name": "Hong Kong Chinese"
            }
        ],
        "name": "Hong Kong"
    },
    {
        "code": "HU",
        "languages": [
            {
                "code": "hu-HU",
                "name": "Hungarian"
            }
        ],
        "name": "Hungary"
    },
    {
        "code": "IS",
        "languages": [
            {
                "code": "is-IS",
                "name": "Icelandic"
            }
        ],
        "name": "Iceland"
    },
    {
        "code": "IN",
        "languages": [
            {
                "code": "en-IN",
                "name": "English (IN)"
            },
            {
                "code": "mr-IN",
                "name": "Marathi"
            },
            {
                "code": "hi-IN",
                "name": "Hindi"
            }
        ],
        "name": "India"
    },
    {
        "code": "IL",
        "languages": [
            {
                "code": "he-IL",
                "name": "Hebrew"
            }
        ],
        "name": "Israel"
    },
    {
        "code": "IT",
        "languages": [
            {
                "code": "it-IT",
                "name": "Italian"
            }
        ],
        "name": "Italy"
    },
    {
        "code": "JP",
        "languages": [
            {
                "code": "ja-JP",
                "name": "Japanese"
            }
        ],
        "name": "Japan"
    },
    {
        "code": "JO",
        "languages": [
            {
                "code": "ar-JO",
                "name": "Arabic (JO)"
            }
        ],
        "name": "Jordan"
    },
    {
        "code": "LV",
        "languages": [
            {
                "code": "lv-LV",
                "name": "Latvian"
            }
        ],
        "name": "Latvia"
    },
    {
        "code": "LT",
        "languages": [
            {
                "code": "lt-LT",
                "name": "Lithuanian"
            }
        ],
        "name": "Lithuania"
    },
    {
        "code": "MK",
        "languages": [
            {
                "code": "mk-MK",
                "name": "Macedonian"
            }
        ],
        "name": "Macedonia"
    },
    {
        "code": "MY",
        "languages": [
            {
                "code": "ms-MY",
                "name": "Malay"
            }
        ],
        "name": "Malaysia"
    },
    {
        "code": "MX",
        "languages": [
            {
                "code": "es-mx",
                "name": "Spanish (MX)"
            }
        ],
        "name": "Mexico"
    },
    {
        "code": "NL",
        "languages": [
            {
                "code": "nl-NL",
                "name": "Dutch (NL)"
            }
        ],
        "name": "Netherlands"
    },
    {
        "code": "NZ",
        "languages": [
            {
                "code": "en-NZ",
                "name": "New Zealand English"
            }
        ],
        "name": "New Zealand"
    },
    {
        "code": "NO",
        "languages": [
            {
                "code": "no-NO",
                "name": "Norwegian"
            }
        ],
        "name": "Norway"
    },
    {
        "code": "PK",
        "languages": [
            {
                "code": "ur-PK",
                "name": "Urdu"
            }
        ],
        "name": "Pakistan"
    },
    {
        "code": "PS",
        "languages": [
            {
                "code": "ar-PS",
                "name": "Arabic (PS)"
            }
        ],
        "name": "Palestine"
    },
    {
        "code": "PE",
        "languages": [
            {
                "code": "es-PE",
                "name": "Español"
            }
        ],
        "name": "Peru"
    },
    {
        "code": "PH",
        "languages": [
            {
                "code": "en-PH",
                "name": "English (PH)"
            }
        ],
        "name": "Philippines"
    },
    {
        "code": "PL",
        "languages": [
            {
                "code": "pl-PL",
                "name": "Polish"
            }
        ],
        "name": "Poland"
    },
    {
        "code": "PT",
        "languages": [
            {
                "code": "pt-PT",
                "name": "Portugese (PT)"
            }
        ],
        "name": "Portugal"
    },
    {
        "code": "RO",
        "languages": [
            {
                "code": "ro-RO",
                "name": "Romanian"
            }
        ],
        "name": "Romania"
    },
    {
        "code": "RU",
        "languages": [
            {
                "code": "ru-RU",
                "name": "Russian (RU)"
            }
        ],
        "name": "Russia"
    },
    {
        "code": "SN",
        "languages": [
            {
                "code": "fr-SN",
                "name": "French (SN)"
            }
        ],
        "name": "Senegal"
    },
    {
        "code": "RS",
        "languages": [
            {
                "code": "sr-SP",
                "name": "Serbian"
            }
        ],
        "name": "Serbia"
    },
    {
        "code": "SG",
        "languages": [
            {
                "code": "en-SG",
                "name": "English (SG)"
            }
        ],
        "name": "Singapore"
    },
    {
        "code": "SK",
        "languages": [
            {
                "code": "sk-SK",
                "name": "Slovak"
            }
        ],
        "name": "Slovakia"
    },
    {
        "code": "SI",
        "languages": [
            {
                "code": "sl-SI",
                "name": "Slovenian"
            }
        ],
        "name": "Slovenia"
    },
    {
        "code": "KR",
        "languages": [
            {
                "code": "ko-KR",
                "name": "Korean"
            }
        ],
        "name": "South Korea"
    },
    {
        "code": "ES",
        "languages": [
            {
                "code": "ca-ES",
                "name": "Catalan"
            },
            {
                "code": "es-es",
                "name": "Spanish (ES)"
            }
        ],
        "name": "Spain"
    },
    {
        "code": "SE",
        "languages": [
            {
                "code": "sv-SE",
                "name": "Swedish"
            }
        ],
        "name": "Sweden"
    },
    {
        "code": "CH",
        "languages": [
            {
                "code": "fr-CH",
                "name": "French (CH)"
            },
            {
                "code": "de-CH",
                "name": "Deutsch (CH)"
            }
        ],
        "name": "Switzerland"
    },
    {
        "code": "TR",
        "languages": [
            {
                "code": "tr-TR",
                "name": "Turkish"
            }
        ],
        "name": "Turkey"
    },
    {
        "code": "UG",
        "languages": [
            {
                "code": "en-UG",
                "name": "English (UG)"
            },
            {
                "code": "lg-UG",
                "name": "Luganda"
            },
            {
                "code": "rk-UG",
                "name": "Runyankore"
            }
        ],
        "name": "Uganda"
    },
    {
        "code": "UA",
        "languages": [
            {
                "code": "uk-UA",
                "name": "Ukrainian"
            },
            {
                "code": "ru-UA",
                "name": "Russian (UA)"
            }
        ],
        "name": "Ukraine"
    },
    {
        "code": "AE",
        "languages": [
            {
                "code": "en-AE",
                "name": "English (UAE)"
            },
            {
                "code": "ar-AE",
                "name": "Arabic (UAE)"
            }
        ],
        "name": "United Arab Emirates"
    },
    {
        "code": "GB",
        "languages": [
            {
                "code": "en-GB",
                "name": "English (GB)"
            }
        ],
        "name": "United Kingdom"
    },
    {
        "code": "US",
        "languages": [
            {
                "code": "en-US",
                "name": "English (US)"
            }
        ],
        "name": "USA"
    }
];
<|endoftext|>


<commit_before>// Taken from example code @ http://plnkr.co/edit/nGj08KzQrZTiCP4ubDOc?p=preview

angular.module('demo.ordinalDate', [])

  .filter('ordinalDate', ['$filter', function($filter) {
    var suffixes = ["th", "st", "nd", "rd"];
    return function(input, format) {
      var dateWithoutOrdinal = $filter('date')(input, format);

      var day = parseInt($filter('date')(input, 'dd'));
      var relevantDigits = (day < 30) ? day % 20 : day % 10;

      var suffix = (relevantDigits <= 3) ? suffixes[relevantDigits] : suffixes[0];
      return dateWithoutOrdinal.replace('oo', suffix);
    };
  }]);<commit_msg>Fix date bug.<commit_after>// Taken from example code @ http://plnkr.co/edit/nGj08KzQrZTiCP4ubDOc?p=preview

angular.module('demo.ordinalDate', [])

  .filter('ordinalDate', ['$filter', function($filter) {
    var suffixes = ["th", "st", "nd", "rd"];
    return function(input, format) {
      var dateWithoutOrdinal = $filter('date')(input, format);
      if(!dateWithoutOrdinal) { return ''; }

      var day = parseInt($filter('date')(input, 'dd'));
      var relevantDigits = (day < 30) ? day % 20 : day % 10;

      var suffix = (relevantDigits <= 3) ? suffixes[relevantDigits] : suffixes[0];
      return dateWithoutOrdinal.replace('oo', suffix);
    };
  }]);<|endoftext|>


<commit_before>/*
 *
 * SignupView
 *
 */

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { showLoading, hideLoading } from 'react-redux-loading-bar'
import api from 'services'
import { withRouter } from 'react-router'
import View from 'components/View'
import { injectIntl, intlShape, FormattedMessage } from 'react-intl'
import { RecoverPasswordForm } from 'components/Login'
import ConditionalPaper from 'components/ConditionalPaper'
import Logo from 'components/Logo'
import P from 'components/P'
import AlertWindow from 'components/AlertWindow'
import messages from './messages'

class RecoverPasswordView extends Component {
  constructor(props) {
    super(props)
    this.state = {
      loading: false,
      error: '',
      sent: false
    }
  }

  resetError = () => {
    this.setState({ error: '' })
  }

  handleSubmit = async (formData) => {
    const { showProgressBar, hideProgressBar } = this.props
    try {
      const data = { ...formData.toJS() }
      showProgressBar()
      await api.RESET_USER_PASSWORD(data)
      hideProgressBar()
      this.setState({ sent: true })
    } catch (error) {
      this.setState({ error: error.message })
    }
  }

  render() {
    const { intl } = this.props
    const { email } = this.props.params
    const { error, sent } = this.state
    const { formatMessage } = intl
    let showError = null
    if (error === 'USER_NOT_EXISTS') {
      showError = (
        <AlertWindow
          title={formatMessage(messages.resetPassword)}
          desc={formatMessage(messages.userNotExists)}
          onReset={this.resetError}
        />
      )
    } else {
      showError = (
        <AlertWindow
          title={formatMessage(messages.resetPassword)}
          desc={formatMessage(messages.passwordNotReset)}
          onReset={this.resetError}
        />
      )
    }
    const renderView = sent ? (

        <Logo src='https://static.arasaac.org/pictograms/5432/5432_300.png' />

          <FormattedMessage {...messages.passwordResetSend} />

    ) : (

        <RecoverPasswordForm onSubmit={this.handleSubmit} email={email} />
        {error && showError}

    )

    return (
      <View>
        <ConditionalPaper>{renderView}</ConditionalPaper>
      </View>
    )
  }
}

RecoverPasswordView.propTypes = {
  intl: intlShape.isRequired,
  params: PropTypes.object.isRequired,
  showProgressBar: PropTypes.func.isRequired,
  hideProgressBar: PropTypes.func.isRequired
}

const mapDispatchToProps = (dispatch) => ({
  showProgressBar: () => dispatch(showLoading()),
  hideProgressBar: () => dispatch(hideLoading())
})

export default connect(
  null,
  mapDispatchToProps
)(injectIntl(withRouter(RecoverPasswordView)))
<commit_msg>fix error with loading bar<commit_after>/*
 *
 * SignupView
 *
 */

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { showLoading, hideLoading } from 'react-redux-loading-bar'
import api from 'services'
import { withRouter } from 'react-router'
import View from 'components/View'
import { injectIntl, intlShape, FormattedMessage } from 'react-intl'
import { RecoverPasswordForm } from 'components/Login'
import ConditionalPaper from 'components/ConditionalPaper'
import Logo from 'components/Logo'
import P from 'components/P'
import AlertWindow from 'components/AlertWindow'
import messages from './messages'

class RecoverPasswordView extends Component {
  constructor(props) {
    super(props)
    this.state = {
      error: '',
      sent: false
    }
  }

  resetError = () => {
    this.setState({ error: '' })
  }

  handleSubmit = async (formData) => {
    const { showProgressBar, hideProgressBar } = this.props
    try {
      const data = { ...formData.toJS() }
      showProgressBar()
      await api.RESET_USER_PASSWORD(data)
      hideProgressBar()
      this.setState({ sent: true })
    } catch (error) {
      hideProgressBar()
      this.setState({ sent: false, error: error.message })
    }
  }

  render() {
    const { intl } = this.props
    const { email } = this.props.params
    const { error, sent } = this.state
    const { formatMessage } = intl
    let showError = null
    if (error === 'USER_NOT_EXISTS') {
      showError = (
        <AlertWindow
          title={formatMessage(messages.resetPassword)}
          desc={formatMessage(messages.userNotExists)}
          onReset={this.resetError}
        />
      )
    } else {
      showError = (
        <AlertWindow
          title={formatMessage(messages.resetPassword)}
          desc={formatMessage(messages.passwordNotReset)}
          onReset={this.resetError}
        />
      )
    }
    const renderView = sent ? (

        <Logo src='https://static.arasaac.org/pictograms/5432/5432_300.png' />

          <FormattedMessage {...messages.passwordResetSend} />

    ) : (

        <RecoverPasswordForm onSubmit={this.handleSubmit} email={email} />
        {error && showError}

    )

    return (
      <View>
        <ConditionalPaper>{renderView}</ConditionalPaper>
      </View>
    )
  }
}

RecoverPasswordView.propTypes = {
  intl: intlShape.isRequired,
  params: PropTypes.object.isRequired,
  showProgressBar: PropTypes.func.isRequired,
  hideProgressBar: PropTypes.func.isRequired
}

const mapDispatchToProps = (dispatch) => ({
  showProgressBar: () => dispatch(showLoading()),
  hideProgressBar: () => dispatch(hideLoading())
})

export default connect(
  null,
  mapDispatchToProps
)(injectIntl(withRouter(RecoverPasswordView)))
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Photo = mongoose.model('Photo'),
	_ = require('lodash');

/**
 * Create a Photo
 */
exports.create = function(req, res) {
  var photo = new Photo(req.body);
  photo.user = req.user;
  photo.likes.push(req.user._id);
  if(req.files.file) {
    photo.image =req.files.file.path.substring(req.files.file.path.indexOf(path.sep)+path.sep.length-1);
  }  else
    photo.image='default.jpg';
  photo.save(function(err) {
    if (err) {
      console.log('detected error:',errorHandler.getErrorMessage(err));
      return res.status(400).send({
	message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json({_id:photo._id});
    }
  });
};

/**
 * Show the current Photo
 */
exports.read = function(req, res) {
  var photo = req.photo;
  //  photo = _.extend(photo , req.body);
  photo.views += 1;
  photo.save(function(err) {
    if (err) {
      console.log('Problem'+err);
      return res.status(400).send({
	message: errorHandler.getErrorMessage(err)
      });
    } else
      console.log(photo);
      res.jsonp(photo);
  });
};

/**
 * Update a Photo
 */
exports.update = function(req, res) {
	var photo = req.photo ;

	photo = _.extend(photo , req.body);

	photo.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(photo);
		}
	});
};

/**
 * Delete an Photo
 */
exports.delete = function(req, res) {
	var photo = req.photo ;

	photo.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(photo);
		}
	});
};

/**
 * List of Photos
 */
exports.list = function(req, res) {
	Photo.find().sort('-created').populate('user', 'displayName').exec(function(err, photos) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(photos);
		}
	});
};
/**
 * Likes a photo
 */
exports.like = function(req, res) {
  var user = req.user;
  var containsValue = false;

  // Determine if user is already in
  for(var i=0; i<req.photo.likes.length; i++) {
    console.log('Comparing ' + req.photo.likes[i] + ' to ' + req.user._id + ' is ' + req.photo.likes[i].equals(req.user._id));
    if(req.photo.likes[i].equals(req.user._id)) {
      containsValue = true;
    }
  }
  if(!containsValue) {
	req.photo.likes.push(req.user._id);
  }
  req.photo.save(function(err) {
    if (err) {
      return res.status(400).send({
		message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(req.photo);
	 }
  });
};

/**
 * Photo middleware
 */
exports.photoByID = function(req, res, next, id) {
  console.log('finding by id:'+id);
	Photo.findById(id).populate('user', 'displayName').exec(function(err, photo) {
	  if (err) return next(err);
	  if (! photo) return next(new Error('Failed to load Photo ' + id));
	  req.photo = photo;
	  next();
	});
};

/**
 * Photo authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.photo.user.id !== req.user.id) {
		return res.status(403).send('User is not authorized');
	}
	next();
};<commit_msg>Revert "n"<commit_after>'use strict';
var path = require('path');
/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Photo = mongoose.model('Photo'),
	_ = require('lodash');

/**
 * Create a Photo
 */
exports.create = function(req, res) {
  var photo = new Photo(req.body);
  photo.user = req.user;
  photo.likes.push(req.user._id);
  if(req.files.file) {
    photo.image =req.files.file.path.substring(req.files.file.path.indexOf(path.sep)+path.sep.length-1);
  }  else
    photo.image='default.jpg';
  photo.save(function(err) {
    if (err) {
      console.log('detected error:',errorHandler.getErrorMessage(err));
      return res.status(400).send({
	message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json({_id:photo._id});
    }
  });
};

/**
 * Show the current Photo
 */
exports.read = function(req, res) {
  var photo = req.photo;
  //  photo = _.extend(photo , req.body);
  photo.views += 1;
  photo.save(function(err) {
    if (err) {
      console.log('Problem'+err);
      return res.status(400).send({
	message: errorHandler.getErrorMessage(err)
      });
    } else
      console.log(photo);
      res.jsonp(photo);
  });
};

/**
 * Update a Photo
 */
exports.update = function(req, res) {
	var photo = req.photo ;

	photo = _.extend(photo , req.body);

	photo.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(photo);
		}
	});
};

/**
 * Delete an Photo
 */
exports.delete = function(req, res) {
	var photo = req.photo ;

	photo.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(photo);
		}
	});
};

/**
 * List of Photos
 */
exports.list = function(req, res) {
	Photo.find().sort('-created').populate('user', 'displayName').exec(function(err, photos) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(photos);
		}
	});
};
/**
 * Likes a photo
 */
exports.like = function(req, res) {
  var user = req.user;
  var containsValue = false;

  // Determine if user is already in
  for(var i=0; i<req.photo.likes.length; i++) {
    console.log('Comparing ' + req.photo.likes[i] + ' to ' + req.user._id + ' is ' + req.photo.likes[i].equals(req.user._id));
    if(req.photo.likes[i].equals(req.user._id)) {
      containsValue = true;
    }
  }
  if(!containsValue) {
	req.photo.likes.push(req.user._id);
  }
  req.photo.save(function(err) {
    if (err) {
      return res.status(400).send({
		message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(req.photo);
	 }
  });
};

/**
 * Photo middleware
 */
exports.photoByID = function(req, res, next, id) {
  console.log('finding by id:'+id);
	Photo.findById(id).populate('user', 'displayName').exec(function(err, photo) {
	  if (err) return next(err);
	  if (! photo) return next(new Error('Failed to load Photo ' + id));
	  req.photo = photo;
	  next();
	});
};

/**
 * Photo authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.photo.user.id !== req.user.id) {
		return res.status(403).send('User is not authorized');
	}
	next();
};
<|endoftext|>


<commit_before>/*
 * grunt-hockeyapp-puck
 * https://github.com/dresources/grunt-hockeyapp-puck.git
 *
 * Copyright (c) 2015 rtregaskis
 * Licensed under the MIT license.
 */

var request = require('request'),
    fs = require('fs'),
	path = require('path');

module.exports = function(grunt) {
    'use strict';

    // Please see the Grunt documentation for more information regarding task
    // creation: http://gruntjs.com/creating-tasks

    grunt.registerMultiTask('hockeyapp_create', 'Create new app on HockeyApp via grunt', function() {
        // Merge task-specific and/or target-specific options with these defaults.
        var options = this.options({
            token: null,
			title: null,
			bundle_identifier: null,
			platform: 'iOS', //Android, Mac OS, Windows Phone, Custom
			release_type: '0',
			custom_release_type: null,
			icon:null,
			private: 'true'
        });

		// warn and exit on missing options
        if (!options['token'] || options['token'] === undefined || options['token'] === '') {
            return grunt.fatal(
                'token option is required!'
            );
        }
        if (!options['title'] || options['title'] === undefined || options['title'] === '') {
            return grunt.fatal(
                'title option is required!'
            );
        }
        if (!options['bundle_identifier'] || options['bundle_identifier'] === undefined || options['bundle_identifier'] === '') {
            return grunt.fatal(
                'bundle_identifier option is required!'
            );
        }

        // construct form data
        // NB: use read stream to access IPA file
        var formData = {
			title:options.title,
			bundle_identifier:options.bundle_identifier,
			platform:options.platform,
			release_type:options.release_type,
			private:options.private
        };

        // tidy up url
        var url = 'https://rink.hockeyapp.net/api/2/apps/new';

        // run this asynchronously
        var done = this.async();

        grunt.log.subhead('Creating a new app instance for '+options.title);
		console.log(options);
		console.log(formData);

        // fire request to server.
        request.post({
            url: url,
            formData: formData,
            headers: {
                'X-HockeyAppToken': options['token']
            }
        }, function(error, response, body) {
            if (error !== null) {
                grunt.log.error(error);
                grunt.log.error('Error creating "' + options['title'] + '"');
                done(false);
            } else {
				grunt.config.set('ha_app_id', body.public_identifier);
                grunt.log.ok('Created new app "' + options['title'] + '" successfully');
                done();
            }
        });
    });

    grunt.registerMultiTask('hockeyapp_upload', 'Upload builds to HockeyApp via grunt', function() {
        // Merge task-specific and/or target-specific options with these defaults.
        var options = this.options({
            token: null,
            app_id: null,
            file: null,
            notes: 'Changelog',
            notify: 2,
            status: 2,
            tags: '',
			teams:null
        });

		// warn and exit on missing options
        if (!options['token'] || options['token'] === undefined || options['token'] === '') {
            return grunt.fatal(
                'Token option is required!'
            );
        } else if (!options['app_id'] || options['app_id'] === undefined || options['app_id'] === '') {
            return grunt.fatal(
                'Application id option is required!'
            );
        } else if (!options['file'] || options['file'] === undefined || options['file'] === '') {
            return grunt.fatal(
                'File option is required!'
            );
        }

        // construct form data
        // NB: use read stream to access IPA file
        var formData = {
            ipa: fs.createReadStream(options['file']),
            status: options.status,
            notify: options.notify,
            notes: options.notes,
            notes_type: 1,
			teams: options.teams
        };

        // tidy up url
        var url = 'https://rink.hockeyapp.net/api/2/apps/' + options.app_id + '/app_versions/upload';

        // run this asynchronously
        var done = this.async();

        grunt.log.subhead('Uploading "' + options['file'] + '"');

        // fire request to server.
        request.post({
            url: url,
            formData: formData,
            headers: {
                'X-HockeyAppToken': options['token']
            }
        }, function(error, response, body) {
            if (error !== null) {
                grunt.log.error(error);
                grunt.log.error('Error uploading "' + options['file'] + '"');
                done(false);
            } else {
                grunt.log.ok('Uploaded "' + options['file'] + '" successfully');
                done();
            }
        });
    });
};
<commit_msg>new add to team task<commit_after>/*
 * grunt-hockeyapp-puck
 * https://github.com/dresources/grunt-hockeyapp-puck.git
 *
 * Copyright (c) 2015 rtregaskis
 * Licensed under the MIT license.
 */

var request = require('request'),
    fs = require('fs'),
	path = require('path');

module.exports = function(grunt) {
    'use strict';

    // Please see the Grunt documentation for more information regarding task
    // creation: http://gruntjs.com/creating-tasks

    grunt.registerMultiTask('hockeyapp_create', 'Create new app on HockeyApp via grunt', function() {
        // Merge task-specific and/or target-specific options with these defaults.
        var options = this.options({
            token: null,
			title: null,
			bundle_identifier: null,
			platform: 'iOS', //Android, Mac OS, Windows Phone, Custom
			release_type: '0',
			custom_release_type: null,
			icon:null,
			private: 'true'
        });

		// warn and exit on missing options
        if (!options['token'] || options['token'] === undefined || options['token'] === '') {
            return grunt.fatal(
                'token option is required!'
            );
        }
        if (!options['title'] || options['title'] === undefined || options['title'] === '') {
            return grunt.fatal(
                'title option is required!'
            );
        }
        if (!options['bundle_identifier'] || options['bundle_identifier'] === undefined || options['bundle_identifier'] === '') {
            return grunt.fatal(
                'bundle_identifier option is required!'
            );
        }

        // construct form data
        // NB: use read stream to access IPA file
        var formData = {
			title:options.title,
			bundle_identifier:options.bundle_identifier,
			platform:options.platform,
			release_type:options.release_type,
			private:options.private
        };

        // tidy up url
        var url = 'https://rink.hockeyapp.net/api/2/apps/new';

        // run this asynchronously
        var done = this.async();

        grunt.log.subhead('Creating a new app instance for '+options.title);
		console.log(options);
		console.log(formData);

        // fire request to server.
        request.post({
            url: url,
            formData: formData,
            headers: {
                'X-HockeyAppToken': options['token']
            }
        }, function(error, response, body) {
            if (error !== null) {
                grunt.log.error(error);
                grunt.log.error('Error creating "' + options['title'] + '"');
                done(false);
            } else {
				grunt.config.set('ha_app_id', body.public_identifier);
                grunt.log.ok('Created new app "' + options['title'] + '" successfully');
                done();
            }
        });
    });

	grunt.registerMultiTask('hockeyapp_addteam', 'Add team to app', function(){
		var options = this.options({
			app_id:null,
			team_id:null
		});

		// warn and exit on missing options
        if (!options['app_id'] || options['app_id'] === undefined || options['app_id'] === '') {
            return grunt.fatal(
                'app_id option is required!'
            );
        }
        if (!options['team_id'] || options['team_id'] === undefined || options['team_id'] === '') {
            return grunt.fatal(
                'team_id option is required!'
            );
        }

        // tidy up url
        var url = 'https://rink.hockeyapp.net/api/2/apps/'+options.app_id+'/app_teams/'+options.team_id;

        // run this asynchronously
        var done = this.async();

        grunt.log.subhead('Add app to team');

        // fire request to server.
        request.put({
            url: url,
            headers: {
                'X-HockeyAppToken': options['token']
            }
        }, function(error, response, body) {
            if (error !== null) {
                grunt.log.error(error);
                grunt.log.error('Error adding team to app!');
                done(false);
            } else {
                grunt.log.ok('Added team to app successfully');
                done();
            }
        });
	});

    grunt.registerMultiTask('hockeyapp_upload', 'Upload builds to HockeyApp via grunt', function() {
        // Merge task-specific and/or target-specific options with these defaults.
        var options = this.options({
            token: null,
            app_id: null,
            file: null,
            notes: 'Changelog',
            notify: 2,
            status: 2,
            tags: '',
			teams:null
        });

		// warn and exit on missing options
        if (!options['token'] || options['token'] === undefined || options['token'] === '') {
            return grunt.fatal(
                'Token option is required!'
            );
        } else if (!options['app_id'] || options['app_id'] === undefined || options['app_id'] === '') {
            return grunt.fatal(
                'Application id option is required!'
            );
        } else if (!options['file'] || options['file'] === undefined || options['file'] === '') {
            return grunt.fatal(
                'File option is required!'
            );
        }

        // construct form data
        // NB: use read stream to access IPA file
        var formData = {
            ipa: fs.createReadStream(options['file']),
            status: options.status,
            notify: options.notify,
            notes: options.notes,
            notes_type: 1,
			teams: options.teams
        };

        // tidy up url
        var url = 'https://rink.hockeyapp.net/api/2/apps/' + options.app_id + '/app_versions/upload';

        // run this asynchronously
        var done = this.async();

        grunt.log.subhead('Uploading "' + options['file'] + '"');

        // fire request to server.
        request.post({
            url: url,
            formData: formData,
            headers: {
                'X-HockeyAppToken': options['token']
            }
        }, function(error, response, body) {
            if (error !== null) {
                grunt.log.error(error);
                grunt.log.error('Error uploading "' + options['file'] + '"');
                done(false);
            } else {
                grunt.log.ok('Uploaded "' + options['file'] + '" successfully');
                done();
            }
        });
    });
};
<|endoftext|>


<commit_before>/*
 * grunt-html-generator
 * https://github.com/yneves/grunt-html-generator
 *
 * Copyright (c) 2013 Yuri Neves
 * Licensed under the MIT license.
 */

"use strict";

// - -------------------------------------------------------------------- - //
// - Exports

module.exports = function(grunt) {

	// - -------------------------------------------------------------------- - //
	// - Stuff

	var path = {};

	function template(content) {
		if (content.indexOf("<%") > -1) {
			return grunt.template.process(content);
		} else {
			return content;
		}
	}

	function replace() {

		var args = arguments,
			file = path.root+"/"+path.html+"/"+args[0]+".html",
			content = grunt.file.exists(file)
				? grunt.file.read(file,"utf8")
				: template(args[0]);

		if (args.length === 3) {

			content = content.replace(
				new RegExp("{"+args[1]+"}","g"),
				args[2]
			);

		} else if (args.length === 2) {

			if (typeof args[1] === "function") {
				content = content.replace(/{[a-z\-]+}/g,function(name) {
					name = name.replace(/^{|}$/g,"");
					return args[1].apply(this,[name]);
				});

			} else if (typeof args[1] === "object") {
				content = content.replace(/{[a-z\-]+}/g,function(name) {
					name = name.replace(/^{|}$/g,"");
					return args[1][name] || "";
				});

			}

		}

		return content;
	}

	function recurse(config) {
		var parts = [];
		if (typeof config === "string") {
			parts.push( replace(config,recurse) );
		} else if (config instanceof Array) {
			for (var c = 0; c < config.length; c++) {
				parts.push( recurse(config[c]) );
			}
		} else if (typeof config === "object") {
			for (var part in config) {
				parts.push( replace(part,config[part]) );
			}
		}
		return parts.join("");
	}

	function entity(content) {
		var map = {
			"º": "°",		"ã": "ã",	"õ": "õ",
			"Ã": "Ã",	"Õ": "Õ",	"â": "â",
			"ê": "ê",		"î": "î",		"ô": "ô",
			"û": "û",		"Â": "Â",		"Ê": "Ê",
			"Î": "Î",		"Ô": "Ô",		"Û": "Û",
			"á": "á",	"é": "é",	"í": "í",
			"ó": "ó",	"ú": "ú",	"Á": "Á",
			"É": "É",	"Í": "Í",	"Ó": "Ó",
			"Ú": "Ú",	"ç": "ç",	"Ç": "Ç",
		};
		for (var key in map) {
			content = content.replace(new RegExp(key,"g"),map[key]);
		}
		return content;
	}

	function tag(name,props,value) {
		var content = "<"+name;
		if (props) {
			for (var prop in props) {
				content += " "+prop+"=\""+props[prop]+"\"";
			}
		}
		if (value) {
			content += ">"+value+"</"+name+">";
		} else {
			content += " />";
		}
		return content;
	}

	function files(match) {
		return grunt.file.expand({ cwd: path.root }, match);
	}

	function html(params) {

		var head = [];

		if (params.title) {
			head.push(tag("title",null,recurse(params.title)));
		}

		if (params.head) {
			head.push(recurse(params.head));
		}

		if (params.css) {
			files(params.css).forEach(function(href) {
				head.push(tag("link",{
					type: "text/css",
					rel: "stylesheet",
					href: href
				}));
			});
		}

		if (params.js) {
			files(params.js).forEach(function(src) {
				head.push(tag("script",{
					type: "text/javascript",
					src: src
				}));
			});
		}

		var body = [];
		if (params.body) {
			body.push(recurse(params.body));
		}

		var doc = [];
		if (params.html) {
			doc.push(recurse(params.html));
		} else {
			doc = [
				"<!DOCTYPE html>\n",
				"\n",
				"\n\t", head.join("\n\t"), "\n\n",
				"\n\t", body.join("\n\t"), "\n\n",
				""
			];
		}

		return entity(doc.join(""));
	}

	// - -------------------------------------------------------------------- - //
	// - Task

	grunt.registerMultiTask("html-generator","Grunt task to generate html files.",function() {

		var options = this.options({
			root: ".",
			html: "html"
		});

		path = options;

		var files = this.data.files;
		for (var file in files) {
			grunt.file.write(file,html(files[file]));
			grunt.log.writeln('File "' + file + '" created.');
		}

	});

};<commit_msg>Fixed not valid self-closing script tags<commit_after>/*
 * grunt-html-generator
 * https://github.com/yneves/grunt-html-generator
 *
 * Copyright (c) 2013 Yuri Neves
 * Licensed under the MIT license.
 */

"use strict";

// - -------------------------------------------------------------------- - //
// - Exports

module.exports = function(grunt) {

	// - -------------------------------------------------------------------- - //
	// - Stuff

	var path = {};

	function template(content) {
		if (content.indexOf("<%") > -1) {
			return grunt.template.process(content);
		} else {
			return content;
		}
	}

	function replace() {

		var args = arguments,
			file = path.root+"/"+path.html+"/"+args[0]+".html",
			content = grunt.file.exists(file)
				? grunt.file.read(file,"utf8")
				: template(args[0]);

		if (args.length === 3) {

			content = content.replace(
				new RegExp("{"+args[1]+"}","g"),
				args[2]
			);

		} else if (args.length === 2) {

			if (typeof args[1] === "function") {
				content = content.replace(/{[a-z\-]+}/g,function(name) {
					name = name.replace(/^{|}$/g,"");
					return args[1].apply(this,[name]);
				});

			} else if (typeof args[1] === "object") {
				content = content.replace(/{[a-z\-]+}/g,function(name) {
					name = name.replace(/^{|}$/g,"");
					return args[1][name] || "";
				});

			}

		}

		return content;
	}

	function recurse(config) {
		var parts = [];
		if (typeof config === "string") {
			parts.push( replace(config,recurse) );
		} else if (config instanceof Array) {
			for (var c = 0; c < config.length; c++) {
				parts.push( recurse(config[c]) );
			}
		} else if (typeof config === "object") {
			for (var part in config) {
				parts.push( replace(part,config[part]) );
			}
		}
		return parts.join("");
	}

	function entity(content) {
		var map = {
			"º": "°",		"ã": "ã",	"õ": "õ",
			"Ã": "Ã",	"Õ": "Õ",	"â": "â",
			"ê": "ê",		"î": "î",		"ô": "ô",
			"û": "û",		"Â": "Â",		"Ê": "Ê",
			"Î": "Î",		"Ô": "Ô",		"Û": "Û",
			"á": "á",	"é": "é",	"í": "í",
			"ó": "ó",	"ú": "ú",	"Á": "Á",
			"É": "É",	"Í": "Í",	"Ó": "Ó",
			"Ú": "Ú",	"ç": "ç",	"Ç": "Ç",
		};
		for (var key in map) {
			content = content.replace(new RegExp(key,"g"),map[key]);
		}
		return content;
	}

	function tag(name,props,value) {
		var content = "<"+name;
		if (props) {
			for (var prop in props) {
				content += " "+prop+"=\""+props[prop]+"\"";
			}
		}
		if (value) {
			content += ">"+value+"</"+name+">";
		}
		else if (name === 'script'){
		  content += "></"+name+">";
		}
		else {
			content += " />";
		}
		return content;
	}

	function files(match) {
		return grunt.file.expand({ cwd: path.root }, match);
	}

	function html(params) {

		var head = [];

		if (params.title) {
			head.push(tag("title",null,recurse(params.title)));
		}

		if (params.head) {
			head.push(recurse(params.head));
		}

		if (params.css) {
			files(params.css).forEach(function(href) {
				head.push(tag("link",{
					type: "text/css",
					rel: "stylesheet",
					href: href
				}));
			});
		}

		if (params.js) {
			files(params.js).forEach(function(src) {
				head.push(tag("script",{
					type: "text/javascript",
					src: src
				}));
			});
		}

		var body = [];
		if (params.body) {
			body.push(recurse(params.body));
		}

		var doc = [];
		if (params.html) {
			doc.push(recurse(params.html));
		} else {
			doc = [
				"<!DOCTYPE html>\n",
				"\n",
				"\n\t", head.join("\n\t"), "\n\n",
				"\n\t", body.join("\n\t"), "\n\n",
				""
			];
		}

		return entity(doc.join(""));
	}

	// - -------------------------------------------------------------------- - //
	// - Task

	grunt.registerMultiTask("html-generator","Grunt task to generate html files.",function() {

		var options = this.options({
			root: ".",
			html: "html"
		});

		path = options;

		var files = this.data.files;
		for (var file in files) {
			grunt.file.write(file,html(files[file]));
			grunt.log.writeln('File "' + file + '" created.');
		}

	});

};<|endoftext|>


<commit_before>'use strict'

const fs = require('fs')
const path = require('path')
const childProcess = require('child_process')
const Download = require('bestikk-download')
const download = new Download({})
const log = require('bestikk-log')
const bfs = require('bestikk-fs')

const graalvmCheckConvert = (result, testName) => {
  if (result.indexOf('
asciidoctor.js, AsciiDoc in JavaScript
') === -1) {
    log.error(`${testName} failed, AsciiDoc source is not converted`)
    process.stdout.write(result)
  }
  if (result.indexOf('Asciidoctor default stylesheet') === -1) {
    log.error(`${testName} failed, default stylesheet not embedded in converted document`)
    process.stdout.write(result)
  }
  if (result.indexOf('include content') === -1) {
    log.error(`${testName} failed, include directive is not processed`)
    process.stdout.write(result)
  }
}

const graalvmJavaCompileAndRun = (specName, className, javacBin, javaBin) => {
  // Compile
  log.debug(`compiling ${specName} to build/`)
  childProcess.execSync(`${javacBin} ./${specName} -d ./build`)

  // Run
  log.debug(`running ${className}`)
  const start = process.hrtime()
  const result = childProcess.execSync(`${javaBin} -classpath ./build ${className}`).toString('utf8')
  log.debug(`running ${className} in ${process.hrtime(start)[0]}s`)
  return result
}

const graalvmRun = (name, jdkInstallDir) => {
  log.task(`run against ${name}`)

  const start = process.hrtime()

  let javacBin
  let javaBin
  const jdkBinDir = path.join(jdkInstallDir, 'bin')
  javacBin = path.join(jdkBinDir, 'javac')
  javaBin = path.join(jdkBinDir, 'java')

  // Java classes
  const asciidoctorClassName = 'AsciidoctorConvertWithGraalVM'
  const asciidoctorSpec = `spec/graalvm/${asciidoctorClassName}.java`

  log.info(`run ${name} java`)
  const javaResult = graalvmJavaCompileAndRun(asciidoctorSpec, asciidoctorClassName, javacBin, javaBin)
  graalvmCheckConvert(javaResult, `run with ${name} java`)
  log.success(`Done ${name} in ${process.hrtime(start)[0]}s`)
}

const downloadGraalVM = async (version) => {
  log.task('download graalvm')

  const target = 'build/graalvm.tar.gz'
  if (fs.existsSync(target)) {
    log.info(target + ' file already exists, skipping "download" task')
    return
  }
  await download.getContentFromURL(`https://github.com/oracle/graal/releases/download/vm-${version}/graalvm-ce-${version}-linux-amd64.tar.gz`, target)
  if (fs.existsSync('build/graalvm')) {
    log.info('build/graalvm directory already exists, skipping "untar" task')
    return Promise.resolve({})
  }
  return bfs.untar(target, 'graalvm', 'build')
}

module.exports = class GraalVM {
  constructor () {
    this.graalvmVersion = '1.0.0-rc7'
  }

  get () {
    return downloadGraalVM(this.graalvmVersion)
  }

  static run () {
    graalvmRun('GraalVM', './build/graalvm')
  }
}
<commit_msg>⬆ Upgrade GraalVM to 1.0.0 RC12 (#673)<commit_after>'use strict'

const fs = require('fs')
const path = require('path')
const childProcess = require('child_process')
const Download = require('bestikk-download')
const download = new Download({})
const log = require('bestikk-log')
const bfs = require('bestikk-fs')

const graalvmCheckConvert = (result, testName) => {
  if (result.indexOf('
asciidoctor.js, AsciiDoc in JavaScript
') === -1) {
    log.error(`${testName} failed, AsciiDoc source is not converted`)
    process.stdout.write(result)
  }
  if (result.indexOf('Asciidoctor default stylesheet') === -1) {
    log.error(`${testName} failed, default stylesheet not embedded in converted document`)
    process.stdout.write(result)
  }
  if (result.indexOf('include content') === -1) {
    log.error(`${testName} failed, include directive is not processed`)
    process.stdout.write(result)
  }
}

const graalvmJavaCompileAndRun = (specName, className, javacBin, javaBin) => {
  // Compile
  log.debug(`compiling ${specName} to build/`)
  childProcess.execSync(`${javacBin} ./${specName} -d ./build`)

  // Run
  log.debug(`running ${className}`)
  const start = process.hrtime()
  const result = childProcess.execSync(`${javaBin} -classpath ./build ${className}`).toString('utf8')
  log.debug(`running ${className} in ${process.hrtime(start)[0]}s`)
  return result
}

const graalvmRun = (name, jdkInstallDir) => {
  log.task(`run against ${name}`)

  const start = process.hrtime()

  let javacBin
  let javaBin
  const jdkBinDir = path.join(jdkInstallDir, 'bin')
  javacBin = path.join(jdkBinDir, 'javac')
  javaBin = path.join(jdkBinDir, 'java')

  // Java classes
  const asciidoctorClassName = 'AsciidoctorConvertWithGraalVM'
  const asciidoctorSpec = `spec/graalvm/${asciidoctorClassName}.java`

  log.info(`run ${name} java`)
  const javaResult = graalvmJavaCompileAndRun(asciidoctorSpec, asciidoctorClassName, javacBin, javaBin)
  graalvmCheckConvert(javaResult, `run with ${name} java`)
  log.success(`Done ${name} in ${process.hrtime(start)[0]}s`)
}

const downloadGraalVM = async (version) => {
  log.task('download graalvm')

  const target = 'build/graalvm.tar.gz'
  if (fs.existsSync(target)) {
    log.info(target + ' file already exists, skipping "download" task')
    return
  }
  await download.getContentFromURL(`https://github.com/oracle/graal/releases/download/vm-${version}/graalvm-ce-${version}-linux-amd64.tar.gz`, target)
  if (fs.existsSync('build/graalvm')) {
    log.info('build/graalvm directory already exists, skipping "untar" task')
    return Promise.resolve({})
  }
  return bfs.untar(target, 'graalvm', 'build')
}

module.exports = class GraalVM {
  constructor () {
    this.graalvmVersion = '1.0.0-rc12'
  }

  get () {
    return downloadGraalVM(this.graalvmVersion)
  }

  static run () {
    graalvmRun('GraalVM', './build/graalvm')
  }
}
<|endoftext|>