Add maintenance options.
- Add new maintenance UI with options to garbage collect (delete) orphan subscriber and analytics records.
This commit is contained in:
parent
8ace25849e
commit
6d820f4f6e
34 changed files with 553 additions and 14 deletions
|
@ -139,6 +139,10 @@ func initHTTPHandlers(e *echo.Echo, app *App) {
|
|||
g.PUT("/api/templates/:id/default", handleTemplateSetDefault)
|
||||
g.DELETE("/api/templates/:id", handleDeleteTemplate)
|
||||
|
||||
g.DELETE("/api/maintenance/subscribers/:type", handleGCSubscribers)
|
||||
g.DELETE("/api/maintenance/analytics/:type", handleGCCampaignAnalytics)
|
||||
g.DELETE("/api/maintenance/subscriptions/unconfirmed", handleGCSubscriptions)
|
||||
|
||||
g.POST("/api/tx", handleSendTxMessage)
|
||||
|
||||
if app.constants.BounceWebhooksEnabled {
|
||||
|
|
92
cmd/maintenance.go
Normal file
92
cmd/maintenance.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// handleGCSubscribers garbage collects (deletes) orphaned or blocklisted subscribers.
|
||||
func handleGCSubscribers(c echo.Context) error {
|
||||
var (
|
||||
app = c.Get("app").(*App)
|
||||
typ = c.Param("type")
|
||||
)
|
||||
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
)
|
||||
|
||||
switch typ {
|
||||
case "blocklisted":
|
||||
n, err = app.core.DeleteBlocklistedSubscribers()
|
||||
case "orphan":
|
||||
n, err = app.core.DeleteOrphanSubscribers()
|
||||
default:
|
||||
err = echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("globals.messages.invalidData"))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, okResp{struct {
|
||||
Count int `json:"count"`
|
||||
}{n}})
|
||||
}
|
||||
|
||||
// handleGCSubscriptions garbage collects (deletes) orphaned or blocklisted subscribers.
|
||||
func handleGCSubscriptions(c echo.Context) error {
|
||||
var (
|
||||
app = c.Get("app").(*App)
|
||||
)
|
||||
|
||||
t, err := time.Parse(time.RFC3339, c.FormValue("before_date"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("globals.messages.invalidData"))
|
||||
}
|
||||
|
||||
n, err := app.core.DeleteUnconfirmedSubscriptions(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, okResp{struct {
|
||||
Count int `json:"count"`
|
||||
}{n}})
|
||||
}
|
||||
|
||||
// handleGCCampaignAnalytics garbage collects (deletes) campaign analytics.
|
||||
func handleGCCampaignAnalytics(c echo.Context) error {
|
||||
var (
|
||||
app = c.Get("app").(*App)
|
||||
typ = c.Param("type")
|
||||
)
|
||||
|
||||
t, err := time.Parse(time.RFC3339, c.FormValue("before_date"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("globals.messages.invalidData"))
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case "all":
|
||||
if err := app.core.DeleteCampaignViews(t); err != nil {
|
||||
return err
|
||||
}
|
||||
err = app.core.DeleteCampaignLinkClicks(t)
|
||||
case "views":
|
||||
err = app.core.DeleteCampaignViews(t)
|
||||
case "clicks":
|
||||
err = app.core.DeleteCampaignLinkClicks(t)
|
||||
default:
|
||||
err = echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("globals.messages.invalidData"))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, okResp{true})
|
||||
}
|
|
@ -566,6 +566,20 @@
|
|||
"logout-variant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "10098901a143c53df6eeaeb317ae3da6",
|
||||
"css": "wrench-outline",
|
||||
"code": 986080,
|
||||
"src": "custom_icons",
|
||||
"selected": true,
|
||||
"svg": {
|
||||
"path": "M941.4 791L564.5 412.1Q593.8 337.9 578.1 258.8T503.9 121.1Q431.6 50.8 332 43T152.3 93.8L312.5 253.9 253.9 312.5 93.8 154.3Q35.2 234.4 42 334T121.1 503.9Q177.7 562.5 255.9 578.1T408.2 566.4L787.1 945.3Q798.8 959 816.4 959T845.7 945.3L941.4 849.6Q955.1 837.9 955.1 821.3T941.4 791ZM816.4 857.4L423.8 462.9Q384.8 492.2 340.8 498T253.9 491.2 180.7 447.3 136.7 378.9 125 302.7L253.9 431.6 429.7 253.9 300.8 125Q384.8 121.1 445.3 179.7 478.5 212.9 491.2 256.8T496.1 344.7 460.9 427.7L853.5 820.3Z",
|
||||
"width": 1000
|
||||
},
|
||||
"search": [
|
||||
"wrench-outline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "f4ad3f6d071a0bfb3a8452b514ed0892",
|
||||
"css": "vector-square",
|
||||
|
@ -42748,20 +42762,6 @@
|
|||
"wrap-disabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "10098901a143c53df6eeaeb317ae3da6",
|
||||
"css": "wrench-outline",
|
||||
"code": 986080,
|
||||
"src": "custom_icons",
|
||||
"selected": false,
|
||||
"svg": {
|
||||
"path": "M941.4 791L564.5 412.1Q593.8 337.9 578.1 258.8T503.9 121.1Q431.6 50.8 332 43T152.3 93.8L312.5 253.9 253.9 312.5 93.8 154.3Q35.2 234.4 42 334T121.1 503.9Q177.7 562.5 255.9 578.1T408.2 566.4L787.1 945.3Q798.8 959 816.4 959T845.7 945.3L941.4 849.6Q955.1 837.9 955.1 821.3T941.4 791ZM816.4 857.4L423.8 462.9Q384.8 492.2 340.8 498T253.9 491.2 180.7 447.3 136.7 378.9 125 302.7L253.9 431.6 429.7 253.9 300.8 125Q384.8 121.1 445.3 179.7 478.5 212.9 491.2 256.8T496.1 344.7 460.9 427.7L853.5 820.3Z",
|
||||
"width": 1000
|
||||
},
|
||||
"search": [
|
||||
"wrench-outline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "d670b0f395ba3a61b975a6387f8a2471",
|
||||
"css": "access-point-network-off",
|
||||
|
|
|
@ -289,3 +289,12 @@ export const getLang = async (lang) => http.get(`/api/lang/${lang}`,
|
|||
export const logout = async () => http.get('/api/logout', {
|
||||
auth: { username: 'wrong', password: 'wrong' },
|
||||
});
|
||||
|
||||
export const deleteGCCampaignAnalytics = async (typ, beforeDate) => http.delete(`/api/maintenance/analytics/${typ}`,
|
||||
{ loading: models.maintenance, params: { before_date: beforeDate } });
|
||||
|
||||
export const deleteGCSubscribers = async (typ) => http.delete(`/api/maintenance/subscribers/${typ}`,
|
||||
{ loading: models.maintenance });
|
||||
|
||||
export const deleteGCSubscriptions = async (beforeDate) => http.delete('/api/maintenance/subscriptions/unconfirmed',
|
||||
{ loading: models.maintenance, params: { before_date: beforeDate } });
|
||||
|
|
2
frontend/src/assets/icons/fontello.css
vendored
2
frontend/src/assets/icons/fontello.css
vendored
|
@ -40,6 +40,7 @@
|
|||
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
||||
}
|
||||
|
||||
|
||||
.mdi-view-dashboard-variant-outline:before { content: '\e800'; } /* '' */
|
||||
.mdi-format-list-bulleted-square:before { content: '\e801'; } /* '' */
|
||||
.mdi-newspaper-variant-outline:before { content: '\e802'; } /* '' */
|
||||
|
@ -80,3 +81,4 @@
|
|||
.mdi-email-bounce:before { content: '\e825'; } /* '' */
|
||||
.mdi-speedometer:before { content: '\e826'; } /* '' */
|
||||
.mdi-logout-variant:before { content: ''; } /* '\f05fd' */
|
||||
.mdi-wrench-outline:before { content: ''; } /* '\f0be0' */
|
||||
|
|
Binary file not shown.
|
@ -69,6 +69,10 @@
|
|||
data-cy="all-settings" icon="cog-outline" :label="$t('menu.settings')">
|
||||
</b-menu-item>
|
||||
|
||||
<b-menu-item :to="{name: 'maintenance'}" tag="router-link" :active="activeItem.maintenance"
|
||||
data-cy="maintenance" icon="wrench-outline" :label="$t('menu.maintenance')">
|
||||
</b-menu-item>
|
||||
|
||||
<b-menu-item :to="{name: 'logs'}" tag="router-link" :active="activeItem.logs"
|
||||
data-cy="logs" icon="newspaper-variant-outline" :label="$t('menu.logs')">
|
||||
</b-menu-item>
|
||||
|
|
|
@ -10,6 +10,7 @@ export const models = Object.freeze({
|
|||
bounces: 'bounces',
|
||||
settings: 'settings',
|
||||
logs: 'logs',
|
||||
maintenance: 'maintenance',
|
||||
});
|
||||
|
||||
// Ad-hoc URIs that are used outside of vuex requests.
|
||||
|
|
|
@ -107,6 +107,12 @@ const routes = [
|
|||
meta: { title: 'logs.title', group: 'settings' },
|
||||
component: () => import(/* webpackChunkName: "main" */ '../views/Logs.vue'),
|
||||
},
|
||||
{
|
||||
path: '/settings/maintenance',
|
||||
name: 'maintenance',
|
||||
meta: { title: 'logs.title', group: 'settings' },
|
||||
component: () => import(/* webpackChunkName: "main" */ '../views/Maintenance.vue'),
|
||||
},
|
||||
];
|
||||
|
||||
const router = new VueRouter({
|
||||
|
|
163
frontend/src/views/Maintenance.vue
Normal file
163
frontend/src/views/Maintenance.vue
Normal file
|
@ -0,0 +1,163 @@
|
|||
<template>
|
||||
<section class="maintenance wrap">
|
||||
<h1 class="title is-4">{{ $t('maintenance.title') }}</h1>
|
||||
<hr />
|
||||
<p class="has-text-grey">
|
||||
{{ $t('maintenance.help') }}
|
||||
</p>
|
||||
<br />
|
||||
|
||||
|
||||
<div class="box">
|
||||
<h4 class="is-size-5">{{ $t('globals.terms.subscribers') }}</h4><br />
|
||||
<div class="columns">
|
||||
<div class="column is-4">
|
||||
<b-field label="Data" message="Orpans = subscribers with no lists">
|
||||
<b-select v-model="subscriberType" expanded>
|
||||
<option value="orphan">{{ $t('dashboard.orphanSubs') }}</option>
|
||||
<option value="blocklisted">{{ $t('subscribers.status.blocklisted') }}</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column is-5"></div>
|
||||
<div class="column">
|
||||
<b-field label=".">
|
||||
<b-button class="is-primary" :loading="loading.maintenance"
|
||||
@click="deleteSubscribers" expanded>{{ $t('globals.buttons.delete') }}</b-button>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- subscribers -->
|
||||
|
||||
<div class="box">
|
||||
<h4 class="is-size-5">{{ $tc('globals.terms.subscriptions', 2) }}</h4><br />
|
||||
<div class="columns">
|
||||
<div class="column is-4">
|
||||
<b-field label="Data">
|
||||
<b-select v-model="subscriptionType" expanded>
|
||||
<option value="optin">{{ $t('maintenance.maintenance.unconfirmedOptins') }}</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<b-field :label="$t('maintenance.olderThan')">
|
||||
<b-datepicker
|
||||
v-model="subscriptionDate"
|
||||
required expanded
|
||||
icon="calendar-clock"
|
||||
:date-formatter="formatDateTime">
|
||||
</b-datepicker>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column is-1"></div>
|
||||
<div class="column">
|
||||
<b-field label=".">
|
||||
<b-button class="is-primary" :loading="loading.maintenance"
|
||||
@click="deleteSubscriptions" expanded>{{ $t('globals.buttons.delete') }}</b-button>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- subscriptions -->
|
||||
|
||||
<div class="box mt-6">
|
||||
<h4 class="is-size-5">{{ $t('globals.terms.analytics') }}</h4><br />
|
||||
<div class="columns">
|
||||
<div class="column is-4">
|
||||
<b-field label="Data">
|
||||
<b-select v-model="analyticsType" expanded>
|
||||
<option selected value="all">{{ $t('globals.terms.all') }}</option>
|
||||
<option value="views">{{ $t('dashboard.campaignViews') }}</option>
|
||||
<option value="clicks">{{ $t('dashboard.linkClicks') }}</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<b-field :label="$t('maintenance.olderThan')">
|
||||
<b-datepicker
|
||||
v-model="analyticsDate"
|
||||
required expanded
|
||||
icon="calendar-clock"
|
||||
:date-formatter="formatDateTime">
|
||||
</b-datepicker>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column is-1"></div>
|
||||
<div class="column">
|
||||
<b-field label=".">
|
||||
<b-button expanded class="is-primary" :loading="loading.maintenance"
|
||||
@click="deleteAnalytics">{{ $t('globals.buttons.delete') }}</b-button>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- analytics -->
|
||||
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import { mapState } from 'vuex';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
subscriberType: 'orphan',
|
||||
analyticsType: 'all',
|
||||
subscriptionType: 'optin',
|
||||
analyticsDate: dayjs().subtract(7, 'day').toDate(),
|
||||
subscriptionDate: dayjs().subtract(7, 'day').toDate(),
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
formatDateTime(s) {
|
||||
return dayjs(s).format('YYYY-MM-DD');
|
||||
},
|
||||
|
||||
deleteSubscribers() {
|
||||
this.$utils.confirm(
|
||||
null,
|
||||
() => {
|
||||
this.$api.deleteGCSubscribers(this.subscriberType).then((data) => {
|
||||
this.$utils.toast(this.$t('globals.messages.deletedCount',
|
||||
{ name: this.$tc('globals.terms.subscribers', 2), num: data.count }));
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
deleteSubscriptions() {
|
||||
this.$utils.confirm(
|
||||
null,
|
||||
() => {
|
||||
this.$api.deleteGCSubscriptions(this.subscriptionDate).then((data) => {
|
||||
this.$utils.toast(this.$t('globals.messages.deletedCount',
|
||||
{ name: this.$tc('globals.terms.subscriptions', 2), num: data.count }));
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
deleteAnalytics() {
|
||||
this.$utils.confirm(
|
||||
null,
|
||||
() => {
|
||||
this.$api.deleteGCCampaignAnalytics(this.analyticsType, this.analyticsDate)
|
||||
.then(() => {
|
||||
this.$utils.toast(this.$t('globals.messages.done'));
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['loading']),
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" vytvořen",
|
||||
"globals.messages.deleted": "\"{name}\" odstraněn",
|
||||
"globals.messages.deletedCount": "{name} ({num}) odstraněn",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Nic zde není",
|
||||
"globals.messages.errorCreating": "Chyba při vytváření {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Chyba při odstraňování {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Srp",
|
||||
"globals.months.9": "Zář",
|
||||
"globals.states.off": "Vypnout",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytika",
|
||||
"globals.terms.bounce": "Nedoručitelnost | Případy nedoručitelnosti",
|
||||
"globals.terms.bounces": "Případy nedoručitelnosti",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Nastavení",
|
||||
"globals.terms.subscriber": "Odběratel | Odběratelé",
|
||||
"globals.terms.subscribers": "Odběratelé",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Značka | Značky",
|
||||
"globals.terms.tags": "Značky",
|
||||
"globals.terms.template": "Šablona | Šablony",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Soukromý",
|
||||
"lists.types.public": "Veřejný",
|
||||
"logs.title": "Protokoly",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Chyba při čtení souboru: {error}",
|
||||
"media.errorResizing": "Chyba při změně velikosti obrázku: {error}",
|
||||
"media.errorSavingThumbnail": "Chyba při ukládání miniatury: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formuláře",
|
||||
"menu.import": "Import",
|
||||
"menu.logs": "Protokoly",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Médium",
|
||||
"menu.newCampaign": "Vytvořit nový",
|
||||
"menu.settings": "Nastavení",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" erstellt",
|
||||
"globals.messages.deleted": "\"{name}\" gelöscht",
|
||||
"globals.messages.deletedCount": "{name} ({num}) gelöscht",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Hier ist nichts",
|
||||
"globals.messages.errorCreating": "Fehler beim Erstellen von {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Fehler beim Löschen von {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Sep",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Statistiken",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Einstellungen",
|
||||
"globals.terms.subscriber": "Abonnent | Abonnenten",
|
||||
"globals.terms.subscribers": "Abonnenten",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tags",
|
||||
"globals.terms.tags": "Tags",
|
||||
"globals.terms.template": "Vorlage | Vorlagen",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privat",
|
||||
"lists.types.public": "Öffentlich",
|
||||
"logs.title": "Logs",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Fehler beim Lesen der Datei: {error}",
|
||||
"media.errorResizing": "Fehler beim Anpassen der Größe des Bildes: {error}",
|
||||
"media.errorSavingThumbnail": "Fehler beim Speichern des Thumbnails: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulare",
|
||||
"menu.import": "Importieren",
|
||||
"menu.logs": "Logs",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Medien",
|
||||
"menu.newCampaign": "Neu Anlegen",
|
||||
"menu.settings": "Einstellungen",
|
||||
|
|
|
@ -154,6 +154,7 @@
|
|||
"globals.messages.created": "\"{name}\" created",
|
||||
"globals.messages.deleted": "\"{name}\" deleted",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Nothing here",
|
||||
"globals.messages.errorCreating": "Error creating {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Error deleting {name}: {error}",
|
||||
|
@ -182,6 +183,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Sep",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -201,6 +203,7 @@
|
|||
"globals.terms.settings": "Settings",
|
||||
"globals.terms.subscriber": "Subscriber | Subscribers",
|
||||
"globals.terms.subscribers": "Subscribers",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tags",
|
||||
"globals.terms.tags": "Tags",
|
||||
"globals.terms.template": "Template | Templates",
|
||||
|
@ -251,6 +254,11 @@
|
|||
"lists.types.private": "Private",
|
||||
"lists.types.public": "Public",
|
||||
"logs.title": "Logs",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Error reading file: {error}",
|
||||
"media.errorResizing": "Error resizing image: {error}",
|
||||
"media.errorSavingThumbnail": "Error saving thumbnail: {error}",
|
||||
|
@ -268,6 +276,7 @@
|
|||
"menu.forms": "Forms",
|
||||
"menu.import": "Import",
|
||||
"menu.logs": "Logs",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Create new",
|
||||
"menu.settings": "Settings",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" creado",
|
||||
"globals.messages.deleted": "\"{name}\" eliminado",
|
||||
"globals.messages.deletedCount": "{name} ({num}) eliminado(s)",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Vacío",
|
||||
"globals.messages.errorCreating": "Error creando {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Error eliminando {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Agosto",
|
||||
"globals.months.9": "Setiembre",
|
||||
"globals.states.off": "Apagado",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analitica",
|
||||
"globals.terms.bounce": "Rebote | Rebotes",
|
||||
"globals.terms.bounces": "Rebotes",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Configuraciones",
|
||||
"globals.terms.subscriber": "Subscriptor | Subscriptores",
|
||||
"globals.terms.subscribers": "Subscriptores",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Etiqueta | Etiquetas",
|
||||
"globals.terms.tags": "Etiqueta",
|
||||
"globals.terms.template": "Plantilla | Plantillas",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privada",
|
||||
"lists.types.public": "Pública",
|
||||
"logs.title": "Registros",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Error leyendo archivo: {error}",
|
||||
"media.errorResizing": "Error cambiando tamaño de imagen: {error}",
|
||||
"media.errorSavingThumbnail": "Error guardando miniatura: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formularios",
|
||||
"menu.import": "Importar",
|
||||
"menu.logs": "Registros (logs)",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Multimedia",
|
||||
"menu.newCampaign": "Crear nueva",
|
||||
"menu.settings": "Configuraciones",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" created",
|
||||
"globals.messages.deleted": "\"{name}\" deleted",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Nothing here",
|
||||
"globals.messages.errorCreating": "Error creating {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Error deleting {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Sep",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Settings",
|
||||
"globals.terms.subscriber": "Subscriber | Subscribers",
|
||||
"globals.terms.subscribers": "Subscribers",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tags",
|
||||
"globals.terms.tags": "Tags",
|
||||
"globals.terms.template": "Template | Templates",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Private",
|
||||
"lists.types.public": "Public",
|
||||
"logs.title": "Logs",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Error reading file: {error}",
|
||||
"media.errorResizing": "Error resizing image: {error}",
|
||||
"media.errorSavingThumbnail": "Error saving thumbnail: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Forms",
|
||||
"menu.import": "Import",
|
||||
"menu.logs": "Logs",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Create new",
|
||||
"menu.settings": "Settings",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "Création de « {name} »",
|
||||
"globals.messages.deleted": "Suppression de « {name} »",
|
||||
"globals.messages.deletedCount": "{name} ({num}) effacé(s)",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Rien",
|
||||
"globals.messages.errorCreating": "Erreur lors de la création de {name} : {error}",
|
||||
"globals.messages.errorDeleting": "Erreur lors de la suppression de {name} : {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "août",
|
||||
"globals.months.9": "sept.",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analyses",
|
||||
"globals.terms.bounce": "Rebond | Rebonds",
|
||||
"globals.terms.bounces": "Rebonds",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Paramètres",
|
||||
"globals.terms.subscriber": "Abonné·e | Abonné·es",
|
||||
"globals.terms.subscribers": "Abonné·es",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Étiquette | Étiquettes",
|
||||
"globals.terms.tags": "Étiquettes",
|
||||
"globals.terms.template": "Modèle | Modèles",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privée",
|
||||
"lists.types.public": "Publique",
|
||||
"logs.title": "Journalisations",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Erreur de lecture du fichier : {error}",
|
||||
"media.errorResizing": "Erreur lors du redimensionnement de l'image : {error}",
|
||||
"media.errorSavingThumbnail": "Erreur lors de l'enregistrement de la miniature : {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulaires",
|
||||
"menu.import": "Importer",
|
||||
"menu.logs": "Journalisations",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Fichiers",
|
||||
"menu.newCampaign": "Nouvelle campagne",
|
||||
"menu.settings": "Paramètres",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" készítette",
|
||||
"globals.messages.deleted": "\"{name}\" törölte",
|
||||
"globals.messages.deletedCount": "{name} ({num}) törölve",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Semmi sincs itt",
|
||||
"globals.messages.errorCreating": "Hiba a létrehozásnál {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Hiba a törléskor {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Sep",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analitika",
|
||||
"globals.terms.bounce": "Visszapattanó | Visszapattanók",
|
||||
"globals.terms.bounces": "Visszapattanók",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Beállítások",
|
||||
"globals.terms.subscriber": "Feliratkozó | Feliratkozók",
|
||||
"globals.terms.subscribers": "Feliratkozók",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Címke | Címkék",
|
||||
"globals.terms.tags": "Címkék",
|
||||
"globals.terms.template": "Sablon | Sablonok",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privát",
|
||||
"lists.types.public": "Nyilvános",
|
||||
"logs.title": "Logok",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Hiba a fájl olvasásakor : {error}",
|
||||
"media.errorResizing": "Hiba a kép átméretezésekor : {error}",
|
||||
"media.errorSavingThumbnail": "Hiba az indexkép mentésekor : {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Űrlapok",
|
||||
"menu.import": "Importálás",
|
||||
"menu.logs": "Logok",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Média",
|
||||
"menu.newCampaign": "Új készítése",
|
||||
"menu.settings": "Beállítások",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" creato",
|
||||
"globals.messages.deleted": "\"{name}\" cancellato",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Niente da visualizzare",
|
||||
"globals.messages.errorCreating": "Errore durante la creazione di {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Errore durante la cancellazione di {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Ago",
|
||||
"globals.months.9": "Set",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Impostazioni",
|
||||
"globals.terms.subscriber": "Iscritto | Iscritti",
|
||||
"globals.terms.subscribers": "Iscritti",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Etichetta | Etichette",
|
||||
"globals.terms.tags": "Etichette",
|
||||
"globals.terms.template": "Modello | Modelli",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privata",
|
||||
"lists.types.public": "Pubblico",
|
||||
"logs.title": "Logs",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Errore di lettura del file: {error}",
|
||||
"media.errorResizing": "Errore di ridimensionamento dell'immagine: {error}",
|
||||
"media.errorSavingThumbnail": "Errore durante il salvataggio dell'immagine: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulari",
|
||||
"menu.import": "Importare",
|
||||
"menu.logs": "Logs",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Creare nuovo",
|
||||
"menu.settings": "Impostazioni",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" が作成されました",
|
||||
"globals.messages.deleted": "\"{name}\" が削除されました",
|
||||
"globals.messages.deletedCount": "{name} ({num}) が削除されました。",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "ここには何もありません",
|
||||
"globals.messages.errorCreating": "{name}作成エラー: {error}",
|
||||
"globals.messages.errorDeleting": "{name}削除エラー: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "8月",
|
||||
"globals.months.9": "9月",
|
||||
"globals.states.off": "オフ",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "分析",
|
||||
"globals.terms.bounce": "バウンス | バウンス",
|
||||
"globals.terms.bounces": "バウンス",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "設定",
|
||||
"globals.terms.subscriber": "加入者 | 加入者",
|
||||
"globals.terms.subscribers": "加入者",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "タグ | タグ",
|
||||
"globals.terms.tags": "タグ",
|
||||
"globals.terms.template": "テンプレート | テンプレート",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "プライベート",
|
||||
"lists.types.public": "パブリック",
|
||||
"logs.title": "ログ",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "ファイル読み込みエラー: {error}",
|
||||
"media.errorResizing": "画像のリサイズエラー: {error}",
|
||||
"media.errorSavingThumbnail": "サムネイル保存エラー: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "フォーム",
|
||||
"menu.import": "インポート",
|
||||
"menu.logs": "ログ",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "メディア",
|
||||
"menu.newCampaign": "新規作成",
|
||||
"menu.settings": "設定",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" നിർമ്മിച്ചു",
|
||||
"globals.messages.deleted": "\"{name}\" നീക്കം ചെയ്തു",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "ഇവിടൊന്നുമില്ല",
|
||||
"globals.messages.errorCreating": "{name} നിർമ്മിക്കുന്നതിൽ പിശകുണ്ടായി: {error}",
|
||||
"globals.messages.errorDeleting": "{name} നീക്കം ചെയ്യുന്നതിൽ പിശകുണ്ടായി: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "ഓഗസ്റ്റ്",
|
||||
"globals.months.9": "സെപ്റ്റംബർ",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "ക്രമീകരണങ്ങൾ",
|
||||
"globals.terms.subscriber": "വരിക്കാരൻ | വരിക്കാർ",
|
||||
"globals.terms.subscribers": "വരിക്കാർ",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "ടാഗ് | ടാഗുകൾ",
|
||||
"globals.terms.tags": "ടാഗുകൾ",
|
||||
"globals.terms.template": "ടെംപ്ലേറ്റ് | ടെംപ്ലേറ്റുകൾ",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "സ്വകാര്യം",
|
||||
"lists.types.public": "പൊതു",
|
||||
"logs.title": "ലോഗുകൾ",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "ഫയൽ വായിക്കാനായില്ല: {error}",
|
||||
"media.errorResizing": "ചിത്രത്തിന്റ വലിപ്പം മാറ്റാനായില്ല: {error}",
|
||||
"media.errorSavingThumbnail": "തമ്പ്നെയിൽ സേവ് ചെയ്യാനായില്ല: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "ഫോമുകൾ",
|
||||
"menu.import": "ഇമ്പോർട്ട്",
|
||||
"menu.logs": "ലോഗുകൾ",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "മീഡിയ",
|
||||
"menu.newCampaign": "പുതിയത് തുടങ്ങുക",
|
||||
"menu.settings": "ക്രമീകരണങ്ങൾ",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" aangemaakt",
|
||||
"globals.messages.deleted": "\"{name}\" verwijderd",
|
||||
"globals.messages.deletedCount": "{name} ({num}) verwijderd",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Niks te zien hier",
|
||||
"globals.messages.errorCreating": "Fout bij aanmaken {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Fout bij verwijderen {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Sep",
|
||||
"globals.states.off": "Uit",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analyse",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Instellingen",
|
||||
"globals.terms.subscriber": "Abonnee | Abonnees",
|
||||
"globals.terms.subscribers": "Abonnees",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Label | Labels",
|
||||
"globals.terms.tags": "Labels",
|
||||
"globals.terms.template": "Sjabloon | Sjablonen",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privé",
|
||||
"lists.types.public": "Publiek",
|
||||
"logs.title": "Logboeken",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Fout bij lezen bestand: {error}",
|
||||
"media.errorResizing": "Fout bij wijzigen formaat afbeelding: {error}",
|
||||
"media.errorSavingThumbnail": "Fout bij opslaan thumbnail: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulieren",
|
||||
"menu.import": "Importeer",
|
||||
"menu.logs": "Logboeken",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Nieuwe aanmaken",
|
||||
"menu.settings": "Instellingen",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" utworzono",
|
||||
"globals.messages.deleted": "\"{name}\" usunięto",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Nic tutaj nie ma",
|
||||
"globals.messages.errorCreating": "Błąd podczas tworzenia {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Błąd podczas usuwania {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Sie",
|
||||
"globals.months.9": "Wrz",
|
||||
"globals.states.off": "Wyłączone",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analityka",
|
||||
"globals.terms.bounce": "Odbicie | Obicia",
|
||||
"globals.terms.bounces": "Odbicia",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Ustawienia",
|
||||
"globals.terms.subscriber": "Subskrypcja | Subskrypcje",
|
||||
"globals.terms.subscribers": "Subskrypcje",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tagi",
|
||||
"globals.terms.tags": "Tagi",
|
||||
"globals.terms.template": "Szablon | Szablony",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Prywatna",
|
||||
"lists.types.public": "Publiczna",
|
||||
"logs.title": "Logi",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Błąd odczytu pliku: {error}",
|
||||
"media.errorResizing": "Błąd zmiany rozmiaru obrazu: {error}",
|
||||
"media.errorSavingThumbnail": "Błąd zapisywania miniaturki: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formularze",
|
||||
"menu.import": "Import",
|
||||
"menu.logs": "Logi",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Utwórz nową",
|
||||
"menu.settings": "Ustawienia",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" criado",
|
||||
"globals.messages.deleted": "\"{name}\" excluído",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deletado",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Nada por aqui",
|
||||
"globals.messages.errorCreating": "Erro ao criar {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Erro ao excluir {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Ago",
|
||||
"globals.months.9": "Set",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Configurações",
|
||||
"globals.terms.subscriber": "Assinante | Assinantes",
|
||||
"globals.terms.subscribers": "Assinantes",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tags",
|
||||
"globals.terms.tags": "Tags",
|
||||
"globals.terms.template": "Modelo | Modelos",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privada",
|
||||
"lists.types.public": "Pública",
|
||||
"logs.title": "Logs",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Erro ao ler arquivo: {error}",
|
||||
"media.errorResizing": "Erro ao redimensionar imagem: {error}",
|
||||
"media.errorSavingThumbnail": "Erro ao salvar miniatura: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulários",
|
||||
"menu.import": "Importação",
|
||||
"menu.logs": "Logs",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Mídia",
|
||||
"menu.newCampaign": "Criar nova",
|
||||
"menu.settings": "Configurações",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" criado",
|
||||
"globals.messages.deleted": "\"{name}\" eliminado",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Não há nada aqui",
|
||||
"globals.messages.errorCreating": "Erro ao criar {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Erro ao eliminar {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Ago",
|
||||
"globals.months.9": "Set",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Definições",
|
||||
"globals.terms.subscriber": "Subscritor | Subcritores",
|
||||
"globals.terms.subscribers": "Subscritores",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Etiqueta | Etiquetas",
|
||||
"globals.terms.tags": "Etiquetas",
|
||||
"globals.terms.template": "Modelo | Modelos",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privado",
|
||||
"lists.types.public": "Público",
|
||||
"logs.title": "Logs (Histórico)",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Erro ao ler ficheiro: {error}",
|
||||
"media.errorResizing": "Erro ao alterar tamanho da imagem: {error}",
|
||||
"media.errorSavingThumbnail": "Erro ao guardar miniatura: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulários",
|
||||
"menu.import": "Importar",
|
||||
"menu.logs": "Logs",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Mídia",
|
||||
"menu.newCampaign": "Criar nova",
|
||||
"menu.settings": "Definições",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{nume}\" creat",
|
||||
"globals.messages.deleted": "\"{nume}\" șters",
|
||||
"globals.messages.deletedCount": "{nume} ({număr}) șters",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Nimic aici",
|
||||
"globals.messages.errorCreating": "Eroare creare {nume}: {eroare}",
|
||||
"globals.messages.errorDeleting": "Eroare ștergere {nume}: {eroare}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Sep",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analitice",
|
||||
"globals.terms.bounce": "Respins | Respinse",
|
||||
"globals.terms.bounces": "Respinse",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Setări",
|
||||
"globals.terms.subscriber": "Abonat | Abonați",
|
||||
"globals.terms.subscribers": "Abonați",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Etichetă | Etichete",
|
||||
"globals.terms.tags": "Etichete",
|
||||
"globals.terms.template": "Șablon | Șabloane",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Privat",
|
||||
"lists.types.public": "Public",
|
||||
"logs.title": "Jurnale",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Eroare citire fisier: {eroare}",
|
||||
"media.errorResizing": "Eroare redimensionare imagine: {eroare}",
|
||||
"media.errorSavingThumbnail": "Eroare la salvarea miniaturii: {eroare}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formulare",
|
||||
"menu.import": "Import",
|
||||
"menu.logs": "Jurnale",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Creaza nou",
|
||||
"menu.settings": "Setări",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" создано",
|
||||
"globals.messages.deleted": "\"{name}\" удалено",
|
||||
"globals.messages.deletedCount": "{name} ({num}) удалено",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Ничего нет",
|
||||
"globals.messages.errorCreating": "Ошибка создания {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Ошибка удаления {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Авг",
|
||||
"globals.months.9": "Сен",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Аналитика",
|
||||
"globals.terms.bounce": "Отскок | Отскоки",
|
||||
"globals.terms.bounces": "Отскоки",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Параметры",
|
||||
"globals.terms.subscriber": "Подписчик | Подписчики",
|
||||
"globals.terms.subscribers": "Подписчики",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Тег | Теги",
|
||||
"globals.terms.tags": "Теги",
|
||||
"globals.terms.template": "Шаблон | Шаблоны",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Приватный",
|
||||
"lists.types.public": "Публичный",
|
||||
"logs.title": "Логи",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Ошибка чтения файла: {error}",
|
||||
"media.errorResizing": "Ошибка изменения размера изображения: {error}",
|
||||
"media.errorSavingThumbnail": "Ошибка сохранения миниатюры: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Формы",
|
||||
"menu.import": "Импорт",
|
||||
"menu.logs": "Логи",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Медиа",
|
||||
"menu.newCampaign": "Создать новую",
|
||||
"menu.settings": "Параметры",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" oluşturma",
|
||||
"globals.messages.deleted": "\"{name}\" silme",
|
||||
"globals.messages.deletedCount": "{name} ({num}) deleted",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Burası Boş",
|
||||
"globals.messages.errorCreating": "Hata oluşturma {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Hata silme {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Aug",
|
||||
"globals.months.9": "Eyl",
|
||||
"globals.states.off": "Off",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "Analytics",
|
||||
"globals.terms.bounce": "Bounce | Bounces",
|
||||
"globals.terms.bounces": "Bounces",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Ayarlar",
|
||||
"globals.terms.subscriber": "Üye | Üyeler",
|
||||
"globals.terms.subscribers": "Üyeler",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tag(lar)",
|
||||
"globals.terms.tags": "Tag(lar)",
|
||||
"globals.terms.template": "Taslak | Taslaklar",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Kişisel",
|
||||
"lists.types.public": "Erişime açık",
|
||||
"logs.title": "Loglar",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Hata, dosya okurken: {error}",
|
||||
"media.errorResizing": "Hata, resim büyüklüğü değişirken: {error}",
|
||||
"media.errorSavingThumbnail": "Hata, önizleme oluşurken: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Formlar",
|
||||
"menu.import": "İçeri aktar",
|
||||
"menu.logs": "Loglar",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Medya",
|
||||
"menu.newCampaign": "Yeni oluştur",
|
||||
"menu.settings": "Ayarlar",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "\"{name}\" đã tạo",
|
||||
"globals.messages.deleted": "\"{name}\" đã xóa",
|
||||
"globals.messages.deletedCount": "{name} ({num}) đã xóa",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "Không có gì ở đây",
|
||||
"globals.messages.errorCreating": "Lỗi khi tạo {name}: {error}",
|
||||
"globals.messages.errorDeleting": "Lỗi khi xóa {name}: {error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "Tháng 8",
|
||||
"globals.months.9": "Tháng 9",
|
||||
"globals.states.off": "Tắt",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "phân tích",
|
||||
"globals.terms.bounce": "Bounces | Bounces",
|
||||
"globals.terms.bounces": "Bị trả lại",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "Cài đặt",
|
||||
"globals.terms.subscriber": "Subscriber | Subscribers",
|
||||
"globals.terms.subscribers": "Người đăng ký",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "Tag | Tags",
|
||||
"globals.terms.tags": "Thẻ",
|
||||
"globals.terms.template": "Template | Templates",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "Riêng tư",
|
||||
"lists.types.public": "Công cộng",
|
||||
"logs.title": "Nhật ký",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "Lỗi khi đọc tệp: {error}",
|
||||
"media.errorResizing": "Lỗi khi thay đổi kích thước hình ảnh: {error}",
|
||||
"media.errorSavingThumbnail": "Lỗi khi lưu hình thu nhỏ: {error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "Biểu mẫu",
|
||||
"menu.import": "Nhập",
|
||||
"menu.logs": "Nhật kí",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "Dữ liệu truyền thông",
|
||||
"menu.newCampaign": "Tạo mới",
|
||||
"menu.settings": "Cài đặt",
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
"globals.messages.created": "“{name}”已创建",
|
||||
"globals.messages.deleted": "“{name}”已删除",
|
||||
"globals.messages.deletedCount": "{name} ({num}) 个已删除",
|
||||
"globals.messages.done": "Done",
|
||||
"globals.messages.emptyState": "这里没有什么",
|
||||
"globals.messages.errorCreating": "创建 {name} 时出错:{error}",
|
||||
"globals.messages.errorDeleting": "删除 {name} 时出错:{error}",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"globals.months.8": "八月",
|
||||
"globals.months.9": "九月",
|
||||
"globals.states.off": "关闭",
|
||||
"globals.terms.all": "All",
|
||||
"globals.terms.analytics": "统计",
|
||||
"globals.terms.bounce": "反弹 | 多个反弹",
|
||||
"globals.terms.bounces": "反弹",
|
||||
|
@ -202,6 +204,7 @@
|
|||
"globals.terms.settings": "设置",
|
||||
"globals.terms.subscriber": "订阅者 | 多个订阅者",
|
||||
"globals.terms.subscribers": "订阅者",
|
||||
"globals.terms.subscriptions": "Subscription | Subscriptions",
|
||||
"globals.terms.tag": "标签 | 多个标签",
|
||||
"globals.terms.tags": "标签",
|
||||
"globals.terms.template": "模板 | 多个模板",
|
||||
|
@ -252,6 +255,11 @@
|
|||
"lists.types.private": "私人的",
|
||||
"lists.types.public": "公开",
|
||||
"logs.title": "日志",
|
||||
"maintenance.help": "Some actions may take a while to complete depending on the amount of data.",
|
||||
"maintenance.maintenance.unconfirmedOptins": "Unconfirmed opt-in subscriptions",
|
||||
"maintenance.olderThan": "Older than",
|
||||
"maintenance.title": "Maintenance",
|
||||
"maintenance.unconfirmedSubs": "Unconfirmed subscriptions older than {name} days.",
|
||||
"media.errorReadingFile": "读取文件时出错:{error}",
|
||||
"media.errorResizing": "调整图像大小时出错:{error}",
|
||||
"media.errorSavingThumbnail": "保存缩略图时出错:{error}",
|
||||
|
@ -269,6 +277,7 @@
|
|||
"menu.forms": "表格",
|
||||
"menu.import": "导入",
|
||||
"menu.logs": "日志",
|
||||
"menu.maintenance": "Maintenance",
|
||||
"menu.media": "媒体",
|
||||
"menu.newCampaign": "创建新的",
|
||||
"menu.settings": "设置",
|
||||
|
|
|
@ -3,6 +3,7 @@ package core
|
|||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
@ -342,3 +343,23 @@ func (c *Core) RegisterCampaignLinkClick(linkUUID, campUUID, subUUID string) (st
|
|||
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// DeleteCampaignViews deletes campaign views older than a given date.
|
||||
func (c *Core) DeleteCampaignViews(before time.Time) error {
|
||||
if _, err := c.q.DeleteCampaignViews.Exec(before); err != nil {
|
||||
c.log.Printf("error deleting campaign views: %s", err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, c.i18n.Ts("public.errorProcessingRequest"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteCampaignLinkClicks deletes campaign views older than a given date.
|
||||
func (c *Core) DeleteCampaignLinkClicks(before time.Time) error {
|
||||
if _, err := c.q.DeleteCampaignLinkClicks.Exec(before); err != nil {
|
||||
c.log.Printf("error deleting campaign link clicks: %s", err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, c.i18n.Ts("public.errorProcessingRequest"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -432,3 +432,29 @@ func (c *Core) DeleteSubscriberBounces(id int, uuid string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteOrphanSubscribers deletes orphan subscriber records (subscribers without lists).
|
||||
func (c *Core) DeleteOrphanSubscribers() (int, error) {
|
||||
res, err := c.q.DeleteOrphanSubscribers.Exec()
|
||||
if err != nil {
|
||||
c.log.Printf("error deleting orphan subscribers: %v", err)
|
||||
return 0, echo.NewHTTPError(http.StatusInternalServerError,
|
||||
c.i18n.Ts("globals.messages.errorDeleting", "name", "{globals.terms.subscribers}", "error", pqErrMsg(err)))
|
||||
}
|
||||
|
||||
n, _ := res.RowsAffected()
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
// DeleteBlocklistedSubscribers deletes blocklisted subscribers.
|
||||
func (c *Core) DeleteBlocklistedSubscribers() (int, error) {
|
||||
res, err := c.q.DeleteBlocklistedSubscribers.Exec()
|
||||
if err != nil {
|
||||
c.log.Printf("error deleting blocklisted subscribers: %v", err)
|
||||
return 0, echo.NewHTTPError(http.StatusInternalServerError,
|
||||
c.i18n.Ts("globals.messages.errorDeleting", "name", "{globals.terms.subscribers}", "error", pqErrMsg(err)))
|
||||
}
|
||||
|
||||
n, _ := res.RowsAffected()
|
||||
return int(n), nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package core
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/lib/pq"
|
||||
|
@ -91,3 +92,17 @@ func (c *Core) UnsubscribeListsByQuery(query string, sourceListIDs, targetListID
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteUnconfirmedSubscriptions sets list subscriptions to 'ubsubscribed' by a given arbitrary query expression.
|
||||
// sourceListIDs is the list of list IDs to filter the subscriber query with.
|
||||
func (c *Core) DeleteUnconfirmedSubscriptions(beforeDate time.Time) (int, error) {
|
||||
res, err := c.q.DeleteUnconfirmedSubscriptions.Exec(beforeDate)
|
||||
if err != nil {
|
||||
c.log.Printf("error deleting unconfirmed subscribers: %v", err)
|
||||
return 0, echo.NewHTTPError(http.StatusInternalServerError,
|
||||
c.i18n.Ts("globals.messages.errorDeleting", "name", "{globals.terms.subscribers}", "error", pqErrMsg(err)))
|
||||
}
|
||||
|
||||
n, _ := res.RowsAffected()
|
||||
return int(n), nil
|
||||
}
|
||||
|
|
|
@ -25,9 +25,12 @@ type Queries struct {
|
|||
BlocklistSubscribers *sqlx.Stmt `query:"blocklist-subscribers"`
|
||||
AddSubscribersToLists *sqlx.Stmt `query:"add-subscribers-to-lists"`
|
||||
DeleteSubscriptions *sqlx.Stmt `query:"delete-subscriptions"`
|
||||
DeleteUnconfirmedSubscriptions *sqlx.Stmt `query:"delete-unconfirmed-subscriptions"`
|
||||
ConfirmSubscriptionOptin *sqlx.Stmt `query:"confirm-subscription-optin"`
|
||||
UnsubscribeSubscribersFromLists *sqlx.Stmt `query:"unsubscribe-subscribers-from-lists"`
|
||||
DeleteSubscribers *sqlx.Stmt `query:"delete-subscribers"`
|
||||
DeleteBlocklistedSubscribers *sqlx.Stmt `query:"delete-blocklisted-subscribers"`
|
||||
DeleteOrphanSubscribers *sqlx.Stmt `query:"delete-orphan-subscribers"`
|
||||
UnsubscribeByCampaign *sqlx.Stmt `query:"unsubscribe-by-campaign"`
|
||||
ExportSubscriberData *sqlx.Stmt `query:"export-subscriber-data"`
|
||||
|
||||
|
@ -65,6 +68,8 @@ type Queries struct {
|
|||
GetCampaignClickCounts *sqlx.Stmt `query:"get-campaign-click-counts"`
|
||||
GetCampaignLinkCounts *sqlx.Stmt `query:"get-campaign-link-counts"`
|
||||
GetCampaignBounceCounts *sqlx.Stmt `query:"get-campaign-bounce-counts"`
|
||||
DeleteCampaignViews *sqlx.Stmt `query:"delete-campaign-views"`
|
||||
DeleteCampaignLinkClicks *sqlx.Stmt `query:"delete-campaign-link-clicks"`
|
||||
|
||||
NextCampaigns *sqlx.Stmt `query:"next-campaigns"`
|
||||
NextCampaignSubscribers *sqlx.Stmt `query:"next-campaign-subscribers"`
|
||||
|
|
20
queries.sql
20
queries.sql
|
@ -147,6 +147,13 @@ INSERT INTO subscriber_lists (subscriber_id, list_id, status)
|
|||
-- Delete one or more subscribers by ID or UUID.
|
||||
DELETE FROM subscribers WHERE CASE WHEN ARRAY_LENGTH($1::INT[], 1) > 0 THEN id = ANY($1) ELSE uuid = ANY($2::UUID[]) END;
|
||||
|
||||
-- name: delete-blocklisted-subscribers
|
||||
DELETE FROM subscribers WHERE status = 'blocklisted';
|
||||
|
||||
-- name: delete-orphan-subscribers
|
||||
DELETE FROM subscribers a WHERE NOT EXISTS
|
||||
(SELECT 1 FROM subscriber_lists b WHERE b.subscriber_id = a.id);
|
||||
|
||||
-- name: blocklist-subscribers
|
||||
WITH b AS (
|
||||
UPDATE subscribers SET status='blocklisted', updated_at=NOW()
|
||||
|
@ -196,6 +203,13 @@ UPDATE subscriber_lists SET status = 'unsubscribed' WHERE
|
|||
-- If $3 is false, unsubscribe from the campaign's lists, otherwise all lists.
|
||||
CASE WHEN $3 IS FALSE THEN list_id = ANY(SELECT list_id FROM lists) ELSE list_id != 0 END;
|
||||
|
||||
-- name: delete-unconfirmed-subscriptions
|
||||
WITH optins AS (
|
||||
SELECT id FROM lists WHERE optin = 'double'
|
||||
)
|
||||
DELETE FROM subscriber_lists
|
||||
WHERE status = 'unconfirmed' AND list_id IN (SELECT id FROM optins) AND created_at < $1;
|
||||
|
||||
-- privacy
|
||||
-- name: export-subscriber-data
|
||||
WITH prof AS (
|
||||
|
@ -670,6 +684,12 @@ u AS (
|
|||
)
|
||||
SELECT * FROM subs;
|
||||
|
||||
-- name: delete-campaign-views
|
||||
DELETE FROM campaign_views WHERE created_at < $1;
|
||||
|
||||
-- name: delete-campaign-link-clicks
|
||||
DELETE FROM link_clicks WHERE created_at < $1;
|
||||
|
||||
-- name: get-one-campaign-subscriber
|
||||
SELECT * FROM subscribers
|
||||
LEFT JOIN subscriber_lists ON (subscribers.id = subscriber_lists.subscriber_id AND subscriber_lists.status != 'unsubscribed')
|
||||
|
|
Loading…
Reference in a new issue