From ddf97b152422f04ee4029afd8c5394689801afc4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <tomas@imaniti.org>
Date: Tue, 2 Apr 2024 16:10:54 +0200
Subject: [PATCH] wip - new poster template

---
 frontend/src/templates.js            |  11 ++
 frontend/src/views/poster/Poster.vue | 266 +++++++++++++++++++++++++++
 frontend/src/views/poster/canvas.js  |  17 ++
 server/server/templates/index.html   |  14 +-
 4 files changed, 305 insertions(+), 3 deletions(-)
 create mode 100644 frontend/src/views/poster/Poster.vue
 create mode 100644 frontend/src/views/poster/canvas.js

diff --git a/frontend/src/templates.js b/frontend/src/templates.js
index 91e15556..6493ba9c 100644
--- a/frontend/src/templates.js
+++ b/frontend/src/templates.js
@@ -6,6 +6,8 @@ import newspaperQuoteBottomImage from './assets/previews/newspaper_quote_bottom.
 import newspaperQuoteMiddleImage from './assets/previews/newspaper_quote_middle.png'
 import facebookSurveyImage from './assets/previews/facebook_survey.png'
 import twitterBannerImage from './assets/previews/twitter_banner.png'
+import posterImage from './assets/previews/basic_photo_banner.png'
+
 
 const TEMPLATES = {
     basic_photo_banner: {
@@ -71,6 +73,15 @@ const TEMPLATES = {
             title: 'Facebook anketa',
         }
     },
+    poster: {
+        name: 'Plakát',
+        image: posterImage,
+        path: '/poster',
+        component: () => import('./views/poster/Poster.vue'),
+        meta: {
+            title: 'Plakát'
+        }
+    },
     twitter_banner: {
         name: 'Twitter banner',
         image: twitterBannerImage,
diff --git a/frontend/src/views/poster/Poster.vue b/frontend/src/views/poster/Poster.vue
new file mode 100644
index 00000000..935283ee
--- /dev/null
+++ b/frontend/src/views/poster/Poster.vue
@@ -0,0 +1,266 @@
+<script setup>
+import { watch, ref } from 'vue'
+
+import COLORS from '../../colors'
+import PEOPLE from '../../people'
+import TEMPLATES from '../../templates'
+import DEFAULT_CONTRACTOR from '../../contractors'
+import { loadFonts, loadCanvasStorage, setCanvasStorage, updateAutoRedrawStorage } from '../../utils'
+
+import Canvas from '../../components/canvas/Canvas.vue'
+import redraw from './canvas'
+
+import Navbar from '../../components/Navbar.vue'
+import MainContainer from '../../components/MainContainer.vue'
+import ImageInput from '../../components/inputs/ImageInput.vue'
+import LongTextInput from '../../components/inputs/text/LongTextInput.vue'
+import ShortTextInput from '../../components/inputs/text/ShortTextInput.vue'
+import RangeInput from '../../components/inputs/RangeInput.vue'
+import InputSeparator from '../../components/inputs/InputSeparator.vue'
+import SelectInput from '../../components/inputs/SelectInput.vue'
+import MultipleColorPicker from '../../components/inputs/colors/MultipleColorPicker.vue'
+import ReloadButton from '../../components/reload/ReloadButton.vue'
+import AutoReloadCheckbox from '../../components/reload/AutoReloadCheckbox.vue'
+</script>
+
+<script>
+await loadFonts([
+    '12px Bebas Neue',
+    '12px Roboto Condensed',
+    'bold 12px Roboto Condensed'
+])
+
+export default {
+    components: {
+        Canvas,
+        Navbar,
+        MainContainer,
+        ImageInput,
+        LongTextInput,
+        ShortTextInput,
+        RangeInput,
+        SelectInput,
+        InputSeparator,
+        MultipleColorPicker
+    },
+    data () {
+        const predefinedColors = {
+            base: {
+                name: 'Základní barvy',
+                colors: {
+                    background: COLORS.black,
+                    highlight: COLORS.yellow1,
+                    arrow: COLORS.yellow1,
+                    baseText: COLORS.white,
+                    highlightedText: COLORS.black,
+                    contractedByText: COLORS.gray1
+                }
+            }
+        }
+
+        return {
+            mainImage: null,
+            personName: null,
+
+            personPosition: null,
+            firstColumn: null,
+            secondColumn: null,
+
+            socialMedia1: null,
+            socialMedia2: null,
+            socialMedia3: null,
+
+            contractedBy: DEFAULT_CONTRACTOR,
+
+            colorLabels: {
+                background: 'Pozadí',
+                highlight: 'Zvýraznění',
+                arrow: 'Šipka',
+                baseText: 'Text',
+                highlightedText: 'Zvýrazněný text'
+            },
+
+            predefinedColors: predefinedColors,
+            colors: predefinedColors.base.colors,
+            autoRedraw: false
+        }
+    },
+    async created () {
+        await loadCanvasStorage(this)
+    },
+    methods: {
+        async reloadCanvasProperties () {
+            const canvasProperties = {
+                mainImage: this.mainImage,
+                personName: this.personName,
+                personPosition: this.personPosition,
+                firstColumn: this.firstColumn,
+                secondColumn: this.secondColumn,
+                socialMedia1: this.socialMedia1,
+                socialMedia2: this.socialMedia2,
+                socialMedia3: this.socialMedia3,
+                contractedBy: this.contractedBy,
+                colors: this.colors
+            }
+
+            await this.$refs.canvas.redraw(canvasProperties)
+
+            delete canvasProperties.colors
+            setCanvasStorage(canvasProperties)
+        }
+    },
+    mounted () {
+        this.$watch(
+            vm => [
+                vm.mainImage,
+                vm.personName,
+                vm.personPosition,
+                vm.firstColumn,
+                vm.secondColumn,
+                vm.socialMedia1,
+                vm.socialMedia2,
+                vm.socialMedia3,
+                vm.contractedBy,
+                vm.colors
+            ],
+            async (value) => {
+                if (this.autoRedraw) {
+                    await this.reloadCanvasProperties()
+                }
+            },
+            {
+                immediate: true,
+                deep: true
+            }
+        )
+
+        this.$watch(
+            vm => [vm.autoRedraw],
+            async (value) => {
+                updateAutoRedrawStorage(this.autoRedraw)
+
+                if (this.autoRedraw) {
+                    await this.reloadCanvasProperties()
+                }
+            }
+        )
+    },
+}
+</script>
+
+<template>
+    <header>
+        <Navbar
+            :defaultTemplate="TEMPLATES.poster"
+        ></Navbar>
+    </header>
+    <main>
+        <MainContainer>
+            <template v-slot:left>
+                <Canvas
+                    ref="canvas"
+                    :redrawFunction="redraw"
+                    width="2000"
+                    height="2000"
+                />
+            </template>
+
+            <template v-slot:right>
+                <ReloadButton
+                    :parentRefs="$refs"
+                    @click="reloadCanvasProperties"
+                />
+                <AutoReloadCheckbox
+                    v-model="autoRedraw"
+                />
+                <ImageInput
+                    name="Obrázek"
+                    v-model="mainImage"
+                    :important="true"
+                    zIndex="10"
+                />
+
+                <ShortTextInput
+                    name="Jméno osoby"
+                    v-model="personName"
+                    v-model:relatedModel="personPosition"
+                    :predefinedValues="PEOPLE"
+                    :important="true"
+                    zIndex="9"
+                />
+                <LongTextInput
+                    ref="refPersonPosition"
+                    name="Pozice osoby"
+                    v-model="personPosition"
+                    :important="false"
+                    zIndex="8"
+                />
+
+                <LongTextInput
+                    name="Sloupec 1"
+                    v-model="firstColumn"
+                    :important="true"
+                    :highlightable="true"
+                    zIndex="7"
+                />
+                <LongTextInput
+                    name="Sloupec 2"
+                    v-model="secondColumn"
+                    :important="true"
+                    :highlightable="true"
+                    zIndex="6"
+                />
+
+                <InputSeparator />
+
+                <ShortTextInput
+                    name="Sociální médium 1 (např. @tvůj_instagram)"
+                    v-model="socialMedia1"
+                    v-model:relatedModel="socialMedia1"
+                    :important="true"
+                    zIndex="9"
+                />
+
+                <ShortTextInput
+                    name="Sociální médium 2 (např. @pirati.cz)"
+                    v-model="socialMedia2"
+                    v-model:relatedModel="socialMedia2"
+                    :important="true"
+                    zIndex="8"
+                />
+
+                <ShortTextInput
+                    name="Sociální médium 3 (např. tvuj@ema.il)"
+                    v-model="socialMedia3"
+                    v-model:relatedModel="socialMedia3"
+                    :important="true"
+                    zIndex="7"
+                />
+
+                <InputSeparator />
+
+                <MultipleColorPicker
+                    name="Barvy"
+                    v-model="colors"
+                    :important="false"
+                    :colorLabels="colorLabels"
+                    :predefinedColors="predefinedColors"
+                    :defaultPredefinedColors="predefinedColors.base"
+                    zIndex="5"
+                ></MultipleColorPicker>
+
+                <ShortTextInput
+                    name="Zadavatel a zpracovatel"
+                    v-model="contractedBy"
+                    :defaultValue="DEFAULT_CONTRACTOR"
+                    :important="false"
+                    zIndex="4"
+                />
+            </template>
+        </MainContainer>
+    </main>
+</template>
+
+<style>
+@import "vue-select/dist/vue-select.css";
+</style>
diff --git a/frontend/src/views/poster/canvas.js b/frontend/src/views/poster/canvas.js
new file mode 100644
index 00000000..09aba139
--- /dev/null
+++ b/frontend/src/views/poster/canvas.js
@@ -0,0 +1,17 @@
+import { fabric } from 'fabric'
+import { clearObjects, sortObjects, transformHighlightedText, checkTextBoxHeight } from '../../components/canvas/utils'
+import { PaddedHighlightingTextbox } from '../../components/canvas/textbox'
+
+const redraw = async (canvas, options) => {
+    clearObjects(
+        [
+        ],
+        canvas
+    )
+
+    canvas.preserveObjectStacking = true
+
+    sortObjects(canvas)
+}
+
+export default redraw
diff --git a/server/server/templates/index.html b/server/server/templates/index.html
index 04621c3a..b895de36 100644
--- a/server/server/templates/index.html
+++ b/server/server/templates/index.html
@@ -5,12 +5,20 @@
     <link rel="icon" href="/static/favicon.ico">
     <link rel="stylesheet" href="https://styleguide.pirati.cz/2.12.x/css/styles.css">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <script>
+      ;(function () {
+          var src = '//cdn.jsdelivr.net/npm/eruda';
+          if (!/eruda=true/.test(window.location) && localStorage.getItem('active-eruda') != 'true') return;
+          document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
+          document.write('<scr' + 'ipt>eruda.init();</scr' + 'ipt>');
+      })();
+    </script>
     <title>Generátor grafiky</title>
-    <script type="module" crossorigin src="/static/index-5f383c1e.js"></script>
-    <link rel="stylesheet" href="/static/index-ba72a822.css">
+    <script type="module" crossorigin src="/static/index-ec81bc4e.js"></script>
+    <link rel="stylesheet" href="/static/index-636cacf0.css">
   </head>
   <body>
     <div id="app"></div>
-
+    
   </body>
 </html>
-- 
GitLab