mirror of
https://github.com/knadh/listmonk.git
synced 2025-11-13 03:02:14 +08:00
Add 'slug' (permalink) support for campaign archives. Closes #1394.
This commit is contained in:
parent
3335171960
commit
0d319ad9fd
43 changed files with 235 additions and 76 deletions
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/gorilla/feeds"
|
"github.com/gorilla/feeds"
|
||||||
"github.com/knadh/listmonk/internal/manager"
|
"github.com/knadh/listmonk/internal/manager"
|
||||||
|
|
@ -120,10 +121,19 @@ func handleCampaignArchivesPage(c echo.Context) error {
|
||||||
func handleCampaignArchivePage(c echo.Context) error {
|
func handleCampaignArchivePage(c echo.Context) error {
|
||||||
var (
|
var (
|
||||||
app = c.Get("app").(*App)
|
app = c.Get("app").(*App)
|
||||||
uuid = c.Param("uuid")
|
id = c.Param("id")
|
||||||
|
uuid = ""
|
||||||
|
slug = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
pubCamp, err := app.core.GetArchivedCampaign(0, uuid)
|
// ID can be the UUID or slug.
|
||||||
|
if reUUID.MatchString(id) {
|
||||||
|
uuid = id
|
||||||
|
} else {
|
||||||
|
slug = id
|
||||||
|
}
|
||||||
|
|
||||||
|
pubCamp, err := app.core.GetArchivedCampaign(0, uuid, slug)
|
||||||
if err != nil || pubCamp.Type != models.CampaignTypeRegular {
|
if err != nil || pubCamp.Type != models.CampaignTypeRegular {
|
||||||
notFound := false
|
notFound := false
|
||||||
if er, ok := err.(*echo.HTTPError); ok {
|
if er, ok := err.(*echo.HTTPError); ok {
|
||||||
|
|
@ -202,7 +212,12 @@ func getCampaignArchives(offset, limit int, renderBody bool, app *App) ([]campAr
|
||||||
Subject: camp.Subject,
|
Subject: camp.Subject,
|
||||||
CreatedAt: camp.CreatedAt,
|
CreatedAt: camp.CreatedAt,
|
||||||
SendAt: camp.SendAt,
|
SendAt: camp.SendAt,
|
||||||
URL: app.constants.ArchiveURL + "/" + camp.UUID,
|
}
|
||||||
|
|
||||||
|
if camp.ArchiveSlug.Valid {
|
||||||
|
archive.URL, _ = url.JoinPath(app.constants.ArchiveURL, camp.ArchiveSlug.String)
|
||||||
|
} else {
|
||||||
|
archive.URL, _ = url.JoinPath(app.constants.ArchiveURL, camp.UUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if renderBody {
|
if renderBody {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/knadh/listmonk/models"
|
"github.com/knadh/listmonk/models"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
|
"gopkg.in/volatiletech/null.v6"
|
||||||
)
|
)
|
||||||
|
|
||||||
// campaignReq is a wrapper over the Campaign model for receiving
|
// campaignReq is a wrapper over the Campaign model for receiving
|
||||||
|
|
@ -48,6 +49,7 @@ type campaignContentReq struct {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
regexFromAddress = regexp.MustCompile(`((.+?)\s)?<(.+?)@(.+?)>`)
|
regexFromAddress = regexp.MustCompile(`((.+?)\s)?<(.+?)@(.+?)>`)
|
||||||
|
regexSlug = regexp.MustCompile(`[^\p{L}\p{M}\p{N}]`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// handleGetCampaigns handles retrieval of campaigns.
|
// handleGetCampaigns handles retrieval of campaigns.
|
||||||
|
|
@ -99,7 +101,7 @@ func handleGetCampaign(c echo.Context) error {
|
||||||
noBody, _ = strconv.ParseBool(c.QueryParam("no_body"))
|
noBody, _ = strconv.ParseBool(c.QueryParam("no_body"))
|
||||||
)
|
)
|
||||||
|
|
||||||
out, err := app.core.GetCampaign(id, "")
|
out, err := app.core.GetCampaign(id, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +246,7 @@ func handleUpdateCampaign(c echo.Context) error {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, err := app.core.GetCampaign(id, "")
|
cm, err := app.core.GetCampaign(id, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -314,9 +316,10 @@ func handleUpdateCampaignArchive(c echo.Context) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
req := struct {
|
req := struct {
|
||||||
Archive bool `json:"archive"`
|
Archive bool `json:"archive"`
|
||||||
TemplateID int `json:"archive_template_id"`
|
TemplateID int `json:"archive_template_id"`
|
||||||
Meta models.JSON `json:"archive_meta"`
|
Meta models.JSON `json:"archive_meta"`
|
||||||
|
ArchiveSlug string `json:"archive_slug"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
// Get and validate fields.
|
// Get and validate fields.
|
||||||
|
|
@ -324,11 +327,19 @@ func handleUpdateCampaignArchive(c echo.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.core.UpdateCampaignArchive(id, req.Archive, req.TemplateID, req.Meta); err != nil {
|
if req.ArchiveSlug != "" {
|
||||||
|
// Format the slug to be alpha-numeric-dash.
|
||||||
|
s := strings.ToLower(req.ArchiveSlug)
|
||||||
|
s = strings.TrimSpace(regexSlug.ReplaceAllString(s, " "))
|
||||||
|
s = regexpSpaces.ReplaceAllString(s, "-")
|
||||||
|
req.ArchiveSlug = s
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.core.UpdateCampaignArchive(id, req.Archive, req.TemplateID, req.Meta, req.ArchiveSlug); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, okResp{true})
|
return c.JSON(http.StatusOK, okResp{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleDeleteCampaign handles campaign deletion.
|
// handleDeleteCampaign handles campaign deletion.
|
||||||
|
|
@ -571,6 +582,18 @@ func validateCampaignFields(c campaignReq, app *App) (campaignReq, error) {
|
||||||
c.ArchiveMeta = json.RawMessage("{}")
|
c.ArchiveMeta = json.RawMessage("{}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.ArchiveSlug.String != "" {
|
||||||
|
// Format the slug to be alpha-numeric-dash.
|
||||||
|
s := strings.ToLower(c.ArchiveSlug.String)
|
||||||
|
s = strings.TrimSpace(regexSlug.ReplaceAllString(s, " "))
|
||||||
|
s = regexpSpaces.ReplaceAllString(s, "-")
|
||||||
|
|
||||||
|
c.ArchiveSlug = null.NewString(s, true)
|
||||||
|
} else {
|
||||||
|
// If there's no slug set, set it to NULL in the DB.
|
||||||
|
c.ArchiveSlug.Valid = false
|
||||||
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ func initHTTPHandlers(e *echo.Echo, app *App) {
|
||||||
if app.constants.EnablePublicArchive {
|
if app.constants.EnablePublicArchive {
|
||||||
e.GET("/archive", handleCampaignArchivesPage)
|
e.GET("/archive", handleCampaignArchivesPage)
|
||||||
e.GET("/archive.xml", handleGetCampaignArchivesFeed)
|
e.GET("/archive.xml", handleGetCampaignArchivesFeed)
|
||||||
e.GET("/archive/:uuid", handleCampaignArchivePage)
|
e.GET("/archive/:id", handleCampaignArchivePage)
|
||||||
e.GET("/archive/latest", handleCampaignArchivePageLatest)
|
e.GET("/archive/latest", handleCampaignArchivePageLatest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt, idempo
|
||||||
campTplID,
|
campTplID,
|
||||||
pq.Int64Array{1},
|
pq.Int64Array{1},
|
||||||
false,
|
false,
|
||||||
|
"welcome-to-listmonk",
|
||||||
archiveTplID,
|
archiveTplID,
|
||||||
`{"name": "Subscriber"}`,
|
`{"name": "Subscriber"}`,
|
||||||
nil,
|
nil,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func (s *store) NextSubscribers(campID, limit int) ([]models.Subscriber, error)
|
||||||
// GetCampaign fetches a campaign from the database.
|
// GetCampaign fetches a campaign from the database.
|
||||||
func (s *store) GetCampaign(campID int) (*models.Campaign, error) {
|
func (s *store) GetCampaign(campID int) (*models.Campaign, error) {
|
||||||
var out = &models.Campaign{}
|
var out = &models.Campaign{}
|
||||||
err := s.queries.GetCampaign.Get(out, campID, nil, "default")
|
err := s.queries.GetCampaign.Get(out, campID, nil, nil, "default")
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ func handleViewCampaignMessage(c echo.Context) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get the campaign.
|
// Get the campaign.
|
||||||
camp, err := app.core.GetCampaign(0, campUUID)
|
camp, err := app.core.GetCampaign(0, campUUID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if er, ok := err.(*echo.HTTPError); ok {
|
if er, ok := err.(*echo.HTTPError); ok {
|
||||||
if er.Code == http.StatusBadRequest {
|
if er.Code == http.StatusBadRequest {
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,43 @@ describe('Archive', () => {
|
||||||
cy.get('.modal input').clear().type('clone').click();
|
cy.get('.modal input').clear().type('clone').click();
|
||||||
cy.get('.modal button.is-primary').click();
|
cy.get('.modal button.is-primary').click();
|
||||||
cy.wait(250);
|
cy.wait(250);
|
||||||
|
|
||||||
|
cy.loginAndVisit('/campaigns');
|
||||||
|
cy.get('[data-cy=btn-clone]').first().click();
|
||||||
|
cy.get('.modal input').clear().type('clone2').click();
|
||||||
|
cy.get('.modal button.is-primary').click();
|
||||||
|
cy.wait(250);
|
||||||
|
|
||||||
cy.clickMenu('all-campaigns');
|
cy.clickMenu('all-campaigns');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Starts un-archived campaign', () => {
|
it('Starts campaigns', () => {
|
||||||
cy.get('td[data-label=Status] a').eq(0).click();
|
cy.get('td[data-label=Status] a').eq(0).click();
|
||||||
cy.get('[data-cy=btn-start]').click();
|
cy.get('[data-cy=btn-start]').click();
|
||||||
cy.get('.modal button.is-primary').click();
|
cy.get('.modal button.is-primary').click();
|
||||||
|
|
||||||
|
cy.get('td[data-label=Status] a').eq(1).click();
|
||||||
|
cy.get('[data-cy=btn-start]').click();
|
||||||
|
cy.get('.modal button.is-primary').click();
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Enables archive on one campaign (no slug)', () => {
|
||||||
|
cy.loginAndVisit('/campaigns');
|
||||||
|
cy.wait(250);
|
||||||
|
cy.get('td[data-label=Status] a').eq(0).click();
|
||||||
|
|
||||||
|
// Switch to archive tab and enable archive.
|
||||||
|
cy.get('.b-tabs nav a').eq(2).click();
|
||||||
|
cy.wait(500);
|
||||||
|
cy.get('[data-cy=btn-archive] .check').click();
|
||||||
|
cy.get('[data-cy=archive-slug]').clear();
|
||||||
|
cy.get('[data-cy=archive-meta]').clear()
|
||||||
|
.type('{"email": "archive@domain.com", "name": "Archive", "attribs": { "city": "Bengaluru"}}', { parseSpecialCharSequences: false });
|
||||||
|
cy.get('[data-cy=btn-save]').click();
|
||||||
|
cy.wait(250);
|
||||||
|
});
|
||||||
|
|
||||||
it('Enables archive on one campaign', () => {
|
it('Enables archive on one campaign', () => {
|
||||||
cy.loginAndVisit('/campaigns');
|
cy.loginAndVisit('/campaigns');
|
||||||
cy.wait(250);
|
cy.wait(250);
|
||||||
|
|
@ -32,21 +59,22 @@ describe('Archive', () => {
|
||||||
cy.get('.b-tabs nav a').eq(2).click();
|
cy.get('.b-tabs nav a').eq(2).click();
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.get('[data-cy=btn-archive] .check').click();
|
cy.get('[data-cy=btn-archive] .check').click();
|
||||||
cy.get('[data-cy=archive-meta]').clear()
|
cy.get('[data-cy=archive-slug]').clear().type('my-archived-campaign');
|
||||||
.type('{"email": "archive@domain.com", "name": "Archive", "attribs": { "city": "Bengaluru"}}', { 'parseSpecialCharSequences': false });
|
|
||||||
|
|
||||||
// Start the campaign.
|
|
||||||
cy.get('[data-cy=btn-save]').click();
|
cy.get('[data-cy=btn-save]').click();
|
||||||
cy.wait(500);
|
cy.wait(250);
|
||||||
cy.get('[data-cy=btn-start]').click();
|
|
||||||
cy.get('.modal button.is-primary').click();
|
|
||||||
cy.wait(1000);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Opens campaign archive page', () => {
|
it('Opens campaign archive page', () => {
|
||||||
cy.loginAndVisit(`${apiUrl}/archive`);
|
for (let i = 0; i < 2; i++) {
|
||||||
cy.get('li a').click();
|
cy.loginAndVisit(`${apiUrl}/archive`);
|
||||||
cy.get('h3').contains('Hi Archive!');
|
cy.get('li a').eq(i).click();
|
||||||
cy.get('p').eq(0).contains('Bengaluru');
|
cy.wait(250);
|
||||||
|
if (i === 0) {
|
||||||
|
cy.get('h3').contains('Hi Archive!');
|
||||||
|
cy.get('p').eq(0).contains('Bengaluru');
|
||||||
|
} else {
|
||||||
|
cy.get('h3').contains('Hi Subscriber!');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
<form @submit.prevent="() => onSubmit(isNew ? 'create' : 'update')">
|
<form @submit.prevent="() => onSubmit(isNew ? 'create' : 'update')">
|
||||||
<b-field :label="$t('globals.fields.name')" label-position="on-border">
|
<b-field :label="$t('globals.fields.name')" label-position="on-border">
|
||||||
<b-input :maxlength="200" :ref="'focus'" v-model="form.name" name="name" :disabled="!canEdit"
|
<b-input :maxlength="200" :ref="'focus'" v-model="form.name" name="name" :disabled="!canEdit"
|
||||||
:placeholder="$t('globals.fields.name')" required />
|
:placeholder="$t('globals.fields.name')" required autofocus />
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field :label="$t('campaigns.subject')" label-position="on-border">
|
<b-field :label="$t('campaigns.subject')" label-position="on-border">
|
||||||
|
|
@ -201,19 +201,32 @@
|
||||||
|
|
||||||
<b-tab-item :label="$t('campaigns.archive')" icon="newspaper-variant-outline" value="archive" :disabled="isNew">
|
<b-tab-item :label="$t('campaigns.archive')" icon="newspaper-variant-outline" value="archive" :disabled="isNew">
|
||||||
<section class="wrap">
|
<section class="wrap">
|
||||||
<b-field :label="$t('campaigns.archiveEnable')" data-cy="btn-archive" :message="$t('campaigns.archiveHelp')">
|
<div class="columns">
|
||||||
<div class="columns">
|
<div class="column is-4">
|
||||||
<div class="column">
|
<b-field :label="$t('campaigns.archiveEnable')" data-cy="btn-archive"
|
||||||
<b-switch data-cy="btn-archive" v-model="form.archive" :disabled="!canArchive" />
|
:message="$t('campaigns.archiveHelp')">
|
||||||
</div>
|
<div class="columns">
|
||||||
<div class="column is-12">
|
<div class="column">
|
||||||
<a :href="`${settings['app.root_url']}/archive/${data.uuid}`" target="_blank" rel="noopener noreferer"
|
<b-switch data-cy="btn-archive" v-model="form.archive" :disabled="!canArchive" />
|
||||||
:class="{ 'has-text-grey-light': !form.archive }" aria-label="$t('campaigns.archive')">
|
</div>
|
||||||
<b-icon icon="link-variant" />
|
<div class="column is-12">
|
||||||
</a>
|
<a :href="`${settings['app.root_url']}/archive/${data.uuid}`" target="_blank" rel="noopener noreferer"
|
||||||
</div>
|
:class="{ 'has-text-grey-light': !form.archive }" aria-label="$t('campaigns.archive')">
|
||||||
|
<b-icon icon="link-variant" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</b-field>
|
||||||
</div>
|
</div>
|
||||||
</b-field>
|
<div class="column is-8 has-text-right">
|
||||||
|
<b-field v-if="!canEdit && canArchive">
|
||||||
|
<b-button @click="onUpdateCampaignArchive" :loading="loading.campaigns" type="is-primary"
|
||||||
|
icon-left="content-save-outline" data-cy="btn-save">
|
||||||
|
{{ $t('globals.buttons.saveChanges') }}
|
||||||
|
</b-button>
|
||||||
|
</b-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-8">
|
<div class="column is-8">
|
||||||
|
|
@ -234,18 +247,18 @@
|
||||||
@click.prevent="onFillArchiveMeta">{}</a>
|
@click.prevent="onFillArchiveMeta">{}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<b-field>
|
||||||
|
<b-field :label="$t('campaigns.archiveSlug')" label-position="on-border"
|
||||||
|
:message="$t('campaigns.archiveSlugHelp')">
|
||||||
|
<b-input :maxlength="200" :ref="'focus'" v-model="form.archiveSlug" name="archive_slug"
|
||||||
|
data-cy="archive-slug" :disabled="!canArchive || !form.archive" />
|
||||||
|
</b-field>
|
||||||
|
</b-field>
|
||||||
<b-field :label="$t('campaigns.archiveMeta')" :message="$t('campaigns.archiveMetaHelp')"
|
<b-field :label="$t('campaigns.archiveMeta')" :message="$t('campaigns.archiveMetaHelp')"
|
||||||
label-position="on-border">
|
label-position="on-border">
|
||||||
<b-input v-model="form.archiveMetaStr" name="archive_meta" type="textarea" data-cy="archive-meta"
|
<b-input v-model="form.archiveMetaStr" name="archive_meta" type="textarea" data-cy="archive-meta"
|
||||||
:disabled="!canArchive || !form.archive" rows="20" />
|
:disabled="!canArchive || !form.archive" rows="20" />
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field v-if="!canEdit && canArchive">
|
|
||||||
<b-button @click="onUpdateCampaignArchive" :loading="loading.campaigns" type="is-primary"
|
|
||||||
icon-left="content-save-outline" data-cy="btn-archive-save">
|
|
||||||
{{ $t('globals.buttons.saveChanges') }}
|
|
||||||
</b-button>
|
|
||||||
</b-field>
|
|
||||||
</section>
|
</section>
|
||||||
</b-tab-item><!-- archive -->
|
</b-tab-item><!-- archive -->
|
||||||
</b-tabs>
|
</b-tabs>
|
||||||
|
|
@ -295,6 +308,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
// Binds form input values.
|
// Binds form input values.
|
||||||
form: {
|
form: {
|
||||||
|
archiveSlug: null,
|
||||||
name: '',
|
name: '',
|
||||||
subject: '',
|
subject: '',
|
||||||
fromEmail: '',
|
fromEmail: '',
|
||||||
|
|
@ -470,6 +484,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
createCampaign() {
|
createCampaign() {
|
||||||
const data = {
|
const data = {
|
||||||
|
archiveSlug: this.form.subject,
|
||||||
name: this.form.name,
|
name: this.form.name,
|
||||||
subject: this.form.subject,
|
subject: this.form.subject,
|
||||||
lists: this.form.lists.map((l) => l.id),
|
lists: this.form.lists.map((l) => l.id),
|
||||||
|
|
@ -494,6 +509,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
async updateCampaign(typ) {
|
async updateCampaign(typ) {
|
||||||
const data = {
|
const data = {
|
||||||
|
archive_slug: this.form.archiveSlug,
|
||||||
name: this.form.name,
|
name: this.form.name,
|
||||||
subject: this.form.subject,
|
subject: this.form.subject,
|
||||||
lists: this.form.lists.map((l) => l.id),
|
lists: this.form.lists.map((l) => l.id),
|
||||||
|
|
@ -523,6 +539,7 @@ export default Vue.extend({
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.$api.updateCampaign(this.data.id, data).then((d) => {
|
this.$api.updateCampaign(this.data.id, data).then((d) => {
|
||||||
this.data = d;
|
this.data = d;
|
||||||
|
this.form.archiveSlug = d.archiveSlug;
|
||||||
this.$utils.toast(this.$t(typMsg, { name: d.name }));
|
this.$utils.toast(this.$t(typMsg, { name: d.name }));
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
@ -538,9 +555,12 @@ export default Vue.extend({
|
||||||
archive: this.form.archive,
|
archive: this.form.archive,
|
||||||
archive_template_id: this.form.archiveTemplateId,
|
archive_template_id: this.form.archiveTemplateId,
|
||||||
archive_meta: JSON.parse(this.form.archiveMetaStr),
|
archive_meta: JSON.parse(this.form.archiveMetaStr),
|
||||||
|
archive_slug: this.form.archiveSlug,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$api.updateCampaignArchive(this.data.id, data);
|
this.$api.updateCampaignArchive(this.data.id, data).then((d) => {
|
||||||
|
this.form.archiveSlug = d.archiveSlug;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Starts or schedule a campaign.
|
// Starts or schedule a campaign.
|
||||||
|
|
|
||||||
|
|
@ -145,8 +145,10 @@
|
||||||
<p v-if="stats.rate">
|
<p v-if="stats.rate">
|
||||||
<label for="#"><b-icon icon="speedometer" size="is-small" /></label>
|
<label for="#"><b-icon icon="speedometer" size="is-small" /></label>
|
||||||
<span class="send-rate">
|
<span class="send-rate">
|
||||||
<b-tooltip :label="`${stats.netRate} / ${$t('campaigns.rateMinuteShort')} @
|
<b-tooltip
|
||||||
${$utils.duration(stats.startedAt, stats.updatedAt)}`" type="is-dark">
|
:label="`${stats.netRate} / ${$t('campaigns.rateMinuteShort')} @
|
||||||
|
${$utils.duration(stats.startedAt, stats.updatedAt)}`"
|
||||||
|
type="is-dark">
|
||||||
{{ stats.rate.toFixed(0) }} / {{ $t('campaigns.rateMinuteShort') }}
|
{{ stats.rate.toFixed(0) }} / {{ $t('campaigns.rateMinuteShort') }}
|
||||||
</b-tooltip>
|
</b-tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -225,8 +227,7 @@
|
||||||
placeholder: $t('globals.fields.name'),
|
placeholder: $t('globals.fields.name'),
|
||||||
value: $t('campaigns.copyOf', { name: props.row.name }),
|
value: $t('campaigns.copyOf', { name: props.row.name }),
|
||||||
},
|
},
|
||||||
(name) => cloneCampaign(name, props.row))" data-cy="btn-clone"
|
(name) => cloneCampaign(name, props.row))" data-cy="btn-clone" :aria-label="$t('globals.buttons.clone')">
|
||||||
:aria-label="$t('globals.buttons.clone')">
|
|
||||||
<b-tooltip :label="$t('globals.buttons.clone')" type="is-dark">
|
<b-tooltip :label="$t('globals.buttons.clone')" type="is-dark">
|
||||||
<b-icon icon="file-multiple-outline" size="is-small" />
|
<b-icon icon="file-multiple-outline" size="is-small" />
|
||||||
</b-tooltip>
|
</b-tooltip>
|
||||||
|
|
@ -405,6 +406,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
name,
|
name,
|
||||||
|
archive_slug: `${c.name}-2`,
|
||||||
subject: c.subject,
|
subject: c.subject,
|
||||||
lists: c.lists.map((l) => l.id),
|
lists: c.lists.map((l) => l.id),
|
||||||
type: c.type,
|
type: c.type,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publica (en curs, aturada, finalitzada) el missatge de campanya a l'arxiu públic ",
|
"campaigns.archiveHelp": "Publica (en curs, aturada, finalitzada) el missatge de campanya a l'arxiu públic ",
|
||||||
"campaigns.archiveMeta": "Metadades de la campanya",
|
"campaigns.archiveMeta": "Metadades de la campanya",
|
||||||
"campaigns.archiveMetaHelp": "Dades del subscriptor de prova per ser usat en el missatge públic que inclou nom, correu electrònic i qualsevol atribut opcional emprat en el missatge de campanya o plantilla.",
|
"campaigns.archiveMetaHelp": "Dades del subscriptor de prova per ser usat en el missatge públic que inclou nom, correu electrònic i qualsevol atribut opcional emprat en el missatge de campanya o plantilla.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Adjunts",
|
"campaigns.attachments": "Adjunts",
|
||||||
"campaigns.cantUpdate": "No es pot actualitzar una campanya en curs o ja finalitzada.",
|
"campaigns.cantUpdate": "No es pot actualitzar una campanya en curs o ja finalitzada.",
|
||||||
"campaigns.clicks": "Clics",
|
"campaigns.clicks": "Clics",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Zveřejnit (bežící, pozastavenou, dokončenou) zprávu kampaně ve veřejném archivu",
|
"campaigns.archiveHelp": "Zveřejnit (bežící, pozastavenou, dokončenou) zprávu kampaně ve veřejném archivu",
|
||||||
"campaigns.archiveMeta": "Metadata kampaně",
|
"campaigns.archiveMeta": "Metadata kampaně",
|
||||||
"campaigns.archiveMetaHelp": "Použít prázdná data přihlášených ve veřejné zpráve včetně jména, emailu a jiných volitelných atributů použitých ve zprávách kampaně nebo šablonách.",
|
"campaigns.archiveMetaHelp": "Použít prázdná data přihlášených ve veřejné zpráve včetně jména, emailu a jiných volitelných atributů použitých ve zprávách kampaně nebo šablonách.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Přílohy",
|
"campaigns.attachments": "Přílohy",
|
||||||
"campaigns.cantUpdate": "Nelze aktualizovat spuštěnou nebo dokončenou kampaň.",
|
"campaigns.cantUpdate": "Nelze aktualizovat spuštěnou nebo dokončenou kampaň.",
|
||||||
"campaigns.clicks": "Klepnutí",
|
"campaigns.clicks": "Klepnutí",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Cyhoeddi neges yr ymgyrch (wrthi'n rhedeg",
|
"campaigns.archiveHelp": "Cyhoeddi neges yr ymgyrch (wrthi'n rhedeg",
|
||||||
"campaigns.archiveMeta": "Ymgyrch metaddata",
|
"campaigns.archiveMeta": "Ymgyrch metaddata",
|
||||||
"campaigns.archiveMetaHelp": "Data tanysgrifiwr ffug i'w defnyddio yn y neges gyhoeddus",
|
"campaigns.archiveMetaHelp": "Data tanysgrifiwr ffug i'w defnyddio yn y neges gyhoeddus",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Atodiadau",
|
"campaigns.attachments": "Atodiadau",
|
||||||
"campaigns.cantUpdate": "Does dim modd diweddaru ymgyrch fyw neu ymgyrch sydd wedi dod i ben.",
|
"campaigns.cantUpdate": "Does dim modd diweddaru ymgyrch fyw neu ymgyrch sydd wedi dod i ben.",
|
||||||
"campaigns.clicks": "Cliciau",
|
"campaigns.clicks": "Cliciau",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Udgiv (kør, hold pause, afslut) kampagnebesked til det offentlige arkiv.",
|
"campaigns.archiveHelp": "Udgiv (kør, hold pause, afslut) kampagnebesked til det offentlige arkiv.",
|
||||||
"campaigns.archiveMeta": "Kampagne metadata",
|
"campaigns.archiveMeta": "Kampagne metadata",
|
||||||
"campaigns.archiveMetaHelp": "Dummy abonnent-data til brug i den offebntlige besked herunder navn, e-mail og enhver valgfri egenskab, der bruges i kampagebeskeden eller skabelonen.",
|
"campaigns.archiveMetaHelp": "Dummy abonnent-data til brug i den offebntlige besked herunder navn, e-mail og enhver valgfri egenskab, der bruges i kampagebeskeden eller skabelonen.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Vedhæftninger",
|
"campaigns.attachments": "Vedhæftninger",
|
||||||
"campaigns.cantUpdate": "Kan ike opdatere en kørende eller afsluttet kampagne.",
|
"campaigns.cantUpdate": "Kan ike opdatere en kørende eller afsluttet kampagne.",
|
||||||
"campaigns.clicks": "Klik",
|
"campaigns.clicks": "Klik",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Veröffentliche die Nachricht (laufende, pausierte, beendete) der Kampagne im öffentlichen Archiv.",
|
"campaigns.archiveHelp": "Veröffentliche die Nachricht (laufende, pausierte, beendete) der Kampagne im öffentlichen Archiv.",
|
||||||
"campaigns.archiveMeta": "Kampagne Metadaten",
|
"campaigns.archiveMeta": "Kampagne Metadaten",
|
||||||
"campaigns.archiveMetaHelp": "Dummy-Abonnentendaten, die in der öffentlichen Nachricht verwendet werden sollen, einschließlich Name, E-Mail und alle optionalen Attribute, die in der Kampagnennachricht oder -vorlage verwendet werden.",
|
"campaigns.archiveMetaHelp": "Dummy-Abonnentendaten, die in der öffentlichen Nachricht verwendet werden sollen, einschließlich Name, E-Mail und alle optionalen Attribute, die in der Kampagnennachricht oder -vorlage verwendet werden.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Anhänge",
|
"campaigns.attachments": "Anhänge",
|
||||||
"campaigns.cantUpdate": "Eine laufende oder abgeschlossene Kampagne kann nicht geändert werden.",
|
"campaigns.cantUpdate": "Eine laufende oder abgeschlossene Kampagne kann nicht geändert werden.",
|
||||||
"campaigns.clicks": "Klicks",
|
"campaigns.clicks": "Klicks",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Δημοσιεύστε το μήνυμα της (σε εξέλιξη, σε παύση, ολοκληρωμένης) εκστρατείας στο δημόσιο αρχείο.",
|
"campaigns.archiveHelp": "Δημοσιεύστε το μήνυμα της (σε εξέλιξη, σε παύση, ολοκληρωμένης) εκστρατείας στο δημόσιο αρχείο.",
|
||||||
"campaigns.archiveMeta": "Μεταδεδομένα εκστρατείας",
|
"campaigns.archiveMeta": "Μεταδεδομένα εκστρατείας",
|
||||||
"campaigns.archiveMetaHelp": "Εικονικά δεδομένα συνδρομητή που χρησιμοποιούνται στο δημόσιο μήνυμα, συμπεριλαμβανομένου του ονόματος, της διεύθυνσης email και οποιωνδήποτε προαιρετικών χαρακτηριστικών που χρησιμοποιούνται στο μήνυμα ή το πρότυπο της εκστρατείας.",
|
"campaigns.archiveMetaHelp": "Εικονικά δεδομένα συνδρομητή που χρησιμοποιούνται στο δημόσιο μήνυμα, συμπεριλαμβανομένου του ονόματος, της διεύθυνσης email και οποιωνδήποτε προαιρετικών χαρακτηριστικών που χρησιμοποιούνται στο μήνυμα ή το πρότυπο της εκστρατείας.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Συνημμένα",
|
"campaigns.attachments": "Συνημμένα",
|
||||||
"campaigns.cantUpdate": "Δεν είναι δυνατή η ενημέρωση μιας εκστρατείας που βρίσκεται σε εξέλιξη ή έχει ολοκληρωθεί.",
|
"campaigns.cantUpdate": "Δεν είναι δυνατή η ενημέρωση μιας εκστρατείας που βρίσκεται σε εξέλιξη ή έχει ολοκληρωθεί.",
|
||||||
"campaigns.clicks": "Κλικ",
|
"campaigns.clicks": "Κλικ",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publish (running, paused, finished) the campaign message on the public archive.",
|
"campaigns.archiveHelp": "Publish (running, paused, finished) the campaign message on the public archive.",
|
||||||
"campaigns.archiveMeta": "Campaign metadata",
|
"campaigns.archiveMeta": "Campaign metadata",
|
||||||
"campaigns.archiveMetaHelp": "Dummy subscriber data to use in the public message including name, email, and any optional attributes used in the campaign message or template.",
|
"campaigns.archiveMetaHelp": "Dummy subscriber data to use in the public message including name, email, and any optional attributes used in the campaign message or template.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Attachments",
|
"campaigns.attachments": "Attachments",
|
||||||
"campaigns.cantUpdate": "Cannot update a running or a finished campaign.",
|
"campaigns.cantUpdate": "Cannot update a running or a finished campaign.",
|
||||||
"campaigns.clicks": "Clicks",
|
"campaigns.clicks": "Clicks",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publicar los mensajes de las campañas (en marcha, pausadas y terminadas) en el archivo público.",
|
"campaigns.archiveHelp": "Publicar los mensajes de las campañas (en marcha, pausadas y terminadas) en el archivo público.",
|
||||||
"campaigns.archiveMeta": "Metadata de la campaña",
|
"campaigns.archiveMeta": "Metadata de la campaña",
|
||||||
"campaigns.archiveMetaHelp": "Información de suscripción de ejemplo (por defecto) para ser usada en el mensaje público incluido nombre, correo electrónico, o cualquier valor accesible mediante atributos `{}` opcionales tanto en el mensaje de la campaña como en la plantilla.",
|
"campaigns.archiveMetaHelp": "Información de suscripción de ejemplo (por defecto) para ser usada en el mensaje público incluido nombre, correo electrónico, o cualquier valor accesible mediante atributos `{}` opcionales tanto en el mensaje de la campaña como en la plantilla.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Archivos adjuntos",
|
"campaigns.attachments": "Archivos adjuntos",
|
||||||
"campaigns.cantUpdate": "No es posible actualizar una campaña iniciada o finalizada.",
|
"campaigns.cantUpdate": "No es posible actualizar una campaña iniciada o finalizada.",
|
||||||
"campaigns.clicks": "Clics",
|
"campaigns.clicks": "Clics",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Julkaise (käynnissä, pausessa, valmis) kampanjaviesti julkisessa arkistossa.",
|
"campaigns.archiveHelp": "Julkaise (käynnissä, pausessa, valmis) kampanjaviesti julkisessa arkistossa.",
|
||||||
"campaigns.archiveMeta": "Kampanjan metatiedot",
|
"campaigns.archiveMeta": "Kampanjan metatiedot",
|
||||||
"campaigns.archiveMetaHelp": "Tietuekuvioita voidaan käyttää julkisessa viestissä, joissa on mukana nimi, sähköposti ja kampanjaviestissä tai mallipohjassa käytetyt valinnaiset attribuutit.",
|
"campaigns.archiveMetaHelp": "Tietuekuvioita voidaan käyttää julkisessa viestissä, joissa on mukana nimi, sähköposti ja kampanjaviestissä tai mallipohjassa käytetyt valinnaiset attribuutit.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Liitteet",
|
"campaigns.attachments": "Liitteet",
|
||||||
"campaigns.cantUpdate": "Käynnissä olevaa tai päättynyttä kampanjaa ei voi päivittää.",
|
"campaigns.cantUpdate": "Käynnissä olevaa tai päättynyttä kampanjaa ei voi päivittää.",
|
||||||
"campaigns.clicks": "Klikkaukset",
|
"campaigns.clicks": "Klikkaukset",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publier (en cours, en pause, terminé) le message de la campagne sur l'archive publique.",
|
"campaigns.archiveHelp": "Publier (en cours, en pause, terminé) le message de la campagne sur l'archive publique.",
|
||||||
"campaigns.archiveMeta": "Métadonnées de la campagne",
|
"campaigns.archiveMeta": "Métadonnées de la campagne",
|
||||||
"campaigns.archiveMetaHelp": "Données d'abonné fictives à utiliser dans le message public, notamment le nom, l'adresse électronique et tout attribut facultatif utilisé dans le message ou le modèle de la campagne.",
|
"campaigns.archiveMetaHelp": "Données d'abonné fictives à utiliser dans le message public, notamment le nom, l'adresse électronique et tout attribut facultatif utilisé dans le message ou le modèle de la campagne.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Pièces jointes",
|
"campaigns.attachments": "Pièces jointes",
|
||||||
"campaigns.cantUpdate": "Impossible de mettre à jour une campagne en cours ou terminée.",
|
"campaigns.cantUpdate": "Impossible de mettre à jour une campagne en cours ou terminée.",
|
||||||
"campaigns.clicks": "Clics",
|
"campaigns.clicks": "Clics",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "פרסם (פועל, מושהה, הושלם) את הודעת הקמפיין בארכיון הציבורי.",
|
"campaigns.archiveHelp": "פרסם (פועל, מושהה, הושלם) את הודעת הקמפיין בארכיון הציבורי.",
|
||||||
"campaigns.archiveMeta": "מטא-נתונים של קמפיין",
|
"campaigns.archiveMeta": "מטא-נתונים של קמפיין",
|
||||||
"campaigns.archiveMetaHelp": "נתוני חבוי של המנויים לשימוש בהודעה ציבורית כולל שם, דואר אלקטרוני, וכל מאפיינים אופציונליים שבשימוש בהודעת הקמפיין או התבנית.",
|
"campaigns.archiveMetaHelp": "נתוני חבוי של המנויים לשימוש בהודעה ציבורית כולל שם, דואר אלקטרוני, וכל מאפיינים אופציונליים שבשימוש בהודעת הקמפיין או התבנית.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "קבצים מצורפים",
|
"campaigns.attachments": "קבצים מצורפים",
|
||||||
"campaigns.cantUpdate": "לא ניתן לעדכן קמפיין בריצה או שהושלם.",
|
"campaigns.cantUpdate": "לא ניתן לעדכן קמפיין בריצה או שהושלם.",
|
||||||
"campaigns.clicks": "לחיצות",
|
"campaigns.clicks": "לחיצות",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "A kampány nyilvános archívumba mentése, közzététele.",
|
"campaigns.archiveHelp": "A kampány nyilvános archívumba mentése, közzététele.",
|
||||||
"campaigns.archiveMeta": "Kapány metaadat",
|
"campaigns.archiveMeta": "Kapány metaadat",
|
||||||
"campaigns.archiveMetaHelp": "A nyilvánosan közzétett kampányüzenetbe helyettesítendő adatok (pl. név, e-mail cím, és amiket a sablon használ).",
|
"campaigns.archiveMetaHelp": "A nyilvánosan közzétett kampányüzenetbe helyettesítendő adatok (pl. név, e-mail cím, és amiket a sablon használ).",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Mellékletek",
|
"campaigns.attachments": "Mellékletek",
|
||||||
"campaigns.cantUpdate": "Nem lehet frissíteni futó vagy befejezett kampányt.",
|
"campaigns.cantUpdate": "Nem lehet frissíteni futó vagy befejezett kampányt.",
|
||||||
"campaigns.clicks": "Kattintások",
|
"campaigns.clicks": "Kattintások",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Pubblicare i messaggi delle campagne (avviate, pausate, finite) nel archivio pubblico.",
|
"campaigns.archiveHelp": "Pubblicare i messaggi delle campagne (avviate, pausate, finite) nel archivio pubblico.",
|
||||||
"campaigns.archiveMeta": "Metadati della campagna",
|
"campaigns.archiveMeta": "Metadati della campagna",
|
||||||
"campaigns.archiveMetaHelp": "Dati fittizi dell'iscritto da utilizzare nel messaggio pubblico, inclusi nome, e-mail ed eventuali attributi facoltativi utilizzati nel messaggio o nel modello della campagna.",
|
"campaigns.archiveMetaHelp": "Dati fittizi dell'iscritto da utilizzare nel messaggio pubblico, inclusi nome, e-mail ed eventuali attributi facoltativi utilizzati nel messaggio o nel modello della campagna.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Allegati",
|
"campaigns.attachments": "Allegati",
|
||||||
"campaigns.cantUpdate": "Impossibile aggiornare una campagna in corso o già effettuata.",
|
"campaigns.cantUpdate": "Impossibile aggiornare una campagna in corso o già effettuata.",
|
||||||
"campaigns.clicks": "Click",
|
"campaigns.clicks": "Click",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "公開アーカイブにキャンペーンメッセージを発行(実行中, 停止された, 終わりましたキャンペーン全部含めて)。",
|
"campaigns.archiveHelp": "公開アーカイブにキャンペーンメッセージを発行(実行中, 停止された, 終わりましたキャンペーン全部含めて)。",
|
||||||
"campaigns.archiveMeta": "キャンペーンメタデータ",
|
"campaigns.archiveMeta": "キャンペーンメタデータ",
|
||||||
"campaigns.archiveMetaHelp": "キャンペーンのメッセージやテンプレートに使う偽データ(名やメールアドレスや設定)。",
|
"campaigns.archiveMetaHelp": "キャンペーンのメッセージやテンプレートに使う偽データ(名やメールアドレスや設定)。",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "添付ファイル",
|
"campaigns.attachments": "添付ファイル",
|
||||||
"campaigns.cantUpdate": "実行中又は終了しているキャンペーンの更新はできません。",
|
"campaigns.cantUpdate": "実行中又は終了しているキャンペーンの更新はできません。",
|
||||||
"campaigns.clicks": "クリック",
|
"campaigns.clicks": "クリック",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "പ്രചാരണ സന്ദേശം (റൺ ചെയ്യുന്ന, താൽക്കാലികമായി നിർത്തിയ, പൂർത്തിയായ) പൊതു ആർക്കൈവിൽ പ്രസിദ്ധീകരിക്കുക.",
|
"campaigns.archiveHelp": "പ്രചാരണ സന്ദേശം (റൺ ചെയ്യുന്ന, താൽക്കാലികമായി നിർത്തിയ, പൂർത്തിയായ) പൊതു ആർക്കൈവിൽ പ്രസിദ്ധീകരിക്കുക.",
|
||||||
"campaigns.archiveMeta": "കാമ്പെയ്ൻ മെറ്റാഡാറ്റ",
|
"campaigns.archiveMeta": "കാമ്പെയ്ൻ മെറ്റാഡാറ്റ",
|
||||||
"campaigns.archiveMetaHelp": "പേര്, ഇമെയിൽ, പ്രചാരണ സന്ദേശത്തിലോ ടെംപ്ലേറ്റിലോ ഉപയോഗിക്കുന്ന ഏതെങ്കിലും ഓപ്ഷണൽ ആട്രിബ്യൂട്ടുകൾ എന്നിവയുൾപ്പെടെ പൊതു സന്ദേശത്തിൽ ഉപയോഗിക്കാനുള്ള ഡമ്മി സബ്സ്ക്രൈബർ ഡാറ്റ.",
|
"campaigns.archiveMetaHelp": "പേര്, ഇമെയിൽ, പ്രചാരണ സന്ദേശത്തിലോ ടെംപ്ലേറ്റിലോ ഉപയോഗിക്കുന്ന ഏതെങ്കിലും ഓപ്ഷണൽ ആട്രിബ്യൂട്ടുകൾ എന്നിവയുൾപ്പെടെ പൊതു സന്ദേശത്തിൽ ഉപയോഗിക്കാനുള്ള ഡമ്മി സബ്സ്ക്രൈബർ ഡാറ്റ.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "അറ്റാച്ച്മെന്റ്സ്",
|
"campaigns.attachments": "അറ്റാച്ച്മെന്റ്സ്",
|
||||||
"campaigns.cantUpdate": "ഇപ്പോൾ നടന്നുകൊണ്ടിരിയ്ക്കുന്നതോ, അവസാനിച്ചതോ ആയ ക്യാമ്പേയ്ൻ പുതുക്കാനാകില്ല.",
|
"campaigns.cantUpdate": "ഇപ്പോൾ നടന്നുകൊണ്ടിരിയ്ക്കുന്നതോ, അവസാനിച്ചതോ ആയ ക്യാമ്പേയ്ൻ പുതുക്കാനാകില്ല.",
|
||||||
"campaigns.clicks": "ക്ലീക്കുകൾ",
|
"campaigns.clicks": "ക്ലീക്കുകൾ",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publiceer (lopende, gepauzeerde, afgeronde) het campange bericht naar het publiek archief.",
|
"campaigns.archiveHelp": "Publiceer (lopende, gepauzeerde, afgeronde) het campange bericht naar het publiek archief.",
|
||||||
"campaigns.archiveMeta": "Campagne metadata",
|
"campaigns.archiveMeta": "Campagne metadata",
|
||||||
"campaigns.archiveMetaHelp": "Dummy-abonneegegevens om te gebruiken in het openbare bericht, inclusief naam, e-mail en eventuele optionele attributen die worden gebruikt in het campagnebericht of de sjabloon.",
|
"campaigns.archiveMetaHelp": "Dummy-abonneegegevens om te gebruiken in het openbare bericht, inclusief naam, e-mail en eventuele optionele attributen die worden gebruikt in het campagnebericht of de sjabloon.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Bijlagen",
|
"campaigns.attachments": "Bijlagen",
|
||||||
"campaigns.cantUpdate": "Kan een lopende of afgelopen campagne niet updaten.",
|
"campaigns.cantUpdate": "Kan een lopende of afgelopen campagne niet updaten.",
|
||||||
"campaigns.clicks": "Kliks",
|
"campaigns.clicks": "Kliks",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Opublikuj (w trakcie, zatrzymane, zakończone) treść kampanii do publicznego archiwum.",
|
"campaigns.archiveHelp": "Opublikuj (w trakcie, zatrzymane, zakończone) treść kampanii do publicznego archiwum.",
|
||||||
"campaigns.archiveMeta": "Metadane kampanii",
|
"campaigns.archiveMeta": "Metadane kampanii",
|
||||||
"campaigns.archiveMetaHelp": "Dane podstawione subskrybenta do użycia w publicznym archiwum. W tym nazwa, email, i dowolne opcjonalne atrybuty użyte w szablonie kampanii.",
|
"campaigns.archiveMetaHelp": "Dane podstawione subskrybenta do użycia w publicznym archiwum. W tym nazwa, email, i dowolne opcjonalne atrybuty użyte w szablonie kampanii.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Załączniki",
|
"campaigns.attachments": "Załączniki",
|
||||||
"campaigns.cantUpdate": "Nie można aktualizować aktywnej ani zakończonej kampanii",
|
"campaigns.cantUpdate": "Nie można aktualizować aktywnej ani zakończonej kampanii",
|
||||||
"campaigns.clicks": "Kliknięcia",
|
"campaigns.clicks": "Kliknięcia",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publicar (executando, pausada, finalizada) a mensagem da campanha no arquivo publico.",
|
"campaigns.archiveHelp": "Publicar (executando, pausada, finalizada) a mensagem da campanha no arquivo publico.",
|
||||||
"campaigns.archiveMeta": "Metadados da campanha",
|
"campaigns.archiveMeta": "Metadados da campanha",
|
||||||
"campaigns.archiveMetaHelp": "Dados de assinante fictício para utilizar na mensagem publica incluindo nome, email e qualquer atributo opcional usado na mensagem ou template da campanha.",
|
"campaigns.archiveMetaHelp": "Dados de assinante fictício para utilizar na mensagem publica incluindo nome, email e qualquer atributo opcional usado na mensagem ou template da campanha.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Anexos",
|
"campaigns.attachments": "Anexos",
|
||||||
"campaigns.cantUpdate": "Não é possível atualizar uma campanha em execução ou finalizada.",
|
"campaigns.cantUpdate": "Não é possível atualizar uma campanha em execução ou finalizada.",
|
||||||
"campaigns.clicks": "Cliques",
|
"campaigns.clicks": "Cliques",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publicar (em execução, em pausa e terminadas) as mensagens da campanha no arquivo público.",
|
"campaigns.archiveHelp": "Publicar (em execução, em pausa e terminadas) as mensagens da campanha no arquivo público.",
|
||||||
"campaigns.archiveMeta": "Metadados da campanha",
|
"campaigns.archiveMeta": "Metadados da campanha",
|
||||||
"campaigns.archiveMetaHelp": "Dados do subscritor modelo a usar em mensagens públicas, tais como nome, email e quais quer outros atributos opcionais usados na mensagem ou template da campanha.",
|
"campaigns.archiveMetaHelp": "Dados do subscritor modelo a usar em mensagens públicas, tais como nome, email e quais quer outros atributos opcionais usados na mensagem ou template da campanha.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Anexos",
|
"campaigns.attachments": "Anexos",
|
||||||
"campaigns.cantUpdate": "Não é possível atualizar uma campanha em curso ou terminada.",
|
"campaigns.cantUpdate": "Não é possível atualizar uma campanha em curso ou terminada.",
|
||||||
"campaigns.clicks": "Cliques",
|
"campaigns.clicks": "Cliques",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publicați (rulând, întrerupt, terminat) mesajul campaniei în arhiva publică.",
|
"campaigns.archiveHelp": "Publicați (rulând, întrerupt, terminat) mesajul campaniei în arhiva publică.",
|
||||||
"campaigns.archiveMeta": "Metadatele campaniei",
|
"campaigns.archiveMeta": "Metadatele campaniei",
|
||||||
"campaigns.archiveMetaHelp": "Datele abonaților inactivi de utilizat în mesajul public, inclusiv numele, e-mailul și orice atribute opționale utilizate în mesajul sau șablonul campaniei.",
|
"campaigns.archiveMetaHelp": "Datele abonaților inactivi de utilizat în mesajul public, inclusiv numele, e-mailul și orice atribute opționale utilizate în mesajul sau șablonul campaniei.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Fișiere atașate",
|
"campaigns.attachments": "Fișiere atașate",
|
||||||
"campaigns.cantUpdate": "Nu se poate actualiza o campanie care rulează sau s-a terminat.",
|
"campaigns.cantUpdate": "Nu se poate actualiza o campanie care rulează sau s-a terminat.",
|
||||||
"campaigns.clicks": "Click-uri",
|
"campaigns.clicks": "Click-uri",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Опубликовать (запущено, на паузе, завершено) сообщение кампании в общедоступном архиве.",
|
"campaigns.archiveHelp": "Опубликовать (запущено, на паузе, завершено) сообщение кампании в общедоступном архиве.",
|
||||||
"campaigns.archiveMeta": "Метаданные кампании",
|
"campaigns.archiveMeta": "Метаданные кампании",
|
||||||
"campaigns.archiveMetaHelp": "Данные фиктивных подписчиков для использования в публичном сообщении, включая имя, электронную почту и любые дополнительные атрибуты, используемые в сообщении или шаблоне кампании.",
|
"campaigns.archiveMetaHelp": "Данные фиктивных подписчиков для использования в публичном сообщении, включая имя, электронную почту и любые дополнительные атрибуты, используемые в сообщении или шаблоне кампании.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Вложения",
|
"campaigns.attachments": "Вложения",
|
||||||
"campaigns.cantUpdate": "Не возможно обновить запущенную или завершённую кампанию.",
|
"campaigns.cantUpdate": "Не возможно обновить запущенную или завершённую кампанию.",
|
||||||
"campaigns.clicks": "Клики",
|
"campaigns.clicks": "Клики",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Publish (running, paused, finished) the campaign message on the public archive.",
|
"campaigns.archiveHelp": "Publish (running, paused, finished) the campaign message on the public archive.",
|
||||||
"campaigns.archiveMeta": "Campaign metadata",
|
"campaigns.archiveMeta": "Campaign metadata",
|
||||||
"campaigns.archiveMetaHelp": "Dummy subscriber data to use in the public message including name, email, and any optional attributes used in the campaign message or template.",
|
"campaigns.archiveMetaHelp": "Dummy subscriber data to use in the public message including name, email, and any optional attributes used in the campaign message or template.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Attachments",
|
"campaigns.attachments": "Attachments",
|
||||||
"campaigns.cantUpdate": "Cannot update a running or a finished campaign.",
|
"campaigns.cantUpdate": "Cannot update a running or a finished campaign.",
|
||||||
"campaigns.clicks": "Clicks",
|
"campaigns.clicks": "Clicks",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Zverejniť (prebiehajúcu, pozastavenú, dokončenú) správu kampane vo verejnom archíve",
|
"campaigns.archiveHelp": "Zverejniť (prebiehajúcu, pozastavenú, dokončenú) správu kampane vo verejnom archíve",
|
||||||
"campaigns.archiveMeta": "Metadáta kampane",
|
"campaigns.archiveMeta": "Metadáta kampane",
|
||||||
"campaigns.archiveMetaHelp": "Použíť prázdne dáta prihlásených vo verejnom archíve vrátane mena, emailu a iných voliteľných atribútov použitých v správach kampane aleebo šablónach.",
|
"campaigns.archiveMetaHelp": "Použíť prázdne dáta prihlásených vo verejnom archíve vrátane mena, emailu a iných voliteľných atribútov použitých v správach kampane aleebo šablónach.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Prílohy",
|
"campaigns.attachments": "Prílohy",
|
||||||
"campaigns.cantUpdate": "Nedá sa aktualizovať spustená alebo dokončená kampaň.",
|
"campaigns.cantUpdate": "Nedá sa aktualizovať spustená alebo dokončená kampaň.",
|
||||||
"campaigns.clicks": "Kliknutia",
|
"campaigns.clicks": "Kliknutia",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Kampanya mesajını genel arşivde yayınlayın (çalışıyor, duraklatıldı, bitti).",
|
"campaigns.archiveHelp": "Kampanya mesajını genel arşivde yayınlayın (çalışıyor, duraklatıldı, bitti).",
|
||||||
"campaigns.archiveMeta": "Kampanya meta verisi",
|
"campaigns.archiveMeta": "Kampanya meta verisi",
|
||||||
"campaigns.archiveMetaHelp": "Ad, e-posta ve kampanya mesajında veya şablonunda kullanılan tüm isteğe bağlı öznitelikler dahil olmak üzere genel mesajda kullanılacak kukla abone verileri.",
|
"campaigns.archiveMetaHelp": "Ad, e-posta ve kampanya mesajında veya şablonunda kullanılan tüm isteğe bağlı öznitelikler dahil olmak üzere genel mesajda kullanılacak kukla abone verileri.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Ekler",
|
"campaigns.attachments": "Ekler",
|
||||||
"campaigns.cantUpdate": "Gönderilmekte olan veya gönderilmiş kampaynalar güncellenemez.",
|
"campaigns.cantUpdate": "Gönderilmekte olan veya gönderilmiş kampaynalar güncellenemez.",
|
||||||
"campaigns.clicks": "Tıklama",
|
"campaigns.clicks": "Tıklama",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Розмістити лист кампанії (запущеної, призупиненої, завершеної) в загальнодоступному архіві.",
|
"campaigns.archiveHelp": "Розмістити лист кампанії (запущеної, призупиненої, завершеної) в загальнодоступному архіві.",
|
||||||
"campaigns.archiveMeta": "Метадані кампанії",
|
"campaigns.archiveMeta": "Метадані кампанії",
|
||||||
"campaigns.archiveMetaHelp": "Дані вигаданої підписни_ці для використання в загальнодоступному листі, зокрема ім'я (name), е-пошта (email) та будь-які необов'язкові атрибути, використані в листі чи шаблоні кампанії.",
|
"campaigns.archiveMetaHelp": "Дані вигаданої підписни_ці для використання в загальнодоступному листі, зокрема ім'я (name), е-пошта (email) та будь-які необов'язкові атрибути, використані в листі чи шаблоні кампанії.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Вкладення",
|
"campaigns.attachments": "Вкладення",
|
||||||
"campaigns.cantUpdate": "Неможливо оновити запущену чи завершену кампанію.",
|
"campaigns.cantUpdate": "Неможливо оновити запущену чи завершену кампанію.",
|
||||||
"campaigns.clicks": "Переходи",
|
"campaigns.clicks": "Переходи",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "Xuất bản (đang chạy, tạm dừng, hoàn thành) tin nhắn chiến dịch vào lưu trữ công khai.",
|
"campaigns.archiveHelp": "Xuất bản (đang chạy, tạm dừng, hoàn thành) tin nhắn chiến dịch vào lưu trữ công khai.",
|
||||||
"campaigns.archiveMeta": "Dữ liệu siêu của chiến dịch",
|
"campaigns.archiveMeta": "Dữ liệu siêu của chiến dịch",
|
||||||
"campaigns.archiveMetaHelp": "Dữ liệu giả của người đăng ký để sử dụng trong tin nhắn công khai bao gồm tên, email và bất kỳ thuộc tính tùy chọn nào được sử dụng trong tin nhắn chiến dịch hoặc mẫu.",
|
"campaigns.archiveMetaHelp": "Dữ liệu giả của người đăng ký để sử dụng trong tin nhắn công khai bao gồm tên, email và bất kỳ thuộc tính tùy chọn nào được sử dụng trong tin nhắn chiến dịch hoặc mẫu.",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "Tệp đính kèm",
|
"campaigns.attachments": "Tệp đính kèm",
|
||||||
"campaigns.cantUpdate": "Không thể cập nhật chiến dịch đang chạy hoặc đã kết thúc.",
|
"campaigns.cantUpdate": "Không thể cập nhật chiến dịch đang chạy hoặc đã kết thúc.",
|
||||||
"campaigns.clicks": "Số lần nhấp chuột",
|
"campaigns.clicks": "Số lần nhấp chuột",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "在公共档案中发布(运行、暂停、完成)活动消息。",
|
"campaigns.archiveHelp": "在公共档案中发布(运行、暂停、完成)活动消息。",
|
||||||
"campaigns.archiveMeta": "活动元数据",
|
"campaigns.archiveMeta": "活动元数据",
|
||||||
"campaigns.archiveMetaHelp": "在公共消息中使用的模拟订阅者数据,包括姓名、电子邮件以及活动消息或模板中使用的任何可选属性。",
|
"campaigns.archiveMetaHelp": "在公共消息中使用的模拟订阅者数据,包括姓名、电子邮件以及活动消息或模板中使用的任何可选属性。",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "附件",
|
"campaigns.attachments": "附件",
|
||||||
"campaigns.cantUpdate": "无法更新正在运行或已完成的广告系列。",
|
"campaigns.cantUpdate": "无法更新正在运行或已完成的广告系列。",
|
||||||
"campaigns.clicks": "点击次数",
|
"campaigns.clicks": "点击次数",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
"campaigns.archiveHelp": "在公開歸檔中發送(運行中、暫停、已完成)的活動訊息。",
|
"campaigns.archiveHelp": "在公開歸檔中發送(運行中、暫停、已完成)的活動訊息。",
|
||||||
"campaigns.archiveMeta": "活動中繼資料",
|
"campaigns.archiveMeta": "活動中繼資料",
|
||||||
"campaigns.archiveMetaHelp": "用於公開訊息的虛擬訂閱者資料,包括姓名、電子郵件和任何在活動訊息或範本中使用的選擇性屬性。",
|
"campaigns.archiveMetaHelp": "用於公開訊息的虛擬訂閱者資料,包括姓名、電子郵件和任何在活動訊息或範本中使用的選擇性屬性。",
|
||||||
|
"campaigns.archiveSlug": "URL Slug",
|
||||||
|
"campaigns.archiveSlugHelp": "A short name for the page to be used in the public URL. eg: my-newsletter-edition-2",
|
||||||
"campaigns.attachments": "附件",
|
"campaigns.attachments": "附件",
|
||||||
"campaigns.cantUpdate": "無法更新正在運行或已完成的廣告系列。",
|
"campaigns.cantUpdate": "無法更新正在運行或已完成的廣告系列。",
|
||||||
"campaigns.clicks": "點擊次數",
|
"campaigns.clicks": "點擊次數",
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,13 @@ func (c *Core) QueryCampaigns(searchStr string, statuses, tags []string, orderBy
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCampaign retrieves a campaign.
|
// GetCampaign retrieves a campaign.
|
||||||
func (c *Core) GetCampaign(id int, uuid string) (models.Campaign, error) {
|
func (c *Core) GetCampaign(id int, uuid, archiveSlug string) (models.Campaign, error) {
|
||||||
return c.getCampaign(id, uuid, campaignTplDefault)
|
return c.getCampaign(id, uuid, archiveSlug, campaignTplDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetArchivedCampaign retrieves a campaign with the archive template body.
|
// GetArchivedCampaign retrieves a campaign with the archive template body.
|
||||||
func (c *Core) GetArchivedCampaign(id int, uuid string) (models.Campaign, error) {
|
func (c *Core) GetArchivedCampaign(id int, uuid, archiveSlug string) (models.Campaign, error) {
|
||||||
out, err := c.getCampaign(id, uuid, campaignTplArchive)
|
out, err := c.getCampaign(id, uuid, archiveSlug, campaignTplArchive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +87,7 @@ func (c *Core) GetArchivedCampaign(id int, uuid string) (models.Campaign, error)
|
||||||
// getCampaign retrieves a campaign. If typlType=default, then the campaign's
|
// getCampaign retrieves a campaign. If typlType=default, then the campaign's
|
||||||
// template body is returned as "template_body". If tplType="archive",
|
// template body is returned as "template_body". If tplType="archive",
|
||||||
// the archive template is returned.
|
// the archive template is returned.
|
||||||
func (c *Core) getCampaign(id int, uuid string, tplType string) (models.Campaign, error) {
|
func (c *Core) getCampaign(id int, uuid, archiveSlug string, tplType string) (models.Campaign, error) {
|
||||||
// Unsafe to ignore scanning fields not present in models.Campaigns.
|
// Unsafe to ignore scanning fields not present in models.Campaigns.
|
||||||
var uu interface{}
|
var uu interface{}
|
||||||
if uuid != "" {
|
if uuid != "" {
|
||||||
|
|
@ -95,7 +95,7 @@ func (c *Core) getCampaign(id int, uuid string, tplType string) (models.Campaign
|
||||||
}
|
}
|
||||||
|
|
||||||
var out models.Campaigns
|
var out models.Campaigns
|
||||||
if err := c.q.GetCampaign.Select(&out, id, uu, tplType); err != nil {
|
if err := c.q.GetCampaign.Select(&out, id, uu, archiveSlug, tplType); err != nil {
|
||||||
// if err := c.db.Select(&out, stmt, 0, pq.Array([]string{}), queryStr, 0, 1); err != nil {
|
// if err := c.db.Select(&out, stmt, 0, pq.Array([]string{}), queryStr, 0, 1); err != nil {
|
||||||
c.log.Printf("error fetching campaign: %v", err)
|
c.log.Printf("error fetching campaign: %v", err)
|
||||||
return models.Campaign{}, echo.NewHTTPError(http.StatusInternalServerError,
|
return models.Campaign{}, echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
|
|
@ -185,6 +185,7 @@ func (c *Core) CreateCampaign(o models.Campaign, listIDs []int, mediaIDs []int)
|
||||||
o.TemplateID,
|
o.TemplateID,
|
||||||
pq.Array(listIDs),
|
pq.Array(listIDs),
|
||||||
o.Archive,
|
o.Archive,
|
||||||
|
o.ArchiveSlug,
|
||||||
o.ArchiveTemplateID,
|
o.ArchiveTemplateID,
|
||||||
o.ArchiveMeta,
|
o.ArchiveMeta,
|
||||||
pq.Array(mediaIDs),
|
pq.Array(mediaIDs),
|
||||||
|
|
@ -198,7 +199,7 @@ func (c *Core) CreateCampaign(o models.Campaign, listIDs []int, mediaIDs []int)
|
||||||
c.i18n.Ts("globals.messages.errorCreating", "name", "{globals.terms.campaign}", "error", pqErrMsg(err)))
|
c.i18n.Ts("globals.messages.errorCreating", "name", "{globals.terms.campaign}", "error", pqErrMsg(err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := c.GetCampaign(newID, "")
|
out, err := c.GetCampaign(newID, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Campaign{}, err
|
return models.Campaign{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -223,6 +224,7 @@ func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs
|
||||||
o.TemplateID,
|
o.TemplateID,
|
||||||
pq.Array(listIDs),
|
pq.Array(listIDs),
|
||||||
o.Archive,
|
o.Archive,
|
||||||
|
o.ArchiveSlug,
|
||||||
o.ArchiveTemplateID,
|
o.ArchiveTemplateID,
|
||||||
o.ArchiveMeta,
|
o.ArchiveMeta,
|
||||||
pq.Array(mediaIDs))
|
pq.Array(mediaIDs))
|
||||||
|
|
@ -232,7 +234,7 @@ func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs
|
||||||
c.i18n.Ts("globals.messages.errorUpdating", "name", "{globals.terms.campaign}", "error", pqErrMsg(err)))
|
c.i18n.Ts("globals.messages.errorUpdating", "name", "{globals.terms.campaign}", "error", pqErrMsg(err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := c.GetCampaign(id, "")
|
out, err := c.GetCampaign(id, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Campaign{}, err
|
return models.Campaign{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -242,7 +244,7 @@ func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs
|
||||||
|
|
||||||
// UpdateCampaignStatus updates a campaign's status, eg: draft to running.
|
// UpdateCampaignStatus updates a campaign's status, eg: draft to running.
|
||||||
func (c *Core) UpdateCampaignStatus(id int, status string) (models.Campaign, error) {
|
func (c *Core) UpdateCampaignStatus(id int, status string) (models.Campaign, error) {
|
||||||
cm, err := c.GetCampaign(id, "")
|
cm, err := c.GetCampaign(id, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Campaign{}, err
|
return models.Campaign{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -297,8 +299,8 @@ func (c *Core) UpdateCampaignStatus(id int, status string) (models.Campaign, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCampaignArchive updates a campaign's archive properties.
|
// UpdateCampaignArchive updates a campaign's archive properties.
|
||||||
func (c *Core) UpdateCampaignArchive(id int, enabled bool, tplID int, meta models.JSON) error {
|
func (c *Core) UpdateCampaignArchive(id int, enabled bool, tplID int, meta models.JSON, archiveSlug string) error {
|
||||||
if _, err := c.q.UpdateCampaignArchive.Exec(id, enabled, tplID, meta); err != nil {
|
if _, err := c.q.UpdateCampaignArchive.Exec(id, enabled, archiveSlug, tplID, meta); err != nil {
|
||||||
c.log.Printf("error updating campaign: %v", err)
|
c.log.Printf("error updating campaign: %v", err)
|
||||||
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@ func (p *pipe) cleanup() {
|
||||||
// Fetch the up-to-date campaign status from the DB.
|
// Fetch the up-to-date campaign status from the DB.
|
||||||
c, err := p.m.store.GetCampaign(p.camp.ID)
|
c, err := p.m.store.GetCampaign(p.camp.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.m.log.Printf("error fetching campaign (%s) for ending", p.camp.Name)
|
p.m.log.Printf("error fetching campaign (%s) for ending: %v", p.camp.Name, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,9 @@ func V3_0_0(db *sqlx.DB, fs stuffbin.FileSystem, ko *koanf.Koanf) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := db.Exec(`ALTER TABLE campaigns ADD COLUMN IF NOT EXISTS archive_slug TEXT NULL UNIQUE`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -252,6 +252,7 @@ type Campaign struct {
|
||||||
TemplateID int `db:"template_id" json:"template_id"`
|
TemplateID int `db:"template_id" json:"template_id"`
|
||||||
Messenger string `db:"messenger" json:"messenger"`
|
Messenger string `db:"messenger" json:"messenger"`
|
||||||
Archive bool `db:"archive" json:"archive"`
|
Archive bool `db:"archive" json:"archive"`
|
||||||
|
ArchiveSlug null.String `db:"archive_slug" json:"archive_slug"`
|
||||||
ArchiveTemplateID int `db:"archive_template_id" json:"archive_template_id"`
|
ArchiveTemplateID int `db:"archive_template_id" json:"archive_template_id"`
|
||||||
ArchiveMeta json.RawMessage `db:"archive_meta" json:"archive_meta"`
|
ArchiveMeta json.RawMessage `db:"archive_meta" json:"archive_meta"`
|
||||||
|
|
||||||
|
|
|
||||||
32
queries.sql
32
queries.sql
|
|
@ -492,16 +492,16 @@ counts AS (
|
||||||
AND subscribers.status='enabled'
|
AND subscribers.status='enabled'
|
||||||
),
|
),
|
||||||
camp AS (
|
camp AS (
|
||||||
INSERT INTO campaigns (uuid, type, name, subject, from_email, body, altbody, content_type, send_at, headers, tags, messenger, template_id, to_send, max_subscriber_id, archive, archive_template_id, archive_meta)
|
INSERT INTO campaigns (uuid, type, name, subject, from_email, body, altbody, content_type, send_at, headers, tags, messenger, template_id, to_send, max_subscriber_id, archive, archive_slug, archive_template_id, archive_meta)
|
||||||
SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12,
|
SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12,
|
||||||
(SELECT id FROM tpl), (SELECT to_send FROM counts),
|
(SELECT id FROM tpl), (SELECT to_send FROM counts),
|
||||||
(SELECT max_sub_id FROM counts), $15,
|
(SELECT max_sub_id FROM counts), $15, $16,
|
||||||
(CASE WHEN $16 = 0 THEN (SELECT id FROM tpl) ELSE $16 END), $17
|
(CASE WHEN $17 = 0 THEN (SELECT id FROM tpl) ELSE $17 END), $18
|
||||||
RETURNING id
|
RETURNING id
|
||||||
),
|
),
|
||||||
med AS (
|
med AS (
|
||||||
INSERT INTO campaign_media (campaign_id, media_id, filename)
|
INSERT INTO campaign_media (campaign_id, media_id, filename)
|
||||||
(SELECT (SELECT id FROM camp), id, filename FROM media WHERE id=ANY($18::INT[]))
|
(SELECT (SELECT id FROM camp), id, filename FROM media WHERE id=ANY($19::INT[]))
|
||||||
)
|
)
|
||||||
INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
||||||
(SELECT (SELECT id FROM camp), id, name FROM lists WHERE id=ANY($14::INT[]))
|
(SELECT (SELECT id FROM camp), id, name FROM lists WHERE id=ANY($14::INT[]))
|
||||||
|
|
@ -517,7 +517,7 @@ INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
||||||
SELECT c.id, c.uuid, c.name, c.subject, c.from_email,
|
SELECT c.id, c.uuid, c.name, c.subject, c.from_email,
|
||||||
c.messenger, c.started_at, c.to_send, c.sent, c.type,
|
c.messenger, c.started_at, c.to_send, c.sent, c.type,
|
||||||
c.body, c.altbody, c.send_at, c.headers, c.status, c.content_type, c.tags,
|
c.body, c.altbody, c.send_at, c.headers, c.status, c.content_type, c.tags,
|
||||||
c.template_id, c.archive, c.archive_template_id, c.archive_meta,
|
c.template_id, c.archive, c.archive_slug, c.archive_template_id, c.archive_meta,
|
||||||
c.created_at, c.updated_at,
|
c.created_at, c.updated_at,
|
||||||
COUNT(*) OVER () AS total,
|
COUNT(*) OVER () AS total,
|
||||||
(
|
(
|
||||||
|
|
@ -539,10 +539,14 @@ SELECT campaigns.*,
|
||||||
COALESCE(templates.body, (SELECT body FROM templates WHERE is_default = true LIMIT 1)) AS template_body
|
COALESCE(templates.body, (SELECT body FROM templates WHERE is_default = true LIMIT 1)) AS template_body
|
||||||
FROM campaigns
|
FROM campaigns
|
||||||
LEFT JOIN templates ON (
|
LEFT JOIN templates ON (
|
||||||
CASE WHEN $3 = 'default' THEN templates.id = campaigns.template_id
|
CASE WHEN $4 = 'default' THEN templates.id = campaigns.template_id
|
||||||
ELSE templates.id = campaigns.archive_template_id END
|
ELSE templates.id = campaigns.archive_template_id END
|
||||||
)
|
)
|
||||||
WHERE CASE WHEN $1 > 0 THEN campaigns.id = $1 ELSE uuid = $2 END;
|
WHERE CASE
|
||||||
|
WHEN $1 > 0 THEN campaigns.id = $1
|
||||||
|
WHEN $3 != '' THEN campaigns.archive_slug = $3
|
||||||
|
ELSE uuid = $2
|
||||||
|
END;
|
||||||
|
|
||||||
-- name: get-archived-campaigns
|
-- name: get-archived-campaigns
|
||||||
SELECT COUNT(*) OVER () AS total, campaigns.*,
|
SELECT COUNT(*) OVER () AS total, campaigns.*,
|
||||||
|
|
@ -808,8 +812,9 @@ WITH camp AS (
|
||||||
messenger=$12,
|
messenger=$12,
|
||||||
template_id=$13,
|
template_id=$13,
|
||||||
archive=$15,
|
archive=$15,
|
||||||
archive_template_id=$16,
|
archive_slug=$16,
|
||||||
archive_meta=$17,
|
archive_template_id=$17,
|
||||||
|
archive_meta=$18,
|
||||||
updated_at=NOW()
|
updated_at=NOW()
|
||||||
WHERE id = $1 RETURNING id
|
WHERE id = $1 RETURNING id
|
||||||
),
|
),
|
||||||
|
|
@ -819,11 +824,11 @@ clists AS (
|
||||||
),
|
),
|
||||||
med AS (
|
med AS (
|
||||||
DELETE FROM campaign_media WHERE campaign_id = $1
|
DELETE FROM campaign_media WHERE campaign_id = $1
|
||||||
AND media_id IS NULL or NOT(media_id = ANY($18)) RETURNING media_id
|
AND media_id IS NULL or NOT(media_id = ANY($19)) RETURNING media_id
|
||||||
),
|
),
|
||||||
medi AS (
|
medi AS (
|
||||||
INSERT INTO campaign_media (campaign_id, media_id, filename)
|
INSERT INTO campaign_media (campaign_id, media_id, filename)
|
||||||
(SELECT $1 AS campaign_id, id, filename FROM media WHERE id=ANY($18::INT[]))
|
(SELECT $1 AS campaign_id, id, filename FROM media WHERE id=ANY($19::INT[]))
|
||||||
ON CONFLICT (campaign_id, media_id) DO NOTHING
|
ON CONFLICT (campaign_id, media_id) DO NOTHING
|
||||||
)
|
)
|
||||||
INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
||||||
|
|
@ -844,8 +849,9 @@ UPDATE campaigns SET status=$2, updated_at=NOW() WHERE id = $1;
|
||||||
-- name: update-campaign-archive
|
-- name: update-campaign-archive
|
||||||
UPDATE campaigns SET
|
UPDATE campaigns SET
|
||||||
archive=$2,
|
archive=$2,
|
||||||
archive_template_id=(CASE WHEN $3 > 0 THEN $3 ELSE archive_template_id END),
|
archive_slug=(CASE WHEN $3::TEXT = '' THEN NULL ELSE $3 END),
|
||||||
archive_meta=(CASE WHEN $4::TEXT != '' THEN $4::JSONB ELSE archive_meta END),
|
archive_template_id=(CASE WHEN $4 > 0 THEN $4 ELSE archive_template_id END),
|
||||||
|
archive_meta=(CASE WHEN $5::TEXT != '' THEN $5::JSONB ELSE archive_meta END),
|
||||||
updated_at=NOW()
|
updated_at=NOW()
|
||||||
WHERE id=$1;
|
WHERE id=$1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ CREATE TABLE campaigns (
|
||||||
|
|
||||||
-- Publishing.
|
-- Publishing.
|
||||||
archive BOOLEAN NOT NULL DEFAULT false,
|
archive BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
archive_slug TEXT NULL UNIQUE,
|
||||||
archive_template_id INTEGER REFERENCES templates(id) ON DELETE SET DEFAULT DEFAULT 1,
|
archive_template_id INTEGER REFERENCES templates(id) ON DELETE SET DEFAULT DEFAULT 1,
|
||||||
archive_meta JSONB NOT NULL DEFAULT '{}',
|
archive_meta JSONB NOT NULL DEFAULT '{}',
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue