<template>
<q-page class="flex">
<div class="column window-height full-width">
<div class="col-2 justify-between flex">
<img src="~assets/le-logo.svg" alt="Logo" id="logo" class="q-mt-xl q-ml-xl h-50">
<p>Version {{ appVersion.toString().split('').join('.') }}</p>
</div>
<div class="col-5 row reverse">
<div class="col-3 bg-secondary row justify-end content-center full-height">
<div id="decorationUpperContainer" class="bg-accent flex flex-center">
<q-icon class="q-ml-md" name="mail" color="primary" size="25vh" />
</div>
<div id="decorationLowerContainer" class="bg-dark">
<q-icon class="q-ml-md" name="subject" color="primary" size="25vh" />
</div>
</div>
<div class="col-8 bg-secondary items-center flex" id="titlearea">
<div class="q-ml-lg">
<h1>Newsletter Creator</h1>
<div class="rotating-text-wrapper">
<h2 class="font-md">{{ $t('inspiring') }}</h2>
<h2 class="font-md">{{ $t('informative') }}</h2>
<h2 class="font-md">{{ $t('innovative') }}</h2>
</div>
</div>
</div>
</div>
<div class="col-5 row justify-between items-end">
<div class="q-mb-xl w-50">
<p class="font-s q-px-xl q-py-sm bg-accent" id="copyright">{{ $t('credit') }}</p>
</div>
<div class="q-mb-xl w-50 row justify-evenly">
<q-btn color="primary" class="button q-mt-md" @click="loadBlankNewsletter">
<div class="column items-center">
<q-icon name="add" size="10vw" />
<p class="font-md">{{ $t('create') }}</p>
<p class="font-s">{{ $t('createSubSlogan') }}</p>
</div>
</q-btn>
<q-btn color="primary" class="button q-mt-md" @click="triggerFileUpload">
<div class="column items-center">
<q-icon name="sym_o_folder_open" size="10vw" />
<p class="font-md">{{ $t('open') }}</p>
<p class="font-s">{{ $t('openSubSlogan') }}</p>
</div>
</q-btn>
<input type="file" id="fileInput" accept=".newsletter" style="display: none" @change="handleFileChange">
</div>
</div>
</div>
</q-page>
<q-dialog v-model="showErrorDialog">
<q-card>
<q-card-section class="row items-center q-pb-none">
<div class="text-h6">Error</div>
<q-space />
<q-btn icon="close" flat round dense @click="showErrorDialog = false" />
</q-card-section>
<q-card-section>
{{ errorMessage }}
</q-card-section>
</q-card>
</q-dialog>
</template>
<script>
import { useNewsletterStore } from 'src/stores/newsletter.js'
import { useSettingsStore } from 'src/stores/settings.js'
export default {
data () {
return {
showErrorDialog: false,
errorMessage: '',
appVersion: useSettingsStore().appVersion
}
},
methods: {
triggerFileUpload () {
document.getElementById('fileInput').click()
// TODO: alternatively use file system api and show modal with last opened files for more seamless experience
},
handleFileChange (event) {
const file = event.target.files[0]
if (file) {
const reader = new FileReader()
reader.onload = (e) => {
const content = e.target.result
try {
this.openNewsletter(content)
} catch (error) {
console.error(error)
event.target.value = ''
}
}
reader.readAsText(file)
}
},
loadBlankNewsletter () {
const blankNewsletter =
{
title: '',
creationTime: new Date().toDateString(),
CreatorVersion: this.appVersion,
sections: [
{
name: 'preface',
elements: []
},
{
name: 'offer',
elements: []
},
{
name: 'onTheGo',
elements: []
},
{
name: 'informed',
elements: []
},
{
name: 'connected',
elements: []
},
{
name: 'outro',
elements: []
}
]
}
this.openNewsletter(JSON.stringify(blankNewsletter))
this.$router.push('/editor')
},
openNewsletter (content) {
const { loadNewsletter } = useNewsletterStore()
try {
loadNewsletter(JSON.parse(content))
} catch (error) {
// show an error message
this.errorMessage = error
this.showErrorDialog = true
throw error
}
this.$router.push('/editor')
}
},
async mounted () {
if (window.api && useNewsletterStore().newsletter.CreatorVersion === undefined) {
const openedFile = await window.api.getFile()
if (openedFile) {
this.openNewsletter(openedFile)
}
} else {
console.error('myAPI is not defined')
}
}
}
</script>
<style scoped lang="scss">
#logo {
object-fit: contain;
}
#titlearea {
border-top-left-radius: 36px;
border-bottom-left-radius: 36px;
}
#decorationUpperContainer {
height: 30%;
width: 70%;
border-top-left-radius: 36px;
overflow: hidden;
}
#decorationLowerContainer {
z-index: 1;
height: 60%;
width: 100%;
border-top-left-radius: 36px;
border-bottom-left-radius: 36px;
}
#copyright {
display: inline;
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
}
.button {
border-radius: 24px;
width: 30%;
}
/* Animation based on https://codingyaar.com/rotating-text-animation-css/ */
.rotating-text-wrapper{
margin-top: -2rem;
}
.rotating-text-wrapper h2 {
animation-duration: 10s;
animation-iteration-count: infinite;
opacity: 0;
}
.rotating-text-wrapper h2:nth-child(1) {
animation-name: rotating-text-1;
}
@keyframes rotating-text-1 {
0% {
transform: translateY(200%);
}
23% {
transform: translateY(100%);
opacity: 1;
}
33% {
opacity: 0;
}
}
.rotating-text-wrapper h2:nth-child(2) {
animation-name: rotating-text-2;
}
@keyframes rotating-text-2 {
33% {
transform: translateY(100%);
opacity: 0;
}
56% {
transform: translateY(0);
opacity: 1;
}
66% {
opacity: 0;
}
}
.rotating-text-wrapper h2:nth-child(3) {
animation-name: rotating-text-3;
}
@keyframes rotating-text-3 {
66% {
transform: translateY(0);
opacity: 0;
}
89% {
transform: translateY(-100%);
opacity: 1;
}
99% {
transform: translateY(-100%);
opacity: 0;
}
}
@media screen and (max-width: 576px) {
.rotating-text-wrapper {
font-size: 0.7rem;
}
}
</style>