Skip to content

Commit

Permalink
Turn off notifications for posts' reactions
Browse files Browse the repository at this point in the history
Fix for missing post_reaction_notifications on organizations

Allow full links for cache buster tool (#3378)

Rescue possible SSLError when fetching a podcast (#3374)

Add functionality to remove and recover identity (#3377)

* Lint some quotation marks

* Add BackupData table

* Add identity and removal functionality

* Test additional functionality

* Remove dependent destroy for backup data

* Add auth_data_dump column

* Add challenge to reserved words

* Add more shoulda matchers

Self-serve sponsorship options (#3371)

* WIP - Initial work on sponsorship landing page

* Add initial partnership page

Remove notifications if article is unpublished (#3362)

* Add tests for article notifications

* Remove notifications if unpublished and refactor

Moved creating a new podcast to a separate ActiveJob #2952 (#3373)

* Podcasts reachable status #2952

* Specs for podcasts statuses

* Moved podcast episode create to a separate ActiveJob

* Use RssItemData wrapper in GetEpisode for consistency

* Reorganize services/podcasts

Escape comment.title to fix failing spec (#3385)
  • Loading branch information
nicolas-amabile committed Jul 7, 2019
1 parent 04ce773 commit 48ade8e
Show file tree
Hide file tree
Showing 69 changed files with 5,083 additions and 83 deletions.
17 changes: 17 additions & 0 deletions app/assets/stylesheets/articles.scss
Expand Up @@ -1121,6 +1121,23 @@
}
}
}
.sidebar-sponsorship-level {
text-align: center;
font-weight: bold;
width: calc(100% - 6px);
padding: 26px 0px;
border-radius: 3px;
margin-bottom: 10px;
font-family: $helvetica-condensed;
font-stretch: condensed;
font-size: 1.1em;
@include themeable(
border,
theme-container-border,
1px solid $outline-color
);
@include themeable(box-shadow, theme-container-box-shadow, $bold-shadow);
}
.widget {
width: calc(100% - 30px);
padding: 10px 12px;
Expand Down
192 changes: 192 additions & 0 deletions app/assets/stylesheets/partnerships.scss
@@ -0,0 +1,192 @@
@import 'variables';
@import 'mixins';

.partnerships-container {
width: 800px;
max-width: 96%;
margin: 100px auto;
&.partnerships-container-show {
h1 {
text-align: left;
}
}
h1 {
text-align: center;
font-size: 2.5em;
padding: 1em 0;
img {
height: 2.2em;
width: 2.2em;
transform: rotate(6deg);
border-radius: 0.2em;
vertical-align: -0.7em;
margin-left: 0.3em;
}
}
.partner-credits-explainer {
@include themeable(
background,
theme-container-background,
$white
);
box-sizing: border-box;
padding: 25px 20px 30px;
border-radius: 12px;
margin: 50px auto 40px;
width: calc(100% - 20px);
@include themeable(
border,
theme-border,
1px solid $light-medium-gray
);
@include themeable(
box-shadow,
theme-container-box-shadow,
2px 2px 8px darken($light-medium-gray, 5%)
);
.partner-explainer-notice {
padding: 15px;
margin: 25px 0px 12px;
border-radius: 3px;
font-weight: bold;
@include themeable(
background,
theme-container-accent-background,
$light-gray
);
}
h4 {
font-size: 0.8em;
margin: 3px 0px;
@include themeable(
color,
theme-secondary-color,
$medium-gray
);
}
h3 {
margin: 5px 0px;
font-size: 1.8em;
@include themeable(
color,
theme-color,
#131a38
);
img {
height: 1.2em;
width: 1.2em;
vertical-align: -0.25em;
border-radius: 100px;
margin-right: 0.3em;
}
}
select {
display: block;
font-size: 1.3em;
}
textarea {
width: 80%;
font-size: 1em;
padding: 0.5em;
border-radius: 3px;
display: block;
height: 300px;
@include themeable(
border,
theme-container-border,
1px solid $light-medium-gray
);
}
input {
width: 50%;
font-size: 1.3em;
padding: 0.5em;
border-radius: 3px;
display: block;
@include themeable(
border,
theme-container-border,
1px solid $light-medium-gray
);
}
a, button {
padding: 5px 20px;
font-size: 1.5em;
border-radius: 8px;
font-weight: bold;
margin: 8px 0px;
display: inline-block;
border: 0px;
@include themeable(
background,
theme-anchor-color,
$bold-blue
);
@include themeable(
color,
theme-container-background,
white
);
}
}
.partnership-options {
margin: 40px 0px;
}
.partnership-option-card {
@include themeable(
background,
theme-container-background,
$white
);
text-align: left;
width: 100%;
@media screen and ( min-width: 820px ){
width: calc(50% - 15px);
margin-right: 8px;
ul {
height: 220px;
}
}
box-sizing: border-box;
padding: 15px;
border-radius: 12px;
margin: 10px 0px;
display: inline-block;
@include themeable(
border,
theme-border,
1px solid $light-medium-gray
);
@include themeable(
box-shadow,
theme-container-box-shadow,
2px 2px 8px darken($light-medium-gray, 5%)
);
li {
padding: 8px 0px;
}
h2 {
margin: 0px;
padding: 10px 0px;
border-bottom: 2px solid rgba(0,0,0,0.1);
}
.partnership-option-cta {
display: block;
font-size: 1.6em;
padding: 20px 0px;
text-align: center;
border-radius: 5px;
font-weight: bold;
@include themeable(
background,
theme-anchor-color,
$bold-blue
);
@include themeable(
color,
theme-container-background,
white
);
}
}
}
12 changes: 10 additions & 2 deletions app/controllers/articles_controller.rb
Expand Up @@ -141,9 +141,8 @@ def update
else
@article.edited_at
end

updated = @article.update(article_params_json.merge(edited_at: edited_at_date))
Notification.send_to_followers(@article, "Published") if updated && @article.published && @article.saved_changes["published_at"]&.include?(nil)
handle_notifications(updated)

respond_to do |format|
format.html do
Expand Down Expand Up @@ -268,6 +267,15 @@ def article_params_json
params.require(:article).permit(allowed_params)
end

def handle_notifications(updated)
if updated && @article.published && @article.saved_changes["published"] == [false, true]
Notification.send_to_followers(@article, "Published")
elsif @article.saved_changes["published"] == [true, false]
Notification.remove_all_without_delay(notifiable_id: @article.id, notifiable_type: "Article", action: "Published")
Notification.remove_all(notifiable_id: @article.id, notifiable_type: "Article", action: "Reaction")
end
end

def redirect_after_creation
@article.decorate
if @article.persisted?
Expand Down
1 change: 1 addition & 0 deletions app/controllers/internal/tools_controller.rb
Expand Up @@ -29,6 +29,7 @@ def handle_article_cache

def bust_link(link)
cb = CacheBuster.new
link.sub!("https://dev.to", "") if link.starts_with?("https://dev.to")
cb.bust(link)
cb.bust(link + "/")
cb.bust(link + "?i=i")
Expand Down
28 changes: 27 additions & 1 deletion app/controllers/internal/users_controller.rb
Expand Up @@ -75,6 +75,32 @@ def merge
redirect_to "/internal/users/#{@user.id}/edit"
end

def remove_identity
identity = Identity.find(user_params[:identity_id])
@user = identity.user
begin
BackupData.backup!(identity)
identity.delete
@user.update("#{identity.provider}_username" => nil)
flash[:success] = "The #{identity.provider.capitalize} identity was successfully deleted and backed up."
rescue StandardError => e
flash[:error] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end

def recover_identity
backup = BackupData.find(user_params[:backup_data_id])
@user = backup.instance_user
begin
identity = backup.recover!
flash[:success] = "The #{identity.provider} identity was successfully recovered, and the backup was removed."
rescue StandardError => e
flash[:error] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end

private

def manage_credits
Expand Down Expand Up @@ -121,7 +147,7 @@ def user_params
new_note note_for_current_role user_status
pro merge_user_id add_credits remove_credits
add_org_credits remove_org_credits ghostify
organization_id
organization_id identity_id backup_data_id
]
params.require(:user).permit(allowed_params)
end
Expand Down
104 changes: 104 additions & 0 deletions app/controllers/partnerships_controller.rb
@@ -0,0 +1,104 @@
class PartnershipsController < ApplicationController
before_action :set_cache_control_headers, only: %i[index]
before_action :authenticate_user!, only: %i[create]
after_action :verify_authorized

def index
skip_authorization
set_surrogate_key_header "partnership-index"
end

def show
skip_authorization
end

def create
@level = params[:sponsorship_level]
@number_of_credits_needed = credits_for_level
@organization = Organization.find(params[:organization_id])
update_sponsorship_instructions
authorize @organization, :admin_of_org?
@available_org_credits = @organization.credits.where(spent: false)
if @level == "tag"
@tag = Tag.find_by(name: params[:tag_name])
@tag.sponsor_organization_id = @organization.id
slackbot_ping("@#{current_user.username} bought a ##{@tag.name} sponsorship for @#{@organization.username}")
if @available_org_credits.size >= @number_of_credits_needed
@tag.save!
spend_credits
redirect_back(fallback_location: "/partnerships")
else
raise "Not enough credits"
end
elsif @level == "media"
# For now. Just ping slack.
slackbot_ping("📹 @#{current_user.username} bought #{@number_of_credits_needed} media credits for @#{@organization.username}")
if @available_org_credits.size >= @number_of_credits_needed
spend_credits
redirect_back(fallback_location: "/partnerships")
end
elsif @level == "editorial"
SlackBot.ping(
message: "@#{current_user.username} bought #{@number_of_credits_needed} credits for @#{@organization.username}",
channel: "incoming-partners",
username: "media_sponsor",
icon_emoji: ":partyparrot:",
)
slackbot_ping("✍ @#{current_user.username} bought an editorial partnership for @#{@organization.username}")
if @available_org_credits.size >= @number_of_credits_needed
spend_credits
redirect_back(fallback_location: "/partnerships")
end
else
@organization.sponsorship_level = @level
@organization.sponsorship_status = "pending"
@organization.sponsorship_expires_at = (@organization.sponsorship_expires_at || Time.current) + 1.month
slackbot_ping("@#{current_user.username} bought a #{@level} sponsorship for @#{@organization.username}")
if @available_org_credits.size >= @number_of_credits_needed
@organization.save!
spend_credits
redirect_back(fallback_location: "/partnerships")
else
raise "Not enough credits"
end
end
end

private

def credits_for_level
if @level == "gold"
6000
elsif @level == "silver"
300
elsif @level == "tag"
500
elsif @level == "bronze"
50
elsif @level == "editorial"
500
elsif @level == "media"
params[:sponsorship_amount].to_i
else
raise "Invalid level"
end
end

def update_sponsorship_instructions
@organization.sponsorship_instructions = @organization.sponsorship_instructions + "\n---\n#{Time.current}\n---\n" + params[:sponsorship_instructions].to_s
@organization.sponsorship_instructions_updated_at = Time.current
end

def spend_credits
@available_org_credits.limit(@number_of_credits_needed).update_all(spent: true)
end

def slackbot_ping(text)
SlackBot.ping(
message: text,
channel: "incoming-partners",
username: "media_sponsor",
icon_emoji: ":partyparrot:",
)
end
end

0 comments on commit 48ade8e

Please sign in to comment.