<commit_before>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import React, { PropTypes } from 'react';

import { MAPBOX_ACCESS_TOKEN } from '../config';

let Leaflet;

if (typeof (window) !== 'undefined') {
  Leaflet = require('react-leaflet');
}

export default class MapboxMap extends React.Component {
  static displayName = 'MapboxMap';

  static propTypes = {
    selectedLocation: PropTypes.shape({
      lat: PropTypes.number,
      lon: PropTypes.number
    }).isRequired,
    viewLocation: PropTypes.shape({
      lat: PropTypes.number,
      lon: PropTypes.number
    }).isRequired
  };

  render() {
    if (!Leaflet) {
      return null;
    }

    let {
      selectedLocation,
      viewLocation,
      ...props
    } = this.props;

    return (
      <Leaflet.Map
        center={viewLocation}
        ref={c => this.leafletMap = c}
        zoom={13}
        {...props}
      >
        <Leaflet.TileLayer
          attribution='© Mapbox © OpenStreetMap Improve this map'
          url={`http://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=${MAPBOX_ACCESS_TOKEN}`}
        />
        <Leaflet.Marker position={selectedLocation} />
      </Leaflet.Map>
    );
  }
}
<commit_msg>Refactor MapboxMap component<commit_after>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import React, { PropTypes } from 'react';
import { isEmpty } from 'lodash';

import { MAPBOX_ACCESS_TOKEN } from '../config';

let Leaflet;

if (typeof (window) !== 'undefined') {
  Leaflet = require('react-leaflet');
}

export default class MapboxMap extends React.Component {
  static displayName = 'MapboxMap';

  static propTypes = {
    frozen: PropTypes.bool,
    noWheelZoom: PropTypes.bool,
    selectedLocation: PropTypes.shape({
      lat: PropTypes.number,
      lon: PropTypes.number
    }),
    viewLocation: PropTypes.shape({
      lat: PropTypes.number,
      lon: PropTypes.number
    })
  };

  static defaultProps = {
    zoom: 13,
    frozen: false,
    noWheelZoom: false
  };

  componentDidMount() {
    let map = this.leafletMap.leafletElement;

    if (this.props.frozen) {
      map.dragging.disable();
      map.touchZoom.disable();
      map.doubleClickZoom.disable();
      map.scrollWheelZoom.disable();
      map.keyboard.disable();
    }

    if (this.props.noWheelZoom) {
      map.scrollWheelZoom.disable();
    }
  }

  render() {
    if (!Leaflet) {
      return null;
    }

    let {
      selectedLocation,
      viewLocation,
      ...props
    } = this.props;

    return (
      <Leaflet.Map
        center={viewLocation}
        ref={c => this.leafletMap = c}
        {...props}
      >
        <Leaflet.TileLayer
          attribution='© Mapbox © OpenStreetMap Improve this map'
          url={`http://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=${MAPBOX_ACCESS_TOKEN}`}
        />
        {!isEmpty(selectedLocation) &&
          <Leaflet.Marker position={selectedLocation} />
        }
      </Leaflet.Map>
    );
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';

class SearchBar extends Component {
  render() {
    return <input />;
  }
}

export default SearchBar;
<commit_msg>Introduce state, use Arrow function instead of onInputChange.<commit_after>import React, { Component } from 'react';

class SearchBar extends Component {
  constructor(props) {
    super(props);

    this.state = {
      term: ''
    };
  }

  render() {
    return (
      <div>
        <input onChange={event => this.setState({ term: event.target.value })} />
        Value of the input: {this.state.term}
      </div>
    );
  }
}

export default SearchBar;
<|endoftext|>


<commit_before>export const expeditions = {
  DEFAULT: {
    default: true,
    snippet: 'We need your help with transcribing these specimens!',
    image: 'default_expedition.png',
    link: '',
  },
  'Herbarium_WeDigFLPlants\' Mints of Florida—More than Mojitos': {
    snippet: `
      Florida is home to over 110 species of native and naturalized mints, including
      Scarlet Calamint. This expedition contains Florida mint specimens from four different
      herbaria.  Help the WeDigFLPlants group transcribe specimens of the flora they dig.
    `,
    image: 'Herbarium_WeDigFLPlants_Mints_of_Florida.jpg',
    link: 'https://biospex.org/project/wedigflplants',
    completed_at: 'June 21 2016',
  },
  'Herbarium_WeDigFLPlants\' Laurels of Florida—Fight Laurel Wilt': {
    snippet: `
      The fatal laurel wilt fungus reached Florida in 2005 and now all members of the family,
      including Sassafras, are threatened. Help the WeDigFLPlants group transcribe specimens of
      Florida's 15 native and naturalized laurel species to build the historical baseline.
    `,
    image: 'Herbarium_WeDigFLPlants_Laurels_of_Florida.jpg',
    link: 'https://biospex.org/project/wedigflplants',
    completed_at: 'June 21 2016',
  },
  'Pinned Specimen_CalBug Bee Flies': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'June 19 2016',
  },
  'Butterfly_New World Swallowtail Butterflies': {
    snippet: `
      I am interested in how climate change has shaped the evolutionary history of New World
      Swallowtail Butterflies. The museum specimens in this collection provide a detailed record
      of the geographical variation and distribution of butterfly species, with which I can better
      understand their history.
    `,
    image: 'Butterfly_Papilio.png',
    link: 'http://hannahlowens.weebly.com/',
    completed_at: 'June 28 2016',
  },
  'Pinned Specimen_CalBug Bee Flies 2': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'June 26 2016',
  },
  'Herbarium_WeDigFLPlants\' St. John\'s Worts of Florida—Diversity to Lift your Spirits': {
    snippet: `
      Florida is home to 37 species in the St. John's Wort Family. Help the
      WeDigFLPlants group transcribe specimens from this medicinally
      important plant family.
    `,
    image: 'Herbarium_WeDigFLPlants_Hypericum.jpg',
    link: 'https://biospex.org/project/wedigflplants',
  },
  'Herbarium_WeDigFLPlants\' Rose Gentians of Florida—Beauty from the Center of its Diversity': {
    snippet: `
      Florida's 12 species of Rose Gentians make it the center of diversity
      for this gorgeous group of gentians.  Help the WeDigFLPlants group
      transcribe specimens to understand the group's diversity and
      distribution at a finer scale.
    `,
    image: 'Herbarium_WeDigFLPlants_Rose_Gentian.jpg',
    link: 'https://biospex.org/project/wedigflplants',
  },
  'Pinned Specimen_CalBug Bee Flies 3': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'July 6 2016',
  },
  'Herbarium_Plants of Virginia - Ant Plants I': {
    snippet: `
      Ants are essential to the life of over 11,000 plant species worldwide.
      Help us learn more about this remarkable partnership in Virginia.
    `,
    image: 'Herbarium_PlantsOfVirginia_Ant_Plants_I.jpg',
    link: 'https://biospex.org/project/ant-plants-of-virginia',
  },
  'Pinned Specimen_CalBug Bee Flies 4': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'July 15 2016',
  },
  'Herbarium_Plants of Arkansas: Discovering Dogwoods': {
    snippet: `
      There is more to this plant family than the widely recognized flowering dogwood.
      Arkansas has 6 dogwood and 3 gum/tupelo species.
    `,
    image: 'Herbarium_Arkansas_Dogwoods.jpg',
    link: 'https://biospex.org/project/plants-of-arkansas-discovery-and-dissemination',
  },
  'Herbarium_Hear Them Ring: Bellflowers of Arkansas': {
    snippet: `
      Members of the Campanulaceae family are called the bellflowers.
      They include bellflowers, lobelias, and Venus\' looking glass.
    `,
    image: 'Herbarium_Arkansas_Campanulaceae.jpg',
    link: 'https://biospex.org/project/plants-of-arkansas-discovery-and-dissemination',
  },
  'Herbarium_Plants of Arkansas: The Delta and Crowley\'s Ridge Flora': {
    snippet: `
      The Delta and Crowley's Ridge Flora--The Arkansas Delta Region
      is a vastly under-explored region of the Natural State in need.
    `,
    image: 'Herbarium_Arkansas_Delta.jpg',
    link: 'https://biospex.org/project/plants-of-arkansas-discovery-and-dissemination',
  },
  'Pinned Specimen_CalBug Bee Flies 5': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
  },
  'Pinned Specimen_Tiger Beetles 1': {
    snippet: `
      This expedition features images of tiger beetles from the University of Alberta’s E.H.
      Strickland Entomological Museum (UASM). The specimens were collected throughout North,
      Central and South America with a specific emphasis on North America. Tiger beetles belong
      to one of the most diverse animal families on the planet, the Carabidae (a.k.a. ground
      beetles), and are some of the fastest running insects in the world. They can be quite
      colorful too, which makes them popular among insect collectors.
    `,
    image: 'Pinned_Specimen_CarabidDrawer_tile.jpg',
    link: 'http://entomology.museums.ualberta.ca/searching.php',
  },
};

Object.keys(expeditions).forEach((k) => {
  expeditions[k].name = k.replace(/^[^_]+_/, '');
  expeditions[k].group = k.replace(/_.+$/, '');
});
<commit_msg>edit tiger beetle snippet<commit_after>export const expeditions = {
  DEFAULT: {
    default: true,
    snippet: 'We need your help with transcribing these specimens!',
    image: 'default_expedition.png',
    link: '',
  },
  'Herbarium_WeDigFLPlants\' Mints of Florida—More than Mojitos': {
    snippet: `
      Florida is home to over 110 species of native and naturalized mints, including
      Scarlet Calamint. This expedition contains Florida mint specimens from four different
      herbaria.  Help the WeDigFLPlants group transcribe specimens of the flora they dig.
    `,
    image: 'Herbarium_WeDigFLPlants_Mints_of_Florida.jpg',
    link: 'https://biospex.org/project/wedigflplants',
    completed_at: 'June 21 2016',
  },
  'Herbarium_WeDigFLPlants\' Laurels of Florida—Fight Laurel Wilt': {
    snippet: `
      The fatal laurel wilt fungus reached Florida in 2005 and now all members of the family,
      including Sassafras, are threatened. Help the WeDigFLPlants group transcribe specimens of
      Florida's 15 native and naturalized laurel species to build the historical baseline.
    `,
    image: 'Herbarium_WeDigFLPlants_Laurels_of_Florida.jpg',
    link: 'https://biospex.org/project/wedigflplants',
    completed_at: 'June 21 2016',
  },
  'Pinned Specimen_CalBug Bee Flies': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'June 19 2016',
  },
  'Butterfly_New World Swallowtail Butterflies': {
    snippet: `
      I am interested in how climate change has shaped the evolutionary history of New World
      Swallowtail Butterflies. The museum specimens in this collection provide a detailed record
      of the geographical variation and distribution of butterfly species, with which I can better
      understand their history.
    `,
    image: 'Butterfly_Papilio.png',
    link: 'http://hannahlowens.weebly.com/',
    completed_at: 'June 28 2016',
  },
  'Pinned Specimen_CalBug Bee Flies 2': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'June 26 2016',
  },
  'Herbarium_WeDigFLPlants\' St. John\'s Worts of Florida—Diversity to Lift your Spirits': {
    snippet: `
      Florida is home to 37 species in the St. John's Wort Family. Help the
      WeDigFLPlants group transcribe specimens from this medicinally
      important plant family.
    `,
    image: 'Herbarium_WeDigFLPlants_Hypericum.jpg',
    link: 'https://biospex.org/project/wedigflplants',
  },
  'Herbarium_WeDigFLPlants\' Rose Gentians of Florida—Beauty from the Center of its Diversity': {
    snippet: `
      Florida's 12 species of Rose Gentians make it the center of diversity
      for this gorgeous group of gentians.  Help the WeDigFLPlants group
      transcribe specimens to understand the group's diversity and
      distribution at a finer scale.
    `,
    image: 'Herbarium_WeDigFLPlants_Rose_Gentian.jpg',
    link: 'https://biospex.org/project/wedigflplants',
  },
  'Pinned Specimen_CalBug Bee Flies 3': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'July 6 2016',
  },
  'Herbarium_Plants of Virginia - Ant Plants I': {
    snippet: `
      Ants are essential to the life of over 11,000 plant species worldwide.
      Help us learn more about this remarkable partnership in Virginia.
    `,
    image: 'Herbarium_PlantsOfVirginia_Ant_Plants_I.jpg',
    link: 'https://biospex.org/project/ant-plants-of-virginia',
  },
  'Pinned Specimen_CalBug Bee Flies 4': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
    completed_at: 'July 15 2016',
  },
  'Herbarium_Plants of Arkansas: Discovering Dogwoods': {
    snippet: `
      There is more to this plant family than the widely recognized flowering dogwood.
      Arkansas has 6 dogwood and 3 gum/tupelo species.
    `,
    image: 'Herbarium_Arkansas_Dogwoods.jpg',
    link: 'https://biospex.org/project/plants-of-arkansas-discovery-and-dissemination',
  },
  'Herbarium_Hear Them Ring: Bellflowers of Arkansas': {
    snippet: `
      Members of the Campanulaceae family are called the bellflowers.
      They include bellflowers, lobelias, and Venus\' looking glass.
    `,
    image: 'Herbarium_Arkansas_Campanulaceae.jpg',
    link: 'https://biospex.org/project/plants-of-arkansas-discovery-and-dissemination',
  },
  'Herbarium_Plants of Arkansas: The Delta and Crowley\'s Ridge Flora': {
    snippet: `
      The Delta and Crowley's Ridge Flora--The Arkansas Delta Region
      is a vastly under-explored region of the Natural State in need.
    `,
    image: 'Herbarium_Arkansas_Delta.jpg',
    link: 'https://biospex.org/project/plants-of-arkansas-discovery-and-dissemination',
  },
  'Pinned Specimen_CalBug Bee Flies 5': {
    snippet: `
      This expedition features 1000 images of bee fly (Bombyliidae) specimens from the CalBug
      project. The specimens were collected across the western Unites States. The bee flies are a
      large family of flies that feed on nectar and pollen. Some are important pollinators. Species
      of bee flies sometimes resemble bees, which is how they got their common name.
    `,
    image: 'Pinned_Specimen_bee_flies_expedition.jpg',
    link: 'http://calbug.berkeley.edu/',
  },
  'Pinned Specimen_Tiger Beetles 1': {
    snippet: `
      This expedition features tiger beetles from the University of Alberta’s E.H.
      Strickland Entomological Museum. The specimens were collected throughout North,
      Central and South America with a specific emphasis on North America. Tiger beetles belong
      to one of the most diverse animal families on the planet, the Carabidae (a.k.a. ground
      beetles), and are some of the fastest running insects in the world.
    `,
    image: 'Pinned_Specimen_CarabidDrawer_tile.jpg',
    link: 'http://entomology.museums.ualberta.ca/searching.php',
  },
};

Object.keys(expeditions).forEach((k) => {
  expeditions[k].name = k.replace(/^[^_]+_/, '');
  expeditions[k].group = k.replace(/_.+$/, '');
});
<|endoftext|>


<commit_before>/**
 * Component for Post creation
 */
import React from 'react'
import { withRouter } from 'react-router'
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'
import Dropzone from 'react-dropzone'
import request from 'superagent'

// TODO: Should move these to environment variables, this is not secure
const CLOUDINARY_UPLOAD_PRESET = 'gec3tjz3';
const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/dqpknoetx/upload';

class CreatePage extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      open: true,
      uploadedFile: null,
      uploadedFileCloudinaryUrl: ''
      };
    }

    onImageDrop(files) {
        this.setState({
            uploadedFile: files[0]
        });

        this.handleImageUpload(files[0]);
    }

    handleImageUpload(file) {
        let upload = request.post(
            CLOUDINARY_UPLOAD_URL).field('upload_preset',
            CLOUDINARY_UPLOAD_PRESET).field('file', file);

        upload.end((err, response) => {
            if (err) {
                console.error("ERR1",err);
            }

            if (response.body.url !== '') {
                this.setState({
                    uploadedFileCloudinaryUrl: response.body.url,
                    imageUrl: response.body.url,
                    userId: this.props.data.user.id
                });
            }
        });
    }
  static propTypes = {
    router: React.PropTypes.object,
    mutate: React.PropTypes.func,
    data: React.PropTypes.object,
  }

  state = {
    name: '',
    description: '',
    imageUrl: '',
    userId: 0
  }

  render () {
    if (!this.props.data.user) {
      console.warn('only logged in users can create new posts')
      this.props.router.replace('/photos')
    }

    return (

          <Dropzone
            onDrop={this.onImageDrop.bind(this)}
            multiple={false}
            accept="image/*">

                {this.state.uploadedFileCloudinaryUrl === '' ? null :

{this.state.uploadedFile.name}

}

          </Dropzone>
          <input
            className='w-100 pa3 mv2'
            value={this.state.name}
            placeholder='Name'
            onChange={(e) => this.setState({name: e.target.value})}
          />
          <input
            className='w-100 pa3 mv2'
            value={this.state.description}
            placeholder='Description'
            onChange={(e) => this.setState({description: e.target.value})}
          />
          <input
            className='w-100 pa3 mv2'
            value={this.state.imageUrl}
            placeholder='Image Url'
            onChange={(e) => this.setState({imageUrl: e.target.value})}
          />
          {this.state.description && this.state.imageUrl && this.state.name &&
            <button className='pa3 bg-black-10 bn dim ttu pointer' onClick={this.handlePhoto}>Post</button>
          }

    )
  }

  handlePhoto = () => {
    this.setState({userId: this.props.data.user.id})
    const {name, description, imageUrl, userId} = this.state
    this.props.mutate({variables: {name, description, imageUrl, userId }})
      .then(() => {
        this.props.router.push('/photos')
      })
  }
}

const createPhoto = gql`
  mutation ($name: String!, $description: String!, $imageUrl: String!, $userId: ID!) {
    createPhoto(name: $name, description: $description, imageUrl: $imageUrl, userId: $userId) {
      id
    }
  }
`

const userQuery = gql`
  query {
    user {
      id
    }
  }
`

export default graphql(createPhoto)(
  graphql(userQuery, { options: { forceFetch: true }} )(withRouter(CreatePage))
)<commit_msg>fixed redirect issue<commit_after>/**
 * Component for Post creation
 */
import React from 'react'
import { withRouter } from 'react-router'
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'
import Dropzone from 'react-dropzone'
import request from 'superagent'

// TODO: Should move these to environment variables, this is not secure
const CLOUDINARY_UPLOAD_PRESET = 'gec3tjz3';
const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/dqpknoetx/upload';

class CreatePage extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      open: true,
      uploadedFile: null,
      uploadedFileCloudinaryUrl: ''
      };
    }

    onImageDrop(files) {
        this.setState({
            uploadedFile: files[0]
        });

        this.handleImageUpload(files[0]);
    }

    handleImageUpload(file) {
        let upload = request.post(
            CLOUDINARY_UPLOAD_URL).field('upload_preset',
            CLOUDINARY_UPLOAD_PRESET).field('file', file);

        upload.end((err, response) => {
            if (err) {
                console.error("ERR1",err);
            }

            if (response.body.url !== '') {
                this.setState({
                    uploadedFileCloudinaryUrl: response.body.url,
                    imageUrl: response.body.url,
                    userId: this.props.data.user.id
                });
            }
        });
    }
  static propTypes = {
    router: React.PropTypes.object,
    mutate: React.PropTypes.func,
    data: React.PropTypes.object,
  }

  state = {
    name: '',
    description: '',
    imageUrl: '',
    userId: 0
  }

  render () {
    if (!this.props.data.user) {
      console.warn('only logged in users can create new posts')
      this.props.router.replace('/photos')
    }

    return (

          <Dropzone
            onDrop={this.onImageDrop.bind(this)}
            multiple={false}
            accept="image/*">

                {this.state.uploadedFileCloudinaryUrl === '' ? null :

{this.state.uploadedFile.name}

}

          </Dropzone>
          <input
            className='w-100 pa3 mv2'
            value={this.state.name}
            placeholder='Name'
            onChange={(e) => this.setState({name: e.target.value})}
          />
          <input
            className='w-100 pa3 mv2'
            value={this.state.description}
            placeholder='Description'
            onChange={(e) => this.setState({description: e.target.value})}
          />
          <input
            className='w-100 pa3 mv2'
            value={this.state.imageUrl}
            placeholder='Image Url'
            onChange={(e) => this.setState({imageUrl: e.target.value})}
          />
          {this.state.description && this.state.imageUrl && this.state.name &&
            <button className='pa3 bg-black-10 bn dim ttu pointer' onClick={this.handlePhoto}>Post</button>
          }

    )
  }

  handlePhoto = () => {
    this.setState({userId: this.props.data.user.id})
    const {name, description, imageUrl, userId} = this.state
    this.props.mutate({variables: {name, description, imageUrl, userId }})
      .then(() => {
        this.props.router.push('/photo')
      })
  }
}

const createPhoto = gql`
  mutation ($name: String!, $description: String!, $imageUrl: String!, $userId: ID!) {
    createPhoto(name: $name, description: $description, imageUrl: $imageUrl, userId: $userId) {
      id
    }
  }
`

const userQuery = gql`
  query {
    user {
      id
    }
  }
`

export default graphql(createPhoto)(
  graphql(userQuery, { options: { forceFetch: true }} )(withRouter(CreatePage))
)<|endoftext|>


<commit_before>import { Provider } from 'react-redux'
import React, { Component } from 'react'
import { syncHistoryWithStore } from 'react-router-redux'
import { Router, browserHistory } from 'react-router'

import routes from '../../routes'
import configureStore from '../../store/configure-store'

let state = window.$REACTBASE_STATE
const store = configureStore(state)
const history = syncHistoryWithStore(browserHistory, store)

class Root extends Component {

  render() {
    return (
      <Provider store={ store }>
        <Router history={ browserHistory } routes={ routes } />
      </Provider>
    )
  }
}

export default Root
<commit_msg>Remove unncesary import<commit_after>import { Provider } from 'react-redux'
import React, { Component } from 'react'
import { Router, browserHistory } from 'react-router'

import routes from '../../routes'
import configureStore from '../../store/configure-store'

let state = window.$REACTBASE_STATE
const store = configureStore(state)

class Root extends Component {

  render() {
    return (
      <Provider store={ store }>
        <Router history={ browserHistory } routes={ routes } />
      </Provider>
    )
  }
}

export default Root
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { FormGroup, Panel } from 'react-bootstrap'
import { connect } from 'react-redux'
import { Field, reduxForm } from 'redux-form'

import Select from '../components/controls/Select'
import TextArea from '../components/controls/TextArea'
import Anchor from '../components/layout/Anchor'
import SliderInput from '../components/SliderInput'
import values from '../selectors/values'

class ValuesForm extends Component {
  render () {
    const { handleSubmit } = this.props
    return (
      <form onSubmit={handleSubmit}>
        <Panel>
          <Anchor id='values' />

            Values

          <FormGroup>
            <Field
              component={SliderInput}
              label='How open are you to sharing space and facilities with your neighbours?'
              name='sharedSpace'
              options={[
                'I’m willing to pay more to have my own private space and facilities',
                'I’m willing to share some space and facilities to save money but I still want plenty of private space',
                'I’m happy to exchange a lot of private space for communal space to save money'
              ]}
            />
          </FormGroup>

          <FormGroup>
            <Field
              component={SliderInput}
              label='Would you like to live with others who share your values or in a diverse and vibrant neighbourhood?'
              name='diversity'
              options={[
                'We want to live with others who have the same ethical values as us',
                'We’re happy either way',
                'We want to live in a diverse, vibrant neighbourhood'
              ]}
            />
          </FormGroup>
          {
            this.props.values.diversity === '1'
              ? (
                <Field
                  component={TextArea}
                  label='What are your three most important values'
                  name='mostImportantValues'
                  rows={4}
                  style={{resize: 'none'}}
                />
              )
              : null
          }

          <FormGroup>
            <Field
              component={SliderInput}
              label='Shared lifestage or multigenerational'
              name='multigenerational'
              options={[
                'We want to live with others who are in the same lifestage as us',
                'We’re happy either way',
                'We want to live in a multigenerational community'
              ]}
            />
          </FormGroup>
          {
            this.props.values.multigenerational === '1'
              ? (
                <Field
                  component={Select}
                  label='What life stage are you in'
                  name='lifestage'
                >
                  <option disabled hidden value=''>Please select...</option>
                  <option value='Young single'>
                    Young single
                  </option>
                  <option value='Young couple/newly weds'>
                    Young couple/newly weds
                  </option>
                  <option value='Young family (babies and kids)'>
                    Young family (babies and kids)
                  </option>
                  <option value='Older family (teenagers and adult children)'>
                    Older family (teenagers and adult children)
                  </option>
                  <option value='Empty nesters'>
                    Empty nesters
                  </option>
                  <option value='Retirees'>
                    Retirees
                  </option>
                  <option value='Prefer not to answer'>
                    Prefer not to answer
                  </option>
                </Field>
              )
              : null
          }

          <FormGroup>
            <Field
              component={SliderInput}
              label='Do you prefer to spend your time indoors or outdoors'
              name='outdoors'
              options={[
                'We prefer to spend our time on the deck or in the garden',
                'We like to do both',
                'We prefer to stay indoors most of the time'
              ]}
            />
          </FormGroup>

          <FormGroup>
            <Field
              component={SliderInput}
              label='How much of the time will you be at home'
              name='timeAtHome'
              options={[
                'Most of the time',
                'Some of the time',
                'Only at night and on weekends'
              ]}
            />
          </FormGroup>
        </Panel>
      </form>
    )
  }
}

const withState = connect(
  state => ({values: values(state)})
)

const validate = values => {
  const errors = {}
  if (values.multigenerational === '1' && !values.lifestage) {
    errors.lifestage = 'Required'
  }
  return errors
}

export default reduxForm({
  destroyOnUnmount: false,
  form: 'values',
  initialValues: {
    diversity: 2,
    multigenerational: 2,
    outdoors: 2,
    sharedSpace: 2,
    timeAtHome: 2
  },
  validate
})(withState(ValuesForm))
<commit_msg>Update diversity value text<commit_after>import React, { Component } from 'react'
import { FormGroup, Panel } from 'react-bootstrap'
import { connect } from 'react-redux'
import { Field, reduxForm } from 'redux-form'

import Select from '../components/controls/Select'
import TextArea from '../components/controls/TextArea'
import Anchor from '../components/layout/Anchor'
import SliderInput from '../components/SliderInput'
import values from '../selectors/values'

class ValuesForm extends Component {
  render () {
    const { handleSubmit } = this.props
    return (
      <form onSubmit={handleSubmit}>
        <Panel>
          <Anchor id='values' />

            Values

          <FormGroup>
            <Field
              component={SliderInput}
              label='How open are you to sharing space and facilities with your neighbours?'
              name='sharedSpace'
              options={[
                'I’m willing to pay more to have my own private space and facilities',
                'I’m willing to share some space and facilities to save money but I still want plenty of private space',
                'I’m happy to exchange a lot of private space for communal space to save money'
              ]}
            />
          </FormGroup>

          <FormGroup>
            <Field
              component={SliderInput}
              label='Do you want to live in a community where people share the same values or one that welcomes people with different values?'
              name='diversity'
              options={[
                'I want to live with others who have the same ethical values',
                'I don’t mind',
                'I want to live with people who welcome others with different values'
              ]}
            />
          </FormGroup>
          {
            this.props.values.diversity === '1'
              ? (
                <Field
                  component={TextArea}
                  label='What are your three most important values'
                  name='mostImportantValues'
                  rows={4}
                  style={{resize: 'none'}}
                />
              )
              : null
          }

          <FormGroup>
            <Field
              component={SliderInput}
              label='Shared lifestage or multigenerational'
              name='multigenerational'
              options={[
                'We want to live with others who are in the same lifestage as us',
                'We’re happy either way',
                'We want to live in a multigenerational community'
              ]}
            />
          </FormGroup>
          {
            this.props.values.multigenerational === '1'
              ? (
                <Field
                  component={Select}
                  label='What life stage are you in'
                  name='lifestage'
                >
                  <option disabled hidden value=''>Please select...</option>
                  <option value='Young single'>
                    Young single
                  </option>
                  <option value='Young couple/newly weds'>
                    Young couple/newly weds
                  </option>
                  <option value='Young family (babies and kids)'>
                    Young family (babies and kids)
                  </option>
                  <option value='Older family (teenagers and adult children)'>
                    Older family (teenagers and adult children)
                  </option>
                  <option value='Empty nesters'>
                    Empty nesters
                  </option>
                  <option value='Retirees'>
                    Retirees
                  </option>
                  <option value='Prefer not to answer'>
                    Prefer not to answer
                  </option>
                </Field>
              )
              : null
          }

          <FormGroup>
            <Field
              component={SliderInput}
              label='Do you prefer to spend your time indoors or outdoors'
              name='outdoors'
              options={[
                'We prefer to spend our time on the deck or in the garden',
                'We like to do both',
                'We prefer to stay indoors most of the time'
              ]}
            />
          </FormGroup>

          <FormGroup>
            <Field
              component={SliderInput}
              label='How much of the time will you be at home'
              name='timeAtHome'
              options={[
                'Most of the time',
                'Some of the time',
                'Only at night and on weekends'
              ]}
            />
          </FormGroup>
        </Panel>
      </form>
    )
  }
}

const withState = connect(
  state => ({values: values(state)})
)

const validate = values => {
  const errors = {}
  if (values.multigenerational === '1' && !values.lifestage) {
    errors.lifestage = 'Required'
  }
  return errors
}

export default reduxForm({
  destroyOnUnmount: false,
  form: 'values',
  initialValues: {
    diversity: 2,
    multigenerational: 2,
    outdoors: 2,
    sharedSpace: 2,
    timeAtHome: 2
  },
  validate
})(withState(ValuesForm))
<|endoftext|>


<commit_before>'use strict';

function PublicationEditController($scope, $controller, formula, formulaAutoCompleteService,
  fileFunnelService, NpolarMessage, NpolarApiSecurity, npdcAppConfig, Publication, NpolarLang,
  npolarApiConfig, npolarCountryService) {
  'ngInject';

  $controller('NpolarEditController', { $scope: $scope });
  $scope.resource = Publication;

  let templates = [{
      match: "people_item",
      template: '<npdc:formula-person></npdc:formula-person>'
    }, {
      match: "placenames_item",
      template: '<npdc:formula-placename></npdc:formula-placename>'
    }
  ];

  let i18n = [{
      map: require('./en.json'),
      code: 'en'
    },
    {
      map: require('./no.json'),
      code: 'nb_NO',
    }];

  $scope.formula = formula.getInstance({
    schema: '//api.npolar.no/schema/publication-1',
    form: 'edit/formula.json',
    language: NpolarLang.getLang(),
    templates: npdcAppConfig.formula.templates.concat(templates),
    languages: npdcAppConfig.formula.languages
  });

  formulaAutoCompleteService.autocomplete({
    match: "publication_lang",
    querySource: npolarApiConfig.base + '/language',
    label: 'native',
    value: 'code'
  }, $scope.formula);

  formulaAutoCompleteService.autocomplete({
    match: "#/conference/country",
    querySource: npolarApiConfig.base + '/country',
    label: 'native',
    value: 'code'
  }, $scope.formula);

  formulaAutoCompleteService.autocomplete({
    match: "@language",
    querySource: npolarApiConfig.base + '/language',
    label: 'native',
    value: 'code'
  }, $scope.formula);

  // @todo, need to redfine ES mapping...
  // let autocompleteFacets = ["id", "schema", "doi", "title", "publication_lang", "published", "volume", "issue", "suppl", "art_no", "page_count", "comment", "created", "updated", "created_by", "updated_by", "_id", "_rev", "abstract.@language", "abstract.@value", "overview.@language", "overview.@value", "locations.placename", "locations.area", "locations.country", "locations.hemisphere", "journal.id", "journal.name", "journal.np_series", "journal.series", "journal.series_no", "conference.id", "conference.name", "conference.place", "conference.country", "conference.dates", "people.id", "people.first_name", "people.last_name", "people.email", "people.roles", "people.organisation", "organisations.id", "organisations.name", "organisations.location", "organisations.roles", "links.rel", "links.href", "links.hreflang", "links.title", "links.type", "files.uri", "files.filename", "files.title", "files.length", "files.type", "files.hash"]
  // formulaAutoCompleteService.autocompleteFacets(autocompleteFacets, $scope.resource, $scope.formula);

  function initFileUpload(formula) {

    let server = `${NpolarApiSecurity.canonicalUri($scope.resource.path)}/:id/_file`;
    fileFunnelService.fileUploader({
      match(field) {
        return field.id === "files";
      },
      server,
      multiple: true,
      progress: false,
      restricted: function () {
        return !formula.getModel().license;
      },
      fileToValueMapper: Publication.fileObject,
      valueToFileMapper: Publication.hashiObject,
      fields: [] // 'type', 'hash'
    }, formula);
  }

  try {
    initFileUpload($scope.formula);
    // edit (or new) action
    $scope.edit();
  } catch (e) {
    NpolarMessage.error(e);
  }
}

module.exports = PublicationEditController;
<commit_msg>Fixed summary/abstract, added download of files with security token (key=)<commit_after>'use strict';

function PublicationEditController($scope, $controller, formula, formulaAutoCompleteService,
  fileFunnelService, NpolarMessage, NpolarApiSecurity, npdcAppConfig, Publication, NpolarLang,
  npolarApiConfig, npolarCountryService) {
  'ngInject';

  $controller('NpolarEditController', { $scope: $scope });
  $scope.resource = Publication;

  let templates = [{
      match: "people_item",
      template: '<npdc:formula-person></npdc:formula-person>'
    }, {
      match: "placenames_item",
      template: '<npdc:formula-placename></npdc:formula-placename>'
    }
  ];

  let i18n = [{
      map: require('./en.json'),
      code: 'en'
    },
    {
      map: require('./no.json'),
      code: 'nb_NO',
    }];

  $scope.formula = formula.getInstance({
    schema: '//api.npolar.no/schema/publication-1',
    form: 'edit/formula.json',
    language: NpolarLang.getLang(),
    templates: npdcAppConfig.formula.templates.concat(templates),
    languages: npdcAppConfig.formula.languages.concat(i18n)
  });

  formulaAutoCompleteService.autocomplete({
    match: "publication_lang",
    querySource: npolarApiConfig.base + '/language',
    label: 'native',
    value: 'code'
  }, $scope.formula);

  formulaAutoCompleteService.autocomplete({
    match: "#/conference/country",
    querySource: npolarApiConfig.base + '/country',
    label: 'native',
    value: 'code'
  }, $scope.formula);

  formulaAutoCompleteService.autocomplete({
    match: "@language",
    querySource: npolarApiConfig.base + '/language',
    label: 'native',
    value: 'code'
  }, $scope.formula);

  // @todo, need to redfine ES mapping...
  // let autocompleteFacets = ["id", "schema", "doi", "title", "publication_lang", "published", "volume", "issue", "suppl", "art_no", "page_count", "comment", "created", "updated", "created_by", "updated_by", "_id", "_rev", "abstract.@language", "abstract.@value", "overview.@language", "overview.@value", "locations.placename", "locations.area", "locations.country", "locations.hemisphere", "journal.id", "journal.name", "journal.np_series", "journal.series", "journal.series_no", "conference.id", "conference.name", "conference.place", "conference.country", "conference.dates", "people.id", "people.first_name", "people.last_name", "people.email", "people.roles", "people.organisation", "organisations.id", "organisations.name", "organisations.location", "organisations.roles", "links.rel", "links.href", "links.hreflang", "links.title", "links.type", "files.uri", "files.filename", "files.title", "files.length", "files.type", "files.hash"]
  // formulaAutoCompleteService.autocompleteFacets(autocompleteFacets, $scope.resource, $scope.formula);

  function initFileUpload(formula) {

    let server = `${NpolarApiSecurity.canonicalUri($scope.resource.path)}/:id/_file`;
    fileFunnelService.fileUploader({
      match(field) {
        return field.id === "files";
      },
      server,
      multiple: true,
      progress: false,
      restricted: function () {
        return !formula.getModel().license;
      },
      fileToValueMapper: Publication.fileObject,
      valueToFileMapper: Publication.hashiObject,
      fields: [] // 'type', 'hash'
    }, formula);
  }

  try {
    initFileUpload($scope.formula);
    // edit (or new) action
    $scope.edit();
  } catch (e) {
    NpolarMessage.error(e);
  }
}

module.exports = PublicationEditController;
<|endoftext|>


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

var createConfigParser = require('./createConfigParser'),
    fs = require('fs'),
    path = require('path'),
    url = require('url'),
    config,
  	windowsConfig,
  	projectRoot,
  	etree;

var logger = {
  log: function () {
    if (process.env.NODE_ENV !== 'test') {
      console.log.apply(this, arguments)
    }
  },
  warn: function() {
    if (process.env.NODE_ENV !== 'test') {
      console.warn.apply(this, arguments)
    }
  }
};

function copyFile(source, target, callback) {
  var cbCalled = false;

  function done(err) {
    if (!cbCalled) {
      callback(err);
      cbCalled = true;
    }
  }

  var rd = fs.createReadStream(source);
  rd.on('error', done);

  var wr = fs.createWriteStream(target);
  wr.on('error', done);
  wr.on('close', function() {
    done();
  });
  rd.pipe(wr);
};

module.exports = function (context) {
  // move contents of the assets folder to the windows platform dir
  var Q = context.requireCordovaModule('q');

  // create a parser for the Cordova configuration
  projectRoot = context.opts.projectRoot;
  var filename = "wrapper";

  var sourcePath = path.join(projectRoot, "assets", "windows", "wrapper.html");
  var destPath = path.join(projectRoot, "platforms","windows", "www", filename + ".html");

  logger.log('Copying wrapper html file for the windows platform from '+ sourcePath + ' to ' + destPath + '.');

  var task = Q.defer();
  copyFile(sourcePath, destPath, function (err) {
    if (err) {
      console.error(err);
      return task.reject();
    }

    console.log("Finished copying wrapper html file for the windows platform.");

    var sourcePath = path.join(projectRoot, "assets", "windows", "wrapper.js");
    var destPath = path.join(projectRoot, "windows", "www", "js", filename +".js");

    logger.log('Copying wrapper js file for the windows platform from '+ sourcePath + ' to ' + destPath + '.');

    copyFile(sourcePath, destPath, function (err) {
      if (err) {
        console.error(err);
        return task.reject();
      }

      console.log("Finished copying wrapper js file for the windows platform.");

      var sourcePath = path.join(projectRoot,"assets", "windows", "wrapper.css");
      var destPath = path.join(projectRoot, "platforms", "windows", "www", "css", filename + ".css");

      logger.log('Copying wrapper css file for the windows platform from '+ sourcePath + ' to ' + destPath + '.');

      copyFile(sourcePath, destPath, function (err) {
        if (err) {
          console.error(err);
          return task.reject();
        }

        console.log("Finished copying wrapper css file for the windows platform.");

        task.resolve();
      });
    });
  });

  return task.promise;
};
<commit_msg>removing unused variables<commit_after>#!/usr/bin/env node

var createConfigParser = require('./createConfigParser'),
    fs = require('fs'),
    path = require('path'),
    url = require('url'),
    config,
  	windowsConfig,
  	projectRoot;

var logger = {
  log: function () {
    if (process.env.NODE_ENV !== 'test') {
      console.log.apply(this, arguments)
    }
  },
  warn: function() {
    if (process.env.NODE_ENV !== 'test') {
      console.warn.apply(this, arguments)
    }
  }
};

function copyFile(source, target, callback) {
  var cbCalled = false;

  function done(err) {
    if (!cbCalled) {
      callback(err);
      cbCalled = true;
    }
  }

  var rd = fs.createReadStream(source);
  rd.on('error', done);

  var wr = fs.createWriteStream(target);
  wr.on('error', done);
  wr.on('close', function() {
    done();
  });
  rd.pipe(wr);
};

module.exports = function (context) {
  // move contents of the assets folder to the windows platform dir
  var Q = context.requireCordovaModule('q');

  // create a parser for the Cordova configuration
  projectRoot = context.opts.projectRoot;
  var filename = "wrapper";

  var sourcePath = path.join(projectRoot, "assets", "windows", "wrapper.html");
  var destPath = path.join(projectRoot, "platforms","windows", "www", filename + ".html");

  logger.log('Copying wrapper html file for the windows platform from '+ sourcePath + ' to ' + destPath + '.');

  var task = Q.defer();
  copyFile(sourcePath, destPath, function (err) {
    if (err) {
      console.error(err);
      return task.reject();
    }

    console.log("Finished copying wrapper html file for the windows platform.");

    var sourcePath = path.join(projectRoot, "assets", "windows", "wrapper.js");
    var destPath = path.join(projectRoot, "windows", "www", "js", filename +".js");

    logger.log('Copying wrapper js file for the windows platform from '+ sourcePath + ' to ' + destPath + '.');

    copyFile(sourcePath, destPath, function (err) {
      if (err) {
        console.error(err);
        return task.reject();
      }

      console.log("Finished copying wrapper js file for the windows platform.");

      var sourcePath = path.join(projectRoot,"assets", "windows", "wrapper.css");
      var destPath = path.join(projectRoot, "platforms", "windows", "www", "css", filename + ".css");

      logger.log('Copying wrapper css file for the windows platform from '+ sourcePath + ' to ' + destPath + '.');

      copyFile(sourcePath, destPath, function (err) {
        if (err) {
          console.error(err);
          return task.reject();
        }

        console.log("Finished copying wrapper css file for the windows platform.");

        task.resolve();
      });
    });
  });

  return task.promise;
};
<|endoftext|>


<commit_before>
var request = require('request');

//here goes an JSON file that contains names of cities that program would fetch info for

//here goes a for loop to gather info for every city in CITIESJSON

var url1 = 'http://ws.audioscrobbler.com/2.0/?method=geo.getevents&location=paris&limit=100&page=&api_key=dbc287366d92998e7f5fb5ba6fb7e7f1&format=json';

request(url1, function(err, res, results){
    var parsedRslts ='';
    var totalPages = 0;
    var perPage = 0;
    var page = 0;
    var url = '';
    if(!err){
        //console.log(results);
        parsedRslts = JSON.parse(results);
        totalPages = parsedRslts.events['@attr'].totalPages;
        perPage = parsedRslts.events['@attr'].perPage;
        page = parsedRslts.events['@attr'].page;
        console.log("total pages to process: " + totalPages);
        console.log("number of results per page: " + perPage);
    }
    else console.log('*** Error in request initiation! ***');

    exports.totalPages = totalPages;

});<commit_msg>DELETE useless class<commit_after><|endoftext|>


<commit_before>import find from 'array-find';
import findIndex from 'array-findindex';
import mongoose from 'mongoose';
import Promise from 'bluebird';

import { GenericError } from '../errors';
import { paginate } from '../utils';
import { fetchMedia } from './search';

const ObjectId = mongoose.Types.ObjectId;

function addMedia(uw, sourceType, sourceID, keys) {
  const Media = uw.model('Media');

  return fetchMedia(sourceType, sourceID, keys)
    .then(media => new Media(media).save());
}

const toPlaylistResponse = model => ({
  _id: model.id,
  name: model.name,
  author: model.author,
  created: model.created,
  description: model.description,
  shared: model.shared,
  nsfw: model.nsfw,
  size: model.media.length
});

export function getPlaylists(uw, page, limit, id) {
  const Playlist = uw.model('Playlist');

  const _page = isNaN(page) ? 0 : page;
  const _limit = isNaN(limit) ? 50 : Math.min(limit, 50);

  return Playlist.find({ author: id })
  .setOptions({ limit: _limit, skip: _limit * _page })
  .exec()
  .then(playlists => playlists.map(toPlaylistResponse));
}

export function createPlaylist(uw, data, mediaArray) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = new Playlist(data);

  return playlist.validate()
  .then(() => {
    if (!mediaArray.length) return playlist.save();

    // TODO save Playlist, too.
    return PlaylistItem.create(mediaArray);
  });
}

export function getPlaylist(uw, id, playlistID) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne({ _id: playlistID, author: id })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, 'playlist not found or private');

    return toPlaylistResponse(playlist);
  });
}

export function deletePlaylist(uw, id, playlistID) {
  const Playlist = uw.model('Playlist');
  let _active = null;

  return uw.redis.get(`playlist:${id}`)
  .then(active => {
    _active = active;
    return Playlist.findOne(new ObjectId(playlistID));
  })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t delete the playlist of another user');
    }
    if (_active && _active === playlist.id) {
      throw new GenericError(403, 'you can\'t delete an active playlist');
    }

    return playlist.remove();
  });
}

export function renamePlaylist(uw, id, playlistID, name) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne(new ObjectId(playlistID))
  .then(playlist => {
    if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t rename the playlist of another user');
    }

    playlist.name = name;
    return playlist.save();
  });
}

export function sharePlaylist(uw, id, playlistID, shared) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne(new ObjectId(playlistID)).then(playlist => {
    if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t share the playlist of another user');
    }

    playlist.shared = shared;
    return playlist.save();
  });
}

export function getPlaylistItems(uw, page, limit, id, playlistID) {
  const Playlist = uw.model('Playlist');
  const PlaylistItem = uw.model('PlaylistItem');
  const _page = isNaN(page) ? 0 : page;
  const _limit = isNaN(limit) ? 100 : Math.min(limit, 100);

  return Playlist.findOne(
    { _id: playlistID, author: id },
    { media: { $slice: [_limit * _page, _limit] } }
  )
  .then(playlist => {
    if (!playlist) throw new GenericError(404, 'playlist not found or private');

    return playlist.media;
  })
  .then(itemIDs => {
    return PlaylistItem.find({ _id: { $in: itemIDs } })
      .populate('media')
      .then(items =>
        // MongoDB returns the playlist items in whichever order it likes, which
        // is usually not the current playlist order. So we need to sort the
        // playlist items according to the itemIDs list here.
        itemIDs.map(itemID => find(items, item => item._id + '' === itemID + ''))
      );
  })
  .then(media => paginate(_page, _limit, media));
}

export function movePlaylistItems(uw, id, playlistID, afterID, movingItems) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne(new ObjectId(playlistID))
  .then(playlist => {
    if (!playlist) {
      throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    }
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t edit the playlist of another user');
    }

    const newMedia = playlist.media.filter(item =>
      movingItems.indexOf(`${item}`) === -1
    );
    const insertIndex = findIndex(newMedia, item => `${item}` === afterID);
    newMedia.splice(insertIndex + 1, 0, ...movingItems);
    playlist.media = newMedia;

    return playlist.save();
  });
}

export async function activatePlaylist(uw, id, playlistID) {
  const Playlist = uw.model('Playlist');
  const playlist = await Playlist.findOne(new ObjectId(playlistID)).populate('author');

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  if (id !== playlist.author.id && playlist.shared) {
    throw new GenericError(403, `${playlist.author.username} has made ${playlist.name} private`);
  }

  await uw.redis.set(`playlist:${id}`, playlist.id);
  return await uw.redis.get(`playlist:${id}`);
}

function isValidPlaylistItem(item) {
  return typeof item === 'object' &&
    typeof item.sourceType === 'string' &&
    (typeof item.sourceID === 'string' || typeof item.sourceID === 'number');
}

export async function createPlaylistItems(uw, id, playlistID, after, items) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');
  const Media = uw.model('Media');

  const createItem = async props => {
    const { sourceType, sourceID, artist, title } = props;
    let { start, end } = props;

    let media = await Media.findOne({ sourceType, sourceID });
    if (!media) {
      media = await addMedia(uw, sourceType, sourceID, uw.keys);
    }

    // Fix up custom start/end times
    if (!start || start < 0) {
      start = 0;
    } else if (start > media.duration) {
      start = media.duration;
    }
    if (!end || end > media.duration) {
      end = media.duration;
    } else if (end < start) {
      end = start;
    }

    const playlistItem = new PlaylistItem({
      media,
      artist: artist || media.artist,
      title: title || media.title,
      start, end
    });

    try {
      await playlistItem.save();
    } catch (e) {
      throw new Error('couldn\'t save media');
    }

    return playlistItem;
  };

  const playlist = await Playlist.findOne(new ObjectId(playlistID));
  if (!playlist) {
    throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  }
  if (playlist.author.toString() !== id) {
    throw new GenericError(403, 'you can\'t edit the playlist of another user');
  }

  const addingItems = items.filter(isValidPlaylistItem).map(createItem);

  const playlistItems = await Promise.all(addingItems);
  const insertIndex = findIndex(playlist.media, item => `${item}` === after);
  playlist.media.splice(insertIndex + 1, 0, ...playlistItems);

  await playlist.save();

  return {
    added: playlistItems,
    playlistSize: playlist.media.length
  };
}

export async function getPlaylistItem(uw, id, playlistID, mediaID) {
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOne(new ObjectId(playlistID)).populate('media');

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  if (id !== playlist.author.toString() && playlist.shared) {
    throw new GenericError(403, 'this playlist is private');
  }

  const playlistItem = find(playlist.media, item => item.id === mediaID);

  if (!playlistItem) {
    throw new GenericError(404, 'media not found');
  }

  return playlistItem;
}

export async function updatePlaylistItem(uw, id, playlistID, mediaID, metadata) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOne(new ObjectId(playlistID));

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  if (id !== playlist.author.toString() && playlist.shared) {
    throw new GenericError(403, 'playlist is private');
  }
  if (playlist.media.indexOf(mediaID) === -1) {
    throw new GenericError(404, 'media not found');
  }

  return await PlaylistItem.findOneAndUpdate({ _id: mediaID }, metadata, { new: true });
}

export async function deletePlaylistItems(uw, id, playlistID, items) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOneAndUpdate(
    { _id: playlistID, author: id },
    { $pullAll: { media: items } },
    { new: true }
  );

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  // return full PlaylistItem object to keep consitency with addMedia route
  const mediaItems = await PlaylistItem.find({ _id: { $in: items } }).populate('media');

  await PlaylistItem.remove({ _id: { $in: items } });

  return {
    removed: mediaItems,
    playlistSize: playlist.media.length
  };
}

export async function copyPlaylistItem(uw, id, fromPlaylistID, mediaID, toPlaylistID) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOne(new ObjectId(fromPlaylistID)).populate('media');

  if (!playlist) {
    throw new GenericError(404, 'originating playlist not found');
  }
  if (playlist.author.toString() !== id && !playlist.shared) {
    throw new GenericError(403, 'originating playlist is private');
  }

  if (!playlist.media.some(item => item.id === mediaID)) {
    throw new GenericError(404, 'Playlist item not found');
  }

  const playlistItem = new PlaylistItem(
    await PlaylistItem.findOne(new ObjectId(mediaID), '-id').lean()
  );

  await playlistItem.save();

  const targetPlaylist = await Playlist.findOne(new ObjectId(toPlaylistID));
  if (!targetPlaylist) {
    throw new GenericError(404, 'playlist not found');
  }
  if (!targetPlaylist.author.toString() !== id) {
    throw new GenericError(403, 'you can\'t copy media to another user\'s playlist');
  }

  targetPlaylist.media.push(playlistItem.id);

  return await targetPlaylist.save();
}
<commit_msg>Call toPlaylistResponse where needed<commit_after>import find from 'array-find';
import findIndex from 'array-findindex';
import mongoose from 'mongoose';
import Promise from 'bluebird';

import { GenericError } from '../errors';
import { paginate } from '../utils';
import { fetchMedia } from './search';

const ObjectId = mongoose.Types.ObjectId;

function addMedia(uw, sourceType, sourceID, keys) {
  const Media = uw.model('Media');

  return fetchMedia(sourceType, sourceID, keys)
    .then(media => new Media(media).save());
}

const toPlaylistResponse = model => ({
  _id: model.id,
  name: model.name,
  author: model.author,
  created: model.created,
  description: model.description,
  shared: model.shared,
  nsfw: model.nsfw,
  size: model.media.length
});

export function getPlaylists(uw, page, limit, id) {
  const Playlist = uw.model('Playlist');

  const _page = isNaN(page) ? 0 : page;
  const _limit = isNaN(limit) ? 50 : Math.min(limit, 50);

  return Playlist.find({ author: id })
  .setOptions({ limit: _limit, skip: _limit * _page })
  .exec()
  .then(playlists => playlists.map(toPlaylistResponse));
}

export function createPlaylist(uw, data, mediaArray) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = new Playlist(data);

  return playlist.validate()
  .then(() => {
    if (!mediaArray.length) return playlist.save().then(toPlaylistResponse);

    // TODO save Playlist, too.
    return PlaylistItem.create(mediaArray);
  });
}

export function getPlaylist(uw, id, playlistID) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne({ _id: playlistID, author: id })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, 'playlist not found or private');

    return toPlaylistResponse(playlist);
  });
}

export function deletePlaylist(uw, id, playlistID) {
  const Playlist = uw.model('Playlist');
  let _active = null;

  return uw.redis.get(`playlist:${id}`)
  .then(active => {
    _active = active;
    return Playlist.findOne(new ObjectId(playlistID));
  })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t delete the playlist of another user');
    }
    if (_active && _active === playlist.id) {
      throw new GenericError(403, 'you can\'t delete an active playlist');
    }

    return playlist.remove().then(toPlaylistResponse);
  });
}

export function renamePlaylist(uw, id, playlistID, name) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne(new ObjectId(playlistID))
  .then(playlist => {
    if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t rename the playlist of another user');
    }

    playlist.name = name;
    return playlist.save().then(toPlaylistResponse);
  });
}

export function sharePlaylist(uw, id, playlistID, shared) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne(new ObjectId(playlistID)).then(playlist => {
    if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t share the playlist of another user');
    }

    playlist.shared = shared;
    return playlist.save().then(toPlaylistResponse);
  });
}

export function getPlaylistItems(uw, page, limit, id, playlistID) {
  const Playlist = uw.model('Playlist');
  const PlaylistItem = uw.model('PlaylistItem');
  const _page = isNaN(page) ? 0 : page;
  const _limit = isNaN(limit) ? 100 : Math.min(limit, 100);

  return Playlist.findOne(
    { _id: playlistID, author: id },
    { media: { $slice: [_limit * _page, _limit] } }
  )
  .then(playlist => {
    if (!playlist) throw new GenericError(404, 'playlist not found or private');

    return playlist.media;
  })
  .then(itemIDs => {
    return PlaylistItem.find({ _id: { $in: itemIDs } })
      .populate('media')
      .then(items =>
        // MongoDB returns the playlist items in whichever order it likes, which
        // is usually not the current playlist order. So we need to sort the
        // playlist items according to the itemIDs list here.
        itemIDs.map(itemID => find(items, item => item._id + '' === itemID + ''))
      );
  })
  .then(media => paginate(_page, _limit, media));
}

export function movePlaylistItems(uw, id, playlistID, afterID, movingItems) {
  const Playlist = uw.model('Playlist');

  return Playlist.findOne(new ObjectId(playlistID))
  .then(playlist => {
    if (!playlist) {
      throw new GenericError(404, `playlist with ID ${playlistID} not found`);
    }
    if (id !== playlist.author.toString()) {
      throw new GenericError(403, 'you can\'t edit the playlist of another user');
    }

    const newMedia = playlist.media.filter(item =>
      movingItems.indexOf(`${item}`) === -1
    );
    const insertIndex = findIndex(newMedia, item => `${item}` === afterID);
    newMedia.splice(insertIndex + 1, 0, ...movingItems);
    playlist.media = newMedia;

    return playlist.save();
  });
}

export async function activatePlaylist(uw, id, playlistID) {
  const Playlist = uw.model('Playlist');
  const playlist = await Playlist.findOne(new ObjectId(playlistID)).populate('author');

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  if (id !== playlist.author.id && playlist.shared) {
    throw new GenericError(403, `${playlist.author.username} has made ${playlist.name} private`);
  }

  await uw.redis.set(`playlist:${id}`, playlist.id);
  return await uw.redis.get(`playlist:${id}`);
}

function isValidPlaylistItem(item) {
  return typeof item === 'object' &&
    typeof item.sourceType === 'string' &&
    (typeof item.sourceID === 'string' || typeof item.sourceID === 'number');
}

export async function createPlaylistItems(uw, id, playlistID, after, items) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');
  const Media = uw.model('Media');

  const createItem = async props => {
    const { sourceType, sourceID, artist, title } = props;
    let { start, end } = props;

    let media = await Media.findOne({ sourceType, sourceID });
    if (!media) {
      media = await addMedia(uw, sourceType, sourceID, uw.keys);
    }

    // Fix up custom start/end times
    if (!start || start < 0) {
      start = 0;
    } else if (start > media.duration) {
      start = media.duration;
    }
    if (!end || end > media.duration) {
      end = media.duration;
    } else if (end < start) {
      end = start;
    }

    const playlistItem = new PlaylistItem({
      media,
      artist: artist || media.artist,
      title: title || media.title,
      start, end
    });

    try {
      await playlistItem.save();
    } catch (e) {
      throw new Error('couldn\'t save media');
    }

    return playlistItem;
  };

  const playlist = await Playlist.findOne(new ObjectId(playlistID));
  if (!playlist) {
    throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  }
  if (playlist.author.toString() !== id) {
    throw new GenericError(403, 'you can\'t edit the playlist of another user');
  }

  const addingItems = items.filter(isValidPlaylistItem).map(createItem);

  const playlistItems = await Promise.all(addingItems);
  const insertIndex = findIndex(playlist.media, item => `${item}` === after);
  playlist.media.splice(insertIndex + 1, 0, ...playlistItems);

  await playlist.save();

  return {
    added: playlistItems,
    playlistSize: playlist.media.length
  };
}

export async function getPlaylistItem(uw, id, playlistID, mediaID) {
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOne(new ObjectId(playlistID)).populate('media');

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  if (id !== playlist.author.toString() && playlist.shared) {
    throw new GenericError(403, 'this playlist is private');
  }

  const playlistItem = find(playlist.media, item => item.id === mediaID);

  if (!playlistItem) {
    throw new GenericError(404, 'media not found');
  }

  return playlistItem;
}

export async function updatePlaylistItem(uw, id, playlistID, mediaID, metadata) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOne(new ObjectId(playlistID));

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  if (id !== playlist.author.toString() && playlist.shared) {
    throw new GenericError(403, 'playlist is private');
  }
  if (playlist.media.indexOf(mediaID) === -1) {
    throw new GenericError(404, 'media not found');
  }

  return await PlaylistItem.findOneAndUpdate({ _id: mediaID }, metadata, { new: true });
}

export async function deletePlaylistItems(uw, id, playlistID, items) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOneAndUpdate(
    { _id: playlistID, author: id },
    { $pullAll: { media: items } },
    { new: true }
  );

  if (!playlist) throw new GenericError(404, `playlist with ID ${playlistID} not found`);
  // return full PlaylistItem object to keep consitency with addMedia route
  const mediaItems = await PlaylistItem.find({ _id: { $in: items } }).populate('media');

  await PlaylistItem.remove({ _id: { $in: items } });

  return {
    removed: mediaItems,
    playlistSize: playlist.media.length
  };
}

export async function copyPlaylistItem(uw, id, fromPlaylistID, mediaID, toPlaylistID) {
  const PlaylistItem = uw.model('PlaylistItem');
  const Playlist = uw.model('Playlist');

  const playlist = await Playlist.findOne(new ObjectId(fromPlaylistID)).populate('media');

  if (!playlist) {
    throw new GenericError(404, 'originating playlist not found');
  }
  if (playlist.author.toString() !== id && !playlist.shared) {
    throw new GenericError(403, 'originating playlist is private');
  }

  if (!playlist.media.some(item => item.id === mediaID)) {
    throw new GenericError(404, 'Playlist item not found');
  }

  const playlistItem = new PlaylistItem(
    await PlaylistItem.findOne(new ObjectId(mediaID), '-id').lean()
  );

  await playlistItem.save();

  const targetPlaylist = await Playlist.findOne(new ObjectId(toPlaylistID));
  if (!targetPlaylist) {
    throw new GenericError(404, 'playlist not found');
  }
  if (!targetPlaylist.author.toString() !== id) {
    throw new GenericError(403, 'you can\'t copy media to another user\'s playlist');
  }

  targetPlaylist.media.push(playlistItem.id);

  return await targetPlaylist.save();
}
<|endoftext|>


<commit_before>/**
 * @file: slide-show and grid-display manager.
 */

(function() {
 /***
  *
  */
 Slides = function (config) {
   var S = this; //that

   //default configuration
   this.conf = config || {};
   this.conf = {
     slider: S.conf.slider || null,
     images: S.conf.images || null,
     current: S.conf.current || 0,
     currentPage: S.conf.currentPage || 0,
     pageSize: S.conf.pageSize || 3,
     jqc: S.conf.context || window.document,
     jq: S.conf.jq || (function () {
       if ('jquery' in S.conf.slider) {
         return S.conf.slider.constructor
       }
       else {
         return null;
       }
     })(),
   }

   //sanity check
   if (S.conf.images == null || S.conf.slider == null) {
     console.error('Must pass "slider" and "images" properties to configuration oject of Slides().');
     return false;
   }

   //
   //initialization
   //
   (function () {
     var slide;
     for (var i in S.conf.images) {
       slide = '';

       //build this slide
       slide += '
';
       if (i < S.conf.pageSize) {
         slide += ''
       }
       slide += '
';

       // initialize a bunch of empty slides
       S.conf.jq(slide).appendTo(S.conf.slider);
     }
     S.conf.jq('

').appendTo(S.conf.slider);
   })();

   return this;
 }

 Slides.prototype.setSlide = function (index) {
   return this;
 }

 Slides.prototype.next = function () {
   this.setSlide(this.current + 1);
   return this;
 }
 Slides.prototype.previous = function () {
   this.setSlide(this.current - 1);
   return this;
 }
 Slides.prototype.pausePlay = function () {
   return this;
 }
})()

<commit_msg>corrctly building the current page.<commit_after>/**
 * @file: slide-show and grid-display manager.
 */

(function() {
 /***
  *
  */
 Slides = function (config) {
   var S = this; //that

   //default configuration
   this.conf = config || {};
   this.conf = {
     slider: S.conf.slider || null,
     images: S.conf.images || null,
     current: S.conf.current || 0,
     currentPage: S.conf.currentPage || 1, //1-based index
     pageSize: S.conf.pageSize || 3,
     jqc: S.conf.context || window.document,
     jq: S.conf.jq || (function () {
       if ('jquery' in S.conf.slider) {
         return S.conf.slider.constructor
       }
       else {
         return null;
       }
     })(),
   }

   //sanity check
   if (S.conf.images == null || S.conf.slider == null) {
     console.error('Must pass "slider" and "images" properties to configuration oject of Slides().');
     return false;
   }

   //
   //initialization
   //
   (function () {
     var slide, page = 0;
     for (var i in S.conf.images) {
       if ((i % S.conf.pageSize) == 0) {
         ++page;
       }

       slide = '';
       //
       //build this slide
       //
       slide += '
';
       if (page == S.conf.currentPage) {
         slide += ''
       }
       slide += '
';

       // initialize a bunch of empty slides
       S.conf.jq(slide).appendTo(S.conf.slider);
     }
     S.conf.jq('

').appendTo(S.conf.slider);
   })();

   return this;
 }

 Slides.prototype.setSlide = function (index) {
   return this;
 }

 Slides.prototype.next = function () {
   this.setSlide(this.current + 1);
   return this;
 }
 Slides.prototype.previous = function () {
   this.setSlide(this.current - 1);
   return this;
 }
 Slides.prototype.pausePlay = function () {
   return this;
 }
})()

<|endoftext|>


<commit_before>exports.register = (server, options, next) => {
  const limitDefault = options.limit || 5;

  const search = function () {
    return this.query.search || null;
  };

  const limit = function () {
    return this.query.limit || limitDefault;
  };

  const offset = function () {
    let page = this.query.page || 1;
    if (page) {
      return limit.call(this) * (page - 1);
    }
    return 0;
  };

  server.decorate('request', 'offset', offset);
  server.decorate('request', 'limit', limit);
  server.decorate('request', 'search', search);

  next();
};

exports.register.attributes = {
  name: 'hapi-paginate',
  version: '1.0.0'
};
<commit_msg>alter plugin paginate<commit_after>exports.register = (server, options, next) => {
  const limitDefault = options.limit || 5;

  const limit = function () {
    return this.query.limit || limitDefault;
  };

  const offset = function () {
    let page = this.query.page || 1;
    if (page) {
      return limit.call(this) * (page - 1);
    }
    return 0;
  };

  server.decorate('request', 'offset', offset);
  server.decorate('request', 'limit', limit);

  next();
};

exports.register.attributes = {
  name: 'hapi-paginate',
  version: '1.0.0'
};
<|endoftext|>


<commit_before>angular.module('achan.cordova.navigator', []).factory('$navigator', function () {
  return navigator;
});
<commit_msg>renames module to achan.cordova<commit_after>angular.module('achan.cordova', []).factory('$navigator', function () {
  return navigator;
});
<|endoftext|>


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

/**
 * @fileoverview
 * This script downloads the module and nomodule builds then runs the bundle
 * size check.
 * This is run during the CI stage = test; job = Bundle Size.
 */

const {
  abortTimedJob,
  downloadModuleOutput,
  downloadNomoduleOutput,
  printChangeSummary,
  printSkipMessage,
  startTimer,
  stopTimer,
  timedExecOrDie,
} = require('./utils');
const {determineBuildTargets} = require('./build-targets');
const {isPullRequestBuild, isTravisBuild} = require('../common/ci');
const {runNpmChecks} = require('./npm-checks');
const {setLoggingPrefix} = require('../common/logging');

const jobName = 'bundle-size.js';

async function main() {
  setLoggingPrefix(jobName);
  const startTime = startTimer(jobName);

  if (!runNpmChecks()) {
    return abortTimedJob(jobName, startTime);
  }

  // TODO(rsimha): Remove this block once Travis is shut off.
  if (isTravisBuild()) {
    printSkipMessage(
      jobName,
      'this is a Travis build. Sizes will be reported from CircleCI'
    );
  }

  if (!isPullRequestBuild()) {
    downloadNomoduleOutput();
    downloadModuleOutput();
    timedExecOrDie('gulp bundle-size --on_push_build');
  } else {
    printChangeSummary();
    const buildTargets = determineBuildTargets();
    if (buildTargets.has('RUNTIME') || buildTargets.has('FLAG_CONFIG')) {
      downloadNomoduleOutput();
      downloadModuleOutput();
      timedExecOrDie('gulp bundle-size --on_pr_build');
    } else {
      timedExecOrDie('gulp bundle-size --on_skipped_build');
      printSkipMessage(
        jobName,
        'this PR does not affect the runtime or flag configs'
      );
    }
  }

  stopTimer(jobName, startTime);
}

main();
<commit_msg>🏗 Fix bundle-size check for Travis builds (#32073)<commit_after>/**
 * Copyright 2020 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

/**
 * @fileoverview
 * This script downloads the module and nomodule builds then runs the bundle
 * size check.
 * This is run during the CI stage = test; job = Bundle Size.
 */

const {
  abortTimedJob,
  downloadModuleOutput,
  downloadNomoduleOutput,
  printChangeSummary,
  printSkipMessage,
  startTimer,
  stopTimer,
  timedExecOrDie,
} = require('./utils');
const {determineBuildTargets} = require('./build-targets');
const {isPullRequestBuild, isTravisBuild} = require('../common/ci');
const {runNpmChecks} = require('./npm-checks');
const {setLoggingPrefix} = require('../common/logging');

const jobName = 'bundle-size.js';

async function main() {
  setLoggingPrefix(jobName);
  const startTime = startTimer(jobName);

  if (!runNpmChecks()) {
    return abortTimedJob(jobName, startTime);
  }

  // TODO(rsimha): Remove this block once Travis is shut off.
  if (isTravisBuild()) {
    printSkipMessage(
      jobName,
      'this is a Travis build. Sizes will be reported from CircleCI'
    );
    return;
  }

  if (!isPullRequestBuild()) {
    downloadNomoduleOutput();
    downloadModuleOutput();
    timedExecOrDie('gulp bundle-size --on_push_build');
  } else {
    printChangeSummary();
    const buildTargets = determineBuildTargets();
    if (buildTargets.has('RUNTIME') || buildTargets.has('FLAG_CONFIG')) {
      downloadNomoduleOutput();
      downloadModuleOutput();
      timedExecOrDie('gulp bundle-size --on_pr_build');
    } else {
      timedExecOrDie('gulp bundle-size --on_skipped_build');
      printSkipMessage(
        jobName,
        'this PR does not affect the runtime or flag configs'
      );
    }
  }

  stopTimer(jobName, startTime);
}

main();
<|endoftext|>


<commit_before>'use strict';

/**
 * this module contains all the code related to the setup data
 */

const { FilesManager, ObjectUtils } = require('turbocommons-ts');
const console = require('./console.js');
const { execSync } = require('child_process');
const { StringUtils } = require('turbocommons-ts');
const validateModule = require('./validate');
const buildModule = require('./build');

let fm = new FilesManager(require('fs'), require('os'), require('path'), process);

/**
 * Initialize the setup structure from the project json
 */
exports.init = function () {

    this.loadSetupFromDisk();

    validateModule.validateBuilderVersion();
}

/**
 * Calculate the turbo builder cmd current version
 */
exports.getBuilderVersion = function () {

    return StringUtils.trim(require(global.installationPaths.root + '/package.json').version);
}

/**
 * Calculate the most recent project semantic version value (major.minor.patch) depending on git tags or other parameters
 */
exports.getProjectRepoSemVer = function (includeGitCommits = false) {

    buildModule.checkGitAvailable();

    let commitsCount = this.countCommitsSinceLatestTag();

    let gitCommits = (includeGitCommits && commitsCount > 0) ? ' +' + commitsCount : '';

    try{

        let execResult = execSync('git describe --abbrev=0 --tags', {stdio : 'pipe'});

        return StringUtils.trim(execResult.toString()) + gitCommits;

    }catch(e){

        return '0.0.0';
    }
}

/**
 * Count the number of commits since the most recent git tag
 */
exports.countCommitsSinceLatestTag = function () {

    buildModule.checkGitAvailable();

    try{

        let execResult = execSync('git describe --abbrev=0 --tags', {stdio : 'pipe'});

        execResult = execSync('git rev-list ' + StringUtils.trim(execResult.toString()) + '.. --count', {stdio : 'pipe'});

        return StringUtils.trim(execResult.toString());

    }catch(e){

        return '0';
    }
}

/**
 * Read the json setup file from the current project and store all the data to a global variable
 */
exports.loadSetupFromDisk = function () {

    if (!fm.isFile(global.runtimePaths.setupFile)) {

        console.error(global.fileNames.setup + ' setup file not found');
    }

    let projectSetup = JSON.parse(fm.readFile(global.runtimePaths.setupFile));

    // Load the template setup
    global.setup = this.customizeSetupTemplateToProjectType(this.detectProjectTypeFromSetup(projectSetup));

    // Merge the project setup into the template one
    mergeSetup(global.setup, projectSetup);
};

/**
 * Detect the project type that is specified on the provided setup object
 */
exports.detectProjectTypeFromSetup = function (setup) {

    let projectType = '';
    let projectTypesCount = 0;

    for (let key of ObjectUtils.getKeys(setup.build)) {

        if(global.setupBuildTypes.indexOf(key) >= 0){

            projectType = key;
            projectTypesCount ++;
        }
    }

    if(projectType === ''){

        console.error("No valid project type specified. Please enable any of [" +
            global.setupBuildTypes.join(', ') + "] under build section in " + global.fileNames.setup);
    }

    if(projectTypesCount !== 1){

        console.error("Please specify only one of the following on build setup: " + global.setupBuildTypes.join(","));
    }

    return projectType;
};

/**
 * Merge the project custom setup with the template default one
 */
let mergeSetup = function (templateSetup, projectSetup) {

    for (let key of ObjectUtils.getKeys(templateSetup)){

        // Clear the sync setup on the template if nothing is specified on the project setup file
        if(key === 'sync' &&
           !projectSetup.hasOwnProperty(key)){

            templateSetup[key] = [];
        }

        // Build project types are deleted from the default template, cause there can only be one
        // defined
        if(global.setupBuildTypes.indexOf(key) >= 0 &&
           !projectSetup.hasOwnProperty(key)){

            delete templateSetup[key];
        }

        if(projectSetup.hasOwnProperty(key)){

            if(ObjectUtils.isObject(templateSetup[key])){

                mergeSetup(templateSetup[key], projectSetup[key]);

            }else{

                templateSetup[key] = projectSetup[key];
            }
        }
    }
};

/**
 * Generate a turbobuilder json setup file based on the specified project type
 */
exports.customizeSetupTemplateToProjectType = function (type) {

    // Read the default template setup file
    let templateSetupPath = global.installationPaths.mainResources + fm.dirSep() + 'project-templates'
        + fm.dirSep() + 'shared' + fm.dirSep() + global.fileNames.setup;

    let setupContents = JSON.parse(fm.readFile(templateSetupPath));

    // Customize the metadata section
    setupContents.metadata.builderVersion = this.getBuilderVersion();

    // Customize the validate section
    setupContents.validate.copyrightHeaders = [];

    // Customize the build section
    for (let key of ObjectUtils.getKeys(setupContents.build)) {

        if(key !== type){

            delete setupContents.build[key];
        }
    }

    // Customize the release section
    if(type !== 'site_php' && type === 'lib_php'){

        delete setupContents.release['optimizePhp'];
    }

    // Customize the sync section
    let syncArray = [];

    for (let syncItem of setupContents.sync) {

        if(type === 'site_php' && syncItem.type === 'fileSystem'){

            syncItem.excludes = [];

            // We expect the following symlink to point to the
            // local webserver http docs root
            syncItem.destPath = 'C:/turbosite-webserver-symlink';

            syncArray.push(syncItem);
        }
    }

    setupContents.sync = syncArray;

    // Customize the test section
    let testArray = [];

    for (let testItem of setupContents.test) {

        if(type === 'lib_php' && testItem.type === 'phpUnit'){

            testArray.push(testItem);
        }

        if((type === 'site_php' || type === 'lib_ts') &&
                testItem.type === 'jasmine'){

            testArray.push(testItem);
        }
    }

    setupContents.test = testArray;

    return setupContents;
}<commit_msg>Added lib_js project type to custom setup file generation<commit_after>'use strict';

/**
 * this module contains all the code related to the setup data
 */

const { FilesManager, ObjectUtils } = require('turbocommons-ts');
const console = require('./console.js');
const { execSync } = require('child_process');
const { StringUtils } = require('turbocommons-ts');
const validateModule = require('./validate');
const buildModule = require('./build');

let fm = new FilesManager(require('fs'), require('os'), require('path'), process);

/**
 * Initialize the setup structure from the project json
 */
exports.init = function () {

    this.loadSetupFromDisk();

    validateModule.validateBuilderVersion();
}

/**
 * Calculate the turbo builder cmd current version
 */
exports.getBuilderVersion = function () {

    return StringUtils.trim(require(global.installationPaths.root + '/package.json').version);
}

/**
 * Calculate the most recent project semantic version value (major.minor.patch) depending on git tags or other parameters
 */
exports.getProjectRepoSemVer = function (includeGitCommits = false) {

    buildModule.checkGitAvailable();

    let commitsCount = this.countCommitsSinceLatestTag();

    let gitCommits = (includeGitCommits && commitsCount > 0) ? ' +' + commitsCount : '';

    try{

        let execResult = execSync('git describe --abbrev=0 --tags', {stdio : 'pipe'});

        return StringUtils.trim(execResult.toString()) + gitCommits;

    }catch(e){

        return '0.0.0';
    }
}

/**
 * Count the number of commits since the most recent git tag
 */
exports.countCommitsSinceLatestTag = function () {

    buildModule.checkGitAvailable();

    try{

        let execResult = execSync('git describe --abbrev=0 --tags', {stdio : 'pipe'});

        execResult = execSync('git rev-list ' + StringUtils.trim(execResult.toString()) + '.. --count', {stdio : 'pipe'});

        return StringUtils.trim(execResult.toString());

    }catch(e){

        return '0';
    }
}

/**
 * Read the json setup file from the current project and store all the data to a global variable
 */
exports.loadSetupFromDisk = function () {

    if (!fm.isFile(global.runtimePaths.setupFile)) {

        console.error(global.fileNames.setup + ' setup file not found');
    }

    let projectSetup = JSON.parse(fm.readFile(global.runtimePaths.setupFile));

    // Load the template setup
    global.setup = this.customizeSetupTemplateToProjectType(this.detectProjectTypeFromSetup(projectSetup));

    // Merge the project setup into the template one
    mergeSetup(global.setup, projectSetup);
};

/**
 * Detect the project type that is specified on the provided setup object
 */
exports.detectProjectTypeFromSetup = function (setup) {

    let projectType = '';
    let projectTypesCount = 0;

    for (let key of ObjectUtils.getKeys(setup.build)) {

        if(global.setupBuildTypes.indexOf(key) >= 0){

            projectType = key;
            projectTypesCount ++;
        }
    }

    if(projectType === ''){

        console.error("No valid project type specified. Please enable any of [" +
            global.setupBuildTypes.join(', ') + "] under build section in " + global.fileNames.setup);
    }

    if(projectTypesCount !== 1){

        console.error("Please specify only one of the following on build setup: " + global.setupBuildTypes.join(","));
    }

    return projectType;
};

/**
 * Merge the project custom setup with the template default one
 */
let mergeSetup = function (templateSetup, projectSetup) {

    for (let key of ObjectUtils.getKeys(templateSetup)){

        // Clear the sync setup on the template if nothing is specified on the project setup file
        if(key === 'sync' &&
           !projectSetup.hasOwnProperty(key)){

            templateSetup[key] = [];
        }

        // Build project types are deleted from the default template, cause there can only be one
        // defined
        if(global.setupBuildTypes.indexOf(key) >= 0 &&
           !projectSetup.hasOwnProperty(key)){

            delete templateSetup[key];
        }

        if(projectSetup.hasOwnProperty(key)){

            if(ObjectUtils.isObject(templateSetup[key])){

                mergeSetup(templateSetup[key], projectSetup[key]);

            }else{

                templateSetup[key] = projectSetup[key];
            }
        }
    }
};

/**
 * Generate a turbobuilder json setup file based on the specified project type
 */
exports.customizeSetupTemplateToProjectType = function (type) {

    // Read the default template setup file
    let templateSetupPath = global.installationPaths.mainResources + fm.dirSep() + 'project-templates'
        + fm.dirSep() + 'shared' + fm.dirSep() + global.fileNames.setup;

    let setupContents = JSON.parse(fm.readFile(templateSetupPath));

    // Customize the metadata section
    setupContents.metadata.builderVersion = this.getBuilderVersion();

    // Customize the validate section
    setupContents.validate.copyrightHeaders = [];

    // Customize the build section
    for (let key of ObjectUtils.getKeys(setupContents.build)) {

        if(key !== type){

            delete setupContents.build[key];
        }
    }

    // Customize the release section
    if(type !== 'site_php' && type === 'lib_php'){

        delete setupContents.release['optimizePhp'];
    }

    // Customize the sync section
    let syncArray = [];

    for (let syncItem of setupContents.sync) {

        if(type === 'site_php' && syncItem.type === 'fileSystem'){

            syncItem.excludes = [];

            // We expect the following symlink to point to the
            // local webserver http docs root
            syncItem.destPath = 'C:/turbosite-webserver-symlink';

            syncArray.push(syncItem);
        }
    }

    setupContents.sync = syncArray;

    // Customize the test section
    let testArray = [];

    for (let testItem of setupContents.test) {

        if(type === 'lib_php' && testItem.type === 'phpUnit'){

            testArray.push(testItem);
        }

        if((type === 'site_php' || type === 'lib_js' || type === 'lib_ts') &&
                testItem.type === 'jasmine'){

            testArray.push(testItem);
        }
    }

    setupContents.test = testArray;

    return setupContents;
}<|endoftext|>