|
3 | 3 | import { hideNotification, shouldShowNotification } from '$lib/helpers/notifications';
|
4 | 4 | import { app } from '$lib/stores/app';
|
5 | 5 | import {
|
6 |
| - type BottomModalAlertAction, |
7 | 6 | type BottomModalAlertItem,
|
8 | 7 | bottomModalAlertsConfig,
|
9 | 8 | dismissBottomModalAlert,
|
|
20 | 19 | import { goto } from '$app/navigation';
|
21 | 20 | import { Typography } from '@appwrite.io/pink-svelte';
|
22 | 21 |
|
23 |
| - let currentIndex = 0; |
24 |
| - let openModalOnMobile = false; |
| 22 | + let currentIndex = $state(0); |
| 23 | + let openModalOnMobile = $state(false); |
25 | 24 |
|
26 |
| - function getPageScope(pathname: string) { |
27 |
| - const isProjectPage = pathname.includes('project-[region]-[project]'); |
28 |
| - const isOrganizationPage = pathname.includes('organization-[organization]'); |
| 25 | + function getPageScope(route: string) { |
| 26 | + const isProjectPage = route.includes('project-[region]-[project]'); |
| 27 | + const isOrganizationPage = route.includes('organization-[organization]'); |
29 | 28 |
|
30 | 29 | return { isProjectPage, isOrganizationPage };
|
31 | 30 | }
|
32 | 31 |
|
33 |
| - function filterModalAlerts(alerts: BottomModalAlertItem[], pathname: string) { |
34 |
| - const { isProjectPage, isOrganizationPage } = getPageScope(pathname); |
| 32 | + function filterModalAlerts(alerts: BottomModalAlertItem[], route: string) { |
| 33 | + const { isProjectPage, isOrganizationPage } = getPageScope(route); |
35 | 34 |
|
36 | 35 | return alerts
|
37 | 36 | .sort((a, b) => b.importance - a.importance)
|
|
51 | 50 | });
|
52 | 51 | }
|
53 | 52 |
|
54 |
| - $: filteredModalAlerts = filterModalAlerts($bottomModalAlertsConfig.alerts, page.route.id); |
| 53 | + const bottomModalAlerts = $derived($bottomModalAlertsConfig.alerts); |
55 | 54 |
|
56 |
| - $: currentModalAlert = filteredModalAlerts[currentIndex] as BottomModalAlertItem; |
| 55 | + const filteredModalAlerts = $derived(filterModalAlerts(bottomModalAlerts, page.route.id)); |
57 | 56 |
|
58 |
| - $: hasOnlyPrimaryCta = typeof currentModalAlert?.learnMore === 'undefined'; |
| 57 | + const currentModalAlert = $derived(filteredModalAlerts[currentIndex] as BottomModalAlertItem); |
59 | 58 |
|
60 |
| - function handleClose() { |
61 |
| - filteredModalAlerts.forEach((alert) => { |
| 59 | + const hasOnlyPrimaryCta = $derived(typeof currentModalAlert?.learnMore === 'undefined'); |
| 60 | +
|
| 61 | + const isOnOnboarding = $derived(page.route.id.includes('(console)/onboarding')); |
| 62 | +
|
| 63 | + function handleClose(id: string | null = null) { |
| 64 | + const alerts = !id |
| 65 | + ? filteredModalAlerts |
| 66 | + : filteredModalAlerts.filter((alert) => alert.id === id); |
| 67 | +
|
| 68 | + alerts.forEach((alert) => { |
62 | 69 | const modalAlert = alert;
|
63 | 70 | dismissBottomModalAlert(modalAlert.id);
|
64 | 71 | hideNotification(modalAlert.id, { coolOffPeriod: 24 * 365 });
|
65 | 72 | if (modalAlert.closed) modalAlert.closed();
|
66 | 73 | });
|
| 74 | +
|
| 75 | + // reset `currentIndex` if we removed the last item |
| 76 | + if (currentIndex >= filteredModalAlerts.length - 1) { |
| 77 | + currentIndex = Math.max(0, filteredModalAlerts.length - 2); |
| 78 | + } |
67 | 79 | }
|
68 | 80 |
|
69 | 81 | function showNext() {
|
|
114 | 126 | }
|
115 | 127 |
|
116 | 128 | // the button component cannot have both href and on:click!
|
117 |
| - function triggerWindowLink(alertAction: BottomModalAlertAction, event?: string) { |
| 129 | + function triggerWindowLink(alert: BottomModalAlertItem, event?: string) { |
| 130 | + const alertAction = alert.cta; |
118 | 131 | const shouldShowUpgrade = showUpgrade();
|
| 132 | +
|
| 133 | + // for correct event tracking after removal |
| 134 | + const currentModalId = currentModalAlert.id; |
| 135 | +
|
119 | 136 | const url = shouldShowUpgrade
|
120 | 137 | ? $upgradeURL
|
121 | 138 | : alertAction.link({
|
|
130 | 147 | }
|
131 | 148 |
|
132 | 149 | if (alertAction?.hideOnClick === true) {
|
133 |
| - // be careful of this one. |
134 |
| - // once clicked, its gone! |
135 |
| - handleClose(); |
| 150 | + handleClose(alert.id); // gone! |
136 | 151 | }
|
137 | 152 |
|
138 | 153 | trackEvent(Click.PromoClick, {
|
139 |
| - promo: currentModalAlert.id, |
140 |
| - type: shouldShowUpgrade ? 'upgrade' : (event ?? `cta_click_${currentModalAlert.id}`) |
| 154 | + promo: currentModalId, |
| 155 | + type: shouldShowUpgrade ? 'upgrade' : (event ?? `cta_click_${currentModalId}`) |
141 | 156 | });
|
142 | 157 | }
|
143 | 158 |
|
|
156 | 171 | }
|
157 | 172 | }
|
158 | 173 |
|
159 |
| - onMount(() => { |
160 |
| - addBottomModalAlerts(); |
161 |
| - }); |
| 174 | + onMount(addBottomModalAlerts); |
162 | 175 | </script>
|
163 | 176 |
|
164 |
| -{#if filteredModalAlerts.length > 0 && currentModalAlert && !page.url.pathname.includes('console/onboarding')} |
| 177 | +{#if !isOnOnboarding && filteredModalAlerts.length > 0 && currentModalAlert} |
165 | 178 | {@const shouldShowUpgrade = showUpgrade()}
|
166 | 179 | <div class="main-alert-wrapper is-not-mobile">
|
167 | 180 | <div class="alert-container">
|
|
170 | 183 | <button
|
171 | 184 | aria-label="Close modal"
|
172 | 185 | class="icon-inline-tag"
|
173 |
| - on:click={() => handleClose()}> |
| 186 | + onclick={() => handleClose()}> |
174 | 187 | <svg
|
175 | 188 | xmlns="http://www.w3.org/2000/svg"
|
176 | 189 | width="20"
|
|
209 | 222 | aria-label="Previous"
|
210 | 223 | class="icon-cheveron-left"
|
211 | 224 | style:cursor={currentIndex !== 0 ? 'pointer' : undefined}
|
212 |
| - on:click={showPrevious} |
| 225 | + onclick={showPrevious} |
213 | 226 | disabled={currentIndex === 0}
|
214 | 227 | class:active={currentIndex > 0}></button>
|
215 | 228 |
|
216 | 229 | <button
|
217 | 230 | aria-label="Next"
|
218 | 231 | class="icon-cheveron-right"
|
219 |
| - on:click={showNext} |
| 232 | + onclick={showNext} |
220 | 233 | style:cursor={currentIndex !==
|
221 | 234 | filteredModalAlerts.length - 1
|
222 | 235 | ? 'pointer'
|
|
248 | 261 | fullWidthMobile
|
249 | 262 | secondary={!hasOnlyPrimaryCta}
|
250 | 263 | class={`${hasOnlyPrimaryCta ? 'only-primary-cta' : ''}`}
|
251 |
| - on:click={() => triggerWindowLink(currentModalAlert.cta)}> |
| 264 | + on:click={() => triggerWindowLink(currentModalAlert)}> |
252 | 265 | {currentModalAlert.cta.text}
|
253 | 266 | </Button>
|
254 | 267 |
|
|
281 | 294 | <button
|
282 | 295 | aria-label="Close modal"
|
283 | 296 | class="icon-inline-tag"
|
284 |
| - on:click={() => handleClose()}> |
| 297 | + onclick={() => handleClose()}> |
285 | 298 | <svg
|
286 | 299 | xmlns="http://www.w3.org/2000/svg"
|
287 | 300 | width="20"
|
|
322 | 335 | style:cursor={currentIndex !== 0
|
323 | 336 | ? 'pointer'
|
324 | 337 | : undefined}
|
325 |
| - on:click={showPrevious} |
| 338 | + onclick={showPrevious} |
326 | 339 | disabled={currentIndex === 0}
|
327 | 340 | class:active={currentIndex > 0}></button>
|
328 | 341 |
|
329 | 342 | <button
|
330 | 343 | aria-label="Next"
|
331 | 344 | class="icon-cheveron-right"
|
332 |
| - on:click={showNext} |
| 345 | + onclick={showNext} |
333 | 346 | style:cursor={currentIndex !==
|
334 | 347 | filteredModalAlerts.length - 1
|
335 | 348 | ? 'pointer'
|
|
364 | 377 | fullWidthMobile
|
365 | 378 | on:click={() => {
|
366 | 379 | openModalOnMobile = false;
|
367 |
| - triggerWindowLink(currentModalAlert.cta); |
| 380 | + triggerWindowLink(currentModalAlert); |
368 | 381 | }}>
|
369 | 382 | {shouldShowUpgrade
|
370 | 383 | ? 'Upgrade plan'
|
|
394 | 407 | {:else}
|
395 | 408 | {@const mobileConfig = getMobileWindowConfig()}
|
396 | 409 | <!-- we don't need keydown because we show this only on mobile -->
|
397 |
| - <!-- svelte-ignore a11y-click-events-have-key-events --> |
| 410 | + <!-- svelte-ignore a11y_click_events_have_key_events --> |
398 | 411 | <div
|
399 | 412 | tabindex="0"
|
400 | 413 | role="button"
|
401 | 414 | class:showing={!openModalOnMobile}
|
402 | 415 | class="card notification-card u-width-full-line"
|
403 |
| - on:click={() => { |
| 416 | + onclick={() => { |
404 | 417 | if (mobileConfig.cta) {
|
405 | 418 | // navigate manually!
|
406 | 419 | triggerMobileWindowLink();
|
|
413 | 426 | <Typography.Text variant="m-500" color="--fgcolor-neutral-primary">
|
414 | 427 | {currentModalAlert.title}
|
415 | 428 | </Typography.Text>
|
416 |
| - <button on:click={hideAllModalAlerts} aria-label="Close"> |
| 429 | + <button onclick={hideAllModalAlerts} aria-label="Close"> |
417 | 430 | <span class="icon-x"></span>
|
418 | 431 | </button>
|
419 | 432 | </div>
|
|
0 commit comments