mirror of
https://github.com/indentlabs/notebook.git
synced 2025-10-26 11:19:22 +00:00
commit
2a3356fdca
@ -33,6 +33,14 @@ class DataController < ApplicationController
|
||||
@threads_posted_to = Thredded::Topic.where(id: @posts.pluck(:postable_id) - @topics.pluck(:id))
|
||||
end
|
||||
|
||||
def collaboration
|
||||
universe_ids = current_user.universes.pluck(:id)
|
||||
@collaborators = Contributor.where(universe_id: universe_ids).includes(:user, :universe)#.uniq { |c| c.user_id }
|
||||
@shared_universes = current_user.universes.where(id: @collaborators.pluck(:universe_id))
|
||||
collaborating_ids = Contributor.where(user_id: current_user.id).pluck(:universe_id)
|
||||
@collaborating_universes = Universe.where(id: collaborating_ids)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_sidenav_expansion
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
class PageUnlockPromoCode < ApplicationRecord
|
||||
has_many :promotions
|
||||
has_many :promotions, dependent: :destroy
|
||||
has_many :users, -> { distinct }, through: :promotions
|
||||
|
||||
serialize :page_types, Array
|
||||
|
||||
@ -31,6 +31,27 @@ class PaypalInvoice < ApplicationRecord
|
||||
description: "Prepaid Premium subscription"
|
||||
)
|
||||
self.save!
|
||||
|
||||
if PromoService.active?(:promo_bogo) && (self.months == 3 || self.months == 6)
|
||||
# During this promo, we create a separate Invoice + PromoCode also
|
||||
self.user.paypal_invoices.create(
|
||||
paypal_id: "None -- Created from promo_bogo promo",
|
||||
status: self.status,
|
||||
user_id: self.user_id,
|
||||
months: self.months,
|
||||
amount_cents: 0,
|
||||
page_unlock_promo_code: PageUnlockPromoCode.create(
|
||||
code: 'BOGO-' + (0...8).map { (65 + rand(26)).chr }.join + '-' + (0...8).map { (65 + rand(26)).chr }.join,
|
||||
page_types: Rails.application.config.content_types[:premium].map(&:name),
|
||||
uses_remaining: 1,
|
||||
days_active: 30 * self.months.to_i,
|
||||
internal_description: "promo_bogo duplicate code",
|
||||
description: "Your free buy-one-get-one-free Premium Code",
|
||||
),
|
||||
approval_url: nil,
|
||||
payer_id: self.payer_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def activateable?
|
||||
|
||||
@ -7,12 +7,12 @@ class PaypalService < Service
|
||||
request.request_body({
|
||||
intent: "CAPTURE",
|
||||
application_context: {
|
||||
return_url: 'https://www.notebook.ai/my/billing/prepay/paid',
|
||||
cancel_url: 'https://www.notebook.ai/my/billing/prepay',
|
||||
brand_name: 'Notebook.ai by Indent Labs',
|
||||
landing_page: 'BILLING',
|
||||
return_url: 'https://www.notebook.ai/my/billing/prepay/paid',
|
||||
cancel_url: 'https://www.notebook.ai/my/billing/prepay',
|
||||
brand_name: 'Notebook.ai by Indent Labs',
|
||||
landing_page: 'BILLING',
|
||||
shipping_preference: 'NO_SHIPPING',
|
||||
user_action: 'PAY_NOW'
|
||||
user_action: 'PAY_NOW'
|
||||
},
|
||||
purchase_units: [{
|
||||
amount: {
|
||||
@ -143,7 +143,7 @@ class PaypalService < Service
|
||||
client_id = Rails.application.config.paypal[:client_id]
|
||||
client_secret = Rails.application.config.paypal[:client_secret]
|
||||
|
||||
environment = if Rails.env.production?
|
||||
environment = if Rails.env.production?
|
||||
PayPal::LiveEnvironment.new(client_id, client_secret)
|
||||
else
|
||||
PayPal::SandboxEnvironment.new(client_id, client_secret)
|
||||
|
||||
13
app/services/promo_service.rb
Normal file
13
app/services/promo_service.rb
Normal file
@ -0,0 +1,13 @@
|
||||
class PromoService < Service
|
||||
def self.active?(promo_key)
|
||||
[
|
||||
Date.current >= Rails.application.config.promos.fetch(promo_key, {}).fetch(:start_date),
|
||||
Date.current <= Rails.application.config.promos.fetch(promo_key, {}).fetch(:end_date)
|
||||
].all?
|
||||
rescue false
|
||||
end
|
||||
|
||||
def self.end_date(promo_key)
|
||||
Rails.application.config.promos.fetch(promo_key, {}).fetch(:end_date)
|
||||
end
|
||||
end
|
||||
@ -10,7 +10,7 @@
|
||||
<% raw_model.contributors.each do |contributor| %>
|
||||
<% next if contributor.user.nil? && (current_user != content.user) %>
|
||||
<li class="collection-item avatar">
|
||||
<i class="material-icons circle white-text">person</i>
|
||||
<i class="material-icons circle white-text <%= User.color %>"><%= User.icon %></i>
|
||||
<span class="title">
|
||||
<%= contributor.user ? link_to(contributor.user.name, contributor.user) : "#{contributor.email} (invited)" %>
|
||||
</span>
|
||||
|
||||
@ -70,20 +70,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if current_user.notice_dismissals.where(notice_id: 5).none? %>
|
||||
<!--
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<div class="hoverable card-panel <%= Country.color %> lighten-6">
|
||||
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 5), class: 'blue-text text-lighten-4 right' %>
|
||||
<i class="material-icons left"><%= Country.icon %></i>
|
||||
New: Check out the new <span class="white-text">Country</span> page type, as well as tons of new fields on the other pages!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<% end %>
|
||||
|
||||
<div class="row">
|
||||
<% @all_content_types.sort_by(&:name).each.with_index do |content_type, i| %>
|
||||
<div class="col s12 m6 l4">
|
||||
|
||||
82
app/views/data/collaboration.html.erb
Normal file
82
app/views/data/collaboration.html.erb
Normal file
@ -0,0 +1,82 @@
|
||||
<h4>
|
||||
<%= link_to data_vault_path, class: 'grey-text tooltipped', style: 'position: relative; top: 4px;', data: {
|
||||
position: 'bottom',
|
||||
enterDelay: '500',
|
||||
tooltip: "Back to your Data Vault"
|
||||
} do %>
|
||||
<i class="material-icons">arrow_back</i>
|
||||
<% end %>
|
||||
Collaboration on Notebook.ai
|
||||
</h4>
|
||||
|
||||
<div class="grey-text uppercase">Your shared universes</div>
|
||||
<% if @shared_universes.any? %>
|
||||
<ul class="collapsible">
|
||||
<% @shared_universes.reverse.each do |universe| %>
|
||||
<li>
|
||||
<div class="collapsible-header white-text <%= Universe.color %>">
|
||||
<i class="material-icons"><%= Universe.icon %></i>
|
||||
<%= universe.name %>
|
||||
(<%= pluralize universe.contributors.count, 'collaborator' %>)
|
||||
</div>
|
||||
<div class="collapsible-body white">
|
||||
<%= render partial: 'content/display/contributors', locals: { content: universe } %>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<p>None yet!</p>
|
||||
<% end %>
|
||||
|
||||
<div class="grey-text uppercase">Universes shared with you</div>
|
||||
<% if @collaborating_universes.any? %>
|
||||
<ul class="collapsible">
|
||||
<% @collaborating_universes.each do |universe| %>
|
||||
<li>
|
||||
<div class="collapsible-header white-text <%= Universe.color %>">
|
||||
<i class="material-icons"><%= Universe.icon %></i>
|
||||
<%= universe.name %>
|
||||
</div>
|
||||
<div class="collapsible-body white">
|
||||
<%= render partial: 'content/display/contributors', locals: { content: universe } %>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<p>None yet!</p>
|
||||
<% end %>
|
||||
|
||||
<% if @collaborators.any? %>
|
||||
<div class="grey-text uppercase">Your collaborators</div>
|
||||
<ul class="collapsible">
|
||||
<% @collaborators.group_by { |c| c.user }.each do |collaborator, collab_list| %>
|
||||
<li>
|
||||
<div class="collapsible-header <%= User.color %> white-text">
|
||||
<i class="material-icons"><%= User.icon %></i>
|
||||
<%= collaborator.name %> <%= "(@#{collaborator.username})" if collaborator.username? %>
|
||||
</div>
|
||||
<div class="collapsible-body">
|
||||
Contributing on:
|
||||
<ul>
|
||||
<% Universe.where(id: collab_list.pluck(:universe_id)).each do |universe| %>
|
||||
<li class="clearfix">
|
||||
<%= link_to universe, class: "#{Universe.color}-text" do %>
|
||||
<i class="material-icons left"><%= Universe.icon %></i>
|
||||
<%= universe.name %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<p>None yet!</p>
|
||||
<% end %>
|
||||
|
||||
<%= content_for :javascript do %>
|
||||
$('.panel').show();
|
||||
<% end %>
|
||||
@ -69,6 +69,20 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m12 l6">
|
||||
<%= link_to discussions_path, class: 'black-text' do %>
|
||||
<div class="hoverable card blue lighten-5">
|
||||
<div class="card-content" style="overflow: hidden; height: <%= card_height %>px">
|
||||
<i class="material-icons right blue-text" style="font-size: <%= icon_fsize %>rem; margin-top: <%= icon_yoffset %>rem; margin-left: 0; margin-right: <%= icon_xoffset %>rem">forum</i>
|
||||
<div class="card-title">Discussion activity</div>
|
||||
<p>
|
||||
See your activity on the discussion boards.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m12 l6">
|
||||
<%= link_to uploads_path, class: 'black-text' do %>
|
||||
<div class="hoverable card amber lighten-5">
|
||||
@ -83,19 +97,21 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="col s12 m12 l6">
|
||||
<%= link_to discussions_path, class: 'black-text' do %>
|
||||
<div class="hoverable card blue lighten-5">
|
||||
<%= link_to collaboration_path, class: 'black-text' do %>
|
||||
<div class="hoverable card purple lighten-5">
|
||||
<div class="card-content" style="overflow: hidden; height: <%= card_height %>px">
|
||||
<i class="material-icons right blue-text" style="font-size: <%= icon_fsize %>rem; margin-top: <%= icon_yoffset %>rem; margin-left: 0; margin-right: <%= icon_xoffset %>rem">forum</i>
|
||||
<div class="card-title">Discussion activity</div>
|
||||
<i class="material-icons right purple-text" style="font-size: <%= icon_fsize %>rem; margin-top: <%= icon_yoffset %>rem; margin-left: 0; margin-right: <%= icon_xoffset %>rem"><%= Universe.icon %></i>
|
||||
<div class="card-title">Collaboration</div>
|
||||
<p>
|
||||
See your activity on the discussion boards.
|
||||
Learn more about collaborating on Notebook.ai and track which universes are shared.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="col s12 m12 l6">
|
||||
<%= link_to privacy_policy_path, class: 'black-text' do %>
|
||||
|
||||
@ -1,6 +1,21 @@
|
||||
<div class="row">
|
||||
<%= render partial: 'main/dashboard_header_links' %>
|
||||
|
||||
<% if PromoService.active?(:promo_bogo) %>
|
||||
<% if current_user.notice_dismissals.where(notice_id: 6).none? %>
|
||||
<div class="col s12">
|
||||
<div class="hoverable card-panel orange lighten-5">
|
||||
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 6), class: 'blue-text right', style: 'padding: 0 10px;' %>
|
||||
<%= link_to prepay_path, class: 'black-text' do %>
|
||||
<i class="material-icons left">card_giftcard</i>
|
||||
Limited-time Discount: Stay safe and stay home while worldbuilding with friends! Shareable 3-month and 6-month Premium Codes are buy-one-get-one-free until
|
||||
<%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>. Happy worldbuilding!
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if @content %>
|
||||
<div class="col s12">
|
||||
<%= render partial: 'cards/serendipitous/content_question', locals: {
|
||||
@ -11,18 +26,6 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.created_at > 3.months.ago && current_user.notice_dismissals.where(notice_id: 4).none? %>
|
||||
<div class="col s12">
|
||||
<div class="hoverable card-panel orange lighten-5">
|
||||
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 4), class: 'blue-text right' %>
|
||||
<%= link_to prepay_path, class: 'black-text' do %>
|
||||
<i class="fa fa-paypal left"></i>
|
||||
New in Notebook.ai: You can now purchase Premium for yourself — or your friends — with PayPal.
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%
|
||||
s_width = 12
|
||||
m_width = 6
|
||||
|
||||
@ -14,6 +14,21 @@
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if PromoService.active?(:promo_bogo) %>
|
||||
<% if current_user.notice_dismissals.where(notice_id: 6).none? %>
|
||||
<div class="col s12">
|
||||
<div class="hoverable card-panel orange lighten-5">
|
||||
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 6), class: 'blue-text right', style: 'padding: 0 10px;' %>
|
||||
<%= link_to prepay_path, class: 'black-text' do %>
|
||||
<i class="material-icons left">card_giftcard</i>
|
||||
Limited-time Discount: Stay safe and stay home while worldbuilding with friends! Shareable 3-month and 6-month Premium Codes are buy-one-get-one-free until
|
||||
<%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>. Click this banner to get started.
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<h4>Subscription Plan</h4>
|
||||
|
||||
<p>
|
||||
|
||||
@ -1,14 +1,40 @@
|
||||
<div class="row">
|
||||
<div class="col s12 m10 offset-m1">
|
||||
<div class="col s12">
|
||||
<div class="hoverable card">
|
||||
<div class="card-content">
|
||||
<div class="card-title">You can now purchase sharable Premium Codes for yourself or others</div>
|
||||
<p>
|
||||
Making a purchase below will generate a single-use code that can be redeemed at any time for a Premium subscription on Notebook.ai.
|
||||
You can purchase these codes for yourself if you'd like to prepay for a certain amount of months without a recurring monthly subscription,
|
||||
or for others if you'd like to gift a Notebook.ai Premium membership to someone else! You can purchase as many codes as you'd like
|
||||
and redeem them whenever you'd like.
|
||||
</p>
|
||||
<div class="card-title">Prepaid Premium Codes</div>
|
||||
<div class="row">
|
||||
<div class="col s12 m8 l9">
|
||||
<p>
|
||||
Making a purchase below will generate a single-use code that can be redeemed at any time for a Premium subscription on Notebook.ai.
|
||||
You can purchase these codes for yourself if you'd like to prepay for a certain amount of months without a recurring monthly subscription,
|
||||
or for others if you'd like to gift a Notebook.ai Premium membership to someone else!
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
You can purchase as many codes as you'd like and redeem them whenever you'd like.
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
While your Premium is active, you'll have access to <%= Rails.application.config.content_types[:premium].count %> additional worldbuilding
|
||||
pages: you'll be able to create unlimited
|
||||
<%=
|
||||
Rails.application.config.content_types[:premium].map { |page|
|
||||
" <strong class='#{page.color}-text'><i class='material-icons tiny'>#{page.icon}</i> #{page.name.pluralize}</strong>"
|
||||
}.to_sentence.html_safe
|
||||
%>!
|
||||
</p>
|
||||
</div>
|
||||
<div class="col hide-on-small-only m4 l3">
|
||||
<%= image_tag 'tristan/small.png',
|
||||
class: 'tooltipped tristan',
|
||||
data: {
|
||||
position: 'left',
|
||||
enterDelay: '500',
|
||||
tooltip: "Hey, I'm Tristan! I'm here to help you around the site!"
|
||||
} %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -18,7 +44,7 @@
|
||||
<div class="row">
|
||||
<div class="col s12 m6">
|
||||
<%= link_to prepay_paypal_gateway_path(months: 1), class: 'black-text' do %>
|
||||
<div class="hoverable card blue lighten-4" style="height: 170px;">
|
||||
<div class="hoverable card blue lighten-4" style="min-height: 170px;">
|
||||
<div class="card-content">
|
||||
<div class="card-title">
|
||||
<i class="material-icons left">star</i>
|
||||
@ -34,41 +60,53 @@
|
||||
</div>
|
||||
<div class="col s12 m6">
|
||||
<%= link_to prepay_paypal_gateway_path(months: 3), class: 'black-text' do %>
|
||||
<div class="hoverable card blue lighten-4" style="height: 170px;">
|
||||
<div class="hoverable card yellow lighten-4" style="min-height: 170px;">
|
||||
<div class="card-content">
|
||||
<div class="card-title">
|
||||
<i class="material-icons left">star</i>
|
||||
3 months of Premium
|
||||
<span class="badge yellow">includes limited-time offer</span>
|
||||
</div>
|
||||
<p>
|
||||
All Premium features
|
||||
for <strong>$24.00</strong><br />
|
||||
for <strong>$24.00</strong>
|
||||
(save $3.00 compared to monthly)
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
Limited-time offer: Purchasing this Premium Code before <%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>
|
||||
will generate <strong>two</strong> Premium Codes for the price of one!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="col s12 m6">
|
||||
<%= link_to prepay_paypal_gateway_path(months: 6), class: 'black-text' do %>
|
||||
<div class="hoverable card blue lighten-4" style="height: 170px;">
|
||||
<div class="hoverable card yellow lighten-4" style="min-height: 170px">
|
||||
<div class="card-content">
|
||||
<div class="card-title">
|
||||
<i class="material-icons left">star</i>
|
||||
6 months of Premium
|
||||
<span class="badge yellow">includes limited-time offer</span>
|
||||
</div>
|
||||
<p>
|
||||
All Premium features
|
||||
for <strong>$48.00</strong><br />
|
||||
for <strong>$48.00</strong>
|
||||
(save $6.00 compared to monthly)
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
Limited-time offer: Purchasing this Premium Code before <%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>
|
||||
will generate <strong>two</strong> Premium Codes for the price of one!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="col s12 m6">
|
||||
<%= link_to prepay_paypal_gateway_path(months: 12), class: 'black-text' do %>
|
||||
<div class="hoverable card blue lighten-4" style="height: 170px;">
|
||||
<div class="hoverable card blue lighten-4" style="min-height: 170px;">
|
||||
<div class="card-content">
|
||||
<div class="card-title">
|
||||
<i class="material-icons left">star</i>
|
||||
@ -76,7 +114,7 @@
|
||||
</div>
|
||||
<p>
|
||||
All Premium features
|
||||
for <strong>$84.00</strong><br />
|
||||
for <strong>$84.00</strong>
|
||||
(save $24.00 compared to monthly)
|
||||
</p>
|
||||
</div>
|
||||
@ -118,8 +156,13 @@
|
||||
</div>
|
||||
<p>
|
||||
<% if invoice.page_unlock_promo_code.present? %>
|
||||
<p>
|
||||
Description: <%= invoice.page_unlock_promo_code.description %>
|
||||
</p>
|
||||
<% if invoice.activateable? %>
|
||||
Promo code: <strong><%= invoice.page_unlock_promo_code.code %></strong>
|
||||
<p>
|
||||
Promo code: <strong><%= invoice.page_unlock_promo_code.code %></strong>
|
||||
</p>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<% if invoice.status == 'APPROVED' %>
|
||||
@ -172,7 +215,7 @@
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="card-action">
|
||||
<% if invoice.page_unlock_promo_code && invoice.page_unlock_promo_code.uses_remaining.zero? %>
|
||||
<% if invoice.page_unlock_promo_code && invoice.page_unlock_promo_code.uses_remaining.zero? && invoice.page_unlock_promo_code.promotions.any? %>
|
||||
Activated <%= time_ago_in_words invoice.page_unlock_promo_code.promotions.last.created_at %> ago
|
||||
<% else %>
|
||||
<% if invoice.status == 'CREATED' %>
|
||||
|
||||
5
config/initializers/promos.rb
Normal file
5
config/initializers/promos.rb
Normal file
@ -0,0 +1,5 @@
|
||||
Rails.application.config.promos = {}
|
||||
|
||||
Rails.application.config.promos[:promo_bogo] = {}
|
||||
Rails.application.config.promos[:promo_bogo][:start_date] = 'March 20, 2020'.to_date
|
||||
Rails.application.config.promos[:promo_bogo][:end_date] = Rails.application.config.promos[:promo_bogo][:start_date] + 2.weeks
|
||||
@ -74,12 +74,13 @@ Rails.application.routes.draw do
|
||||
# TODO delete deprecated/unused referrals controller/views
|
||||
|
||||
scope '/data' do
|
||||
get '/', to: 'data#index', as: :data_vault
|
||||
get '/usage', to: 'data#usage'
|
||||
get '/recyclebin', to: 'data#recyclebin'
|
||||
get '/archive', to: 'data#archive'
|
||||
get '/uploads', to: 'data#uploads'
|
||||
get '/discussions', to: 'data#discussions'
|
||||
get '/', to: 'data#index', as: :data_vault
|
||||
get '/usage', to: 'data#usage'
|
||||
get '/recyclebin', to: 'data#recyclebin'
|
||||
get '/archive', to: 'data#archive'
|
||||
get '/uploads', to: 'data#uploads'
|
||||
get '/discussions', to: 'data#discussions'
|
||||
get '/collaboration', to: 'data#collaboration'
|
||||
|
||||
scope 'export' do
|
||||
get '/', to: 'export#index', as: :notebook_export
|
||||
|
||||
Loading…
Reference in New Issue
Block a user