Skip to content
Snippets Groups Projects
FeatureListTable.vue 13.3 KiB
Newer Older

<template>
  <div data-tab="list" class="dataTables_wrapper no-footer">
    <table id="table-features" class="ui compact table">
      <thead>
        <tr>
          <th class="center"></th>

          <th class="center">
            Statut
            <i
              :class="{
                down: isSortedAsc('statut'),
                up: isSortedDesc('statut'),
              }"
              class="icon sort"
              @click="changeSort('statut')"
            />
          </th>
          <th class="center">
            Type
            <i
              :class="{
                down: isSortedAsc('type'),
                up: isSortedDesc('type'),
              }"
              class="icon sort"
              @click="changeSort('type')"
            />
          </th>
          <th class="center">
            Nom
            <i
              :class="{
                down: isSortedAsc('nom'),
                up: isSortedDesc('nom'),
              }"
              class="icon sort"
              @click="changeSort('nom')"
            />
          </th>
          <th class="center">
            Dernière modification
            <i
              :class="{
                down: isSortedAsc('updated_on'),
                up: isSortedDesc('updated_on'),
              }"
              class="icon sort"
              @click="changeSort('updated_on')"
            />
          </th>
          <th class="center" v-if="user">
            Auteur
            <i
              :class="{
                down: isSortedAsc('display_creator'),
                up: isSortedDesc('display_creator'),
              }"
              class="icon sort"
              @click="changeSort('display_creator')"
            />
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(feature, index) in paginatedFeatures" :key="index">
          <td class="center">
            <div class="ui checkbox">
              <input
                type="checkbox"
                :id="feature.id"
                :value="feature.id"
                v-model="checkedFeatures"
                :checked="checkedFeatures[feature.id]"
              />
              <label></label>
            </div>
          </td>

          <td class="center">
            <div
              v-if="feature.properties.status.value === 'archived'"
              data-tooltip="Archivé"
            >
              <i class="grey archive icon"></i>
            </div>
            <div
              v-else-if="feature.properties.status.value === 'pending'"
              data-tooltip="En attente de publication"
            >
              <i class="teal hourglass outline icon"></i>
            </div>
            <div
              v-else-if="feature.properties.status.value === 'published'"
              data-tooltip="Publié"
            >
              <i class="olive check icon"></i>
            </div>
            <div
              v-else-if="feature.properties.status.value === 'draft'"
              data-tooltip="Brouillon"
            >
              <i class="orange pencil alternate icon"></i>
            </div>
          </td>
          <td class="center">
            <router-link
              :to="{
                name: 'details-type-signalement',
                params: {
                  feature_type_slug: feature.properties.feature_type.slug,
                },
              }"
            >
              {{ feature.properties.feature_type.title }}
            </router-link>
          </td>
          <td class="center">
            <router-link
              :to="{
                name: 'details-signalement',
                params: {
                  slug_type_signal: feature.properties.feature_type.slug,
                  slug_signal: feature.properties.slug || feature.id,
                },
              }"
              >{{ getFeatureDisplayName(feature) }}</router-link
            >
          </td>
          <td class="center">
            <!-- |date:'Ymd' -->
            {{ feature.properties.updated_on }}
          </td>
          <td class="center" v-if="user">
            {{ feature.properties.creator.username || " ---- " }}
          </td>
        </tr>
        <tr v-if="filteredFeatures.length === 0" class="odd">
          <td colspan="5" class="dataTables_empty" valign="top">
            Aucune donnée disponible
          </td>
        </tr>
      </tbody>
    </table>
    <div
      id="table-features_info"
      role="status"
      aria-live="polite"
    >
      Affichage de l'élément {{ pagination.start + 1 }} à
      {{ displayedPageEnd }}
      sur {{ filteredFeatures.length }} éléments
    </div>
    <div
      id="table-features_paginate"
      class="dataTables_paginate paging_simple_numbers"
    >
      <a
        @click="toPreviousPage"
        id="table-features_previous"
        :class="[
          'paginate_button previous',
          { disabled: pagination.currentPage === 1 },
        ]"
        aria-controls="table-features"
        data-dt-idx="0"
        tabindex="0"
        >Précédent</a
      >
      <span>
        <a
Timothee P's avatar
Timothee P committed
          v-for="pageNumber in nbPages"
          :key="'page' + pageNumber"
          :class="[
            'paginate_button',
Timothee P's avatar
Timothee P committed
            { current: pageNumber === pagination.currentPage },
          ]"
          aria-controls="table-features"
          data-dt-idx="1"
          tabindex="0"
Timothee P's avatar
Timothee P committed
          >{{ pageNumber }}</a
        >
      </span>
      <!-- // TODO : <span v-if="nbPages > 4" class="ellipsis">...</span> -->
      <a
        id="table-features_next"
        :class="[
          'paginate_button next',
          { disabled: pagination.currentPage === nbPages.length },
        ]"
        aria-controls="table-features"
        data-dt-idx="7"
        tabindex="0"
        @click="toNextPage"
        >Suivant</a
      >
    </div>
  </div>
</template>

<script>
export default {
  name: "FeatureListTable",

  props: ["filteredFeatures", "user", "checkedFeatures"],

  data() {
    return {
      pagination: {
        currentPage: 1,
        pagesize: 15,
        start: 0,
Timothee P's avatar
Timothee P committed
        end: 15,
      },
      sort: {
        column: "",
        ascending: true,
      },
    };
  },

  computed: {
    paginatedFeatures() {
      let filterdFeatures = [...this.filteredFeatures];
      // Ajout du tri
      if (this.sort.column != "") {
        filterdFeatures = filterdFeatures.sort((a, b) => {
          let aProp = this.getFeatureDisplayName(a);
          let bProp = this.getFeatureDisplayName(b);
          if (this.sort.column === "statut") {
            aProp = a.properties.status.value;
            bProp = b.properties.status.value;
          } else if (this.sort.column === "type") {
            aProp = a.properties.feature_type.title;
            bProp = b.properties.feature_type.title;
          } else if (this.sort.column === "updated_on") {
            aProp = a.properties.updated_on;
            bProp = b.properties.updated_on;
          } else if (this.sort.column === "display_creator") {
            aProp = a.properties.display_creator;
            bProp = b.properties.display_creator;
          }
          //ascending
          if (this.sort.ascending) {
            if (aProp < bProp) {
              return -1;
            }
            if (aProp > bProp) {
              return 1;
            }
            return 0;
          } else {
            //descending
            if (aProp < bProp) {
              return 1;
            }
            if (aProp > bProp) {
              return -1;
            }
            return 0;
          }
        });
      }
      return filterdFeatures.slice(this.pagination.start, this.pagination.end);
    },
Timothee P's avatar
Timothee P committed
    nbPages() {
      let N = Math.round(
        this.filteredFeatures.length / this.pagination.pagesize
      );
      const arr = [...Array(N).keys()].map(function (x) {
        ++x;
        return x;
      });
      return arr;
    },

    displayedPageEnd() {
Timothee P's avatar
Timothee P committed
      return this.filteredFeatures.length <= this.pagination.end
        ? this.filteredFeatures.length
Timothee P's avatar
Timothee P committed
        : this.pagination.end;
  },

  methods: {
    getFeatureDisplayName(feature) {
      return feature.properties.title || feature.id;
    },

    isSortedAsc(column) {
      return this.sort.column === column && this.sort.ascending;
    },
    isSortedDesc(column) {
      return this.sort.column === column && !this.sort.ascending;
    },

    changeSort(column) {
      if (this.sort.column === column) {
        //changer order
        this.sort.ascending = !this.sort.ascending;
      } else {
        this.sort.column = column;
        this.sort.ascending = true;
      }
    },

    toPage(pageNumber) {
      const toAddOrRemove =
        (pageNumber - this.pagination.currentPage) * this.pagination.pagesize;
      this.pagination.start += toAddOrRemove;
      this.pagination.end += toAddOrRemove;
      this.pagination.currentPage = pageNumber;
    },

    toPreviousPage() {
      if (this.pagination.start > 0) {
        this.pagination.start -= this.pagination.pagesize;
        this.pagination.end -= this.pagination.pagesize;
        this.pagination.currentPage -= 1;
      }
    },

    toNextPage() {
      if (this.pagination.end < this.filteredFeatures.length) {
        this.pagination.start += this.pagination.pagesize;
        this.pagination.end += this.pagination.pagesize;
        this.pagination.currentPage += 1;
      }
    },
  },
};
</script>

<style scoped>
/* datatables */
.dataTables_wrapper {
  position: relative;
  clear: both;
}
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_processing,
.dataTables_wrapper .dataTables_paginate {
  color: #333;
}
.dataTables_wrapper .dataTables_info {
  clear: both;
  float: left;
  padding-top: 0.755em;
}
.dataTables_wrapper .dataTables_paginate {
  float: right;
  text-align: right;
  padding-top: 0.25em;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
  color: #333 !important;
  border: 1px solid #979797;
  background-color: white;
  background: -webkit-gradient(
    linear,
    left top,
    left bottom,
    color-stop(0%, #fff),
    color-stop(100%, #dcdcdc)
  );
  background: -webkit-linear-gradient(top, #fff 0%, #dcdcdc 100%);
  background: -moz-linear-gradient(top, #fff 0%, #dcdcdc 100%);
  background: -ms-linear-gradient(top, #fff 0%, #dcdcdc 100%);
  background: -o-linear-gradient(top, #fff 0%, #dcdcdc 100%);
  background: linear-gradient(to bottom, #fff 0%, #dcdcdc 100%);
}
.dataTables_wrapper .dataTables_paginate .paginate_button {
  box-sizing: border-box;
  display: inline-block;
  min-width: 1.5em;
  padding: 0.5em 1em;
  margin-left: 2px;
  text-align: center;
  text-decoration: none !important;
  cursor: pointer;
  color: #333 !important;
  border: 1px solid transparent;
  border-radius: 2px;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
  color: white !important;
  border: 1px solid #111;
  background-color: #585858;
  background: -webkit-gradient(
    linear,
    left top,
    left bottom,
    color-stop(0%, #585858),
    color-stop(100%, #111)
  );
  background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
  background: -moz-linear-gradient(top, #585858 0%, #111 100%);
  background: -ms-linear-gradient(top, #585858 0%, #111 100%);
  background: -o-linear-gradient(top, #585858 0%, #111 100%);
  background: linear-gradient(to bottom, #585858 0%, #111 100%);
}
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
  cursor: default;
  color: #666 !important;
  border: 1px solid transparent;
  background: transparent;
  box-shadow: none;
}

i.icon.sort:not(.down):not(.up) {
  color: rgb(220, 220, 220);
}

/* 
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
@media only screen and (max-width: 760px),
  (min-device-width: 768px) and (max-device-width: 1024px) {
  /* Force table to not be like tables anymore */
  table,
  thead,
  tbody,
  th,
  td,
  tr {
    display: block;
  }

  /* Hide table headers (but not display: none;, for accessibility) */
  thead tr {
    position: absolute;
    top: -9999px;
    left: -9999px;
  }

  tr {
    border: 1px solid #ccc;
  }

  td {
    /* Behave  like a "row" */
    border: none;
    border-bottom: 1px solid #eee;
    position: relative;
    padding-left: 50%;
  }

  td:before {
    /* Now like a table header */
    position: absolute;
    /* Top/left values mimic padding */
    /* top: 6px; */
    left: 6px;
    /* width: 45%; */
    padding-right: 10px;
    white-space: nowrap;
  }

  /*
	Label the data
	*/
  td:nth-of-type(1):before {
    content: "";
  }
  td:nth-of-type(2):before {
    content: "Statut";
  }
  td:nth-of-type(3):before {
    content: "Type";
  }
  td:nth-of-type(4):before {
    content: "Nom";
  }
  td:nth-of-type(5):before {
    content: "Dernière modification";
  }
  td:nth-of-type(6):before {
    content: "Auteur";
  }

  .center {
    text-align: right !important;
  }

  #table-features {
    margin-left: 1em;
    width: calc(100% - 1em);
  }

  .ui.checkbox {
    position: absolute;
    left: -1.75em;
    top: 5em;
  }
}
</style>