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>