From 5077e36d051db300a96f38cdf6b063aef8ba3d09 Mon Sep 17 00:00:00 2001 From: Abban Dunne Date: Thu, 7 Dec 2023 15:07:48 +0100 Subject: [PATCH 01/15] Prepare thank you banner Ticket: https://phabricator.wikimedia.org/T352651 --- banners/thank_you/MembershipFormActions.ts | 31 +++ banners/thank_you/banner_ctrl.de.ts | 59 +++++ banners/thank_you/banner_ctrl.en.ts | 59 +++++ banners/thank_you/banner_ctrl.wpde.ts | 61 +++++ banners/thank_you/banner_var.de.ts | 59 +++++ banners/thank_you/banner_var.en.ts | 59 +++++ banners/thank_you/banner_var.wpde.ts | 61 +++++ .../thank_you/components/BannerCtrl.de.vue | 121 +++++++++ .../thank_you/components/BannerCtrl.en.vue | 121 +++++++++ banners/thank_you/components/BannerVar.de.vue | 133 ++++++++++ banners/thank_you/components/BannerVar.en.vue | 133 ++++++++++ .../thank_you/components/FullPageBanner.vue | 34 +++ .../thank_you/components/MembershipButton.vue | 30 +++ banners/thank_you/components/MiniBanner.vue | 51 ++++ banners/thank_you/components/ProgressBar.vue | 18 ++ .../components/icons/CheckCircleIcon.vue | 14 + .../thank_you/components/icons/HandIcon.vue | 6 + .../thank_you/components/icons/HeartIcon.vue | 6 + .../thank_you/components/icons/MoneyIcon.vue | 6 + .../thank_you/components/icons/PeopleIcon.vue | 6 + .../content/FullPageBannerText.de.vue | 53 ++++ .../content/FullPageBannerText.en.vue | 50 ++++ .../thank_you/content/ImageWithCopyright.vue | 17 ++ .../content/MembershipBenefits.de.vue | 11 + .../content/MembershipBenefits.en.vue | 11 + .../thank_you/content/MiniBannerSlides.de.vue | 25 ++ .../thank_you/content/MiniBannerSlides.en.vue | 25 ++ .../thank_you/content/MiniBannerText.de.vue | 5 + .../thank_you/content/MiniBannerText.en.vue | 6 + banners/thank_you/content/StatsBox.vue | 36 +++ banners/thank_you/createSubscribeURL.ts | 16 ++ banners/thank_you/event_map.ts | 22 ++ banners/thank_you/messages.de.ts | 29 +++ banners/thank_you/messages.en.ts | 31 +++ banners/thank_you/styles/Banner.scss | 59 +++++ banners/thank_you/styles/ButtonClose.scss | 38 +++ banners/thank_you/styles/FullPageBanner.scss | 116 +++++++++ .../thank_you/styles/ImageWithCopyright.scss | 32 +++ banners/thank_you/styles/KeenSlider.scss | 66 +++++ .../thank_you/styles/MembershipBenefits.scss | 27 ++ .../styles/MembershipFormButton.scss | 26 ++ banners/thank_you/styles/MiniBanner.scss | 55 ++++ banners/thank_you/styles/ProgressBar.scss | 44 ++++ banners/thank_you/styles/StatsBox.scss | 38 +++ banners/thank_you/styles/_firework.scss | 168 ++++++++++++ .../styles/settings/_breakpoints.scss | 37 +++ banners/thank_you/styles/settings/_fonts.scss | 9 + .../thank_you/styles/settings/_globals.scss | 4 + banners/thank_you/styles/settings/colors.ts | 12 + banners/thank_you/styles/styles.scss | 12 + campaign_info_main.toml | 244 ++++++++++++++++++ docs/Use-of-Funds-integration.md | 2 +- src/tracking/TrackingEvent.ts | 4 +- .../events/ThankYouModalShownEvent.ts | 10 + .../components/BannerCtrl.de.spec.ts | 106 ++++++++ .../components/BannerCtrl.en.spec.ts | 106 ++++++++ .../thank_you/components/BannerVar.de.spec.ts | 112 ++++++++ .../thank_you/components/BannerVar.en.spec.ts | 112 ++++++++ .../components/FullPageBanner.spec.ts | 31 +++ .../components/MembershipButton.spec.ts | 27 ++ .../thank_you/components/MiniBanner.spec.ts | 63 +++++ .../thank_you/components/ProgressBar.spec.ts | 33 +++ 62 files changed, 2996 insertions(+), 2 deletions(-) create mode 100644 banners/thank_you/MembershipFormActions.ts create mode 100644 banners/thank_you/banner_ctrl.de.ts create mode 100644 banners/thank_you/banner_ctrl.en.ts create mode 100644 banners/thank_you/banner_ctrl.wpde.ts create mode 100644 banners/thank_you/banner_var.de.ts create mode 100644 banners/thank_you/banner_var.en.ts create mode 100644 banners/thank_you/banner_var.wpde.ts create mode 100644 banners/thank_you/components/BannerCtrl.de.vue create mode 100644 banners/thank_you/components/BannerCtrl.en.vue create mode 100644 banners/thank_you/components/BannerVar.de.vue create mode 100644 banners/thank_you/components/BannerVar.en.vue create mode 100644 banners/thank_you/components/FullPageBanner.vue create mode 100644 banners/thank_you/components/MembershipButton.vue create mode 100644 banners/thank_you/components/MiniBanner.vue create mode 100644 banners/thank_you/components/ProgressBar.vue create mode 100644 banners/thank_you/components/icons/CheckCircleIcon.vue create mode 100644 banners/thank_you/components/icons/HandIcon.vue create mode 100644 banners/thank_you/components/icons/HeartIcon.vue create mode 100644 banners/thank_you/components/icons/MoneyIcon.vue create mode 100644 banners/thank_you/components/icons/PeopleIcon.vue create mode 100644 banners/thank_you/content/FullPageBannerText.de.vue create mode 100644 banners/thank_you/content/FullPageBannerText.en.vue create mode 100644 banners/thank_you/content/ImageWithCopyright.vue create mode 100644 banners/thank_you/content/MembershipBenefits.de.vue create mode 100644 banners/thank_you/content/MembershipBenefits.en.vue create mode 100644 banners/thank_you/content/MiniBannerSlides.de.vue create mode 100644 banners/thank_you/content/MiniBannerSlides.en.vue create mode 100644 banners/thank_you/content/MiniBannerText.de.vue create mode 100644 banners/thank_you/content/MiniBannerText.en.vue create mode 100644 banners/thank_you/content/StatsBox.vue create mode 100644 banners/thank_you/createSubscribeURL.ts create mode 100644 banners/thank_you/event_map.ts create mode 100644 banners/thank_you/messages.de.ts create mode 100644 banners/thank_you/messages.en.ts create mode 100644 banners/thank_you/styles/Banner.scss create mode 100644 banners/thank_you/styles/ButtonClose.scss create mode 100644 banners/thank_you/styles/FullPageBanner.scss create mode 100644 banners/thank_you/styles/ImageWithCopyright.scss create mode 100644 banners/thank_you/styles/KeenSlider.scss create mode 100644 banners/thank_you/styles/MembershipBenefits.scss create mode 100644 banners/thank_you/styles/MembershipFormButton.scss create mode 100644 banners/thank_you/styles/MiniBanner.scss create mode 100644 banners/thank_you/styles/ProgressBar.scss create mode 100644 banners/thank_you/styles/StatsBox.scss create mode 100644 banners/thank_you/styles/_firework.scss create mode 100644 banners/thank_you/styles/settings/_breakpoints.scss create mode 100644 banners/thank_you/styles/settings/_fonts.scss create mode 100644 banners/thank_you/styles/settings/_globals.scss create mode 100644 banners/thank_you/styles/settings/colors.ts create mode 100644 banners/thank_you/styles/styles.scss create mode 100644 campaign_info_main.toml create mode 100644 src/tracking/events/ThankYouModalShownEvent.ts create mode 100644 test/banners/thank_you/components/BannerCtrl.de.spec.ts create mode 100644 test/banners/thank_you/components/BannerCtrl.en.spec.ts create mode 100644 test/banners/thank_you/components/BannerVar.de.spec.ts create mode 100644 test/banners/thank_you/components/BannerVar.en.spec.ts create mode 100644 test/banners/thank_you/components/FullPageBanner.spec.ts create mode 100644 test/banners/thank_you/components/MembershipButton.spec.ts create mode 100644 test/banners/thank_you/components/MiniBanner.spec.ts create mode 100644 test/banners/thank_you/components/ProgressBar.spec.ts diff --git a/banners/thank_you/MembershipFormActions.ts b/banners/thank_you/MembershipFormActions.ts new file mode 100644 index 000000000..a8476a744 --- /dev/null +++ b/banners/thank_you/MembershipFormActions.ts @@ -0,0 +1,31 @@ +/* eslint-disable camelcase */ +import { TrackingParameters } from '@src/domain/TrackingParameters'; +import { ImpressionCount } from '@src/utils/ImpressionCount'; + +const MEMBERSHIP_FORM_URL = 'https://spenden.wikimedia.de/apply-for-membership'; + +export interface MembershipFormActions { + create( extraUrlParameters: Record ): string; +} + +export class TrackingMembershipFormActions implements MembershipFormActions { + private _tracking: TrackingParameters; + private _impressionCount: ImpressionCount; + + public constructor( tracking: TrackingParameters, impressionCount: ImpressionCount ) { + this._tracking = tracking; + this._impressionCount = impressionCount; + } + + public create( extraUrlParameters: Record = {} ): string { + const urlParameters = new URLSearchParams( { + piwik_kwd: this._tracking.keyword, + piwik_campaign: this._tracking.campaign, + impCount: String( this._impressionCount.overallCountIncremented ), + bImpCount: String( this._impressionCount.bannerCountIncremented ), + ...extraUrlParameters + } ); + + return `${MEMBERSHIP_FORM_URL}?${urlParameters}`; + } +} diff --git a/banners/thank_you/banner_ctrl.de.ts b/banners/thank_you/banner_ctrl.de.ts new file mode 100644 index 000000000..d72daa74a --- /dev/null +++ b/banners/thank_you/banner_ctrl.de.ts @@ -0,0 +1,59 @@ +import { createVueApp } from '@src/createVueApp'; + +import './styles/styles.scss'; + +import PageWPORG from '@src/page/PageWPORG'; +import { SkinFactory } from '@src/page/skin/SkinFactory'; +import { WindowSizeIssueChecker } from '@src/utils/SizeIssueChecker/WindowSizeIssueChecker'; +import { Translator } from '@src/Translator'; +import { WindowMediaWiki } from '@src/page/MediaWiki/WindowMediaWiki'; +import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; +import { LocalImpressionCount } from '@src/utils/LocalImpressionCount'; +import { LegacyTrackerWPORG } from '@src/tracking/LegacyTrackerWPORG'; +import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; +import { WindowResizeHandler } from '@src/utils/ResizeHandler'; +import Banner from './components/BannerCtrl.de.vue'; +import messages from './messages.de'; +import eventMappings from '../thank_you/event_map'; +import TranslationPlugin from '@src/TranslationPlugin'; +import DynamicTextPlugin from '@src/DynamicTextPlugin'; +import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe'; +import { TrackingMembershipFormActions } from './MembershipFormActions'; +import { createSubscribeURL } from './createSubscribeURL'; + +const localeFactory = new LocaleFactoryDe(); + +const translator = new Translator( messages ); +const mediaWiki = new WindowMediaWiki(); +const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin(), new WindowSizeIssueChecker( 400 ) ); +const runtimeEnvironment = new UrlRuntimeEnvironment( window.location ); +const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment ); +const tracker = new LegacyTrackerWPORG( mediaWiki, page.getTracking().keyword, eventMappings, runtimeEnvironment ); + +const app = createVueApp( BannerConductor, { + page, + bannerConfig: { + delay: 0, + transitionDuration: 1000 + }, + bannerProps: { + progressBarFillPercentage: 80, + subscribeURL: createSubscribeURL( page.getTracking(), impressionCount ) + }, + resizeHandler: new WindowResizeHandler(), + banner: Banner, + impressionCount +} ); + +app.use( TranslationPlugin, translator ); +app.use( DynamicTextPlugin, { + campaignParameters: page.getCampaignParameters(), + date: new Date(), + formatters: localeFactory.getFormatters(), + impressionCount, + translator +} ); +app.provide( 'tracker', tracker ); +app.provide( 'formActions', new TrackingMembershipFormActions( page.getTracking(), impressionCount ) ); + +app.mount( page.getBannerContainer() ); diff --git a/banners/thank_you/banner_ctrl.en.ts b/banners/thank_you/banner_ctrl.en.ts new file mode 100644 index 000000000..1a785360c --- /dev/null +++ b/banners/thank_you/banner_ctrl.en.ts @@ -0,0 +1,59 @@ +import { createVueApp } from '@src/createVueApp'; + +import './styles/styles.scss'; + +import PageWPORG from '@src/page/PageWPORG'; +import { SkinFactory } from '@src/page/skin/SkinFactory'; +import { WindowSizeIssueChecker } from '@src/utils/SizeIssueChecker/WindowSizeIssueChecker'; +import { Translator } from '@src/Translator'; +import { WindowMediaWiki } from '@src/page/MediaWiki/WindowMediaWiki'; +import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; +import { LocalImpressionCount } from '@src/utils/LocalImpressionCount'; +import { LegacyTrackerWPORG } from '@src/tracking/LegacyTrackerWPORG'; +import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; +import { WindowResizeHandler } from '@src/utils/ResizeHandler'; +import Banner from './components/BannerCtrl.en.vue'; +import messages from './messages.en'; +import eventMappings from '../thank_you/event_map'; +import TranslationPlugin from '@src/TranslationPlugin'; +import DynamicTextPlugin from '@src/DynamicTextPlugin'; +import { TrackingMembershipFormActions } from './MembershipFormActions'; +import { createSubscribeURL } from './createSubscribeURL'; +import { LocaleFactoryEn } from '@src/utils/LocaleFactory/LocaleFactoryEn'; + +const localeFactory = new LocaleFactoryEn(); + +const translator = new Translator( messages ); +const mediaWiki = new WindowMediaWiki(); +const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin(), new WindowSizeIssueChecker( 400 ) ); +const runtimeEnvironment = new UrlRuntimeEnvironment( window.location ); +const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment ); +const tracker = new LegacyTrackerWPORG( mediaWiki, page.getTracking().keyword, eventMappings, runtimeEnvironment ); + +const app = createVueApp( BannerConductor, { + page, + bannerConfig: { + delay: 0, + transitionDuration: 1000 + }, + bannerProps: { + progressBarFillPercentage: 80, + subscribeURL: createSubscribeURL( page.getTracking(), impressionCount ) + }, + resizeHandler: new WindowResizeHandler(), + banner: Banner, + impressionCount +} ); + +app.use( TranslationPlugin, translator ); +app.use( DynamicTextPlugin, { + campaignParameters: page.getCampaignParameters(), + date: new Date(), + formatters: localeFactory.getFormatters(), + impressionCount, + translator +} ); +app.provide( 'tracker', tracker ); +app.provide( 'formActions', new TrackingMembershipFormActions( page.getTracking(), impressionCount ) ); + +app.mount( page.getBannerContainer() ); diff --git a/banners/thank_you/banner_ctrl.wpde.ts b/banners/thank_you/banner_ctrl.wpde.ts new file mode 100644 index 000000000..5ec1cf4eb --- /dev/null +++ b/banners/thank_you/banner_ctrl.wpde.ts @@ -0,0 +1,61 @@ +import { createVueApp } from '@src/createVueApp'; + +import './styles/styles.scss'; +import { Translator } from '@src/Translator'; +import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; +import { LocalImpressionCount } from '@src/utils/LocalImpressionCount'; +import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; +import { WindowResizeHandler } from '@src/utils/ResizeHandler'; +import Banner from './components/BannerCtrl.de.vue'; +import messages from './messages.de'; +import TranslationPlugin from '@src/TranslationPlugin'; +import DynamicTextPlugin from '@src/DynamicTextPlugin'; +import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe'; +import { TrackingMembershipFormActions } from './MembershipFormActions'; +import { createSubscribeURL } from './createSubscribeURL'; +import PageWPDE from '@src/page/PageWPDE'; +import { TrackerWPDE } from '@src/tracking/TrackerWPDE'; +import eventMap from '../wpde_desktop/event_map'; + +const localeFactory = new LocaleFactoryDe(); +const translator = new Translator( messages ); + +// Tracking placeholders will be replaced by webpack string-replace-loader +// using the campaign configuration ( campaign_info.toml ) for the correct values +const tracking = { + campaign: '!insert-campaign-here!', + keyword: '!insert-keyword-here!' +}; + +const page = new PageWPDE( tracking ); +const runtimeEnvironment = new UrlRuntimeEnvironment( window.location ); +const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment ); +const tracker = new TrackerWPDE( 'FundraisingTracker', page.getTracking().keyword, eventMap, runtimeEnvironment ); + +const app = createVueApp( BannerConductor, { + page, + bannerConfig: { + delay: 0, + transitionDuration: 1000 + }, + bannerProps: { + progressBarFillPercentage: 80, + subscribeURL: createSubscribeURL( page.getTracking(), impressionCount ) + }, + resizeHandler: new WindowResizeHandler(), + banner: Banner, + impressionCount +} ); + +app.use( TranslationPlugin, translator ); +app.use( DynamicTextPlugin, { + campaignParameters: page.getCampaignParameters(), + date: new Date(), + formatters: localeFactory.getFormatters(), + impressionCount, + translator +} ); +app.provide( 'tracker', tracker ); +app.provide( 'formActions', new TrackingMembershipFormActions( page.getTracking(), impressionCount ) ); + +app.mount( page.getBannerContainer() ); diff --git a/banners/thank_you/banner_var.de.ts b/banners/thank_you/banner_var.de.ts new file mode 100644 index 000000000..9f95e9d84 --- /dev/null +++ b/banners/thank_you/banner_var.de.ts @@ -0,0 +1,59 @@ +import { createVueApp } from '@src/createVueApp'; + +import './styles/styles.scss'; + +import PageWPORG from '@src/page/PageWPORG'; +import { SkinFactory } from '@src/page/skin/SkinFactory'; +import { WindowSizeIssueChecker } from '@src/utils/SizeIssueChecker/WindowSizeIssueChecker'; +import { Translator } from '@src/Translator'; +import { WindowMediaWiki } from '@src/page/MediaWiki/WindowMediaWiki'; +import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; +import { LocalImpressionCount } from '@src/utils/LocalImpressionCount'; +import { LegacyTrackerWPORG } from '@src/tracking/LegacyTrackerWPORG'; +import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; +import { WindowResizeHandler } from '@src/utils/ResizeHandler'; +import Banner from './components/BannerVar.de.vue'; +import messages from './messages.de'; +import eventMappings from '../thank_you/event_map'; +import TranslationPlugin from '@src/TranslationPlugin'; +import DynamicTextPlugin from '@src/DynamicTextPlugin'; +import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe'; +import { TrackingMembershipFormActions } from './MembershipFormActions'; +import { createSubscribeURL } from './createSubscribeURL'; + +const localeFactory = new LocaleFactoryDe(); + +const translator = new Translator( messages ); +const mediaWiki = new WindowMediaWiki(); +const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin(), new WindowSizeIssueChecker( 400 ) ); +const runtimeEnvironment = new UrlRuntimeEnvironment( window.location ); +const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment ); +const tracker = new LegacyTrackerWPORG( mediaWiki, page.getTracking().keyword, eventMappings, runtimeEnvironment ); + +const app = createVueApp( BannerConductor, { + page, + bannerConfig: { + delay: 0, + transitionDuration: 1000 + }, + bannerProps: { + progressBarFillPercentage: 80, + subscribeURL: createSubscribeURL( page.getTracking(), impressionCount ) + }, + resizeHandler: new WindowResizeHandler(), + banner: Banner, + impressionCount +} ); + +app.use( TranslationPlugin, translator ); +app.use( DynamicTextPlugin, { + campaignParameters: page.getCampaignParameters(), + date: new Date(), + formatters: localeFactory.getFormatters(), + impressionCount, + translator +} ); +app.provide( 'tracker', tracker ); +app.provide( 'formActions', new TrackingMembershipFormActions( page.getTracking(), impressionCount ) ); + +app.mount( page.getBannerContainer() ); diff --git a/banners/thank_you/banner_var.en.ts b/banners/thank_you/banner_var.en.ts new file mode 100644 index 000000000..48dc0800a --- /dev/null +++ b/banners/thank_you/banner_var.en.ts @@ -0,0 +1,59 @@ +import { createVueApp } from '@src/createVueApp'; + +import './styles/styles.scss'; + +import PageWPORG from '@src/page/PageWPORG'; +import { SkinFactory } from '@src/page/skin/SkinFactory'; +import { WindowSizeIssueChecker } from '@src/utils/SizeIssueChecker/WindowSizeIssueChecker'; +import { Translator } from '@src/Translator'; +import { WindowMediaWiki } from '@src/page/MediaWiki/WindowMediaWiki'; +import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; +import { LocalImpressionCount } from '@src/utils/LocalImpressionCount'; +import { LegacyTrackerWPORG } from '@src/tracking/LegacyTrackerWPORG'; +import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; +import { WindowResizeHandler } from '@src/utils/ResizeHandler'; +import Banner from './components/BannerVar.en.vue'; +import messages from './messages.en'; +import eventMappings from '../thank_you/event_map'; +import TranslationPlugin from '@src/TranslationPlugin'; +import DynamicTextPlugin from '@src/DynamicTextPlugin'; +import { TrackingMembershipFormActions } from './MembershipFormActions'; +import { createSubscribeURL } from './createSubscribeURL'; +import { LocaleFactoryEn } from '@src/utils/LocaleFactory/LocaleFactoryEn'; + +const localeFactory = new LocaleFactoryEn(); + +const translator = new Translator( messages ); +const mediaWiki = new WindowMediaWiki(); +const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin(), new WindowSizeIssueChecker( 400 ) ); +const runtimeEnvironment = new UrlRuntimeEnvironment( window.location ); +const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment ); +const tracker = new LegacyTrackerWPORG( mediaWiki, page.getTracking().keyword, eventMappings, runtimeEnvironment ); + +const app = createVueApp( BannerConductor, { + page, + bannerConfig: { + delay: 0, + transitionDuration: 1000 + }, + bannerProps: { + progressBarFillPercentage: 80, + subscribeURL: createSubscribeURL( page.getTracking(), impressionCount ) + }, + resizeHandler: new WindowResizeHandler(), + banner: Banner, + impressionCount +} ); + +app.use( TranslationPlugin, translator ); +app.use( DynamicTextPlugin, { + campaignParameters: page.getCampaignParameters(), + date: new Date(), + formatters: localeFactory.getFormatters(), + impressionCount, + translator +} ); +app.provide( 'tracker', tracker ); +app.provide( 'formActions', new TrackingMembershipFormActions( page.getTracking(), impressionCount ) ); + +app.mount( page.getBannerContainer() ); diff --git a/banners/thank_you/banner_var.wpde.ts b/banners/thank_you/banner_var.wpde.ts new file mode 100644 index 000000000..6debb9ccf --- /dev/null +++ b/banners/thank_you/banner_var.wpde.ts @@ -0,0 +1,61 @@ +import { createVueApp } from '@src/createVueApp'; + +import './styles/styles.scss'; +import { Translator } from '@src/Translator'; +import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; +import { LocalImpressionCount } from '@src/utils/LocalImpressionCount'; +import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; +import { WindowResizeHandler } from '@src/utils/ResizeHandler'; +import Banner from './components/BannerVar.de.vue'; +import messages from './messages.de'; +import TranslationPlugin from '@src/TranslationPlugin'; +import DynamicTextPlugin from '@src/DynamicTextPlugin'; +import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe'; +import { TrackingMembershipFormActions } from './MembershipFormActions'; +import { createSubscribeURL } from './createSubscribeURL'; +import PageWPDE from '@src/page/PageWPDE'; +import { TrackerWPDE } from '@src/tracking/TrackerWPDE'; +import eventMap from '../wpde_desktop/event_map'; + +const localeFactory = new LocaleFactoryDe(); +const translator = new Translator( messages ); + +// Tracking placeholders will be replaced by webpack string-replace-loader +// using the campaign configuration ( campaign_info.toml ) for the correct values +const tracking = { + campaign: '!insert-campaign-here!', + keyword: '!insert-keyword-here!' +}; + +const page = new PageWPDE( tracking ); +const runtimeEnvironment = new UrlRuntimeEnvironment( window.location ); +const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment ); +const tracker = new TrackerWPDE( 'FundraisingTracker', page.getTracking().keyword, eventMap, runtimeEnvironment ); + +const app = createVueApp( BannerConductor, { + page, + bannerConfig: { + delay: 0, + transitionDuration: 1000 + }, + bannerProps: { + progressBarFillPercentage: 80, + subscribeURL: createSubscribeURL( page.getTracking(), impressionCount ) + }, + resizeHandler: new WindowResizeHandler(), + banner: Banner, + impressionCount +} ); + +app.use( TranslationPlugin, translator ); +app.use( DynamicTextPlugin, { + campaignParameters: page.getCampaignParameters(), + date: new Date(), + formatters: localeFactory.getFormatters(), + impressionCount, + translator +} ); +app.provide( 'tracker', tracker ); +app.provide( 'formActions', new TrackingMembershipFormActions( page.getTracking(), impressionCount ) ); + +app.mount( page.getBannerContainer() ); diff --git a/banners/thank_you/components/BannerCtrl.de.vue b/banners/thank_you/components/BannerCtrl.de.vue new file mode 100644 index 000000000..9abf7d43a --- /dev/null +++ b/banners/thank_you/components/BannerCtrl.de.vue @@ -0,0 +1,121 @@ + + + diff --git a/banners/thank_you/components/BannerCtrl.en.vue b/banners/thank_you/components/BannerCtrl.en.vue new file mode 100644 index 000000000..15beaaf39 --- /dev/null +++ b/banners/thank_you/components/BannerCtrl.en.vue @@ -0,0 +1,121 @@ + + + diff --git a/banners/thank_you/components/BannerVar.de.vue b/banners/thank_you/components/BannerVar.de.vue new file mode 100644 index 000000000..271e3bf20 --- /dev/null +++ b/banners/thank_you/components/BannerVar.de.vue @@ -0,0 +1,133 @@ + + + diff --git a/banners/thank_you/components/BannerVar.en.vue b/banners/thank_you/components/BannerVar.en.vue new file mode 100644 index 000000000..c69221913 --- /dev/null +++ b/banners/thank_you/components/BannerVar.en.vue @@ -0,0 +1,133 @@ + + + diff --git a/banners/thank_you/components/FullPageBanner.vue b/banners/thank_you/components/FullPageBanner.vue new file mode 100644 index 000000000..6d8e260e0 --- /dev/null +++ b/banners/thank_you/components/FullPageBanner.vue @@ -0,0 +1,34 @@ + + + diff --git a/banners/thank_you/components/MembershipButton.vue b/banners/thank_you/components/MembershipButton.vue new file mode 100644 index 000000000..85235d1b1 --- /dev/null +++ b/banners/thank_you/components/MembershipButton.vue @@ -0,0 +1,30 @@ + + + diff --git a/banners/thank_you/components/MiniBanner.vue b/banners/thank_you/components/MiniBanner.vue new file mode 100644 index 000000000..e653b1389 --- /dev/null +++ b/banners/thank_you/components/MiniBanner.vue @@ -0,0 +1,51 @@ + + + diff --git a/banners/thank_you/components/ProgressBar.vue b/banners/thank_you/components/ProgressBar.vue new file mode 100644 index 000000000..1fcc49c99 --- /dev/null +++ b/banners/thank_you/components/ProgressBar.vue @@ -0,0 +1,18 @@ + + + diff --git a/banners/thank_you/components/icons/CheckCircleIcon.vue b/banners/thank_you/components/icons/CheckCircleIcon.vue new file mode 100644 index 000000000..3eb239500 --- /dev/null +++ b/banners/thank_you/components/icons/CheckCircleIcon.vue @@ -0,0 +1,14 @@ + diff --git a/banners/thank_you/components/icons/HandIcon.vue b/banners/thank_you/components/icons/HandIcon.vue new file mode 100644 index 000000000..b7ec7acf1 --- /dev/null +++ b/banners/thank_you/components/icons/HandIcon.vue @@ -0,0 +1,6 @@ + diff --git a/banners/thank_you/components/icons/HeartIcon.vue b/banners/thank_you/components/icons/HeartIcon.vue new file mode 100644 index 000000000..fd290f6c8 --- /dev/null +++ b/banners/thank_you/components/icons/HeartIcon.vue @@ -0,0 +1,6 @@ + diff --git a/banners/thank_you/components/icons/MoneyIcon.vue b/banners/thank_you/components/icons/MoneyIcon.vue new file mode 100644 index 000000000..2e0b279b8 --- /dev/null +++ b/banners/thank_you/components/icons/MoneyIcon.vue @@ -0,0 +1,6 @@ + diff --git a/banners/thank_you/components/icons/PeopleIcon.vue b/banners/thank_you/components/icons/PeopleIcon.vue new file mode 100644 index 000000000..e3d7938fc --- /dev/null +++ b/banners/thank_you/components/icons/PeopleIcon.vue @@ -0,0 +1,6 @@ + diff --git a/banners/thank_you/content/FullPageBannerText.de.vue b/banners/thank_you/content/FullPageBannerText.de.vue new file mode 100644 index 000000000..463af14ad --- /dev/null +++ b/banners/thank_you/content/FullPageBannerText.de.vue @@ -0,0 +1,53 @@ + + + diff --git a/banners/thank_you/content/FullPageBannerText.en.vue b/banners/thank_you/content/FullPageBannerText.en.vue new file mode 100644 index 000000000..5c89d8d72 --- /dev/null +++ b/banners/thank_you/content/FullPageBannerText.en.vue @@ -0,0 +1,50 @@ + + + diff --git a/banners/thank_you/content/ImageWithCopyright.vue b/banners/thank_you/content/ImageWithCopyright.vue new file mode 100644 index 000000000..22de54efc --- /dev/null +++ b/banners/thank_you/content/ImageWithCopyright.vue @@ -0,0 +1,17 @@ + diff --git a/banners/thank_you/content/MembershipBenefits.de.vue b/banners/thank_you/content/MembershipBenefits.de.vue new file mode 100644 index 000000000..a5b49d33a --- /dev/null +++ b/banners/thank_you/content/MembershipBenefits.de.vue @@ -0,0 +1,11 @@ + + diff --git a/banners/thank_you/content/MembershipBenefits.en.vue b/banners/thank_you/content/MembershipBenefits.en.vue new file mode 100644 index 000000000..41a38efe1 --- /dev/null +++ b/banners/thank_you/content/MembershipBenefits.en.vue @@ -0,0 +1,11 @@ + + diff --git a/banners/thank_you/content/MiniBannerSlides.de.vue b/banners/thank_you/content/MiniBannerSlides.de.vue new file mode 100644 index 000000000..2bf14e923 --- /dev/null +++ b/banners/thank_you/content/MiniBannerSlides.de.vue @@ -0,0 +1,25 @@ + + + diff --git a/banners/thank_you/content/MiniBannerSlides.en.vue b/banners/thank_you/content/MiniBannerSlides.en.vue new file mode 100644 index 000000000..2bf14e923 --- /dev/null +++ b/banners/thank_you/content/MiniBannerSlides.en.vue @@ -0,0 +1,25 @@ + + + diff --git a/banners/thank_you/content/MiniBannerText.de.vue b/banners/thank_you/content/MiniBannerText.de.vue new file mode 100644 index 000000000..83d89098a --- /dev/null +++ b/banners/thank_you/content/MiniBannerText.de.vue @@ -0,0 +1,5 @@ + diff --git a/banners/thank_you/content/MiniBannerText.en.vue b/banners/thank_you/content/MiniBannerText.en.vue new file mode 100644 index 000000000..228a44b7c --- /dev/null +++ b/banners/thank_you/content/MiniBannerText.en.vue @@ -0,0 +1,6 @@ + diff --git a/banners/thank_you/content/StatsBox.vue b/banners/thank_you/content/StatsBox.vue new file mode 100644 index 000000000..8283a7337 --- /dev/null +++ b/banners/thank_you/content/StatsBox.vue @@ -0,0 +1,36 @@ + + diff --git a/banners/thank_you/createSubscribeURL.ts b/banners/thank_you/createSubscribeURL.ts new file mode 100644 index 000000000..0a83a43ee --- /dev/null +++ b/banners/thank_you/createSubscribeURL.ts @@ -0,0 +1,16 @@ +/* eslint-disable camelcase */ +import { TrackingParameters } from '@src/domain/TrackingParameters'; +import { ImpressionCount } from '@src/utils/ImpressionCount'; + +const SUBSCRIBE_URL = 'https://www.wikimedia.de/mitglieder/'; + +export function createSubscribeURL( tracking: TrackingParameters, impressionCount: ImpressionCount ): string { + const urlParameters = new URLSearchParams( { + piwik_kwd: tracking.keyword, + piwik_campaign: tracking.campaign, + impCount: String( impressionCount.overallCountIncremented ), + bImpCount: String( impressionCount.bannerCountIncremented ) + } ); + + return `${SUBSCRIBE_URL}?${urlParameters}`; +} diff --git a/banners/thank_you/event_map.ts b/banners/thank_you/event_map.ts new file mode 100644 index 000000000..a065d9b25 --- /dev/null +++ b/banners/thank_you/event_map.ts @@ -0,0 +1,22 @@ +import { TrackingEventConverterFactory } from '@src/tracking/LegacyTrackerWPORG'; +import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent'; +import { WMDESizeIssueEvent } from '@src/tracking/WPORG/WMDEBannerSizeIssue'; +import { createViewportInfo } from '@src/tracking/LegacyEventTracking/createViewportInfo'; +import { ThankYouModalShownEvent } from '@src/tracking/events/ThankYouModalShownEvent'; +import { WMDELegacyBannerEvent } from '@src/tracking/WPORG/WMDELegacyBannerEvent'; +import { CloseEvent } from '@src/tracking/events/CloseEvent'; +import { mapCloseEvent } from '@src/tracking/LegacyEventTracking/mapCloseEvent'; + +export default new Map( [ + [ CloseEvent.EVENT_NAME, mapCloseEvent ], + [ + BannerSubmitEvent.EVENT_NAME, + ( e: BannerSubmitEvent ): WMDESizeIssueEvent => { + return new WMDESizeIssueEvent( `submit-${e.userChoice}`, createViewportInfo(), 1 ); + } + ], + [ + ThankYouModalShownEvent.EVENT_NAME, + ( e: ThankYouModalShownEvent ): WMDELegacyBannerEvent => new WMDELegacyBannerEvent( e.eventName, 1 ) + ] +] ); diff --git a/banners/thank_you/messages.de.ts b/banners/thank_you/messages.de.ts new file mode 100644 index 000000000..7438ad8b8 --- /dev/null +++ b/banners/thank_you/messages.de.ts @@ -0,0 +1,29 @@ +import { TranslationMessages } from '@src/Translator'; +import DynamicCampaignTextDe from '@src/utils/DynamicContent/messages/DynamicCampaignText.de'; + +const messages: TranslationMessages = { + ...DynamicCampaignTextDe, + 'call-to-action-more-info': 'Weitere Informationen auf unserer Webseite', + 'call-to-action-button-amount-per-month': 'Mit {{amount}} € im Monat fördern', + 'call-to-action-button-different-amount': 'Mit anderem Betrag fördern', + 'open-modal': 'Dankestext lesen', + 'close-modal': 'Dankestext schließen', + 'progress-bar-inner-text-win': 'Geschafft!', + 'progress-bar-inner-text-lose': 'Dennoch: Spendenziel nicht erreicht', + 'image-copyright-holder': 'Annika Möller für Wikimedia Deutschland', + 'subscribe-title': 'Benötigen Sie weitere Informationen zur Mitgliedschaft?', + 'subscribe-text': 'Tragen Sie einfach Ihre E-Mail-Adresse ein', + 'subscribe-link': 'oder besuchen Sie unsere Webseite', + 'subscribe-privacy': 'Datenschutz', + 'subscribe-button': 'Senden', + 'subscribe-placeholder': 'E-Mail-Adresse', + 'subscribe-form-error': 'Bitte geben Sie eine gültige E-Mail-Adresse an.', + 'stats-people-amount': '102.000', + 'stats-people-text': 'Fördermitglied bereits', + 'stats-average-amount': '55 €', + 'stats-average-text': 'durchschnittlicher Jahresbeitrag', + 'stats-contribution-amount': '2 €', + 'stats-contribution-text': 'Mindestbeitrag nur 2 €/Monat' +}; + +export default messages; diff --git a/banners/thank_you/messages.en.ts b/banners/thank_you/messages.en.ts new file mode 100644 index 000000000..74f53f2d2 --- /dev/null +++ b/banners/thank_you/messages.en.ts @@ -0,0 +1,31 @@ +import { TranslationMessages } from '@src/Translator'; +import DynamicCampaignTextEn from '@src/utils/DynamicContent/messages/DynamicCampaignText.en'; + +const messages: TranslationMessages = { + ...DynamicCampaignTextEn, + 'call-to-action-more-info': 'For more information, please visit our website', + 'call-to-action-button': 'Become a supporter now', + 'call-to-action-button-amount-per-month': 'Support with €{{amount}} per month', + 'call-to-action-button-different-amount': 'Support with a custom amount', + 'open-modal': 'Open thank you message', + 'close-modal': 'Close thank you message', + 'progress-bar-inner-text': 'Accomplished!', + 'progress-bar-inner-text-win': 'Accomplished!', + 'progress-bar-inner-text-lose': 'Failed', + 'image-copyright-holder': 'Annika Möller for Wikimedia Deutschland', + 'subscribe-title': 'Need more information about membership?', + 'subscribe-text': 'Simply enter your e-mail address', + 'subscribe-link': 'or visit our website', + 'subscribe-privacy': 'Privacy', + 'subscribe-button': 'Send', + 'subscribe-placeholder': 'E-Mail Address', + 'subscribe-form-error': 'Please enter a valid email address.', + 'stats-people-amount': '102.000', + 'stats-people-text': 'Fördermitglied bereits', + 'stats-average-amount': '55 €', + 'stats-average-text': 'durchschnittlicher Jahresbeitrag', + 'stats-contribution-amount': '2 €', + 'stats-contribution-text': 'Mindestbeitrag nur 2 €/Monat' +}; + +export default messages; diff --git a/banners/thank_you/styles/Banner.scss b/banners/thank_you/styles/Banner.scss new file mode 100644 index 000000000..2dd778b0f --- /dev/null +++ b/banners/thank_you/styles/Banner.scss @@ -0,0 +1,59 @@ +@use 'settings/fonts'; +@use 'settings/globals'; +@use 'settings/breakpoints'; + +.wmde-banner { + font-family: fonts.$ui; + + * { + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + img { + border: 0 none; + } + + p { + margin: 0 0 24px; + } + + &--pending { + .wmde-banner-wrapper { + box-shadow: none; + } + } + + &--closed { + .wmde-banner-wrapper { + display: none; + } + } + + &-button { + display: inline-block; + border: 0; + margin: 0; + padding: 0 20px; + border-radius: 16px; + font-weight: bold; + font-size: 18px; + height: 40px; + cursor: pointer; + color: var( --color-white ); + background: var( --color-secondary ); + transition: background-color 500ms ease-in-out; + + &:hover, + &:focus { + background: var( --color-secondary-hover ); + } + + &.hollow { + background: var( --color-white ); + color: var( --color-secondary ); + border: 4px solid var( --color-secondary ); + } + } +} diff --git a/banners/thank_you/styles/ButtonClose.scss b/banners/thank_you/styles/ButtonClose.scss new file mode 100644 index 000000000..e7c0fd8a5 --- /dev/null +++ b/banners/thank_you/styles/ButtonClose.scss @@ -0,0 +1,38 @@ +.wmde-banner { + &-close { + position: absolute; + top: 14px; + right: 14px; + height: 34px; + width: 34px; + border: 0; + background: 0; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + + svg path { + fill: var( --color-primary ); + } + } + + &-full { + .wmde-banner-close { + width: auto; + font-size: 14px; + font-weight: bold; + color: var( --color-grey-dark ); + transition: color 500ms ease-in-out; + + &:hover, + &:focus { + color: var( --color-black ); + } + + svg { + margin-left: 10px; + } + } + } +} diff --git a/banners/thank_you/styles/FullPageBanner.scss b/banners/thank_you/styles/FullPageBanner.scss new file mode 100644 index 000000000..32930ee3a --- /dev/null +++ b/banners/thank_you/styles/FullPageBanner.scss @@ -0,0 +1,116 @@ +@use 'settings/globals'; +@use 'settings/breakpoints'; + +.wmde-banner { + &-full { + visibility: hidden; + opacity: 0; + transform: scale( 1.1 ); + font-size: 16px; + line-height: 1.5; + background: var( --color-black-transparent ); + position: fixed; + display: flex; + align-items: center; + top: 0; + z-index: 1000; + height: 100vh; + width: 100vw; + transition: opacity 500ms globals.$banner-easing, visibility 500ms globals.$banner-easing, transform 500ms globals.$banner-easing; + + @include breakpoints.medium-up { + font-size: 18px; + } + + &-scroll { + padding: 10px; + max-height: 100vh; + overflow-y: auto; + } + + &-inner { + position: relative; + background: var( --color-white ); + padding: 48px 20px; + border-radius: 6px; + box-shadow: 0 5px 5px rgba( 0 0 0 / 0.2 ); + + @include breakpoints.medium-up { + padding: 48px; + } + } + + &-cta { + background: var( --color-off-white ); + padding: 20px; + border: 1px solid var( --color-primary ); + border-radius: 6px; + + @include breakpoints.medium-up { + padding: 40px; + } + + &-columns { + display: flex; + flex-wrap: wrap; + justify-content: stretch; + align-items: stretch; + margin: 0; + + @include breakpoints.small-up { + margin: 0 -20px; + } + } + + &-benefits, + &-buttons { + width: 100%; + + @include breakpoints.small-up { + width: 50%; + padding: 0 20px; + } + + @include breakpoints.large-up { + width: auto; + } + } + + &-buttons { + display: flex; + flex-direction: column; + } + } + + p.wmde-banner-full-subscribe { + margin-bottom: 20px; + font-size: 14px; + font-weight: bold; + + a { + color: var( --color-black ); + text-decoration: underline; + transition: color 500ms ease-in-out; + + &:hover, + &:focus { + color: var( --color-secondary ); + } + } + + @include breakpoints.medium-up { + margin-bottom: 0; + } + } + } + + &-wrapper { + &--full-page { + .wmde-banner-full { + visibility: visible; + opacity: 1; + transform: scale( 1 ); + } + } + } +} diff --git a/banners/thank_you/styles/ImageWithCopyright.scss b/banners/thank_you/styles/ImageWithCopyright.scss new file mode 100644 index 000000000..31379199b --- /dev/null +++ b/banners/thank_you/styles/ImageWithCopyright.scss @@ -0,0 +1,32 @@ +@use 'settings/breakpoints'; + +.wmde-banner { + &-image { + font-size: 12px; + text-align: center; + position: relative; + padding: 0; + width: 156px; + margin: 0 auto 20px; + + img { + border-radius: 50%; + } + + @include breakpoints.x-small-up { + margin: 6px 30px 10px 0; + float: left; + } + + &-copyright { + position: absolute; + top: 0; + left: -10px; + width: 210px; + height: 210px; + font-size: 6px; + float: left; + transform: rotate( 270deg ); + } + } +} diff --git a/banners/thank_you/styles/KeenSlider.scss b/banners/thank_you/styles/KeenSlider.scss new file mode 100644 index 000000000..303898713 --- /dev/null +++ b/banners/thank_you/styles/KeenSlider.scss @@ -0,0 +1,66 @@ +@use 'settings/fonts'; +@use 'settings/breakpoints'; +@use 'src/components/Slider/KeenSlider'; + +.wmde-banner { + @include KeenSlider.layout; + + &-slider-container { + font-family: fonts.$ui; + font-size: 24px; + padding: 16px 0; + line-height: 1.2; + + @include breakpoints.small-up { + font-size: 1.3em; + line-height: 1.5; + } + } + + &-slide { + cursor: grab; + + &--current { + .wmde-banner-slider-text-animated-highlight { + background-position: 0 0; + } + } + + &-content { + text-align: center; + padding: 0 30px; + + p { + margin: 0 0 1em; + } + + p:last-child { + margin: 0; + } + } + } + + &-slider-pagination { + &-dot { + background: var( --color-grey ); + width: 15px; + height: 15px; + margin: 0 4px; + border-radius: 50%; + cursor: pointer; + border: 3px solid var( --color-white ); + + &:focus { + outline: 0; + } + } + .is-active { + background: var( --color-white ); + border: 3px solid var( --color-primary ); + } + } + + &-navigation-wrapper { + margin-bottom: 16px; + } +} diff --git a/banners/thank_you/styles/MembershipBenefits.scss b/banners/thank_you/styles/MembershipBenefits.scss new file mode 100644 index 000000000..5d1b62fe2 --- /dev/null +++ b/banners/thank_you/styles/MembershipBenefits.scss @@ -0,0 +1,27 @@ +.wmde-banner { + &-benefits { + list-style-type: none; + list-style-image: none; + padding: 0; + margin: 0 0 20px; + + li { + margin-bottom: 10px; + position: relative; + padding-left: 24px; + + &:last-child { + margin-bottom: 0; + } + } + svg { + position: absolute; + top: 5px; + left: 0; + + path { + stroke: var( --color-primary ); + } + } + } +} diff --git a/banners/thank_you/styles/MembershipFormButton.scss b/banners/thank_you/styles/MembershipFormButton.scss new file mode 100644 index 000000000..c10e2708a --- /dev/null +++ b/banners/thank_you/styles/MembershipFormButton.scss @@ -0,0 +1,26 @@ +@use 'settings/breakpoints'; + +.wmde-banner { + &-button-membership { + width: 100%; + max-width: 330px; + height: 50px; + border: 0; + display: inline-block; + padding: 0 14px; + font-size: 18px; + font-weight: bold; + border-radius: 6px; + text-decoration: none; + margin: 0 0.5em 0.5em 0; + white-space: nowrap; + cursor: pointer; + + @include breakpoints.medium-up { + height: 58px; + padding: 0 32px; + font-size: 24px; + max-width: 410px; + } + } +} diff --git a/banners/thank_you/styles/MiniBanner.scss b/banners/thank_you/styles/MiniBanner.scss new file mode 100644 index 000000000..53b5bbe90 --- /dev/null +++ b/banners/thank_you/styles/MiniBanner.scss @@ -0,0 +1,55 @@ +@use 'settings/fonts'; +@use 'settings/breakpoints'; + +.wmde-banner { + &-mini { + background: var( --color-primary ); + position: relative; + padding: 10px; + overflow: hidden; + text-align: center; + + &-inner { + padding: 20px; + background: var( --color-white ); + border-radius: 6px; + box-shadow: 0 5px 5px rgba( 0 0 0 / 0.2 ); + + @include breakpoints.small-up { + padding: 70px 48px; + } + } + + &-text { + font-size: 24px; + + &-columns { + display: flex; + } + &-progress { + flex: 1 1 auto; + padding-top: 2px; + } + &-button { + flex: 0 0 auto; + padding-left: 16px; + } + } + } + + &-info-button { + position: absolute; + top: 10px; + left: 10px; + height: 34px; + width: 34px; + padding: 8px; + background: none; + border: 0; + cursor: pointer; + + svg circle { + fill: var( --color-primary ); + } + } +} diff --git a/banners/thank_you/styles/ProgressBar.scss b/banners/thank_you/styles/ProgressBar.scss new file mode 100644 index 000000000..f82f33620 --- /dev/null +++ b/banners/thank_you/styles/ProgressBar.scss @@ -0,0 +1,44 @@ +@use 'settings/globals'; + +.wmde-banner { + &-progress-bar { + font-size: 16px; + border: 3px solid var( --color-primary ); + border-radius: 15px; + position: relative; + height: 36px; + line-height: 30px; + margin: 0; + + &-fill { + width: 10%; + transition: width 3000ms globals.$banner-easing; + position: absolute; + top: 0; + left: 0; + height: 100%; + text-align: left; + padding: 0 10px; + color: var( --color-white ); + font-weight: bold; + border-radius: 12px; + background: var( --color-primary ); + + &-text { + opacity: 0; + transition: opacity 300ms globals.$banner-easing; + transition-delay: 3000ms; + } + } + } + + &--visible { + .wmde-banner-progress-bar-fill { + width: var( --wmde-banner-progress-bar-width ); + + &-text { + opacity: 1; + } + } + } +} diff --git a/banners/thank_you/styles/StatsBox.scss b/banners/thank_you/styles/StatsBox.scss new file mode 100644 index 000000000..991ccfd40 --- /dev/null +++ b/banners/thank_you/styles/StatsBox.scss @@ -0,0 +1,38 @@ +@use 'settings/breakpoints'; + +.wmde-banner { + &-stats-box { + background: var( --color-off-white ); + border-radius: 6px; + padding: 12px; + margin: 0 0 24px; + + @include breakpoints.x-small-up { + float: right; + max-width: 184px; + margin: 0 0 10px 10px; + } + + &-row { + display: flex; + + &:not( :last-child ) { + margin-bottom: 12px; + } + } + + &-icon { + flex: 0 0 auto; + } + + &-text { + flex: 1 1 auto; + padding-left: 12px; + font-size: 12px; + + strong { + font-size: 16px; + } + } + } +} diff --git a/banners/thank_you/styles/_firework.scss b/banners/thank_you/styles/_firework.scss new file mode 100644 index 000000000..44f478794 --- /dev/null +++ b/banners/thank_you/styles/_firework.scss @@ -0,0 +1,168 @@ +/* stylelint-disable */ + +@keyframes firework { + 0% { + transform: translate( var( --x ), var( --initialY ) ); + width: var( --initialSize ); + opacity: 1; + } + 50% { + width: 0.5vmin; + opacity: 1; + } + 100% { + width: var( --finalSize ); + opacity: 0; + } +} + +.wmde-banner { + &-firework, + &-firework::before, + &-firework::after { + --initialSize: 0.5vmin; + --finalSize: 45vmin; + --particleSize: 0.2vmin; + --color1: yellow; + --color2: khaki; + --color3: white; + --color4: lime; + --color5: gold; + --color6: mediumseagreen; + --y: -20vmin; + --x: -50%; + --initialY: 60vmin; + content: ""; + animation: firework 4s infinite; + position: absolute; + top: 50%; + left: 50%; + transform: translate( -50%, var( --y ) ); + width: var(--initialSize); + aspect-ratio: 1; + pointer-events: none; + background: radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 50% 0%, + radial-gradient(circle, var(--color2) var(--particleSize), #0000 0) 100% 50%, + radial-gradient(circle, var(--color3) var(--particleSize), #0000 0) 50% 100%, + radial-gradient(circle, var(--color4) var(--particleSize), #0000 0) 0% 50%, + /* bottom right */ radial-gradient(circle, var(--color5) var(--particleSize), #0000 0) 80% 90%, + radial-gradient(circle, var(--color6) var(--particleSize), #0000 0) 95% 90%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 90% 70%, + radial-gradient(circle, var(--color2) var(--particleSize), #0000 0) 100% 60%, + radial-gradient(circle, var(--color3) var(--particleSize), #0000 0) 55% 80%, + radial-gradient(circle, var(--color4) var(--particleSize), #0000 0) 70% 77%, + /* bottom left */ radial-gradient(circle, var(--color5) var(--particleSize), #0000 0) 22% 90%, + radial-gradient(circle, var(--color6) var(--particleSize), #0000 0) 45% 90%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 33% 70%, + radial-gradient(circle, var(--color2) var(--particleSize), #0000 0) 10% 60%, + radial-gradient(circle, var(--color3) var(--particleSize), #0000 0) 31% 80%, + radial-gradient(circle, var(--color4) var(--particleSize), #0000 0) 28% 77%, + radial-gradient(circle, var(--color5) var(--particleSize), #0000 0) 13% 72%, + /* top left */ radial-gradient(circle, var(--color6) var(--particleSize), #0000 0) 80% 10%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 95% 14%, + radial-gradient(circle, var(--color2) var(--particleSize), #0000 0) 90% 23%, + radial-gradient(circle, var(--color3) var(--particleSize), #0000 0) 100% 43%, + radial-gradient(circle, var(--color4) var(--particleSize), #0000 0) 85% 27%, + radial-gradient(circle, var(--color5) var(--particleSize), #0000 0) 77% 37%, + radial-gradient(circle, var(--color6) var(--particleSize), #0000 0) 60% 7%, + /* top right */ radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 22% 14%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 45% 20%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 33% 34%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 10% 29%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 31% 37%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 28% 7%, + radial-gradient(circle, var(--color1) var(--particleSize), #0000 0) 13% 42%; + background-size: var(--initialSize) var(--initialSize); + background-repeat: no-repeat; + } + + &-firework::before { + --x: -50%; + --y: -50%; + --initialY: -50%; + transform: translate( -50%, -50% ) rotate( 40deg ) scale( 1.3 ) rotateY( 40deg ); + } + + &-firework::after { + --x: -50%; + --y: -50%; + --initialY: -50%; + transform: translate( -50%, -50% ) rotate( 170deg ) scale( 1.15 ) rotateY( -30deg ); + } + + &-firework-left { + --x: 30vmin; + } + + &-firework-lefter { + --x: 60vmin; + } + + &-firework-left, + &-firework-left::before, + &-firework-left::after { + --color1: pink; + --color2: violet; + --color3: fuchsia; + --color4: orchid; + --color5: plum; + --color6: lavender; + --finalSize: 40vmin; + left: 30%; + top: 60%; + animation-delay: -0.25s; + } + + &-firework-lefter, + &-firework-lefter::before, + &-firework-lefter::after { + --color1: #ffc0c0; + --color2: #ee8282; + --color3: #ff0000; + --color4: #da7070; + --color5: #dda0a0; + --color6: #fae6e6; + --finalSize: 40vmin; + left: 30%; + top: 60%; + animation-delay: -0.15s; + } + + &-firework-right { + --x: -30vmin; + } + + &-firework-righter { + --x: -60vmin; + } + + &-firework-right, + &-firework-right::before, + &-firework-right::after { + --color1: cyan; + --color2: lightcyan; + --color3: lightblue; + --color4: PaleTurquoise; + --color5: SkyBlue; + --color6: lavender; + --finalSize: 35vmin; + left: 70%; + top: 60%; + animation-delay: -0.4s; + } + + &-firework-righter, + &-firework-righter::before, + &-firework-righter::after { + --color1: #5eff00; + --color2: #eaffe0; + --color3: #c2e6ad; + --color4: #c8eeaf; + --color5: #afeb87; + --color6: #edfae6; + --finalSize: 35vmin; + left: 70%; + top: 60%; + animation-delay: -0.8s; + } +} diff --git a/banners/thank_you/styles/settings/_breakpoints.scss b/banners/thank_you/styles/settings/_breakpoints.scss new file mode 100644 index 000000000..414a7e043 --- /dev/null +++ b/banners/thank_you/styles/settings/_breakpoints.scss @@ -0,0 +1,37 @@ +$breakpoint-xs: 440px; +$breakpoint-s: 750px; +$breakpoint-m: 1000px; +$breakpoint-l: 1400px; + +/* +MIXIN USAGE: +.my-selector { + @include breakpoints.small-up { + // Stuff that happens when bigger than $small + } +} +*/ + +@mixin x-small-up { + @media ( min-width: $breakpoint-xs ) { + @content; + } +} + +@mixin small-up { + @media ( min-width: $breakpoint-s ) { + @content; + } +} + +@mixin medium-up { + @media ( min-width: $breakpoint-m ) { + @content; + } +} + +@mixin large-up { + @media ( min-width: $breakpoint-l ) { + @content; + } +} diff --git a/banners/thank_you/styles/settings/_fonts.scss b/banners/thank_you/styles/settings/_fonts.scss new file mode 100644 index 000000000..c75d4f2e0 --- /dev/null +++ b/banners/thank_you/styles/settings/_fonts.scss @@ -0,0 +1,9 @@ +/* These font stacks come from: https://github.com/system-fonts/modern-font-stacks */ +$-neo-grotesque: 'Inter', 'Roboto', 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', 'Arial', sans-serif; +$-transitional: 'Iowan Old Style', 'Bitstream Charter', 'Sitka Text', 'Cambria', serif; + +/* This is used for all the ui text, buttons, inputs, labels etc */ +$ui: $-neo-grotesque !default; + +/* This is the font the for the copy and is only applied to the long form text */ +$content: $-transitional !default; diff --git a/banners/thank_you/styles/settings/_globals.scss b/banners/thank_you/styles/settings/_globals.scss new file mode 100644 index 000000000..4cdc3ef67 --- /dev/null +++ b/banners/thank_you/styles/settings/_globals.scss @@ -0,0 +1,4 @@ +/* This is the easing function that most of the banner transitions use */ +$banner-easing: cubic-bezier( 0.63, 0.155, 0.38, 0.885 ) !default; + +$banner-bg-gradient: linear-gradient( 135deg, rgba( 246, 246, 246 ) 0%, rgba( 246, 246, 246 ) 50%, rgba( 251, 251, 251 ) 50%, rgba( 251, 251, 251 ) 100% ); diff --git a/banners/thank_you/styles/settings/colors.ts b/banners/thank_you/styles/settings/colors.ts new file mode 100644 index 000000000..ce651318b --- /dev/null +++ b/banners/thank_you/styles/settings/colors.ts @@ -0,0 +1,12 @@ +export default { + '--color-white': '#ffffff', + '--color-off-white': '#efefef', + '--color-grey': '#bababa', + '--color-grey-dark': '#505050', + '--color-black': '#000000', + '--color-black-transparent': 'rgb( 0 0 0 / 60% )', + '--color-primary': '#ab150a', + '--color-primary-hover': '#9e1208', + '--color-secondary': '#6e9e00', + '--color-secondary-hover': '#669400' +}; diff --git a/banners/thank_you/styles/styles.scss b/banners/thank_you/styles/styles.scss new file mode 100644 index 000000000..46b5dd623 --- /dev/null +++ b/banners/thank_you/styles/styles.scss @@ -0,0 +1,12 @@ +@use 'src/components/BannerConductor/banner-transition'; +@use 'firework'; +@use 'Banner'; +@use 'ButtonClose'; +@use 'FullPageBanner'; +@use 'ImageWithCopyright'; +@use 'KeenSlider'; +@use 'MembershipBenefits'; +@use 'MembershipFormButton'; +@use 'MiniBanner'; +@use 'ProgressBar'; +@use 'StatsBox'; diff --git a/campaign_info_main.toml b/campaign_info_main.toml new file mode 100644 index 000000000..8a930e267 --- /dev/null +++ b/campaign_info_main.toml @@ -0,0 +1,244 @@ +# NOTE: The "pagename" value must start with an uppercase "B" and should be followed by the year (YY) and WMDE. +# Example: "B18WMDE_" +# See https://github.com/wmde/fundraising-infrastructure/wiki/How-to-manage-banners-on-de.wikipedia.org + +# A Campaign with global settings +[desktop] +name = "Desktop" +icon = "desktop" +campaign = "C23_WMDE_Desktop_DE_16" +description = "based on ctrl of test 15, variant has a donor heart" +campaign_tracking = "16-ba-231129" +preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE" + +# Banners of the campaign, key after "banners" can be anything +[desktop.banners.ctrl] +filename = "./banners/desktop/banner_ctrl.ts" +pagename = "B23_WMDE_Desktop_DE_16_ctrl" +tracking = "org-16-231129-ctrl" + +[desktop.banners.var] +filename = "./banners/desktop/banner_var.ts" +pagename = "B23_WMDE_Desktop_DE_16_var" +tracking = "org-16-231129-var" + +[desktop.test_matrix] +platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] +resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] + + +[mobile] +name = "Mobile" +icon = "mobile" +campaign = "C23_WMDE_Mobile_DE_11_2" +description = "based on ctrl 10, Var redirects users to the donation page with the amount button" +campaign_tracking = "mob-de-11-ba-231201" +preview_link = "/mobile/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype&useskin=minerva" +preview_url = 'https://de.m.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&useskin=minerva&devMode' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE" + +# Banners of the campaign, key after "banners" can be anything +[mobile.banners.ctrl] +filename = "./banners/mobile/banner_ctrl.ts" +pagename = "B23_WMDE_Mobile_DE_11_2_ctrl" +tracking = "org-mob11_2-231201-ctrl" + +[mobile.banners.var] +filename = "./banners/mobile/banner_var.ts" +pagename = "B23_WMDE_Mobile_DE_11_2_var" +tracking = "org-mob11_2-231201-var" + +[mobile.test_matrix] +device = [ 'samsung_s10', 'iphone_xs_max', 'iphone_5s', 'iphone_se', "iphone_8", "iphone_12_mini", "iphone_7_plus", "iphone_11_pro_max"] +orientation = [ "portrait", "landscape"] + + +[pad] +name = "iPad" +icon = "pad" +campaign = "C23_WMDE_iPad_01" +description = "VAR has payment logos" +campaign_tracking = "pad01-ba-231030" +preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE" + +[pad.banners.ctrl] +filename = "./banners/pad/banner_ctrl.ts" +pagename = "B23_WMDE_iPad_01_ctrl" +tracking = "org-pad01-231030-ctrl" + +[pad.banners.var] +filename = "./banners/pad/banner_var.ts" +pagename = "B23_WMDE_iPad_01_var" +tracking = "org-pad01-231030-var" + +[pad.test_matrix] +device = [ 'ipad_mini', 'ipad', 'ipad_pro_9_7_inch', 'ipad_pro_12_inch' ] +orientation = [ "portrait", "landscape"] + + + +[wikipediade] +name = "WPDE Desktop" +icon = "desktop" +campaign = "C23_WPDE_Desktop_01" +description = "VAR has translated WMF copy" +campaign_tracking = "wpde-01-231030" +preview_link = "/wikipedia.de?devbanner={{banner}}&banner=dev-mode-wpde" +wrapper_template = "wikipedia_de" +wrap_in_wikitext = false +preview_url = 'https://www.wikipedia.de/?banner={{banner}}' + +[wikipediade.banners.ctrl] +filename = "./banners/wpde_desktop/banner_ctrl.ts" +pagename = "B23_WPDE_Desktop_01_ctrl" +tracking = "wpde-01-231030-ctrl" + +[wikipediade.banners.var] +filename = "./banners/wpde_desktop/banner_var.ts" +pagename = "B23_WPDE_Desktop_01_var" +tracking = "wpde-01-231030-var" + + +[wikipediade_mobile] +name = "WPDE Mobile" +icon = "mobile" +campaign = "C23_WPDE_Mobile_01" +description = "Based on CRTL of WPDE_mob_01" +campaign_tracking = "wpde-mob01-231030" +preview_link = "/wikipedia.de?devbanner={{banner}}&banner=dev-mode-wpde" +wrapper_template = "wikipedia_de" +wrap_in_wikitext = false +preview_url = 'https://www.wikipedia.de/?banner={{banner}}' + +[wikipediade_mobile.banners.ctrl] +filename = "./banners/wpde_mobile/banner_ctrl.ts" +pagename = "B23_WPDE_Mobile_01_ctrl" +tracking = "wpde-mob01-231030-ctrl" + +[wikipediade_mobile.banners.var] +filename = "./banners/wpde_mobile/banner_var.ts" +pagename = "B23_WPDE_Mobile_01_var" +tracking = "wpde-mob01-231030-var" + + + +[english] +name = "English Desktop" +icon = "desktop" +campaign = "C23_WMDE_Desktop_EN_03" +description = "VAR has the WMF text" +campaign_tracking = "en03-ba-231120" +preview_link = "/wiki/Main_Page?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://en.wikipedia.org/wiki/Main_Page?banner={{banner}}&devMode' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" + +[english.banners.ctrl] +filename = "./banners/english/banner_ctrl.ts" +pagename = "B23_WMDE_Desktop_EN_03_ctrl" +tracking = "org-en03-231120-ctrl" + +[english.banners.var] +filename = "./banners/english/banner_var.ts" +pagename = "B23_WMDE_Desktop_EN_03_var" +tracking = "org-en03-231120-var" + +[english.test_matrix] +platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] +resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] + + + +[mobile_english] +name = "English Mobile" +icon = "mobile" +campaign = "C23_WMDE_Mobile_EN_01" +description = "Tab button VS interior button on mini banners" +campaign_tracking = "mob_en01-ba-231030" +preview_link = "/en-mobile/wiki/Main_Page?devbanner={{banner}}&useskin=minerva&banner=B22_WMDE_local_prototype" +preview_url = 'https://en.m.wikipedia.org/wiki/Main_Page?banner={{banner}}&devMode&useskin=minerva' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" + +[mobile_english.banners.ctrl] +filename = "./banners/mobile_english/banner_ctrl.ts" +pagename = "B23_WMDE_Mobile_EN_01_ctrl" +tracking = "org-mob_en01-231030-ctrl" + +[mobile_english.banners.var] +filename = "./banners/mobile_english/banner_var.ts" +pagename = "B23_WMDE_Mobile_EN_01_var" +tracking = "org-mob_en01-231030-var" + +[mobile_english.test_matrix] +device = [ 'samsung_s10', 'nexus_6', 'iphone_xs_max', 'iphone_5s', 'iphone_se', "iphone_8", "iphone_12_mini", "iphone_7_plus", "iphone_11_pro_max" ] +orientation = [ "portrait", "landscape" ] + + +[pad_en] +name = "English iPad" +icon = "pad" +campaign = "C23_WMDE_iPad_EN_00" +description = "VAR has soft close" +campaign_tracking = "en-ipad00-230426" +preview_link ='/wiki/Main_Page?devbanner={{banner}}&banner=B22_WMDE_local_prototype' +preview_url = 'https://en.wikipedia.org/wiki/Main_Page?banner={{banner}}&devMode' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" + +[pad_en.banners.ctrl] +filename = "./banners/pad_english/banner_ctrl.ts" +pagename = "B23_WMDE_iPad_EN_00_ctrl" +tracking = "org-en-ipad00-230501-ctrl" + +[pad_en.banners.var] +filename = "./banners/pad_english/banner_var.ts" +pagename = "B23_WMDE_iPad_EN_00_var" +tracking = "org-en-ipad00-230501-var" + +[pad_en.test_matrix] +device = [ 'ipad_mini', 'ipad', 'ipad_pro_9_7_inch', 'ipad_pro_12_inch'] +orientation = [ "portrait", "landscape"] + + +[thank_you] +name = "Thank you banner" +icon = "desktop" +campaign = "C23_Thank_You_00" +description = "Development campaign for thank you banner" +campaign_tracking = "ty-240101" +preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode' +wrapper_template = "wikipedia_org" +use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" + +[thank_you.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.de.ts" +pagename = "B23_WMDE_Thank_You_DE_00_ctrl" +tracking = "org-ty00-240101-ctrl" + +[thank_you.banners.var] +filename = "./banners/thank_you/banner_var.de.ts" +pagename = "B23_WMDE_Thank_You_DE_00_var" +tracking = "org-ty00-240101-var" + +[thank_you.banners.ctrl_en] +filename = "./banners/thank_you/banner_ctrl.en.ts" +pagename = "B23_WMDE_Thank_You_EN_00_ctrl" +tracking = "org-en-ty00-240101-ctrl" + +[thank_you.banners.var_en] +filename = "./banners/thank_you/banner_var.en.ts" +pagename = "B23_WMDE_Thank_You_EN_00_var" +tracking = "org-en-ty00-240101-var" + +[thank_you.test_matrix] +platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] +resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] diff --git a/docs/Use-of-Funds-integration.md b/docs/Use-of-Funds-integration.md index c7ffdeca7..a705a741c 100644 --- a/docs/Use-of-Funds-integration.md +++ b/docs/Use-of-Funds-integration.md @@ -24,7 +24,7 @@ Each year, create two new pages on meta.wikipedia.org, one for English and one f * https://meta.wikimedia.org/wiki/MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE * https://meta.wikimedia.org/wiki/MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN -To use different pages, change the setting `use_of_funds_source` in the file [`campaigns_info.toml`](../campaign_info.toml). +To use different pages, change the setting `use_of_funds_source` in the file [`campaigns_info.toml`](../campaign_info_main.toml). ## Initializing the loader class in the entry points diff --git a/src/tracking/TrackingEvent.ts b/src/tracking/TrackingEvent.ts index ed9b2f1c6..5df7e9cce 100644 --- a/src/tracking/TrackingEvent.ts +++ b/src/tracking/TrackingEvent.ts @@ -16,7 +16,9 @@ export type TrackingFeatureName = '' | 'CustomAmountForm' | 'UpgradeToYearlyForm' | 'UpgradeToMonthlyForm' | - 'AddressTypeForm'; + 'AddressTypeForm' | + + 'ThankYouBanner'; /** * @param T - Defines the type of the customData property diff --git a/src/tracking/events/ThankYouModalShownEvent.ts b/src/tracking/events/ThankYouModalShownEvent.ts new file mode 100644 index 000000000..844f9f7d9 --- /dev/null +++ b/src/tracking/events/ThankYouModalShownEvent.ts @@ -0,0 +1,10 @@ +import { TrackingEvent, TrackingFeatureName } from '@src/tracking/TrackingEvent'; + +export class ThankYouModalShownEvent implements TrackingEvent { + public static readonly EVENT_NAME = 'thank-you-modal-shown'; + + public readonly eventName = ThankYouModalShownEvent.EVENT_NAME; + public readonly customData: void; + public readonly feature: TrackingFeatureName = 'ThankYouBanner'; + public readonly userChoice: string = ''; +} diff --git a/test/banners/thank_you/components/BannerCtrl.de.spec.ts b/test/banners/thank_you/components/BannerCtrl.de.spec.ts new file mode 100644 index 000000000..bc6502d62 --- /dev/null +++ b/test/banners/thank_you/components/BannerCtrl.de.spec.ts @@ -0,0 +1,106 @@ +import { describe, expect, it, vi } from 'vitest'; +import { mount, VueWrapper } from '@vue/test-utils'; +import { CloseEvent } from '@src/tracking/events/CloseEvent'; +import { CloseChoices } from '@src/domain/CloseChoices'; +import BannerCtrl from '../../../../banners/thank_you/components/BannerCtrl.de.vue'; +import { Tracker } from '@src/tracking/Tracker'; +import { ThankYouModalShownEvent } from '@src/tracking/events/ThankYouModalShownEvent'; +import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent'; +import { MembershipFormActions } from '../../../../banners/thank_you/MembershipFormActions'; + +const formActions: MembershipFormActions = { + create: ( extraUrlParameters: Record ) => `URL [ ${ extraUrlParameters?.interval }, ${ extraUrlParameters?.fee } ]` +}; + +describe( 'BannerCtrl.de.vue', () => { + let tracker: Tracker; + + const getWrapper = (): VueWrapper => { + tracker = { trackEvent: vi.fn() }; + return mount( BannerCtrl, { + props: { + progressBarFillPercentage: 80, + subscribeURL: 'SUBSCRIBE URL' + }, + global: { + mocks: { + $translate: ( key: string ): string => key + }, + provide: { + tracker: tracker, + formActions + } + } + } ); + }; + + it( 'emits close event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-close' ).trigger( 'click' ); + + expect( wrapper.emitted( 'bannerClosed' ).length ).toStrictEqual( 1 ); + expect( wrapper.emitted( 'bannerClosed' )[ 0 ][ 0 ] ).toStrictEqual( new CloseEvent( 'MainBanner', CloseChoices.Close ) ); + } ); + + it( 'emits modal shown event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-button' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toHaveBeenCalledOnce(); + expect( tracker.trackEvent ).toHaveBeenCalledWith( new ThankYouModalShownEvent() ); + } ); + + it( 'sets progress bar fill percentage on slider', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 750 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'sets progress bar fill percentage on text', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 751 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'redirects when membership buttons are clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ 1, 200 ]' ); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ undefined, undefined ]' ); + } ); + + it( 'tracks when membership buttons are clicked', async () => { + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: { href: '' } } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toBeCalledTimes( 2 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'with-amount-2' ) ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'without-amount' ) ); + } ); + + it( 'tracks and redirects when subscribe link is clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-subscribe a' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'SUBSCRIBE URL' ); + expect( tracker.trackEvent ).toBeCalledTimes( 1 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'subscribe' ) ); + } ); +} ); diff --git a/test/banners/thank_you/components/BannerCtrl.en.spec.ts b/test/banners/thank_you/components/BannerCtrl.en.spec.ts new file mode 100644 index 000000000..0d32220c6 --- /dev/null +++ b/test/banners/thank_you/components/BannerCtrl.en.spec.ts @@ -0,0 +1,106 @@ +import { describe, expect, it, vi } from 'vitest'; +import { mount, VueWrapper } from '@vue/test-utils'; +import { CloseEvent } from '@src/tracking/events/CloseEvent'; +import { CloseChoices } from '@src/domain/CloseChoices'; +import BannerCtrl from '../../../../banners/thank_you/components/BannerCtrl.en.vue'; +import { Tracker } from '@src/tracking/Tracker'; +import { ThankYouModalShownEvent } from '@src/tracking/events/ThankYouModalShownEvent'; +import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent'; +import { MembershipFormActions } from '../../../../banners/thank_you/MembershipFormActions'; + +const formActions: MembershipFormActions = { + create: ( extraUrlParameters: Record ) => `URL [ ${ extraUrlParameters?.interval }, ${ extraUrlParameters?.fee } ]` +}; + +describe( 'BannerCtrl.en.vue', () => { + let tracker: Tracker; + + const getWrapper = (): VueWrapper => { + tracker = { trackEvent: vi.fn() }; + return mount( BannerCtrl, { + props: { + progressBarFillPercentage: 80, + subscribeURL: 'SUBSCRIBE URL' + }, + global: { + mocks: { + $translate: ( key: string ): string => key + }, + provide: { + tracker: tracker, + formActions + } + } + } ); + }; + + it( 'emits close event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-close' ).trigger( 'click' ); + + expect( wrapper.emitted( 'bannerClosed' ).length ).toStrictEqual( 1 ); + expect( wrapper.emitted( 'bannerClosed' )[ 0 ][ 0 ] ).toStrictEqual( new CloseEvent( 'MainBanner', CloseChoices.Close ) ); + } ); + + it( 'emits modal shown event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-button' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toHaveBeenCalledOnce(); + expect( tracker.trackEvent ).toHaveBeenCalledWith( new ThankYouModalShownEvent() ); + } ); + + it( 'sets progress bar fill percentage on slider', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 750 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'sets progress bar fill percentage on text', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 751 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'redirects when membership buttons are clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ 1, 200 ]' ); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ undefined, undefined ]' ); + } ); + + it( 'tracks when membership buttons are clicked', async () => { + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: { href: '' } } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toBeCalledTimes( 2 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'with-amount-2' ) ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'without-amount' ) ); + } ); + + it( 'tracks and redirects when subscribe link is clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-subscribe a' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'SUBSCRIBE URL' ); + expect( tracker.trackEvent ).toBeCalledTimes( 1 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'subscribe' ) ); + } ); +} ); diff --git a/test/banners/thank_you/components/BannerVar.de.spec.ts b/test/banners/thank_you/components/BannerVar.de.spec.ts new file mode 100644 index 000000000..ea5c32590 --- /dev/null +++ b/test/banners/thank_you/components/BannerVar.de.spec.ts @@ -0,0 +1,112 @@ +import { describe, expect, it, vi } from 'vitest'; +import { mount, VueWrapper } from '@vue/test-utils'; +import { CloseEvent } from '@src/tracking/events/CloseEvent'; +import { CloseChoices } from '@src/domain/CloseChoices'; +import BannerCtrl from '../../../../banners/thank_you/components/BannerVar.de.vue'; +import { Tracker } from '@src/tracking/Tracker'; +import { ThankYouModalShownEvent } from '@src/tracking/events/ThankYouModalShownEvent'; +import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent'; +import { MembershipFormActions } from '../../../../banners/thank_you/MembershipFormActions'; + +const formActions: MembershipFormActions = { + create: ( extraUrlParameters: Record ) => `URL [ ${ extraUrlParameters?.interval }, ${ extraUrlParameters?.fee } ]` +}; + +describe( 'BannerVar.de.vue', () => { + let tracker: Tracker; + + const getWrapper = (): VueWrapper => { + tracker = { trackEvent: vi.fn() }; + return mount( BannerCtrl, { + props: { + progressBarFillPercentage: 80, + subscribeURL: 'SUBSCRIBE URL' + }, + global: { + mocks: { + $translate: ( key: string ): string => key + }, + provide: { + tracker: tracker, + formActions + } + } + } ); + }; + + it( 'emits close event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-close' ).trigger( 'click' ); + + expect( wrapper.emitted( 'bannerClosed' ).length ).toStrictEqual( 1 ); + expect( wrapper.emitted( 'bannerClosed' )[ 0 ][ 0 ] ).toStrictEqual( new CloseEvent( 'MainBanner', CloseChoices.Close ) ); + } ); + + it( 'emits modal shown event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-button' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toHaveBeenCalledOnce(); + expect( tracker.trackEvent ).toHaveBeenCalledWith( new ThankYouModalShownEvent() ); + } ); + + it( 'sets progress bar fill percentage on slider', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 750 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'sets progress bar fill percentage on text', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 751 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'redirects when membership buttons are clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ 1, 200 ]' ); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:nth-child( 2 )' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ 1, 500 ]' ); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ undefined, undefined ]' ); + } ); + + it( 'tracks when membership buttons are clicked', async () => { + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: { href: '' } } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:nth-child( 2 )' ).trigger( 'click' ); + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toBeCalledTimes( 3 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'with-amount-2' ) ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'with-amount-5' ) ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'without-amount' ) ); + } ); + + it( 'tracks and redirects when subscribe link is clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-subscribe a' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'SUBSCRIBE URL' ); + expect( tracker.trackEvent ).toBeCalledTimes( 1 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'subscribe' ) ); + } ); +} ); diff --git a/test/banners/thank_you/components/BannerVar.en.spec.ts b/test/banners/thank_you/components/BannerVar.en.spec.ts new file mode 100644 index 000000000..f7f859d66 --- /dev/null +++ b/test/banners/thank_you/components/BannerVar.en.spec.ts @@ -0,0 +1,112 @@ +import { describe, expect, it, vi } from 'vitest'; +import { mount, VueWrapper } from '@vue/test-utils'; +import { CloseEvent } from '@src/tracking/events/CloseEvent'; +import { CloseChoices } from '@src/domain/CloseChoices'; +import BannerCtrl from '../../../../banners/thank_you/components/BannerVar.en.vue'; +import { Tracker } from '@src/tracking/Tracker'; +import { ThankYouModalShownEvent } from '@src/tracking/events/ThankYouModalShownEvent'; +import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent'; +import { MembershipFormActions } from '../../../../banners/thank_you/MembershipFormActions'; + +const formActions: MembershipFormActions = { + create: ( extraUrlParameters: Record ) => `URL [ ${ extraUrlParameters?.interval }, ${ extraUrlParameters?.fee } ]` +}; + +describe( 'BannerVar.en.vue', () => { + let tracker: Tracker; + + const getWrapper = (): VueWrapper => { + tracker = { trackEvent: vi.fn() }; + return mount( BannerCtrl, { + props: { + progressBarFillPercentage: 80, + subscribeURL: 'SUBSCRIBE URL' + }, + global: { + mocks: { + $translate: ( key: string ): string => key + }, + provide: { + tracker: tracker, + formActions + } + } + } ); + }; + + it( 'emits close event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-close' ).trigger( 'click' ); + + expect( wrapper.emitted( 'bannerClosed' ).length ).toStrictEqual( 1 ); + expect( wrapper.emitted( 'bannerClosed' )[ 0 ][ 0 ] ).toStrictEqual( new CloseEvent( 'MainBanner', CloseChoices.Close ) ); + } ); + + it( 'emits modal shown event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-button' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toHaveBeenCalledOnce(); + expect( tracker.trackEvent ).toHaveBeenCalledWith( new ThankYouModalShownEvent() ); + } ); + + it( 'sets progress bar fill percentage on slider', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 750 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'sets progress bar fill percentage on text', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 751 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-progress-bar' ).attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 80%;' ); + } ); + + it( 'redirects when membership buttons are clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ 1, 200 ]' ); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:nth-child( 2 )' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ 1, 500 ]' ); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'URL [ undefined, undefined ]' ); + } ); + + it( 'tracks when membership buttons are clicked', async () => { + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: { href: '' } } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:first-child' ).trigger( 'click' ); + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:nth-child( 2 )' ).trigger( 'click' ); + await wrapper.find( '.wmde-banner-full-cta-buttons .wmde-banner-button:last-child' ).trigger( 'click' ); + + expect( tracker.trackEvent ).toBeCalledTimes( 3 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'with-amount-2' ) ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'with-amount-5' ) ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'without-amount' ) ); + } ); + + it( 'tracks and redirects when subscribe link is clicked', async () => { + const location = { href: '' }; + Object.defineProperty( window, 'location', { writable: true, configurable: true, value: location } ); + const wrapper = getWrapper(); + + await wrapper.find( '.wmde-banner-full-subscribe a' ).trigger( 'click' ); + + expect( location.href ).toStrictEqual( 'SUBSCRIBE URL' ); + expect( tracker.trackEvent ).toBeCalledTimes( 1 ); + expect( tracker.trackEvent ).toBeCalledWith( new BannerSubmitEvent( 'ThankYouBanner', 'subscribe' ) ); + } ); +} ); diff --git a/test/banners/thank_you/components/FullPageBanner.spec.ts b/test/banners/thank_you/components/FullPageBanner.spec.ts new file mode 100644 index 000000000..beaf0f3e8 --- /dev/null +++ b/test/banners/thank_you/components/FullPageBanner.spec.ts @@ -0,0 +1,31 @@ +import { describe, expect, it, vi } from 'vitest'; +import { mount, VueWrapper } from '@vue/test-utils'; +import FullPageBanner from '../../../../banners/thank_you/components/FullPageBanner.vue'; +import { Tracker } from '@src/tracking/Tracker'; + +describe( 'FullPageBanner.vue', () => { + let tracker: Tracker; + + const getWrapper = (): VueWrapper => { + tracker = { trackEvent: vi.fn() }; + return mount( FullPageBanner, { + global: { + mocks: { + $translate: ( key: string ): string => key + }, + provide: { + subscribeURL: 'SUBSCRIBE URL', + tracker + } + } + } ); + }; + + it( 'emits close event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-close' ).trigger( 'click' ); + + expect( wrapper.emitted( 'close' ).length ).toStrictEqual( 1 ); + } ); +} ); diff --git a/test/banners/thank_you/components/MembershipButton.spec.ts b/test/banners/thank_you/components/MembershipButton.spec.ts new file mode 100644 index 000000000..74fb3b503 --- /dev/null +++ b/test/banners/thank_you/components/MembershipButton.spec.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from 'vitest'; +import { shallowMount } from '@vue/test-utils'; +import MembershipButton from '../../../../banners/thank_you/components/MembershipButton.vue'; +import { MembershipFormActions } from '../../../../banners/thank_you/MembershipFormActions'; + +const formActions: MembershipFormActions = { + create: ( extraUrlParameters: Record ) => `URL ${ extraUrlParameters.nananana }` +}; + +describe( 'MembershipButton.vue', () => { + it( 'emits submit event', () => { + const wrapper = shallowMount( MembershipButton, { + props: { + label: 'SAME BAT TIME', + extraUrlParameters: { nananana: 'batman' } + }, + global: { + provide: { formActions } + } + } ); + + wrapper.trigger( 'click' ); + + expect( wrapper.emitted( 'submit' ).length ).toStrictEqual( 1 ); + expect( wrapper.emitted( 'submit' )[ 0 ][ 0 ] ).toStrictEqual( 'URL batman' ); + } ); +} ); diff --git a/test/banners/thank_you/components/MiniBanner.spec.ts b/test/banners/thank_you/components/MiniBanner.spec.ts new file mode 100644 index 000000000..ba92e4c2c --- /dev/null +++ b/test/banners/thank_you/components/MiniBanner.spec.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from 'vitest'; +import { mount, VueWrapper } from '@vue/test-utils'; +import MiniBanner from '../../../../banners/thank_you/components/MiniBanner.vue'; + +describe( 'MiniBanner.vue', () => { + + const getWrapper = (): VueWrapper => { + return mount( MiniBanner, { + props: { + progressbarFillPercentage: 42 + }, + global: { + mocks: { + $translate: ( key: string ): string => key + } + } + } ); + }; + + it( 'shows slider content on small screens', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 750 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-mini-slider' ).exists() ).toBeTruthy(); + expect( wrapper.find( '.wmde-banner-mini-text' ).exists() ).toBeFalsy(); + } ); + + it( 'shows slider content on big screens', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 751 } ); + const wrapper = getWrapper(); + + expect( wrapper.find( '.wmde-banner-mini-text' ).exists() ).toBeTruthy(); + expect( wrapper.find( '.wmde-banner-mini-slider' ).exists() ).toBeFalsy(); + } ); + + it( 'emits showModal events from slider content', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 750 } ); + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-mini-inner' ).trigger( 'click' ); + wrapper.find( '.wmde-banner-button' ).trigger( 'click' ); + + expect( wrapper.emitted( 'showModal' ).length ).toStrictEqual( 2 ); + } ); + + it( 'emits showModal events from text content', () => { + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 751 } ); + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-mini-inner' ).trigger( 'click' ); + wrapper.find( '.wmde-banner-button' ).trigger( 'click' ); + + expect( wrapper.emitted( 'showModal' ).length ).toStrictEqual( 2 ); + } ); + + it( 'emits close event', () => { + const wrapper = getWrapper(); + + wrapper.find( '.wmde-banner-close' ).trigger( 'click' ); + + expect( wrapper.emitted( 'close' ).length ).toStrictEqual( 1 ); + } ); +} ); diff --git a/test/banners/thank_you/components/ProgressBar.spec.ts b/test/banners/thank_you/components/ProgressBar.spec.ts new file mode 100644 index 000000000..b05f87f3d --- /dev/null +++ b/test/banners/thank_you/components/ProgressBar.spec.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from 'vitest'; +import { shallowMount, VueWrapper } from '@vue/test-utils'; +import ProgressBar from '../../../../banners/thank_you/components/ProgressBar.vue'; + +describe( 'ProgressBar.vue', () => { + + const getWrapper = ( fillPercentage: number ): VueWrapper => { + return shallowMount( ProgressBar, { + props: { + fillPercentage + }, + global: { + mocks: { + $translate: ( key: string ): string => key + } + } + } ); + }; + + it( 'shows the win content', () => { + const wrapper = getWrapper( 100 ); + + expect( wrapper.attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 100%;' ); + expect( wrapper.find( '.wmde-banner-progress-bar-fill-text' ).text() ).toStrictEqual( 'progress-bar-inner-text-win' ); + } ); + + it( 'shows the lose content', () => { + const wrapper = getWrapper( 66 ); + + expect( wrapper.attributes( 'style' ) ).toStrictEqual( '--wmde-banner-progress-bar-width: 66%;' ); + expect( wrapper.find( '.wmde-banner-progress-bar-fill-text' ).text() ).toStrictEqual( 'progress-bar-inner-text-lose' ); + } ); +} ); From 3c78e17c0c9baa311ef2e080cba273ff7017242a Mon Sep 17 00:00:00 2001 From: Gabriel Birke Date: Thu, 14 Dec 2023 19:06:44 +0100 Subject: [PATCH 02/15] Add dev and build scripts for thank you banners Make `campaign_info.toml` with fundraising banners the default again, reverting the previous edit to the documentation. Add `campaign_info.thank_you.toml` Modify Webpack configuration to check for `env.campaign_info` parameter, use `campaign_info.toml` as the default Add two new `npm` scripts for running a special "thank you" dev environment and building the thank you banners Move file reading code to CampaignConfig class Adapt README to document the thank you functionality --- README.md | 11 ++ campaign_info.thank_you.toml | 171 ++++++++++++++++++++++ campaign_info_main.toml | 244 ------------------------------- docs/Use-of-Funds-integration.md | 2 +- package.json | 2 + webpack.common.js | 148 +++++++++---------- webpack.config.js | 9 +- webpack.production.js | 5 +- webpack/campaign_config.js | 7 + 9 files changed, 273 insertions(+), 326 deletions(-) create mode 100644 campaign_info.thank_you.toml delete mode 100644 campaign_info_main.toml diff --git a/README.md b/README.md index c75a9ee59..4744b3c54 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,17 @@ tracking pixels inside the banner. 1. Duplicate an existing folder with banner entry points, e.g. `banners/desktop`. 2. Create a new campaign and its banner configuration in `campaign_info.toml`. +## Developing and building "thank you" banners + +The "thank you" banners have a special configuration file, `campaign_info.thank_you.toml`. +Edit this file for the necessary campaign and tracking parameters. + +To use this file instead of the standard `campaign_info.toml` file, run `npm run thankyou` instead of `npm run dev`. +This environment does *not* use `nodemon` to watch for changes in `campaign_info.thank_you.toml`. +If you change that file or one of the webpack configuration files, you need to restart the server. + +To build the "thank you" banners, run `npm run build:thankyou` instead of `npm run build`. + ### Creating A/B tests TODO: Rewrite this section for different types of tests (text changes, diff --git a/campaign_info.thank_you.toml b/campaign_info.thank_you.toml new file mode 100644 index 000000000..97d147077 --- /dev/null +++ b/campaign_info.thank_you.toml @@ -0,0 +1,171 @@ +# Example: "B18WMDE_" +# See https://github.com/wmde/fundraising-infrastructure/wiki/How-to-manage-banners-on-de.wikipedia.org + + +# Thank You Campaign +[thank_you] +name = "Desktop" +campaign = "C23_WMDE_Thank_You_DE_00" +icon = "desktop" +campaign_tracking = "ty01-240101" +description = "Thank you banner" +preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_org" + +[thank_you.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.de.ts" +pagename = "B23_WMDE_Thank_You_Desktop_DE_ctrl" +tracking = "org-ty-240101-ctrl" + +[thank_you.banners.var] +filename = "./banners/thank_you/banner_var.de.ts" +pagename = "B23_WMDE_Thank_You_Desktop_DE_var" +tracking = "org-ty-240101-var" + +[thank_you.test_matrix] +platform = ["edge", "ie11", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] +resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] + + +[thank_you_en] +name = "English Desktop" +campaign = "C23_WMDE_Thank_You_Desktop_EN_00" +icon = "desktop" +campaign_tracking = "ty01-240101" +description = "Thank you banner" +preview_link = "/wiki/Main_Page?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://en.wikipedia.org/wiki/Main_Page?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_org" + +[thank_you_en.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.en.ts" +pagename = "B23_WMDE_Thank_You_Desktop_EN_ctrl" +tracking = "org-ty-240101-en-ctrl" + +[thank_you_en.banners.var] +filename = "./banners/thank_you/banner_var.en.ts" +pagename = "B23_WMDE_Thank_You_Desktop_EN_var" +tracking = "org-ty-240101-en-var" + +[thank_you_en.test_matrix] +platform = ["edge", "ie11", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] +resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] + +# Thank you campaign mobile wp.org +[thank_you_mobile] +name = "Mobile" +campaign = "C23_WMDE_Thank_You_Mobile_DE_00" +icon = "mobile" +campaign_tracking = "ty01-mob-240101" +description = "Thank you banner" +preview_link = "/mobile/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&useskin=minerva&banner=B22_WMDE_local_prototype" +preview_url = 'https://de.m.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_org" + +[thank_you_mobile.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.de.ts" +pagename = "B23_WMDE_Thank_You_Mobile_DE_ctrl" +tracking = "org-mob-ty-240101-ctrl" + +[thank_you_mobile.banners.var] +filename = "./banners/thank_you/banner_var.de.ts" +pagename = "B23_WMDE_Thank_You_Mobile_DE_var" +tracking = "org-mob-ty-240101-var" + +[thank_you_mobile.test_matrix] +device = [ 'samsung_s10', 'iphone_xs_max', 'iphone_5s', 'iphone_se', "iphone_8", "iphone_12_mini", "iphone_7_plus", "iphone_11_pro_max"] +orientation = [ "portrait", "landscape"] + +# English Thank you campaign mobile wp.org +[thank_you_mobile_en] +name = "English Mobile" +campaign = "C23_WMDE_Thank_You_Mobile_EN_00" +icon = "mobile" +campaign_tracking = "ty01-mob-en-240101" +description = "Thank you banner" +preview_link = "/en-mobile/wiki/Main_Page?devbanner={{banner}}&useskin=minerva&banner=B22_WMDE_local_prototype" +preview_url = 'https://en.m.wikipedia.org/wiki/Main_Page?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_org" + +[thank_you_mobile_en.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.en.ts" +pagename = "B23_WMDE_Thank_You_Mobile_EN_ctrl" +tracking = "org-mob-ty-240101-en-ctrl" + +[thank_you_mobile_en.banners.var] +filename = "./banners/thank_you/banner_var.en.ts" +pagename = "B23_WMDE_Thank_You_Mobile_EN_var" +tracking = "org-mob-ty-240101-en-var" + +[thank_you_mobile_en.test_matrix] +device = [ 'samsung_s10', 'iphone_xs_max', 'iphone_5s', 'iphone_se', "iphone_8", "iphone_12_mini", "iphone_7_plus", "iphone_11_pro_max"] +orientation = [ "portrait", "landscape"] + +# Thank you campaign ipad wp.org +[thank_you_ipad] +name = "iPad" +campaign = "C23_WMDE_Thank_You_iPad_00" +icon = "pad" +campaign_tracking = "ty01-ipad-240101" +description = "Thank you banner" +preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" +preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_org" + +[thank_you_ipad.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.de.ts" +pagename = "B23_WMDE_Thank_You_iPad_ctrl" +tracking = "org-ipad-ty-240101-ctrl" + +[thank_you_ipad.banners.var] +filename = "./banners/thank_you/banner_var.de.ts" +pagename = "B23_WMDE_Thank_You_iPad_var" +tracking = "org-ipad-ty-240101-var" + +[thank_you_ipad.test_matrix] +device = [ 'ipad_mini', 'ipad', 'ipad_pro_9_7_inch', 'ipad_pro_12_inch' ] +orientation = [ "portrait", "landscape"] + +# Thank you campaign wp.de +[thank_you_wpde] +campaign = "WPDE Desktop" +name = "C23_WPDE_Thank_You_Desktop_00" +icon = "desktop" +campaign_tracking = "ty01-wpde-240101" +description = "Thank you banner" +preview_link = "/wikipedia.de?devbanner={{banner}}&banner=dev-mode-wpde" +preview_url = 'https://www.wikipedia.de/?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_de" +wrap_in_wikitext = false + +[thank_you_wpde.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.wpde.ts" +pagename = "B23_WPDE_Thank_You_Desktop_ctrl" +tracking = "de-wpde-ty-240101-ctrl" + +[thank_you_wpde.banners.var] +filename = "./banners/thank_you/banner_var.wpde.ts" +pagename = "B23_WPDE_Thank_You_Desktop_var" +tracking = "de-wpde-ty-240101-var" + +[thank_you_wpde_mobile] +campaign = "WPDE Mobile" +name = "C23_WPDE_Thank_You_Mobile_00" +icon = "mobile" +campaign_tracking = "ty01-wpde-mob-240101" +description = "Thank you banner" +preview_link = "/wikipedia.de?devbanner={{banner}}&banner=dev-mode-wpde" +preview_url = 'https://www.wikipedia.de/?banner={{PLACEHOLDER}}' +wrapper_template = "wikipedia_de" +wrap_in_wikitext = false + +[thank_you_wpde_mobile.banners.ctrl] +filename = "./banners/thank_you/banner_ctrl.wpde.ts" +pagename = "B23_WPDE_Thank_You_Mobile_ctrl" +tracking = "de-wpde-mob-ty-240101-ctrl" + +[thank_you_wpde_mobile.banners.var] +filename = "./banners/thank_you/banner_var.wpde.ts" +pagename = "B23_WPDE_Thank_You_Mobile_var" +tracking = "de-wpde-mob-ty-240101-var" diff --git a/campaign_info_main.toml b/campaign_info_main.toml deleted file mode 100644 index 8a930e267..000000000 --- a/campaign_info_main.toml +++ /dev/null @@ -1,244 +0,0 @@ -# NOTE: The "pagename" value must start with an uppercase "B" and should be followed by the year (YY) and WMDE. -# Example: "B18WMDE_" -# See https://github.com/wmde/fundraising-infrastructure/wiki/How-to-manage-banners-on-de.wikipedia.org - -# A Campaign with global settings -[desktop] -name = "Desktop" -icon = "desktop" -campaign = "C23_WMDE_Desktop_DE_16" -description = "based on ctrl of test 15, variant has a donor heart" -campaign_tracking = "16-ba-231129" -preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" -preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE" - -# Banners of the campaign, key after "banners" can be anything -[desktop.banners.ctrl] -filename = "./banners/desktop/banner_ctrl.ts" -pagename = "B23_WMDE_Desktop_DE_16_ctrl" -tracking = "org-16-231129-ctrl" - -[desktop.banners.var] -filename = "./banners/desktop/banner_var.ts" -pagename = "B23_WMDE_Desktop_DE_16_var" -tracking = "org-16-231129-var" - -[desktop.test_matrix] -platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] -resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] - - -[mobile] -name = "Mobile" -icon = "mobile" -campaign = "C23_WMDE_Mobile_DE_11_2" -description = "based on ctrl 10, Var redirects users to the donation page with the amount button" -campaign_tracking = "mob-de-11-ba-231201" -preview_link = "/mobile/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype&useskin=minerva" -preview_url = 'https://de.m.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&useskin=minerva&devMode' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE" - -# Banners of the campaign, key after "banners" can be anything -[mobile.banners.ctrl] -filename = "./banners/mobile/banner_ctrl.ts" -pagename = "B23_WMDE_Mobile_DE_11_2_ctrl" -tracking = "org-mob11_2-231201-ctrl" - -[mobile.banners.var] -filename = "./banners/mobile/banner_var.ts" -pagename = "B23_WMDE_Mobile_DE_11_2_var" -tracking = "org-mob11_2-231201-var" - -[mobile.test_matrix] -device = [ 'samsung_s10', 'iphone_xs_max', 'iphone_5s', 'iphone_se', "iphone_8", "iphone_12_mini", "iphone_7_plus", "iphone_11_pro_max"] -orientation = [ "portrait", "landscape"] - - -[pad] -name = "iPad" -icon = "pad" -campaign = "C23_WMDE_iPad_01" -description = "VAR has payment logos" -campaign_tracking = "pad01-ba-231030" -preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" -preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE" - -[pad.banners.ctrl] -filename = "./banners/pad/banner_ctrl.ts" -pagename = "B23_WMDE_iPad_01_ctrl" -tracking = "org-pad01-231030-ctrl" - -[pad.banners.var] -filename = "./banners/pad/banner_var.ts" -pagename = "B23_WMDE_iPad_01_var" -tracking = "org-pad01-231030-var" - -[pad.test_matrix] -device = [ 'ipad_mini', 'ipad', 'ipad_pro_9_7_inch', 'ipad_pro_12_inch' ] -orientation = [ "portrait", "landscape"] - - - -[wikipediade] -name = "WPDE Desktop" -icon = "desktop" -campaign = "C23_WPDE_Desktop_01" -description = "VAR has translated WMF copy" -campaign_tracking = "wpde-01-231030" -preview_link = "/wikipedia.de?devbanner={{banner}}&banner=dev-mode-wpde" -wrapper_template = "wikipedia_de" -wrap_in_wikitext = false -preview_url = 'https://www.wikipedia.de/?banner={{banner}}' - -[wikipediade.banners.ctrl] -filename = "./banners/wpde_desktop/banner_ctrl.ts" -pagename = "B23_WPDE_Desktop_01_ctrl" -tracking = "wpde-01-231030-ctrl" - -[wikipediade.banners.var] -filename = "./banners/wpde_desktop/banner_var.ts" -pagename = "B23_WPDE_Desktop_01_var" -tracking = "wpde-01-231030-var" - - -[wikipediade_mobile] -name = "WPDE Mobile" -icon = "mobile" -campaign = "C23_WPDE_Mobile_01" -description = "Based on CRTL of WPDE_mob_01" -campaign_tracking = "wpde-mob01-231030" -preview_link = "/wikipedia.de?devbanner={{banner}}&banner=dev-mode-wpde" -wrapper_template = "wikipedia_de" -wrap_in_wikitext = false -preview_url = 'https://www.wikipedia.de/?banner={{banner}}' - -[wikipediade_mobile.banners.ctrl] -filename = "./banners/wpde_mobile/banner_ctrl.ts" -pagename = "B23_WPDE_Mobile_01_ctrl" -tracking = "wpde-mob01-231030-ctrl" - -[wikipediade_mobile.banners.var] -filename = "./banners/wpde_mobile/banner_var.ts" -pagename = "B23_WPDE_Mobile_01_var" -tracking = "wpde-mob01-231030-var" - - - -[english] -name = "English Desktop" -icon = "desktop" -campaign = "C23_WMDE_Desktop_EN_03" -description = "VAR has the WMF text" -campaign_tracking = "en03-ba-231120" -preview_link = "/wiki/Main_Page?devbanner={{banner}}&banner=B22_WMDE_local_prototype" -preview_url = 'https://en.wikipedia.org/wiki/Main_Page?banner={{banner}}&devMode' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" - -[english.banners.ctrl] -filename = "./banners/english/banner_ctrl.ts" -pagename = "B23_WMDE_Desktop_EN_03_ctrl" -tracking = "org-en03-231120-ctrl" - -[english.banners.var] -filename = "./banners/english/banner_var.ts" -pagename = "B23_WMDE_Desktop_EN_03_var" -tracking = "org-en03-231120-var" - -[english.test_matrix] -platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] -resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] - - - -[mobile_english] -name = "English Mobile" -icon = "mobile" -campaign = "C23_WMDE_Mobile_EN_01" -description = "Tab button VS interior button on mini banners" -campaign_tracking = "mob_en01-ba-231030" -preview_link = "/en-mobile/wiki/Main_Page?devbanner={{banner}}&useskin=minerva&banner=B22_WMDE_local_prototype" -preview_url = 'https://en.m.wikipedia.org/wiki/Main_Page?banner={{banner}}&devMode&useskin=minerva' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" - -[mobile_english.banners.ctrl] -filename = "./banners/mobile_english/banner_ctrl.ts" -pagename = "B23_WMDE_Mobile_EN_01_ctrl" -tracking = "org-mob_en01-231030-ctrl" - -[mobile_english.banners.var] -filename = "./banners/mobile_english/banner_var.ts" -pagename = "B23_WMDE_Mobile_EN_01_var" -tracking = "org-mob_en01-231030-var" - -[mobile_english.test_matrix] -device = [ 'samsung_s10', 'nexus_6', 'iphone_xs_max', 'iphone_5s', 'iphone_se', "iphone_8", "iphone_12_mini", "iphone_7_plus", "iphone_11_pro_max" ] -orientation = [ "portrait", "landscape" ] - - -[pad_en] -name = "English iPad" -icon = "pad" -campaign = "C23_WMDE_iPad_EN_00" -description = "VAR has soft close" -campaign_tracking = "en-ipad00-230426" -preview_link ='/wiki/Main_Page?devbanner={{banner}}&banner=B22_WMDE_local_prototype' -preview_url = 'https://en.wikipedia.org/wiki/Main_Page?banner={{banner}}&devMode' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" - -[pad_en.banners.ctrl] -filename = "./banners/pad_english/banner_ctrl.ts" -pagename = "B23_WMDE_iPad_EN_00_ctrl" -tracking = "org-en-ipad00-230501-ctrl" - -[pad_en.banners.var] -filename = "./banners/pad_english/banner_var.ts" -pagename = "B23_WMDE_iPad_EN_00_var" -tracking = "org-en-ipad00-230501-var" - -[pad_en.test_matrix] -device = [ 'ipad_mini', 'ipad', 'ipad_pro_9_7_inch', 'ipad_pro_12_inch'] -orientation = [ "portrait", "landscape"] - - -[thank_you] -name = "Thank you banner" -icon = "desktop" -campaign = "C23_Thank_You_00" -description = "Development campaign for thank you banner" -campaign_tracking = "ty-240101" -preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype" -preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode' -wrapper_template = "wikipedia_org" -use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN" - -[thank_you.banners.ctrl] -filename = "./banners/thank_you/banner_ctrl.de.ts" -pagename = "B23_WMDE_Thank_You_DE_00_ctrl" -tracking = "org-ty00-240101-ctrl" - -[thank_you.banners.var] -filename = "./banners/thank_you/banner_var.de.ts" -pagename = "B23_WMDE_Thank_You_DE_00_var" -tracking = "org-ty00-240101-var" - -[thank_you.banners.ctrl_en] -filename = "./banners/thank_you/banner_ctrl.en.ts" -pagename = "B23_WMDE_Thank_You_EN_00_ctrl" -tracking = "org-en-ty00-240101-ctrl" - -[thank_you.banners.var_en] -filename = "./banners/thank_you/banner_var.en.ts" -pagename = "B23_WMDE_Thank_You_EN_00_var" -tracking = "org-en-ty00-240101-var" - -[thank_you.test_matrix] -platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"] -resolution = ["800x600", "1024x768", "1280x960", "1600x1200", "1920x1200", "2560x1440"] diff --git a/docs/Use-of-Funds-integration.md b/docs/Use-of-Funds-integration.md index a705a741c..c7ffdeca7 100644 --- a/docs/Use-of-Funds-integration.md +++ b/docs/Use-of-Funds-integration.md @@ -24,7 +24,7 @@ Each year, create two new pages on meta.wikipedia.org, one for English and one f * https://meta.wikimedia.org/wiki/MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE * https://meta.wikimedia.org/wiki/MediaWiki:WMDE_Fundraising/UseOfFunds_2023_EN -To use different pages, change the setting `use_of_funds_source` in the file [`campaigns_info.toml`](../campaign_info_main.toml). +To use different pages, change the setting `use_of_funds_source` in the file [`campaigns_info.toml`](../campaign_info.toml). ## Initializing the loader class in the entry points diff --git a/package.json b/package.json index 03c047eb8..8a2d3300f 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "watch": "webpack --watch", "build": "npm-run-all -s check-content-version build:banners", "build:banners": "webpack --config webpack.production.js", + "build:thankyou": "webpack --config webpack.production.js --env campaign_info=campaign_info.thank_you.toml", "start": "npm run dev", "dev": "nodemon", + "thankyou": "webpack serve --host 0.0.0.0 --env campaign_info=campaign_info.thank_you.toml", "clean": "rimraf dist/*.js dist/*.wikitext dist/*.map", "lint": "npm-run-all lint:*", "lint:js": "eslint --ext .js,.vue,.ts,.cjs --cache --cache-location .eslintcache --ignore-path .gitignore .", diff --git a/webpack.common.js b/webpack.common.js index c57d26011..d15a53b78 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,86 +1,86 @@ const path = require( 'path' ); -const fs = require( 'fs' ); -const toml = require( 'toml' ); const webpack = require( 'webpack' ); const { VueLoaderPlugin } = require( 'vue-loader' ); const CampaignConfig = require( './webpack/campaign_config' ); -const campaigns = new CampaignConfig( toml.parse( fs.readFileSync( 'campaign_info.toml', 'utf8' ) ) ); -module.exports = { - entry: campaigns.getEntryPoints(), - output: { - filename: '[name].js', - path: path.resolve( __dirname, 'dist' ), - publicPath: '/' - }, - module: { - rules: [ - { - test: /\.ts$/, - loader: 'ts-loader', - options: { - appendTsSuffixTo: [ /\.vue$/ ] - } - }, - { - test: /(wpde_desktop|wpde_mobile)\/banner(_ctrl|_var)\.ts/, - use: [ - { - loader: 'ts-loader', - options: { - appendTsSuffixTo: [ /\.vue$/ ] - } - }, - { - loader: 'string-replace-loader', - options: { - search: /!insert-(campaign|keyword)-here!/g, - /** - * @param { string } match The whole matched placeholder - * @param { string } captureGroupMatch Either "campaign" or "keyword" from the regex match group - * @return { string } - */ - replace( match, captureGroupMatch ) { - const tracking = campaigns.getCampaignTrackingForEntryPoint( this.resource ); - const placeholderToTrackingKeyMap = { - campaign: 'campaignTracking', - keyword: 'bannerTracking' - }; - return tracking[ placeholderToTrackingKeyMap[ captureGroupMatch ] ]; +module.exports = ( env ) => { + const campaigns = CampaignConfig.readFromFile( env.campaign_info ?? 'campaign_info.toml' ); + return { + entry: campaigns.getEntryPoints(), + output: { + filename: '[name].js', + path: path.resolve( __dirname, 'dist' ), + publicPath: '/' + }, + module: { + rules: [ + { + test: /\.ts$/, + loader: 'ts-loader', + options: { + appendTsSuffixTo: [ /\.vue$/ ] + } + }, + { + test: /(wpde_desktop|wpde_mobile)\/banner(_ctrl|_var)\.ts/, + use: [ + { + loader: 'ts-loader', + options: { + appendTsSuffixTo: [ /\.vue$/ ] + } + }, + { + loader: 'string-replace-loader', + options: { + search: /!insert-(campaign|keyword)-here!/g, + /** + * @param { string } match The whole matched placeholder + * @param { string } captureGroupMatch Either "campaign" or "keyword" from the regex match group + * @return { string } + */ + replace( match, captureGroupMatch ) { + const tracking = campaigns.getCampaignTrackingForEntryPoint( this.resource ); + const placeholderToTrackingKeyMap = { + campaign: 'campaignTracking', + keyword: 'bannerTracking' + }; + return tracking[ placeholderToTrackingKeyMap[ captureGroupMatch ] ]; + } } } - } - ] - }, - { - test: /\.vue$/, - loader: 'vue-loader' - }, - { - test: /\.html$/, - use: 'html-loader' + ] + }, + { + test: /\.vue$/, + loader: 'vue-loader' + }, + { + test: /\.html$/, + use: 'html-loader' + }, + { + test: /\.(scss|css)$/, + use: [ 'style-loader', 'css-loader', 'sass-loader' ] + } + ] + }, + resolve: { + extensions: [ '.ts', '.js', '.json' ], + alias: { + '@src': path.resolve( __dirname, 'src' ) }, - { - test: /\.(scss|css)$/, - use: [ 'style-loader', 'css-loader', 'sass-loader' ] + fallback: { + // Don't import node.js 'path' polyfill in compiled code. it shouldn't be used. + path: false } - ] - }, - resolve: { - extensions: [ '.ts', '.js', '.json' ], - alias: { - '@src': path.resolve( __dirname, 'src' ) }, - fallback: { - // Don't import node.js 'path' polyfill in compiled code. it shouldn't be used. - path: false - } - }, - plugins: [ - new VueLoaderPlugin(), - new webpack.ProvidePlugin( { - jQuery: 'jquery' - } ) - ] + plugins: [ + new VueLoaderPlugin(), + new webpack.ProvidePlugin( { + jQuery: 'jquery' + } ) + ] + }; }; diff --git a/webpack.config.js b/webpack.config.js index 60bc82e52..9a0231f8f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -20,14 +20,15 @@ const getBranch = () => new Promise( ( resolve ) => { } ); } ); -const readCampaignFile = () => fs.readFile( 'campaign_info.toml', 'utf8' ) +// eslint-disable-next-line security/detect-non-literal-fs-filename +const readCampaignFile = ( fileName ) => fs.readFile( fileName, 'utf8' ) .then( contents => toml.parse( contents ) ); -module.exports = () => Promise.all( [ +module.exports = ( env ) => Promise.all( [ getBranch(), - readCampaignFile() + readCampaignFile( env.campaign_info ?? 'campaign_info.toml' ) ] ).then( ( [ currentBranch, campaignConfig ] ) => merge( - CommonConfig, + CommonConfig( env ), { mode: 'development', entry: { diff --git a/webpack.production.js b/webpack.production.js index e959171a8..0fdc9f284 100644 --- a/webpack.production.js +++ b/webpack.production.js @@ -1,6 +1,5 @@ const fs = require( 'fs' ); const rimraf = require( 'rimraf' ); -const toml = require( 'toml' ); const { mergeWithCustomize, customizeObject } = require( 'webpack-merge' ); const CommonConfig = require( './webpack.common.js' ); const MediaWikiTextWrapper = require( './webpack/mediawiki_text_wrapper' ); @@ -8,7 +7,6 @@ const LoadVueOnWpde = require( './webpack/load_vue_on_wpde' ); const CampaignConfig = require( './webpack/campaign_config' ); const path = require( 'path' ); -const campaigns = new CampaignConfig( toml.parse( fs.readFileSync( 'campaign_info.toml', 'utf8' ) ) ); function readWrapperTemplate( name ) { // eslint-disable-next-line security/detect-non-literal-fs-filename @@ -18,6 +16,7 @@ function readWrapperTemplate( name ) { module.exports = ( env ) => { let entrypointRules = {}; let customizationRules = { customizeObject: () => undefined }; + const campaigns = CampaignConfig.readFromFile( env.campaign_info ?? 'campaign_info.toml' ); if ( env.banner ) { const bannerName = env.banner; const singleEntry = campaigns.getEntryPoints()[ bannerName ]; @@ -32,7 +31,7 @@ module.exports = ( env ) => { } ); } return mergeWithCustomize( customizationRules )( - CommonConfig, + CommonConfig( env ), { devtool: false, mode: 'production', diff --git a/webpack/campaign_config.js b/webpack/campaign_config.js index 904e7245d..2cc1ea527 100644 --- a/webpack/campaign_config.js +++ b/webpack/campaign_config.js @@ -1,4 +1,6 @@ const path = require( 'path' ); +const { parse } = require( 'toml' ); +const { readFileSync } = require( 'fs' ); function CampaignConfig( config ) { this.config = config; @@ -111,4 +113,9 @@ CampaignConfig.prototype.getCampaignTrackingForEntryPoint = function ( entryPoin return trackingData; }; +CampaignConfig.readFromFile = function ( fileName ) { + // eslint-disable-next-line security/detect-non-literal-fs-filename + return new CampaignConfig( parse( readFileSync( fileName, 'utf8' ) ) ); +}; + module.exports = CampaignConfig; From fa2a06dd61485f2781841dc90492dc9ecfe61d8f Mon Sep 17 00:00:00 2001 From: Abban Dunne Date: Mon, 18 Dec 2023 11:45:06 +0100 Subject: [PATCH 03/15] Hide fireworks if target is not reached Ticket: https://phabricator.wikimedia.org/T352651 --- banners/thank_you/components/BannerCtrl.de.vue | 1 + banners/thank_you/components/BannerCtrl.en.vue | 1 + banners/thank_you/components/BannerVar.de.vue | 1 + banners/thank_you/components/BannerVar.en.vue | 1 + banners/thank_you/components/MiniBanner.vue | 17 ++++++++++++----- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/banners/thank_you/components/BannerCtrl.de.vue b/banners/thank_you/components/BannerCtrl.de.vue index 9abf7d43a..5e7b706cf 100644 --- a/banners/thank_you/components/BannerCtrl.de.vue +++ b/banners/thank_you/components/BannerCtrl.de.vue @@ -1,6 +1,7 @@