Skip to content

Commit

Permalink
Merge branch 'master' of github.com:octobox/octobox into ca/master/gi…
Browse files Browse the repository at this point in the history
…thub-client-refactors-for-pat

* 'master' of github.com:octobox/octobox: (27 commits)
  Uncheck all selected notifications after "Mark as Read" is done (octobox#1293)
  Remove some console.logs from search suggestions js (octobox#1291)
  Add a linked button to reply on GitHub to bottom of threads (octobox#1288)
  remove redundant .subject-link class (octobox#1292)
  Fix javascript error when opening external subject links (octobox#1290)
  Turn off autocomplete on all checkboxes (octobox#1289)
  Allow deleting notifications from search results (octobox#1287)
  Bump simple_form from 4.0.1 to 4.1.0 (octobox#1286)
  Disambiguate 'installing' from 'signing in' (octobox#1280)
  Only attempt to sync users who have an access token (octobox#1283)
  Involved users should always be ones that haven't been recently synced (octobox#1282)
  Skip enqueuing repository sync tasks if repo exists (octobox#1281)
  Skip syncing the repository if it's already present (octobox#1279)
  Use update rather than update_attributes when saving existing repos (octobox#1278)
  Add initial action_cable setup (octobox#1080)
  Enable momentum scrolling in thread view on iOS (octobox#1274)
  Always expand the last comment in a thread (octobox#1272)
  Show a spinner when loading a thread view (octobox#1271)
  Order comments from oldest to newest (octobox#1270)
  Order comments by date rather than ID (octobox#1269)
  ...

# Conflicts:
#	app/models/subject.rb
  • Loading branch information
coreyja committed Nov 24, 2018
2 parents 9a60825 + c749c26 commit fa4ee98
Show file tree
Hide file tree
Showing 42 changed files with 319 additions and 143 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
language: ruby
sudo: false
rvm:
- 2.5.3

Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.5)
sidekiq (>= 4.0, < 6.0)
thor (~> 0)
simple_form (4.0.1)
simple_form (4.1.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
simplecov (0.16.1)
Expand Down
Binary file added app/assets/images/notification-basic.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/notification-enhanced.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ $(document).on('click', '.toggle-star', function() {
Octobox.toggleStarClick($(this))
});

$(document).on('click', '.subject-link', Octobox.viewThread);
$(document).on('click', '.thread-link', Octobox.viewThread);
13 changes: 13 additions & 0 deletions app/assets/javascripts/cable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//
//= require action_cable
//= require_self
//= require_tree ./channels

(function() {
this.App || (this.App = {});

App.cable = ActionCable.createConsumer();

}).call(this);
16 changes: 16 additions & 0 deletions app/assets/javascripts/channels/sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
$(document).on("turbolinks:load", function () {
if ($("meta[name='push_notifications']").length >0) {
App.sync = App.cable.subscriptions.create("NotificationsChannel", {
received: function(data) {
if($(data.id).length) {
var selected = $(data.id).has("input:checked");

$(data.id)[0].outerHTML = data.html;
if (selected.length) {
$(data.id).find("input[type=checkbox]").prop('checked', true);
}
}
}
});
}
});
65 changes: 54 additions & 11 deletions app/assets/javascripts/octobox.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ var Octobox = (function() {
getDisplayedRows().find("input").prop("checked", checked).trigger("change");
};

var uncheckAll = function () {
$(".js-select_all").prop("checked", false);
checkAll();
}

var muteThread = function() {
var id = $('#notification-thread').data('id');
mute(id);
Expand All @@ -145,9 +150,14 @@ var Octobox = (function() {
var mute = function(ids){
var result = confirm("Are you sure you want to mute?");
if (result) {
$.post( "/notifications/mute_selected" + location.search, { "id[]": ids}).done(function() {
$.post( "/notifications/mute_selected" + location.search, { "id[]": ids})
.done(function() {
resetCursorAfterRowsRemoved(ids);
updateFavicon();
})
.fail(function(){
$(".header-flash-messages").empty();
notify("Could not mute notification(s)", "danger");
});
}
};
Expand All @@ -156,12 +166,17 @@ var Octobox = (function() {
if (getDisplayedRows().length === 0) return;
var rows = getMarkedOrCurrentRows();
rows.addClass("blur-action");
$.post("/notifications/mark_read_selected" + location.search, {"id[]": getIdsFromRows(rows)}).done(function () {
$.post("/notifications/mark_read_selected" + location.search, {"id[]": getIdsFromRows(rows)})
.done(function () {
rows.removeClass("blur-action");
rows.removeClass("active");
rows.find("input[type=checkbox]").prop('checked', false);
uncheckAll();
updateFavicon();
})
.fail(function(){
$(".header-flash-messages").empty();
notify("Could not mark notification(s) read", "danger");
});
};

var toggleArchive = function() {
Expand Down Expand Up @@ -195,9 +210,14 @@ var Octobox = (function() {
}

var archive = function(ids, value){
$.post( "/notifications/archive_selected" + location.search, { "id[]": ids, "value": value } ).done(function() {
$.post( "/notifications/archive_selected" + location.search, { "id[]": ids, "value": value } )
.done(function() {
resetCursorAfterRowsRemoved(ids);
updateFavicon();
})
.fail(function(){
$(".header-flash-messages").empty();
notify("Could not archive notification(s)", "danger");
});
}

Expand Down Expand Up @@ -283,10 +303,14 @@ var Octobox = (function() {
};

var star = function(id){
console.log(id);
$('#notification-thread').data('id') == id ? $('#thread').find('.toggle-star').toggleClass("star-active star-inactive") : null;
$("#notification-"+id).find(".toggle-star").toggleClass("star-active star-inactive");
$.post("/notifications/"+id+"/star")
.fail(function(){
$('#notification-thread').data('id') == id ? $('#thread').find('.toggle-star').toggleClass("star-active star-inactive") : null;
$("#notification-"+id).find(".toggle-star").toggleClass("star-active star-inactive");
notify("Could not toggle star(s)", "danger");
});
};

var changeArchive = function() {
Expand Down Expand Up @@ -337,8 +361,13 @@ var Octobox = (function() {
};

function markRead(id) {
$.post( "/notifications/"+id+"/mark_read").done(function() {
$.post( "/notifications/"+id+"/mark_read")
.done(function() {
updateFavicon();
})
.fail(function(){
$(".header-flash-messages").empty();
notify("Could not mark notification(s) read", "danger");
});
$("#notification-"+id).removeClass("active");
};
Expand All @@ -362,6 +391,9 @@ var Octobox = (function() {

window.onpopstate = function(event) {
if(event.state.thread){

$('#thread').html($('#loading').html())

$.get(event.state.thread, function(data){
$('#thread').html(data)
});
Expand All @@ -372,9 +404,14 @@ var Octobox = (function() {
var deleteNotifications = function(ids){
var result = confirm("Are you sure you want to delete?");
if (result) {
$.post("/notifications/delete_selected" + location.search, {"id[]": ids}).done(function() {
$.post("/notifications/delete_selected" + location.search, {"id[]": ids})
.done(function() {
resetCursorAfterRowsRemoved(ids);
updateFavicon();
})
.fail(function(){
$(".header-flash-messages").empty();
notify("Could not delete notification", "danger");
});
}
}
Expand All @@ -394,6 +431,9 @@ var Octobox = (function() {

var viewThread = function() {
history.pushState({thread: $(this).attr('href')}, 'Octobox', $(this).attr('href'))

$('#thread').html($('#loading').html())

$.get($(this).attr('href'), function(data){
if (data["error"] != null) {
$(".header-flash-messages").empty();
Expand Down Expand Up @@ -474,13 +514,16 @@ var Octobox = (function() {
};

var notify = function(message, type) {
$(".header-flash-messages").remove();
var alert_html = [
"<div class='alert alert-" + type + " fade show'>",
" <button class='close' data-dismiss='alert'>x</button>",
message,
"<div class='flex-header header-flash-messages'>",
" <div class='alert alert-" + type + " fade show'>",
" <button class='close' data-dismiss='alert'>x</button>",
message,
" </div>",
"</div>"
].join("\n");
$(".header-flash-messages").append(alert_html);
$(".flex-header").after(alert_html);
};

var autoSync = function() {
Expand Down
18 changes: 0 additions & 18 deletions app/assets/javascripts/search_suggestion.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,16 @@ SearchSuggestion = {
// Let us open our database
var dbOpenRequest = window.indexedDB.open("SearchSuggestionList", 2);

// these two event handlers act on the database being opened successfully, or not
dbOpenRequest.onerror = function(event) {
console.log("Error loading database.");
};

dbOpenRequest.onsuccess = function(event) {
console.log('Database Loaded successfully');
db = dbOpenRequest.result;
};

dbOpenRequest.onupgradeneeded = function(event) {
var db = event.target.result;

db.onerror = function(event) {
console.log('Error loading database');
};

// Create an objectStore for this database
var objectStore = db.createObjectStore("SearchSuggestionList", { keyPath: "queryString" });
objectStore.createIndex("timestamp", "timestamp", { unique: false });
console.log("Object store created.");
}
},

Expand Down Expand Up @@ -111,9 +100,6 @@ SearchSuggestion = {
}
// open a read/write db transaction, ready for adding the data
var transaction = db.transaction(["SearchSuggestionList"], "readwrite");
transaction.onerror = function() {
console.log('Transaction not opened due to error: ' + transaction.error);
};

// call an object store that's already been added to the database
var objectStore = transaction.objectStore("SearchSuggestionList");
Expand All @@ -130,9 +116,6 @@ SearchSuggestion = {
}
// Make a request to add our newItem object to the object store
var objectStoreRequest = objectStore.add({queryString: searchQuery, timestamp: SearchSuggestion.getTimestamp()});
objectStoreRequest.onsuccess = function(event) {
console.log('Search Suggestion to Added IndexedDB :: ' + searchQuery);
};
}
}
},
Expand All @@ -151,7 +134,6 @@ SearchSuggestion = {
// report that the data item has been deleted
transaction.oncomplete = function() {
SearchSuggestion.displaySearchSuggestions();
console.log('Search Suggestion deleted.')
};
},

Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/_application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,9 @@
.blur-action {
opacity: .5;
}

@include media-breakpoint-down(lg){
.not-a-nav{
background-color: $body-bg;
}
}
4 changes: 1 addition & 3 deletions app/assets/stylesheets/_layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,11 @@ body {

.container{
padding: 0 1rem;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}

.flex-main{
.flex-main, .flex-thread{
height: 100%;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}

Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/_notifications.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ $notification-items: (
.table-notifications {
td{
padding: 0.6rem;
&.notification-archived, .notification-repo{
padding: 0;
svg, small{
margin: 0.6rem;
}
}
}
.active {
font-weight: bold;
Expand Down
4 changes: 4 additions & 0 deletions app/channels/application_cable/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end
19 changes: 19 additions & 0 deletions app/channels/application_cable/connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user

def connect
self.current_user = find_verified_user
end

private

def find_verified_user
if current_user = User.find_by(id: cookies.permanent.signed[:user_id])
current_user
else
reject_unauthorized_connection
end
end
end
end
9 changes: 9 additions & 0 deletions app/channels/notifications_channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class NotificationsChannel < ApplicationCable::Channel
def subscribed
stream_from "notifications:#{current_user.id}"
end

def unsubscribed
stop_all_streams
end
end
2 changes: 2 additions & 0 deletions app/controllers/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ def show
@previous = ids[position-1] unless position-1 < 0
@next = ids[position+1] unless position+1 > ids.length

@comments = @notification.subject.comments.order('created_at ASC')

render partial: "notifications/thread", layout: false if request.xhr?
end

Expand Down
9 changes: 7 additions & 2 deletions app/helpers/notifications_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,15 @@ def no_url_filter_parameters_present
notification_param_keys.all?{|param| params[param].blank? }
end

def notification_icon(subject_type, state = nil)
state = nil unless display_subject?
def notification_icon(notification)
subject_type = notification.subject_type
state = notification.user.github_app_authorized? ? notification.state : nil
return 'issue-closed' if subject_type == 'Issue' && state == 'closed'
return 'git-merge' if subject_type == 'PullRequest' && state == 'merged'
subject_type_icon(subject_type)
end

def subject_type_icon(subject_type)
SUBJECT_TYPES[subject_type]
end

Expand Down
4 changes: 4 additions & 0 deletions app/models/comment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ def author_url_path
def bot_author?
BOT_AUTHOR_REGEX.match?(author)
end

def unread?(notification)
notification.last_read_at && DateTime.parse(notification.last_read_at) < created_at
end
end
15 changes: 15 additions & 0 deletions app/models/notification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def self.search_by_subject_title(title)
validates :subject_url, presence: true
validates :archived, inclusion: [true, false]

after_update :push_if_changed

paginates_per 20

class << self
Expand Down Expand Up @@ -174,4 +176,17 @@ def subject_number
def display_thread?
Octobox.include_comments? && subjectable? && subject.present? && user.display_comments?
end

def push_if_changed
push_to_channel if (saved_changes.keys & pushable_fields).any?
end

def pushable_fields
['archived', 'reason', 'subject_title', 'subject_url', 'subject_type', 'unread']
end

def push_to_channel
string = ApplicationController.render(partial: 'notifications/notification', locals: { notification: self})
ActionCable.server.broadcast "notifications:#{user_id}", { id: "#notification-#{id}", html: string }
end
end

0 comments on commit fa4ee98

Please sign in to comment.