Commit ea7eb7bc 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 e70eae5c
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
@@ -669,49 +669,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;
@@ -931,6 +893,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