diff --git a/banners/mobile/C24_WMDE_Mobile_DE_12/banner_var.ts b/banners/mobile/C24_WMDE_Mobile_DE_12/banner_var.ts index 2835b1e97..130119991 100644 --- a/banners/mobile/C24_WMDE_Mobile_DE_12/banner_var.ts +++ b/banners/mobile/C24_WMDE_Mobile_DE_12/banner_var.ts @@ -1,6 +1,6 @@ import { createVueApp } from '@src/createVueApp'; -import './styles/styles.scss'; +import './styles/styles_var.scss'; import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue'; import Banner from './components/BannerVar.vue'; @@ -23,6 +23,7 @@ import { createFormItems } from './form_items'; import { createFormActions } from '@src/createFormActions'; import { LocalStorageCloseTracker } from '@src/utils/LocalCloseTracker'; import { WindowTimer } from '@src/utils/Timer'; +import { currentCampaignTimePercentage } from '@src/components/ProgressBar/currentCampaignTimePercentage'; const localeFactory = new LocaleFactoryDe(); const translator = new Translator( messages ); @@ -31,7 +32,7 @@ const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin( 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 date = new Date(); const currencyFormatter = localeFactory.getCurrencyFormatter(); const app = createVueApp( BannerConductor, { @@ -54,7 +55,7 @@ const app = createVueApp( BannerConductor, { app.use( TranslationPlugin, translator ); app.use( DynamicTextPlugin, { campaignParameters: page.getCampaignParameters(), - date: new Date(), + date, formatters: localeFactory.getFormatters(), impressionCount, translator, @@ -66,5 +67,6 @@ app.provide( 'formItems', createFormItems( translator, currencyFormatter.euroAmo app.provide( 'formActions', createFormActions( page.getTracking(), impressionCount ) ); app.provide( 'tracker', tracker ); app.provide( 'timer', new WindowTimer() ); +app.provide( 'currentCampaignTimePercentage', currentCampaignTimePercentage( date, page.getCampaignParameters() ) ); app.mount( page.getBannerContainer() ); diff --git a/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.vue b/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.vue index e28a0d24c..92d61325a 100644 --- a/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.vue +++ b/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.vue @@ -9,7 +9,9 @@ @@ -24,9 +26,7 @@ - + + + diff --git a/banners/mobile/C24_WMDE_Mobile_DE_12/content/ProgressBar.vue b/banners/mobile/C24_WMDE_Mobile_DE_12/content/ProgressBar.vue new file mode 100644 index 000000000..54bed9a88 --- /dev/null +++ b/banners/mobile/C24_WMDE_Mobile_DE_12/content/ProgressBar.vue @@ -0,0 +1,30 @@ + + + diff --git a/banners/mobile/C24_WMDE_Mobile_DE_12/messages_var.ts b/banners/mobile/C24_WMDE_Mobile_DE_12/messages_var.ts new file mode 100644 index 000000000..29192b85b --- /dev/null +++ b/banners/mobile/C24_WMDE_Mobile_DE_12/messages_var.ts @@ -0,0 +1,32 @@ +import DynamicCampaignTextDe from '@src/utils/DynamicContent/messages/DynamicCampaignText.de'; +import { TranslationMessages } from '@src/Translator'; +import UpgradeToYearlyDe from '@src/components/DonationForm/Forms/messages/UpgradeToYearly.de'; +import FooterDe from '@src/components/Footer/messages/Footer.de'; +import MainDonationFormDe from '@src/components/DonationForm/Forms/messages/MainDonationForm.de'; +import SoftCloseDe from '@src/components/SoftClose/messages/SoftClose.de'; +import DoubleProgressBarDe from '@src/components/ProgressBar/messages/DoubleProgressBar.de'; + +const messages: TranslationMessages = { + ...DynamicCampaignTextDe, + ...FooterDe, + ...MainDonationFormDe, + ...UpgradeToYearlyDe, + ...SoftCloseDe, + ...DoubleProgressBarDe, + + // custom messages here + 'use-of-funds-link': 'Was Ihre Spende bewirkt', + 'payment-bank-transfer': 'Überweisung', + 'payment-sofort': 'Sofort', + 'upgrade-to-yearly-copy': '

Jedes Jahr sind wir auf Menschen wie Sie angewiesen. Jährliche Spenden helfen uns' + + ' besonders und ermöglichen langfristige Weiterentwicklungen.

' + + '

Sie gehen kein Risiko ein: Jederzeit formlos zu sofort kündbar.

', + 'upgrade-to-yearly-no': 'Nein, ich spende einmalig {{amount}}', + 'upgrade-to-yearly-yes': 'Ja, ich spende {{amount}} jährlich', + 'campaign-day-only-n-days': 'Heute sind es nur noch {{days}} Tage bis zum Ende unserer Spendenkampagne.', + 'soft-close-prompt': 'Wikipedia später unterstützen?', + 'soft-close-button-already-donated': 'Habe schon gespendet', + 'amount-total': '' +}; + +export default messages; diff --git a/banners/mobile/C24_WMDE_Mobile_DE_12/styles/styles_var.scss b/banners/mobile/C24_WMDE_Mobile_DE_12/styles/styles_var.scss new file mode 100644 index 000000000..82cffc1b4 --- /dev/null +++ b/banners/mobile/C24_WMDE_Mobile_DE_12/styles/styles_var.scss @@ -0,0 +1,28 @@ +@use 'src/themes/Modo/swatches/skin_default' with ( + $upgrade-to-yearly-button-form: true, + $double-progress-bar: true, + $soft-close: true, + $thank-you-box: true +); +@use 'src/components/BannerConductor/banner-transition'; +@use 'src/themes/UseOfFunds/swatches/skin_default' as uof-default; +@use 'src/themes/UseOfFunds/UseOfFunds'; +@use 'src/themes/Modo/defaults'; +@use 'Banner'; +@use 'MiniBanner' with ( + $height: 336px, + $height-l-up: 306px +); +@use 'FullPageBanner'; +@use 'src/themes/Modo/Footer/Footer'; +@use 'src/themes/Modo/ThankYouBox/ThankYouBox'; +@use 'src/themes/Modo/Footer/SelectionInput'; +@use 'src/themes/Modo/DonationForm/MultiStepDonation'; +@use 'src/themes/Modo/DonationForm/Forms/UpgradeToYearlyButtonForm'; +@use 'src/themes/Modo/DonationForm/SubComponents/SelectGroup'; +@use 'src/themes/Modo/DonationForm/SubComponents/SelectCustomAmount'; +@use 'src/themes/Modo/DonationForm/SubComponents/SmsBox'; +@use 'src/themes/Modo/Slider/Slider'; +@use 'src/themes/Modo/SoftClose/SoftClose'; +@use 'src/themes/Modo/ProgressBar/DoubleProgressBar'; +@use 'src/themes/Modo/Message/Message'; diff --git a/src/components/ProgressBar/ConfigurableDoubleProgressBar.vue b/src/components/ProgressBar/ConfigurableDoubleProgressBar.vue new file mode 100644 index 000000000..9456c1367 --- /dev/null +++ b/src/components/ProgressBar/ConfigurableDoubleProgressBar.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/components/ProgressBar/Icons/HandIcon.vue b/src/components/ProgressBar/Icons/HandIcon.vue new file mode 100644 index 000000000..f1b49c7a0 --- /dev/null +++ b/src/components/ProgressBar/Icons/HandIcon.vue @@ -0,0 +1,6 @@ + diff --git a/src/components/ProgressBar/Icons/TimerIcon.vue b/src/components/ProgressBar/Icons/TimerIcon.vue new file mode 100644 index 000000000..42cd4c430 --- /dev/null +++ b/src/components/ProgressBar/Icons/TimerIcon.vue @@ -0,0 +1,6 @@ + diff --git a/src/themes/Modo/ProgressBar/DoubleProgressBar.scss b/src/themes/Modo/ProgressBar/DoubleProgressBar.scss new file mode 100644 index 000000000..dbea0737d --- /dev/null +++ b/src/themes/Modo/ProgressBar/DoubleProgressBar.scss @@ -0,0 +1,81 @@ +@use 'src/components/ProgressBar/DoubleProgressBar'; +@use 'transitionsDouble'; + +.wmde-banner { + @include DoubleProgressBar.layout; + + .wmde-banner { + &-double-progress { + margin: 0; + font-size: 12px; + + &-labels { + display: flex; + justify-content: space-between; + font-weight: bold; + margin-bottom: 6px; + } + + &-amount, + &-time { + height: 16px; + line-height: 16px; + padding-right: 10px; + border-radius: 12px; + + &-fill, + &-difference { + color: var( --double-progress-color ); + height: 100%; + padding: 0 10px; + } + + &-fill { + display: flex; + justify-content: space-between; + } + } + + &-right-text { + float: right; + color: var( --double-progress-right-text-color ); + } + + &-amount { + margin-bottom: 10px; + background: var( --double-progress-time-background ); + + &-fill, + &-difference { + border-radius: 12px; + } + + &-fill { + background: var( --double-progress-time-fill-background ); + z-index: 2; + } + + &-difference { + background: var( --double-progress-difference-background ); + z-index: 1; + text-align: right; + color: var( --double-progress-difference-color ); + } + + svg { + position: relative; + top: 2px; + } + } + + &-time { + background: var( --double-progress-amount-background ); + + &-fill { + border-radius: 12px; + background: var( --double-progress-amount-fill-background ); + } + } + } + } +} diff --git a/src/themes/Modo/ProgressBar/_transitionsDouble.scss b/src/themes/Modo/ProgressBar/_transitionsDouble.scss new file mode 100644 index 000000000..d5015aec0 --- /dev/null +++ b/src/themes/Modo/ProgressBar/_transitionsDouble.scss @@ -0,0 +1,49 @@ +@use '../variables/globals'; + +.wmde-banner { + &-double-progress-amount-difference, + &-double-progress-time-fill, + &-double-progress-amount-fill { + transition: width 3000ms globals.$banner-easing; + width: 0; + max-width: 100%; + } + + &-double-progress .text-fade { + opacity: 0; + transition: opacity 300ms globals.$banner-easing; + transition-delay: 3000ms; + } + + &--visible { + .wmde-banner-mini { + .wmde-banner-double-progress-amount-difference, + .wmde-banner-double-progress-time-fill { + width: var( --wmde-banner-progress-bar-time-width ); + } + + .wmde-banner-double-progress-amount-fill { + width: var( --wmde-banner-progress-bar-width ); + } + + .wmde-banner-double-progress .text-fade { + opacity: 1; + } + } + } + + &-wrapper--full-page { + .wmde-banner-double-progress-amount-difference, + .wmde-banner-double-progress-time-fill { + width: var( --wmde-banner-progress-bar-time-width ); + } + + .wmde-banner-double-progress-amount-fill { + width: var( --wmde-banner-progress-bar-width ); + } + + .wmde-banner-double-progress .text-fade { + opacity: 1; + } + } +} diff --git a/src/themes/Modo/swatches/color_light.scss b/src/themes/Modo/swatches/color_light.scss index 5bb64a0b4..2040e4e93 100644 --- a/src/themes/Modo/swatches/color_light.scss +++ b/src/themes/Modo/swatches/color_light.scss @@ -10,8 +10,10 @@ $grey700: #54595d; $grey400: #a2a9b1; $grey350: #c8ccd1; $grey100: #eaecf0; -$grey90: #eeeeee; +$grey75: #e8e8e8; +$grey50: #eeeeee; +$blue300: #66cfff; $blue400: #5d9fd0; $blue500: #648196; $blue600: #386d94; @@ -37,11 +39,15 @@ $green800: #1d865b; $purple10: #ebe2fc; $purple100: #6b4ba1; +$red200: #f17678; +$red300: #ff5233; + @mixin swatch( $address-type-button-form: false, $upgrade-to-yearly-button-form: false, $select-group-image-label: false, $progress-bar: false, + $double-progress-bar: false, $soft-close: false, $subscription-form: false, $thank-you-box: false @@ -57,7 +63,7 @@ $purple100: #6b4ba1; --mini-info-background: #{$green800}; --mini-box-shadow: 0 3px 0.6em rgba( 60 60 60 / 40% ); - --mini-close-background: #{$grey90}; + --mini-close-background: #{$grey50}; --mini-headline-line: #{$yellow200}; --mini-headline-background: #{$green800}; @@ -82,7 +88,7 @@ $purple100: #6b4ba1; --full-smallprint-color: #{$grey700}; - --full-close-background: #{$grey90}; + --full-close-background: #{$grey50}; --slider-pagination-background: #{$grey350}; --slider-pagination-background-active: #{$white}; @@ -148,6 +154,21 @@ $purple100: #6b4ba1; --progress-bar-color: #{$black}; } + @if $double-progress-bar { + --double-progress-color: #{$black}; + --double-progress-time-background: #{$grey75}; + --double-progress-time-fill-background: #{$yellow200}; + --double-progress-difference-background: #{$red300}; + --double-progress-difference-color: #{$white}; + + --double-progress-amount-background: #{$grey75}; + --double-progress-amount-fill-background: #{$blue300}; + --double-progress-right-text-color: #{$black}; + + --double-progress-hand-fill: #{$black}; + --double-progress-timer-fill: #{$black}; + } + @if $soft-close { --soft-close-background: #{$white}; --soft-close-box-shadow: 0 3px 0.6em rgba( 60 60 60 / 40% ); @@ -155,7 +176,7 @@ $purple100: #6b4ba1; --soft-close-prompt-color: #{$white}; --soft-close-prompt-background: #{$green800}; - --soft-close-close-button-background: #{$grey90}; + --soft-close-close-button-background: #{$grey50}; --soft-close-button-background: #{$blue700}; --soft-close-button-color: #{$white}; diff --git a/src/themes/Modo/swatches/skin_default.scss b/src/themes/Modo/swatches/skin_default.scss index ea2f5b9bb..0ea568f4a 100644 --- a/src/themes/Modo/swatches/skin_default.scss +++ b/src/themes/Modo/swatches/skin_default.scss @@ -4,6 +4,7 @@ $address-type-button-form: false !default; $upgrade-to-yearly-button-form: false !default; $select-group-image-label: false !default; $progress-bar: false !default; +$double-progress-bar: false !default; $soft-close: false !default; $subscription-form: false !default; $thank-you-box: false !default; @@ -14,6 +15,7 @@ $thank-you-box: false !default; $upgrade-to-yearly-button-form, $select-group-image-label, $progress-bar, + $double-progress-bar, $soft-close, $subscription-form, $thank-you-box diff --git a/test/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.spec.ts b/test/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.spec.ts index a3216e878..24deaec0f 100644 --- a/test/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.spec.ts +++ b/test/banners/mobile/C24_WMDE_Mobile_DE_12/components/BannerVar.spec.ts @@ -72,7 +72,8 @@ describe( 'BannerVar.vue', () => { currencyFormatter: new CurrencyDe(), formItems, tracker, - timer: timer ?? new TimerStub() + timer: timer ?? new TimerStub(), + currentCampaignTimePercentage: 42 } } } ); diff --git a/test/components/ProgressBar/ConfigurableDoubleProgressBar.spec.ts b/test/components/ProgressBar/ConfigurableDoubleProgressBar.spec.ts new file mode 100644 index 000000000..86b8b5db7 --- /dev/null +++ b/test/components/ProgressBar/ConfigurableDoubleProgressBar.spec.ts @@ -0,0 +1,54 @@ +import { mount } from '@vue/test-utils'; +import { describe, it, expect, beforeEach } from 'vitest'; +import ProgressBar from '@src/components/ProgressBar/ConfigurableDoubleProgressBar.vue'; +import { DynamicContent } from '@src/utils/DynamicContent/DynamicContent'; +import { DateAndTime } from '@src/utils/DynamicContent/DateAndTime'; + +describe( 'ConfigurableDoubleProgressBar.vue', () => { + let dynamicCampaignContent: DynamicContent; + + beforeEach( () => { + dynamicCampaignContent = { + campaignDaySentence: '', + currentDate: '', + getCurrentDateAndTime(): DateAndTime { + return { currentDate: '', currentTime: '' }; + }, + currentDayName: '', + daysLeftSentence: 'daysLeftSentence', + daysPassedSentence: 'daysPassedSentence', + donorsNeededSentence: '', + goalDonationSum: '', + remainingDonationSum: '', + overallImpressionCount: 0, + progressBarContent: { + percentageTowardsTarget: 42, + donationTarget: 'donationTarget', + donationTargetAmount: 'donationTargetAmount', + amountDonated: 'amountDonated', + amountNeeded: 'amountNeeded', + isLateProgress: false + }, + visitorsVsDonorsSentence: '', + averageDonation: '' + }; + } ); + + it( 'should add the donation percentages as css variables', () => { + const wrapper = mount( ProgressBar, { + props: { amountToShowOnRight: 'TARGET' }, + global: { + mocks: { + $translate: ( key: string ) => key + }, + provide: { + dynamicCampaignText: dynamicCampaignContent, + currentCampaignTimePercentage: 66 + } + } + } ); + + expect( wrapper.attributes( 'style' ) ).toContain( '--wmde-banner-progress-bar-width: 42%' ); + expect( wrapper.attributes( 'style' ) ).toContain( '--wmde-banner-progress-bar-time-width: 66%' ); + } ); +} );