commit f392a814352ab35147709115e6746e2348853a5e Author: julien Date: Tue Jan 14 17:52:22 2025 +0100 first commit diff --git a/.env b/.env new file mode 100644 index 0000000..df0f000 --- /dev/null +++ b/.env @@ -0,0 +1,13 @@ +POSTGRES_USER=listmonk +POSTGRES_DB=listmonk +#POSTGRES_PASSWORD= + +TZ=Europe/Paris + +LISTMONK_app__address=0.0.0.0:9000 +LISTMONK_db__host=info-marche-quimpernetignet_postgres +LISTMONK_db__port=5432 +LISTMONK_db__user=listmonk +#LISTMONK_db__password= +LISTMONK_db__database=listmonk +LISTMONK_db__ssl_mode=disable diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57d9655 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +volumes/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..b40d7bc --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# info-marche-quimper.netig.net + +## Maintenance + +To perform database upgrade, first stop the containers, then : +``` +# nerdctl compose run --rm listmonk ./listmonk --static-dir=/listmonk/static --upgrade +``` diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..a175061 --- /dev/null +++ b/compose.yml @@ -0,0 +1,25 @@ +services: + postgres: + image: postgres:15 + container_name: info-marche-quimpernetignet_postgres + env_file: + - .env + - ../passwords/info-marche-quimpernetignet.pass + volumes: + - ./volumes/postgres:/var/lib/postgresql/data + restart: unless-stopped + listmonk: + image: listmonk/listmonk:latest + container_name: info-marche-quimpernetignet_listmonk + depends_on: + - postgres + env_file: + - .env + - ../passwords/info-marche-quimpernetignet.pass + ports: + - "127.0.0.1:9010:9000" + command: "./listmonk --static-dir=/listmonk/static" + volumes: + - ./volumes/uploads:/listmonk/uploads + - ./conf/static:/listmonk/static + restart: unless-stopped diff --git a/conf/static/email-templates/base.html b/conf/static/email-templates/base.html new file mode 100644 index 0000000..f0bd274 --- /dev/null +++ b/conf/static/email-templates/base.html @@ -0,0 +1,97 @@ +{{ define "header" }} + + + + + + + + + + +
 
+
+
+ {{ if ne LogoURL "" }} + listmonk + {{ end }} +
+{{ end }} + +{{ define "footer" }} +
+ + +
 
+ + +{{ end }} diff --git a/conf/static/email-templates/campaign-status.html b/conf/static/email-templates/campaign-status.html new file mode 100644 index 0000000..4ccbdc6 --- /dev/null +++ b/conf/static/email-templates/campaign-status.html @@ -0,0 +1,25 @@ +{{ define "campaign-status" }} +{{ template "header" . }} +

{{ L.Ts "email.status.campaignUpdateTitle" }}

+ + + + + + + + + + + + + + {{ if ne (index . "Reason") "" }} + + + + + {{ end }} +
{{ L.Ts "globals.terms.campaign" }}{{ index . "Name" }}
{{ L.Ts "email.status.status" }}{{ index . "Status" }}
{{ L.Ts "email.status.campaignSent" }}{{ index . "Sent" }} / {{ index . "ToSend" }}
{{ L.Ts "email.status.campaignReason" }}{{ index . "Reason" }}
+{{ template "footer" }} +{{ end }} diff --git a/conf/static/email-templates/default-archive.tpl b/conf/static/email-templates/default-archive.tpl new file mode 100644 index 0000000..103a23c --- /dev/null +++ b/conf/static/email-templates/default-archive.tpl @@ -0,0 +1,97 @@ + + + + {{ .Campaign.Subject }} + + + + + + +
 
+
+ {{ template "content" . }} +
+ + + + diff --git a/conf/static/email-templates/default.tpl b/conf/static/email-templates/default.tpl new file mode 100644 index 0000000..6b8ae96 --- /dev/null +++ b/conf/static/email-templates/default.tpl @@ -0,0 +1,103 @@ + + + + {{ .Campaign.Subject }} + + + + + + +
 
+
+ {{ template "content" . }} +
+ + +
 {{ TrackView }}
+ + diff --git a/conf/static/email-templates/import-status.html b/conf/static/email-templates/import-status.html new file mode 100644 index 0000000..39748cc --- /dev/null +++ b/conf/static/email-templates/import-status.html @@ -0,0 +1,19 @@ +{{ define "import-status" }} +{{ template "header" . }} +

{{ L.Ts "email.status.importTitle" }}

+ + + + + + + + + + + + + +
{{ L.Ts "email.status.importFile" }}{{ .Name }}
{{ L.Ts "email.status.status" }}{{ .Status }}
{{ L.Ts "email.status.importRecords" }}{{ .Imported }} / {{ .Total }}
+{{ template "footer" }} +{{ end }} diff --git a/conf/static/email-templates/sample-tx.tpl b/conf/static/email-templates/sample-tx.tpl new file mode 100644 index 0000000..9687f02 --- /dev/null +++ b/conf/static/email-templates/sample-tx.tpl @@ -0,0 +1,107 @@ + + + + + + + + + + +
 
+
+

Hello {{ .Subscriber.Name }}

+

+ Order number: {{ .Tx.Data.order_id }}
+ Shipping date: {{ .Tx.Data.shipping_date }}
+

+
+

+ Transactional templates supports arbitrary parameters. + Render them using .Tx.Data.YourParamName. For more information, + see the transactional mailing documentation. +

+
+ + + + diff --git a/conf/static/email-templates/smtp-test.html b/conf/static/email-templates/smtp-test.html new file mode 100644 index 0000000..61cfb38 --- /dev/null +++ b/conf/static/email-templates/smtp-test.html @@ -0,0 +1,5 @@ +{{ define "smtp-test" }} +{{ template "header" . }} +

{{ L.Ts "settings.smtp.testConnection" }}

+{{ template "footer" }} +{{ end }} diff --git a/conf/static/email-templates/subscriber-data.html b/conf/static/email-templates/subscriber-data.html new file mode 100644 index 0000000..4a8c34d --- /dev/null +++ b/conf/static/email-templates/subscriber-data.html @@ -0,0 +1,8 @@ +{{ define "subscriber-data" }} +{{ template "header" . }} +

{{ L.Ts "email.data.title" }}

+

+ {{ L.Ts "email.data.info" }} +

+{{ template "footer" }} +{{ end }} diff --git a/conf/static/email-templates/subscriber-optin-campaign.html b/conf/static/email-templates/subscriber-optin-campaign.html new file mode 100644 index 0000000..084d24e --- /dev/null +++ b/conf/static/email-templates/subscriber-optin-campaign.html @@ -0,0 +1,17 @@ +{{ define "optin-campaign" }} + +

{{ L.Ts "email.optin.confirmSubWelcome" }} {{ "{{" }}.Subscriber.FirstName {{ "}}" }}

+

{{ L.Ts "email.optin.confirmSubInfo" }}

+ +

+ {{ L.Ts "email.optin.confirmSub" }} +

+{{ end }} diff --git a/conf/static/email-templates/subscriber-optin.html b/conf/static/email-templates/subscriber-optin.html new file mode 100644 index 0000000..caecf35 --- /dev/null +++ b/conf/static/email-templates/subscriber-optin.html @@ -0,0 +1,22 @@ +{{ define "subscriber-optin" }} +{{ template "header" . }} +

{{ L.Ts "email.optin.confirmSubTitle" }}

+

{{ L.Ts "email.optin.confirmSubWelcome" }} {{ .Subscriber.FirstName }}

+

{{ L.Ts "email.optin.confirmSubInfo" }}

+ +

{{ L.Ts "email.optin.confirmSubHelp" }}

+

+ {{ L.Ts "email.optin.confirmSub" }} +

+{{ L.T "email.unsub" }} + +{{ template "footer" }} +{{ end }} diff --git a/conf/static/public/static/favicon.png b/conf/static/public/static/favicon.png new file mode 100644 index 0000000..0ca8f02 Binary files /dev/null and b/conf/static/public/static/favicon.png differ diff --git a/conf/static/public/static/logo.png b/conf/static/public/static/logo.png new file mode 100644 index 0000000..4697ced Binary files /dev/null and b/conf/static/public/static/logo.png differ diff --git a/conf/static/public/static/logo.svg b/conf/static/public/static/logo.svg new file mode 100644 index 0000000..d3d36e7 --- /dev/null +++ b/conf/static/public/static/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/conf/static/public/static/rss.svg b/conf/static/public/static/rss.svg new file mode 100644 index 0000000..8562d88 --- /dev/null +++ b/conf/static/public/static/rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/conf/static/public/static/script.js b/conf/static/public/static/script.js new file mode 100644 index 0000000..e69de29 diff --git a/conf/static/public/static/style.css b/conf/static/public/static/style.css new file mode 100644 index 0000000..905b79d --- /dev/null +++ b/conf/static/public/static/style.css @@ -0,0 +1,207 @@ +* { + box-sizing: border-box; +} +html, body { + padding: 0; + margin: 0; + min-width: 320px; +} +body { + background: #f9f9f9; + font-family: "Inter", "Open Sans", "Helvetica Neue", sans-serif; + font-size: 16px; + line-height: 26px; + color: #111; +} +a { + color: #0055d4; + text-decoration-color: #abcbfb; +} +a:hover { + color: #111; +} +label { + cursor: pointer; + color: #444; +} +h1, +h2, +h3, +h4 { + font-weight: 400; +} +.section { + margin-bottom: 45px; +} + +input[type="text"], input[type="email"], select { + padding: 10px 15px; + border: 1px solid #888; + border-radius: 3px; + width: 100%; + box-shadow: 2px 2px 0 #f3f3f3; + border: 1px solid #ddd; + font-size: 1em; +} + input:focus { + border-color: #0055d4; + } + +input:focus::placeholder { + color: transparent; +} + +input[disabled] { + opacity: 0.5; +} + +.center { + text-align: center; +} +.right { + text-align: right; +} +.button { + background: #0055d4; + padding: 15px 30px; + border-radius: 3px; + border: 0; + cursor: pointer; + text-decoration: none; + color: #ffff; + display: inline-block; + min-width: 150px; + font-size: 1.1em; + text-align: center; +} +.button:hover { + background: #333; + color: #fff; +} +.button.button-outline { + background: #fff; + border: 1px solid #0055d4; + color: #0055d4; +} +.button.button-outline:hover { + background-color: #0055d4; + color: #fff; +} + +.container { + margin: 60px auto 15px auto; + max-width: 550px; +} + +.wrap { + background: #fff; + padding: 40px; + box-shadow: 2px 2px 0 #f3f3f3; + border: 1px solid #eee; +} + +.header { + border-bottom: 1px solid #eee; + padding-bottom: 15px; + margin-bottom: 30px; +} +.header .logo img { + width: auto; + max-width: 150px; +} + +.unsub-all { + margin-top: 30px; + padding-top: 30px; + border-top: 1px solid #eee; +} + +.row { + margin-bottom: 20px; +} +.lists { + list-style-type: none; + padding: 0; +} + .lists li { + margin: 0 0 5px 0; + } + .lists .description { + margin: 0 0 15px 0; + font-size: 0.875em; + line-height: 1.3rem; + color: #888; + margin-left: 25px; + } + .form .nonce { + display: none; + } + .form .captcha { + margin-top: 30px; + } + +.archive { + list-style-type: none; + margin: 25px 0 0 0; + padding: 0; +} + .archive .date { + display: block; + color: #666; + font-size: 0.875em; + } + .archive li { + margin-bottom: 15px; + } + .feed { + margin-right: 15px; + } + +.home-options { + margin-top: 30px; +} + .home-options a { + margin: 0 7px; + } + +.pagination { + margin-top: 30px; + text-align: center; +} + .pg-page { + display: inline-block; + padding: 0 10px; + text-decoration: none; + } + .pg-page.pg-selected { + text-decoration: underline; + font-weight: bold; + } + +#btn-back { + display: none; +} + +footer.container { + margin-top: 15px; + text-align: center; + color: #aaa; + font-size: 0.775em; + margin-top: 30px; + margin-bottom: 30px; +} + footer a { + color: #aaa; + text-decoration: none; + } + footer a:hover { + color: #111; + } + +@media screen and (max-width: 650px) { + .wrap { + margin: 0; + padding: 30px; + max-width: none; + } +} diff --git a/conf/static/public/templates/archive.html b/conf/static/public/templates/archive.html new file mode 100644 index 0000000..5f4a886 --- /dev/null +++ b/conf/static/public/templates/archive.html @@ -0,0 +1,41 @@ +{{ define "archive" }} +{{ template "header" .}} +
+

{{ L.T "public.archiveTitle" }}

+ + + + {{ if not .Data.Campaigns }} + {{ L.T "public.archiveEmpty" }} + {{ end }} + + {{ if .EnablePublicSubPage }} + + {{ end }} + + {{ if gt .Data.TotalPages 1 }} + + {{ end }} +
+ +{{ template "footer" .}} +{{ end }} diff --git a/conf/static/public/templates/home.html b/conf/static/public/templates/home.html new file mode 100644 index 0000000..5bd3b26 --- /dev/null +++ b/conf/static/public/templates/home.html @@ -0,0 +1,18 @@ +{{ define "home" }} +{{ template "header" .}} + +
+ {{ L.T "users.login" }} + +
+ {{ if .EnablePublicSubPage }} + {{ L.T "public.sub" }} + {{ end }} + {{ if .EnablePublicArchive }} + {{ L.T "public.archiveTitle" }} + {{ end }} +
+
+ +{{ template "footer" .}} +{{ end }} \ No newline at end of file diff --git a/conf/static/public/templates/index.html b/conf/static/public/templates/index.html new file mode 100644 index 0000000..d5b1523 --- /dev/null +++ b/conf/static/public/templates/index.html @@ -0,0 +1,47 @@ +{{ define "header" }} + + + + + {{ .Data.Title }} - {{ .SiteName }} + + + + {{ if .EnablePublicArchive }} + + {{ end }} + + + + + + {{ if ne .FaviconURL "" }} + + {{ else }} + + {{ end }} + + +
+
+ +
+{{ end }} + +{{ define "footer" }} +
+ + + + +{{ end }} diff --git a/conf/static/public/templates/message.html b/conf/static/public/templates/message.html new file mode 100644 index 0000000..bb070f3 --- /dev/null +++ b/conf/static/public/templates/message.html @@ -0,0 +1,27 @@ +{{ define "message" }} + {{ template "header" .}} + +

{{ .Data.Title }}

+
+ {{ .Data.Message }} +
+ +

+ {{ L.T "globals.buttons.back" }} +

+ + + {{ template "footer" .}} +{{ end }} diff --git a/conf/static/public/templates/optin.html b/conf/static/public/templates/optin.html new file mode 100644 index 0000000..3bc7050 --- /dev/null +++ b/conf/static/public/templates/optin.html @@ -0,0 +1,30 @@ +{{ define "optin" }} +{{ template "header" .}} +
+

{{ L.T "public.confirmSubTitle" }}

+

+ {{ L.T "public.confirmSubInfo" }} +

+ +
+
    + {{ range $i, $l := .Data.Lists }} + + {{ if eq $l.Type "public" }} +
  • {{ $l.Name }}
  • + {{ else }} +
  • {{ L.Ts "public.subPrivateList" }}
  • + {{ end }} + {{ end }} +
+

+ + +

+
+
+ +{{ template "footer" .}} +{{ end }} \ No newline at end of file diff --git a/conf/static/public/templates/subscription-form.html b/conf/static/public/templates/subscription-form.html new file mode 100644 index 0000000..a99e034 --- /dev/null +++ b/conf/static/public/templates/subscription-form.html @@ -0,0 +1,52 @@ +{{ define "subscription-form" }} +{{ template "header" . }} +
+

{{ L.T "public.subTitle" }}

+ +
+
+

+ + + + +

+

+ + +

+ +
    +

    {{ L.T "globals.terms.lists" }}

    + {{ range $i, $l := .Data.Lists }} +
  • + + + {{ if ne $l.Description "" }} +

    {{ $l.Description }}

    + {{ end }} +
  • + {{ end }} +
+ + {{ if .Data.CaptchaKey }} +
+
+ +
+ {{ end }} +

+ + + {{ if .EnablePublicArchive }} +

+ {{ L.T "public.archiveTitle" }} +

+ {{ end }} +

+
+
+
+ +{{ template "footer" .}} +{{ end }} diff --git a/conf/static/public/templates/subscription.html b/conf/static/public/templates/subscription.html new file mode 100644 index 0000000..07bd086 --- /dev/null +++ b/conf/static/public/templates/subscription.html @@ -0,0 +1,123 @@ +{{ define "subscription" }} +{{ template "header" .}} +
+ {{ if not .Data.ShowManage }} +

{{ L.T "public.unsubTitle" }}

+
+
+ {{ if .Data.AllowBlocklist }} +

{{ L.T "public.unsubHelp" }}

+

+ + +

+ {{ end }} + +

+ +

+ + {{ if .Data.AllowPreferences }} + {{ L.T "public.managePrefs" }} + {{ end }} +
+
+ {{ else }} +
+
+ + +

{{ L.T "public.managePrefs" }}

+ + + + {{ if .Data.Subscriptions }} +

+

{{ L.T "public.managePrefsUnsub" }}

+
    + {{ range $i, $l := .Data.Subscriptions }} + {{ if ne $l.SubscriptionStatus.Value "unsubscribed" }} +
  • + + +
  • + {{ end }} + {{ end }} +
+ {{ end }} + + {{ if .Data.AllowBlocklist }} +

+ + +

+ {{ end }} + +

+ +

+
+
+ {{ end }} +
+ +{{ if or .Data.AllowExport .Data.AllowWipe }} +
+
+

{{ L.T "public.privacyTitle" }}

+ {{ if .Data.AllowExport }} +
+ + +
+ {{ L.T "public.privacyExportHelp" }} +
+ {{ end }} + + {{ if .Data.AllowWipe }} +
+ + +
+ {{ L.T "public.privacyWipeHelp" }} +
+ {{ end }} +

+ +

+
+
+ +{{ end }} + +{{ template "footer" .}} +{{ end }} \ No newline at end of file