<commit_before>import constants from './constants';
import BlueprintApi from '../data/BlueprintApi';
import MetadataApi from '../data/MetadataApi';
import utils from './utils';

export function createBlueprintApi(events, blueprint) {
  BlueprintApi.handleCreateBlueprint(events, blueprint);
}

export function fetchBlueprintContentsApi(blueprintName) {
  const blueprintContents = Promise.all([BlueprintApi.getBlueprint(blueprintName)])
    .then(data => {
      const blueprint = data[0];
      blueprint.id = blueprintName;
      return blueprint;
    })
    .catch(err => console.log(`Error in fetchBlueprintContents promise: ${err}`));
  return blueprintContents;
}

export function fetchWorkspaceBlueprintContentsApi(blueprintRaw) {
  const blueprintContents = Promise.all([BlueprintApi.getBlueprintWorkspace(blueprintRaw)])
    .then(data => {
      const blueprint = data[0];
      return blueprint;
    })
    .catch(err => console.log(`Error in fetchModalBlueprintContents promise: ${err}`));
  return blueprintContents;
}

export function fetchBlueprintInputsApi(filter, selectedInputPage, pageSize) {
  const page = selectedInputPage * pageSize;
  const p = new Promise((resolve, reject) => {
      // /modules/list looks like:
      // {"modules":[{"name":"389-ds-base","group_type":"rpm"},{"name":"389-ds-base-libs","group_type":"rpm"}, ...]}
    utils.apiFetch(`${constants.get_modules_list + filter}?limit=${pageSize}&offset=${page}`)
      .then(data => {
        const total = data.total;
        let components = data.modules;
        const componentNames = MetadataApi.getNames(components);
        Promise.all([
          MetadataApi.getData(constants.get_projects_info + componentNames),
        ]).then((result) => {
          components = MetadataApi.updateInputMetadata(components, result[0], true);
          components.map(i => { i.ui_type = 'RPM'; return i; }); // eslint-disable-line no-param-reassign
          resolve([components, total]);
        }).catch(e => console.log(`Error getting blueprint metadata: ${e}`));
      })
      .catch(e => {
        console.log('Failed to get inputs during blueprint edit', e);
        reject();
      });
  });
  return p;
}

export function fetchBlueprintNamesApi() {
  const blueprintNames = utils.apiFetch(constants.get_blueprints_list)
    .then(response => response.blueprints);
  return blueprintNames;
}

export function fetchBlueprintInfoApi(blueprintName) {
  const blueprintFetch = utils.apiFetch(constants.get_blueprints_info + blueprintName)
    .then(blueprintdata => {
      if (blueprintdata.blueprints.length > 0) {
        let blueprint = blueprintdata.blueprints[0];
        blueprint.id = blueprintName;
        return blueprint;
      }
      return null;
    });
  return blueprintFetch;
}

export function fetchModalCreateImageTypesApi() {
  const imageTypes = utils.apiFetch(constants.get_image_types)
    .then(data => data.types)
    .catch(e => console.log('Error getting component types', e));
  return imageTypes;
}

export function setBlueprintDescriptionApi(blueprint, description) {
  BlueprintApi.handleEditDescription(description);
}

export function deleteBlueprintApi(blueprint) {
  const deletedBlueprint = Promise.all([BlueprintApi.deleteBlueprint(blueprint)])
    .then(() => blueprint);
  return deletedBlueprint;
}

export function commitToWorkspaceApi(blueprint) {
  return utils.apiFetch(constants.post_blueprints_workspace, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(blueprint),
  }, true);
}

export function fetchDiffWorkspaceApi(blueprintId) {
  const p = new Promise((resolve, reject) => {
    utils.apiFetch('/api/v0/blueprints/diff/' + blueprintId + '/NEWEST/WORKSPACE')
    .then(data => {
      resolve(data);
    })
    .catch(e => {
      console.log('Error fetching diff', e);
      reject();
    });
  });
  return p;
}

export function depsolveComponentsApi(packages) {
  const p = new Promise((resolve, reject) => {
    const packageNames = packages.map(item => item.name);
    let dependencies = [];
    if (packageNames.length > 0) {
      utils.apiFetch(constants.get_projects_deps + packageNames)
        .then(depData => {
          // bdcs-api v0.3.0 includes module (component) and dependency NEVRAs
          // tagging all dependencies a "RPM" for now
          dependencies = BlueprintApi.setType(depData.projects, 'RPM');
          resolve(dependencies);
        })
        .catch(e => {
          console.log('getBlueprint: Error getting component and dependency metadata', e);
          reject();
        });
    } else {
      resolve(dependencies);
    }
  });
  return p;
}

export function fetchSourceInfoApi(sourceName) {
  const sourceFetch = utils.apiFetch(constants.get_sources_info + sourceName)
    .then(sourceData => {
      if (sourceData) {
        return sourceData;
      }
      return null;
    }).catch(e => {
      console.log('Error fetching sources', e);
    });
  return sourceFetch;
}

export function startComposeApi(blueprintName, composeType) {
  const requestBody = {
    blueprint_name: blueprintName,
    compose_type: composeType,
    branch: "master"
  };

  utils.apiFetch(constants.post_compose_start, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(requestBody),
  }, true)
  .then(data => JSON.parse(data))
  .catch(e => console.log('Error starting compose', e));
}

export function fetchImageStatusApi(uuid) {
  return utils.apiFetch(constants.get_image_status + uuid)
  .then(data => data)
  .catch(e => console.log('Error fetching image status', e));
}

export function fetchComposeQueueApi() {
  return utils.apiFetch(constants.get_compose_queue)
  .then(data => data.new.concat(data.run))
  .catch(e => console.log('Error fetching queued composes', e));
}

export function fetchComposeFinishedApi() {
  return utils.apiFetch(constants.get_compose_finished)
  .then(data => data.finished)
  .catch(e => console.log('Error fetching finished composes', e));
}

export function fetchComposeFailedApi() {
  return utils.apiFetch(constants.get_compose_failed)
  .then(data => data.failed)
  .catch(e => console.log('Error fetching failed composes', e));
}
<commit_msg>Fixed bug where startComposeApi would not return start compose response<commit_after>import constants from './constants';
import BlueprintApi from '../data/BlueprintApi';
import MetadataApi from '../data/MetadataApi';
import utils from './utils';

export function createBlueprintApi(events, blueprint) {
  BlueprintApi.handleCreateBlueprint(events, blueprint);
}

export function fetchBlueprintContentsApi(blueprintName) {
  const blueprintContents = Promise.all([BlueprintApi.getBlueprint(blueprintName)])
    .then(data => {
      const blueprint = data[0];
      blueprint.id = blueprintName;
      return blueprint;
    })
    .catch(err => console.log(`Error in fetchBlueprintContents promise: ${err}`));
  return blueprintContents;
}

export function fetchWorkspaceBlueprintContentsApi(blueprintRaw) {
  const blueprintContents = Promise.all([BlueprintApi.getBlueprintWorkspace(blueprintRaw)])
    .then(data => {
      const blueprint = data[0];
      return blueprint;
    })
    .catch(err => console.log(`Error in fetchModalBlueprintContents promise: ${err}`));
  return blueprintContents;
}

export function fetchBlueprintInputsApi(filter, selectedInputPage, pageSize) {
  const page = selectedInputPage * pageSize;
  const p = new Promise((resolve, reject) => {
      // /modules/list looks like:
      // {"modules":[{"name":"389-ds-base","group_type":"rpm"},{"name":"389-ds-base-libs","group_type":"rpm"}, ...]}
    utils.apiFetch(`${constants.get_modules_list + filter}?limit=${pageSize}&offset=${page}`)
      .then(data => {
        const total = data.total;
        let components = data.modules;
        const componentNames = MetadataApi.getNames(components);
        Promise.all([
          MetadataApi.getData(constants.get_projects_info + componentNames),
        ]).then((result) => {
          components = MetadataApi.updateInputMetadata(components, result[0], true);
          components.map(i => { i.ui_type = 'RPM'; return i; }); // eslint-disable-line no-param-reassign
          resolve([components, total]);
        }).catch(e => console.log(`Error getting blueprint metadata: ${e}`));
      })
      .catch(e => {
        console.log('Failed to get inputs during blueprint edit', e);
        reject();
      });
  });
  return p;
}

export function fetchBlueprintNamesApi() {
  const blueprintNames = utils.apiFetch(constants.get_blueprints_list)
    .then(response => response.blueprints);
  return blueprintNames;
}

export function fetchBlueprintInfoApi(blueprintName) {
  const blueprintFetch = utils.apiFetch(constants.get_blueprints_info + blueprintName)
    .then(blueprintdata => {
      if (blueprintdata.blueprints.length > 0) {
        let blueprint = blueprintdata.blueprints[0];
        blueprint.id = blueprintName;
        return blueprint;
      }
      return null;
    });
  return blueprintFetch;
}

export function fetchModalCreateImageTypesApi() {
  const imageTypes = utils.apiFetch(constants.get_image_types)
    .then(data => data.types)
    .catch(e => console.log('Error getting component types', e));
  return imageTypes;
}

export function setBlueprintDescriptionApi(blueprint, description) {
  BlueprintApi.handleEditDescription(description);
}

export function deleteBlueprintApi(blueprint) {
  const deletedBlueprint = Promise.all([BlueprintApi.deleteBlueprint(blueprint)])
    .then(() => blueprint);
  return deletedBlueprint;
}

export function commitToWorkspaceApi(blueprint) {
  return utils.apiFetch(constants.post_blueprints_workspace, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(blueprint),
  }, true);
}

export function fetchDiffWorkspaceApi(blueprintId) {
  const p = new Promise((resolve, reject) => {
    utils.apiFetch('/api/v0/blueprints/diff/' + blueprintId + '/NEWEST/WORKSPACE')
    .then(data => {
      resolve(data);
    })
    .catch(e => {
      console.log('Error fetching diff', e);
      reject();
    });
  });
  return p;
}

export function depsolveComponentsApi(packages) {
  const p = new Promise((resolve, reject) => {
    const packageNames = packages.map(item => item.name);
    let dependencies = [];
    if (packageNames.length > 0) {
      utils.apiFetch(constants.get_projects_deps + packageNames)
        .then(depData => {
          // bdcs-api v0.3.0 includes module (component) and dependency NEVRAs
          // tagging all dependencies a "RPM" for now
          dependencies = BlueprintApi.setType(depData.projects, 'RPM');
          resolve(dependencies);
        })
        .catch(e => {
          console.log('getBlueprint: Error getting component and dependency metadata', e);
          reject();
        });
    } else {
      resolve(dependencies);
    }
  });
  return p;
}

export function fetchSourceInfoApi(sourceName) {
  const sourceFetch = utils.apiFetch(constants.get_sources_info + sourceName)
    .then(sourceData => {
      if (sourceData) {
        return sourceData;
      }
      return null;
    }).catch(e => {
      console.log('Error fetching sources', e);
    });
  return sourceFetch;
}

export function startComposeApi(blueprintName, composeType) {
  const requestBody = {
    blueprint_name: blueprintName,
    compose_type: composeType,
    branch: "master"
  };
  return utils.apiFetch(constants.post_compose_start, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(requestBody),
  }, true)
  .then(data => JSON.parse(data))
  .catch(e => console.log('Error starting compose', e));
}

export function fetchImageStatusApi(uuid) {
  return utils.apiFetch(constants.get_image_status + uuid)
  .then(data => data)
  .catch(e => console.log('Error fetching image status', e));
}

export function fetchComposeQueueApi() {
  return utils.apiFetch(constants.get_compose_queue)
  .then(data => data.new.concat(data.run))
  .catch(e => console.log('Error fetching queued composes', e));
}

export function fetchComposeFinishedApi() {
  return utils.apiFetch(constants.get_compose_finished)
  .then(data => data.finished)
  .catch(e => console.log('Error fetching finished composes', e));
}

export function fetchComposeFailedApi() {
  return utils.apiFetch(constants.get_compose_failed)
  .then(data => data.failed)
  .catch(e => console.log('Error fetching failed composes', e));
}
<|endoftext|>


<commit_before>(function() {
  // 2. This code loads the IFrame Player API code asynchronously.
  var dom = {
    findBox: document.getElementById('box'),
    statusBox: document.getElementById('status'),
    infoBox: document.getElementById('info'),
    scoreBox: document.getElementById('scorebox'),
    creatorLink: document.getElementById('creator-link'),
    showStatus: function showStatus(text) {
      this.statusBox.textContent = text;
    },
    showInfo: function showInfo() {
      this.infoBox.setAttribute('style', 'display: block; -webkit-animation: example 4s; animation: example 4s; -webkit-animation-fill-mode: forwards; animation-fill-mode: forwards;');
    },
    showTime: function showTime(time) {
      var timeStr = time.toPrecision(2);
      if (time > 0) {
        timeStr = '+'+timeStr;
        this.scoreBox.className += ' win-hue';
        this.creatorLink.setAttribute('style', 'display: inline');
      }
      timeStr += 's';
      this.scoreBox.textContent = timeStr;
    }
  };
  var successMsgs = ['Good job.', 'Nice work.', 'Good eye.', 'Well done.', 'Nicely done.'];
  var pauseMsgs = ['Looks fine there.', 'Seems ok.', 'All clear there.', 'Just splashing around.'];

  var videos = [{
    videoId: '4sFuULOY5ik',
    drowningStartSecs: 12.2,
    whistleSecs: 14.5,
    swimmerSavedSecs: 25,
    findBoxStyle: "left: 455px; top: -365px; position: relative; width: 50px; height: 34px;"
  }, {
    videoId: 'JYQ9AwsTkAw',
    drowningStartSecs: 18.4,
    whistleSecs: 21,
    swimmerSavedSecs: 28.5,
    findBoxStyle: "left: 383px; top: -326px; position: relative; width: 80px; height: 65px;"
  }, {
    videoId: 'PuAfTA2wf7o',
    drowningStartSecs: 37.3,
    whistleSecs: 45.1,
    swimmerSavedSecs: 50.5,
    findBoxStyle: "left: 329px; top: -385px; position: relative; width: 103px; height: 37px;"
  }, {
    videoId: 'T5mDQeDkca0',
    drowningStartSecs: 54.0,
    whistleSecs: 56.5,
    swimmerSavedSecs: 62.8,
    findBoxStyle: "left: 606px; top: -265px; position: relative; width: 102px; height: 102px;",
  }];

  var gameState = pickRandom(videos);
  var player;

  function init() {
    youtubeInit(onPlayerReady, onPlayerStateChange);
    wireDom(dom);
  }
  init();

  function onPlayerReady(event) {
    setupItem(gameState);

    setInterval(function gameFrame() {
      if (!player || !player.getCurrentTime || player.getPlayerState() !== YT.PlayerState.PLAYING)
          return;
      var time = player.getCurrentTime();
      // State transitions: ok -> drowning -> spotted -> saved
      if (time > gameState.swimmerSavedSecs && gameState.status() === 'spotted') {
          gameState.status('saved');
      } else if (time > gameState.whistleSecs && gameState.status() === 'drowning') {
          gameState.status('spotted');
      } else if (time > gameState.drowningStartSecs && gameState.status() === 'ok') {
          gameState.status('drowning');
      }
    }, 100);
  }

  function youtubeInit(onPlayerReady, onPlayerStateChange) {
    window.onYouTubeIframeAPIReady = function() {
      player = new YT.Player('player', {
        height: '480',
        width: '854',
        videoId: gameState.videoId,
        playerVars: {
          controls: 0,
          rel: 0,
          showinfo: 0,
          playsinline: 1,
          modestbranding: 1,
          fs: 0
        },
        events: {
          'onReady': onPlayerReady,
          'onStateChange': onPlayerStateChange
        }
      });
    };
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  }

  function wireDom(dom) {
    dom.findBox.addEventListener('click', function() {
      if (gameState.status() === 'drowning' || gameState.status() === 'spotted') {
        success();
        dom.findBox.setAttribute('style', 'display: none;');
      }
    });
  }

  function setupItem(nextItem) {
    nextItem.status = observable();
    nextItem.status('ok');
    player.cueVideoById(nextItem.videoId, undefined, 'large');
    dom.findBox.setAttribute('style', nextItem.findBoxStyle);
    player.playVideo();

    gameState.status(function(newStatus) {
      if (newStatus === 'drowning') {
        dom.findBox.setAttribute('style', 'display: block;' + nextItem.findBoxStyle);
      } else if (newStatus === 'saved') {
        end();
      } else if (newStatus === 'spotted') {
        if (!gameState.winTime) {
          dom.showStatus('Spot the drowning child. Click the video to help the lifeguard.');
        }
      }
    });
  }

  function success() {
    gameState.winTime = player.getCurrentTime();

    if (gameState.status() === 'drowning') {
      player.seekTo(gameState.whistleSecs);
    }
    gameState.status('spotted');
    player.setPlaybackRate(2);

    var time = gameState.whistleSecs - gameState.winTime;
    var msg = pickRandom(successMsgs);
    dom.showStatus(msg);
    dom.showTime(time);
  }

  function end() {
    dom.showInfo();
  }

  // 4. The API will call this function when the video player is ready.

  function onPlayerStateChange(event) {
    var status = gameState.status();
    if (event.data === YT.PlayerState.ENDED) {
      end();
    } else if (event.data === YT.PlayerState.PAUSED) {
      if (status === 'drowning' || status === 'ok') {
        var pauseMsg = pickRandom(pauseMsgs);
        dom.showStatus(pauseMsg + ' Keep looking.');
      } else if (status === 'spotted' || status === 'saved') {
        end();
      }
    } else if (event.data === YT.PlayerState.PLAYING &&
        (status === 'drowning' || status === 'ok')) {
      dom.showStatus('Spot the drowning child.');
    }
  }

  function pickRandom(items) {
    return items[Math.floor(Math.random()*items.length)];
  }
})();
<commit_msg>New video.<commit_after>(function() {
  // 2. This code loads the IFrame Player API code asynchronously.
  var dom = {
    findBox: document.getElementById('box'),
    statusBox: document.getElementById('status'),
    infoBox: document.getElementById('info'),
    scoreBox: document.getElementById('scorebox'),
    creatorLink: document.getElementById('creator-link'),
    showStatus: function showStatus(text) {
      this.statusBox.textContent = text;
    },
    showInfo: function showInfo() {
      this.infoBox.setAttribute('style', 'display: block; -webkit-animation: example 4s; animation: example 4s; -webkit-animation-fill-mode: forwards; animation-fill-mode: forwards;');
    },
    showTime: function showTime(time) {
      var timeStr = time.toPrecision(2);
      if (time > 0) {
        timeStr = '+'+timeStr;
        this.scoreBox.className += ' win-hue';
        this.creatorLink.setAttribute('style', 'display: inline');
      }
      timeStr += 's';
      this.scoreBox.textContent = timeStr;
    }
  };
  var successMsgs = ['Good job.', 'Nice work.', 'Good eye.', 'Well done.', 'Nicely done.'];
  var pauseMsgs = ['Looks fine there.', 'Seems ok.', 'All clear there.', 'Just splashing around.'];

  var videos = [{
    videoId: '4sFuULOY5ik',
    drowningStartSecs: 12.2,
    whistleSecs: 14.5,
    swimmerSavedSecs: 25,
    findBoxStyle: "left: 455px; top: -365px; position: relative; width: 50px; height: 34px;"
  }, {
    videoId: 'JYQ9AwsTkAw',
    drowningStartSecs: 18.4,
    whistleSecs: 21,
    swimmerSavedSecs: 28.5,
    findBoxStyle: "left: 383px; top: -326px; position: relative; width: 80px; height: 65px;"
  }, {
    videoId: 'PuAfTA2wf7o',
    drowningStartSecs: 37.3,
    whistleSecs: 45.1,
    swimmerSavedSecs: 50.5,
    findBoxStyle: "left: 329px; top: -385px; position: relative; width: 103px; height: 37px;"
  }, {
    videoId: 'T5mDQeDkca0',
    drowningStartSecs: 54.0,
    whistleSecs: 56.5,
    swimmerSavedSecs: 62.8,
    findBoxStyle: "left: 606px; top: -265px; position: relative; width: 102px; height: 102px;",
  }, {
    "videoId": "L0KTqPloUiU",
    "drowningStartSecs": 31.506069,
    "whistleSecs": 37.946069,
    "swimmerSavedSecs": 45.126069,
    "findBoxStyle": "left: 601px; top: -302px; position: relative; width: 203px; height: 136px;"
    }];

  var gameState = pickRandom(videos);
  var player;

  function init() {
    youtubeInit(onPlayerReady, onPlayerStateChange);
    wireDom(dom);
  }
  init();

  function onPlayerReady(event) {
    setupItem(gameState);

    setInterval(function gameFrame() {
      if (!player || !player.getCurrentTime || player.getPlayerState() !== YT.PlayerState.PLAYING)
          return;
      var time = player.getCurrentTime();
      // State transitions: ok -> drowning -> spotted -> saved
      if (time > gameState.swimmerSavedSecs && gameState.status() === 'spotted') {
          gameState.status('saved');
      } else if (time > gameState.whistleSecs && gameState.status() === 'drowning') {
          gameState.status('spotted');
      } else if (time > gameState.drowningStartSecs && gameState.status() === 'ok') {
          gameState.status('drowning');
      }
    }, 100);
  }

  function youtubeInit(onPlayerReady, onPlayerStateChange) {
    window.onYouTubeIframeAPIReady = function() {
      player = new YT.Player('player', {
        height: '480',
        width: '854',
        videoId: gameState.videoId,
        playerVars: {
          controls: 0,
          rel: 0,
          showinfo: 0,
          playsinline: 1,
          modestbranding: 1,
          fs: 0
        },
        events: {
          'onReady': onPlayerReady,
          'onStateChange': onPlayerStateChange
        }
      });
    };
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  }

  function wireDom(dom) {
    dom.findBox.addEventListener('click', function() {
      if (gameState.status() === 'drowning' || gameState.status() === 'spotted') {
        success();
        dom.findBox.setAttribute('style', 'display: none;');
      }
    });
  }

  function setupItem(nextItem) {
    nextItem.status = observable();
    nextItem.status('ok');
    player.cueVideoById(nextItem.videoId, undefined, 'large');
    dom.findBox.setAttribute('style', nextItem.findBoxStyle);
    player.playVideo();

    gameState.status(function(newStatus) {
      if (newStatus === 'drowning') {
        dom.findBox.setAttribute('style', 'display: block;' + nextItem.findBoxStyle);
      } else if (newStatus === 'saved') {
        end();
      } else if (newStatus === 'spotted') {
        if (!gameState.winTime) {
          dom.showStatus('Spot the drowning child. Click the video to help the lifeguard.');
        }
      }
    });
  }

  function success() {
    gameState.winTime = player.getCurrentTime();

    if (gameState.status() === 'drowning') {
      player.seekTo(gameState.whistleSecs);
    }
    gameState.status('spotted');
    player.setPlaybackRate(2);

    var time = gameState.whistleSecs - gameState.winTime;
    var msg = pickRandom(successMsgs);
    dom.showStatus(msg);
    dom.showTime(time);
  }

  function end() {
    dom.showInfo();
  }

  // 4. The API will call this function when the video player is ready.

  function onPlayerStateChange(event) {
    var status = gameState.status();
    if (event.data === YT.PlayerState.ENDED) {
      end();
    } else if (event.data === YT.PlayerState.PAUSED) {
      if (status === 'drowning' || status === 'ok') {
        var pauseMsg = pickRandom(pauseMsgs);
        dom.showStatus(pauseMsg + ' Keep looking.');
      } else if (status === 'spotted' || status === 'saved') {
        end();
      }
    } else if (event.data === YT.PlayerState.PLAYING &&
        (status === 'drowning' || status === 'ok')) {
      dom.showStatus('Spot the drowning child.');
    }
  }

  function pickRandom(items) {
    return items[Math.floor(Math.random()*items.length)];
  }
})();
<|endoftext|>


<commit_before>var UserView = {
    uploading: false,
    IMAGE_HEIGHT: 168,
    IMAGE_WIDTH: 168,
    showUploadedImage: function( source ) {
        $( ".avatar img" ).remove();
        $image = $( '' );
        $image.load( function() {
            UserView.fixImageSize( $image );
        } );
        $( ".avatar" ).append( $image );
    },
    createImageError: function() {
        $( '.text-center' ).prepend( "
This isn't an image
" )
    },
    removeImageError: function() {
        $( '.text-center .alert.alert-danger' ).remove();
    },
    fixImageSize: function( $image ) {
        var imgWidth = $image.width();
        var imgHeight = $image.height();

        if ( imgWidth > imgHeight ) {
            $image.height( UserView.IMAGE_HEIGHT );
            $image.css( 'top', 0 );
            $image.css( 'left', -Math.floor( ( $image.width() - UserView.IMAGE_WIDTH ) / 2 ) );
        }
        else {
            $image.width( UserView.IMAGE_WIDTH );
            $image.css( 'left', 0 );
            $image.css( 'top', -Math.floor( ( $image.height() - UserView.IMAGE_HEIGHT ) / 2 ) );
        }
    },
    finishUploadAnimation: function() {
        $( ".uploading" ).hide();
        $( ".uploading" ).removeClass( 'animate' );
        UserView.uploading = false;
    },
    startUploadAnimation: function() {
        $( ".upload-link" ).hide();
        $( ".uploading" ).show();
        $( ".uploading" ).addClass( 'animate' );
        UserView.uploading = true;
    },
    ready: function() {
        $( '.avatar img' ).load( function() {
            UserView.fixImageSize( $( '.avatar img' ) );
        } );
        $( ".avatar" ).mouseover( function() {
            if ( $( ".profile-header" ).attr( 'data-sameUser' ) == 'no' || UserView.uploading ) {
                return;
            }
            $( ".upload-link" ).show();
        } );
        $( ".avatar" ).mouseout( function() {
            if ( UserView.uploading ) {
                return;
            }
            $( ".upload-link" ).hide();
        } );
        $( ".upload-link" ).click( function() {
            $( "#image" ).trigger( 'click' );
            return false;
        } );
        $( '#unfollow' ).click( function() {
            $( '#unfollow-form' ).submit();
            return false;
        } );
        $( '#follow' ).click( function() {
            var $form = $( "#follow-form" );
            var followedid = $( "[name='followedid']", $form ).val();
            var token = $( "[name='token']", $form ).val();
            var formData = new FormData();

            formData.append( "followedid", followedid );
            formData.append( "token", token );

            $.ajax( {
                url: "follow/create",
                type: "POST",
                data: formData,
                cache: false,
                dataType: "json",
                processData: false,
                contentType: false,
                complete: function() {
                    $( "a#follow" ).replaceWith(
                        "<button class='btn btn-primary follow'>Unfollow</button>"
                    );
                    $( "form#follow-form" ).replaceWith(
                        "<form id='logout-form' action='session/delete' method='post' > \
                            <input type='hidden' name='token' value='" + token + "' /> \
                            <input type='hidden' name='followedid' value='" + followedid + "'  /> \
                        </form>"
                    );
                }
            } );
            return false;
        } );
        $( "#image" ).change( function() {
            var image = document.getElementById( "image" ).files[ 0 ];
            var token = $( "input[type=hidden]" ).val();
            var formData = new FormData();

            UserView.removeImageError();

            if ( !image ) {
                return false;
            }

            formData.append( "image", image );
            formData.append( "token", token );

            UserView.startUploadAnimation();

            $.ajax( {
                url: "image/create",
                type: "POST",
                data: formData,
                cache: false,
                dataType: "json",
                processData: false,
                contentType: false,
                success: function( targetPath ) {
                    var reader = new FileReader();

                    UserView.finishUploadAnimation();

                    reader.onloadend = function ( e ) {
                        UserView.showUploadedImage( targetPath );
                    }
                    reader.readAsDataURL( image );
                },
                error: function( jqXHR, textStatus, errorThrown ) {
                    UserView.finishUploadAnimation();

                    UserView.createImageError();
                }
            } );

            return false;
        } );
    }
}
$( document ).ready( UserView.ready );
<commit_msg>make unfollow button work with ajax too and debug<commit_after>var UserView = {
    uploading: false,
    IMAGE_HEIGHT: 168,
    IMAGE_WIDTH: 168,
    showUploadedImage: function( source ) {
        $( ".avatar img" ).remove();
        $image = $( '' );
        $image.load( function() {
            UserView.fixImageSize( $image );
        } );
        $( ".avatar" ).append( $image );
    },
    createImageError: function() {
        $( '.text-center' ).prepend( "
This isn't an image
" )
    },
    removeImageError: function() {
        $( '.text-center .alert.alert-danger' ).remove();
    },
    fixImageSize: function( $image ) {
        var imgWidth = $image.width();
        var imgHeight = $image.height();

        if ( imgWidth > imgHeight ) {
            $image.height( UserView.IMAGE_HEIGHT );
            $image.css( 'top', 0 );
            $image.css( 'left', -Math.floor( ( $image.width() - UserView.IMAGE_WIDTH ) / 2 ) );
        }
        else {
            $image.width( UserView.IMAGE_WIDTH );
            $image.css( 'left', 0 );
            $image.css( 'top', -Math.floor( ( $image.height() - UserView.IMAGE_HEIGHT ) / 2 ) );
        }
    },
    finishUploadAnimation: function() {
        $( ".uploading" ).hide();
        $( ".uploading" ).removeClass( 'animate' );
        UserView.uploading = false;
    },
    startUploadAnimation: function() {
        $( ".upload-link" ).hide();
        $( ".uploading" ).show();
        $( ".uploading" ).addClass( 'animate' );
        UserView.uploading = true;
    },
    ready: function() {
        $( '.avatar img' ).load( function() {
            UserView.fixImageSize( $( '.avatar img' ) );
        } );
        $( ".avatar" ).mouseover( function() {
            if ( $( ".profile-header" ).attr( 'data-sameUser' ) == 'no' || UserView.uploading ) {
                return;
            }
            $( ".upload-link" ).show();
        } );
        $( ".avatar" ).mouseout( function() {
            if ( UserView.uploading ) {
                return;
            }
            $( ".upload-link" ).hide();
        } );
        $( ".upload-link" ).click( function() {
            $( "#image" ).trigger( 'click' );
            return false;
        } );
        $( document ).on( "click", "#unfollow", function() {
            var $form = $( "#unfollow-form" );
            var followedid = $( "[name='followedid']", $form ).val();
            var token = $( "[name='token']", $form ).val();
            var formData = new FormData();

            formData.append( "followedid", followedid );
            formData.append( "token", token );

            $.ajax( {
                url: "follow/delete",
                type: "POST",
                data: formData,
                cache: false,
                dataType: "json",
                processData: false,
                contentType: false,
                complete: function() {
                    $( "a#unfollow" ).replaceWith(
                        "<button class='btn btn-primary follow'>Follow</button>"
                    );
                    $( "form#unfollow-form" ).replaceWith(
                        "<form id='follow-form' action='follow/create' method='post' > \
                            <input type='hidden' name='token' value='" + token + "' /> \
                            <input type='hidden' name='followedid' value='" + followedid + "'  /> \
                        </form>"
                    );
                }
            } );
            return false;
        } );
        $( document ).on( "click", "#follow", function() {
            var $form = $( "#follow-form" );
            var followedid = $( "[name='followedid']", $form ).val();
            var token = $( "[name='token']", $form ).val();
            var formData = new FormData();

            formData.append( "followedid", followedid );
            formData.append( "token", token );

            $.ajax( {
                url: "follow/create",
                type: "POST",
                data: formData,
                cache: false,
                dataType: "json",
                processData: false,
                contentType: false,
                complete: function() {
                    $( "a#follow" ).replaceWith(
                        "<button class='btn btn-primary follow'>Unfollow</button>"
                    );
                    $( "form#follow-form" ).replaceWith(
                        "<form id='unfollow-form' action='follow/delete' method='post' > \
                            <input type='hidden' name='token' value='" + token + "' /> \
                            <input type='hidden' name='followedid' value='" + followedid + "'  /> \
                        </form>"
                    );
                }
            } );
            return false;
        } );
        $( "#image" ).change( function() {
            var image = document.getElementById( "image" ).files[ 0 ];
            var token = $( "input[type=hidden]" ).val();
            var formData = new FormData();

            UserView.removeImageError();

            if ( !image ) {
                return false;
            }

            formData.append( "image", image );
            formData.append( "token", token );

            UserView.startUploadAnimation();

            $.ajax( {
                url: "image/create",
                type: "POST",
                data: formData,
                cache: false,
                dataType: "json",
                processData: false,
                contentType: false,
                success: function( targetPath ) {
                    var reader = new FileReader();

                    UserView.finishUploadAnimation();

                    reader.onloadend = function ( e ) {
                        UserView.showUploadedImage( targetPath );
                    }
                    reader.readAsDataURL( image );
                },
                error: function( jqXHR, textStatus, errorThrown ) {
                    UserView.finishUploadAnimation();

                    UserView.createImageError();
                }
            } );

            return false;
        } );
    }
}
$( document ).ready( UserView.ready );
<|endoftext|>


<commit_before>var scene, camera, renderer;
var geometry, material, mesh;
var SKYBOX_MAX_RADIUS = 3000;
var MAX_BOUND = 2000;

var objects = [new Ball(new THREE.Vector3(0,0,0), new THREE.Vector3(30,29,0), 0xff33bb),new Ball(new THREE.Vector3(-2,0,0), new THREE.Vector3(10,12,3), 0xa351bf)]

$(document).ready(function()
{
	init();
	createSkyBox();
	for (var obj in objects)
		scene.add(objects[obj].mesh);
	/*scene.add(new THREE.Mesh(
		new THREE.BoxGeometry(MAX_BOUND*2,MAX_BOUND*2,MAX_BOUND*2),
		new THREE.MeshPhongMaterial({wireframe:true})));*/
	animate();
	console.log(objects[0])
});

function Ball(position,velocity,color){
	var RADIUS = 50;
	this.color = color;
	this.position = position;
	this.velocity = velocity;
	this.sphere = function(){
		return THREE.Sphere(position,RADIUS)
	}
	this.mesh = new THREE.Mesh(
			new THREE.SphereGeometry(RADIUS),
			new THREE.MeshPhongMaterial({color:this.color}));
	this.update = function(){
		position.add(velocity);
		if (Math.abs(position.x) > MAX_BOUND)
		{
			position.x = position.x > 0 ? MAX_BOUND : -MAX_BOUND;
			velocity.x *= -1;
		}
		if (Math.abs(position.y) > MAX_BOUND)
		{
			position.y = position.y > 0 ? MAX_BOUND : -MAX_BOUND;
			velocity.y *= -1;
		}
		if (Math.abs(position.z) > MAX_BOUND)
		{
			position.z = position.z > 0 ? MAX_BOUND : -MAX_BOUND;
			velocity.z *= -1;
		}
		this.mesh.translateX(position.x-this.mesh.position.x);
		this.mesh.translateY(position.y-this.mesh.position.y);
		this.mesh.translateZ(position.z-this.mesh.position.z);
	}
}
function init() {

	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
	camera.position.z = 1000;
	var light = new THREE.PointLight( 0xffffff, 1, 3000 );
	light.position.set( 0, 0, 0 );
	scene.add(light);
	scene.add(new THREE.AmbientLight( 0x323232 ));
	renderer = new THREE.WebGLRenderer();
	renderer.autoClear = true;
	renderer.setSize( window.innerWidth, window.innerHeight );
	controls = new THREE.OrbitControls(camera, renderer.domElement);
	controls.maxDistance = SKYBOX_MAX_RADIUS;
	controls.noPan = true;
	$("body").append(renderer.domElement);

}
function createSkyBox() {
	var geometry = new THREE.SphereGeometry(SKYBOX_MAX_RADIUS,10,10);
	var uniforms = {
		texture: { type: 't', value: THREE.ImageUtils.loadTexture('assets/skybox.jpg') }
	};

	var material = new THREE.ShaderMaterial( {
		uniforms:       uniforms,
		vertexShader:   document.getElementById('sky-vertex').textContent,
		fragmentShader: document.getElementById('sky-fragment').textContent
	});

	skyBox = new THREE.Mesh(geometry, material);
	skyBox.scale.set(-1, 1, 1);
	skyBox.eulerOrder = 'XZY';
	skyBox.renderDepth = 1000.0;
	scene.add(skyBox);
}
function animate() {

	requestAnimationFrame( animate );
	for (var obj in objects)
		objects[obj].update()

	renderer.render( scene, camera );

}<commit_msg>Player movement<commit_after>var scene, camera, renderer;
var geometry, material, mesh;
var SKYBOX_MAX_RADIUS = 10000;
var MAX_BOUND = 1000;

var objects = [new Ball(new THREE.Vector3(0,0,0), new THREE.Vector3(30,29,10), 0xff33bb),new Ball(new THREE.Vector3(-2,0,0), new THREE.Vector3(10,12,3), 0xa351bf)]
var players = [new Player(5,0xccaacc)];
$(document).ready(function()
{
	init();
	createSkyBox();
	for (var obj in objects)
		scene.add(objects[obj].mesh);
	for (var player in players)
		scene.add(players[player].mesh);
	scene.add(new THREE.Mesh(
		new THREE.BoxGeometry(MAX_BOUND*2,MAX_BOUND*2,MAX_BOUND*2),
		new THREE.MeshPhongMaterial({color:0x0A0A0A, transparent: true, side: THREE.DoubleSide, opacity: 0.2})));
	animate();
	console.log(objects[0])
});

function Ball(position,velocity,color){
	var RADIUS = 50;
	this.color = color;
	this.position = position;
	this.velocity = velocity;
	this.sphere = function(){
		return THREE.Sphere(position,RADIUS)
	}
	this.mesh = new THREE.Mesh(
			new THREE.SphereGeometry(RADIUS),
			new THREE.MeshPhongMaterial({color:this.color}));
	this.update = function(){
		this.position.add(velocity);
		if (Math.abs(this.position.x) > MAX_BOUND)
		{
			this.position.x = this.position.x > 0 ? MAX_BOUND : -MAX_BOUND;
			this.velocity.x *= -1;
		}
		if (Math.abs(this.position.y) > MAX_BOUND)
		{
			this.position.y = this.position.y > 0 ? MAX_BOUND : -MAX_BOUND;
			this.velocity.y *= -1;
		}
		if (Math.abs(this.position.z) > MAX_BOUND)
		{
			this.position.z = this.position.z > 0 ? MAX_BOUND : -MAX_BOUND;
			this.velocity.z *= -1;
		}
		this.mesh.translateX(position.x-this.mesh.position.x);
		this.mesh.translateY(position.y-this.mesh.position.y);
		this.mesh.translateZ(position.z-this.mesh.position.z);
	}
}

function Player(num,color){
	var SIZE = 300;
	this.color = color;
	this.position = new THREE.Vector2(0,0);
	this.mesh = new THREE.Mesh(
		new THREE.PlaneGeometry(SIZE,SIZE),
		new THREE.MeshPhongMaterial({color:this.color, side:THREE.DoubleSide}))
	/* Positions:
		0: -x
		1: +x
		2: -y
		3: +y
		4: -z
		5: +z
	*/
	switch (num){
		case 0:
			this.mesh.rotation.y = -Math.PI/2;
			this.mesh.translateZ(MAX_BOUND);
			break;
		case 1:
			this.mesh.rotation.y = Math.PI/2;
			this.mesh.translateZ(MAX_BOUND);
			break;
		case 2:
			this.mesh.rotation.x = Math.PI/2;
			this.mesh.translateZ(MAX_BOUND);
			break;
		case 3:
			this.mesh.rotation.x = -Math.PI/2;
			this.mesh.translateZ(MAX_BOUND);
			break;
		case 4:
			this.mesh.rotation.z = Math.PI/2;
			this.mesh.translateZ(MAX_BOUND);
			break;
		case 5:
			this.mesh.rotation.z = -Math.PI/2;
			this.mesh.translateZ(-MAX_BOUND);
			break;
	}
	this.moveY = function(step){

		if (this.position.y + step > MAX_BOUND/2 + SIZE)
		{
			step = MAX_BOUND/2 + SIZE - this.position.y;
			this.position.y = MAX_BOUND/2 + SIZE;
		}
		else if (this.position.y + step < -MAX_BOUND/2 - SIZE)
		{
			step = -MAX_BOUND/2 - SIZE - this.position.y;
			this.position.y = -MAX_BOUND/2 - SIZE;
		}
		else
		{
			this.position.y += step;
		}

		switch (num){
			case 0:
				this.mesh.translateY(step);
				break;
			case 1:
				this.mesh.translateY(step);
				break;
			case 2:
				this.mesh.translateY(step);
				break;
			case 3:
				this.mesh.translateX(step);
				break;
			case 4:
				this.mesh.translateX(step);
				break;
			case 5:
				this.mesh.translateX(-step);
				break;
		}
	}
	this.moveX = function(step){
		if (this.position.x + step > MAX_BOUND/2 + SIZE)
		{
			step = MAX_BOUND/2 + SIZE - this.position.x;
			this.position.x = MAX_BOUND/2 + SIZE;
		}
		else if (this.position.x + step < -MAX_BOUND/2 - SIZE)
		{
			step = -MAX_BOUND/2 - SIZE - this.position.x;
			this.position.x = -MAX_BOUND/2 - SIZE;
		}
		else {
			this.position.x += step;
		}
		switch (num){
			case 0:
				this.mesh.translateX(step);
				break;
			case 1:
				this.mesh.translateX(step);
				break;
			case 2:
				this.mesh.translateX(step);
				break;
			case 3:
				this.mesh.translateY(-step);
				break;
			case 4:
				this.mesh.translateY(-step);
				break;
			case 5:
				this.mesh.translateY(-step);
				break;
		}
	}

}
function init() {

	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
	camera.position.z = 1000;
	var light = new THREE.PointLight( 0xffffff, 1, 3000 );
	light.position.set( 0, 0, 0 );
	scene.add(light);
	scene.add(new THREE.AmbientLight( 0x323232 ));
	renderer = new THREE.WebGLRenderer();
	renderer.autoClear = true;
	renderer.setSize( window.innerWidth, window.innerHeight );
	controls = new THREE.OrbitControls(camera, renderer.domElement);
	controls.maxDistance = SKYBOX_MAX_RADIUS;
	controls.noPan = true;
	controls.dollyOut(900);
	$("body").append(renderer.domElement);

}
function createSkyBox() {
	var geometry = new THREE.SphereGeometry(SKYBOX_MAX_RADIUS,10,10);
	var uniforms = {
		texture: { type: 't', value: THREE.ImageUtils.loadTexture('assets/skybox.jpg') }
	};

	var material = new THREE.ShaderMaterial( {
		uniforms:       uniforms,
		vertexShader:   document.getElementById('sky-vertex').textContent,
		fragmentShader: document.getElementById('sky-fragment').textContent
	});

	skyBox = new THREE.Mesh(geometry, material);
	skyBox.scale.set(-1, 1, 1);
	skyBox.eulerOrder = 'XZY';
	skyBox.renderDepth = 1000.0;
	scene.add(skyBox);
}
function animate() {

	requestAnimationFrame( animate );
	for (var obj in objects)
		objects[obj].update()
	controls.update();
	renderer.render( scene, camera );

}<|endoftext|>


<commit_before>var sqrt2 = Math.sqrt(2)
var π = Math.PI

var width = 400,
    height = 400,
    margin = {left: 100, right: 100, top: 100, bottom: 100}

var svg = d3.select('#dragon-curve')
    .append('svg')
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

function addLine(a, b, ℓ, θ){
  svg.append('path')
      .attr('d', ['M', a, 'L', b].join(''))

  var done;
  svg.append('rect')
      .attr({x: a[0], y: a[1], height: ℓ/sqrt2, width: ℓ/sqrt2})
      .attr('transform', 'rotate(-45,' + a + ')')
      .on('mouseover', function(){
        if (done) return

        var ℓ1 = ℓ/2*sqrt2

        var θ1 = (θ - 45) % 360
        var b1 = extendLine(a, ℓ1, θ1)
        addLine(a, b1, ℓ1, θ + 45)

        var θ2 = (θ + 45) % 360
        var a1 = extendLine(b, ℓ1, θ2 - 180)
        addLine(a1, b, ℓ1, θ - 45)

        done = true
      })
}

var length = width
addLine([0, height/2], [length, height/2], length, 90)

function extendLine(a, ℓ, θ){
  // debugger
  return [a[0] + ℓ*Math.sin(θ*π/180), a[1] + ℓ*Math.cos(θ*π/180)]
}<commit_msg>adjusting angle increase<commit_after>var sqrt2 = Math.sqrt(2)
var π = Math.PI

var width = 400,
    height = 400,
    margin = {left: 100, right: 100, top: 100, bottom: 100}

var svg = d3.select('#dragon-curve')
    .append('svg')
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

function addLine(a, b, ℓ, θ){
  var line = svg.append('path')
      .attr('d', ['M', a, 'L', b].join(''))

  var done;
  var rect = svg.append('rect')
      .attr({x: a[0], y: a[1], height: ℓ/sqrt2, width: ℓ/sqrt2})
      .attr('transform', ['rotate(', θ - 135 ,',', a, ')'].join(''))
      .on('mouseover', function(){
        if (done) return

        var ℓ1 = ℓ/2*sqrt2

        var θ1 = (θ - 45) % 360
        var b1 = extendLine(a, ℓ1, θ1)
        addLine(a, b1, ℓ1, θ1)

        var θ2 = (θ + 45) % 360
        var a1 = extendLine(b, ℓ1, θ2 - 180)
        addLine(a1, b, ℓ1, θ2)

        line.style('opacity', .2)
        rect.style('opacity', .05)
        done = true
      })
}

var length = width
addLine([0, height/2], [length, height/2], length, 90)

function extendLine(a, ℓ, θ){
  return [a[0] + ℓ*Math.sin(θ*π/180), a[1] + ℓ*Math.cos(θ*π/180)]
}<|endoftext|>


<commit_before>/**
 * @flow
 *
 * Building Hours "report a problem" screen.
 */

import * as React from 'react'
import {ScrollView, View, StyleSheet, Text} from 'react-native'
import moment from 'moment-timezone'
import {CellTextField} from '../../components/cells/textfield'
import {CellToggle} from '../../components/cells/toggle'
import {DeleteButtonCell} from '../../components/cells/delete-button'
import {ButtonCell} from '../../components/cells/button'
import * as c from '../../components/colors'
import {TableView, Section, Cell} from 'react-native-tableview-simple'
import type {
	BuildingType,
	NamedBuildingScheduleType,
	SingleBuildingScheduleType,
} from '../types'
import type {TopLevelViewPropsType} from '../../types'
import {summarizeDays, formatBuildingTimes, blankSchedule} from '../lib'
import {submitReport} from './submit'

const styles = StyleSheet.create({
	helpWrapper: {
		backgroundColor: c.white,
		borderWidth: StyleSheet.hairlineWidth,
		borderTopColor: c.iosHeaderTopBorder,
		borderBottomColor: c.iosHeaderBottomBorder,
		marginBottom: 10,
	},
	helpTitle: {
		fontSize: 16,
		fontWeight: 'bold',
		paddingTop: 15,
		paddingHorizontal: 15,
	},
	helpDescription: {
		fontSize: 14,
		paddingTop: 5,
		paddingBottom: 15,
		paddingHorizontal: 15,
	},
})

type Props = TopLevelViewPropsType & {
	navigation: {state: {params: {initialBuilding: BuildingType}}},
}

type State = {
	building: BuildingType,
}

export class BuildingHoursProblemReportView extends React.PureComponent<
	Props,
	State,
> {
	static navigationOptions = {
		title: 'Report a Problem',
	}

	state = {
		building: this.props.navigation.state.params.initialBuilding,
	}

	openEditor = (
		scheduleIdx: number,
		setIdx: number,
		set: ?SingleBuildingScheduleType = null,
	) => {
		this.props.navigation.navigate('BuildingHoursScheduleEditorView', {
			initialSet: set,
			onEditSet: (editedData: SingleBuildingScheduleType) =>
				this.editHoursRow(scheduleIdx, setIdx, editedData),
			onDeleteSet: () => this.deleteHoursRow(scheduleIdx, setIdx),
		})
	}

	editSchedule = (idx: number, newSchedule: NamedBuildingScheduleType) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]
			schedules.splice(idx, 1, newSchedule)

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	deleteSchedule = (idx: number) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]
			schedules.splice(idx, 1)

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	addSchedule = () => {
		this.setState(state => {
			return {
				...state,
				building: {
					...state.building,
					schedule: [
						...state.building.schedule,
						{
							title: 'Hours',
							hours: [blankSchedule()],
						},
					],
				},
			}
		})
	}

	addHoursRow = (idx: number) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]

			schedules[idx] = {
				...schedules[idx],
				hours: [...schedules[idx].hours, blankSchedule()],
			}

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	editHoursRow = (
		scheduleIdx: number,
		setIdx: number,
		newData: SingleBuildingScheduleType,
	) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]

			const hours = [...schedules[scheduleIdx].hours]
			hours.splice(setIdx, 1, newData)

			schedules[scheduleIdx] = {...schedules[scheduleIdx], hours}

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	deleteHoursRow = (scheduleIdx: number, setIdx: number) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]

			const hours = [...schedules[scheduleIdx].hours]
			hours.splice(setIdx, 1)

			schedules[scheduleIdx] = {...schedules[scheduleIdx], hours}

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	submit = () => {
		console.log(JSON.stringify(this.state.building))
		submitReport(
			this.props.navigation.state.params.initialBuilding,
			this.state.building,
		)
	}

	render() {
		const {schedule: schedules = []} = this.state.building

		return (
			<ScrollView>
				<View style={styles.helpWrapper}>
					<Text style={styles.helpTitle}>Thanks for spotting a problem!</Text>
					<Text style={styles.helpDescription}>
						If you could tell us what the new times are, we’d greatly
						appreciate it.
					</Text>
				</View>

				<TableView>
					{schedules.map((s, i) => (
						<EditableSchedule
							key={i}
							addRow={this.addHoursRow}
							editRow={this.openEditor}
							onDelete={this.deleteSchedule}
							onEditSchedule={this.editSchedule}
							schedule={s}
							scheduleIndex={i}
						/>
					))}

						<Cell
							accessory="DisclosureIndicator"
							onPress={this.addSchedule}
							title="Add New Schedule"
						/>

						<ButtonCell onPress={this.submit} title="Submit Report" />

				</TableView>
			</ScrollView>
		)
	}
}

type EditableScheduleProps = {
	schedule: NamedBuildingScheduleType,
	scheduleIndex: number,
	addRow: (idx: number) => any,
	editRow: (
		schedIdx: number,
		setIdx: number,
		set: SingleBuildingScheduleType,
	) => any,
	onEditSchedule: (idx: number, set: NamedBuildingScheduleType) => any,
	onDelete: (idx: number) => any,
}

class EditableSchedule extends React.PureComponent<EditableScheduleProps> {
	onEdit = data => {
		const idx = this.props.scheduleIndex
		this.props.onEditSchedule(idx, {
			...this.props.schedule,
			...data,
		})
	}

	editTitle = (newValue: string) => {
		this.onEdit({title: newValue})
	}

	editNotes = (newValue: string) => {
		this.onEdit({notes: newValue})
	}

	toggleChapel = (newValue: boolean) => {
		this.onEdit({closedForChapelTime: newValue})
	}

	addHoursRow = () => {
		this.props.addRow(this.props.scheduleIndex)
	}

	delete = () => {
		this.props.onDelete(this.props.scheduleIndex)
	}

	openEditor = (setIndex: number, hoursSet: SingleBuildingScheduleType) => {
		this.props.editRow(this.props.scheduleIndex, setIndex, hoursSet)
	}

	render() {
		const {schedule} = this.props
		const now = moment()

		return (
			<View>

					<TitleCell onChange={this.editTitle} text={schedule.title || ''} />
					<NotesCell onChange={this.editNotes} text={schedule.notes || ''} />

					{/*<CellToggle
						label="Closes for Chapel"
						onChange={this.toggleChapel}
						value={Boolean(schedule.closedForChapelTime)}
					/>*/}

					{schedule.hours.map((set, i) => (
						<TimesCell
							key={i}
							now={now}
							onPress={this.openEditor}
							set={set}
							setIndex={i}
						/>
					))}

					<Cell
						accessory="DisclosureIndicator"
						onPress={this.addHoursRow}
						title="Add More Hours"
					/>

					<DeleteButtonCell onPress={this.delete} title="Delete Schedule" />

			</View>
		)
	}
}

type TextFieldProps = {text: string, onChange: string => any}
// "Title" will become a textfield like the login form
const TitleCell = ({text, onChange = () => {}}: TextFieldProps) => (
	<CellTextField
		autoCapitalize="words"
		hideLabel={true}
		onChangeText={onChange}
		onSubmitEditing={onChange}
		placeholder="Title"
		returnKeyType="done"
		value={text}
	/>
)

// "Notes" will become a big textarea
const NotesCell = ({text, onChange}: TextFieldProps) => (
	<CellTextField
		autoCapitalize="sentences"
		hideLabel={true}
		onChangeText={onChange}
		onSubmitEditing={onChange}
		placeholder="Notes"
		returnKeyType="done"
		value={text}
	/>
)

type TimesCellProps = {
	set: SingleBuildingScheduleType,
	setIndex: number,
	onPress: (setIdx: number, set: SingleBuildingScheduleType) => any,
	now: moment,
}

class TimesCell extends React.PureComponent<TimesCellProps> {
	onPress = () => {
		this.props.onPress(this.props.setIndex, this.props.set)
	}

	render() {
		const {set, now} = this.props

		return (
			<Cell
				accessory="DisclosureIndicator"
				cellStyle="RightDetail"
				detail={formatBuildingTimes(set, now)}
				onPress={this.onPress}
				title={set.days.length ? summarizeDays(set.days) : 'Days'}
			/>
		)
	}
}
<commit_msg>fix lint error<commit_after>/**
 * @flow
 *
 * Building Hours "report a problem" screen.
 */

import * as React from 'react'
import {ScrollView, View, StyleSheet, Text} from 'react-native'
import moment from 'moment-timezone'
import {CellTextField} from '../../components/cells/textfield'
// import {CellToggle} from '../../components/cells/toggle'
import {DeleteButtonCell} from '../../components/cells/delete-button'
import {ButtonCell} from '../../components/cells/button'
import * as c from '../../components/colors'
import {TableView, Section, Cell} from 'react-native-tableview-simple'
import type {
	BuildingType,
	NamedBuildingScheduleType,
	SingleBuildingScheduleType,
} from '../types'
import type {TopLevelViewPropsType} from '../../types'
import {summarizeDays, formatBuildingTimes, blankSchedule} from '../lib'
import {submitReport} from './submit'

const styles = StyleSheet.create({
	helpWrapper: {
		backgroundColor: c.white,
		borderWidth: StyleSheet.hairlineWidth,
		borderTopColor: c.iosHeaderTopBorder,
		borderBottomColor: c.iosHeaderBottomBorder,
		marginBottom: 10,
	},
	helpTitle: {
		fontSize: 16,
		fontWeight: 'bold',
		paddingTop: 15,
		paddingHorizontal: 15,
	},
	helpDescription: {
		fontSize: 14,
		paddingTop: 5,
		paddingBottom: 15,
		paddingHorizontal: 15,
	},
})

type Props = TopLevelViewPropsType & {
	navigation: {state: {params: {initialBuilding: BuildingType}}},
}

type State = {
	building: BuildingType,
}

export class BuildingHoursProblemReportView extends React.PureComponent<
	Props,
	State,
> {
	static navigationOptions = {
		title: 'Report a Problem',
	}

	state = {
		building: this.props.navigation.state.params.initialBuilding,
	}

	openEditor = (
		scheduleIdx: number,
		setIdx: number,
		set: ?SingleBuildingScheduleType = null,
	) => {
		this.props.navigation.navigate('BuildingHoursScheduleEditorView', {
			initialSet: set,
			onEditSet: (editedData: SingleBuildingScheduleType) =>
				this.editHoursRow(scheduleIdx, setIdx, editedData),
			onDeleteSet: () => this.deleteHoursRow(scheduleIdx, setIdx),
		})
	}

	editSchedule = (idx: number, newSchedule: NamedBuildingScheduleType) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]
			schedules.splice(idx, 1, newSchedule)

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	deleteSchedule = (idx: number) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]
			schedules.splice(idx, 1)

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	addSchedule = () => {
		this.setState(state => {
			return {
				...state,
				building: {
					...state.building,
					schedule: [
						...state.building.schedule,
						{
							title: 'Hours',
							hours: [blankSchedule()],
						},
					],
				},
			}
		})
	}

	addHoursRow = (idx: number) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]

			schedules[idx] = {
				...schedules[idx],
				hours: [...schedules[idx].hours, blankSchedule()],
			}

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	editHoursRow = (
		scheduleIdx: number,
		setIdx: number,
		newData: SingleBuildingScheduleType,
	) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]

			const hours = [...schedules[scheduleIdx].hours]
			hours.splice(setIdx, 1, newData)

			schedules[scheduleIdx] = {...schedules[scheduleIdx], hours}

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	deleteHoursRow = (scheduleIdx: number, setIdx: number) => {
		this.setState(state => {
			const schedules = [...state.building.schedule]

			const hours = [...schedules[scheduleIdx].hours]
			hours.splice(setIdx, 1)

			schedules[scheduleIdx] = {...schedules[scheduleIdx], hours}

			return {
				...state,
				building: {
					...state.building,
					schedule: schedules,
				},
			}
		})
	}

	submit = () => {
		console.log(JSON.stringify(this.state.building))
		submitReport(
			this.props.navigation.state.params.initialBuilding,
			this.state.building,
		)
	}

	render() {
		const {schedule: schedules = []} = this.state.building

		return (
			<ScrollView>
				<View style={styles.helpWrapper}>
					<Text style={styles.helpTitle}>Thanks for spotting a problem!</Text>
					<Text style={styles.helpDescription}>
						If you could tell us what the new times are, we’d greatly
						appreciate it.
					</Text>
				</View>

				<TableView>
					{schedules.map((s, i) => (
						<EditableSchedule
							key={i}
							addRow={this.addHoursRow}
							editRow={this.openEditor}
							onDelete={this.deleteSchedule}
							onEditSchedule={this.editSchedule}
							schedule={s}
							scheduleIndex={i}
						/>
					))}

						<Cell
							accessory="DisclosureIndicator"
							onPress={this.addSchedule}
							title="Add New Schedule"
						/>

						<ButtonCell onPress={this.submit} title="Submit Report" />

				</TableView>
			</ScrollView>
		)
	}
}

type EditableScheduleProps = {
	schedule: NamedBuildingScheduleType,
	scheduleIndex: number,
	addRow: (idx: number) => any,
	editRow: (
		schedIdx: number,
		setIdx: number,
		set: SingleBuildingScheduleType,
	) => any,
	onEditSchedule: (idx: number, set: NamedBuildingScheduleType) => any,
	onDelete: (idx: number) => any,
}

class EditableSchedule extends React.PureComponent<EditableScheduleProps> {
	onEdit = data => {
		const idx = this.props.scheduleIndex
		this.props.onEditSchedule(idx, {
			...this.props.schedule,
			...data,
		})
	}

	editTitle = (newValue: string) => {
		this.onEdit({title: newValue})
	}

	editNotes = (newValue: string) => {
		this.onEdit({notes: newValue})
	}

	toggleChapel = (newValue: boolean) => {
		this.onEdit({closedForChapelTime: newValue})
	}

	addHoursRow = () => {
		this.props.addRow(this.props.scheduleIndex)
	}

	delete = () => {
		this.props.onDelete(this.props.scheduleIndex)
	}

	openEditor = (setIndex: number, hoursSet: SingleBuildingScheduleType) => {
		this.props.editRow(this.props.scheduleIndex, setIndex, hoursSet)
	}

	render() {
		const {schedule} = this.props
		const now = moment()

		return (
			<View>

					<TitleCell onChange={this.editTitle} text={schedule.title || ''} />
					<NotesCell onChange={this.editNotes} text={schedule.notes || ''} />

					{/*<CellToggle
						label="Closes for Chapel"
						onChange={this.toggleChapel}
						value={Boolean(schedule.closedForChapelTime)}
					/>*/}

					{schedule.hours.map((set, i) => (
						<TimesCell
							key={i}
							now={now}
							onPress={this.openEditor}
							set={set}
							setIndex={i}
						/>
					))}

					<Cell
						accessory="DisclosureIndicator"
						onPress={this.addHoursRow}
						title="Add More Hours"
					/>

					<DeleteButtonCell onPress={this.delete} title="Delete Schedule" />

			</View>
		)
	}
}

type TextFieldProps = {text: string, onChange: string => any}
// "Title" will become a textfield like the login form
const TitleCell = ({text, onChange = () => {}}: TextFieldProps) => (
	<CellTextField
		autoCapitalize="words"
		hideLabel={true}
		onChangeText={onChange}
		onSubmitEditing={onChange}
		placeholder="Title"
		returnKeyType="done"
		value={text}
	/>
)

// "Notes" will become a big textarea
const NotesCell = ({text, onChange}: TextFieldProps) => (
	<CellTextField
		autoCapitalize="sentences"
		hideLabel={true}
		onChangeText={onChange}
		onSubmitEditing={onChange}
		placeholder="Notes"
		returnKeyType="done"
		value={text}
	/>
)

type TimesCellProps = {
	set: SingleBuildingScheduleType,
	setIndex: number,
	onPress: (setIdx: number, set: SingleBuildingScheduleType) => any,
	now: moment,
}

class TimesCell extends React.PureComponent<TimesCellProps> {
	onPress = () => {
		this.props.onPress(this.props.setIndex, this.props.set)
	}

	render() {
		const {set, now} = this.props

		return (
			<Cell
				accessory="DisclosureIndicator"
				cellStyle="RightDetail"
				detail={formatBuildingTimes(set, now)}
				onPress={this.onPress}
				title={set.days.length ? summarizeDays(set.days) : 'Days'}
			/>
		)
	}
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2018 Kinvey Inc.
 *
 * 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.
 */

const http = require('http');
const https = require('https');
const data = require('./service/data');
const flex = require('../package.json');
const functions = require('./service/functions');
const auth = require('./service/auth');
const moduleGenerator = require('./service/moduleGenerator');
const logger = require('./service/logger');
const receiver = require('kinvey-code-task-runner');
const kinveyErrors = require('kinvey-datalink-errors');

let terminated = false;

http.globalAgent.maxSockets = 100;
https.globalAgent.maxSockets = 100;

class Flex {
  constructor(options, callback) {
    let gracefulShutdownTimeout;

    if (!callback && typeof options === 'function') {
      callback = options;
      options = null;
    }

    options = options || {};

    options.type = process.env.SDK_RECEIVER === 'tcp' ? 'tcp' : 'http';

    if (options.type === 'tcp') {
      delete options.host;
      delete options.port;
    }

    this.data = this.dataLink = data;
    this.functions = this.businessLogic = functions;
    this.auth = auth;
    this.logger = logger;
    this.moduleGenerator = moduleGenerator;
    this.version = flex.version;

    if (options.sharedSecret) {
      this.sharedSecret = options.sharedSecret;
    }

    function terminate(err) {
      clearTimeout(gracefulShutdownTimeout);

      if (err) {
        process.exit(-1);
      }
      process.exit();
    }

    function shutdown() {
      if (terminated) {
        return terminate('Force quit!');
      }

      terminated = true;
      gracefulShutdownTimeout = setTimeout(terminate, 50000);
      receiver.stop((err) => terminate(err));
    }

    // TODO Remove legacy taskType values
    const taskReceivedCallback = ((task, completionCallback) => {
      task.sdkVersion = this.version;

      if (this.sharedSecret != null && task.taskType !== 'serviceDiscovery' && task.taskType !== 'logger' && task.taskType !== 'moduleGenerator' && this.sharedSecret !== task.authKey) {
        task.response = task.response || {};
        const result = task.response;
        result.body = kinveyErrors.generateKinveyError('Unauthorized', 'The Authorization Key was not valid or missing.').toJSON();
        result.statusCode = result.body.statusCode;
        delete result.body.statusCode;
        task.response.continue = false;
        return completionCallback(null, task);
      }

      if ((!this[task.taskType] && task.taskType !== 'serviceDiscovery') || task.taskType === 'logger' || task.taskType === 'moduleGenerator') {
        task.response = task.response || {};
        const result = task.response;
        result.body = kinveyErrors.generateKinveyError('BadRequest', 'Invalid task Type').toJSON();
        result.statusCode = result.body.statusCode;
        delete result.body.statusCode;
        task.response.continue = false;
        return completionCallback(null, task);
      }

      if (task.taskType === 'serviceDiscovery') {
        task.discoveryObjects = {
          dataLink: {
            serviceObjects: this.data.getServiceObjects()
          },
          businessLogic: {
            handlers: this.functions.getHandlers()
          },
          auth: {
            handlers: this.auth.getHandlers()
          }
        };
        return completionCallback(null, task);
      }

      return this[task.taskType].process(task, this.moduleGenerator.generate(task), (taskWithError, task) => {
        completionCallback(null, taskWithError || task);
      });
    });

    receiver.start(options, taskReceivedCallback, (err) => {
      if (err != null) {
        return callback(new Error(`Could not start task receiver: ${err}`));
      }
      return callback(null, this);
    });

    process.on('SIGTERM', shutdown);
    process.on('SIGKILL', shutdown);
    process.on('SIGINT', shutdown);
  }
}

function generateFlexService(options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }

  return new Flex(options, (err, service) => {
    callback(err, service);
  });
}

exports.service = generateFlexService;
<commit_msg>Added logging<commit_after>/**
 * Copyright (c) 2018 Kinvey Inc.
 *
 * 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.
 */

const http = require('http');
const https = require('https');
const data = require('./service/data');
const flex = require('../package.json');
const functions = require('./service/functions');
const auth = require('./service/auth');
const moduleGenerator = require('./service/moduleGenerator');
const logger = require('./service/logger');
const receiver = require('kinvey-code-task-runner');
const kinveyErrors = require('kinvey-datalink-errors');

let terminated = false;

http.globalAgent.maxSockets = 100;
https.globalAgent.maxSockets = 100;

class Flex {
  constructor(options, callback) {
    let gracefulShutdownTimeout;

    if (!callback && typeof options === 'function') {
      callback = options;
      options = null;
    }

    options = options || {};

    options.type = process.env.SDK_RECEIVER === 'tcp' ? 'tcp' : 'http';

    if (options.type === 'tcp') {
      delete options.host;
      delete options.port;
    }

    this.data = this.dataLink = data;
    this.functions = this.businessLogic = functions;
    this.auth = auth;
    this.logger = logger;
    this.moduleGenerator = moduleGenerator;
    this.version = flex.version;

    if (options.sharedSecret) {
      this.sharedSecret = options.sharedSecret;
    }

    function terminate(err) {
      clearTimeout(gracefulShutdownTimeout);

      if (err) {
        console.log(`Shutdown Error: ${err}`);
        process.exit(-1);
      }
      process.exit();
    }

    function shutdown() {
      if (terminated) {
        // non-graceful shutdown, requires two successive signals
        console.log('\nForced quit!\n');
        return terminate('Force quit!');
      }

      terminated = true;
      console.log('Signal received, initiating graceful shutdown.  Press ctrl-c or send SIGTERM/SIGKILL/SIGINT to force-quit immediately.');
      gracefulShutdownTimeout = setTimeout(terminate, 50000);
      receiver.stop((err) => terminate(err));
    }

    // TODO Remove legacy taskType values
    const taskReceivedCallback = ((task, completionCallback) => {
      task.sdkVersion = this.version;

      if (this.sharedSecret != null && task.taskType !== 'serviceDiscovery' && task.taskType !== 'logger' && task.taskType !== 'moduleGenerator' && this.sharedSecret !== task.authKey) {
        task.response = task.response || {};
        const result = task.response;
        result.body = kinveyErrors.generateKinveyError('Unauthorized', 'The Authorization Key was not valid or missing.').toJSON();
        result.statusCode = result.body.statusCode;
        delete result.body.statusCode;
        task.response.continue = false;
        return completionCallback(null, task);
      }

      if ((!this[task.taskType] && task.taskType !== 'serviceDiscovery') || task.taskType === 'logger' || task.taskType === 'moduleGenerator') {
        task.response = task.response || {};
        const result = task.response;
        result.body = kinveyErrors.generateKinveyError('BadRequest', 'Invalid task Type').toJSON();
        result.statusCode = result.body.statusCode;
        delete result.body.statusCode;
        task.response.continue = false;
        return completionCallback(null, task);
      }

      if (task.taskType === 'serviceDiscovery') {
        task.discoveryObjects = {
          dataLink: {
            serviceObjects: this.data.getServiceObjects()
          },
          businessLogic: {
            handlers: this.functions.getHandlers()
          },
          auth: {
            handlers: this.auth.getHandlers()
          }
        };
        return completionCallback(null, task);
      }

      return this[task.taskType].process(task, this.moduleGenerator.generate(task), (taskWithError, task) => {
        completionCallback(null, taskWithError || task);
      });
    });

    receiver.start(options, taskReceivedCallback, (err) => {
      if (err != null) {
        return callback(new Error(`Could not start task receiver: ${err}`));
      }
      return callback(null, this);
    });

    process.on('SIGTERM', shutdown);
    process.on('SIGKILL', shutdown);
    process.on('SIGINT', shutdown);
  }
}

function generateFlexService(options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }

  return new Flex(options, (err, service) => {
    callback(err, service);
  });
}

exports.service = generateFlexService;
<|endoftext|>


<commit_before>'use strict';

var fs          = require('fs'),
    path        = require('path'),
    readify     = require('readify/legacy'),
    size        = require('trammel'),

    check       = require('checkup'),
    time        = require('timem'),
    win         = require('win32/legacy'),

    copymitter  = require('copymitter'),
    remy        = require('remy'),
    mkdir       = require('mkdirp'),

    flop        = exports,

    isWin       = process.platform === 'win32';

exports.create  = function(path, callback) {
    check
        .type('path', path, 'string')
        .type('callback', callback, 'function');

    mkdir(path, callback);
};

exports.read    = function(path, type, callback) {
    if (!callback)
        callback = type;

    check
        .type('path', path, 'string')
        .type('callback', callback, 'function');

    switch (type) {
    case 'size':
        size(path, callback);
        break;

    case 'size raw':
        size(path, {type: 'raw'}, callback);
        break;

    case 'time':
        time(path, callback);
        break;

    case 'time raw':
        time(path, 'raw', callback);
        break;

    default:
        if (isWin && path === '/')
            getRoot(callback);
        else
            readify(path, callback);
        break;
    }
};

exports.delete  = function(path, files, callback) {
    var wasError, rm;

    if (!callback) {
        callback    = files;
        files       = null;
    }

    check
        .type('path', path, 'string')
        .type('callback', callback, 'function');

    rm = remy(path, files);

    rm.on('error', function(error) {
        callback(error);
        wasError = true;
        rm.abort();
    });

    rm.on('end', function() {
        if (!wasError)
            callback();
    });
};

exports.move    = function(from, to, callback) {
    check
        .type('from', from, 'string')
        .type('to', to, 'string')
        .type('callback', callback, 'function');

    fs.rename(from, to, function(error) {
        var regexp = /EXDEV|ENOTEMPTY/;

        if (!error || !regexp.test(error.code))
            callback(error);
        else
            flop.copy(from, to, function(error) {
                if (error)
                    callback(error);
                else
                    flop.delete(from, callback);
            });
    });
};

exports.copy    = function(from, to, callback) {
    var wasError, cp, fromPart, toPart, name;

    check
        .type('from', from, 'string')
        .type('to', to, 'string')
        .type('callback', callback, 'function');

    name        = path.basename(from);
    fromPart    = from.replace(name, '');
    toPart      = to.replace(name, '');

    cp = copymitter(fromPart, toPart, [name]);

    cp.on('error', function(error) {
        callback(error);
        wasError = true;
        cp.abort();
    });

    cp.on('end', function() {
        if (!wasError)
            callback();
    });
};

function getRoot(callback) {
    win.getVolumes(function(error, volumes) {
        var data = {
            path    : '/',
            files   : []
        };

        if (!error)
            data.files = volumes.map(function(volume) {
                return {
                    name: volume,
                    size: 'dir',
                    date: '--.--.----',
                    mode: '--- --- ---',
                    owner: 0
                };
            });

        callback(error, data);
    });
}

<commit_msg>chore(flop) one var -> multiple var<commit_after>'use strict';

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

var readify = require('readify/legacy');
var size = require('trammel');
var check = require('checkup');
var time = require('timem');
var win = require('win32/legacy');

var copymitter = require('copymitter');
var remy = require('remy');
var mkdir = require('mkdirp');

var flop = exports;

var isWin = process.platform === 'win32';

exports.create = function(path, callback) {
    check
        .type('path', path, 'string')
        .type('callback', callback, 'function');

    mkdir(path, callback);
};

exports.read    = function(path, type, callback) {
    if (!callback)
        callback = type;

    check
        .type('path', path, 'string')
        .type('callback', callback, 'function');

    switch (type) {
    case 'size':
        size(path, callback);
        break;

    case 'size raw':
        size(path, {type: 'raw'}, callback);
        break;

    case 'time':
        time(path, callback);
        break;

    case 'time raw':
        time(path, 'raw', callback);
        break;

    default:
        if (isWin && path === '/')
            getRoot(callback);
        else
            readify(path, callback);
        break;
    }
};

exports.delete  = function(path, files, callback) {
    var wasError, rm;

    if (!callback) {
        callback    = files;
        files       = null;
    }

    check
        .type('path', path, 'string')
        .type('callback', callback, 'function');

    rm = remy(path, files);

    rm.on('error', function(error) {
        callback(error);
        wasError = true;
        rm.abort();
    });

    rm.on('end', function() {
        if (!wasError)
            callback();
    });
};

exports.move    = function(from, to, callback) {
    check
        .type('from', from, 'string')
        .type('to', to, 'string')
        .type('callback', callback, 'function');

    fs.rename(from, to, function(error) {
        var regexp = /EXDEV|ENOTEMPTY/;

        if (!error || !regexp.test(error.code))
            callback(error);
        else
            flop.copy(from, to, function(error) {
                if (error)
                    callback(error);
                else
                    flop.delete(from, callback);
            });
    });
};

exports.copy    = function(from, to, callback) {
    var wasError, cp, fromPart, toPart, name;

    check
        .type('from', from, 'string')
        .type('to', to, 'string')
        .type('callback', callback, 'function');

    name        = path.basename(from);
    fromPart    = from.replace(name, '');
    toPart      = to.replace(name, '');

    cp = copymitter(fromPart, toPart, [name]);

    cp.on('error', function(error) {
        callback(error);
        wasError = true;
        cp.abort();
    });

    cp.on('end', function() {
        if (!wasError)
            callback();
    });
};

function getRoot(callback) {
    win.getVolumes(function(error, volumes) {
        var data = {
            path    : '/',
            files   : []
        };

        if (!error)
            data.files = volumes.map(function(volume) {
                return {
                    name: volume,
                    size: 'dir',
                    date: '--.--.----',
                    mode: '--- --- ---',
                    owner: 0
                };
            });

        callback(error, data);
    });
}

<|endoftext|>


<commit_before>var util = require('util'),
    EventEmitter = require('events').EventEmitter;

var _ = require('underscore'),
    debug = require('debug')('hmpo:form'),
    dataFormatter = require('./formatting'),
    dataValidator = require('./validation'),
    ErrorClass = require('./error');

var Form = function Form(options) {
    if (!options) {
        throw new Error('Options must be provided');
    }
    if (!options.template) {
        throw new Error('A template must be provided');
    }
    options.defaultFormatters = options.defaultFormatters || ['trim', 'singlespaces', 'hyphens'];
    options.fields = options.fields || {};
    this.options = options;
    this.Error = ErrorClass;
};

util.inherits(Form, EventEmitter);

_.extend(Form.prototype, {
    requestHandler: function () {
        return function (req, res, callback) {
            var method = req.method.toLowerCase();
            if (typeof this[method] === 'function') {
                this[method](req, res, function (err) {
                    if (err) {
                        this.errorHandler(err, req, res, callback);
                    } else {
                        callback();
                    }
                }.bind(this));
            } else {
                res.send(405, 'Method ' + method + ' not allowed.');
            }
        }.bind(this);
    },
    get: function (req, res, callback) {
        var errors = this.getErrors(req, res);
        this._getValues(req, res, function (err, values) {
            if (err) {
                return callback(err);
            }
            debug('Rendering form for ' + req.path);
            if (_.isEmpty(this.options.fields) && this.options.next) {
                this.emit('complete', req, res);
            }
            _.extend(res.locals, {
                errors: errors,
                errorlist: _.map(errors, _.identity),
                values: values,
                options: this.options
            }, this.locals(req, res));
            this.render(req, res, callback);
        }.bind(this));
    },
    post: function (req, res, callback) {
        debug('Received POST for ' + req.path);
        this.setErrors(null, req, res);
        this._process(req, res, function (err) {
            if (err) {
                return callback(err);
            }
            this._validate(req, res, function (err) {
                if (err) {
                    debug('Validation failed for ' + req.path);
                    debug(err);
                    callback(err);
                } else {
                    debug('Validation passed for ' + req.path);
                    this.saveValues(req, res, function (err) {
                        if (err) {
                            callback(err);
                        } else {
                            this.successHandler(req, res);
                        }
                    }.bind(this));
                }
            }.bind(this));
        }.bind(this));
    },
    locals: function (/*req, res*/) {
        return {};
    },
    render: function (req, res/*, callback*/) {
        res.render(this.options.template);
    },
    // placeholder methods for persisting error messages between POST and GET
    getErrors: function (/*req, res*/) {
        return {};
    },
    setErrors: function (/*err, req, res*/) {},
    _validate: function (req, res, callback) {
        debug('Validating...');

        var formatter = dataFormatter(this.options.fields, this.options.defaultFormatters);

        var validator = dataValidator(this.options.fields),
            errors = {};

        _.each(req.form.values, function (value, key) {
            var emptyValue = formatter(key, '');

            var error = validator(key, value, req.form.values, emptyValue);
            if (error) {
                if (error.group) {
                    errors[error.group] = new this.Error(error.group, error);
                } else {
                    errors[error.key] = new this.Error(error.key, error);
                }
            }
        }, this);

        if (!_.isEmpty(errors)) {
            callback(errors);
        } else {
            this.validate(req, res, callback);
        }
    },
    validate: function (req, res, callback) {
        callback();
    },
    _process: function (req, res, callback) {
        req.form = { values: {} };
        var formatter = dataFormatter(this.options.fields, this.options.defaultFormatters);
        _.each(this.options.fields, function (value, key) {
            req.form.values[key] = formatter(key, req.body[key] || '');
        });
        this.process(req, res, callback);
    },
    process: function (req, res, callback) {
        callback();
    },
    _getValues: function (req, res, callback) {
        this.getValues(req, res, callback);
    },
    getValues: function (req, res, callback) {
        callback();
    },
    saveValues: function (req, res, callback) {
        callback();
    },
    getNextStep: function (req) {
        var next = this.options.next || req.path;
        return req.baseUrl + next;
    },
    getErrorStep: function (err, req) {
        var redirect = req.path;
        var redirectedError = _.find(err, function (error) {
            return error.redirect;
        });
        if (redirectedError) {
            redirect = redirectedError.redirect;
        }
        return req.baseUrl + redirect;
    },
    isValidationError: function (err) {
        return !_.isEmpty(err) && _.all(err, function (e) { return e instanceof this.Error; }, this);
    },
    errorHandler: function (err, req, res, callback) {
        if (this.isValidationError(err)) {
            this.setErrors(err, req, res);
            res.redirect(this.getErrorStep(err, req));
        } else {
            // if the error is not a validation error then throw and let the error handler pick it up
            return callback(err);
        }
    },
    successHandler: function (req, res) {
        this.emit('complete', req, res);
        res.redirect(this.getNextStep(req, res));
    }
});

module.exports = Form;
<commit_msg>Allow per-field validation<commit_after>var util = require('util'),
    EventEmitter = require('events').EventEmitter;

var _ = require('underscore'),
    debug = require('debug')('hmpo:form'),
    dataFormatter = require('./formatting'),
    dataValidator = require('./validation'),
    ErrorClass = require('./error');

var Form = function Form(options) {
    if (!options) {
        throw new Error('Options must be provided');
    }
    if (!options.template) {
        throw new Error('A template must be provided');
    }
    options.defaultFormatters = options.defaultFormatters || ['trim', 'singlespaces', 'hyphens'];
    options.fields = options.fields || {};
    this.options = options;
    this.Error = ErrorClass;

    this.formatter = dataFormatter(this.options.fields, this.options.defaultFormatters);
    this.validator = dataValidator(this.options.fields);
};

util.inherits(Form, EventEmitter);

_.extend(Form.prototype, {
    requestHandler: function () {
        return function (req, res, callback) {
            var method = req.method.toLowerCase();
            if (typeof this[method] === 'function') {
                this[method](req, res, function (err) {
                    if (err) {
                        this.errorHandler(err, req, res, callback);
                    } else {
                        callback();
                    }
                }.bind(this));
            } else {
                res.send(405, 'Method ' + method + ' not allowed.');
            }
        }.bind(this);
    },
    get: function (req, res, callback) {
        var errors = this.getErrors(req, res);
        this._getValues(req, res, function (err, values) {
            if (err) {
                return callback(err);
            }
            debug('Rendering form for ' + req.path);
            if (_.isEmpty(this.options.fields) && this.options.next) {
                this.emit('complete', req, res);
            }
            _.extend(res.locals, {
                errors: errors,
                errorlist: _.map(errors, _.identity),
                values: values,
                options: this.options
            }, this.locals(req, res));
            this.render(req, res, callback);
        }.bind(this));
    },
    post: function (req, res, callback) {
        debug('Received POST for ' + req.path);
        this.setErrors(null, req, res);
        this._process(req, res, function (err) {
            if (err) {
                return callback(err);
            }
            this._validate(req, res, function (err) {
                if (err) {
                    debug('Validation failed for ' + req.path);
                    debug(err);
                    callback(err);
                } else {
                    debug('Validation passed for ' + req.path);
                    this.saveValues(req, res, function (err) {
                        if (err) {
                            callback(err);
                        } else {
                            this.successHandler(req, res);
                        }
                    }.bind(this));
                }
            }.bind(this));
        }.bind(this));
    },
    locals: function (/*req, res*/) {
        return {};
    },
    render: function (req, res/*, callback*/) {
        res.render(this.options.template);
    },
    // placeholder methods for persisting error messages between POST and GET
    getErrors: function (/*req, res*/) {
        return {};
    },
    setErrors: function (/*err, req, res*/) {},
    _validate: function (req, res, callback) {
        debug('Validating...');

        var errors = {};

        _.each(req.form.values, function (value, key) {
            var error = this.validateField(key, req);
            if (error) {
                if (error.group) {
                    errors[error.group] = new this.Error(error.group, error);
                } else {
                    errors[error.key] = new this.Error(error.key, error);
                }
            }
        }, this);

        if (!_.isEmpty(errors)) {
            callback(errors);
        } else {
            this.validate(req, res, callback);
        }
    },
    validate: function (req, res, callback) {
        callback();
    },
    validateField: function (key, req) {
        var emptyValue = this.formatter(key, '');
        return this.validator(key, req.form.values[key], req.form.values, emptyValue);
    },
    _process: function (req, res, callback) {
        req.form = { values: {} };
        var formatter = dataFormatter(this.options.fields, this.options.defaultFormatters);
        _.each(this.options.fields, function (value, key) {
            req.form.values[key] = formatter(key, req.body[key] || '');
        });
        this.process(req, res, callback);
    },
    process: function (req, res, callback) {
        callback();
    },
    _getValues: function (req, res, callback) {
        this.getValues(req, res, callback);
    },
    getValues: function (req, res, callback) {
        callback();
    },
    saveValues: function (req, res, callback) {
        callback();
    },
    getNextStep: function (req) {
        var next = this.options.next || req.path;
        return req.baseUrl + next;
    },
    getErrorStep: function (err, req) {
        var redirect = req.path;
        var redirectedError = _.find(err, function (error) {
            return error.redirect;
        });
        if (redirectedError) {
            redirect = redirectedError.redirect;
        }
        return req.baseUrl + redirect;
    },
    isValidationError: function (err) {
        return !_.isEmpty(err) && _.all(err, function (e) { return e instanceof this.Error; }, this);
    },
    errorHandler: function (err, req, res, callback) {
        if (this.isValidationError(err)) {
            this.setErrors(err, req, res);
            res.redirect(this.getErrorStep(err, req));
        } else {
            // if the error is not a validation error then throw and let the error handler pick it up
            return callback(err);
        }
    },
    successHandler: function (req, res) {
        this.emit('complete', req, res);
        res.redirect(this.getNextStep(req, res));
    }
});

module.exports = Form;
<|endoftext|>


<commit_before>const $ = require('jquery');

function Lingo(){
  $(document).ready(function(){
    $('#start-button').on('click',function(){
      console.log('congrats');
      // generateMysteryWord();
      // hideMysteryWord();
      // renderMysteryWord();
    });
  });

  Lingo.prototype.generateWordArray = function(word) {
    return word.toLowerCase().split('');
  };
  Lingo.prototype.checkWordArrayForLetter = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return true;
      }
    }
  };

  Lingo.prototype.generateMysteryWord = function(array) {
      var mysteryWord = array[(Math.floor(Math.random()*(array.length)))];
      return mysteryWord;
  };

  Lingo.prototype.getCharIndex = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return i;
      }
    }
  };

  Lingo.prototype.getGridColor = function (wordArray, character, index) {
     var mysteryCharacterIndex = this.getCharIndex(wordArray, character);
     if (mysteryCharacterIndex === index) { return 'green'; }

     var characterExistsInWord = this.checkWordArrayForLetter(wordArray, character);
     if (characterExistsInWord) { return 'yellow'; }
     else { return 'red'; }
   };

var guess = $('input').on('keypress',function(event){
  if (isLetter(event)) {
    var nextInput = guess.get(guess.index(this)+1);
    if (nextInput) {
    nextInput.focus();
  } else { event.preventDefault();}
}
  function swapRow(){
    var row = guess.closest('tr');
    row.insertAfter(row.next());
  }
  function clearInputRow(){
    guess.map(function(){
      return this.value = "";
    });
  }
  function getWordArray(){
    var wordArray = guess.map(function(){
       return this.value;
    }).get();
    return wordArray;
  }
  function newWordRow(){
    var wordArray = getWordArray();
    return "
"+wordArray[0]+"	"+wordArray[1]+"	"+wordArray[2]+"	"+wordArray[3]+"	"+wordArray[4]+"
";
  }
  function prependRow(){
    guess.closest('tr').after(newWordRow());
  }
  if (rowIsFilled() === true) { //Continually replace last letter on keypress;
    if (isLetter(event) === true) {
      $('.letter-last').val(String.fromCharCode(event.which));
    }
    // swapRow();
    if (event.which === 13) {
      prependRow();
      swapRow();
      clearInputRow();
      scanTron();
    }
     //get finds the Nth element in the matched element set
  }
  //If the rowIsFilled(); and a key is pressed, replace the last letter in the row with keyCode
  //On enter submit the row to the scanTron. (UI / RULES NEEDS TO INDICATE WHY ENTER)
  if (event.which === 46) { // DELETE KEY EVENT LISTENER
    console.log('delete');
    var lastInput = guess.get(guess.index(this)-1); //get finds the Nth element in the matched element set
    if (lastInput) {
      lastInput.focus();
    }
    //Should return user to next cell over
    }
    //SHOULD ANYTHING HAPPEN WHEN THE ARROW KEYS ARE PRESSED? NAVIGATE THROUGH THE INPUT GRID?
  });
}

function isLetter(event){
  if (event.keyCode >= 97 && event.keyCode <= 122 ) {
    return true;
  }
}

function rowIsFilled(){
  if ($('.letter-last').val() !== "") { // Need to make sure that blank spaces cannot be submitted
    console.log('is filled');
    return true;
  }
}

function scanTron(){
  if (event.which === 13) {
    console.log('enter');
    return $('.input-tile').css('background-color','yellow');
    // Submit to scanTron
    //The scanTron returns the results (x color in correct place, y color if wrong place, z color not in the word)
  }
}

module.exports = Lingo;
<commit_msg>enter key functions<commit_after>const $ = require('jquery');

function Lingo(){
  $(document).ready(function(){
    $('#start-button').on('click',function(){
    });
  });

  Lingo.prototype.generateWordArray = function(word) {
    return word.toLowerCase().split('');
  };
  Lingo.prototype.checkWordArrayForLetter = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return true;
      }
    }
  };

  Lingo.prototype.generateMysteryWord = function(array) {
      var mysteryWord = array[(Math.floor(Math.random()*(array.length)))];
      return mysteryWord;
  };

  Lingo.prototype.getCharIndex = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return i;
      }
    }
  };

  Lingo.prototype.getGridColor = function (wordArray, character, index) {
     var mysteryCharacterIndex = this.getCharIndex(wordArray, character);
     if (mysteryCharacterIndex === index) { return 'green'; }

     var characterExistsInWord = this.checkWordArrayForLetter(wordArray, character);
     if (characterExistsInWord) { return 'yellow'; }
     else { return 'red'; }
   };

var guess = $('input').on('keypress',function(event){
  if (isLetter(event)) {
    var nextInput = guess.get(guess.index(this)+1);
    if (nextInput) { nextInput.focus(); }
  }
  function swapRow(){
    var row = guess.closest('tr');
    row.insertAfter(row.next());
  }
  function clearInputRow(){
    guess.map(function(){
      return this.value = "";
    });
  }
  function getWordArray(){
    var wordArray = guess.map(function(){
       return this.value;
    }).get();
    return wordArray;
  }
  function newWordRow(){
    var wordArray = getWordArray();
    return "
"+wordArray[0]+"	"+wordArray[1]+"	"+wordArray[2]+"	"+wordArray[3]+"	"+wordArray[4]+"
";
  }
  function prependRow(){
    guess.closest('tr').after(newWordRow());
  }
  if (event.which === 13) {
      prependRow();
      swapRow();
      clearInputRow();
      removeRow();
  }
  if (event.which === 46) { // DELETE KEY EVENT LISTENER
      console.log('delete');
  }
});

function removeRow() {
  $('tr:last').remove();
}

function isLetter(event){
  if (event.keyCode >= 97 && event.keyCode <= 122 ) {
    return true;
  }
}
}
module.exports = Lingo;
<|endoftext|>