<commit_before>app.directive('courseCreateCreatecourse', [
    "settings",
    "$location",
    "$window",
    "Course",
    "ChatService",
    "SessionService",
  function(
    settings,
    $location,
    $window,
    Course,
    ChatService,
    SessionService
  ) {

    return {
      templateUrl: settings.widgets + 'course/create/createcourse.html',
      link: function(scope, element, attrs) {

        // CURRENT COURSE VARIABLES
        //
        // session_user : ._id
        // id : on createCourse()
        // url : view + create/update course
        // name : view
        // description : view
        // start, end : view
        //

        //get session_user
        scope.session_user;
        SessionService.getSession().success(function(response){
            scope.session_user = response.user;
        });

        // Updates the GUI according to edit/add-state
        scope.isEditing = false;
        scope.btnAddOrUpdate = 'Create course';

        var stepFinishedIndex = 0;
        scope.isCopying = 0;

        var AvailableCourses, oldcourse, selectedCourseName;

        AvailableCourses = Course.get();

        //This method creates a  slack channel via API and then updates the course
        //it needs to be connected to
        var createSlackChannelwithCourse = function(courseId, channelName, UserIdentifier){
          ChatService.createChannel(channelName, UserIdentifier).success(function(slackChannel){
            console.log(slackChannel);
            if(slackChannel.error != null){
              return;
            }

            ChatService.getChannels(UserIdentifier).success(function(channels){
              for(x = 0; x < channels.channels.length; x++){
                if(channels.channels[x].name == channelName){
                  console.log(channels.channels[x]);
                  Course.update({ _id : courseId } , {$push: { slack_channels: { channelId: channels.channels[x].id} } },
                  function (res)
                  {
                    console.log(res);
                  });
                  break;
                }
              }
            });
          });
        }

        // Note: How to make it work when directive loads?
        // Gui function fetch selected course data for editing
        scope.prepareEditCourse = function (id){
            isEditingCourse = true;
            scope.btnAddOrUpdateTextCourse = 'Update';
            //get info from db to put in the form boxes
            scope.course = Course.getById(id);
            //scope.url = scope.course.url;
        };

        //Note: Update to dynamically load when revisits a ongoing creation
        //stores maximum steps allowed
        var stepsTaken = 0;

        //get session_user
        scope.session_user;
        SessionService.getSession().success(function(response){
            scope.session_user = response.user;
        });

        // Updates the GUI according to edit/add-state
        var isEditingCourse = false;
        scope.btnAddOrUpdate = 'Create course';

        var dateIsValid = function(start, end){
            return Date.parse(start) < Date.parse(end);
        }

        //Gui function add course
        scope.addOrUpdateCourse = function(){

        if(typeof scope.course.name !== 'undefined'){

            if(dateIsValid(scope.course.start, scope.course.end)){
              console.log("date valid");
              var result = AvailableCourses.filter(function( obj ) {
                return obj.name == selectedCourseName;
              });

              //scope.assignment.added_on = (new Date()).toJSON();

              if(scope.isEditing == 0){

                  if(scope.session_user.slack_token != undefined){

                      scope.isEditing = 1;

                      scope.course._id = undefined;

                      scope.btnAddOrUpdate = "Update course";

                      Course.create(scope.course, function(course){
                          scope.$root.$broadcast('addedCourse');
                          console.log("Added course:", course[0]);
                          oldcourse = JSON.parse(JSON.stringify(course[0]));
                          scope.incrementStep();

                          createSlackChannelwithCourse(course[0]._id, course[0].code, scope.session_user.email);
                          console.log("Created slack channel ", course[0]._id, course[0].code, scope.session_user.email);
                      });
                  }
                  else{
                    console.log("You need to add your slack token");
                  }
              } else if (scope.isEditing == 1){

                  console.log("Updating course");
                  console.log(scope.course);
                  console.log("old course: ", oldcourse);

                    Course.update({_id: oldcourse._id},scope.course, function(res){
                        console.log("Update res: ", res);
                        oldcourse = "";
                        oldcourse = JSON.parse(JSON.stringify(scope.course));
                        scope.incrementStep();
                    });
                }
              }
              else{
                console.log("please check start/end date");
              }
            }
          }

        //All the steps in the create course process, ng-switch states
        scope.steps = [{
              name: "Create or copy",
              icon: "fa-leaf",
          },{
              name: "Details",
              icon: "fa-i-cursor",
          },{
              name: "Preview",
              icon: "fa-eye",
          }];

          //All the steps in the create course process, ng-switch states
          scope.createsteps = [{
                name: "Create or copy",
                icon: "fa-leaf",
            },
            {
  						name: "Select course",
  						icon: "fa-file-text-o",
  					},
            {
                name: "Details",
                icon: "fa-i-cursor",
            },{
                name: "Preview",
                icon: "fa-eye",
            }];

            scope.courseSelect = {
              repeatSelect: null,
              availableOptions: AvailableCourses
          }

        //start out on step
        scope.selection = scope.steps[0].name;

        scope.getCurrentStepIndex = function(){
          if(scope.isCopying){
              // Find index of the current step by object name
              for(var i = 0; i < scope.createsteps.length; i += 1) {
                  if(scope.createsteps[i].name === scope.selection) {
                      return i;
                  }
              }
            } else {
              // Find index of the current step by object name
              for(var i = 0; i < scope.steps.length; i += 1) {
                  if(scope.steps[i].name === scope.selection) {
                      return i;
                  }
              }
            }
        }

        scope.setCreate = function() {
          scope.course = undefined;
          scope.isEditing = 0;
          scope.isCopying = 0;
          scope.btnAddOrUpdate = "Create course";
          console.log("Creating course");
          scope.incrementStep();
      }

      scope.setCopy = function() {
        scope.course = undefined;
        scope.isEditing = 0;
          scope.isCopying = 1;
          console.log("Copying course");
          scope.btnAddOrUpdate = "Create course";
          scope.incrementStep();
      }

      		       	// Move to a defined step index
      		        scope.goToStep = function(index) {
      			        // If you are going backwards in the flow: No worries
      			        if(scope.getCurrentStepIndex() > index){
      			        	console.log("Moving to step:", index, " from step:", scope.getCurrentStepIndex());
      			        	if(scope.isCopying){
      							           scope.selection = scope.createsteps[index].name;
      						    } else {
      							           scope.selection = scope.steps[index].name;
      						    }
      					}
      					// Going forwards in the flow
      					else {
      						// If you are going to a step that are finished
      						if(stepFinishedIndex >= index)
      						{
      							console.log("Moving to step:", index, " from step:", scope.getCurrentStepIndex());
      							if(scope.isCopying){
      								scope.selection = scope.createsteps[index].name;
      							} else {
      								scope.selection = scope.steps[index].name;
      							}
      						}
      					}
      		      }

        // Return true if step has next step, false if not
        scope.hasNextStep = function(){
            var stepIndex = scope.getCurrentStepIndex();
            var nextStep = stepIndex + 1;

            if(scope.isCopying){
              if(scope.createsteps[nextStep] == undefined) {
                  return false;
              }
              else {
                  return true;
              }
            } else {
              if(scope.steps[nextStep] == undefined) {
                  return false;
              }
              else {
                  return true;
              }
            }
        };

        // Return true if step has previous step, false if not
        scope.hasPreviousStep = function(){
            var stepIndex = scope.getCurrentStepIndex();
            var previousStep = stepIndex - 1;
            if(scope.steps[previousStep] == undefined) {
                return false
            }
            else {
                return true
            };
        };

        //move to next step
        scope.incrementStep = function() {
            if (scope.hasNextStep()){
        var stepIndex = scope.getCurrentStepIndex();
        var nextStep = stepIndex + 1;

        if(scope.isCopying){
          scope.selection = scope.createsteps[nextStep].name;
        } else {
          scope.selection = scope.steps[nextStep].name;
        }

        if(stepIndex >= stepFinishedIndex) {
            console.log("Step ", stepFinishedIndex, " done");
          stepFinishedIndex++;
        }
            }
        }

        //move to previous step
        scope.decrementStep = function() {
            if(scope.hasPreviousStep()){
              var stepIndex = scope.getCurrentStepIndex();
              var previousStep = stepIndex - 1;

              if(scope.isCopying){
                scope.selection = scope.createsteps[previousStep].name;
              } else {
                scope.selection = scope.steps[previousStep].name;
              }
              }
        }

        scope.loadDetails = function(){
          console.log("loading details");

          var obj = AvailableCourses.filter(function(obj){
            return obj.name === selectedCourseName;
          })[0];

          // var assignmentIndex = AvailableAssignments.indexOf(selectedAssignmentName);

          obj.end = new Date(obj.end);
          obj.start = new Date(obj.start);

          scope.course = obj;
            scope.incrementStep();

        }

        scope.selectCourseChanged = function (){
        selectedCourseName = scope.courseSelect.repeatSelect;
        console.log(selectedCourseName);
        }

        //create a new course and set GUI edit options
        scope.createCourse = function(){
            Course.create(
            {
                status: true,
                code: scope.code,
                url: scope.url,
                name: scope.name,
                description: scope.description,
                end: scope.end,
                start: scope.start,
                creator: scope.session_user._id
            }, function(course)
                {
                    scope.$root.$broadcast('addedCourse');
                              console.log("You hear me?");

                    //update GUI edit mode
                    scope.course = course[0];
                    scope.url = "/courses/" + scope.course.url;
                    isEditingCourse = true;
                    scope.btnAddOrUpdate = 'Update details';
                    scope.incrementStep();
                }
            );
        }

        //update a course
        scope.updateCourse = function(){
            //update current course in scope
            Course.update({
                _id: scope.course._id
              },{
                status: true,
                code: scope.code,
                url: scope.url,
                name: scope.name,
                description: scope.description,
                start: scope.start,
                end: scope.end

            });
            scope.url = "/courses/" + scope.course.url;
            scope.incrementStep();
        };

        //roate location
        scope.pathLocation = function() {
            Course.get({name: scope.course.name, description: scope.course.description, end: scope.course.end}, function(fetchedCourse){
        console.log("fetched course: ", fetchedCourse);
        scope.$parent.hideModal();
        $window.location.href = '/courses/' + fetchedCourse[0].url;
         });
        }

        scope.closeModalSession = function() {
            scope.course = "";
            //use course for update and scope storage(?) ex. course.code
            scope.code ="";
            scope.url = "";
            scope.name = "";
            scope.description = "",
            scope.start = "",
            scope.end = "";
            scope.url = "";
            console.log(scope.url);
            scope.selection = scope.steps[0].name;
            scope.$parent.hideModal();
        }

      }//end link
    }
  }
]);
<commit_msg>bug fix creator update<commit_after>app.directive('courseCreateCreatecourse', [
    "settings",
    "$location",
    "$window",
    "Course",
    "ChatService",
    "SessionService",
  function(
    settings,
    $location,
    $window,
    Course,
    ChatService,
    SessionService
  ) {

    return {
      templateUrl: settings.widgets + 'course/create/createcourse.html',
      link: function(scope, element, attrs) {

        // CURRENT COURSE VARIABLES
        //
        // session_user : ._id
        // id : on createCourse()
        // url : view + create/update course
        // name : view
        // description : view
        // start, end : view
        //

        //get session_user
        scope.session_user;
        SessionService.getSession().success(function(response){
            scope.session_user = response.user;
        });

        // Updates the GUI according to edit/add-state
        scope.isEditing = false;
        scope.btnAddOrUpdate = 'Create course';

        var stepFinishedIndex = 0;
        scope.isCopying = 0;

        var AvailableCourses, oldcourse, selectedCourseName;

        AvailableCourses = Course.get();

        //This method creates a  slack channel via API and then updates the course
        //it needs to be connected to
        var createSlackChannelwithCourse = function(courseId, channelName, UserIdentifier){
          ChatService.createChannel(channelName, UserIdentifier).success(function(slackChannel){
            console.log(slackChannel);
            if(slackChannel.error != null){
              return;
            }

            ChatService.getChannels(UserIdentifier).success(function(channels){
              for(x = 0; x < channels.channels.length; x++){
                if(channels.channels[x].name == channelName){
                  console.log(channels.channels[x]);
                  Course.update({ _id : courseId } , {$push: { slack_channels: { channelId: channels.channels[x].id} } },
                  function (res)
                  {
                    console.log(res);
                  });
                  break;
                }
              }
            });
          });
        }

        // Note: How to make it work when directive loads?
        // Gui function fetch selected course data for editing
        scope.prepareEditCourse = function (id){
            isEditingCourse = true;
            scope.btnAddOrUpdateTextCourse = 'Update';
            //get info from db to put in the form boxes
            scope.course = Course.getById(id);
            //scope.url = scope.course.url;
        };

        //Note: Update to dynamically load when revisits a ongoing creation
        //stores maximum steps allowed
        var stepsTaken = 0;

        //get session_user
        scope.session_user;
        SessionService.getSession().success(function(response){
            scope.session_user = response.user;
        });

        // Updates the GUI according to edit/add-state
        var isEditingCourse = false;
        scope.btnAddOrUpdate = 'Create course';

        var dateIsValid = function(start, end){
            return Date.parse(start) < Date.parse(end);
        }

        //Gui function add course
        scope.addOrUpdateCourse = function(){

        if(typeof scope.course.name !== 'undefined'){

            if(dateIsValid(scope.course.start, scope.course.end)){
              console.log("date valid");
              var result = AvailableCourses.filter(function( obj ) {
                return obj.name == selectedCourseName;
              });

              //scope.assignment.added_on = (new Date()).toJSON();

              if(scope.isEditing == 0){

                  if(scope.session_user.slack_token != undefined){

                      scope.isEditing = 1;

                      scope.course._id = undefined;

                      scope.btnAddOrUpdate = "Update course";

                      Course.create(scope.course, function(course){
                        console.log(scope.course, "the course to be created and its details");
                          scope.$root.$broadcast('addedCourse');
                          console.log("Added course:", course[0]);
                          oldcourse = JSON.parse(JSON.stringify(course[0]));
                          scope.incrementStep();

                          createSlackChannelwithCourse(course[0]._id, course[0].code, scope.session_user.email);
                          console.log("Created slack channel ", course[0]._id, course[0].code, scope.session_user.email);
                          Course.update({_relate:{ items:course[0],creator:scope.session_user }},function(res){});
                      });
                  }
                  else{
                    console.log("You need to add your slack token");
                  }
              } else if (scope.isEditing == 1){

                  console.log("Updating course");
                  console.log(scope.course);
                  console.log("old course: ", oldcourse);

                    Course.update({_id: oldcourse._id},scope.course, function(res){
                        console.log("Update res: ", res);
                        oldcourse = "";
                        oldcourse = JSON.parse(JSON.stringify(scope.course));
                        scope.incrementStep();
                    });
                }
              }
              else{
                console.log("please check start/end date");
              }
            }
          }

        //All the steps in the create course process, ng-switch states
        scope.steps = [{
              name: "Create or copy",
              icon: "fa-leaf",
          },{
              name: "Details",
              icon: "fa-i-cursor",
          },{
              name: "Preview",
              icon: "fa-eye",
          }];

          //All the steps in the create course process, ng-switch states
          scope.createsteps = [{
                name: "Create or copy",
                icon: "fa-leaf",
            },
            {
  						name: "Select course",
  						icon: "fa-file-text-o",
  					},
            {
                name: "Details",
                icon: "fa-i-cursor",
            },{
                name: "Preview",
                icon: "fa-eye",
            }];

            scope.courseSelect = {
              repeatSelect: null,
              availableOptions: AvailableCourses
          }

        //start out on step
        scope.selection = scope.steps[0].name;

        scope.getCurrentStepIndex = function(){
          if(scope.isCopying){
              // Find index of the current step by object name
              for(var i = 0; i < scope.createsteps.length; i += 1) {
                  if(scope.createsteps[i].name === scope.selection) {
                      return i;
                  }
              }
            } else {
              // Find index of the current step by object name
              for(var i = 0; i < scope.steps.length; i += 1) {
                  if(scope.steps[i].name === scope.selection) {
                      return i;
                  }
              }
            }
        }

        scope.setCreate = function() {
          scope.course = undefined;
          scope.isEditing = 0;
          scope.isCopying = 0;
          scope.btnAddOrUpdate = "Create course";
          console.log("Creating course");
          scope.incrementStep();
      }

      scope.setCopy = function() {
        scope.course = undefined;
        scope.isEditing = 0;
          scope.isCopying = 1;
          console.log("Copying course");
          scope.btnAddOrUpdate = "Create course";
          scope.incrementStep();
      }

      		       	// Move to a defined step index
      		        scope.goToStep = function(index) {
      			        // If you are going backwards in the flow: No worries
      			        if(scope.getCurrentStepIndex() > index){
      			        	console.log("Moving to step:", index, " from step:", scope.getCurrentStepIndex());
      			        	if(scope.isCopying){
      							           scope.selection = scope.createsteps[index].name;
      						    } else {
      							           scope.selection = scope.steps[index].name;
      						    }
      					}
      					// Going forwards in the flow
      					else {
      						// If you are going to a step that are finished
      						if(stepFinishedIndex >= index)
      						{
      							console.log("Moving to step:", index, " from step:", scope.getCurrentStepIndex());
      							if(scope.isCopying){
      								scope.selection = scope.createsteps[index].name;
      							} else {
      								scope.selection = scope.steps[index].name;
      							}
      						}
      					}
      		      }

        // Return true if step has next step, false if not
        scope.hasNextStep = function(){
            var stepIndex = scope.getCurrentStepIndex();
            var nextStep = stepIndex + 1;

            if(scope.isCopying){
              if(scope.createsteps[nextStep] == undefined) {
                  return false;
              }
              else {
                  return true;
              }
            } else {
              if(scope.steps[nextStep] == undefined) {
                  return false;
              }
              else {
                  return true;
              }
            }
        };

        // Return true if step has previous step, false if not
        scope.hasPreviousStep = function(){
            var stepIndex = scope.getCurrentStepIndex();
            var previousStep = stepIndex - 1;
            if(scope.steps[previousStep] == undefined) {
                return false
            }
            else {
                return true
            };
        };

        //move to next step
        scope.incrementStep = function() {
            if (scope.hasNextStep()){
        var stepIndex = scope.getCurrentStepIndex();
        var nextStep = stepIndex + 1;

        if(scope.isCopying){
          scope.selection = scope.createsteps[nextStep].name;
        } else {
          scope.selection = scope.steps[nextStep].name;
        }

        if(stepIndex >= stepFinishedIndex) {
            console.log("Step ", stepFinishedIndex, " done");
          stepFinishedIndex++;
        }
            }
        }

        //move to previous step
        scope.decrementStep = function() {
            if(scope.hasPreviousStep()){
              var stepIndex = scope.getCurrentStepIndex();
              var previousStep = stepIndex - 1;

              if(scope.isCopying){
                scope.selection = scope.createsteps[previousStep].name;
              } else {
                scope.selection = scope.steps[previousStep].name;
              }
              }
        }

        scope.loadDetails = function(){
          console.log("loading details");

          var obj = AvailableCourses.filter(function(obj){
            return obj.name === selectedCourseName;
          })[0];

          // var assignmentIndex = AvailableAssignments.indexOf(selectedAssignmentName);

          obj.end = new Date(obj.end);
          obj.start = new Date(obj.start);

          scope.course = obj;
            scope.incrementStep();

        }

        scope.selectCourseChanged = function (){
        selectedCourseName = scope.courseSelect.repeatSelect;
        console.log(selectedCourseName);
        }

        //create a new course and set GUI edit options
        scope.createCourse = function(){
            Course.create(
            {
                status: true,
                code: scope.code,
                url: scope.url,
                name: scope.name,
                description: scope.description,
                end: scope.end,
                start: scope.start,
                creator: scope.session_user._id
            }, function(course)
                {
                    scope.$root.$broadcast('addedCourse');
                              console.log("You hear me?");

                    //update GUI edit mode
                    scope.course = course[0];
                    scope.url = "/courses/" + scope.course.url;
                    isEditingCourse = true;
                    scope.btnAddOrUpdate = 'Update details';
                    scope.incrementStep();
                }
            );
        }

        //update a course
        scope.updateCourse = function(){
            //update current course in scope
            Course.update({
                _id: scope.course._id
              },{
                status: true,
                code: scope.code,
                url: scope.url,
                name: scope.name,
                description: scope.description,
                start: scope.start,
                end: scope.end

            });
            scope.url = "/courses/" + scope.course.url;
            scope.incrementStep();
        };

        //roate location
        scope.pathLocation = function() {
            Course.get({name: scope.course.name, description: scope.course.description, end: scope.course.end}, function(fetchedCourse){
        console.log("fetched course: ", fetchedCourse);
        scope.$parent.hideModal();
        $window.location.href = '/courses/' + fetchedCourse[0].url;
         });
        }

        scope.closeModalSession = function() {
            scope.course = "";
            //use course for update and scope storage(?) ex. course.code
            scope.code ="";
            scope.url = "";
            scope.name = "";
            scope.description = "",
            scope.start = "",
            scope.end = "";
            scope.url = "";
            console.log(scope.url);
            scope.selection = scope.steps[0].name;
            scope.$parent.hideModal();
        }

      }//end link
    }
  }
]);
<|endoftext|>


<commit_before>// @flow
import React from "react"
import { Route, Switch } from "react-router-dom"
import MainPage from "features/MainPage/MainPage"
import SummaryContainer from "features/Summary/SummaryContainer"
import OntologyContainer from "features/Ontology/OntologyContainer"
// import ProteinInformationContainer from "features/ProteinInformation/ProteinInformationContainer"
import Login from "features/Authentication/Login"
import OauthCallback from "features/Authentication/OauthCallback"
import AuthLoader from "features/Authentication/AuthLoader"
import Logout from "features/Authentication/Logout"
import PageNotReady from "common/components/PageNotReady"

// id subroutes need to be updated

const Routes = () => {
  return (
    <Switch>
      <Route exact path="/" component={MainPage} />
      <Route exact path="/login" component={Login} />
      <Route exact path="/:provider/callback" component={OauthCallback} />
      <Route exact path="/load/auth" component={AuthLoader} />
      <Route exact path="/logout" component={Logout} />
      <Route path="/:id/protein" component={props => <SummaryContainer />} />
      <Route path="/:id/goa" component={props => <OntologyContainer />} />
      <Route path="/:id/orthologs" component={props => <SummaryContainer />} />
      <Route path="/:id/phenotypes" component={props => <SummaryContainer />} />
      <Route path="/:id/references" component={props => <SummaryContainer />} />
      <Route path="/:id/blast" component={props => <SummaryContainer />} />
      <Route path="/:id" component={props => <SummaryContainer />} />
      <Route exact path="*" component={PageNotReady} />
    </Switch>
  )
}

export default Routes
<commit_msg>update route for nonexistent /id/ paths<commit_after>// @flow
import React from "react"
import { Route, Switch } from "react-router-dom"
import MainPage from "features/MainPage/MainPage"
import SummaryContainer from "features/Summary/SummaryContainer"
import OntologyContainer from "features/Ontology/OntologyContainer"
// import ProteinInformationContainer from "features/ProteinInformation/ProteinInformationContainer"
import Login from "features/Authentication/Login"
import OauthCallback from "features/Authentication/OauthCallback"
import AuthLoader from "features/Authentication/AuthLoader"
import Logout from "features/Authentication/Logout"
import PageNotReady from "common/components/PageNotReady"

const Routes = () => {
  return (
    <Switch>
      <Route exact path="/" component={MainPage} />
      <Route exact path="/login" component={Login} />
      <Route exact path="/:provider/callback" component={OauthCallback} />
      <Route exact path="/load/auth" component={AuthLoader} />
      <Route exact path="/logout" component={Logout} />
      <Route path="/:id/protein" component={props => <SummaryContainer />} />
      <Route path="/:id/goa" component={props => <OntologyContainer />} />
      <Route path="/:id/orthologs" component={props => <SummaryContainer />} />
      <Route path="/:id/phenotypes" component={props => <SummaryContainer />} />
      <Route path="/:id/references" component={props => <SummaryContainer />} />
      <Route path="/:id/blast" component={props => <SummaryContainer />} />
      <Route exact path="/:id/*" component={PageNotReady} />
      <Route path="/:id" component={props => <SummaryContainer />} />
      <Route exact path="*" component={PageNotReady} />
    </Switch>
  )
}

export default Routes
<|endoftext|>


<commit_before>//@ts-check
const Booru = require('./Booru.js')
const Utils = require('../Utils.js')
const Constants = require('../Constants.js')
const Post = require('../structures/Post.js')
const Snekfetch = require('snekfetch')

/**
 * A class designed for Derpibooru
 * >:(
 * @private
 * @extends Booru
 * @inheritDoc
 */
class Derpibooru extends Booru {
  /**
   * Create a new booru for Derpibooru from a site
   * @param {Site} site The site to use
   * @param {Object?} credentials Credentials for the API (Currently not used)
   */
  constructor(site, credentials) {
    super(site, credentials)
  }

  /** @inheritDoc */
  search(tags, {limit = 1, random = false, credentials = false} = {}) {
    if(!credentials && this.credentials) credentials = this.credentials;

    if (!Array.isArray(tags)) {
      tags = [tags]
    }

    // For any image, you must supply *
    if (tags[0] === undefined) {
      tags[0] = '*'
    }

    // Includes random limit for derpi
    // http://example.com/posts/?tags=some_example&limit=100&sf=random%AB43FF
    // Sorry, but derpibooru has an odd and confusing api that's not similar to the others at all
    const uri = Constants.searchURI(this.domain, this.site, tags, limit) + (random ?
      `&${this.site.random}` +
      //`${(this.site.random.endsWith('%'))?Array(7).fill(0).map(v=>Utils.randInt(0,16)).join(''):''}`
      : '') + (credentials ? "&key=" + credentials : "")

    console.log(uri)

    const options = Constants.defaultOptions

    return new Promise((resolve, reject) => {
      Snekfetch.get(uri, options)
        .then(result => {
          resolve((result.body.search).slice(0, limit).map(v => new Post(v, this)))
        })
        .catch(e => {e.name = 'BooruError'; reject(e)})
    })
  }
}
module.exports = Derpibooru
<commit_msg>wow, typo, it works now<commit_after>//@ts-check
const Booru = require('./Booru.js')
const Utils = require('../Utils.js')
const Constants = require('../Constants.js')
const Post = require('../structures/Post.js')
const Snekfetch = require('snekfetch')

/**
 * A class designed for Derpibooru
 * >:(
 * @private
 * @extends Booru
 * @inheritDoc
 */
class Derpibooru extends Booru {
  /**
   * Create a new booru for Derpibooru from a site
   * @param {Site} site The site to use
   * @param {Object?} credentials Credentials for the API (Currently not used)
   */
  constructor(site, credentials) {
    super(site, credentials)
  }

  /** @inheritDoc */
  search(tags, {limit = 1, random = false, credentials = false} = {}) {
    if(!credentials && this.credentials) credentials = this.credentials;

    if (!Array.isArray(tags)) {
      tags = [tags]
    }

    // For any image, you must supply *
    if (tags[0] === undefined) {
      tags[0] = '*'
    }

    // Includes random limit for derpi
    // http://example.com/posts/?tags=some_example&limit=100&sf=random%AB43FF
    // Sorry, but derpibooru has an odd and confusing api that's not similar to the others at all
    const uri = Constants.searchURI(this.domain, this.site, tags, limit) + (random ?
      `&${this.site.random}`
      //+ `${(this.site.random.endsWith('%'))?Array(7).fill(0).map(v=>Utils.randInt(0,16)).join(''):''}`
      : '') + (credentials ? "&key=" + credentials : "")

    //console.log(uri)

    const options = Constants.defaultOptions

    return new Promise((resolve, reject) => {
      Snekfetch.get(uri, options)
        .then(result => {
          resolve((result.body.search).slice(0, limit).map(v => new Post(v, this)))
        })
        .catch(e => {e.name = 'BooruError'; reject(e)})
    })
  }
}
module.exports = Derpibooru
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Web3 from 'web3';
import {BigNumber} from 'bignumber.js';
import { createBlockbinContract } from '../util/ethereum';

const SUPPORTED_CODECS = {
  'ASCII': 'ascii'
};

const TWO_GWEI_IN_WEI = '2000000000';
const DEFAULT_ETH_PRICE = '500';
const DEFAULT_ESTIMATE = '21000';

function SuccessBanner(props) {
  if (!props.successes || !props.successes.length) {
    return null;
  }
  var successItems = props.successes.map(function(success, index){
    return

;
  });
  return (

{successItems}

  );
}

function WarningBanner(props) {
  if (!props.errors || !props.errors.length) {
    return null;
  }
  var errorItems = props.errors.map(function(error, index){
    return

;
  });
  return (

{errorItems}

  );
}

class NewCubeForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      content: '',
      codec: SUPPORTED_CODECS.ASCII,
      estimate: DEFAULT_ESTIMATE,
      gasPrice: TWO_GWEI_IN_WEI,
      ethPrice: DEFAULT_ETH_PRICE,
      contentHash: 'n/a',
      cubeBytes: '0x',
      errors: [],
      successes: [],
    };

    if (Web3.givenProvider) {
      this.web3 = new Web3(Web3.givenProvider);
      this.contractInstance = createBlockbinContract(this.web3);
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Persisting content to the blockchain requires the use of Metamask to fuel the transaction with some ethereum. Go to https://metamask.io/ to install it then refresh this page.'
        ]
      })
    }

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  encode(content, codec) {
    if (codec === SUPPORTED_CODECS.ASCII) {
      return Web3.utils.asciiToHex(content);
    } else {
      throw new Error('Unsupported codec: ' + codec);
    }
  };

  handleChange(event) {
    const content = event.target.value;
    const cubeBytes = this.encode(content, this.state.codec)
    const contentHash = Web3.utils.sha3(cubeBytes);

    this.setState({
        content: content,
        cubeBytes: cubeBytes,
        contentHash: contentHash
    })

    this.contractInstance.methods.dumpCube(cubeBytes, contentHash).estimateGas(
      { from: this.web3.eth.accounts[0] },
      this.estimateGasCb.bind(this)
    );
  }

  getGasPriceCb(error, result) {
    if (!error) {
      this.setState({gasPrice: result});
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Not able to estimate gasPrice! error msg: ' + error
        ]
      });
    }
  }

  estimateGasCb(error, result) {
    if (!error) {
      this.setState({estimate: result});
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Not able to estimate gas. error msg: ' + error
        ]
      });
    }
  };

  handleSubmit(event) {
    event.preventDefault();

    this.web3.eth.getAccounts().then(function(accounts) {
      this.contractInstance.methods.dumpCube(
        this.state.cubeBytes,
        this.state.contentHash
      ).send(
        {
          // Metamask uses accounts[0] to pass the preferred account
          from: accounts[0],
          gas: this.state.estimate,
          gasPrice: this.state.gasPrice,
        },
        this.sendTransactionCb.bind(this)
      );
    }.bind(this)).catch(function(e) {
      alert('Error when getting Metamask accounts: ' + e.toString());
    });
  }

  sendTransactionCb(error, result) {
    if (!error) {
      this.setState({
        successes: [
          ...this.state.successes,
          'Saved!

Cube hash: ' + this.state.contentHash + '
TxID: ' + result + '
Cube Permalink'
        ]
      });
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Error in processing your transaction: ' + error
        ]
      });
    }
  };

  componentDidMount() {
    this.web3.eth.getGasPrice(this.getGasPriceCb.bind(this));
    fetch('https://api.coinmarketcap.com/v1/ticker/ethereum/')
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          ethPrice: responseJson[0]['price_usd']
        });
      })
      .catch((error) => {
        console.error(error);
        this.setState({
          errors: [
            ...this.state.errors,
            'Error in processing your transaction: ' + error
          ]
        });
      });
  }

  render() {
    var gasLimit = new BigNumber(this.state.estimate).multipliedBy(2);
    var totalEstimateETH = new BigNumber(
      this.web3.utils.fromWei(
        new BigNumber(this.state.gasPrice).multipliedBy(gasLimit).toString(),
        'gwei'
       )
    );
    var totalEstimateUSD = new BigNumber(
      new BigNumber(
        this.web3.utils.fromWei(
          new BigNumber(this.state.gasPrice).multipliedBy(gasLimit).toString(),
          'ether'
        )
      ) * new BigNumber(this.state.ethPrice)
    )

    var doesNotHaveWeb3 = this.web3 === undefined;
    return (
      <form onSubmit={this.handleSubmit}>
        <SuccessBanner successes={this.state.successes} />
        <WarningBanner errors={this.state.errors} />

          New Cube

              Encoding
              <select id="codec">
                <option value="ascii">ASCII</option>
              </select>

        <textarea
          className="new-cube-textarea nerdy"
          onChange={this.handleChange}
          value={this.state.content}
          rows={10}
        />

Hash: {this.state.contentHash}

Length: {(this.state.cubeBytes.length-2)/2} bytes

Gas limit: {gasLimit.toFormat()} (twice the estimate of {this.state.estimate})

Gas price: {Web3.utils.fromWei(this.state.gasPrice, 'gwei')} Gwei

Total: {totalEstimateETH.precision(6).toFormat()} ETH (approx. {totalEstimateUSD.precision(6).toFormat()} USD)

        <button
          className="submit-button"
          disabled={doesNotHaveWeb3 ? 'disabled' : ''}
        >
          Mine to blockchain
        </button>
      </form>
    );
  }
}

export default NewCubeForm;
<commit_msg>Fix tests by isolating the parts that require web3.<commit_after>import React, { Component } from 'react';
import Web3 from 'web3';
import {BigNumber} from 'bignumber.js';
import { createBlockbinContract } from '../util/ethereum';

const SUPPORTED_CODECS = {
  'ASCII': 'ascii'
};

const TWO_GWEI_IN_WEI = '2000000000';
const DEFAULT_ETH_PRICE = '500';
const DEFAULT_ESTIMATE = '21000';

function SuccessBanner(props) {
  if (!props.successes || !props.successes.length) {
    return null;
  }
  var successItems = props.successes.map(function(success, index){
    return

;
  });
  return (

{successItems}

  );
}

function WarningBanner(props) {
  if (!props.errors || !props.errors.length) {
    return null;
  }
  var errorItems = props.errors.map(function(error, index){
    return

;
  });
  return (

{errorItems}

  );
}

class NewCubeForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      content: '',
      codec: SUPPORTED_CODECS.ASCII,
      estimate: DEFAULT_ESTIMATE,
      gasPrice: TWO_GWEI_IN_WEI,
      ethPrice: DEFAULT_ETH_PRICE,
      contentHash: 'n/a',
      cubeBytes: '0x',
      errors: [],
      successes: [],
    };

    if (Web3.givenProvider) {
      this.web3 = new Web3(Web3.givenProvider);
      this.contractInstance = createBlockbinContract(this.web3);
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Persisting content to the blockchain requires the use of Metamask to fuel the transaction with some ethereum. Go to https://metamask.io/ to install it then refresh this page.'
        ]
      })
    }

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  encode(content, codec) {
    if (codec === SUPPORTED_CODECS.ASCII) {
      return Web3.utils.asciiToHex(content);
    } else {
      throw new Error('Unsupported codec: ' + codec);
    }
  };

  handleChange(event) {
    const content = event.target.value;
    const cubeBytes = this.encode(content, this.state.codec)
    const contentHash = Web3.utils.sha3(cubeBytes);

    this.setState({
        content: content,
        cubeBytes: cubeBytes,
        contentHash: contentHash
    })

    this.contractInstance.methods.dumpCube(cubeBytes, contentHash).estimateGas(
      { from: this.web3.eth.accounts[0] },
      this.estimateGasCb.bind(this)
    );
  }

  getGasPriceCb(error, result) {
    if (!error) {
      this.setState({gasPrice: result});
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Not able to estimate gasPrice! error msg: ' + error
        ]
      });
    }
  }

  estimateGasCb(error, result) {
    if (!error) {
      this.setState({estimate: result});
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Not able to estimate gas. error msg: ' + error
        ]
      });
    }
  };

  handleSubmit(event) {
    event.preventDefault();

    this.web3.eth.getAccounts().then(function(accounts) {
      this.contractInstance.methods.dumpCube(
        this.state.cubeBytes,
        this.state.contentHash
      ).send(
        {
          // Metamask uses accounts[0] to pass the preferred account
          from: accounts[0],
          gas: this.state.estimate,
          gasPrice: this.state.gasPrice,
        },
        this.sendTransactionCb.bind(this)
      );
    }.bind(this)).catch(function(e) {
      alert('Error when getting Metamask accounts: ' + e.toString());
    });
  }

  sendTransactionCb(error, result) {
    if (!error) {
      this.setState({
        successes: [
          ...this.state.successes,
          'Saved!

Cube hash: ' + this.state.contentHash + '
TxID: ' + result + '
Cube Permalink'
        ]
      });
    } else {
      this.setState({
        errors: [
          ...this.state.errors,
          'Error in processing your transaction: ' + error
        ]
      });
    }
  };

  componentDidMount() {
    if (this.state.content.length && this.web3) {
      this.web3.eth.getGasPrice(this.getGasPriceCb.bind(this));
      fetch('https://api.coinmarketcap.com/v1/ticker/ethereum/')
        .then((response) => response.json())
        .then((responseJson) => {
          this.setState({
            ethPrice: responseJson[0]['price_usd']
          });
        })
        .catch((error) => {
          console.error(error);
          this.setState({
            errors: [
              ...this.state.errors,
              'Error in processing your transaction: ' + error
            ]
          });
        });
    }
  }

  render() {
    var cubeInfo;
    if (this.state.content.length && this.web3) {
      var gasLimit = new BigNumber(this.state.estimate).multipliedBy(2);
      var totalEstimateETH = new BigNumber(
        this.web3.utils.fromWei(
          new BigNumber(this.state.gasPrice).multipliedBy(gasLimit).toString(),
          'gwei'
         )
      );
      var totalEstimateUSD = new BigNumber(
        new BigNumber(
          this.web3.utils.fromWei(
            new BigNumber(this.state.gasPrice).multipliedBy(gasLimit).toString(),
            'ether'
          )
        ) * new BigNumber(this.state.ethPrice)
      );

      cubeInfo =

Hash: {this.state.contentHash}

Length: {(this.state.cubeBytes.length-2)/2} bytes

Gas limit: {gasLimit.toFormat()} (twice the estimate of {this.state.estimate})

Gas price: {Web3.utils.fromWei(this.state.gasPrice, 'gwei')} Gwei

Total: {totalEstimateETH.precision(6).toFormat()} ETH (approx. {totalEstimateUSD.precision(6).toFormat()} USD)

        <button
          className="submit-button"
        >
          Mine to blockchain
        </button>

    } else {
      cubeInfo = null
    }

    return (
      <form onSubmit={this.handleSubmit}>
        <SuccessBanner successes={this.state.successes} />
        <WarningBanner errors={this.state.errors} />

          New Cube

              Encoding
              <select id="codec">
                <option value="ascii">ASCII</option>
              </select>

        <textarea
          className="new-cube-textarea nerdy"
          onChange={this.handleChange}
          value={this.state.content}
          rows={10}
        />
        {cubeInfo}
      </form>
    );
  }
}

export default NewCubeForm;
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    var isWindows = require("ace/lib/useragent").isWindows;
    module.exports = function initInput(ace) {
        var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
        var KEY_MODS = require("ace/lib/keys").KEY_MODS;
        var specialKeys = new HashHandler();
        // http://www.math.utah.edu/docs/info/features_7.html
        specialKeys.bindKeys({
            "Shift-PageUp"      : {command: "pageup"},
            "Shift-PageDown"    : {command: "pagedown"},
            "Ctrl-Up"           : {command: "scrollup"},
            "Ctrl-Down"         : {command: "scrolldown"},

            "Backspace"         : '\x7f',
            "Shift-Backspace"   : '\x08',
            "Alt-Backspace"     : '\x1b\x7f',
            "Tab"               : '\t',
            "Shift-Tab"         : '\x1b[Z',
            "Return"            : '\r',
            "Escape"            : '\x1b',
            "Left"              : '\x1b[D',
            "Ctrl-Left"         : '\x1b[5D',
            "Right"             : '\x1b[C',
            "Ctrl-Right"        : '\x1b[5C',
            "Up"                : '\x1b[A',
            "Down"              : '\x1b[B',
            "Delete"            : '\x1b[3~',
            "Insert"            : '\x1b[2~',
            "Home"              : '\x1b[1~',
            "End"               : '\x1b[4~',
            "PageUp"            : '\x1b[5~',
            "PageDown"          : '\x1b[6~',
            "F1"                : '\x1bOP',
            "F2"                : '\x1bOQ',
            "F3"                : '\x1bOR',
            "F4"                : '\x1bOS',
            "F5"                : '\x1b[15~',
            "F6"                : '\x1b[17~',
            "F7"                : '\x1b[18~',
            "F8"                : '\x1b[19~',
            "F9"                : '\x1b[20~',
            "F10"               : '\x1b[21~',
            "F11"               : '\x1b[23~',
            "F12"               : '\x1b[24~'
        });

        // make shell to behave more like regular editor
        var aliases = [{
            bindKey: {win: "Ctrl-left", mac: "Option-left"},
            name: "\u001bb" // "alt-b"
        }, {
            bindKey: {win: "Ctrl-right", mac: "Option-right"},
            name: "\u001bf" //"alt-b"
        }, {
            bindKey: {win: "Ctrl-Delete", mac: "Option-Delete"},
            name: "\u001bd" //"alt-d"
        }, {
            bindKey: {win: "Ctrl-Backspace", mac: "Option-Backspace"},
            name: "\x1b\x7f" //"alt-backspace"
        }, {
            bindKey: {win: "Ctrl-Delete", mac: "Option-Delete"},
            name: "\u001bd" //"alt-d"
        }, {
            bindKey: {win: "Alt-Backspace", mac: "Ctrl-Backspace"},
            name: "\u0017" //"ctrl-w"
        }, {
            bindKey: {win: "Alt-Backspace", mac: "Ctrl-Backspace"},
            name: "\u0017" //"ctrl-w"
        }, {
            bindKey: {win: "Ctrl-z", mac: "Cmd-z"},
            name: "\u0018\u0015" //"ctrl-x ctrl-u"
        }];

        specialKeys.addCommands(aliases);
        // SS3 as ^[O for 7-bit  '\x8fD';  SS3 as 0x8f for 8-bit
        var applicationKeys = {
            "left":      '\x1bOD',
            "right":     '\x1bOC',
            "up":        '\x1bOA',
            "down":      '\x1bOB',
            "home":      '\x1bOH',
            "end":       '\x1bOF'
        };

        function defaultHandler(ev) {
            var key = null;
            var keyCode = ev.keyCode;
            var isControl = ev.ctrlKey;
            var isMeta = specialKeys.platform == "mac" ? ev.metaKey : ev.altKey;
            // a-z and space
            if (isControl) {
                if (keyCode >= 65 && keyCode <= 90) {
                    key = String.fromCharCode(keyCode - 64);
                } else if (keyCode === 32) {
                    // NUL
                    key = String.fromCharCode(0);
                } else if (keyCode >= 51 && keyCode <= 55) {
                    // escape, file sep, group sep, record sep, unit sep
                    key = String.fromCharCode(keyCode - 51 + 27);
                } else if (keyCode === 56) {
                    // delete
                    key = String.fromCharCode(127);
                } else if (keyCode === 219) {
                    // ^[ - escape
                    key = String.fromCharCode(27);
                } else if (keyCode === 221) {
                    // ^] - group sep
                    key = String.fromCharCode(29);
                } else if (keyCode === 189 || keyCode === 173) {
                    // _
                    key = String.fromCharCode(31);
                }
            } else if (isMeta) {
                if (keyCode >= 65 && keyCode <= 90) {
                    key = '\x1b' + String.fromCharCode(keyCode + 32);
                } else if (keyCode === 192) {
                    key = '\x1b`';
                } else if (keyCode >= 48 && keyCode <= 57) {
                    key = '\x1b' + (keyCode - 48);
                }
            }
            return key;
        }

        this.handleKeyboard = function(data, hashId, keyString, keyCode, ev) {
            var term = data.editor.session.term;
            if (hashId == -1) {
                this.send(keyString);
                return {command: "null"};
            }
            if (term.applicationKeypad) {
                if (applicationKeys[keyString]) {
                    this.send(applicationKeys[keyString]);
                    return {command: "null"};
                }
            }
            var key = specialKeys.findKeyCommand(hashId, keyString);
            if (typeof key == "string") {
                this.send(key);
                return {command: "null"};
            } else if (key && key.command) {
                return key;
            } else if (key && key.exec) {
                if (!key.isAvailable || key.isAvailable(ace))
                    return {command: key};
            } else if (key && key.name) {
                this.send(key.name);
                return {command: "null"};
            }

            key = defaultHandler(ev);
            if (key)
                this.send(key);

            return {
                command: "null",
                passEvent: !hashId || hashId === KEY_MODS.shift || (
                    // on mac key combos without ctrl or cmd trigger textinput
                    specialKeys.platform === "mac" && !(hashId & (KEY_MODS.ctrl | KEY_MODS.cmd))
                ) || (
                    // on windows 8+ calling preventDefault on win+space breaks textinput
                    specialKeys.platform === "win" && hashId == KEY_MODS.cmd && (keyCode == 32 || keyCode == -1)
                )
            };
        };

        var isCopyAvailable = function(ed) {
            if (ed && !ed.getCopyText)
                ed = ed.ace || ed.$editor;
            return ed && !!ed.getCopyText();
        };
        var noop = function() {};

        // Add special handling for editor keys
        specialKeys.addCommands([{
            name: "copy",
            bindKey: {mac: "Cmd-c", win: "Ctrl-c"},
            exec: noop,
            isAvailable: isCopyAvailable,
            passEvent: true
        },{
            name: "cut",
            bindKey: {mac: "Cmd-x", win: "Ctrl-x"},
            exec: noop,
            isAvailable: isCopyAvailable,
            passEvent: true
        },{
            name: "paste",
            bindKey: {mac: "Cmd-v", win: "Ctrl-v"},
            exec: noop,
            isAvailable: function(ed) {
                return true;
            },
            passEvent: true
        },{
            name: "clear",
            bindKey: {mac: "Cmd-K", win: "Ctrl-K"},
            exec: function(ed) {
                var term = ed.ace.session.term;
                term.clear();
                term.send("\x0c"); //"ctrl-l"
            },
            isAvailable: function(editor) {
                return true; // todo disable in vim?
            }
        }]);

        ace.onPaste = function(text) {
            this.send(text);
        };

        ace.setKeyboardHandler(this);
        ace.keyBinding.addKeyboardHandler(ace.commands);
        ace.commands.commandKeyBinding = {};

        this.send = ace.send = function(text) {
            ace.session.send && ace.session.send(text);
        };
        return specialKeys;
    };
});<commit_msg>change \r\n to \n when pasting in terminal<commit_after>define(function(require, exports, module) {
    var isWindows = require("ace/lib/useragent").isWindows;
    module.exports = function initInput(ace) {
        var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
        var KEY_MODS = require("ace/lib/keys").KEY_MODS;
        var specialKeys = new HashHandler();
        // http://www.math.utah.edu/docs/info/features_7.html
        specialKeys.bindKeys({
            "Shift-PageUp"      : {command: "pageup"},
            "Shift-PageDown"    : {command: "pagedown"},
            "Ctrl-Up"           : {command: "scrollup"},
            "Ctrl-Down"         : {command: "scrolldown"},

            "Backspace"         : '\x7f',
            "Shift-Backspace"   : '\x08',
            "Alt-Backspace"     : '\x1b\x7f',
            "Tab"               : '\t',
            "Shift-Tab"         : '\x1b[Z',
            "Return"            : '\r',
            "Escape"            : '\x1b',
            "Left"              : '\x1b[D',
            "Ctrl-Left"         : '\x1b[5D',
            "Right"             : '\x1b[C',
            "Ctrl-Right"        : '\x1b[5C',
            "Up"                : '\x1b[A',
            "Down"              : '\x1b[B',
            "Delete"            : '\x1b[3~',
            "Insert"            : '\x1b[2~',
            "Home"              : '\x1b[1~',
            "End"               : '\x1b[4~',
            "PageUp"            : '\x1b[5~',
            "PageDown"          : '\x1b[6~',
            "F1"                : '\x1bOP',
            "F2"                : '\x1bOQ',
            "F3"                : '\x1bOR',
            "F4"                : '\x1bOS',
            "F5"                : '\x1b[15~',
            "F6"                : '\x1b[17~',
            "F7"                : '\x1b[18~',
            "F8"                : '\x1b[19~',
            "F9"                : '\x1b[20~',
            "F10"               : '\x1b[21~',
            "F11"               : '\x1b[23~',
            "F12"               : '\x1b[24~'
        });

        // make shell to behave more like regular editor
        var aliases = [{
            bindKey: {win: "Ctrl-left", mac: "Option-left"},
            name: "\u001bb" // "alt-b"
        }, {
            bindKey: {win: "Ctrl-right", mac: "Option-right"},
            name: "\u001bf" //"alt-b"
        }, {
            bindKey: {win: "Ctrl-Delete", mac: "Option-Delete"},
            name: "\u001bd" //"alt-d"
        }, {
            bindKey: {win: "Ctrl-Backspace", mac: "Option-Backspace"},
            name: "\x1b\x7f" //"alt-backspace"
        }, {
            bindKey: {win: "Ctrl-Delete", mac: "Option-Delete"},
            name: "\u001bd" //"alt-d"
        }, {
            bindKey: {win: "Alt-Backspace", mac: "Ctrl-Backspace"},
            name: "\u0017" //"ctrl-w"
        }, {
            bindKey: {win: "Alt-Backspace", mac: "Ctrl-Backspace"},
            name: "\u0017" //"ctrl-w"
        }, {
            bindKey: {win: "Ctrl-z", mac: "Cmd-z"},
            name: "\u0018\u0015" //"ctrl-x ctrl-u"
        }];

        specialKeys.addCommands(aliases);
        // SS3 as ^[O for 7-bit  '\x8fD';  SS3 as 0x8f for 8-bit
        var applicationKeys = {
            "left":      '\x1bOD',
            "right":     '\x1bOC',
            "up":        '\x1bOA',
            "down":      '\x1bOB',
            "home":      '\x1bOH',
            "end":       '\x1bOF'
        };

        function defaultHandler(ev) {
            var key = null;
            var keyCode = ev.keyCode;
            var isControl = ev.ctrlKey;
            var isMeta = specialKeys.platform == "mac" ? ev.metaKey : ev.altKey;
            // a-z and space
            if (isControl) {
                if (keyCode >= 65 && keyCode <= 90) {
                    key = String.fromCharCode(keyCode - 64);
                } else if (keyCode === 32) {
                    // NUL
                    key = String.fromCharCode(0);
                } else if (keyCode >= 51 && keyCode <= 55) {
                    // escape, file sep, group sep, record sep, unit sep
                    key = String.fromCharCode(keyCode - 51 + 27);
                } else if (keyCode === 56) {
                    // delete
                    key = String.fromCharCode(127);
                } else if (keyCode === 219) {
                    // ^[ - escape
                    key = String.fromCharCode(27);
                } else if (keyCode === 221) {
                    // ^] - group sep
                    key = String.fromCharCode(29);
                } else if (keyCode === 189 || keyCode === 173) {
                    // _
                    key = String.fromCharCode(31);
                }
            } else if (isMeta) {
                if (keyCode >= 65 && keyCode <= 90) {
                    key = '\x1b' + String.fromCharCode(keyCode + 32);
                } else if (keyCode === 192) {
                    key = '\x1b`';
                } else if (keyCode >= 48 && keyCode <= 57) {
                    key = '\x1b' + (keyCode - 48);
                }
            }
            return key;
        }

        this.handleKeyboard = function(data, hashId, keyString, keyCode, ev) {
            var term = data.editor.session.term;
            if (hashId == -1) {
                this.send(keyString);
                return {command: "null"};
            }
            if (term.applicationKeypad) {
                if (applicationKeys[keyString]) {
                    this.send(applicationKeys[keyString]);
                    return {command: "null"};
                }
            }
            var key = specialKeys.findKeyCommand(hashId, keyString);
            if (typeof key == "string") {
                this.send(key);
                return {command: "null"};
            } else if (key && key.command) {
                return key;
            } else if (key && key.exec) {
                if (!key.isAvailable || key.isAvailable(ace))
                    return {command: key};
            } else if (key && key.name) {
                this.send(key.name);
                return {command: "null"};
            }

            key = defaultHandler(ev);
            if (key)
                this.send(key);

            return {
                command: "null",
                passEvent: !hashId || hashId === KEY_MODS.shift || (
                    // on mac key combos without ctrl or cmd trigger textinput
                    specialKeys.platform === "mac" && !(hashId & (KEY_MODS.ctrl | KEY_MODS.cmd))
                ) || (
                    // on windows 8+ calling preventDefault on win+space breaks textinput
                    specialKeys.platform === "win" && hashId == KEY_MODS.cmd && (keyCode == 32 || keyCode == -1)
                )
            };
        };

        var isCopyAvailable = function(ed) {
            if (ed && !ed.getCopyText)
                ed = ed.ace || ed.$editor;
            return ed && !!ed.getCopyText();
        };
        var noop = function() {};

        // Add special handling for editor keys
        specialKeys.addCommands([{
            name: "copy",
            bindKey: {mac: "Cmd-c", win: "Ctrl-c"},
            exec: noop,
            isAvailable: isCopyAvailable,
            passEvent: true
        },{
            name: "cut",
            bindKey: {mac: "Cmd-x", win: "Ctrl-x"},
            exec: noop,
            isAvailable: isCopyAvailable,
            passEvent: true
        },{
            name: "paste",
            bindKey: {mac: "Cmd-v", win: "Ctrl-v"},
            exec: noop,
            isAvailable: function(ed) {
                return true;
            },
            passEvent: true
        },{
            name: "clear",
            bindKey: {mac: "Cmd-K", win: "Ctrl-K"},
            exec: function(ed) {
                var term = ed.ace.session.term;
                term.clear();
                term.send("\x0c"); //"ctrl-l"
            },
            isAvailable: function(editor) {
                return true; // todo disable in vim?
            }
        }]);

        ace.onPaste = function(text) {
            this.send(text.replace(/\r\n/g, "\n"));
        };

        ace.setKeyboardHandler(this);
        ace.keyBinding.addKeyboardHandler(ace.commands);
        ace.commands.commandKeyBinding = {};

        this.send = ace.send = function(text) {
            ace.session.send && ace.session.send(text);
        };
        return specialKeys;
    };
});<|endoftext|>


<commit_before>window.optly.mrkt.jobsPage = {};
var jobList = require('jobList');

window.optly.mrkt.jobsPage.testimonials = function() {
    var lastIndex = 0;
    var $quotes = $('h4.quotes q');
    var $icons = $('.employee-icons li');

    $icons.on('click', function(e){
        e.preventDefault();
        var index = $(this).index();

        if(index !== lastIndex) {
            $( $quotes[index] ).removeClass('hide');
            $(this).removeClass('opaque');

            $( $quotes[lastIndex] ).addClass('hide');
            $( $icons[lastIndex] ).addClass('opaque');

            lastIndex = index;
        }
    });
};

$('#view-all-jobs').click(function() {
  $('html, body').animate({scrollTop: $('#jobs-list').offset().top}, 700);
  return false;
});

window.optly.mrkt.jobsPage.testimonials();

/*
* Jobs and Department titles are hidden or
* shown based on the filter criteria.
*/
function showOrHideJobs(filterText, $jobLocation, $closestDepartmentTitle, $departmentTitles) {
  if (!filterText.includes($jobLocation.text())) {
    if (filterText === 'All Locations') {
      $closestDepartmentTitle.show();
      $departmentTitles.show();
    } else {
      $closestDepartmentTitle.hide();
      $departmentTitles.each(function() {
        var hideTitle = $(this).next().children().filter(function() {
          return this.style.display !== 'none';
        }).length === 0;
        if (hideTitle) {
          $(this).hide();
        }
      });
    }
  } else { // filter text matches target text
    $closestDepartmentTitle.show();
    $jobLocation.closest('ul').prev().show(); //Show the department title
  }
}

/*
* Click event on jobs dropdown filter
*/
function registerJobsFilterClick() {
  $('.js-location-filter').on('click', function() {
    var filterText = $(this).text();
    var $departmentTitles = $('.department-title');
    $('.js-filter-holder').text(filterText);
    $('.job-location').each(function() {
      var $jobLocation = $(this);
      var $closestDepartmentTitle = $jobLocation.closest('li');

      showOrHideJobs(filterText, $jobLocation, $closestDepartmentTitle, $departmentTitles);
    });
  });
}

function getGreenhouseData(data) {
  var locations = [];

  if(typeof data === 'object'){

    $.each(data.departments, function(i, department) {
      if(department.jobs.length === 0){
        delete data.departments[i];
      } else {
        // iterate over jobs to get all locations
        $.each(department.jobs, function(j, job) {
          locations.push(job.location.name);
        });
      }
    });
    $.unique(locations);

    // Add locations as dropdown options
    $.each(locations, function(index, location) {
      $('#js-locations').append('
' + location + '
');
    });
    $('#job-list-cont').append( jobList(data) );

    registerJobsFilterClick();
  }
}

// Jobs location filter dropdown
var $dropdownElems = $('.js-dropdown');
$dropdownElems.click(function() {
  var $this = $(this);
  $this.toggleClass('active');
  $dropdownElems.not( $this ).removeClass( 'active' );
  $this.one('mouseleave', function(){
    $this.removeClass( 'active' );
  });
});

var deferred = $.getJSON('https://api.greenhouse.io/v1/boards/optimizely7/embed/departments?callback=?');

deferred.then(getGreenhouseData, function(err) {
    window.analytics.track('https://api.greenhouse.io/v1/boards/optimizely7/embed/departments?callback=?', {
      category: 'api error',
      label: err.responseText + ', Response Code: ' + err.status,
    }, {
      integrations: {
        Marketo: false
      }
    });
});
<commit_msg>address cheston's comments<commit_after>window.optly.mrkt.jobsPage = {};
var jobList = require('jobList');

window.optly.mrkt.jobsPage.testimonials = function() {
    var lastIndex = 0;
    var $quotes = $('h4.quotes q');
    var $icons = $('.employee-icons li');

    $icons.on('click', function(e){
        e.preventDefault();
        var index = $(this).index();

        if(index !== lastIndex) {
            $( $quotes[index] ).removeClass('hide');
            $(this).removeClass('opaque');

            $( $quotes[lastIndex] ).addClass('hide');
            $( $icons[lastIndex] ).addClass('opaque');

            lastIndex = index;
        }
    });
};

$('#view-all-jobs').click(function() {
  $('html, body').animate({
    scrollTop: $('#jobs-list').offset().top
  }, 700);
  return false;
});

window.optly.mrkt.jobsPage.testimonials();

/*
* Jobs and Department titles are hidden or
* shown based on the filter criteria.
*/
function showOrHideJobs(filterText, $jobLocation, $closestDepartmentTitle, $departmentTitles) {
  if (filterText.indexOf($jobLocation.text()) === -1) {
    if (filterText === 'All Locations') {
      $closestDepartmentTitle.show();
      $departmentTitles.show();
    } else {
      $closestDepartmentTitle.hide();
      $departmentTitles.each(function() {
        var hideTitle = $(this).next().children().filter(function(filterIndex, filterElement) {
          return filterElement.style.display !== 'none';
        }).length === 0;
        if (hideTitle) {
          $(this).hide();
        }
      });
    }
  } else { // filter text matches target text
    $closestDepartmentTitle.show();
    $jobLocation.closest('ul').prev().show(); //Show the department title
  }
}

/*
* Click event on jobs dropdown filter
*/
function registerJobsFilterClick() {
  $('.js-location-filter').on('click', function() {
    var filterText = $(this).text();
    var $departmentTitles = $('.department-title');
    $('.js-filter-holder').text(filterText);
    $('.job-location').each(function() {
      var $jobLocation = $(this);
      var $closestDepartmentTitle = $jobLocation.closest('li');

      showOrHideJobs(filterText, $jobLocation, $closestDepartmentTitle, $departmentTitles);
    });
  });
}

function getGreenhouseData(data) {
  var locations = [];

  if(typeof data === 'object'){

    $.each(data.departments, function(i, department) {
      if(department.jobs.length === 0){
        delete data.departments[i];
      } else {
        // iterate over jobs to get all locations
        $.each(department.jobs, function(j, job) {
          locations.push(job.location.name);
        });
      }
    });
    $.unique(locations);

    // Add locations as dropdown options
    $.each(locations, function(index, location) {
      $('#js-locations').append('
' + location + '
');
    });
    $('#job-list-cont').append( jobList(data) );

    registerJobsFilterClick();
  }
}

// Jobs location filter dropdown
var $dropdownElems = $('.js-dropdown');
$dropdownElems.click(function() {
  var $this = $(this);
  $this.toggleClass('active');
  $dropdownElems.not( $this ).removeClass( 'active' );
  $this.one('mouseleave', function(){
    $this.removeClass( 'active' );
  });
});

var deferred = $.getJSON('https://api.greenhouse.io/v1/boards/optimizely7/embed/departments?callback=?');

deferred.then(getGreenhouseData, function(err) {
    window.analytics.track('https://api.greenhouse.io/v1/boards/optimizely7/embed/departments?callback=?', {
      category: 'api error',
      label: err.responseText + ', Response Code: ' + err.status,
    }, {
      integrations: {
        Marketo: false
      }
    });
});
<|endoftext|>


<commit_before>/* globals Prism */
(function ($, Prism) {
    'use strict';

    // My plugin default options
    var defaultOptions = {};

    function highlightIt(text, language) {
        return [
            '
',
            '' + Prism.highlight(text, Prism.languages[language]) + '',
            '
',
        ].join('');
    }

    // If my plugin is a button
    function buildButtonDef(trumbowyg) {
        return {
            fn: function () {
                var $modal = trumbowyg.openModal('Code', [
                    '
',
                    '   <select class="' + trumbowyg.o.prefix + 'highlight-form-control language">',
                    (function () {
                        var options = '';

                        for (var lang in Prism.languages) {
                            if (Prism.languages.hasOwnProperty(lang)) {
                                options += '<option value="' + lang + '">' + lang + '</option>';
                            }
                        }

                        return options;
                    })(),
                    '   </select>',
                    '
',
                    '
',
                    '   <textarea class="' + trumbowyg.o.prefix + 'highlight-form-control code"></textarea>',
                    '
',
                ].join('\n')),
                $language = $modal.find('.language'),
                $code = $modal.find('.code');

                // Listen clicks on modal box buttons
                $modal.on('tbwconfirm', function () {
                    trumbowyg.restoreRange();
                    trumbowyg.execCmd('insertHTML', highlightIt($code.val(), $language.val()));
                    trumbowyg.execCmd('insertHTML', '

');

                    trumbowyg.closeModal();
                });

                $modal.on('tbwcancel', function () {
                    trumbowyg.closeModal();
                });
            }
        };
    }

    $.extend(true, $.trumbowyg, {
        // Add some translations
        langs: {
            en: {
                highlight: 'Code syntax highlight'
            },
            pt_br: {
                highlight: 'Realçar sintaxe de código'
            }
        },
        // Add our plugin to Trumbowyg registred plugins
        plugins: {
            highlight: {
                init: function (trumbowyg) {
                    // Fill current Trumbowyg instance with my plugin default options
                    trumbowyg.o.plugins.highlight = $.extend(true, {},
                        defaultOptions,
                        trumbowyg.o.plugins.highlight || {}
                    );

                    // If my plugin is a button
                    trumbowyg.addBtnDef('highlight', buildButtonDef(trumbowyg));
                }
            }
        }
    });
})(jQuery, Prism);
<commit_msg>feat: add korean translation to highlight plugin<commit_after>/* globals Prism */
(function ($, Prism) {
    'use strict';

    // My plugin default options
    var defaultOptions = {};

    function highlightIt(text, language) {
        return [
            '
',
            '' + Prism.highlight(text, Prism.languages[language]) + '',
            '
',
        ].join('');
    }

    // If my plugin is a button
    function buildButtonDef(trumbowyg) {
        return {
            fn: function () {
                var $modal = trumbowyg.openModal('Code', [
                    '
',
                    '   <select class="' + trumbowyg.o.prefix + 'highlight-form-control language">',
                    (function () {
                        var options = '';

                        for (var lang in Prism.languages) {
                            if (Prism.languages.hasOwnProperty(lang)) {
                                options += '<option value="' + lang + '">' + lang + '</option>';
                            }
                        }

                        return options;
                    })(),
                    '   </select>',
                    '
',
                    '
',
                    '   <textarea class="' + trumbowyg.o.prefix + 'highlight-form-control code"></textarea>',
                    '
',
                ].join('\n')),
                $language = $modal.find('.language'),
                $code = $modal.find('.code');

                // Listen clicks on modal box buttons
                $modal.on('tbwconfirm', function () {
                    trumbowyg.restoreRange();
                    trumbowyg.execCmd('insertHTML', highlightIt($code.val(), $language.val()));
                    trumbowyg.execCmd('insertHTML', '

');

                    trumbowyg.closeModal();
                });

                $modal.on('tbwcancel', function () {
                    trumbowyg.closeModal();
                });
            }
        };
    }

    $.extend(true, $.trumbowyg, {
        // Add some translations
        langs: {
            en: {
                highlight: 'Code syntax highlight'
            },
            pt_br: {
                highlight: 'Realçar sintaxe de código'
            },
            ko: {
                highlight: '코드 문법 하이라이트'
            },
        },
        // Add our plugin to Trumbowyg registred plugins
        plugins: {
            highlight: {
                init: function (trumbowyg) {
                    // Fill current Trumbowyg instance with my plugin default options
                    trumbowyg.o.plugins.highlight = $.extend(true, {},
                        defaultOptions,
                        trumbowyg.o.plugins.highlight || {}
                    );

                    // If my plugin is a button
                    trumbowyg.addBtnDef('highlight', buildButtonDef(trumbowyg));
                }
            }
        }
    });
})(jQuery, Prism);
<|endoftext|>


<commit_before>import * as antd from 'uniforms-antd';
import * as bootstrap3 from 'uniforms-bootstrap3';
import * as bootstrap4 from 'uniforms-bootstrap4';
import * as material from 'uniforms-material';
import * as semantic from 'uniforms-semantic';
import * as unstyled from 'uniforms-unstyled';

const themes = {
  antd,
  bootstrap3,
  bootstrap4,
  material,
  semantic,
  unstyled
};

export default themes;
<commit_msg>Selected semanthic theme as default in playground.<commit_after>import * as antd from 'uniforms-antd';
import * as bootstrap3 from 'uniforms-bootstrap3';
import * as bootstrap4 from 'uniforms-bootstrap4';
import * as material from 'uniforms-material';
import * as semantic from 'uniforms-semantic';
import * as unstyled from 'uniforms-unstyled';

const themes = {
  semantic,
  bootstrap3,
  bootstrap4,
  material,
  antd,
  unstyled
};

export default themes;
<|endoftext|>


<commit_before>/**
 * A simple folder picker plugin built on Treebeard.
 * Takes the same options as Treebeard and additionally requires an
 * `onChooseFolder` option (the callback executed when a folder is selected).
 *
 * Usage:
 *
 *     $('#myPicker').folderpicker({
 *         data: // Array of Treebeard-formatted data or URL to fetch data
 *         onPickFolder: function(evt, folder) {
 *             // do something with folder
 *         }
 *     });
 */
;(function (global, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery', 'treebeard'], factory);
    } else if (typeof $script === 'function') {
        $script.ready(['treebeard'], function() {
            global.FolderPicker = factory(jQuery, Treebeard);
            $script.done('folderPicker');
        });
    } else {
        global.FolderPicker = factory(jQuery, global.Treebeard);
    }
}(this, function($, Treebeard){
    'use strict';

    // Extend the default Treebeard name column
    FolderPicker.columnTitles = [];
    FolderPicker.columnTitles.push({
            title: 'Folders',
            width : '75%',
            sort : false
        },
        {
            title : 'Select',
            width : '25%',
            sort : false
    });

    FolderPicker.resolveRows = [];
    FolderPicker.resolveRows.push({
            data : 'name',  // Data field name
            folderIcons : true,
            filter : false,
            custom : _treebeardTitleColumn
        },
        {
            sortInclude : false,
            filter : false,
            custom : _treebeardSelectView
    });

    function _treebeardResolveToggle(item){
        if (item.data.path!="/") {
            item.open=false;
            var toggleMinus = m('i.icon-minus', ' '),
                togglePlus = m('i.icon-plus', ' ');
            if (item.kind === 'folder') {
                if (item.open) {
                    return toggleMinus;
                }
                return togglePlus;
            }
        }
        return '';
    }

    // Returns custom icons for OSF
    function _treebeardResolveIcon(item){
        var openFolder  = m('i.icon-folder-open-alt', ' '),
            closedFolder = m('i.icon-folder-close-alt', ' ');

        if (item.open) {
            return openFolder;
        }

        return closedFolder;
    }

    var INPUT_NAME = '-folder-select';
    //THIS NEEDS TO BE FIXED SO THAT ON CLICK IT OPENS THE FOLDER.
    function _treebeardTitleColumn (item, col) {
        return m('span', item.data.name);
    }

    /**
     * Returns the folder select button for a single row.
     */
    function _treebeardSelectView(item) {

        return m("input",{
            type:"radio",
            name:this.selector + INPUT_NAME,
            value:item.id,
            checked:function(){
                console.log("Proof of Concept: RADIO BUTTON CLICKED");
                return item._fpChecked ? ' checked ': ' ';
            }
        }, " ")
    }

    function _treebeardColumnTitle(){
        var columns = [];
        columns.push({
            title: 'Folders',
            width : '75%',
            sort : false
        },
        {
            title : 'Select',
            width : '25%',
            sort : false
        });

        return columns;
    }

    function _treebeardResolveRows(item){
        // this = treebeard;
        item.css = '';
        var default_columns = [];             // Defines columns based on data
        default_columns.push({
            data : 'name',  // Data field name
            folderIcons : true,
            filter : false,
            custom : _treebeardTitleColumn
        });

        default_columns.push(
            {
            sortInclude : false,
            custom : _treebeardSelectView
        });

        return default_columns;
    }

    // Upon clicking the name of folder, toggle its collapsed state
    //function onClickName(evt, row, grid) {
    //    grid.toggleCollapse(row);
    //}

    // Default HGrid options
    var defaults = {
        columnTitles : _treebeardColumnTitle,
        resolveRows : _treebeardResolveRows,
        resolveIcon : _treebeardResolveIcon,
        resolveToggle : _treebeardResolveToggle,
        // Disable uploads
        uploads: false
        // Add listener that expands a folder upon clicking its name
        /*listeners: [
            {selector: '.' + HGrid.Html.nameClass, on: 'click',
            callback: onClickName}
        ],*/
    };

    function FolderPicker(selector, opts) {
        var self = this;
        self.selector = selector;
        self.checkedRowId = null;
        // Custom Treebeard action to select a folder that uses the passed in
        // "onChooseFolder" callback
        if (!opts.onPickFolder) {
            throw 'FolderPicker must have the "onPickFolder" option defined';
        }
        self.options = $.extend({}, defaults, opts);
        self.options.filterOn = false;
        self.options.divID = selector.substring(1);

        //self.options.columnTitles = _treebeardTitleColumn();
        //self.options.resolveRows = _treebeardSelectView();

        // Start up the grid
        self.grid = Treebeard.run(self.options);
        // Set up listener for folder selection
        $(selector).on('change', 'input[name="' + self.selector + INPUT_NAME + '"]', function(evt) {
            console.log("RADIO BUTTON CHANGED");
            var id = $(this).val();
            var row = self.grid.getByID(id);
            // Store checked state of rows so that it doesn't uncheck when HGrid is redrawn
            var oldRow = self.grid.getByID(self.checkedRowId);
            if (oldRow) {
                oldRow._fpChecked = false;
            }
            self.checkedRowId = row.id;
            row._fpChecked = true;
            self.options.onPickFolder.call(self, evt, row);
        });
    }

    // Augment jQuery
    $.fn.folderpicker = function(options) {
        this.each(function() {
            // Treebeard must take an ID as a selector if using as a jQuery plugin
            if (!this.id) { throw 'FolderPicker must have an ID if initializing with jQuery.'; }
            var selector = '#' + this.id;
            return new FolderPicker(selector, options);
        });
    };
    // Export
    return FolderPicker;
}));
<commit_msg>Radio Buttons Function<commit_after>/**
 * A simple folder picker plugin built on Treebeard.
 * Takes the same options as Treebeard and additionally requires an
 * `onChooseFolder` option (the callback executed when a folder is selected).
 *
 * Usage:
 *
 *     $('#myPicker').folderpicker({
 *         data: // Array of Treebeard-formatted data or URL to fetch data
 *         onPickFolder: function(evt, folder) {
 *             // do something with folder
 *         }
 *     });
 */
;(function (global, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery', 'treebeard'], factory);
    } else if (typeof $script === 'function') {
        $script.ready(['treebeard'], function() {
            global.FolderPicker = factory(jQuery, Treebeard);
            $script.done('folderPicker');
        });
    } else {
        global.FolderPicker = factory(jQuery, global.Treebeard);
    }
}(this, function($, Treebeard){
    'use strict';

    // Extend the default Treebeard name column
    FolderPicker.columnTitles = [];
    FolderPicker.columnTitles.push({
            title: 'Folders',
            width : '75%',
            sort : false
        },
        {
            title : 'Select',
            width : '25%',
            sort : false
    });

    FolderPicker.resolveRows = [];
    FolderPicker.resolveRows.push({
            data : 'name',  // Data field name
            folderIcons : true,
            filter : false,
            custom : _treebeardTitleColumn
        },
        {
            sortInclude : false,
            filter : false,
            custom : _treebeardSelectView
    });

    function _treebeardResolveToggle(item){
        if (item.data.path!="/") {
            item.open=false;
            var toggleMinus = m('i.icon-minus', ' '),
                togglePlus = m('i.icon-plus', ' ');
            if (item.kind === 'folder') {
                if (item.open) {
                    return toggleMinus;
                }
                return togglePlus;
            }
        }
        return '';
    }

    // Returns custom icons for OSF
    function _treebeardResolveIcon(item){
        var openFolder  = m('i.icon-folder-open-alt', ' '),
            closedFolder = m('i.icon-folder-close-alt', ' ');

        if (item.open) {
            return openFolder;
        }

        return closedFolder;
    }

    var INPUT_NAME = '-folder-select';
    //THIS NEEDS TO BE FIXED SO THAT ON CLICK IT OPENS THE FOLDER.
    function _treebeardTitleColumn (item, col) {
        return m('span', item.data.name);
    }

    /**
     * Returns the folder select button for a single row.
     */
    function _treebeardSelectView(item) {

        return m("input",{
            type:"radio",
            name: "#" + this.options.divID + INPUT_NAME,
            value:item.id,
            checked: item._fpChecked ? ' checked ': ' '
        }, " ")
    }

    function _treebeardColumnTitle(){
        var columns = [];
        columns.push({
            title: 'Folders',
            width : '75%',
            sort : false
        },
        {
            title : 'Select',
            width : '25%',
            sort : false
        });

        return columns;
    }

    function _treebeardResolveRows(item){
        // this = treebeard;
        item.css = '';
        var default_columns = [];             // Defines columns based on data
        default_columns.push({
            data : 'name',  // Data field name
            folderIcons : true,
            filter : false,
            custom : _treebeardTitleColumn
        });

        default_columns.push(
            {
            sortInclude : false,
            custom : _treebeardSelectView
        });

        return default_columns;
    }

    // Upon clicking the name of folder, toggle its collapsed state
    //function onClickName(evt, row, grid) {
    //    grid.toggleCollapse(row);
    //}

    // Default HGrid options
    var defaults = {
        columnTitles : _treebeardColumnTitle,
        resolveRows : _treebeardResolveRows,
        resolveIcon : _treebeardResolveIcon,
        resolveToggle : _treebeardResolveToggle,
        // Disable uploads
        uploads: false
        // Add listener that expands a folder upon clicking its name
        /*listeners: [
            {selector: '.' + HGrid.Html.nameClass, on: 'click',
            callback: onClickName}
        ],*/
    };

    function FolderPicker(selector, opts) {
        var self = this;
        self.selector = selector;
        self.checkedRowId = null;
        // Custom Treebeard action to select a folder that uses the passed in
        // "onChooseFolder" callback
        if (!opts.onPickFolder) {
            throw 'FolderPicker must have the "onPickFolder" option defined';
        }
        self.options = $.extend({}, defaults, opts);
        self.options.filterOn = false;
        self.options.divID = selector.substring(1);

        //self.options.columnTitles = _treebeardTitleColumn();
        //self.options.resolveRows = _treebeardSelectView();

        // Start up the grid
        self.grid = Treebeard.run(self.options);
        // Set up listener for folder selection
        $(selector).on('change', 'input[name="' + self.selector + INPUT_NAME + '"]', function(evt) {
            console.log("RADIO BUTTON CHANGED");
            var id = $(this).val();
            var row = self.grid.find(id);
            // Store checked state of rows so that it doesn't uncheck when HGrid is redrawn
            var oldRow = self.grid.find(self.checkedRowId);
            if (oldRow) {
                oldRow._fpChecked = false;
            }
            self.checkedRowId = row.id;
            row._fpChecked = true;
            self.options.onPickFolder.call(self, evt, row);
        });
    }

    // Augment jQuery
    $.fn.folderpicker = function(options) {
        this.each(function() {
            // Treebeard must take an ID as a selector if using as a jQuery plugin
            if (!this.id) { throw 'FolderPicker must have an ID if initializing with jQuery.'; }
            var selector = '#' + this.id;
            return new FolderPicker(selector, options);
        });
    };
    // Export
    return FolderPicker;
}));
<|endoftext|>


<commit_before>/**
 * Initialization code for the home page.
 */

'use strict';

var $ = require('jquery');
var m = require('mithril');

var QuickSearchProject = require('js/home-page/quickProjectSearchPlugin');
var NewAndNoteworthy = require('js/home-page/newAndNoteworthyPlugin');
var MeetingsAndConferences = require('js/home-page/meetingsAndConferencesPlugin');
var AddProject = require('js/addProjectPlugin');
var $osf = require('js/osfHelpers');
var Raven = require('raven-js');

var xhrconfig = function (xhr) {
    xhr.withCredentials = true;
    xhr.setRequestHeader('Content-Type', 'application/vnd.api+json;');
    xhr.setRequestHeader('Accept', 'application/vnd.api+json; ext=bulk');
};
var columnSizeClass = '.col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2';

$(document).ready(function(){
    var osfHome = {
        controller : function(){
            var self = this;
            self.categoryList = [];
            self.loadCategories = function _loadCategories () {
                var promise = m.request({method : 'OPTIONS', url : $osf.apiV2Url('nodes/', { query : {}}), config : xhrconfig});
                promise.then(function _success(results){
                    if(results.actions.POST.category){
                        self.categoryList = results.actions.POST.category.choices;
                        self.categoryList.sort(function(a, b){ // Quick alphabetical sorting
                            if(a.value < b.value) return -1;
                            if(a.value > b.value) return 1;
                            return 0;
                        });
                    }
                }, function _error(results){
                    var message = 'Error loading project category names for the home page.';
                    Raven.captureMessage(message, {requestReturn: results});
                });
                return promise;
            };
            self.loadCategories();

        },
        view : function(ctrl, args) {
            return [
                m('.quickSearch', m('.container.p-t-lg',
                    [
                        m('.row', [
                            m(columnSizeClass, m('.pull-right',
                                m.component(AddProject, {
                                    buttonTemplate : m('button.btn.btn-success.m-t-md[data-toggle="modal"][data-target="#addProjectFromHome"]', {onclick: function(){
                                        $osf.trackClick('quickSearch', 'add-project', 'open-add-project-modal');
                                    }}, 'Create New Project'),
                                    modalID : 'addProjectFromHome',
                                    categoryList : ctrl.categoryList,
                                    stayCallback : function _stayCallback_inPanel() {
                                        document.location.reload(true);
                                    },
                                    trackingCategory: 'quickSearch',
                                    trackingAction: 'add-project'
                                })
                            ))
                        ]),
                        m('.row.m-t-lg', [
                            m(columnSizeClass, m.component(QuickSearchProject, {}))
                        ])
                    ]
                )),
                m('.newAndNoteworthy', m('.container',
                    [
                        m('.row', [
                            m(columnSizeClass,m('h3', 'Discover Public Projects'))
                        ]),
                        m('.row', [
                            m(columnSizeClass, m.component(NewAndNoteworthy, {}))
                        ])

                    ]
                )),
                m('.meetings', m('.container',
                    [
                        m('.row', [
                            m(columnSizeClass,  m.component(MeetingsAndConferences, {}))
                        ])

                    ]
                ))
            ];
        }
    };
    // If logged in...
    m.mount(document.getElementById('osfHome'), m.component(osfHome, {}));

});
<commit_msg>Remove loading of categories and therefore, controller. Top level projects don't have categories.<commit_after>/**
 * Initialization code for the home page.
 */

'use strict';

var $ = require('jquery');
var m = require('mithril');

var QuickSearchProject = require('js/home-page/quickProjectSearchPlugin');
var NewAndNoteworthy = require('js/home-page/newAndNoteworthyPlugin');
var MeetingsAndConferences = require('js/home-page/meetingsAndConferencesPlugin');
var AddProject = require('js/addProjectPlugin');
var $osf = require('js/osfHelpers');
var Raven = require('raven-js');

var xhrconfig = function (xhr) {
    xhr.withCredentials = true;
    xhr.setRequestHeader('Content-Type', 'application/vnd.api+json;');
    xhr.setRequestHeader('Accept', 'application/vnd.api+json; ext=bulk');
};
var columnSizeClass = '.col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2';

$(document).ready(function(){
    var osfHome = {
        view : function(ctrl, args) {
            return [
                m('.quickSearch', m('.container.p-t-lg',
                    [
                        m('.row', [
                            m(columnSizeClass, m('.pull-right',
                                m.component(AddProject, {
                                    buttonTemplate : m('button.btn.btn-success.m-t-md[data-toggle="modal"][data-target="#addProjectFromHome"]', {onclick: function(){
                                        $osf.trackClick('quickSearch', 'add-project', 'open-add-project-modal');
                                    }}, 'Create New Project'),
                                    modalID : 'addProjectFromHome',
                                    categoryList : ctrl.categoryList,
                                    stayCallback : function _stayCallback_inPanel() {
                                        document.location.reload(true);
                                    },
                                    trackingCategory: 'quickSearch',
                                    trackingAction: 'add-project'
                                })
                            ))
                        ]),
                        m('.row.m-t-lg', [
                            m(columnSizeClass, m.component(QuickSearchProject, {}))
                        ])
                    ]
                )),
                m('.newAndNoteworthy', m('.container',
                    [
                        m('.row', [
                            m(columnSizeClass,m('h3', 'Discover Public Projects'))
                        ]),
                        m('.row', [
                            m(columnSizeClass, m.component(NewAndNoteworthy, {}))
                        ])

                    ]
                )),
                m('.meetings', m('.container',
                    [
                        m('.row', [
                            m(columnSizeClass,  m.component(MeetingsAndConferences, {}))
                        ])

                    ]
                ))
            ];
        }
    };
    // If logged in...
    m.mount(document.getElementById('osfHome'), m.component(osfHome, {}));

});
<|endoftext|>