Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Adicionar ação de Pressão do Bonde como Plugin #122

Merged
merged 9 commits into from
Sep 27, 2023
21 changes: 21 additions & 0 deletions TUTORIAIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### Etapas para cadastrar um site

#### Adicionar registro de domínio

Variaveis:
- Comunidade ID (2548): Obrigatório
- Endereço de domínio do SITE (busao.localhost:8000): Obrigatório
- Comentário: Opcional

```
insert into dns_hosted_zones(community_id, domain_name, comment) values(2548, 'busao.localhost:8000', 'Criado manualmente');
```

#### Configurar ALLOWED_HOSTS e novo Site no projeto

Variaveis:
- Endereço de domínio do SITE (busao.localhost:8000): Obrigatório

Adicionar Endereço de domínio na variavel ALLOWED_HOSTS do serviço no Portainer.

Criar novo Site através do Administrador (Linkar tutorial de inserir Novo Site)
7 changes: 6 additions & 1 deletion app/contrib/actions/pressure/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class PressurePlugin(CMSPluginBase):

def render(self, context, instance, placeholder):
obj = instance.get_widget()
request = context["request"]
initial = (
{
"email_subject": obj.settings.get("pressure_subject", ""),
Expand All @@ -28,7 +29,11 @@ def render(self, context, instance, placeholder):

if instance.reference_id:
form = PressureAjaxForm(
initial={"reference_id": instance.reference_id, **initial}
initial={
"reference_id": instance.reference_id,
"referrer_path": f"{request.scheme}://{request.get_host()}{request.path}",
**initial,
}
)

context.update(
Expand Down
35 changes: 27 additions & 8 deletions app/contrib/actions/pressure/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import json
import jwt
import requests

from django import forms
from django.conf import settings

from contrib.bonde.forms import ReferenceBaseModelForm
from tailwind.forms import StyledBaseForm
Expand All @@ -18,6 +21,7 @@ class Meta(ReferenceBaseModelForm.Meta):

class PressureAjaxForm(StyledBaseForm):
reference_id = forms.IntegerField(widget=forms.HiddenInput)
referrer_path = forms.CharField(widget=forms.HiddenInput)

email_address = forms.EmailField(label="Seu e-mail")
name = forms.CharField(label="Seu nome", max_length=80)
Expand All @@ -39,13 +43,28 @@ def submit(self):
"email_subject": self.cleaned_data["email_subject"],
"email_body": self.cleaned_data["email_body"],
"form_data": json.dumps(self.cleaned_data),
"token": jwt.encode({}, settings.BONDE_ACTION_SECRET_KEY),
}

print(
"Submitting ->>",
{
"activist": activist,
"input": input,
"widget_id": self.cleaned_data["reference_id"],
},
)
query = """
mutation Pressure($activist: ActivistInput!, $input: EmailPressureInput, $widget_id: Int!) {
create_email_pressure(
activist: $activist,
widget_id: $widget_id,
input: $input
) {
data
}
}
"""
variables = {
"activist": activist,
"input": input,
"widget_id": self.cleaned_data["reference_id"],
}

resp = requests.post(settings.BONDE_ACTION_API_URL, json={"query": query, "variables": variables})
if resp.status_code == 200:
print(resp.json())
else:
raise Exception("Query failed to run by returning code of {}. {}".format(resp.status_code, query))
31 changes: 26 additions & 5 deletions app/contrib/actions/pressure/static/pressure/js/pressure.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,31 @@

$(function () {
$(".pressure-plugin form").on("submit", function (evt) {
const $form = $(this);
const $form = $(this);

function handleResponse(data) {
if (data.success) {
alert("success");
function showTooltip() {
const tooltip = $("#copyToClipboardTooltip");
tooltip.toggleClass("tooltip-open hover:before:block hover:after:block");

// hide after 3 seconds
window.setTimeout(function () {
tooltip.removeClass("tooltip-open hover:before:block hover:after:block");
}, 2000);
}

function handleResponse(data) {
if (data.success) {
$("#pressureWrapper").empty();
$("#pressureWrapper").html(data.html);

$("#copyToClipboard").on("click", function () {
const textToCopy = window.location.href;

navigator.clipboard
.writeText(textToCopy)
.then(showTooltip)
.catch(() => console.error("Erro ao copiar link, tente novamente."));
});
window.gtag("event", "form_submit_success", { form_id: $form.attr("id") });
} else {
$form.find('.errorlist').empty();
Expand All @@ -25,10 +45,11 @@
}

evt.preventDefault();
$("#id_referrer_path").val(window.location.href);
$.ajax($form.attr('action'), {
type: 'POST',
data: $form.serialize(),
}).always(handleResponse);
});
});
}(window.jQuery));
}(window.jQuery));
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
<script type="text/javascript" src="{% static 'pressure/js/pressure.js' %}"></script>
{% endaddtoblock %}

<div class="container pressure-plugin plugin">
<div id="pressureWrapper" class="container pressure-plugin plugin">
<div class="bg-white rounded-lg">
<h3 class="text-lg font-bold text-center px-4 pt-4">{{settings.title}}</h3>
<div class="bg-gray-200 px-6 py-4">
<h3 class="px-4 pt-4 text-lg font-bold text-center">{{settings.title}}</h3>
<div class="px-6 py-4 bg-gray-200">
{% with settings.targets|length as targets_size %}
<p class="mb-2">Quem você vai pressionar? ({{targets_size}} alvo{% if targets_size > 1 %}s{% endif %})</p>
<ul class="flex gap-2 overflow-x-auto pb-2">
<ul class="flex overflow-x-auto gap-2 pb-2">
{% for target in settings.targets %}
<li class="bg-white text-sm py-2 px-4">
<li class="px-4 py-2 text-sm bg-white">
<p class="font-bold">{{ target.name }}</p>
<p>{{ target.email }}</p>
</li>
{% endfor %}
</ul>
{% endwith %}
</div>

<form id="pressureForm" method="post" action="{% url 'action_pressure' %}" novalidate>
{% csrf_token %}
{% for field in form.visible_fields %}
<div class="form-control py-2 px-6">
<div class="px-6 py-2 form-control">
<div class="relative">
{{ field }}
{% if field.label %}
Expand All @@ -37,13 +37,13 @@ <h3 class="text-lg font-bold text-center px-4 pt-4">{{settings.title}}</h3>
</div>
{% endfor %}
{% for hidden_field in form.hidden_fields %}{{hidden_field}}{% endfor %}
<div class="px-6 pt-4 pb-6 flex flex-col gap-4">
<button type="submit" class="btn w-full">{{settings.button}}</button>
<div class="flex flex-col gap-4 px-6 pt-4 pb-6">
<button type="submit" class="w-full btn">{{settings.button}}</button>
<p class="text-xs">Ao inserir seus dados, você concorda em ter seus dados compartilhados com os organizadores
dessa página e aceita receber emails de atualização, conforme descrito na política de privacidade. Você pode
cancelar o recebimento desses e-mails a qualquer momento.</p>
<p class="text-lg text-center font-bold">{{ size }} {{ settings.count }}</p>
<p class="py-4 text-sm text-center text-bold">{{ size }} {{ settings.count }}</p>
</div>
</form>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<div class="px-4 py-4 bg-white rounded-lg">
<h3 class="px-4 pt-4 text-lg font-bold text-center">Valeu, {{form_data.name}}! 🎉 <br/>Sua pressão foi enviada.</h3>
<p class="py-4 text-center">Agora compartilhe nas redes para mais gente fazer parte desse movimento:</p>
<div class="flex flex-col gap-4 justify-center pb-4">
<a class="w-full btn btn-whatsapp" href="https://wa.me/?text={{ form_data.referrer_path }}" target="_blank">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.0002 7.79396C16.0002 12.0985 12.4839 15.5879 8.14553 15.5879C6.76826 15.5879 5.47438 15.2359 4.34868 14.6181L0 16L1.4178 11.8183C0.702587 10.6439 0.29067 9.26649 0.29067 7.79396C0.29067 3.48942 3.80734 0 8.14553 0C12.4842 0 16.0002 3.48942 16.0002 7.79396ZM8.14553 1.24124C4.50388 1.24124 1.54171 4.1808 1.54171 7.79396C1.54171 9.22773 2.00909 10.5556 2.79968 11.6357L1.9746 14.0693L4.51241 13.2628C5.55509 13.9474 6.80418 14.3467 8.1457 14.3467C11.7868 14.3467 14.7495 11.4075 14.7495 7.79431C14.7495 4.18116 11.787 1.24124 8.14553 1.24124ZM12.112 9.58898C12.0634 9.50951 11.9353 9.46151 11.7429 9.36604C11.5502 9.27058 10.6033 8.80818 10.4273 8.74471C10.2508 8.68107 10.1221 8.64907 9.99391 8.84018C9.86573 9.03147 9.49665 9.46151 9.38412 9.58898C9.27176 9.7168 9.15958 9.7328 8.96687 9.63716C8.77451 9.54169 8.15424 9.33973 7.41876 8.68907C6.84649 8.18276 6.45999 7.55769 6.34764 7.36622C6.23546 7.17511 6.3359 7.07182 6.43208 6.97671C6.51884 6.89102 6.6248 6.7536 6.72097 6.64213C6.81751 6.53049 6.84951 6.45102 6.91333 6.32338C6.97787 6.19591 6.94569 6.08444 6.89733 5.98862C6.84933 5.89316 6.4639 4.95307 6.30355 4.57049C6.14319 4.18827 5.98301 4.25191 5.87047 4.25191C5.7583 4.25191 5.62976 4.23591 5.5014 4.23591C5.37305 4.23591 5.16433 4.28373 4.9878 4.47484C4.81144 4.66613 4.31419 5.12836 4.31419 6.06827C4.31419 7.00836 5.0038 7.91662 5.10033 8.04391C5.19651 8.1712 6.4319 10.163 8.38926 10.928C10.3468 11.6926 10.3468 11.4375 10.6999 11.4055C11.0526 11.3737 11.8387 10.9435 11.9998 10.4976C12.1598 10.051 12.1598 9.66862 12.112 9.58898Z" fill="white"/>
</svg>
<span class="ml-2">COMPARTILHAR NO WHATSAPP</span>
</a>
<a class="w-full btn btn-twitter" href="https://twitter.com/intent/tweet?url={{ form_data.referrer_path }}" target="_blank">
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.6975 1.89305C18.9725 2.21429 18.1946 2.43216 17.3773 2.52942C18.2118 2.02968 18.8506 1.23702 19.1534 0.295398C18.3706 0.758193 17.5065 1.09424 16.5858 1.27641C15.8485 0.489895 14.7998 0 13.6367 0C11.4051 0 9.59574 1.80937 9.59574 4.03969C9.59574 4.35601 9.63144 4.66496 9.70038 4.96039C6.3426 4.79174 3.36515 3.18301 1.37239 0.738495C1.02404 1.33425 0.825879 2.02842 0.825879 2.76943C0.825879 4.1714 1.53979 5.40841 2.62295 6.13213C1.96074 6.10999 1.33792 5.92782 0.792664 5.62502V5.67549C0.792664 7.63256 2.186 9.2659 4.03351 9.63764C3.69502 9.72873 3.33808 9.7792 2.96882 9.7792C2.70789 9.7792 2.45556 9.75335 2.20815 9.70411C2.72263 11.3104 4.21446 12.4785 5.98199 12.5105C4.59972 13.5937 2.85681 14.2374 0.963762 14.2374C0.637594 14.2374 0.316319 14.2177 0 14.182C1.78845 15.3304 3.91169 16 6.19371 16C13.6269 16 17.69 9.84321 17.69 4.50374L17.6764 3.98063C18.4703 3.41439 19.1571 2.70297 19.6975 1.89305Z" fill="white"/>
</svg>
<span class="ml-2">COMPARTILHAR NO TWITTER</span>
</a>
<a class="w-full btn btn-facebook" href="http://www.facebook.com/sharer.php?u={{ form_data.referrer_path }}" target="_blank">
<svg width="9" height="16" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.272495 8.52159H2.1242V15.7419C2.1242 15.8845 2.24615 16 2.39667 16H5.53631C5.68683 16 5.80878 15.8845 5.80878 15.7419V8.55562H7.9375C8.07591 8.55562 8.19238 8.45725 8.20818 8.32703L8.53149 5.66888C8.54036 5.59575 8.51591 5.5225 8.46424 5.46763C8.41254 5.41272 8.33854 5.38128 8.26087 5.38128H5.80891V3.715C5.80891 3.21272 6.09444 2.958 6.65771 2.958C6.73798 2.958 8.26087 2.958 8.26087 2.958C8.41139 2.958 8.53333 2.84244 8.53333 2.69994V0.259969C8.53333 0.117406 8.41139 0.00190625 8.26087 0.00190625H6.05145C6.03587 0.0011875 6.00126 0 5.95025 0C5.5669 0 4.23438 0.0712812 3.18178 0.988437C2.01552 2.00481 2.17765 3.22172 2.21639 3.43272V5.38122H0.272462C0.121945 5.38122 0 5.49672 0 5.63928V8.2635C3.29937e-05 8.40603 0.121978 8.52159 0.272495 8.52159Z" fill="white"/>
</svg>
<span class="ml-2">COMPARTILHAR NO FACEBOOK</span>
</a>
<div id="copyToClipboardTooltip" class="tooltip tooltip-bottom hover:before:hidden hover:after:hidden" data-tip="Link copiado">
<button id="copyToClipboard" class="w-full btn btn-copy">
<svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.0352 19H2.96241C1.32889 19 0 17.6683 0 16.0312V5.97461C0 4.33759 1.32889 3.00586 2.96241 3.00586H10.0352C11.6687 3.00586 12.9976 4.33759 12.9976 5.97461V16.0312C12.9976 17.6683 11.6687 19 10.0352 19ZM2.96241 4.49023C2.14572 4.49023 1.48121 5.15617 1.48121 5.97461V16.0312C1.48121 16.8497 2.14572 17.5156 2.96241 17.5156H10.0352C10.8519 17.5156 11.5164 16.8497 11.5164 16.0312V5.97461C11.5164 5.15617 10.8519 4.49023 10.0352 4.49023H2.96241ZM15.96 14.1758V2.96875C15.96 1.33173 14.6311 0 12.9976 0H4.77689C4.36782 0 4.03629 0.332245 4.03629 0.742188C4.03629 1.15213 4.36782 1.48438 4.77689 1.48438H12.9976C13.8143 1.48438 14.4788 2.15031 14.4788 2.96875V14.1758C14.4788 14.5857 14.8103 14.918 15.2194 14.918C15.6285 14.918 15.96 14.5857 15.96 14.1758Z" fill="white"/>
</svg>
<span class="ml-2">COPIAR LINK</span>
</button>
</div>
</div>
<p class="py-4 text-sm text-center text-bold">{{ form_data.total_actions }}</p>
</div>
44 changes: 20 additions & 24 deletions app/contrib/actions/pressure/views.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
import json

from django.http import HttpResponse
from django.http import JsonResponse
from django.views.generic import FormView
from django.shortcuts import render

from .forms import PressureAjaxForm


class AjaxableResponseMixin(object):
"""
Mixin to add AJAX support to a form.
Must be used with an object-based FormView (e.g. CreateView)
"""

def render_to_json_response(self, context, **response_kwargs):
data = json.dumps(context)
response_kwargs["content_type"] = "application/json"
return HttpResponse(data, **response_kwargs)
return JsonResponse(context, **response_kwargs)

def form_invalid(self, form):
response = super(AjaxableResponseMixin, self).form_invalid(form)
response = super().form_invalid(form)
if self.request.is_ajax():
return self.render_to_json_response(form.errors) # , status=400)
return self.render_to_json_response({'success': False, 'errors': form.errors}, status=400)
else:
return response

def form_valid(self, form):
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
response = super(AjaxableResponseMixin, self).form_valid(form)
if self.request.is_ajax():
data = {
"success": True,
}
return self.render_to_json_response(data)
else:
return response
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
response = super().form_valid(form)

if self.request.is_ajax():
form.submit()
data = {
'success': True,
'html': render(self.request, 'pressure/pressure_success.html', {"form_data": form.cleaned_data}).content.decode('utf-8')
}
return self.render_to_json_response(data)
else:
return response


class PressureFormAjaxView(AjaxableResponseMixin, FormView):
Expand All @@ -50,9 +51,4 @@ class PressureFormAjaxView(AjaxableResponseMixin, FormView):
# this plugin is coming from.
#
def get_success_url(self):
return self.request.path

def form_valid(self, form):
# AjaxableResponseMixin expects our contact object to be 'self.object'.
self.object = form.submit()
return super(PressureFormAjaxView, self).form_valid(form)
return self.request.path
5 changes: 3 additions & 2 deletions app/contrib/bonde/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ def __str__(self):
return self.name

def get_signature(self):
signature = self.signature or {}
return {
"name": self.signature.get("name", self.name),
"url": self.signature.get("url", "#"),
"name": signature.get("name", self.name),
"url": signature.get("url", "#"),
}


Expand Down
4 changes: 4 additions & 0 deletions app/project/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@
"contrib.bonde.router.AuthRouter",
]

BONDE_ACTION_API_URL = env.str("BONDE_ACTION_API_URL", "http://api-graphql.localhost/v1/graphql")

BONDE_ACTION_SECRET_KEY = env.str("BONDE_ACTION_SECRET_KEY", "")

# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

Expand Down
2 changes: 2 additions & 0 deletions app/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ whitenoise
svglib
reportlab
django-social-share
pyjwt
requests
28 changes: 28 additions & 0 deletions app/tailwind/plugins/socialbuttons.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const plugin = require('tailwindcss/plugin');
const colorFunctions = require('daisyui/src/theming/functions');

const colorProperties = (colorName, theme) => {
const color = theme("colors." + colorName);
const colorFocus = colorFunctions.generateDarkenColorFrom(color);
// const colorContent = colorFunctions.generateForegroundColorFrom(color);

return {
'color': 'white',
'background-color': color,
'&:hover': {
'background-color': theme("colors." + colorName + "-focus", "hsl(" + colorFocus + ")")
}
}
}

const socialbutton = plugin(({ addUtilities, theme }) => {

addUtilities({
'.btn-whatsapp': colorProperties('whatsapp', theme),
'.btn-facebook': colorProperties('facebook', theme),
'.btn-twitter': colorProperties('twitter', theme),
'.btn-copy': colorProperties('copy', theme),
})
})

module.exports = socialbutton
Loading
Loading