Skip to content
This repository has been archived by the owner on Mar 27, 2023. It is now read-only.

Add ability to create WhatsApp shares. #1169

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
097094a
Don't run simple_format on emails body
rodrei Jun 13, 2018
70623d5
Update email spec
vincemtnz Jun 14, 2018
86dfd9b
[hack] check to see if $ is being clobbered somewhere. (#1185)
osahyoun Jun 14, 2018
caa2d20
Update pension emails spec
vincemtnz Jun 14, 2018
7a6f9b3
Various bugfixes (#1187)
eyko Jun 14, 2018
157bfb2
Redo: "Release (#1188)"
vincemtnz Jun 14, 2018
75d5712
Set user context in sentry
vincemtnz Jun 18, 2018
4142aab
Add locale data in ComponentWrapper
vincemtnz Jun 18, 2018
dd6151d
Use jQuery from npm. Use eventemitter3 for pub/sub
vincemtnz Jun 19, 2018
fd0c9ba
Alias jquery to window.$, except for app/javascript/vendor/*
vincemtnz Jun 19, 2018
7b9a814
Also vendor lodash (using NPM, append to global)
vincemtnz Jun 20, 2018
f83f9ab
Update: reorganise some files (see desc)
vincemtnz Jun 20, 2018
b0245c1
Add migration, model and controller for whatsapp shares. Stopping wor…
Tuuleh May 8, 2018
87513ba
Refactor shares controller to use sp variant builder only for sp shares
Tuuleh May 31, 2018
32c744c
Move SP variant builder code into ShareVariantBuilder which will also…
Tuuleh Jun 1, 2018
a48659e
Make button URL update work with non-sp shares
Tuuleh Jun 1, 2018
bbdb39d
Make it possible to update text and url on whatsapp buttons
Tuuleh Jun 4, 2018
a4b6cc6
Add working UI component for whatsapp buttons
Tuuleh Jun 5, 2018
22813c8
fix specs
Tuuleh Jun 5, 2018
cbc28a6
Stuck in gsub for link string, continue tomorrow
Tuuleh Jun 5, 2018
0cd55ef
Add variant ID to whatsapp button container and link URL, and serve w…
Tuuleh Jun 7, 2018
324c9f9
Remove whatsapp button on other than mobile devices
Tuuleh Jun 8, 2018
57b20d0
Add / modify specs
Tuuleh Jun 8, 2018
5d57bbd
Rename 'share_count' to 'conversion_count' for whatsapp shares
Tuuleh Jun 8, 2018
3b49c60
Default values for click and conversion count
Tuuleh Jun 12, 2018
fd82eda
Use ERB::Util instead of CGI.escape to escape whatsapp strings to get…
Tuuleh Jun 12, 2018
d5213b4
Add tracking for whatsapp clicks and conversions
Tuuleh Jun 8, 2018
9a0473f
Add a some scopes and request specs and a buggy UI to view click and …
Tuuleh Jun 12, 2018
e9959bd
Less buggy UI but still not 100%
Tuuleh Jun 12, 2018
9f0a251
Add working UI and conversion count calculation
Tuuleh Jun 13, 2018
120cb5e
Fix share tracking, add spec for sp scope on button
Tuuleh Jun 13, 2018
19d8794
Rename sp_type to share_type and sp_button_html to share_button_html
Tuuleh Jun 14, 2018
cdb27ee
Show share titles if there are shares on the page
Tuuleh Jun 14, 2018
9dd8446
Add method to construct the variant HTML in the Whatsapp model.
Tuuleh Jun 19, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/assets/stylesheets/member-facing/_colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ $dark-navy: #1f2533;
$facebook: #597ac7;
$twitter: #5dbeec;
$paypal: #1a9ddb;
$whatsapp: #25D366;

// grays, named per http://davidwalsh.name/sass-color-variables-dont-suck
$chalk-gray: #ececec;
Expand Down
28 changes: 19 additions & 9 deletions app/assets/stylesheets/member-facing/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,16 @@ button.button {
// shareprogress isn't super customization friendly, so we do
// what we can.
.button {
&--facebook, &--twitter {
float: left;
width: 145px;
&.sp_em_small, &.sp_em_large, &.sp_tw_small, &.sp_tw_large, &.sp_fb_small, &.sp_fb_large {
a {
width: 100%;
max-width: 145px;
padding-top: 20px;
}
&--facebook, &--twitter, &--whatsapp {
margin-top: 10px;
margin-left: 5px;
margin-right: 5px;
display: inline-block;
width: 135px;
a {
width: 100%;
max-width: 135px;
padding-top: 20px;
}

a::before {
Expand Down Expand Up @@ -96,6 +97,15 @@ button.button {
}
}
}
&--whatsapp {
a {
@include button($whatsapp);
padding-top: 15px;
color: $whatsapp;
font-size: 1px;
font-size: 0;
}
}
&--facebook a::before {
content: "Share";
}
Expand Down
15 changes: 14 additions & 1 deletion app/controllers/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class PagesController < ApplicationController
before_action :get_page_or_homepage, only: [:show]
before_action :redirect_unless_published, only: %i[show follow_up]
before_action :localize, only: %i[show follow_up]
before_action :record_tracking, only: %i[show]

def index
@pages = Search::PageSearcher.search(search_params)
Expand All @@ -33,7 +34,8 @@ def new
end

def edit
@variations = @page.shares
@sp_variations = @page.shares('sp')
@local_variations = @page.shares('local')
render :edit
end

Expand Down Expand Up @@ -126,6 +128,17 @@ def update

private

def record_tracking
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be a part of the upcoming work on this (recording actions on different WhatsApp variants on Champaign).

# Currently the only use case is to parse query parameters for a whatsapp variant
# to see if the member has come from a whatsapp share.
return unless params[:src] == 'whatsapp'
Share::Whatsapp.find(params[:variant_id]).increment!(:conversion_count)
rescue ActiveRecord::RecordNotFound
Rails.logger.error(
"Conversion count increment attempted on an invalid #{params[:src]} variant ID #{params[:variant_id]}."
)
end

def get_page
@page = Page.find(params[:id])
rescue ActiveRecord::RecordNotFound
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/share/emails_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true

class Share::EmailsController < Share::SharesController
private

Expand All @@ -12,7 +13,7 @@ def new_defaults
def permitted_params
params
.require(:share_email)
.permit(:subject, :body)
.permit(:subject, :body, :name)
end

def share_class
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/share/facebooks_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true

class Share::FacebooksController < Share::SharesController
private

Expand All @@ -16,6 +17,6 @@ def share_class
def permitted_params
params
.require(:share_facebook)
.permit(:title, :image_id, :description)
.permit(:title, :image_id, :description, :name)
end
end
30 changes: 18 additions & 12 deletions app/controllers/share/shares_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# frozen_string_literal: true

require 'share_progress'

class Share::SharesController < ApplicationController
before_action :set_resource
before_action :find_page
before_action :authenticate_user!
before_action :find_page, except: 'track'
before_action :authenticate_user!, except: 'track'

def new
@share = share_class.new(new_defaults)
Expand All @@ -22,7 +23,7 @@ def index
end

def update
@share = ShareProgressVariantBuilder.update(
@share = ShareVariantBuilder.update(
params: permitted_params,
variant_type: @resource.to_sym,
page: @page,
Expand All @@ -40,24 +41,23 @@ def update

def update_url
@page.share_buttons.each do |button|
url = params[button.sp_type.to_sym]
url = params[button.share_type.to_sym]

if url
ShareProgressVariantBuilder.update_button_url(url, button)
ShareVariantBuilder.update_button_url(url, button)
end
end

render :update_url_form
end

def create
@share = ShareProgressVariantBuilder.create(
@share = ShareVariantBuilder.create(
params: permitted_params,
variant_type: @resource.to_sym,
page: @page,
url: member_facing_page_url(@page)
)

respond_to do |format|
if @share.errors.empty?
format.html { redirect_to index_path }
Expand All @@ -71,7 +71,7 @@ def create

def destroy
find_share
@deleted_share = ShareProgressVariantBuilder.destroy(
@deleted_share = ShareVariantBuilder.destroy(
params: {},
variant_type: @resource.to_sym,
page: @page,
Expand All @@ -86,17 +86,23 @@ def destroy
end
end

def track
params.permit(:variant_type, :variant_id)
case params[:variant_type]
when 'whatsapp'
Share::Whatsapp.find(params[:variant_id]).increment!(:click_count)
end
end

private

def find_share
@share = share_class.find params[:id]
end

#
# Assigns resource name, which is taken from controller's class name.
# +Share::TwittersController+ becomes +twitter+
#
def set_resource
# Assigns resource name, which is taken from controller's class name.
# +Share::TwittersController+ becomes +twitter+
@resource = self.class.name.demodulize.gsub('Controller', '').downcase.singularize
end

Expand Down
3 changes: 2 additions & 1 deletion app/controllers/share/twitters_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true

class Share::TwittersController < Share::SharesController
private

Expand All @@ -9,7 +10,7 @@ def new_defaults
def permitted_params
params
.require(:share_twitter)
.permit(:description)
.permit(:description, :name)
end

def share_class
Expand Down
19 changes: 19 additions & 0 deletions app/controllers/share/whatsapps_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class Share::WhatsappsController < Share::SharesController
private

def new_defaults
{ text: "#{@page.title} {LINK}" }
end

def permitted_params
params
.require(:share_whatsapp)
.permit(:text, :name)
end

def share_class
Share::Whatsapp
end
end
9 changes: 7 additions & 2 deletions app/helpers/pages_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def record_range(page_number, per_page)
def prefill_link(new_variant)
new_variant.description = '{LINK}' if new_variant.name == 'twitter'
new_variant.body = '{LINK}' if new_variant.name == 'email'
new_variant.text = '{LINK}' if new_variant.name == 'whatsapp'
new_variant
end

Expand Down Expand Up @@ -155,8 +156,12 @@ def toggle_featured_link(page)
end
end

def share_url(button)
"http://sumof.us/99/#{button.sp_id}/#{button.sp_type}"
def share_url(variant)
if variant.share_progress?
"http://sumof.us/99/#{variant.button.sp_id}/#{variant.button.share_type}"
else
URI.extract(variant.html).first
end
end

def collapse_share_url_form(page)
Expand Down
5 changes: 4 additions & 1 deletion app/javascript/campaigner_facing/actions_editor.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// @flow
import $ from 'jquery';
import ee from '../shared/pub_sub';
import setupOnce from './setup_once';
import Backbone from 'backbone';

const ActionsEditor = Backbone.View.extend({
events: {
Expand Down Expand Up @@ -35,6 +38,6 @@ const ActionsEditor = Backbone.View.extend({
},
});

$.subscribe('actions:edit', function() {
ee.on('actions:edit', function() {
setupOnce('.actions-editor', ActionsEditor);
});
5 changes: 4 additions & 1 deletion app/javascript/campaigner_facing/ajax.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import ErrorDisplay from '../shared/show_errors';
import $ from 'jquery';

$(function() {
var handleStart = function(e, i) {
var button = $(e.target).find('.xhr-feedback');

$(e.target).find('.xhr-feedback-saving').remove();
$(e.target)
.find('.xhr-feedback-saving')
.remove();

button.prop('disabled', true);

Expand Down
3 changes: 2 additions & 1 deletion app/javascript/campaigner_facing/analytics.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
import $ from 'jquery';
import d3 from 'd3';
const Y_AXIS_LABEL_LIMIT = 20;

class AnalyticsDashboard {
Expand Down
12 changes: 8 additions & 4 deletions app/javascript/campaigner_facing/collection_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
//
// Twitter's typeahead: http://twitter.github.io/typeahead.js/
// - Use for autocompleting for setting the field's name value

import $ from 'jquery';
import ee from '../shared/pub_sub';
import setupOnce from './setup_once';
import ErrorDisplay from '../shared/show_errors';
import GlobalEvents from '../shared/global_events';
Expand Down Expand Up @@ -57,7 +57,9 @@ const CollectionEditor = Backbone.View.extend({
this.makeSortable();
this.autoComplete();
this.$el.on('ajax:success', 'a[data-method=delete]', function() {
$(this).parents('.list-group-item').fadeOut();
$(this)
.parents('.list-group-item')
.fadeOut();
});
GlobalEvents.bindEvents(this);
},
Expand Down Expand Up @@ -149,12 +151,14 @@ const CollectionEditor = Backbone.View.extend({
i,
el
) {
const action = $(el).attr('action').replace(/\d+/, resp.form_id);
const action = $(el)
.attr('action')
.replace(/\d+/, resp.form_id);
$(el).attr('action', action);
});
},
});

$.subscribe('collection:edit:loaded', function() {
ee.on('collection:edit:loaded', function() {
setupOnce('.collection-editor', CollectionEditor);
});
24 changes: 17 additions & 7 deletions app/javascript/campaigner_facing/configure_wysiwyg.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// @flow
import $ from 'jquery';
import ee from '../shared/pub_sub';

const TALL_EDITORS = ['page_body'];

function configureWysiwyg(e, id) {
function configureWysiwyg(id) {
const $editor = $('#' + id);
if ($editor.length === 0) {
return false;
return;
}

// $FlowIgnore
$editor.summernote({
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
Expand All @@ -28,8 +31,9 @@ function configureWysiwyg(e, id) {
},
});
const $contentField = $('#' + id + '_content');

// $FlowIgnore
$editor.summernote('fontSize', '16'); // default
// $FlowIgnore
$editor.summernote('code', $contentField.val());

// In order to make an iframe size down with the containing column
Expand All @@ -42,17 +46,23 @@ function configureWysiwyg(e, id) {
}
const $html = $(html);
// addClass is idempotent so we just call it every time we save
$html.find('iframe').parent().addClass('iframe-responsive-container');
$html
.find('iframe')
.parent()
.addClass('iframe-responsive-container');
// this little goof is just cause jquery doesn't have $el.outerHtml();
return $('<div></div>').append($html).html();
return $('<div></div>')
.append($html)
.html();
};

const updateContentBeforeSave = function() {
// $FlowIgnore
const content = encapsulateIframes($editor.summernote('code'));
$contentField.val(content);
};

$.subscribe('wysiwyg:submit', updateContentBeforeSave);
ee.on('wysiwyg:submit', updateContentBeforeSave);
}

$.subscribe('wysiwyg:setup', configureWysiwyg);
ee.on('wysiwyg:setup', configureWysiwyg);
Loading