mirror of
https://github.com/knadh/listmonk.git
synced 2025-10-05 21:07:36 +08:00
Fix compatibility issues with master
.
- Fix merge conflicts. - Simply logic in campaign preview handler. - Remove redundant `GetCampaignForPreviewWithTemplate()` and switch to the old query that optionally takes a template. - Fix Vue linting issues.
This commit is contained in:
parent
82e2b705bd
commit
c1f81cfadd
8 changed files with 61 additions and 79 deletions
|
@ -142,16 +142,25 @@ func (a *App) PreviewCampaign(c echo.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Fetch the campaign body from the DB.
|
||||
tplID, _ := strconv.Atoi(c.FormValue("template_id"))
|
||||
var (
|
||||
isPost = c.Request().Method == http.MethodPost
|
||||
contentType = c.FormValue("content_type")
|
||||
tplID, _ = strconv.Atoi(c.FormValue("template_id"))
|
||||
)
|
||||
// For visual content type don't use the template for preview, use only body.
|
||||
if contentType == models.CampaignContentTypeVisual && tplID < 1 {
|
||||
tplID = 0
|
||||
}
|
||||
|
||||
// Get the campaign from the DB for previewing.
|
||||
camp, err := a.core.GetCampaignForPreview(id, tplID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// There's a body in the request to preview instead of the body in the DB.
|
||||
if c.Request().Method == http.MethodPost {
|
||||
camp.ContentType = c.FormValue("content_type")
|
||||
if isPost {
|
||||
camp.ContentType = contentType
|
||||
camp.Body = c.FormValue("body")
|
||||
}
|
||||
|
||||
|
@ -214,9 +223,6 @@ func (a *App) CreateCampaign(c echo.Context) error {
|
|||
o.Type = models.CampaignTypeRegular
|
||||
}
|
||||
|
||||
if o.ContentType == "" {
|
||||
o.ContentType = models.CampaignContentTypeRichtext
|
||||
}
|
||||
if o.Messenger == "" {
|
||||
o.Messenger = "email"
|
||||
}
|
||||
|
@ -228,7 +234,7 @@ func (a *App) CreateCampaign(c echo.Context) error {
|
|||
o = c
|
||||
}
|
||||
|
||||
if o.ArchiveTemplateID == 0 {
|
||||
if o.ArchiveTemplateID.Valid && o.ArchiveTemplateID.Int != 0 {
|
||||
o.ArchiveTemplateID = o.TemplateID
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ func (a *App) CreateTemplate(c echo.Context) error {
|
|||
// Subject is only relevant for fixed tx templates. For campaigns,
|
||||
// the subject changes per campaign and is on models.Campaign.
|
||||
var funcs template.FuncMap
|
||||
if o.Type == models.TemplateTypeCampaign {
|
||||
if o.Type == models.TemplateTypeCampaign || o.Type == models.TemplateTypeCampaignVisual {
|
||||
o.Subject = ""
|
||||
funcs = a.manager.TemplateFuncs(nil)
|
||||
} else {
|
||||
|
@ -130,7 +130,7 @@ func (a *App) CreateTemplate(c echo.Context) error {
|
|||
}
|
||||
|
||||
// Create the template the in the DB.
|
||||
out, err := a.core.CreateTemplate(o.Name, o.Type, o.Subject, []byte(o.Body))
|
||||
out, err := a.core.CreateTemplate(o.Name, o.Type, o.Subject, []byte(o.Body), o.BodySource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ func (a *App) UpdateTemplate(c echo.Context) error {
|
|||
|
||||
// Update the template in the DB.
|
||||
id := getID(c)
|
||||
out, err := a.core.UpdateTemplate(id, o.Name, o.Subject, []byte(o.Body))
|
||||
out, err := a.core.UpdateTemplate(id, o.Name, o.Subject, []byte(o.Body), o.BodySource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ func (a *App) validateTemplate(o models.Template) error {
|
|||
// previewTemplate renders the HTML preview of a template.
|
||||
func (a *App) previewTemplate(tpl models.Template) ([]byte, error) {
|
||||
var out []byte
|
||||
if tpl.Type == models.TemplateTypeCampaign {
|
||||
if tpl.Type == models.TemplateTypeCampaign || tpl.Type == models.TemplateTypeCampaignVisual {
|
||||
camp := models.Campaign{
|
||||
UUID: dummyUUID,
|
||||
Name: a.i18n.T("templates.dummyName"),
|
||||
|
|
|
@ -46,5 +46,6 @@
|
|||
"terser": "^5.34.1",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
</b-select>
|
||||
</b-field>
|
||||
|
||||
<b-field v-if="computedValue.contentType !== 'visual'" :label="$t('globals.terms.baseTemplate')" label-position="on-border">
|
||||
<b-field v-if="computedValue.contentType !== 'visual'" :label="$t('globals.terms.baseTemplate')"
|
||||
label-position="on-border">
|
||||
<b-select :placeholder="$t('globals.terms.none')" v-model="templateId" name="template" :disabled="disabled">
|
||||
<template v-for="t in applicableTemplates">
|
||||
<option :value="t.id" :key="t.id">
|
||||
|
@ -38,22 +39,25 @@
|
|||
</b-field>
|
||||
|
||||
<div v-else>
|
||||
<b-button v-if="!isVisualTplSelector" @click="onShowVisualTplSelector" type="is-ghost" icon-left="file-find-outline" data-cy="btn-select-visual-tpl">
|
||||
<b-button v-if="!isVisualTplSelector" @click="onShowVisualTplSelector" type="is-ghost"
|
||||
icon-left="file-find-outline" data-cy="btn-select-visual-tpl">
|
||||
{{ $t('globals.terms.copyVisualTemplate') }}
|
||||
</b-button>
|
||||
|
||||
<b-field v-else :label="$t('globals.terms.copyVisualTemplate')" label-position="on-border">
|
||||
<b-select :placeholder="$t('globals.terms.none')" v-model="visualTemplateId" name="template" :disabled="disabled" class="copy-visual-template-list">
|
||||
<template v-for="t in applicableTemplates">
|
||||
<option :value="t.id" :key="t.id">
|
||||
{{ t.name }}
|
||||
</option>
|
||||
</template>
|
||||
</b-select>
|
||||
<b-select :placeholder="$t('globals.terms.none')" v-model="visualTemplateId" name="template"
|
||||
:disabled="disabled" class="copy-visual-template-list">
|
||||
<template v-for="t in applicableTemplates">
|
||||
<option :value="t.id" :key="t.id">
|
||||
{{ t.name }}
|
||||
</option>
|
||||
</template>
|
||||
</b-select>
|
||||
|
||||
<b-button :disabled="isVisualTplApplied" class="ml-3" @click="onApplyVisualTpl" type="is-primary" icon-left="content-save-outline" data-cy="btn-save-visual-tpl">
|
||||
{{ $t('globals.terms.apply') }}
|
||||
</b-button>
|
||||
<b-button :disabled="isVisualTplApplied" class="ml-3" @click="onApplyVisualTpl" type="is-primary"
|
||||
icon-left="content-save-outline" data-cy="btn-save-visual-tpl">
|
||||
{{ $t('globals.terms.apply') }}
|
||||
</b-button>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,7 +72,8 @@
|
|||
<richtext-editor v-if="computedValue.contentType === 'richtext'" v-model="computedValue.body" />
|
||||
|
||||
<!-- visual editor //-->
|
||||
<visual-editor v-if="computedValue.contentType === 'visual'" :source="computedValue.bodySource" @change="onChangeVisualEditor" height="65vh" />
|
||||
<visual-editor v-if="computedValue.contentType === 'visual'" :source="computedValue.bodySource"
|
||||
@change="onChangeVisualEditor" height="65vh" />
|
||||
|
||||
<!-- raw html editor //-->
|
||||
<html-editor v-if="computedValue.contentType === 'html'" v-model="computedValue.body" />
|
||||
|
@ -77,8 +82,8 @@
|
|||
<markdown-editor v-if="computedValue.contentType === 'markdown'" v-model="computedValue.body" />
|
||||
|
||||
<!-- plain text //-->
|
||||
<b-input v-if="computedValue.contentType === 'plain'" v-model="computedValue.body"
|
||||
type="textarea" name="content" ref="plainEditor" class="plain-editor" />
|
||||
<b-input v-if="computedValue.contentType === 'plain'" v-model="computedValue.body" type="textarea" name="content"
|
||||
ref="plainEditor" class="plain-editor" />
|
||||
|
||||
<!-- campaign preview //-->
|
||||
<campaign-preview v-if="isPreviewing" is-post @close="onTogglePreview" type="campaign" :id="id" :title="title"
|
||||
|
@ -131,7 +136,7 @@ export default {
|
|||
isVisualTplApplied: false,
|
||||
contentType: this.$props.value.contentType,
|
||||
templateId: '',
|
||||
visualTemplateId: ''
|
||||
visualTemplateId: '',
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -291,7 +296,7 @@ export default {
|
|||
this.isVisualTplApplied = true;
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -302,7 +307,7 @@ export default {
|
|||
const defaultTemplate = this.applicableTemplates.find((t) => t.isDefault === true);
|
||||
this.templateId = defaultTemplate?.id || this.applicableTemplates[0]?.id || null;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
|
@ -124,27 +124,11 @@ func (c *Core) getCampaign(id int, uuid, archiveSlug string, tplType string) (mo
|
|||
return out[0], nil
|
||||
}
|
||||
|
||||
// GetCampaignForPreview retrieves a campaign with a template body.
|
||||
func (c *Core) GetCampaignForPreview(id int) (models.Campaign, error) {
|
||||
// GetCampaignForPreview retrieves a campaign with a template body. If the optional tplID is > 0
|
||||
// that particular template is used, otherwise, the template saved on the campaign is.
|
||||
func (c *Core) GetCampaignForPreview(id int, tplID int) (models.Campaign, error) {
|
||||
var out models.Campaign
|
||||
if err := c.q.GetCampaignForPreview.Get(&out, id); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return models.Campaign{}, echo.NewHTTPError(http.StatusBadRequest,
|
||||
c.i18n.Ts("globals.messages.notFound", "name", "{globals.terms.campaign}"))
|
||||
}
|
||||
|
||||
c.log.Printf("error fetching campaign: %v", err)
|
||||
return models.Campaign{}, echo.NewHTTPError(http.StatusInternalServerError,
|
||||
c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.terms.campaign}", "error", pqErrMsg(err)))
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetCampaignForPreview retrieves a campaign with a template body.
|
||||
func (c *Core) GetCampaignForPreviewWithTemplate(id int, tplID *int) (models.Campaign, error) {
|
||||
var out models.Campaign
|
||||
if err := c.q.GetCampaignForPreviewWithTemplate.Get(&out, id, tplID); err != nil {
|
||||
if err := c.q.GetCampaignForPreview.Get(&out, id, tplID); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return models.Campaign{}, echo.NewHTTPError(http.StatusBadRequest,
|
||||
c.i18n.Ts("globals.messages.notFound", "name", "{globals.terms.campaign}"))
|
||||
|
@ -199,11 +183,11 @@ func (c *Core) CreateCampaign(o models.Campaign, listIDs []int, mediaIDs []int)
|
|||
o.Headers,
|
||||
pq.StringArray(normalizeTags(o.Tags)),
|
||||
o.Messenger,
|
||||
o.TemplateID.Int64,
|
||||
o.TemplateID.Int,
|
||||
pq.Array(listIDs),
|
||||
o.Archive,
|
||||
o.ArchiveSlug,
|
||||
o.ArchiveTemplateID.Int64,
|
||||
o.ArchiveTemplateID.Int,
|
||||
o.ArchiveMeta,
|
||||
pq.Array(mediaIDs),
|
||||
o.BodySource,
|
||||
|
|
|
@ -234,11 +234,11 @@ type Campaign struct {
|
|||
ContentType string `db:"content_type" json:"content_type"`
|
||||
Tags pq.StringArray `db:"tags" json:"tags"`
|
||||
Headers Headers `db:"headers" json:"headers"`
|
||||
TemplateID null.Int64 `db:"template_id" json:"template_id"`
|
||||
TemplateID null.Int `db:"template_id" json:"template_id"`
|
||||
Messenger string `db:"messenger" json:"messenger"`
|
||||
Archive bool `db:"archive" json:"archive"`
|
||||
ArchiveSlug null.String `db:"archive_slug" json:"archive_slug"`
|
||||
ArchiveTemplateID null.Int64 `db:"archive_template_id" json:"archive_template_id"`
|
||||
ArchiveTemplateID null.Int `db:"archive_template_id" json:"archive_template_id"`
|
||||
ArchiveMeta json.RawMessage `db:"archive_meta" json:"archive_meta"`
|
||||
|
||||
// TemplateBody is joined in from templates by the next-campaigns query.
|
||||
|
|
|
@ -58,15 +58,14 @@ type Queries struct {
|
|||
UpdateListsDate *sqlx.Stmt `query:"update-lists-date"`
|
||||
DeleteLists *sqlx.Stmt `query:"delete-lists"`
|
||||
|
||||
CreateCampaign *sqlx.Stmt `query:"create-campaign"`
|
||||
QueryCampaigns string `query:"query-campaigns"`
|
||||
GetCampaign *sqlx.Stmt `query:"get-campaign"`
|
||||
GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
|
||||
GetCampaignForPreviewWithTemplate *sqlx.Stmt `query:"get-campaign-for-preview-with-tpl"`
|
||||
GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
|
||||
GetCampaignStatus *sqlx.Stmt `query:"get-campaign-status"`
|
||||
GetArchivedCampaigns *sqlx.Stmt `query:"get-archived-campaigns"`
|
||||
CampaignHasLists *sqlx.Stmt `query:"campaign-has-lists"`
|
||||
CreateCampaign *sqlx.Stmt `query:"create-campaign"`
|
||||
QueryCampaigns string `query:"query-campaigns"`
|
||||
GetCampaign *sqlx.Stmt `query:"get-campaign"`
|
||||
GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
|
||||
GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
|
||||
GetCampaignStatus *sqlx.Stmt `query:"get-campaign-status"`
|
||||
GetArchivedCampaigns *sqlx.Stmt `query:"get-archived-campaigns"`
|
||||
CampaignHasLists *sqlx.Stmt `query:"campaign-has-lists"`
|
||||
|
||||
// These two queries are read as strings and based on settings.individual_tracking=on/off,
|
||||
// are interpolated and copied to view and click counts. Same query, different tables.
|
||||
|
|
17
queries.sql
17
queries.sql
|
@ -663,7 +663,7 @@ LEFT JOIN bounces AS b ON (b.campaign_id = id)
|
|||
ORDER BY ARRAY_POSITION($1, id);
|
||||
|
||||
-- name: get-campaign-for-preview
|
||||
SELECT campaigns.*, COALESCE(templates.body, '') AS template_body,
|
||||
SELECT campaigns.*, COALESCE(templates.body, (SELECT body FROM templates WHERE is_default = true LIMIT 1)) AS template_body,
|
||||
(
|
||||
SELECT COALESCE(ARRAY_TO_JSON(ARRAY_AGG(l)), '[]') FROM (
|
||||
SELECT COALESCE(campaign_lists.list_id, 0) AS id,
|
||||
|
@ -672,20 +672,7 @@ SELECT campaigns.*, COALESCE(templates.body, '') AS template_body,
|
|||
) l
|
||||
) AS lists
|
||||
FROM campaigns
|
||||
LEFT JOIN templates ON templates.id = campaigns.template_id
|
||||
WHERE campaigns.id = $1;
|
||||
|
||||
-- name: get-campaign-for-preview-with-tpl
|
||||
SELECT campaigns.*, COALESCE(templates.body, '') AS template_body,
|
||||
(
|
||||
SELECT COALESCE(ARRAY_TO_JSON(ARRAY_AGG(l)), '[]') FROM (
|
||||
SELECT COALESCE(campaign_lists.list_id, 0) AS id,
|
||||
campaign_lists.list_name AS name
|
||||
FROM campaign_lists WHERE campaign_lists.campaign_id = campaigns.id
|
||||
) l
|
||||
) AS lists
|
||||
FROM campaigns
|
||||
LEFT JOIN templates ON templates.id = $2
|
||||
LEFT JOIN templates ON (templates.id = (CASE WHEN $2=0 THEN campaigns.template_id ELSE $2 END))
|
||||
WHERE campaigns.id = $1;
|
||||
|
||||
-- name: get-campaign-status
|
||||
|
|
Loading…
Add table
Reference in a new issue