<commit_before>'use strict';

/* Controllers */

function HeaderController($scope, $location) {

  $scope.alreadyhome = function() {
    return $location.path() == '/playground/';
  }

}

function PageController($scope, $http, DoSerial, $routeParams, $window, $location) {

  function getconfig() {
    return $http.get('/playground/getconfig')
    .success(function(data, status, headers, config) {
       $scope.config = data;
    });
  };

  function getprojects() {
    return $http.get('/playground/getprojects')
    .success(function(data, status, headers, config) {
      $scope.projects = data;
    });
  };

  DoSerial
  .then(getconfig)
  .then(getprojects)

  $scope.namespace = function() {
    return $routeParams.project_id ||
           ($scope.config && $scope.config.playground_namespace);
  };

  // TODO: use window open service
  $scope.datastore_admin = function() {
    $window.open('/playground/datastore/' + $scope.namespace(), '_blank');
  };

  // TODO: use window open service
  $scope.memcache_admin = function() {
    $window.open('/playground/memcache/' + $scope.namespace(), '_blank');
  };

  // TODO: test
  $scope.big_red_button = function() {
    DoSerial
    .then(function() {
      return $http.post('/playground/nuke')
      .success(function(data, status, headers, config) {
        document.body.scrollTop = 0;
        $window.location.reload();
      });
    });
  };

  // TODO: test
  $scope.has_projects = function() {
    for (var i in $scope.projects) {
      return true;
    }
    return false;
  };

  // TODO: test
  $scope.prompt_to_delete_project = function(project) {
    // TODO: use $dialog instead of prompt()
    var answer = prompt("Are you sure you want to delete project " +
                        project.name + "?\nType 'yes' to confirm.", "no");
    if (!answer || answer.toLowerCase()[0] != 'y') {
      return;
    }
    $scope.project = undefined;
    $http.post('/playground/p/' + encodeURI(project.key) + '/delete')
    .success(function(data, status, headers, config) {
      for (var i in $scope.projects) {
        if ($scope.projects[i] == project) {
          $scope.projects.splice(i, 1);
          break;
        }
      }
      $location.path('/playground/');
    });
  };

}

function MainController($scope, $http, $window, $location, DoSerial) {

  DoSerial
  .then(function() {
    return $http.get('/playground/gettemplates')
    .success(function(data, status, headers, config) {
      $scope.templates = data;
    });
  })
  .then(function() {
    $scope.loaded = true;
  });

  $scope.login = function() {
    $window.location.replace('/playground/login');
  }

  $scope.new_project = function(template) {
    DoSerial
    .then(function() {
      var data = {
        'name': '(Creating project...)',
        'description': '(Please wait...)',
      };
      $scope.projects.push(data);
    })
    .then(function() {
      return $http.post('/playground/createproject', {
          template_url: template.key,
          project_name: template.name,
          project_description: template.description})
      .success(function(data, status, headers, config) {
        $scope.projects.pop();
        $scope.projects.push(data);
      });
    });
  };

  $scope.select_project = function(project) {
    DoSerial
    .then(function() {
      return $http.post('/playground/p/' + project.key + '/touch')
      .success(function(data, status, headers, config) {
        for (var i in $scope.projects) {
          if ($scope.projects[i] == project) {
            $scope.projects[i] = project = data;
            break;
          }
        }
        $location.path('/playground/p/' + project.key);
      });
    });
  }

}

// TODO: test
function NewFileController($scope, $log, dialog) {

  $scope.close = function(path) {
    dialog.close(path);
  }

}

function ProjectController($scope, $browser, $http, $routeParams, $window,
                           $dialog, $log, DoSerial, DomElementById, WrappedElementById) {

  // TODO: remove once file contents are returned in JSON response
  $scope.no_json_transform = function(data) { return data; };

  $scope.url_of = function(file) {
    return '//' + $scope.config.PLAYGROUND_USER_CONTENT_HOST +
           // TODO: replace with $location.path()
           //$location.path() +
           $window.location.pathname +
           'getfile/' +
           encodeURI(file.name);
  };

  $scope.image_url_of = function(file) {
    return (file && $scope.is_image_mime_type(file.mime_type)) ?
        $scope.url_of(file) : '';
  };

  // TODO: this.foo = function() {...} // for testability
  $scope._get = function(file, success_cb) {
    if (file.hasOwnProperty('contents')) {
      success_cb();
      return;
    }
    var url = $scope.url_of(file);
    $http.get(url, {transformResponse: $scope.no_json_transform})
    .success(function(data, status, headers, config) {
      file.contents = data;
      file.dirty = false;
      success_cb();
    });
  };

  $scope.is_image_mime_type = function(mime_type) {
    return /^image\//.test(mime_type);
  };

  $scope._list_files = function() {
    // Workaround https://github.com/angular/angular.js/issues/1761
    var url = $browser.url() + 'listfiles';
    return $http.get(url)
    .success(function(data, status, headers, config) {
      $scope.files = {};
      angular.forEach(data, function(props, i) {
        $scope.files[props.name] = props;
      });
    });
  };

  // TODO: test
  function _save_dirty_files() {
    for (var path in $scope.files) {
      if ($scope.files[path].dirty) {
        var dirtypath = path;
        DoSerial
        .then(function() {
          return _save(dirtypath);
        })
        break;
      }
    }
  }

  // TODO: test
  $scope.editor_on_change = function(from, to, text, next) {
    $scope.$apply(function() {
      $scope.current_file.contents = $scope._editor.getValue();
      if ($scope.current_file.dirty) {
        return;
      }
      $scope.current_file.dirty = true;
      Backoff.schedule(_save_dirty_files);
    });
  };

  // TODO: consider replacing DOM maniupulation here with a directive
  // TODO: create CodeMirror service (directives can't be injected into controller)
  $scope.create_editor = function(mime_type) {
    if ($scope._editor) {
      angular.element($scope._editor.getWrapperElement()).remove();
    }
    $scope._editor = $window.CodeMirror(DomElementById('source-code'), {
      mode: mime_type,
      lineNumbers: true,
      matchBrackets: true,
      undoDepth: 440, // default = 40
    });
    //$scope._editor.getScrollerElement().id = 'scroller-element';
    $scope._editor.setValue($scope.current_file.contents);
    $scope._editor.setOption('onChange', $scope.editor_on_change);
    $scope._editor.focus();
  }

  $scope.select_file = function(file) {
    if ($scope.is_image_mime_type(file.mime_type)) {
      $scope.current_file = file;
      return;
    }
    $scope._get(file, function() {
      return DoSerial
      .then(function() {
        $scope.current_file = file;
      })
      .tick() // needed when switching from source-image to editor
      .then(function() {
        $scope.create_editor(file.mime_type);
      });
    });
  };

  $scope._select_first_file = function() {
    for (var path in $scope.files) {
      $scope.select_file($scope.files[path]);
      break;
    }
  }

  DoSerial
  .then(function() {
    for (var i in $scope.projects) {
      if ($scope.projects[i].key == $routeParams.project_id) {
        $scope.project = $scope.projects[i];
        break;
      }
    }
  })
  .then($scope._list_files)
  .then($scope._select_first_file);

  // TODO: test
  $scope.insert_path = function(path) {
    var file = $scope.files[path];
    if (!file) {
      file = {
          name: path,
          mime_type: 'text/plain',
          contents: '',
          dirty: false,
      };
      $scope.files[path] = file;
    }
    $scope.select_file(file);
  };

  // TODO: test
  $scope.prompt_new_file = function() {
    $dialog.dialog({
        controller: 'NewFileController',
        templateUrl: '/playground/new_file_modal.html',
    })
    .open().then(function(path) {
      if (path) {
        // remove leading and trailing slash(es)
        path = path.replace(/^\/*(.*?)\/*$/, '$1')
        $scope.insert_path(path);
      }
    });
  };

  // TODO: remove
  function hide_context_menus() {
    $scope.showfilecontextmenu = false;
    $scope.showprojectcontextmenu = false;
  }

  // TODO: remove
  window.addEventListener('click', function(evt) {
    hide_context_menus();
    $scope.$apply();
  }, false);

  // TODO: test
  // TODO: replace with $dialog
  $scope.project_context_menu = function(evt) {
    // TODO: avoid DOM access; use directive instead
    evt.stopPropagation();
    hide_context_menus();
    $scope.showprojectcontextmenu = true;
    var menuDiv = WrappedElementById('project-context-menu');
    menuDiv.css('left', evt.pageX + 'px');
    menuDiv.css('top', evt.pageY + 'px');
  };

  // TODO: test
  $scope.prompt_project_rename = function(project) {
    // TODO: user $dialog instead of prompt()
    var new_project_name = prompt('Enter a new name for this project',
                                  project.name);
    if (!new_project_name) {
      return;
    }
    DoSerial
    .then(function() {
      return $http.post('rename', {newname: new_project_name})
      .success(function(data, status, headers, config) {
        for (var i in $scope.projects) {
          if ($scope.projects[i] == project) {
            $scope.project = $scope.projects[i] = data;
            break;
          }
        }
      });
    });
  }

}

/*

function ProjectController($scope, $http, $filter, $log, $timeout, $routeParams,
                           Backoff, DoSerial, DomElementById,
                           WrappedElementById) {

  // TODO: use directive
  var source_image = WrappedElementById('source-image');

  // { "app.yaml" : {
  //        "name"     : "app.yaml",
  //        "mime_type": "text/yaml",
  //        "contents" : "...",
  //        "dirty"    : false },
  //   "main.py" : {
  //        ...
  //   }
  // }
  $scope.files = {};

  var _output_window;
  var _popout = false;

  $scope.popout = function() {
    _popout = true;
    _output_window = undefined;
  }

  $scope.selectme = function(evt) {
    var elem = evt.srcElement;
    elem.focus();
    elem.select();
  }

  $scope.run = function() {
    return DoSerial
    .then(function() {
      _save_dirty_files();
    })
    .then(function() {
      // TODO: try to avoid DOM access
      var container = WrappedElementById('output-container');
      if (_output_window && _output_window.closed) {
        _popout = false;
      }
      if (_popout) {
        container.addClass('hidden');
        // TODO: create open window service (so we can test)
        // TODO: read https://github.com/vojtajina/ng-directive-testing
        _output_window = window.open($scope.project.run_url,
                                     $scope.project.key);
      } else {
        container.removeClass('hidden');
        var iframe = WrappedElementById('output-iframe');
        iframe.attr('src', $scope.project.run_url);
      }
    });
  }

  function _save(path) {
    var file = $scope.files[path];
    if (!file.dirty) {
      return;
    }
    file.dirty = false;
    $scope.filestatus = 'Saving ' + path + ' ...';
    return $http.put('putfile/' + encodeURI(path), file.contents, {
                     headers: {'Content-Type': 'text/plain; charset=utf-8'}
    })
    .success(function(data, status, headers, config) {
      $scope.filestatus = ''; // saved
      Backoff.reset();
    })
    .error(function(data, status, headers, config) {
      $scope.filestatus = 'Failed to save ' + path;
      file.dirty = true;
      // implement seconds() function
      var secs = Backoff.backoff() / 1000;
      $log.warn(path, 'failed to save; will retry in', secs, 'secs');
      Backoff.schedule(_save_dirty_files);
    });
  }

  // TODO: don't use prompt()
  $scope.prompt_file_delete = function() {
    var answer = prompt("Are you sure you want to delete " +
                        $scope.current_file.name + "?\nType 'yes' to confirm.",
                        "no");
    if (!answer || answer.toLowerCase()[0] != 'y') {
      return;
    }
    $scope.deletefile($scope.current_file);
  }

  // TODO: don't use prompt()
  $scope.prompt_file_rename = function() {
    var new_filename = prompt(
        'New filename?\n(You may specify a full path such as: foo/bar.txt)',
        $scope.current_file.name);
    if (!new_filename) {
      return;
    }
    if (new_filename[0] == '/') {
      new_filename = new_filename.substr(1);
    }
    if (!new_filename || new_filename == $scope.current_file.name) {
      return;
    }
    $scope.movefile($scope.current_file, new_filename);
  }

  // TODO: avoid DOM access; use directive instead
  $scope.file_context_menu = function(evt, file) {
    evt.stopPropagation();
    hide_context_menus();
    $scope.select_file(file);
    $scope.showfilecontextmenu = true;
    var menuDiv = WrappedElementById('file-context-menu');
    menuDiv.css('left', evt.pageX + 'px');
    menuDiv.css('top', evt.pageY + 'px');
  };

  $scope.deletefile = function(file) {
    DoSerial
    .then(function() {
      return $http.post('deletepath/' + encodeURI(file.name))
      .success(function(data, status, headers, config) {
        delete $scope.files[file.name];
        $scope._select_first_file();
      });
    });
  };

  $scope.movefile = function(file, newpath) {
    DoSerial
    .then(function() {
      var oldpath = file.name;
      $scope.files[newpath] = file;
      $scope.files[newpath].name = newpath;
      delete $scope.files[oldpath];
      return $http.post('movefile/' + encodeURI(oldpath), {newpath: newpath})
      .success(function(data, status, headers, config) {
        $scope.current_file = file;
      });
    });
  };

}
*/
<commit_msg>uncomment _save<commit_after>'use strict';

/* Controllers */

function HeaderController($scope, $location) {

  $scope.alreadyhome = function() {
    return $location.path() == '/playground/';
  }

}

function PageController($scope, $http, DoSerial, $routeParams, $window, $location) {

  function getconfig() {
    return $http.get('/playground/getconfig')
    .success(function(data, status, headers, config) {
       $scope.config = data;
    });
  };

  function getprojects() {
    return $http.get('/playground/getprojects')
    .success(function(data, status, headers, config) {
      $scope.projects = data;
    });
  };

  DoSerial
  .then(getconfig)
  .then(getprojects)

  $scope.namespace = function() {
    return $routeParams.project_id ||
           ($scope.config && $scope.config.playground_namespace);
  };

  // TODO: use window open service
  $scope.datastore_admin = function() {
    $window.open('/playground/datastore/' + $scope.namespace(), '_blank');
  };

  // TODO: use window open service
  $scope.memcache_admin = function() {
    $window.open('/playground/memcache/' + $scope.namespace(), '_blank');
  };

  // TODO: test
  $scope.big_red_button = function() {
    DoSerial
    .then(function() {
      return $http.post('/playground/nuke')
      .success(function(data, status, headers, config) {
        document.body.scrollTop = 0;
        $window.location.reload();
      });
    });
  };

  // TODO: test
  $scope.has_projects = function() {
    for (var i in $scope.projects) {
      return true;
    }
    return false;
  };

  // TODO: test
  $scope.prompt_to_delete_project = function(project) {
    // TODO: use $dialog instead of prompt()
    var answer = prompt("Are you sure you want to delete project " +
                        project.name + "?\nType 'yes' to confirm.", "no");
    if (!answer || answer.toLowerCase()[0] != 'y') {
      return;
    }
    $scope.project = undefined;
    $http.post('/playground/p/' + encodeURI(project.key) + '/delete')
    .success(function(data, status, headers, config) {
      for (var i in $scope.projects) {
        if ($scope.projects[i] == project) {
          $scope.projects.splice(i, 1);
          break;
        }
      }
      $location.path('/playground/');
    });
  };

}

function MainController($scope, $http, $window, $location, DoSerial) {

  DoSerial
  .then(function() {
    return $http.get('/playground/gettemplates')
    .success(function(data, status, headers, config) {
      $scope.templates = data;
    });
  })
  .then(function() {
    $scope.loaded = true;
  });

  $scope.login = function() {
    $window.location.replace('/playground/login');
  }

  $scope.new_project = function(template) {
    DoSerial
    .then(function() {
      var data = {
        'name': '(Creating project...)',
        'description': '(Please wait...)',
      };
      $scope.projects.push(data);
    })
    .then(function() {
      return $http.post('/playground/createproject', {
          template_url: template.key,
          project_name: template.name,
          project_description: template.description})
      .success(function(data, status, headers, config) {
        $scope.projects.pop();
        $scope.projects.push(data);
      });
    });
  };

  $scope.select_project = function(project) {
    DoSerial
    .then(function() {
      return $http.post('/playground/p/' + project.key + '/touch')
      .success(function(data, status, headers, config) {
        for (var i in $scope.projects) {
          if ($scope.projects[i] == project) {
            $scope.projects[i] = project = data;
            break;
          }
        }
        $location.path('/playground/p/' + project.key);
      });
    });
  }

}

// TODO: test
function NewFileController($scope, $log, dialog) {

  $scope.close = function(path) {
    dialog.close(path);
  }

}

function ProjectController($scope, $browser, $http, $routeParams, $window,
                           $dialog, $log, DoSerial, DomElementById, WrappedElementById,
                           Backoff) {

  // TODO: remove once file contents are returned in JSON response
  $scope.no_json_transform = function(data) { return data; };

  $scope.url_of = function(file) {
    return '//' + $scope.config.PLAYGROUND_USER_CONTENT_HOST +
           // TODO: replace with $location.path()
           //$location.path() +
           $window.location.pathname +
           'getfile/' +
           encodeURI(file.name);
  };

  $scope.image_url_of = function(file) {
    return (file && $scope.is_image_mime_type(file.mime_type)) ?
        $scope.url_of(file) : '';
  };

  // TODO: this.foo = function() {...} // for testability
  $scope._get = function(file, success_cb) {
    if (file.hasOwnProperty('contents')) {
      success_cb();
      return;
    }
    var url = $scope.url_of(file);
    $http.get(url, {transformResponse: $scope.no_json_transform})
    .success(function(data, status, headers, config) {
      file.contents = data;
      file.dirty = false;
      success_cb();
    });
  };

  $scope.is_image_mime_type = function(mime_type) {
    return /^image\//.test(mime_type);
  };

  $scope._list_files = function() {
    // Workaround https://github.com/angular/angular.js/issues/1761
    var url = $browser.url() + 'listfiles';
    return $http.get(url)
    .success(function(data, status, headers, config) {
      $scope.files = {};
      angular.forEach(data, function(props, i) {
        $scope.files[props.name] = props;
      });
    });
  };

  // TODO: test
  function _save(path) {
    var file = $scope.files[path];
    if (!file.dirty) {
      return;
    }
    file.dirty = false;
    $scope.filestatus = 'Saving ' + path + ' ...';
    return $http.put('putfile/' + encodeURI(path), file.contents, {
                     headers: {'Content-Type': 'text/plain; charset=utf-8'}
    })
    .success(function(data, status, headers, config) {
      $scope.filestatus = ''; // saved
      Backoff.reset();
    })
    .error(function(data, status, headers, config) {
      $scope.filestatus = 'Failed to save ' + path;
      file.dirty = true;
      // implement seconds() function
      var secs = Backoff.backoff() / 1000;
      $log.warn(path, 'failed to save; will retry in', secs, 'secs');
      Backoff.schedule(_save_dirty_files);
    });
  }

  // TODO: test
  function _save_dirty_files() {
    for (var path in $scope.files) {
      if ($scope.files[path].dirty) {
        var dirtypath = path;
        DoSerial
        .then(function() {
          return _save(dirtypath);
        })
        break;
      }
    }
  }

  // TODO: test
  $scope.editor_on_change = function(from, to, text, next) {
    $scope.$apply(function() {
      $scope.current_file.contents = $scope._editor.getValue();
      if ($scope.current_file.dirty) {
        return;
      }
      $scope.current_file.dirty = true;
      Backoff.schedule(_save_dirty_files);
    });
  };

  // TODO: consider replacing DOM maniupulation here with a directive
  // TODO: create CodeMirror service (directives can't be injected into controller)
  $scope.create_editor = function(mime_type) {
    if ($scope._editor) {
      angular.element($scope._editor.getWrapperElement()).remove();
    }
    $scope._editor = $window.CodeMirror(DomElementById('source-code'), {
      mode: mime_type,
      lineNumbers: true,
      matchBrackets: true,
      undoDepth: 440, // default = 40
    });
    //$scope._editor.getScrollerElement().id = 'scroller-element';
    $scope._editor.setValue($scope.current_file.contents);
    $scope._editor.setOption('onChange', $scope.editor_on_change);
    $scope._editor.focus();
  }

  $scope.select_file = function(file) {
    if ($scope.is_image_mime_type(file.mime_type)) {
      $scope.current_file = file;
      return;
    }
    $scope._get(file, function() {
      return DoSerial
      .then(function() {
        $scope.current_file = file;
      })
      .tick() // needed when switching from source-image to editor
      .then(function() {
        $scope.create_editor(file.mime_type);
      });
    });
  };

  $scope._select_first_file = function() {
    for (var path in $scope.files) {
      $scope.select_file($scope.files[path]);
      break;
    }
  }

  DoSerial
  .then(function() {
    for (var i in $scope.projects) {
      if ($scope.projects[i].key == $routeParams.project_id) {
        $scope.project = $scope.projects[i];
        break;
      }
    }
  })
  .then($scope._list_files)
  .then($scope._select_first_file);

  // TODO: test
  $scope.insert_path = function(path) {
    var file = $scope.files[path];
    if (!file) {
      file = {
          name: path,
          mime_type: 'text/plain',
          contents: '',
          dirty: false,
      };
      $scope.files[path] = file;
    }
    $scope.select_file(file);
  };

  // TODO: test
  $scope.prompt_new_file = function() {
    $dialog.dialog({
        controller: 'NewFileController',
        templateUrl: '/playground/new_file_modal.html',
    })
    .open().then(function(path) {
      if (path) {
        // remove leading and trailing slash(es)
        path = path.replace(/^\/*(.*?)\/*$/, '$1')
        $scope.insert_path(path);
      }
    });
  };

  // TODO: remove
  function hide_context_menus() {
    $scope.showfilecontextmenu = false;
    $scope.showprojectcontextmenu = false;
  }

  // TODO: remove
  window.addEventListener('click', function(evt) {
    hide_context_menus();
    $scope.$apply();
  }, false);

  // TODO: test
  // TODO: replace with $dialog
  $scope.project_context_menu = function(evt) {
    // TODO: avoid DOM access; use directive instead
    evt.stopPropagation();
    hide_context_menus();
    $scope.showprojectcontextmenu = true;
    var menuDiv = WrappedElementById('project-context-menu');
    menuDiv.css('left', evt.pageX + 'px');
    menuDiv.css('top', evt.pageY + 'px');
  };

  // TODO: test
  $scope.prompt_project_rename = function(project) {
    // TODO: user $dialog instead of prompt()
    var new_project_name = prompt('Enter a new name for this project',
                                  project.name);
    if (!new_project_name) {
      return;
    }
    DoSerial
    .then(function() {
      return $http.post('rename', {newname: new_project_name})
      .success(function(data, status, headers, config) {
        for (var i in $scope.projects) {
          if ($scope.projects[i] == project) {
            $scope.project = $scope.projects[i] = data;
            break;
          }
        }
      });
    });
  }

}

/*

function ProjectController($scope, $http, $filter, $log, $timeout, $routeParams,
                           Backoff, DoSerial, DomElementById,
                           WrappedElementById) {

  // TODO: use directive
  var source_image = WrappedElementById('source-image');

  // { "app.yaml" : {
  //        "name"     : "app.yaml",
  //        "mime_type": "text/yaml",
  //        "contents" : "...",
  //        "dirty"    : false },
  //   "main.py" : {
  //        ...
  //   }
  // }
  $scope.files = {};

  var _output_window;
  var _popout = false;

  $scope.popout = function() {
    _popout = true;
    _output_window = undefined;
  }

  $scope.selectme = function(evt) {
    var elem = evt.srcElement;
    elem.focus();
    elem.select();
  }

  $scope.run = function() {
    return DoSerial
    .then(function() {
      _save_dirty_files();
    })
    .then(function() {
      // TODO: try to avoid DOM access
      var container = WrappedElementById('output-container');
      if (_output_window && _output_window.closed) {
        _popout = false;
      }
      if (_popout) {
        container.addClass('hidden');
        // TODO: create open window service (so we can test)
        // TODO: read https://github.com/vojtajina/ng-directive-testing
        _output_window = window.open($scope.project.run_url,
                                     $scope.project.key);
      } else {
        container.removeClass('hidden');
        var iframe = WrappedElementById('output-iframe');
        iframe.attr('src', $scope.project.run_url);
      }
    });
  }

  // TODO: don't use prompt()
  $scope.prompt_file_delete = function() {
    var answer = prompt("Are you sure you want to delete " +
                        $scope.current_file.name + "?\nType 'yes' to confirm.",
                        "no");
    if (!answer || answer.toLowerCase()[0] != 'y') {
      return;
    }
    $scope.deletefile($scope.current_file);
  }

  // TODO: don't use prompt()
  $scope.prompt_file_rename = function() {
    var new_filename = prompt(
        'New filename?\n(You may specify a full path such as: foo/bar.txt)',
        $scope.current_file.name);
    if (!new_filename) {
      return;
    }
    if (new_filename[0] == '/') {
      new_filename = new_filename.substr(1);
    }
    if (!new_filename || new_filename == $scope.current_file.name) {
      return;
    }
    $scope.movefile($scope.current_file, new_filename);
  }

  // TODO: avoid DOM access; use directive instead
  $scope.file_context_menu = function(evt, file) {
    evt.stopPropagation();
    hide_context_menus();
    $scope.select_file(file);
    $scope.showfilecontextmenu = true;
    var menuDiv = WrappedElementById('file-context-menu');
    menuDiv.css('left', evt.pageX + 'px');
    menuDiv.css('top', evt.pageY + 'px');
  };

  $scope.deletefile = function(file) {
    DoSerial
    .then(function() {
      return $http.post('deletepath/' + encodeURI(file.name))
      .success(function(data, status, headers, config) {
        delete $scope.files[file.name];
        $scope._select_first_file();
      });
    });
  };

  $scope.movefile = function(file, newpath) {
    DoSerial
    .then(function() {
      var oldpath = file.name;
      $scope.files[newpath] = file;
      $scope.files[newpath].name = newpath;
      delete $scope.files[oldpath];
      return $http.post('movefile/' + encodeURI(oldpath), {newpath: newpath})
      .success(function(data, status, headers, config) {
        $scope.current_file = file;
      });
    });
  };

}
*/
<|endoftext|>


<commit_before>'use strict';

var http = require('http');
var querystring = require('querystring');
var slack = require('slack-notify')(process.env.SLACK_HOOK_URL);
var prependHttp = require('prepend-http');

var config =  {
  username: process.env.USERNAME || 'slackshot',
  emoji: process.env.EMOJI || ':round_pushpin:',
  token: process.env.SLACK_TOKEN || void 0
};

http.createServer(function (req, res) {
  var body = '';
  req.on('data', function(chunk) {
    body += chunk;
  });

  req.on('end', function() {
    res.writeHead(200, "OK", {'Content-Type': 'text/html'});
    res.end();

    body = querystring.parse(body);
    console.log(body);

    handlePayload(body);
  });
}).listen(process.env.PORT || 1337);

function handlePayload(body){
  if(config.token && config.token !== body.token){
    return console.error('Token `' + body.token + '` didn\'t match environment variable');
  }

  var text = body.text.split(' ');
  var site = text.shift();
  var url = prependHttp(site);

  var query = {
    access_key: process.env.SCREENSHOTLAYER_TOKEN,
    url: url,
    viewport: "1440x900",
    width: 900
  }

  var screenshot = "http://api.screenshotlayer.com/api/capture" + "?" + querystring.stringify(query);

  slack.send({
    username: config.username,
    icon_emoji: config.emoji,
    channel: body.channel_id,
    text: '*<' + url + '|' + site + '>* ' + text.join(" "),
    unfurl_links: false,
    unfurl_media: false,
    attachments: [
      {
        title: "Screenshot",
        title_link: screenshot,
        image_url: screenshot
      }
    ]
  });
}
<commit_msg>Adds delay to let images/fonts load<commit_after>'use strict';

var http = require('http');
var querystring = require('querystring');
var slack = require('slack-notify')(process.env.SLACK_HOOK_URL);
var prependHttp = require('prepend-http');

var config =  {
  username: process.env.USERNAME || 'slackshot',
  emoji: process.env.EMOJI || ':round_pushpin:',
  token: process.env.SLACK_TOKEN || void 0
};

http.createServer(function (req, res) {
  var body = '';
  req.on('data', function(chunk) {
    body += chunk;
  });

  req.on('end', function() {
    res.writeHead(200, "OK", {'Content-Type': 'text/html'});
    res.end();

    body = querystring.parse(body);
    console.log(body);

    handlePayload(body);
  });
}).listen(process.env.PORT || 1337);

function handlePayload(body){
  if(config.token && config.token !== body.token){
    return console.error('Token `' + body.token + '` didn\'t match environment variable');
  }

  var text = body.text.split(' ');
  var site = text.shift();
  var url = prependHttp(site);

  var query = {
    access_key: process.env.SCREENSHOTLAYER_TOKEN,
    url: url,
    viewport: "1440x900",
    width: 900,
    delay: 3
  }

  var screenshot = "http://api.screenshotlayer.com/api/capture" + "?" + querystring.stringify(query);

  slack.send({
    username: config.username,
    icon_emoji: config.emoji,
    channel: body.channel_id,
    text: '*<' + url + '|' + site + '>* ' + text.join(" "),
    unfurl_links: false,
    unfurl_media: false,
    attachments: [
      {
        title: "Screenshot",
        title_link: screenshot,
        image_url: screenshot
      }
    ]
  });
}
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('myApp.controllers', ['ngSanitize']).
  controller('CalendarCtrl', ['$scope', 'googleCalendar', '$modal', '$timeout', function ($scope, googleCalendar, $modal, $timeout) {
      var today = new Date(),
      isFamilyCalendar = function(calendar) {
        // TODO: Lag regexp
        if (calendar.summary ===  'Jørgen Ryland' || calendar.summary === 'Kontakters fødselsdager og aktiviteter' ||
          calendar.summary === 'Helligdager i Norge' || calendar.summary === 'Ukenumre') {
          return false;
        }

        return true;
      },
      isPublicHolidayCalendar = function(calendar) {
        return calendar.summary === 'Helligdager i Norge' ? true : false;
      },
      isPublicHoliday = function(event) {
        // TODO: Lag regexp
        if (event.summary === 'nyttårsdag' ||
          event.summary === 'palmesøndag' ||
          event.summary === 'skjærtorsdag' ||
          event.summary === 'langfredag' ||
          event.summary === '1. påskedag' ||
          event.summary === '2. påskedag' ||
          event.summary === 'offentlig høytidsdag' ||
          event.summary === 'grunnlovsdag' ||
          event.summary === 'Kristi Himmelfartsdag' ||
          event.summary === '1. pinsedag' ||
          event.summary === '2. pinsedag' ||
          event.summary === 'julaften' ||
          event.summary === '1. juledag' ||
          event.summary === '2. juledag' ||
          event.summary === 'nyttårsaften') {
          return true;
        }

        return false;
      },
      isValidMonth = function(event) {
        var startDate, endDate, validMonth;
        var firstUnvalidDate = new Date( $scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() + $scope.pageSize);
        if (event.start.date) {
          startDate = new Date(event.start.date);
          endDate = new Date(event.end.date);
        }
        else {
          startDate = new Date(event.start.dateTime);
          endDate = new Date(event.end.dateTime);
        }
        validMonth = $scope.getDiffNumberOfDays($scope.currentStartDate, startDate) >= 0 && $scope.getDiffNumberOfDays(startDate, firstUnvalidDate) > 0 ||
          $scope.getDiffNumberOfDays($scope.currentStartDate, endDate) >= 0 && $scope.getDiffNumberOfDays(endDate, firstUnvalidDate) > 0;
        //if(validMonth) {
        //  console.log('Current ' + $scope.currentStartDate + ', ' + startDate + ' - ' + endDate);
        //}
        return validMonth;
      },
      getCalendarSummary = function(calendar) {
        return calendar.summary;
      },
      getCalendarId = function(calendar) {
        return calendar.id;
      },
      refreshDatesAndEventsMap = function() {
        $scope.dates = createDatesAndEventsMap($scope.calendarsWithEvents);

        $scope.calendarsWithEvents.forEach(function(calendar, calendarIndex) {
          calendar.events.filter(isValidMonth).forEach(function(event) {
            addEventToDatesAndEventsMap(event, calendarIndex);
          })
        });

        $scope.publicHolidaysCalendar.forEach(function(calendar) {
          calendar.events.filter(isPublicHoliday).filter(isValidMonth).forEach(function(event) {
            addPublicHolidayEventToDatesAndEventsMap(event);
          })
        });
      },
      createDatesAndEventsMap = function(calendars) {
        var dates = [];
        var i, j;
        for (i = 0; i < $scope.pageSize; i++) {
          dates[i] = { 'date' :  new Date( $scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() + i), 'events' : []};
          for (j = 0; j < calendars.length; j++) {
            dates[i].events.push([]);
          }
        }
        return dates;
      },
      addEventToDatesAndEventsMap = function(event, calendarIndex) {
        var startDate, i, index;
        if (event.start.dateTime) {
          $scope.dates[$scope.getDiffNumberOfDays($scope.currentStartDate, new Date(event.start.dateTime))].events[calendarIndex].push(event);
          return;
        }
        startDate = new Date(event.start.date);
        var startIndex = $scope.getDiffNumberOfDays($scope.currentStartDate, startDate);

        var durationInDays = $scope.getDiffNumberOfDays(startDate, new Date(event.end.date));

        for (i = startIndex ; i < Math.min(startIndex + durationInDays, $scope.pageSize); i++) {
          if (i >= 0) {
            $scope.dates[i].events[calendarIndex].push(event);
          }
        }
      },
      addPublicHolidayEventToDatesAndEventsMap  = function(event) {
        var index = $scope.getDiffNumberOfDays($scope.currentStartDate, new Date(event.start.date));
        console.log(event.summary);
        if(index >= 0) {
          $scope.dates[index].publicHoliday = event.summary;
        }
      },
      setDefaultEventRegValues = function() {
        $scope.selectedStartTime = 25200000;
        $scope.selectedEndTime = 25200000;
        $scope.fullDayOrTimeboxed = 0;
        $scope.recurrence = 0;
      },
      // TODO: Fix mocking in tests..
      modal = $modal ? $modal({scope: $scope, template: 'partials/create-event-modal.html', show: false}) : null;

      setDefaultEventRegValues();

      $scope.pageSize = 7;
      $scope.currentStartDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());

      $scope.numberOfDays = [
        { value:1, label:'1'},
        { value:2, label:'2'},
        { value:3, label:'3'},
        { value:4, label:'4'},
        { value:5, label:'5'},
        { value:6, label:'6'},
        { value:7, label:'7'}
      ];
      $scope.selectedNumberOfDays = $scope.numberOfDays[0];

      $scope.icons = [
        { value:'nada', label:'Ikon...'},
        { value:'glyphicon glyphicon-music', label:''},
        { value:'glyphicon glyphicon-headphones', label:''},
        { value:'glyphicon glyphicon-glass', label:''},
        { value:'glyphicon glyphicon-film', label:''},
        { value:'glyphicon glyphicon-plane', label:''},
        { value:'glyphicon glyphicon-heart', label:''},
        { value:'glyphicon glyphicon-road', label:''},
        { value:'glyphicon glyphicon-camera', label:''},
        { value:'glyphicon glyphicon-gift', label:''},
        { value:'glyphicon glyphicon-picture', label:''},
        { value:'glyphicon glyphicon-shopping-cart', label:''},
        { value:'glyphicon glyphicon-wrench', label:''},
        { value:'glyphicon glyphicon-globe', label:''},
        { value:'glyphicon glyphicon-tree-conifer', label:''},
        { value:'glyphicon glyphicon-pencil', label:''},
      ];
      $scope.selectedIcon = $scope.icons[0].value;

      $scope.getDiffNumberOfDays = function(startDate, endDate) {
        var strippedStartDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
        var strippedEndDate = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
        var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
        var days = Math.round((strippedEndDate.getTime() - strippedStartDate.getTime())/(oneDay));
        return days;
      }

      $scope.loadEvents = function(initialRequest) {
        $scope.loading = true;
        googleCalendar.loadData(initialRequest).then(function() {
          $scope.calendarsWithEvents = googleCalendar.calendars.filter(isFamilyCalendar);
          $scope.publicHolidaysCalendar = googleCalendar.calendars.filter(isPublicHolidayCalendar);

          $scope.calendarSummaries = $scope.calendarsWithEvents.map(getCalendarSummary);
          $scope.calendarIds = $scope.calendarsWithEvents.map(getCalendarId);
          refreshDatesAndEventsMap();
          $timeout($scope.loadEvents, 60000);
        });
      }

      $scope.showCalendarColor = function(calendarIndex, day) {
        var weekDay = day.date.getDay();
        var dateIndex = $scope.getDiffNumberOfDays($scope.currentStartDate, day.date);
        return $scope.dates[dateIndex].events[calendarIndex].length > 0 ? $scope.calendarsWithEvents[calendarIndex].color
        : (weekDay === 0 || weekDay === 6 || day.publicHoliday ? '#E6E6E6' : '');
      }

      $scope.getDayBgColor = function(day) {
        return day.date.getDay() === 0 || day.date.getDay() === 6 || day.publicHoliday ? '#E6E6E6' : '';
      }

      $scope.getDayFontColor = function(day) {
        return day.date.getDay() === 0 || day.date.getDay() === 6 || day.publicHoliday ? 'red' : '';
      }

      $scope.getCalendarColor = function(calendarIndex) {
        return $scope.calendarsWithEvents[calendarIndex].color;
      }

      $scope.incrementMonth = function() {
        $scope.currentStartDate = new Date($scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() + $scope.pageSize );
        refreshDatesAndEventsMap();
      }

      $scope.decrementMonth = function() {
        $scope.currentStartDate = new Date($scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() - $scope.pageSize );
        refreshDatesAndEventsMap();
      }

      $scope.setSelected = function ( calendarIndex, date ) {
        $scope.selectedCalendar = { 'index' : calendarIndex, 'id' : $scope.calendarIds[calendarIndex], 'summary' : $scope.calendarSummaries[calendarIndex]};
        $scope.selectedDate = date;
        modal.$promise.then(modal.show);
      }

      $scope.saveEvent = function () {
        var startTime, endTime, isFulldayEvent, title, recurrence, description;
        if (this.fullDayOrTimeboxed) {
          startTime = new Date(this.selectedStartTime);
          endTime = new Date(this.selectedEndTime);
          startTime.setYear($scope.selectedDate.getFullYear());
          startTime.setMonth($scope.selectedDate.getMonth());
          startTime.setDate($scope.selectedDate.getDate());
          endTime.setYear($scope.selectedDate.getFullYear());
          endTime.setMonth($scope.selectedDate.getMonth());
          endTime.setDate($scope.selectedDate.getDate());
          if(endTime.getHours() === 0 && endTime.getMinutes() === 0) {
            endTime.setDate(endTime.getDate() + 1);
          }
          isFulldayEvent = false;
        }
        else {
          startTime = new Date(Date.UTC($scope.selectedDate.getFullYear(), $scope.selectedDate.getMonth(), $scope.selectedDate.getDate()));
          endTime  = new Date(Date.UTC($scope.selectedDate.getFullYear(), $scope.selectedDate.getMonth(), $scope.selectedDate.getDate() + this.selectedNumberOfDays.value));
          isFulldayEvent = true;
        }
        recurrence = this.recurrence === 0 ? null : (this.recurrence === 1 ? 'weekly' : 'yearly');
        description = this.selectedIcon === 'nada' ? null : this.selectedIcon.slice(0);
        this.selectedIcon = this.icons[0];
        title = this.title.slice(0);
        this.title = null;

        this.selectedStartTime = this.selectedEndTime = 25200000;
        this.fullDayOrTimeboxed = this.recurrence = 0;
        this.$hide();

        googleCalendar.saveEvent($scope.selectedCalendar.id, startTime, endTime, title, isFulldayEvent, recurrence, description).then(function() {
          $scope.loadEvents();
        });
      }

      $scope.hasEvents = function () {
        var index = $scope.getDiffNumberOfDays($scope.currentStartDate, $scope.selectedDate);
        if (index < 0 || index > $scope.pageSize) {
          return false;
        }
        return $scope.dates[index].events[$scope.selectedCalendar.index].length > 0;
      }

      $scope.deleteEvent = function ( eventId, recurringEventId ) {
        var id = recurringEventId ? recurringEventId : eventId;
        googleCalendar.deleteEvent($scope.selectedCalendar.id, id).then(function() {
          $scope.loadEvents();
        });
      }
      //$scope.loadEvents();
  }]);<commit_msg>Fixed icon select bug<commit_after>'use strict';

/* Controllers */

angular.module('myApp.controllers', ['ngSanitize']).
  controller('CalendarCtrl', ['$scope', 'googleCalendar', '$modal', '$timeout', function ($scope, googleCalendar, $modal, $timeout) {
      var today = new Date(),
      isFamilyCalendar = function(calendar) {
        // TODO: Lag regexp
        if (calendar.summary ===  'Jørgen Ryland' || calendar.summary === 'Kontakters fødselsdager og aktiviteter' ||
          calendar.summary === 'Helligdager i Norge' || calendar.summary === 'Ukenumre') {
          return false;
        }

        return true;
      },
      isPublicHolidayCalendar = function(calendar) {
        return calendar.summary === 'Helligdager i Norge' ? true : false;
      },
      isPublicHoliday = function(event) {
        // TODO: Lag regexp
        if (event.summary === 'nyttårsdag' ||
          event.summary === 'palmesøndag' ||
          event.summary === 'skjærtorsdag' ||
          event.summary === 'langfredag' ||
          event.summary === '1. påskedag' ||
          event.summary === '2. påskedag' ||
          event.summary === 'offentlig høytidsdag' ||
          event.summary === 'grunnlovsdag' ||
          event.summary === 'Kristi Himmelfartsdag' ||
          event.summary === '1. pinsedag' ||
          event.summary === '2. pinsedag' ||
          event.summary === 'julaften' ||
          event.summary === '1. juledag' ||
          event.summary === '2. juledag' ||
          event.summary === 'nyttårsaften') {
          return true;
        }

        return false;
      },
      isValidMonth = function(event) {
        var startDate, endDate, validMonth;
        var firstUnvalidDate = new Date( $scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() + $scope.pageSize);
        if (event.start.date) {
          startDate = new Date(event.start.date);
          endDate = new Date(event.end.date);
        }
        else {
          startDate = new Date(event.start.dateTime);
          endDate = new Date(event.end.dateTime);
        }
        validMonth = $scope.getDiffNumberOfDays($scope.currentStartDate, startDate) >= 0 && $scope.getDiffNumberOfDays(startDate, firstUnvalidDate) > 0 ||
          $scope.getDiffNumberOfDays($scope.currentStartDate, endDate) >= 0 && $scope.getDiffNumberOfDays(endDate, firstUnvalidDate) > 0;
        //if(validMonth) {
        //  console.log('Current ' + $scope.currentStartDate + ', ' + startDate + ' - ' + endDate);
        //}
        return validMonth;
      },
      getCalendarSummary = function(calendar) {
        return calendar.summary;
      },
      getCalendarId = function(calendar) {
        return calendar.id;
      },
      refreshDatesAndEventsMap = function() {
        $scope.dates = createDatesAndEventsMap($scope.calendarsWithEvents);

        $scope.calendarsWithEvents.forEach(function(calendar, calendarIndex) {
          calendar.events.filter(isValidMonth).forEach(function(event) {
            addEventToDatesAndEventsMap(event, calendarIndex);
          })
        });

        $scope.publicHolidaysCalendar.forEach(function(calendar) {
          calendar.events.filter(isPublicHoliday).filter(isValidMonth).forEach(function(event) {
            addPublicHolidayEventToDatesAndEventsMap(event);
          })
        });
      },
      createDatesAndEventsMap = function(calendars) {
        var dates = [];
        var i, j;
        for (i = 0; i < $scope.pageSize; i++) {
          dates[i] = { 'date' :  new Date( $scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() + i), 'events' : []};
          for (j = 0; j < calendars.length; j++) {
            dates[i].events.push([]);
          }
        }
        return dates;
      },
      addEventToDatesAndEventsMap = function(event, calendarIndex) {
        var startDate, i, index;
        if (event.start.dateTime) {
          $scope.dates[$scope.getDiffNumberOfDays($scope.currentStartDate, new Date(event.start.dateTime))].events[calendarIndex].push(event);
          return;
        }
        startDate = new Date(event.start.date);
        var startIndex = $scope.getDiffNumberOfDays($scope.currentStartDate, startDate);

        var durationInDays = $scope.getDiffNumberOfDays(startDate, new Date(event.end.date));

        for (i = startIndex ; i < Math.min(startIndex + durationInDays, $scope.pageSize); i++) {
          if (i >= 0) {
            $scope.dates[i].events[calendarIndex].push(event);
          }
        }
      },
      addPublicHolidayEventToDatesAndEventsMap  = function(event) {
        var index = $scope.getDiffNumberOfDays($scope.currentStartDate, new Date(event.start.date));
        console.log(event.summary);
        if(index >= 0) {
          $scope.dates[index].publicHoliday = event.summary;
        }
      },
      setDefaultEventRegValues = function() {
        $scope.selectedStartTime = 25200000;
        $scope.selectedEndTime = 25200000;
        $scope.fullDayOrTimeboxed = 0;
        $scope.recurrence = 0;
      },
      // TODO: Fix mocking in tests..
      modal = $modal ? $modal({scope: $scope, template: 'partials/create-event-modal.html', show: false}) : null;

      setDefaultEventRegValues();

      $scope.pageSize = 7;
      $scope.currentStartDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());

      $scope.numberOfDays = [
        { value:1, label:'1'},
        { value:2, label:'2'},
        { value:3, label:'3'},
        { value:4, label:'4'},
        { value:5, label:'5'},
        { value:6, label:'6'},
        { value:7, label:'7'}
      ];
      $scope.selectedNumberOfDays = $scope.numberOfDays[0];

      $scope.icons = [
        { value:'nada', label:'Ikon...'},
        { value:'glyphicon glyphicon-music', label:''},
        { value:'glyphicon glyphicon-headphones', label:''},
        { value:'glyphicon glyphicon-glass', label:''},
        { value:'glyphicon glyphicon-film', label:''},
        { value:'glyphicon glyphicon-plane', label:''},
        { value:'glyphicon glyphicon-heart', label:''},
        { value:'glyphicon glyphicon-road', label:''},
        { value:'glyphicon glyphicon-camera', label:''},
        { value:'glyphicon glyphicon-gift', label:''},
        { value:'glyphicon glyphicon-picture', label:''},
        { value:'glyphicon glyphicon-shopping-cart', label:''},
        { value:'glyphicon glyphicon-wrench', label:''},
        { value:'glyphicon glyphicon-globe', label:''},
        { value:'glyphicon glyphicon-tree-conifer', label:''},
        { value:'glyphicon glyphicon-pencil', label:''},
      ];
      $scope.selectedIcon = $scope.icons[0].value;

      $scope.getDiffNumberOfDays = function(startDate, endDate) {
        var strippedStartDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
        var strippedEndDate = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
        var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
        var days = Math.round((strippedEndDate.getTime() - strippedStartDate.getTime())/(oneDay));
        return days;
      }

      $scope.loadEvents = function(initialRequest) {
        $scope.loading = true;
        googleCalendar.loadData(initialRequest).then(function() {
          $scope.calendarsWithEvents = googleCalendar.calendars.filter(isFamilyCalendar);
          $scope.publicHolidaysCalendar = googleCalendar.calendars.filter(isPublicHolidayCalendar);

          $scope.calendarSummaries = $scope.calendarsWithEvents.map(getCalendarSummary);
          $scope.calendarIds = $scope.calendarsWithEvents.map(getCalendarId);
          refreshDatesAndEventsMap();
          $timeout($scope.loadEvents, 60000);
        });
      }

      $scope.showCalendarColor = function(calendarIndex, day) {
        var weekDay = day.date.getDay();
        var dateIndex = $scope.getDiffNumberOfDays($scope.currentStartDate, day.date);
        return $scope.dates[dateIndex].events[calendarIndex].length > 0 ? $scope.calendarsWithEvents[calendarIndex].color
        : (weekDay === 0 || weekDay === 6 || day.publicHoliday ? '#E6E6E6' : '');
      }

      $scope.getDayBgColor = function(day) {
        return day.date.getDay() === 0 || day.date.getDay() === 6 || day.publicHoliday ? '#E6E6E6' : '';
      }

      $scope.getDayFontColor = function(day) {
        return day.date.getDay() === 0 || day.date.getDay() === 6 || day.publicHoliday ? 'red' : '';
      }

      $scope.getCalendarColor = function(calendarIndex) {
        return $scope.calendarsWithEvents[calendarIndex].color;
      }

      $scope.incrementMonth = function() {
        $scope.currentStartDate = new Date($scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() + $scope.pageSize );
        refreshDatesAndEventsMap();
      }

      $scope.decrementMonth = function() {
        $scope.currentStartDate = new Date($scope.currentStartDate.getFullYear(), $scope.currentStartDate.getMonth(), $scope.currentStartDate.getDate() - $scope.pageSize );
        refreshDatesAndEventsMap();
      }

      $scope.setSelected = function ( calendarIndex, date ) {
        $scope.selectedCalendar = { 'index' : calendarIndex, 'id' : $scope.calendarIds[calendarIndex], 'summary' : $scope.calendarSummaries[calendarIndex]};
        $scope.selectedDate = date;
        modal.$promise.then(modal.show);
      }

      $scope.saveEvent = function () {
        var startTime, endTime, isFulldayEvent, title, recurrence, description;
        if (this.fullDayOrTimeboxed) {
          startTime = new Date(this.selectedStartTime);
          endTime = new Date(this.selectedEndTime);
          startTime.setYear($scope.selectedDate.getFullYear());
          startTime.setMonth($scope.selectedDate.getMonth());
          startTime.setDate($scope.selectedDate.getDate());
          endTime.setYear($scope.selectedDate.getFullYear());
          endTime.setMonth($scope.selectedDate.getMonth());
          endTime.setDate($scope.selectedDate.getDate());
          if(endTime.getHours() === 0 && endTime.getMinutes() === 0) {
            endTime.setDate(endTime.getDate() + 1);
          }
          isFulldayEvent = false;
        }
        else {
          startTime = new Date(Date.UTC($scope.selectedDate.getFullYear(), $scope.selectedDate.getMonth(), $scope.selectedDate.getDate()));
          endTime  = new Date(Date.UTC($scope.selectedDate.getFullYear(), $scope.selectedDate.getMonth(), $scope.selectedDate.getDate() + this.selectedNumberOfDays.value));
          isFulldayEvent = true;
        }
        recurrence = this.recurrence === 0 ? null : (this.recurrence === 1 ? 'weekly' : 'yearly');
        description = this.selectedIcon === 'nada' ? null : this.selectedIcon.slice(0);
        this.selectedIcon = this.icons[0].value;
        title = this.title.slice(0);
        this.title = null;

        this.selectedStartTime = this.selectedEndTime = 25200000;
        this.fullDayOrTimeboxed = this.recurrence = 0;
        this.$hide();

        googleCalendar.saveEvent($scope.selectedCalendar.id, startTime, endTime, title, isFulldayEvent, recurrence, description).then(function() {
          $scope.loadEvents();
        });
      }

      $scope.hasEvents = function () {
        var index = $scope.getDiffNumberOfDays($scope.currentStartDate, $scope.selectedDate);
        if (index < 0 || index > $scope.pageSize) {
          return false;
        }
        return $scope.dates[index].events[$scope.selectedCalendar.index].length > 0;
      }

      $scope.deleteEvent = function ( eventId, recurringEventId ) {
        var id = recurringEventId ? recurringEventId : eventId;
        googleCalendar.deleteEvent($scope.selectedCalendar.id, id).then(function() {
          $scope.loadEvents();
        });
      }
      //$scope.loadEvents();
  }]);<|endoftext|>


<commit_before>#!/usr/bin/env node

var request = require('request');
var isNaN = require('is-nan');
var commandLineArgs = require('command-line-args');
var hexToRgb = require('hex-rgb');
var fs = require('fs');

var cli = commandLineArgs([
  { name: 'id', type: String, defaultOption: true },
  { name: 'filename', alias: 'f', type: String}
]);

var options = cli.parse();

var ID;

if(isNaN( parseInt(options.id) ) ){
  ID = options.id.match(/(?:palette\/(\d+)|(\d+))/)[1];
} else {
  ID = parseInt(options.id);
}

function getPaletteNameFromURL(url){
  return url.match(/palette\/\d+\/(.*)/)[1];
}

request('http://www.colourlovers.com/api/palette/'+ ID +'?format=json', function (error, response, content) {
  var output = '';
  var body;
  var name;

  content = JSON.parse(content);

  if (!error && response.statusCode == 200 && content.length > 0) {

    body = content[0];

    output += 'GIMP Paletten\n';
    output += 'Name: ' + body.title + '\n';
    output += 'Columns: 0\n';
    output += '#\n';

    body.colors.forEach(function(color){

      var rbg = hexToRgb(color);
      output += rbg[0] +'\t'+rbg[1] +'\t'+rbg[2] +'\n';

    });

    if(typeof options.filename == 'undefined'){
      name = getPaletteNameFromURL(body.url);
    } else {
      name = options.filename;
    }

    fs.writeFile('./'+name+'.gpl', output, function(err) {
      if(err) {
        return console.log(err);
      }
    });

  } else {

    if(content.length == 0){
      console.log('ERROR: Palette not found. Check if this palette really exists! ');
    }

  }

});

<commit_msg>Add help command to display the usage guide<commit_after>#!/usr/bin/env node

var request = require('request');
var isNaN = require('is-nan');
var commandLineArgs = require('command-line-args');
var hexToRgb = require('hex-rgb');
var fs = require('fs');

var cli = commandLineArgs([
  { name: 'id', type: String, defaultOption: true, description: 'The id of the palette'},
  { name: 'filename', alias: 'f', type: String, description: 'Set the name of the file'},
  { name: 'help', alias: 'h', type: Boolean, description: 'Display usage guide'}
]);

var options = cli.parse();

var ID;

if(options.help){
  console.log(cli.getUsage({
    title: 'palette-lovers',
    description: 'Generate a palette file with a COLOURLovers palette',
    synopsis: [
      '$ palette-lovers http://www.colourlovers.com/palette/3950622/violet_gen',
      '$ palette-lovers 3950622',
      '$ palette-lovers 3950622 --filename violet_color_ramp',
      '$ palette-lovers 3950622 --f violet_color_ramp'
    ],
    hide: "id"
  }));

  return false;

}

if(isNaN( parseInt(options.id) ) ){
  ID = options.id.match(/(?:palette\/(\d+)|(\d+))/)[1];
} else {
  ID = parseInt(options.id);
}

function getPaletteNameFromURL(url){
  return url.match(/palette\/\d+\/(.*)/)[1];
}

request('http://www.colourlovers.com/api/palette/'+ ID +'?format=json', function (error, response, content) {
  var output = '';
  var body;
  var name;

  content = JSON.parse(content);

  if (!error && response.statusCode == 200 && content.length > 0) {

    body = content[0];

    output += 'GIMP Paletten\n';
    output += 'Name: ' + body.title + '\n';
    output += 'Columns: 0\n';
    output += '#\n';

    body.colors.forEach(function(color){

      var rbg = hexToRgb(color);
      output += rbg[0] +'\t'+rbg[1] +'\t'+rbg[2] +'\n';

    });

    if(typeof options.filename == 'undefined'){
      name = getPaletteNameFromURL(body.url);
    } else {
      name = options.filename;
    }

    fs.writeFile('./'+name+'.gpl', output, function(err) {
      if(err) {
        return console.log(err);
      }
    });

  } else {

    if(content.length == 0){
      console.log('ERROR: Palette not found. Check if this palette really exists! ');
    }

  }

});

<|endoftext|>


<commit_before>'use strict';

var cvAppControllers = angular.module('cvAppControllers', []);

cvAppControllers.controller('HomeController', ['$scope', '$http', function($scope, $http) {
	$http.get('info/info.json').success(function(data) {
		$scope.info = data;
	});
}]);

cvAppControllers.controller('AboutController', ['$scope', '$http', function($scope, $http) {
	$http.get('info/info.json').success(function(data) {
		$scope.info = data;
	});
}]);<commit_msg>Add boilerplate for controllers<commit_after>'use strict';

/* Controllers */

var cvAppControllers = angular.module('cvAppControllers', []);

cvAppControllers.controller('HomeController', ['$scope', '$http', function($scope, $http) {
	$http.get('info/info.json').success(function(data) {
		$scope.info = data;
	});
}]);

cvAppControllers.controller('AboutController', ['$scope', '$http', function($scope, $http) {
	$http.get('info/info.json').success(function(data) {
		$scope.info = data;
	});
}]);<|endoftext|>


<commit_before>'use strict';

module.exports = builder;

// ## Usage
// ```js
// builder(options)
// .on('warn', function () {
// })
// .parse(filepath, callback);
// ```
function builder (options) {
  return new Builder(options || {});
}

builder.Builder = Builder;

var fs = require('fs');
var path = require('path');
var util = require('util');
var async = require('async');
var path = require('path');
var _ = require('underscore');
var EE = require('events').EventEmitter;

function Builder (opt) {
  var self = this;
  this._uuid = 0;
  this.opt = opt;
  this.cwd = opt.cwd;
  this.pkg = opt.pkg;
  this.locals = {};
  this.entries = this.pkg.entries || [];
  this.asyncDependencies = this.pkg.asyncDependencies || {};
  this.as = this.pkg.as || {};
  this.loaders = opt.loaders;
  this.loader_version = opt.loader_version;

  var asyncDependencies = this.asyncDependencies;
  var as = this.as;

  this.asyncDepsToMix = {};
  this.globalMap = {};
  this.asyncDeps = [];

  this.entries = this.entries.map(function(entry) {
    entry = self._generateId(entry, true);
    self._addLocals(entry);
    return entry;
  });

  Objects.keys(asyncDependencies).forEach(function(name) {
    var version = asyncDependencies[name];
    var id = addToAsync(name, version, name);
    self.asyncDeps.push(id);
  });

  Objects.keys(as).forEach(function(alias) {
    var name = as[alias];
    var version = asyncDependencies[name];
    if (self._isForeign(alias) && self._isForeign(name) && asyncDependencies[name]) {
      addToAsync(name, version, alias);
    }
  });

  function addToAsync(name, version, key) {
    var id = [name, version].join("@");
    self.asyncDepsToMix[key] = id;
    self._addLocals(id);
    return id;
  }
};

util.inherits(Builder, EE);

Builder.prototype.parse = function(filepath, callback) {
  var self = this;
  var resolved = {};
  var pkg = this.pkg;
  var locals = this.locals;

  async.waterfall([

    function(done) {
      self._getDeps(filepath, done);
    },
    function(nodes, done){
      self._resolveDeps(nodes, done);
    },
    function(codes, done){
      self._generateCode(codes, done);
    }
  ], callback);
}

Builder.prototype._resolveDeps = function(nodes, callback) {
  this.nodes = nodes;
  var codes = {};
  var errmsg = "";
  for (var id in nodes) {
    var mod = nodes[id];
    if (mod.foreign) {
      continue;
    }

    try {
      mod.resolved = this._resolveModuleDependencies(id, mod);
    } catch (e) {
      if (e.code == "ENOTINSTALLED") {
        errmsg = "Explicit version of dependency <%= deps.map(function(dep){return '\"' + dep + '\"'}).join(\", \") %> <%= deps.length > 1 ? 'are' : 'is' %> not defined in package.json.\n Use \"cortex install <%= deps.join(' ') %> --save\". file: <%= file %>";
      } else if (e.code == "EOUTENTRY") {
        errmsg = "Relative dependency \"<%= deps[0] %>\" out of main entry\'s directory. file: <%= file %>";
      } else {
        errmsg = e.message;
      }
      e.file = id;
      return callback(new Error(_.template(errmsg)(e)));
    }
    codes[id] = mod;
  }

  callback(null, codes);
};

Builder.prototype._generateCode = function(codes, callback) {
  var self = this;
  var locals = this.locals;
  var code = _.keys(codes).map(function(id) {
    var mod = codes[id];
    return self._wrapping(id, mod);
  }).join("\n\n");
  var variables = [];
  var template = "(function(){\n" + "function mix(a,b){for(var k in b){a[k]=b[k];}return a;}\n" + "<%= variables %>" + "<%= code %>\n" + "})();";

  function declareVarible(name, value, raw) {
    var statement = 'var ' + name + ' = ' + (raw ? value : JSON.stringify(value)) + ';\n';
    if (value) {
      variables.push(statement);
    }
  }

  _.keys(locals).forEach(function(v) {
    declareVarible(locals[v], v);
  });

  ["entries", "asyncDeps", "asyncDepsToMix"].forEach(function(key) {
    var value = self[key];
    (key == "asyncDepsToMix" || value.length) && declareVarible(key, self._toLocals(value), true);
  });
  declareVarible("globalMap", _.keys(self.globalMap).length ? ("mix(" + self._toLocals(self.globalMap) + ",asyncDepsToMix)") : "asyncDepsToMix", true)
  code = _.template(template)({
    variables: variables.join(""),
    code: code
  });

  callback(null, code);
}

Builder.prototype._getDeps = function(filepath, callback) {
  var self = this;
  var walker = require('cortex-commonjs-walker');
  var pkg = this.pkg;
  walker(filepath, {
    allow_cyclic: true,
    check_require_length: true,
    allow_absolute_path: false,
    extensions: ['.js', '.json'],
    require_resolve: true,
    require_async: true

  }, function(err, deps){
    if(err){return callback(err);}
    callback(null, deps);
  })
  .on('warn', function (message) {
    self.emit('warn', message);
  });
};

Builder.prototype._wrapping = function(id, mod) {
  var self = this;
  var pkg = this.pkg;
  var opt = this.opt;
  var filepath = id;
  var entries = this.entries;
  var resolvedDeps = _.values(mod.resolved);
  var module_options = this._generateModuleOptions(id, mod);
  var id = this._generateId(filepath);
  var code = mod.code.toString().replace(/\r\n/g, '\n');
  var template = "define(<%= id %>, <%= deps %>, function(require, exports, module, __filename, __dirname) {\n" + "<%= code %>\n" + "}<%= module_options ? module_options : '' %>);";

  function optionsToString(module_options) {
    var pairs = [];
    for (var key in module_options) {
      var value = module_options[key];
      value = ({
        "asyncDeps": "asyncDeps",
        "entries": "entries",
        "map": _.keys(value).length ? ("mix(" + self._toLocals(value) + ",globalMap)") : "globalMap",
        "main": "true"
      })[key];

      pairs.push(key + ":" + value);
    }
    return pairs.length ? (", {\n\t" + pairs.join(",\n\t") + "\n}").replace(/\t/g, "    ") : "";
  }

  module_options = optionsToString(module_options);

  var result = _.template(template)({
    id: self._toLocals(id),
    deps: this._toLocals(resolvedDeps),
    code: this._dealCode(id, code),
    module_options: module_options
  });

  return result;
};

Builder.prototype.dealCode = function(id, code){
  if(path.extname(id) == '.json'){
    return "module.exports = " + code;
  }else{
    return code;
  }
}

Builder.prototype._generateId = function(filepath, relative) {
  // the exact identifier
  var cwd = this.cwd;
  var pkg = this.pkg;
  var main_id = [pkg.name, pkg.version].join("@");
  var reg = new RegExp("\\" + path.sep, "g");
  var relative_path = relative ? filepath : path.relative(cwd, filepath);

  // -> 'module@0.0.1/folder/foo'
  var id = path.join(main_id, relative_path);
  id = id.replace(reg, "/");
  id = id.toLowerCase();
  this._addLocals(id);
  return id;
}

Builder.prototype._isForeign = function(str) {
  var isWindowsAbsolute = str.match(/^\w+:\\/);
  var isRelative = ["../", "./"].some(function(prefix) {
    return str.indexOf(prefix) === 0;
  });
  var isUnixAbsolute = str.indexOf("/") == 0;
  return !isRelative && !isUnixAbsolute && !isWindowsAbsolute;
}

Builder.prototype._outOfDir = function(dep, file) {
  var cwd = path.resolve(this.cwd);
  var mod_path = path.resolve(path.join(path.dirname(file), dep));
  return mod_path.indexOf(cwd) == -1;
}

Builder.prototype._generateModuleOptions = function(id, mod) {
  var self = this;
  var pkg = this.pkg;
  var cwd = this.cwd;
  var entries = this.entries;
  var asyncDeps = this.asyncDeps;
  var module_options = {};
  if (asyncDeps.length) {
    module_options.asyncDeps = true;
  }

  if (entries.length) {
    module_options.entries = true;
  }

  if (pkg.main && mod.entry && path.resolve(id) === path.resolve(cwd, pkg.main)) {
    module_options.main = true;
  }

  var map = this._generateMap(id, mod);
  module_options.map = map;

  return _.keys(module_options).length ? module_options : null;
}

Builder.prototype._generateMap = function(id, mod) {
  var self = this;
  var resolved = mod.resolved;
  var dependencies = mod.dependencies;
  var resolvedDeps = _.keys(resolved);
  var map = {};
  var nodes = this.nodes;
  var as = this.pkg.as || {};
  resolvedDeps.forEach(function(dep) {
    // to lower cases
    // resolve dir
    var result;
    var realDependency = dependencies[dep];

    if (!self._isForeign(realDependency)) {
      result = realDependency.toLowerCase();
      result = self._generateId(realDependency);
    } else if (as[dep]) {
      result = self._resolveForeignDependency(realDependency);
      self.globalMap[realDependency] = result;
    }

    if (result) {
      map[dep] = result;
      self._addLocals(result);
    }
  });
  return map;
};

Builder.prototype._resolveForeignDependency = function(module_name) {
  var pkg = this.pkg;
  var deps = ["dependencies", "asyncDependencies", "devDependencies"];
  for (var i = 0; i < deps.length; i++) {
    var dep = deps[i];
    if (pkg[dep] && pkg[dep][module_name]) {
      return module_name + "@" + pkg[dep][module_name];
    }
  }
  return false;
};

Builder.prototype._resolveModuleDependencies = function(id, mod) {
  var self = this;
  var pkg = this.pkg;
  var cwd = this.cwd;
  var deps = mod.dependencies;
  var notInstalled = [];
  var resolvedDeps = {};

  for (var module_name in deps) {
    var opt = self.opt;
    var resolved;
    var realDependency = deps[module_name];

    if (self._isForeign(realDependency)) {
      resolved = self._resolveForeignDependency(realDependency);
      if (!resolved) {
        notInstalled.push(realDependency);
      }

    } else {
      if (self._outOfDir(module_name, id)) {
        throw {
          code: "EOUTENTRY",
          deps: [module_name]
        };
      }
      resolved = self._generateId(deps[module_name]);
    }
    resolvedDeps[module_name] = resolved;
    self._addLocals(resolved);
  }

  if (notInstalled.length) {
    throw {
      code: "ENOTINSTALLED",
      deps: notInstalled
    }
  }

  return resolvedDeps;
}

Builder.prototype._addLocals = function(val) {
  var locals = this.locals;
  if (!locals[val]) {
    locals[val] = "_" + this._uuid;
    this._uuid++;
  }
}

Builder.prototype._toLocals = function(obj) {
  var locals = this.locals;

  function toLocals(item) {
    return locals[item] || null;
  }

  function notNull(item) {
    return item !== null;
  }
  if (_.isString(obj)) {
    return toLocals(obj);
  }

  if (_.isArray(obj)) {
    return '[' + obj.map(toLocals).filter(notNull).join(",") + ']'
  };

  if (_.isObject(obj)) {
    return '{' + _.keys(obj).map(function(k) {
      var value = toLocals(obj[k]);
      return value ? ('"' + k + '"' + ':' + value) : null
    }).filter(notNull).join(',') + '}';
  }
}
<commit_msg>refractor in progress<commit_after>'use strict';

module.exports = builder;

// ## Usage
// ```js
// builder(options)
// .on('warn', function () {
// })
// .parse(filepath, callback);
// ```
function builder(options) {
  return new Builder(options || {});
}

builder.Builder = Builder;

var fs = require('fs');
var path = require('path');
var util = require('util');
var async = require('async');
var path = require('path');
var _ = require('underscore');
var EE = require('events').EventEmitter;
var walker = require('commonjs-walker');

function Builder(options) {
  var self = this;
  this._uuid = 0;
  this.options = opt;
  this.cwd = options.cwd;
  this.pkg = options.pkg;
  this.locals = {};
  this.entries = this.pkg.entries || [];
  this.asyncDependencies = this.pkg.asyncDependencies || {};
  this.as = this.pkg.as || {};
  this.loaders = options.loaders;
  this.loader_version = options.loader_version;

  var asyncDependencies = this.asyncDependencies;
  // var as = this.as;

  this.asyncDepsToMix = {};
  this.globalMap = {};
  this.asyncDeps = [];

  this.entries = this.entries.map(function(entry) {
    entry = self._generate_module_id(entry, true);
    self._add_locals(entry);
    return entry;
  });

  Objects.keys(asyncDependencies).forEach(function(name) {
    var version = asyncDependencies[name];
    var id = addToAsync(name, version, name);
    self.asyncDeps.push(id);
  });

  // Objects.keys(as).forEach(function(alias) {
  //   var name = as[alias];
  //   var version = asyncDependencies[name];
  //   if (self._is_foreign(alias) && self._is_foreign(name) && asyncDependencies[name]) {
  //     addToAsync(name, version, alias);
  //   }
  // });

  function addToAsync(name, version, key) {
    var id = [name, version].join('@');
    self.asyncDepsToMix[key] = id;
    self._add_locals(id);
    return id;
  }
};

util.inherits(Builder, EE);

Builder.prototype.parse = function(filepath, callback) {
  var self = this;
  var resolved = {};
  var pkg = this.pkg;
  var locals = this.locals;

  async.waterfall([
    function(done) {
      self._get_dependency_tree(filepath, done);
    },
    function(nodes, done) {
      self._resolve_dependencies(nodes, done);
    },
    function(codes, done) {
      self._generateCode(codes, done);
    }
  ], callback);
};

// Gets the dependency tree from the entry file
// @param {String} filepath
// @param {function(err, nodes)} callback
Builder.prototype._get_dependency_tree = function(filepath, callback) {
  var self = this;
  walker(filepath, {
    allow_cyclic: true,
    check_require_length: true,
    allow_absolute_path: false,
    extensions: ['.js', '.json'],
    require_resolve: true,
    require_async: true

  }, function(err, nodes) {
    if (err) {
      return callback(err);
    }

    self.nodes = nodes;
    callback(null, nodes);
  })
  .on('warn', function(message) {
    self.emit('warn', message);
  });
};

Builder.prototype._resolve_dependencies = function(nodes, callback) {
  var codes = {};
  var errmsg = '';
  var id;
  var mod
  for (id in nodes) {
    mod = nodes[id];
    if (mod.foreign) {
      continue;
    }

    try {
      mod.resolved = this._resolveModuleDependencies(id, mod);
    } catch (e) {
      if (e.code == 'ENOTINSTALLED') {
        errmsg = 'Explicit version of dependency <%= deps.map(function(dep){return '\'' + dep + '\''}).join(\', \') %> <%= deps.length > 1 ? 'are' : 'is' %> not defined in package.json.\n Use \'cortex install <%= deps.join(' ') %> --save\'. file: <%= file %>';
      } else if (e.code == 'EOUTENTRY') {
        errmsg = 'Relative dependency \'<%= deps[0] %>\' out of main entry\'s directory. file: <%= file %>';
      } else {
        errmsg = e.message;
      }
      e.file = id;
      return callback(new Error(_.template(errmsg)(e)));
    }
    codes[id] = mod;
  }

  callback(null, codes);
};

var CODE_TEMPLATE =
  ';(function(){\n' +
    'function mix(a, b){ for(var k in b) { a[k]=b[k]; } return a; }\n' +
    '<%= variables %>' +
    '<%= code %>\n' +
  '})();';

Builder.prototype._generateCode = function(codes, callback) {
  var self = this;
  var locals = this.locals;
  var code = _.keys(codes).map(function(id) {
    var mod = codes[id];
    return self._wrapping(id, mod);
  }).join('\n\n');

  var variables = [];

  function declareVarible(name, value, raw) {
    var statement = 'var ' + name + ' = ' + (raw ? value : JSON.stringify(value)) + ';\n';
    if (value) {
      variables.push(statement);
    }
  }

  _.keys(locals).forEach(function(v) {
    declareVarible(locals[v], v);
  });

  ['entries', 'asyncDeps', 'asyncDepsToMix'].forEach(function(key) {
    var value = self[key];
    (key == 'asyncDepsToMix' || value.length) && declareVarible(key, self._toLocals(value), true);
  });
  declareVarible('globalMap', _.keys(self.globalMap).length ? ('mix(' + self._toLocals(self.globalMap) + ',asyncDepsToMix)') : 'asyncDepsToMix', true)
  code = _.template(CODE_TEMPLATE)({
    variables: variables.join(''),
    code: code
  });

  callback(null, code);
};

Builder.prototype._wrapping = function(id, mod) {
  var self = this;
  var pkg = this.pkg;
  var opt = this.options;
  var filepath = id;
  var entries = this.entries;
  var resolvedDeps = _.values(mod.resolved);
  var module_options = this._generateModuleOptions(id, mod);
  var id = this._generate_module_id(filepath);
  var code = mod.code.toString().replace(/\r\n/g, '\n');
  var template = 'define(<%= id %>, <%= deps %>, function(require, exports, module, __filename, __dirname) {\n' + '<%= code %>\n' + '}<%= module_options ? module_options : '' %>);';

  function optionsToString(module_options) {
    var pairs = [];
    for (var key in module_options) {
      var value = module_options[key];
      value = ({
        'asyncDeps': 'asyncDeps',
        'entries': 'entries',
        'map': _.keys(value).length ? ('mix(' + self._toLocals(value) + ',globalMap)') : 'globalMap',
        'main': 'true'
      })[key];

      pairs.push(key + ':' + value);
    }
    return pairs.length ? (', {\n\t' + pairs.join(',\n\t') + '\n}').replace(/\t/g, '    ') : '';
  }

  module_options = optionsToString(module_options);

  var result = _.template(template)({
    id: self._toLocals(id),
    deps: this._toLocals(resolvedDeps),
    code: this._dealCode(id, code),
    module_options: module_options
  });

  return result;
};

Builder.prototype.dealCode = function(id, code) {
  if (path.extname(id) == '.json') {
    return 'module.exports = ' + code;
  } else {
    return code;
  }
};

Builder.prototype._generate_module_id = function(filepath, relative) {
  // the exact identifier
  var cwd = this.cwd;
  var pkg = this.pkg;
  var main_id = [pkg.name, pkg.version].join('@');

  var relative_path = relative
    ? filepath
    : path.relative(cwd, filepath);

  // -> 'module@0.0.1/folder/foo'
  var id = path.join(main_id, relative_path);

  // fixes windows paths
  id = id.replace(new RegExp('\\' + path.sep, 'g'), '/');

  id = id.toLowerCase();
  this._add_locals(id);
  return id;
};

Builder.prototype._is_foreign = function(str) {
  var isWindowsAbsolute = str.match(/^\w+:\\/);
  var isRelative = ['../', './'].some(function(prefix) {
    return str.indexOf(prefix) === 0;
  });
  var isUnixAbsolute = str.indexOf('/') == 0;
  return !isRelative && !isUnixAbsolute && !isWindowsAbsolute;
};

Builder.prototype._outOfDir = function(dep, file) {
  var cwd = path.resolve(this.cwd);
  var mod_path = path.resolve(path.join(path.dirname(file), dep));
  return mod_path.indexOf(cwd) == -1;
};

Builder.prototype._generateModuleOptions = function(id, mod) {
  var self = this;
  var pkg = this.pkg;
  var cwd = this.cwd;
  var entries = this.entries;
  var asyncDeps = this.asyncDeps;
  var module_options = {};
  if (asyncDeps.length) {
    module_options.asyncDeps = true;
  }

  if (entries.length) {
    module_options.entries = true;
  }

  if (pkg.main && mod.entry && path.resolve(id) === path.resolve(cwd, pkg.main)) {
    module_options.main = true;
  }

  var map = this._generateMap(id, mod);
  module_options.map = map;

  return _.keys(module_options).length ? module_options : null;
};

Builder.prototype._generateMap = function(id, mod) {
  var self = this;
  var resolved = mod.resolved;
  var dependencies = mod.dependencies;
  var resolvedDeps = _.keys(resolved);
  var map = {};
  var nodes = this.nodes;
  var as = this.pkg.as || {};
  resolvedDeps.forEach(function(dep) {
    // to lower cases
    // resolve dir
    var result;
    var realDependency = dependencies[dep];

    if (!self._is_foreign(realDependency)) {
      result = realDependency.toLowerCase();
      result = self._generate_module_id(realDependency);
    } else if (as[dep]) {
      result = self._resolveForeignDependency(realDependency);
      self.globalMap[realDependency] = result;
    }

    if (result) {
      map[dep] = result;
      self._add_locals(result);
    }
  });
  return map;
};

Builder.prototype._resolveForeignDependency = function(module_name) {
  var pkg = this.pkg;
  var deps = ['dependencies', 'asyncDependencies', 'devDependencies'];
  for (var i = 0; i < deps.length; i++) {
    var dep = deps[i];
    if (pkg[dep] && pkg[dep][module_name]) {
      return module_name + '@' + pkg[dep][module_name];
    }
  }
  return false;
};

Builder.prototype._resolveModuleDependencies = function(id, mod) {
  var self = this;
  var pkg = this.pkg;
  var cwd = this.cwd;
  var deps = mod.dependencies;
  var notInstalled = [];
  var resolvedDeps = {};

  for (var module_name in deps) {
    var opt = self.options;
    var resolved;
    var realDependency = deps[module_name];

    if (self._is_foreign(realDependency)) {
      resolved = self._resolveForeignDependency(realDependency);
      if (!resolved) {
        notInstalled.push(realDependency);
      }

    } else {
      if (self._outOfDir(module_name, id)) {
        throw {
          code: 'EOUTENTRY',
          deps: [module_name]
        };
      }
      resolved = self._generate_module_id(deps[module_name]);
    }
    resolvedDeps[module_name] = resolved;
    self._add_locals(resolved);
  }

  if (notInstalled.length) {
    throw {
      code: 'ENOTINSTALLED',
      deps: notInstalled
    }
  }

  return resolvedDeps;
};

Builder.prototype._add_locals = function(val) {
  var locals = this.locals;
  if (!locals[val]) {
    locals[val] = '_' + this._uuid ++;
  }
};

Builder.prototype._toLocals = function(obj) {
  var locals = this.locals;

  function toLocals(item) {
    return locals[item] || null;
  }

  function notNull(item) {
    return item !== null;
  }
  if (_.isString(obj)) {
    return toLocals(obj);
  }

  if (_.isArray(obj)) {
    return '[' + obj.map(toLocals).filter(notNull).join(',') + ']'
  };

  if (_.isObject(obj)) {
    return '{' + _.keys(obj).map(function(k) {
      var value = toLocals(obj[k]);
      return value ? (''' + k + ''' + ':' + value) : null
    }).filter(notNull).join(',') + '}';
  }
};
<|endoftext|>


<commit_before>
define([
  'jquery',
  'underscore',
  'backbone',
  'text!templates/topic_right_nav.html',
], function ($, _, Backbone, TopicRightNavTemplate) {
  return {

    initialize: function (title) {
      // unbind previous events
      $('#main').off();

      // unbind previous scroll event
      $(window).off('scroll');

      // remove binding of refresh button and hide by default
      $('#refresh-topic-container').off();

      // scrollTop with initialize
      $(window).scrollTop();

      // clear page content
      if (typeof (title) != undefined) {
        $('#main').html ('');
        this.setTitle (title);
      }

      this.loader(false);
    },

    setTitle: function (title, rightNavOptions) {
      $('#navbar-title').text (title);
      $('title').text (title);

      this.setRightNavbar (
        _.template (TopicRightNavTemplate, rightNavOptions));

      $('#refresh-topic').hide();
    },

    setRightNavbar: function (content) {
      $('ul.navbar-right').html (content);
    },

    bindRefresh: function (view) {
      $('#refresh-topic').show();
      $('#refresh-topic').click (function () {
        view.refresh ();
        return false;
      });
    },

    bindScroll: function(view) {
      $(window).scroll(function(ev) {
        view.checkScroll();
      });
    },

    checkScroll: function(view) {
      return $(window).scrollTop () + $(window).height () >
                 $("#main").height () - 200;
    },

    // loading animation
    // state is true if its loading, false if its not
    // need to wait before hiding animation
    loader_current_state: false,
    loader_current_timeout: -1,
    loader_show: function () {
      $('#loader').show();
    },
    loader_hide: function () {
      $('#loader').hide();
    },
    loader: function (state) {
      if (state == true && this.loader_current_state == false) {
        this.loader_show();
        this.loader_current_state = true;
      } else if (this.loader_current_state == true) {
        var that = this;
        if (this.loader_current_timeout != -1) {
          clearTimeout(this.loader_current_timeout);
        }

        this.loader_current_timeout = setTimeout(function () {
          that.loader_hide();
          that.loader_current_state = false;
          that.loader_current_timeout = -1;
        }, 1000);
      }
    }

  };
});
<commit_msg>Use scrollTo<commit_after>
define([
  'jquery',
  'underscore',
  'backbone',
  'text!templates/topic_right_nav.html',
], function ($, _, Backbone, TopicRightNavTemplate) {
  return {

    initialize: function (title) {
      // unbind previous events
      $('#main').off();

      // unbind previous scroll event
      $(window).off('scroll');

      // remove binding of refresh button and hide by default
      $('#refresh-topic-container').off();

      // scrollTop with initialize
      window.scrollTo(0, 0);

      // clear page content
      if (typeof (title) != undefined) {
        $('#main').html ('');
        this.setTitle (title);
      }

      this.loader(false);
    },

    setTitle: function (title, rightNavOptions) {
      $('#navbar-title').text (title);
      $('title').text (title);

      this.setRightNavbar (
        _.template (TopicRightNavTemplate, rightNavOptions));

      $('#refresh-topic').hide();
    },

    setRightNavbar: function (content) {
      $('ul.navbar-right').html (content);
    },

    bindRefresh: function (view) {
      $('#refresh-topic').show();
      $('#refresh-topic').click (function () {
        view.refresh ();
        return false;
      });
    },

    bindScroll: function(view) {
      $(window).scroll(function(ev) {
        view.checkScroll();
      });
    },

    checkScroll: function(view) {
      return $(window).scrollTop () + $(window).height () >
                 $("#main").height () - 200;
    },

    // loading animation
    // state is true if its loading, false if its not
    // need to wait before hiding animation
    loader_current_state: false,
    loader_current_timeout: -1,
    loader_show: function () {
      $('#loader').show();
    },
    loader_hide: function () {
      $('#loader').hide();
    },
    loader: function (state) {
      if (state == true && this.loader_current_state == false) {
        this.loader_show();
        this.loader_current_state = true;
      } else if (this.loader_current_state == true) {
        var that = this;
        if (this.loader_current_timeout != -1) {
          clearTimeout(this.loader_current_timeout);
        }

        this.loader_current_timeout = setTimeout(function () {
          that.loader_hide();
          that.loader_current_state = false;
          that.loader_current_timeout = -1;
        }, 1000);
      }
    }

  };
});
<|endoftext|>


<commit_before>var express = require('express'),
    bodyParser = require('body-parser'),
    querystring = require('querystring'),
    request = require('request');

var PORT = (process.env.PORT || 5000),
    AUTH_TOKEN_LINE = process.env.AUTH_TOKEN_LINE,
    WEBHOOK_LINE = ('/' + process.env.WEBHOOK_LINE || '/webhook_line');

var app = express();
app.use(bodyParser.json());

app.set('port', PORT);

app.use(express.static(__dirname + '/public'));

// views is directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

function replyBack(token, msg) {
    // multiline message
    msg = msg.replace(/\n/g, " ");
    var queryUrl = 'http://api.asksusi.com/susi/chat.json?q=' + encodeURI(msg);
    var message = '',
    options = {
        url: queryUrl,
        json: true
    };

    request(options, function (error, response, body) {
        console.log('Susi response:', JSON.stringify(body));
        if (!error && response.statusCode == 200) {
            message = body.answers[0].actions[0].expression;
        } else {
            message = 'Oops, Looks like Susi is taking a break, She will be back soon';
        }

        var replyMsg = {
            replyToken: token,
            messages: [
            {
                type: "text",
                text: message
            }
            ]
        };
        console.log('Token:', e.replyToken);
        console.log('Message:', message);
        var options = {
            uri: 'https://api.line.me/v2/bot/message/reply',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + AUTH_TOKEN_LINE
            },
            json: replyMsg
        };

        request(options, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                console.log('Send');
            }
        });
    });
}

app.get('/', function(request, response) {
    response.send('Susi says Hello.');
});

app.post(WEBHOOK_LINE, function(request, response) {
    console.log('Data:', JSON.stringify(request.body));
    for(e of request.body.events) {
        replyBack(e.replyToken , e.message.text);
    }
    response.send('Not a right place to visit.');
});

app.listen(PORT, function() {
    console.log('Node app is running on port ', PORT);
});

<commit_msg>Updating (#1)<commit_after>var express = require('express'),
    bodyParser = require('body-parser'),
    querystring = require('querystring'),
    request = require('request');

var PORT = (process.env.PORT || 5000),
    AUTH_TOKEN_LINE = process.env.AUTH_TOKEN_LINE,
    WEBHOOK_LINE = ('/' + process.env.WEBHOOK_LINE || '/webhook_line');

var app = express();
app.use(bodyParser.json());

app.set('port', PORT);

app.use(express.static(__dirname + '/public'));

// views is directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

function replyBack(token, msg) {
    // multiline message
    if(msg !== undefined) {
        msg = msg.replace(/\n/g, " ");
    }
    var queryUrl = 'http://api.asksusi.com/susi/chat.json?q=' + encodeURI(msg);
    var message = '',
    options = {
        url: queryUrl,
        json: true
    };

    request(options, function (error, response, body) {
        console.log('Susi response:', JSON.stringify(body));
        if (!error && response.statusCode == 200) {
            message = body.answers[0].actions[0].expression;
        } else {
            message = 'Oops, Looks like Susi is taking a break, She will be back soon';
        }

        var replyMsg = {
            replyToken: token,
            messages: [
            {
                type: "text",
                text: message
            }
            ]
        };
        var options = {
            uri: 'https://api.line.me/v2/bot/message/reply',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + AUTH_TOKEN_LINE
            },
            json: replyMsg
        };

        request(options, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                console.log('Token:', e.replyToken);
                console.log('Sent:', message);
            }
        });
    });
}

app.get('/', function(request, response) {
    response.send('Susi says Hello.');
});

app.post(WEBHOOK_LINE, function(request, response) {
    console.log('Data:', JSON.stringify(request.body));
    for(e of request.body.events) {
        replyBack(e.replyToken , e.message.text);
    }
    response.send('Not a right place to visit.');
});

app.listen(PORT, function() {
    console.log('Node app is running on port ', PORT);
});

<|endoftext|>


<commit_before>var app = app || {};

app.BuildView = Backbone.View.extend({

	id: '#buildView',

	template: templates['build.hbs'],

	events: {
		'click #buildNav': 'navClick',
		'click #buildSingleNav': 'navSingle',
		'click #closeForm': 'closeForm',
		'keypress': 'closeOnEsc'
	},

	initialize: function() {
		this.listenTo(app.Router, 'close', this.close);

		this.childViews = [];
		this.viewMethods = [
			app.NameView,
			app.EmailView,
			app.EducationsView,
			app.EmploymentsView,
			app.SkillsView,
			app.InterestsView,
			app.ProfilesView
		];

		this.changeForms = {
			changeName: app.Name,
			changeEmail: app.Email
		};

		this.forms = {
			addEducation: app.EducationFormView,
			addEmployment: app.EmploymentFormView,
			addSkill: app.SkillFormView,
			addInterest: app.InterestFormView,
			addProfile: app.ProfileFormView
		};

	},

	navSingle: function(e) {
		var navButton = $(e.target).parent();

		if (navButton.hasClass('active')) {
			return;
		}
		$('#build nav').children().removeClass('active');
		navButton.addClass('active');

		if (this.activeForm) {
			this.activeForm.close();
		}

		this.activeForm = new app.ChangeFormView({model: this.changeForms[e.target.id]});
		this.listenTo(this.activeForm, 'close', this.removeClass);
		this.activeForm.render();

	},

	removeClass: function() {
		$('#build nav').children().removeClass('active');
	},

	navClick: function(e) {
		var navButton = $(e.target).parent();
		if (navButton.hasClass('active')) {
			return;
		}

		$('#buildForm').empty();
		$('#build nav').children().removeClass('active');
		navButton.addClass('active');

		if (this.activeForm) {
			this.activeForm.close();
		}

		this.activeForm = new this.forms[e.target.id]({
			options: {
				action:'add'
			}
		});

		this.activeForm.render();

	},

	edit: function(model) {
		this.forms.addEducation.values = model.toJSON();
		this.forms.addEducation.render();
	},

	render: function() {
		$('#outlet').append(this.$el.html(this.template('')));
		var viewStack = this.childViews;

		_.each(this.viewMethods, function(view) {
				var newView = new view();
				viewStack.push(newView);
		});

	},

	closeOnEsc: function(e) {
		if (e.keyCode === 27) {
			this.closeForm();
		}
	},

	closeForm: function() {
		this.activeForm.close();
		this.activeForm = null;
	},

	close: function() {
		_.each(this.childViews, function(childView) {
			childView.close();
		});
		if (this.activeForm) {
			this.activeForm.close();
		}
		this.remove();
		this.unbind();
	}

});<commit_msg>Fixed active class issue.<commit_after>var app = app || {};

app.BuildView = Backbone.View.extend({

	id: '#buildView',

	template: templates['build.hbs'],

	events: {
		'click #buildNav': 'navClick',
		'click #buildSingleNav': 'navSingle',
		'click #closeForm': 'closeForm',
		'keypress': 'closeOnEsc'
	},

	initialize: function() {
		this.listenTo(app.Router, 'close', this.close);

		this.childViews = [];
		this.viewMethods = [
			app.NameView,
			app.EmailView,
			app.EducationsView,
			app.EmploymentsView,
			app.SkillsView,
			app.InterestsView,
			app.ProfilesView
		];

		this.changeForms = {
			changeName: app.Name,
			changeEmail: app.Email
		};

		this.forms = {
			addEducation: app.EducationFormView,
			addEmployment: app.EmploymentFormView,
			addSkill: app.SkillFormView,
			addInterest: app.InterestFormView,
			addProfile: app.ProfileFormView
		};

	},

	navSingle: function(e) {
		var navButton = $(e.target).parent();

		if (navButton.hasClass('active')) {
			return;
		}
		$('#build nav').children().removeClass('active');
		navButton.addClass('active');

		if (this.activeForm) {
			this.activeForm.close();
		}

		this.activeForm = new app.ChangeFormView({model: this.changeForms[e.target.id]});
		this.activeForm.render();

	},

	removeClass: function() {
		$('#build nav').children().removeClass('active');
	},

	navClick: function(e) {
		var navButton = $(e.target).parent();
		if (navButton.hasClass('active')) {
			return;
		}

		$('#buildForm').empty();
		$('#build nav').children().removeClass('active');
		navButton.addClass('active');

		if (this.activeForm) {
			this.activeForm.close();
		}

		this.activeForm = new this.forms[e.target.id]({
			options: {
				action:'add'
			}
		});

		this.activeForm.render();

	},

	edit: function(model) {
		this.forms.addEducation.values = model.toJSON();
		this.forms.addEducation.render();
	},

	render: function() {
		$('#outlet').append(this.$el.html(this.template('')));
		var viewStack = this.childViews;

		_.each(this.viewMethods, function(view) {
				var newView = new view();
				viewStack.push(newView);
		});

	},

	closeOnEsc: function(e) {
		if (e.keyCode === 27) {
			this.closeForm();
		}
	},

	closeForm: function() {
		this.activeForm.close();
		this.activeForm = null;
	},

	close: function() {
		_.each(this.childViews, function(childView) {
			childView.close();
		});
		if (this.activeForm) {
			this.activeForm.close();
		}
		this.remove();
		this.unbind();
	}

});<|endoftext|>