Rule.vue 11.3 KB
Newer Older
1
<template>
David Foucher's avatar
David Foucher committed
2
  <div id="Rule">
3
    <div class="mb-5">
4
      <div class="row mb-3">
5
        <div  class="col-md-6 col-sm-12 col-xs-12">
6
          <h5>
7
            <span style="vertical-align:-30%" >{{ displayedName }}</span>
8
          </h5>
9
          <span v-if="this.modification_count" @click="displayModification()" style="cursor:pointer">({{ this.modification_count }} modification<span v-if="this.modification_count > 1">s</span> en cours)</span>
10
        </div>
11
        <div class="col-md-6 col-sm-12 col-xs-12">
12
          <h4 v-if="isEditMode" class="pull-right"><em>Modification de la règle</em></h4>
13
          <input v-else v-b-modal.auth-modal type="button" class="main-button btn pull-right" value="Soumettre une modification"/>
14
          <!-- TODO: show gitlab link of modification if exists -->
15 16
        </div>
      </div>
17

18 19 20 21 22
      <div v-show="!isEditMode" class="row">
        <div class="col-md-12">
          <span v-html="printRulePath"></span>
        </div>
      </div>
23
    </div>
24 25 26 27 28 29
    <div v-if="viewModification">
      <div v-for="modification in modification_list" :key="modification.id">
        <Modification :modification="modification"/>
      </div>
    </div>
    <div v-show="!isEditMode && !viewModification">
30 31
      <ul>
        <TreeItem class="item" :item="this.ruleTree" :rootElement="true" :rulePath="this.rulePath"></TreeItem>
32 33 34
      </ul>
    </div>
    <div v-show="isEditMode">
35 36 37 38 39 40 41 42
      <div class="row mb-3">
        <div class="col-md-6 pl-0">
          <input @click="closeEdit" type="button" class="btn btn-outline-danger pull-left" value="Annuler"/>
        </div>
        <div class="col-md-6 pr-0">
          <button v-b-modal.mail-modal class="btn btn-outline-success pull-right">Enregistrer</button>
        </div>
      </div>
43 44
      <div class="container">
        <div class="row mb-3">
45
          <label for="content"><u>Contenu de la règle</u></label>
46
          <textarea-autosize id="content" v-model="content" class="rule-modification-text" :class="{editErrorClass: notModified}"></textarea-autosize>
47
          <span v-if="notModified" class="text-danger font-weight-light">Aucune modification n'a été renseignée</span>
48
        </div>
49 50 51 52 53
        <div class="row mb-3">
          <div class="col-md-6 pl-0">
            <input @click="closeEdit" type="button" class="btn btn-outline-danger pull-left" value="Annuler"/>
          </div>
          <div class="col-md-6 pr-0">
54
            <button v-b-modal.mail-modal class="btn btn-outline-success pull-right">Enregistrer</button>
55
          </div>
56
        </div>
57

58
        <b-modal id="auth-modal" title="Authentifiez-vous pour soumettre une modification">
59
          <label for="contributor_email" class="pb-2"><u>Votre email</u> *</label><br>
60 61 62 63
          <input id="contributor_email" v-model="auth.user" type="text" :class="{editErrorClass: (badUser || noUser)}" class="form-control" style="border: 1px solid #bfbfbf; border-radius: 2px;"/><br>
          <span v-if="noUser" class="mt-0 text-danger font-weight-light">Ce champ est obligatoire</span><br>
          <label for="contributor_passwd" class="pb-2"><u>Votre mot de passe</u> *</label><br>
          <input id="contributor_passwd" v-model="auth.pass" type="password" :class="{editErrorClass: (badUser || noPass)}" class="form-control" style="border: 1px solid #bfbfbf; border-radius: 2px;"/><br>
64
          <span v-if="badUser" class="text-danger font-weight-light">Cet utilisateur n'est pas autorisé à soumettre des modifications</span>
65 66 67 68 69 70 71 72 73 74 75 76
          <span v-if="noPass" class="text-danger font-weight-light">Ce champ est obligatoire</span>
          <span v-if="!noUser && !noPass" class="font-weight-light">* Champs obligatoires</span>
          <template v-slot:modal-footer>       
            <input @click="auth_to_edit" type="button" class="btn btn-outline-success pull-right" value="Suivant"/>
          </template>
        </b-modal>

        <b-modal id="mail-modal" title="Soumettre votre modification">
          <label for="comment" class="mb-2"><u>Résumé de la modification</u> * </label>
          <textarea id="comment" v-model="comment" :class="{editErrorClass: noResume}" rows="3"></textarea>
          <span v-if="noResume" class="text-danger font-weight-light">Ce champ est obligatoire</span>
          <span v-if="!noUser && !noResume" class="font-weight-light">* Champ obligatoire</span>
77 78 79 80 81
          <template v-slot:modal-footer>       
            <input @click="save" type="button" class="btn btn-outline-success pull-right" value="Enregistrer"/>
          </template>
        </b-modal>

82 83
      </div>
    </div>
84
  </div>
85

86 87
</template>
<script>
88
  import TreeItem from './TreeItem.vue';
89
  import Modification from './Modification.vue';
90 91 92 93 94 95 96

  function Node(name) {
    this.name = name;
    this.parent = null;
    this.children = [];
  }

David Foucher's avatar
David Foucher committed
97
  export default {
98
    name: 'Rule',
99 100
    components: {
      TreeItem,
101
      Modification
102
    },
103
    props: ['name', 'data', 'path', 'printRulePath', 'rulePath'],
104 105 106 107 108
    data: function(){
      return {
        ruleData: this.data,
        content: '',
        comment: '',
109 110 111 112
        auth: {
          user: '',
          pass: ''
        },
113 114 115 116
        isEditMode: '',
        modification_list: [],
        badUser: false,
        notModified: false,
117 118 119 120
        noUser: false,
        noPass: false,
        noResume: false,
        viewModification: false,
121 122
      }
    },
123
    beforeMount: function() {
124 125
      this.loadInProgressModification();
    },
126
    computed: {
127 128 129 130
      displayedName: function () {
        return this.name.split('.')[0];
      },
      modification_count: function () {
131
        return Object.keys(this.modification_list).length;
132
      },
133 134 135 136 137 138 139
      ruleTree: function() {
        return this.toTree(this.ruleData.split('\n'));
      },
      ruleToEdit: function() {
        return this.ruleData;
      },
    },
140
    methods: {
141 142
      loadInProgressModification: function () {
        this.$http
143
          .get('/source/modified?branch='+encodeURIComponent(this.displayedName))
144
          .then(response => {
145 146 147 148 149
            this.modification_list = response.body;
            return true;
          }, response => {
            if(response.status == 500) this.modification_list = {};
            return false;
150 151
          })
      },
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
      auth_to_edit: function () {
        this.noUser = false;
        this.noPass = false;

        if (this.auth.user== '' ) {
          this.noUser = true;
        }
        if (this.auth.pass== '' ) {
          this.noPass = true;
          return false;
        }
        /*this.$http
          .post('/source/authentification', this.auth)
          .then(() => {
            this.content = this.ruleToEdit;
            this.isEditMode=!this.isEditMode;
            this.$bvModal.hide("auth-modal");
          }, error => { 
            if (error.status == 401) {
              this.badUser = true;
              this.noUser = false;
              this.noResume = false;
            }
            else if (error.status == 422) {
              if (error.body.args == "`user` est vide") {
                this.noUser = true;
                this.badUser = false;
              } else if (error.body.args == "`pass` est vide") {
                this.noResume = true;
                this.noUser = false;
              }
              this.badUser = false;
            }
          });*/

          this.$parent.collapsed = true;
          this.content = this.ruleToEdit;
          this.isEditMode=!this.isEditMode;
          this.$bvModal.hide("auth-modal");
191 192 193 194
      },
      closeEdit: function () {
        this.content = this.ruleToEdit;
        this.comment = "";
195
        this.auth = "";
196 197 198 199
        this.isEditMode=!this.isEditMode;
      },
      save: function() {
        this.ruleData = this.content
200 201 202 203
        if (this.comment == '') {
          this.noResume = true;
          return false;
        }
204
        const postData = {
205 206
          author_email:this.auth.user,
          author_name:this.auth.user.split("@")[0],
207
          title: this.displayedName,
208 209
          comment: this.comment,
          content: this.content,
210
          filename: 'trefle/config/rules/' + this.path
211 212 213 214 215
        }

        this.$http
          .post('/source/save', postData)
          .then(response => {
216 217 218 219 220
            var commit = {}
            commit.url = 'https://beta.pole-emploi.fr/open-source/trefle/commit/' + response.id
            commit.title = response.title
            this.$parent.rules[this.name]['data'] = this.data
            this.$parent.rules[this.name]['gitlab'] = {'commit': commit}
221 222
            this.$bvModal.hide("mail-modal");
            return this.isEditMode=!this.isEditMode            
223 224
          }, error => {
              if(error.status == 304){
225
                this.notModified = true;
226 227
                this.noUser = false;
                this.noResume = false;
228
                this.badUser = false;
229
                this.$bvModal.hide("mail-modal");
230
              } 
231
              else if (error.status == 401) {
232
                this.badUser = true;
233 234 235 236 237 238 239 240 241 242 243 244 245
                this.noUser = false;
                this.notModified = false;
                this.noResume = false;
              }
              else if (error.status == 422) {
                if (error.body.args == "`author_email` est vide") {
                  this.noUser = true;
                  this.badUser = false;
                } else if (error.body.args == "`comment` est vide") {
                  this.noResume = true;
                  this.noUser = false;
                }
                this.badUser = false;
246 247 248
                this.notModified = false;
              }
              return false;
249 250 251
          });
      },
      toTree: function (lines) { // eslint-disable-line no-unused-vars
252
        var root= new Node(this.name.split('.')[0]);
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
        var currentIndent=-1;
        var currentNode=root;
        // we scan the rules line by line
        for (var i=0;i<lines.length;i++) {
          var line=lines[i];
          if (line.match(/^\s*$/)) continue; // Empty line, skip
          var indent=line.search(/\S|$/); // number of indenting spaces
          var newNode= new Node(line.trim());
          if (indent>currentIndent) { // New child
            // Set the new node parent
            newNode.parent=currentNode;
            // attach the new node to its parent
            currentNode.children.push(newNode);
            // Set the new current node
            currentNode=newNode;
            currentIndent=indent;
          } else if (indent<currentIndent){
            // Move up in the tree
            var level=currentIndent-indent;
            for (var j=0;j<level/4;j++) {
              // up one level
              currentNode=currentNode.parent;
              currentIndent=currentIndent-4;
            }
            newNode.parent=currentNode.parent;
            currentNode.parent.children.push(newNode); // Add a sibbling
            currentNode=newNode;
          } else {
            // Add as sibbling
            newNode.parent=currentNode.parent;
            currentNode.parent.children.push(newNode);
            currentNode=newNode;
          }
        }
        return root;
288 289 290 291
      },
      displayModification: function () {
        this.viewModification = !this.viewModification;
        this.$parent.collapsed = true;
292
      }
293
    },
David Foucher's avatar
David Foucher committed
294 295
  }
</script>
296
<style scoped>
297 298 299
.editErrorClass {
  color: #dc3545;
  border: 1px solid #dc3545;
300 301
  border-radius:3px;
}
302 303 304
.rule-modification-text {
  font-family: 'Courier New', Courier, monospace;
}
305 306 307 308 309

textarea {
  border: 1px solid #bfbfbf;
  border-radius: 2px;
}
310

311
</style>