Skip to content

Commit df4c4d8

Browse files
authored
Merge pull request #308 from wmde/C23_WPDE_Desktop_02
C23_WPDE_Desktop_02
2 parents 4615d5f + 9b9fe39 commit df4c4d8

40 files changed

+1105
-89
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { createVueApp } from '@src/createVueApp';
2+
3+
import './styles/styles.scss';
4+
5+
import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue';
6+
import Banner from './components/BannerCtrl.vue';
7+
import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment';
8+
import { WindowResizeHandler } from '@src/utils/ResizeHandler';
9+
import PageWPDE from '@src/page/PageWPDE';
10+
import TranslationPlugin from '@src/TranslationPlugin';
11+
import { TrackerWPDE } from '@src/tracking/TrackerWPDE';
12+
import eventMap from './event_map';
13+
import { Translator } from '@src/Translator';
14+
import DynamicTextPlugin from '@src/DynamicTextPlugin';
15+
import { LocalImpressionCount } from '@src/utils/LocalImpressionCount';
16+
17+
// Channel specific form setup
18+
import { createFormItems } from './form_items';
19+
import { createFormActions } from '@src/createFormActions';
20+
21+
// Content
22+
import messages from './messages';
23+
import { LocaleFactoryWpDe } from '@src/utils/LocaleFactory/LocaleFactoryWpDe';
24+
25+
const localeFactory = new LocaleFactoryWpDe();
26+
const translator = new Translator( messages );
27+
28+
// Tracking placeholders will be replaced by webpack string-replace-loader
29+
// using the campaign configuration ( campaign_info.toml ) for the correct values
30+
const tracking = {
31+
campaign: '!insert-campaign-here!',
32+
keyword: '!insert-keyword-here!'
33+
};
34+
35+
// This is channel specific and must be changed for wp.org banners
36+
const page = new PageWPDE( tracking );
37+
const runtimeEnvironment = new UrlRuntimeEnvironment( window.location );
38+
const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment );
39+
const tracker = new TrackerWPDE( 'FundraisingTracker', page.getTracking().keyword, eventMap, runtimeEnvironment );
40+
41+
const app = createVueApp( BannerConductor, {
42+
page,
43+
bannerConfig: {
44+
delay: runtimeEnvironment.getBannerDelay( 0 ),
45+
transitionDuration: 1000
46+
},
47+
bannerProps: {
48+
useOfFundsContent: localeFactory.getUseOfFundsLoader().getContent(),
49+
remainingImpressions: impressionCount.getRemainingImpressions( page.getMaxBannerImpressions() )
50+
},
51+
resizeHandler: new WindowResizeHandler(),
52+
banner: Banner,
53+
impressionCount
54+
} );
55+
56+
app.use( TranslationPlugin, translator );
57+
app.use( DynamicTextPlugin, {
58+
campaignParameters: page.getCampaignParameters(),
59+
date: new Date(),
60+
formatters: localeFactory.getFormatters(),
61+
impressionCount,
62+
translator
63+
} );
64+
65+
const currencyFormatter = localeFactory.getCurrencyFormatter();
66+
app.provide( 'currencyFormatter', currencyFormatter );
67+
app.provide( 'formItems', createFormItems( translator, currencyFormatter.euroAmount.bind( currencyFormatter ) ) );
68+
app.provide( 'formActions', createFormActions( page.getTracking(), impressionCount ) );
69+
app.provide( 'tracker', tracker );
70+
71+
app.mount( page.getBannerContainer() );
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { createVueApp } from '@src/createVueApp';
2+
3+
import './styles/styles.scss';
4+
5+
import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue';
6+
import Banner from './components/BannerVar.vue';
7+
import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment';
8+
import { WindowResizeHandler } from '@src/utils/ResizeHandler';
9+
import PageWPDE from '@src/page/PageWPDE';
10+
import TranslationPlugin from '@src/TranslationPlugin';
11+
import { TrackerWPDE } from '@src/tracking/TrackerWPDE';
12+
import eventMap from './event_map';
13+
import { Translator } from '@src/Translator';
14+
import DynamicTextPlugin from '@src/DynamicTextPlugin';
15+
import { LocalImpressionCount } from '@src/utils/LocalImpressionCount';
16+
17+
// Channel specific form setup
18+
import { createFormItems } from './form_items';
19+
import { createFormActions } from '@src/createFormActions';
20+
21+
// Content
22+
import messages from './messages';
23+
import { LocaleFactoryWpDe } from '@src/utils/LocaleFactory/LocaleFactoryWpDe';
24+
25+
const localeFactory = new LocaleFactoryWpDe();
26+
const translator = new Translator( messages );
27+
28+
// Tracking placeholders will be replaced by webpack string-replace-loader
29+
// using the campaign configuration ( campaign_info.toml ) for the correct values
30+
const tracking = {
31+
campaign: '!insert-campaign-here!',
32+
keyword: '!insert-keyword-here!'
33+
};
34+
35+
// This is channel specific and must be changed for wp.org banners
36+
const page = new PageWPDE( tracking );
37+
const runtimeEnvironment = new UrlRuntimeEnvironment( window.location );
38+
const impressionCount = new LocalImpressionCount( page.getTracking().keyword, runtimeEnvironment );
39+
const tracker = new TrackerWPDE( 'FundraisingTracker', page.getTracking().keyword, eventMap, runtimeEnvironment );
40+
41+
const app = createVueApp( BannerConductor, {
42+
page,
43+
bannerConfig: {
44+
delay: runtimeEnvironment.getBannerDelay( 0 ),
45+
transitionDuration: 1000
46+
},
47+
bannerProps: {
48+
useOfFundsContent: localeFactory.getUseOfFundsLoader().getContent(),
49+
remainingImpressions: impressionCount.getRemainingImpressions( page.getMaxBannerImpressions() )
50+
},
51+
resizeHandler: new WindowResizeHandler(),
52+
banner: Banner,
53+
impressionCount
54+
} );
55+
56+
app.use( TranslationPlugin, translator );
57+
app.use( DynamicTextPlugin, {
58+
campaignParameters: page.getCampaignParameters(),
59+
date: new Date(),
60+
formatters: localeFactory.getFormatters(),
61+
impressionCount,
62+
translator
63+
} );
64+
65+
const currencyFormatter = localeFactory.getCurrencyFormatter();
66+
app.provide( 'currencyFormatter', currencyFormatter );
67+
app.provide( 'formItems', createFormItems( translator, currencyFormatter.euroAmount.bind( currencyFormatter ) ) );
68+
app.provide( 'formActions', createFormActions( page.getTracking(), impressionCount ) );
69+
app.provide( 'tracker', tracker );
70+
71+
app.mount( page.getBannerContainer() );
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<template>
2+
<div class="wmde-banner-wrapper" :class="contentState">
3+
<SetCookieImage v-if="showSetCookieImage"/>
4+
<MainBanner
5+
@close="onCloseMain"
6+
@form-interaction="$emit( 'bannerContentChanged' )"
7+
:bannerState="bannerState"
8+
v-if="contentState === ContentStates.Main"
9+
>
10+
<template #banner-text>
11+
<BannerText/>
12+
</template>
13+
14+
<template #banner-slides="{ play }: any">
15+
<KeenSlider :with-navigation="true" :play="play" :interval="5000">
16+
17+
<template #slides="{ currentSlide }: any">
18+
<BannerSlides :currentSlide="currentSlide"/>
19+
</template>
20+
21+
<template #left-icon>
22+
<ChevronLeftIcon :fill="'#990a00'"/>
23+
</template>
24+
25+
<template #right-icon>
26+
<ChevronRightIcon :fill="'#990a00'"/>
27+
</template>
28+
29+
</KeenSlider>
30+
</template>
31+
32+
<template #progress>
33+
<ProgressBar amount-to-show-on-right="TARGET"/>
34+
</template>
35+
36+
<template #donation-form="{ formInteraction }: any">
37+
<MultiStepDonation :step-controllers="stepControllers" @form-interaction="formInteraction">
38+
39+
<template #[FormStepNames.MainDonationFormStep]="{ pageIndex, submit, isCurrent, previous }: any">
40+
<MainDonationForm :page-index="pageIndex" @submit="submit" :is-current="isCurrent" @previous="previous"/>
41+
</template>
42+
43+
<template #[FormStepNames.UpgradeToYearlyFormStep]="{ pageIndex, submit, isCurrent, previous }: any">
44+
<UpgradeToYearlyForm :page-index="pageIndex" @submit="submit" :is-current="isCurrent" @previous="previous"/>
45+
</template>
46+
47+
<template #[FormStepNames.CustomAmountFormStep]="{ pageIndex, submit, isCurrent, previous }: any">
48+
<CustomAmountForm :page-index="pageIndex" @submit="submit" :is-current="isCurrent" @previous="previous"/>
49+
</template>
50+
51+
</MultiStepDonation>
52+
</template>
53+
54+
<template #footer>
55+
<BannerFooter @showFundsModal="isFundsModalVisible = true" />
56+
</template>
57+
</MainBanner>
58+
59+
<FundsModal
60+
:content="useOfFundsContent"
61+
:is-funds-modal-visible="isFundsModalVisible"
62+
@hideFundsModal="isFundsModalVisible = false"
63+
/>
64+
65+
<SoftClose
66+
v-if="contentState === ContentStates.SoftClosing"
67+
@close="() => onClose( 'SoftClose', CloseChoices.Close )"
68+
@maybe-later="() => onClose( 'SoftClose', CloseChoices.MaybeLater )"
69+
@time-out-close="() => onClose( 'SoftClose', CloseChoices.TimeOut )"
70+
/>
71+
</div>
72+
</template>
73+
74+
<script setup lang="ts">
75+
import { BannerStates } from '@src/components/BannerConductor/StateMachine/BannerStates';
76+
import { ref, watch } from 'vue';
77+
import { UseOfFundsContent as useOfFundsContentInterface } from '@src/domain/UseOfFunds/UseOfFundsContent';
78+
import MainBanner from './MainBanner.vue';
79+
import FundsModal from '@src/components/UseOfFunds/FundsModal.vue';
80+
import BannerText from '../content/BannerText.vue';
81+
import BannerSlides from '../content/BannerSlides.vue';
82+
import ProgressBar from '@src/components/ProgressBar/ProgressBar.vue';
83+
import MultiStepDonation from '@src/components/DonationForm/MultiStepDonation.vue';
84+
import BannerFooter from '@src/components/Footer/BannerFooter.vue';
85+
import MainDonationForm from '@src/components/DonationForm/Forms/MainDonationForm.vue';
86+
import UpgradeToYearlyForm from '@src/components/DonationForm/Forms/UpgradeToYearlyForm.vue';
87+
import CustomAmountForm from '@src/components/DonationForm/Forms/CustomAmountForm.vue';
88+
import KeenSlider from '@src/components/Slider/KeenSlider.vue';
89+
import ChevronLeftIcon from '@src/components/Icons/ChevronLeftIcon.vue';
90+
import ChevronRightIcon from '@src/components/Icons/ChevronRightIcon.vue';
91+
import { useFormModel } from '@src/components/composables/useFormModel';
92+
import {
93+
createSubmittableMainDonationForm
94+
} from '@src/components/DonationForm/StepControllers/SubmittableMainDonationForm';
95+
import {
96+
createSubmittableUpgradeToYearly
97+
} from '@src/components/DonationForm/StepControllers/SubmittableUpgradeToYearly';
98+
import { createSubmittableCustomAmount } from '@src/components/DonationForm/StepControllers/SubmittableCustomAmount';
99+
import { CloseChoices } from '@src/domain/CloseChoices';
100+
import { CloseEvent } from '@src/tracking/events/CloseEvent';
101+
import { TrackingFeatureName } from '@src/tracking/TrackingEvent';
102+
import SoftClose from '@src/components/SoftClose/SoftClose.vue';
103+
import SetCookieImage from '@src/components/SetWPDECookieImage/SetCookieImage.vue';
104+
105+
enum ContentStates {
106+
Main = 'wmde-banner-wrapper--main',
107+
SoftClosing = 'wmde-banner-wrapper--soft-closing'
108+
}
109+
110+
enum FormStepNames {
111+
CustomAmountFormStep = 'CustomAmountForm',
112+
MainDonationFormStep = 'MainDonationForm',
113+
UpgradeToYearlyFormStep = 'UpgradeToYearlyForm'
114+
}
115+
116+
interface Props {
117+
bannerState: BannerStates;
118+
useOfFundsContent: useOfFundsContentInterface;
119+
remainingImpressions: number;
120+
}
121+
122+
const props = defineProps<Props>();
123+
const emit = defineEmits( [ 'bannerClosed', 'bannerContentChanged' ] );
124+
125+
const isFundsModalVisible = ref<boolean>( false );
126+
const showSetCookieImage = ref<boolean>( false );
127+
const contentState = ref<ContentStates>( ContentStates.Main );
128+
const formModel = useFormModel();
129+
const stepControllers = [
130+
createSubmittableMainDonationForm( formModel, FormStepNames.UpgradeToYearlyFormStep ),
131+
createSubmittableUpgradeToYearly( formModel, FormStepNames.CustomAmountFormStep, FormStepNames.MainDonationFormStep ),
132+
createSubmittableCustomAmount( formModel, FormStepNames.UpgradeToYearlyFormStep )
133+
];
134+
135+
watch( contentState, async () => {
136+
emit( 'bannerContentChanged' );
137+
} );
138+
139+
function onCloseMain(): void {
140+
if ( props.remainingImpressions > 0 ) {
141+
contentState.value = ContentStates.SoftClosing;
142+
} else {
143+
onClose( 'MainBanner', CloseChoices.Close );
144+
}
145+
}
146+
147+
function onClose( feature: TrackingFeatureName, userChoice: CloseChoices ): void {
148+
emit( 'bannerClosed', new CloseEvent( feature, userChoice ) );
149+
if ( userChoice !== CloseChoices.MaybeLater ) {
150+
showSetCookieImage.value = true;
151+
}
152+
}
153+
154+
</script>

0 commit comments

Comments
 (0)