From fd31ac6f582c98f799a7cc8b5addfd114197c82c Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sun, 19 Jan 2025 16:06:39 +0530 Subject: [PATCH 1/4] Remove redundant `send_later` param in campaign POST/PUT. --- cmd/campaigns.go | 5 +---- frontend/src/views/Campaign.vue | 2 -- internal/core/campaigns.go | 4 +++- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/cmd/campaigns.go b/cmd/campaigns.go index aa09022d3..468dc91e8 100644 --- a/cmd/campaigns.go +++ b/cmd/campaigns.go @@ -24,9 +24,6 @@ import ( type campaignReq struct { models.Campaign - // Indicates if the "send_at" date should be written or set to null. - SendLater bool `json:"send_later"` - // This overrides Campaign.Lists to receive and // write a list of int IDs during creation and updation. // Campaign.Lists is JSONText for sending lists children @@ -269,7 +266,7 @@ func handleUpdateCampaign(c echo.Context) error { o = c } - out, err := app.core.UpdateCampaign(id, o.Campaign, o.ListIDs, o.MediaIDs, o.SendLater) + out, err := app.core.UpdateCampaign(id, o.Campaign, o.ListIDs, o.MediaIDs) if err != nil { return err } diff --git a/frontend/src/views/Campaign.vue b/frontend/src/views/Campaign.vue index d8f5f91ae..7fd7893de 100644 --- a/frontend/src/views/Campaign.vue +++ b/frontend/src/views/Campaign.vue @@ -497,7 +497,6 @@ export default Vue.extend({ messenger: this.form.messenger, type: 'regular', tags: this.form.tags, - send_later: this.form.sendLater, send_at: this.form.sendLater ? this.form.sendAtDate : null, headers: this.form.headers, template_id: this.form.templateId, @@ -521,7 +520,6 @@ export default Vue.extend({ messenger: this.form.messenger, type: 'regular', tags: this.form.tags, - send_later: this.form.sendLater, send_at: this.form.sendLater ? this.form.sendAtDate : null, headers: this.form.headers, template_id: this.form.templateId, diff --git a/internal/core/campaigns.go b/internal/core/campaigns.go index 168583e7b..f54dda23b 100644 --- a/internal/core/campaigns.go +++ b/internal/core/campaigns.go @@ -208,7 +208,9 @@ func (c *Core) CreateCampaign(o models.Campaign, listIDs []int, mediaIDs []int) } // UpdateCampaign updates a campaign. -func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs []int, sendLater bool) (models.Campaign, error) { +func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs []int) (models.Campaign, error) { + sendLater := o.SendAt.Valid + _, err := c.q.UpdateCampaign.Exec(id, o.Name, o.Subject, From 61c6b7e15ab86ec213c36894e09fb97c483a52d1 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sun, 19 Jan 2025 16:27:39 +0530 Subject: [PATCH 2/4] Add explicit `Unschedule` button on campaign UI. --- frontend/src/views/Campaign.vue | 17 +++++++++++++++++ i18n/ca.json | 1 + i18n/cs-cz.json | 1 + i18n/cy.json | 1 + i18n/da.json | 1 + i18n/de.json | 1 + i18n/el.json | 1 + i18n/en.json | 1 + i18n/eo.json | 1 + i18n/es.json | 1 + i18n/fi.json | 1 + i18n/fr-CA.json | 1 + i18n/fr.json | 1 + i18n/he.json | 1 + i18n/hu.json | 1 + i18n/it.json | 1 + i18n/jp.json | 1 + i18n/ml.json | 1 + i18n/nl.json | 1 + i18n/pl.json | 1 + i18n/pt-BR.json | 1 + i18n/pt.json | 1 + i18n/ro.json | 1 + i18n/ru.json | 1 + i18n/se.json | 1 + i18n/sk.json | 1 + i18n/sl.json | 1 + i18n/tr.json | 1 + i18n/uk.json | 1 + i18n/vi.json | 1 + i18n/zh-CN.json | 1 + i18n/zh-TW.json | 1 + internal/core/campaigns.go | 3 --- queries.sql | 25 ++++++++++++------------- 34 files changed, 60 insertions(+), 16 deletions(-) diff --git a/frontend/src/views/Campaign.vue b/frontend/src/views/Campaign.vue index 7fd7893de..86b9356a1 100644 --- a/frontend/src/views/Campaign.vue +++ b/frontend/src/views/Campaign.vue @@ -43,6 +43,12 @@ {{ $t('campaigns.schedule') }} + + + {{ $t('campaigns.unSchedule') }} + + @@ -593,6 +599,13 @@ export default Vue.extend({ }, ); }, + + unscheduleCampaign() { + this.$api.changeCampaignStatus(this.data.id, 'draft').then((d) => { + this.data = d; + this.form.archiveSlug = d.archiveSlug; + }); + }, }, computed: { @@ -607,6 +620,10 @@ export default Vue.extend({ return this.data.status === 'draft' && this.data.sendAt; }, + canUnSchedule() { + return this.data.status === 'scheduled' && this.data.sendAt; + }, + canStart() { return this.data.status === 'draft' && !this.data.sendAt; }, diff --git a/i18n/ca.json b/i18n/ca.json index 7315e2674..0ec701363 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -98,6 +98,7 @@ "campaigns.testSent": "S'ha enviat el missatge de prova", "campaigns.timestamps": "Segells de temps", "campaigns.trackLink": "Enllaç de seguiment", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Visualitzacions", "dashboard.campaignViews": "Visualitzacions de la campanya", "dashboard.linkClicks": "Clics a enllaços", diff --git a/i18n/cs-cz.json b/i18n/cs-cz.json index bd14c3079..50a3eabdf 100644 --- a/i18n/cs-cz.json +++ b/i18n/cs-cz.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Testovací zpráva odeslána", "campaigns.timestamps": "Časová razítka", "campaigns.trackLink": "Sledovací odkaz", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Pohledy", "dashboard.campaignViews": "Pohledy na kampaň", "dashboard.linkClicks": "Klepnutí na odkaz", diff --git a/i18n/cy.json b/i18n/cy.json index 1c7d66313..655f17d20 100644 --- a/i18n/cy.json +++ b/i18n/cy.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Wedi anfon neges brawf", "campaigns.timestamps": "Stamp amser", "campaigns.trackLink": "Olrhain dolen", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Nifer y bobl sydd wedi'i gweld", "dashboard.campaignViews": "Nifer y bobl sydd wedi gweld yr ymgyrch", "dashboard.linkClicks": "Nifer y bobl sydd wedi clicio'r ddolen", diff --git a/i18n/da.json b/i18n/da.json index aaea2d73e..c2c96ed03 100644 --- a/i18n/da.json +++ b/i18n/da.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Testmeddelelse sendt", "campaigns.timestamps": "Tidsstempler", "campaigns.trackLink": "Link til spor", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Udsigt over", "dashboard.campaignViews": "Kampagnevisninger", "dashboard.linkClicks": "Klik på link", diff --git a/i18n/de.json b/i18n/de.json index 6c334b36b..906f77bf4 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Testnachricht gesendet", "campaigns.timestamps": "Zeitstempel", "campaigns.trackLink": "Track Link", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Ansichten", "dashboard.campaignViews": "Kampagnenansichten", "dashboard.linkClicks": "Linkklicks", diff --git a/i18n/el.json b/i18n/el.json index e6489801d..8423da02d 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Το δοκιμαστικό μήνυμα στάλθηκε", "campaigns.timestamps": "Χρονοσήματα", "campaigns.trackLink": "Σύνδεσμος παρακολούθησης", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Προβολές", "dashboard.campaignViews": "Προβολές εκστρατειών", "dashboard.linkClicks": "Κλικ συνδέσμων", diff --git a/i18n/en.json b/i18n/en.json index eb6eba6ee..285946a20 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Test message sent", "campaigns.timestamps": "Timestamps", "campaigns.trackLink": "Track link", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Views", "dashboard.campaignViews": "Campaign views", "dashboard.linkClicks": "Link clicks", diff --git a/i18n/eo.json b/i18n/eo.json index 79c6cd053..7246c4fd0 100644 --- a/i18n/eo.json +++ b/i18n/eo.json @@ -98,6 +98,7 @@ "campaigns.testSent": "S'ha enviat el missatge de prova", "campaigns.timestamps": "Segells de temps", "campaigns.trackLink": "Enllaç de seguiment", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Visualitzacions", "dashboard.campaignViews": "Visualitzacions de la campanya", "dashboard.linkClicks": "Clics a enllaços", diff --git a/i18n/es.json b/i18n/es.json index 6de21bb1a..a8a3d3398 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Mensaje de prueba enviado", "campaigns.timestamps": "Marcas de tiempo", "campaigns.trackLink": "Enlace de rastreo (Track link)", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Vistas", "dashboard.campaignViews": "Vista de campaña", "dashboard.linkClicks": "Enlaces cliqueados", diff --git a/i18n/fi.json b/i18n/fi.json index bf0532449..7437479ea 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Testiviesti lähetetty", "campaigns.timestamps": "Aikaleimat", "campaigns.trackLink": "Seuraa linkkejä", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Katselukerrat", "dashboard.campaignViews": "Kampanjan katselukerrat", "dashboard.linkClicks": "Linkkiklikkaukset", diff --git a/i18n/fr-CA.json b/i18n/fr-CA.json index 21f4d0f20..0241c8ebc 100644 --- a/i18n/fr-CA.json +++ b/i18n/fr-CA.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Message de test envoyé", "campaigns.timestamps": "Horodatages", "campaigns.trackLink": "Lien de suivi", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Vues", "dashboard.campaignViews": "vues de campagne", "dashboard.linkClicks": "clics sur liens", diff --git a/i18n/fr.json b/i18n/fr.json index 8857d21ca..b229f3c09 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Message de test envoyé", "campaigns.timestamps": "Horodatages", "campaigns.trackLink": "Lien de suivi", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Vues", "dashboard.campaignViews": "vues de campagne", "dashboard.linkClicks": "clics sur liens", diff --git a/i18n/he.json b/i18n/he.json index aa01fe38b..a3655a09c 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -98,6 +98,7 @@ "campaigns.testSent": "הודעת בדיקה נשלחה", "campaigns.timestamps": "חותמות זמן", "campaigns.trackLink": "קישור מעקב", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "צפיות", "dashboard.campaignViews": "צפיות בקמפיין", "dashboard.linkClicks": "לחיצות על קישורים", diff --git a/i18n/hu.json b/i18n/hu.json index 3243a37b0..2088f5a5b 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Tesztüzenet elküldve", "campaigns.timestamps": "Időbélyegek", "campaigns.trackLink": "Nyomkövetőhivatkozás", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Megtekintések", "dashboard.campaignViews": "Megtekintések", "dashboard.linkClicks": "Kattintások", diff --git a/i18n/it.json b/i18n/it.json index 874148f5e..bc113594b 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Messaggio di prova inviato", "campaigns.timestamps": "Marcatura temporale ", "campaigns.trackLink": "Link di tracciamento", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Visualizzazioni", "dashboard.campaignViews": "Visualizzazioni della campagna", "dashboard.linkClicks": "Clic sui link", diff --git a/i18n/jp.json b/i18n/jp.json index 6cfe65a95..c5761ccad 100644 --- a/i18n/jp.json +++ b/i18n/jp.json @@ -99,6 +99,7 @@ "campaigns.testSent": "テストメッセージ送信済み", "campaigns.timestamps": "タイムスタンプ", "campaigns.trackLink": "リンクの追跡", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "ビュー", "dashboard.campaignViews": "キャンペーンビュー", "dashboard.linkClicks": "リンクのクリック", diff --git a/i18n/ml.json b/i18n/ml.json index 6f50117bb..cef0d3e03 100644 --- a/i18n/ml.json +++ b/i18n/ml.json @@ -98,6 +98,7 @@ "campaigns.testSent": "പരീക്ഷണ സന്ദേശം അയച്ചു", "campaigns.timestamps": "ടൈംസ്റ്റാമ്പുകൾ", "campaigns.trackLink": "ട്രാക്ക് ലിങ്ക്", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "കാഴ്ചകൾ", "dashboard.campaignViews": "ക്യാമ്പേയ്ൻ കാഴ്ചകൾ", "dashboard.linkClicks": "ലിങ്ക് ക്ലിക്കുകൾ", diff --git a/i18n/nl.json b/i18n/nl.json index 01fda0460..f5183a704 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Testbericht verzonden", "campaigns.timestamps": "Tijdstippen", "campaigns.trackLink": "Traceerbare link", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Bekeken", "dashboard.campaignViews": "Campagneviews", "dashboard.linkClicks": "Linkkliks", diff --git a/i18n/pl.json b/i18n/pl.json index 12dfe0e81..49af654e1 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Wiadomość testowa wysłana", "campaigns.timestamps": "Sygnatury czasowe", "campaigns.trackLink": "Link śledzący", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Wyświetlenia", "dashboard.campaignViews": "Wyświetlenia kampanii", "dashboard.linkClicks": "Kliknięcia linków", diff --git a/i18n/pt-BR.json b/i18n/pt-BR.json index 83a0b7ec9..60f6cab0f 100644 --- a/i18n/pt-BR.json +++ b/i18n/pt-BR.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Mensagem de teste enviada", "campaigns.timestamps": "Data e hora", "campaigns.trackLink": "Link de rastreamento", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Visualizações", "dashboard.campaignViews": "Visualizações da campanha", "dashboard.linkClicks": "Links clicados", diff --git a/i18n/pt.json b/i18n/pt.json index e3bbe937b..5359b3abf 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Mensagem de teste enviada", "campaigns.timestamps": "Carimbo de hora", "campaigns.trackLink": "Link de rastreamento", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Visualizações", "dashboard.campaignViews": "Vista de campanhas", "dashboard.linkClicks": "Cliques nos links", diff --git a/i18n/ro.json b/i18n/ro.json index d8e12d9ec..6cd7c6544 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Mesaj de testare trimis", "campaigns.timestamps": "Marcajele", "campaigns.trackLink": "Track link-ul", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Vizualizări", "dashboard.campaignViews": "Vizualizările campaniei", "dashboard.linkClicks": "Clicuri pe link", diff --git a/i18n/ru.json b/i18n/ru.json index e97fb04fa..fe2847304 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Тестовое сообщение отправлено", "campaigns.timestamps": "Метки времени", "campaigns.trackLink": "Ссылка на трек", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Просмотры", "dashboard.campaignViews": "Просмотров кампаний", "dashboard.linkClicks": "Кликов по ссылкам", diff --git a/i18n/se.json b/i18n/se.json index a44a460bb..d0ebaf27b 100644 --- a/i18n/se.json +++ b/i18n/se.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Testmeddelande skickat", "campaigns.timestamps": "Tidsstämplar", "campaigns.trackLink": "Spåra länk", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Visningar", "dashboard.campaignViews": "Visningar av kampanjer", "dashboard.linkClicks": "Länkklickar", diff --git a/i18n/sk.json b/i18n/sk.json index 40eada6bf..02e22fcb9 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Testovacia správa odoslaná", "campaigns.timestamps": "Časové razítka", "campaigns.trackLink": "Sledovací odkaz", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Zobrazenia", "dashboard.campaignViews": "Zobrazenia kampane", "dashboard.linkClicks": "Kliknutia na odkaz", diff --git a/i18n/sl.json b/i18n/sl.json index ec67f0024..add1a024d 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Poslano testno sporočilo", "campaigns.timestamps": "Časovni žigi", "campaigns.trackLink": "Sledenje povezavi", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Ogledi", "dashboard.campaignViews": "Ogledi oglaševalske akcije", "dashboard.linkClicks": "Kliki povezav", diff --git a/i18n/tr.json b/i18n/tr.json index 1fbee52b6..8807d1d2e 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Test mesajı gönderildi", "campaigns.timestamps": "Zaman etiketi", "campaigns.trackLink": "İzleme bağlantısı", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Görüntülenme", "dashboard.campaignViews": "Kampanya görüntülenme Sayısı", "dashboard.linkClicks": "Linklerin tıklanması", diff --git a/i18n/uk.json b/i18n/uk.json index aff9330e6..2c6fbde22 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -98,6 +98,7 @@ "campaigns.testSent": "Пробний лист надіслано", "campaigns.timestamps": "Історія", "campaigns.trackLink": "Відстежувати посилання", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Перегляди", "dashboard.campaignViews": "Перегляди кампаній", "dashboard.linkClicks": "Переходи за посиланнями", diff --git a/i18n/vi.json b/i18n/vi.json index 56afd403d..6401f0088 100644 --- a/i18n/vi.json +++ b/i18n/vi.json @@ -99,6 +99,7 @@ "campaigns.testSent": "Gửi tin nhắn thử", "campaigns.timestamps": "Dấu thời gian", "campaigns.trackLink": "Theo dõi liên kết", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "Lượt xem", "dashboard.campaignViews": "Chế độ xem chiến dịch", "dashboard.linkClicks": "Liên kết nhấp chuột", diff --git a/i18n/zh-CN.json b/i18n/zh-CN.json index 25bf6060d..4ac318451 100644 --- a/i18n/zh-CN.json +++ b/i18n/zh-CN.json @@ -98,6 +98,7 @@ "campaigns.testSent": "已发送测试消息", "campaigns.timestamps": "时间戳", "campaigns.trackLink": "跟踪链接", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "视图", "dashboard.campaignViews": "广告系列视图", "dashboard.linkClicks": "链接点击次数", diff --git a/i18n/zh-TW.json b/i18n/zh-TW.json index 1593250d9..0029cacdb 100644 --- a/i18n/zh-TW.json +++ b/i18n/zh-TW.json @@ -99,6 +99,7 @@ "campaigns.testSent": "測試電子郵件已寄送", "campaigns.timestamps": "時間戳記", "campaigns.trackLink": "追蹤連結", + "campaigns.unSchedule": "Unschedule", "campaigns.views": "開信", "dashboard.campaignViews": "活動開信", "dashboard.linkClicks": "連結點擊次數", diff --git a/internal/core/campaigns.go b/internal/core/campaigns.go index f54dda23b..cf3fbbd39 100644 --- a/internal/core/campaigns.go +++ b/internal/core/campaigns.go @@ -209,8 +209,6 @@ func (c *Core) CreateCampaign(o models.Campaign, listIDs []int, mediaIDs []int) // UpdateCampaign updates a campaign. func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs []int) (models.Campaign, error) { - sendLater := o.SendAt.Valid - _, err := c.q.UpdateCampaign.Exec(id, o.Name, o.Subject, @@ -219,7 +217,6 @@ func (c *Core) UpdateCampaign(id int, o models.Campaign, listIDs []int, mediaIDs o.AltBody, o.ContentType, o.SendAt, - sendLater, o.Headers, pq.StringArray(normalizeTags(o.Tags)), o.Messenger, diff --git a/queries.sql b/queries.sql index c5b755dde..39071d2de 100644 --- a/queries.sql +++ b/queries.sql @@ -830,33 +830,32 @@ WITH camp AS ( altbody=(CASE WHEN $6 = '' THEN NULL ELSE $6 END), content_type=$7::content_type, send_at=$8::TIMESTAMP WITH TIME ZONE, - status=(CASE WHEN NOT $9 THEN 'draft' ELSE status END), - headers=$10, - tags=$11::VARCHAR(100)[], - messenger=$12, - template_id=$13, - archive=$15, - archive_slug=$16, - archive_template_id=$17, - archive_meta=$18, + headers=$9, + tags=$10::VARCHAR(100)[], + messenger=$11, + template_id=$12, + archive=$14, + archive_slug=$15, + archive_template_id=$16, + archive_meta=$17, updated_at=NOW() WHERE id = $1 RETURNING id ), clists AS ( -- Reset list relationships - DELETE FROM campaign_lists WHERE campaign_id = $1 AND NOT(list_id = ANY($14)) + DELETE FROM campaign_lists WHERE campaign_id = $1 AND NOT(list_id = ANY($13)) ), med AS ( DELETE FROM campaign_media WHERE campaign_id = $1 - AND ( media_id IS NULL or NOT(media_id = ANY($19))) RETURNING media_id + AND ( media_id IS NULL or NOT(media_id = ANY($18))) RETURNING media_id ), medi AS ( INSERT INTO campaign_media (campaign_id, media_id, filename) - (SELECT $1 AS campaign_id, id, filename FROM media WHERE id=ANY($19::INT[])) + (SELECT $1 AS campaign_id, id, filename FROM media WHERE id=ANY($18::INT[])) ON CONFLICT (campaign_id, media_id) DO NOTHING ) INSERT INTO campaign_lists (campaign_id, list_id, list_name) - (SELECT $1 as campaign_id, id, name FROM lists WHERE id=ANY($14::INT[])) + (SELECT $1 as campaign_id, id, name FROM lists WHERE id=ANY($13::INT[])) ON CONFLICT (campaign_id, list_id) DO UPDATE SET list_name = EXCLUDED.list_name; -- name: update-campaign-counts From 5ba0adcb0b15aff94142b2052b7dcdf07cbd9782 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sun, 19 Jan 2025 16:35:16 +0530 Subject: [PATCH 3/4] Automatically switch scheduled campaigns to `draft` when `send_at` date it removed. --- queries.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/queries.sql b/queries.sql index 39071d2de..7772fce79 100644 --- a/queries.sql +++ b/queries.sql @@ -830,6 +830,12 @@ WITH camp AS ( altbody=(CASE WHEN $6 = '' THEN NULL ELSE $6 END), content_type=$7::content_type, send_at=$8::TIMESTAMP WITH TIME ZONE, + status=( + CASE + WHEN status = 'scheduled' AND $8 IS NULL THEN 'draft' + ELSE status + END + ), headers=$9, tags=$10::VARCHAR(100)[], messenger=$11, From 3d383cd537272f317242f896a47d474e04e2137e Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sun, 19 Jan 2025 16:40:25 +0530 Subject: [PATCH 4/4] Make paused campaigns editable. --- cmd/campaigns.go | 14 +++++++------- frontend/src/views/Campaign.vue | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/campaigns.go b/cmd/campaigns.go index 468dc91e8..0514dd79b 100644 --- a/cmd/campaigns.go +++ b/cmd/campaigns.go @@ -248,7 +248,7 @@ func handleUpdateCampaign(c echo.Context) error { return err } - if isCampaignalMutable(cm.Status) { + if !canEditCampaign(cm.Status) { return echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("campaigns.cantUpdate")) } @@ -597,12 +597,12 @@ func validateCampaignFields(c campaignReq, app *App) (campaignReq, error) { return c, nil } -// isCampaignalMutable tells if a campaign's in a state where it's -// properties can be mutated. -func isCampaignalMutable(status string) bool { - return status == models.CampaignStatusRunning || - status == models.CampaignStatusCancelled || - status == models.CampaignStatusFinished +// canEditCampaign returns true if a campaign is in a status where updating +// its properties is allowed. +func canEditCampaign(status string) bool { + return status == models.CampaignStatusDraft || + status == models.CampaignStatusPaused || + status == models.CampaignStatusScheduled } // makeOptinCampaignMessage makes a default opt-in campaign message body. diff --git a/frontend/src/views/Campaign.vue b/frontend/src/views/Campaign.vue index 86b9356a1..9e922b137 100644 --- a/frontend/src/views/Campaign.vue +++ b/frontend/src/views/Campaign.vue @@ -613,7 +613,7 @@ export default Vue.extend({ canEdit() { return this.isNew - || this.data.status === 'draft' || this.data.status === 'scheduled'; + || this.data.status === 'draft' || this.data.status === 'scheduled' || this.data.status === 'paused'; }, canSchedule() { @@ -625,7 +625,7 @@ export default Vue.extend({ }, canStart() { - return this.data.status === 'draft' && !this.data.sendAt; + return this.data.status === 'draft' || this.data.status === 'paused'; }, canArchive() {