github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/directeurs/src/views/Lettre.vue (about) 1 <template> 2 <div class="ma-3"> 3 <v-dialog 4 v-model="showPreview" 5 content-class="content-lettre" 6 max-height="98%" 7 > 8 <object 9 type="application/pdf" 10 v-if="showPreview" 11 :data="urlDownload" 12 class="object" 13 > 14 <p> 15 Vous ne pouvez pas visualiser de pdfs. Merci de mettre à jour votre 16 navigateur (Chrome, Firefox ou Safari sont conseillés). 17 </p> 18 </object> 19 </v-dialog> 20 21 <v-dialog v-model="showInfoLettre"> 22 <info-lettre 23 :paveEspacePerso="paveEspacePerso" 24 :disabledAdd="disabledAddPave" 25 @add="addPaveEspacePerso" 26 @done="doneInfoLettre" 27 ></info-lettre> 28 </v-dialog> 29 30 <v-dialog v-model="showOptions" max-width="800px"> 31 <v-card> 32 <v-card-title>Options de l'entête</v-card-title> 33 <v-card-text> 34 <v-row> 35 <v-col> 36 <v-switch 37 v-model="lettre.use_coord_centre" 38 hint="Activer pour remplacer les coordonnées du directeur par ceux du centre, dans l'entête de la lettre." 39 persistent-hint 40 label="Coordonnées du centre" 41 ></v-switch> 42 </v-col> 43 <v-col cols="5"> 44 <v-switch 45 v-show="!lettre.use_coord_centre" 46 v-model="lettre.show_adresse_postale" 47 hint="Afficher l'adresse postale du directeur." 48 persistent-hint 49 label="Ajouter l'adresse postale" 50 ></v-switch> 51 </v-col> 52 </v-row> 53 <v-row class="mt-2"> 54 <v-col cols="6"> 55 <color-field 56 label="Couleur du texte de l'entête" 57 v-model="lettre.color_coord" 58 :swatches="swatches" 59 ></color-field> 60 </v-col> 61 </v-row> 62 </v-card-text> 63 </v-card> 64 </v-dialog> 65 66 <v-toolbar dense id="toolbar-lettre"> 67 <v-toolbar-title> 68 <v-btn icon small @click="showInfoLettre = !showInfoLettre"> 69 <v-icon>{{ $icons["mdi-information-outline"] }}</v-icon> 70 </v-btn> 71 Lettre aux parents 72 </v-toolbar-title> 73 <div class="mx-3 font-italic body-2" v-html="descriptionDocument"></div> 74 <v-spacer></v-spacer> 75 76 <v-toolbar-items> 77 <tooltip-btn 78 tooltip="Afficher les options" 79 @click="showOptions = true" 80 text 81 > 82 <v-icon>{{ $icons["mdi-cog"] }}</v-icon> 83 Options 84 </tooltip-btn> 85 <v-divider vertical></v-divider> 86 <tooltip-btn 87 tooltip="Sauvegarder et prévisualiser" 88 @click="save" 89 icon 90 :disabled="loading" 91 > 92 <v-icon>{{ $icons["mdi-content-save"] }}</v-icon> 93 </tooltip-btn> 94 </v-toolbar-items> 95 </v-toolbar> 96 <tinymce-editor 97 v-if="tinymceActive" 98 id="myEditor" 99 v-model="lettre.html" 100 :init="tinyMceOptions" 101 ></tinymce-editor> 102 </div> 103 </template> 104 105 <script lang="ts"> 106 import Vue from "vue"; 107 import Component from "vue-class-component"; 108 import { PublicDocument, Lettredirecteur, Time } from "../logic/types"; 109 import { C } from "../logic/controller"; 110 import { Formatter } from "../logic/formatter"; 111 import InfoLettre from "@/components/lettre/InfoLettre.vue"; 112 import TooltipBtn from "@/components/TooltipBtn.vue"; 113 114 import Editor from "@tinymce/tinymce-vue"; 115 import "tinymce"; //side effect 116 117 import "tinymce/themes/silver/theme"; 118 import "tinymce/langs/fr_FR"; 119 import "tinymce/plugins/lists"; 120 import "tinymce/plugins/advlist"; 121 import "tinymce/plugins/image"; 122 import "tinymce/plugins/paste"; 123 import "tinymce/plugins/code"; 124 import "tinymce/plugins/link"; 125 import ToolbarSwitch from "../components/ToolbarSwitch.vue"; 126 import ColorField from "@/components/ColorField.vue"; 127 128 /** Colors proposed by tinymce, should be kept in sync */ 129 const swatchColors = [ 130 "#BFEDD2", 131 "#FBEEB8", 132 "#F8CAC6", 133 "#ECCAFA", 134 "#C2E0F4", 135 "#2DC26B", 136 "#F1C40F", 137 "#E03E2D", 138 "#B96AD9", 139 "#3598DB", 140 "#169179", 141 "#E67E23", 142 "#BA372A", 143 "#843FA1", 144 "#236FA1", 145 "#ECF0F1", 146 "#CED4D9", 147 "#95A5A6", 148 "#7E8C8D", 149 "#34495E", 150 "#000000", 151 "#ffffff" 152 ]; 153 154 // Bloc à ajouter à la lettre. 155 // Attention, en cas de modification, vérifier la mise à page via tinmyce + htmltopdf 156 const paveEspacePerso = `<p><span style="font-size: 14pt; color: #3598db;" data-mce-style="font-size: 14pt; color: #3598db;">ESPACE PERSONNEL</span> </p><p>Lors de l'inscription de votre enfant, un espace personnel <em>Parents</em> vous a été attribué et un lien vers celui-ci envoyé dans le mail de confirmation (<span style="background-color: #ffffff;" data-mce-style="background-color: #ffffff;">Mon</span> <span style="background-color: #ffffff;" data-mce-style="background-color: #ffffff;">Dossier</span>). Dans cet espace vous trouverez :</p><ul><li>le <strong>suivi financier</strong> : vous pourrez alors joindre en ligne les aides auxquelles vous avez le droit (bons CAF, Comité d'entreprise...), afin que le centre d'inscription puisse les déduire de la facture finale.</li><li>les <strong>documents liés au séjour</strong> : liste de vêtement, lettre aux parents, plan d’accès au site ....</li><li>les <strong>documents à compléter</strong> ou joindre en ligne : test d'aisance aquatique si besoin ...</li><li>l’accès à l'<strong>album photo</strong> du séjour</li><li>la <strong>fiche sanitaire</strong> à compléter en ligne avec les allergies alimentaires.</li></ul><p><em>TOUTES LES INFOS ET DOCUMENTS DU SÉJOUR SE TROUVENT DANS VOTRE ESPACE DÉDIÉ !</em></p>`; 157 158 const LettreProps = Vue.extend({ 159 props: {} 160 }); 161 162 @Component({ 163 components: { 164 InfoLettre, 165 TinymceEditor: Editor, 166 ToolbarSwitch, 167 TooltipBtn, 168 ColorField 169 } 170 }) 171 export default class Lettre extends LettreProps { 172 tinymceActive = true; 173 pdfBuffer = null; 174 lettre: Lettredirecteur = { 175 id_camp: 0, 176 html: "", 177 use_coord_centre: false, 178 show_adresse_postale: false, 179 color_coord: "" 180 }; 181 publicDocument: PublicDocument = { 182 url_download: "", 183 id_crypted: "", 184 nom_client: "", 185 taille: 0, 186 date_heure_modif: "" as Time, 187 url_miniature: "" 188 }; 189 showPreview = false; 190 showInfoLettre = false; 191 192 showOptions = false; 193 get swatches() { 194 const out: string[][] = []; 195 let N = swatchColors.length; 196 let chunk = 5; 197 for (let i = 0; i < N; i += chunk) { 198 out.push(swatchColors.slice(i, i + chunk)); 199 } 200 return out; 201 } 202 203 disabledAddPave = false; 204 paveEspacePerso = paveEspacePerso; 205 C = C; 206 207 get tinyMceOptions() { 208 return { 209 language: "fr_FR", 210 height: "75vh", 211 plugins: "lists advlist image paste code link", 212 menubar: false, 213 statusbar: false, 214 paste_data_images: true, 215 image_advtab: false, // style_format permet d'ajouter une marge à droite 216 browser_spellcheck: true, 217 contextmenu: false, 218 font_formats: "Arial=arial;", 219 toolbar: [ 220 "undo redo | cut copy paste | bold italic underline strikethrough | alignleft aligncenter alignright | fontsizeselect | bullist numlist outdent indent | forecolor backcolor current_backcolor | image styleselect link" 221 ], 222 target_list: [{ title: "Nouvelle page", value: "_blank" }], 223 link_title: false, 224 link_assume_external_targets: true, 225 relative_urls: false, 226 remove_script_host: false, 227 images_upload_url: C.getUrlUploadImage(), 228 automatic_uploads: true, 229 formats: { 230 imageMargin: { selector: "img", styles: { marginRight: "20px" } } 231 }, 232 style_formats: [{ title: "Espacer à droite", format: "imageMargin" }] 233 }; 234 } 235 236 get descriptionDocument() { 237 if (!this.publicDocument.id_crypted) { 238 return "<i>(aucune lettre enregistrée)</i>"; 239 } 240 return `modifiée le ${Formatter.date_heure( 241 this.publicDocument.date_heure_modif 242 )} <br/> taille : ${Formatter.taille(this.publicDocument.taille)}`; 243 } 244 get urlDownload() { 245 let url = this.publicDocument.url_download; 246 url = url + "&no-attachment=ok"; 247 return url; 248 } 249 250 deactivated() { 251 // tinymce BUG 252 this.tinymceActive = false; 253 } 254 activated() { 255 // tinymce BUG 256 this.tinymceActive = true; 257 } 258 259 get loading() { 260 return C.notifications.progress; 261 } 262 263 async created() { 264 const data = await C.getLettreDirecteur(); 265 if (data == undefined) return; 266 this.lettre = data.lettre; 267 this.publicDocument = data.document; 268 C.notifications.success = "Lettre chargée."; 269 if (!this.publicDocument.id_crypted) { 270 // aucune lettre d'enregistrée, on affiche l'info 271 // et on ajoute par défaut le bloc EspacePerso 272 this.lettre.html += paveEspacePerso; 273 // du coup on désactive l'ajout additionnel 274 this.disabledAddPave = true; 275 this.showInfoLettre = true; 276 } 277 } 278 279 addPaveEspacePerso() { 280 this.lettre.html += paveEspacePerso; 281 this.showInfoLettre = false; 282 } 283 doneInfoLettre() { 284 // on re active la fonction ajout pave 285 this.showInfoLettre = false; 286 this.disabledAddPave = false; 287 } 288 async save() { 289 const data = await C.updateLettreDirecteur(this.lettre); 290 if (data == undefined) return; 291 this.lettre = data.lettre; 292 this.publicDocument = data.document; 293 C.notifications.success = "Lettre mise à jour avec succès."; 294 this.showPreview = true; 295 } 296 } 297 </script> 298 299 <style> 300 .content-lettre { 301 height: 90vh; 302 } 303 </style>