<commit_before>'use strict';

var moment = require('moment-timezone');
var overlap = require('word-overlap');
var clc = require('cli-color');
var eventsResult = {
  'meta': {},
  'events': []
};
var eventsToday = {
  'meta': {},
  'events': []
};
var eventsHour = {
  'meta': {},
  'events': []
}
var logger = require('tracer').colorConsole({
  format: '{{timestamp}} <{{title}}> ({{path}}:{{line}}:{{pos}}:{{method}}) {{message}}',
  dateformat: 'mmm dd HH:MM:ss',
  preprocess:  function(data) {
    data.path = data.path.replace(process.cwd(), '');
  }
});

module.exports = function(config) {
  var whitelistEvents = config.whitelistEvents;
  var blacklistEvents = config.blacklistEvents;
  var API = {
    getFacebookEvents: require('./facebookEvents')(config).get,
    getMeetupEvents: require('./meetupEvents')(config).get,
    getEventbriteEvents: require('./eventbriteEvents')(config).get,
    getIcsEvents: require('./icsEvents')(config).get
  };

  function isDuplicateEvent(event1, event2) {
    var options = {
      ignoreCase: true,
      ignoreCommonWords: true,
      ignoreNumber: true,
      common: config.ignoreWordsInDuplicateEvents.concat(config.city.toLowerCase()),
      depluralize: true
    };

    var overlappedEventName = overlap(event1.name, event2.name, options);
    var overlappedEventLocation = overlap(event1.location, event2.location, options);
    var overlappedEventDescription = overlap(event1.description, event2.description, options);

    if ((event1.formatted_time === event2.formatted_time) &&
      (event1.name === event2.name)) {
      // console.log(clc.magenta('Info: Duplicate event added: ' + event2.url));
      // console.log(clc.magenta('Info: Duplicate event overlaps: ' + overlappedEventDescription));
      // console.log(clc.magenta('-----------'))
      return true;
    }

    if ((event1.formatted_time === event2.formatted_time) &&
        (overlappedEventLocation.length > 0)) {
      if (overlappedEventName.length > 0 || overlappedEventDescription.length > 5) {
        console.log(clc.magenta('Duplicate event removed [' + overlappedEventDescription.length + ']: ' + event1.url));
        console.log(clc.magenta('Info: Duplicate event added: ' + event2.url));
        console.log(clc.magenta('Info: Duplicate event overlaps: ' + overlappedEventDescription));
        console.log(clc.magenta('-----------'))
        return true;
      }
    }

    return false;
  }

  function afterToday(evt) {
    return moment(evt.formatted_time, config.displayTimeformat) > moment();
  }

  function timeComparer(a, b) {
    return (moment(a.start_time).valueOf() -
            moment(b.start_time).valueOf());
  }

  function addEvents(type) {
    API[ 'get' + type + 'Events' ]().then(function(data) {
      data = data || [];
      var whiteEvents = data.filter(function(evt) {
        return !blacklistEvents.some(function(blackEvent) {
          return blackEvent.id === evt.id;
        });
      });

      var beforeNum = eventsResult.events.length
      eventsResult.events = eventsResult.events.concat(whiteEvents);
      eventsResult.events = eventsResult.events.filter(afterToday);

      eventsResult.events.sort(timeComparer);
      eventsResult.events = removeDuplicates(eventsResult.events);
      eventsResult.meta.total_events = eventsResult.events.length;

      var afterNum = eventsResult.events.length
      logger.info(clc.green('Success: Added ' + (afterNum - beforeNum) + ' ' + type + ' events'));

      eventsToday.events = getCurrentDayData(eventsResult);
      eventsToday.meta.generated_at = eventsResult.meta.generated_at;
      eventsToday.meta.location = eventsResult.meta.location;
      eventsToday.meta.api_version = eventsResult.meta.api_version;
      eventsToday.meta.total_events = eventsToday.events.length;

      eventsHour.events = getCurrentHourData(eventsResult);
      eventsHour.meta.generated_at = eventsResult.meta.generated_at;
      eventsHour.meta.location = eventsResult.meta.location;
      eventsHour.meta.api_version = eventsResult.meta.api_version;
      eventsHour.meta.total_events = eventsToday.events.length;
    }).catch(function(err) {
      logger.error('Failed to add ' + type + ' events: HTTP Status Code ' + err.statusCode || err);
    });
  }

  function removeDuplicates(feed) {
    var uniqueEvents = [];
    var isDuplicate;

    feed.forEach(function(thisEvent) {
      isDuplicate = uniqueEvents.some(function(thatEvent) {
        return isDuplicateEvent(thisEvent, thatEvent);
      })

      if (!isDuplicate) {
        uniqueEvents.push(thisEvent);
      }
    })

    return uniqueEvents;
  }

  function getCurrentDayData(data) {
    return data.events.filter(function(element) {
      return moment(data.meta.generated_at).diff(moment(element.start_time), 'days') === 0;
    })
  }

  function getCurrentHourData(data) {
    return data.events.filter(function (element) {
      return moment(element.formatted_time, 'DD MMM YYYY, ddd, hh:mm a').isBefore(moment().add(1, 'hour'))
    })
  }

  return {
    feed: eventsResult,
    day: eventsToday,
    hour: eventsHour,
    get: function(count) {
      var answer = {
        meta: {
          'generated_at': new Date().toISOString(),
          'location': config.city,
          'api_version': config.api_version,
          'total_events': parseInt(count)
        },
        events: eventsResult.events.slice(0, parseInt(count))
      }

      return answer
    },
    update: function() {
      eventsResult.meta = {
        'generated_at': new Date().toISOString(),
        'location': config.city,
        'api_version': config.api_version
      }
      eventsResult.events = whitelistEvents.filter(afterToday);
      logger.info('Updating the events feed... this may take a while');
      addEvents('Meetup');
      addEvents('Facebook');
      addEvents('Eventbrite');
      addEvents('Ics');
    }
  }
};
<commit_msg>fix: compare string id for blacklist events<commit_after>'use strict';

var moment = require('moment-timezone');
var overlap = require('word-overlap');
var clc = require('cli-color');
var eventsResult = {
  'meta': {},
  'events': []
};
var eventsToday = {
  'meta': {},
  'events': []
};
var eventsHour = {
  'meta': {},
  'events': []
}
var logger = require('tracer').colorConsole({
  format: '{{timestamp}} <{{title}}> ({{path}}:{{line}}:{{pos}}:{{method}}) {{message}}',
  dateformat: 'mmm dd HH:MM:ss',
  preprocess:  function(data) {
    data.path = data.path.replace(process.cwd(), '');
  }
});

module.exports = function(config) {
  var whitelistEvents = config.whitelistEvents;
  var blacklistEvents = config.blacklistEvents;

  var API = {
    getFacebookEvents: require('./facebookEvents')(config).get,
    getMeetupEvents: require('./meetupEvents')(config).get,
    getEventbriteEvents: require('./eventbriteEvents')(config).get,
    getIcsEvents: require('./icsEvents')(config).get
  };

  function isDuplicateEvent(event1, event2) {
    var options = {
      ignoreCase: true,
      ignoreCommonWords: true,
      ignoreNumber: true,
      common: config.ignoreWordsInDuplicateEvents.concat(config.city.toLowerCase()),
      depluralize: true
    };

    var overlappedEventName = overlap(event1.name, event2.name, options);
    var overlappedEventLocation = overlap(event1.location, event2.location, options);
    var overlappedEventDescription = overlap(event1.description, event2.description, options);

    if ((event1.formatted_time === event2.formatted_time) &&
      (event1.name === event2.name)) {
      // console.log(clc.magenta('Info: Duplicate event added: ' + event2.url));
      // console.log(clc.magenta('Info: Duplicate event overlaps: ' + overlappedEventDescription));
      // console.log(clc.magenta('-----------'))
      return true;
    }

    if ((event1.formatted_time === event2.formatted_time) &&
        (overlappedEventLocation.length > 0)) {
      if (overlappedEventName.length > 0 || overlappedEventDescription.length > 5) {
        console.log(clc.magenta('Duplicate event removed [' + overlappedEventDescription.length + ']: ' + event1.url));
        console.log(clc.magenta('Info: Duplicate event added: ' + event2.url));
        console.log(clc.magenta('Info: Duplicate event overlaps: ' + overlappedEventDescription));
        console.log(clc.magenta('-----------'))
        return true;
      }
    }

    return false;
  }

  function afterToday(evt) {
    return moment(evt.formatted_time, config.displayTimeformat) > moment();
  }

  function timeComparer(a, b) {
    return (moment(a.start_time).valueOf() -
            moment(b.start_time).valueOf());
  }

  function addEvents(type) {
    API[ 'get' + type + 'Events' ]().then(function(data) {
      data = data || [];
      var whiteEvents = data.filter(function(evt) {
        return !blacklistEvents.some(function(blackEvent) {
          return blackEvent.id.toString() === evt.id.toString();
        });
      });

      var beforeNum = eventsResult.events.length
      eventsResult.events = eventsResult.events.concat(whiteEvents);
      eventsResult.events = eventsResult.events.filter(afterToday);

      eventsResult.events.sort(timeComparer);
      eventsResult.events = removeDuplicates(eventsResult.events);
      eventsResult.meta.total_events = eventsResult.events.length;

      var afterNum = eventsResult.events.length
      logger.info(clc.green('Success: Added ' + (afterNum - beforeNum) + ' ' + type + ' events'));

      eventsToday.events = getCurrentDayData(eventsResult);
      eventsToday.meta.generated_at = eventsResult.meta.generated_at;
      eventsToday.meta.location = eventsResult.meta.location;
      eventsToday.meta.api_version = eventsResult.meta.api_version;
      eventsToday.meta.total_events = eventsToday.events.length;

      eventsHour.events = getCurrentHourData(eventsResult);
      eventsHour.meta.generated_at = eventsResult.meta.generated_at;
      eventsHour.meta.location = eventsResult.meta.location;
      eventsHour.meta.api_version = eventsResult.meta.api_version;
      eventsHour.meta.total_events = eventsToday.events.length;
    }).catch(function(err) {
      logger.error('Failed to add ' + type + ' events: HTTP Status Code ' + err.statusCode || err);
    });
  }

  function removeDuplicates(feed) {
    var uniqueEvents = [];
    var isDuplicate;

    feed.forEach(function(thisEvent) {
      isDuplicate = uniqueEvents.some(function(thatEvent) {
        return isDuplicateEvent(thisEvent, thatEvent);
      })

      if (!isDuplicate) {
        uniqueEvents.push(thisEvent);
      }
    })

    return uniqueEvents;
  }

  function getCurrentDayData(data) {
    return data.events.filter(function(element) {
      return moment(data.meta.generated_at).diff(moment(element.start_time), 'days') === 0;
    })
  }

  function getCurrentHourData(data) {
    return data.events.filter(function (element) {
      return moment(element.formatted_time, 'DD MMM YYYY, ddd, hh:mm a').isBefore(moment().add(1, 'hour'))
    })
  }

  return {
    feed: eventsResult,
    day: eventsToday,
    hour: eventsHour,
    get: function(count) {
      var answer = {
        meta: {
          'generated_at': new Date().toISOString(),
          'location': config.city,
          'api_version': config.api_version,
          'total_events': parseInt(count)
        },
        events: eventsResult.events.slice(0, parseInt(count))
      }

      return answer
    },
    update: function() {
      eventsResult.meta = {
        'generated_at': new Date().toISOString(),
        'location': config.city,
        'api_version': config.api_version
      }
      eventsResult.events = whitelistEvents.filter(afterToday);
      logger.info('Updating the events feed... this may take a while');
      addEvents('Meetup');
      addEvents('Facebook');
      addEvents('Eventbrite');
      addEvents('Ics');
    }
  }
};
<|endoftext|>


<commit_before>/*
Code for Life

Copyright (C) 2015, Ocado Limited

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/>.

ADDITIONAL TERMS – Section 7 GNU General Public Licence

This licence does not grant any right, title or interest in any “Ocado” logos,
trade names or the trademark “Ocado” or any other trademarks or domain names
owned by Ocado Innovation Limited or the Ocado group of companies or any other
distinctive brand features of “Ocado” as may be secured from time to time. You
must not distribute any modification of this program using the trademark
“Ocado” or claim any affiliation or association with Ocado or its employees.

You are not authorised to use the name Ocado (or any of its trade names) or
the names of any author or contributor in advertising or for publicity purposes
pertaining to the distribution of this program, without the prior written
authorisation of Ocado.

Any propagation, distribution or conveyance of this program must include this
copyright notice and these terms. You must not misrepresent the origins of this
program; modified versions of the program must be marked as such and not
identified as the original program.
*/
var ocargo = ocargo || {};

// Object containing helper js objects (buttons etc).
ocargo.jsElements = {
    image: function(url, class_) {
        return "";
    },
    nextEpisodeButton: function(episode, random){
        return ocargo.button.redirectButtonHtml('next_episode_button', "/rapidrouter/episode/" + episode + "/", 'Next episode') +
          (random ? ocargo.button.redirectButtonHtml('random_level_button', "/rapidrouter/levels/random/" + (episode-1) + "/", 'Random level') : "") +
            ocargo.button.redirectButtonHtml('home_button', "/rapidrouter/", "Home");
    },

    buttonHelpButton: '<button onclick="ocargo.Drawing.showButtonHelp();">Button help</button>'
};

//FIXME: actually use Django's internationalisation framework.
ocargo.messages = {
    nextEpisode: function(episode, random) {
        return "Well done, you've completed the episode!
 Are you ready for the next " +
            "challenge? " + (random ? "Or try one of this episode's random levels!" : "") ;
    },

    anotherRandomLevel: "Do you want to try another random level?",
    loggedOutWarning: "You are not logged in. Your progress won't be saved.",
    nowTryPython: "Looks like you've got a route sorted using Blockly.

" +
        "Now go to the Python tab and see if you can do the same in Python! ",
    lastLevel: "That's all we've got for you right now. Carry on the fun by creating your own challenges.",

    illegalBlocks: "Sorry, this workspace has blocks in it that aren't allowed in this level!",
    tooManyBlocks: "Whoops! You used too many blocks.",
    ohNo: "Oh no!",
    winTitle: "You win!",
    failTitle: "Oh dear! ",
    tryagainLabel: "Try again",
    needHint: "Are you stuck? Do you need help?",
    terminated: "Program terminated!",
    crashed: "Your program crashed!",
    queryInfiniteLoop: "It looks as though your program's been running a while. Check your repeat loops are okay.",
    compilationError: "Your program doesn't look quite right...",
    stoppingTitle: "Stopping...",
    errorTitle: "Error",

    outOfFuel : "You ran out of fuel! Try to find a shorter route to the destination.",
    outOfInstructions: "The van ran out of instructions before it reached a destination."  +
      "Make sure there are enough instructions to complete the delivery.",
    disconnectedStartBlock: "

Make sure your blocks are connected to the Start block.",
    passedDestination: "The van visited the destination, but didn't stop there!",
    throughRedLight: "Uh oh, you just sent the van through a red light! Stick to the Highway " +
        "Code - the van must wait for green.",
    alreadyDelivered: "You have already delivered to that destination! You must only deliver " +
        "once to each destination.",
    undeliveredDestinations: "There are destinations that have not been delivered to. " +
        "Ensure you visit all destinations and use the deliver command at each one.",
    offRoad : function(correctSteps){
        if (correctSteps === 0) {
            return "Your first move was a crash. What went wrong?";
        }
        if (correctSteps === 1) {
            return "Your first move was right. What went wrong after that?";
        }
        else {
            return "Your first " + correctSteps + " moves worked. What went wrong after that?";
        }
    },

    collisionWithCow: "You ran into a cow! Keep in mind that cows can appear anywhere on the map.",

    // Level editor.
    levelEditorTitle: "Welcome to the Level editor! ",
    levelEditorSubtitle: "Click  " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/help.svg', 'popupHelp') +
        "Help for clues on getting started. ",
    noStartOrEndSubtitle: "You forgot to mark the start and end points. ",
    noStartOrEnd: "In " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon') +
        "Map menu, click on  " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/origin.svg', 'popupIcon') +
        "Mark start or " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/destination.svg', 'popupIcon') +
        "Mark end then select the square where you want the road to start or end.",
    somethingWrong: "Something is wrong...",
    noStartEndRouteSubtitle: "There is no way to get from the start to the destination.",
    noStartEndRoute: "Edit your level to allow the driver to get to the end.",
    noBlocksSubtitle: "You haven't selected any blocks to use in your level.",
    noBlocks: "Go to " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/blockly.svg', 'popupIcon') +
        "Code and select some to use. Remember to include the move and turn commands!",
    levelEditorPCSubtitle: "To get started, draw a road.

 Click on the square you want " +
        "the road to start from. Then, without letting go of the mouse button, drag to the " +
        "square you’d like the road to end on.
 Do this as many times as you like to add " +
        "new sections of road. ",
    trafficLightsWarning: "You need to complete level 44 before using a traffic light. ",
    levelEditorHelpText: "In " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon') +
        "Map menu, click " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/origin.svg', 'popupIcon') +
        "Mark start and select a square for your road to start from. The starting point " +
        "can only be placed on dead ends.
 Make sure you use " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/destination.svg', 'popupIcon') +
        "Mark end to select a final destination.

 To remove road, click the " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/delete_road.svg', 'popupIcon') +
        "Delete road button and select a section to get rid of.

 Click " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/random.svg', 'popupIcon') +
        "Random if you want the computer to create a random route for you.

 Select " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/decor.svg', 'popupIcon') +
        "Scenery and choose trees, bushes and more to place around your road. These will " +
        "show in the top left corner - drag them into place. Delete items by dragging them into " +
        "the bin in the bottom right.
 To rotate a traffic light, " +
        "simply double click on it. Remember, using the traffic lights is not covered until " +
        "level 44.

 Choose a character to play with from the " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/character.svg', 'popupIcon') +
        "Character menu.

 Select which blocks of code you want to be used to " +
        "create a route for your character from the " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/blockly.svg', 'popupIcon') +
        "Blocks menu.

 Setting a fuel level means the route will need to be short " +
        "enough for the fuel not to run out. When you're ready click " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/play.svg', 'popupIcon') +
        "Play, or " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/save.svg', 'popupIcon') +
        "Save your road or " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/share.svg', 'popupIcon') +
        "Share it with a friend. Don't forget to choose a good name for it!

 " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/quit.svg', 'popupIcon') +
        "Quit will take you back to the Rapid Router homepage.",
    notLoggedIn: function(activity) {
        return "Unfortunately you need to be logged in to " + activity +
            " levels. You can log on here.";
    },
    independentStudentSharing:  "Sorry but as an independent student you'll need to join a school or club to " +
        "share your levels with others.",
    internetDown: "Could not connect to server. Your internet might not be working properly.",
    notSaved: "Please save your level before continuing!",
    notOwned: "You do not own this level. If you would like to share it you will first have to " +
        "save your own copy! ",
    changesSinceLastSave: "Please save your latest changes! ",
    saveOverwriteWarning: function(newName) {
        return "Level '" + newName + "' already exists. Are you sure you want to overwrite it?";
    },
    shareSuccessful: "Your level has been successfully shared! ",

    // Scoring.
    totalScore: function(score, maxScore) {
        return "Your total score: " + score + "/" + maxScore;
    },

    // End level message
    endLevelMsg: function(a) {
        switch (a){
            case 'pathLonger':
                return this.pathLonger;
                break;
            case 'algorithmLonger':
                return this.algorithmLonger;
                break;
            case 'algorithmShorter':
                return this.algorithmShorter;
                break;
            case 'scorePerfect':
                return this.scorePerfect;
                break;
            default:
                return "";
        }
    },
    addNewLine: function(arr){
        var html = '';
        for(var i = 0 ; i < arr.length ; i++ ){
            html += arr[i] + '
';
        }
        return html;
    },
    pathScore: "Route score: ",
    pathLonger: "Try finding a shorter route to the destination. ",
    algorithmScore: "Algorithm score: ",
    algorithmLonger: "Try creating a simpler program. ",
    algorithmShorter: "That solution isn't quite right. Read the level instructions or click Help.",
    scorePerfect: "Congratulations! You've aced it. ",

    // Malformed program.
    whileConditionError: "Perhaps try looking at your 'repeat' blocks? ",
    whileBodyError: "Perhaps try looking at your 'repeat' blocks? ",
    eventConditionError: "Perhaps try looking at your 'event' blocks? ",
    eventBodyError: "Perhaps try looking at your 'event' blocks? ",
    ifConditionError: "Perhaps try looking at your 'if' blocks? ",
    procMissingNameError: "Perhaps try looking at your 'define' blocks? ",
    procMissingBodyError: "Perhaps try looking at your 'define' blocks? ",
    procDupNameError: "Perhaps try checking the names of your 'define' blocks? ",
    procCallNameError: "Perhaps try checking the names in your 'call' blocks? ",

    pythonCommands: "
Run the following commands on the van object v, e.g. v.move_forwards()
" +
        	"
" +
            "
" +
                  "
Movement" +
                  "
v.move_forwards()" +
                  "
v.turn_left()" +
                  "
v.turn_right()" +
                  "
v.turn_around()" +
                  "
v.wait()
" +
                "
" +
                "
" +
                  "
Position" +
                  "
v.at_dead_end()" +
                  "
v.at_destination()" +
                  "
v.at_red_traffic_light()" +
                  "
v.at_green_traffic_light()" +
                  "
v.at_traffic_light(c)" +
                  "
where c is 'RED' or 'GREEN'
" +
                "
" +
                "
" +
                  "
" +
                  "
v.is_road_forward()" +
                  "
v.is_road_left()" +
                  "
v.is_road_right()" +
                  "
v.is_road(d)" +
                  "
where d is 'FORWARD'," +
                  "
'LEFT', or 'RIGHT'
" +
                "
" +
              "
"
};
<commit_msg>#651 Correcting a typo in game messages. Removing exclamation marks (don't shout at the kids).<commit_after>/*
Code for Life

Copyright (C) 2015, Ocado Limited

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/>.

ADDITIONAL TERMS – Section 7 GNU General Public Licence

This licence does not grant any right, title or interest in any “Ocado” logos,
trade names or the trademark “Ocado” or any other trademarks or domain names
owned by Ocado Innovation Limited or the Ocado group of companies or any other
distinctive brand features of “Ocado” as may be secured from time to time. You
must not distribute any modification of this program using the trademark
“Ocado” or claim any affiliation or association with Ocado or its employees.

You are not authorised to use the name Ocado (or any of its trade names) or
the names of any author or contributor in advertising or for publicity purposes
pertaining to the distribution of this program, without the prior written
authorisation of Ocado.

Any propagation, distribution or conveyance of this program must include this
copyright notice and these terms. You must not misrepresent the origins of this
program; modified versions of the program must be marked as such and not
identified as the original program.
*/
var ocargo = ocargo || {};

// Object containing helper js objects (buttons etc).
ocargo.jsElements = {
    image: function(url, class_) {
        return "";
    },
    nextEpisodeButton: function(episode, random){
        return ocargo.button.redirectButtonHtml('next_episode_button', "/rapidrouter/episode/" + episode + "/", 'Next episode') +
          (random ? ocargo.button.redirectButtonHtml('random_level_button', "/rapidrouter/levels/random/" + (episode-1) + "/", 'Random level') : "") +
            ocargo.button.redirectButtonHtml('home_button', "/rapidrouter/", "Home");
    },

    buttonHelpButton: '<button onclick="ocargo.Drawing.showButtonHelp();">Button help</button>'
};

//FIXME: actually use Django's internationalisation framework.
ocargo.messages = {
    nextEpisode: function(episode, random) {
        return "Well done, you've completed the episode!
 Are you ready for the next " +
            "challenge? " + (random ? "Or try one of this episode's random levels!" : "") ;
    },

    anotherRandomLevel: "Do you want to try another random level?",
    loggedOutWarning: "You are not logged in. Your progress won't be saved.",
    nowTryPython: "Looks like you've got a route sorted using Blockly.

" +
        "Now go to the Python tab and see if you can do the same in Python! ",
    lastLevel: "That's all we've got for you right now. Carry on the fun by creating your own challenges.",

    illegalBlocks: "Sorry, this workspace has blocks in it that aren't allowed in this level!",
    tooManyBlocks: "Whoops. You used too many blocks.",
    ohNo: "Oh no!",
    winTitle: "You win!",
    failTitle: "Oh dear! ",
    tryagainLabel: "Try again",
    needHint: "Are you stuck? Do you need help?",
    terminated: "Program terminated.",
    crashed: "Your program crashed.",
    queryInfiniteLoop: "It looks as though your program's been running a while. Check your repeat loops are okay.",
    compilationError: "Your program doesn't look quite right...",
    stoppingTitle: "Stopping...",
    errorTitle: "Error",

    outOfFuel : "You ran out of fuel! Try to find a shorter route to the destination.",
    outOfInstructions: "The van ran out of instructions before it reached a destination. "  +
      "Make sure there are enough instructions to complete the delivery.",
    disconnectedStartBlock: "

Make sure your blocks are connected to the Start block.",
    passedDestination: "The van visited the destination, but didn't stop there!",
    throughRedLight: "Uh oh, you just sent the van through a red light! Stick to the Highway " +
        "Code - the van must wait for green.",
    alreadyDelivered: "You have already delivered to that destination! You must only deliver " +
        "once to each destination.",
    undeliveredDestinations: "There are destinations that have not been delivered to. " +
        "Ensure you visit all destinations and use the deliver command at each one.",
    offRoad : function(correctSteps){
        if (correctSteps === 0) {
            return "Your first move was a crash. What went wrong?";
        }
        if (correctSteps === 1) {
            return "Your first move was right. What went wrong after that?";
        }
        else {
            return "Your first " + correctSteps + " moves worked. What went wrong after that?";
        }
    },

    collisionWithCow: "You ran into a cow! Keep in mind that cows can appear anywhere on the map.",

    // Level editor.
    levelEditorTitle: "Welcome to the Level editor! ",
    levelEditorSubtitle: "Click  " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/help.svg', 'popupHelp') +
        "Help for clues on getting started. ",
    noStartOrEndSubtitle: "You forgot to mark the start and end points. ",
    noStartOrEnd: "In " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon') +
        "Map menu, click on  " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/origin.svg', 'popupIcon') +
        "Mark start or " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/destination.svg', 'popupIcon') +
        "Mark end then select the square where you want the road to start or end.",
    somethingWrong: "Something is wrong...",
    noStartEndRouteSubtitle: "There is no way to get from the start to the destination.",
    noStartEndRoute: "Edit your level to allow the driver to get to the end.",
    noBlocksSubtitle: "You haven't selected any blocks to use in your level.",
    noBlocks: "Go to " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/blockly.svg', 'popupIcon') +
        "Code and select some to use. Remember to include the move and turn commands!",
    levelEditorPCSubtitle: "To get started, draw a road.

 Click on the square you want " +
        "the road to start from. Then, without letting go of the mouse button, drag to the " +
        "square you’d like the road to end on.
 Do this as many times as you like to add " +
        "new sections of road. ",
    trafficLightsWarning: "You need to complete level 44 before using a traffic light. ",
    levelEditorHelpText: "In " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon') +
        "Map menu, click " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/origin.svg', 'popupIcon') +
        "Mark start and select a square for your road to start from. The starting point " +
        "can only be placed on dead ends.
 Make sure you use " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/destination.svg', 'popupIcon') +
        "Mark end to select a final destination.

 To remove road, click the " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/delete_road.svg', 'popupIcon') +
        "Delete road button and select a section to get rid of.

 Click " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/random.svg', 'popupIcon') +
        "Random if you want the computer to create a random route for you.

 Select " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/decor.svg', 'popupIcon') +
        "Scenery and choose trees, bushes and more to place around your road. These will " +
        "show in the top left corner - drag them into place. Delete items by dragging them into " +
        "the bin in the bottom right.
 To rotate a traffic light, " +
        "simply double click on it. Remember, using the traffic lights is not covered until " +
        "level 44.

 Choose a character to play with from the " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/character.svg', 'popupIcon') +
        "Character menu.

 Select which blocks of code you want to be used to " +
        "create a route for your character from the " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/blockly.svg', 'popupIcon') +
        "Blocks menu.

 Setting a fuel level means the route will need to be short " +
        "enough for the fuel not to run out. When you're ready click " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/play.svg', 'popupIcon') +
        "Play, or " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/save.svg', 'popupIcon') +
        "Save your road or " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/share.svg', 'popupIcon') +
        "Share it with a friend. Don't forget to choose a good name for it!

 " +
        ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/quit.svg', 'popupIcon') +
        "Quit will take you back to the Rapid Router homepage.",
    notLoggedIn: function(activity) {
        return "Unfortunately you need to be logged in to " + activity +
            " levels. You can log on here.";
    },
    independentStudentSharing:  "Sorry but as an independent student you'll need to join a school or club to " +
        "share your levels with others.",
    internetDown: "Could not connect to server. Your internet might not be working properly.",
    notSaved: "Please save your level before continuing!",
    notOwned: "You do not own this level. If you would like to share it you will first have to " +
        "save your own copy! ",
    changesSinceLastSave: "Please save your latest changes! ",
    saveOverwriteWarning: function(newName) {
        return "Level '" + newName + "' already exists. Are you sure you want to overwrite it?";
    },
    shareSuccessful: "Your level has been successfully shared! ",

    // Scoring.
    totalScore: function(score, maxScore) {
        return "Your total score: " + score + "/" + maxScore;
    },

    // End level message
    endLevelMsg: function(a) {
        switch (a){
            case 'pathLonger':
                return this.pathLonger;
                break;
            case 'algorithmLonger':
                return this.algorithmLonger;
                break;
            case 'algorithmShorter':
                return this.algorithmShorter;
                break;
            case 'scorePerfect':
                return this.scorePerfect;
                break;
            default:
                return "";
        }
    },
    addNewLine: function(arr){
        var html = '';
        for(var i = 0 ; i < arr.length ; i++ ){
            html += arr[i] + '
';
        }
        return html;
    },
    pathScore: "Route score: ",
    pathLonger: "Try finding a shorter route to the destination. ",
    algorithmScore: "Algorithm score: ",
    algorithmLonger: "Try creating a simpler program. ",
    algorithmShorter: "That solution isn't quite right. Read the level instructions or click Help.",
    scorePerfect: "Congratulations! You've aced it. ",

    // Malformed program.
    whileConditionError: "Perhaps try looking at your 'repeat' blocks? ",
    whileBodyError: "Perhaps try looking at your 'repeat' blocks? ",
    eventConditionError: "Perhaps try looking at your 'event' blocks? ",
    eventBodyError: "Perhaps try looking at your 'event' blocks? ",
    ifConditionError: "Perhaps try looking at your 'if' blocks? ",
    procMissingNameError: "Perhaps try looking at your 'define' blocks? ",
    procMissingBodyError: "Perhaps try looking at your 'define' blocks? ",
    procDupNameError: "Perhaps try checking the names of your 'define' blocks? ",
    procCallNameError: "Perhaps try checking the names in your 'call' blocks? ",

    pythonCommands: "
Run the following commands on the van object v, e.g. v.move_forwards()
" +
        	"
" +
            "
" +
                  "
Movement" +
                  "
v.move_forwards()" +
                  "
v.turn_left()" +
                  "
v.turn_right()" +
                  "
v.turn_around()" +
                  "
v.wait()
" +
                "
" +
                "
" +
                  "
Position" +
                  "
v.at_dead_end()" +
                  "
v.at_destination()" +
                  "
v.at_red_traffic_light()" +
                  "
v.at_green_traffic_light()" +
                  "
v.at_traffic_light(c)" +
                  "
where c is 'RED' or 'GREEN'
" +
                "
" +
                "
" +
                  "
" +
                  "
v.is_road_forward()" +
                  "
v.is_road_left()" +
                  "
v.is_road_right()" +
                  "
v.is_road(d)" +
                  "
where d is 'FORWARD'," +
                  "
'LEFT', or 'RIGHT'
" +
                "
" +
              "
"
};
<|endoftext|>


<commit_before>/**
 * editor_plugin_src.js
 *
 * Copyright 2010, Ephox * Released under TODO
 *
 * License: TODO
 */

(function() {
	tinymce.create('tinymce.plugins.AutolinkPlugin', {
		/**
		 * Initializes the plugin, this will be executed after the plugin has been created.
		 * This call is done before the editor instance has finished it's initialization so use the onInit event
		 * of the editor instance to intercept that event.
		 *
		 * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
		 * @param {string} url Absolute URL to where the plugin is located.
		 */

		init : function(ed, url) {
			// Add a node change handler
			ed.onKeyUp.add(function(ed, e) {
                switch(e.keyCode) {
                    case 13: // \n character
/*
                        var a = ed.selection.getNode();
                        var b = a.previousSibling;
                        ed.selection.select(b);
                        ed.selection.collapse(true);
                        var r = ed.selection.getRng();
*/

                    case 32:  // space character
                        var end = start = ed.selection.getRng().endOffset -1;
                        var endContainer = ed.selection.getRng().endContainer;
                        do
                        {
                            var r = ed.dom.createRng();
                            r.setStart(endContainer, end - 2);
                            r.setEnd(endContainer, end - 1);
                            ed.selection.setRng(r);
                            end -= 1;
                        } while (ed.selection.getContent({format : 'text'}) != ' ' &&
                                 ed.selection.getContent({format : 'text'}) != '' && (ed.selection.getRng().startOffset -1) >= 0)

                        if (ed.selection.getRng().startOffset == 0) {
                            var r = ed.dom.createRng();
                            r.setStart(endContainer, 0)
                            r.setEnd(endContainer, start);
                            ed.selection.setRng(r);
                        }
                        else {
                            var r = ed.dom.createRng();
                            r.setStart(endContainer, end);
                            r.setEnd(endContainer, start);
                            ed.selection.setRng(r);
                        }

                        break;

                    default:
                        return;
                }

                var text = ed.selection.getContent({format : 'text'});
                var matches = text.match(/^(https?:\/\/|ftp:\/\/|file:\/|www\.)(.+)$/i);
                if (matches)
                    tinyMCE.execCommand('mceInsertLink',false, matches[1] + matches[2]);

                // collapse the selection, moving caret to end of selection
                ed.selection.collapse(false);
                ed.selection.select(ed.selection.getNode().nextSibling);
                ed.selection.collapse(true);
                tinyMCE.execCommand('mceInsertContent',false, ' ');
            });
		},

		/**
		 * Creates control instances based in the incomming name. This method is normally not
		 * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons
		 * but you sometimes need to create more complex controls like listboxes, split buttons etc then this
		 * method can be used to create those.
		 *
		 * @param {String} n Name of the control to create.
		 * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.
		 * @return {tinymce.ui.Control} New control instance or null if no control was created.
		 */
		createControl : function(n, cm) {
			return null;
		},

		/**
		 * Returns information about the plugin as a name/value array.
		 * The current keys are longname, author, authorurl, infourl and version.
		 *
		 * @return {Object} Name/value array containing information about the plugin.
		 */
		getInfo : function() {
			return {
				longname : 'Autolink plugin',
				author : 'Ephox - Yonas Yanfa',
				authorurl : 'http://www.ephox.com',
				infourl : 'http://www.ephox.com',
				version : "1.0"
			};
		}
	});

	// Register plugin
	tinymce.PluginManager.add('autolink', tinymce.plugins.AutolinkPlugin);
})();<commit_msg>Remove detection for pressing the enter key.<commit_after>/**
 * editor_plugin_src.js
 *
 * Copyright 2010, Ephox * Released under TODO
 *
 * License: TODO
 */

(function() {
	tinymce.create('tinymce.plugins.AutolinkPlugin', {
		/**
		 * Initializes the plugin, this will be executed after the plugin has been created.
		 * This call is done before the editor instance has finished it's initialization so use the onInit event
		 * of the editor instance to intercept that event.
		 *
		 * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
		 * @param {string} url Absolute URL to where the plugin is located.
		 */

		init : function(ed, url) {
			// Add a node change handler
			ed.onKeyUp.add(function(ed, e) {
                switch(e.keyCode) {
                    case 32:  // space character
                        var end = start = ed.selection.getRng().endOffset -1;
                        var endContainer = ed.selection.getRng().endContainer;
                        break;

                    default:
                        return;
                }

                do
                {
                    var r = ed.dom.createRng();
                    r.setStart(endContainer, end - 2);
                    r.setEnd(endContainer, end - 1);
                    ed.selection.setRng(r);
                    end -= 1;
                } while (ed.selection.getContent({format : 'text'}) != ' ' &&
                        ed.selection.getContent({format : 'text'}) != '' && (ed.selection.getRng().startOffset -1) >= 0)

                if (ed.selection.getRng().startOffset == 0) {
                    var r = ed.dom.createRng();
                    r.setStart(endContainer, 0)
                        r.setEnd(endContainer, start);
                    ed.selection.setRng(r);
                }
                else {
                    var r = ed.dom.createRng();
                    r.setStart(endContainer, end);
                    r.setEnd(endContainer, start);
                    ed.selection.setRng(r);
                }

                var text = ed.selection.getContent({format : 'text'});
                var matches = text.match(/^(https?:\/\/|ftp:\/\/|file:\/|www\.)(.+)$/i);
                if (matches)
                    tinyMCE.execCommand('mceInsertLink',false, matches[1] + matches[2]);

                // collapse the selection, moving caret to end of selection
                ed.selection.collapse(false);
                ed.selection.select(ed.selection.getNode().nextSibling);
                ed.selection.collapse(true);
                tinyMCE.execCommand('mceInsertContent',false, ' ');
            });
		},

		/**
		 * Creates control instances based in the incomming name. This method is normally not
		 * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons
		 * but you sometimes need to create more complex controls like listboxes, split buttons etc then this
		 * method can be used to create those.
		 *
		 * @param {String} n Name of the control to create.
		 * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.
		 * @return {tinymce.ui.Control} New control instance or null if no control was created.
		 */
		createControl : function(n, cm) {
			return null;
		},

		/**
		 * Returns information about the plugin as a name/value array.
		 * The current keys are longname, author, authorurl, infourl and version.
		 *
		 * @return {Object} Name/value array containing information about the plugin.
		 */
		getInfo : function() {
			return {
				longname : 'Autolink plugin',
				author : 'Ephox - Yonas Yanfa',
				authorurl : 'http://www.ephox.com',
				infourl : 'http://www.ephox.com',
				version : "1.0"
			};
		}
	});

	// Register plugin
	tinymce.PluginManager.add('autolink', tinymce.plugins.AutolinkPlugin);
})();<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react/lib/ReactTestUtils';
import expect from 'expect';
import {spy, stub} from 'sinon';
import { shallow, mount, render } from 'enzyme';
import DocumentPage from '../Document-page.jsx';
import DocumentActions from '../../../actions/DocumentActions';

describe('<DocumentPage />', () => {
  let wrapper;
  beforeEach(() => {
    wrapper = mount(<DocumentPage params={{id:21}} />);
  });

  afterEach(() => {
    wrapper.unmount();
  });
  it('expects component to render', ()  => {
    let doc = {
      ownerId: {
        _id: 23
      }
    };
    expect(wrapper).toExist();
  });

  it('Test handleRequestClose', () => {
    const instance = wrapper.instance();
    spy(instance, 'handleRequestClose');
    instance.handleRequestClose();
    expect(wrapper.state().snackopen).toBe(false);
    instance.handleRequestClose.restore();
    wrapper.unmount();
  });

  it('Test handleOpen', () => {
    const instance = wrapper.instance();
    spy(instance, 'handleOpen');
    instance.handleOpen();
    expect(wrapper.state().open).toBe(true);
    instance.handleOpen.restore();
  });

  it('Test handleClose', () => {
    const instance = wrapper.instance();
    spy(instance, 'handleClose');
    instance.handleClose();
    expect(wrapper.state().open).toBe(false);
    instance.handleClose.restore();
  });

  it('Test onSession - valid', () => {
    stub(DocumentActions, 'getDocument').returns(true);
    spy(DocumentActions, 'getDocumentSuccess');
    const instance = wrapper.instance();
    spy(instance, 'onSession');
    let state = {
      user: {
        role: {
          title: 'admin'
        }
      },
      error: null
    }
    instance.onSession(state);
    expect(wrapper.state().open).toBe(false);
    expect(DocumentActions.getDocument.called).toBe(true);
    instance.onSession.restore();
    DocumentActions.getDocument.restore();
    DocumentActions.getDocumentSuccess.restore();
  });

  it('Test onSession - invalid', () => {
    stub(DocumentActions, 'getDocument').returns(true);
    const instance = wrapper.instance();
    spy(instance, 'onSession');
    let state = {
      user: null,
      error: 'error'
    }
    instance.onSession(state);
    expect(wrapper.state().open).toBe(false);
    instance.onSession.restore();
    expect(DocumentActions.getDocument.called).toBe(true);
    DocumentActions.getDocument.restore();
  });

  it('Test handleDelete', () => {
    stub(DocumentActions, 'deleteDocument').returns(true);
    const instance = wrapper.instance();
    spy(instance, 'handleDelete');
    let state = {
      user: null,
      error: 'error'
    }
    instance.handleDelete(state);
    expect(wrapper.state().open).toBe(false);
    instance.handleDelete.restore();
    expect(DocumentActions.deleteDocument.called).toBe(true);
    expect(wrapper.state('snackopen')).toBe(true);
    DocumentActions.deleteDocument.restore();
  });

});
<commit_msg>Add more tests<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react/lib/ReactTestUtils';
import expect from 'expect';
import {spy, stub} from 'sinon';
import { shallow, mount, render } from 'enzyme';
import DocumentPage from '../Document-page.jsx';
import DocumentActions from '../../../actions/DocumentActions';
import { browserHistory } from 'react-router';

describe('<DocumentPage />', () => {
  let wrapper;
  let instance;
  beforeEach(() => {
    stub(localStorage, 'getItem').returns(true);
    wrapper = mount(<DocumentPage params={{id:21}} />);
    instance = wrapper.instance();
  });

  afterEach(() => {
    localStorage.getItem.restore();
    wrapper.unmount();
  });
  it('expects component to render', ()  => {
    let doc = {
      ownerId: {
        _id: 23
      }
    };
    expect(wrapper).toExist();
  });

  it('Test handleRequestClose', () => {
    spy(instance, 'handleRequestClose');
    instance.handleRequestClose();
    expect(wrapper.state().snackopen).toBe(false);
    instance.handleRequestClose.restore();
  });

  it('Test handleOpen', () => {
    spy(instance, 'handleOpen');
    instance.handleOpen();
    expect(wrapper.state().open).toBe(true);
    instance.handleOpen.restore();
  });

  it('Test handleClose', () => {
    spy(instance, 'handleClose');
    instance.handleClose();
    expect(wrapper.state().open).toBe(false);
    instance.handleClose.restore();
  });

  it('Test onSession - valid', () => {
    stub(DocumentActions, 'getDocument').returns(true);
    spy(DocumentActions, 'getDocumentSuccess');
    spy(instance, 'onSession');
    let state = {
      user: {
        role: {
          title: 'admin'
        }
      },
      error: null
    }
    instance.onSession(state);
    expect(wrapper.state().open).toBe(false);
    expect(DocumentActions.getDocument.called).toBe(true);
    instance.onSession.restore();
    DocumentActions.getDocument.restore();
    DocumentActions.getDocumentSuccess.restore();
  });

  it('Test onSession - invalid', () => {
    stub(DocumentActions, 'getDocument').returns(true);
    spy(instance, 'onSession');
    let state = {
      user: null,
      error: 'error'
    }
    instance.onSession(state);
    expect(wrapper.state().open).toBe(false);
    instance.onSession.restore();
    expect(DocumentActions.getDocument.called).toBe(true);
    DocumentActions.getDocument.restore();
  });

  it('Test handleDelete', () => {
    stub(DocumentActions, 'deleteDocument').returns(true);
    spy(instance, 'handleDelete');
    let state = {
      user: null,
      error: 'error'
    }
    instance.handleDelete(state);
    expect(wrapper.state().open).toBe(false);
    instance.handleDelete.restore();
    expect(DocumentActions.deleteDocument.called).toBe(true);
    expect(wrapper.state('snackopen')).toBe(true);
    DocumentActions.deleteDocument.restore();
  });

  it('Test onChange - success', () => {
    stub(browserHistory, 'push').returns(true);
    spy(instance, 'onChange');
    let state = {
      user: null,
      message: 'delete successfuly'
    }
    instance.onChange(state);
    expect(browserHistory.push.called).toBe(true);
    instance.onChange.restore();
    browserHistory.push.restore();
  });

  it('Test onChange -- error', () => {
    spy(instance, 'onChange');
    let state = {
      doc: {
        data: {
          _id: 32,
          ownerId: {
            _id: 1,
            name: {first: 'kodk', last: 'jdjsnj'}
          },
          category: {_id: 31, category: 'dbj'}
        }
      }
    }
    instance.onChange(state);
    expect(wrapper.state('docId')).toBe(32);
    instance.onChange.restore();
  });

  it('expects component to render without token', ()  => {
    wrapper.unmount();
    localStorage.getItem.restore();
    stub(localStorage, 'getItem').returns(false);
    wrapper = mount(<DocumentPage params={{id:21}} />);
    let doc = {
      ownerId: {
        _id: 23
      }
    };
    expect(wrapper).toExist();
  });

});
<|endoftext|>


<commit_before>// @flow
const React = require("react");
const { DOM: dom, PropTypes } = React;
const ImPropTypes = require("react-immutable-proptypes");
const { bindActionCreators } = require("redux");
const { connect } = require("react-redux");
const { formatKeyShortcut } = require("../utils/text");
const SourcesTree = React.createFactory(require("./SourcesTree"));
const actions = require("../actions");
const { getSelectedSource, getSources } = require("../selectors");

require("./Sources.css");

const Sources = React.createClass({
  propTypes: {
    sources: ImPropTypes.map.isRequired,
    selectSource: PropTypes.func.isRequired,
    horizontal: PropTypes.bool.isRequired,
    toggleFileSearch: PropTypes.func.isRequired
  },

  displayName: "Sources",

  renderShortcut() {
    if (this.props.horizontal) {
      return dom.span(
        {
          className: "sources-header-info",
          dir: "ltr",
          onClick: () => this.props.toggleFileSearch()
        },
        L10N.getFormatStr("sources.search",
          formatKeyShortcut(`CmdOrCtrl+${L10N.getStr("sources.search.key")}`))
      );
    }
  },

  render() {
    const { sources, selectSource } = this.props;

    return dom.div(
      { className: "sources-panel" },
      dom.div({ className: "sources-header" },
        this.renderShortcut()
      ),
      SourcesTree({ sources, selectSource })
    );
  }
});

module.exports = connect(
  state => ({ selectedSource: getSelectedSource(state),
    sources: getSources(state) }),
  dispatch => bindActionCreators(actions, dispatch)
)(Sources);
<commit_msg>refactor Sources.js to es6 class<commit_after>// @flow
const React = require("react");
const {DOM: dom, PropTypes, Component} = React;
const ImPropTypes = require("react-immutable-proptypes");
const {bindActionCreators} = require("redux");
const {connect} = require("react-redux");
const {formatKeyShortcut} = require("../utils/text");
const SourcesTree = React.createFactory(require("./SourcesTree"));
const actions = require("../actions");
const {getSelectedSource, getSources} = require("../selectors");

require("./Sources.css");

class Sources extends Component {

  renderShortcut() {
    if (this.props.horizontal) {
      return dom.span(
        {
          className: "sources-header-info",
          dir: "ltr",
          onClick: () => this.props.toggleFileSearch()
        },
        L10N.getFormatStr("sources.search",
          formatKeyShortcut(`CmdOrCtrl+${L10N.getStr("sources.search.key")}`))
      );
    }
  }

  render() {
    const {sources, selectSource} = this.props;

    return dom.div(
      {className: "sources-panel"},
      dom.div({className: "sources-header"},
        this.renderShortcut()
      ),
      SourcesTree({sources, selectSource})
    );
  }
}

Sources.propTypes = {
  sources: ImPropTypes.map.isRequired,
  selectSource: PropTypes.func.isRequired,
  horizontal: PropTypes.bool.isRequired,
  toggleFileSearch: PropTypes.func.isRequired
};

Sources.displayName = "Sources";

module.exports = connect(
  state => ({
    selectedSource: getSelectedSource(state),
    sources: getSources(state)
  }),
  dispatch => bindActionCreators(actions, dispatch)
)(Sources);
<|endoftext|>


<commit_before>/*
---

name: View

description: Provides an element on the screen and the interfaces for managing
             the content in that area.

license: MIT-style license.

authors:
	- Jean-Philippe Dery (jeanphilippe.dery@gmail.com)

requires:
	- Core

provides:
	- View

...
*/

Moobile.View = new Class({

	Extends: UI.Element,

	window: null,

	parentView: null,

	wrapper: null,

	childViews: [],

	childElements: [],

	childControls: [],

	scroller: null,

	options: {
		title: 'View',
		className: 'view',
		scrollable: true,
		wrappable: true
	},

	setup: function() {
		if (this.options.wrappable) this.injectWrapper();
		if (this.options.scrollable) this.injectScroller();
		this.attachChildElements();
		this.attachChildControls();
		return this.parent();
	},

	destroy: function() {
		this.destroyChildViews();
		this.destroyChildElements();
		this.destroyChildControls();
		if (this.options.wrappable) this.destroyWrapper();
		if (this.options.scrollable) this.destroyScroller();
		this.parent();
		return this;
	},

	attachEvents: function() {
  		return this;
	},

	detachEvents: function() {
		return this;
	},

	destroyChildViews: function() {
		this.childViews.each(function(view) { view.destroy(); });
		this.childViews = null;
		this.childViews = [];
	},

	destroyChildElements: function() {
		this.childElements.each(function(element) { element.destroy(); });
		this.childElements = null;
		this.childElements = [];
	},

	destroyChildControls: function() {
		this.childControls.each(function(control) { control.destroy(); });
		this.childControls = null;
		this.childControls = [];
	},

	injectScroller: function() {
		this.scroller = new Moobile.Scroller(this.element);
		this.scroller.setup();
		this.wrapper = this.element.getElement('div.' + this.options.className + '-wrapper');
		return this;
	},

	destroyScroller: function() {
		this.scroller.destroy();
		this.scroller = null;
		return this;
	},

	enableScroller: function() {
		if (this.scroller) this.scroller.enable();
		return this;
	},

	disableScroller: function() {
		if (this.scroller) this.scroller.disable();
		return this;
	},

	updateScroller: function() {
		if (this.scroller) this.scroller.refresh();
		return this;
	},

	injectWrapper: function() {
		var content = this.getContent();
		var element = new Element('div.' + this.options.className + '-wrapper').set('html', content.get('html'));
		content.empty();
		content.adopt(element);
		this.wrapper = element;
		return this;
	},

	destroyWrapper: function() {
		this.wrapper.destroy();
		this.wrapper = null;
		return this;
	},

	addChildView: function(view) {
		this.childViews.push(view);
		view.setParentView(this);
		view.setWindow(this.window);
		this.adopt(view);
		return this;
	},

	removeChildViews: function() {
		this.childViews.each(this.removeChildView.bind(this));
		this.childViews = null;
		this.childViews = [];
		return this;
	},

	removeChildView: function(view) {
		var removed = this.childViews.remove(view);
		if (removed) view.dispose();
		return this;
	},

	removeFromParentView: function() {
		var parent = this.parentView || this.window;
		if (parent) parent.removeChildView(this);
		return this;
	},

	attachChildControls: function() {
		this.element.getElements('[data-role=control]').each(this.attachChildControl.bind(this));
		return this;
	},

	attachChildControl: function(element) {
		var control = Class.from(element.getProperty('data-control') || 'UI.Control', element);
		var name = element.getProperty('data-name');
		if (name) {
			control.name = name;
			control.member = control.name.camelize();
			if (this[control.member] == null || this[control.member] == undefined) {
				this[control.member] = control;
			}
		}
		this.childControls.push(control);
		return this;
	},

	detachChildControls: function() {
		this.childControls = null;
		this.childControls = [];
		return this;
	},

	detachChildControl: function(control) {
		this.childControls.remove(control);
		return this;
	},

	addChildControl: function(control) {
		this.attachChildControl(control);
		this.adopt(control);
		return this;
	},

	getChildControl: function(name) {
		return this.childControls.find(function(control) { return control.name == name; });
	},

	removeChildControls: function() {
		this.childControls.each(this.removeChildElement.bind(this));
		this.childControls = null;
		this.childControls = [];
		return this;
	},

	removeChildControl: function(control) {
		var removed = this.childControls.remove(control);
		if (removed) control.dispose();
		return this;
	},

	attachChildElements: function() {
		this.element.getElements('[data-role=element]').each(this.attachChildElement.bind(this));
		return this;
	},

	attachChildElement: function(element) {
		this.childElements.push(element);
		return this;
	},

	detachChildElements: function() {
		this.childElements = null;
		this.childElements = [];
		return this;
	},

	detachChildElement: function(element) {
		this.childElements.remove(element);
		return this;
	},

	addChildElement: function(element) {
		this.attachChildElement(element);
		this.adopt(element);
		return this;
	},

	getChildElement: function(name) {
		return this.childElements.find(function(element) { return element.getProperty('data-name') == name; });
	},

	removeChildElements: function() {
		this.childElements.each(this.removeChildElement.bind(this));
		this.childElements = null;
		this.childElements = [];
		return this;
	},

	removeChildElement: function(element) {
		var removed = this.childElements.remove(element);
		if (removed) element.dispose();
		return this;
	},

	adopt: function() {
		var content = this.getContent();
		var where = arguments[arguments.lenght - 1];
		if (typeof where == 'string') {
			if (where == 'element') content = this.element;
			if (where == 'wrapper') content = this.wrapper;
			Array.prototype.pop.call(arguments);
		}
		content.adopt.apply(content, arguments);
		return this;
	},

	setWindow: function(window) {
		this.window = window;
		return this;
	},

	getWindow: function() {
		return this.window;
	},

	setParentView: function(parentView) {
		this.parentView = parentView;
		return this;
	},

	getParentView: function() {
		return this.parentView;
	},

	getTitle: function() {
		return this.element.getProperty('data-title') || this.options.title;
	},

	getContent: function() {
		return this.wrapper || this.element;
	}

});<commit_msg>Added missings 'return this;'.<commit_after>/*
---

name: View

description: Provides an element on the screen and the interfaces for managing
             the content in that area.

license: MIT-style license.

authors:
	- Jean-Philippe Dery (jeanphilippe.dery@gmail.com)

requires:
	- Core

provides:
	- View

...
*/

Moobile.View = new Class({

	Extends: UI.Element,

	window: null,

	parentView: null,

	wrapper: null,

	childViews: [],

	childElements: [],

	childControls: [],

	scroller: null,

	options: {
		title: 'View',
		className: 'view',
		scrollable: true,
		wrappable: true
	},

	setup: function() {
		if (this.options.wrappable) this.injectWrapper();
		if (this.options.scrollable) this.injectScroller();
		this.attachChildElements();
		this.attachChildControls();
		return this.parent();
	},

	destroy: function() {
		this.destroyChildViews();
		this.destroyChildElements();
		this.destroyChildControls();
		if (this.options.wrappable) this.destroyWrapper();
		if (this.options.scrollable) this.destroyScroller();
		this.parent();
		return this;
	},

	attachEvents: function() {
  		return this;
	},

	detachEvents: function() {
		return this;
	},

	destroyChildViews: function() {
		this.childViews.each(function(view) { view.destroy(); });
		this.childViews = null;
		this.childViews = [];
		return this;
	},

	destroyChildElements: function() {
		this.childElements.each(function(element) { element.destroy(); });
		this.childElements = null;
		this.childElements = [];
		return this;
	},

	destroyChildControls: function() {
		this.childControls.each(function(control) { control.destroy(); });
		this.childControls = null;
		this.childControls = [];
		return this;
	},

	injectScroller: function() {
		this.scroller = new Moobile.Scroller(this.element);
		this.scroller.setup();
		this.wrapper = this.element.getElement('div.' + this.options.className + '-wrapper');
		return this;
	},

	destroyScroller: function() {
		this.scroller.destroy();
		this.scroller = null;
		return this;
	},

	enableScroller: function() {
		if (this.scroller) this.scroller.enable();
		return this;
	},

	disableScroller: function() {
		if (this.scroller) this.scroller.disable();
		return this;
	},

	updateScroller: function() {
		if (this.scroller) this.scroller.refresh();
		return this;
	},

	injectWrapper: function() {
		var content = this.getContent();
		var element = new Element('div.' + this.options.className + '-wrapper').set('html', content.get('html'));
		content.empty();
		content.adopt(element);
		this.wrapper = element;
		return this;
	},

	destroyWrapper: function() {
		this.wrapper.destroy();
		this.wrapper = null;
		return this;
	},

	addChildView: function(view) {
		this.childViews.push(view);
		view.setParentView(this);
		view.setWindow(this.window);
		this.adopt(view);
		return this;
	},

	removeChildViews: function() {
		this.childViews.each(this.removeChildView.bind(this));
		this.childViews = null;
		this.childViews = [];
		return this;
	},

	removeChildView: function(view) {
		var removed = this.childViews.remove(view);
		if (removed) view.dispose();
		return this;
	},

	removeFromParentView: function() {
		var parent = this.parentView || this.window;
		if (parent) parent.removeChildView(this);
		return this;
	},

	attachChildControls: function() {
		this.element.getElements('[data-role=control]').each(this.attachChildControl.bind(this));
		return this;
	},

	attachChildControl: function(element) {
		var control = Class.from(element.getProperty('data-control') || 'UI.Control', element);
		var name = element.getProperty('data-name');
		if (name) {
			control.name = name;
			control.member = control.name.camelize();
			if (this[control.member] == null || this[control.member] == undefined) {
				this[control.member] = control;
			}
		}
		this.childControls.push(control);
		return this;
	},

	detachChildControls: function() {
		this.childControls = null;
		this.childControls = [];
		return this;
	},

	detachChildControl: function(control) {
		this.childControls.remove(control);
		return this;
	},

	addChildControl: function(control) {
		this.attachChildControl(control);
		this.adopt(control);
		return this;
	},

	getChildControl: function(name) {
		return this.childControls.find(function(control) { return control.name == name; });
	},

	removeChildControls: function() {
		this.childControls.each(this.removeChildElement.bind(this));
		this.childControls = null;
		this.childControls = [];
		return this;
	},

	removeChildControl: function(control) {
		var removed = this.childControls.remove(control);
		if (removed) control.dispose();
		return this;
	},

	attachChildElements: function() {
		this.element.getElements('[data-role=element]').each(this.attachChildElement.bind(this));
		return this;
	},

	attachChildElement: function(element) {
		this.childElements.push(element);
		return this;
	},

	detachChildElements: function() {
		this.childElements = null;
		this.childElements = [];
		return this;
	},

	detachChildElement: function(element) {
		this.childElements.remove(element);
		return this;
	},

	addChildElement: function(element) {
		this.attachChildElement(element);
		this.adopt(element);
		return this;
	},

	getChildElement: function(name) {
		return this.childElements.find(function(element) { return element.getProperty('data-name') == name; });
	},

	removeChildElements: function() {
		this.childElements.each(this.removeChildElement.bind(this));
		this.childElements = null;
		this.childElements = [];
		return this;
	},

	removeChildElement: function(element) {
		var removed = this.childElements.remove(element);
		if (removed) element.dispose();
		return this;
	},

	adopt: function() {
		var content = this.getContent();
		var where = arguments[arguments.lenght - 1];
		if (typeof where == 'string') {
			if (where == 'element') content = this.element;
			if (where == 'wrapper') content = this.wrapper;
			Array.prototype.pop.call(arguments);
		}
		content.adopt.apply(content, arguments);
		return this;
	},

	setWindow: function(window) {
		this.window = window;
		return this;
	},

	getWindow: function() {
		return this.window;
	},

	setParentView: function(parentView) {
		this.parentView = parentView;
		return this;
	},

	getParentView: function() {
		return this.parentView;
	},

	getTitle: function() {
		return this.element.getProperty('data-title') || this.options.title;
	},

	getContent: function() {
		return this.wrapper || this.element;
	}

});<|endoftext|>


<commit_before>[
{"id":"layer_new","title":"Nije laach"},
{"id":"layer_delete","title":"Laach fuortsmite"},
{"id":"layer_rename","title":"Laach omneame"},
{"id":"layer_up","title":"Laach omheech bringe"},
{"id":"layer_down","title":"Laach omleech bringe"},
{"id":"tool_clear","title":"Nije ™fbielding"},
{"id":"tool_open","title":"ïfbielding iepenje"},
{"id":"tool_save","title":"ïfbielding bewarje"},
{"id":"tool_docprops","title":"Dokuminteigenskippen"},
{"id":"tool_source","title":"Boarne oanpasse"},
{"id":"tool_undo","title":"Ungedien meitjse"},
{"id":"tool_redo","title":"Op 'e nij"},
{"id":"tool_clone","title":"ónderdiel duplisearje"},
{"id":"tool_delete","title":"ónderdiel fuortsmite"},
{"id":"tool_move_top","title":"Nei foargržn"},
{"id":"tool_move_bottom","title":"Nei eftergržn"},
{"id":"group_opacity","title":"Trochsichtigens oanpasse"},
{"id":"angle","title":"Draaie"},
{"id":"tool_clone_multi","title":"ónderdielen duplisearje"},
{"id":"tool_delete_multi","title":"ónderdielen fuortsmite"},
{"id":"tool_alignleft","title":"Lofts œtlijne"},
{"id":"tool_aligncenter","title":"Midden œtlijne"},
{"id":"tool_alignright","title":"Rjochts œtlijne"},
{"id":"tool_aligntop","title":"Boppe œtlijne"},
{"id":"tool_alignmiddle","title":"Midden œtlijne"},
{"id":"tool_alignbottom","title":"ónder œtlijne"},
{"id":"align_relative_to","title":"òtlijne relatyf oan..."},
{"id":"tool_group","title":"ónderdielen groepearje"},
{"id":"tool_ungroup","title":"Groepering opheffe"},
{"id":"rect_width","title":"Breedte rjochthoeke oanpasse"},
{"id":"rect_height","title":"Hichte rjochthoeke oanpasse"},
{"id":"rect_rx","title":"Hoekeradius oanpasse"},
{"id":"image_width","title":"Breedte ™fbielding oanpasse"},
{"id":"image_height","title":"Hichte ™fbielding oanpasse"},
{"id":"image_url","title":"URL oanpasse"},
{"id":"circle_cx" ,"title":"Feroarje it X-košrdinaat fan it middelpunt fan'e sirkel."},
{"id":"circle_cy" ,"title":"Feroarje it Y-košrdinaat fan it middelpunt fan'e sirkel."},
{"id":"circle_r","title":"Feroarje sirkelradius"},
{"id":"ellipse_cx","title":"Feroarje it X-košrdinaat fan it middelpunt fan'e ellips."},
{"id":"ellipse_cy","title":"Feroarje it Y-košrdinaat fan it middelpunt fan'e ellips."},
{"id":"ellipse_rx","title":"Feroarje ellips X radius"},
{"id":"ellipse_ry","title":"Feroarje ellips Y radius"},
{"id":"line_x1","title":"Feroarje start X košrdinaat fan'e line"},
{"id":"line_y1","title":"Feroarje start Y košrdinaat fan'e line"},
{"id":"line_x2","title":"Feroarje ein X košrdinaat fan'e line"},
{"id":"line_y2","title":"Feroarje ein Y košrdinaat fan'e line"},
{"id":"tool_bold","title":"Fet"},
{"id":"tool_italic","title":"Skean"},
{"id":"font_family","title":"Lettertype oanpasse"},
{"id":"font_size","title":"Lettergrutte oanpasse"},
{"id":"text","title":"Tekst oanpasse"},
{"id":"tool_select","title":"Selektearje"},
{"id":"tool_fhpath","title":"Potlead"},
{"id":"tool_line","title":"Line"},
{"id":"tools_rect_show","title":"Fjouwerkant/rjochthoeke"},
{"id":"tools_ellipse_show","title":"Ellips/sirkel"},
{"id":"tool_text","title":"Tekst"},
{"id":"tool_path","title":"Paad"},
{"id":"tool_image","title":"ïfbielding"},
{"id":"tool_zoom","title":"Zoom"},
{"id":"zoom","title":"Yn-/œtzoome"},
{"id":"fill_color","title":"Folkleur oanpasse"},
{"id":"stroke_color","title":"Linekleur oanpasse"},
{"id":"stroke_width","title":"Linebreedte oanpasse"},
{"id":"stroke_style","title":"Linestijl oanpasse"},
{"id":"palette","title":"Klik om de folkleur te feroarjen, shift-klik om de linekleur te feroarjen."},
{"id":"tool_square","title":"Fjouwerkant"},
{"id":"tool_rect","title":"Rjochthoeke"},
{"id":"tool_fhrect","title":"Frije rjochthoeke"},
{"id":"tool_circle","title":"Sirkel"},
{"id":"tool_ellipse","title":"Ellips"},
{"id":"tool_fhellipse","title":"Frije ellips"},
{"id":"bkgnd_color","title":"Eftergržnkleur/trochsichtigens oanpasse"},
{"id":"rwidthLabel","textContent":"Breedte:"},
{"id":"rheightLabel","textContent":"Hichte:"},
{"id":"cornerRadiusLabel","textContent":"Hoekradius:"},
{"id":"iwidthLabel","textContent":"Breedte:"},
{"id":"iheightLabel","textContent":"Hichte:"},
{"id":"svginfo_width","textContent":"Breedte:"},
{"id":"svginfo_height","textContent":"Hichte:"},
{"id":"angleLabel","textContent":"Hoek:"},
{"id":"relativeToLabel","textContent":"Relatief tsjinoer:"},
{"id":"zoomLabel","textContent":"Zoom:"},
{"id":"layersLabel","textContent":"Lagen:"},
{"id":"selectedPredefined","textContent":"Selektearje:"},
{"id":"fitToContent","textContent":"Passe op ynh‰ld"},
{"id":"tool_source_save","textContent":"Feroarings tapasse"},
{"id":"tool_docprops_save","textContent":"Ok"},
{"id":"tool_docprops_cancel","textContent":"ïfbrekke"},
{"id":"tool_source_cancel","textContent":"ïfbrekke"},
{"id":"fit_to_all","textContent":"Op alle ynh‰ld passe"},
{"id":"fit_to_layer_content" ,"textContent":"Op laachynh‰ld passe"},
{"id":"fit_to_sel","textContent":"Op seleksje passe"},
{"id":"fit_to_canvas","textContent":"Op kanvas passe"},
{"id":"selected_objects","textContent":"Selektearre žnderdielen"},
{"id":"largest_object","textContent":"Grutste žnderdiel"},
{"id":"smallest_object","textContent":"Lytste žnderdiel"},
{"id":"page","textContent":"Side"},
{"id":"fill_tool_bottom","textContent":"Kleur:"},
{"id":"stroke_tool_bottom","textContent":"Line:"},
{"id":"path_node_x","title":"X-košrdinaat knooppunt oanpasse"},
{"id":"path_node_y","title":"Y-košrdinaat knooppunt oanpasse"},
{"id":"seg_type","title":"Segmenttype oanpasse"},
{"id":"straight_segments","textContent":"Rjocht"},
{"id":"curve_segments","textContent":"Bžcht"},
{"id":"tool_node_clone","title":"Knooppunt duplisearje"},
{"id":"tool_node_delete","title":"Knooppunt fuortsmite"},
{"id":"selLayerLabel","textContent":"ónderdielen ferplaate nei:"},
{"id":"selLayerNames","title":"Selektearre žnderdielen ferplaatse nei in oare laach"},
{"id":"sidepanel_handle","title":"Sleep nei links/rjochts om it sidepaniel grutter as lytser te meitjen","textContent":"L a g e n"},
{"id":"tool_wireframe","title":"Triemodel"},
{"id":"svginfo_image_props","textContent":"ïfbieldingseigenskippen"},
{"id":"svginfo_title","textContent":"Titel"},
{"id":"svginfo_dim","textContent":"Kanvasgrutte"},
{"id":"includedImages","textContent":"Ynslœten ™fbieldingen"},
{"id":"image_opt_embed","textContent":"Ynformaasje tafoege (lokale triemen)"},
{"id":"image_opt_ref","textContent":"Triemreferensje bržke"},
{"id":"svginfo_editor_prefs","textContent":"Eigenskippen bewurker"},
{"id":"svginfo_lang","textContent":"Taal"},
{"id":"svginfo_change_background","textContent":"Eftergržn bewurker"},
{"id":"svginfo_bg_note","textContent":"Let op: de eftergržn wurd net mei de ™fbielding bewarre."},
{"id":"svginfo_icons","textContent":"Ikoangrutte"},
{"id":"icon_small","textContent":"Lyts"},
{"id":"icon_medium","textContent":"Middel"},
{"id":"icon_large","textContent":"Grut"},
{"id":"icon_xlarge","textContent":"Ekstra grut"},
{"id":"selected_x","title":"X-košrdinaat oanpasse"},
{"id":"selected_y","title":"Y-košrdinaat oanpasse"},
{"id":"tool_topath","title":"Omsette nei paad"},
{"id":"tool_reorient","title":"Paad opnij orientearje"},
{"id":"tool_node_link","title":"Knooppunten keppelje"},
{"js_strings": {
		"invalidAttrValGiven":"Ferkearde waarde jžn",
		"noContentToFitTo":"Gjin ynh‰ld om te passen",
		"layer":"Laach",
		"dupeLayerName":"Der is al in laach mei dy namme!",
		"enterUniqueLayerName":"Type in unyke laachnamme",
		"enterNewLayerName":"Type in nije laachnamme",
		"layerHasThatName":"Laach hat dy namme al",
		"QmoveElemsToLayer":"Selektearre žnderdielen ferplaatse nei '%s'?",
		"QwantToClear":"ïfbielding leechmeitsje? Dit sil ek de skiednis fuortsmite!",
		"QerrorsRevertToSource":"Der wiene flaters yn de SVG-boarne.\nWeromgean nei foarige SVG-boarne?",
		"QignoreSourceChanges":"Feroarings yn SVG-boarne negeare?",
		"featNotSupported":"Funksje wurdt net žndersteund",
		"enterNewImgURL":"Jou de nije URL",
		"ok":"Ok",
		"cancel":"ïfbrekke",
		"pathNodeTooltip":"Fersleepje dit knooppunt as džbelklik om it segmenttype oan te passen.",
		"pathCtrlPtTooltip":"Fersleepje dit knooppunt om de boocheigenskippen oan te passen.",
		"key_up":"omheech",
		"key_down":"omleech",
		"key_backspace":"backspace",
		"key_del":"delete"
	}
}
]
<commit_msg>Update the Frisian language file by Wander Nauta (hopefully with the proper encoding!)<commit_after>[
{"id":"layer_new","title":"Nije laach"},
{"id":"layer_delete","title":"Laach fuortsmite"},
{"id":"layer_rename","title":"Laach omneame"},
{"id":"layer_up","title":"Laach omheech bringe"},
{"id":"layer_down","title":"Laach omleech bringe"},
{"id":"tool_clear","title":"Nije ôfbielding"},
{"id":"tool_open","title":"Ôfbielding iepenje"},
{"id":"tool_save","title":"Ôfbielding bewarje"},
{"id":"tool_docprops","title":"Dokuminteigenskippen"},
{"id":"tool_source","title":"Boarne oanpasse"},
{"id":"tool_undo","title":"Ungedien meitjse"},
{"id":"tool_redo","title":"Op 'e nij"},
{"id":"tool_clone","title":"Ûnderdiel duplisearje"},
{"id":"tool_delete","title":"Ûnderdiel fuortsmite"},
{"id":"tool_move_top","title":"Nei foargrûn"},
{"id":"tool_move_bottom","title":"Nei eftergrûn"},
{"id":"group_opacity","title":"Trochsichtigens oanpasse"},
{"id":"angle","title":"Draaie"},
{"id":"tool_clone_multi","title":"Ûnderdielen duplisearje"},
{"id":"tool_delete_multi","title":"Ûnderdielen fuortsmite"},
{"id":"tool_alignleft","title":"Lofts útlijne"},
{"id":"tool_aligncenter","title":"Midden útlijne"},
{"id":"tool_alignright","title":"Rjochts útlijne"},
{"id":"tool_aligntop","title":"Boppe útlijne"},
{"id":"tool_alignmiddle","title":"Midden útlijne"},
{"id":"tool_alignbottom","title":"Ûnder útlijne"},
{"id":"align_relative_to","title":"Útlijne relatyf oan..."},
{"id":"tool_group","title":"Ûnderdielen groepearje"},
{"id":"tool_ungroup","title":"Groepering opheffe"},
{"id":"rect_width","title":"Breedte rjochthoeke oanpasse"},
{"id":"rect_height","title":"Hichte rjochthoeke oanpasse"},
{"id":"rect_rx","title":"Hoekeradius oanpasse"},
{"id":"image_width","title":"Breedte ôfbielding oanpasse"},
{"id":"image_height","title":"Hichte ôfbielding oanpasse"},
{"id":"image_url","title":"URL oanpasse"},
{"id":"circle_cx" ,"title":"Feroarje it X-koördinaat fan it middelpunt fan'e sirkel."},
{"id":"circle_cy" ,"title":"Feroarje it Y-koördinaat fan it middelpunt fan'e sirkel."},
{"id":"circle_r","title":"Feroarje sirkelradius"},
{"id":"ellipse_cx","title":"Feroarje it X-koördinaat fan it middelpunt fan'e ellips."},
{"id":"ellipse_cy","title":"Feroarje it Y-koördinaat fan it middelpunt fan'e ellips."},
{"id":"ellipse_rx","title":"Feroarje ellips X radius"},
{"id":"ellipse_ry","title":"Feroarje ellips Y radius"},
{"id":"line_x1","title":"Feroarje start X koördinaat fan'e line"},
{"id":"line_y1","title":"Feroarje start Y koördinaat fan'e line"},
{"id":"line_x2","title":"Feroarje ein X koördinaat fan'e line"},
{"id":"line_y2","title":"Feroarje ein Y koördinaat fan'e line"},
{"id":"tool_bold","title":"Fet"},
{"id":"tool_italic","title":"Skean"},
{"id":"font_family","title":"Lettertype oanpasse"},
{"id":"font_size","title":"Lettergrutte oanpasse"},
{"id":"text","title":"Tekst oanpasse"},
{"id":"tool_select","title":"Selektearje"},
{"id":"tool_fhpath","title":"Potlead"},
{"id":"tool_line","title":"Line"},
{"id":"tools_rect_show","title":"Fjouwerkant/rjochthoeke"},
{"id":"tools_ellipse_show","title":"Ellips/sirkel"},
{"id":"tool_text","title":"Tekst"},
{"id":"tool_path","title":"Paad"},
{"id":"tool_image","title":"Ôfbielding"},
{"id":"tool_zoom","title":"Zoom"},
{"id":"zoom","title":"Yn-/útzoome"},
{"id":"fill_color","title":"Folkleur oanpasse"},
{"id":"stroke_color","title":"Linekleur oanpasse"},
{"id":"stroke_width","title":"Linebreedte oanpasse"},
{"id":"stroke_style","title":"Linestijl oanpasse"},
{"id":"palette","title":"Klik om de folkleur te feroarjen, shift-klik om de linekleur te feroarjen."},
{"id":"tool_square","title":"Fjouwerkant"},
{"id":"tool_rect","title":"Rjochthoeke"},
{"id":"tool_fhrect","title":"Frije rjochthoeke"},
{"id":"tool_circle","title":"Sirkel"},
{"id":"tool_ellipse","title":"Ellips"},
{"id":"tool_fhellipse","title":"Frije ellips"},
{"id":"bkgnd_color","title":"Eftergrûnkleur/trochsichtigens oanpasse"},
{"id":"rwidthLabel","textContent":"Breedte:"},
{"id":"rheightLabel","textContent":"Hichte:"},
{"id":"cornerRadiusLabel","textContent":"Hoekradius:"},
{"id":"iwidthLabel","textContent":"Breedte:"},
{"id":"iheightLabel","textContent":"Hichte:"},
{"id":"svginfo_width","textContent":"Breedte:"},
{"id":"svginfo_height","textContent":"Hichte:"},
{"id":"angleLabel","textContent":"Hoek:"},
{"id":"relativeToLabel","textContent":"Relatief tsjinoer:"},
{"id":"zoomLabel","textContent":"Zoom:"},
{"id":"layersLabel","textContent":"Lagen:"},
{"id":"selectedPredefined","textContent":"Selektearje:"},
{"id":"fitToContent","textContent":"Passe op ynhâld"},
{"id":"tool_source_save","textContent":"Feroarings tapasse"},
{"id":"tool_docprops_save","textContent":"Ok"},
{"id":"tool_docprops_cancel","textContent":"Ôfbrekke"},
{"id":"tool_source_cancel","textContent":"Ôfbrekke"},
{"id":"fit_to_all","textContent":"Op alle ynhâld passe"},
{"id":"fit_to_layer_content" ,"textContent":"Op laachynhâld passe"},
{"id":"fit_to_sel","textContent":"Op seleksje passe"},
{"id":"fit_to_canvas","textContent":"Op kanvas passe"},
{"id":"selected_objects","textContent":"Selektearre ûnderdielen"},
{"id":"largest_object","textContent":"Grutste ûnderdiel"},
{"id":"smallest_object","textContent":"Lytste ûnderdiel"},
{"id":"page","textContent":"Side"},
{"id":"fill_tool_bottom","textContent":"Kleur:"},
{"id":"stroke_tool_bottom","textContent":"Line:"},
{"id":"path_node_x","title":"X-koördinaat knooppunt oanpasse"},
{"id":"path_node_y","title":"Y-koördinaat knooppunt oanpasse"},
{"id":"seg_type","title":"Segmenttype oanpasse"},
{"id":"straight_segments","textContent":"Rjocht"},
{"id":"curve_segments","textContent":"Bûcht"},
{"id":"tool_node_clone","title":"Knooppunt duplisearje"},
{"id":"tool_node_delete","title":"Knooppunt fuortsmite"},
{"id":"selLayerLabel","textContent":"Ûnderdielen ferplaate nei:"},
{"id":"selLayerNames","title":"Selektearre ûnderdielen ferplaatse nei in oare laach"},
{"id":"sidepanel_handle","title":"Sleep nei links/rjochts om it sidepaniel grutter as lytser te meitjen","textContent":"L a g e n"},
{"id":"tool_wireframe","title":"Triemodel"},
{"id":"svginfo_image_props","textContent":"Ôfbieldingseigenskippen"},
{"id":"svginfo_title","textContent":"Titel"},
{"id":"svginfo_dim","textContent":"Kanvasgrutte"},
{"id":"includedImages","textContent":"Ynslúten ôfbieldingen"},
{"id":"image_opt_embed","textContent":"Ynformaasje tafoege (lokale triemen)"},
{"id":"image_opt_ref","textContent":"Triemreferensje brûke"},
{"id":"svginfo_editor_prefs","textContent":"Eigenskippen bewurker"},
{"id":"svginfo_lang","textContent":"Taal"},
{"id":"svginfo_change_background","textContent":"Eftergrûn bewurker"},
{"id":"svginfo_bg_note","textContent":"Let op: de eftergrûn wurd net mei de ôfbielding bewarre."},
{"id":"svginfo_icons","textContent":"Ikoangrutte"},
{"id":"icon_small","textContent":"Lyts"},
{"id":"icon_medium","textContent":"Middel"},
{"id":"icon_large","textContent":"Grut"},
{"id":"icon_xlarge","textContent":"Ekstra grut"},
{"id":"selected_x","title":"X-koördinaat oanpasse"},
{"id":"selected_y","title":"Y-koördinaat oanpasse"},
{"id":"tool_topath","title":"Omsette nei paad"},
{"id":"tool_reorient","title":"Paad opnij orientearje"},
{"id":"tool_node_link","title":"Knooppunten keppelje"},
{"js_strings": {
		"invalidAttrValGiven":"Ferkearde waarde jûn",
		"noContentToFitTo":"Gjin ynhâld om te passen",
		"layer":"Laach",
		"dupeLayerName":"Der is al in laach mei dy namme!",
		"enterUniqueLayerName":"Type in unyke laachnamme",
		"enterNewLayerName":"Type in nije laachnamme",
		"layerHasThatName":"Laach hat dy namme al",
		"QmoveElemsToLayer":"Selektearre ûnderdielen ferplaatse nei '%s'?",
		"QwantToClear":"Ôfbielding leechmeitsje? Dit sil ek de skiednis fuortsmite!",
		"QerrorsRevertToSource":"Der wiene flaters yn de SVG-boarne.\nWeromgean nei foarige SVG-boarne?",
		"QignoreSourceChanges":"Feroarings yn SVG-boarne negeare?",
		"featNotSupported":"Funksje wurdt net ûndersteund",
		"enterNewImgURL":"Jou de nije URL",
		"ok":"Ok",
		"cancel":"Ôfbrekke",
		"pathNodeTooltip":"Fersleepje dit knooppunt as dûbelklik om it segmenttype oan te passen.",
		"pathCtrlPtTooltip":"Fersleepje dit knooppunt om de boocheigenskippen oan te passen.",
		"key_up":"omheech",
		"key_down":"omleech",
		"key_backspace":"backspace",
		"key_del":"delete"
	}
}
]
<|endoftext|>


<commit_before>const got = require('got');

const request = require('request');
const Buffer = require('Buffer');
const canonicalize = require('canon');
const crypto = require('crypto-js');
const companyCode = 88801;
const Oauth = require('client-oauth2');
const cID = '268b2069-b099-4fa2-8148-1f1c0327fe63';
const cS = 'b383c35d-3c11-4ce6-b631-8767f4c2084b';
const aK = '0dfb11cd-b140-40cd-b65a-220e9998a129';
const aS = '199505e4-9d5f-4ba9-bb96-a3ea8b2f69c1';

const auth = new Oauth({
  clientId: cID,
  clientSecret: cS,
  accessTokenUri: 'https://api.finhacks.id/api/oauth/token',
});

function getAccessToken (handleData) {

  let header = {
    Authorization: 'Basic ' + new Buffer(cID + ':' + cS).toString('base64'),
    'Content-Type': 'application/x-www-form-urlencoded',
  };

  let body = { grant_type: 'client_credentials' };
  let options = {
    method: 'POST',
    url: 'https://api.finhacks.id/api/oauth/token',
    headers: header,
  };

  request.post(options).form(body)
    .on('response', function(response) {
      response.on('data', function(data){
        handleData(data);
      });
    })
    .on('error', function(error) {
      handleData(error);
    });
}

function createHeader (data, body){
  let method = 'post'.toUpperCase();
  let url = encodeURI('/ewallet/customers');
  console.log(url);
  let accessToken = data.access_token;
  let bd = "";
  if(Object.keys(body).length != 0 && body.constructor === Object){
    bd = JSON.stringify(body);
    bd = crypto.SHA256(bd).toString()l
  }
  bd.toLowerCase();
  console.log(bd)
  let dt = new Date();
  dt = dt.toISOString();

  let str = method + ':' + url + ':' + accessToken + ':' + bd + ':' + dt;

  let hash = crypto.HmacSHA256(str, aS).toString();

  var header = {
    'Authorization' : 'Bearer '+accessToken,
    'X-BCA-Key' : aK,
    'X-BCA-Signature' : hash,
    'X-BCA-Timestamp' : dt
  }

  return header;
}

function registerUser (req, res) {

  let body = {};
  body.CustomerName = req.customer_name;
  body.DateOfBirth = req.birth_date;
  body.PrimaryID = req.primary_id;
  body.MobileNumber = req.mobile_number;
  body.EmailAddress = req.email_address;
  body.IDNumber = req.id_number;
  body.CompanyCode = companyCode;

  let header = {};

  getAccessToken(function(data){
    let header = createHeader(JSON.parse(data), body);
  //   let options = {
  //     url: 'https://api.finhacks.id/ewallet/customers',
  //     headers: header,
  //     method: 'POST',
  //     json: 'true'
  //   }
  //   request.post(options).form(body)
  //     .on('response',function(response){
  //       response.on('data', function(data){
  //         res.send(data);
  //       })
  //     })
  //     .on('error', function(error){
  //       res.send(error);
  //     });
  });
}

module.exports = {
  getAccessToken,
  registerUser,
};
<commit_msg>try access token<commit_after>const got = require('got');

const request = require('request');
const Buffer = require('Buffer');
const canonicalize = require('canon');
const crypto = require('crypto-js');
const companyCode = 88801;
const Oauth = require('client-oauth2');
const cID = '268b2069-b099-4fa2-8148-1f1c0327fe63';
const cS = 'b383c35d-3c11-4ce6-b631-8767f4c2084b';
const aK = '0dfb11cd-b140-40cd-b65a-220e9998a129';
const aS = '199505e4-9d5f-4ba9-bb96-a3ea8b2f69c1';

const auth = new Oauth({
  clientId: cID,
  clientSecret: cS,
  accessTokenUri: 'https://api.finhacks.id/api/oauth/token',
});

function getAccessToken (handleData) {

  let header = {
    Authorization: 'Basic ' + new Buffer(cID + ':' + cS).toString('base64'),
    'Content-Type': 'application/x-www-form-urlencoded',
  };

  let body = { grant_type: 'client_credentials' };
  let options = {
    method: 'POST',
    url: 'https://api.finhacks.id/api/oauth/token',
    headers: header,
  };

  request.post(options).form(body)
    .on('response', function(response) {
      response.on('data', function(data){
        handleData(data);
      });
    })
    .on('error', function(error) {
      handleData(error);
    });
}

function createHeader (data, body){
  let method = 'post'.toUpperCase();
  let url = encodeURI('/ewallet/customers');
  console.log(url);
  let accessToken = data.access_token;
  let bd = "";
  if(Object.keys(body).length != 0 && body.constructor === Object){
    bd = JSON.parse(JSON.stringify(body));
    console.log(bd)
    bd = crypto.SHA256(bd).toString();
  }
  bd.toLowerCase();
  console.log(bd)
  let dt = new Date();
  dt = dt.toISOString();

  let str = method + ':' + url + ':' + accessToken + ':' + bd + ':' + dt;

  let hash = crypto.HmacSHA256(str, aS).toString();

  var header = {
    'Authorization' : 'Bearer '+accessToken,
    'X-BCA-Key' : aK,
    'X-BCA-Signature' : hash,
    'X-BCA-Timestamp' : dt
  }

  return header;
}

function registerUser (req, res) {

  let body = {};
  body.CustomerName = req.body.customer_name;
  body.DateOfBirth = req.body.birth_date;
  body.PrimaryID = req.body.primary_id;
  body.MobileNumber = req.body.mobile_number;
  body.EmailAddress = req.body.email_address;
  body.IDNumber = req.body.id_number;
  body.CompanyCode = companyCode;

  let header = {};

  getAccessToken(function(data){
    let header = createHeader(JSON.parse(data), body);
  //   let options = {
  //     url: 'https://api.finhacks.id/ewallet/customers',
  //     headers: header,
  //     method: 'POST',
  //     json: 'true'
  //   }
  //   request.post(options).form(body)
  //     .on('response',function(response){
  //       response.on('data', function(data){
  //         res.send(data);
  //       })
  //     })
  //     .on('error', function(error){
  //       res.send(error);
  //     });
  });
}

module.exports = {
  getAccessToken,
  registerUser,
};
<|endoftext|>