Skip to content
Snippets Groups Projects
Commit 37720baf authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

add email signature generator

parent f4a0b5e4
No related branches found
No related tags found
3 merge requests!5Release,!4Release,!3Release
Pipeline #11628 passed
Showing
with 290 additions and 7 deletions
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class MailSignatureConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'mail_signature'
from django.db import models
# Create your models here.
{% extends "shared/base.html" %}
{% load render_bundle from webpack_loader %}
{% block title %}Generátor emailových podpisů{% endblock %}
{% block header_name %}Emailové podpisy{% endblock %}
{% block description %}Vyplněním získáš HTML kód, který můžeš vložit jako podpis do svých emailů.{% endblock %}
{% block head %}
<link
rel="stylesheet"
href="https://styleguide.pirati.cz/2.11.x/css/styles.css"
>
{% render_bundle "mail_signature" %}
{% endblock %}
{% block content %}
<main>
<h1 class="text-6xl font-bebas mb-5">Generátor emailových podpisů</h1>
<div class="prose max-w-none mb-5">
<p>
Vyplněním následujícího formuláře získáš HTML kód,
který můžeš vložit jako podpis do svých emailů.
</p>
</div>
<div class="grid gap-4 grid-cols-1 lg:grid-cols-2">
<form class="flex flex-col gap-3" id="source">
<div class="flex gap-4 items-center">
<label class="basis-56 flex items-center font-bold" for="name">
Jméno:
</label>
<input
id="name"
name="name"
type="text"
class="border border-gray-200 p-2 rounded-md grow w-full"
>
</div>
<div class="flex gap-4 items-center">
<label class="basis-56 flex items-center font-bold" for="function">
Název funkce:
</label>
<input
id="function"
name="function"
type="text"
class="border border-gray-200 p-2 rounded-md grow w-full"
>
</div>
<div class="flex gap-4 items-center">
<label class="basis-56 flex items-center font-bold" for="email">
E-mail:
</label>
<input
id="email"
name="email"
type="email"
class="border border-gray-200 p-2 rounded-md grow w-full"
>
</div>
<div class="flex gap-4 items-center">
<label class="basis-56 flex items-center font-bold" for="phone">
Telefonní číslo:
</label>
<input
id="phone"
name="phone"
type="tel"
class="border border-gray-200 p-2 rounded-md grow w-full"
>
</div>
<div class="flex gap-4 items-center">
<label class="basis-56 flex items-center font-bold" for="fejsbuk">
Facebook odkaz:
</label>
<input
id="fejsbuk"
name="fejsbuk"
type="url"
class="border border-gray-200 p-2 rounded-md grow w-full"
>
</div>
<div class="flex gap-4 items-center">
<label class="basis-56 flex items-center font-bold" for="linkedin">
LinkedIn odkaz:
</label>
<input
id="linkedin"
name="linkedin"
type="url"
class="border border-gray-200 p-2 rounded-md grow w-full"
>
</div>
<div class="text-right">
<button id="generate" class="btn btn--icon" type="button">
<div class="btn__body-wrap">
<div class="btn__body">Vygenerovat</div>
<div class="btn__icon">
<i class="ico--chevron-right"></i>
</div>
</div>
</button>
</div>
</form>
<div class="flex flex-col gap-3">
<div class="border border-gray-400 border-dotted p-2 rounded-md" id="preview"></div>
<textarea
class="border border-gray-200 p-2 font-mono rounded-md w-full"
rows="5"
id="content"
readonly
></textarea>
</div>
</div>
</main>
{% endblock %}
from django.test import TestCase
# Create your tests here.
from django.urls import path
from . import views
app_name = "mail_signature"
urlpatterns = [
path("", views.index, name="index"),
]
from django.shortcuts import render
# Create your views here.
def index(request):
return render(
request,
"mail_signature/index.html"
)
......@@ -4,6 +4,7 @@
"description": "",
"private": true,
"dependencies": {
"@tailwindcss/typography": "^0.5.9",
"css-loader": "^6.7.3",
"jquery": "^3.6.3",
"js-cookie": "^3.0.1",
......
......@@ -25,12 +25,14 @@
<main>
<h1 class="text-6xl font-bebas mb-5">Kalkulačka hlasování RV</h1>
<p class="mb-5 text-gray-800">
Jednací řád k nahlédnutí <a
class="underline"
href="https://wiki.pirati.cz/rules/jrrv#rozhodujici_hlasovani_pri_referendu"
>na wiki</a>, § 9 (3).
</p>
<div class="prose max-w-none mb-5">
<p>
Jednací řád k nahlédnutí <a
class="underline"
href="https://wiki.pirati.cz/rules/jrrv#rozhodujici_hlasovani_pri_referendu"
>na wiki</a>, § 9 (3).
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-7">
<div>
......
......@@ -48,6 +48,7 @@ INSTALLED_APPS = [
"shared",
"member_group_size_calc",
"rv_voting_calc",
"mail_signature",
]
MIDDLEWARE = [
......
......@@ -18,5 +18,6 @@ from django.urls import include, path
urlpatterns = [
path("vypocet-skupiny-clenu/", include("member_group_size_calc.urls")),
path("hlasovani-rv/", include("rv_voting_calc.urls")),
path("emailove-podpisy/", include("mail_signature.urls")),
path("", include("shared.urls")),
]
shared/static/shared/signature.webp

113 KiB

......@@ -34,6 +34,7 @@
</div>
</div>
</li>
<li class="card">
<a href="{% url "rv_voting_calc:index" %}">
<img
......@@ -53,6 +54,7 @@
</div>
</div>
</li>
<li class="card">
<a href="https://z.pirati.cz" target="_blank">
<img
......@@ -72,6 +74,26 @@
</div>
</div>
</li>
<li class="card">
<a href="{% url "mail_signature:index" %}" target="_blank">
<img
src="{% static "shared/signature.webp" %}"
alt="Generátor emailových podpisů"
class="w-full h-48 object-cover"
>
</a>
<div class="p-4">
<h2 class="mb-2 text-xl font-bold">
<a href="{% url "mail_signature:index" %}" target="_blank">
Generátor emailových podpisů
</a>
</h2>
<div class="font-light text-sm break-words">
Vyplněním získáš HTML kód, který můžeš vložit jako podpis do svých emailů.
</div>
</div>
</li>
</ul>
</main>
{% endblock %}
import $ from "jquery";
const escapeHTML = (str) => {
return new Option(str).innerHTML;
}
const generateSignature = () => {
let result = `<style>
@import url(https://gfonts.pirati.cz/css?family=Roboto);
body { font-family: Roboto, Arial; background: white; color:black; }
.pv { font-family: Roboto Condensed, Arial, sans-serif; font-size: 10pt; font-weight: normal; margin: 1em; background: white; color: black; }
.pv>.bl { margin-bottom:0.5em; line-height: 1.1em; }
.name { font-size: 13pt; font-weight: bold; }
.social { box-sizing: content-box; font-weight: bold; color: white !important; background: black; margin: 0.1em; padding: 0.2em; width: 1em; height: 1em; display: inline-block; text-align: center; text-decoration:none; border-radius: 0.5em; }
.logo { margin-top: 1.5em; }
.logo img { height: 3.5em; margin-left:-0.1em; }
</style>
<div class="pv">`;
let name = $("#name").val();
let func = $("#function").val();
if (name !== "") {
name = escapeHTML(name);
result += `<div class="bl">
<strong class="name">${name}</strong>`;
func = escapeHTML(func);
if (func !== "") {
result += `<br>${func}`;
}
result += "</div>";
}
let email = $("#email").val();
let phone = $("#phone").val();
let fejsbuk = $("#fejsbuk").val();
let linkedin = $("#linkedin").val();
if (email !== "" || phone !== "" || fejsbuk !== "" || linkedin !== "") {
result += "<div class=\"bl\">";
if (email !== "") {
email = escapeHTML(email);
result += `<a href="${email}">${email}</a><br>`;
}
if (phone !== "") {
phone = escapeHTML(phone);
result += `<a href="${phone}">${phone}</a><br>`;
}
if (fejsbuk !== "") {
fejsbuk = escapeHTML(fejsbuk);
result += `<a href="${fejsbuk}" class="social">f</a>`;
}
if (linkedin !== "") {
linkedin = escapeHTML(linkedin);
result += `<a href="${linkedin}" class="social">in</a>`;
}
result += "</div>";
}
result += `<div class="logo">
<img
src="data:image/png;base64,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"
alt="Logo Pirátské Strany"
>
</div>
</div>`;
$("#preview").html(result);
$("#content").val(result);
}
$(window).ready(
() => {
generateSignature();
$("#generate").on(
"click",
event => {
const form = $("#source")[0];
if (!form.checkValidity()) {
form.reportValidity();
return;
}
generateSignature();
}
);
}
);
......@@ -14,5 +14,7 @@ module.exports = {
},
},
},
plugins: [],
plugins: [
require("@tailwindcss/typography"),
],
}
......@@ -17,6 +17,10 @@ module.exports = {
import: path.resolve("static_src", "rv_voting_calc.js"),
dependOn: "shared",
},
mail_signature: {
import: path.resolve("static_src", "mail_signature.js"),
dependOn: "shared",
},
shared: ["jquery"],
},
output: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment