Commit f26be2af authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

Merge branch 'spartan' into hm/document-classification

parents 2bbe1e60 a165956c
Loading
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -74,6 +74,10 @@ data/documents/public/**
!data/documents/public/.gitkeep
data/documents/request/**
!data/documents/request/.gitkeep
data/generated-documents/activity/**
!data/generated-documents/activity/bordereau.docx
!data/generated-documents/activity/fiche.docx
!data/generated-documents/activity/sample.docx

# Gabarits
data/templates/timesheet_activity_synthesis.html.php
+178 −0
Original line number Diff line number Diff line
<template>
  <!-- Liste des comptes -->
  <section class="account-list admin">

    <transition name="fade">
      <div class="overlay" v-if="editedAccount">
        <div class="overlay-content">
          <h3>
            Modification de la masse budgétaire pour le compte
            <strong>{{ editedAccount.label }}</strong>
            <span class="overlay-closer" @click="editedAccount = null">X</span>
          </h3>
          <p>
            Code OSCAR : <strong>{{ editedAccount.code }}</strong>
            Code Comptable (SIFAC) : <strong>{{ editedAccount.codeFull }}</strong>
          </p>

          <p>
            Choisissez une annexe budgétaire :
            <select name="" id="" class="form-control" v-model="editedAccount.annexe">
              <option value="0">Ignorer</option>
              <option value="1">Traiter comme une recette</option>
              <option :value="masse" v-for="text,masse in masses">{{ text }}</option>
            </select>
          </p>
          <hr>
          <button @click="editedAccount = null" class="btn btn-danger"><i class="icon-cancel-circled"></i>Annuler</button>
          <button @click="handlerPerformEdit" class="btn btn-success"><i class="icon-floppy"></i>Enregistrer</button>
        </div>
      </div>
    </transition>

    <transition name="fade">
      <div class="overlay" v-if="error">
        <div class="overlay-content">
          <h3><i class="icon-bug"></i> ERREUR</h3>
          <pre class="alert-danger alert">{{ error }}</pre>
          <nav class="buttons text-center">
            <button @click="error = null" class="btn btn-default">
              Fermer
            </button>
          </nav>
        </div>
      </div>
    </transition>

    <transition name="fade">
      <div class="overlay" v-if="pending">
        <div class="overlay-content">
          <p class="text-center">
            <i class="animate-spin icon-spinner"></i>
            {{ Pending }}
          </p>
        </div>
      </div>
    </transition>

    <p class="alert alert-info">
      <i class="icon-info-outline"></i>
      Vous trouverez ci-dessous la liste des comptes utilisés dans la remontée des dépenses. Ceux apparaissant en rouge dans cette liste n'ont pas de masse attribués et seront affichés en rouge dans une catégorie <strong>Hors-Masse</strong> dans la zone de synthèse des dépenses de la fiche activité.
    </p>

    <article v-for="a in accounts" class="card account-infos"
             :class="{
                'missing': a.annexe == null,
                'ignored': a.annexe == 0,
                'input': a.annexe == 1
              }">
      <h3>
        <code title="Code utilisé dans SIFAC">
          <a :href="'/activites-de-recherche/advancedsearch?q=&criteria[]=cb2%3B'+a.codeFull" style="color: white">
            {{ a.codeFull }}
          </a>
        </code>
        <strong>
          {{ a.label }}
          <small title="Numéro dans OSCAR">({{ a.code }})</small>
          <a href="#" @click.prevent="handlerEdit(a)" class="btn btn-xs" :class="{ 'btn-primary': a.annexe == null, 'btn-default': a.annexe != null }">
            <i class="icon-edit"></i>
            Modifier l'annexe budgétaire</a>
        </strong>



        <em v-if="a.annexe == '0'" class="off">Ignorée</em>
        <em v-else-if="a.annexe == '1'" class="plus">Recette</em>
        <em v-else-if="a.annexe" class="minus">{{ masses[a.annexe] }}</em>
        <em v-else class="value-missing">AUCUNE</em>
      </h3>
    </article>
  </section>
</template>
<script>
/**
 node node_modules/.bin/vue-cli-service build --name AccountList --dest ../public/js/oscar/dist --no-clean --formats umd,umd-min --target lib src/AccountList.vue
 */
  export default {

    props: {
      url: { default: "" },
      manage: { default: "" }
    },

    data(){
      return {
        accounts: [],
        masses: [],
        editedAccount: null,
        error: "",
        pending: ""
      }
    },

    methods: {

      /**
       * Chargement des comptes utilisés dans OSCAR
       */
      fetch(){
        this.pending = "Chargement des comptes utilisés";
        this.$http.get(this.url).then( ok => {
          this.accounts = ok.data.accounts;
          this.masses = ok.data.masses;
        }, ko => {
          let message = "Erreur inconnue";
          try {
            message = ko.body;
          } catch (e) {
            message = "Erreur JS : " + e;
          }
          this.error = "Impossible de charger des comptes utilisés " + message;
        }).then( this.pending = null )
      },

      /**
       * Affichage de la fenêtre de modification des annexes budgétaires.
       *
       * @param account
       */
      handlerEdit(account){
        this.editedAccount = JSON.parse(JSON.stringify(account));
      },

      /**
       * Envoi des modifications.
       */
      handlerPerformEdit(){
        this.pending = "Enregistrement en cours";
        let accountId = this.editedAccount.id;
        let annexe = this.editedAccount.annexe;
        let data = new FormData();
        data.append('id', accountId);
        data.append('annexe', annexe);
        data.append('action', 'annexe');
        this.$http.post(this.manage, data).then(
          ok => {
            this.editedAccount = null;
            this.fetch();
          }, ko => {
              let message = "";
              console.log(ko.body);
              try {
                message = ko.body;
              } catch (e) {
                message = "Erreur JS : " + e;
              }
              console.log(message);
              this.error = "Impossible de modifier l'annexe budgétaire : " + message;
            }
        );
      }
    },

    mounted() {
      this.fetch();
    }
}
</script>
 No newline at end of file
+5 −3
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@
                    <div>
                        <label for="form_files">Fichiers à ajouter</label>
                        <p class="help">Vous pouvez sélectionner plusieurs fichiers en maintenant la touche CTRL enfoncé lors de la sélection d'un fichier</p>
                        <input type="file" name="files[]" id="form_files">
                        <input type="file" name="files[]" id="form_files" multiple>
                    </div>

                    <div class="alert alert-info">
@@ -265,7 +265,9 @@
    </section>
</template>
<script>
    // poi watch --format umd --moduleName  ActivityRequest --filename.css ActivityRequest.css --filename.js ActivityRequest.js --dist public/js/oscar/dist public/js/oscar/src/ActivityRequest.vue
    // node node_modules/.bin/vue-cli-service build --name ActivityRequest --dest ../public/js/oscar/dist --no-clean --formats umd,umd-min --target lib src/ActivityRequest.vue

    import JCKSelector from "./components/JCKSelector";

    export default {
        data(){
@@ -316,7 +318,7 @@
        },

        components: {
            'jckselector': require('./JCKSelector.vue').default,
            'jckselector': JCKSelector
        },

        methods:{
+105 −12
Original line number Diff line number Diff line
<template>
  <div>

    <template>
      <div class="oscar-ajax" v-show="loading || error">
        <div class="oscar-ajax-content">
@@ -15,7 +14,7 @@
        </div>
      </div>
    </template>
    <code>{{ entityEdited }}</code>

    <div class="overlay" v-if="entityDelete">
      <div class="overlay-content">
        <i class="icon-cancel-outline overlay-closer" @click="entityDelete = null"></i>
@@ -62,6 +61,7 @@
                en tant que <em>{{ entityEdited.role }}</em>
            </span>
          </h2>

          <input type="hidden" name="enroled" class="form-control select2" v-model="entityEdited.enrolled"/>

          <div class="row">
@@ -125,8 +125,8 @@
                        </span>
            <div class="form-group" v-else>
              <label class=" control-label" for="enroled">{{ title }}</label>
              <personselector @change="handlerEnrolledSelected($event)" v-if="title == 'Personne'" v-model="selectedPerson"/>
              <organizationselector @change="handlerEnrolledSelected($event)" v-else/>
              <personselector @change="handlerEnrolledSelectedPerson($event)" v-if="title == 'Personne'" v-model="selected"/>
              <organizationselector @change="handlerEnrolledSelected($event)" v-else v-model="selected" />
            </div>

            <div class="form-group">
@@ -172,7 +172,56 @@
        <i class="icon-doc-add"></i>
        Nouveau
      </a>
      <a class="oscar-link" @click="handlerEditEnable()">
        <i class="icon-edit"></i>
        Modifier
      </a>
    </nav>

    <section v-if="editMode">
      <div class="alert alert-info">
        Détails des affectations. Une personne peut apparaître plusieurs fois selon le contexte et le rôle
      </div>
      <article class="row card" v-for="e in sortedFull">
        <div class="col-md-6">
          <i class="icon-cube" v-if="e.context == 'activity'"></i>
          <i class="icon-cubes" v-else></i>
          <strong>{{ e.enrolledLabel }}</strong>
          <small>
            (<span v-if="e.context == 'activity'">
                <i class="icon-cube"></i>
                {{ e.contextKey }}</span>
              <span v-else>
                <i class="icon-cubes"></i>
                {{ e.contextKey }}</span>)
          </small>
        </div>
        <div class="col-md-3">
          <em :class="{'bold': e.rolePrincipal }">{{ e.roleLabel }}</em>
        </div>
        <div class="col-md-3 text-right">
          <a  @click="handlerEdit(e)" style="white-space: nowrap">
            <i class="icon-pencil-1 icon-clickable" v-if="manage"></i>&nbsp;Modifier
          </a>

          <a  @click="handlerDelete(e)" style="white-space: nowrap">
            <i class="icon-trash icon-clickable" v-if="manage"></i>&nbsp;Supprimer
          </a>
        </div>
      </article>
    </section>
    <section v-else>
      <span class="cartouche" v-for="e in stacked" :class="e.hasPrimary ? 'primary' : 'default' ">
        {{ e.enrolledLabel }}
        <span class="addon principal" >
          <span v-for="r in e.roles" class="addon-module" :class="{'primary': r.rolePrincipal}">
            {{ r.role }}
          </span>
        </span>
      </span>
    </section>

<!--
    <span class="cartouche" v-for="e in entities" :class="{'primary': e.rolePrincipal, 'outofdate past': e.past }">
      <i v-if="e.context == 'activity'" class="icon-cube"></i>
      <i v-else class="icon-cubes"></i>
@@ -184,6 +233,7 @@
        <i class="icon-trash icon-clickable" v-if="manage" @click="handlerDelete(e)"></i>
      </span>
    </span>
-->
  </div>
</template>
<script>
@@ -215,15 +265,48 @@ export default {
  data() {
    return {
      selectedPerson: null,
      selected: null,
      entities: [],
      entityEdited: null,
      entityDelete: null,
      entityNew: null,
      error: null,
      loading: false
      loading: false,
      editMode: false
    };
  },

  computed: {
    sortedFull(){
      console.log("sort");
      return this.entities.sort( (a, b) => a.enrolled - b.enrolled )
    },
    stacked(){
      let stacks = {};
      this.entities.forEach(i => {
        let id = i.enrolled;
        if( !stacks.hasOwnProperty(id) ){
          stacks[id] = {
            enrolled: i.enrolled,
            enrolledLabel: i.enrolledLabel,
            hasPrimary: false
          }
          stacks[id]['roles'] = {};
        }
        stacks[id]['roles'][i.roleId] = {
          role: i.roleLabel,
          roleId: i.roleId,
          rolePrincipal: i.rolePrincipal,
          context: i.context,
        };
        if( i.rolePrincipal ){
          stacks[id].hasPrimary = true;
        }

      })
      return stacks;
    }
  },

  methods: {
    handlerEdit(item) {
@@ -245,7 +328,12 @@ export default {
    },

    handlerEnrolledSelected(data) {
      console.log(data);
      this.entityNew.enroled = data.id;
      this.entityNew.enroledLabel = data.label;
    },

    handlerEnrolledSelectedPerson(data) {
      this.selected = data.id;
      this.entityNew.enroled = data.id;
      this.entityNew.enroledLabel = data.label;
    },
@@ -260,9 +348,12 @@ export default {
      document.location = url;
    },

    handlerEditEnable() {
      this.editMode = !this.editMode;
    },

    performDelete() {
      this.loading = "Suppression...";
      console.log(url, this.entityDelete);
      var url = this.entityDelete.urlDelete;
      this.entityDelete = null;

@@ -298,7 +389,8 @@ export default {
    performNew() {
      let data = new FormData();
      this.loading = "Création...";
      var enroled = this.entityNew.enroled;
      console.log("ENTITYNEW:", JSON.stringify(this.entityNew));
      var enroled = this.selected;
      data.append('dateStart', this.entityNew.start);
      data.append('dateEnd', this.entityNew.end);
      data.append('role', this.entityNew.role);
@@ -338,6 +430,7 @@ export default {
  },

  mounted() {
    console.log("MOUNTED");
    this.fetch();
  }
}
+106 −0
Original line number Diff line number Diff line
<template>
  <div>
    <button @click="handlerDisplayUi()" class="btn btn-primary">
      Migration des numérotations
      TEST
    </button>
    <div class="overlay" v-if="display">
      <div class="overlay-content">
        <h3 v-if="message">
          {{ message }}
        </h3>
        <article class="row" v-else>
          <div class="col-md-12">
            <h3>Outils de migration de clef de numérotation</h3>
            <p class="alert alert-info">
              Cette écran permet de mettre à jour automatiquement les activités utilisant certaines clefs vers une des clefs déclarée dans la liste des clefs configurer. <strong>Les valeurs sont concervées.</strong>
            </p>
          </div>
          <div class="col-md-6">
            Déplacer la clef :
            <select name="from" v-model="formData.from">
              <option value="">Selectionnez un clef à déplacer</option>
              <option v-for="k in unreferencedSorted" :value="k">{{ k }}</option>
            </select>
          </div>
          <div class="col-md-6">
            vers la clef :
            <select name="to" id="" v-model="formData.to">
              <option value="">Choisir une clef</option>
              <option v-for="dest in referenced" :value="dest">{{ dest }}</option>
            </select>
          </div>
        </article>
        <hr>
        <nav class="buttons">
          <button @click="handlerHideUi()" class="btn btn-danger">
            Fermer
          </button>
          <button v-if="!message" @click="handlerSave()"
                  class="btn btn-success"
                  :class="{'disabled': !formData.from || !formData.to }">
            Enregistrer
          </button>
        </nav>
      </div>
    </div>
  </div>
</template>
<script>
// node node_modules/.bin/vue-cli-service build --name NumberMigrate --dest ../public/js/oscar/dist --no-clean --formats umd,umd-min --target lib src/NumberMigrate.vue
export default {
  data(){
    return {
      display: false,
      formData: {
        from: "",
        to: ""
      },
      message: "",
      unreferenced: [],
      referenced: []
    }
  },
  computed: {
    unreferencedSorted(){
      return this.unreferenced.sort();
    }
  },
  methods:{
    handlerSave(){
      let form = new FormData();
      form.append("from", this.formData.from);
      form.append("to", this.formData.to);
      this.$http.post('?action=migrate', form).then(
          ok => {
            this.$emit("migrate");
            this.message = ok.data;
          },
          ko => {
            this.message = ko.data;
          }
      )
    },

    handlerDisplayUi(){
      this.display = true;
      this.$http.get('?action=migrate').then(
          ok => {
            console.log('OK', ok);
            this.unreferenced = ok.data.unreferenced;
            this.referenced = ok.data.referenced;
          },
          ko => {
            this.message = ko.data;
          }
      )
    },
    handlerHideUi(){
      this.display = false;
      if( this.message ){
        document.location.reload();
      }
    }
  }
}
</script>
 No newline at end of file
Loading