<commit_before>import uuid from 'uuid';

import { BrowserSessionStorage } from '../browserstorage';

const API_ROOT_URL = 'https://api.spotify.com';
const ACCOUNTS_ROOT_URL = 'https://accounts.spotify.com';
const CLIENT_ID = '847878927a644fc98c98d6313d7f4cdd';

const spotifyBrowserStorage = new BrowserSessionStorage({
  entryName: 'spotify',
  defaultState: () => {
    return {
      token: null,
      authState: null,
    };
  },
});

class SpotifyApi {

  constructor() {
    this.token = spotifyBrowserStorage.read().token;
    this.scopes = ['user-follow-read', 'user-read-private', 'user-top-read'];
    this.redirectUri = `${window.location.protocol}//${window.location.host}/spotify/callback`;
    this.authorizing = false;
    this.me = new MeApi(this);
    this.artists = new ArtistsApi(this);
  }

  get(url) {
    const headers = {};
    if (this.token) {
      headers['Authorization'] = `Bearer ${this.token}`;
    }

    const options = { headers };

    return fetch(`${API_ROOT_URL}${url}`, options).then(response => {
      if (!response.ok) {
        if (response.status) {
          switch (response.status) {
          case 401:
            return this.authorize();
          default:
            throw new Error(`Got HTTP error ${response.status} calling Spotify API`);
          }
        }

        throw new Error(`Failed response: ${response}`);
      }
      return response.json();
    });
  }

  authorize() {
    // Redirect only once
    if (!this.authorizing) {
      this.authorizing = true;

      const authState = uuid.v4();
      this.writeInStorage({
        authState,
      });

      const joinedScopes = this.scopes.join(' ');
      window.location = `${ACCOUNTS_ROOT_URL}/authorize?response_type=token&client_id=${CLIENT_ID}&scope=${joinedScopes}&redirect_uri=${this.redirectUri}&state=${authState}`;
    }

    // Promise that never resolves, because of a inflight authorization
    return new Promise(() => {});
  }

  handleCallback(callbackArgs) {
    return new Promise((resolve, reject) => {
      const token = callbackArgs.access_token;
      const authState = callbackArgs.state;

      if (token) {
        const storageAuthState = spotifyBrowserStorage.read().authState;
        if (authState !== storageAuthState) {
          reject(new Error('State from callback different from current session state'));
        } else {
          this.writeInStorage({
            token,
          });
          this.token = token;

          resolve();
        }
      } else {
        reject(new Error(`Got error from Spotify auth: ${callbackArgs.error}`));
      }
    });
  }

  writeInStorage(newStorage) {
    const storage = spotifyBrowserStorage.read();
    const mergedStorage = {
      ...storage,
      ...newStorage,
    };
    spotifyBrowserStorage.write(mergedStorage);
  }

}

class MeApi {

  constructor(base) {
    this.base = base;
  }

  getProfile() {
    return this.base.get('/v1/me');
  }

  getFollowedArtists() {
    return this.base.get('/v1/me/following?type=artist&limit=50');
  }

  getTopArtists() {
    return this.base.get('/v1/me/top/artists?limit=50');
  }

}

class ArtistsApi {

  constructor(base) {
    this.base = base;
  }

  getAlbums(artistId) {
    // TODO Market as parameter
    return this.base.get(`/v1/artists/${artistId}/albums?album_type=album&market=FR`);
  }

}

export const api = new SpotifyApi();
<commit_msg>Better use of Promise API<commit_after>import uuid from 'uuid';

import { BrowserSessionStorage } from '../browserstorage';

const API_ROOT_URL = 'https://api.spotify.com';
const ACCOUNTS_ROOT_URL = 'https://accounts.spotify.com';
const CLIENT_ID = '847878927a644fc98c98d6313d7f4cdd';

const spotifyBrowserStorage = new BrowserSessionStorage({
  entryName: 'spotify',
  defaultState: () => {
    return {
      token: null,
      authState: null,
    };
  },
});

function unresolvablePromise() {
  return new Promise(() => {});
}

function syncPromise(callback) {
  return new Promise(resolve => {
    return resolve(callback());
  });
}

class SpotifyApi {

  constructor() {
    this.token = spotifyBrowserStorage.read().token;
    this.scopes = ['user-follow-read', 'user-read-private', 'user-top-read'];
    this.redirectUri = `${window.location.protocol}//${window.location.host}/spotify/callback`;
    this.authorizing = false;
    this.me = new MeApi(this);
    this.artists = new ArtistsApi(this);
  }

  get(url) {
    const headers = {};
    if (this.token) {
      headers['Authorization'] = `Bearer ${this.token}`;
    }

    const options = { headers };

    return fetch(`${API_ROOT_URL}${url}`, options).then(response => {
      if (!response.ok) {
        if (response.status) {
          switch (response.status) {
          case 401:
            return this.authorize();
          default:
            throw new Error(`Got HTTP error ${response.status} calling Spotify API`);
          }
        }

        throw new Error(`Failed response: ${response}`);
      }
      return response.json();
    });
  }

  authorize() {
    // Redirect only once
    if (!this.authorizing) {
      this.authorizing = true;

      const authState = uuid.v4();
      this.writeInStorage({
        authState,
      });

      const joinedScopes = this.scopes.join(' ');
      window.location = `${ACCOUNTS_ROOT_URL}/authorize?response_type=token&client_id=${CLIENT_ID}&scope=${joinedScopes}&redirect_uri=${this.redirectUri}&state=${authState}`;
    }

    // Promise that never resolves, because of a inflight authorization
    return unresolvablePromise();
  }

  handleCallback(callbackArgs) {
    return syncPromise(() => {
      const token = callbackArgs.access_token;
      const authState = callbackArgs.state;

      if (!token) {
        throw new Error(`Got error from Spotify auth: ${callbackArgs.error}`);
      }

      const storageAuthState = spotifyBrowserStorage.read().authState;
      if (authState !== storageAuthState) {
        throw new Error('State from callback different from current session state');
      }

      this.writeInStorage({
        token,
      });
      this.token = token;

    });
  }

  writeInStorage(newStorage) {
    const storage = spotifyBrowserStorage.read();
    const mergedStorage = {
      ...storage,
      ...newStorage,
    };
    spotifyBrowserStorage.write(mergedStorage);
  }

}

class MeApi {

  constructor(base) {
    this.base = base;
  }

  getProfile() {
    return this.base.get('/v1/me');
  }

  getFollowedArtists() {
    return this.base.get('/v1/me/following?type=artist&limit=50');
  }

  getTopArtists() {
    return this.base.get('/v1/me/top/artists?limit=50');
  }

}

class ArtistsApi {

  constructor(base) {
    this.base = base;
  }

  getAlbums(artistId) {
    // TODO Market as parameter
    return this.base.get(`/v1/artists/${artistId}/albums?album_type=album&market=FR`);
  }

}

export const api = new SpotifyApi();
<|endoftext|>


<commit_before>'use strict';

angular.module('ddsCommon').constant('droitsDescription', {
    'cmu_c': {
        'id':'cmu_c',
        'label':'Couverture Maladie Universelle Complémentaire',
        'shortLabel':'CMU-C',
        'description':'La CMU-C est une protection complémentaire santé gratuite.',
        'conditions': [
            'Résider en France depuis plus de 3 mois.'
        ],
        'imgSrc':'logo_cmu.png',
        'link':'http://www.cmu.fr/cmu-complementaire.php'
    },
    'acs': {
        'id':'acs',
        'isMontantAnnuel':true,
        'label':'Aide pour une Complémentaire Santé',
        'shortLabel':'ACS',
        'description':'L’aide pour l’acquisition d’une assurance complémentaire santé, dite ACS, est une aide financière pour payer une complémentaire santé (exemple : une mutuelle).',
        'conditions': [
            'Résider en France depuis plus de 3 mois.'
        ],
        'imgSrc':'logo_cmu.png',
        'link':'http://www.cmu.fr/acs.php'
    },
    'aspa': {
        'id':'aspa',
        'label':'Allocation de Solidarité aux Personnes Âgées',
        'shortLabel':'ASPA',
        'description':'L’allocation de solidarité aux personnes âgées (Aspa) est une allocation destinée aux personnes âgées disposant de faibles revenus en vue de leur assurer un niveau minimum de ressources. Elle remplace le minimum vieillesse depuis 2006.',
        'conditions': [
            'Résider en France plus de 6 mois cette année.',
            'Avoir demandé toutes les retraites (générale, réversion, complémentaire…) auxquelles vous avez droit.',
            'Votre conjoint doit avoir demandé toutes les retraites (générale, réversion, complémentaire…) auxquelles il ou elle a droit.'
        ],

        'imgSrc':'logo_aspa.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F16871.xhtml'
    },
    'asi': {
        'id':'asi',
        'label':'Allocation Supplémentaire d’Invalidité',
        'shortLabel':'ASI',
        'description':'L’allocation supplémentaire d’invalidité (Asi) est une prestation versée sous certaines conditions aux personnes invalides titulaires d’une pension de retraite ou d’invalidité qui n’ont pas atteint l’âge légal de départ à la retraite pour bénéficier de l’allocation de solidarité aux personnes âgées (Aspa)',
        'imgSrc':'logo_aspa.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F16940.xhtml'
    },
    'af': {
        'id':'af',
        'label':'Allocations Familiales',
        'shortLabel':'AF',
        'description':'Les allocations familiales sont versées aux personnes ayant au moins 2 enfants de moins de 20 ans à charge. Le montant des prestations dépend du nombre d’enfants à charge, de leur âge et des ressources de la famille.',
        'conditions': [
            'Résider en France plus de 6 mois cette année.'
        ],
        'imgSrc':'logo_caf.png',
        'link':'http://www.caf.fr/aides-et-services/s-informer-sur-les-aides/petite-enfance/les-allocations-familiales-af-0'
    },
    'cf': {
        'id':'cf',
        'label':'Complément Familial',
        'shortLabel':'CF',
        'description':'Le complément familial est versé, sous certaines conditions, aux personnes ayant au moins 3 enfants à charge.',
        'imgSrc':'logo_caf.png',
        'link':'http://www.caf.fr/aides-et-services/s-informer-sur-les-aides/enfance-et-jeunesse/le-complement-familialcf',
        'isBaseRessourcesYearMoins2':true
    },
    'asf': {
        'id':'asf',
        'label':'Allocation de Soutien Familial',
        'shortLabel':'ASF',
        'description':'L’ASF est versée par la CAF ou la MSA au parent qui élève seul son enfant ou à la personne qui a recueilli un enfant, qu’elle vive seule ou en couple.',
        'conditions': [
            'Ne pas toucher l’intégralité d’une pension alimentaire qui vous aurait été attribuée par une décision de justice, ou que cette pension soit d’un montant inférieur à celui de l’ASF.'
        ],
        'imgSrc':'logo_caf.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F815.xhtml'
    },
    'paje_base': {
        'id':'paje_base',
        'label':'Prestation d’Accueil du Jeune Enfant - Allocation de base',
        'shortLabel':'PAJE-BASE',
        'description': 'L’allocation de base vous aide à assurer les dépenses liées à l’entretien et à l’éducation de votre enfant.',
        'imgSrc':'logo_caf.png',
        'link':'https://www.caf.fr/aides-et-services/s-informer-sur-les-aides/petite-enfance/l-allocation-de-base',
        'isBaseRessourcesYearMoins2':true
    },
    'rsa': {
        'id':'rsa',
        'label':'Revenu de Solidarité Active',
        'shortLabel':'RSA',
        'description':'Le RSA est destiné à assurer aux personnes disposant de faibles ressources un niveau minimum de revenu variable selon la composition de leur foyer.',
        'conditions': [
            'Résider en France plus de 9 mois par an.',
            'Si vous êtes ressortissant.e d’un pays de l’UE, de l’EEE ou Suisse, résider en France depuis plus de 3 mois.',
            'Si vous êtes ressortissant.e d’un autre pays, résider en France depuis plus de 5 ans.'
        ],
        'imgSrc':'logo_rsa.png',
        'link':'http://vosdroits.service-public.fr/particuliers/N19775.xhtml',
        'uncomputability': {
            'tns': {
                'reason': 'vous avez des revenus en tant qu’indépendant.e',
                'solution': 'Vous pouvez demander à bénéficier du RSA, mais c’est le président de votre conseil départemental qui décidera de la manière dont vos revenus non salariés impacteront le montant de votre aide.'
            },
            'conjoint_tns': {
                'reason': 'votre conjoint.e a des revenus en tant qu’indépendant.e',
                'solution': 'Vous pouvez demander à bénéficier du RSA, mais c’est le président de votre conseil départemental qui décidera de la manière dont les revenus non salariés de votre conjoint.e impacteront le montant de votre aide.'
            }
        }
    },
    'aide_logement': {
        'id':'aide_logement',
        'label':'Aides au Logement',
        'shortLabel':'AL',
        'description':'L’aide au logement est une aide financière destinée à réduire le montant de votre loyer ou votre mensualité d’emprunt immobilier. Elle est attribuée selon la nature de votre logement et la composition de votre famille.',
        'conditions': [
            'Résider au moins 8 mois par an dans le logement que vous avez décrit.',
            'Apparaître sur le bail ou contrat de prêt.',
            'Le logement doit être décent.'
        ],
        'imgSrc':'logo_caf.png',
        'link':'https://www.caf.fr/aides-et-services/s-informer-sur-les-aides/logement-et-cadre-de-vie/les-aides-au-logement-0',
        'isBaseRessourcesYearMoins2':true,
        'uncomputability': {
            'primo_accedant': {
                'reason': 'vous êtes primo-accédant à la propriété de votre résidence principale',
                'solution': 'Le simulateur de la CAF pourra estimer vos droits sur la base de la valeur de votre bien.'
            },
            'locataire_foyer': {
                'reason': 'vous logez dans un foyer',
                'solution': 'Le simulateur de la CAF vous donnera des estimations selon les différentes conventions possibles de votre foyer.'
            }

        }
    },
    'ass': {
        'id':'ass',
        'label':'Allocation de Solidarité Spécifique',
        'shortLabel':'ASS',
        'description':'L’allocation de solidarité spécifique (ASS) est une aide financière destinée aux personnes ayant épuisé leurs droits aux allocations chômage.',
        'imgSrc':'logo_ass.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F12484.xhtml'
    },
    'bourse_college': {
        'id':'bourse_college',
        'isMontantAnnuel':true,
        'label':'Bourse de collège',
        'shortLabel':'Bourse collège',
        'description':'La bourse des collèges est une aide destinée à favoriser la scolarité des collégiens. Elle est versée sous conditions de ressources.',
        'imgSrc':'logo_education_nationale.png',
        'link':'http://www.education.gouv.fr/cid88/les-aides-financieres-au-college.html#Les%20bourses%20de%20coll%C3%A8ge',
        'isBaseRessourcesYearMoins2':true
    },
    'bourse_lycee': {
        'id':'bourse_lycee',
        'isMontantAnnuel':true,
        'label':'Bourse de lycée',
        'shortLabel':'Bourse lycée',
        'description':'La bourse des lycées est accordée, sous condition de ressources, à la famille d’un lycéen. Son montant dépend des ressources et des charges de la famille. Cette bourse peut être accompagnée de diverses primes (prime d’équipement, prime à la qualification, bourse au mérite au lycée, prime à l’internat...).',
        'imgSrc':'logo_education_nationale.png',
        'link':'http://www.education.gouv.fr/cid151/aides-financieres-au-lycee.html#Les%20bourses%20de%20lycée',
        'isBaseRessourcesYearMoins2':true
    },
    'paris_logement_familles': {
        'id':'paris_logement_familles',
        'isMontantAnnuel':false,
        'label':'Paris Logement Familles',
        'shortLabel':'PLF',
        'description':'L’allocation Paris Logement Familles permet aux familles parisiennes de mieux supporter leurs dépenses de logement.',
        'conditions': [
            'Avoir demandé le versements des aides logement auxquelles vous avez droit auprès de la CAF.',
            'Ne toucher aucune autre prestation logement de la part de la mairie de Paris ou du département.'
        ],
        'imgSrc':'logo_mairie_paris.png',
        'link':'http://www.paris.fr/aides',
        'isBaseRessourcesYearMoins2':false
    }
});
<commit_msg>Explicit AF dependency on N-2 resources<commit_after>'use strict';

angular.module('ddsCommon').constant('droitsDescription', {
    'cmu_c': {
        'id':'cmu_c',
        'label':'Couverture Maladie Universelle Complémentaire',
        'shortLabel':'CMU-C',
        'description':'La CMU-C est une protection complémentaire santé gratuite.',
        'conditions': [
            'Résider en France depuis plus de 3 mois.'
        ],
        'imgSrc':'logo_cmu.png',
        'link':'http://www.cmu.fr/cmu-complementaire.php'
    },
    'acs': {
        'id':'acs',
        'isMontantAnnuel':true,
        'label':'Aide pour une Complémentaire Santé',
        'shortLabel':'ACS',
        'description':'L’aide pour l’acquisition d’une assurance complémentaire santé, dite ACS, est une aide financière pour payer une complémentaire santé (exemple : une mutuelle).',
        'conditions': [
            'Résider en France depuis plus de 3 mois.'
        ],
        'imgSrc':'logo_cmu.png',
        'link':'http://www.cmu.fr/acs.php'
    },
    'aspa': {
        'id':'aspa',
        'label':'Allocation de Solidarité aux Personnes Âgées',
        'shortLabel':'ASPA',
        'description':'L’allocation de solidarité aux personnes âgées (Aspa) est une allocation destinée aux personnes âgées disposant de faibles revenus en vue de leur assurer un niveau minimum de ressources. Elle remplace le minimum vieillesse depuis 2006.',
        'conditions': [
            'Résider en France plus de 6 mois cette année.',
            'Avoir demandé toutes les retraites (générale, réversion, complémentaire…) auxquelles vous avez droit.',
            'Votre conjoint doit avoir demandé toutes les retraites (générale, réversion, complémentaire…) auxquelles il ou elle a droit.'
        ],

        'imgSrc':'logo_aspa.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F16871.xhtml'
    },
    'asi': {
        'id':'asi',
        'label':'Allocation Supplémentaire d’Invalidité',
        'shortLabel':'ASI',
        'description':'L’allocation supplémentaire d’invalidité (Asi) est une prestation versée sous certaines conditions aux personnes invalides titulaires d’une pension de retraite ou d’invalidité qui n’ont pas atteint l’âge légal de départ à la retraite pour bénéficier de l’allocation de solidarité aux personnes âgées (Aspa)',
        'imgSrc':'logo_aspa.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F16940.xhtml'
    },
    'af': {
        'id':'af',
        'label':'Allocations Familiales',
        'shortLabel':'AF',
        'description':'Les allocations familiales sont versées aux personnes ayant au moins 2 enfants de moins de 20 ans à charge. Le montant des prestations dépend du nombre d’enfants à charge, de leur âge et des ressources de la famille.',
        'conditions': [
            'Résider en France plus de 6 mois cette année.'
        ],
        'imgSrc':'logo_caf.png',
        'link':'http://www.caf.fr/aides-et-services/s-informer-sur-les-aides/petite-enfance/les-allocations-familiales-af-0',
        'isBaseRessourcesYearMoins2':true
    },
    'cf': {
        'id':'cf',
        'label':'Complément Familial',
        'shortLabel':'CF',
        'description':'Le complément familial est versé, sous certaines conditions, aux personnes ayant au moins 3 enfants à charge.',
        'imgSrc':'logo_caf.png',
        'link':'http://www.caf.fr/aides-et-services/s-informer-sur-les-aides/enfance-et-jeunesse/le-complement-familialcf',
        'isBaseRessourcesYearMoins2':true
    },
    'asf': {
        'id':'asf',
        'label':'Allocation de Soutien Familial',
        'shortLabel':'ASF',
        'description':'L’ASF est versée par la CAF ou la MSA au parent qui élève seul son enfant ou à la personne qui a recueilli un enfant, qu’elle vive seule ou en couple.',
        'conditions': [
            'Ne pas toucher l’intégralité d’une pension alimentaire qui vous aurait été attribuée par une décision de justice, ou que cette pension soit d’un montant inférieur à celui de l’ASF.'
        ],
        'imgSrc':'logo_caf.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F815.xhtml'
    },
    'paje_base': {
        'id':'paje_base',
        'label':'Prestation d’Accueil du Jeune Enfant - Allocation de base',
        'shortLabel':'PAJE-BASE',
        'description': 'L’allocation de base vous aide à assurer les dépenses liées à l’entretien et à l’éducation de votre enfant.',
        'imgSrc':'logo_caf.png',
        'link':'https://www.caf.fr/aides-et-services/s-informer-sur-les-aides/petite-enfance/l-allocation-de-base',
        'isBaseRessourcesYearMoins2':true
    },
    'rsa': {
        'id':'rsa',
        'label':'Revenu de Solidarité Active',
        'shortLabel':'RSA',
        'description':'Le RSA est destiné à assurer aux personnes disposant de faibles ressources un niveau minimum de revenu variable selon la composition de leur foyer.',
        'conditions': [
            'Résider en France plus de 9 mois par an.',
            'Si vous êtes ressortissant.e d’un pays de l’UE, de l’EEE ou Suisse, résider en France depuis plus de 3 mois.',
            'Si vous êtes ressortissant.e d’un autre pays, résider en France depuis plus de 5 ans.'
        ],
        'imgSrc':'logo_rsa.png',
        'link':'http://vosdroits.service-public.fr/particuliers/N19775.xhtml',
        'uncomputability': {
            'tns': {
                'reason': 'vous avez des revenus en tant qu’indépendant.e',
                'solution': 'Vous pouvez demander à bénéficier du RSA, mais c’est le président de votre conseil départemental qui décidera de la manière dont vos revenus non salariés impacteront le montant de votre aide.'
            },
            'conjoint_tns': {
                'reason': 'votre conjoint.e a des revenus en tant qu’indépendant.e',
                'solution': 'Vous pouvez demander à bénéficier du RSA, mais c’est le président de votre conseil départemental qui décidera de la manière dont les revenus non salariés de votre conjoint.e impacteront le montant de votre aide.'
            }
        }
    },
    'aide_logement': {
        'id':'aide_logement',
        'label':'Aides au Logement',
        'shortLabel':'AL',
        'description':'L’aide au logement est une aide financière destinée à réduire le montant de votre loyer ou votre mensualité d’emprunt immobilier. Elle est attribuée selon la nature de votre logement et la composition de votre famille.',
        'conditions': [
            'Résider au moins 8 mois par an dans le logement que vous avez décrit.',
            'Apparaître sur le bail ou contrat de prêt.',
            'Le logement doit être décent.'
        ],
        'imgSrc':'logo_caf.png',
        'link':'https://www.caf.fr/aides-et-services/s-informer-sur-les-aides/logement-et-cadre-de-vie/les-aides-au-logement-0',
        'isBaseRessourcesYearMoins2':true,
        'uncomputability': {
            'primo_accedant': {
                'reason': 'vous êtes primo-accédant à la propriété de votre résidence principale',
                'solution': 'Le simulateur de la CAF pourra estimer vos droits sur la base de la valeur de votre bien.'
            },
            'locataire_foyer': {
                'reason': 'vous logez dans un foyer',
                'solution': 'Le simulateur de la CAF vous donnera des estimations selon les différentes conventions possibles de votre foyer.'
            }

        }
    },
    'ass': {
        'id':'ass',
        'label':'Allocation de Solidarité Spécifique',
        'shortLabel':'ASS',
        'description':'L’allocation de solidarité spécifique (ASS) est une aide financière destinée aux personnes ayant épuisé leurs droits aux allocations chômage.',
        'imgSrc':'logo_ass.png',
        'link':'http://vosdroits.service-public.fr/particuliers/F12484.xhtml'
    },
    'bourse_college': {
        'id':'bourse_college',
        'isMontantAnnuel':true,
        'label':'Bourse de collège',
        'shortLabel':'Bourse collège',
        'description':'La bourse des collèges est une aide destinée à favoriser la scolarité des collégiens. Elle est versée sous conditions de ressources.',
        'imgSrc':'logo_education_nationale.png',
        'link':'http://www.education.gouv.fr/cid88/les-aides-financieres-au-college.html#Les%20bourses%20de%20coll%C3%A8ge',
        'isBaseRessourcesYearMoins2':true
    },
    'bourse_lycee': {
        'id':'bourse_lycee',
        'isMontantAnnuel':true,
        'label':'Bourse de lycée',
        'shortLabel':'Bourse lycée',
        'description':'La bourse des lycées est accordée, sous condition de ressources, à la famille d’un lycéen. Son montant dépend des ressources et des charges de la famille. Cette bourse peut être accompagnée de diverses primes (prime d’équipement, prime à la qualification, bourse au mérite au lycée, prime à l’internat...).',
        'imgSrc':'logo_education_nationale.png',
        'link':'http://www.education.gouv.fr/cid151/aides-financieres-au-lycee.html#Les%20bourses%20de%20lycée',
        'isBaseRessourcesYearMoins2':true
    },
    'paris_logement_familles': {
        'id':'paris_logement_familles',
        'isMontantAnnuel':false,
        'label':'Paris Logement Familles',
        'shortLabel':'PLF',
        'description':'L’allocation Paris Logement Familles permet aux familles parisiennes de mieux supporter leurs dépenses de logement.',
        'conditions': [
            'Avoir demandé le versements des aides logement auxquelles vous avez droit auprès de la CAF.',
            'Ne toucher aucune autre prestation logement de la part de la mairie de Paris ou du département.'
        ],
        'imgSrc':'logo_mairie_paris.png',
        'link':'http://www.paris.fr/aides',
        'isBaseRessourcesYearMoins2':false
    }
});
<|endoftext|>


<commit_before>import assignIn from 'lodash/assignIn';

import {
  DISPATCH_TYPE,
  STATE_TYPE
} from '../constants';

class Store {
  /**
   * Creates a new Proxy store
   * @param  {object} options An object of form {portName, state, extensionId}, where `portName` is a required string and defines the name of the port for state transition changes, `state` is the initial state of this store (default `{}`) `extensionId` is the extension id as defined by chrome when extension is loaded (default `''`)
   */
  constructor({portName, state = {}, extensionId = ''}) {
    if (!portName) {
      throw new Error('portName is required in options');
    }

    chrome.runtime.onConnect.addListener(port => {
      if (port.name === portName) {
        this.readyResolve();
      }
    });

    this.readyResolved = false;
    this.readyPromise = new Promise(resolve => this.readyResolve = resolve);

    this.extensionId = extensionId; //keep the extensionId as an instance variable
    this.port = chrome.runtime.connect(this.extensionId, {name: portName});
    this.listeners = [];
    this.state = state;

    this.port.onMessage.addListener((message) => {
      if (message.type === STATE_TYPE) {
        this.replaceState(message.payload);

        if (!this.readyResolved) {
          this.readyResolved = true;
          this.readyResolve();
        }
      }
    });

    this.dispatch = this.dispatch.bind(this); //add this context to dispatch
  }

  /**
  * Returns a promise that resolves when the store is ready. Optionally a callback may be passed in instead.
  * @param [function] callback An optional callback that may be passed in and will fire when the store is ready.
  * @return {object} promise A promise that resolves when the store has established a connection with the background page.
  */
  ready(cb = null) {
    if (cb !== null) {
      return this.readyPromise.then(cb);
    }

    return this.readyPromise;
  }

  /**
   * Subscribes a listener function for all state changes
   * @param  {function} listener A listener function to be called when store state changes
   * @return {function}          An unsubscribe function which can be called to remove the listener from state updates
   */
  subscribe(listener) {
    this.listeners.push(listener);

    return () => {
      this.listeners = this.listeners.filter((l) => l !== listener);
    };
  }

  /**
   * Replace the current state with a new state. Notifies all listeners of state change.
   * @param  {object} state The new state for the store
   */
  replaceState(state) {
    this.state = state;

    this.listeners.forEach((l) => l());
  }

  /**
   * Get the current state of the store
   * @return {object} the current store state
   */
  getState() {
    return this.state;
  }

  /**
   * Dispatch an action to the background using messaging passing
   * @param  {object} data The action data to dispatch
   * @return {Promise}     Promise that will resolve/reject based on the action response from the background
   */
  dispatch(data) {
    return new Promise((resolve, reject) => {
      chrome.runtime.sendMessage(
        this.extensionId,
      {
        type: DISPATCH_TYPE,
        payload: data
      }, ({error, value}) => {
        if (error) {
          reject(assignIn((new Error()), error));
        } else {
          resolve(value && value.payload);
        }
      });
    });
  }
}

export default Store;
<commit_msg>remove portName connection artifact<commit_after>import assignIn from 'lodash/assignIn';

import {
  DISPATCH_TYPE,
  STATE_TYPE
} from '../constants';

class Store {
  /**
   * Creates a new Proxy store
   * @param  {object} options An object of form {portName, state, extensionId}, where `portName` is a required string and defines the name of the port for state transition changes, `state` is the initial state of this store (default `{}`) `extensionId` is the extension id as defined by chrome when extension is loaded (default `''`)
   */
  constructor({portName, state = {}, extensionId = ''}) {
    if (!portName) {
      throw new Error('portName is required in options');
    }

    this.readyResolved = false;
    this.readyPromise = new Promise(resolve => this.readyResolve = resolve);

    this.extensionId = extensionId; //keep the extensionId as an instance variable
    this.port = chrome.runtime.connect(this.extensionId, {name: portName});
    this.listeners = [];
    this.state = state;

    this.port.onMessage.addListener((message) => {
      if (message.type === STATE_TYPE) {
        this.replaceState(message.payload);

        if (!this.readyResolved) {
          this.readyResolved = true;
          this.readyResolve();
        }
      }
    });

    this.dispatch = this.dispatch.bind(this); //add this context to dispatch
  }

  /**
  * Returns a promise that resolves when the store is ready. Optionally a callback may be passed in instead.
  * @param [function] callback An optional callback that may be passed in and will fire when the store is ready.
  * @return {object} promise A promise that resolves when the store has established a connection with the background page.
  */
  ready(cb = null) {
    if (cb !== null) {
      return this.readyPromise.then(cb);
    }

    return this.readyPromise;
  }

  /**
   * Subscribes a listener function for all state changes
   * @param  {function} listener A listener function to be called when store state changes
   * @return {function}          An unsubscribe function which can be called to remove the listener from state updates
   */
  subscribe(listener) {
    this.listeners.push(listener);

    return () => {
      this.listeners = this.listeners.filter((l) => l !== listener);
    };
  }

  /**
   * Replace the current state with a new state. Notifies all listeners of state change.
   * @param  {object} state The new state for the store
   */
  replaceState(state) {
    this.state = state;

    this.listeners.forEach((l) => l());
  }

  /**
   * Get the current state of the store
   * @return {object} the current store state
   */
  getState() {
    return this.state;
  }

  /**
   * Dispatch an action to the background using messaging passing
   * @param  {object} data The action data to dispatch
   * @return {Promise}     Promise that will resolve/reject based on the action response from the background
   */
  dispatch(data) {
    return new Promise((resolve, reject) => {
      chrome.runtime.sendMessage(
        this.extensionId,
      {
        type: DISPATCH_TYPE,
        payload: data
      }, ({error, value}) => {
        if (error) {
          reject(assignIn((new Error()), error));
        } else {
          resolve(value && value.payload);
        }
      });
    });
  }
}

export default Store;
<|endoftext|>


<commit_before>'use strict';
/*
 * Teensy controller for handling the quit button in the side menu
 */

angular.module('quit', [])

    .controller('QuitCtrl', function($scope, apiFactory) {
        $scope.exit  = function() {

            apiFactory.auth.logout()
                .then(function (results) {
                    navigator.app.exitApp();
                })
                .catch(function (error) {
                    navigator.app.exitApp();
                })

        };
});

<commit_msg>Refactor quit controller<commit_after>'use strict';

/*
 * Teensy controller for handling the quit button in the side menu
 */

angular.module('quit', [])
.controller('QuitCtrl', function ($scope, apiFactory) {
    $scope.exit  = function () {
        apiFactory.auth.logout()
            .then(function () {
                navigator.app.exitApp();
            })
            .catch(function () {
                navigator.app.exitApp();
            });
    };
});

<|endoftext|>


<commit_before>
//Fetch from svalbard sightings couch database here the owner's observations
sightingControllers.controller('MyObservationsCtrl', function($scope, $http) {
  /* $http.jsonp('http://apptest.data.npolar.no/sighting/?q=&format=json&callback=JSON_CALLBACK&locales=utf-8')
    .success(function(data) {
        $scope.full = data;
     }).error(function (data, status, headers, config) {
     }); */
});

//View entry here
sightingControllers.controller('ViewObservationCtrl', function($scope, $routeParams,$http, SightingDBUpdate) {
      $scope.entry = SightingDBUpdate.get({id: $routeParams.id }, function(){
        console.log($scope.entry);
  });
   //get hostname
   $scope.hostname = location.host;
});

//New entry created here
sightingControllers.controller('NewObservationCtrl', function($scope, $http, npolarApiSecurity, npolarApiUser, Sighting) {
   $scope.entry = {};

   /*Set select menu for species*/
   $scope.items = species_gallery;

   $scope.submit = function() {

      /* Populate with inital values */
      console.log($scope.entry);
      entry = $scope.entry
      entry.schema = 'http://api.npolar.no/schema/sighting.json';
      entry.collection = 'sighting';
      entry.base = 'http://api.npolar.no';
      entry.language = 'en';
      entry.basis_of_record = 'HumanObservation';
      entry.rights = 'No licence announced on the web site';
      entry.rights_holder = 'Norwegian Polar Institute';
      entry.recorded_by = npolarApiUser.getUser().username;
      entry.recorded_by_name = npolarApiUser.getUser().username;
      entry.created = (new Date()).toISOString();
      entry.created_by = npolarApiUser.getUser().username;
     // entry.expedition.start_date = '2014-03-01';

      $scope.entry = entry;

      //Update species
      if (typeof entry.species != "undefined") {
        $scope.entry.species = entry.species.family;
      }
     /* if (typeof $scope.entry.event_date != "undefined") {
          $scope.entry.event_date = (entry.event_date).toISOString();
      } */
 /*     if (typeof $scope.entry.expedition.start_date != "undefined") {
          $scope.entry.expedition.start_date = entry.expedition.start_date;
      } */
     /* if (typeof $scope.entry.expedition.end_date != "undefined") {
          $scope.entry.expedition.end_date = entry.expedition.end_date;
      } */

       console.log(JSON.stringify($scope.entry));

      //Sighting.save(entry);
      var entry = new Sighting($scope.entry);

      var ret = entry.$save();

      console.log("New entry" + JSON.stringify(entry));
      console.log("New entry2 " + JSON.stringify(ret));

  }
});

//Update entry from Svalbard MMS couch database here
sightingControllers.controller('EditObservationCtrl',  function($scope, $routeParams, $http,
  Sighting, SightingDBUpdate, npolarApiSecurity, npolarApiUser) {
    var entry = SightingDBUpdate.get({id: $routeParams.id }, function(){
    $scope.entry = entry;
     console.log('edit ' + JSON.stringify(entry));
    $scope.items = species_gallery;
  });

    //Store update
    $scope.submit = function(id) {
      var entry = new Sighting($scope.entry);
      console.log('edit ' + JSON.stringify(entry));
      console.log("http "  + JSON.stringify($http.defaults.headers.common));
      entry.$update();
  }
});

//Delete entry here by updating so entry is still available
sightingControllers.controller('DeleteObservationCtrl',
  function($scope, $http, $routeParams, Sighting, SightingDBUpdate) {

     //Delete by put update, set _deleted to true
    $scope.submit = function(id) {
          var entry = new Sighting($scope.entry);
          //Delete by setting _deleted to true
          entry._deleted = true;
          entry.$update();
          console.log("entry object: ", entry);
   }
});

//Controller for Excel file upload
sightingControllers.controller('UploadObservationsCtrl', function($scope, $http) {
     $scope.filesChanged = function(elm){
        $scope.files=elm.files;
        $scope.$apply();
       // console.log($scope.files);
     }
     $scope.upload = function() {
        var fd = new FormData();

        angular.forEach($scope.files, function(file){
          fd.append('file',file);
        });

        console.log(fd);

        $http.post('https://apptest.data.npolar.no:4444/upload_excel', fd,
        {
          transformrequest:angular.identity,
          headers:{'Content-Type':'multipart/form-data'}
        } )
        .success(function(data, status, headers, config) {
         console.log('success: ' + data);

        })
        .error(function(data, status, headers, config) {
         console.log('error' + data);
        });
   }
});
<commit_msg>fixed date format in forms<commit_after>
//Fetch from svalbard sightings couch database here the owner's observations
sightingControllers.controller('MyObservationsCtrl', function($scope, $http) {
  /* $http.jsonp('http://apptest.data.npolar.no/sighting/?q=&format=json&callback=JSON_CALLBACK&locales=utf-8')
    .success(function(data) {
        $scope.full = data;
     }).error(function (data, status, headers, config) {
     }); */
});

//View entry here
sightingControllers.controller('ViewObservationCtrl', function($scope, $routeParams,$http, SightingDBUpdate) {
      $scope.entry = SightingDBUpdate.get({id: $routeParams.id }, function(){
        console.log($scope.entry);
  });
   //get hostname
   $scope.hostname = location.host;
});

//New entry created here
sightingControllers.controller('NewObservationCtrl', function($scope, $http, npolarApiSecurity, npolarApiUser, Sighting) {
   $scope.entry = {};

   /*Set select menu for species*/
   $scope.items = species_gallery;

   $scope.submit = function() {

      /* Populate with inital values */
      console.log($scope.entry);
      entry = $scope.entry
      entry.schema = 'http://api.npolar.no/schema/sighting.json';
      entry.collection = 'sighting';
      entry.base = 'http://api.npolar.no';
      entry.language = 'en';
      entry.basis_of_record = 'HumanObservation';
      entry.rights = 'No licence announced on the web site';
      entry.rights_holder = 'Norwegian Polar Institute';
      entry.recorded_by = npolarApiUser.getUser().username;
      entry.recorded_by_name = npolarApiUser.getUser().username;
      entry.created = (new Date()).toISOString();
      entry.created_by = npolarApiUser.getUser().username;
     // entry.expedition.start_date = '2014-03-01';

      $scope.entry = entry;

      //Update species
      if (typeof entry.species != "undefined") {
        $scope.entry.species = entry.species.family;
      }
     /* if (typeof $scope.entry.event_date != "undefined") {
          $scope.entry.event_date = (entry.event_date).toISOString();
      } */
 /*     if (typeof $scope.entry.expedition.start_date != "undefined") {
          $scope.entry.expedition.start_date = entry.expedition.start_date;
      } */
     /* if (typeof $scope.entry.expedition.end_date != "undefined") {
          $scope.entry.expedition.end_date = entry.expedition.end_date;
      } */

       console.log(JSON.stringify($scope.entry));

      //Sighting.save(entry);
      var entry = new Sighting($scope.entry);

      var ret = entry.$save();

      console.log("New entry" + JSON.stringify(entry));
      console.log("New entry2 " + JSON.stringify(ret));

  }
});

//Update entry from Svalbard MMS couch database here
sightingControllers.controller('EditObservationCtrl',  function($scope, $routeParams, $http,
  Sighting, SightingDBUpdate, npolarApiSecurity, npolarApiUser) {
    var entry = SightingDBUpdate.get({id: $routeParams.id }, function(){
    $scope.entry = entry;
    /*Set abbreviated dates*/
    $scope.entry.event_date = entry.event_date.substring(0,10);
    $scope.entry.expedition.start_date = entry.expedition.end_date.substring(0,10);
    $scope.entry.expedition.end_date = entry.expedition.end_date.substring(0,10);
     console.log('edit ' + JSON.stringify(entry));
    $scope.items = species_gallery;
  });

    //Store update
    $scope.submit = function(id) {
      var entry = new Sighting($scope.entry);
      console.log('edit ' + JSON.stringify(entry));
      console.log("http "  + JSON.stringify($http.defaults.headers.common));
      entry.$update();
  }
});

//Delete entry here by updating so entry is still available
sightingControllers.controller('DeleteObservationCtrl',
  function($scope, $http, $routeParams, Sighting, SightingDBUpdate) {

     //Delete by put update, set _deleted to true
    $scope.submit = function(id) {
          var entry = new Sighting($scope.entry);
          //Delete by setting _deleted to true
          entry._deleted = true;
          entry.$update();
          console.log("entry object: ", entry);
   }
});

//Controller for Excel file upload
sightingControllers.controller('UploadObservationsCtrl', function($scope, $http) {
     $scope.filesChanged = function(elm){
        $scope.files=elm.files;
        $scope.$apply();
       // console.log($scope.files);
     }
     $scope.upload = function() {
        var fd = new FormData();

        angular.forEach($scope.files, function(file){
          fd.append('file',file);
        });

        console.log(fd);

        $http.post('https://apptest.data.npolar.no:4444/upload_excel', fd,
        {
          transformrequest:angular.identity,
          headers:{'Content-Type':'multipart/form-data'}
        } )
        .success(function(data, status, headers, config) {
         console.log('success: ' + data);

        })
        .error(function(data, status, headers, config) {
         console.log('error' + data);
        });
   }
});
<|endoftext|>


<commit_before>function days(num) {
  return num*60*60*1000*24
}

module.exports = function parseCumGddGraph(gddData, callback) {
	var dates = gddData.date;
	var cumValue = [];
	var dailyValue = [];
	var numberOfDays = dates.length-1;
	var startDate = new Date() - days(numberOfDays);

	for(var i = 0; i <= dates.length-1; i++){
		cumValue.push({x: i, y: gddData.cum[i]});
		dailyValue.push({x: i, y: gddData.gdd[i]})
	}
	console.log("CUMVALUE");
	console.log(cumValue);
	callback([
    {
      values: cumValue,
      key: 'Cumulative GDD',
      color: '#ff7f0e'
    },
    {
      values: dailyValue,
      key: 'Daily GDD',
      color: '#2ca02c'
    }
  ]);
};<commit_msg>added x-axis date values<commit_after>function days(num) {
  return num*60*60*1000*24
}

module.exports = function parseCumGddGraph(gddData, callback) {
	var dates = gddData.date;
	var cumValue = [];
	var dailyValue = [];
	var numberOfDays = dates.length-1;
	var startDate = new Date() - days(numberOfDays);

	for(var i = 0; i <= dates.length-1; i++){
		cumValue.push({x: new Date(startDate + days(i)), y: gddData.cum[i]});
		dailyValue.push({x: new Date(startDate + days(i)), y: gddData.gdd[i]})
	}
	console.log("CUMVALUE");
	console.log(cumValue);
	callback([
    {
      values: cumValue,
      key: 'Cumulative GDD',
      color: '#ff7f0e',
      area: true
    },
    {
      values: dailyValue,
      key: 'Daily GDD',
      color: '#2ca02c',
      area: true
    }
  ]);
};<|endoftext|>


<commit_before>(function (ns) {

    var sanitizer = require("./sanitizer/sanitizer.js"),
        resolver =  require("../resolve/resolve.js"),
        staticTransformer = require("./constants/staticTransformer.js"),
        uniformAnalysis = require("./uniformExpressions/uniformAnalysis.js"),
        validator = require("./validator.js"),
        AnalysisContext = require("./analysiscontext.js"),
        inference = require("./typeinference/typeinference.js"),
        spaceTransformer = require("../generate/space/transform.js").SpaceTransformer,
        Annotations = require("./../base/annotation.js"),
        codegen = require("escodegen");

    var ANNO = Annotations.ANNO;

    /**
     *
     * @param {Object} ast
     * @param {Object|null} opt
     * @returns {Object}
     */
    var analyze = function (ast, processingData, opt) {
        opt = opt || {};
        processingData = processingData || {};

        var error;

        try {
            // Resolve BRDF closures
            ast = opt.implementation ? resolver.resolveClosuresPreTypeInference(ast, opt.implementation, processingData, opt) : ast;

            // Sanitize strange expressions into something
            // that is better analysable
            ast = opt.sanitize ? sanitizer.sanitize(ast, opt) : ast;

            //console.log("Analyze", codegen.generate(ast), ast.type, opt.sanitize);
            var context = new AnalysisContext(ast, function(ast, options) {
                    // Calculate types and static values
                    ast = inference.infer(ast, this, options);

            ast = opt.implementation ? resolver.resolveClosuresPostTypeInference(ast, opt.implementation, processingData, opt) : ast;

                    // Remove/Replace dead code and static expressions
                    ast = staticTransformer.transform(ast, options);

                    ast = opt.extractUniformExpressions ? uniformAnalysis.extract(ast, opt) : ast;
                    //console.log(opt.uniformExpressions);

                    return ast;

            }, opt);

            context.analyse();
            if (opt.entry) {
                context.injectCall(opt.entry, (opt.inject &&  opt.inject[opt.entry]) || []);
            }
            ast = context.getResult();

            opt.transformSpaces && spaceTransformer.transformAast(ast, opt);

            // check for remaining code the completeness of annotations
            ast = opt.validate ? validator.validate(ast) : ast;

            if(opt.transformSpaces)
                processingData.spaceInfo = spaceTransformer.transformAast(ast, opt);

        } catch (e) {
            if(opt.throwOnError) {
                throw e;
            }
            error = e;
        }

        return {
            ast: ast,
            error: error
        };

    };

    ns.analyze = analyze;

}(exports));
<commit_msg>UExp: Fixes from rebase<commit_after>(function (ns) {

    var sanitizer = require("./sanitizer/sanitizer.js"),
        resolver =  require("../resolve/resolve.js"),
        staticTransformer = require("./constants/staticTransformer.js"),
        uniformAnalysis = require("./uniformExpressions/uniformAnalysis.js"),
        validator = require("./validator.js"),
        AnalysisContext = require("./analysiscontext.js"),
        inference = require("./typeinference/typeinference.js"),
        spaceTransformer = require("../generate/space/transform.js").SpaceTransformer,
        Annotations = require("./../base/annotation.js"),
        codegen = require("escodegen");

    var ANNO = Annotations.ANNO;

    /**
     *
     * @param {Object} ast
     * @param {Object|null} opt
     * @returns {Object}
     */
    var analyze = function (ast, processingData, opt) {
        opt = opt || {};
        processingData = processingData || {};

        var error;

        try {
            // Resolve BRDF closures
            ast = opt.implementation ? resolver.resolveClosuresPreTypeInference(ast, opt.implementation, processingData, opt) : ast;

            // Sanitize strange expressions into something
            // that is better analysable
            ast = opt.sanitize ? sanitizer.sanitize(ast, opt) : ast;

            //console.log("Analyze", codegen.generate(ast), ast.type, opt.sanitize);
            var context = new AnalysisContext(ast, function(ast, options) {
                    // Calculate types and static values
                    ast = inference.infer(ast, this, options);

                    // Remove/Replace dead code and static expressions
                    ast = staticTransformer.transform(ast, options);

                    ast = opt.extractUniformExpressions ? uniformAnalysis.extract(ast, opt) : ast;
                    //console.log(opt.uniformExpressions);

                    return ast;

            }, opt);

            context.analyse();
            if (opt.entry) {
                context.injectCall(opt.entry, (opt.inject &&  opt.inject[opt.entry]) || []);
            }
            ast = context.getResult();

            ast = opt.implementation ? resolver.resolveClosuresPostTypeInference(ast, opt.implementation, processingData, opt) : ast;

            // check for remaining code the completeness of annotations
            ast = opt.validate ? validator.validate(ast) : ast;

            if(opt.transformSpaces)
                processingData.spaceInfo = spaceTransformer.transformAast(ast, opt);

        } catch (e) {
            if(opt.throwOnError) {
                throw e;
            }
            error = e;
        }

        return {
            ast: ast,
            error: error
        };

    };

    ns.analyze = analyze;

}(exports));
<|endoftext|>


<commit_before>/* global define, $ */
define(function(require, exports, module) {
    var http_cache = require("../../lib/http_cache");

    return {
        fetchUrl: function(url, callback) {
            http_cache.fetchUrl(url, {}, callback);
        },
        get: function(url, type, callback) {
            $.get(url, function(data) {
                callback(null, data);
            }, type).fail(function(jqXHR) {
                callback(jqXHR.status);
            });
        },
        post: function(url, options, callback) {
            options = options || {};

            options = options || {};

            $.ajax({
                url: url,
                type: 'POST',
                headers: options.headers,
                data: options.data,
                dataType: options.type
            }).done(function(body) {
                callback(null, body);
            }).fail(function(jqXHR) {
                callback(jqXHR.status);
            });
        }
    };
});<commit_msg>Removed dupe.<commit_after>/* global define, $ */
define(function(require, exports, module) {
    var http_cache = require("../../lib/http_cache");

    return {
        fetchUrl: function(url, callback) {
            http_cache.fetchUrl(url, {}, callback);
        },
        get: function(url, type, callback) {
            $.get(url, function(data) {
                callback(null, data);
            }, type).fail(function(jqXHR) {
                callback(jqXHR.status);
            });
        },
        post: function(url, options, callback) {
            options = options || {};

            $.ajax({
                url: url,
                type: 'POST',
                headers: options.headers,
                data: options.data,
                dataType: options.type
            }).done(function(body) {
                callback(null, body);
            }).fail(function(jqXHR) {
                callback(jqXHR.status);
            });
        }
    };
});
<|endoftext|>


<commit_before>var request     = require('request');
var crypto      = require('crypto');
var querystring = require('qs');

/**
 * KrakenClient connects to the Kraken.com API
 * @param {String} key    API Key
 * @param {String} secret API Secret
 * @param {String|Object} [options={}]  Additional options. If a string is passed, will default to just setting `options.otp`.
 * @param {String} [options.otp] Two-factor password (optional) (also, doesn't work)
 * @param {Number} [options.timeout] Maximum timeout (in milliseconds) for all API-calls (passed to `request`)
 */
function KrakenClient(key, secret, options) {
	var self = this;

	// make sure to be backwards compatible
	options = options || {};

	if(typeof options === 'string') {
		options = { otp: options };
	}

	var config = {
		url: 'https://api.kraken.com',
		version: options.version || '0',
		key: key,
		secret: secret,
		otp: options.otp,
		timeout: options.timeout || 15000,
	};

	/**
	 * This method makes a public or private API request.
	 * @param  {String}   method   The API method (public or private)
	 * @param  {Object}   params   Arguments to pass to the api call
	 * @param  {Function} callback A callback function to be executed when the request is complete
	 * @return {Object}            The request object
	 */
	function api(method, params, callback) {
		var methods = {
			public: ['Time', 'Assets', 'AssetPairs', 'Ticker', 'Depth', 'Trades', 'Spread', 'OHLC'],
			private: ['Balance', 'TradeBalance', 'OpenOrders', 'ClosedOrders', 'QueryOrders', 'TradesHistory', 'QueryTrades', 'OpenPositions', 'Ledgers', 'QueryLedgers', 'TradeVolume', 'AddOrder', 'CancelOrder', 'DepositMethods', 'DepositAddresses', 'DepositStatus', 'WithdrawInfo', 'Withdraw', 'WithdrawStatus', 'WithdrawCancel']
		};
		if (methods.public.indexOf(method) !== -1) {
			return publicMethod(method, params, callback);
		}
		else if (methods.private.indexOf(method) !== -1) {
			return privateMethod(method, params, callback);
		}
		else {
			throw new Error(method + ' is not a valid API method.');
		}
	}

	/**
	 * This method makes a public API request.
	 * @param  {String}   method   The API method (public or private)
	 * @param  {Object}   params   Arguments to pass to the api call
	 * @param  {Function} callback A callback function to be executed when the request is complete
	 * @return {Object}            The request object
	 */
	function publicMethod(method, params, callback) {
		params = params || {};

		var path = '/' + config.version + '/public/' + method;
		var url  = config.url + path;

		return rawRequest(url, {}, params, callback);
	}

	/**
	 * This method makes a private API request.
	 * @param  {String}   method   The API method (public or private)
	 * @param  {Object}   params   Arguments to pass to the api call
	 * @param  {Function} callback A callback function to be executed when the request is complete
	 * @return {Object}            The request object
	 */
	function privateMethod(method, params, callback) {
		params = params || {};

		var path = '/' + config.version + '/private/' + method;
		var url  = config.url + path;

		if (!params.nonce) {
			params.nonce = new Date() * 1000; // spoof microsecond
		}

		if (config.otp !== undefined) {
			params.otp = config.otp;
		}

		var signature = getMessageSignature(path, params, params.nonce);

		var headers = {
			'API-Key': config.key,
			'API-Sign': signature
		};

		return rawRequest(url, headers, params, callback);
	}

	/**
	 * This method returns a signature for a request as a Base64-encoded string
	 * @param  {String}  path    The relative URL path for the request
	 * @param  {Object}  request The POST body
	 * @param  {Integer} nonce   A unique, incrementing integer
	 * @return {String}          The request signature
	 */
	function getMessageSignature(path, request, nonce) {
		var message     = querystring.stringify(request);
		var secret      = new Buffer(config.secret, 'base64');
		var hash        = new crypto.createHash('sha256');
		var hmac        = new crypto.createHmac('sha512', secret);
		var hash_digest = hash.update(nonce + message).digest('binary');
		var hmac_digest = hmac.update(path + hash_digest, 'binary').digest('base64');

		return hmac_digest;
	}

	/**
	 * This method sends the actual HTTP request
	 * @param  {String}   url      The URL to make the request
	 * @param  {Object}   headers  Request headers
	 * @param  {Object}   params   POST body
	 * @param  {Function} callback A callback function to call when the request is complete
	 * @return {Object}            The request object
	 */
	function rawRequest(url, headers, params, callback) {
		// Set custom User-Agent string
		headers['User-Agent'] = 'Kraken Javascript API Client';

		var options = {
			url     : url,
			method  : 'POST',
			headers : headers,
			form    : params,
			timeout : config.timeout,
		};

		var req = request.post(options, function(error, response, body) {
			if (typeof callback === 'function') {
				var data;

				if (error) {
					return callback.call(self, new Error('Error in server response: ' + JSON.stringify(error)), null);
				}

				try {
					data = JSON.parse(body);
				}
				catch (e) {
					return callback.call(self, new Error('Could not understand response from server: ' + body), null);
				}
				//If any errors occured, Kraken will give back an array with error strings under
				//the key "error". We should then propagate back the error message as a proper error.
				if(data.error && Array.isArray(data.error)) {
					var krakenError = null;
					data.error.forEach(function(element) {
						if (element.charAt(0) === "E") {
							krakenError = element.substr(1);
							return false;
						}
					});
					if (krakenError) {
						return callback.call(self, new Error('Kraken API returned error: ' + krakenError), null);
					} else {
						return callback.call(self, new Error('Kraken API returned an unknown error'), null);
					}
				}
				else {
					return callback.call(self, null, data);
				}
			}
		});
		return req;
	}

	self.api           = api;
	self.publicMethod  = publicMethod;
	self.privateMethod = privateMethod;
}

module.exports = KrakenClient;
<commit_msg>update to ES6<commit_after>const request     = require('request');
const crypto      = require('crypto');
const querystring = require('qs');

// Public/Private method names
const methods = {
	public  : [ 'Time', 'Assets', 'AssetPairs', 'Ticker', 'Depth', 'Trades', 'Spread', 'OHLC' ],
	private : [ 'Balance', 'TradeBalance', 'OpenOrders', 'ClosedOrders', 'QueryOrders', 'TradesHistory', 'QueryTrades', 'OpenPositions', 'Ledgers', 'QueryLedgers', 'TradeVolume', 'AddOrder', 'CancelOrder', 'DepositMethods', 'DepositAddresses', 'DepositStatus', 'WithdrawInfo', 'Withdraw', 'WithdrawStatus', 'WithdrawCancel' ],
};

// Default options
const defaults = {
	url     : 'https://api.kraken.com',
	version : 0,
	timeout : 5000,
};

/**
 * KrakenClient connects to the Kraken.com API
 * @param {String}        key               API Key
 * @param {String}        secret            API Secret
 * @param {String|Object} [options={}]      Additional options. If a string is passed, will default to just setting `options.otp`.
 * @param {String}        [options.otp]     Two-factor password (optional) (also, doesn't work)
 * @param {Number}        [options.timeout] Maximum timeout (in milliseconds) for all API-calls (passed to `request`)
 */
class KrakenClient {
	constructor(key, secret, options) {
		// Allow passing the OTP as the third argument for backwards compatibility
		if(typeof options === 'string') {
			options = { otp : options };
		}

		this.config = Object.assign({ key, secret }, defaults, options);
	}

	/**
	 * This method makes a public or private API request.
	 * @param  {String}   method   The API method (public or private)
	 * @param  {Object}   params   Arguments to pass to the api call
	 * @param  {Function} callback A callback function to be executed when the request is complete
	 * @return {Object}            The request object
	 */
	api(method, params, callback) {
		if(methods.public.indexOf(method) !== -1) {
			return this.publicMethod(method, params, callback);
		}
		else if(methods.private.indexOf(method) !== -1) {
			return this.privateMethod(method, params, callback);
		}
		else {
			throw new Error(method + ' is not a valid API method.');
		}
	}

	/**
	 * This method makes a public API request.
	 * @param  {String}   method   The API method (public or private)
	 * @param  {Object}   params   Arguments to pass to the api call
	 * @param  {Function} callback A callback function to be executed when the request is complete
	 * @return {Object}            The request object
	 */
	publicMethod(method, params, callback) {
		params = params || {};

		const path = '/' + this.config.version + '/public/' + method;
		const url  = this.config.url + path;

		return this.rawRequest(url, {}, params, callback);
	}

	/**
	 * This method makes a private API request.
	 * @param  {String}   method   The API method (public or private)
	 * @param  {Object}   params   Arguments to pass to the api call
	 * @param  {Function} callback A callback function to be executed when the request is complete
	 * @return {Object}            The request object
	 */
	privateMethod(method, params, callback) {
		params = params || {};

		const path = '/' + this.config.version + '/private/' + method;
		const url  = this.config.url + path;

		if(!params.nonce) {
			params.nonce = new Date() * 1000; // spoof microsecond
		}

		if(this.config.otp !== undefined) {
			params.otp = this.config.otp;
		}

		const signature = this.getMessageSignature(path, params, params.nonce);

		const headers = {
			'API-Key'  : this.config.key,
			'API-Sign' : signature,
		};

		return this.rawRequest(url, headers, params, callback);
	}

	/**
	 * This method returns a signature for a request as a Base64-encoded string
	 * @param  {String}  path    The relative URL path for the request
	 * @param  {Object}  request The POST body
	 * @param  {Integer} nonce   A unique, incrementing integer
	 * @return {String}          The request signature
	 */
	getMessageSignature(path, request, nonce) {
		const message     = querystring.stringify(request);
		const secret      = new Buffer(this.config.secret, 'base64');
		const hash        = new crypto.createHash('sha256');
		const hmac        = new crypto.createHmac('sha512', secret);
		const hash_digest = hash.update(nonce + message).digest('binary');
		const hmac_digest = hmac.update(path + hash_digest, 'binary').digest('base64');

		return hmac_digest;
	}

	/**
	 * This method sends the actual HTTP request
	 * @param  {String}   url      The URL to make the request
	 * @param  {Object}   headers  Request headers
	 * @param  {Object}   params   POST body
	 * @param  {Function} callback A callback function to call when the request is complete
	 * @return {Object}            The request object
	 */
	rawRequest(url, headers, params, callback) {
		// Set custom User-Agent string
		headers['User-Agent'] = 'Kraken Javascript API Client';

		const options = {
			url     : url,
			method  : 'POST',
			headers : headers,
			form    : params,
			timeout : this.config.timeout,
		};

		const req = request.post(options, function(error, response, body) {
			if (typeof callback === 'function') {
				let data;

				if (error) {
					return callback(new Error('Error in server response: ' + JSON.stringify(error)), null);
				}

				try {
					data = JSON.parse(body);
				}
				catch (e) {
					return callback(new Error('Could not understand response from server: ' + body), null);
				}

				// If any errors occured, Kraken will give back an array with error strings under
				// the key "error". We should then propagate back the error message as a proper error.
				if(data.error && data.error.length) {
					let krakenError = null;

					data.error.forEach(function(element) {
						if (element.charAt(0) === "E") {
							krakenError = element.substr(1);
							return false;
						}
					});
					if (krakenError) {
						return callback(new Error('Kraken API returned error: ' + krakenError), null);
					}
					else {
						return callback(new Error('Kraken API returned an unknown error'), null);
					}
				}
				else {
					return callback(null, data);
				}
			}
		});

		return req;
	}
}

module.exports = KrakenClient;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React, { Component } from 'react'
import CommentInputArea from './CommentInputArea'
import PanelComment from './PanelComment'
import Button from 'components/Button'
import { scrollElementToCenter } from 'helpers/domHelpers'

export default class PanelComments extends Component {
  static propTypes = {
    autoFocus: PropTypes.bool,
    autoShowComments: PropTypes.bool,
    commentActions: PropTypes.object.isRequired,
    comments: PropTypes.array.isRequired,
    inputAreaInnerRef: PropTypes.func,
    inputAtBottom: PropTypes.bool,
    inputTypeLabel: PropTypes.string,
    loadMoreButton: PropTypes.bool.isRequired,
    loadMoreComments: PropTypes.func.isRequired,
    onSubmit: PropTypes.func.isRequired,
    parent: PropTypes.shape({
      id: PropTypes.number.isRequired,
      type: PropTypes.string.isRequired
    }).isRequired,
    style: PropTypes.object,
    type: PropTypes.string,
    userId: PropTypes.number
  }

  state = {
    isLoading: false,
    commentSubmitted: false,
    lastDeletedCommentIndex: null
  }

  Comments = {}

  componentDidUpdate(prevProps) {
    const { commentSubmitted } = this.state
    const { autoShowComments, comments, inputAtBottom } = this.props
    if (prevProps.comments.length > comments.length) {
      if (comments.length === 0) {
        return scrollElementToCenter(this.PanelComments)
      }
      if (
        comments[comments.length - 1].id !==
        prevProps.comments[prevProps.comments.length - 1].id
      ) {
        scrollElementToCenter(this.Comments[comments[comments.length - 1].id])
      }
    }
    if (
      inputAtBottom &&
      commentSubmitted &&
      comments.length > prevProps.comments.length &&
      (prevProps.comments.length === 0 ||
        comments[comments.length - 1].id >
          prevProps.comments[prevProps.comments.length - 1].id)
    ) {
      this.setState({ commentSubmitted: false })
      scrollElementToCenter(this.Comments[comments[comments.length - 1].id])
    }
    if (
      !autoShowComments &&
      prevProps.comments.length === 0 &&
      comments.length > 0 &&
      !commentSubmitted
    ) {
      scrollElementToCenter(this.CommentInputArea)
    }
  }

  render() {
    const {
      onSubmit,
      autoFocus,
      loadMoreButton,
      comments = [],
      inputAreaInnerRef,
      inputTypeLabel,
      parent,
      style,
      inputAtBottom
    } = this.props
    const { isLoading } = this.state
    return (

 {
          this.PanelComments = ref
        }}
      >
        {!inputAtBottom && (
          <CommentInputArea
            autoFocus={autoFocus}
            InputFormRef={ref => (this.CommentInputArea = ref)}
            innerRef={inputAreaInnerRef}
            inputTypeLabel={inputTypeLabel}
            onSubmit={comment => {
              this.setState({ commentSubmitted: true })
              onSubmit(comment, parent)
            }}
          />
        )}
        {comments.length > 0 && (

            {inputAtBottom &&
              loadMoreButton && (
                <Button
                  filled
                  info
                  disabled={isLoading}
                  onClick={this.loadMoreComments}
                  style={{
                    width: '100%',
                    display: 'flex',
                    justifyContent: 'center',
                    marginTop: '1rem'
                  }}
                >
                  Load More
                </Button>
              )}
            {this.renderComments()}
            {!inputAtBottom &&
              loadMoreButton && (
                <Button
                  filled
                  info
                  disabled={isLoading}
                  onClick={this.loadMoreComments}
                  style={{
                    width: '100%',
                    display: 'flex',
                    justifyContent: 'center',
                    marginTop: '1rem'
                  }}
                >
                  Load More
                </Button>
              )}

        )}
        {inputAtBottom && (
          <CommentInputArea
            autoFocus={autoFocus}
            InputFormRef={ref => (this.CommentInputArea = ref)}
            innerRef={inputAreaInnerRef}
            style={{ marginTop: '1rem' }}
            inputTypeLabel={inputTypeLabel}
            onSubmit={comment => {
              this.setState({ commentSubmitted: true })
              onSubmit(comment, parent)
            }}
          />
        )}

    )
  }

  renderComments = () => {
    const { comments, userId, parent, commentActions, type } = this.props
    const { lastDeletedCommentIndex, deleteListenerToggle } = this.state
    return comments.map((comment, index) => (
      <PanelComment
        {...commentActions}
        index={index}
        innerRef={ref => {
          this.Comments[comment.id] = ref
        }}
        type={type}
        parent={parent}
        comment={comment}
        isFirstComment={index === 0}
        key={comment.id}
        userId={userId}
        deleteCallback={this.deleteCallback}
        lastDeletedCommentIndex={lastDeletedCommentIndex}
        deleteListenerToggle={deleteListenerToggle}
      />
    ))
  }

  deleteCallback = (index, isFirstComment) => {
    this.setState({
      lastDeletedCommentIndex: index,
      deletedFirstComment: isFirstComment
    })
  }

  loadMoreComments = () => {
    const { isLoading } = this.state
    const { inputAtBottom } = this.props
    if (!isLoading) {
      const { comments, parent, loadMoreComments } = this.props
      this.setState({ isLoading: true }, async() => {
        const lastCommentLocation = inputAtBottom ? 0 : comments.length - 1
        const lastCommentId = comments[lastCommentLocation]
          ? comments[lastCommentLocation].id
          : 0
        try {
          await loadMoreComments({
            lastCommentId,
            type: parent.type,
            contentId: parent.id,
            rootType: parent.type
          })
          this.setState({ isLoading: false })
        } catch (error) {
          console.error(error)
        }
      })
    }
  }
}
<commit_msg>revert last change<commit_after>import PropTypes from 'prop-types'
import React, { Component } from 'react'
import CommentInputArea from './CommentInputArea'
import PanelComment from './PanelComment'
import Button from 'components/Button'
import { scrollElementToCenter } from 'helpers/domHelpers'

export default class PanelComments extends Component {
  static propTypes = {
    autoFocus: PropTypes.bool,
    autoShowComments: PropTypes.bool,
    commentActions: PropTypes.object.isRequired,
    comments: PropTypes.array.isRequired,
    inputAreaInnerRef: PropTypes.func,
    inputAtBottom: PropTypes.bool,
    inputTypeLabel: PropTypes.string,
    loadMoreButton: PropTypes.bool.isRequired,
    loadMoreComments: PropTypes.func.isRequired,
    onSubmit: PropTypes.func.isRequired,
    parent: PropTypes.shape({
      id: PropTypes.number.isRequired,
      type: PropTypes.string.isRequired
    }).isRequired,
    style: PropTypes.object,
    type: PropTypes.string,
    userId: PropTypes.number
  }

  state = {
    isLoading: false,
    commentSubmitted: false,
    lastDeletedCommentIndex: null
  }

  Comments = {}

  componentDidUpdate(prevProps) {
    const { commentSubmitted } = this.state
    const { autoShowComments, comments, inputAtBottom } = this.props
    if (prevProps.comments.length > comments.length) {
      if (comments.length === 0) {
        return scrollElementToCenter(this.PanelComments)
      }
      if (
        comments[comments.length - 1].id !==
        prevProps.comments[prevProps.comments.length - 1].id
      ) {
        scrollElementToCenter(this.Comments[comments[comments.length - 1].id])
      }
    }
    if (
      inputAtBottom &&
      commentSubmitted &&
      comments.length > prevProps.comments.length &&
      (prevProps.comments.length === 0 ||
        comments[comments.length - 1].id >
          prevProps.comments[prevProps.comments.length - 1].id)
    ) {
      this.setState({ commentSubmitted: false })
      scrollElementToCenter(this.Comments[comments[comments.length - 1].id])
    }
    if (
      !autoShowComments &&
      prevProps.comments.length === 0 &&
      comments.length > 0 &&
      !commentSubmitted
    ) {
      scrollElementToCenter(this.CommentInputArea)
    }
  }

  render() {
    const {
      onSubmit,
      autoFocus,
      loadMoreButton,
      comments = [],
      inputAreaInnerRef,
      inputTypeLabel,
      parent,
      style,
      inputAtBottom
    } = this.props
    const { isLoading } = this.state
    return (

 {
          this.PanelComments = ref
        }}
      >
        {!inputAtBottom && (
          <CommentInputArea
            autoFocus={autoFocus}
            innerRef={inputAreaInnerRef}
            inputTypeLabel={inputTypeLabel}
            onSubmit={comment => {
              this.setState({ commentSubmitted: true })
              onSubmit(comment, parent)
            }}
          />
        )}
        {comments.length > 0 && (

            {inputAtBottom &&
              loadMoreButton && (
                <Button
                  filled
                  info
                  disabled={isLoading}
                  onClick={this.loadMoreComments}
                  style={{
                    width: '100%',
                    display: 'flex',
                    justifyContent: 'center',
                    marginTop: '1rem'
                  }}
                >
                  Load More
                </Button>
              )}
            {this.renderComments()}
            {!inputAtBottom &&
              loadMoreButton && (
                <Button
                  filled
                  info
                  disabled={isLoading}
                  onClick={this.loadMoreComments}
                  style={{
                    width: '100%',
                    display: 'flex',
                    justifyContent: 'center',
                    marginTop: '1rem'
                  }}
                >
                  Load More
                </Button>
              )}

        )}
        {inputAtBottom && (
          <CommentInputArea
            autoFocus={autoFocus}
            InputFormRef={ref => (this.CommentInputArea = ref)}
            innerRef={inputAreaInnerRef}
            style={{ marginTop: '1rem' }}
            inputTypeLabel={inputTypeLabel}
            onSubmit={comment => {
              this.setState({ commentSubmitted: true })
              onSubmit(comment, parent)
            }}
          />
        )}

    )
  }

  renderComments = () => {
    const { comments, userId, parent, commentActions, type } = this.props
    const { lastDeletedCommentIndex, deleteListenerToggle } = this.state
    return comments.map((comment, index) => (
      <PanelComment
        {...commentActions}
        index={index}
        innerRef={ref => {
          this.Comments[comment.id] = ref
        }}
        type={type}
        parent={parent}
        comment={comment}
        isFirstComment={index === 0}
        key={comment.id}
        userId={userId}
        deleteCallback={this.deleteCallback}
        lastDeletedCommentIndex={lastDeletedCommentIndex}
        deleteListenerToggle={deleteListenerToggle}
      />
    ))
  }

  deleteCallback = (index, isFirstComment) => {
    this.setState({
      lastDeletedCommentIndex: index,
      deletedFirstComment: isFirstComment
    })
  }

  loadMoreComments = () => {
    const { isLoading } = this.state
    const { inputAtBottom } = this.props
    if (!isLoading) {
      const { comments, parent, loadMoreComments } = this.props
      this.setState({ isLoading: true }, async() => {
        const lastCommentLocation = inputAtBottom ? 0 : comments.length - 1
        const lastCommentId = comments[lastCommentLocation]
          ? comments[lastCommentLocation].id
          : 0
        try {
          await loadMoreComments({
            lastCommentId,
            type: parent.type,
            contentId: parent.id,
            rootType: parent.type
          })
          this.setState({ isLoading: false })
        } catch (error) {
          console.error(error)
        }
      })
    }
  }
}
<|endoftext|>


<commit_before>////////////////////////
// Seeds some tickets //
////////////////////////

'use strict';

module.exports = function (db) {
    db.Ticket.create({
        username: 10155,
        displayName: 'Gabriel Juchault',
        mail: 'gabriel.juchault@gmail.com',
        student: true,
        contributor: true,
        paid: true,
        paid_at: new Date(),
        paid_with: 'buckutt',
        temporarlyOut: false,
        barcode: '3780173904905',
        validatedMap: null,
        birthdate: '21/09/1994'
    }).complete(function (err, galaGJ) {
        if (err) {
            Error.emit(null, 500, '500 - SQL Server error', err.toString());
        }

        db.Price.find({ name: 'Gala 2015 - Prix étudiant cotisant en prévente' }).complete(function (err, price) {
            if (err) {
                Error.emit(null, 500, '500 - SQL Server error', err.toString());
            }

            galaGJ.setPrice(price);
        });

        galaGJ.setEvent(1);
    });

    db.Ticket.create({
        username: 55101,
        displayName: 'Gabriel Juchault',
        mail: 'gabriel.juchault@gmail.com',
        student: true,
        contributor: true,
        paid: true,
        paid_at: new Date(),
        paid_with: 'buckutt',
        temporarlyOut: false,
        barcode: '123456',
        validatedMap: null,
        birthdate: '22/09/1994'
    }).complete(function (err, galaGJ) {
        if (err) {
            Error.emit(null, 500, '500 - SQL Server error', err.toString());
        }

        db.Price.find({ name: 'Gala 2015 - Prix étudiant cotisant en prévente' }).complete(function (err, price) {
            if (err) {
                Error.emit(null, 500, '500 - SQL Server error', err.toString());
            }

            galaGJ.setPrice(price);
        });

        galaGJ.setEvent(1);
    });
};
<commit_msg>Seed mainTicket<commit_after>////////////////////////
// Seeds some tickets //
////////////////////////

'use strict';

module.exports = function (db) {
    db.Ticket.create({
        username: 10155,
        displayName: 'Gabriel Juchault',
        mail: 'gabriel.juchault@gmail.com',
        student: true,
        contributor: true,
        paid: true,
        paid_at: new Date(),
        paid_with: 'buckutt',
        temporarlyOut: false,
        barcode: '3780173904905',
        validatedMap: null,
        birthdate: '21/09/1994',
        mainTicket: 0
    }).complete(function (err, galaGJ) {
        if (err) {
            Error.emit(null, 500, '500 - SQL Server error', err.toString());
        }

        db.Price.find({ name: 'Gala 2015 - Prix étudiant cotisant en prévente' }).complete(function (err, price) {
            if (err) {
                Error.emit(null, 500, '500 - SQL Server error', err.toString());
            }

            galaGJ.setPrice(price);
        });

        galaGJ.setEvent(1);
    });

    db.Ticket.create({
        username: 55101,
        displayName: 'Gabriel Juchault',
        mail: 'gabriel.juchault@gmail.com',
        student: true,
        contributor: true,
        paid: true,
        paid_at: new Date(),
        paid_with: 'buckutt',
        temporarlyOut: false,
        barcode: '123456',
        validatedMap: null,
        birthdate: '22/09/1994',
        mainTicket: 0
    }).complete(function (err, galaGJ) {
        if (err) {
            Error.emit(null, 500, '500 - SQL Server error', err.toString());
        }

        db.Price.find({ name: 'Gala 2015 - Prix étudiant cotisant en prévente' }).complete(function (err, price) {
            if (err) {
                Error.emit(null, 500, '500 - SQL Server error', err.toString());
            }

            galaGJ.setPrice(price);
        });

        galaGJ.setEvent(1);
    });
};
<|endoftext|>