Add Fullscreen in viewer, Track links with Google Analytics, Use .env file
All checks were successful
continuous-integration/drone/push Build is passing

- Fullscreen is a component that watches a store value set by the Carousel component on a picture click
- Use a .env file for API and website related settings and informations
- Google Analytics is now in place, tracking each routes link and viewer photo change
This commit is contained in:
2020-03-28 15:21:51 +01:00
parent 23db9e343c
commit 0635b65abf
20 changed files with 384 additions and 138 deletions

View File

@@ -0,0 +1,142 @@
<script context="module">
import { stores } from '@sapper/app'
import { apiEndpoints } from '../../../../utils/store'
// Define either to preload data or use the store
let preloaded
currentPhotos.subscribe(store => preloaded = store ? store : undefined)
// Preload data
export async function preload (page, session) {
// Load the photos if not loaded
if (!preloaded) {
// Fields
const fields = [
'id', 'name', 'slug', 'date', 'image.private_hash',
'location.id', 'location.name', 'location.slug', 'location.country.name', 'location.country.slug'
]
const req = await this.fetch(`${apiEndpoints.rest}/items/photos?fields=${fields.join()}&filter[location.slug][rlike]=%${page.params.place}%`)
const photos = await req.json()
if (req.ok) {
return { photos: photos.data }
}
}
// Use the store otherwise
else return {
photos: preloaded
}
this.error(404, 'Not found')
}
</script>
<script>
import { onMount, createEventDispatcher } from 'svelte'
import {
site,
locations,
currentLocation,
currentPhotos,
pageReady,
pageTransition
} from '../../../../utils/store'
import { getThumbnail, analyticsUpdate } from '../../../../utils/functions'
// Components
import IconGlobe from '../../../../atoms/IconGlobe'
import IconCross from '../../../../atoms/IconCross'
import Carousel from '../../../../organisms/Carousel'
import Fullscreen from '../../../../organisms/Fullscreen'
import SocialMetas from '../../../../utils/SocialMetas'
// Animations
import { animateIn } from '../../../../animations/viewer'
pageTransition.onAnimationEnd = animateIn
// Props
export let photos
// Variables
const { page } = stores()
const dispatch = createEventDispatcher()
let windowWidth
let currentPhoto = photos.find(photo => photo.slug === $page.params.photo)
// Update store current location
if (!$currentLocation) currentLocation.set($locations.find(loc => loc.slug === $page.params.place))
if (!$currentPhotos) currentPhotos.set(photos)
// Photo has changed from the Carousel component
const photoChanged = event => {
currentPhoto = event.detail.currentPhoto
// Change the URL to the current photo
if (!event.detail.init) {
const windowPathname = window.location.pathname
const newUrl = windowPathname.substring(0, windowPathname.lastIndexOf('/') + 1) + currentPhoto.slug
history.pushState('', document.title, newUrl)
analyticsUpdate(newUrl)
}
}
// Access a direct photo or navigate in history
const photoSlug = $page.params.photo
// On init, send an event to the Carousel component with the photoSlug to set currentIndex and then change the photo
// Pop event from browser (prev/next)
const changedUrl = event => dispatch('changedUrl', { currentPhoto: currentPhoto })
/*
** Run code when mounted
*/
onMount(() => {
// Page is loaded
pageReady.set(true)
dispatch('changeUrl', { page: $page })
})
</script>
<svelte:head>
<!-- TODO:
- Change the title with the current photo name and update Metas (with window location url)
-->
<title>{$site.seo_name} Photos of {$currentLocation.name}, {$currentLocation.country.name}</title>
<meta name="description" content="{$site.seo_name} {$currentLocation.name} {$currentLocation.description}">
<SocialMetas
url="https://{$page.host}/viewer/{currentPhoto.location.country.slug}/{currentPhoto.location.slug}/{currentPhoto.slug}"
title="{$site.seo_name} - Beautiful homes of {$currentLocation.name}, {$currentLocation.country.name}"
description="{$site.seo_name} {$currentLocation.name} {$currentLocation.description}"
image={getThumbnail(currentPhoto.image.private_hash, 1200, 630)}
/>
</svelte:head>
<svelte:window bind:innerWidth={windowWidth} />
<section class="viewer">
<div class="viewer__top">
<p class="tip">Tap for fullscreen</p>
<div class="viewer__buttons">
<a href="/choose" class="button-control button-control--dashed" aria-label="Change the location" rel="prefetch">
<IconGlobe color="#fff" width={windowWidth >= 768 ? 22 : 18} />
<svg>
<circle cx="50%" cy="50%" r="{windowWidth >= 768 ? 32 : 24}px"></circle>
</svg>
</a>
<a href="/location/{$currentLocation.country.slug}/{$currentLocation.slug}" class="button-control button-control--pink dir-bottom" aria-label="Back to photos" rel="prefetch">
<IconCross color="#fff" width="18" class="icon" />
<IconCross color="#fff" width="18" class="icon" hidden="true" />
</a>
</div>
</div>
<Carousel
viewer="true"
photos={photos}
init={$page}
on:photoChange={photoChanged}
/>
<Fullscreen />
</section>