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

- UI : écran de synthèse des déclarations en temps en cours

parent 0fd55cfe
Loading
Loading
Loading
Loading
Loading
+259 −21
Original line number Diff line number Diff line
@@ -6,15 +6,110 @@
      Synthèse des déclarations
    </button>

    <div class="overlay" v-if="infosPerson">
      <div class="overlay-content" style="flex-basis: 90%; max-height: 90%">
        <h2>
          Détails pour
          <strong>{{ infosPerson.person }}</strong>
          pour <em>{{ infosPerson.period | periodStrFromKey }}</em>

          <a href="#" @click.prevent="infosPerson = null"><i class="icon-cancel-outline"></i></a>
        </h2>

        <a :href="'/feuille-de-temps/document/person' + '?period=' + infosPerson.period +'&format=pdf&person=' +infosPerson.person_id"
           class="btn btn-default">
          <i class="icon-download"></i>
          Télécharger le PDF
        </a>

        <table class="table bordered period-person-details">
          <thead>
          <tr>
            <th> ~</th>
            <th v-for="d, i in infosPerson.days">
              <small>{{ d.label }}</small>
              {{ d.i }}
            </th>
            <th> Total</th>
          </tr>
          </thead>
          <tbody v-for="activity in organize(infosPerson).activities">
            <tr>
              <th :colspan="infosPerson.dayNbr + 2"><h3><i class="icon-cube"></i>{{ activity.acronym }}</h3>
              </th>
            </tr>
            <tr v-for="workpackage in activity.workpackages" class="subline">
              <th>{{ workpackage.code }}</th>
              <td v-for="d, i in infosPerson.days" class="day" :class="{ 'off': d.locked }">
                <strong v-if="workpackage.days[i]">
                  {{ workpackage.days[i] | hours }}
                </strong>
                <small v-else>0.0</small>
              </td>
              <th class="total">{{ workpackage.total | hours }}</th>
            </tr>
            <tr>
              <th>Total</th>
              <td :colspan="infosPerson.dayNbr">&nbsp;</td>
              <th class="total">{{ activity.total | hours }}</th>
            </tr>
          </tbody>
          <tbody>
          <tr>
            <th :colspan="infosPerson.dayNbr + 2"><h3><i class="icon-tags"></i>Hors-lot</h3></th>
          </tr>
          <tr v-for="other in organize(infosPerson).others">
            <th>{{ other.label }}</th>
            <td v-for="d, i in infosPerson.days" class="day" :class="{ 'off': d.locked }">
              <strong v-if="other.days[i]">
                {{ other.days[i] | hours }}
              </strong>
              <small v-else>0.0</small>
            </td>
            <th class="total">{{ other.total | hours }}</th>
          </tr>

          </tbody>
          <tfoot>
          <tr>
            <th>Total</th>
            <th v-for="d, i in infosPerson.days" class="day" :class="{'off': d.locked }">
              <small>{{ d.total | hours }}</small>
            </th>
            <th>{{ infosPerson.total | hours }}</th>
          </tr>
          </tfoot>
        </table>
      </div>
    </div>

    <div class="overlay-content">
      <a href="#" class="overlay-closer" @click="handlerCloseSynthesis()">Close</a>
      <h1>
        <small>Cumul de temps pour</small>
        <strong>
          <i class="icon-cube"></i>
          {{ mainContext }}

        </strong>
      </h1>
      <div v-if="synthese" class="activity-timesheet-synthesis">
        <nav class="text-center">
          <button v-for="p, person_id in persons"
                  class="btn"
                  :class="filterPersons.indexOf(parseInt(person_id)) < 0 ? 'btn-primary' : 'btn-default'"
                  @click="handlerTooglePerson(person_id)">
            {{ p }}
          <h2>
            <i class="icon-users"></i>
            Déclarants :
          </h2>
          <button v-for="p in persons"
                  class="btn btn-xs"
                  :class="filterPersons.indexOf(parseInt(p.id)) < 0 ? 'btn-primary' : 'btn-default'"
                  @click="handlerTooglePerson(p.id)"
                  @click.shift="handlerOnePerson(p.id)"
          >
            <i class="icon-user"></i>
            {{ p.displayname }}
            <small>(
              <i class="icon-clock"></i>
              {{ p.total }} heure(s))</small>
          </button>
        </nav>

@@ -25,7 +120,10 @@
              <i class="icon-angle-down" v-show="y.open"></i>
              {{ y.label }}
            </strong>
            <em class="total" v-show="!y.open">{{ y.totalmain | hours }}</em>
            <em class="total" v-show="!y.open">
              <i class="icon-clock"></i>
              {{ y.totalmain | hours }}
            </em>
          </h3>

          <section v-for="p in y.periods" class="month" v-show="y.open" :class="{'open': y.open }">
@@ -38,10 +136,27 @@
              <em class="total" v-show="!p.open">{{ p.totalmain | hours }}</em>
            </h4>

            <section v-for="pers in p.persons" class="person" v-show="p.open" :class="{'open': p.open }" @click="handlerOpenPerson(pers)">
            <section v-for="pers in p.persons" class="person" v-show="p.open" :class="{'open': p.open }"
                     @click="handlerOpenPerson(pers)">
              <h5 class="line">
                <strong>{{ pers.label }}</strong>
                <em class="total">{{ pers.totalmain | hours }}</em>
                <strong class="person-label">
                  <i class="icon-angle-right" v-show="!pers.open"></i>
                  <i class="icon-angle-down" v-show="pers.open"></i>
                  <i class="icon-user"></i>
                  {{ pers.label }}
                  <small>
                    <a href="#" @click.stop.prevent="details(pers.key, p.key)">
                      <i class="icon-search-outline"></i>Voir la répartition
                    </a>
                    -
                    <a :href="'/feuille-de-temps/document/person' + '?period=' + p.key +'&format=pdf&person=' +pers.key" @click.stop="">
                      <i class="icon-search-outline"></i>Télécharger la feuille de temps
                    </a>
                  </small>
                </strong>
                <em class="total">
                  <i class="icon-clock"></i>
                  {{ pers.totalmain | hours }}</em>
              </h5>
              <section class="details-person" v-if="pers.open">
                <article class="line">
@@ -53,7 +168,6 @@
                  </em>
                </article>
                <section class="othersprojects" v-if="pers.othersprojects.total > 0">

                  <article v-for="projectDuration, projectName in pers.othersprojects.projects" class="line">
                    <strong>
                      <i class="icon-cube"></i> {{ projectName }}
@@ -66,6 +180,7 @@
                <section class="othersprojects" v-if="pers.others.total > 0">
                  <article v-for="otherDuration, otherName in pers.others.context" class="line">
                    <strong>
                      <i :class="'icon-'+otherName"></i>
                      {{ otherName | contextLabel }}
                    </strong>
                    <em>
@@ -75,7 +190,7 @@
                </section>
                <article class="line totalline">
                  <strong>
                    Total pour cette période :
                    Total déclaré pour cette période :
                  </strong>
                  <em>
                    {{ pers.total | hours }}
@@ -124,6 +239,12 @@ node node_modules/.bin/gulp activityTimesheetSynthesisMenu

 */

let periodStrFromKey = function (key) {
  let year = parseInt(key.substring(0, 4));
  let month = parseInt(key.substring(5, 7));
  return periodFullStr(year, month);
};

let periodStr = function (year, month) {
  return year + '-' + (month < 10 ? '0' + month : month);
};
@@ -171,6 +292,9 @@ export default {
      openYear: [],
      openPeriod: [],
      openPerson: [],

      //
      infosPerson: null
    }
  },

@@ -185,6 +309,9 @@ export default {
        return contextsLabels[contextKey];
      }
      return contextKey + "*";
    },
    periodStrFromKey(periodKey) {
      return periodStrFromKey(periodKey);
    }
  },

@@ -311,6 +438,27 @@ export default {
  },

  methods: {
    /**
     * Affiche uniquement la personne.
     *
     * @param id
     */
    handlerOnePerson(id) {
      let personId = parseInt(id);
      this.filterPersons.splice(0, this.filterPersons.length);
      Object.keys(this.persons).forEach(personIdStr => {
        let personIdInt = parseInt(personIdStr);
        if (personIdInt != personId) {
          this.filterPersons.push(personIdInt);
        }
      });
    },

    /**
     * Affiche/Cache le personne.
     *
     * @param id
     */
    handlerTooglePerson(id) {
      let personId = parseInt(id);
      let indexId = this.filterPersons.indexOf(personId);
@@ -321,6 +469,88 @@ export default {
      }
    },

    details: function (personId, period) {
      this.$http.get('/feuille-de-temps/synthesis?person_id=' + personId + '&format=json&period=' + period).then(
          ok => {
            this.infosPerson = ok.data;
          }
      );
    },

    organize(personDatas) {
      let datas = {
        activities: {},
        others: {}
      };

      Object.keys(personDatas.activities).forEach(activityId => {
        var activity = personDatas.activities[activityId];
        datas.activities[activityId] = {
          acronym: activity.acronym,
          id: activity.id,
          label: activity.label,
          total: activity.total,
          workpackages: {},
          days: {}
        };
      });

      Object.keys(personDatas.workpackages).forEach(wpId => {
        var wp = personDatas.workpackages[wpId];
        datas.activities[wp.activity_id].workpackages[wpId] = {
          code: wp.code,
          id: wp.id,
          label: wp.label,
          total: wp.total,
          days: {}
        };
      });

      Object.keys(personDatas.otherWP).forEach(otherKey => {
        var other = personDatas.otherWP[otherKey];
        datas.others[otherKey] = {
          label: other.label,
          code: other.code,
          total: other.total,
          days: {}
        };
      });

      Object.keys(personDatas.days).forEach(date => {
        var day = personDatas.days[date];

        if (day.declarations) {
          day.declarations.forEach(declaration => {
            var wpId = declaration.wp_id;
            var activityId = declaration.activity_id;
            var duration = declaration.duration;

            if (!datas.activities[activityId].days.hasOwnProperty(date)) {
              datas.activities[activityId].days[date] = 0.0;
            }
            datas.activities[activityId].days[date] += duration;

            if (!datas.activities[activityId].workpackages[wpId].days.hasOwnProperty(date)) {
              datas.activities[activityId].workpackages[wpId].days[date] = 0.0;
            }
            datas.activities[activityId].workpackages[wpId].days[date] += duration;
          });
        }
        if (day.othersWP) {
          day.othersWP.forEach(otherInfos => {
            var otherKey = otherInfos.code;
            var duration = otherInfos.duration;
            if (!datas.others[otherKey].days.hasOwnProperty(date)) {
              datas.others[otherKey].days[date] = 0.0;
            }
            datas.others[otherKey].days[date] += duration;
          })

        }
      });
      return datas;
    },

    handlerOpenPerson(person) {
      console.log(person);
      let indexId = this.openPerson.indexOf(person.indexOpen);
@@ -392,11 +622,19 @@ export default {

      datas.synthesis.forEach(e => {
        if (!persons.hasOwnProperty(e.person_id)) {
          persons[e.person_id] = e.displayname;
          persons[e.person_id] = {
            "id": e.person_id,
            "displayname": e.displayname,
            "total": 0.0
          }
        }
        if (contexts.indexOf(e.context) < 0 && e.activity_id != this.mainContextId) {
          contexts.push(e.context)
        }

        if (e.activity_id == this.mainContextId) {
          persons[e.person_id].total += parseFloat(e.duration)
        }
      });

      this.periods = periods;
+1 −1
Original line number Diff line number Diff line
@@ -208,7 +208,7 @@ return array(
                        'validationActivity2', 'validationHWPPerson', 'validatePersonPeriod',
                        'importIcal', 'declarations', 'resumeActivity',
                        'resolveInvalidLabels', 'syntheseActivity', 'synthesisAll', 'synthesisActivityPeriod',
                        'exportActivityDates', 'checkperiod'
                        'exportActivityDates', 'checkperiod', 'documentPerson'
                    ],
                    'roles' => ['user']
                ],
+6 −0
Original line number Diff line number Diff line
@@ -170,6 +170,12 @@ timesheet:
                defaults:
                    action: synthesisActivityPeriod

        document_person:
            type: segment
            options:
                route: /document/person
                defaults:
                    action: documentPerson

        synthesis:
            type: segment
+0 −1
Original line number Diff line number Diff line
@@ -172,7 +172,6 @@ class PublicController extends AbstractOscarController implements UseTimesheetSe
        if( DEBUG_OSCAR ){
            return [];
        }
        die("to test");
    }

    /**
+769 −489

File changed.

Preview size limit exceeded, changes collapsed.

Loading