From ed48e12d8adbdde9433c55dc20035f61778cdc48 Mon Sep 17 00:00:00 2001 From: paidge <paidge_cs@hotmail.com> Date: Mon, 20 Dec 2021 04:56:35 +0100 Subject: [PATCH] =?UTF-8?q?am=C3=A9liorer=20la=20vue=20d'un=20membre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/css/_bootstrap.scss | 4 +- components/certif/List.vue | 33 +++++++++++ layouts/default.vue | 1 + nuxt.config.js | 1 + package-lock.json | 11 ++++ package.json | 1 + pages/hash/_hash.vue | 103 ++++++++++++++++++++--------------- pages/soin.vue | 109 +++++++++++++++++++++++++++++++++++++ plugins/filters.js | 9 +++ 9 files changed, 225 insertions(+), 47 deletions(-) create mode 100644 components/certif/List.vue create mode 100644 pages/soin.vue create mode 100644 plugins/filters.js diff --git a/assets/css/_bootstrap.scss b/assets/css/_bootstrap.scss index 2b295d5..80d8123 100644 --- a/assets/css/_bootstrap.scss +++ b/assets/css/_bootstrap.scss @@ -18,10 +18,10 @@ // @import "~bootstrap/scss/custom-forms"; @import "~bootstrap/scss/nav"; @import "~bootstrap/scss/navbar"; -// @import "~bootstrap/scss/card"; + @import "~bootstrap/scss/card"; @import "~bootstrap/scss/breadcrumb"; // @import "~bootstrap/scss/pagination"; -// @import "~bootstrap/scss/badge"; + @import "~bootstrap/scss/badge"; // @import "~bootstrap/scss/jumbotron"; // @import "~bootstrap/scss/alert"; // @import "~bootstrap/scss/progress"; diff --git a/components/certif/List.vue b/components/certif/List.vue new file mode 100644 index 0000000..81a1875 --- /dev/null +++ b/components/certif/List.vue @@ -0,0 +1,33 @@ +<template> +<ul class="list-group"> + <li class="list-group-item" v-for="certif in certifs"> + <div>{{ getNeighbor(certif) }}</div> + <small class="text-muted">Expire le {{ certif.expires_on | formatDate }}</small> + </li> +</ul> +</template> + +<script> +export default { + props : { + certifs : Array, + type : { + type: String, + required: true, + validator: function (value) { + const types = ['recieved','sent'] + return types.indexOf(value) !== -1 + } + } + }, + methods : { + getNeighbor(certif) { + return this.type == "recieved" ? certif.from.uid : certif.to.uid + } + } +} +</script> + +<style> + +</style> \ No newline at end of file diff --git a/layouts/default.vue b/layouts/default.vue index 35fe300..6ea2fbb 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -16,6 +16,7 @@ export default { items : [ {path: '/appolo',title: 'Appolo'}, {path: '/chartjs',title: 'ChartJS'}, + {path: '/soin',title: 'Prendre soin de ses contacts'} ]}, { title: 'Un menu', diff --git a/nuxt.config.js b/nuxt.config.js index f1c0d97..1218695 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -26,6 +26,7 @@ export default { // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins plugins: [ + '~plugins/filters.js' ], // Auto import components: https://go.nuxtjs.dev/config-components diff --git a/package-lock.json b/package-lock.json index fcad10c..1b527d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "bootstrap": "^4.6.0", "chart.js": "^3.6.2", "core-js": "^3.15.1", + "dayjs": "^1.10.7", "graphql-tag": "^2.12.6", "nuxt": "^2.15.8", "nuxt-purgecss": "^1.0.0" @@ -9590,6 +9591,11 @@ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" }, + "node_modules/dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "node_modules/de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -29164,6 +29170,11 @@ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" }, + "dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", diff --git a/package.json b/package.json index 65cfb1d..569e357 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "bootstrap": "^4.6.0", "chart.js": "^3.6.2", "core-js": "^3.15.1", + "dayjs": "^1.10.7", "graphql-tag": "^2.12.6", "nuxt": "^2.15.8", "nuxt-purgecss": "^1.0.0" diff --git a/pages/hash/_hash.vue b/pages/hash/_hash.vue index db76383..9621541 100644 --- a/pages/hash/_hash.vue +++ b/pages/hash/_hash.vue @@ -1,5 +1,5 @@ <template> - <main class="content"> + <main class="content container"> <div class="spinner-border text-primary mx-auto d-block mb-3" role="status" @@ -7,31 +7,38 @@ <span class="sr-only">Loading...</span> </div> <div v-if="!$apollo.queries.idFromHash.loading"> - <h2 class="display-2 text-center mb-5">{{ idFromHash.uid }}</h2> <div class="row"> - <div class="col-8 m-auto"> - <div class="table-responsive"> - <table class="table striped"> - <thead> - <th>Champ</th> - <th>Valeur</th> - </thead> - <tbody> - <tr v-for="(value, propertyName) in idFromHash" :key="propertyName"> - <td>{{ propertyName }}</td> - <td>{{ value }}</td> - </tr> - </tbody> - </table> + <div class="col-6 mx-auto mt-3"> + <div class="card"> + <div class="card-body"> + <h2 class="card-title">{{ idFromHash.uid }} <small><span class="badge badge-secondary">{{ idFromHash.status }}</span></small></h2> + <div class="card-subtitle mb-2 text-muted">{{ idFromHash.pubkey }}</div> + <div> Référent : {{ isReferent ? 'Oui' : 'Non' }}</div> + <div> Qualité : {{ Math.round(idFromHash.quality.ratio*100)/100 }}</div> + <div> Date limite d'adhésion : {{ idFromHash.limitDate | formatDate }}</div> + <div> Date avant de manquer de certifs : {{ idFromHash.received_certifications.limit | formatDate }}</div> + <div> Pourra certifier à partir du : {{ idFromHash.minDatePassed || 'Déjà dispo' }}</div> + <div> Nbre de certifs disponibles : {{ 100-idFromHash.sent_certifications.length }}</div> + </div> </div> </div> </div> + <div class="row mt-3"> + <div class="col-6"> + <h3>Certifications reçues</h3> + <CertifList :certifs="idFromHash.received_certifications.certifications" type="recieved" /> + </div> + <div class="col-6"> + <h3>Certifications envoyées</h3> + <CertifList :certifs="idFromHash.sent_certifications" type="sent" /> + </div> + </div> </div> </main> </template> <script> -import gql from "graphql-tag"; +import gql from "graphql-tag" export default { data() { @@ -39,53 +46,53 @@ export default { return {}; }, // Fonctions locales - methods: {}, + methods: { + + }, apollo: { idFromHash: { query: gql` query Search($hash: Hash!) { idFromHash(hash: $hash) { + ...memberAttributes pubkey - uid - status - hash - membership_pending - membership_pending_block { - number - } - membership_pending_limitDate - id_written_block { - number - } - lastApplication { - number - } - limitDate isLeaving sentry - received_certifications { - limit + minDate + minDatePassed + membership_pending + limitDate + quality { + ratio } distance { value { ratio } + dist_ok } - distanceE { - value { - ratio + received_certifications { + limit + certifications { + from { + ...memberAttributes + } + expires_on } } - quality { - ratio - } - qualityE { - ratio + sent_certifications { + to { + ...memberAttributes + } + expires_on } - minDate - minDatePassed } } + fragment memberAttributes on Identity { + uid + hash + status + } `, variables() { return { hash: this.$route.params.hash }; @@ -99,6 +106,12 @@ export default { // Mise à jour du fil d'ariane au chargement $nuxt.$emit("changeRoute", this.breadcrumb); }, + computed: { + isReferent () { + const nb_certifs_referent = 5 + return this.idFromHash.received_certifications.certifications.length > nb_certifs_referent && this.idFromHash.sent_certifications.length > nb_certifs_referent + } + } }; </script> diff --git a/pages/soin.vue b/pages/soin.vue new file mode 100644 index 0000000..e8d99b8 --- /dev/null +++ b/pages/soin.vue @@ -0,0 +1,109 @@ +<template> +<main class="content"> + <h2 class="display-2 text-center mb-5">Prendre soin de ses contacts</h2> + <div class="row mb-4"> + <div class="col-6 m-auto text-center"> + <label for="rech" class="form-label">Votre recherche</label> + <input type="text" class="form-control" id="rech" aria-describedby="rechHelp" v-model="param" autocomplete="off"> + <small id="rechHelp" class="form-text text-muted">Saisissez le début d'un pseudo ou d'une clé publique</small> + </div> + </div> + <NavigationLoader :isLoading="$apollo.queries.idSearch.loading" class="d-block mx-auto" /> + <div class="row" v-if="idSearch && !$apollo.queries.idSearch.loading && param.length > 2"> + <div class="col-8 m-auto"> + <div class="table-responsive"> + <table class="table striped"> + <thead> + <tr> + <th scope="col">UID</th> + <th scope="col" class="d-none d-xl-table-cell">PUBKEY</th> + <th scope="col" class="d-none d-sm-table-cell">STATUS</th> + </tr> + </thead> + <tbody> + <tr v-for="member in idSearch.ids" :key="member.uid" + @click="redirect('/hash/' + member.hash)" + :class="{ + 'table-danger' : member.status == 'REVOKED', + 'table-success' : member.status == 'MEMBER', + 'table-info' : member.status == 'NEWCOMER', + 'table-warning' : member.status == 'MISSING', + }"> + <th scope="row">{{ member.uid }}</th> + <td class="d-none d-xl-table-cell">{{ member.pubkey }}</td> + <td class="d-none d-sm-table-cell">{{ member.status }}</td> + </tr> + </tbody> + </table> + </div> + </div> + </div> +</main> +</template> + +<script> +import gql from 'graphql-tag' + +export default { + data() { + // Variables locales + return { + // Fil d'ariane + breadcrumb: [ + { + text: 'Accueil', + to: '/' + }, + { + text: 'Prendre soin de ses contacts', + active: true + } + ], + // Requête graphQL + param: '', + } + }, + // Fonctions locales + methods: { + redirect(path) { + this.$router.push({ path: path }) + } + }, + apollo: { + idSearch : { + query: gql` + query Search($hint: String) { + idSearch(with: {hint: $hint}) { + ids { + pubkey + uid + status + hash + } + } + } `, + variables(){return {hint:this.param}}, + skip() {return this.param.length < 3} + } + }, + mounted () { + // Mise à jour du fil d'ariane au chargement + $nuxt.$emit('changeRoute',this.breadcrumb) + } +} +</script> + +<style lang="sass" scoped> +// CSS Lié au composant +.table.striped tbody + color: var(--dark) + tr + opacity: .9 + cursor: pointer + + &:nth-child(2n+1) + opacity: .7 + + &:hover + opacity: 1 +</style> \ No newline at end of file diff --git a/plugins/filters.js b/plugins/filters.js new file mode 100644 index 0000000..1b62a42 --- /dev/null +++ b/plugins/filters.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import dayjs from 'dayjs' +import 'dayjs/locale/fr' + +dayjs.locale('fr') + +Vue.filter('formatDate', (value) => { + return dayjs(value*1000).format('D MMMM YYYY') +}) \ No newline at end of file -- GitLab