Commit 3a32fa41 authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

- Système de réaffectation en cours

- Fix : Erreur au chargement des organisations si les organisations n'ont pas de rôle (Anciennes données ?) Un warning est poussé dans les logs si besoin
parent bd474832
Loading
Loading
Loading
Loading
Loading
+13 −0
Changes for front/gulpfile.js: 13 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -187,6 +187,19 @@ exports.componentRNSRField = componentRNSRField;
exports.componentRNSRFieldWatch = function(cb){ watch('./src/components/RNSRField.vue', componentRNSRField); }


// //// GLOBALE
// function replaceStrengthenPerson(cb) {
//     compile("ReplaceStrengthenPerson");
//     cb();
// }
// exports.replaceStrengthenPerson = replaceStrengthenPerson;
// exports.replaceStrengthenPersonWatch = function(cb){
//     watch([
//         pathModuleSrc + "ReplaceStrengthenPerson.vue",
//         pathModuleSrc + "components/PersonAutoCompleter.vue"
//     ], replaceStrengthenPerson);
// }


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let commands = [
+3 −1
Changes for front/src/ActivityValidator.vue: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -79,13 +79,15 @@
            <h5 class="personcard-header">
              <img :src="'//www.gravatar.com/avatar/' + p.mailMd5 +'?s=40'" alt="" class="personcard-gravatar">
              <div class="personcard-infos">
                <strong>{{ p.person }}</strong><br>
                <strong>{{ p.person }}</strong> <a :href="p.url_show" v-if="p.url_show">Fiche</a>
                <br>
                <small>
                  <i class="icon-mail"></i>
                  {{ p.mail }}
                </small><br>
                Rôle(s) : <strong>{{ p.roles.join(', ') }}</strong>
              </div>

            </h5>
          </article>
        </section>
+160 −41
Changes for front/src/ReplaceStrengthenPerson.vue: 160 added lines, 41 removed lines.
Original line number Diff line number Diff line
<template>
  <div>
    <div class="overlay" v-if="mode != ''">
      <div class="overlay-content" :style="{'overflow': recap ? 'scroll' : 'visible'}">
      <div class="overlay-content" style="overflow: scroll">
        <a href="#" @click.prevent="handlerCancel()" class="overlay-closer">X</a>
        <h1>
          {{ mode }}
          <strong>{{ person }}</strong>
          <strong>{{ person.displayname }}</strong>
        </h1>

        <div class="alert-info alert">
          Remplacer <strong>{{ person }}</strong> par une autre personnes pour la validation des feuilles de temps dans les activités de recherche
          Remplacer <strong>{{ person.displayname }}</strong> par une autre personnes
        </div>

        <div v-if="recapPending">
          <i class="icon-spinner animate-spin"></i>
          {{ recapPending }}
@@ -19,30 +21,127 @@
          <strong>Erreur</strong> :
          {{ errorRecap }}
        </div>
        <div v-else-if="recap" class="alert alert-info">
          <h2>{{ recap.info }}</h2>
          <ul>
            <li v-for="prj in recap.prj">
              <i class="icon-cube"></i><em>Validation project</em> <strong>{{ prj.label }}</strong>
            </li>
            <li v-for="sci in recap.sci">
              <i class="icon-beaker"></i><em>Validation scientifique</em> <strong>{{ sci.label }}</strong>
            </li>
            <li v-for="adm in recap.adm">
              <i class="icon-book"></i><em>Validation administratif</em> <strong>{{ adm.label }}</strong>
            </li>
          </ul>
        <div v-else>
          <p>Choisissez une personne pour {{ mode }}</p>
          <person-auto-completer @change="handlerSelectPerson" style="z-index: 10"/>
        </div>

        <section class="">
          <!-- <h2>INFOS : {{ recap.infos }}</h2> -->
          <section class="affectations" v-if="affectations">
            <section>
              <h2>
                <i class="icon-beaker"></i>
                Activité/projet de recherche
              </h2>

              <section class="projects">
                <h4><i class="icon-cubes"></i> Projets</h4>
                <p v-if="replacer_id">
                  <strong>{{ replacer }}</strong>
                  va être ajouté dans le(s) <strong>{{ affectations.projects.length }}</strong> projet(s) suivant :
                </p>
                <div class="columns-3">
                  <div class="card xs applyable"
                       @click="handlerSwitchApply(p)"
                       v-for="p in affectations.projects" :class="{ 'apply': p.apply }">
                    <div class="">
                      <strong>
                        <i class="icon-cubes"></i>
                        {{ p.acronym }}
                      </strong>
                      <small>{{ p.label }}</small>
                      <span class="badge bg-info on-right">{{ p.activities_count }}</span>
                    </div>
                    HHH
                    <span class="cartouche xs">
                      {{ p.roles.join(', ') }}
                    </span>
                  </div>
                </div>
              </section>

              <h3><i class="icon-cube"></i> Activités</h3>

              <div style="columns: 3">
                <div v-for="p in activities" class="card xs applyable"
                     @click="handlerSwitchApply(p)"
                     :class="{ 'active': p.active, 'disabled': !p.active, 'apply': p.apply }">
                  <div style="border-bottom: solid thin #ccc">
                    <strong>
                      <i class="icon-cube"></i>
                      {{ p.acronym }}
                    </strong>
                    <em>{{ p.label }}</em>
                    <i class="on-right" :class="'icon-status-' + p.status" :title="p.status_text"></i>
                  </div>
                  <small>({{ p.roles.join(', ') }})</small>
                </div>
              </div>
            </section>

            <section>
              <h2>
                <i class="icon-building-filled"></i>
                Structure
              </h2>

                <div v-for="p in structures" class="card xs applyable"
                     @click="handlerSwitchApply(p)"
                     :class="{'apply': p.apply }">
                  <strong>{{ p.label }}</strong>
                  <small>({{ p.roles.join(', ') }})</small>
                </div>

            </section>

            <section>
              <h2>
                <i class="icon-calendar"></i>
                Validation
              </h2>

              <div v-if="affectations.validations.prj">
                <h4><i class="icon-cube"></i>Validation projet</h4>
                <div class="card xs applyable"
                     @click="v.apply = !v.apply; console.log('OK')"
                     v-for="v in affectations.validations.prj"
                     :class="{'apply': v.apply }">
                  <strong>{{ v.acronym }}</strong>
                  <em>{{ v.label }}</em>
                </div>
              </div>

              <div v-if="affectations.validations.sci">
                <h4><i class="icon-beaker"></i>Validation scientifique</h4>
                <div class="card xs applyable"
                     @click="v.apply = !v.apply"
                     v-for="v in affectations.validations.sci"
                     :class="{'apply': v.apply }">
                  <strong>{{ v.acronym }}</strong>
                  <em>{{ v.label }}</em>
                </div>
              </div>

              <div v-if="affectations.validations.adm">
                <h4><i class="icon-book"></i>Validation administratif</h4>
                <div class="card xs applyable"
                     @click="v.apply = !v.apply"
                     v-for="v in affectations.validations.adm"
                     :class="{'apply': v.apply }">
                  <strong>{{ v.acronym }}</strong>
                  <em>{{ v.label }}</em>
                </div>
              </div>
            </section>
          </section>
          <hr>
          <nav class="buttons text-center">
            <button class="btn btn-success" @click="handlerConfirmReplace()">
              Confirmer
            </button>
          </nav>
        </div>
        <div v-else>
          <p>Choisissez une personne pour {{ mode }}</p>
          <person-auto-completer @change="handlerSelectPerson" style="z-index: 10"/>
        </div>
        </section>
      </div>
    </div>

@@ -81,6 +180,9 @@ export default {
    },
    urlStrengthen: {
      required: true
    },
    affectations: {
      required: true
    }
  },

@@ -90,7 +192,14 @@ export default {
      recap: null,
      recapPending: "",
      errorRecap: "",
      error: ""
      error: "",
      replacer: "",
      replacer_id: null,

      projects: {},
      activities: {},
      structures: {},
      validations: {}
    }
  },

@@ -99,36 +208,42 @@ export default {
      this.mode = 'Remplacer';
    },

    handlerSwitchApply(item){
      console.log("handlerSwitchApply", item);
      item.apply = !item.apply;
    },

    /**
     * Récap des changements.
     *
     * @param e
     */
    handlerSelectPerson(e) {
      let data = new FormData();
      this.recapPending = "Chargement";
      data.append("replacer_id", e.id);
      this.$http.post(this.urlReplace, data).then(
          ok => {
            this.recap = ok.body.summary;
          }, ko => {
            if( ko.status == 403 ){
              this.errorRecap = "Non-autorisé";
            } else {
              if( ko.body.error ){
               this.errorRecap = "Erreur : " + ko.body.error;
              } else {
               this.errorRecap = ko.body;
              }
            }
          }
      ).then( foo => this.recapPending = "");
      console.log("handlerSelectPerson");

      this.replacer = e.displayname;
      this.replacer_id = e.id;

      this.recap = {
        "replacer_id": e.id,
        "infos": "Remplacer " + this.person.displayname + " par " + e.displayname,
        "dump": this.person
      };
      console.log(e);
    },

    handlerConfirmReplace(){
      let data = new FormData();
      let out = {
        'projects': this.projects,
        'activities': this.activities,
        'structures': this.structures,
        'validations': this.validations,
        'replacer_id': this.replacer_id
      };
      console.log('OUT', out);
      this.recapPending = "Remplacement...";
      data.append("summary", JSON.stringify(this.recap));
      data.append("out", JSON.stringify(out));

      this.$http.post(this.urlReplace, data).then(
          ok => {
@@ -159,6 +274,10 @@ export default {
  // Lifecycle
  mounted() {
    console.log("mounted");
    this.projects = this.affectations.projects;
    this.activities = this.affectations.activities;
    this.structures = this.affectations.structures;
    this.validations = this.affectations.validations;
  }
}
</script>
 No newline at end of file
+4 −41
Changes for module/Oscar/src/Oscar/Controller/PersonController.php: 4 added lines, 41 removed lines.
Original line number Diff line number Diff line
@@ -663,49 +663,11 @@ class PersonController extends AbstractOscarController implements UsePersonServi
                    // TODO droits d'accès

                    try {
                        $summary = $this->params()->fromPost('summary', null);
                        if($summary != null) {
                            $datas = json_decode($summary, true);
                            $replacer = $this->getPersonService()->getPersonById($datas['replacer_id'], true);
                            $this->getPersonService()->validatorReplace($person, $replacer);
                        $out = $this->params()->fromPost('out', "VIDE");
                        $this->getPersonService()->affectationsReplace($person, json_decode($out, true));
                        return $this->getResponseOk("done");
                        } else {
                            $replacerId = (int)$this->params()->fromPost('replacer_id');
                            $replacer = $this->getPersonService()->getPersonById($replacerId, true);
                            $summary = [
                                "info" => sprintf("Remplacer %s par %s", $person, $replacer),
                                "replacer_id" => $replacer->getId(),
                                "prj" => [],
                                "sci" => [],
                                "adm" => []
                            ];

                            foreach ($person->getValidatorActivitiesPrj() as $activity) {
                                $summary["prj"][] = [
                                    "id" => $activity->getId(),
                                    "label" => $activity->getFullLabel()
                                ];
                            }
                            foreach ($person->getValidatorActivitiesSci() as $activity) {
                                $summary["sci"][] = [
                                    "id" => $activity->getId(),
                                    "label" => $activity->getFullLabel()
                                ];
                            }
                            foreach ($person->getValidatorActivitiesAdm() as $activity) {
                                $summary["adm"][] = [
                                    "id" => $activity->getId(),
                                    "label" => $activity->getFullLabel()
                                ];
                            }

                            $response = $this->baseJsonResponse();
                            $response['summary'] = $summary;
                            return $this->jsonOutput($response);
                        }

                    } catch (\Exception $e) {
                        return $this->getResponseInternalError("Impossible de remplacer $person : " . $e->getMessage());
                        return $this->getResponseInternalError($e->getMessage());
                    }

                    break;
@@ -925,6 +887,7 @@ class PersonController extends AbstractOscarController implements UsePersonServi
            'validations' => $validations,
            'authentification' => $auth,
            'auth' => $auth,
            'affectations' => $this->getPersonService()->getPersonAffectationsArray($person),
            'allowTimesheet' => $allowTimesheet,
            'projects' => new UnicaenDoctrinePaginator($this->getProjectService()->getProjectUser($person->getId()), $page),
            'activities' => $this->getProjectGrantService()->personActivitiesWithoutProject($person->getId()),
+0 −59
Changes for module/Oscar/src/Oscar/Controller/ProjectController.php: 0 added lines, 59 removed lines.
Original line number Diff line number Diff line
@@ -391,65 +391,6 @@ class ProjectController extends AbstractOscarController
            return $this->getResponseInternalError($e->getMessage());
        }

//        /**
//         * @var ActivityPerson $activityPerson
//         */
//        foreach ($activity->getPersonsDeep() as $activityPerson) {
//            if (get_class($activityPerson) == ActivityPerson::class) {
//                $urlDelete = $deletableA ? $this->url()->fromRoute(
//                    'personactivity/delete',
//                    ['idenroll' => $activityPerson->getId()]
//                ) : false;
//                $urlEdit = $editableA ? $this->url()->fromRoute(
//                    'personactivity/edit',
//                    ['idenroll' => $activityPerson->getId()]
//                ) : false;
//                $editable = $editableA;
//                $deletable = $deletableA;
//                $context = "activity";
//                $idEnroller = $activityPerson->getActivity()->getId();
//            } else {
//                $urlDelete = $deletableA ? $this->url()->fromRoute(
//                    'personproject/delete',
//                    ['idenroll' => $activityPerson->getId()]
//                ) : false;
//                $urlEdit = $editableA ? $this->url()->fromRoute(
//                    'personproject/edit',
//                    ['idenroll' => $activityPerson->getId()]
//                ) : false;
//                $editable = $editableP;
//                $deletable = $deletableP;
//                $context = "project";
//                $idEnroller = $activityPerson->getProject()->getId();
//            }
//            $urlShow = false;
//            if ($showable) {
//                $urlShow = $showable ? $this->url()->fromRoute(
//                    'person/show',
//                    ['id' => $activityPerson->getPerson()->getId()]
//                ) : false;
//            }
//
//            $out[] = [
//                'id' => $activityPerson->getId(),
//                'role' => $activityPerson->getRole(),
//                'roleLabel' => $activityPerson->getRole(),
//                'roleId' => $activityPerson->getRoleObj() ? $activityPerson->getRoleObj()->getId() : "",
//                'rolePrincipal' => $activityPerson->isPrincipal(),
//                'urlDelete' => $urlDelete,
//                'context' => $context,
//                'urlEdit' => $urlEdit,
//                'urlShow' => $urlShow,
//                'enroller' => $idEnroller,
//                'enrollerLabel' => $activity->getLabel(),
//                'editable' => $editable,
//                'deletable' => $deletable,
//                'enrolled' => $activityPerson->getPerson()->getId(),
//                'enrolledLabel' => $activityPerson->getPerson()->getDisplayName(),
//                'start' => DateTimeUtils::toStr($activityPerson->getDateStart(), 'Y-m-d'),
//                'end' => DateTimeUtils::toStr($activityPerson->getDateEnd(), 'Y-m-d'),
//            ];
//        }

        return $this->ajaxResponse($out);
    }
Loading