diff --git a/app/assets/stylesheets/admin/pages/publisher.scss b/app/assets/stylesheets/admin/pages/publisher.scss
index a1b9207bd7..e880aff91d 100644
--- a/app/assets/stylesheets/admin/pages/publisher.scss
+++ b/app/assets/stylesheets/admin/pages/publisher.scss
@@ -159,3 +159,14 @@
}
}
}
+
+.not-verified {
+ color: $braveGray-6;
+
+ img {
+ filter: grayscale(100%);
+ }
+ a {
+ color: $braveGray-6;
+ }
+}
diff --git a/app/assets/stylesheets/pages/home.scss b/app/assets/stylesheets/pages/home.scss
index ac136d83a0..f2c8a55352 100644
--- a/app/assets/stylesheets/pages/home.scss
+++ b/app/assets/stylesheets/pages/home.scss
@@ -232,9 +232,6 @@
}
.channel--promo-info-container {
- position: absolute;
- right: 24px;
-
@media only screen and (max-width: 520px) {
margin: 8px 0;
display: flex;
@@ -700,6 +697,11 @@
.channel-summary {
width: 100%;
+ // Apply a max width when the screen gets smaller to trim long channel names
+ @media only screen and (max-width: 768px) {
+ max-width: 10rem;
+ }
+
h3 {
font-size: 20px;
}
@@ -718,6 +720,13 @@
}
}
+ .channel-secondary-information {
+ @media only screen and (max-width: 560px) {
+ width: 100%;
+ margin: 0.5em 0;
+ }
+ }
+
&.channel-incomplete,
&.channel-started,
&.channel-failed {
@@ -870,7 +879,6 @@
}
&--intro {
- margin-bottom: 8px;
display: flex;
align-items: center;
}
@@ -901,7 +909,6 @@
.bat-channel {
&--amount {
font-size: 28px;
- font-weight: bolder;
display: inline;
line-height: 1;
}
@@ -1058,9 +1065,6 @@
overflow-y: auto;
max-height: calc(100vh - 150px);
}
- &--icon {
- margin: 0;
- }
}
.new-tag {
diff --git a/app/controllers/admin/publishers_controller.rb b/app/controllers/admin/publishers_controller.rb
index 8d3f343cba..d1dad12c43 100644
--- a/app/controllers/admin/publishers_controller.rb
+++ b/app/controllers/admin/publishers_controller.rb
@@ -112,7 +112,7 @@ def refresh_uphold
connection = UpholdConnection.find_by(publisher: params[:publisher_id])
if connection.present?
connection.sync_from_uphold!
- CreateUpholdCardsJob.perform_now(uphold_connection_id: connection.id)
+ connection.create_uphold_cards
end
redirect_to admin_publisher_path(@publisher.id)
end
diff --git a/app/controllers/publishers/uphold_controller.rb b/app/controllers/publishers/uphold_controller.rb
index c0775d0cdd..0bc155c638 100644
--- a/app/controllers/publishers/uphold_controller.rb
+++ b/app/controllers/publishers/uphold_controller.rb
@@ -32,7 +32,7 @@ def confirm_default_currency
uphold_connection.update(confirm_default_currency_params.merge(default_currency_confirmed_at: Time.now))
if uphold_connection.can_create_uphold_cards?
- uphold_connection.create_uphold_card_for_default_currency
+ uphold_connection.create_uphold_cards
# TODO do we need this refresh?
render(json: {
diff --git a/app/controllers/publishers_controller.rb b/app/controllers/publishers_controller.rb
index 5ec1669c5c..54456f9b57 100644
--- a/app/controllers/publishers_controller.rb
+++ b/app/controllers/publishers_controller.rb
@@ -212,7 +212,7 @@ def home
uphold_connection.sync_from_uphold!
# Handles legacy case where user is missing an Uphold card
- uphold_connection.create_uphold_card_for_default_currency if uphold_connection.missing_card?
+ uphold_connection.create_uphold_cards if uphold_connection.missing_card?
end
end
diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb
index 9a7a8aa431..8f5c19960c 100644
--- a/app/helpers/admin_helper.rb
+++ b/app/helpers/admin_helper.rb
@@ -77,12 +77,13 @@ def publisher_link(publisher)
end
def payout_report_status_header(account_type)
- report_date = PayoutReport.most_recent_final_report.created_at.strftime("%b %d")
+ report_date = PayoutReport.most_recent_final_report.created_at
+ report_date = report_date.strftime("%B #{report_date.day.ordinalize}")
if account_type == 'owner'
- "#{report_date}'s Payout Report Status (Referrals)"
+ "#{report_date} Payout (Referrals)"
else account_type == 'channel'
- "#{report_date}'s Payout Report Status (Contributions)"
+ "#{report_date} Payout Contributions"
end
end
end
diff --git a/app/javascript/views/admin/components/userNavbar/components/TopNav/TopNavStyle.ts b/app/javascript/views/admin/components/userNavbar/components/TopNav/TopNavStyle.ts
index 64d13a509d..e35f03d329 100644
--- a/app/javascript/views/admin/components/userNavbar/components/TopNav/TopNavStyle.ts
+++ b/app/javascript/views/admin/components/userNavbar/components/TopNav/TopNavStyle.ts
@@ -17,7 +17,6 @@ export const Container = styled.div`
display: none;
}
background-color: white;
- box-shadow: rgba(99, 105, 110, 0.18) 0px 1px 12px 0px;
padding: 28px;
margin-top: -53px;
`;
diff --git a/app/jobs/create_uphold_cards_job.rb b/app/jobs/create_uphold_cards_job.rb
index 2c3945c285..7d33c9bad7 100644
--- a/app/jobs/create_uphold_cards_job.rb
+++ b/app/jobs/create_uphold_cards_job.rb
@@ -9,8 +9,17 @@ def perform(uphold_connection_id:)
return
end
+ card = nil
+
# Search for an existing card
- card = uphold_connection.uphold_client.card.where(uphold_connection: uphold_connection)&.first
+ cards = uphold_connection.uphold_client.card.where(uphold_connection: uphold_connection)
+ existing_private_cards = UpholdConnectionForChannel.select(:card_id).where(uphold_connection: uphold_connection).to_a
+
+ cards.each do |c|
+ # We don't want to accidentally set the Publisher's card used for auto contribute and referral deposits into a channel card
+ # So we should check the address for the card and make sure that we haven't already used it
+ card = c and break if existing_private_cards.exclude?(c.id)
+ end
# If the card doesn't exist so we should create it
if card.blank?
diff --git a/app/jobs/create_uphold_channel_card_job.rb b/app/jobs/create_uphold_channel_card_job.rb
new file mode 100644
index 0000000000..df5568aac0
--- /dev/null
+++ b/app/jobs/create_uphold_channel_card_job.rb
@@ -0,0 +1,70 @@
+class CreateUpholdChannelCardJob < ApplicationJob
+ queue_as :default
+
+ def perform(uphold_connection_id:, channel_id:)
+ uphold_connection = UpholdConnection.find(uphold_connection_id)
+ channel = Channel.find(channel_id)
+ return unless uphold_connection&.is_member? && channel&.verified?
+
+ unless uphold_connection.can_create_uphold_cards?
+ Rails.logger.info("Could not create uphold card for channel #{uphold_connection.publisher_id}. Uphold Verified: #{uphold_connection.uphold_verified}")
+ return
+ end
+
+ upfc = UpholdConnectionForChannel.find_by(
+ uphold_connection: uphold_connection,
+ currency: uphold_connection.default_currency,
+ channel_identifier: channel.details.channel_identifier
+ )
+
+ if upfc.present?
+ card_id = upfc.card_id
+ else
+ (card_id, upfc) = create_card(uphold_connection, channel)
+ end
+
+ # If the channel was deleted and then recreated we should update this to be the new channel id
+ upfc.update(
+ address: get_address(uphold_connection, card_id),
+ channel_id: channel.id
+ )
+ end
+
+ def create_card(uphold_connection, channel)
+ card_label = "#{channel.type_display} - #{channel.details.publication_title} - Brave Rewards"
+
+ # If the card doesn't exist so we should create it
+ card_id = uphold_connection.uphold_client.card.create(
+ uphold_connection: uphold_connection,
+ currency: uphold_connection.default_currency,
+ label: card_label
+ ).id
+
+ upfc = UpholdConnectionForChannel.create(
+ uphold_connection: uphold_connection,
+ channel: channel,
+ card_id: card_id,
+ currency: uphold_connection.default_currency,
+ channel_identifier: channel.details.channel_identifier
+ )
+
+ [card_id, upfc]
+ end
+
+ def get_address(uphold_connection, card_id)
+ addresses = uphold_connection.uphold_client.address.all(
+ uphold_connection: uphold_connection,
+ id: card_id
+ )
+ address = addresses.detect { |a| a.type == UpholdConnectionForChannel::NETWORK }
+ address = address.formats.first.dig('value') if address.present?
+
+ return address if address.present?
+
+ uphold_connection.uphold_client.address.create(
+ uphold_connection: uphold_connection,
+ id: card_id,
+ network: UpholdConnectionForChannel::NETWORK
+ )
+ end
+end
diff --git a/app/jobs/migrate_uphold_access_parameters_job.rb b/app/jobs/migrate_uphold_access_parameters_job.rb
index c4690a45fd..a5037b81e8 100644
--- a/app/jobs/migrate_uphold_access_parameters_job.rb
+++ b/app/jobs/migrate_uphold_access_parameters_job.rb
@@ -19,7 +19,7 @@ def perform(publisher_id:, parameters:, default_currency:)
connection.reload
# Sync the uphold card or create it if the card is missing
- CreateUpholdCardsJob.perform_later(uphold_connection_id: connection.id)
+ connection.create_uphold_cards
else
Rails.logger.info("Couldn't find publisher #{publisher_id} in creator's database but exists on mongo owner's database (Probably not a big deal)")
end
diff --git a/app/models/channel.rb b/app/models/channel.rb
index 3f515cf540..c2a4bd5500 100644
--- a/app/models/channel.rb
+++ b/app/models/channel.rb
@@ -48,6 +48,7 @@ class Channel < ApplicationRecord
}, foreign_key: 'details_id'
has_one :promo_registration, dependent: :destroy
+ has_many :uphold_connection_for_channel
has_one :contesting_channel, class_name: "Channel", foreign_key: 'contested_by_channel_id'
@@ -76,7 +77,7 @@ class Channel < ApplicationRecord
validate :verified_duplicate_channels_must_be_contested, if: -> { verified? }
after_save :register_channel_for_promo, if: :should_register_channel_for_promo
- after_save :notify_slack, if: :saved_change_to_verified?
+ after_save :create_channel_card, :notify_slack, if: -> { :saved_change_to_verified? && verified? }
before_save :clear_verified_at_if_necessary
@@ -360,6 +361,10 @@ def most_recent_potential_payment
PayoutReport.most_recent_final_report&.potential_payments&.where(channel_id: id)&.first
end
+ def uphold_connection
+ @uphold_connection ||= UpholdConnectionForChannel.joins(:uphold_connection).where(channel_id: id).where("uphold_connections.default_currency = uphold_connection_for_channels.currency").first
+ end
+
private
def should_register_channel_for_promo
@@ -376,6 +381,10 @@ def register_channel_for_promo
Promo::RegisterChannelForPromoJob.new.perform(channel: self)
end
+ def create_channel_card
+ CreateUpholdChannelCardJob.perform_later(uphold_connection_id: publisher.uphold_connection&.id, channel_id: id)
+ end
+
def notify_slack
return unless verified?
emoji =
diff --git a/app/models/json_builders/channels_json_builder_v2.rb b/app/models/json_builders/channels_json_builder_v2.rb
index e4e4cb86b4..a3c722ee7e 100644
--- a/app/models/json_builders/channels_json_builder_v2.rb
+++ b/app/models/json_builders/channels_json_builder_v2.rb
@@ -55,9 +55,9 @@ def include_verified_channel(verified_channel)
# Skip if channel publisher has not yet KYC'd
return unless verified_channel.publisher&.uphold_connection&.is_member
- wallet_address_id = verified_channel.publisher&.uphold_connection&.address
+ wallet_address_id = verified_channel.uphold_connection&.address
+
return if wallet_address_id.nil?
- return if existing_wallet_address?(wallet_address_id)
@channels.push([
verified_channel.details.channel_identifier,
diff --git a/app/models/uphold_connection.rb b/app/models/uphold_connection.rb
index 3b4d1a7c45..cb79ea8866 100644
--- a/app/models/uphold_connection.rb
+++ b/app/models/uphold_connection.rb
@@ -26,6 +26,8 @@ class UpholdAccountState
belongs_to :publisher
+ has_many :uphold_connection_for_channels
+
# uphold_code is an intermediate step to acquiring uphold_access_parameters
# and should be cleared once it has been used to get uphold_access_parameters
validates :uphold_code, absence: true, if: -> { uphold_access_parameters.present? || uphold_verified? }
@@ -38,7 +40,7 @@ class UpholdAccountState
}
# If the user became KYC'd let's create the uphold card for them
- after_save :create_uphold_card_for_default_currency, if: -> { saved_change_to_is_member? && is_member? }
+ after_save :create_uphold_cards, if: -> { saved_change_to_is_member? && uphold_verified? }
# publishers that have access params that havent accepted by eyeshade
# can be cleared after 2 hours
@@ -141,9 +143,14 @@ def wallet
@wallet ||= publisher&.wallet
end
- def create_uphold_card_for_default_currency
+ def create_uphold_cards
return unless can_create_uphold_cards?
+
CreateUpholdCardsJob.perform_now(uphold_connection_id: id)
+
+ publisher.channels.each do |channel|
+ CreateUpholdChannelCardJob.perform_now(uphold_connection_id: id, channel_id: channel.id)
+ end
end
def missing_card?
diff --git a/app/models/uphold_connection_for_channel.rb b/app/models/uphold_connection_for_channel.rb
new file mode 100644
index 0000000000..dc33d8c916
--- /dev/null
+++ b/app/models/uphold_connection_for_channel.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# Creates a connection between uphold and a channel
+#
+# We use this to look up existing cards. If a user deletes a channel then we should not destroy this.
+# Really the only time we should delete is if the uphold connection gets deleted, which should only happen if the publisher
+class UpholdConnectionForChannel < ApplicationRecord
+ belongs_to :uphold_connection
+ belongs_to :channel
+
+ NETWORK = 'anonymous'
+
+ validates :channel_identifier, uniqueness: { scope: [:uphold_connection_id, :channel_identifier, :currency] }
+end
diff --git a/app/services/payout_report_publisher_includer.rb b/app/services/payout_report_publisher_includer.rb
index e173305f64..4791bc87b7 100644
--- a/app/services/payout_report_publisher_includer.rb
+++ b/app/services/payout_report_publisher_includer.rb
@@ -14,7 +14,7 @@ def perform
uphold_connection.sync_from_uphold!
if uphold_connection.missing_card?
- uphold_connection.create_uphold_card_for_default_currency
+ uphold_connection.create_uphold_cards
end
probi = wallet.referral_balance.amount_probi # probi = balance
diff --git a/app/services/uphold/client.rb b/app/services/uphold/client.rb
index 6e7db5cff6..0150ba18d2 100644
--- a/app/services/uphold/client.rb
+++ b/app/services/uphold/client.rb
@@ -4,6 +4,10 @@ def initialize(params = {})
@connection = connection
end
+ def address
+ @address ||= Uphold::Models::Address.new
+ end
+
def card
@card ||= Uphold::Models::Card.new
end
diff --git a/app/services/uphold/models/address.rb b/app/services/uphold/models/address.rb
new file mode 100644
index 0000000000..a9a19d762c
--- /dev/null
+++ b/app/services/uphold/models/address.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'addressable/template'
+
+module Uphold
+ module Models
+ class Address < Client
+ include Initializable
+
+ # For more information about how these URI templates are structured read the explaination in the RFC
+ # https://www.rfc-editor.org/rfc/rfc6570.txt
+ PATH = Addressable::Template.new("/v0/me/cards/{id}/addresses")
+
+ attr_accessor :formats, :type
+
+ def initialize(params = {})
+ super
+ end
+
+ # Lists all the addresses a specified card has
+ #
+ # @param [UpholdConnection] connection The uphold connection to find.
+ # @param [string] iid The id of the card you want to find.
+ #
+ # @return [Uphold::Models::Address[]] an array of th addresses
+ def all(uphold_connection:, id: nil)
+ Rails.logger.info("Connection #{uphold_connection.id} is missing uphold_access_parameters") and return if uphold_connection.uphold_access_parameters.blank?
+ id = uphold_connection.address if id.blank?
+
+ response = get(PATH.expand(id: id), {}, authorization(uphold_connection))
+
+ JSON.parse(response.body).map { |a| Address.new(a) }
+ end
+
+ # Creates an address for a given card
+ #
+ # @param [string] network Network for the card, must be one of ["anonymous", "bitcoin", "bitcoin-cash", "bitcoin-gold", "dash", "ethereum", "litecoin", "voxel", "xrp-ledger"]
+ #
+ # @returns the id for the address
+ def create(uphold_connection:, id:, network: "anonymous")
+ Rails.logger.info("Connection #{uphold_connection.id} is missing uphold_access_parameters") and return if uphold_connection.uphold_access_parameters.blank?
+
+ response = post(PATH.expand(id: id), { network: network }, authorization(uphold_connection))
+
+ JSON.parse(response.body).dig('id')
+ end
+
+ def authorization(uphold_connection)
+ token = JSON.parse(uphold_connection.uphold_access_parameters || "{}").try(:[], "access_token")
+ "Authorization: Bearer #{token}"
+ end
+ end
+ end
+end
diff --git a/app/services/uphold/models/card.rb b/app/services/uphold/models/card.rb
index 6eb791d71b..d4373c238c 100644
--- a/app/services/uphold/models/card.rb
+++ b/app/services/uphold/models/card.rb
@@ -74,6 +74,7 @@ def create(uphold_connection:, currency: nil, label: "Brave Rewards")
params = {
currency: currency || uphold_connection.default_currency,
label: label,
+ settings: { starred: true },
}
response = post(PATH, params, authorization(uphold_connection))
diff --git a/app/views/admin/publishers/_channel.html.slim b/app/views/admin/publishers/_channel.html.slim
new file mode 100644
index 0000000000..39f2536b6d
--- /dev/null
+++ b/app/views/admin/publishers/_channel.html.slim
@@ -0,0 +1,135 @@
+
+.m-3 class=(channel.verified? ? '' : 'not-verified')
+ / This is information for this
+ div
+ / Container for the title, contributions and referrals
+ div
+ / Title
+ div
+ small.text-muted TITLE
+ .d-flex
+ h5.m-0.font-weight-bold
+ img src=(channel_type_icon_url(channel)) width=16 height=16 class="mr-3"
+ = link_to(channel.publication_title, channel.details.url, target: '_blank')
+
+ - if channel.details.is_a?(SiteChannelDetails)
+ .d-flex.align-items-center
+ .text-muted.mx-3= "|"
+ - case channel.details.verification_method
+ - when "dns_record"
+ = fa_icon "server", class: 'text-muted'
+ - when "public_file"
+ = fa_icon "file-o", class: 'text-muted'
+ - when "wordpress"
+ = fa_icon "wordpress", class: 'text-muted'
+ span.text-muted.ml-2 data-tooltip="Verification method"
+ = channel.details.verification_method
+
+ - if channel.uphold_connection.blank? && channel.verified?
+ .mt-3
+ .rounded.p-3.alert-warning
+ .d-flex.align-items-center.mb-2
+ =fa_icon "exclamation-circle", class: 'mr-2'
+ .font-weight-bold This channel does not have an associated Uphold card.
+ div In newer versions of Brave this channel will no longer appear has verified. In order to resolve this the creator must verify their identity with Uphold.
+
+
+ / This is the details and statistics information
+ - if channel.verified?
+ .d-flex.mt-3
+ div
+ div
+ small.text-muted CONTRIBUTIONS
+ .d-flex
+ h6.font-weight-bold= publisher_channel_bat_balance(@publisher, channel.details.channel_identifier)
+ small.ml-1 BAT
+
+ - if channel.promo_registration.present?
+ div
+ div.mr-5
+ small.text-muted REFERRAL CODE
+ h6.m-0.font-weight-bold= channel.promo_registration.referral_code
+
+
+ .d-flex
+ - potential_contribution_payment = channel.most_recent_potential_payment
+ - if potential_contribution_payment.present?
+ .border-right.mx-3
+ .d-flex.flex-column.d-inline-flex
+ span.mb-1.text-wrap=payout_report_status_header('channel')
+ small.text-muted AMOUNT
+ div
+ span.font-weight-bold= "#{(potential_contribution_payment.amount.to_d * 1/1E18).round(2)}"
+ small.mt-1.ml-1 BAT
+
+ .d-flex
+ - if channel.promo_registration.present?
+ .border-right.mx-3
+ div
+ span Referral Statistics
+ - totals = channel.promo_registration.aggregate_stats
+ - if totals.present?
+ .d-flex
+ div.mr-3
+ small.text-muted DOWNLOADED
+ .font-weight-bold.text-center= totals[PromoRegistration::RETRIEVALS]
+ div.mx-3
+ small.text-muted INSTALLED
+ .font-weight-bold.text-center= totals[PromoRegistration::FIRST_RUNS]
+ div.mx-3
+ small.text-muted CONFIRMED
+ .font-weight-bold.text-center= totals[PromoRegistration::FINALIZED]
+
+
+ div
+ - if channel.details.stats.is_a?(Hash)
+ .border-right.mx-3
+ div
+ span Channel Statistics
+ .d-flex
+ - channel.details.stats.keys.each do |key|
+ - if channel.details.stats[key].present? && key.exclude?("comment")
+ div.mx-3.text-center
+ small.text-muted= "#{key.upcase.gsub("_", " ")}"
+ .font-weight-bold
+ = number_with_delimiter(channel.details.stats[key])
+
+ / When the channel is being contested
+ - if channel.verification_pending?
+ small= link_to "Channel is being contested", admin_channel_transfer_path(@publisher)
+ - elsif !channel.verified?
+ / Unverified channel, let the admins know
+ .mt-2
+ = fa_icon "exclamation-circle", class: 'mr-2'
+ span Unverified
+
+
+ - if channel.verification_awaiting_admin_approval?
+ .d-flex.align-items-center
+ span.text-danger= "Admin approval required"
+ .admin-approval-button.ml-2
+ = form_for channel, as: :channel, method: :patch, url: approve_channel_admin_publishers_path(channel_id: channel.id) do |f|
+ = f.submit("Approve", class: "btn btn-primary")
+ - elsif channel.verification_approved_by_admin?
+ .mt-3
+ small.text-muted= "Admin approved"
+
+ - if channel.uphold_connection.present?
+
+ small
+ a id="view_more_#{channel.id}" href="#" View More
+ div.toggle.d-none id="more_info_#{channel.id}"
+ small.text-muted= "UPHOLD CARD"
+ table.table.small.d-inline-flex
+ tr
+ td Card ID
+ td= channel.uphold_connection.card_id
+ tr
+ td Address
+ td= channel.uphold_connection.address
+ tr
+ td Currency
+ td= channel.uphold_connection.currency
+ javascript:
+ document.getElementById("view_more_#{channel.id}").onclick = function anonymous() { document.getElementById("more_info_#{channel.id}").classList.toggle("d-none"); return false; }
+
diff --git a/app/views/admin/publishers/_uphold.html.slim b/app/views/admin/publishers/_uphold.html.slim
index f18b26b979..9765ba01c7 100644
--- a/app/views/admin/publishers/_uphold.html.slim
+++ b/app/views/admin/publishers/_uphold.html.slim
@@ -29,7 +29,7 @@ h3.text-dark.d-flex.align-items-center
= @publisher.uphold_connection.is_member? ? fa_icon("check", text: "Yes") : fa_icon("times", text: "No")
tr
td Uphold ID
- td= link_to @publisher.uphold_connection.uphold_id, admin_publishers_path(q: @publisher.uphold_connection.uphold_id)
+ td= link_to_if @publisher.uphold_connection.uphold_id, @publisher.uphold_connection.uphold_id, admin_publishers_path(q: @publisher.uphold_connection.uphold_id)
tr
td Country
td= @publisher.uphold_connection.country
diff --git a/app/views/admin/publishers/show.html.slim b/app/views/admin/publishers/show.html.slim
index ca8c3a8909..805c12c895 100644
--- a/app/views/admin/publishers/show.html.slim
+++ b/app/views/admin/publishers/show.html.slim
@@ -8,11 +8,13 @@ div.row
= submit_tag("Search", class: 'btn btn-default')
hr
#publisher
- #publisher-section
+ #publisher-section.shadow-sm
= render partial: 'admin/shared/publisher_header', locals: { navigation_view: @navigation_view }
+ .border-top
- .rounded-box.split-row-container
+ .p-4.split-row-container.bg-white
.split-row
+ h5= "Overview"
.db-info-row
.db-field = "ID:"
.db-value = @publisher.id
@@ -69,7 +71,7 @@ hr
.db-value= @referral_owner_status
#statement-section.split-row
- h3.admin-header = "Statements"
+ h5.admin-header = "Statements"
.statement
= link_to("this month", statement_admin_publishers_path(publisher_id: @publisher.id, statement_period: "this_month"))
.statement
@@ -78,7 +80,7 @@ hr
= link_to("all", statement_admin_publishers_path(publisher_id: @publisher.id, statement_period: "all"))
.payout-report-status-section
- if @potential_referral_payment.present?
- h4= payout_report_status_header('owner')
+ h5= payout_report_status_header('owner')
.db-info-row
.db-field = "Uphold status"
.db-value = @potential_referral_payment.uphold_status || 'unavailable'
@@ -87,7 +89,7 @@ hr
.db-field = "Reauthorization status"
.db-value = @potential_referral_payment.reauthorization_needed
.db-info-row
- .db-field = "Uphold membership stattus"
+ .db-field = "Uphold membership status"
.db-value = @potential_referral_payment.uphold_member
- if @potential_referral_payment.suspended
.db-info-row
@@ -101,61 +103,22 @@ hr
.db-field = "Approx. amount"
.db-value = "#{@potential_referral_payment.amount.to_d * 1/1E18} BAT"
- .c-4.shadow-sm.rounded.p-3.my-4
+ .c-4.shadow-sm.bg-white.rounded.p-3.my-4
= render partial: 'uphold'
-if @publisher.partner?
- hr
- =render partial: "invoices", locals: { partner: @publisher.becomes(Partner), limit: params[:view_more].present? ? nil : 3 }
-
- h3.admin-header = "Channels (#{@publisher.channels.count})"
- #channels-section
- - @publisher.channels.each do |channel|
- .channel
- .channel-link
- = link_to(on_channel_type(channel), channel.details.url)
- .channel-info
- - if channel.verification_awaiting_admin_approval?
- .admin-approval
- span.admin-approval-warning = "Admin approval required"
- span.admin-approval-button
- = form_for channel, as: :channel, method: :patch, url: approve_channel_admin_publishers_path(channel_id: channel.id) do |f|
- = f.submit("Approve", class: "btn btn-primary")
- hr
- - elsif channel.verification_approved_by_admin?
- .admin-approval
- span.admin-approval-success = "Admin approved"
- hr
- .db-info-row
- .db-field = "Channel BAT balance"
- .db-value = publisher_channel_bat_balance(@publisher, channel.details.channel_identifier)
- - if channel.details.is_a?(SiteChannelDetails)
- .db-info-row
- .db-field = "Verified"
- .db-value = channel.verified?
- .db-info-row
- .db-field = "Verification Method"
- .db-value = channel.details.verification_method
- .db-info-row
- .db-field = "Token"
- .db-value.token = channel.details.verification_token
- - if channel.promo_registration.present?
- .db-info-row
- .db-field = "Referral code:"
- .db-value = channel.promo_registration.referral_code
- - if channel.verified?
- .payout-report-status-section
- - potential_contribution_payment = channel.most_recent_potential_payment
- - if potential_contribution_payment.present?
- h4= payout_report_status_header('channel')
- .db-info-row
- .db-field = "Approx. amount"
- .db-value = "#{potential_contribution_payment.amount.to_d * 1/1E18} BAT"
-
+ .c-4.shadow-sm.bg-white.rounded.p-3.my-4
+ =render partial: "invoices", locals: { partner: @publisher.becomes(Partner), limit: params[:view_more].present? ? nil : 3 }
- hr
+ .c-4.shadow-sm.bg-white.rounded.p-3.my-4
+ h3.text-dark Channels
+ #channels-section
+ - @publisher.channels.each do |channel|
+ = render partial: 'channel', locals: { channel: channel }
+ - unless channel == @publisher.channels.last
+ hr
- .c-4.shadow-sm.rounded.p-3.accordion.mb-4
+ .c-4.shadow-sm.bg-white.rounded.p-3.my-4
.panel
input type="checkbox" name="panels" id="panel_id"
label for="panel_id"
@@ -164,7 +127,7 @@ hr
= render partial: 'admin/publisher_notes/form', locals: { note: PublisherNote.new, publisher: @publisher }
- .c-4.shadow-sm.rounded.p-3.mt-4
+ .c-4.shadow-sm.bg-white.rounded.p-3.my-4
h3.text-dark.d-flex.align-items-center
small=fa_icon "hourglass-half", class: 'mx-2'
= "History"
@@ -184,5 +147,12 @@ hr
+javascript:
+ window.addEventListener("keydown",function (e) {
+ if ((e.ctrlKey || e.metaKey) && e.keyCode === 70) {
+ document.querySelectorAll('.toggle').forEach((i) => i.classList.toggle('d-none'))
+ }
+ })
+
= javascript_pack_tag 'tribute'
= stylesheet_pack_tag 'tribute'
diff --git a/app/views/admin/shared/_publisher_header.html.slim b/app/views/admin/shared/_publisher_header.html.slim
index 73be8b7bd2..2bf3045567 100644
--- a/app/views/admin/shared/_publisher_header.html.slim
+++ b/app/views/admin/shared/_publisher_header.html.slim
@@ -1,2 +1,2 @@
=javascript_pack_tag "UserNavbar"
-.mt-5.mb-3#publisherHeader data-props=navigation_view
+.mt-5#publisherHeader data-props=navigation_view
diff --git a/app/views/publishers/_channel.html.slim b/app/views/publishers/_channel.html.slim
index 85388b261f..b040f006f5 100644
--- a/app/views/publishers/_channel.html.slim
+++ b/app/views/publishers/_channel.html.slim
@@ -1,90 +1,92 @@
.row.channel-row id=("channel_row_#{channel.id}") data-remove-message=(t("shared.channel_removed"))
.col.mb-4
div class=("channel-panel channel-#{channel_verification_status(channel)}")
- .channel-panel--intro
+ .channel-panel--intro.mb-1
.channel-panel--intro-icon
img src=(channel_type_icon_url(channel)) width=16 height=16
.channel-panel--intro-body
= channel_type(channel).upcase
- - if channel.verified?
- - if current_publisher.promo_status(promo_running?) == :active && channel.promo_enabled? && !current_publisher.only_user_funds?
- .channel--promo-info-container
- = link_to("", tweet_url(channel.promo_registration.referral_code), target: :_blank, class: "promo-share-button promo-share-button-twitter")
- = link_to("", facebook_url(channel.promo_registration.referral_code), target: :_blank, class: "promo-share-button promo-share-button-facebook")
- .referral-link-url.promo-info-item
- span= https_referral_url(channel.promo_registration.referral_code)
- .referral-link-button.referral-link-button-desktop.promo-info-item
- span= t("promo.shared.referral_link")
- .referral-link-button.referral-link-button-mobile.promo-info-item.copy-button data-clipboard-text="#{https_referral_url(channel.promo_registration.referral_code)}"
- span= t("promo.shared.referral_link")
- .referral-link-copy-button.promo-info-item.copy-button data-clipboard-text="#{https_referral_url(channel.promo_registration.referral_code)}"
- span= t("promo.shared.copy")
- / Need to tell the users that it will take 48 hours for their verified channel to appear in the web browser
- - if channel.created_at > 2.days.ago
- .channel-info
- .info-popup
- .info--details
- // JS will break if the next two elements aren't siblings
- span.info--what-happened=t(".verification_status_title")
- span.info--explanation
- span.verification-failed-explanation--content
- = t(".verification_status")
- - else
- .channel-status.float-right
+
+ .d-flex.justify-content-between.align-items-center.flex-wrap
+ / Channel name
+ div.my-1
+ .channel-summary
+ h3.text-truncate= channel.publication_title
+
+ / The secondary information on the tile, balance, etc
+ div.channel-secondary-information.d-flex.justify-content-between
+ / Show the balance if the channel has been verified
+ - if channel.verified?
.bat-channel
h4.bat-channel--amount id=("channel_amount_bat_#{channel.details.channel_identifier}")
= publisher_channel_bat_balance(current_publisher, channel.details.channel_identifier)
span.bat-channel--currency= " BAT"
.bat-channel--period
- = t(".channel_balance_period")
- .channel-summary
- h3= channel.publication_title
- .channel-details
- .added-date
- = t(".added", date: channel.created_at.to_date.iso8601)
- span.separator
- = ' | '
- a.remove-channel href="#" data-channel-id=(channel.id)
- = t(".remove_verified")
- script type="text/html" data-js-channel-removal-confirmation-template=(channel.id)
- = render "publishers/remove_channel_modal", channel: channel
- = form_for(channel, html: {id: "remove_channel_#{channel.id}"}) do |f|
- - elsif channel.verification_failed?
- .channel-status.float-right
- .verification-failed
- .verification-failed--header
- = t("helpers.channels.verification_failure")
- .verification-failed--details
- // JS will break if the next two elements aren't siblings
- span.verification-failed--what-happened=t("helpers.channels.verification_failure_what_happened")
- span.verification-failed--explanation
- span.verification-failed-explanation--content
- = channel_verification_details(channel).upcase_first
- span.separator
- = ' | '
- a.remove-channel href="#" data-channel-id=(channel.id)
- = t(".remove_verified")
- script type="text/html" data-js-channel-removal-confirmation-template=(channel.id)
- = render "publishers/remove_channel_modal", channel: channel
- = form_for(channel, html: {id: "remove_channel_#{channel.id}"}) do |f|
- = link_to(t(".try_again"), channel_next_step_path(channel), class: "btn btn-primary try-again")
- - elsif channel.verification_pending?
- .channel-status.float-right
- = t("shared.channel_contested", time_until_transfer: time_until_transfer(channel))
- - elsif channel.verification_awaiting_admin_approval?
- .channel-status.float-right
- = t("helpers.channels.verification_awaiting_admin_approval")
- - else
- .channel-status.float-right
- = link_to(t(".lets_finish"), channel_next_step_path(channel), class: "btn btn-primary")
- .channel-progress.float-right
- .one-more-step= t(".one_more_step")
- - unless channel.verified
- .channel-summary
- h3.unverified = channel.publication_title
+ small= t(".channel_balance_period")
+
+ / Show the promo registration if the promo is running
+ - if current_publisher.promo_status(promo_running?) == :active && channel.promo_enabled? && !current_publisher.only_user_funds?
+ .d-flex.channel--promo-info-container.ml-3
+ .d-none.d-sm-block
+ = link_to("", tweet_url(channel.promo_registration.referral_code), target: :_blank, class: "promo-share-button promo-share-button-twitter")
+ = link_to("", facebook_url(channel.promo_registration.referral_code), target: :_blank, class: "promo-share-button promo-share-button-facebook")
+ div
+ .referral-link-url.promo-info-item
+ span= https_referral_url(channel.promo_registration.referral_code)
+ .referral-link-button.referral-link-button-desktop.promo-info-item
+ span= t("promo.shared.referral_link")
+ .referral-link-button.referral-link-button-mobile.promo-info-item.copy-button data-clipboard-text="#{https_referral_url(channel.promo_registration.referral_code)}"
+ span= t("promo.shared.referral_link")
+ .referral-link-copy-button.promo-info-item.copy-button data-clipboard-text="#{https_referral_url(channel.promo_registration.referral_code)}"
+ span= t("promo.shared.copy")
+
+ / If the verification failed we should tell the user
+ - if channel.verification_failed?
+ .channel-status
+ .verification-failed
+ .verification-failed--header
+ = t("helpers.channels.verification_failure")
+ .verification-failed--details
+ // JS will break if the next two elements aren't siblings
+ span.verification-failed--what-happened=t("helpers.channels.verification_failure_what_happened")
+ span.verification-failed--explanation
+ span.verification-failed-explanation--content
+ = channel_verification_details(channel).upcase_first
+ .ml-2
+ = link_to(t(".try_again"), channel_next_step_path(channel), class: "btn btn-primary try-again")
+
+
+ - if channel.verification_pending?
+ span.channel-contested= t("shared.channel_contested", time_until_transfer: time_until_transfer(channel))
+ - elsif channel.verification_awaiting_admin_approval?
+ = t("helpers.channels.verification_awaiting_admin_approval")
+ - elsif !channel.verified? && !channel.verification_failed?
+ .channel-progress
+ .one-more-step= t(".one_more_step")
+ .channel-status
+ = link_to(t(".lets_finish"), channel_next_step_path(channel), class: "btn btn-primary")
+
+ .d-flex.flex-wrap
+ .added-date.d-none.d-sm-block
+ = t(".added", date: channel.created_at.to_date.iso8601)
+ span.mx-2= ' | '
+ - if channel.uphold_connection.present?
+ =image_tag 'uphold.svg', style: "width: 18px; height: 18px; margin-top: 3px;"
+ =link_to(t('.uphold'), "#{uphold_dashboard_url}/cards/#{channel.uphold_connection.card_id}", class: 'px-1', target: "_blank")
+ span.mx-2
+ = ' | '
+ a.remove-channel href="#" data-channel-id=(channel.id)
+ = t(".remove_verified")
+ script type="text/html" data-js-channel-removal-confirmation-template=(channel.id)
+ = render "publishers/remove_channel_modal", channel: channel
+ = form_for(channel, html: {id: "remove_channel_#{channel.id}"}) do |f|
+
+
+
- if channel.contested_by_channel
.channel-contested
p = t "shared.channel_contested_by", time_until_transfer: time_until_transfer(channel.contested_by_channel),
verified_by_email: channel.contested_by_channel.publisher.email
a.reject_transfer href=token_reject_transfer_url(channel, channel.contest_token)
= t ".reject_transfer"
+
diff --git a/app/views/static/index.html b/app/views/static/index.html
index 75034cedd0..d8b2566450 100644
--- a/app/views/static/index.html
+++ b/app/views/static/index.html
@@ -1 +1 @@
-
Earn more for content you publish to the web - Brave Creators
\ No newline at end of file
+Earn more for content you publish to the web - Brave Creators
\ No newline at end of file
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 15dcca7806..381b08330b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -609,13 +609,15 @@ en:
update: Update
channel:
added: added %{date}
- remove_verified: Remove Channel
+ remove_verified: Remove channel
one_more_step: One more step to complete...
- lets_finish: Let's Finish
- try_again: Try Again
+ lets_finish: Let's finish
+ try_again: Try again
verification_status: Verification status will be displayed in the Brave browser within the next 24-48 hours
verification_status_title: Verification Information
channel_balance_period: CURRENT PERIOD
+ uphold: Uphold
+ reject_transfer: Reject transfer
omniauth_callbacks:
register_youtube_channel:
channel_already_registered: You have already registered this YouTube channel.
diff --git a/db/migrate/20190730162819_create_uphold_connection_for_channel.rb b/db/migrate/20190730162819_create_uphold_connection_for_channel.rb
new file mode 100644
index 0000000000..b3220f17df
--- /dev/null
+++ b/db/migrate/20190730162819_create_uphold_connection_for_channel.rb
@@ -0,0 +1,15 @@
+class CreateUpholdConnectionForChannel < ActiveRecord::Migration[5.2]
+ def change
+ create_table :uphold_connection_for_channels, id: :uuid, default: -> { "uuid_generate_v4()"}, force: :cascade do |t|
+ t.belongs_to :uphold_connection, type: :uuid, index: true, null: false
+ t.belongs_to :channel, type: :uuid, index: true, null: false
+
+ t.string :currency, index: true
+ t.string :channel_identifier, index: true
+ t.string :card_id
+ t.string :address
+ end
+
+ add_index :uphold_connection_for_channels, [:channel_identifier, :currency, :uphold_connection_id], unique: true, name: 'unique_uphold_connection_for_channels'
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 9fc89cfc63..ac7aadd90c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_07_17_030948) do
+ActiveRecord::Schema.define(version: 2019_07_30_162819) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -505,6 +505,20 @@
t.index ["publisher_id"], name: "index_u2f_registrations_on_publisher_id"
end
+ create_table "uphold_connection_for_channels", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t|
+ t.uuid "uphold_connection_id", null: false
+ t.uuid "channel_id", null: false
+ t.string "currency"
+ t.string "channel_identifier"
+ t.string "card_id"
+ t.string "address"
+ t.index ["channel_id"], name: "index_uphold_connection_for_channels_on_channel_id"
+ t.index ["channel_identifier", "currency", "uphold_connection_id"], name: "unique_uphold_connection_for_channels", unique: true
+ t.index ["channel_identifier"], name: "index_uphold_connection_for_channels_on_channel_identifier"
+ t.index ["currency"], name: "index_uphold_connection_for_channels_on_currency"
+ t.index ["uphold_connection_id"], name: "index_uphold_connection_for_channels_on_uphold_connection_id"
+ end
+
create_table "uphold_connections", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t|
t.string "uphold_state_token"
t.boolean "uphold_verified", default: false
diff --git a/lib/tasks/database_updates/create_cards_for_channels.rake b/lib/tasks/database_updates/create_cards_for_channels.rake
new file mode 100644
index 0000000000..f211b702dc
--- /dev/null
+++ b/lib/tasks/database_updates/create_cards_for_channels.rake
@@ -0,0 +1,16 @@
+namespace :database_updates do
+ task :create_cards_for_channels => :environment do
+
+ completed_kyc = UpholdConnection.where(is_member: true)
+
+ puts "Queueing up create cards for #{completed_kyc.size} users"
+ completed_kyc.each do |connection|
+ next unless connection.can_create_uphold_cards?
+
+ connection.publisher.channels.each do |channel|
+ CreateUpholdChannelCardJob.perform_later(uphold_connection_id: connection.id, channel_id: channel.id)
+ end
+ end
+ puts 'Done!'
+ end
+end
diff --git a/lib/tasks/database_updates/mock_data.rake b/lib/tasks/database_updates/mock_data.rake
index eefaee3647..591c1c45bf 100644
--- a/lib/tasks/database_updates/mock_data.rake
+++ b/lib/tasks/database_updates/mock_data.rake
@@ -9,6 +9,19 @@ namespace :database_updates do
PromoRegistration.find_each do |promo|
stats = [REFERRAL_CODES_1, REFERRAL_CODES_2].sample
stats = stats.each { |x| x["referral_code"] = promo.referral_code }
+
+ date = Date.today
+ entry = stats.reverse.each_slice(2).map do |a, b|
+ next if a.nil?
+ a["ymd"] = date
+ next if b.nil?
+ b["ymd"] = date
+
+ date -= 1.day
+
+ [a, b]
+ end.flatten
+
promo.stats = stats.to_json
if promo.save
puts "Saved stats to promo #{promo.referral_code}"
diff --git a/public/asset-manifest.json b/public/asset-manifest.json
index 8544d89ff0..6db2b4d44f 100644
--- a/public/asset-manifest.json
+++ b/public/asset-manifest.json
@@ -1,6 +1,6 @@
{
"files": {
- "main.css": "/static/css/main.dec8ec33.chunk.css",
+ "main.css": "/static/css/main.35597b27.chunk.css",
"main.js": "/static/js/main.71177221.chunk.js",
"main.js.map": "/static/js/main.71177221.chunk.js.map",
"runtime~main.js": "/static/js/runtime~main.a8a9905a.js",
@@ -8,9 +8,9 @@
"static/js/2.afab0b54.chunk.js": "/static/js/2.afab0b54.chunk.js",
"static/js/2.afab0b54.chunk.js.map": "/static/js/2.afab0b54.chunk.js.map",
"index.html": "/index.html",
- "precache-manifest.c6b8c25924c72c5e54d05623453f02ae.js": "/precache-manifest.c6b8c25924c72c5e54d05623453f02ae.js",
+ "precache-manifest.c565935f291e217d63c168970232e219.js": "/precache-manifest.c565935f291e217d63c168970232e219.js",
"service-worker.js": "/service-worker.js",
- "static/css/main.dec8ec33.chunk.css.map": "/static/css/main.dec8ec33.chunk.css.map",
+ "static/css/main.35597b27.chunk.css.map": "/static/css/main.35597b27.chunk.css.map",
"static/media/brave-rewards-creators-logo.svg": "/static/media/brave-rewards-creators-logo.74b29633.svg",
"static/media/brave-rewards-creators-mobile-logo.svg": "/static/media/brave-rewards-creators-mobile-logo.58394134.svg",
"static/media/built-with-bat-pill.svg": "/static/media/built-with-bat-pill.f4c2d5ec.svg",
diff --git a/public/precache-manifest.c6b8c25924c72c5e54d05623453f02ae.js b/public/precache-manifest.c565935f291e217d63c168970232e219.js
similarity index 89%
rename from public/precache-manifest.c6b8c25924c72c5e54d05623453f02ae.js
rename to public/precache-manifest.c565935f291e217d63c168970232e219.js
index f5339bc352..be42f7f9f4 100644
--- a/public/precache-manifest.c6b8c25924c72c5e54d05623453f02ae.js
+++ b/public/precache-manifest.c565935f291e217d63c168970232e219.js
@@ -1,18 +1,18 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
- "revision": "78734c31a3dc41ceb14ddf16f6f534ea",
+ "revision": "4185b1e2898c3e2e8889ec5078c1f57d",
"url": "/index.html"
},
{
- "revision": "14c941efab2dc136810e",
- "url": "/static/css/main.dec8ec33.chunk.css"
+ "revision": "be4f1a1897ae818cee38",
+ "url": "/static/css/main.35597b27.chunk.css"
},
{
"revision": "0714d1baebf2047752cb",
"url": "/static/js/2.afab0b54.chunk.js"
},
{
- "revision": "14c941efab2dc136810e",
+ "revision": "be4f1a1897ae818cee38",
"url": "/static/js/main.71177221.chunk.js"
},
{
diff --git a/public/service-worker.js b/public/service-worker.js
index eb4a2db352..f967dbbe2f 100644
--- a/public/service-worker.js
+++ b/public/service-worker.js
@@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.0/workbox-sw.js");
importScripts(
- "/precache-manifest.c6b8c25924c72c5e54d05623453f02ae.js"
+ "/precache-manifest.c565935f291e217d63c168970232e219.js"
);
self.addEventListener('message', (event) => {
diff --git a/public/static/css/main.dec8ec33.chunk.css b/public/static/css/main.35597b27.chunk.css
similarity index 52%
rename from public/static/css/main.dec8ec33.chunk.css
rename to public/static/css/main.35597b27.chunk.css
index 5902a64b81..90c3b71554 100644
--- a/public/static/css/main.dec8ec33.chunk.css
+++ b/public/static/css/main.35597b27.chunk.css
@@ -1,2 +1,2 @@
-/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}h1,h2,h3,h4,h5,h6{font-family:Poppins,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,"sans-serif",Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}body,p{line-height:1.6!important}h4{font-weight:400!important}.main-btns{align-items:center;display:flex;flex-wrap:wrap}#nav{position:absolute;top:0;width:100%;z-index:400}.carousel-container{margin-bottom:60px}@media (max-width:960px){.carousel-container{flex-direction:column-reverse!important}}#carousel-img{z-index:400;max-width:500px;align-self:center;max-height:300px}#carousel-img img,#signoff img{max-width:100%;max-height:100%}.carousel-quote{min-width:300px;max-width:700px}#row-reverse{flex-direction:row-reverse}.top-swoop{top:-2px}.bottom-swoop,.top-swoop{position:absolute;width:100vw!important}.bottom-swoop{bottom:-2px;z-index:0}.terms-help{position:absolute;bottom:60px;left:72px;color:#b6b6b6}.terms-help a{font-size:14px}.terms-help img{display:none}@media (max-width:840px){.terms-help{position:absolute;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.terms-help img{display:flex}}.sign-icon{padding:8px;display:flex;border-radius:40px;margin:4px}.sign-icon svg{height:32px;width:32px}.sign-icon:hover{background:rgba(0,0,0,.2)}.confetti-overflow{position:relative}.bat-pill img{display:none;height:24px}@media (max-width:840px){.bat-pill img{display:flex;align-self:flex-start;margin:0 0 18px}}#zindex{z-index:2}.fade{position:absolute;bottom:0;width:100%;z-index:0;opacity:.05}.email-input{display:flex;flex-direction:column}@media (max-width:720px){.notification-layer{width:96%}}.summary-spacer{height:100px}@media (min-width:1200px){.summary-spacer{height:200px}}.spacer{display:flex;height:60px}.icon{height:180px}.bat-svg{overflow:visible}.circle{-webkit-animation:pulse 1.3s infinite alternate;animation:pulse 1.3s infinite alternate;z-index:30}.circle2{-webkit-animation:pulse 1.7s infinite alternate;animation:pulse 1.7s infinite alternate;z-index:30}.circle-delay{-webkit-animation:pulse 2.2s infinite alternate;animation:pulse 2.2s infinite alternate;z-index:30}.circle-delay2{-webkit-animation:pulse 2.6s infinite alternate;animation:pulse 2.6s infinite alternate;z-index:30}@-webkit-keyframes pulse{0%{opacity:0;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-timing-function:ease;transition-timing-function:ease}to{opacity:1;-webkit-transform:translateY(4px);transform:translateY(4px);-webkit-transition-timing-function:ease;transition-timing-function:ease}}@keyframes pulse{0%{opacity:0;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-timing-function:ease;transition-timing-function:ease}to{opacity:1;-webkit-transform:translateY(4px);transform:translateY(4px);-webkit-transition-timing-function:ease;transition-timing-function:ease}}a{text-decoration:none}
-/*# sourceMappingURL=main.dec8ec33.chunk.css.map */
\ No newline at end of file
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}h1,h2,h3,h4,h5,h6{font-family:Poppins,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,"sans-serif",Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}body,p{line-height:1.6!important}h4{font-weight:400!important}.main-btns{align-items:center;display:flex;flex-wrap:wrap}#nav{position:absolute;top:0;width:100%;z-index:400}.carousel-container{margin-bottom:60px}@media (max-width:960px){.carousel-container{flex-direction:column-reverse!important}}#carousel-img{z-index:400;max-width:500px;align-self:center;max-height:300px}#carousel-img img,#signoff img{max-width:100%;max-height:100%}.carousel-quote{min-width:300px;max-width:700px}#row-reverse{flex-direction:row-reverse}.top-swoop{position:absolute;top:-2px;width:100%!important}.bottom-swoop{position:absolute;bottom:-2px;width:100vw!important;z-index:0}.terms-help{position:absolute;bottom:60px;left:72px;color:#b6b6b6}.terms-help a{font-size:14px}.terms-help img{display:none}@media (max-width:840px){.terms-help{position:absolute;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.terms-help img{display:flex}}.sign-icon{padding:8px;display:flex;border-radius:40px;margin:4px}.sign-icon svg{height:32px;width:32px}.sign-icon:hover{background:rgba(0,0,0,.2)}.confetti-overflow{position:relative}.bat-pill img{display:none;height:24px}@media (max-width:840px){.bat-pill img{display:flex;align-self:flex-start;margin:0 0 18px}}#zindex{z-index:2}.fade{position:absolute;bottom:0;width:100%;z-index:0;opacity:.05}.email-input{display:flex;flex-direction:column}@media (max-width:720px){.notification-layer{width:96%}}.summary-spacer{height:100px}@media (min-width:1200px){.summary-spacer{height:200px}}.spacer{display:flex;height:60px}.icon{height:180px}.bat-svg{overflow:visible}.circle{-webkit-animation:pulse 1.3s infinite alternate;animation:pulse 1.3s infinite alternate;z-index:30}.circle2{-webkit-animation:pulse 1.7s infinite alternate;animation:pulse 1.7s infinite alternate;z-index:30}.circle-delay{-webkit-animation:pulse 2.2s infinite alternate;animation:pulse 2.2s infinite alternate;z-index:30}.circle-delay2{-webkit-animation:pulse 2.6s infinite alternate;animation:pulse 2.6s infinite alternate;z-index:30}@-webkit-keyframes pulse{0%{opacity:0;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-timing-function:ease;transition-timing-function:ease}to{opacity:1;-webkit-transform:translateY(4px);transform:translateY(4px);-webkit-transition-timing-function:ease;transition-timing-function:ease}}@keyframes pulse{0%{opacity:0;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-timing-function:ease;transition-timing-function:ease}to{opacity:1;-webkit-transform:translateY(4px);transform:translateY(4px);-webkit-transition-timing-function:ease;transition-timing-function:ease}}a{text-decoration:none}
+/*# sourceMappingURL=main.35597b27.chunk.css.map */
\ No newline at end of file
diff --git a/public/static/css/main.35597b27.chunk.css.map b/public/static/css/main.35597b27.chunk.css.map
new file mode 100644
index 0000000000..02d42062d6
--- /dev/null
+++ b/public/static/css/main.35597b27.chunk.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["normalize-style.css","style.css"],"names":[],"mappings":"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","file":"main.35597b27.chunk.css","sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15;\n /* 1 */\n -webkit-text-size-adjust: 100%;\n /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box;\n /* 1 */\n height: 0;\n /* 1 */\n overflow: visible;\n /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace;\n /* 1 */\n font-size: 1em;\n /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none;\n /* 1 */\n text-decoration: underline;\n /* 2 */\n text-decoration: underline dotted;\n /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace;\n /* 1 */\n font-size: 1em;\n /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit;\n /* 1 */\n font-size: 100%;\n /* 1 */\n line-height: 1.15;\n /* 1 */\n margin: 0;\n /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput {\n /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect {\n /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box;\n /* 1 */\n color: inherit;\n /* 2 */\n display: table;\n /* 1 */\n max-width: 100%;\n /* 1 */\n padding: 0;\n /* 3 */\n white-space: normal;\n /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box;\n /* 1 */\n padding: 0;\n /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield;\n /* 1 */\n outline-offset: -2px;\n /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button;\n /* 1 */\n font: inherit;\n /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}","h1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-family: \"Poppins\", \"-apple-system\", \"BlinkMacSystemFont\", \"Segoe UI\",\n \"Helvetica\", \"Arial\", \"sans-serif\", \"Apple Color Emoji\", \"Segoe UI Emoji\",\n \"Segoe UI Symbol\";\n}\n\n/* correct the tight line height on Muli */\n\nbody,\np {\n line-height: 1.6 !important;\n}\n\nh4 {\n font-weight: 400 !important;\n}\n\n/* Main section styling */\n\n.main-btns {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n}\n\n#nav {\n position: absolute;\n top: 0;\n width: 100%;\n z-index: 400;\n}\n\n.carousel-container {\n margin-bottom: 60px;\n}\n\n@media (max-width: 960px) {\n .carousel-container {\n flex-direction: column-reverse !important;\n }\n}\n\n#carousel-img {\n z-index: 400;\n max-width: 500px;\n align-self: center;\n max-height: 300px;\n}\n\n#carousel-img img {\n max-width: 100%;\n max-height: 100%;\n}\n\n#signoff img {\n max-width: 100%;\n max-height: 100%;\n}\n\n.carousel-quote {\n min-width: 300px;\n max-width: 700px;\n}\n\n/* reverses the order of the carousel divs */\n\n#row-reverse {\n flex-direction: row-reverse;\n}\n\n/* swoop positioning */\n\n.top-swoop {\n position: absolute;\n top: -2px;\n width: 100% !important;\n}\n\n.bottom-swoop {\n position: absolute;\n bottom: -2px;\n width: 100vw !important;\n z-index: 0;\n}\n\n/* Terms in Signup and Signin */\n\n.terms-help {\n position: absolute;\n bottom: 60px;\n left: 72px;\n color: rgb(182, 182, 182);\n}\n\n.terms-help a {\n font-size: 14px;\n}\n\n.terms-help img {\n display: none;\n}\n\n@media (max-width: 840px) {\n .terms-help {\n position: absolute;\n left: 50%;\n transform: translate(-50%, -50%);\n width: fit-content;\n }\n\n .terms-help img {\n display: flex;\n }\n}\n\n.sign-icon {\n padding: 8px;\n display: flex;\n border-radius: 40px;\n margin: 4px;\n}\n\n.sign-icon svg {\n height: 32px;\n width: 32px;\n}\n\n.sign-icon:hover {\n background: rgba(0, 0, 0, 0.2);\n}\n\n.confetti-overflow {\n position: relative;\n}\n\n/* Responsive BAT pill changes oh landing main section */\n\n.bat-pill img {\n display: none;\n height: 24px;\n}\n\n@media (max-width: 840px) {\n .bat-pill img {\n display: flex;\n align-self: flex-start;\n margin: 0 0 18px;\n }\n}\n\n#zindex {\n z-index: 2;\n}\n\n.fade {\n position: absolute;\n bottom: 0;\n width: 100%;\n z-index: 0;\n opacity: 0.05;\n}\n\n.email-input {\n display: flex;\n flex-direction: column;\n}\n\n@media (max-width: 720px) {\n .notification-layer {\n width: 96%;\n }\n}\n\n.summary-spacer {\n height: 100px;\n}\n\n@media (min-width: 1200px) {\n .summary-spacer {\n height: 200px;\n }\n}\n\n.spacer {\n display: flex;\n height: 60px;\n}\n\n/* BAT Logo Animation */\n.icon {\n height: 180px;\n}\n\n.bat-svg {\n overflow: visible;\n}\n\n.circle {\n animation: pulse 1.3s alternate infinite;\n z-index: 30;\n}\n\n.circle2 {\n animation: pulse 1.7s alternate infinite;\n z-index: 30;\n}\n\n.circle-delay {\n animation: pulse 2.2s alternate infinite;\n z-index: 30;\n}\n\n.circle-delay2 {\n animation: pulse 2.6s alternate infinite;\n z-index: 30;\n}\n\n@keyframes pulse {\n 0% {\n opacity: 0;\n transform: translateY(0);\n transition-timing-function: ease;\n }\n\n 100% {\n opacity: 1;\n transform: translateY(4px);\n transition-timing-function: ease;\n }\n}\n\na {\n text-decoration: none;\n}\n"]}
\ No newline at end of file
diff --git a/public/static/css/main.dec8ec33.chunk.css.map b/public/static/css/main.dec8ec33.chunk.css.map
deleted file mode 100644
index af7bc1c6b7..0000000000
--- a/public/static/css/main.dec8ec33.chunk.css.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["normalize-style.css","style.css"],"names":[],"mappings":"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","file":"main.dec8ec33.chunk.css","sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15;\n /* 1 */\n -webkit-text-size-adjust: 100%;\n /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box;\n /* 1 */\n height: 0;\n /* 1 */\n overflow: visible;\n /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace;\n /* 1 */\n font-size: 1em;\n /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none;\n /* 1 */\n text-decoration: underline;\n /* 2 */\n text-decoration: underline dotted;\n /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace;\n /* 1 */\n font-size: 1em;\n /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit;\n /* 1 */\n font-size: 100%;\n /* 1 */\n line-height: 1.15;\n /* 1 */\n margin: 0;\n /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput {\n /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect {\n /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box;\n /* 1 */\n color: inherit;\n /* 2 */\n display: table;\n /* 1 */\n max-width: 100%;\n /* 1 */\n padding: 0;\n /* 3 */\n white-space: normal;\n /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box;\n /* 1 */\n padding: 0;\n /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield;\n /* 1 */\n outline-offset: -2px;\n /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button;\n /* 1 */\n font: inherit;\n /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}","h1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-family: \"Poppins\", \"-apple-system\", \"BlinkMacSystemFont\", \"Segoe UI\",\n \"Helvetica\", \"Arial\", \"sans-serif\", \"Apple Color Emoji\", \"Segoe UI Emoji\",\n \"Segoe UI Symbol\";\n}\n\n/* correct the tight line height on Muli */\n\nbody,\np {\n line-height: 1.6 !important;\n}\n\nh4 {\n font-weight: 400 !important;\n}\n\n/* Main section styling */\n\n.main-btns {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n}\n\n#nav {\n position: absolute;\n top: 0;\n width: 100%;\n z-index: 400;\n}\n\n.carousel-container {\n margin-bottom: 60px;\n}\n\n@media (max-width: 960px) {\n .carousel-container {\n flex-direction: column-reverse !important;\n }\n}\n\n#carousel-img {\n z-index: 400;\n max-width: 500px;\n align-self: center;\n max-height: 300px;\n}\n\n#carousel-img img {\n max-width: 100%;\n max-height: 100%;\n}\n\n#signoff img {\n max-width: 100%;\n max-height: 100%;\n}\n\n.carousel-quote {\n min-width: 300px;\n max-width: 700px;\n}\n\n/* reverses the order of the carousel divs */\n\n#row-reverse {\n flex-direction: row-reverse;\n}\n\n/* swoop positioning */\n\n.top-swoop {\n position: absolute;\n top: -2px;\n width: 100vw !important;\n}\n\n.bottom-swoop {\n position: absolute;\n bottom: -2px;\n width: 100vw !important;\n z-index: 0;\n}\n\n/* Terms in Signup and Signin */\n\n.terms-help {\n position: absolute;\n bottom: 60px;\n left: 72px;\n color: rgb(182, 182, 182);\n}\n\n.terms-help a {\n font-size: 14px;\n}\n\n.terms-help img {\n display: none;\n}\n\n@media (max-width: 840px) {\n .terms-help {\n position: absolute;\n left: 50%;\n transform: translate(-50%, -50%);\n width: fit-content;\n }\n\n .terms-help img {\n display: flex;\n }\n}\n\n.sign-icon {\n padding: 8px;\n display: flex;\n border-radius: 40px;\n margin: 4px;\n}\n\n.sign-icon svg {\n height: 32px;\n width: 32px;\n}\n\n.sign-icon:hover {\n background: rgba(0, 0, 0, 0.2);\n}\n\n.confetti-overflow {\n position: relative;\n}\n\n/* Responsive BAT pill changes oh landing main section */\n\n.bat-pill img {\n display: none;\n height: 24px;\n}\n\n@media (max-width: 840px) {\n .bat-pill img {\n display: flex;\n align-self: flex-start;\n margin: 0 0 18px;\n }\n}\n\n#zindex {\n z-index: 2;\n}\n\n.fade {\n position: absolute;\n bottom: 0;\n width: 100%;\n z-index: 0;\n opacity: 0.05;\n}\n\n.email-input {\n display: flex;\n flex-direction: column;\n}\n\n@media (max-width: 720px) {\n .notification-layer {\n width: 96%;\n }\n}\n\n.summary-spacer {\n height: 100px;\n}\n\n@media (min-width: 1200px) {\n .summary-spacer {\n height: 200px;\n }\n}\n\n.spacer {\n display: flex;\n height: 60px;\n}\n\n/* BAT Logo Animation */\n.icon {\n height: 180px;\n}\n\n.bat-svg {\n overflow: visible;\n}\n\n.circle {\n animation: pulse 1.3s alternate infinite;\n z-index: 30;\n}\n\n.circle2 {\n animation: pulse 1.7s alternate infinite;\n z-index: 30;\n}\n\n.circle-delay {\n animation: pulse 2.2s alternate infinite;\n z-index: 30;\n}\n\n.circle-delay2 {\n animation: pulse 2.6s alternate infinite;\n z-index: 30;\n}\n\n@keyframes pulse {\n 0% {\n opacity: 0;\n transform: translateY(0);\n transition-timing-function: ease;\n }\n\n 100% {\n opacity: 1;\n transform: translateY(4px);\n transition-timing-function: ease;\n }\n}\n\na {\n text-decoration: none;\n}\n"]}
\ No newline at end of file
diff --git a/test/controllers/admin/payout_reports_controller_test.rb b/test/controllers/admin/payout_reports_controller_test.rb
index 2f26364856..005fb144d1 100644
--- a/test/controllers/admin/payout_reports_controller_test.rb
+++ b/test/controllers/admin/payout_reports_controller_test.rb
@@ -11,6 +11,11 @@ class PayoutReportsControllerTest < ActionDispatch::IntegrationTest
before do
@prev_eyeshade_offline = Rails.application.secrets[:api_eyeshade_offline]
stub_request(:get, uphold_url).to_return(body: { status: "ok", memberAt: "2019", uphold_id: "123e4567-e89b-12d3-a456-426655440000" }.to_json)
+
+ # Mock out the creation of cards
+ stub_request(:get, /cards/).to_return(body: [id: "fb25048b-79df-4e64-9c4e-def07c8f5c04"].to_json)
+ stub_request(:post, /cards/).to_return(body: { id: "fb25048b-79df-4e64-9c4e-def07c8f5c04" }.to_json)
+ stub_request(:get, /address/).to_return(body: [{ formats: [{ format: "uuid", value: "e306ec64-461b-4723-bf75-015ffc99ebe1" }], type: "anonymous" }].to_json)
end
after do
diff --git a/test/controllers/channel_transfer_controller_test.rb b/test/controllers/channel_transfer_controller_test.rb
index 89e6cae3b1..410bf493c9 100644
--- a/test/controllers/channel_transfer_controller_test.rb
+++ b/test/controllers/channel_transfer_controller_test.rb
@@ -13,24 +13,24 @@ class ChannelTransferControllerTest < ActionDispatch::IntegrationTest
# contest channel
Channels::ContestChannel.new(channel: channel, contested_by: contested_by_channel).perform
- assert_enqueued_jobs(4) do
+ assert_enqueued_jobs(5) do
get token_reject_transfer_path(channel, channel.contest_token)
end
assert_redirected_to home_publishers_path
- assert_equal I18n.t("shared.channel_transfer_rejected"), flash[:notice]
+ assert_equal I18n.t("shared.channel_transfer_rejected"), flash[:notice]
end
test "#rejects_transfer does not go thorugh and redirects to home with fake contest token" do
channel = channels(:fraudulently_verified_site)
contested_by_channel = channels(:locked_out_site)
-
+
# contest channel
Channels::ContestChannel.new(channel: channel, contested_by: contested_by_channel).perform
get token_reject_transfer_path(channel, "fake token")
assert response.status, 404
assert_redirected_to home_publishers_path
- assert_equal I18n.t("shared.channel_not_found"), flash[:notice]
+ assert_equal I18n.t("shared.channel_not_found"), flash[:notice]
end
end
diff --git a/test/controllers/publishers/omniauth_callbacks_controller_test.rb b/test/controllers/publishers/omniauth_callbacks_controller_test.rb
index b5267101d4..1dd06a5cf9 100644
--- a/test/controllers/publishers/omniauth_callbacks_controller_test.rb
+++ b/test/controllers/publishers/omniauth_callbacks_controller_test.rb
@@ -23,6 +23,10 @@ def request_login_email(publisher:)
Rails.application.secrets[:active_promo_id] = ""
uphold_url = Rails.application.secrets[:uphold_api_uri] + "/v0/me"
stub_request(:get, uphold_url).to_return(body: { status: "pending", memberAt: "2019", uphold_id: "123e4567-e89b-12d3-a456-426655440000" }.to_json)
+ # Mock out the creation of cards
+ stub_request(:get, /cards/).to_return(body: [id: "fb25048b-79df-4e64-9c4e-def07c8f5c04"].to_json)
+ stub_request(:post, /cards/).to_return(body: { id: "fb25048b-79df-4e64-9c4e-def07c8f5c04" }.to_json)
+ stub_request(:get, /address/).to_return(body: [{ formats: [{ format: "uuid", value: "e306ec64-461b-4723-bf75-015ffc99ebe1" }], type: "anonymous" }].to_json)
end
after(:example) do
@@ -131,7 +135,7 @@ def channel_data(options = {})
follow_redirect!
end
- assert_select('div.channel-status.float-right') do |element|
+ assert_select('span.channel-contested') do |element|
assert_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(publisher.channels.where(verification_pending: true).first)), element.text)
end
end
@@ -178,7 +182,7 @@ def channel_data(options = {})
follow_redirect!
# Channel was transferred
- assert_select('div.channel-status.float-right') do |element|
+ assert_select('span.channel-contested') do |element|
assert_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(publisher.channels.where(verification_pending: true).first)), element.text)
end
@@ -191,7 +195,7 @@ def channel_data(options = {})
get(url)
follow_redirect!
- assert_select('div.channel-status.float-right') do |element|
+ assert_select('.channel-secondary-information') do |element|
refute_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(Channel.where(verification_pending: true).first)), element.text)
end
end
@@ -485,7 +489,7 @@ def auth_hash(options = {})
follow_redirect!
end
- assert_select('div.channel-status') do |element|
+ assert_select('span.channel-contested') do |element|
assert_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(publisher.channels.where(verification_pending: true).first)),
element.text)
end
@@ -592,7 +596,8 @@ def auth_hash(options = {})
follow_redirect!
end
- assert_select('div.channel-status') do |element|
+
+ assert_select('span.channel-contested') do |element|
assert_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(publisher.channels.where(verification_pending: true).first)),
element.text)
end
@@ -689,7 +694,7 @@ def auth_hash(options = {})
follow_redirect!
end
- assert_select('div.channel-status') do |element|
+ assert_select('span.channel-contested') do |element|
assert_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(publisher.channels.where(verification_pending: true).first)),
element.text)
end
@@ -785,7 +790,7 @@ def auth_hash(options = {})
follow_redirect!
end
- assert_select('div.channel-status') do |element|
+ assert_select('span.channel-contested') do |element|
assert_match(I18n.t("shared.channel_contested", time_until_transfer: time_until_transfer(publisher.channels.where(verification_pending: true).first)),
element.text)
end
diff --git a/test/controllers/site_channels_controller_test.rb b/test/controllers/site_channels_controller_test.rb
index 3b917a54ad..9bb5fe036a 100644
--- a/test/controllers/site_channels_controller_test.rb
+++ b/test/controllers/site_channels_controller_test.rb
@@ -265,7 +265,7 @@ class SiteChannelsControllerTest < ActionDispatch::IntegrationTest
new_channel = publisher.channels.order(created_at: :asc).last
# Triggering an update to test if the promo was created
- assert_no_enqueued_jobs do
+ assert_enqueued_jobs(1) do
new_channel.update(verified: true)
end
ensure
diff --git a/test/features/publishers_home_test.rb b/test/features/publishers_home_test.rb
index 44b1ce9391..484c69a73f 100644
--- a/test/features/publishers_home_test.rb
+++ b/test/features/publishers_home_test.rb
@@ -9,6 +9,10 @@ class PublishersHomeTest < Capybara::Rails::TestCase
@prev_eyeshade_offline = Rails.application.secrets[:api_eyeshade_offline]
stub_request(:get, uphold_url).to_return(body: { status: "restricted", uphold_id: "123e4567-e89b-12d3-a456-426655440000", currencies: [] }.to_json)
+ # Mock out the creation of cards
+ stub_request(:get, /cards/).to_return(body: [id: "fb25048b-79df-4e64-9c4e-def07c8f5c04"].to_json)
+ stub_request(:post, /cards/).to_return(body: { id: "fb25048b-79df-4e64-9c4e-def07c8f5c04" }.to_json)
+ stub_request(:get, /address/).to_return(body: [{ formats: [{ format: "uuid", value: "e306ec64-461b-4723-bf75-015ffc99ebe1" }], type: "anonymous" }].to_json)
end
after do
@@ -100,7 +104,7 @@ class PublishersHomeTest < Capybara::Rails::TestCase
visit home_publishers_path
assert_content page, channel.publication_title
- find("#channel_row_#{channel.id}").click_link('Remove Channel')
+ find("#channel_row_#{channel.id}").click_link('Remove channel')
assert_content page, "Are you sure you want to remove this channel?"
find('[data-test-modal-container]').click_link("Remove Channel")
wait_until { !page.find('.cssload-container', visible: :all).visible? }
diff --git a/test/jobs/transfer_channels_job_test.rb b/test/jobs/transfer_channels_job_test.rb
index abaaa0f6dc..b9adbafadd 100644
--- a/test/jobs/transfer_channels_job_test.rb
+++ b/test/jobs/transfer_channels_job_test.rb
@@ -2,13 +2,20 @@
require "webmock/minitest"
class TransferChannelsJobTest < ActiveJob::TestCase
+ before do
+ # Mock out the creation of cards
+ stub_request(:get, /cards/).to_return(body: [id: "fb25048b-79df-4e64-9c4e-def07c8f5c04"].to_json)
+ stub_request(:post, /cards/).to_return(body: { id: "fb25048b-79df-4e64-9c4e-def07c8f5c04" }.to_json)
+ stub_request(:get, /address/).to_return(body: [{ formats: [{ format: "uuid", value: "e306ec64-461b-4723-bf75-015ffc99ebe1" }], type: "anonymous" }].to_json)
+ end
+
test "does not approve channels unless timeout period has passed" do
channel = channels(:fraudulently_verified_site)
contested_by_channel = channels(:locked_out_site)
# contest channel
Channels::ContestChannel.new(channel: channel, contested_by: contested_by_channel).perform
- assert_enqueued_jobs(0) do
+ assert_enqueued_jobs(0) do
TransferChannelsJob.perform_now
end
@@ -23,10 +30,10 @@ class TransferChannelsJobTest < ActiveJob::TestCase
Channels::ContestChannel.new(channel: channel, contested_by: contested_by_channel).perform
travel (Channel::CONTEST_TIMEOUT + 1.minute) do
- assert_enqueued_jobs(4) do
+ assert_enqueued_jobs(6) do
TransferChannelsJob.perform_now
end
-
+
contested_by_channel.reload
assert contested_by_channel.verified
end
diff --git a/test/models/channel_test.rb b/test/models/channel_test.rb
index 10fde74afa..6005b73b90 100644
--- a/test/models/channel_test.rb
+++ b/test/models/channel_test.rb
@@ -4,6 +4,13 @@ class ChannelTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
include ActionMailer::TestHelper
+ before do
+ # Mock out the creation of cards
+ stub_request(:get, /cards/).to_return(body: [id: "fb25048b-79df-4e64-9c4e-def07c8f5c04"].to_json)
+ stub_request(:post, /cards/).to_return(body: { id: "fb25048b-79df-4e64-9c4e-def07c8f5c04" }.to_json)
+ stub_request(:get, /address/).to_return(body: [{ formats: [{ format: "uuid", value: "e306ec64-461b-4723-bf75-015ffc99ebe1" }], type: "anonymous" }].to_json)
+ end
+
test "site channel must have details" do
channel = channels(:verified)
assert channel.valid?
@@ -82,7 +89,7 @@ class ChannelTest < ActionDispatch::IntegrationTest
# verify RegisterChannelForPromoJob is called
channel.verified = true
- assert_enqueued_jobs(1) do
+ assert_enqueued_with(job: ActionMailer::DeliveryJob) do
channel.save!
end
@@ -112,7 +119,7 @@ class ChannelTest < ActionDispatch::IntegrationTest
# check that RegisterChannelForPromoJob is called when it is verified
# channel_copy.verified = true
channel_copy = Channel.new(details: channel_details_copy, verified: true, publisher: publisher)
- assert_enqueued_jobs(1) do
+ assert_enqueued_with(job: ActionMailer::DeliveryJob) do
channel_copy.save!
end
diff --git a/test/services/channels/contest_channel_test.rb b/test/services/channels/contest_channel_test.rb
index 0d214dfd34..a163799fcc 100644
--- a/test/services/channels/contest_channel_test.rb
+++ b/test/services/channels/contest_channel_test.rb
@@ -6,7 +6,7 @@ class ContestChannelTest < ActiveJob::TestCase
channel = channels(:fraudulently_verified_site)
contested_by_channel = channels(:locked_out_site)
- assert_enqueued_jobs(2) do
+ assert_enqueued_jobs(3) do
Channels::ContestChannel.new(channel: channel, contested_by: contested_by_channel).perform
end
end
diff --git a/test/services/payout_report_publisher_includer_test.rb b/test/services/payout_report_publisher_includer_test.rb
index 21c32181d4..96940f4add 100644
--- a/test/services/payout_report_publisher_includer_test.rb
+++ b/test/services/payout_report_publisher_includer_test.rb
@@ -10,6 +10,11 @@ class PayoutReportPublisherIncluderTest < ActiveJob::TestCase
PotentialPayment.destroy_all
@prev_offline = Rails.application.secrets[:api_eyeshade_offline]
@prev_fee_rate = Rails.application.secrets[:fee_rate]
+
+ # Mock out the creation of cards
+ stub_request(:get, /cards/).to_return(body: [id: "fb25048b-79df-4e64-9c4e-def07c8f5c04"].to_json)
+ stub_request(:post, /cards/).to_return(body: { id: "fb25048b-79df-4e64-9c4e-def07c8f5c04" }.to_json)
+ stub_request(:get, /address/).to_return(body: [{ formats: [{ format: "uuid", value: "e306ec64-461b-4723-bf75-015ffc99ebe1" }], type: "anonymous" }].to_json)
end
after do