├── log └── .keep ├── app ├── mailers │ └── .keep ├── assets │ ├── images │ │ └── .keep │ ├── stylesheets │ │ ├── shared │ │ │ ├── clearfix.css.scss │ │ │ ├── form.css.scss │ │ │ └── gradient.css.scss │ │ ├── homepage.scss │ │ ├── application.css.scss │ │ ├── navbar.css.scss │ │ ├── teams.css.scss │ │ └── scaffolds.css.scss │ └── javascripts │ │ ├── application.js │ │ └── bookmarklet.js ├── models │ ├── concerns │ │ └── .keep │ ├── team_member.rb │ ├── repository_url_parser.rb │ ├── service.rb │ ├── issue_url_parser.rb │ ├── ship_list.rb │ ├── git_hub_url_parser.rb │ ├── issue_updater.rb │ ├── user.rb │ ├── team.rb │ ├── bucket.rb │ └── issue.rb ├── controllers │ ├── concerns │ │ └── .keep │ ├── user_controller.rb │ ├── ship_lists_controller.rb │ ├── audit_entries_controller.rb │ ├── sessions_controller.rb │ ├── import_controller.rb │ ├── radars_controller.rb │ ├── teams_controller.rb │ ├── buckets_controller.rb │ ├── application_controller.rb │ └── services_controller.rb ├── views │ ├── teams │ │ ├── _team_preview.html.erb │ │ └── index.html.erb │ ├── audit_entries │ │ ├── _archive_issues.html.erb │ │ ├── _create_bucket.html.erb │ │ ├── _remove_issue.html.erb │ │ ├── _rename_bucket.html.erb │ │ ├── _move_bucket.html.erb │ │ ├── _import_issue.html.erb │ │ ├── _remove_bucket.html.erb │ │ ├── index.html.erb │ │ └── _prioritize_issue.html.erb │ ├── buckets │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ ├── _navbar.html.erb │ │ ├── _bucket.html.erb │ │ ├── _form.html.erb │ │ ├── index.html.erb │ │ └── _issue.html.erb │ ├── shared │ │ ├── _scripts.html.erb │ │ └── _head.html.erb │ ├── ship_lists │ │ ├── show.html.erb │ │ └── index.html.erb │ ├── layouts │ │ ├── _messages.html.erb │ │ └── application.html.erb │ ├── radars │ │ └── show.html.erb │ ├── sessions │ │ └── new.html.erb │ ├── prioritized_issues │ │ └── new.html.erb │ └── import │ │ └── index.html.erb ├── services │ └── application_service.rb └── helpers │ └── application_helper.rb ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── favicon.ico ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── test ├── helpers │ └── .keep ├── mailers │ └── .keep ├── controllers │ └── .keep ├── fixtures │ ├── buckets.yml │ ├── prioritized_issues.yml │ ├── users.yml │ ├── issues.yml │ └── vcr_cassettes │ │ └── test__from_issue_does_not_update_issue_when_github_returns_304_not_modified.yml ├── models │ ├── issue_test.rb │ ├── issue_updater_test.rb │ ├── bucket_test.rb │ ├── repository_url_parser_test.rb │ ├── issue_url_parser_test.rb │ ├── prioritized_issue_test.rb │ └── audit_entry_test.rb ├── services │ └── application_service_test.rb └── test_helper.rb ├── .ruby-version ├── vendor └── assets │ ├── javascripts │ └── .keep │ ├── stylesheets │ └── .keep │ ├── bower.json │ └── bower_components │ └── octicons │ ├── svg │ ├── dash.svg │ ├── playback-play.svg │ ├── primitive-square.svg │ ├── triangle-down.svg │ ├── zap.svg │ ├── arrow-down.svg │ ├── arrow-left.svg │ ├── arrow-up.svg │ ├── triangle-up.svg │ ├── arrow-right.svg │ ├── arrow-small-up.svg │ ├── color-mode.svg │ ├── triangle-left.svg │ ├── arrow-small-down.svg │ ├── arrow-small-left.svg │ ├── arrow-small-right.svg │ ├── check.svg │ ├── playback-pause.svg │ ├── plus.svg │ ├── chevron-down.svg │ ├── chevron-left.svg │ ├── chevron-right.svg │ ├── chevron-up.svg │ ├── jump-up.svg │ ├── move-up.svg │ ├── triangle-right.svg │ ├── jump-down.svg │ ├── jump-left.svg │ ├── jump-right.svg │ ├── move-down.svg │ ├── playback-rewind.svg │ ├── move-left.svg │ ├── mail-reply.svg │ ├── move-right.svg │ ├── playback-fast-forward.svg │ ├── three-bars.svg │ ├── inbox.svg │ ├── x.svg │ ├── code.svg │ ├── milestone.svg │ ├── pencil.svg │ ├── ruby.svg │ ├── sign-out.svg │ ├── versions.svg │ ├── link-external.svg │ ├── mute.svg │ ├── primitive-dot.svg │ ├── star.svg │ ├── comment.svg │ ├── home.svg │ ├── quote.svg │ ├── alignment-unalign.svg │ ├── file-symlink-file.svg │ ├── gist.svg │ ├── pulse.svg │ ├── stop.svg │ ├── alignment-align.svg │ ├── file-code.svg │ ├── file-text.svg │ ├── graph.svg │ ├── list-unordered.svg │ ├── alignment-aligned-to.svg │ ├── mail.svg │ ├── mirror.svg │ ├── sign-in.svg │ ├── diff.svg │ ├── file-directory.svg │ ├── location.svg │ ├── ellipsis.svg │ ├── gist-secret.svg │ ├── settings.svg │ ├── terminal.svg │ ├── heart.svg │ ├── unfold.svg │ ├── browser.svg │ ├── fold.svg │ ├── diff-removed.svg │ ├── horizontal-rule.svg │ ├── screen-full.svg │ ├── screen-normal.svg │ ├── file-binary.svg │ ├── device-desktop.svg │ ├── diff-ignored.svg │ ├── lock.svg │ ├── diff-renamed.svg │ ├── list-ordered.svg │ ├── podium.svg │ ├── comment-discussion.svg │ ├── file-media.svg │ ├── diff-added.svg │ ├── file-symlink-directory.svg │ ├── split.svg │ ├── file-zip.svg │ ├── briefcase.svg │ ├── clock.svg │ ├── repo-push.svg │ ├── issue-opened.svg │ ├── repo.svg │ ├── diff-modified.svg │ ├── git-commit.svg │ ├── tag.svg │ ├── alert.svg │ ├── mail-read.svg │ ├── rss.svg │ ├── flame.svg │ ├── markdown.svg │ ├── credit-card.svg │ ├── question.svg │ ├── repo-pull.svg │ ├── search.svg │ ├── bookmark.svg │ ├── file-submodule.svg │ ├── key.svg │ ├── device-mobile.svg │ ├── circle-slash.svg │ ├── mortar-board.svg │ ├── package.svg │ ├── beer.svg │ ├── eye.svg │ ├── keyboard.svg │ ├── history.svg │ ├── issue-closed.svg │ ├── no-newline.svg │ ├── repo-force-push.svg │ ├── microscope.svg │ ├── link.svg │ ├── steps.svg │ ├── repo-forked.svg │ ├── info.svg │ ├── calendar.svg │ ├── person.svg │ ├── clippy.svg │ ├── jersey.svg │ ├── sync.svg │ ├── issue-reopened.svg │ ├── repo-clone.svg │ ├── pin.svg │ ├── hubot.svg │ ├── law.svg │ ├── trashcan.svg │ ├── checklist.svg │ ├── light-bulb.svg │ ├── book.svg │ ├── gear.svg │ ├── server.svg │ ├── squirrel.svg │ ├── rocket.svg │ ├── git-compare.svg │ ├── unmute.svg │ ├── broadcast.svg │ ├── git-branch.svg │ ├── tools.svg │ ├── database.svg │ ├── git-pull-request.svg │ ├── megaphone.svg │ ├── file-pdf.svg │ ├── git-merge.svg │ ├── paintcan.svg │ ├── device-camera.svg │ ├── circuit-board.svg │ ├── cloud-download.svg │ ├── cloud-upload.svg │ ├── mark-github.svg │ ├── gift.svg │ ├── hourglass.svg │ ├── octoface.svg │ ├── mention.svg │ ├── device-camera-video.svg │ ├── telescope.svg │ ├── dashboard.svg │ ├── organization.svg │ ├── plug.svg │ ├── bug.svg │ ├── radio-tower.svg │ └── globe.svg │ ├── octicons │ ├── octicons.eot │ ├── octicons.ttf │ ├── octicons.woff │ └── octicons-local.ttf │ ├── .gitignore │ ├── LICENSE.txt │ ├── bower.json │ └── .bower.json ├── config ├── initializers │ ├── octokit.rb │ ├── cookies_serializer.rb │ ├── session_store.rb │ ├── omniauth.rb │ ├── mime_types.rb │ ├── pusher.rb │ ├── filter_parameter_logging.rb │ ├── backtrace_silencers.rb │ ├── wrap_parameters.rb │ └── inflections.rb ├── environment.rb ├── boot.rb ├── locales │ ├── en.bootstrap.yml │ └── en.yml ├── unicorn.rb ├── secrets.yml ├── application.rb ├── routes.rb └── environments │ ├── development.rb │ └── test.rb ├── Procfile ├── extensions ├── chrome.zip └── chrome │ ├── icon48.png │ ├── icon128.png │ ├── background.js │ ├── manifest.json │ └── bookmarklet.js ├── bin ├── bundle ├── rake ├── rails └── spring ├── config.ru ├── db ├── migrate │ ├── 20140608224139_add_labels_to_issues.rb │ ├── 20140608175825_add_assigee_to_issues.rb │ ├── 20140609022534_add_synced_at_to_issues.rb │ ├── 20140614210138_remove_synced_at_from_issues.rb │ ├── 20160127054900_add_pull_request_to_issue.rb │ ├── 20140609223855_add_archived_at_to_prioritized_issue.rb │ ├── 20140608063204_add_team_id_to_users_and_buckets.rb │ ├── 20140606063200_create_users.rb │ ├── 20140606063633_create_services.rb │ ├── 20140607075001_create_buckets.rb │ ├── 20140608195129_rename_fields.rb │ ├── 20140607173338_create_prioritized_issues.rb │ ├── 20140606051823_create_issues.rb │ ├── 20140614190256_add_indexes.rb │ └── 20140805221233_create_audit_entries.rb └── seeds.rb ├── Rakefile ├── .gitignore ├── CONTRIBUTING.md ├── Gemfile └── LICENSE /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3.0 2 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/initializers/octokit.rb: -------------------------------------------------------------------------------- 1 | Octokit.auto_paginate = true 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb 2 | -------------------------------------------------------------------------------- /extensions/chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/extensions/chrome.zip -------------------------------------------------------------------------------- /extensions/chrome/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/extensions/chrome/icon48.png -------------------------------------------------------------------------------- /extensions/chrome/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/extensions/chrome/icon128.png -------------------------------------------------------------------------------- /app/views/teams/_team_preview.html.erb: -------------------------------------------------------------------------------- 1 | <%= team.name %> 2 |
3 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /app/models/team_member.rb: -------------------------------------------------------------------------------- 1 | class TeamMember 2 | def initialize(params) 3 | @login = params[:login] 4 | end 5 | 6 | attr_reader :login 7 | end 8 | -------------------------------------------------------------------------------- /vendor/assets/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "i-got-issues", 3 | "dependencies": { 4 | "octicons": "git@github.com:github/octicons.git" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /app/views/audit_entries/_archive_issues.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> archived closed issues for <%= entry.team_name %> 2 | -------------------------------------------------------------------------------- /app/views/audit_entries/_create_bucket.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> created the <%= entry.target_bucket_name %> bucket 2 | -------------------------------------------------------------------------------- /app/assets/stylesheets/shared/clearfix.css.scss: -------------------------------------------------------------------------------- 1 | @mixin clearfix { 2 | &:after { 3 | content: ""; 4 | display: table; 5 | clear: both; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /app/models/repository_url_parser.rb: -------------------------------------------------------------------------------- 1 | class RepositoryUrlParser < GitHubUrlParser 2 | def url_pattern 3 | /https?\:\/\/github\.(?:com|dev)\/(.+)\/(.+)/ 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/dash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /db/migrate/20140608224139_add_labels_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddLabelsToIssues < ActiveRecord::Migration 2 | def change 3 | add_column :issues, :labels, :binary 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/octicons/octicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/vendor/assets/bower_components/octicons/octicons/octicons.eot -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/octicons/octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/vendor/assets/bower_components/octicons/octicons/octicons.ttf -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/octicons/octicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/vendor/assets/bower_components/octicons/octicons/octicons.woff -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_issues_session' 4 | -------------------------------------------------------------------------------- /db/migrate/20140608175825_add_assigee_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddAssigeeToIssues < ActiveRecord::Migration 2 | def change 3 | add_column :issues, :assignee, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/playback-play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path("../application", __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/initializers/omniauth.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.middleware.use OmniAuth::Builder do 2 | provider :github, ENV["GITHUB_KEY"], ENV["GITHUB_SECRET"], :scope => "user,repo" 3 | end 4 | -------------------------------------------------------------------------------- /db/migrate/20140609022534_add_synced_at_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddSyncedAtToIssues < ActiveRecord::Migration 2 | def change 3 | add_column :issues, :synced_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/octicons/octicons-local.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonmagic/i-got-issues/HEAD/vendor/assets/bower_components/octicons/octicons/octicons-local.ttf -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/primitive-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140614210138_remove_synced_at_from_issues.rb: -------------------------------------------------------------------------------- 1 | class RemoveSyncedAtFromIssues < ActiveRecord::Migration 2 | def change 3 | remove_column :issues, :synced_at 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/triangle-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/zap.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__) 3 | 4 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 5 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle 2 | /.rbenv-version 3 | /node_modules 4 | /bin 5 | /build 6 | /tmp 7 | /font 8 | /support/font-builder/support 9 | /site/_site/ 10 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/triangle-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audit_entries/_remove_issue.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> removed <%= link_to entry.issue_title, github_issue_url(entry.issue) %> from <%= entry.team_name %> 2 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | require_relative '../config/boot' 7 | require 'rake' 8 | Rake.application.run 9 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-small-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/color-mode.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/triangle-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audit_entries/_rename_bucket.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> renamed the bucket <%= entry.source_bucket_name %> to <%= entry.target_bucket_name %> 2 | -------------------------------------------------------------------------------- /config/initializers/pusher.rb: -------------------------------------------------------------------------------- 1 | # config/initializers/pusher.rb 2 | 3 | if ENV["PUSHER_URL"].present? 4 | require 'pusher' 5 | 6 | Pusher.url = ENV["PUSHER_URL"] 7 | Pusher.logger = Rails.logger 8 | end 9 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-small-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-small-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/arrow-small-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/playback-pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audit_entries/_move_bucket.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> moved bucket <%= entry.source_bucket_name %> to the #<%= entry.bucket_end_position %> column 2 | -------------------------------------------------------------------------------- /db/migrate/20160127054900_add_pull_request_to_issue.rb: -------------------------------------------------------------------------------- 1 | class AddPullRequestToIssue < ActiveRecord::Migration 2 | def change 3 | add_column :issues, :pull_request, :boolean, :default => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/chevron-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/jump-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/move-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/triangle-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/jump-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/jump-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/jump-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/move-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/playback-rewind.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audit_entries/_import_issue.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> imported <%= link_to entry.issue_title, github_issue_url(entry.issue) %> into bucket <%= entry.target_bucket_name %> 2 | -------------------------------------------------------------------------------- /app/views/buckets/new.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "navbar" %> 3 | <% end %> 4 | 5 |
6 |

New bucket

7 | 8 | <%= render 'form' %> 9 |
10 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/move-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/service.rb: -------------------------------------------------------------------------------- 1 | class Service < ActiveRecord::Base 2 | # column :user_id 3 | belongs_to :user 4 | 5 | # column :uid 6 | # column :provider 7 | # column :created_at 8 | # column :updated_at 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20140609223855_add_archived_at_to_prioritized_issue.rb: -------------------------------------------------------------------------------- 1 | class AddArchivedAtToPrioritizedIssue < ActiveRecord::Migration 2 | def change 3 | add_column :prioritized_issues, :archived_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mail-reply.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/move-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/playback-fast-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/three-bars.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/inbox.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audit_entries/_remove_bucket.html.erb: -------------------------------------------------------------------------------- 1 | <%= entry.user_login %> removed the <%= entry.source_bucket_name %> bucket and reassigned all issues to the <%= entry.target_bucket_name %> bucket 2 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/issue_url_parser.rb: -------------------------------------------------------------------------------- 1 | class IssueUrlParser < GitHubUrlParser 2 | def url_pattern 3 | /https?\:\/\/github\.(?:com|dev)\/(.+)\/(.+)\/(?:issues|pull)\/(\d*)/ 4 | end 5 | 6 | def number 7 | matches[3].to_i 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /db/migrate/20140608063204_add_team_id_to_users_and_buckets.rb: -------------------------------------------------------------------------------- 1 | class AddTeamIdToUsersAndBuckets < ActiveRecord::Migration 2 | def change 3 | add_column :users, :team_id, :integer 4 | add_column :buckets, :team_id, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | APP_PATH = File.expand_path('../../config/application', __FILE__) 7 | require_relative '../config/boot' 8 | require 'rails/commands' 9 | -------------------------------------------------------------------------------- /db/migrate/20140606063200_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration 2 | def change 3 | create_table :users do |t| 4 | t.string :name 5 | t.string :email 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/milestone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/LICENSE.txt: -------------------------------------------------------------------------------- 1 | (c) 2012-2014 GitHub 2 | 3 | Font License: SIL OFL 1.1 (http://scripts.sil.org/OFL) 4 | Applies to all font files 5 | 6 | Code License: MIT (http://choosealicense.com/licenses/mit/) 7 | Applies to all other files 8 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/pencil.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/ruby.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/sign-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/versions.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/link-external.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mute.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/primitive-dot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/comment.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/quote.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/controllers/user_controller.rb: -------------------------------------------------------------------------------- 1 | class UserController < ApplicationController 2 | def set_team 3 | if team.member?(current_user) 4 | current_user.update_attribute :team_id, params[:team_id] 5 | end 6 | 7 | redirect_to team_path(current_user.team) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/ship_lists_controller.rb: -------------------------------------------------------------------------------- 1 | class ShipListsController < ApplicationController 2 | before_filter :authorize_read_team! 3 | 4 | def index 5 | @ship_lists = @team.ship_lists 6 | end 7 | 8 | def show 9 | @ship_list = @team.ship_list(params[:id]) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/alignment-unalign.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-symlink-file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/gist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/pulse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140606063633_create_services.rb: -------------------------------------------------------------------------------- 1 | class CreateServices < ActiveRecord::Migration 2 | def change 3 | create_table :services do |t| 4 | t.references :user, index: true 5 | t.string :provider 6 | t.string :uid 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/alignment-align.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/graph.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/list-unordered.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140607075001_create_buckets.rb: -------------------------------------------------------------------------------- 1 | class CreateBuckets < ActiveRecord::Migration 2 | def change 3 | create_table :buckets do |t| 4 | t.string :name, :null => false 5 | t.integer :row_order, :null => false, :default => 0 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/shared/_scripts.html.erb: -------------------------------------------------------------------------------- 1 | <% if Pusher.app_id.present? %> 2 | 3 | 6 | <% end %> 7 | <%= javascript_include_tag "application" %> 8 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/alignment-aligned-to.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140608195129_rename_fields.rb: -------------------------------------------------------------------------------- 1 | class RenameFields < ActiveRecord::Migration 2 | def change 3 | rename_column :issues, :github_owner, :owner 4 | rename_column :issues, :github_repository, :repository 5 | rename_column :issues, :github_id, :number 6 | rename_column :users, :name, :login 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mirror.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/sign-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/diff.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-directory.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/fixtures/buckets.yml: -------------------------------------------------------------------------------- 1 | current: 2 | name: Current 3 | row_order: 0 4 | team_id: 203770 5 | 6 | backlog: 7 | name: Backlog 8 | row_order: 1 9 | team_id: 203770 10 | 11 | icebox: 12 | name: Icebox 13 | row_order: 2 14 | team_id: 203770 15 | 16 | other: 17 | name: Other Bucket 18 | row_order: 0 19 | team_id: 203768 20 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/location.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/models/issue_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class IssueTest < ActiveSupport::TestCase 4 | test "#state returns nil when not set" do 5 | assert_nil Issue.new.state 6 | end 7 | 8 | test "#state returns :open when set to open" do 9 | issue = Issue.new :state => :open 10 | assert_equal "open", issue.state 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/ellipsis.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/gist-secret.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/controllers/audit_entries_controller.rb: -------------------------------------------------------------------------------- 1 | class AuditEntriesController < ApplicationController 2 | before_filter :authorize_read_team! 3 | 4 | def index 5 | @entries = AuditEntry.by_team_id(team.id) 6 | 7 | respond_to do |format| 8 | format.json { render :json => @entries } 9 | format.html { render } 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/terminal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/shared/form.css.scss: -------------------------------------------------------------------------------- 1 | .form-container { 2 | width: 500px; 3 | margin: auto; 4 | 5 | h1 { 6 | font-size: 30px; 7 | font-weight: 300; 8 | line-height: 1.6em; 9 | border-bottom: 1px solid #e9e9e9; 10 | } 11 | 12 | .actions { 13 | margin: 15px 0; 14 | } 15 | 16 | .field { 17 | margin-top: 20px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/unfold.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/browser.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/ship_list.rb: -------------------------------------------------------------------------------- 1 | class ShipList 2 | def initialize(params={}) 3 | @timestamp = params[:timestamp].try(:to_time) 4 | @issues = params[:issues] || [] 5 | end 6 | 7 | attr_reader :timestamp, :issues 8 | 9 | def to_s 10 | timestamp.strftime("%A, %B %e %Y at %H:%M %Z") 11 | end 12 | 13 | def to_param 14 | timestamp.iso8601 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/fold.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/git_hub_url_parser.rb: -------------------------------------------------------------------------------- 1 | class GitHubUrlParser 2 | class InvalidUrl < StandardError; end 3 | 4 | def initialize(url) 5 | @matches = url_pattern.match(url) 6 | raise InvalidUrl unless @matches.present? 7 | end 8 | 9 | attr_reader :matches 10 | 11 | def owner 12 | matches[1] 13 | end 14 | 15 | def repository 16 | matches[2] 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/diff-removed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/horizontal-rule.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/screen-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/screen-normal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140607173338_create_prioritized_issues.rb: -------------------------------------------------------------------------------- 1 | class CreatePrioritizedIssues < ActiveRecord::Migration 2 | def change 3 | create_table :prioritized_issues do |t| 4 | t.integer :issue_id, :null => false 5 | t.integer :bucket_id, :null => false 6 | t.integer :row_order, :null => false, :default => 0 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-binary.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/device-desktop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/diff-ignored.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/diff-renamed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/list-ordered.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/podium.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/buckets/edit.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "navbar" %> 3 | <% end %> 4 | 5 |
6 |

Editing bucket

7 | 8 | <%= render 'form' %> 9 | 10 | <%= form_for @bucket, :url => team_bucket_path(@team, @bucket), :method => "delete" do |f| %> 11 | <%= f.submit "Delete Bucket", :class => "button danger" %> 12 | <% end %> 13 |
14 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/comment-discussion.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-media.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/diff-added.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/ship_lists/show.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "buckets/navbar" %> 3 | <% end %> 4 |
5 |
6 |

#### Ship List for <%= @ship_list %>

7 |

8 | <% @ship_list.issues.each do |issue| %>* ([<%= github_issue_nwo_id(issue) %>](<%= github_issue_url(issue) %>)) <%= issue.title %>
<% end %> 9 |

10 |
11 |
12 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-symlink-directory.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/split.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audit_entries/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "buckets/navbar" %> 3 | <% end %> 4 |
5 | <% @entries.each do |entry| %> 6 |
7 | <%= time_ago_in_words(entry.created_at) %> ago 8 | <%= render :partial => entry.action.to_s, :locals => {:entry => entry} %> 9 |
10 | <% end %> 11 |
12 | -------------------------------------------------------------------------------- /extensions/chrome/background.js: -------------------------------------------------------------------------------- 1 | chrome.browserAction.onClicked.addListener(function(tab) { 2 | chrome.tabs.executeScript(tab.id, {file: "bookmarklet.js"}); 3 | }); 4 | 5 | chrome.commands.onCommand.addListener(function(command) { 6 | if(command == "import-issue"){ 7 | chrome.tabs.query({"active": true}, function(tabs) { 8 | chrome.tabs.executeScript(tabs[0].id, {file: "bookmarklet.js"}); 9 | }); 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-zip.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/briefcase.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/repo-push.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/issue-opened.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/repo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/homepage.scss: -------------------------------------------------------------------------------- 1 | .homepage { 2 | text-align: center; 3 | padding: 100px 0; 4 | } 5 | 6 | .site-title { 7 | font-weight: 300; 8 | font-size: 40px; 9 | 10 | .mega-octicon { 11 | display: block; 12 | margin-bottom: 15px; 13 | color: #ddd; 14 | } 15 | } 16 | 17 | .auth-box { 18 | border: 1px solid #e0e0e0; 19 | width: 360px; 20 | border-radius: 3px; 21 | padding: 15px; 22 | margin: 80px auto 0; 23 | } 24 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/diff-modified.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/git-commit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/tag.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mail-read.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/rss.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140606051823_create_issues.rb: -------------------------------------------------------------------------------- 1 | class CreateIssues < ActiveRecord::Migration 2 | def change 3 | create_table :issues do |t| 4 | t.string :title, :null => false 5 | t.string :github_owner, :null => false 6 | t.string :github_repository, :null => false 7 | t.integer :github_id, :null => false 8 | t.integer :state, :null => false 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/flame.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/markdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/credit-card.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/question.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/repo-pull.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css.scss: -------------------------------------------------------------------------------- 1 | /* 2 | = require octicons 3 | */ 4 | 5 | $grid-gutter-width: 5px; 6 | 7 | @import "bootstrap-sprockets"; 8 | @import "bootstrap"; 9 | @import "bootstrap/theme"; 10 | @import "buckets"; 11 | @import "teams"; 12 | @import "navbar"; 13 | @import "homepage"; 14 | @import "shared/form"; 15 | @import "shared/buttons"; 16 | @import "shared/clearfix"; 17 | 18 | .primary-content { 19 | padding: 0 8px 60px; 20 | } 21 | 22 | .container-fluid { 23 | padding: 0; 24 | } 25 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/controllers/sessions_controller.rb: -------------------------------------------------------------------------------- 1 | class SessionsController < ApplicationController 2 | skip_before_filter :authenticate_user!, :only => :new 3 | 4 | def new 5 | if current_user 6 | if current_user.team 7 | redirect_to team_path(:team_id => current_user.team.id) 8 | else 9 | redirect_to teams_path 10 | end 11 | else 12 | render :layout => false 13 | end 14 | end 15 | 16 | def destroy 17 | logout! 18 | redirect_to root_url 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/bookmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-submodule.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/key.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/device-mobile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/circle-slash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/layouts/_messages.html.erb: -------------------------------------------------------------------------------- 1 | <%# Rails flash messages styled for Bootstrap 3.0 %> 2 | <% flash.each do |name, msg| %> 3 | <% if msg.is_a?(String) %> 4 |
alert-dismissible" role="alert"> 5 | 6 | <%= content_tag :div, msg, :id => "flash_#{name}" %> 7 |
8 | <% end %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mortar-board.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | 8 | namespace :test do 9 | Rake::TestTask.new(services: "test:prepare") do |t| 10 | t.libs << "test" 11 | t.pattern = 'test/services/**/*_test.rb' 12 | end 13 | end 14 | 15 | Rake::Task[:test].enhance { Rake::Task["test:services"].invoke } 16 | -------------------------------------------------------------------------------- /app/models/issue_updater.rb: -------------------------------------------------------------------------------- 1 | class IssueUpdater 2 | def initialize(github_client) 3 | @github_client = github_client 4 | end 5 | 6 | attr_reader :github_client 7 | 8 | def from_issue(issue) 9 | github_issue = github_client.issue "#{issue.owner}/#{issue.repository}", issue.number 10 | 11 | github_client.update_issue \ 12 | "#{issue.owner}/#{issue.repository}", issue.number, 13 | github_issue[:title], github_issue[:body], 14 | :state => issue.state, :assignee => issue.assignee 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/package.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/beer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/eye.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/migrate/20140614190256_add_indexes.rb: -------------------------------------------------------------------------------- 1 | class AddIndexes < ActiveRecord::Migration 2 | def change 3 | add_index :buckets, [:team_id, :row_order] 4 | add_index :issues, [:owner, :repository, :number], :unique => true 5 | add_index :prioritized_issues, [:bucket_id, :issue_id], :unique => true 6 | add_index :prioritized_issues, [:bucket_id, :row_order] 7 | add_index :services, [:provider, :uid], :unique => true 8 | add_index :users, [:login], :unique => true 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/buckets/_navbar.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/keyboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/history.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/issue-closed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/*.log 16 | /tmp 17 | 18 | .env 19 | 20 | scratchpad 21 | -------------------------------------------------------------------------------- /test/fixtures/prioritized_issues.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | pi1: 8 | issue: issue1 9 | bucket: icebox 10 | row_order: 0 11 | 12 | pi2: 13 | issue: issue2 14 | bucket: backlog 15 | row_order: 0 16 | 17 | pi3: 18 | issue: issue3 19 | bucket: icebox 20 | row_order: 1 21 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/no-newline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/repo-force-push.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/radars/show.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "buckets/navbar" %> 3 | <% end %> 4 |
5 |
6 |

##### Did:

7 | <% @did.each do |issue| %> 8 | - [x] [<%= github_issue_nwo_id(issue) %>](<%= github_issue_url(issue) %>): <%= issue.title %>
9 | <% end %> 10 |
11 |

##### Doing:

12 | <% @doing.each do |issue| %> 13 | - [ ] [<%= github_issue_nwo_id(issue) %>](<%= github_issue_url(issue) %>): <%= issue.title %>
14 | <% end %> 15 |
16 |
17 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/microscope.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you'd like to hack on I got issues, start by forking the repo on GitHub: 4 | 5 | https://github.com/jonmagic/i-got-issues 6 | 7 | The best way to get your changes merged back into core is as follows: 8 | 9 | 1. Clone down your fork 10 | 1. Create a thoughtfully named topic branch to contain your change 11 | 1. Hack away 12 | 1. If you are adding new functionality, document it in the README 13 | 1. If necessary, rebase your commits into logical chunks, without errors 14 | 1. Push the branch up to GitHub 15 | 1. Send a pull request for your branch 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/shared/gradient.css.scss: -------------------------------------------------------------------------------- 1 | // Creates a linear gradient background, from top to bottom. 2 | // 3 | // $start - The color hex at the top. 4 | // $end - The color hex at the bottom. 5 | // 6 | // Compatibility untested. 7 | @mixin gradient($start: #fafafa, $end: #eaeaea){ 8 | background-color: $end; 9 | // FF 3.6+ 10 | background-image: -moz-linear-gradient($start, $end); 11 | // Safari 5.1+, Chrome 10+ 12 | background-image: -webkit-linear-gradient($start, $end); 13 | background-image: linear-gradient($start, $end); 14 | background-repeat: repeat-x; 15 | } 16 | -------------------------------------------------------------------------------- /app/controllers/import_controller.rb: -------------------------------------------------------------------------------- 1 | class ImportController < ApplicationController 2 | before_filter :authorize_write_team! 3 | 4 | def index 5 | # just renders a form 6 | end 7 | 8 | def create 9 | prioritized_issue_service. 10 | import_issues_from_repository(params[:url], params[:labels], params[:state]) 11 | 12 | redirect_to team_path(team) 13 | end 14 | 15 | private 16 | 17 | def prioritized_issue_service 18 | @prioritized_issue_service ||= \ 19 | PrioritizedIssueService. 20 | for_user_and_team(current_user, team) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/views/buckets/_bucket.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | <%= bucket.name %> 5 | <%= link_to octicon("pencil"), edit_team_bucket_path(@team, bucket), :class => "edit-bucket" %> 6 |

7 |
8 | 9 | 12 |
13 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast 4 | # It gets overwritten when you run the `spring binstub` command 5 | 6 | unless defined?(Spring) 7 | require "rubygems" 8 | require "bundler" 9 | 10 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m) 11 | ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) 12 | ENV["GEM_HOME"] = "" 13 | Gem.paths = ENV 14 | 15 | gem "spring", match[1] 16 | require "spring/binstub" 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config/locales/en.bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | helpers: 6 | actions: "Actions" 7 | links: 8 | back: "Back" 9 | cancel: "Cancel" 10 | confirm: "Are you sure?" 11 | destroy: "Delete" 12 | new: "New" 13 | edit: "Edit" 14 | titles: 15 | edit: "Edit %{model}" 16 | save: "Save %{model}" 17 | new: "New %{model}" 18 | delete: "Delete %{model}" 19 | -------------------------------------------------------------------------------- /test/fixtures/users.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | jonmagic: 8 | login: jonmagic 9 | email: jonmagic@test.com 10 | 11 | jonmagic-test: 12 | login: jonmagic-test 13 | email: jonmagic-test@test.com 14 | team_id: 203770 15 | 16 | juliamae: 17 | login: juliamae 18 | email: juliamae@test.com 19 | -------------------------------------------------------------------------------- /app/controllers/radars_controller.rb: -------------------------------------------------------------------------------- 1 | class RadarsController < ApplicationController 2 | before_filter :authorize_read_team! 3 | 4 | def show 5 | @did = [] 6 | @doing = [] 7 | 8 | team.buckets.each do |bucket| 9 | PrioritizedIssue.bucket(bucket).each do |prioritized_issue| 10 | if prioritized_issue.assignee == params[:id] 11 | if prioritized_issue.closed? 12 | @did.push(prioritized_issue.issue) 13 | else 14 | @doing.push(prioritized_issue.issue) 15 | end 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /test/fixtures/issues.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | issue1: 4 | title: fix the copy 5 | owner: jonmagic 6 | repository: scriptular 7 | number: 10 8 | state: 0 9 | assignee: jonmagic 10 | labels: ["bug"] 11 | 12 | issue2: 13 | title: Fails when .env file doesn't exist 14 | owner: bkeepers 15 | repository: dotenv 16 | number: 2 17 | state: 0 18 | assignee: bkeepers 19 | 20 | issue3: 21 | title: It's dangerous to go alone. Take this! 22 | owner: hoytus 23 | repository: acme 24 | number: 1 25 | state: 0 26 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/steps.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/repo-forked.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/ship_lists/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "buckets/navbar" %> 3 | <% end %> 4 |
5 |
6 | <% if @ship_lists.any? %> 7 |
8 | <% @ship_lists.each do |ship_list| %> 9 | <%= link_to ship_list, team_ship_list_path(@team, ship_list), :class => "list-group-item" %> 10 | <% end %> 11 |
12 | <% else %> 13 |

While viewing your teams buckets click Archive closed issues to rollup closed issues into a Ship List.

14 | <% end %> 15 |
16 |
17 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/person.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/clippy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "octicons", 3 | "description": "GitHub's icon font", 4 | "version": "1.5.2", 5 | "license": "SIL OFL 1.1, MIT", 6 | "private": true, 7 | "homepage": "http://octicons.github.com", 8 | "authors": [ 9 | "GitHub " 10 | ], 11 | "main": [ 12 | "octicons/sprockets-octicons.scss", 13 | "octicons/octicons.eot", 14 | "octicons/octicons.svg", 15 | "octicons/octicons.ttf", 16 | "octicons/octicons.woff" 17 | ], 18 | "keywords": [ 19 | "GitHub", 20 | "icons", 21 | "font", 22 | "web font", 23 | "icon font" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/jersey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/sync.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/models/issue_updater_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class IssueUpdaterTest < ActiveSupport::TestCase 4 | 5 | def github_client 6 | @github_client ||= Octokit::Client.new(:access_token => TEST_ACCESS_TOKEN) 7 | end 8 | 9 | test "#from_issue updates issue on GitHub" do 10 | VCR.use_cassette method_name do 11 | updater = IssueUpdater.new(github_client) 12 | importer = IssueImporter.new(github_client) 13 | issue = issues(:issue3) 14 | issue.state = "closed" 15 | updater.from_issue(issue) 16 | importer.from_issue(issue) 17 | issue.reload 18 | assert_equal "closed", issue.state 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/issue-reopened.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/teams/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% @organizations.each do |organization, teams| %> 4 |
5 |

6 | " class="org-avatar"><%= organization %> 7 |

8 | <% teams.sort_by{ |team| team.name.downcase }.each do |team| %> 9 | 10 | <%= render :partial => "teams/team_preview", :locals => {:team => team} %> 11 | 12 | <% end %> 13 |
14 | <% end %> 15 |
16 |
17 | -------------------------------------------------------------------------------- /config/unicorn.rb: -------------------------------------------------------------------------------- 1 | worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3) 2 | timeout 15 3 | preload_app true 4 | 5 | before_fork do |server, worker| 6 | Signal.trap 'TERM' do 7 | puts 'Unicorn master intercepting TERM and sending myself QUIT instead' 8 | Process.kill 'QUIT', Process.pid 9 | end 10 | 11 | defined?(ActiveRecord::Base) and 12 | ActiveRecord::Base.connection.disconnect! 13 | end 14 | 15 | after_fork do |server, worker| 16 | Signal.trap 'TERM' do 17 | puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT' 18 | end 19 | 20 | defined?(ActiveRecord::Base) and 21 | ActiveRecord::Base.establish_connection 22 | end 23 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/repo-clone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= render :partial => "shared/head" %> 5 | 6 | 7 |
8 |

9 | 10 | I Got Issues 11 |

12 |

Teams, Buckets, and Issues

13 |
14 |

Please authenticate with GitHub to continue using the Issues application.

15 | <%= t('auth.github_html') %> 16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /test/models/bucket_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class BucketTest < ActiveSupport::TestCase 4 | test "buckets are sortable" do 5 | current = buckets(:current) 6 | backlog = buckets(:backlog) 7 | icebox = buckets(:icebox) 8 | team = Team.new(:id => current.team_id) 9 | assert_equal [current, backlog, icebox], team.buckets.all 10 | 11 | current.change_position(:last) 12 | assert_equal [backlog, icebox, current], team.buckets.all 13 | end 14 | 15 | test "#current_position returns column position" do 16 | assert_equal 1, buckets(:current).current_position 17 | assert_equal 2, buckets(:backlog).current_position 18 | assert_equal 3, buckets(:icebox).current_position 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | ruby "2.3.0" 4 | 5 | gem "rails", "4.2.5" 6 | gem "bootstrap-sass" 7 | gem "coffee-rails" 8 | gem "dotenv-rails", :groups => [:development, :test] 9 | gem "jquery-rails" 10 | gem "jquery-ui-rails" 11 | gem "newrelic_rpm" 12 | gem "octokit" 13 | gem "omniauth-github" 14 | gem "pg" 15 | gem "pusher" 16 | gem "rails_12factor", :group => :production 17 | gem "ranked-model" 18 | gem "sass-rails" 19 | gem "spring", :group => :development 20 | gem "turbolinks" 21 | gem "uglifier" 22 | gem "unicorn" 23 | 24 | group :test do 25 | gem "webmock" 26 | gem "vcr" 27 | end 28 | 29 | group :test, :development do 30 | gem "minitest-rails-capybara" 31 | gem "pry" 32 | gem "rack_session_access" 33 | end 34 | -------------------------------------------------------------------------------- /app/assets/stylesheets/navbar.css.scss: -------------------------------------------------------------------------------- 1 | .issue-url { 2 | min-width: 25em; 3 | } 4 | 5 | .navbar-default { 6 | box-shadow: none; 7 | background-image: none; 8 | border-radius: 0; 9 | min-height: 0; 10 | 11 | .main .octicon { 12 | margin-right: 7px; 13 | } 14 | 15 | .navbar-form { 16 | margin: 4px 0; 17 | } 18 | } 19 | 20 | .navbar-nav li > a { 21 | padding-top: 10px; 22 | padding-bottom: 10px; 23 | border-bottom: 3px solid transparent; 24 | } 25 | 26 | .navbar-nav .active > a { 27 | border-bottom-color: #86cbe9; 28 | font-weight: bold; 29 | 30 | background: transparent !important; 31 | box-shadow: none !important; 32 | } 33 | 34 | .navbar-default.navbar-fixed-bottom li > a { 35 | color: #08c; 36 | } 37 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/hubot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/law.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/trashcan.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/services/application_service_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ApplicationServiceTest < ActiveSupport::TestCase 4 | test ".for_user_and_team returns instance with user and team set" do 5 | user = User.new 6 | team = Team.new 7 | service = ApplicationService.for_user_and_team(user, team) 8 | 9 | assert_equal user, service.user 10 | assert_equal team, service.team 11 | end 12 | 13 | test "#github_client returns github client for user" do 14 | user = User.new 15 | user.github_client = "fake github client" 16 | team = Team.new 17 | service = ApplicationService.for_user_and_team(user, team) 18 | 19 | assert_equal "fake github client", service.github_client 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | app: 3 | title: "GitHub Issues" 4 | auth: 5 | twitter_html: "Login with Twitter" 6 | github_html: "Login with GitHub" 7 | logout: "Logout" 8 | notifications: 9 | account_created: 'Your account has been created and you have been logged in!' 10 | provider_already_connected: 'Your account at %{provider} is already connected!.' 11 | provider_added: 'Your %{provider} account has been added for logging in!.' 12 | provider_unlinked: 'Your %{provider} account has been unlinked!.' 13 | authentication_error: 'There was an error at the remote authentication service!.' 14 | logged_in: "Successfully logged in." 15 | import_issues: 16 | select_a_team: "Select a team to import issue into." 17 | -------------------------------------------------------------------------------- /app/views/buckets/_form.html.erb: -------------------------------------------------------------------------------- 1 | <% url = @bucket.new_record? ? team_buckets_path(@team) : team_bucket_path(@team, @bucket) %> 2 | 3 | <%= form_for @bucket, :url => url do |f| %> 4 | <% if @bucket.errors.any? %> 5 |
6 |

<%= pluralize(@bucket.errors.count, "error") %> prohibited this bucket from being saved:

7 | 8 | 13 |
14 | <% end %> 15 | 16 |
17 | <%= f.label :name %>
18 | <%= f.text_field :name, :class => "form-control" %> 19 |
20 | 21 |
22 | <%= f.submit "Save", :class => "button" %> 23 |
24 | <% end %> 25 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/checklist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | 3 | # Public: GitHub login. 4 | # column :login 5 | # Returns a String. 6 | validates :login, :uniqueness => true 7 | 8 | # Public: Primary email address on GitHub. 9 | # column :email 10 | # Returns a String. 11 | 12 | # Public: Id of team on GitHub. 13 | # column :team_id 14 | # Returns an Integer. 15 | 16 | has_many :buckets, -> { rank(:row_order) }, 17 | :primary_key => "team_id", 18 | :foreign_key => "team_id" 19 | 20 | def issues 21 | PrioritizedIssue.where(:bucket => buckets) 22 | end 23 | 24 | # column :created_at 25 | # column :updated_at 26 | 27 | has_many :services 28 | 29 | attr_accessor :github_client 30 | 31 | def team 32 | Team.new(:id => team_id) if team_id 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /app/views/audit_entries/_prioritize_issue.html.erb: -------------------------------------------------------------------------------- 1 | <% if entry.source_bucket_id == entry.target_bucket_id %> 2 | <%= entry.user_login %> prioritized <%= link_to entry.issue_title, github_issue_url(entry.issue) %> from the #<%= entry.issue_start_position %> position to the #<%= entry.issue_end_position %> position in bucket <%= entry.target_bucket_name %> 3 | <% else %> 4 | <%= entry.user_login %> moved <%= link_to entry.issue_title, github_issue_url(entry.issue) %> from the #<%= entry.issue_start_position %> position in bucket <%= entry.source_bucket_name %> to the #<%= entry.issue_end_position %> position in bucket <%= entry.target_bucket_name %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /test/models/repository_url_parser_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RepositoryUrlParserTest < ActiveSupport::TestCase 4 | test "raises error if the url does not match pattern" do 5 | assert_raises(RepositoryUrlParser::InvalidUrl) { RepositoryUrlParser.new("foo") } 6 | end 7 | 8 | test "works with pull request url" do 9 | assert_nothing_raised { RepositoryUrlParser.new("https://github.com/jonmagic/scriptular") } 10 | end 11 | 12 | test "#owner" do 13 | parsed = RepositoryUrlParser.new("https://github.com/jonmagic/scriptular") 14 | assert_equal "jonmagic", parsed.owner 15 | end 16 | 17 | test "#repository" do 18 | parsed = RepositoryUrlParser.new("https://github.com/jonmagic/scriptular") 19 | assert_equal "scriptular", parsed.repository 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /extensions/chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tissues", 3 | "description": "Import GitHub issue into Tissues.", 4 | "homepage_url": "https://teams-buckets-issues.herokuapp.com", 5 | "version": "0.1", 6 | "manifest_version": 2, 7 | "permissions": [ "tabs", "https://github.com/" ], 8 | "background": { 9 | "scripts": ["background.js"], 10 | "persistent": false 11 | }, 12 | "icons": { 13 | "48": "icon48.png", 14 | "128": "icon128.png" 15 | }, 16 | "browser_action": { 17 | "default_icon": "icon128.png", 18 | "default_title": "Tissues" 19 | }, 20 | "commands": { 21 | "import-issue": { 22 | "suggested_key": { 23 | "default": "Ctrl+I", 24 | "mac": "Ctrl+I" 25 | }, 26 | "description": "Import issue into Tissues" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/light-bulb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/book.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require bootstrap-sprockets 16 | //= require turbolinks 17 | //= require jquery.ui.sortable 18 | //= require buckets 19 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/gear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/server.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/squirrel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/rocket.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/controllers/teams_controller.rb: -------------------------------------------------------------------------------- 1 | class TeamsController < ApplicationController 2 | before_filter :authorize_write_team!, :only => [:archive_closed_issues] 3 | after_filter :notify_team_subscribers, :only => [:archive_closed_issues] 4 | 5 | def index 6 | @organizations = current_user. 7 | github_client. 8 | user_teams. 9 | map {|t| Team.new(t) }. 10 | group_by {|t| t.organization.downcase }. 11 | sort 12 | end 13 | 14 | # Archives all closed, non-archived issues for the team. 15 | def archive_closed_issues 16 | team.issues.closed.where(:archived_at => nil).update_all :archived_at => Time.now.beginning_of_minute 17 | 18 | AuditEntry.create do |entry| 19 | entry.user = current_user 20 | entry.team = team 21 | entry.action = :archive_issues 22 | end 23 | 24 | head :ok 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/views/prioritized_issues/new.html.erb: -------------------------------------------------------------------------------- 1 | <% @organizations.each do |organization, teams| %> 2 | <% next unless teams.inject(0) {|num, team| num += team.buckets.count } > 0 %> 3 |
4 |
5 |

<%= organization %>

6 | <% teams.each do |team| %> 7 | <% next unless team.buckets.any? %> 8 |
9 | <%= form_tag team_bucket_prioritized_issues_path(team, team.buckets.last) do %> 10 | <%= hidden_field_tag :url, @url %> 11 | <%= hidden_field_tag :return, @return %> 12 | 15 | <% end %> 16 |
17 | <% end %> 18 |
19 |
20 | <% end %> 21 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/git-compare.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # Create user 2 | User.create(:login => "jonmagic", :email => "jonmagic@gmail.com") 3 | 4 | # Create buckets 5 | icebox = Bucket.create(:name => "Icebox", :row_order => 2) 6 | backlog = Bucket.create(:name => "Backlog", :row_order => 1) 7 | current = Bucket.create(:name => "Current", :row_order => 0) 8 | 9 | # Create prioritized issues 10 | (99..117).each do |n| 11 | github_issue = Octokit.issue "bkeepers/dotenv", n 12 | issue = Issue.create \ 13 | :title => github_issue["title"], 14 | :owner => "bkeepers", 15 | :repository => "dotenv", 16 | :number => github_issue["number"], 17 | :state => github_issue["state"], 18 | :assignee => github_issue["assignee"] ? github_issue["assignee"]["login"] : nil, 19 | :labels => github_issue["labels"].map {|label| label[:name] } 20 | 21 | issue.prioritized_issues.create :bucket => icebox 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20140805221233_create_audit_entries.rb: -------------------------------------------------------------------------------- 1 | class CreateAuditEntries < ActiveRecord::Migration 2 | def change 3 | create_table :audit_entries do |t| 4 | t.integer :team_id, :null => false 5 | t.string :team_name 6 | t.integer :user_id, :null => false 7 | t.string :user_login 8 | t.integer :action 9 | t.integer :issue_id 10 | t.string :issue_title 11 | t.integer :prioritized_issue_id 12 | t.integer :issue_start_position 13 | t.integer :issue_end_position 14 | t.integer :source_bucket_id 15 | t.string :source_bucket_name 16 | t.integer :target_bucket_id 17 | t.string :target_bucket_name 18 | t.integer :bucket_start_position 19 | t.integer :bucket_end_position 20 | t.datetime :created_at 21 | end 22 | 23 | add_index :audit_entries, [:created_at, :team_id] 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/unmute.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/broadcast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/git-branch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/models/issue_url_parser_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class IssueUrlParserTest < ActiveSupport::TestCase 4 | test "raises error if the url does not match pattern" do 5 | assert_raises(IssueUrlParser::InvalidUrl) { IssueUrlParser.new("foo") } 6 | end 7 | 8 | test "works with pull request url" do 9 | assert_nothing_raised { IssueUrlParser.new("https://github.com/jonmagic/scriptular/pull/33") } 10 | end 11 | 12 | test "#owner" do 13 | parsed = IssueUrlParser.new("https://github.com/jonmagic/scriptular/issues/1") 14 | assert_equal "jonmagic", parsed.owner 15 | end 16 | 17 | test "#repository" do 18 | parsed = IssueUrlParser.new("https://github.com/jonmagic/scriptular/issues/1") 19 | assert_equal "scriptular", parsed.repository 20 | end 21 | 22 | test "#number" do 23 | parsed = IssueUrlParser.new("https://github.com/jonmagic/scriptular/issues/1") 24 | assert_equal 1, parsed.number 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "octicons", 3 | "description": "GitHub's icon font", 4 | "version": "1.5.2", 5 | "license": "SIL OFL 1.1, MIT", 6 | "private": true, 7 | "homepage": "http://octicons.github.com", 8 | "authors": [ 9 | "GitHub " 10 | ], 11 | "main": [ 12 | "octicons/sprockets-octicons.scss", 13 | "octicons/octicons.eot", 14 | "octicons/octicons.svg", 15 | "octicons/octicons.ttf", 16 | "octicons/octicons.woff" 17 | ], 18 | "keywords": [ 19 | "GitHub", 20 | "icons", 21 | "font", 22 | "web font", 23 | "icon font" 24 | ], 25 | "_release": "1.5.2", 26 | "_resolution": { 27 | "type": "version", 28 | "tag": "v1.5.2", 29 | "commit": "067e188f7d47fd81cd4d0ee067da3ce9ae52bf19" 30 | }, 31 | "_source": "git@github.com:github/octicons.git", 32 | "_target": "*", 33 | "_originalSource": "git@github.com:github/octicons.git" 34 | } -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/tools.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/import/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "buckets/navbar" %> 3 | <% end %> 4 |
5 |

Import Repository Issues

6 | <%= form_tag do %> 7 |
8 | <%= label_tag :url, "Repository Url" %>
9 | <%= text_field_tag :url, "", :class => "form-control", :placeholder => "https://github.com/jonmagic/scriptular" %> 10 |
11 | 12 |
13 | <%= label_tag :labels, "Only These Labels" %>
14 | <%= text_field_tag :labels, "", :class => "form-control", :placeholder => "bug,enhancement" %> 15 |
16 | 17 |
18 | <%= label_tag :state, "Issue State" %>
19 | <%= select_tag :state, options_for_select(["open", "closed"]) %> 20 |
21 | 22 |
23 | <%= submit_tag "Import Issues", :class => "button" %> 24 |
25 | <% end %> 26 |
27 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/database.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/git-pull-request.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] ||= "test" 2 | require File.expand_path("../../config/environment", __FILE__) 3 | require "rails/test_help" 4 | require "minitest/rails/capybara" 5 | require "rack_session_access/capybara" 6 | 7 | class ActiveSupport::TestCase 8 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 9 | # 10 | # Note: You'll currently still have to declare fixtures explicitly in integration tests 11 | # -- they do not yet inherit this setting 12 | fixtures :buckets, :issues, :prioritized_issues, :users 13 | 14 | # Add more helper methods to be used by all tests here... 15 | end 16 | 17 | VCR.configure do |c| 18 | c.cassette_library_dir = "test/fixtures/vcr_cassettes" 19 | c.hook_into :webmock 20 | end 21 | 22 | TEST_ACCESS_TOKEN = "fake_access_token" 23 | 24 | def login(user, access_token=TEST_ACCESS_TOKEN) 25 | page.set_rack_session :user_id => user.id 26 | page.set_rack_session :oauth_token => access_token 27 | end 28 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/megaphone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/file-pdf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/bookmarklet.js: -------------------------------------------------------------------------------- 1 | function post(path, params, method) { 2 | method = method || "post"; // Set method to post by default if not specified. 3 | 4 | // The rest of this code assumes you are not using a library. 5 | // It can be made less wordy if you use one. 6 | var form = document.createElement("form"); 7 | form.setAttribute("method", method); 8 | form.setAttribute("action", path); 9 | 10 | for(var key in params) { 11 | if(params.hasOwnProperty(key)) { 12 | var hiddenField = document.createElement("input"); 13 | hiddenField.setAttribute("type", "hidden"); 14 | hiddenField.setAttribute("name", key); 15 | hiddenField.setAttribute("value", params[key]); 16 | 17 | form.appendChild(hiddenField); 18 | } 19 | } 20 | 21 | document.body.appendChild(form); 22 | form.submit(); 23 | } 24 | 25 | post("https://teams-buckets-issues.herokuapp.com/prioritized_issues", {url: location.href}); 26 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/git-merge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/paintcan.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /extensions/chrome/bookmarklet.js: -------------------------------------------------------------------------------- 1 | function post(path, params, method) { 2 | method = method || "post"; // Set method to post by default if not specified. 3 | 4 | // The rest of this code assumes you are not using a library. 5 | // It can be made less wordy if you use one. 6 | var form = document.createElement("form"); 7 | form.setAttribute("method", method); 8 | form.setAttribute("action", path); 9 | 10 | for(var key in params) { 11 | if(params.hasOwnProperty(key)) { 12 | var hiddenField = document.createElement("input"); 13 | hiddenField.setAttribute("type", "hidden"); 14 | hiddenField.setAttribute("name", key); 15 | hiddenField.setAttribute("value", params[key]); 16 | 17 | form.appendChild(hiddenField); 18 | } 19 | } 20 | 21 | document.body.appendChild(form); 22 | form.submit(); 23 | } 24 | 25 | post("https://teams-buckets-issues.herokuapp.com/prioritized_issues", {url: location.href, return: 1}); 26 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/device-camera.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/models/prioritized_issue_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PrioritizedIssueTest < ActiveSupport::TestCase 4 | test "reorder issues in a bucket" do 5 | pi1 = prioritized_issues(:pi1) 6 | pi3 = prioritized_issues(:pi3) 7 | icebox = buckets(:icebox) 8 | 9 | pi1.change_position(2) 10 | assert_equal [pi3, pi1], PrioritizedIssue.bucket(icebox).all 11 | end 12 | 13 | test "move issue to different bucket and change priority" do 14 | pi1 = prioritized_issues(:pi1) 15 | pi2 = prioritized_issues(:pi2) 16 | backlog = buckets(:backlog) 17 | 18 | assert_equal "Icebox", pi1.bucket.name 19 | 20 | pi1.move_to_bucket backlog, :first 21 | 22 | assert_equal "Backlog", pi1.bucket.name 23 | assert_equal [pi1, pi2], PrioritizedIssue.bucket(backlog).all 24 | end 25 | 26 | test "#current_position returns position of issue in bucket" do 27 | assert_equal 1, prioritized_issues(:pi1).current_position 28 | assert_equal 2, prioritized_issues(:pi3).current_position 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/circuit-board.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/cloud-download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/cloud-upload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: bec4ba127922a757bde7f95399f57e9cc9963c2004028160f3383273c9c13940e98a3233bd8dd1e3841e31929b94f5272f371316c1f783d569d641a996b8f959 15 | 16 | test: 17 | secret_key_base: 5899f9f4067381c61078ddb7c18622cf502fad97c89a1512351634c3a23562d51c26153b38ef2df789c323be1a3c9d6eb6d088df7c95fcd69e60b93d8bf5f7ff 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mark-github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/services/application_service.rb: -------------------------------------------------------------------------------- 1 | # Services should inherit from ApplicationService in order to take advantage 2 | # of .for_user_and_team instantiation. 3 | class ApplicationService 4 | 5 | # Public: Create instance of ApplicationService for a User and a Team. 6 | # 7 | # user - User instance 8 | # team - Team instance 9 | # 10 | # Returns an ApplicationService or subclass instance. 11 | def self.for_user_and_team(user, team) 12 | new(user, team) 13 | end 14 | 15 | def initialize(user, team) 16 | @user = user 17 | @team = team 18 | end 19 | 20 | # Internal: The User this service will be acting for. 21 | # 22 | # Returns a User. 23 | attr_reader :user 24 | 25 | # Internal: The Team this service will be acting on. 26 | # 27 | # Returns a Team. 28 | attr_reader :team 29 | 30 | # Internal: The github client that the service will use to interact with 31 | # the GitHub API. 32 | # 33 | # Returns an Octokit::Client instance. 34 | def github_client 35 | @github_client ||= user.github_client 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/gift.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/team.rb: -------------------------------------------------------------------------------- 1 | class Team 2 | include ActiveModel::Conversion 3 | extend ActiveModel::Naming 4 | 5 | def initialize(params={}) 6 | @id = params[:id] 7 | @name = params[:name] 8 | @organization = params[:organization] ? params[:organization][:login] : nil 9 | @avatar_url = params[:organization] ? params[:organization][:avatar_url] : nil 10 | end 11 | 12 | attr_accessor :id, :name, :organization, :avatar_url, :members 13 | 14 | def to_param 15 | id.to_s 16 | end 17 | 18 | def buckets 19 | Bucket.by_team_id(id) 20 | end 21 | 22 | def issues 23 | PrioritizedIssue.bucket(buckets) 24 | end 25 | 26 | def ship_lists 27 | PrioritizedIssue.archives(buckets).map {|timestamp| ShipList.new(:timestamp => timestamp) } 28 | end 29 | 30 | def ship_list(timestamp) 31 | issues = PrioritizedIssue.archive(buckets, timestamp.to_time) 32 | ShipList.new(:timestamp => timestamp, :issues => issues) 33 | end 34 | 35 | def member?(user) 36 | !!members.detect {|member| user.login == member.login } 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/hourglass.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/teams.css.scss: -------------------------------------------------------------------------------- 1 | .team-container { 2 | padding-bottom: 100px 3 | } 4 | 5 | .team { 6 | border: 1px solid #08c; 7 | display: block; 8 | float: left; 9 | padding: 10px; 10 | text-align: left; 11 | width: 48%; 12 | border-radius: 3px; 13 | margin-right: 2%; 14 | margin-bottom: 15px; 15 | font-weight: bold; 16 | 17 | &:hover { 18 | background: #08c; 19 | color: #fff; 20 | text-decoration: none; 21 | } 22 | } 23 | 24 | .org { 25 | border-top: 1px solid #e0e0e0; 26 | 27 | &:nth-child(1), 28 | &:nth-child(2) { 29 | border-top: 0; 30 | } 31 | } 32 | 33 | .org-avatar { 34 | width: 48px; 35 | height: 48px; 36 | vertical-align: middle; 37 | margin-right: 10px; 38 | } 39 | 40 | .teams-link { 41 | .divider { 42 | padding: 0 5px; 43 | } 44 | .teams-link-organization, 45 | .teams-link-name { 46 | font-weight: bold; 47 | color: #333; 48 | text-transform: capitalize; 49 | } 50 | } 51 | 52 | .teams-link-change { 53 | margin-left: 10px; 54 | font-size: 10px; 55 | text-transform: uppercase; 56 | vertical-align: bottom; 57 | } 58 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/octoface.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jonathan Hoyt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path("../boot", __FILE__) 2 | 3 | require "rails/all" 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you"ve limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module Issues 10 | class Application < Rails::Application 11 | # Settings in config/environments/* take precedence over those specified here. 12 | # Application configuration should go into files in config/initializers 13 | # -- all .rb files in that directory are automatically loaded. 14 | 15 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 16 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 17 | # config.time_zone = "Central Time (US & Canada)" 18 | 19 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 20 | # config.i18n.load_path += Dir[Rails.root.join("my", "locales", "*.{rb,yml}").to_s] 21 | # config.i18n.default_locale = :de 22 | 23 | config.assets.precompile += %w(bookmarklet.js *.svg *.eot *.woff *.ttf) 24 | 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/mention.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/device-camera-video.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/telescope.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/scaffolds.css.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | color: #333; 4 | font-family: verdana, arial, helvetica, sans-serif; 5 | font-size: 13px; 6 | line-height: 18px; 7 | } 8 | 9 | p, ol, ul, td { 10 | font-family: verdana, arial, helvetica, sans-serif; 11 | font-size: 13px; 12 | line-height: 18px; 13 | } 14 | 15 | pre { 16 | background-color: #eee; 17 | padding: 10px; 18 | font-size: 11px; 19 | } 20 | 21 | a { 22 | color: #000; 23 | &:visited { 24 | color: #666; 25 | } 26 | &:hover { 27 | color: #fff; 28 | background-color: #000; 29 | } 30 | } 31 | 32 | div { 33 | &.field, &.actions { 34 | margin-bottom: 10px; 35 | } 36 | } 37 | 38 | #notice { 39 | color: green; 40 | } 41 | 42 | .field_with_errors { 43 | padding: 2px; 44 | background-color: red; 45 | display: table; 46 | } 47 | 48 | #error_explanation { 49 | width: 450px; 50 | border: 2px solid red; 51 | padding: 7px; 52 | padding-bottom: 0; 53 | margin-bottom: 20px; 54 | background-color: #f0f0f0; 55 | h2 { 56 | text-align: left; 57 | font-weight: bold; 58 | padding: 5px 5px 5px 15px; 59 | font-size: 12px; 60 | margin: -7px; 61 | margin-bottom: 0px; 62 | background-color: #c00; 63 | color: #fff; 64 | } 65 | ul li { 66 | font-size: 12px; 67 | list-style: square; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | resources :teams, :only => :index do 3 | get "/" => "buckets#index" 4 | post "/archive_closed_issues" => "teams#archive_closed_issues" 5 | get "/audit_log" => "audit_entries#index" 6 | 7 | resources :buckets, :only => [:new, :edit, :create, :update, :destroy] do 8 | resources :prioritized_issues, :only => [:create, :update, :destroy] do 9 | post :sync, :as => :sync 10 | patch "move" => "prioritized_issues#move_to_bucket" 11 | end 12 | end 13 | 14 | resources :ship_lists, :only => [:index, :show] 15 | resources :radars, :only => [:show] 16 | resources :import, :only => [:index, :create] 17 | end 18 | 19 | post "/prioritized_issues" => "prioritized_issues#bookmarklet_legacy" 20 | get "/prioritized_issues/new" => "prioritized_issues#new", :as => :new_prioritized_issue 21 | 22 | get "/user/set_team", :to => "user#set_team", :as => :set_team 23 | 24 | match "/auth/:service/callback" => "services#create", :via => %i(get post) 25 | match "/auth/failure" => "services#failure", :via => %i(get post) 26 | match "/logout" => "sessions#destroy", :via => %i(get delete), :as => :logout 27 | 28 | resources :services, :only => %i(create destroy) 29 | 30 | root :to => "sessions#new" 31 | end 32 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/dashboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def navbar_link_class(controller, actions) 3 | "active" if params[:controller] == controller.to_s && Array(actions).include?(params[:action].to_sym) 4 | end 5 | 6 | def github_issue_url(issue) 7 | "https://github.com/#{issue.owner}/#{issue.repository}/issues/#{issue.number}" 8 | end 9 | 10 | def github_issue_nwo_id(issue) 11 | "#{issue.owner}/#{issue.repository}##{issue.number}" 12 | end 13 | 14 | def github_user_url(issue) 15 | "https://github.com/#{issue.assignee}" 16 | end 17 | 18 | def github_repository_url(issue) 19 | "https://github.com/#{issue.owner}/#{issue.repository}" 20 | end 21 | 22 | def octicon(code) 23 | content_tag :span, '', :class => "octicon octicon-#{code.to_s.dasherize}" 24 | end 25 | 26 | def teams_link(team) 27 | text, css_class = if team.present? && team.name.present? 28 | string = octicon("jersey") 29 | string += content_tag :span, team.organization, :class => "teams-link-organization" 30 | string += content_tag :span, "/", :class => "divider" 31 | string += content_tag :span, team.name, :class => "teams-link-name" 32 | string += content_tag :span, "(change)", :class => "teams-link-change" 33 | [string, "teams-link"] 34 | else 35 | ["Teams", ""] 36 | end 37 | 38 | link_to text, teams_path, :class => css_class 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /app/models/bucket.rb: -------------------------------------------------------------------------------- 1 | class Bucket < ActiveRecord::Base 2 | include RankedModel 3 | 4 | # Public: Bucket name. 5 | # column :name 6 | # Returns a String. 7 | validates :name, :presence => true 8 | 9 | # Public: Has many issues. 10 | has_many :issues, :class_name => "PrioritizedIssue" 11 | 12 | # Public: Position of bucket. 13 | # column :row_order 14 | # Returns an Integer. 15 | validates :row_order, :presence => true 16 | ranks :row_order, :with_same => :team_id 17 | 18 | # Public: Change position of Bucket. 19 | # 20 | # position - Integer or symbol (:first, :last, :up, :down). 21 | def change_position(position) 22 | update_attribute :row_order_position, position 23 | end 24 | 25 | # Public: Get the current column position of the bucket. Columns start at 1 26 | # and go up. 27 | # 28 | # Returns an Integer >= 1. 29 | def current_position 30 | team.buckets.pluck(:row_order).index(row_order) + 1 31 | end 32 | 33 | # Public: Id of team on GitHub. 34 | # column :team_id 35 | # Returns an Integer. 36 | validates :team_id, :presence => true 37 | 38 | # Public: Team this bucket belongs to. 39 | # 40 | # Returns a Team. 41 | def team 42 | Team.new(:id => team_id) 43 | end 44 | 45 | # column :created_at 46 | # column :updated_at 47 | 48 | # Buckets by team id. 49 | scope :by_team_id, -> (team_id) { where(:team_id => team_id).rank(:row_order) } 50 | end 51 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= render :partial => "shared/head" %> 5 | <%= render :partial => "shared/scripts" %> 6 | 7 | 8 | 27 | 28 | 29 |
30 | <%= render 'layouts/messages' %> 31 | <%= yield %> 32 |
33 | 34 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/organization.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/buckets/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :header_nav do %> 2 | <%= render "navbar" %> 3 | <% end %> 4 | <% if Pusher.app_id.present? %> 5 |
6 | <% end %> 7 |
8 | <%= render :partial => "bucket", :collection => @buckets %> 9 |
10 | <% content_for :footer_nav do %> 11 | 29 | <% end %> 30 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations. 23 | config.active_record.migration_error = :page_load 24 | 25 | # Debug mode disables concatenation and preprocessing of assets. 26 | # This option may cause significant delays in view rendering with a large 27 | # number of complex assets. 28 | config.assets.debug = true 29 | 30 | # Adds additional error checking when serving assets at runtime. 31 | # Checks for improperly declared sprockets dependencies. 32 | # Raises helpful error messages. 33 | config.assets.raise_runtime_errors = true 34 | 35 | # Raises error for missing translations 36 | # config.action_view.raise_on_missing_translations = true 37 | end 38 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/plug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/models/issue.rb: -------------------------------------------------------------------------------- 1 | class Issue < ActiveRecord::Base 2 | # Public: Issue title. 3 | # column :title 4 | # Returns a String. 5 | 6 | # Public: Login for GitHub issue owner. 7 | # column :owner 8 | # Returns a String. 9 | 10 | # Public: GitHub repository name issue belongs to. 11 | # column :repository 12 | # Returns a String. 13 | 14 | # Public: Issue number for repository on GitHub. 15 | # column :number 16 | # Returns an Integer. 17 | 18 | # Public: Issue state. 19 | # column :state 20 | # Returns a String. 21 | enum :state => [:open, :closed] 22 | 23 | # Public: Has many prioritized issues. 24 | has_many :prioritized_issues, :dependent => :destroy 25 | 26 | # Public: Login of assignee. 27 | # column :assignee 28 | # Returns a String. 29 | 30 | # Public: Labels for issue. 31 | # column :labels 32 | serialize :labels, Array 33 | # Stop gap to get onto Rails 4.2. Will be replaced with type casting in 34 | # Rails 5: http://edgeapi.rubyonrails.org/classes/ActiveModel/Type/Value.html 35 | def labels 36 | labels = super 37 | 38 | if labels.is_a? String 39 | JSON.parse(labels) 40 | else 41 | labels 42 | end 43 | end 44 | 45 | # column :created_at 46 | # column :updated_at 47 | 48 | # Public: Set assignee. 49 | # 50 | # assignee - String users GitHub login. 51 | def assignee=(assignee) 52 | write_attribute :assignee, assignee.present? ? assignee : nil 53 | end 54 | 55 | # Public: Find issue by owner, repository, and number. 56 | scope :by_owner_repo_number, -> (owner, repository, number) { 57 | where(:owner => owner, :repository => repository, :number => number) 58 | } 59 | end 60 | -------------------------------------------------------------------------------- /app/views/shared/_head.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= content_for?(:title) ? yield(:title) : "Issues" %> 5 | <%= csrf_meta_tags %> 6 | 7 | 8 | 11 | 12 | <%= stylesheet_link_tag "application", :media => "all" %> 13 | 14 | 15 | 16 | <%= favicon_link_tag 'apple-touch-icon-144x144-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '144x144' %> 17 | 18 | 19 | 20 | <%= favicon_link_tag 'apple-touch-icon-114x114-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '114x114' %> 21 | 22 | 23 | 24 | <%= favicon_link_tag 'apple-touch-icon-72x72-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '72x72' %> 25 | 26 | 27 | 28 | <%= favicon_link_tag 'apple-touch-icon-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png' %> 29 | 30 | 31 | 32 | <%= favicon_link_tag 'favicon.ico', :rel => 'shortcut icon' %> 33 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /app/controllers/buckets_controller.rb: -------------------------------------------------------------------------------- 1 | class BucketsController < ApplicationController 2 | before_filter :authorize_read_team! 3 | before_filter :authorize_write_team!, :only => [:new, :create, :edit, :update, :destroy] 4 | after_filter :notify_team_subscribers, :only => [:create, :update, :destroy] 5 | 6 | def index 7 | if team.buckets.any? 8 | @buckets = team.buckets 9 | @columns = 12 / (@buckets.length > 0 ? @buckets.length : 1) 10 | @assignees = team_members.map &:login 11 | else 12 | redirect_to new_team_bucket_path(team) 13 | end 14 | end 15 | 16 | def new 17 | @bucket = Bucket.new 18 | end 19 | 20 | def edit 21 | @bucket = bucket_service.for_bucket_by_id(params[:id]).bucket 22 | end 23 | 24 | def create 25 | bucket_service.create_bucket_with_params(bucket_params) 26 | 27 | redirect_to team_path(team), :notice => "Bucket was successfully created." 28 | end 29 | 30 | def update 31 | bucket_service. 32 | for_bucket_by_id(params[:id]). 33 | update_bucket_with_params(bucket_params) 34 | 35 | respond_to do |format| 36 | format.json { render :json => bucket_service.bucket } 37 | format.html { redirect_to team_path(team) } 38 | end 39 | end 40 | 41 | def destroy 42 | bucket_service.for_bucket_by_id(params[:id]).move_issues_and_remove_bucket 43 | 44 | redirect_to team_path(team), :notice => "Bucket was successfully destroyed." 45 | end 46 | 47 | private 48 | # Only allow a trusted parameter "white list" through. 49 | def bucket_params 50 | params.require(:bucket).permit(:name, :row_order_position) 51 | end 52 | 53 | def bucket_service 54 | @bucket_service ||= \ 55 | BucketService.for_user_and_team(current_user, team) 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/bug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/buckets/_issue.html.erb: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static asset server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = "public, max-age=3600" 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Print deprecation notices to the stderr. 35 | config.active_support.deprecation = :stderr 36 | 37 | # Raises error for missing translations 38 | # config.action_view.raise_on_missing_translations = true 39 | 40 | # Middleware to make integration testing easier. Let's you set the session 41 | # programmatically. 42 | config.middleware.use RackSessionAccess::Middleware 43 | 44 | config.active_support.test_order = :random 45 | end 46 | -------------------------------------------------------------------------------- /test/fixtures/vcr_cassettes/test__from_issue_does_not_update_issue_when_github_returns_304_not_modified.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.github.com/repos/jonmagic/scriptular/issues/10 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Accept: 11 | - application/vnd.github.v3+json 12 | User-Agent: 13 | - Octokit Ruby Gem 3.1.0 14 | Authorization: 15 | - token fake_access_token 16 | If-Modified-Since: 17 | - Sun, 17 Jan 2016 08:00:00 GMT 18 | Accept-Encoding: 19 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 20 | response: 21 | status: 22 | code: 304 23 | message: Not Modified 24 | headers: 25 | Server: 26 | - GitHub.com 27 | Date: 28 | - Fri, 29 Jan 2016 19:00:48 GMT 29 | Status: 30 | - 304 Not Modified 31 | X-Ratelimit-Limit: 32 | - '5000' 33 | X-Ratelimit-Remaining: 34 | - '4946' 35 | X-Ratelimit-Reset: 36 | - '1454097001' 37 | Cache-Control: 38 | - private, max-age=60, s-maxage=60 39 | Last-Modified: 40 | - Fri, 15 Jan 2016 10:16:22 GMT 41 | Access-Control-Allow-Credentials: 42 | - 'true' 43 | Access-Control-Expose-Headers: 44 | - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, 45 | X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval 46 | Access-Control-Allow-Origin: 47 | - "*" 48 | Content-Security-Policy: 49 | - default-src 'none' 50 | Strict-Transport-Security: 51 | - max-age=31536000; includeSubdomains; preload 52 | X-Content-Type-Options: 53 | - nosniff 54 | X-Frame-Options: 55 | - deny 56 | X-Xss-Protection: 57 | - 1; mode=block 58 | Vary: 59 | - Accept-Encoding 60 | X-Served-By: 61 | - a241e1a8264a6ace03db946c85b92db3 62 | X-Github-Request-Id: 63 | - 04358526:14F4A:25C996F:56ABB6E0 64 | body: 65 | encoding: UTF-8 66 | string: '' 67 | http_version: 68 | recorded_at: Fri, 29 Jan 2016 19:00:48 GMT 69 | recorded_with: VCR 2.9.2 70 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/radio-tower.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vendor/assets/bower_components/octicons/svg/globe.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery :with => :exception 3 | 4 | before_filter :authenticate_user! 5 | 6 | helper_method :logged_in? 7 | helper_method :current_user 8 | helper_method :current_service 9 | helper_method :pusher_channel 10 | 11 | rescue_from "Octokit::NotFound" do |exception| 12 | redirect_to root_path 13 | end 14 | 15 | protected 16 | def current_user 17 | @current_user ||= begin 18 | if session.has_key?(:user_id) 19 | user = User.find(session[:user_id]) 20 | user.github_client = Octokit::Client.new(:access_token => session[:oauth_token]) 21 | user 22 | end 23 | end 24 | rescue ActiveRecord::RecordNotFound 25 | session[:user_id] = nil 26 | end 27 | 28 | def current_service 29 | if session.has_key?(:service_id) 30 | @current_service ||= Service.where(user_id: session[:user_id], id: session[:service_id]).first 31 | end 32 | rescue ActiveRecord::RecordNotFound 33 | session[:service_id] = nil 34 | end 35 | 36 | def current_user? 37 | !!current_user 38 | end 39 | 40 | def logged_in? 41 | current_user? 42 | end 43 | 44 | def authenticate_user! 45 | if session.has_key?(:user_id) 46 | current_user 47 | else 48 | session[:redirect_to] = request.path 49 | redirect_to root_path 50 | end 51 | end 52 | 53 | def logout! 54 | @current_user = nil 55 | reset_session 56 | end 57 | 58 | def team_members 59 | @team_members ||= begin 60 | current_user. 61 | github_client. 62 | team_members(params[:team_id]). 63 | map {|attributes| TeamMember.new(attributes) } 64 | end 65 | end 66 | 67 | def team 68 | @team ||= begin 69 | team = Team.new(current_user.github_client.team(params[:team_id])) 70 | team.members = team_members 71 | team 72 | end 73 | end 74 | 75 | def authorize_read_team! 76 | unless team 77 | redirect_to teams_path 78 | end 79 | end 80 | 81 | def authorize_write_team! 82 | unless team.member?(current_user) 83 | redirect_to team_path(team) 84 | end 85 | end 86 | 87 | def pusher_channel 88 | "team.#{team.id}" 89 | end 90 | 91 | def notify_team_subscribers 92 | return if Pusher.app_id.blank? 93 | 94 | Pusher[pusher_channel].trigger('update', params.merge(:user_id => current_user.id)) 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /test/models/audit_entry_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AuditEntryTest < ActiveSupport::TestCase 4 | test "#team returns team with team_id" do 5 | entry = AuditEntry.new(:team_id => 1) 6 | 7 | assert_equal 1, entry.team.id 8 | end 9 | 10 | test "#team= sets team_id and team_name" do 11 | team = Team.new(:id => 1, :name => "foo") 12 | entry = AuditEntry.new 13 | entry.team = team 14 | 15 | assert_equal 1, entry.team_id 16 | assert_equal "foo", entry.team_name 17 | end 18 | 19 | test "#user= sets user_id and user_login" do 20 | user = users(:jonmagic) 21 | entry = AuditEntry.new 22 | entry.user = user 23 | 24 | assert_equal user.id, entry.user_id 25 | assert_equal "jonmagic", entry.user_login 26 | end 27 | 28 | test "#action= does not allow unknown action" do 29 | entry = AuditEntry.new 30 | assert_raises(ArgumentError) { entry.action = :foo } 31 | end 32 | 33 | test "#issue_before_action sets a myriad of attributes" do 34 | pi = prioritized_issues(:pi1) 35 | entry = AuditEntry.new 36 | entry.issue_before_action = pi 37 | 38 | assert_equal pi.issue.id, entry.issue_id 39 | assert_equal pi.issue.title, entry.issue_title 40 | assert_equal pi.id, entry.prioritized_issue_id 41 | assert_equal 1, entry.issue_start_position 42 | assert_equal pi.bucket.id, entry.source_bucket_id 43 | assert_equal pi.bucket.name, entry.source_bucket_name 44 | end 45 | 46 | test "#issue_after_action sets a few attributes" do 47 | pi = prioritized_issues(:pi1) 48 | entry = AuditEntry.new 49 | entry.issue_after_action = pi 50 | 51 | assert_equal 1, entry.issue_end_position 52 | assert_equal pi.bucket.id, entry.target_bucket_id 53 | assert_equal pi.bucket.name, entry.target_bucket_name 54 | end 55 | 56 | test "#bucket_before_action= sets source bucket attributes" do 57 | bucket = buckets(:current) 58 | entry = AuditEntry.new 59 | entry.bucket_before_action = bucket 60 | 61 | assert_equal bucket.id, entry.source_bucket_id 62 | assert_equal bucket.name, entry.source_bucket_name 63 | assert_equal 1, entry.bucket_start_position 64 | end 65 | 66 | test "#bucket_after_action= sets target bucket attributes" do 67 | bucket = buckets(:current) 68 | entry = AuditEntry.new 69 | entry.bucket_after_action = bucket 70 | 71 | assert_equal bucket.id, entry.target_bucket_id 72 | assert_equal bucket.name, entry.target_bucket_name 73 | assert_equal 1, entry.bucket_end_position 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /app/controllers/services_controller.rb: -------------------------------------------------------------------------------- 1 | class ServicesController < ApplicationController 2 | skip_before_filter :authenticate_user!, :only => [:create, :failure] 3 | 4 | def create 5 | current_service = Service.where(:provider => omnihash[:provider], :uid => omnihash[:uid]).first 6 | 7 | if logged_in? 8 | if current_service 9 | flash[:notice] = I18n.t("notifications.provider_already_connected", :provider => omnihash[:provider]) 10 | else 11 | current_user.services.create!({ 12 | provider: omnihash[:provider], 13 | uid: omnihash[:uid] 14 | }) 15 | 16 | flash[:notice] = I18n.t("notifications.provider_added", :provider => omnihash[:provider]) 17 | end 18 | else 19 | if current_service 20 | session[:user_id] = current_service.user.id 21 | session[:service_id] = current_service.id 22 | session[:oauth_token] = omnihash[:credentials][:token] 23 | else 24 | user = User.where(:login => omnihash[:info][:nickname]).first_or_initialize 25 | user.email = omnihash[:info][:email] 26 | user_service = user.services.build({ 27 | :provider => omnihash[:provider], 28 | :uid => omnihash[:uid] 29 | }) 30 | 31 | if user.save! 32 | session[:user_id] = user.id 33 | session[:service_id] = user_service.id 34 | session[:oauth_token] = omnihash[:credentials][:token] 35 | 36 | flash[:notice] = I18n.t("notifications.account_created") 37 | end 38 | end 39 | end 40 | 41 | if path = session[:redirect_to] 42 | session[:redirect_to] = nil 43 | redirect_to path 44 | elsif current_user.team_id.present? 45 | redirect_to team_path(current_user.team) 46 | else 47 | redirect_to teams_path 48 | end 49 | end 50 | 51 | def destroy 52 | service = current_user.services.find(params[:id]) 53 | if service.respond_to?(:destroy) and service.destroy 54 | flash[:notice] = I18n.t("notifications.provider_unlinked", :provider => service.provider) 55 | redirect_to root_url 56 | end 57 | end 58 | 59 | def failure 60 | flash[:error] = I18n.t("notifications.authentication_error") 61 | redirect_to root_url 62 | end 63 | 64 | private 65 | def omnihash 66 | request.env["omniauth.auth"] 67 | end 68 | 69 | def omniauth_providers 70 | (OmniAuth::Strategies.local_constants.map(&:downcase) - %i(developer oauth oauth2)).map(&:to_s) 71 | end 72 | end 73 | --------------------------------------------------------------------------------