Remove buffer gem and related code: step 1 (#12993)
* Remove buffer gem and related code * Remove more Buffer-related code * Remove one more Buffer spec * Remove DUS * Remove more Buffer code
This commit is contained in:
parent
0beacb19c9
commit
7c31a9cc98
54 changed files with 44 additions and 1128 deletions
1
Gemfile
1
Gemfile
|
|
@ -19,7 +19,6 @@ gem "ahoy_matey", "~> 3.2" # Tracking analytics for Rails
|
|||
gem "ancestry", "~> 3.2" # Ancestry allows the records of a ActiveRecord model to be organized in a tree structure
|
||||
gem "blazer", "~> 2.4.2" # Allows admins to query data
|
||||
gem "bootsnap", ">= 1.1.0", require: false # Boot large ruby/rails apps faster
|
||||
gem "buffer", "~> 0.1" # Buffer is a Ruby Wrapper for the Buffer API
|
||||
gem "carrierwave", "~> 2.2" # Upload files in your Ruby applications, map them to a range of ORMs, store them on different backends
|
||||
gem "carrierwave-bombshelter", "~> 0.2" # Protect your carrierwave from image bombs
|
||||
gem "cloudinary", "~> 1.19" # Client library for easily using the Cloudinary service
|
||||
|
|
|
|||
14
Gemfile.lock
14
Gemfile.lock
|
|
@ -149,15 +149,6 @@ GEM
|
|||
brpoplpush-redis_script (0.1.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||
redis (>= 1.0, <= 5.0)
|
||||
buffer (0.1.3)
|
||||
addressable
|
||||
environs
|
||||
faraday
|
||||
faraday_middleware
|
||||
hashie
|
||||
multi_json
|
||||
rake
|
||||
yajl-ruby
|
||||
buftok (0.2.0)
|
||||
builder (3.2.4)
|
||||
bullet (6.1.4)
|
||||
|
|
@ -262,7 +253,6 @@ GEM
|
|||
email_validator (2.2.2)
|
||||
activemodel
|
||||
emoji_regex (3.2.2)
|
||||
environs (1.1.0)
|
||||
equalizer (0.0.11)
|
||||
errbase (0.2.1)
|
||||
erubi (1.10.0)
|
||||
|
|
@ -284,8 +274,6 @@ GEM
|
|||
multipart-post (>= 1.2, < 3)
|
||||
ruby2_keywords
|
||||
faraday-net_http (1.0.1)
|
||||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.1)
|
||||
fastly (3.0.1)
|
||||
feedjira (3.1.2)
|
||||
|
|
@ -859,7 +847,6 @@ GEM
|
|||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
yajl-ruby (1.4.1)
|
||||
yard (0.9.26)
|
||||
yard-activerecord (0.0.16)
|
||||
yard (>= 0.8.3)
|
||||
|
|
@ -888,7 +875,6 @@ DEPENDENCIES
|
|||
blazer (~> 2.4.2)
|
||||
bootsnap (>= 1.1.0)
|
||||
brakeman (~> 5.0)
|
||||
buffer (~> 0.1)
|
||||
bullet (~> 6.1)
|
||||
bundler-audit (~> 0.8)
|
||||
capybara (~> 3.35.3)
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ label {
|
|||
// rendered from boostrap. We want to remove these to be
|
||||
// consistent with links in the crayons design system.
|
||||
.crayons-link,
|
||||
.crayons-tabs__item {
|
||||
.crayons-tabs__item {
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
|
|
|
|||
|
|
@ -7,22 +7,10 @@ module Admin
|
|||
end
|
||||
|
||||
def index
|
||||
@pending_buffer_updates = BufferUpdate.where(status: "pending").includes(:article)
|
||||
@user_buffer_updates = BufferUpdate.where(status: "sent_direct", approver_user_id: current_user.id).where(
|
||||
"created_at > ?", 24.hours.ago
|
||||
)
|
||||
|
||||
case params[:state]
|
||||
when /not-buffered/
|
||||
days_ago = params[:state].split("-")[2].to_f
|
||||
@articles = articles_not_buffered(days_ago)
|
||||
when /top-/
|
||||
months_ago = params[:state].split("-")[1].to_i.months.ago
|
||||
@articles = articles_top(months_ago)
|
||||
when "satellite"
|
||||
@articles = articles_satellite
|
||||
when "satellite-not-buffered"
|
||||
@articles = articles_satellite.where(last_buffered: nil)
|
||||
when "boosted-additional-articles"
|
||||
@articles = articles_boosted_additional
|
||||
when "chronological"
|
||||
|
|
@ -49,17 +37,6 @@ module Admin
|
|||
|
||||
private
|
||||
|
||||
def articles_not_buffered(days_ago)
|
||||
Article.published
|
||||
.where(last_buffered: nil)
|
||||
.where("published_at > ? OR crossposted_at > ?", days_ago.days.ago, days_ago.days.ago)
|
||||
.includes(:user)
|
||||
.limited_columns_internal_select
|
||||
.order(public_reactions_count: :desc)
|
||||
.page(params[:page])
|
||||
.per(50)
|
||||
end
|
||||
|
||||
def articles_top(months_ago)
|
||||
Article.published
|
||||
.where("published_at > ?", months_ago)
|
||||
|
|
@ -70,19 +47,9 @@ module Admin
|
|||
.per(50)
|
||||
end
|
||||
|
||||
def articles_satellite
|
||||
Article.published.where(last_buffered: nil)
|
||||
.includes(:user, :buffer_updates)
|
||||
.tagged_with(Tag.bufferized_tags, any: true).unscope(:select)
|
||||
.limited_columns_internal_select
|
||||
.order(hotness_score: :desc)
|
||||
.page(params[:page])
|
||||
.per(60)
|
||||
end
|
||||
|
||||
def articles_boosted_additional
|
||||
Article.boosted_via_additional_articles
|
||||
.includes(:user, :buffer_updates)
|
||||
.includes(:user)
|
||||
.limited_columns_internal_select
|
||||
.order(published_at: :desc)
|
||||
.page(params[:page])
|
||||
|
|
@ -111,7 +78,7 @@ module Admin
|
|||
Article.published.or(Article.where(published_from_feed: true))
|
||||
.where(featured: true)
|
||||
.where("featured_number > ?", Time.current.to_i)
|
||||
.includes(:user, :buffer_updates)
|
||||
.includes(:user)
|
||||
.limited_columns_internal_select
|
||||
.order(featured_number: :desc)
|
||||
end
|
||||
|
|
@ -128,7 +95,6 @@ module Admin
|
|||
featured_number
|
||||
user_id
|
||||
co_author_ids_list
|
||||
last_buffered
|
||||
published_at]
|
||||
params.require(:article).permit(allowed_params)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
module Admin
|
||||
class BufferUpdatesController < Admin::ApplicationController
|
||||
def create
|
||||
article_id = params[:article_id]
|
||||
article = Article.find(article_id) if article_id.present?
|
||||
fb_post = params[:fb_post]
|
||||
tweet = params[:tweet]
|
||||
listing_id = params[:listing_id]
|
||||
listing = Listing.find(params[:listing_id]) if listing_id.present?
|
||||
article&.update(featured: true)
|
||||
case params[:social_channel]
|
||||
when "main_twitter"
|
||||
Bufferizer::MainTweet.call(article, tweet, current_user.id)
|
||||
render body: nil
|
||||
when "satellite_twitter"
|
||||
Bufferizer::SatelliteTweet.call(article, tweet, current_user.id)
|
||||
render body: nil
|
||||
when "facebook"
|
||||
Bufferizer::FacebookPost.call(article, fb_post, current_user.id)
|
||||
render body: nil
|
||||
when "listings_twitter"
|
||||
Bufferizer::ListingsTweet.call(listing, tweet, current_user.id)
|
||||
render body: nil
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
BufferUpdate.upbuff!(params[:id], current_user.id, params[:body_text], params[:status])
|
||||
render body: nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authorize_admin
|
||||
authorize BufferUpdate, :access?, policy_class: InternalPolicy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -75,7 +75,6 @@ class ArticlesController < ApplicationController
|
|||
@article = @article.decorate
|
||||
@user = @article.user
|
||||
@rating_vote = RatingVote.where(article_id: @article.id, user_id: @user.id).first
|
||||
@buffer_updates = BufferUpdate.where(composer_user_id: @user.id, article_id: @article.id)
|
||||
@organizations = @user&.organizations
|
||||
# TODO: fix this for multi orgs
|
||||
@org_members = @organization.users.pluck(:name, :id) if @organization
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
class BufferUpdatesController < ApplicationController
|
||||
after_action :verify_authorized
|
||||
|
||||
def create
|
||||
@article = Article.find(params[:buffer_update][:article_id])
|
||||
authorize @article, policy_class: BufferUpdatePolicy
|
||||
create_main_tweet
|
||||
create_satellite_tweets
|
||||
create_facebook_post
|
||||
redirect_back(fallback_location: "/mod")
|
||||
end
|
||||
|
||||
def create_main_tweet
|
||||
BufferUpdate.create(
|
||||
article_id: @article.id,
|
||||
composer_user_id: current_user.id,
|
||||
body_text: modified_body_text,
|
||||
social_service_name: "twitter",
|
||||
buffer_profile_id_code: ApplicationConfig["BUFFER_TWITTER_ID"],
|
||||
status: "pending",
|
||||
)
|
||||
end
|
||||
|
||||
def create_satellite_tweets
|
||||
tags_names = @article.decorate.cached_tag_list_array
|
||||
tags_names.each do |name|
|
||||
tag = Tag.find_by(name: name)
|
||||
|
||||
next if tag&.buffer_profile_id_code.blank?
|
||||
|
||||
BufferUpdate.create(
|
||||
article_id: @article.id,
|
||||
composer_user_id: current_user.id,
|
||||
body_text: modified_body_text,
|
||||
social_service_name: "twitter",
|
||||
buffer_profile_id_code: tag.buffer_profile_id_code,
|
||||
tag_id: tag.id,
|
||||
status: "pending",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def create_facebook_post
|
||||
BufferUpdate.create(
|
||||
article_id: @article.id,
|
||||
composer_user_id: current_user.id,
|
||||
body_text: "#{params[:buffer_update][:body_text]} #{URL.article(@article)}",
|
||||
social_service_name: "facebook",
|
||||
buffer_profile_id_code: ApplicationConfig["BUFFER_FACEBOOK_ID"],
|
||||
status: "pending",
|
||||
)
|
||||
end
|
||||
|
||||
def modified_body_text
|
||||
@user = @article.user
|
||||
[
|
||||
params[:buffer_update][:body_text],
|
||||
("\n\n{ author: @#{@user.twitter_username} }" if @user.twitter_username.present?),
|
||||
(" #{SiteConfig.twitter_hashtag}" if SiteConfig.twitter_hashtag.present?),
|
||||
"\n#{URL.article(@article)}",
|
||||
].compact.join
|
||||
end
|
||||
end
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
import { Application } from 'stimulus';
|
||||
import BufferController from '../../controllers/buffer_controller';
|
||||
|
||||
describe('BufferController', () => {
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = `
|
||||
<div data-controller="buffer"
|
||||
data-buffer-bg-highlighted-class="bg-highlighted"
|
||||
data-buffer-border-highlighted-class="border-highlighted">
|
||||
<h2 data-buffer-target="header"></h2>
|
||||
<button data-action="buffer#tagBufferUpdateConfirmed"></button>
|
||||
<button data-action="buffer#tagBufferUpdateDismissed"></button>
|
||||
<button data-action="buffer#highlightElement"></button>
|
||||
</div>`;
|
||||
|
||||
const application = Application.start();
|
||||
application.register('buffer', BufferController);
|
||||
});
|
||||
|
||||
describe('#tagBufferUpdateConfirmed', () => {
|
||||
it('adds a badge to the header', () => {
|
||||
const button = document.getElementsByTagName('button')[0];
|
||||
const header = document.getElementsByTagName('h2')[0];
|
||||
|
||||
button.click();
|
||||
|
||||
expect(header.firstChild.textContent).toMatch(/Confirm/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#tagBufferUpdateDismissed', () => {
|
||||
it('adds a badge to the header', () => {
|
||||
const button = document.getElementsByTagName('button')[1];
|
||||
const header = document.getElementsByTagName('h2')[0];
|
||||
|
||||
button.click();
|
||||
|
||||
expect(header.firstChild.textContent).toMatch(/Dismiss/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#highlightElement', () => {
|
||||
it('adds a class to the controller element', () => {
|
||||
const button = document.getElementsByTagName('button')[2];
|
||||
const element = document.querySelector("[data-controller='buffer']");
|
||||
|
||||
button.click();
|
||||
|
||||
expect(
|
||||
element.classList.contains('bg-highlighted', 'border-highlighted'),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -85,16 +85,16 @@ describe('SidebarController', () => {
|
|||
|
||||
describe('#disableCurrentNavItem', () => {
|
||||
it('sets the disabled attribute on the open menu button', () => {
|
||||
window.dispatchEvent(new Event('load'))
|
||||
window.dispatchEvent(new Event('load'));
|
||||
const button = document.getElementById('apps_button');
|
||||
|
||||
expect(button.getAttribute("disabled")).toEqual("true");
|
||||
expect(button.getAttribute('disabled')).toEqual('true');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#expandDropdown', () => {
|
||||
beforeEach(() => {
|
||||
let assignMock = jest.fn();
|
||||
const assignMock = jest.fn();
|
||||
|
||||
delete window.location;
|
||||
window.location = { href: assignMock };
|
||||
|
|
@ -108,15 +108,14 @@ describe('SidebarController', () => {
|
|||
const button = document.getElementById('advanced_button');
|
||||
button.click();
|
||||
|
||||
expect(window.location.href).toEqual("/admin/advanced/broadcasts")
|
||||
expect(window.location.href).toEqual('/admin/advanced/broadcasts');
|
||||
});
|
||||
|
||||
it('closes other menu items', () => {
|
||||
const button = document.getElementById('advanced_button');
|
||||
button.click();
|
||||
|
||||
expect(document.getElementById('apps').classList).toContain("hide");
|
||||
expect(document.getElementById('apps').classList).toContain('hide');
|
||||
});
|
||||
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
import { Controller } from 'stimulus';
|
||||
|
||||
const CONFIRM_BADGE_HTML =
|
||||
'<span class="ml-2 badge badge-success">Confirm</span>';
|
||||
const DISMISS_BADGE_HTML =
|
||||
'<span class="ml-2 badge badge-danger">Dismiss</span>';
|
||||
|
||||
export default class BufferController extends Controller {
|
||||
static classes = ['bgHighlighted', 'borderHighlighted'];
|
||||
static targets = ['header', 'bodyText'];
|
||||
|
||||
tagBufferUpdateConfirmed() {
|
||||
this.clearPreviousBadge();
|
||||
|
||||
this.headerTarget.innerHTML += CONFIRM_BADGE_HTML;
|
||||
}
|
||||
|
||||
tagBufferUpdateDismissed() {
|
||||
this.clearPreviousBadge();
|
||||
|
||||
this.headerTarget.innerHTML += DISMISS_BADGE_HTML;
|
||||
}
|
||||
|
||||
highlightElement() {
|
||||
this.element.classList.add(
|
||||
this.bgHighlightedClass,
|
||||
this.borderHighlightedClass,
|
||||
);
|
||||
setTimeout(() => {
|
||||
this.element.classList.remove(this.bgHighlightedClass);
|
||||
}, 350);
|
||||
}
|
||||
|
||||
autosizeBodyText() {
|
||||
this.bodyTextTarget.rows = this.bodyTextTarget.value.split(
|
||||
/\r\n|\r|\n/,
|
||||
).length;
|
||||
}
|
||||
|
||||
clearPreviousBadge() {
|
||||
const badge = this.headerTarget.getElementsByClassName('badge')[0];
|
||||
if (badge) {
|
||||
badge.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,14 @@ import { Controller } from 'stimulus';
|
|||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
export default class SidebarController extends Controller {
|
||||
static targets = [
|
||||
'submenu'
|
||||
];
|
||||
static targets = ['submenu'];
|
||||
|
||||
disableCurrentNavItem() {
|
||||
const activeMenuId = this.submenuTargets.filter((item) => item.classList.contains("show"))[0].id
|
||||
const activeMenuId = this.submenuTargets.filter((item) =>
|
||||
item.classList.contains('show'),
|
||||
)[0].id;
|
||||
const activeButton = document.getElementById(`${activeMenuId}_button`);
|
||||
activeButton.setAttribute("disabled", true)
|
||||
activeButton.setAttribute('disabled', true);
|
||||
}
|
||||
|
||||
expandDropdown(event) {
|
||||
|
|
@ -26,7 +26,7 @@ export default class SidebarController extends Controller {
|
|||
const collapsedList = ['collapse', 'hide'];
|
||||
|
||||
this.submenuTargets.map((item) => {
|
||||
if (item.classList.contains("show")) {
|
||||
if (item.classList.contains('show')) {
|
||||
item.classList.remove(...expandedList);
|
||||
item.classList.add(...collapsedList);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
## Mention autocomplete
|
||||
|
||||
The `MentionAutocompleteTextArea` component uses the [Reach UI Combobox](https://reach.tech/combobox/) under the hood. It works by _replacing_ the textarea you pass in props with one enhanced with the `@mention` functionality.
|
||||
The `MentionAutocompleteTextArea` component uses the
|
||||
[Reach UI Combobox](https://reach.tech/combobox/) under the hood. It works by
|
||||
_replacing_ the textarea you pass in props with one enhanced with the `@mention`
|
||||
functionality.
|
||||
|
||||
The autocomplete will begin fetching suggestions once a user has typed `@` plus at least two characters. A user's selection is confirmed when they either:
|
||||
The autocomplete will begin fetching suggestions once a user has typed `@` plus
|
||||
at least two characters. A user's selection is confirmed when they either:
|
||||
|
||||
- Click on a search option
|
||||
- Hit enter on a search option
|
||||
|
|
@ -11,8 +15,15 @@ The autocomplete will begin fetching suggestions once a user has typed `@` plus
|
|||
|
||||
### Mention autocomplete accessibility
|
||||
|
||||
The component replaces the given textarea with one generated using [Reach UI Combobox](https://reach.tech/combobox/). The underlying behavior then conforms to the [WAI_ARIA guidelines on comboboxes](https://www.w3.org/TR/wai-aria-practices-1.2/#combobox).
|
||||
The component replaces the given textarea with one generated using
|
||||
[Reach UI Combobox](https://reach.tech/combobox/). The underlying behavior then
|
||||
conforms to the
|
||||
[WAI_ARIA guidelines on comboboxes](https://www.w3.org/TR/wai-aria-practices-1.2/#combobox).
|
||||
|
||||
An `aria-live` region communicates to a screen reader user when the list has been populated with suggestions.
|
||||
An `aria-live` region communicates to a screen reader user when the list has
|
||||
been populated with suggestions.
|
||||
|
||||
Please note: When using the `MentionAutocompleteTextArea`, you must have either an `aria-labelledby` or `aria-label` attribute on the textarea you pass as a prop. These attributes are copied across to the Reach UI Combobox input, ensuring it is labelled correctly for accessibility.
|
||||
Please note: When using the `MentionAutocompleteTextArea`, you must have either
|
||||
an `aria-labelledby` or `aria-label` attribute on the textarea you pass as a
|
||||
prop. These attributes are copied across to the Reach UI Combobox input,
|
||||
ensuring it is labelled correctly for accessibility.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ module Constants
|
|||
"Resource Admin: Badge",
|
||||
"Resource Admin: BadgeAchievement",
|
||||
"Resource Admin: Broadcast",
|
||||
"Resource Admin: BufferUpdate",
|
||||
"Resource Admin: ChatChannel",
|
||||
"Resource Admin: Comment",
|
||||
"Resource Admin: Config",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
class Article < ApplicationRecord
|
||||
self.ignored_columns = %w[facebook_last_buffered last_buffered].freeze
|
||||
|
||||
include CloudinaryHelper
|
||||
include ActionView::Helpers
|
||||
include Storext.model
|
||||
|
|
@ -29,7 +31,6 @@ class Article < ApplicationRecord
|
|||
counter_culture :user
|
||||
counter_culture :organization
|
||||
|
||||
has_many :buffer_updates, dependent: :destroy
|
||||
has_many :comments, as: :commentable, inverse_of: :commentable, dependent: :nullify
|
||||
has_many :html_variant_successes, dependent: :nullify
|
||||
has_many :html_variant_trials, dependent: :nullify
|
||||
|
|
@ -115,9 +116,8 @@ class Article < ApplicationRecord
|
|||
# data in the column. However, since `published_at` is a *very* diverse
|
||||
# column and can scope down the result set significantly, the query planner
|
||||
# can make heavy use of it.
|
||||
scope :published, -> {
|
||||
self
|
||||
.where(published: true)
|
||||
scope :published, lambda {
|
||||
where(published: true)
|
||||
.where("published_at <= ?", Time.current)
|
||||
}
|
||||
scope :unpublished, -> { where(published: false) }
|
||||
|
|
@ -165,8 +165,7 @@ class Article < ApplicationRecord
|
|||
:video, :user_id, :organization_id, :video_source_url, :video_code,
|
||||
:video_thumbnail_url, :video_closed_caption_track_url, :social_image,
|
||||
:published_from_feed, :crossposted_at, :published_at, :featured_number,
|
||||
:last_buffered, :facebook_last_buffered, :created_at, :body_markdown,
|
||||
:email_digest_eligible, :processed_html, :co_author_ids)
|
||||
:created_at, :body_markdown, :email_digest_eligible, :processed_html, :co_author_ids)
|
||||
}
|
||||
|
||||
scope :boosted_via_additional_articles, lambda {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ class Listing < ApplicationRecord
|
|||
# We used to use both "classified listing" and "listing" throughout the app.
|
||||
# We standardized on the latter, but keeping the table name was easier.
|
||||
self.table_name = "classified_listings"
|
||||
self.ignored_columns = ["last_buffered"].freeze
|
||||
|
||||
include Searchable
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
require_relative "../lib/acts_as_taggable_on/tag"
|
||||
|
||||
class Tag < ActsAsTaggableOn::Tag
|
||||
self.ignored_columns = ["buffer_profile_id_code"].freeze
|
||||
|
||||
attr_accessor :points, :tag_moderator_id, :remove_moderator_id
|
||||
|
||||
acts_as_followable
|
||||
|
|
@ -21,7 +23,6 @@ class Tag < ActsAsTaggableOn::Tag
|
|||
belongs_to :badge, optional: true
|
||||
belongs_to :mod_chat_channel, class_name: "ChatChannel", optional: true
|
||||
|
||||
has_many :buffer_updates, dependent: :nullify
|
||||
has_many :articles, through: :taggings, source: :taggable, source_type: "Article"
|
||||
|
||||
has_one :sponsorship, as: :sponsorable, inverse_of: :sponsorable, dependent: :destroy
|
||||
|
|
@ -66,12 +67,6 @@ class Tag < ActsAsTaggableOn::Tag
|
|||
User.with_role(:tag_moderator, self).order(id: :asc).ids
|
||||
end
|
||||
|
||||
def self.bufferized_tags
|
||||
Rails.cache.fetch("bufferized_tags_cache", expires_in: 2.hours) do
|
||||
where.not(buffer_profile_id_code: nil).pluck(:name)
|
||||
end
|
||||
end
|
||||
|
||||
def self.valid_categories
|
||||
ALLOWED_CATEGORIES
|
||||
end
|
||||
|
|
|
|||
|
|
@ -131,10 +131,6 @@ class User < ApplicationRecord
|
|||
inverse_of: :blocked, dependent: :delete_all
|
||||
has_many :blocker_blocks, class_name: "UserBlock", foreign_key: :blocker_id,
|
||||
inverse_of: :blocker, dependent: :delete_all
|
||||
has_many :buffer_updates_approved, class_name: "BufferUpdate", foreign_key: :approver_user_id,
|
||||
inverse_of: :approver_user, dependent: :nullify
|
||||
has_many :buffer_updates_composed, class_name: "BufferUpdate", foreign_key: :composer_user_id,
|
||||
inverse_of: :composer_user, dependent: :nullify
|
||||
has_many :chat_channel_memberships, dependent: :destroy
|
||||
has_many :chat_channels, through: :chat_channel_memberships
|
||||
has_many :collections, dependent: :destroy
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
class BufferUpdatePolicy < ApplicationPolicy
|
||||
def create?
|
||||
user_is_trusted? || user_is_author?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_is_author?
|
||||
record.user_id == user.id
|
||||
end
|
||||
end
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
module Bufferizer
|
||||
class FacebookPost
|
||||
def self.call(article, post, admin_id)
|
||||
return unless article && post && admin_id
|
||||
|
||||
BufferUpdate.buff!(
|
||||
article.id,
|
||||
fb_buffer_text(post, article),
|
||||
social_service_name: "facebook",
|
||||
admin_id: admin_id,
|
||||
)
|
||||
|
||||
BufferUpdate.buff!(
|
||||
article.id,
|
||||
fb_buffer_text(post, article) + social_tags(article),
|
||||
social_service_name: "linkedin",
|
||||
admin_id: admin_id,
|
||||
)
|
||||
|
||||
article.update(facebook_last_buffered: Time.current)
|
||||
end
|
||||
|
||||
def self.fb_buffer_text(post, article)
|
||||
"#{post} #{URL.article(article)}"
|
||||
end
|
||||
|
||||
private_class_method :fb_buffer_text
|
||||
|
||||
def self.social_tags(article)
|
||||
# for linkedin's followable tags
|
||||
tags = article.tag_list.map { |tag| "##{tag}" }.join(" ")
|
||||
" #programming #softwareengineering #{tags}"
|
||||
end
|
||||
|
||||
private_class_method :social_tags
|
||||
end
|
||||
end
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
module Bufferizer
|
||||
class ListingsTweet
|
||||
TWEET_SIZE_LIMIT = 255
|
||||
|
||||
def self.call(listing, tweet)
|
||||
return unless listing && tweet
|
||||
|
||||
buffer_listings_id = ApplicationConfig["BUFFER_LISTINGS_PROFILE"]
|
||||
|
||||
BufferUpdate.send_to_buffer(
|
||||
listings_twitter_text(tweet, listing),
|
||||
buffer_listings_id,
|
||||
)
|
||||
|
||||
listing.update(last_buffered: Time.current)
|
||||
end
|
||||
|
||||
def self.listings_twitter_text(tweet, listing)
|
||||
"#{tweet} #{URL.url(listing.path)}" if tweet.size <= TWEET_SIZE_LIMIT
|
||||
end
|
||||
|
||||
private_class_method :listings_twitter_text
|
||||
end
|
||||
end
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
module Bufferizer
|
||||
class MainTweet
|
||||
TWEET_SIZE_LIMIT = 255
|
||||
|
||||
def self.call(article, tweet, admin_id)
|
||||
return unless article && tweet && admin_id
|
||||
|
||||
BufferUpdate.buff!(
|
||||
article.id,
|
||||
twitter_buffer_text(tweet, article),
|
||||
admin_id: admin_id,
|
||||
)
|
||||
|
||||
article.update(last_buffered: Time.current)
|
||||
end
|
||||
|
||||
def self.twitter_buffer_text(tweet, article)
|
||||
"#{tweet} #{URL.article(article)}" if tweet.size <= TWEET_SIZE_LIMIT
|
||||
end
|
||||
|
||||
private_class_method :twitter_buffer_text
|
||||
end
|
||||
end
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
module Bufferizer
|
||||
class SatelliteTweet
|
||||
TWEET_SIZE_LIMIT = 255
|
||||
TEXT_SIZE_LIMIT = 250
|
||||
|
||||
def self.call(article, tweet, admin_id)
|
||||
return unless article && tweet && admin_id
|
||||
|
||||
article.tags.find_each do |tag|
|
||||
next if tag.buffer_profile_id_code.blank?
|
||||
|
||||
text = twitter_buffer_text(tweet, article)
|
||||
|
||||
if text.length < TEXT_SIZE_LIMIT && SiteConfig.twitter_hashtag
|
||||
text = text.gsub(
|
||||
" #{SiteConfig.twitter_hashtag}",
|
||||
" #{SiteConfig.twitter_hashtag} ##{tag.name}",
|
||||
)
|
||||
end
|
||||
|
||||
BufferUpdate.buff!(
|
||||
article.id,
|
||||
text,
|
||||
buffer_profile_id_code: tag.buffer_profile_id_code,
|
||||
tag_id: tag.id,
|
||||
admin_id: admin_id,
|
||||
)
|
||||
end
|
||||
|
||||
article.update(last_buffered: Time.current)
|
||||
end
|
||||
|
||||
def self.twitter_buffer_text(tweet, article)
|
||||
"#{tweet} #{URL.article(article)}" if tweet.size <= TWEET_SIZE_LIMIT
|
||||
end
|
||||
|
||||
private_class_method :twitter_buffer_text
|
||||
end
|
||||
end
|
||||
|
|
@ -8,7 +8,6 @@ module Users
|
|||
virtual_articles = user.articles.map { |article| Article.new(article.attributes) }
|
||||
user.articles.find_each do |article|
|
||||
article.reactions.delete_all
|
||||
article.buffer_updates.delete_all
|
||||
article.comments.includes(:user).find_each do |comment|
|
||||
comment.reactions.delete_all
|
||||
EdgeCache::BustComment.call(comment.commentable)
|
||||
|
|
|
|||
|
|
@ -126,36 +126,12 @@
|
|||
<%= f.check_box :boosted_additional_articles, id: "boosted_additional_articles-#{article.id}" %>
|
||||
<label for="boosted_additional_articles-<%= article.id %>">Boosted</label>
|
||||
</div>
|
||||
<% unless article.last_buffered %>
|
||||
<div class="form-check col">
|
||||
<%= f.check_box :last_buffered, id: "last_buffered-#{article.id}" %>
|
||||
<label for="last_buffered-<%= article.id %>">Mark as buffered</label>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="col">
|
||||
<button class="btn btn-primary float-right">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if article.last_buffered %>
|
||||
<div class="mt-5">
|
||||
<em>Last Buffered <%= article.last_buffered %></em>
|
||||
<% article.buffer_updates.order(created_at: :asc).each do |buffer_update| %>
|
||||
<h5>
|
||||
<a href="https://buffer.com/app/profile/<%= buffer_update.buffer_profile_id_code %>/buffer/queue/list">
|
||||
<%= buffer_update.social_service_name %>
|
||||
<%= " MAIN" if buffer_update.buffer_profile_id_code == ApplicationConfig["BUFFER_TWITTER_ID"] %>
|
||||
</a>
|
||||
</h5>
|
||||
<%= time_ago_in_words(buffer_update.created_at) %> ago
|
||||
<p class="bg-warning">
|
||||
<%= buffer_update.body_text %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if article.boosted_dev_digest_email %>
|
||||
<br /><br />
|
||||
<% phrase = "#{article.path}?booster_org=#{article.organization&.slug || 'generic'}" %>
|
||||
|
|
@ -173,53 +149,5 @@
|
|||
<%= EmailMessage.where("subject LIKE ?", "%#{phrase}%").where.not(opened_at: nil).where.not(opened_at: nil).where("sent_at > ?", 1.week.ago).size %>
|
||||
OPENED EMAILS IN THE PAST WEEK</b>
|
||||
<% end %>
|
||||
|
||||
<div class="d-flex justify-content-between" style="padding-top:15px;">
|
||||
<button class="btn btn-dark btn-lg btn-block" data-toggle="collapse" data-target="#article-<%= article.id %>-buffer-area"
|
||||
area-expanded="false" area-controls="article-<%= article.id %>-buffer-area">
|
||||
Social Distribution
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="article-<%= article.id %>-buffer-area" class="buffering-area-for-single-article collapse" style="padding-top:25px;">
|
||||
<div class="row">
|
||||
<div class="article-body-html col col-7" style="background:white;max-height: 800px;padding-top:8px;overflow:auto;border-radius: 3px;">
|
||||
<%= article.processed_html&.html_safe %>
|
||||
</div>
|
||||
|
||||
<div class="col col-5">
|
||||
<%= form_with url: admin_buffer_updates_path, html: { data: { action: "submit->article#highlightElement" } } do %>
|
||||
<input type="hidden" name="social_channel" value="main_twitter" />
|
||||
<input type="hidden" name="article_id" value="<%= article.id %>" />
|
||||
<h5>Twitter MAIN</h5>
|
||||
<div class="form-group">
|
||||
<textarea rows="5" wrap="hard" name="tweet" maxlength="255" class="form-control"><%= BufferUpdate.twitter_default_text(article) %></textarea>
|
||||
</div>
|
||||
<button class="btn btn-primary mb-2">🦅 Tweet to @<%= SiteConfig.social_media_handles["twitter"] %></button>
|
||||
<% end %>
|
||||
|
||||
<% if (article.decorate.cached_tag_list_array & Tag.bufferized_tags).any? %>
|
||||
<%= form_with url: admin_buffer_updates_path, html: { data: { action: "submit->article#highlightElement" } } do %>
|
||||
<input type="hidden" name="social_channel" value="satellite_twitter" />
|
||||
<input type="hidden" name="article_id" value="<%= article.id %>" />
|
||||
<h5>Twitter Satellite</h5>
|
||||
<div class="form-group">
|
||||
<textarea rows="5" wrap="hard" name="tweet" maxlength="255" class="form-control"><%= BufferUpdate.twitter_default_text(article) %></textarea>
|
||||
</div>
|
||||
<button class="btn btn-primary mb-2">🐦 Tweet to satellites</button>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<%= form_with url: admin_buffer_updates_path, html: { data: { action: "submit->article#highlightElement" } } do %>
|
||||
<input type="hidden" name="social_channel" value="facebook" />
|
||||
<input type="hidden" name="article_id" value="<%= article.id %>" />
|
||||
<h5>Facebook & LinkedIn</h5>
|
||||
<div class="form-group">
|
||||
<textarea rows="5" wrap="hard" name="fb_post" class="form-control" required></textarea>
|
||||
</div>
|
||||
<button class="btn btn-primary mb-2">📘 Post to Facebook</button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,3 @@
|
|||
<% if ENV["BUFFER_ACCESS_TOKEN"].blank? %>
|
||||
<div class="crayons-notice crayons-notice--info mb-6" role="alert">
|
||||
<p><strong>All references to "Buffering" are legacy and social media functionality is not currently operational.</strong></p>
|
||||
<p>Buffer, the social media scheduling tool, has discontinued its API, so send-to-buffer functionality only works for legacy clients.</p>
|
||||
<p>We will replace this functionality in the future with a functional alternative.</p>
|
||||
</div>
|
||||
<% elsif @user_buffer_updates.any? %>
|
||||
<div class="crayons-notice crayons-notice--success mb-6" role="alert">
|
||||
You have sent <strong><%= @user_buffer_updates.size %></strong> buffers so far in the past 24 hours. Keep it up!
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="crayons-notice crayons-notice--warning mb-6" role="alert">
|
||||
You haven't sent any buffers in the past 24 hours, let's get to work!
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<main class="row">
|
||||
<div class="col-12">
|
||||
<ul class="nav nav-tabs nav-fill">
|
||||
|
|
@ -30,29 +14,6 @@
|
|||
href="<%= admin_articles_path(state: :satellite) %>"
|
||||
class="nav-link <%= "active" if params[:state] == "satellite" %>">Satellite</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span class="nav-link disabled">Not Buffered:</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="<%= admin_articles_path(state: "not-buffered-0.25") %>"
|
||||
class="nav-link <%= "active" if params[:state] == "not-buffered-0.25" %>">6hr</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="<%= admin_articles_path(state: "not-buffered-1") %>"
|
||||
class="nav-link <%= "active" if params[:state] == "not-buffered-1" %>">1d</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="<%= admin_articles_path(state: "not-buffered-7") %>"
|
||||
class="nav-link <%= "active" if params[:state] == "not-buffered-7" %>">7d</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="<%= admin_articles_path(state: "satellite-not-buffered") %>"
|
||||
class="nav-link <%= "active" if params[:state] == "satellite-not-buffered" %>">Satellite</a>
|
||||
</li>
|
||||
</ul>
|
||||
<% if params[:state] && params[:state].include?("top-") && params[:state] != "top-3" && params[:state] != "top-6" %>
|
||||
<h1 style="color:red">
|
||||
|
|
@ -60,73 +21,6 @@
|
|||
</h1>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if @pending_buffer_updates.any? %>
|
||||
<div class="col-12 mb-2">
|
||||
<details>
|
||||
<summary style="font-size: 1.3em; cursor: pointer;">Suggested Tweets (<%= @pending_buffer_updates.size %>)</summary>
|
||||
<% @pending_buffer_updates.each do |buffer_update| %>
|
||||
<% next unless buffer_update.article %>
|
||||
<div
|
||||
class="card my-3"
|
||||
id="suggested-tweet-<%= buffer_update.id %>"
|
||||
data-controller="buffer"
|
||||
data-action="load@window->buffer#autosizeBodyText"
|
||||
data-buffer-bg-highlighted-class="bg-highlighted"
|
||||
data-buffer-border-highlighted-class="border-highlighted">
|
||||
<div class="card-header">
|
||||
<h2 class="my-0" data-buffer-target="header"><%= buffer_update.article.title %></h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h4>Score: <%= buffer_update.article.score %></h4>
|
||||
<div class="blockquote">
|
||||
<%= HTML_Truncator.truncate(
|
||||
buffer_update.article.processed_html,
|
||||
50,
|
||||
ellipsis: "<a class=\"comment-read-more\" href=\"#{buffer_update.article.path}\">... Read Entire Post</a>",
|
||||
).html_safe %>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<code><b><%= Tag.find_by(id: buffer_update.tag_id)&.name || buffer_update.social_service_name %>:</b></code>
|
||||
|
||||
<%= form_with(
|
||||
url: admin_buffer_update_path(buffer_update.id),
|
||||
class: "buffer-form buffer-confirm",
|
||||
html: { data: { action: "submit->buffer#highlightElement" } },
|
||||
) do |f| %>
|
||||
<div class="form-group">
|
||||
<input name="utf8" type="hidden" value="✓">
|
||||
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
|
||||
<input type="hidden" name="_method" value="patch" />
|
||||
<input type="hidden" name="status" value="confirmed" />
|
||||
<textarea
|
||||
class="w-100 suggested-tweet-body-text"
|
||||
name="body_text"
|
||||
class="form-control"
|
||||
data-buffer-target="bodyText"><%= buffer_update.body_text %></textarea>
|
||||
</div>
|
||||
<button value="confirmed" name="status" class="btn btn-success" data-action="buffer#tagBufferUpdateConfirmed">Confirm</button>
|
||||
<% end %>
|
||||
|
||||
<%= form_with(
|
||||
url: admin_buffer_update_path(buffer_update.id),
|
||||
class: "buffer-form buffer-dismiss",
|
||||
html: { data: { action: "submit->buffer#highlightElement" } },
|
||||
) do |f| %>
|
||||
<div class="form-group">
|
||||
<input name="utf8" type="hidden" value="✓">
|
||||
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
|
||||
<input type="hidden" name="_method" value="patch" />
|
||||
<input type="hidden" name="status" value="dismissed" />
|
||||
</div>
|
||||
<button value="dismissed" name="status" class="btn btn-danger" data-action="buffer#tagBufferUpdateDismissed">Dismiss</button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</details>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="col-12">
|
||||
<% if @featured_articles.present? %>
|
||||
<h2>Manually Featured Articles</h2>
|
||||
|
|
|
|||
|
|
@ -58,45 +58,6 @@
|
|||
<td><%= listing.published ? "Yes" : "No" %></td>
|
||||
<td><%= listing.bumped_at ? "#{time_ago_in_words(listing.bumped_at)} ago" : "Draft" %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
class="buffer-cell border-0"
|
||||
colspan="7"
|
||||
data-controller="buffer"
|
||||
data-action="load@window->buffer#autosizeBodyText"
|
||||
data-buffer-bg-highlighted-class="bg-highlighted"
|
||||
data-buffer-border-highlighted-class="border-highlighted">
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
data-toggle="collapse"
|
||||
data-target="#buffering-area-for-listing-<%= listing.id %>"
|
||||
aria-expanded="false"
|
||||
aria-controls="buffering-area-for-listing-<%= listing.id %>">
|
||||
Share to Buffer
|
||||
</button>
|
||||
|
||||
<% if listing.last_buffered.present? %>
|
||||
<em class="ml-1">
|
||||
Last shared: <%= listing.last_buffered.strftime("%d %B %Y") %>
|
||||
</em>
|
||||
<% end %>
|
||||
<div id="buffering-area-for-listing-<%= listing.id %>" class="collapse buffer-area mt-3">
|
||||
<p><strong><%= listing.title %></strong></p>
|
||||
<p><%= listing.processed_html&.html_safe %></p>
|
||||
<%= form_with url: admin_buffer_updates_path, html: { data: { action: "submit->buffer#highlightElement" } } do %>
|
||||
<input type="hidden" name="social_channel" value="listings_twitter" />
|
||||
<input type="hidden" name="listing_id" value="<%= listing.id %>" />
|
||||
<textarea class="form-control" wrap="hard" name="tweet" maxlength="255" data-buffer-target="bodyText">
|
||||
📋 New <%= community_name %> Listing!

Category: <%= listing.category %>

<%= listing.title %>

|
||||
<% if listing.user.twitter_username? %>
|
||||
Posted by @<%= listing.user.twitter_username %>
|
||||
<% end %>
|
||||
</textarea>
|
||||
<button class="btn btn-primary mt-2">🐦 Tweet 🐦</button>
|
||||
<% end %>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
<a class="crayons-link crayons-link--block <%= "crayons-link--current" if deduced_controller(request) == group[:children][0][:controller] %>"
|
||||
href="/admin/<%= group[:children][0][:controller] %>"
|
||||
aria-page="<%= "page" if deduced_controller(request) == group[:children][0][:controller] %>"
|
||||
data-action="click->sidebar#expandDropdown"
|
||||
>
|
||||
data-action="click->sidebar#expandDropdown">
|
||||
<%= inline_svg_tag(group[:svg], aria: true, class: "dropdown-icon crayons-icon") %>
|
||||
<%= display_name(group_name) %>
|
||||
</a>
|
||||
|
|
@ -19,22 +18,19 @@
|
|||
data-target-href="/admin/<%= group_name %>/<%= group[:children][0][:controller] %>"
|
||||
aria-expanded="<%= (deduced_scope(request) == group_name.to_s).to_s %>"
|
||||
aria-controls="<%= group_name %>"
|
||||
data-action="click->sidebar#expandDropdown"
|
||||
>
|
||||
data-action="click->sidebar#expandDropdown">
|
||||
<%= inline_svg_tag(group[:svg], aria: true, class: "dropdown-icon crayons-icon") %>
|
||||
<%= display_name(group_name) %>
|
||||
</button>
|
||||
<ul id="<%= group_name %>"
|
||||
data-sidebar-target="submenu"
|
||||
class="<%= deduced_scope(request) == group_name.to_s ? "expand show" : "collapse hide" %>"
|
||||
>
|
||||
class="<%= deduced_scope(request) == group_name.to_s ? "expand show" : "collapse hide" %>">
|
||||
<% group[:children].each do |item| %>
|
||||
<% if item[:visible] %>
|
||||
<li>
|
||||
<a class="crayons-link crayons-link--block ml-7 <%= "fw-bold" if deduced_controller(request) == item[:controller].to_s %>"
|
||||
href="/admin/<%= group_name %>/<%= item[:controller] %>"
|
||||
aria-page="<%= "page" if deduced_controller(request) == item[:controller].to_s %>"
|
||||
>
|
||||
aria-page="<%= "page" if deduced_controller(request) == item[:controller].to_s %>">
|
||||
<%= item[:name].to_s.titleize %>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<li>
|
||||
<a
|
||||
href="/admin/<%= deduced_scope(request) %>/<%= item[:controller] %>"
|
||||
class="crayons-tabs__item <%= "crayons-tabs__item--current" if deduced_controller(request)&.match?(item[:controller]) %>" <>
|
||||
class="crayons-tabs__item <%= "crayons-tabs__item--current" if deduced_controller(request)&.match?(item[:controller]) %>">
|
||||
<%= item[:name].to_s.titleize %>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -30,21 +30,6 @@
|
|||
|
||||
<div class="dashboard-container crayons-layout">
|
||||
<%= render "dashboards/dashboard_article", article: @article, organization: @article.organization, org_admin: @user.org_admin?(@article.organization), manage_view: true %>
|
||||
<% if @buffer_updates.any? %>
|
||||
<div class="single-article thanks-for-suggesting-a-tweet">
|
||||
Tweet Suggestion Sent 🙏
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="single-article single-article-manage-form-wrapper">
|
||||
<%= form_for(BufferUpdate.new) do |f| %>
|
||||
<h2>Suggest a Tweet</h2>
|
||||
<%= f.hidden_field :article_id, value: @article.id %>
|
||||
<%= f.text_area :body_text, minlength: 10, maxlength: 220 %>
|
||||
<%= f.submit "Share Tweet Suggestion" %>
|
||||
<p>Suggestion can be a quote, summary, or bullet points from the post.</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="single-article single-article-manage-form-wrapper">
|
||||
<%= form_for(RatingVote.new) do |f| %>
|
||||
<h2>Experience Level of Post</h2>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@
|
|||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
||||
<%= yield %>
|
||||
<% if @help_url %>
|
||||
<a class="admin-help-button crayons-btn crayons-btn--icon-rounded crayons-btn--s" href="<%= @help_url %>" target="_blank" rel="noopener noreferer">
|
||||
|
|
|
|||
|
|
@ -204,15 +204,5 @@
|
|||
Who <em>might</em> find this post most valuable, based on overall experience level?
|
||||
</p>
|
||||
</div>
|
||||
<% if @moderatable.last_buffered.blank? %>
|
||||
<div class="tag-mod-form">
|
||||
<%= form_for(BufferUpdate.new) do |f| %>
|
||||
<h2>Suggest a Tweet for @<%= SiteConfig.social_media_handles["twitter"] %></h2>
|
||||
<%= f.hidden_field :article_id, value: @moderatable.id %>
|
||||
<%= f.text_area :body_text, maxlength: 220, placeholder: "Can be a TLDR of the post, an interesting quote from the post, or bullet points from topics covered in the post, etc." %>
|
||||
<%= f.submit "Share Tweet Suggestion" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ Rails.application.routes.draw do
|
|||
remote_token http_origin session_hijacking] } })
|
||||
mount flipper_ui, at: "feature_flags"
|
||||
end
|
||||
resources :buffer_updates, only: %i[create update]
|
||||
resources :feedback_messages, only: %i[index show]
|
||||
resources :invitations, only: %i[index new create destroy]
|
||||
resources :organization_memberships, only: %i[update destroy create]
|
||||
|
|
@ -383,7 +382,6 @@ Rails.application.routes.draw do
|
|||
resources :credits, only: %i[index new create] do
|
||||
get "purchase", on: :collection, to: "credits#new"
|
||||
end
|
||||
resources :buffer_updates, only: [:create]
|
||||
resources :reading_list_items, only: [:update]
|
||||
resources :poll_votes, only: %i[show create]
|
||||
resources :poll_skips, only: [:create]
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
module DataUpdateScripts
|
||||
class RemoveOrphanedBufferUpdatesByArticle
|
||||
def run
|
||||
# Delete all BufferUpdates belonging to Articles that don't exist anymore
|
||||
ActiveRecord::Base.connection.execute(
|
||||
<<~SQL.squish,
|
||||
DELETE FROM buffer_updates
|
||||
WHERE article_id NOT IN (SELECT id FROM articles);
|
||||
SQL
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -66,7 +66,6 @@ module DataUpdateScripts
|
|||
# Poll is ignored because it's related to the liquid tag inside the article, also user's can't use polls
|
||||
# TagAdjustment is ignored as there's likely no reason for article to have an adjustment moved over
|
||||
models_with_a_direct_relation = [
|
||||
BufferUpdate,
|
||||
HtmlVariantSuccess,
|
||||
HtmlVariantSuccess,
|
||||
HtmlVariantTrial,
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
module DataUpdateScripts
|
||||
class NullifyOrphanRowsFromBufferUpdatesByComposerUserId
|
||||
def run
|
||||
# Nullify all BufferUpdates composer_user_id belonging to Users that don't exist anymore
|
||||
ActiveRecord::Base.connection.execute(
|
||||
<<~SQL.squish,
|
||||
UPDATE buffer_updates
|
||||
SET composer_user_id = NULL
|
||||
WHERE composer_user_id IS NOT NULL
|
||||
AND composer_user_id NOT IN (SELECT id FROM users);
|
||||
SQL
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
FactoryBot.define do
|
||||
factory :buffer_update do
|
||||
article
|
||||
tag
|
||||
end
|
||||
end
|
||||
|
|
@ -18,7 +18,6 @@ RSpec.describe Article, type: :model do
|
|||
it { is_expected.to belong_to(:organization).optional }
|
||||
it { is_expected.to belong_to(:user) }
|
||||
|
||||
it { is_expected.to have_many(:buffer_updates).dependent(:destroy) }
|
||||
it { is_expected.to have_many(:comments).dependent(:nullify) }
|
||||
it { is_expected.to have_many(:html_variant_successes).dependent(:nullify) }
|
||||
it { is_expected.to have_many(:html_variant_trials).dependent(:nullify) }
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe BufferUpdate, type: :model do
|
||||
let(:article) { create(:article) }
|
||||
let(:tag1) { create(:tag) }
|
||||
let(:tag2) { create(:tag) }
|
||||
|
||||
describe "validations" do
|
||||
describe "builtin validations" do
|
||||
subject { described_class.buff!(article.id, "twitter_buffer_text") }
|
||||
|
||||
it { is_expected.to belong_to(:approver_user).optional }
|
||||
it { is_expected.to belong_to(:composer_user).optional }
|
||||
it { is_expected.to belong_to(:tag).optional }
|
||||
end
|
||||
end
|
||||
|
||||
it "creates update" do
|
||||
described_class.buff!(article.id, "twitter_buffer_text")
|
||||
expect(described_class.all.size).to eq(1)
|
||||
end
|
||||
|
||||
it "does not allow duplicate updates" do
|
||||
described_class.buff!(article.id, "twitter_buffer_text")
|
||||
described_class.buff!(article.id, "twitter_buffer_text")
|
||||
expect(described_class.all.size).to eq(1)
|
||||
end
|
||||
|
||||
it "does not allow duplicate updates if the first one was a little while ago" do
|
||||
b1 = described_class.buff!(article.id, "twitter_buffer_text")
|
||||
b1.update_column(:created_at, 5.minutes.ago)
|
||||
described_class.buff!(article.id, "twitter_buffer_text")
|
||||
expect(described_class.all.size).to eq(2)
|
||||
described_class.buff!(article.id, "twitter_buffer_text")
|
||||
expect(described_class.all.size).to eq(2)
|
||||
described_class.buff!(article.id, "twitter_buffer_text yoyo")
|
||||
expect(described_class.all.size).to eq(3)
|
||||
end
|
||||
|
||||
it "allows same text across different social platforms" do
|
||||
described_class.buff!(article.id, "twitter_buffer_text", social_service_name: "facebook")
|
||||
described_class.buff!(article.id, "twitter_buffer_text")
|
||||
expect(described_class.all.size).to eq(2)
|
||||
end
|
||||
|
||||
it "allows same text across different tags" do
|
||||
described_class.buff!(article.id, "twitter_buffer_text", tag_id: tag1.id)
|
||||
described_class.buff!(article.id, "twitter_buffer_text", tag_id: tag2.id)
|
||||
expect(described_class.all.size).to eq(2)
|
||||
end
|
||||
|
||||
it "allows same text across different articles with the same tag" do
|
||||
described_class.buff!(article.id, "twitter_buffer_text", tag_id: tag1.id)
|
||||
described_class.buff!(create(:article).id, "twitter_buffer_text", tag_id: tag1.id)
|
||||
expect(described_class.all.size).to eq(2)
|
||||
end
|
||||
|
||||
it "does not allow more than 3 suggestions" do
|
||||
Array.new(3) do |i|
|
||||
described_class.buff!(article.id, "twitter_buffer_text_#{i}")
|
||||
end
|
||||
invalid_buffer = described_class.buff!(article.id, "twitter_buffer_text_4")
|
||||
expect(described_class.all.size).to eq(3)
|
||||
expect(invalid_buffer.errors.full_messages.first).to include("already has multiple suggestions")
|
||||
end
|
||||
end
|
||||
|
|
@ -8,7 +8,6 @@ RSpec.describe Tag, type: :model do
|
|||
subject { tag }
|
||||
|
||||
it { is_expected.to belong_to(:badge).optional }
|
||||
it { is_expected.to have_many(:buffer_updates).dependent(:nullify) }
|
||||
it { is_expected.to have_one(:sponsorship).inverse_of(:sponsorable).dependent(:destroy) }
|
||||
|
||||
it { is_expected.to validate_length_of(:name).is_at_most(30) }
|
||||
|
|
|
|||
|
|
@ -145,22 +145,6 @@ RSpec.describe User, type: :model do
|
|||
.dependent(:delete_all)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(subject).to have_many(:buffer_updates_approved)
|
||||
.class_name("BufferUpdate")
|
||||
.with_foreign_key("approver_user_id")
|
||||
.inverse_of(:approver_user)
|
||||
.dependent(:nullify)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(subject).to have_many(:buffer_updates_composed)
|
||||
.class_name("BufferUpdate")
|
||||
.with_foreign_key("composer_user_id")
|
||||
.inverse_of(:composer_user)
|
||||
.dependent(:nullify)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(subject).to have_many(:created_podcasts)
|
||||
.class_name("Podcast")
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe BufferUpdatePolicy, type: :policy do
|
||||
subject { described_class.new(user, article) }
|
||||
|
||||
let(:article) { build_stubbed(:article) }
|
||||
|
||||
context "when user is trusted" do
|
||||
let(:user) { build(:user, :trusted) }
|
||||
|
||||
it { is_expected.to permit_actions(%i[create]) }
|
||||
end
|
||||
end
|
||||
|
|
@ -163,9 +163,6 @@ RSpec.configure do |config|
|
|||
stub_request(:any, /localhost:9090/)
|
||||
.to_return(status: 200, body: "OK".to_json, headers: {})
|
||||
|
||||
stub_request(:post, /api.bufferapp.com/)
|
||||
.to_return(status: 200, body: { fake_text: "so fake" }.to_json, headers: {})
|
||||
|
||||
# for twitter image cdn
|
||||
stub_request(:get, /twimg.com/)
|
||||
.to_return(status: 200, body: "", headers: {})
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
require "rails_helper"
|
||||
require "requests/shared_examples/internal_policy_dependant_request"
|
||||
|
||||
RSpec.describe "/admin/buffer_updates", type: :request do
|
||||
let(:user) { create(:user) }
|
||||
let(:article) { create(:article, user_id: user.id) }
|
||||
let(:comment) { build_stubbed(:comment, user_id: user.id, commentable: article) }
|
||||
|
||||
it_behaves_like "an InternalPolicy dependant request", BufferUpdate do
|
||||
let(:request) { post "/admin/buffer_updates" }
|
||||
end
|
||||
|
||||
describe "POST /admin/buffer_updates" do
|
||||
before do
|
||||
user.add_role(:super_admin)
|
||||
sign_in user
|
||||
end
|
||||
|
||||
it "creates buffer update for tweet if tweet params are passed" do
|
||||
post "/admin/buffer_updates",
|
||||
params:
|
||||
{ social_channel: "main_twitter", article_id: article.id, tweet: "Hello this is a test" }
|
||||
expect(BufferUpdate.all.size).to eq(1)
|
||||
post "/admin/buffer_updates",
|
||||
params: { social_channel: "main_twitter", article_id: article.id, tweet: "Hello this is a test!" }
|
||||
expect(BufferUpdate.all.size).to eq(2)
|
||||
expect(BufferUpdate.last.article_id).to eq(article.id)
|
||||
end
|
||||
|
||||
it "updates last buffered at" do
|
||||
post "/admin/buffer_updates",
|
||||
params:
|
||||
{ social_channel: "main_twitter", article_id: article.id, tweet: "Hello this is a test" }
|
||||
expect(article.reload.last_buffered).not_to eq(nil)
|
||||
end
|
||||
|
||||
it "marks article as featured" do
|
||||
post "/admin/buffer_updates",
|
||||
params:
|
||||
{ social_channel: "main_twitter", article_id: article.id, tweet: "Hello this is a test" }
|
||||
expect(article.reload.featured).to be true
|
||||
end
|
||||
|
||||
it "updates last buffered at with satellite buffer" do
|
||||
post "/admin/buffer_updates",
|
||||
params:
|
||||
{ social_channel: "satellite_twitter", article_id: article.id, tweet: "Hello this is a test" }
|
||||
expect(article.reload.last_buffered).not_to eq(nil)
|
||||
end
|
||||
|
||||
it "updates last facebook buffered at" do
|
||||
post "/admin/buffer_updates",
|
||||
params:
|
||||
{ social_channel: "facebook", article_id: article.id, fb_post: "Hello this is a test" }
|
||||
expect(article.reload.facebook_last_buffered).not_to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /admin/buffer_updates" do
|
||||
let(:tag) { create(:tag) }
|
||||
let(:buffer_update) do
|
||||
BufferUpdate.create(article_id: article.id,
|
||||
composer_user_id: user.id,
|
||||
body_text: "This is text - #{rand(100)}",
|
||||
social_service_name: "twitter",
|
||||
tag_id: tag.id,
|
||||
status: "pending")
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in user
|
||||
user.add_role(:super_admin)
|
||||
end
|
||||
|
||||
it "sends to buffer" do
|
||||
put "/admin/buffer_updates/#{buffer_update.id}", params: {
|
||||
status: "confirmed", body_text: "test"
|
||||
}
|
||||
expect(buffer_update.reload.buffer_response).not_to eq(nil)
|
||||
expect(buffer_update.reload.status).to eq("confirmed")
|
||||
expect(buffer_update.reload.approver_user_id).to eq(user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe "BufferUpdates", type: :request do
|
||||
let(:user) { create(:user) }
|
||||
let(:mod_user) { create(:user) }
|
||||
let(:article) { create(:article, user_id: user.id) }
|
||||
let(:mod_article) { create(:article, user_id: mod_user.id) }
|
||||
let(:comment) { create(:comment, user_id: user.id, commentable: article) }
|
||||
|
||||
context "when trusted user is logged in" do
|
||||
before do
|
||||
sign_in mod_user
|
||||
mod_user.add_role(:trusted)
|
||||
end
|
||||
|
||||
it "creates buffer update for tweet if tweet params are passed" do
|
||||
post "/buffer_updates",
|
||||
params:
|
||||
{ buffer_update: { body_text: "This is the text!!!!", tag_id: "javascript", article_id: article.id } }
|
||||
expect(BufferUpdate.all.size).to eq(2)
|
||||
expect(BufferUpdate.last.body_text).to start_with("This is the text!!!!")
|
||||
expect(BufferUpdate.last.status).to eq("pending")
|
||||
end
|
||||
|
||||
it "creates buffer update with link" do
|
||||
post "/buffer_updates",
|
||||
params:
|
||||
{ buffer_update: { body_text: "This is the text!!!!", tag_id: "javascript", article_id: article.id } }
|
||||
expect(BufferUpdate.first.body_text).to include(article.path)
|
||||
end
|
||||
|
||||
it "creates buffer hashtag" do
|
||||
allow(SiteConfig).to receive(:twitter_hashtag).and_return("#DEVCommunity")
|
||||
post "/buffer_updates",
|
||||
params:
|
||||
{ buffer_update: { body_text: "This is the text!!!!", tag_id: "javascript", article_id: article.id } }
|
||||
expect(BufferUpdate.first.body_text).to include(SiteConfig.twitter_hashtag.to_s)
|
||||
end
|
||||
|
||||
it "creates satellite and Facebook buffer" do
|
||||
article.update_column(:cached_tag_list, "ruby, rails, meta")
|
||||
create(:tag, name: "rails")
|
||||
tag = create(:tag, buffer_profile_id_code: "placeholder", name: "ruby")
|
||||
post "/buffer_updates",
|
||||
params:
|
||||
{ buffer_update: { body_text: "This is the text!!!!", tag_id: "javascript", article_id: article.id } }
|
||||
expect(BufferUpdate.all.size).to eq(3)
|
||||
expect(BufferUpdate.second.tag_id).to eq(tag.id)
|
||||
expect(BufferUpdate.last.social_service_name).to eq("facebook")
|
||||
end
|
||||
end
|
||||
|
||||
context "when non-trusted user is logged in" do
|
||||
before do
|
||||
sign_in user
|
||||
mod_user.add_role(:trusted)
|
||||
end
|
||||
|
||||
it "rejects buffer update for non-trusted user" do
|
||||
expect do
|
||||
post "/buffer_updates",
|
||||
params:
|
||||
{ buffer_update: { body_text: "This is the text!!!!", tag_id: "javascript", article_id: mod_article.id } }
|
||||
end.to raise_error(Pundit::NotAuthorizedError)
|
||||
end
|
||||
|
||||
it "accepts buffer update from author of article" do
|
||||
post "/buffer_updates",
|
||||
params:
|
||||
{ buffer_update: { body_text: "This is the text!!!!", tag_id: "javascript", article_id: article.id } }
|
||||
expect(BufferUpdate.first.body_text).to include(article.path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Bufferizer::FacebookPost, type: :service do
|
||||
describe "#call" do
|
||||
let(:user) { create(:user) }
|
||||
let(:tag) { create(:tag, buffer_profile_id_code: "test") }
|
||||
let(:article) { create(:article, user_id: user.id, tags: tag.name) }
|
||||
|
||||
context "when article is nil" do
|
||||
it "doesn't raise an error" do
|
||||
post = "test post"
|
||||
expect { described_class.call(nil, post, user.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when post is nil" do
|
||||
it "doesn't raise an error" do
|
||||
expect { described_class.call(article, nil, user.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when admin_id is nil" do
|
||||
it "doesn't raise an error" do
|
||||
post = "test post"
|
||||
expect { described_class.call(article, post, nil) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
it "sends to buffer facebook" do
|
||||
post = "test facebook post"
|
||||
described_class.call(article, post, user.id)
|
||||
expect(article.facebook_last_buffered.utc.to_i).to be > 2.minutes.ago.to_i
|
||||
end
|
||||
|
||||
it "adds linkedin social tags" do
|
||||
post = "test facebook post"
|
||||
described_class.call(article, post, user.id)
|
||||
expect(BufferUpdate.last.body_text).to include(" #programming")
|
||||
expect(BufferUpdate.last.body_text).to include(" ##{article.tag_list.first}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Bufferizer::ListingsTweet, type: :service do
|
||||
describe "#call" do
|
||||
let(:user) { create(:user) }
|
||||
let(:listing) { create(:listing, user_id: user.id) }
|
||||
|
||||
context "when listing is nil" do
|
||||
it "doesn't raise an error" do
|
||||
tweet = "test tweet"
|
||||
expect { described_class.call(nil, tweet) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when tweet is nil" do
|
||||
it "doesn't raise an error" do
|
||||
expect { described_class.call(listing, nil) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
it "sends to buffer listings" do
|
||||
text = "test listing"
|
||||
described_class.call(listing, text)
|
||||
expect(listing.last_buffered).not_to be(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Bufferizer::MainTweet, type: :service do
|
||||
describe "#call" do
|
||||
let(:user) { create(:user) }
|
||||
let(:article) { create(:article, user_id: user.id) }
|
||||
|
||||
context "when article is nil" do
|
||||
it "doesn't raise an error" do
|
||||
tweet = "test tweet"
|
||||
expect { described_class.call(nil, tweet, user.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when tweet is nil" do
|
||||
it "doesn't raise an error" do
|
||||
expect { described_class.call(article, nil, user.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when admin_id is nil" do
|
||||
it "doesn't raise an error" do
|
||||
tweet = "test tweet"
|
||||
expect { described_class.call(article, tweet, nil) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
it "sends to buffer twitter" do
|
||||
tweet = "test tweet"
|
||||
described_class.call(article, tweet, user.id)
|
||||
expect(article.last_buffered.utc.to_i).to be > 2.minutes.ago.to_i
|
||||
end
|
||||
|
||||
it "includes admin approver" do
|
||||
tweet = "test tweet"
|
||||
described_class.call(article, tweet, user.id)
|
||||
expect(BufferUpdate.last.approver_user_id).to be user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Bufferizer::SatelliteTweet, type: :service do
|
||||
describe "#call" do
|
||||
let(:user) { create(:user) }
|
||||
let(:tag) { create(:tag, buffer_profile_id_code: "test") }
|
||||
let(:article) { create(:article, user_id: user.id, tags: tag.name) }
|
||||
|
||||
context "when article is nil" do
|
||||
it "doesn't raise an error" do
|
||||
tweet = "test tweet"
|
||||
expect { described_class.call(nil, tweet, user.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when tweet is nil" do
|
||||
it "doesn't raise an error" do
|
||||
expect { described_class.call(article, nil, user.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "when admin_id is nil" do
|
||||
it "doesn't raise an error" do
|
||||
tweet = "test tweet"
|
||||
expect { described_class.call(article, tweet, nil) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
it "sends to buffer sattelite twitter" do
|
||||
allow(SiteConfig).to receive(:twitter_hashtag).and_return("#DEVCommunity")
|
||||
tweet = "test tweet #{SiteConfig.twitter_hashtag}"
|
||||
described_class.call(article, tweet, user.id)
|
||||
expect(article.last_buffered.utc.to_i).to be > 2.minutes.ago.to_i
|
||||
expect(BufferUpdate.last.body_text).to include(" #{SiteConfig.twitter_hashtag} ##{tag.name} http")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -36,14 +36,6 @@ RSpec.describe Users::DeleteArticles, type: :service do
|
|||
expect(Comment.where(commentable_id: article.id, commentable_type: "Article").any?).to be false
|
||||
end
|
||||
|
||||
it "deletes articles' buffer updates" do
|
||||
BufferUpdate.buff!(article.id, "twitter_buffer_text")
|
||||
|
||||
described_class.call(user)
|
||||
|
||||
expect(BufferUpdate.where(article_id: article.id).any?).to be false
|
||||
end
|
||||
|
||||
it "busts cache" do
|
||||
described_class.call(user)
|
||||
expect(EdgeCache::BustComment).to have_received(:call).with(article).twice
|
||||
|
|
|
|||
|
|
@ -95,8 +95,6 @@ RSpec.describe Users::Delete, type: :service do
|
|||
affected_feedback_messages
|
||||
audit_logs
|
||||
banished_users
|
||||
buffer_updates_approved
|
||||
buffer_updates_composed
|
||||
created_podcasts
|
||||
offender_feedback_messages
|
||||
page_views
|
||||
|
|
|
|||
BIN
vendor/cache/buffer-0.1.3.gem
vendored
BIN
vendor/cache/buffer-0.1.3.gem
vendored
Binary file not shown.
BIN
vendor/cache/environs-1.1.0.gem
vendored
BIN
vendor/cache/environs-1.1.0.gem
vendored
Binary file not shown.
BIN
vendor/cache/faraday_middleware-1.0.0.gem
vendored
BIN
vendor/cache/faraday_middleware-1.0.0.gem
vendored
Binary file not shown.
BIN
vendor/cache/yajl-ruby-1.4.1.gem
vendored
BIN
vendor/cache/yajl-ruby-1.4.1.gem
vendored
Binary file not shown.
Loading…
Add table
Reference in a new issue