github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/directeurs/src/components/photos/InviteContacts.vue (about) 1 <template> 2 <v-card> 3 <v-dialog v-model="showNouvelleAdresse" max-width="300"> 4 <v-card> 5 <v-card-title class="headline">Ajouter une adresse mail</v-card-title> 6 <v-card-text> 7 <v-text-field 8 ref="newAdress" 9 label="Adresse mail" 10 v-model="nouvelleAdresse" 11 :rules="[v => isEmailValid(v) || 'Mail non accepté par JOOMEO']" 12 ></v-text-field> 13 </v-card-text> 14 <v-card-actions> 15 <v-spacer></v-spacer> 16 <v-btn @click="ajouteMail" class="success">Ajouter</v-btn> 17 </v-card-actions> 18 </v-card> 19 </v-dialog> 20 21 <v-dialog v-model="confirmeInvite" max-width="500"> 22 <v-card> 23 <v-card-title>Confirmer</v-card-title> 24 <v-card-text> 25 Confirmez-vous l'ajout de 26 <b>{{ validMails.length }}</b> 27 contact(s) (en lecture) à cet album ? 28 <div v-if="inviteWithMail"> 29 Un <b>mail d'invitation</b> sera envoyé. 30 <div v-if="invalidMails.length > 0"> 31 <br />Attention, les adresses mails suivantes sont invalides : 32 <br /> 33 <div class="text-center"> 34 <span 35 v-for="im in invalidMails" 36 :key="im" 37 class="warning--text" 38 > 39 {{ im }} 40 <br /> 41 </span> 42 </div> 43 </div> 44 </div> 45 <p v-else> 46 <b>Aucun mail</b> ne sera envoyé. Les identifiants Joomeo seront 47 accessibles sur les espaces personnels des contacts. 48 </p> 49 </v-card-text> 50 <v-card-actions> 51 <v-btn @click="confirmeInvite = false" class="warning">Annuler</v-btn> 52 <v-spacer></v-spacer> 53 <v-btn class="success" @click="invite">Inviter</v-btn> 54 </v-card-actions> 55 </v-card> 56 </v-dialog> 57 58 <v-card-title class="headline small-padding" 59 >Inviter des contacts</v-card-title 60 > 61 <v-card-text> 62 <v-container> 63 <v-layout row> 64 <v-flex xs="12" md="6"> 65 <v-layout column> 66 <v-flex> 67 <v-checkbox 68 v-model="inclutResponsables" 69 label="Inclure les responsables des participants" 70 ></v-checkbox> 71 </v-flex> 72 <v-flex> 73 <v-checkbox 74 v-model="inclutInscrits" 75 label="Inclure les participants" 76 ></v-checkbox> 77 </v-flex> 78 <v-flex> 79 <v-checkbox 80 v-model="inclutEquipiers" 81 label="Inclure les équipiers" 82 ></v-checkbox> 83 </v-flex> 84 </v-layout> 85 </v-flex> 86 87 <v-flex xs="12" md="6"> 88 <v-toolbar dense> 89 <v-toolbar-title>Adresses mails</v-toolbar-title> 90 <v-spacer></v-spacer> 91 <v-toolbar-items> 92 <tooltip-btn 93 tooltip="Ajouter une adresse mail" 94 @click="setupNouvelleAdresse" 95 icon 96 > 97 <v-icon color="success">{{ $icons["mdi-plus"] }}</v-icon> 98 </tooltip-btn> 99 </v-toolbar-items> 100 </v-toolbar> 101 <v-list dense class="fixed-height"> 102 <v-list-item v-for="mail in mails" :key="mail.mail"> 103 <v-list-item-content>{{ mail.mail }}</v-list-item-content> 104 <v-list-item-action 105 v-if="mail.categorie == 'custom'" 106 class="my-1" 107 > 108 <v-btn small @click="supprimeMail(mail.mail)" icon> 109 <v-icon color="red">{{ $icons["mdi-delete"] }}</v-icon> 110 </v-btn> 111 </v-list-item-action> 112 </v-list-item> 113 </v-list> 114 </v-flex> 115 </v-layout> 116 </v-container> 117 </v-card-text> 118 <v-card-actions> 119 <v-btn @click="askInvite(false)" class="warning" small 120 >Ajouter sans envoi de mail</v-btn 121 > 122 <v-spacer></v-spacer> 123 <v-btn @click="askInvite(true)" class="success">Inviter par mail</v-btn> 124 </v-card-actions> 125 </v-card> 126 </template> 127 128 <script lang="ts"> 129 import Vue from "vue"; 130 import Component from "vue-class-component"; 131 import TooltipBtn from "@/components/TooltipBtn.vue"; 132 133 // Joomeo special case of mails, stricter 134 const patternMail = /^[A-Z0-9._%+-]{1,64}@(?:[A-Z0-9-]{1,63}\.){1,125}[A-Z]{2,63}$/i; 135 136 const InviteContactsProps = Vue.extend({ 137 props: { 138 mailsEquipiers: Array as () => string[], 139 mailsInscrits: Array as () => string[], 140 mailsResponsables: Array as () => string[] 141 } 142 }); 143 144 type Categorie = "custom" | "equipe" | "inscrits" | "responsables"; 145 146 @Component({ 147 components: { TooltipBtn } 148 }) 149 export default class InviteContacts extends InviteContactsProps { 150 showNouvelleAdresse = false; 151 nouvelleAdresse = ""; 152 inclutEquipiers = false; 153 inclutInscrits = false; 154 inclutResponsables = false; 155 inviteWithMail = true; 156 confirmeInvite = false; 157 mailsCustom: string[] = []; 158 159 $refs!: { 160 newAdress: Vue; 161 }; 162 get mails() { 163 const l: { [key: string]: { mail: string; categorie: Categorie } } = {}; 164 this.mailsCustom.map(m => (l[m] = { mail: m, categorie: "custom" })); 165 if (this.inclutEquipiers) { 166 this.mailsEquipiers.map(m => (l[m] = { mail: m, categorie: "equipe" })); 167 } 168 if (this.inclutInscrits) { 169 this.mailsInscrits.map(m => (l[m] = { mail: m, categorie: "inscrits" })); 170 } 171 if (this.inclutResponsables) { 172 this.mailsResponsables.map( 173 m => (l[m] = { mail: m, categorie: "responsables" }) 174 ); 175 } 176 return Object.values(l); 177 } 178 get validMails() { 179 return this.mails.map(m => m.mail).filter(this.isEmailValid); 180 } 181 get invalidMails() { 182 return this.mails.map(m => m.mail).filter(v => !this.isEmailValid(v)); 183 } 184 185 isEmailValid(value: string) { 186 return patternMail.test(value); 187 } 188 setupNouvelleAdresse() { 189 this.showNouvelleAdresse = true; 190 setTimeout(() => { 191 // on attends le rendering du form 192 const input = this.$refs.newAdress.$el.querySelector( 193 "input" 194 ) as HTMLInputElement; 195 input.select(); 196 }, 50); 197 } 198 ajouteMail() { 199 this.mailsCustom.push(this.nouvelleAdresse); 200 this.showNouvelleAdresse = false; 201 } 202 supprimeMail(mail: string) { 203 this.mailsCustom = this.mailsCustom.filter(m => !(m == mail)); 204 } 205 askInvite(withMail: boolean) { 206 this.inviteWithMail = withMail; 207 this.confirmeInvite = true; 208 } 209 invite() { 210 this.confirmeInvite = false; 211 this.$emit("invite", this.inviteWithMail, this.validMails); 212 } 213 } 214 </script> 215 216 <style> 217 .fixed-height { 218 height: 300px; 219 overflow-y: auto; 220 } 221 222 .small-padding { 223 padding-bottom: 2px; 224 padding-top: 2px; 225 } 226 </style>